示例#1
0
function plugin_pre_convert()
{
    if (file_exists(PLUGIN_DIR . 'code/codehighlight.php')) {
        require_once PLUGIN_DIR . 'code/codehighlight.php';
    } else {
        die_message('file ' . PLUGIN_DIR . 'code/codehighlight.php not exist or not readable.');
    }
    static $id_number = 0;
    // プラグインが呼ばれた回数(IDに利用)
    $id_number++;
    $option = array('number' => false, 'nonumber' => false, 'vervatim' => false, 'novervatim' => false, 'icon' => false, 'noicon' => false, 'link' => false, 'nolink' => false);
    $num_of_arg = func_num_args();
    $args = func_get_args();
    $text = '';
    $number = '';
    $style = '';
    $stylecnt = 0;
    $begin = 1;
    $end = null;
    $a = array();
    // オプションを調べる
    for ($i = 0; $i < $num_of_arg - 1; ++$i) {
        if (!_plugin_code_check_argment($args[$i], $option)) {
            if (!_plugin_code_get_region($args[$i], $begin, $end)) {
                // style
                if ($stylecnt == 0) {
                    $color = $args[$i];
                    ++$stylecnt;
                } else {
                    $bgcolor = $args[$i];
                }
            }
        }
    }
    if ($stylecnt) {
        // Invalid color
        foreach (array($color, $bgcolor) as $col) {
            if ($col != '' && !preg_match(PLUGIN_PRE_COLOR_REGEX, $col)) {
                return '<p class="error">#pre():Invalid color: ' . htmlspecialchars($col) . ';</p>';
            }
        }
        if ($color != '') {
            $style = ' style="color:' . $color;
            if ($bgcolor != '') {
                $style .= ';background-color:' . $bgcolor . '"';
            } else {
                $style .= '"';
            }
        } else {
            if ($bgcolor != '') {
                $style .= ' style="background-color:' . $bgcolor . '"';
            } else {
                $style = '';
            }
        }
    }
    _plugin_code_multiline_argment($args[$num_of_arg - 1], $data, $option, $begin, $end);
    if (isset($data['_error']) && $data['_error'] != '') {
        return $data['_error'];
    }
    $text = $data['data'];
    $title = $data['title'];
    if ($end === null) {
        $end = substr_count($text, "\n") + $begin - 1;
    }
    if (PLUGIN_PRE_VERVATIM && !$option['novervatim'] || $option['vervatim']) {
        $text = htmlspecialchars($text);
    } else {
        $text = make_link($text);
    }
    $html = '<pre class="' . PLUGIN_PRE_HEADER . 'body" ' . $style . '>' . $text . '</pre>';
    if (PLUGIN_PRE_NUMBER && !$option['nonumber'] || $option['number']) {
        $number = '<pre class="' . PLUGIN_PRE_HEADER . 'number">' . _plugin_code_makeNumber($end, $begin) . '</pre>';
        $html = '<div id="' . PLUGIN_PRE_HEADER . $id_number . '" class="' . PLUGIN_PRE_HEADER . 'table">' . _plugin_code_column($html, $number, null) . '</div>';
    }
    return $title . $html;
}
 /**
  * ソースからHTML生成
  */
 function srcToHTML(&$string, &$lang, $id_number, &$option)
 {
     // テーブルジャンプ用ハッシュ
     $switchHash = array();
     $capital = false;
     // 大文字小文字を区別しない
     $mkoutline = $option['outline'];
     $mknumber = $option['number'];
     // 改行
     $switchHash["\n"] = PLUGIN_CODE_CARRIAGERETURN;
     $switchHash['\\'] = PLUGIN_CODE_ESCAPE;
     // 識別子開始文字
     for ($i = ord('a'); $i <= ord('z'); ++$i) {
         $switchHash[chr($i)] = PLUGIN_CODE_IDENTIFIRE;
     }
     for ($i = ord('A'); $i <= ord('Z'); ++$i) {
         $switchHash[chr($i)] = PLUGIN_CODE_IDENTIFIRE;
     }
     $switchHash['_'] = PLUGIN_CODE_IDENTIFIRE;
     // 文字列開始文字
     $switchHash['"'] = PLUGIN_CODE_STRING_LITERAL;
     // 言語定義ファイル読み込み
     include PLUGIN_DIR . 'code/keyword.' . $lang . '.php';
     // 文字->html変換用ハッシュ
     $htmlHash = array('"' => '&quot;', '\'' => '&#039;', '<' => '&lt;', '>' => '&gt;', '&' => '&amp;', "\t" => PLUGIN_CODE_WIDTHOFTAB);
     $html = '';
     $str_len = strlen($string);
     $str_pos = 0;
     $line = 0;
     // 行数をカウント
     // for outline
     $outline = array();
     // $outline[lineno][nest] $outline[lineno][blockno]がある。
     $nest = 1;
     // ネスト
     $blockno = 0;
     // 何番目のブロックか?IDをユニークにするために用いる
     $last_start = false;
     // 最後にブロック開始だったか、、、。
     $commentno = 0;
     // 最初の検索用に読み込み
     if ($str_len == $str_pos) {
         $code = false;
     } else {
         $code = $string[$str_pos++];
     }
     // getc
     while ($code !== false) {
         switch ($switchHash[$code]) {
             case PLUGIN_CODE_CARRIAGERETURN:
                 // 改行
                 ++$line;
                 $html .= "\n";
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_ESCAPE:
                 // escape charactor
                 $start = $code;
                 // 判定用にもう1文字読み込む
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 if (ctype_alnum($code)) {
                     // 文字(変数)なら終端まで見付ける
                     --$str_pos;
                     // エラー処理したくないからpreg_matchで必ず見つかるようにする
                     $result = substr($string, $str_pos);
                     preg_match('/[A-Za-z0-9_]+/', $result, $matches);
                     $str_pos += strlen($matches[0]);
                     $result = $matches[0];
                 } else {
                     // 記号なら1文字だけ切り出す
                     $result = $code;
                     if ($code == "\n") {
                         ++$line;
                     }
                 }
                 // htmlに追加
                 $html .= htmlspecialchars($start . $result, ENT_QUOTES);
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_COMMENT:
                 // コメント
                 --$str_pos;
                 $result = substr($string, $str_pos);
                 foreach ($code_comment[$code] as $pattern) {
                     if (preg_match($pattern[0], $result)) {
                         //if (!strncmp($pattern[1], $result, $pattern[0])) {
                         $pos = strpos($result, $pattern[1]);
                         if ($pos === false) {
                             // 見つからないときは終わりまで
                             $str_pos = $str_len;
                             //$result = $result; ってことで何もしない
                         } else {
                             $pos += $pattern[2];
                             $str_pos += $pos;
                             $result = substr($result, 0, $pos);
                         }
                         // ライン数カウント
                         $line += substr_count($result, "\n");
                         ++$commentno;
                         // htmlに追加
                         $result = str_replace('\\t', PLUGIN_CODE_WIDTHOFTAB, htmlspecialchars($result, ENT_QUOTES));
                         if ($option['link']) {
                             $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                         }
                         $html .= '<span class="' . PLUGIN_CODE_HEADER . 'comment" id="' . PLUGIN_CODE_HEADER . $id_number . '_cmt_' . $commentno . '">' . $result . '</span>';
                         // 次の検索用に読み込み
                         if ($str_len == $str_pos) {
                             $code = false;
                         } else {
                             $code = $string[$str_pos++];
                         }
                         // getc
                         continue 3;
                     }
                 }
                 // コメントではない
                 ++$str_pos;
                 break;
             case PLUGIN_CODE_COMMENT_WORD:
                 // 文字列から始まるコメント
                 // 出来る限り長く識別子を得る
                 --$str_pos;
                 $result = substr($string, $str_pos);
                 foreach ($code_comment[$code] as $pattern) {
                     if (preg_match($pattern[0], $result)) {
                         $pos = strpos($result, $pattern[1]);
                         if ($pos === false) {
                             // 見つからないときは終わりまで
                             $str_pos = $str_len;
                             //$result = $result; ってことで何もしない
                         } else {
                             $pos += $pattern[2];
                             $str_pos += $pos;
                             $result = substr($result, 0, $pos);
                         }
                         // ライン数カウント
                         $line += substr_count($result, "\n");
                         ++$commentno;
                         // htmlに追加
                         $result = str_replace('\\t', PLUGIN_CODE_WIDTHOFTAB, htmlspecialchars($result, ENT_QUOTES));
                         if ($option['link']) {
                             $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                         }
                         $html .= '<span class="' . PLUGIN_CODE_HEADER . 'comment" id="' . PLUGIN_CODE_HEADER . $id_number . '_cmt_' . $commentno . '">' . $result . '</span>';
                         // 次の検索用に読み込み
                         if ($str_len == $str_pos) {
                             $code = false;
                         } else {
                             $code = $string[$str_pos++];
                         }
                         // getc
                         continue 3;
                     }
                 }
                 ++$str_pos;
                 // コメントでなければ文字列 break を使わない
             // コメントでなければ文字列 break を使わない
             case PLUGIN_CODE_IDENTIFIRE:
                 // 識別子(アルファベットから始まっている)
                 // 出来る限り長く識別子を得る
                 --$str_pos;
                 // エラー処理したくないからpreg_matchで必ず見つかるようにする
                 $result = substr($string, $str_pos);
                 preg_match('/[A-Za-z0-9_\\-]+/', $result, $matches);
                 $str_pos += strlen($matches[0]);
                 $result = $matches[0];
                 // htmlに追加
                 if ($capital) {
                     $index = $code_keyword[strtolower($result)];
                 } else {
                     $index = $code_keyword[$result];
                 }
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($index != '') {
                     $html .= '<span class="' . PLUGIN_CODE_HEADER . $code_css[$index - 1] . '">' . $result . '</span>';
                 } else {
                     $html .= $result;
                 }
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_SPECIAL_IDENTIFIRE:
                 // 特殊文字から始まる識別子
                 // 次の文字が英字か判定
                 if (!ctype_alpha($string[$str_pos])) {
                     break;
                 }
                 $result = substr($string, $str_pos);
                 preg_match('/[A-Za-z0-9_\\-]+/', $result, $matches);
                 $str_pos += strlen($matches[0]);
                 $result = $code . $matches[0];
                 // htmlに追加
                 if ($capital) {
                     $index = $code_keyword[strtolower($result)];
                 } else {
                     $index = $code_keyword[$result];
                 }
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($index != '') {
                     $html .= '<span class="' . PLUGIN_CODE_HEADER . $code_css[$index - 1] . '">' . $result . '</span>';
                 } else {
                     $html .= $result;
                 }
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_STRING_LITERAL:
                 // 文字列
                 // 文字列リテラルを得る
                 $pos = $str_pos;
                 do {
                     $result = substr($string, $str_pos);
                     $pos1 = strpos($result, $code);
                     // 文字列終了文字検索
                     if ($pos1 === false) {
                         // 文字列が終わらなかったので全部文字列とする
                         $str_pos = $str_len - 1;
                         break;
                     }
                     $str_pos += $pos1 + 1;
                 } while ($string[$str_pos - 2] == '\\');
                 // 前の文字がエスケープ文字なら続ける
                 $result = $code . substr($string, $pos, $str_pos - $pos);
                 // ライン数カウント
                 $line += substr_count($result, "\n");
                 // htmlに追加
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($option['link']) {
                     $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                 }
                 $html .= '<span class="' . PLUGIN_CODE_HEADER . 'string">' . $result . '</span>';
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_NONESCAPE_LITERAL:
                 // エスケープ文字と式展開を無視した文字列
                 // 文字列リテラルを得る
                 $pos = $str_pos;
                 $result = substr($string, $str_pos);
                 $pos1 = strpos($result, $code);
                 // 文字列終了文字検索
                 if ($pos1 === false) {
                     // 文字列が終わらなかったので全部文字列とする
                     $str_pos = $str_len - 1;
                 } else {
                     $str_pos += $pos1 + 1;
                 }
                 $result = $code . substr($string, $pos, $str_pos - $pos);
                 // ライン数カウント
                 $line += substr_count($result, "\n");
                 // htmlに追加
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($option['link']) {
                     $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                 }
                 $html .= '<span class="' . PLUGIN_CODE_HEADER . 'string">' . $result . '</span>';
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_PAIR_LITERAL:
                 // 対記号で囲まれた文字列リテラルを得る PostScript
                 $pos = $str_pos;
                 do {
                     $result = substr($string, $str_pos);
                     $pos1 = strpos($result, $literal_delimiter);
                     // 文字列終了文字検索
                     if ($pos1 === false) {
                         // 文字列が終わらなかったので全部文字列とする
                         $str_pos = $str_len - 1;
                         break;
                     }
                     $str_pos += $pos1 + 1;
                 } while ($string[$str_pos - 2] == '\\');
                 // 前の文字がエスケープ文字なら続ける
                 $result = $code . substr($string, $pos, $str_pos - $pos);
                 // ライン数カウント
                 $line += substr_count($result, "\n");
                 // htmlに追加
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($option['link']) {
                     $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                 }
                 $html .= '<span class="' . PLUGIN_CODE_HEADER . 'string">' . $result . '</span>';
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_FORMULA:
                 // TeXの数式に使用 将来的には汎用性を持たせる
                 $pos = $str_pos;
                 $result = substr($string, $str_pos);
                 $pos1 = strpos($result, $code);
                 // 文字列終了文字検索
                 if ($pos1 === false) {
                     // 文字列が終わらなかったので全部文字列とする
                     $str_pos = $str_len - 1;
                 } else {
                     $str_pos += $pos1 + 1;
                 }
                 $result = $code . substr($string, $pos, $str_pos - $pos);
                 // htmlに追加
                 $result = htmlspecialchars($result, ENT_QUOTES);
                 if ($option['link']) {
                     $result = preg_replace('/(s?https?:\\/\\/|ftp:\\/\\/|mailto:)([-_.!~*()a-zA-Z0-9;\\/:@?=+$,%#]|&amp;)+/', '<a href="$0">$0</a>', $result);
                 }
                 $html .= '<span class="' . PLUGIN_CODE_HEADER . 'formula">' . $result . '</span>';
                 // 次の検索用に読み込み
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_BLOCK_START:
                 // outline 表示用開始文字 {, (
                 ++$blockno;
                 ++$nest;
                 //if(! array_key_exists($line,$outline)) {
                 if (!isset($outline[$line])) {
                     $outline[$line] = array();
                 }
                 array_push($outline[$line], array('nest' => $nest, 'blockno' => $blockno));
                 // アウトラインが閉じた時に表示する画像を埋め込む場所
                 $html .= $code . '<span id="' . PLUGIN_CODE_HEADER . $id_number . _ . $blockno . '_img" display="none"></span>' . '<span id="' . PLUGIN_CODE_HEADER . $id_number . _ . $blockno . '">';
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
             case PLUGIN_CODE_BLOCK_END:
                 // outline 表示終了文字 }, )
                 --$nest;
                 //if(! array_key_exists($line,$outline)) {
                 if (!isset($outline[$line])) {
                     $outline[$line] = array();
                     array_push($outline[$line], array('nest' => $nest, 'blockno' => 0));
                 } else {
                     $old = array_pop($outline[$line]);
                     if ($old['blockno'] != 0 && $nest + 1 == $old['nest']) {
                     } else {
                         if (!is_null($old)) {
                             array_push($outline[$line], $old);
                         }
                         array_push($outline[$line], array('nest' => $nest, 'blockno' => 0));
                     }
                 }
                 $last_start = false;
                 $html .= '</span>' . $code;
                 if ($str_len == $str_pos) {
                     $code = false;
                 } else {
                     $code = $string[$str_pos++];
                 }
                 // getc
                 continue 2;
         }
         // switch
         // その他の文字
         $result = $htmlHash[$code];
         if ($result) {
             $html .= $result;
         } else {
             $html .= $code;
         }
         // 次の検索用に読み込み
         if ($str_len == $str_pos) {
             $code = false;
         } else {
             $code = $string[$str_pos++];
         }
         // getc
     }
     // while
     // 最後の余分な改行を削除
     if ($html[strlen($html) - 2] == ' ') {
         $html = substr($html, 0, -2);
     } else {
         $html = substr($html, 0, -1);
     }
     $html = array('src' => $html, 'number' => '', 'outline' => '', 'blocknum' => $blockno, 'commentnum' => $commentno);
     if ($mkoutline) {
         return $this->makeOutline($html, $line - 1, $nest, $mknumber, $outline, $blockno, $id_number);
     }
     if ($mknumber) {
         $html['number'] = _plugin_code_makeNumber($line - 1);
     }
     return $html;
 }