ノイアー のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- ノイアー へ行く。
- 1 (2016-12-10 (土) 13:31:52)
- 2 (2016-12-10 (土) 14:43:58)
?php
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) . "\n"; $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] . "\n"; } 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)); }
}
function Factory_Table($tree, $text)
{
if (! preg_match('/^\|(.+)\|([hHfFcC]?)$/', $text, $out)) { $obj = Factory_Inline($text); } else { $obj = new Table($out); } return $obj->add($tree);
}
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, $matches) && exist_plugin_convert($matches[1])) { $obj = new Div($matches); } else { $obj = new Paragraph($text); } } else { // Hack code if(preg_match('/^#([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', $text, $matches) && 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\}{' . $len . '}/', $text, $body)) { $matches[2] .= "\r" . $body[1] . "\r"; $obj = new Div($matches); // Seems multiline-enabled block plugin } } 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"), $this->elements); }
}
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), $tree); }
function canContain($obj) { return is_a($obj, 'Inline'); }
function toString() { return $this->wrap(parent::toString(), 'p', $this->param); }
}
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->getAnchor($text, $this->level); $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 . '"'); }
}
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->tag && $this->level == $obj->level; }
function toString() { global $_list_pad_str;
$style = sprintf($_list_pad_str, $this->level, $this->margin, $this->margin); return $this->wrap(parent::toString(), $this->tag, $style); }
}
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($tree[0]->elements) - 1]), $tree); } if (! is_a($tree[0], 'ListContainer')) $tree = $this->buildContainer($tree); $tree[0]->elements[] = & $this; return array_merge(array(& $this->elements[0], & $this), $tree); }
function canContain(& $obj) { return (! is_a($obj, 'ListElement') || ($obj->level > $this->level)); }
function toString() { return $this->wrap(parent::toString(), $this->tag2); }
}
class UList extends ListElement
{
var $tag = 'ul'; var $tag2 = 'li';
function UList($text) { $level = min(3, strspn($text, '-')); parent::ListElement($level, substr($text, $level)); }
}
class OList extends ListElement
{
var $tag = 'ol'; var $tag2 = 'li';
function OList($text) { $level = min(3, strspn($text, '+')); parent::ListElement($level, substr($text, $level)); }
}
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), $tree); }
}
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->level)); 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->level != $tree[0]->level) $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 != $tree[0]->level + 1)) { $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->level); }
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\(([#\w]+)\)|SIZE\((\d+)\)):(.*)$/', $text, $matches)) { if ($matches[1]) { $this->style['align'] = 'text-align:' . strtolower($matches[1]) . ';'; $text = $matches[5]; } else if ($matches[3]) { $name = $matches[2] ? 'background-color' : 'color'; $this->style[$name] = $name . ':' . htmlspecialchars($matches[3]) . ';'; $text = $matches[5]; } else if ($matches[4]) { $this->style['size'] = 'font-size:' . htmlspecialchars($matches[4]) . 'px;'; $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 . '</' . $tag . '>'; }
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, $param); }
}
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', ''=>'tbody');
// rowspanを設定(下から上へ) for ($ncol = 0; $ncol < $this->col; $ncol++) { $rowspan = 1; foreach (array_reverse(array_keys($this->elements)) as $nrow) { $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]->style); } $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_table" cellspacing="1" border="0"');
return $this->wrap($string, 'div', ' class="ie5"'); }
}
class YTable extends Element
{
var $col;
function YTable($_value) { $align = $value = $matches = array(); foreach($_value as $val) { if (preg_match('/^(\s+)?(.+?)(\s+)?$/', $val, $matches)) { $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 + $colspan[$i]] == '==') $colspan[$i]++; $colspan[$i] = ($colspan[$i] > 1) ? ' colspan="' . $colspan[$i] . '"' : ''; $str .= '<td class="style_td"' . $align[$i] . $colspan[$i] . '>' . make_link($value[$i]) . '</td>'; } } $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->col); }
function toString() { $rows = ''; foreach ($this->elements as $str) $rows .= "\n" . '<tr class="style_tr">' . $str . '</tr>' . "\n"; $rows = $this->wrap($rows, 'table', ' class="style_table" cellspacing="1" border="0"'); return $this->wrap($rows, 'div', ' class="ie5"'); }
}
class Pre extends Element
{
function Pre($text) { global $preformat_ltrim;
$this->elements[] = htmlspecialchars( (! $preformat_ltrim || $text == '' || $text{0} != ' ') ? $text : substr($text, 1)); }
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'); }
}
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); }
}
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="text-align:' . $this->align . '"'); }
}
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, $matches)) { // <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, $matches)) { $len = strlen($matches[1]); $line .= "\r"; // Delimiter while (! empty($lines)) { $next_line = preg_replace("/[\r\n]*$/", '', array_shift($lines)); 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 from $text if ($id == '') { // Not specified $id = & $autoid; $anchor = ''; } else { $anchor = ' &aname(' . $id . ',super,full){' . $_symbol_anchor . '};'; }
$text = ' ' . $text;
$this->contents[] = compact('level', 'text', 'id');
// Add heding return array($text . $anchor, $this->count > 1 ? "\n" . $top : '', $autoid); }
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['level'], $param['id']); $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->level); 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 ? 1 : $step);
return parent::connect($tree); }
}
?>