Révision | 43e5b18be3a0a76fe1c79145c49e354ecff8f536 (tree) |
---|---|
l'heure | 2003-01-27 14:44:11 |
Auteur | panda <panda> |
Commiter | panda |
PukiWiki/1.4 first beta release
@@ -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 | +?> |
@@ -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 | +?> |
@@ -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 | +?> |
@@ -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 | +?> |