PukiWiki/1.4/ちょっと便利に/convert_htmlの改造実験/差し替えファイル
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
#topicpath
convert_html.php 1ファイルのみです
<?php
// PukiWiki - Yet another WikiWikiWeb clone
// $Id: convert_html.php,v 1.16 2005/07/19 15:38:35 heno...
// Copyright (C)
// 2002-2005 PukiWiki Developers Team
// 2001-2002 Originally written by yu-ji
// License: GPL v2 or (at your option) any later version
//
// function 'convert_html()', wiki text parser
// and related classes-and-functions
function convert_html($lines)
{
global $vars, $digest;
static $contents_id = 0;
// Set digest
$digest = md5(join('', get_source($vars['page'])));
if (! is_array($lines)) $lines = explode("\n", $lines);
$body = & new Body(++$contents_id);
$body->parse($lines);
return $body->toString();
}
// ブロック要素
class Element
{
var $elements = array(); // 要素の配列
function add($tree)
{
while (! empty($tree)) {
if ($tree[0]->canContain($this))
return $this->connect($tree);
array_shift($tree);
}
die('oops');
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return array_merge(array(& $this), $tree);
}
function canContain($obj)
{
return TRUE;
}
function wrap($string, $tag, $param = '')
{
return $string == '' ? '' :
'<' . $tag . $param . '>' . $string . '</' . $tag . '...
}
function toString()
{
$ret = array();
foreach (array_keys($this->elements) as $key)
$ret[] = $this->elements[$key]->toString();
return join("\n", $ret);
}
function dump($indent = 0)
{
$ret = str_repeat(' ', $indent) . get_class($this) . "...
$indent += 2;
foreach (array_keys($this->elements) as $key) {
$ret .= is_object($this->elements[$key]) ?
$this->elements[$key]->dump($indent) : '';
//str_repeat(' ', $indent) . $this->elements[$key] ....
}
return $ret;
}
}
function & Factory_Inline($text)
{
if (substr($text, 0, 1) == '~') {
// 行頭 '~' 。パラグラフ開始
return new Paragraph(' ' . substr($text, 1));
} else {
return new Inline($text);
}
}
function Factory_DList($tree, $text)
{
$out = explode('|', ltrim($text), 2);
if (count($out) < 2) {
$obj = Factory_Inline($text);
return $obj->add($tree);
} else {
$level = min(3, strspn($out[0], ':'));
$title = new DTitle($out[0], $level);
$data = new DData($out[1], $level);
return $data->add($title->add($tree));
}
}
// '|'-separated table
function Factory_Table($tree, $text)
{
if (! preg_match('/^\|(.+)\|([hHfFcC]?)$/', $text, $out...
$obj = Factory_Inline($text);
} else {
$obj = new Table($out);
}
return $obj->add($tree);
}
// Comma-separated table
function Factory_YTable($tree, $text)
{
if ($text == ',') {
$obj = Factory_Inline($text);
} else {
$obj = new YTable(csv_explode(',', substr($text, 1)));
}
return $obj->add($tree);
}
function Factory_Div($tree, $text)
{
$matches = array();
// Seems block plugin?
if (PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK) {
// Usual code
if (preg_match('/^\#([^\(]+)(?:\((.*)\))?/', $text, $m...
exist_plugin_convert($matches[1])) {
$obj = new Div($matches);
} else {
$obj = new Paragraph($text);
}
} else {
// Hack code
if(preg_match('/^#([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', ...
exist_plugin_convert($matches[1])) {
$len = strlen($matches[3]);
$body = array();
if ($len == 0) {
$obj = new Div($matches); // Seems legacy block plugin
} else if (preg_match('/\{{' . $len . '}\s*\r(.*)\r\}...
$matches[2] .= "\r" . $body[1] . "\r";
$obj = new Div($matches); // Seems multiline-enabled...
}
} else {
$obj = new Paragraph($text);
}
}
return $obj->add($tree);
}
// インライン要素
class Inline extends Element
{
function Inline($text)
{
$this->elements[] = $text ? trim(make_link($text)) : '';
}
function connect($tree)
{
if (is_a($tree[0], 'Inline')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
if (is_a($tree[0], 'Body')) {
$obj = new Paragraph('');
$tree = $obj->connect($tree);
}
return parent::connect($tree);
}
function canContain($obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
global $line_break;
return join(($line_break ? '<br />' . "\n" : "\n"), $t...
}
}
// Paragraph: blank-line-separated sentences
class Paragraph extends Element
{
var $param;
function Paragraph($text, $param = '')
{
$this->param = $param;
if ($text == '') return;
if (substr($text, 0, 1) == '~')
$text = ' ' . substr($text, 1);
$this->elements[] = new Inline($text);
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return empty($this->elements) ?
array_merge(array(& $this), $tree) :
array_merge(array(& $this->elements[0], & $this), $tr...
}
function canContain($obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
return $this->wrap(parent::toString(), 'p', $this->par...
}
}
// * Heading1
// ** Heading2
// *** Heading3
class Heading extends Element
{
var $level;
var $id;
var $msg_top;
function Heading(& $root, $text)
{
$this->level = min(3, strspn($text, '*'));
list($text, $this->msg_top, $this->id) = $root->getAnc...
$this->elements[] = & new Inline($text);
$this->level++; // h2,h3,h4
}
function connect($tree)
{
$tree = array_slice($tree, -1);
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
return $this->msg_top . $this->wrap(parent::toString(),
'h' . $this->level, ' id="' . $this->id . '"');
}
}
// ----
// Horizontal Rule
class HRule extends Element
{
function connect($tree)
{
$tree = array_slice($tree, -1);
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
global $hr;
return $hr;
}
}
class ListContainer extends Element
{
var $tag;
var $level;
var $margin;
function ListContainer($tag, $level)
{
$this->tag = $tag;
$this->level = $level;
}
function connect($tree)
{
//マージンを取得
$var_margin = '_' . $this->tag . '_margin';
$var_left_margin = '_' . $this->tag . '_left_margin';
global $$var_margin, $$var_left_margin;
$step = $this->level;
if (isset($tree[1]) && is_a($tree[1], 'ListContainer'))
$step -= $tree[1]->level;
$this->margin = $$var_margin * $step;
if ($step == $this->level)
$this->margin += $$var_left_margin;
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'ListElement') && $this->tag == $obj...
}
function toString()
{
global $_list_pad_str;
$style = sprintf($_list_pad_str, $this->level, $this->...
return $this->wrap(parent::toString(), $this->tag, $st...
}
}
class ListElement extends Element
{
var $tag;
var $tag2;
var $level;
function ListElement($level, $text)
{
$this->level = $level;
if ($text != '')
$this->elements[] = Factory_Inline($text);
}
function buildContainer($tree)
{
$obj = new ListContainer($this->tag, $this->level);
return $obj->connect($tree);
}
function connect($tree)
{
if (empty($this->elements)) {
if (! is_a($tree[0], 'ListContainer'))
return parent::connect($this->buildContainer($tree));
// 行頭文字のみの指定時はUL/OLブロックを脱出
return array_merge(array(& $tree[0]->elements[count($...
}
if (! is_a($tree[0], 'ListContainer'))
$tree = $this->buildContainer($tree);
$tree[0]->elements[] = & $this;
return array_merge(array(& $this->elements[0], & $this...
}
function canContain(& $obj)
{
return (! is_a($obj, 'ListElement') || ($obj->level > ...
}
function toString()
{
return $this->wrap(parent::toString(), $this->tag2);
}
}
// - One
// - Two
// - Three
class UList extends ListElement
{
var $tag = 'ul';
var $tag2 = 'li';
function UList($text)
{
$level = min(3, strspn($text, '-'));
parent::ListElement($level, substr($text, $level));
}
}
// + One
// + Two
// + Three
class OList extends ListElement
{
var $tag = 'ol';
var $tag2 = 'li';
function OList($text)
{
$level = min(3, strspn($text, '+'));
parent::ListElement($level, substr($text, $level));
}
}
// : definition1 | description1
// : definition2 | description2
// : definition3 | description3
class DTitle extends ListElement
{
var $tag = 'dl';
var $tag2 = 'dt';
function DTitle($text, $level)
{
parent::ListElement($level, substr($text, $level));
}
}
class DData extends ListElement
{
var $tag = 'dl';
var $tag2 = 'dd';
function DData($text, $level)
{
parent::ListElement($level, $text);
}
function connect($tree)
{
// 脱出処理させたくないので
$tree[0]->elements[] = & $this;
return empty($this->elements) ?
array_merge(array(& $this), $tree) :
array_merge(array(& $this->elements[0], & $this), $tr...
}
}
// > Someting cited
// > like E-mail text
class BQuote extends Element
{
var $text;
var $level;
var $close;
function BQuote($text)
{
$this->text = $text;
$this->level = min(3, strspn($text, $text{0}));
$this->close = ($text{0} == '<');
}
function buildContainer($tree)
{
$obj = new BQuoteContainer($this->level);
return $obj->connect($tree);
}
function connect($tree)
{
if ($this->close) {
if (! is_a($tree[0], 'BQuoteContainer')) {
// 対応するコンテナが無い
$obj = new Inline($this->text);
return $obj->connect($tree);
}
if ($this->level == $tree[0]->level) {
array_shift($tree);
if ($this->level == 1) {
// 全て抜けた
$obj = Factory_Inline(substr($this->text, $this->le...
return $obj->connect($tree);
}
$this->text = ltrim(substr($this->text, $this->level...
}
} else {
$this->text = ltrim(substr($this->text, $this->level));
if (! is_a($tree[0], 'BQuoteContainer') || $this->lev...
$tree = $this->buildContainer($tree);
}
$obj = new Paragraph($this->text, ' class="quotation"');
return $obj->connect($tree);
}
}
class BQuoteContainer extends Element
{
var $level;
function BQuoteContainer($level)
{
$this->level = $level;
}
function connect($tree)
{
if ($this->level != 1 &&
(! is_a($tree[0], 'BQuoteContainer') || $this->level ...
$obj = new BQuoteContainer($this->level - 1);
$tree = $obj->connect($tree);
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return (! is_a($obj, 'BQuote') || $obj->level >= $this...
}
function toString()
{
return $this->wrap(parent::toString(), 'blockquote');
}
}
class TableCell extends Element
{
var $tag = 'td'; // {td|th}
var $colspan = 1;
var $rowspan = 1;
var $style = array(); // is array('width'=>, 'align'=>....
function TableCell($text, $is_template = FALSE)
{
$matches = array();
while (preg_match('/^(?:(LEFT|CENTER|RIGHT)|(BG)?COLOR...
$text, $matches)) {
if ($matches[1]) {
$this->style['align'] = 'text-align:' . strtolower($...
$text = $matches[5];
} else if ($matches[3]) {
$name = $matches[2] ? 'background-color' : 'color';
$this->style[$name] = $name . ':' . htmlspecialchars...
$text = $matches[5];
} else if ($matches[4]) {
$this->style['size'] = 'font-size:' . htmlspecialcha...
$text = $matches[5];
}
}
if ($is_template && is_numeric($text))
$this->style['width'] = 'width:' . $text . 'px;';
if ($text == '>') {
$this->colspan = 0;
} else if ($text == '~') {
$this->rowspan = 0;
} else if (substr($text, 0, 1) == '~') {
$this->tag = 'th';
$text = substr($text, 1);
}
if ($text != '' && $text{0} == '#') {
// セル内容が'#'で始まるときはDivクラスを通してみる
$tree = array(& $this);
Factory_Div($tree, $text);
} else {
$this->elements[] = Factory_Inline($text);
}
}
function setStyle($style)
{
foreach ($style as $key=>$value)
if (! isset($this->style[$key]))
$this->style[$key] = $value;
}
function wrap($string, $tag, $param)
{
return '<' . $tag . $param . '>' . $string . '</' . $t...
}
function toString()
{
if ($this->rowspan == 0 || $this->colspan == 0) return...
$param = ' class="style_' . $this->tag . '"';
if ($this->rowspan > 1)
$param .= ' rowspan="' . $this->rowspan . '"';
if ($this->colspan > 1) {
$param .= ' colspan="' . $this->colspan . '"';
unset($this->style['width']);
}
if (! empty($this->style))
$param .= ' style="' . join(' ', $this->style) . '"';
return $this->wrap(parent::toString(), $this->tag, $pa...
}
}
// | title1 | title2 | title3 |
// | cell1 | cell2 | cell3 |
// | cell4 | cell5 | cell6 |
class Table extends Element
{
var $types;
var $col; // number of column
function Table($out)
{
$cells = explode('|', $out[1]);
$type = strtolower($out[2]);
$is_template = ($type == 'c');
$this->col = count($cells);
$this->types = array($type);
$row = array();
foreach ($cells as $cell)
$row[] = new TableCell($cell, $is_template);
$this->elements[] = $row;
}
function connect($tree)
{
if (is_a($tree[0], 'Table')) {
$tree[0]->elements[] = $this->elements[0];
$tree[0]->types[] = $this->types[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'Table') && ($obj->col == $this->col);
}
function toString()
{
static $parts = array('h'=>'thead', 'f'=>'tfoot', ''=>...
// rowspanを設定(下から上へ)
for ($ncol = 0; $ncol < $this->col; $ncol++) {
$rowspan = 1;
foreach (array_reverse(array_keys($this->elements)) a...
$row = & $this->elements[$nrow];
if ($row[$ncol]->rowspan == 0) {
++$rowspan;
continue;
}
$row[$ncol]->rowspan = $rowspan;
while (--$rowspan) // 行種別を継承する
$this->types[$nrow + $rowspan] = $this->types[$nrow];
$rowspan = 1;
}
}
// colspan,styleを設定
$stylerow = NULL;
foreach (array_keys($this->elements) as $nrow) {
$row = & $this->elements[$nrow];
if ($this->types[$nrow] == 'c')
$stylerow = & $row;
$colspan = 1;
foreach (array_keys($row) as $ncol) {
if ($row[$ncol]->colspan == 0) {
++$colspan;
continue;
}
$row[$ncol]->colspan = $colspan;
if ($stylerow !== NULL) {
$row[$ncol]->setStyle($stylerow[$ncol]->style);
while (--$colspan) // 列スタイルを継承する
$row[$ncol - $colspan]->setStyle($stylerow[$ncol]-...
}
$colspan = 1;
}
}
// テキスト化
$string = '';
foreach ($parts as $type => $part)
{
$part_string = '';
foreach (array_keys($this->elements) as $nrow) {
if ($this->types[$nrow] != $type)
continue;
$row = & $this->elements[$nrow];
$row_string = '';
foreach (array_keys($row) as $ncol)
$row_string .= $row[$ncol]->toString();
$part_string .= $this->wrap($row_string, 'tr');
}
if ($part_string != '')
$string .= $this->wrap($part_string, $part);
}
$string = $this->wrap($string, 'table', ' class="style...
return $this->wrap($string, 'div', ' class="ie5"');
}
}
// , title1 , title2 , title3
// , cell1 , cell2 , cell3
// , cell4 , cell5 , cell6
class YTable extends Element
{
var $col;
function YTable($_value)
{
$align = $value = $matches = array();
foreach($_value as $val) {
if (preg_match('/^(\s+)?(.+?)(\s+)?$/', $val, $matche...
$align[] =($matches[1] != '') ?
((isset($matches[3]) && $matches[3] != '') ?
' style="text-align:center"' :
' style="text-align:right"'
) : '';
$value[] = $matches[2];
} else {
$align[] = '';
$value[] = $val;
}
}
$this->col = count($value);
$colspan = array();
foreach ($value as $val)
$colspan[] = ($val == '==') ? 0 : 1;
$str = '';
$count = count($value);
for ($i = 0; $i < $count; $i++) {
if ($colspan[$i]) {
while ($i + $colspan[$i] < $count && $value[$i + $co...
$colspan[$i]++;
$colspan[$i] = ($colspan[$i] > 1) ? ' colspan="' . $...
$str .= '<td class="style_td"' . $align[$i] . $colsp...
}
}
$this->elements[] = $str;
}
function connect($tree)
{
if (is_a($tree[0], 'YTable')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'YTable') && ($obj->col == $this->co...
}
function toString()
{
$rows = '';
foreach ($this->elements as $str)
$rows .= "\n" . '<tr class="style_tr">' . $str . '</t...
$rows = $this->wrap($rows, 'table', ' class="style_tab...
return $this->wrap($rows, 'div', ' class="ie5"');
}
}
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
class Pre extends Element
{
function Pre($text)
{
global $preformat_ltrim;
$this->elements[] = htmlspecialchars(
(! $preformat_ltrim || $text == '' || $text{0} != ' '...
}
function connect($tree)
{
if (is_a($tree[0], 'Pre')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'Pre');
}
function toString()
{
return $this->wrap(join("\n", $this->elements), 'pre');
}
}
// Block plugin: #something (started with '#')
class Div extends Element
{
var $name;
var $param;
function Div($out)
{
list(, $this->name, $this->param) = array_pad($out, 3,...
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
// Call #plugin
return do_plugin_convert($this->name, $this->param);
}
}
// LEFT:/CENTER:/RIGHT:
class Align extends Element
{
var $align;
function Align($align)
{
$this->align = $align;
}
function canContain(& $obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
return $this->wrap(parent::toString(), 'div', ' style=...
}
}
// Body
class Body extends Element
{
var $id;
var $count = 0;
var $contents = array();
function Body($id)
{
$this->id = $id;
}
function parse($lines)
{
$classes = array(
'-' => 'UList',
'+' => 'OList',
'>' => 'BQuote',
'<' => 'BQuote'
);
$factories = array(
':' => 'DList',
'|' => 'Table',
',' => 'YTable',
'#' => 'Div'
);
$tree = array(& $this);
$matches = array();
while (! empty($lines)) {
$line = array_shift($lines);
// Escape comments
if (substr($line, 0, 2) == '//') continue;
if (preg_match('/^(LEFT|CENTER|RIGHT):(.*)$/', $line,...
// <div style="text-align:...">
$obj = & new Align(strtolower($matches[1]));
$tree = $obj->add($tree);
if ($matches[2] == '') continue;
$line = $matches[2];
}
$line = preg_replace("/[\r\n]+$/", '', $line);
// Empty
if ($line == '') {
$tree = array(& $this);
continue;
}
// Horizontal Rule
if (substr($line, 0, 4) == '----') {
$obj = & new HRule();
$tree = $obj->add($tree);
continue;
}
// Multiline-enabled block plugin
if (! PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK &&
preg_match('/^#[^{]+(\{\{+)\s*$/', $line, $matche...
$len = strlen($matches[1]);
$line .= "\r"; // Delimiter
while (! empty($lines)) {
$next_line = preg_replace("/[\r\n]*$/", '', array_s...
if (preg_match('/\}{' . $len . '}/', $next_line)) {
$line .= $next_line;
break;
} else {
$line .= $next_line .= "\r"; // Delimiter
}
}
}
// The first character
$head = $line{0};
// Heading
if ($head == '*') {
$obj = & new Heading($this, $line);
$tree = $obj->add($tree);
continue;
}
// Pre
if ($head == ' ' || $head == "\t") {
$obj = & new Pre($line);
$tree = $obj->add($tree);
continue;
}
// Line Break
if (substr($line, -1) == '~')
$line = substr($line, 0, -1) . "\r";
// Other Character
if (isset($classes[$head])) {
$classname = $classes[$head];
$obj = & new $classname($line);
$tree = $obj->add($tree);
continue;
}
// Other Character
if (isset($factories[$head])) {
$factoryname = 'Factory_' . $factories[$head];
$tree = $factoryname($tree, $line);
continue;
}
// Default
$obj = & Factory_Inline($line);
$tree = $obj->add($tree);
}
}
function getAnchor($text, $level)
{
global $top, $_symbol_anchor;
// Heading id (auto-generated)
$autoid = 'content_' . $this->id . '_' . $this->count;
$this->count++;
// Heading id (specified by users)
$id = make_heading($text, FALSE); // Cut fixed-anchor ...
if ($id == '') {
// Not specified
$id = & $autoid;
$anchor = '';
} else {
$anchor = ' &aname(' . $id . ',super,full){' . $_symb...
}
$text = ' ' . $text;
$this->contents[] = compact('level', 'text', 'id');
// Add heding
return array($text . $anchor, $this->count > 1 ? "\n" ...
}
function toString()
{
global $vars;
$text = parent::toString();
// #contents
$text = preg_replace_callback('/<#_contents_>/',
array(& $this, 'replace_contents'), $text);
return $text . "\n";
}
function replace_contents($arr)
{
$Contents = & new Element();
$tree = array(& $Contents);
foreach ($this->contents as $param) {
$obj = & new Contents_UList($param['text'], $param['l...
$tree = $obj->add($tree);
}
return '<div class="contents">' . "\n" .
'<a id="contents_' . $this->id . '"></a>' . "\n" .
$Contents->toString() . "\n" .
'</div>' . "\n";
}
}
class Contents_UList extends UList
{
function Contents_UList($text, $level, $id)
{
make_heading($text);
$text = '[[' . $text . '>#' . $id . ']]';
ListElement::ListElement($level, $text);
}
function buildContainer($tree)
{
$obj = new Contents_ListContainer($this->tag, $this->l...
return $obj->connect($tree);
}
}
class Contents_ListContainer extends ListContainer
{
function connect($tree)
{
$var_margin = '_' . $this->tag . '_margin';
$var_left_margin = '_' . $this->tag . '_left_margin';
global $$var_margin, $$var_left_margin;
$step = $this->level;
$this->margin = $$var_left_margin;
if (isset($tree[1]) && is_a($tree[1], 'ListContainer')...
$step -= $tree[1]->level;
$margin = 0;
}
$this->margin += $$var_margin * ($step == $this->level...
return parent::connect($tree);
}
}
?>
終了行:
#topicpath
convert_html.php 1ファイルのみです
<?php
// PukiWiki - Yet another WikiWikiWeb clone
// $Id: convert_html.php,v 1.16 2005/07/19 15:38:35 heno...
// Copyright (C)
// 2002-2005 PukiWiki Developers Team
// 2001-2002 Originally written by yu-ji
// License: GPL v2 or (at your option) any later version
//
// function 'convert_html()', wiki text parser
// and related classes-and-functions
function convert_html($lines)
{
global $vars, $digest;
static $contents_id = 0;
// Set digest
$digest = md5(join('', get_source($vars['page'])));
if (! is_array($lines)) $lines = explode("\n", $lines);
$body = & new Body(++$contents_id);
$body->parse($lines);
return $body->toString();
}
// ブロック要素
class Element
{
var $elements = array(); // 要素の配列
function add($tree)
{
while (! empty($tree)) {
if ($tree[0]->canContain($this))
return $this->connect($tree);
array_shift($tree);
}
die('oops');
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return array_merge(array(& $this), $tree);
}
function canContain($obj)
{
return TRUE;
}
function wrap($string, $tag, $param = '')
{
return $string == '' ? '' :
'<' . $tag . $param . '>' . $string . '</' . $tag . '...
}
function toString()
{
$ret = array();
foreach (array_keys($this->elements) as $key)
$ret[] = $this->elements[$key]->toString();
return join("\n", $ret);
}
function dump($indent = 0)
{
$ret = str_repeat(' ', $indent) . get_class($this) . "...
$indent += 2;
foreach (array_keys($this->elements) as $key) {
$ret .= is_object($this->elements[$key]) ?
$this->elements[$key]->dump($indent) : '';
//str_repeat(' ', $indent) . $this->elements[$key] ....
}
return $ret;
}
}
function & Factory_Inline($text)
{
if (substr($text, 0, 1) == '~') {
// 行頭 '~' 。パラグラフ開始
return new Paragraph(' ' . substr($text, 1));
} else {
return new Inline($text);
}
}
function Factory_DList($tree, $text)
{
$out = explode('|', ltrim($text), 2);
if (count($out) < 2) {
$obj = Factory_Inline($text);
return $obj->add($tree);
} else {
$level = min(3, strspn($out[0], ':'));
$title = new DTitle($out[0], $level);
$data = new DData($out[1], $level);
return $data->add($title->add($tree));
}
}
// '|'-separated table
function Factory_Table($tree, $text)
{
if (! preg_match('/^\|(.+)\|([hHfFcC]?)$/', $text, $out...
$obj = Factory_Inline($text);
} else {
$obj = new Table($out);
}
return $obj->add($tree);
}
// Comma-separated table
function Factory_YTable($tree, $text)
{
if ($text == ',') {
$obj = Factory_Inline($text);
} else {
$obj = new YTable(csv_explode(',', substr($text, 1)));
}
return $obj->add($tree);
}
function Factory_Div($tree, $text)
{
$matches = array();
// Seems block plugin?
if (PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK) {
// Usual code
if (preg_match('/^\#([^\(]+)(?:\((.*)\))?/', $text, $m...
exist_plugin_convert($matches[1])) {
$obj = new Div($matches);
} else {
$obj = new Paragraph($text);
}
} else {
// Hack code
if(preg_match('/^#([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', ...
exist_plugin_convert($matches[1])) {
$len = strlen($matches[3]);
$body = array();
if ($len == 0) {
$obj = new Div($matches); // Seems legacy block plugin
} else if (preg_match('/\{{' . $len . '}\s*\r(.*)\r\}...
$matches[2] .= "\r" . $body[1] . "\r";
$obj = new Div($matches); // Seems multiline-enabled...
}
} else {
$obj = new Paragraph($text);
}
}
return $obj->add($tree);
}
// インライン要素
class Inline extends Element
{
function Inline($text)
{
$this->elements[] = $text ? trim(make_link($text)) : '';
}
function connect($tree)
{
if (is_a($tree[0], 'Inline')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
if (is_a($tree[0], 'Body')) {
$obj = new Paragraph('');
$tree = $obj->connect($tree);
}
return parent::connect($tree);
}
function canContain($obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
global $line_break;
return join(($line_break ? '<br />' . "\n" : "\n"), $t...
}
}
// Paragraph: blank-line-separated sentences
class Paragraph extends Element
{
var $param;
function Paragraph($text, $param = '')
{
$this->param = $param;
if ($text == '') return;
if (substr($text, 0, 1) == '~')
$text = ' ' . substr($text, 1);
$this->elements[] = new Inline($text);
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return empty($this->elements) ?
array_merge(array(& $this), $tree) :
array_merge(array(& $this->elements[0], & $this), $tr...
}
function canContain($obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
return $this->wrap(parent::toString(), 'p', $this->par...
}
}
// * Heading1
// ** Heading2
// *** Heading3
class Heading extends Element
{
var $level;
var $id;
var $msg_top;
function Heading(& $root, $text)
{
$this->level = min(3, strspn($text, '*'));
list($text, $this->msg_top, $this->id) = $root->getAnc...
$this->elements[] = & new Inline($text);
$this->level++; // h2,h3,h4
}
function connect($tree)
{
$tree = array_slice($tree, -1);
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
return $this->msg_top . $this->wrap(parent::toString(),
'h' . $this->level, ' id="' . $this->id . '"');
}
}
// ----
// Horizontal Rule
class HRule extends Element
{
function connect($tree)
{
$tree = array_slice($tree, -1);
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
global $hr;
return $hr;
}
}
class ListContainer extends Element
{
var $tag;
var $level;
var $margin;
function ListContainer($tag, $level)
{
$this->tag = $tag;
$this->level = $level;
}
function connect($tree)
{
//マージンを取得
$var_margin = '_' . $this->tag . '_margin';
$var_left_margin = '_' . $this->tag . '_left_margin';
global $$var_margin, $$var_left_margin;
$step = $this->level;
if (isset($tree[1]) && is_a($tree[1], 'ListContainer'))
$step -= $tree[1]->level;
$this->margin = $$var_margin * $step;
if ($step == $this->level)
$this->margin += $$var_left_margin;
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'ListElement') && $this->tag == $obj...
}
function toString()
{
global $_list_pad_str;
$style = sprintf($_list_pad_str, $this->level, $this->...
return $this->wrap(parent::toString(), $this->tag, $st...
}
}
class ListElement extends Element
{
var $tag;
var $tag2;
var $level;
function ListElement($level, $text)
{
$this->level = $level;
if ($text != '')
$this->elements[] = Factory_Inline($text);
}
function buildContainer($tree)
{
$obj = new ListContainer($this->tag, $this->level);
return $obj->connect($tree);
}
function connect($tree)
{
if (empty($this->elements)) {
if (! is_a($tree[0], 'ListContainer'))
return parent::connect($this->buildContainer($tree));
// 行頭文字のみの指定時はUL/OLブロックを脱出
return array_merge(array(& $tree[0]->elements[count($...
}
if (! is_a($tree[0], 'ListContainer'))
$tree = $this->buildContainer($tree);
$tree[0]->elements[] = & $this;
return array_merge(array(& $this->elements[0], & $this...
}
function canContain(& $obj)
{
return (! is_a($obj, 'ListElement') || ($obj->level > ...
}
function toString()
{
return $this->wrap(parent::toString(), $this->tag2);
}
}
// - One
// - Two
// - Three
class UList extends ListElement
{
var $tag = 'ul';
var $tag2 = 'li';
function UList($text)
{
$level = min(3, strspn($text, '-'));
parent::ListElement($level, substr($text, $level));
}
}
// + One
// + Two
// + Three
class OList extends ListElement
{
var $tag = 'ol';
var $tag2 = 'li';
function OList($text)
{
$level = min(3, strspn($text, '+'));
parent::ListElement($level, substr($text, $level));
}
}
// : definition1 | description1
// : definition2 | description2
// : definition3 | description3
class DTitle extends ListElement
{
var $tag = 'dl';
var $tag2 = 'dt';
function DTitle($text, $level)
{
parent::ListElement($level, substr($text, $level));
}
}
class DData extends ListElement
{
var $tag = 'dl';
var $tag2 = 'dd';
function DData($text, $level)
{
parent::ListElement($level, $text);
}
function connect($tree)
{
// 脱出処理させたくないので
$tree[0]->elements[] = & $this;
return empty($this->elements) ?
array_merge(array(& $this), $tree) :
array_merge(array(& $this->elements[0], & $this), $tr...
}
}
// > Someting cited
// > like E-mail text
class BQuote extends Element
{
var $text;
var $level;
var $close;
function BQuote($text)
{
$this->text = $text;
$this->level = min(3, strspn($text, $text{0}));
$this->close = ($text{0} == '<');
}
function buildContainer($tree)
{
$obj = new BQuoteContainer($this->level);
return $obj->connect($tree);
}
function connect($tree)
{
if ($this->close) {
if (! is_a($tree[0], 'BQuoteContainer')) {
// 対応するコンテナが無い
$obj = new Inline($this->text);
return $obj->connect($tree);
}
if ($this->level == $tree[0]->level) {
array_shift($tree);
if ($this->level == 1) {
// 全て抜けた
$obj = Factory_Inline(substr($this->text, $this->le...
return $obj->connect($tree);
}
$this->text = ltrim(substr($this->text, $this->level...
}
} else {
$this->text = ltrim(substr($this->text, $this->level));
if (! is_a($tree[0], 'BQuoteContainer') || $this->lev...
$tree = $this->buildContainer($tree);
}
$obj = new Paragraph($this->text, ' class="quotation"');
return $obj->connect($tree);
}
}
class BQuoteContainer extends Element
{
var $level;
function BQuoteContainer($level)
{
$this->level = $level;
}
function connect($tree)
{
if ($this->level != 1 &&
(! is_a($tree[0], 'BQuoteContainer') || $this->level ...
$obj = new BQuoteContainer($this->level - 1);
$tree = $obj->connect($tree);
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return (! is_a($obj, 'BQuote') || $obj->level >= $this...
}
function toString()
{
return $this->wrap(parent::toString(), 'blockquote');
}
}
class TableCell extends Element
{
var $tag = 'td'; // {td|th}
var $colspan = 1;
var $rowspan = 1;
var $style = array(); // is array('width'=>, 'align'=>....
function TableCell($text, $is_template = FALSE)
{
$matches = array();
while (preg_match('/^(?:(LEFT|CENTER|RIGHT)|(BG)?COLOR...
$text, $matches)) {
if ($matches[1]) {
$this->style['align'] = 'text-align:' . strtolower($...
$text = $matches[5];
} else if ($matches[3]) {
$name = $matches[2] ? 'background-color' : 'color';
$this->style[$name] = $name . ':' . htmlspecialchars...
$text = $matches[5];
} else if ($matches[4]) {
$this->style['size'] = 'font-size:' . htmlspecialcha...
$text = $matches[5];
}
}
if ($is_template && is_numeric($text))
$this->style['width'] = 'width:' . $text . 'px;';
if ($text == '>') {
$this->colspan = 0;
} else if ($text == '~') {
$this->rowspan = 0;
} else if (substr($text, 0, 1) == '~') {
$this->tag = 'th';
$text = substr($text, 1);
}
if ($text != '' && $text{0} == '#') {
// セル内容が'#'で始まるときはDivクラスを通してみる
$tree = array(& $this);
Factory_Div($tree, $text);
} else {
$this->elements[] = Factory_Inline($text);
}
}
function setStyle($style)
{
foreach ($style as $key=>$value)
if (! isset($this->style[$key]))
$this->style[$key] = $value;
}
function wrap($string, $tag, $param)
{
return '<' . $tag . $param . '>' . $string . '</' . $t...
}
function toString()
{
if ($this->rowspan == 0 || $this->colspan == 0) return...
$param = ' class="style_' . $this->tag . '"';
if ($this->rowspan > 1)
$param .= ' rowspan="' . $this->rowspan . '"';
if ($this->colspan > 1) {
$param .= ' colspan="' . $this->colspan . '"';
unset($this->style['width']);
}
if (! empty($this->style))
$param .= ' style="' . join(' ', $this->style) . '"';
return $this->wrap(parent::toString(), $this->tag, $pa...
}
}
// | title1 | title2 | title3 |
// | cell1 | cell2 | cell3 |
// | cell4 | cell5 | cell6 |
class Table extends Element
{
var $types;
var $col; // number of column
function Table($out)
{
$cells = explode('|', $out[1]);
$type = strtolower($out[2]);
$is_template = ($type == 'c');
$this->col = count($cells);
$this->types = array($type);
$row = array();
foreach ($cells as $cell)
$row[] = new TableCell($cell, $is_template);
$this->elements[] = $row;
}
function connect($tree)
{
if (is_a($tree[0], 'Table')) {
$tree[0]->elements[] = $this->elements[0];
$tree[0]->types[] = $this->types[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'Table') && ($obj->col == $this->col);
}
function toString()
{
static $parts = array('h'=>'thead', 'f'=>'tfoot', ''=>...
// rowspanを設定(下から上へ)
for ($ncol = 0; $ncol < $this->col; $ncol++) {
$rowspan = 1;
foreach (array_reverse(array_keys($this->elements)) a...
$row = & $this->elements[$nrow];
if ($row[$ncol]->rowspan == 0) {
++$rowspan;
continue;
}
$row[$ncol]->rowspan = $rowspan;
while (--$rowspan) // 行種別を継承する
$this->types[$nrow + $rowspan] = $this->types[$nrow];
$rowspan = 1;
}
}
// colspan,styleを設定
$stylerow = NULL;
foreach (array_keys($this->elements) as $nrow) {
$row = & $this->elements[$nrow];
if ($this->types[$nrow] == 'c')
$stylerow = & $row;
$colspan = 1;
foreach (array_keys($row) as $ncol) {
if ($row[$ncol]->colspan == 0) {
++$colspan;
continue;
}
$row[$ncol]->colspan = $colspan;
if ($stylerow !== NULL) {
$row[$ncol]->setStyle($stylerow[$ncol]->style);
while (--$colspan) // 列スタイルを継承する
$row[$ncol - $colspan]->setStyle($stylerow[$ncol]-...
}
$colspan = 1;
}
}
// テキスト化
$string = '';
foreach ($parts as $type => $part)
{
$part_string = '';
foreach (array_keys($this->elements) as $nrow) {
if ($this->types[$nrow] != $type)
continue;
$row = & $this->elements[$nrow];
$row_string = '';
foreach (array_keys($row) as $ncol)
$row_string .= $row[$ncol]->toString();
$part_string .= $this->wrap($row_string, 'tr');
}
if ($part_string != '')
$string .= $this->wrap($part_string, $part);
}
$string = $this->wrap($string, 'table', ' class="style...
return $this->wrap($string, 'div', ' class="ie5"');
}
}
// , title1 , title2 , title3
// , cell1 , cell2 , cell3
// , cell4 , cell5 , cell6
class YTable extends Element
{
var $col;
function YTable($_value)
{
$align = $value = $matches = array();
foreach($_value as $val) {
if (preg_match('/^(\s+)?(.+?)(\s+)?$/', $val, $matche...
$align[] =($matches[1] != '') ?
((isset($matches[3]) && $matches[3] != '') ?
' style="text-align:center"' :
' style="text-align:right"'
) : '';
$value[] = $matches[2];
} else {
$align[] = '';
$value[] = $val;
}
}
$this->col = count($value);
$colspan = array();
foreach ($value as $val)
$colspan[] = ($val == '==') ? 0 : 1;
$str = '';
$count = count($value);
for ($i = 0; $i < $count; $i++) {
if ($colspan[$i]) {
while ($i + $colspan[$i] < $count && $value[$i + $co...
$colspan[$i]++;
$colspan[$i] = ($colspan[$i] > 1) ? ' colspan="' . $...
$str .= '<td class="style_td"' . $align[$i] . $colsp...
}
}
$this->elements[] = $str;
}
function connect($tree)
{
if (is_a($tree[0], 'YTable')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'YTable') && ($obj->col == $this->co...
}
function toString()
{
$rows = '';
foreach ($this->elements as $str)
$rows .= "\n" . '<tr class="style_tr">' . $str . '</t...
$rows = $this->wrap($rows, 'table', ' class="style_tab...
return $this->wrap($rows, 'div', ' class="ie5"');
}
}
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
// ' 'Space-beginning sentence
class Pre extends Element
{
function Pre($text)
{
global $preformat_ltrim;
$this->elements[] = htmlspecialchars(
(! $preformat_ltrim || $text == '' || $text{0} != ' '...
}
function connect($tree)
{
if (is_a($tree[0], 'Pre')) {
$tree[0]->elements[] = $this->elements[0];
return $tree;
}
return parent::connect($tree);
}
function canContain(& $obj)
{
return is_a($obj, 'Pre');
}
function toString()
{
return $this->wrap(join("\n", $this->elements), 'pre');
}
}
// Block plugin: #something (started with '#')
class Div extends Element
{
var $name;
var $param;
function Div($out)
{
list(, $this->name, $this->param) = array_pad($out, 3,...
}
function connect($tree)
{
$tree[0]->elements[] = & $this;
return $tree;
}
function canContain(& $obj)
{
return FALSE;
}
function toString()
{
// Call #plugin
return do_plugin_convert($this->name, $this->param);
}
}
// LEFT:/CENTER:/RIGHT:
class Align extends Element
{
var $align;
function Align($align)
{
$this->align = $align;
}
function canContain(& $obj)
{
return is_a($obj, 'Inline');
}
function toString()
{
return $this->wrap(parent::toString(), 'div', ' style=...
}
}
// Body
class Body extends Element
{
var $id;
var $count = 0;
var $contents = array();
function Body($id)
{
$this->id = $id;
}
function parse($lines)
{
$classes = array(
'-' => 'UList',
'+' => 'OList',
'>' => 'BQuote',
'<' => 'BQuote'
);
$factories = array(
':' => 'DList',
'|' => 'Table',
',' => 'YTable',
'#' => 'Div'
);
$tree = array(& $this);
$matches = array();
while (! empty($lines)) {
$line = array_shift($lines);
// Escape comments
if (substr($line, 0, 2) == '//') continue;
if (preg_match('/^(LEFT|CENTER|RIGHT):(.*)$/', $line,...
// <div style="text-align:...">
$obj = & new Align(strtolower($matches[1]));
$tree = $obj->add($tree);
if ($matches[2] == '') continue;
$line = $matches[2];
}
$line = preg_replace("/[\r\n]+$/", '', $line);
// Empty
if ($line == '') {
$tree = array(& $this);
continue;
}
// Horizontal Rule
if (substr($line, 0, 4) == '----') {
$obj = & new HRule();
$tree = $obj->add($tree);
continue;
}
// Multiline-enabled block plugin
if (! PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK &&
preg_match('/^#[^{]+(\{\{+)\s*$/', $line, $matche...
$len = strlen($matches[1]);
$line .= "\r"; // Delimiter
while (! empty($lines)) {
$next_line = preg_replace("/[\r\n]*$/", '', array_s...
if (preg_match('/\}{' . $len . '}/', $next_line)) {
$line .= $next_line;
break;
} else {
$line .= $next_line .= "\r"; // Delimiter
}
}
}
// The first character
$head = $line{0};
// Heading
if ($head == '*') {
$obj = & new Heading($this, $line);
$tree = $obj->add($tree);
continue;
}
// Pre
if ($head == ' ' || $head == "\t") {
$obj = & new Pre($line);
$tree = $obj->add($tree);
continue;
}
// Line Break
if (substr($line, -1) == '~')
$line = substr($line, 0, -1) . "\r";
// Other Character
if (isset($classes[$head])) {
$classname = $classes[$head];
$obj = & new $classname($line);
$tree = $obj->add($tree);
continue;
}
// Other Character
if (isset($factories[$head])) {
$factoryname = 'Factory_' . $factories[$head];
$tree = $factoryname($tree, $line);
continue;
}
// Default
$obj = & Factory_Inline($line);
$tree = $obj->add($tree);
}
}
function getAnchor($text, $level)
{
global $top, $_symbol_anchor;
// Heading id (auto-generated)
$autoid = 'content_' . $this->id . '_' . $this->count;
$this->count++;
// Heading id (specified by users)
$id = make_heading($text, FALSE); // Cut fixed-anchor ...
if ($id == '') {
// Not specified
$id = & $autoid;
$anchor = '';
} else {
$anchor = ' &aname(' . $id . ',super,full){' . $_symb...
}
$text = ' ' . $text;
$this->contents[] = compact('level', 'text', 'id');
// Add heding
return array($text . $anchor, $this->count > 1 ? "\n" ...
}
function toString()
{
global $vars;
$text = parent::toString();
// #contents
$text = preg_replace_callback('/<#_contents_>/',
array(& $this, 'replace_contents'), $text);
return $text . "\n";
}
function replace_contents($arr)
{
$Contents = & new Element();
$tree = array(& $Contents);
foreach ($this->contents as $param) {
$obj = & new Contents_UList($param['text'], $param['l...
$tree = $obj->add($tree);
}
return '<div class="contents">' . "\n" .
'<a id="contents_' . $this->id . '"></a>' . "\n" .
$Contents->toString() . "\n" .
'</div>' . "\n";
}
}
class Contents_UList extends UList
{
function Contents_UList($text, $level, $id)
{
make_heading($text);
$text = '[[' . $text . '>#' . $id . ']]';
ListElement::ListElement($level, $text);
}
function buildContainer($tree)
{
$obj = new Contents_ListContainer($this->tag, $this->l...
return $obj->connect($tree);
}
}
class Contents_ListContainer extends ListContainer
{
function connect($tree)
{
$var_margin = '_' . $this->tag . '_margin';
$var_left_margin = '_' . $this->tag . '_left_margin';
global $$var_margin, $$var_left_margin;
$step = $this->level;
$this->margin = $$var_left_margin;
if (isset($tree[1]) && is_a($tree[1], 'ListContainer')...
$step -= $tree[1]->level;
$margin = 0;
}
$this->margin += $$var_margin * ($step == $this->level...
return parent::connect($tree);
}
}
?>
ページ名: