WordPressでPlantUMLを利用して図を描画する

Table of Content

目的

WordPressでPlantUMLを利用して図を作成します。
なおこの際、日ノ本言葉を使うものとします。
plantumlphp.png

環境

PHP 7.3
Wordpress 5.2

PlantUML Renderer

PlantUML RendererはWordPressのプラグインとして以下に公開されています。
https://ja.wordpress.org/plugins/plantuml-renderer/

WordPressのソースブロックに以下を記載します。

PlantUML Syntax:
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response

以下のような画像が表示されます。

plantumlphp0.png

ただし当然の権利のように日ノ本言葉を記載すると文字化けします。

仕組み

PlantUML Renderのソースは以下にあります。
https://plugins.trac.wordpress.org/browser/plantuml-renderer/trunk/public/class-plantuml-renderer-public.php

            public function pumlr_shortcode_handler( $atts, $content = null ) {
                    $new_content = str_replace( '>','>',$content );                                      // Right angle bracket.
                    $new_content = str_replace( '<','<',$new_content );                  // Left angle bracket.
                    $new_content = str_replace( '–','--',$new_content );      // En-dash  (WP converts "--" to one en-dash).
                    $new_content = str_replace( '—','--',$new_content );      // Em-dash  (WP converts "--" to one em-dash).
                    $new_content = str_replace( '“','"',$new_content );         // Curly left double quote
                    $new_content = str_replace( '”','"',$new_content );         // Curly right double quote
                    $new_content = str_replace( '”','"',$new_content );         // Curly right double quote
                    $remove_array = array( '<p>', '</p>', '<br />', '<br/>' );              // Remove HTML tags.
                    $new_content = str_replace( $remove_array, '', $new_content );
                    $img = '<p><img src=http://www.plantuml.com/plantuml/img/';
                    $img .= $this->encodep( $new_content );
                    $img .= ' alt="PlantUML Syntax:' . $content . '" usemap="#plantuml_map">';

                    // Get the image map, if our syntax has plantuml link syntax.
                    $linkpos = strpos( $new_content, '[[' );
                    if ( false !== $linkpos ) {
                            $response = wp_remote_get( 'http://www.plantuml.com/plantuml/map/' . $this->encodep( $new_content ) );
                            if ( is_array( $response ) ) {
                                    $body = $response['body'];
                                    $img .= $body;
                            }
                    }
                    $img .= '</p>';
                    return $img;
            }
            /**
             * Encode our plantuml syntax - See PlantUML PHP Doc for details - where this was lifted from.
             *
             * @param    string $text Our text to encode.
             * @since    1.0.0
             */
            private function encodep( $text ) {
                    $data = utf8_encode( $text );
                    $compressed = gzdeflate( $data, 9 );
                    return $this->encode64( $compressed );
            }
  1. UTF-8でエンコードする
  2. 圧縮する
  3. base64で表現する
  4. http://www.plantuml.com/plantuml/map/3の結果」を呼び出す
  5. 画像が作成されるのでimgタグで表示する

この仕組みは以下のページに記載されており、プラグインはそれを忠実に実装しています。
http://plantuml.com/ja/code-php

上記ページからたどれるPHPのサンプルでは同様に化けます。

JavaScriptでの実装

PlantUMLの公式ページでPHPではなく、JavaScriptで同じことをしている箇所があります。
http://plantuml.com/en/demo-javascript-synchronous

このページでは日本語が化けることはありません。
どんな実装をしているか見てみましょう。

demo-javascript-synchronous

function compress(a){
  a=unescape(encodeURIComponent(a));
  GID("im").src="http://www.plantuml.com/plantuml/img/"+encode64(zip_deflate(a,9))
};

encode64とzip_deflateはsynchro.jsに実装されていてPHP側の実装と同様です。
問題はこのパラメータに与えるaにあります。

ここではaをencodeURIComponentをしたあと、unescapeを実行しています。
unescapeはASCII以外対応していないので日本語は文字化けします。
そして、その化けた内容をそのまま利用しています。

つまり、PHPのutf8_encodeが不要ということになります。

修正内容

インストールしたプラグインのファイルを直接修正して対応します。
このファイルは以下に存在してました。
/ワードプレスのパス/wp-content/plugins/plantuml-renderer/public

utf8_encodeを除去します

class-plantuml-renderer-public.php

    /**
     * Encode our plantuml syntax - See PlantUML PHP Doc for details - where this was lifted from.
     *
     * @param    string $text Our text to encode.
     * @since    1.0.0
     */
    private function encodep( $text ) {
        //$data = utf8_encode( $text );
        $data = $text; // http://plantuml.com/en/demo-javascript-synchronous のJSではunescape(encodeURIComponent(a))でASCII以外は化けているデータを送ってうまくいっている
        $compressed = gzdeflate( $data, 9 );
        return $this->encode64( $compressed );
    }

また、「"」が混ざった場合、imgタグのaltが上手く表示できなくなるのでそれもあわせてなおします。ここでは全角に変換してます。

class-plantuml-renderer-public.php

    /**
     * Our lovely shortcode.
     *
     * @param    array  $atts    Attributes passed into shortcode.
     * @param    string $content Content within the shortcode tags.
     * @since    0.0.3
     */
    public function pumlr_shortcode_handler( $atts, $content = null ) {
        $new_content = str_replace( '>','>',$content );                   // Right angle bracket.
        $new_content = str_replace( '<','<',$new_content );           // Left angle bracket.
        $new_content = str_replace( '–','--',$new_content );  // En-dash  (WP converts "--" to one en-dash).
        $new_content = str_replace( '—','--',$new_content );  // Em-dash  (WP converts "--" to one em-dash).
        $new_content = str_replace( '“','"',$new_content );    // Curly left double quote
        $new_content = str_replace( '”','"',$new_content );    // Curly right double quote
        $new_content = str_replace( '”','"',$new_content );    // Curly right double quote
        $remove_array = array( '<p>', '</p>', '<br />', '<br/>' );      // Remove HTML tags.
        $new_content = str_replace( $remove_array, '', $new_content );
        $img = '<p><img src=http://www.plantuml.com/plantuml/img/';
        $img .= $this->encodep( $new_content );
        // "を全角に変換して表示する
        $img .= ' alt="PlantUML Syntax:' . str_replace( '"', '”', $content) . '" usemap="#plantuml_map">';

        // Get the image map, if our syntax has plantuml link syntax.
        $linkpos = strpos( $new_content, '[[' );
        if ( false !== $linkpos ) {
            $response = wp_remote_get( 'http://www.plantuml.com/plantuml/map/' . $this->encodep( $new_content ) );
            if ( is_array( $response ) ) {
                $body = $response['body'];
                $img .= $body;
            }
        }
        $img .= '</p>';
        return $img;
    }

結果

上記2つの対応により、日ノ本言葉がつかえるようになります。
plantumlphp.png

改造案

いまのままだと外部のURLに頼ってしまうので自前のサーバにPlantUMLのJARを配置した方がいいでしょう。
以下のページが参考になりそうです。
http://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Fpukiwiki%2Fuml.inc.php

「WordPressでPlantUMLを利用して図を描画する」への1件の返信

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です