Wikiエンジン、大幅に改変
現在の状況
コード
今日もコードから
- cording.php
<? class cording{ function cording_p($buffer, $add_p=TRUE){ global $a_target; $end = count($buffer); for ($i=0; $i<$end; $i++){ $str = $buffer[$i]; $str = preg_replace("/<([^\.=]*)>/", "<$1>", $str); $str = preg_replace("/[\\\]{2} +/", "<br />", $str); $str = preg_replace("/\*\*([^\*]*)\*\*/", "<b>$1</b>", $str); $str = preg_replace("/\/\/([^\/\[\]\{\}]*)\/\//", "<i>$1</i>", $str); $str = preg_replace("/__([^_]*)__/", "<u>$1</u>", $str); $str = preg_replace("/--([^-]*)--/", "<del>$1</del>", $str); $str = preg_replace("/\[\[http:\/\/([^\|\]]*)\|([^\]]*)\]\]/", '<a href="http://$1"'.$a_target.'>$2</a>', $str); $str = preg_replace("/\[\[http:\/\/([^\|\]]*)\]\]/", '<a href="http://$1"'.$a_target.'>$1</a>', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*)\}\}/", '<img src="http://$1" alt="$1" />', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*)\?([0-9]*)\}\}/", '<img src="http://$1" width="$2" alt="$1" />', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*)\?([0-9]*)x([0-9]*)\}\}/", '<img src="http://$1" width="$2" height="$3" alt="$1" />', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*) *\}\}/", '<img src="http://$1" alt="$1" class="img_left" align="left" />', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*)\?([0-9]*) *\}\}/", '<img src="http://$1" width="$2" alt="$1" class="img_left" align="left"/>', $str); $str = preg_replace("/\{\{http:\/\/([^\|\}\? ]*)\?([0-9]*)x([0-9]*) *\}\}/", '<img src="http://$1" width="$2" height="$3" alt="$1" class="img_left" align="left"/>', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*)\}\}/", '<img src="http://$1" alt="$1" class="img_right" align="rignt" />', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*)\?([0-9]*)\}\}/", '<img src="http://$1" width="$2" alt="$1" class="img_right" align="right" />', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*)\?([0-9]*)x([0-9]*)\}\}/", '<img src="http://$1" width="$2" height="$3" alt="$1" class="img_right" align="right" />', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*) +\}\}/", '<img src="http://$1" alt="$1" class="img_center" />', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*)\?([0-9]*) +\}\}/", '<img src="http://$1" width="$2" alt="$1" class="img_center" />', $str); $str = preg_replace("/\{\{ +http:\/\/([^\|\}\? ]*)\?([0-9]*)x([0-9]*) +\}\}/", '<img src="http://$1" width="$2" height="$3" alt="$1" class="img_center" />', $str); $str = preg_replace("/< ?\.([^\| ]*) ?\|([^>]*)>/", '<span class="$1">$2</span>', $str); $str = preg_replace("/< ?= ?([^\| ]*) ?\|([^>]*)>/", '<span style="$1">$2</span>', $str); if ($add_p){ $result .= "<p>".$str."</p>\n"; }else{ $result .= $str; } } return $result; } function cording_div($buffer){ $start_line = array_shift($buffer); if (preg_match("/^\#([^\.\#]*) ?\.([^\.\#\{]*)\{$/", $start_line, $data)){ $result = '<div id="'.$data[1].'" class="'.$data[2].'">'."\n"; }else if (preg_match("/^\.([^\.\#]*) ?\#([^\.\#\{]*)\{$/", $start_line, $data)){ $result = '<div class="'.$data[1].'" id="'.$data[2].'">'."\n"; }else if (preg_match("/^\.([^\.\#\{]*)\{$/", $start_line, $data)){ $result = '<div class="'.$data[1].'">'."\n"; }else if (preg_match("/^\#([^\.\#\{]*)\{$/", $start_line, $data)){ $result = '<div id="'.$data[1].'">'."\n"; } array_pop($buffer); $result .= $this->cording_p($buffer)."</div>\n"; return $result; } function cording_table($buffer){} function cording_list($buffer){ $end = count($buffer); for ($i=0; $i<$end; $i++){ $line = $buffer[$i]; if (preg_match("/^([ ]+)- ?(.*)$/", $line, $data)){ $list[$i] = array('type' => 'ol', 'level' => floor(strlen($data[1])/2), 'body' => $data[2]); }else if (preg_match("/^([ ]+)\* ?(.*)$/", $line, $data)){ $list[$i] = array('type' => 'ul', 'level' => floor(strlen($data[1])/2), 'body' => $data[2]); } } $line = $list[0]; $last_type = $line['type']; $last_level = $line['level']; $open_tag = array($last_type); $result = "<".$last_type.' class="level_'.$last_level.'">'."\n".str_repeat(" ", ($last_level-1)*2+2).'<li class="level'.$last_level.'">'.$this->cording_p(array($line['body']), FALSE)."</li>\n"; for ($i=1; $i<$end; $i++){ $line = $list[$i]; $now_type = $line['type']; $now_level = $line['level']; if ($now_level > $last_level){ array_unshift($open_tag, $now_type); $result .= str_repeat(" ", ($last_level-1)*2+2)."<".$now_type.' class="level_'.$now_level.'">'."\n".str_repeat(" ", ($now_level-1)*2+2).'<li class="level'.$now_level.'">'.$this->cording_p(array($line['body']), FALSE)."</li>\n"; }else if ($now_level < $last_level){ array_shift($open_tag); $result .= str_repeat(" ", ($last_level-1)*2)."</".$last_type.">\n".str_repeat(" ", ($now_level-1)*2+2).'<li class="level'.$now_level.'">'.$this->cording_p(array($line['body']), FALSE)."</li>\n"; }else{ $result .= str_repeat(" ", ($now_level-1)*2+2).'<li class="level'.$now_level.'">'.$this->cording_p(array($line['body']), FALSE)."</li>\n"; } $last_type = $now_type; $last_level = $now_level; } $end = count($open_tag); for ($i=0; $i<$end; $i++){ $line = $open_tag[$i]; $result .= str_repeat(" ", ($last_level-1)*2)."</".$line.">\n"; $last_level --; } return $result; } function cording_blockquote($buffer){} function cording_code($buffer){} function cording_heading($buffer){ $end = count($buffer); for ($i=0; $i<$end; $i++){ $str = $buffer[$i]; $str = preg_replace("/^===== ?([^\=]*)$/", "<h5>$1</h5>\n", $str); $str = preg_replace("/^==== ?([^\=]*)$/", "<h4>$1</h4>\n", $str); $str = preg_replace("/^=== ?([^\=]*)$/", "<h3>$1</h3>\n", $str); $str = preg_replace("/^== ?([^\=]*)$/", "<h2>$1</h2>\n", $str); $result .= $str; } return $result; } function get_type($line){ $str1 = substr($line, 0, 1); $str2 = substr($line, 0, 2); $str3 = substr($line, 0, 3); static $mode_fix = FALSE; static $result; if ($line == ""){ $result = "EOF"; }else if (!$mode_fix){ if ($str2 === "=="){ $result = "cording_heading"; }else if (preg_match("/^[\^\|]([^\^\|]*)[\^\|]/",$line)){ $result = "cording_table"; }else if (preg_match("/^ +[\*-](.*)/", $line)){ $result = "cording_list"; }else if (preg_match("/^<code ?(.*)>$/", $line)){ $result = "cording_code"; $mode_fix = TRUE; }else if (preg_match("/^[\.\#]([^\{]*)\{$/", $line)){ $result = "cording_div"; $mode_fix = TRUE; }else if ($line === "}"){ $result = "cording_div"; }else{ $result = "cording_p"; } }else if (($result === "cording_code" && $line === '</code>') || ($result === "cording_div" && $line === "}")){ $mode_fix = FALSE; } return $result; } function is_buffer($current_line, $follow_line){ global $_cording; $result = FALSE; if (($_cording = $this->get_type($current_line)) == $this->get_type($follow_line)){ $result = TRUE; } return $result; } function cording_start($text){ global $_cording; $corded = array(); $buffer = array(); $before_cording = preg_split("/[\r\n]/", $text, -1, PREG_SPLIT_NO_EMPTY); $end = count($before_cording); for ($i=0; $i<$end; $i++){ $current_line = $before_cording[$i]; $follow_line = $before_cording[$i+1]; array_push ($buffer, $current_line); if (!$this->is_buffer($current_line, $follow_line)){ array_push ($corded, $this->$_cording($buffer)); $buffer = array(); } } $this->cording_finish($corded); } function cording_finish($corded = array()){ while ($line = array_shift($corded)){ echo $line."\n"; } } } ?>
どう変えた? なぜ変えた??
昨日のコードでは、テキストを1行ずつ順にHTML変換していましたが、ある程度のブロックごとに区切り、まとめてHTML変換するように変えました。これは、テーブルの処理を次の「テーブル処理案」ような流れで行おうと考えているからです。
cording_table()に1行ずつ値を渡し、1行ずつHTML変換させていたのでは、テーブルデータ全体を見渡すことができません。先が見えない状態で1行ずつ処理させるよりも、いったん全てのデータを配列に整頓してしまい、それから一気にHTML変換した方がやりやすいような気がしますし、何より「rowspanに対応」させることも可能になります。
そういうわけで、「いまは何を変換しようとしているのか」をチェックし、変換しようとしているタイプ1)が同じ間は$bufferにためておき、タイプが変わった瞬間に該当するメソッドに$bufferを渡すように変えたわけです。
テーブル処理案
1. テーブル箇所を$bufferにまとめてcording_table()に渡す
$buffer = array( [1] => "^ row-1 col-1 ^ row-1 col-2 ^ row-1 col-3 ^ row-1 col-4 ^", [2] => "| row-2 col-1 | row-2 col-2 | row-2 col-3 | row-2 col-4 |", [3] => "| row-3 col-1 | row-3 col-2 | row-3 col-3 | row-3 col-4 |")
2. cording_table()内で$bufferを次のように変換する
$table = array( "row-1" => array( "col-1" => array( "type" => "th", "class" => "centeralign", "colspan" => "0", "rowspan" => "0", "body" => "row-1 col-1"), "col-2" => array( "type" => "th", "class" => "centeralign", "colspan" => "0", "rowspan" => "0", "body" => "row-1 col-2"), "col-3" => array( ... 略 ... ), "col-4" => array( ... 略 ... )), "row-2" => array( "col-1" => ... 以下略
3. HTMLに変換する
Discussion
- 投稿する前に「Discussionのガイドライン」をご一読くださいませ。
1)
現在はdiv, p, table, list, heading, blockquote, codeの7種。まだ増える可能性アリ。