コミットメタ情報

リビジョン33b86fab9ef39c4010e29eeaca630512d131ea46 (tree)
日時2003-01-27 14:44:11
作者panda <panda>
コミッターpanda

ログメッセージ

PukiWiki/1.4 first beta release

変更サマリ

差分

--- /dev/null
+++ b/convert_html.php
@@ -0,0 +1,755 @@
1+<?php
2+/////////////////////////////////////////////////
3+// PukiWiki - Yet another WikiWikiWeb clone.
4+//
5+// $Id: convert_html.php,v 1.1 2003/01/27 05:44:11 panda Exp $
6+//
7+
8+function convert_html($string)
9+{
10+ global $script,$vars,$digest;
11+ static $contents_id = 0;
12+
13+ $contents = new Contents(++$contents_id);
14+
15+ $string = rtrim($string);
16+ $string = preg_replace("/^#freeze\n/","","$string\n"); // 凍結指示子除去
17+ $string = preg_replace("/\n\/\/[^\n]*/","", "\n$string"); // コメント除去
18+ $string = preg_replace("/\n\n+/","\n\n\n", $string); // 空行の調整
19+ $string = preg_replace("/(?<=[\r\n])(?!\s)([^\n]*~)\n/", "$1\r", "\n$string");
20+
21+ $lines = split("\n", $string);
22+
23+ $digest = md5(@join('',get_source($vars['page'])));
24+
25+ $body = new Body();
26+ $last =& $body->insert(new Paragraph(''));
27+
28+ foreach ($lines as $line) {
29+ if (substr($line,0,2) == '//') { //コメントは処理しない
30+ continue;
31+ }
32+
33+ $align = '';
34+ if (preg_match('/^(LEFT|CENTER|RIGHT):(.*)$/',$line,$matches)) {
35+ $last =& $last->add(new Align(strtolower($matches[1]))); // <div style="text-align:...">
36+ if ($matches[2] == '') {
37+ continue;
38+ }
39+ $line = $matches[2];
40+ }
41+
42+ // 行頭文字
43+ $head = substr($line,0,1);
44+ if ($line == '') { $last =& $body; } // 空行
45+ else if (rtrim($line) == '----') {
46+ $last =& $body->insert(new HRule()); } // HRule
47+ else if ($head == '*') {
48+ $last =& $body->insert(new Heading($line, $contents)); } // Heading
49+ else if ($head == '-') { $last =& $last->add(new UList($line)); } // UList
50+ else if ($head == '+') { $last =& $last->add(new OList($line)); } // OList
51+ else if ($head == ':') { $last =& $last->add(new DList($line)); } // DList
52+ else if ($head == '|') { $last =& $last->add(new Table($line)); } // Table
53+ else if ($head == ',') { $last =& $last->add(new YTable($line)); } // Table(YukiWiki互換)
54+ else if ($head == ' ' or $head == "\t")
55+ { $last =& $last->add(new Pre($line)); } // Pre
56+ else if ($head == '>') { $last =& $last->add(new BQuote($line)); } // BrockQuote
57+ else if ($head == '<') { $last =& bq_end($last, $line); } // BlockQuote end
58+ else if ($head == '#') { $last =& $last->add(new Div($line)); } // Div
59+ else { $last =& $last->add(new Inline($line)); } // 段落
60+ }
61+ $ret = $body->toArray();
62+// $ret = inline2($ret);
63+ $ret = $contents->replaceContents($ret);
64+
65+ return join("\n",$ret);
66+
67+}
68+
69+class Element
70+{
71+ var $parent;
72+
73+ function setParent(&$parent)
74+ {
75+ $this->parent =& $parent;
76+ }
77+}
78+
79+class Inline extends Element
80+{ // インライン要素
81+ var $text;
82+
83+ function Inline($text)
84+ {
85+ if (substr($text,0,1) == '~') { // 行頭~。パラグラフ開始
86+ $parent =& $this->parent;
87+ $this = new Paragraph(" ".substr($text,1));
88+ $this->setParent($parent);
89+ }
90+ else {
91+ $this->text = trim((preg_match("/^\n/", $text)) ? $text : inline($text));
92+ }
93+ }
94+ function &add(&$obj)
95+ {
96+ return $this->insert($obj);
97+ }
98+ function &insert(&$obj)
99+ {
100+ return $this->parent->add($obj);
101+ }
102+ function toArray()
103+ {
104+ return ($this->text == '') ? array() : array(inline2($this->text));
105+ }
106+ function toPara($class = '')
107+ {
108+ $obj = new Paragraph('',$class);
109+ $obj->insert($this);
110+ $this->setParent($obj);
111+ return $obj;
112+ }
113+}
114+class Block extends Element
115+{ // ブロック要素
116+ var $elements; // 要素の配列
117+
118+ function Block() {
119+ $this->elements = array();
120+ }
121+
122+ function &add(&$obj) // エレメントを追加
123+ {
124+ if ($this->canContain($obj)) {
125+ return $this->insert($obj);
126+ }
127+ return $this->parent->add($obj);
128+ }
129+ function &insert(&$obj)
130+ {
131+ $obj->setParent($this);
132+ $this->elements[] =& $obj;
133+ if (isset($obj->last) and is_object($obj->last)) {
134+ return $obj->last;
135+ }
136+ return $obj;
137+ }
138+ function canContain($obj)
139+ {
140+ return TRUE;
141+ }
142+ function toArray()
143+ {
144+ $arr = array();
145+ if (isset($this->elements) and count($this->elements) > 0) {
146+ foreach ($this->elements as $obj) {
147+ array_splice($arr, count($arr), 0, $obj->toArray());
148+ }
149+ }
150+ return $arr;
151+ }
152+ function wrap($arr, $tag, $param = '')
153+ {
154+ if (count($arr) > 0) {
155+ array_unshift($arr,"<$tag$param>");
156+ array_push($arr,"</$tag>");
157+ }
158+ return $arr;
159+ }
160+}
161+class Body extends Block
162+{ // Body
163+
164+ function &insert(&$obj)
165+ {
166+ if (is_a($obj,'Inline')) {
167+ $obj =& $obj->toPara();
168+ }
169+ return parent::insert($obj);
170+ }
171+}
172+class Paragraph extends Block
173+{ // 段落
174+ var $class;
175+
176+ function Paragraph($text, $class = '')
177+ {
178+ parent::Block();
179+ $this->class = $class;
180+ if ($text == '') {
181+ return;
182+ }
183+ if (substr($text,0,1) == '~') {
184+ $text = substr($text,1);
185+ }
186+ $this->elements[] =& new Inline($text);
187+ }
188+ function canContain($obj)
189+ {
190+ return is_a($obj,'Inline');
191+ }
192+ function toArray()
193+ {
194+ return $this->wrap(parent::toArray(), 'p', $this->class);
195+ }
196+}
197+
198+class Heading extends Block
199+{ // *
200+ function Heading($text, &$contents)
201+ {
202+ parent::Block();
203+ preg_match("/^(\*{1,3})\s*(.*)$/",$text,$out) or die("Heading");
204+ $this->level = strlen($out[1]) + 1;
205+ list($this->text,$this->contents_str) = $contents->getAnchor($out[2], $this->level);
206+ }
207+ function canContain(&$obj)
208+ {
209+ return FALSE;
210+ }
211+ function toArray()
212+ {
213+ return $this->wrap(array($this->text),'h'.$this->level, $this->contents_str);
214+ }
215+}
216+class HRule extends Block
217+{ // ----
218+ function canContain(&$obj)
219+ {
220+ return FALSE;
221+ }
222+ function toArray()
223+ {
224+ global $hr;
225+
226+ return array($hr);
227+ }
228+}
229+class _List extends Block
230+{
231+ var $level;
232+ var $step, $margin, $left_margin;
233+
234+ function _List($tag, $tag2, $level, $text)
235+ {
236+ parent::Block();
237+ //マージンを取得
238+ $var_margin = "_{$tag}_margin";
239+ $var_left_margin = "_{$tag}_left_margin";
240+ global $$var_margin, $$var_left_margin;
241+ $this->margin = $$var_margin;
242+ $this->left_margin = $$var_left_margin;
243+
244+ //初期化
245+ $this->tag = $tag;
246+ $this->tag2 = $tag2;
247+ $this->level = $level;
248+
249+ if ($text != '') {
250+ $this->insert(new Inline($text));
251+ }
252+ }
253+
254+ function canContain(&$obj)
255+ {
256+ return is_a($obj, '_List') ? ($this->tag == $obj->tag and $this->level == $obj->level) : TRUE;
257+ }
258+ function setParent(&$parent)
259+ {
260+ parent::setParent($parent);
261+ $this->step = $this->level;
262+ if (isset($parent->parent) and is_a($parent->parent,'_List')) {
263+ $this->step -= $parent->parent->level;
264+ }
265+ }
266+ function &insert(&$obj)
267+ {
268+ if (is_a($obj, get_class($this))) {
269+ for ($n = 0; $n < count($obj->elements); $n++) {
270+ $this->last =& parent::insert($obj->elements[$n]);
271+ }
272+ return $this->last;
273+ }
274+ else {
275+ $obj =& new ListElement($obj, $this->level, $this->tag2); // wrap
276+ }
277+ $this->last =& $obj;
278+ return parent::insert($obj);
279+ }
280+ function toArray($param='')
281+ {
282+ global $_list_left_margin, $_list_margin, $_list_pad_str;
283+
284+ $margin = $_list_margin * $this->step;
285+ if ($this->level == $this->step) {
286+ $margin += $_list_left_margin;
287+ }
288+ $style = sprintf($_list_pad_str,$this->level,$margin,$margin);
289+ return $this->wrap(Block::toArray(),$this->tag,$style.$param);
290+ }
291+}
292+class ListElement extends Block
293+{
294+ function ListElement($obj,$level,$head)
295+ {
296+ parent::Block();
297+ $this->level = $level;
298+ $this->head = $head;
299+ $this->insert($obj);
300+ }
301+ function canContain(&$obj)
302+ {
303+ return !(is_a($obj, '_List') and ($obj->level <= $this->level));
304+ }
305+ function toArray()
306+ {
307+ return $this->wrap(parent::toArray(), $this->head);
308+ }
309+}
310+class UList extends _List
311+{ // -
312+ function UList($text)
313+ {
314+ preg_match("/^(\-{1,3})([\n]?.*)$/",$text,$out) or die("UList $text");
315+ parent::_List('ul', 'li', strlen($out[1]), $out[2]);
316+ }
317+}
318+class OList extends _List
319+{ // +
320+ function OList($text)
321+ {
322+ preg_match("/^(\+{1,3})(.*)$/",$text,$out) or die("OList");
323+ parent::_List('ol', 'li', strlen($out[1]), $out[2]);
324+ }
325+}
326+class DList extends _List
327+{ // :
328+ function DList($text)
329+ {
330+ if (!preg_match("/^(:{1,3})(.*)\|(.*)$/",$text,$out)) {
331+ $this = new Inline($text);
332+ return;
333+ }
334+ parent::_List('dl', 'dd', strlen($out[1]), $out[3]);
335+ if ($out[2] != '') {
336+ array_unshift($this->elements,new Inline("\n".'<dt>'.inline($out[2]).'</dt>'));
337+ }
338+ }
339+}
340+class BQuote extends Block
341+{ // >
342+ function BQuote($text)
343+ {
344+ parent::Block();
345+ preg_match("/^(\>{1,3})(.*)$/",$text,$out) or die("BQuote");
346+ $this->level = strlen($out[1]);
347+ $this->text = $out[2];
348+ $this->insert(new Paragraph($this->text, ' class="quotation"'));
349+ }
350+ function canContain(&$obj)
351+ {
352+ if (!is_a($obj, get_class($this))) {
353+ return TRUE;
354+ }
355+ return ($this->level <= $obj->level);
356+ }
357+ function &insert(&$obj)
358+ {
359+ if (is_a($obj, 'BQuote') and $obj->level == $this->level) {
360+ $obj =& $obj->elements[0];
361+ }
362+ else if (is_a($obj,'Inline')) {
363+ $obj = $obj->toPara('quotation');
364+ }
365+ $this->last =& $obj;
366+ return parent::insert($obj);
367+ }
368+ function toArray()
369+ {
370+ return $this->wrap(parent::toArray(),'blockquote');
371+ }
372+}
373+function &bq_end(&$last, $text)
374+{
375+ preg_match("/^(\<{1,3})(.*)$/",$text,$out) or die("bq_end");
376+ $level = strlen($out[1]);
377+ $parent =& $last;
378+ while (is_object($parent)) {
379+ if (is_a($parent,'BQuote') and $parent->level == $level) {
380+ return $parent->parent->insert(new Inline($out[2]));
381+ }
382+ $parent =& $parent->parent;
383+ }
384+ return $last->insert(new Inline($text));
385+}
386+class Table extends Block
387+{ // |
388+ var $col;
389+
390+ function Table($text)
391+ {
392+ parent::Block();
393+ if (!preg_match("/^\|(.+)\|([hHfFcC]?)$/",$text,$out)) {
394+ $this = new Inline($text);
395+ return;
396+ }
397+ $this->elements = array();
398+ $cells = explode('|',$out[1]);
399+ $this->level = count($cells);
400+ $char = strtolower($out[2]);
401+ if ($char == 'c') {
402+ $this->col =& new Col($cells);
403+ }
404+ else {
405+ $this->insert(new Row($cells,($char == 'h' ? 0 : ($char == 'f' ? 1 : 2))));
406+ }
407+ }
408+ function canContain(&$obj)
409+ {
410+ return is_a($obj, 'Table') and $obj->level == $this->level;
411+ }
412+ function &insert(&$obj)
413+ {
414+ if (is_a($obj, 'Table')) {
415+ if (isset($obj->col) and is_object($obj->col)) {
416+ $this->col = $obj->col;
417+ return $this;
418+ }
419+ $obj =& $obj->elements[0];
420+ $last = count($this->elements) - 1;
421+ for ($n = 0; $n < count($obj->elements); $n++) {
422+ if ($obj->elements[$n] != '~') {
423+ continue;
424+ }
425+ $obj->type = $this->elements[$last]->type;
426+ for ($m = $last; $m >= 0; $m--) {
427+ if ($this->elements[$m]->elements[$n] == '~') {
428+ continue;
429+ }
430+ $this->elements[$m]->row[$n]++;
431+ break;
432+ }
433+ }
434+ }
435+ $this->elements[] = $obj;
436+ return $this;
437+ }
438+ function toArray()
439+ {
440+ $col = NULL;
441+ if (isset($this->col) and is_object($this->col)) {
442+ $col =& $this->col;
443+ }
444+ $arr = $col ? $this->col->toArray() : array();
445+ $part = array(0=>'thead',1=>'tfoot',2=>'tbody');
446+ foreach ($part as $type=>$str) {
447+ $tmp = array();
448+ foreach ($this->elements as $row) {
449+ if ($row->type != $type) {
450+ continue;
451+ }
452+ $tmp = array_merge($tmp,$row->toArray($col));
453+ }
454+ if (count($tmp) > 0) {
455+ $arr = array_merge($arr,$this->wrap($tmp,$str));
456+ }
457+ }
458+ if (count($arr) > 0) {
459+ array_unshift($arr, '<div class="ie5">','<table class="style_table" cellspacing="1" border="0">');
460+ array_push($arr,'</table>','</div>');
461+ }
462+ return $arr;
463+ }
464+}
465+class Row extends Block
466+{
467+ var $col,$row,$type;
468+
469+ function Row($cells,$type='')
470+ {
471+ parent::Block();
472+ $this->elements = $cells;
473+ $this->type = $type;
474+ $span = 1;
475+ for ($n = 0; $n < count($cells); $n++) {
476+ $this->row[$n] = 1;
477+ if ($cells[$n] == '>') {
478+ $this->col[$n] = 0;
479+ $span++;
480+ }
481+ else {
482+ $this->col[$n] = $span;
483+ $span = 1;
484+ }
485+ }
486+ }
487+ function toArray($obj)
488+ {
489+ $cells = array();
490+ for ($n = 0; $n < count($this->elements); $n++) {
491+ $cell = $this->elements[$n];
492+ if ($cell == '>' or $cell == '~') {
493+ continue;
494+ }
495+ $row = $col = '';
496+ if ($this->row[$n] > 1) {
497+ $row = " rowspan=\"{$this->row[$n]}\"";
498+ }
499+ if ($this->col[$n] > 1) {
500+ $col = " colspan=\"{$this->col[$n]}\"";
501+ }
502+ $align = $width = '';
503+ if (is_object($obj)) {
504+ $align = $obj->align[$n];
505+ if ($this->col[$n] == 1) {
506+ $width = $obj->width[$n];
507+ }
508+ }
509+ if (preg_match("/^(LEFT|CENTER|RIGHT):(.*)$/",$cell,$out)) {
510+ $align = strtolower($out[1]);
511+ $cell = $out[2];
512+ }
513+ if (preg_match('/^~(.+)$/',$cell,$matches)) {
514+ $tag = 'th'; $cell = $matches[1];
515+ }
516+ else {
517+ $tag = 'td';
518+ }
519+ $style = $width == '' ? '' : 'width:'.$width.'px;';
520+ $style.= $align == '' ? '' : 'text-align:'.$align.';';
521+ $style = $style == '' ? '' : ' style="'.$style.'"';
522+ $cells[] = "<$tag class=\"style_$tag\"$style$row$col>".inline2(inline($cell))."</$tag>";
523+ }
524+ return $this->wrap($cells,'tr');
525+ }
526+}
527+class Col extends Row
528+{
529+ var $width,$align;
530+
531+ function Col($cells)
532+ {
533+ parent::Row($cells);
534+ $align = $width = '';
535+ for ($n = count($this->elements) - 1; $n >= 0; $n--) {
536+ if ($cells[$n] == '') {
537+ $align = $width = '';
538+ }
539+ else if ($cells[$n] != '>') {
540+ if (preg_match("/^(LEFT|CENTER|RIGHT):(.*)$/",$cells[$n],$out)) {
541+ $align = strtolower($out[1]);
542+ $cell = $out[2];
543+ }
544+ $width = htmlspecialchars($cell);
545+ }
546+ $this->align[$n] = $align;
547+ $this->width[$n] = $width;
548+ }
549+ }
550+ function toArray()
551+ {
552+ $cells = array();
553+ for ($n = 0; $n < count($this->elements); $n++) {
554+ $cell = $this->elements[$n];
555+ if ($cell == '>') {
556+ continue;
557+ }
558+ $span = " span=\"{$this->col[$n]}\"";
559+ $align = $this->align[$n] == '' ? '' : ' align="'.$this->align[$n].'"';
560+ $width = $this->width[$n] == '' ? '' : ' width="'.$this->width[$n].'"';
561+ $cells[] = "<colgroup$span$align$width></colgroup>";
562+ }
563+ return $cells;
564+ }
565+}
566+class YTable extends Block
567+{ // ,
568+ var $col;
569+
570+ function YTable($text)
571+ {
572+ parent::Block();
573+ if (!preg_match_all('/("[^"]*(?:""[^"]*)*"|[^,]*),/',"$text,",$out)) {
574+ $this = new Inline($text);
575+ return;
576+ }
577+ array_shift($out[1]);
578+ $_value = array();
579+ foreach ($out[1] as $val) {
580+ $_value[] = preg_match('/^"(.*)"$/',$val,$matches) ? str_replace('""','"',$matches[1]) : $val;
581+ }
582+ $align = array();
583+ $value = array();
584+ foreach($_value as $val) {
585+ if (preg_match('/^(\s+)?(.+?)(\s+)?$/',$val,$matches)) {
586+ $align[] =($matches[1] != '') ?
587+ ((array_key_exists(3,$matches) and $matches[3] != '') ? ' style="text-align:center"' : ' style="text-align:right"') : '';
588+ $value[] = $matches[2];
589+ }
590+ else {
591+ $align[] = '';
592+ $value[] = $val;
593+ }
594+ }
595+ $this->col = count($value);
596+ $colspan = array();
597+ foreach ($value as $val) {
598+ $colspan[] = ($val == '==') ? 0 : 1;
599+ }
600+ $str = '';
601+ for ($i = 0; $i < count($value); $i++) {
602+ if ($colspan[$i]) {
603+ while ($i + $colspan[$i] < count($value) and $value[$i + $colspan[$i]] == '==') {
604+ $colspan[$i]++;
605+ }
606+ $colspan[$i] = ($colspan[$i] > 1) ? " colspan=\"{$colspan[$i]}\"" : '';
607+ $str .= "<td class=\"style_td\"{$align[$i]}{$colspan[$i]}>".inline2(inline($value[$i])).'</td>';
608+ }
609+ }
610+ $this->elements[] = $str;
611+ }
612+ function canContain(&$obj)
613+ {
614+ return is_a($obj, 'YTable') and $obj->col == $this->col;
615+ }
616+ function &insert(&$obj)
617+ {
618+ $this->elements[] = $obj->elements[0];
619+ return $this;
620+ }
621+ function toArray()
622+ {
623+ $arr = array();
624+ foreach ($this->elements as $str) {
625+ $arr[] = '<tr class="style_tr">';
626+ $arr[] = $str;
627+ $arr[] = '</tr>';
628+ }
629+ array_unshift($arr, '<div class="ie5">','<table class="style_table" cellspacing="1" border="0">');
630+ array_push($arr,'</table>','</div>');
631+ return $arr;
632+ }
633+}
634+class Pre extends Block
635+{ // ' '
636+
637+ function Pre($text)
638+ {
639+ parent::Block();
640+ $tab = 8;
641+ while (preg_match('/^([^\t]*)(\t+)(.+)$/',$text,$m)) {
642+ $text = $m[1].str_repeat(' ',strlen($m[2]) * $tab - strlen($m[1]) % $tab).$m[3];
643+ }
644+ $this->elements[] = htmlspecialchars($text,ENT_NOQUOTES);
645+ }
646+ function canContain(&$obj)
647+ {
648+ return is_a($obj, 'Pre');
649+ }
650+ function &insert(&$obj)
651+ {
652+ $this->elements[] = $obj->elements[0];
653+ return $this;
654+ }
655+ function toArray()
656+ {
657+ return $this->wrap($this->elements,'pre');
658+ }
659+}
660+class Div extends Block
661+{ // #
662+ var $text;
663+
664+ function Div($text)
665+ {
666+ parent::Block();
667+ $this->text = $text;
668+ }
669+ function canContain(&$obj)
670+ {
671+ return FALSE;
672+ }
673+ function toArray()
674+ {
675+ if (preg_match("/^\#([^\(]+)(.*)$/",$this->text,$out) and exist_plugin_convert($out[1])) {
676+ if ($out[2]) {
677+ $_plugin = preg_replace("/^\#([^\(]+)\((.*)\)$/ex","do_plugin_convert('$1','$2')",$this->text);
678+ }
679+ else {
680+ $_plugin = preg_replace("/^\#([^\(]+)$/ex","do_plugin_convert('$1','$2')",$this->text);
681+ }
682+ $text = "\t$_plugin";
683+ }
684+ else {
685+ $text = '<p>'.htmlspecialchars($this->text).'</p>';
686+ }
687+ return array($text);
688+ }
689+}
690+class Align extends Body
691+{ // LEFT:/CENTER:/RIGHT:
692+ var $align;
693+
694+ function Align($align)
695+ {
696+ $this->align = $align;
697+ }
698+ function toArray()
699+ {
700+ $arr = parent::toArray();
701+ if (count($arr)) {
702+ if (preg_match('/^(.+)style="(.+)$/',$arr[0],$matches)) {
703+ $arr[0] = $matches[1].'style="text-align:'.$this->align.'; '.$matches[2];
704+ }
705+ else {
706+ $arr[0] = preg_replace('/(<[a-z]+)/', '$1 style="text-align:'.$this->align.';"',$arr[0]);
707+ }
708+ }
709+ return $arr;
710+ }
711+}
712+//見出しの一覧関係
713+class Contents
714+{
715+ var $id,$count,$top,$contents,$last;
716+ function Contents($id)
717+ {
718+ global $top;
719+ $this->id = $id;
720+ $this->count = 0;
721+ $this->top = "<a href=\"#contents_$id\">$top</a>";
722+ $this->contents =& new Block();
723+ $this->last =& $this->contents;
724+ }
725+ function getAnchor($text,$level)
726+ {
727+ $content_str = "content_{$this->id}_{$this->count}";
728+ $this->last =& $this->last->add(new Contents_UList($text,$this->id,$level,$content_str));
729+ $this->count++;
730+ return array(inline2(inline($text)).$this->top," id=\"{$content_str}\"");
731+ }
732+ function replaceContents($text)
733+ {
734+ global $strip_link_wall;
735+
736+ $contents = "<a id=\"contents_{$this->id}\"></a>";
737+ $contents .= join("\n",$this->contents->toArray());
738+ if($strip_link_wall) {
739+ $contents = preg_replace("/\[\[([^\]]+)\]\]/","$1",$contents);
740+ }
741+ return preg_replace("/^<p>#contents<\/p>/",$contents,$text);
742+ }
743+}
744+class Contents_UList extends _List
745+{ // -
746+ function Contents_UList($text,$id,$level,$content_str)
747+ {
748+ $this->id = $id;
749+ // テキストのリフォーム
750+ $text = "\n<a href=\"#{$content_str}\">".
751+ strip_htmltag(make_user_rules(inline($text,TRUE))).'</a>';
752+ parent::_List('ul', 'li', --$level, $text);
753+ }
754+}
755+?>
--- /dev/null
+++ b/diff.php
@@ -0,0 +1,256 @@
1+<?php
2+/////////////////////////////////////////////////
3+// PukiWiki - Yet another WikiWikiWeb clone.
4+//
5+// $Id: diff.php,v 1.1 2003/01/27 05:44:11 panda Exp $
6+//
7+
8+//衝突時に対応表を出す
9+define('DIFF_SHOW_TABLE',TRUE);
10+
11+// 差分の作成
12+function do_diff($strlines1,$strlines2)
13+{
14+ $obj = new line_diff();
15+ return $obj->str_compare($strlines1,$strlines2);
16+}
17+
18+// 差分の作成(更新の衝突)
19+function do_update_diff($pagestr,$poststr,$original)
20+{
21+// $obj = new line_diff('+','!','');
22+// $body = $obj->str_compare($oldstr,$newstr);
23+// $auto = ($obj->delete_count == 0 and $obj->add_count == 0);
24+
25+ $obj = new line_diff();
26+
27+ $obj->set_str('left',$original,$pagestr);
28+ $obj->compare();
29+ $diff1 = $obj->toArray();
30+
31+ $obj->set_str('right',$original,$poststr);
32+ $obj->compare();
33+ $diff2 = $obj->toArray();
34+
35+ $arr = $obj->arr_compare('all',$diff1,$diff2);
36+
37+ if (DIFF_SHOW_TABLE) {
38+ global $do_update_diff_table;
39+ $do_update_diff_table = '<p>l : base → pagedata<br />r : base → postdata</p>'."\n";
40+ $do_update_diff_table .= '<table border="1"><tr><th>l</th><th>r</th><th>text</th></tr>'."\n";
41+ foreach ($arr as $_obj) {
42+ $do_update_diff_table .= '<tr><td>'.$_obj->get('left').'</td><td>'.$_obj->get('right').'</td><td>'.htmlspecialchars($_obj->text()).'</td></tr>'."\n";
43+ }
44+ $do_update_diff_table .= '</table>'."\n";
45+ }
46+
47+ $body = '';
48+ foreach ($arr as $_obj) {
49+ if ($_obj->get('left') != '-' and $_obj->get('right') != '-') {
50+ $body .= $_obj->text();
51+ }
52+ }
53+
54+ $auto = 1;
55+
56+ return array(rtrim($body)."\n",$auto);
57+}
58+
59+/*
60+line_diffクラス
61+
62+以下の情報を参考にして作成しました。
63+
64+S. Wu, <A HREF="http://www.cs.arizona.edu/people/gene/vita.html">
65+E. Myers,</A> U. Manber, and W. Miller,
66+<A HREF="http://www.cs.arizona.edu/people/gene/PAPERS/np_diff.ps">
67+"An O(NP) Sequence Comparison Algorithm,"</A>
68+Information Processing Letters 35, 6 (1990), 317-323.
69+
70+*/
71+
72+class line_diff
73+{
74+ var $arr1,$arr2,$m,$n,$pos,$key,$plus,$minus,$equal,$reverse;
75+
76+ function line_diff($plus='+',$minus='-',$equal=' ')
77+ {
78+ $this->plus = $plus;
79+ $this->minus = $minus;
80+ $this->equal = $equal;
81+ }
82+ function arr_compare($key,$arr1,$arr2)
83+ {
84+ $this->key = $key;
85+// array_unshift($arr1,'');
86+// array_unshift($arr2,'');
87+ $this->arr1 = $arr1;
88+ $this->arr2 = $arr2;
89+ $this->compare();
90+ $arr = $this->toArray();
91+// array_shift($arr);
92+ return $arr;
93+ }
94+ function set_str($key,$str1,$str2)
95+ {
96+ $this->key = $key;
97+ preg_match_all("/[^\n]*\n*/",preg_replace("/\r/",'',$str1),$arr1);
98+ preg_match_all("/[^\n]*\n*/",preg_replace("/\r/",'',$str2),$arr2);
99+
100+ $this->arr1 = array();
101+ foreach ($arr1[0] as $line) {
102+ $this->arr1[] = new DiffLine($line);
103+ }
104+
105+ $this->arr2 = array();
106+ foreach ($arr2[0] as $line) {
107+ $this->arr2[] = new DiffLine($line);
108+ }
109+ }
110+ function str_compare($str1,$str2)
111+ {
112+ $this->set_str('diff',$str1,$str2);
113+ $this->compare();
114+
115+ $str = '';
116+ foreach ($this->toArray() as $obj) {
117+ $str .= $obj->get('diff').$obj->text();
118+ }
119+
120+ return $str;
121+ }
122+ function compare()
123+ {
124+ array_unshift($this->arr1,new DiffLine('')); //sentinel
125+ array_unshift($this->arr2,new DiffLine('')); //sentinel
126+ $this->reverse = (count($this->arr1) > count($this->arr2));
127+ if ($this->reverse) {
128+ $tmp = $this->arr1;
129+ $this->arr1 = $this->arr2;
130+ $this->arr2 = $tmp;
131+ unset($tmp);
132+ }
133+ $this->m = count($this->arr1) - 1;
134+ $this->n = count($this->arr2) - 1;
135+ $this->pos = array(0=>array('x'=>-1,'y'=>-1)); //sentinel
136+ if ($this->m <= 0) {
137+ $this->pos[] = array('x'=>$this->m + 1, 'y' => $this->n + 1);
138+ return;
139+ }
140+ $delta = $this->n - $this->m; // must be >=0;
141+ $fp = array();
142+ for ($p = -($this->m)-1; $p <= $this->n + 1; $p++) {
143+ $fp[$p] = -1;
144+ }
145+
146+ for ($p = 0;; $p++) {
147+ for ($k = -$p; $k < $delta; $k++) {
148+ $fp[$k] = $this->snake($k, max($fp[$k - 1] + 1, $fp[$k + 1]));
149+ }
150+
151+ for ($k = $delta + $p; $k > $delta; $k--) {
152+ $fp[$k] = $this->snake($k, max($fp[$k - 1] + 1, $fp[$k + 1]));
153+ }
154+
155+ $fp[$delta] = $this->snake($delta, max($fp[$delta - 1] + 1, $fp[$delta + 1]));
156+
157+ if ($fp[$delta] == $this->n) {
158+ $this->pos = array_reverse($this->pos);
159+ $this->pos[] = array('x'=>$this->m + 1, 'y' => $this->n + 1); // sentinel
160+
161+ return;
162+ }
163+ }
164+ }
165+ function snake($k, $y)
166+ {
167+ $x = $y - $k;
168+ while (($x < $this->m) and ($y < $this->n) and $this->arr1[$x + 1]->compare($this->arr2[$y + 1])) {
169+
170+ $x++; $y++;
171+ if ($x > $this->pos[0]['x'] and $y > $this->pos[0]['y']) {
172+ array_unshift($this->pos,array('x'=>$x,'y'=>$y));
173+ }
174+ }
175+ return $y;
176+ }
177+ function strcmp($str1, $str2) //ぐぅ。
178+ {
179+ return rtrim($str1) == rtrim($str2);
180+ }
181+ function toArray()
182+ {
183+ $arr = array();
184+ if ($this->reverse) { //姑息な…
185+ $_x = 'y'; $_y = 'x'; $m = $this->n; $arr1 =& $this->arr2; $arr2 =& $this->arr1;
186+ }
187+ else {
188+ $_x = 'x'; $_y = 'y'; $m = $this->m; $arr1 =& $this->arr1; $arr2 =& $this->arr2;
189+ }
190+
191+ $x = $y = 0;
192+ $this->add_count = $this->delete_count = 0;
193+ foreach ($this->pos as $pos) {
194+ $this->delete_count += ($pos[$_x] - $x);
195+ $this->add_count += ($pos[$_y] - $y);
196+
197+ while ($pos[$_x] > $x) {
198+ $arr1[$x]->set($this->key,$this->minus);
199+ $arr[] = $arr1[$x++];
200+ }
201+
202+ while ($pos[$_y] > $y) {
203+ $arr2[$y]->set($this->key,$this->plus);
204+ $arr[] = $arr2[$y++];
205+ }
206+
207+ if ($x <= $this->m) {
208+ $arr1[$x]->merge($arr2[$y]);
209+ $arr1[$x]->set($this->key,$this->equal);
210+ $arr[] = $arr1[$x];
211+ }
212+ $x++; $y++;
213+ }
214+ array_shift($arr); // drop sentinel
215+ return $arr;
216+ }
217+}
218+
219+class DiffLine
220+{
221+ var $text,$lfcount;
222+ var $status;
223+
224+ function DiffLine($text)
225+ {
226+ if (preg_match("/^([^\n]*)(\n*)$/",$text,$matches)) {
227+ $this->text = $matches[1]; $this->lfcount = strlen($matches[2]);
228+ }
229+ else {
230+ $this->text = $text; $this->lfcount = 1;
231+ }
232+ $this->status = array();
233+ }
234+ function compare($obj)
235+ {
236+ return $this->text == $obj->text;
237+ }
238+ function set($key,$status)
239+ {
240+ $this->status[$key] = $status;
241+ }
242+ function get($key)
243+ {
244+ return array_key_exists($key,$this->status) ? $this->status[$key] : '';
245+ }
246+ function merge($obj)
247+ {
248+ $this->status = array_merge($this->status,$obj->status);
249+ $this->lfcount = max($this->lfcount,$obj->lfcount);
250+ }
251+ function text()
252+ {
253+ return $this->text.str_repeat("\n",($this->lfcount == 0) ? 1 : $this->lfcount);
254+ }
255+}
256+?>
--- /dev/null
+++ b/mysql.php
@@ -0,0 +1,37 @@
1+<?php
2+/////////////////////////////////////////////////
3+// PukiWiki - Yet another WikiWikiWeb clone.
4+//
5+// $Id: mysql.php,v 1.1 2003/01/27 05:44:11 panda Exp $
6+//
7+
8+function db_exec($sql)
9+{
10+ $conn = mysql_pconnect()
11+ or die_message('cannot connect db.');
12+ mysql_select_db('pukiwiki',$conn)
13+ or die_message('cannot select db.');
14+ $result = mysql_query($sql,$conn)
15+ or die_message("query '$sql' failure.\n".mysql_error($conn));
16+ return $result;
17+}
18+
19+
20+function db_query($sql)
21+{
22+ $result = db_exec($sql);
23+
24+ $rows = array();
25+ while ($row = mysql_fetch_array($result)) {
26+ $rows[] = $row;
27+ }
28+ mysql_free_result($result);
29+
30+ return $rows;
31+}
32+
33+/*
34+create table page (id integer auto_increment primary key, name text not null, lastmod integer not null);
35+create table link (page_id integer not null, ref_id integer not null);
36+*/
37+?>
--- /dev/null
+++ b/pgsql.php
@@ -0,0 +1,35 @@
1+<?php
2+/////////////////////////////////////////////////
3+// PukiWiki - Yet another WikiWikiWeb clone.
4+//
5+// $Id: pgsql.php,v 1.1 2003/01/27 05:44:11 panda Exp $
6+//
7+
8+function db_exec($sql)
9+{
10+ $conn = pg_pconnect(PG_CONNECT_STRING)
11+ or die_message('cannot connect db.');
12+ $result = pg_query($conn,$sql)
13+ or die_message("query '$sql' failure.");
14+ return $result;
15+}
16+
17+function db_query($sql)
18+{
19+ $result = db_exec($sql);
20+
21+ $rows = array();
22+ while ($row = pg_fetch_array($result)) {
23+ $rows[] = $row;
24+ }
25+ pg_free_result($result);
26+
27+ return $rows;
28+}
29+
30+/*
31+create table page (id serial primary key, name text not null, lastmod integer not null);
32+create table link (page_id integer not null, ref_id integer not null);
33+grant all on page,link,page_id_seq to apache;
34+*/
35+?>
旧リポジトリブラウザで表示