【編集中】 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
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    
    #spanend
    #spanadd
    <?php
    #spanend
    #spanadd
     
    #spanend
    #spanadd
    function plugin_diag_convert()
    #spanend
    #spanadd
    {
    #spanend
        $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
        return '<div class="diag">'.plugin_diag_core($arg, 'convert').'</div>';
    #spanadd
    }
    #spanend
    #spanadd
     
    #spanend
    #spanadd
    function plugin_diag_inline()
    #spanend
    #spanadd
    {
    #spanend
        $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
        return '<span class="diag">'.plugin_diag_core($arg, 'inline').'</span>';
    #spanadd
    }
    #spanend
    #spanadd
     
    #spanend
    #spanadd
    function plugin_diag_core($arg, $mode)
    #spanend
    #spanadd
    {
    #spanend
        $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);
    #spanadd
    //  return '<img style="width:'.$width.'em; height:'.$height.'em; vertical-align:'.$depth.'em;". src="'.$diag_dir.$img.'" alt="$$'.$arg.'$$" title="'.$arg.'">';
    #spanend
    #spanadd
    //  return '<img src="'.$diag_dir.$img.'" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'">';
    #spanend
    #spanadd
    //  return '<object type="image/svg+xml" data="'.$diag_dir.$img.'" style="width:'.$width.'; height:'.$height.';" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'"></object>';
    #spanend
    #spanadd
    //  return $svg.'<pre>'.htmlspecialchars(print_r($matches, TRUE)).'</pre>';
    #spanend
        return '<div style="width: '.$width.'px;" >'.$svg.'</div>';
    #spanadd
    }
    #spanend
    #spanadd
    ?>
    #spanend
    #spanadd

開発メモ EditToHeaderToFooter

文字コード変換 EditToHeaderToFooter

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

svg 非対応ブラウザ EditToHeaderToFooter

  • ブラウザ情報を解析して、png で出すべし。
  • 技術的に実現可能と分かっているが、検証できそうにないので先延ばし…
    • ブラウザ情報を表示するページでも用意し、他力本願で報告フォームを使おうか?
    初基 一覧 検索 最新 バックアップ リンク元   ヘルプ   最終更新のRSS