2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
5 // $Id: convert_html.php,v 1.7 2003/01/31 09:49:03 panda Exp $
8 function &convert_html(&$lines)
10 global $script,$vars,$digest;
11 static $contents_id = 0;
13 $digest = md5(join('',get_source($vars['page'])));
15 $contents = new Contents(++$contents_id);
20 foreach ($lines as $line) {
21 if (substr($line,0,2) == '//') { //¥³¥á¥ó¥È¤Ï½èÍý¤·¤Ê¤¤
28 if (preg_match('/^(LEFT|CENTER|RIGHT):(.*)$/',$line,$matches)) {
29 $last =& $last->add(new Align(strtolower($matches[1]))); // <div style="text-align:...">
30 if ($matches[2] == '') {
37 $head = substr($line,0,1);
39 if ($line == '') { // ¶õ¹Ô
42 else if (substr($line,0,4) == '----') { // HRule
43 $last =& $body->insert(new HRule());
45 else if ($head == ' ' or $head == "\t") { // Pre
46 $last =& $last->add(new Pre($line));
48 else if ($head == '*') { // Heading
49 $last =& $body->insert(new Heading($line, $contents));
52 if (substr($line,-1) == '~') {
55 if ($head == '-') { // UList
56 $last =& $last->add(new UList($line));
58 else if ($head == '+') { // OList
59 $last =& $last->add(new OList($line));
61 else if ($head == ':') { // DList
62 $last =& $last->add(new DList($line));
64 else if ($head == '|') { // Table
65 $last =& $last->add(new Table($line));
67 else if ($head == ',') { // Table(YukiWiki¸ß´¹)
68 $last =& $last->add(new YTable($line));
70 else if ($head == '>') { // BrockQuote
71 $last =& $last->add(new BQuote($line));
73 else if ($head == '<') { // BlockQuote end
74 $last =& bq_end($last, $line);
76 else if ($head == '#') { // Div
77 $last =& $last->add(new Div($line));
80 $last =& $last->add(new Inline($line));
84 $ret = $body->toString();
87 $ret = preg_replace("/<p>#contents<\/p>/",$contents->getContents(),$ret);
90 $ret = preg_replace('/#related/e','make_related($vars[\'page\'],TRUE)',$ret);
99 function setParent(&$parent)
101 $this->parent =& $parent;
105 class Inline extends Element
109 function Inline($text)
111 if (substr($text,0,1) == '~') { // ¹ÔƬ~¡£¥Ñ¥é¥°¥é¥Õ³«»Ï
112 $parent =& $this->parent;
113 $this = new Paragraph(substr($text,1));
114 $this->setParent($parent);
117 $this->text = (substr($text,0,1) == "\n") ? $text : inline2(inline($text));
122 return $this->insert($obj);
124 function &insert(&$obj)
126 return $this->parent->add($obj);
132 function toPara($class = '')
134 $obj = new Paragraph('',$class);
136 $this->setParent($obj);
140 class Block extends Element
142 var $elements; // Í×ÁǤÎÇÛÎó
145 $this->elements = array();
148 function &add(&$obj) // ¥¨¥ì¥á¥ó¥È¤òÄɲÃ
150 if ($this->canContain($obj)) {
151 return $this->insert($obj);
153 return $this->parent->add($obj);
155 function &insert(&$obj)
157 $obj->setParent($this);
158 $this->elements[] =& $obj;
159 if (isset($obj->last) and is_object($obj->last)) {
164 function canContain($obj)
171 if (isset($this->elements) and count($this->elements) > 0) {
172 foreach ($this->elements as $obj) {
173 $ret .= $obj->toString();
178 function wrap($string, $tag, $param = '')
180 return ($string == '') ? '' : "\n<$tag$param>$string</$tag>\n";
183 class Body extends Block
186 function &insert(&$obj)
188 if (is_a($obj,'Inline')) {
189 $obj =& $obj->toPara();
191 return parent::insert($obj);
194 class Paragraph extends Block
198 function Paragraph($text, $class = '')
201 $this->class = $class;
205 if (substr($text,0,1) == '~') {
206 $text = substr($text,1);
208 $this->elements[] =& new Inline($text);
210 function canContain($obj)
212 return is_a($obj,'Inline');
216 return $this->wrap(parent::toString(), 'p', $this->class);
220 class Heading extends Block
223 function Heading($text, &$contents)
226 preg_match("/^(\*{1,3})\s*(.*)$/",$text,$out) or die("Heading");
227 $this->level = strlen($out[1]) + 1;
228 list($this->text,$this->contents_str) = $contents->getAnchor($out[2], $this->level);
230 function canContain(&$obj)
236 return $this->wrap($this->text,'h'.$this->level, $this->contents_str);
239 class HRule extends Block
241 function canContain(&$obj)
252 class _List extends Block
255 var $step, $margin, $left_margin;
257 function _List($tag, $tag2, $level, $text)
261 $var_margin = "_{$tag}_margin";
262 $var_left_margin = "_{$tag}_left_margin";
263 global $$var_margin, $$var_left_margin;
264 $this->margin = $$var_margin;
265 $this->left_margin = $$var_left_margin;
270 $this->level = $level;
273 $this->insert(new Inline($text));
277 function canContain(&$obj)
279 return is_a($obj, '_List') ? ($this->tag == $obj->tag and $this->level == $obj->level) : TRUE;
281 function setParent(&$parent)
283 parent::setParent($parent);
284 $this->step = $this->level;
285 if (isset($parent->parent) and is_a($parent->parent,'_List')) {
286 $this->step -= $parent->parent->level;
289 function &insert(&$obj)
291 if (is_a($obj, get_class($this))) {
292 for ($n = 0; $n < count($obj->elements); $n++) {
293 $this->last =& parent::insert($obj->elements[$n]);
297 $obj =& new ListElement($obj, $this->level, $this->tag2); // wrap
299 return parent::insert($obj);
301 function toString($param='')
303 global $_list_left_margin, $_list_margin, $_list_pad_str;
305 $margin = $_list_margin * $this->step;
306 if ($this->level == $this->step) {
307 $margin += $_list_left_margin;
309 $style = sprintf($_list_pad_str,$this->level,$margin,$margin);
310 return $this->wrap(Block::toString(),$this->tag,$style.$param);
313 class ListElement extends Block
315 function ListElement(&$obj,$level,$head)
318 $this->level = $level;
322 if (isset($obj->last) and is_object($obj->last)) {
323 $this->last =& $obj->last;
326 function canContain(&$obj)
328 return !(is_a($obj, '_List') and ($obj->level <= $this->level));
332 return $this->wrap(parent::toString(), $this->head);
335 class UList extends _List
337 function UList($text)
339 preg_match("/^(\-{1,3})([\n]?.*)$/",$text,$out) or die("UList $text");
340 parent::_List('ul', 'li', strlen($out[1]), $out[2]);
343 class OList extends _List
345 function OList($text)
347 preg_match("/^(\+{1,3})(.*)$/",$text,$out) or die("OList");
348 parent::_List('ol', 'li', strlen($out[1]), $out[2]);
351 class DList extends _List
353 function DList($text)
355 if (!preg_match("/^(:{1,3})(.*)\|(.*)$/",$text,$out)) {
356 $this = new Inline($text);
359 parent::_List('dl', 'dd', strlen($out[1]), $out[3]);
361 array_unshift($this->elements,new Inline("\n<dt>".inline2(inline($out[2]))."</dt>\n"));
365 class BQuote extends Block
369 function BQuote($text)
372 preg_match("/^(\>{1,3})(.*)$/",$text,$out) or die("BQuote");
373 $this->level = strlen($out[1]);
374 $this->text = $out[2];
375 $this->last =& $this->insert(new Paragraph($this->text, ' class="quotation"'));
377 function canContain(&$obj)
379 if (!is_a($obj, get_class($this))) {
382 return ($this->level <= $obj->level);
384 function &insert(&$obj)
386 if (is_a($obj, 'BQuote') and $obj->level == $this->level) {
387 if (is_a($this->last,'Paragraph')) {
388 $this->last->insert($obj->elements[0]->elements[0]);
390 $this->last =& $this->insert($obj->elements[0]);
395 return parent::insert($obj);
399 return $this->wrap(parent::toString(),'blockquote');
402 function &bq_end(&$last, $text)
404 preg_match("/^(\<{1,3})(.*)$/",$text,$out) or die("bq_end");
405 $level = strlen($out[1]);
407 while (is_object($parent)) {
408 if (is_a($parent,'BQuote') and $parent->level == $level) {
409 return $parent->parent->insert(new Inline($out[2]));
411 $parent =& $parent->parent;
413 return $last->insert(new Inline($text));
415 class Table extends Block
417 var $col,$head,$foot;
420 function Table($text)
423 if (!preg_match("/^\|(.+)\|([hHfFcC]?)$/",$text,$out)) {
424 $this = new Inline($text);
427 $this->elements = array();
428 $cells = explode('|',$out[1]);
429 $this->level = count($cells);
430 $char = strtolower($out[2]);
432 $this->col =& new Col($cells);
435 $this->insert(new Row($cells,($char == 'h' ? 0 : ($char == 'f' ? 1 : 2))));
438 function canContain(&$obj)
440 return is_a($obj, 'Table') and $obj->level == $this->level;
442 function &insert(&$obj)
444 if (is_a($obj, 'Table')) {
445 if (isset($obj->col) and is_object($obj->col)) {
446 $this->col = $obj->col;
449 $obj =& $obj->elements[0];
450 $last = count($this->elements) - 1;
451 for ($n = 0; $n < count($obj->elements); $n++) {
452 if ($obj->elements[$n] != '~') {
455 $obj->type = $this->elements[$last]->type;
456 for ($m = $last; $m >= 0; $m--) {
457 if ($this->elements[$m]->elements[$n] == '~') {
460 $this->elements[$m]->row[$n]++;
465 $this->elements[] = $obj;
471 if (isset($this->col) and is_object($this->col)) {
474 $string = $col ? $this->col->toString() : '';
475 $part = array(0=>'thead',1=>'tfoot',2=>'tbody');
476 foreach ($part as $type=>$str) {
478 foreach ($this->elements as $row) {
479 if ($row->type != $type) {
482 $tmp .= $row->toString($col);
485 $string .= $this->wrap($tmp,$str);
492 <table class="style_table" cellspacing="1" border="0">
501 class Row extends Block
505 function Row($cells,$type='')
508 $this->elements = $cells;
511 for ($n = 0; $n < count($cells); $n++) {
513 if ($cells[$n] == '>') {
518 $this->col[$n] = $span;
523 function toString($obj)
526 for ($n = 0; $n < count($this->elements); $n++) {
527 $cell = $this->elements[$n];
528 if ($cell == '>' or $cell == '~') {
532 if ($this->row[$n] > 1) {
533 $row = " rowspan=\"{$this->row[$n]}\"";
535 if ($this->col[$n] > 1) {
536 $col = " colspan=\"{$this->col[$n]}\"";
538 $align = $width = '';
539 if (is_object($obj)) {
540 $align = $obj->align[$n];
541 if ($this->col[$n] == 1) {
542 $width = $obj->width[$n];
545 if (preg_match("/^(LEFT|CENTER|RIGHT):(.*)$/",$cell,$out)) {
546 $align = strtolower($out[1]);
549 if (preg_match('/^~(.+)$/',$cell,$matches)) {
550 $tag = 'th'; $cell = $matches[1];
555 $style = $width == '' ? '' : 'width:'.$width.'px;';
556 $style.= $align == '' ? '' : 'text-align:'.$align.';';
557 $style = $style == '' ? '' : ' style="'.$style.'"';
558 $cells .= "\n<$tag class=\"style_$tag\"$style$row$col>".inline2(inline($cell))."</$tag>\n";
560 return $this->wrap($cells,'tr');
563 class Col extends Row
570 $align = $width = '';
571 for ($n = count($this->elements) - 1; $n >= 0; $n--) {
572 if ($cells[$n] == '') {
573 $align = $width = '';
575 else if ($cells[$n] != '>') {
576 if (preg_match("/^(LEFT|CENTER|RIGHT):(.*)$/",$cells[$n],$out)) {
577 $align = strtolower($out[1]);
578 $width = htmlspecialchars($out[2]);
581 $this->align[$n] = $align;
582 $this->width[$n] = $width;
588 for ($n = 0; $n < count($this->elements); $n++) {
589 $cell = $this->elements[$n];
593 $span = " span=\"{$this->col[$n]}\"";
594 $align = $this->align[$n] == '' ? '' : ' align="'.$this->align[$n].'"';
595 $width = $this->width[$n] == '' ? '' : ' width="'.$this->width[$n].'"';
596 $cells .= "\n<colgroup$span$align$width></colgroup>\n";
601 class YTable extends Block
605 function YTable($text)
608 if (!preg_match_all('/("[^"]*(?:""[^"]*)*"|[^,]*),/',"$text,",$out)) {
609 $this = new Inline($text);
612 array_shift($out[1]);
614 foreach ($out[1] as $val) {
615 $_value[] = preg_match('/^"(.*)"$/',$val,$matches) ? str_replace('""','"',$matches[1]) : $val;
619 foreach($_value as $val) {
620 if (preg_match('/^(\s+)?(.+?)(\s+)?$/',$val,$matches)) {
621 $align[] =($matches[1] != '') ?
622 ((array_key_exists(3,$matches) and $matches[3] != '') ? ' style="text-align:center"' : ' style="text-align:right"') : '';
623 $value[] = $matches[2];
630 $this->col = count($value);
632 foreach ($value as $val) {
633 $colspan[] = ($val == '==') ? 0 : 1;
636 for ($i = 0; $i < count($value); $i++) {
638 while ($i + $colspan[$i] < count($value) and $value[$i + $colspan[$i]] == '==') {
641 $colspan[$i] = ($colspan[$i] > 1) ? " colspan=\"{$colspan[$i]}\"" : '';
642 $str .= "<td class=\"style_td\"{$align[$i]}{$colspan[$i]}>".inline2(inline($value[$i])).'</td>';
645 $this->elements[] = $str;
647 function canContain(&$obj)
649 return is_a($obj, 'YTable') and $obj->col == $this->col;
651 function &insert(&$obj)
653 $this->elements[] = $obj->elements[0];
659 foreach ($this->elements as $str) {
660 $rows .= "\n<tr class=\"style_tr\">$str</tr>\n";
665 <table class="style_table" cellspacing="1" border="0">
674 class Pre extends Block
681 while (preg_match('/^([^\t]*)(\t+)(.+)$/',$text,$m)) {
682 $text = $m[1].str_repeat(' ',strlen($m[2]) * $tab - strlen($m[1]) % $tab).$m[3];
684 $this->elements[] = htmlspecialchars($text,ENT_NOQUOTES);
686 function canContain(&$obj)
688 return is_a($obj, 'Pre');
690 function &insert(&$obj)
692 $this->elements[] = $obj->elements[0];
697 return $this->wrap(join("\n",$this->elements),'pre');
700 class Div extends Block
709 function canContain(&$obj)
715 if (preg_match("/^\#([^\(]+)(.*)$/",$this->text,$out) and exist_plugin_convert($out[1])) {
717 $_plugin = preg_replace("/^\#([^\(]+)\((.*)\)$/ex","do_plugin_convert('$1','$2')",$this->text);
720 $_plugin = preg_replace("/^\#([^\(]+)$/ex","do_plugin_convert('$1','$2')",$this->text);
722 $text = "\t$_plugin";
725 $text = "\n<p>".htmlspecialchars($this->text)."</p>\n";
730 class Align extends Body
731 { // LEFT:/CENTER:/RIGHT:
734 function Align($align)
736 $this->align = $align;
740 $string = parent::toString();
742 if (preg_match('/^(\s*<[^>]+style=")([^"]+)"/',$string,$matches)) {
743 $string = $matches[1]."text-align:{$this->align};".$matches[2];
746 $string = preg_replace('/^(\s*<[a-z]+)/', '$1 style="text-align:'.$this->align.';"',$string);
755 var $id,$count,$top,$contents,$last;
757 function Contents($id)
763 $this->top = "<a href=\"#contents_$id\">$top</a>";
764 $this->contents =& new Block();
765 $this->last =& $this->contents;
767 function getAnchor($text,$level)
769 $content_str = "content_{$this->id}_{$this->count}";
770 $this->last =& $this->last->add(new Contents_UList($text,$this->id,$level,$content_str));
772 return array(inline2(inline($text)).$this->top," id=\"{$content_str}\"");
774 function getContents()
776 global $strip_link_wall;
778 $contents = "<a id=\"contents_{$this->id}\"></a>";
779 $contents .= $this->contents->toString();
780 if ($strip_link_wall) {
781 $contents = preg_replace("/\[\[([^\]]+)\]\]/","$1",$contents);
786 class Contents_UList extends _List
790 function Contents_UList($text,$id,$level,$content_str)
793 // ¥Æ¥¥¹¥È¤Î¥ê¥Õ¥©¡¼¥à
794 // ¹ÔƬ\n¤ÇÀ°·ÁºÑ¤ß¤òɽ¤¹ ... X(
795 $text = "\n<a href=\"#{$content_str}\">".
796 strip_htmltag(inline2(inline($text,TRUE))).
798 parent::_List('ul', 'li', --$level, $text);