【編集中】 EditToHeaderToFooter

方針 EditToHeaderToFooter

  • コードで画像を出力したい。
  • 特定用途なら専用言語で良い。
  • 汎用用途ならコーディングし易さを考慮した汎用言語が良い。svg のタグ打ちはコーダーに優しくない。

仕様 EditToHeaderToFooter

  • blockdiagという便利な作図ツールが作られている。
  • Python で実装されているため、プラグイン扱いで拡張する。
  • blockdiag、seqdiag、actdiag、nwdiag、packetdiag とコマンド名が分かれているが、コードから判別可能のため、プラグインは diag に統一。
  • 出力は HTML と親和性の高い SVG 直埋め込みとする。ただ、IE8など非対応ブラウザには png で出すべし。

実装 EditToHeaderToFooter

  • plugin/diag.inc.php を新規作成。
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
    
    <?php
     
    function plugin_diag_convert()
    {
        $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
        return '<div class="diag">'.plugin_diag_core($arg, 'convert').'</div>';
    }
     
    function plugin_diag_inline()
    {
        $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
        return '<span class="diag">'.plugin_diag_core($arg, 'inline').'</span>';
    }
     
    function plugin_diag_core($arg, $mode)
    {
        $diag_dir = './diag/';                                      // 数式と数式画像のパス
        $err_msg_end_phrase = 'No pages of output.'.PHP_EOL;    // エラー終了を示す文字列(platexの出力依存)
        
        $prefix_convert = 'diag-nc-';             //  ブロック用ファイル衝突を避けるための接頭語
        $prefix_inline  = 'diag-ni-';             // インライン用ファイル衝突を避けるための接頭語
        
        $key = ($mode=='inline') ? $prefix_inline.md5($arg) : $prefix_convert.md5($arg);
        
        $diag_euc = $key.'.euc.diag';       // 照合用引数出力(保存ファイル)
        $diag_utf = $key.'.utf.diag';       // コンパイル出力(保存ファイル)
        $img = $key.'.svg';                 // 数式の画像出力(保存ファイル)
        
        $old_dir = getcwd();
        chdir($diag_dir);
        
        if (!file_exists($img) || $arg != file_get_contents($diag_euc))
        {
            $std  = $key.'.std.log';   // Tex の標準出力、エラー出力用
            $euc  = $key.'.std.log';   // Tex の標準出力、エラー出力用
            
            flush();    // Timeout 対策
            
            //$arg = "diag {\n" . $arg . "\n}";      // コード補完
            //$arg = mb_convert_encoding($arg, 'utf8-win');
            
            $command = "blockdiag ";
            //$command = str_replace(";", ";\n", $command);
            if (preg_match(   '/^\s*seqdiag\b/', $arg)) {$command =    "seqdiag ";}
            if (preg_match(   '/^\s*actdiag\b/', $arg)) {$command =    "actdiag ";}
            if (preg_match(    '/^\s*nwdiag\b/', $arg)) {$command =     "nwdiag ";}
            if (preg_match(  '/^\s*rackdiag\b/', $arg)) {$command =   "rackdiag ";}
            if (preg_match('/^\s*packetdiag\b/', $arg)) {$command = "packetdiag ";}
            
            //$arg = mb_convert_encoding($arg,  'SJIS-WIN', 'UTF-8');
            //$arg = mb_convert_encoding(mb_convert_encoding($arg, 'sjis-win', 'eucJP-win'), 'UTF-8', 'sjis-win');
            
            file_put_contents($diag_euc, $arg);
            exec('nkf -w '.$diag_euc.' > '.$diag_utf);
            exec($command . $diag_utf.'  -f %windir%\fonts\msgothic.ttc -Tsvg -o '. $img . ' 2> ' . $std );
            exec('nkf -e --overwrite '.$img);
            
            flush();    // Timeout 対策
            if (!file_exists($img)) // Tex Error
            {
                $err_flag = false;
                $err_code = "diag Error:\n\n";
                
                if ($log_code = fopen($std, 'r'))
                {
                    while (!feof($log_code)) 
                    {
                        $msg = fgets($log_code);
                        $err_code .= $msg;
                    }
                    fclose($log_code);
                }
                chdir($old_dir);
                return '<pre class=diag_error_title>'.$arg.'</pre><pre class=diag_error_message>'.$err_code.'</pre>';
            }
            flush();    // Timeout 対策
        }
        
        $xml = file($img);
        array_shift($xml);
        array_shift($xml);
        $match = array();
        preg_match('/^<svg[^>]+viewBox\s*=\s*\"\s*\d+\s*\d+\s*(\d+)\s*(\d+)\s*\"/', $xml[0], $matches);
        $width  = $matches[1];
        $height = $matches[2];
        $svg = implode($xml);
        
        $agent = getenv('HTTP_USER_AGENT');
        chdir($old_dir);
    //  return '<img style="width:'.$width.'em; height:'.$height.'em; vertical-align:'.$depth.'em;". src="'.$diag_dir.$img.'" alt="$$'.$arg.'$$" title="'.$arg.'">';
    //  return '<img src="'.$diag_dir.$img.'" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'">';
    //  return '<object type="image/svg+xml" data="'.$diag_dir.$img.'" style="width:'.$width.'; height:'.$height.';" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'"></object>';
    //  return $svg.'<pre>'.htmlspecialchars(print_r($matches, TRUE)).'</pre>';
        return '<div style="width: '.$width.'px;" >'.$svg.'</div>';
    }
    ?>

開発メモ EditToHeaderToFooter

文字コード変換 EditToHeaderToFooter

  • 日本語を扱うため、EUC ⇒ UTF8 ⇒ EUC と変換する必要がある
    • 流用した PukiWiki が EUC ベースなため、プラグイン引数は EUC
    • diag 達の標準エンコーディングは UTF8なため、コンパイル前に変換する必要がある。
    • PukiWiki で出力される HTML に直埋め込みするため、再度 EUC に変換する必要がある。
  • 訳分からんが、PHP の mb 関数は変換してくれない。
  • とりあえず、nkf というツールがあったので、それで仮実装。
    • Tex にあった。

svg 非対応ブラウザ EditToHeaderToFooter

  • ブラウザ情報を解析して、png で出すべし。
  • 技術的に実現可能と分かっているが、検証できそうにないので先延ばし…
    • ブラウザ情報を表示するページでも用意し、他力本願で報告フォームを使おうか?
リロード   新規 編集 凍結 差分 添付 複製 改名   初基 一覧 検索 最新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: 2013.0403 (水) 0355.1400 (1485d)