Open8

Zenn の投稿に Plantuml を自動で 埋め込みたい

mitakemitake

PlantUML では、UML 情報を圧縮・エンコードした文字列をパラメタに PlantUML サーバにリクエストを出すと、そのレスポンスとして UML 画像を取得することができる。


例えば、下記 UML 情報を例に考える。

@startuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
@enduml

この UML 情報を圧縮・エンコードを行うと、下記文字列が得られる。

Syp9J4vLqBLJSCfFib9mB2t9ICqhoKnEBCdCprC8IYqiJIqkuGBAAUW2rO0LOr5LN92VLvpA1G00

この結果を得るには次の処理を行います:

  • テキストをUTF-8でエンコードします。
  • DeflateまたはBrotliアルゴリズムで圧縮します。
  • Base64に類似したアルゴリズムを使って、ASCIIに再エンコーディングします。

via https://plantuml.com/ja/text-encoding

そんでもって、この文字列をパラメタとして PlantUML サーバにリクエストを出せば、無事画像化することができる。

![](http://www.plantuml.com/plantuml/png/Syp9J4vLqBLJSCfFib9mB2t9ICqhoKnEBCdCprC8IYqiJIqkuGBAAUW2rO0LOr5LN92VLvpA1G00)
mitakemitake

とりあえず pandoc の filter 機能を使って、変換処理を実現してみる

mitakemitake

original content

---
title: "test"
emoji: "📌"
type: "tech" # tech: 技術記事 / idea: アイデア
topics: ["topic1", "topic2"]
published: false
---

```plantuml
Alice -> Bob
Bob --> Alice: 日本語
```\

pandoc ast

$ pandoc -f markdown -t json ./articles/7a8f978bd25bd3ae393d.md  | jq .
{
  "pandoc-api-version": [
    1,
    22
  ],
  "meta": {
    "emoji": {
      "t": "MetaInlines",
      "c": [
        {
          "t": "Str",
          "c": "📌"
        }
      ]
    },
    "published": {
      "t": "MetaBool",
      "c": false
    },
    "title": {
      "t": "MetaInlines",
      "c": [
        {
          "t": "Str",
          "c": "test"
        }
      ]
    },
    "topics": {
      "t": "MetaList",
      "c": [
        {
          "t": "MetaInlines",
          "c": [
            {
              "t": "Str",
              "c": "topic1"
            }
          ]
        },
        {
          "t": "MetaInlines",
          "c": [
            {
              "t": "Str",
              "c": "topic2"
            }
          ]
        }
      ]
    },
    "type": {
      "t": "MetaInlines",
      "c": [
        {
          "t": "Str",
          "c": "tech"
        }
      ]
    }
  },
  "blocks": [
    {
      "t": "CodeBlock",
      "c": [
        [
          "",
          [
            "plantuml"
          ],
          []
        ],
        "Alice -> Bob\nBob --> Alice: 日本語"
      ]
    }
  ]
}
$

関係ないが、codeblock 内で、バッククオート(`)がエスケープできない

mitakemitake

実現したいこととして、

  • 記述した UML が自動的に UML 画像へ変換
  • UML の再編集

があるわけだけど、
pandoc を用いて markdown -> markdown の変換を行うので、_articles/*.md -> articles/*.md みたいに articles ディレクトリをファイル出力ディレクトリとして、_article など別のディレクトリに原本の md ファイルを格納して運用することになってしまいそう。

この運用をすると、

  • Zenn から提供されているプレビューツールが使用できない
    • 普段 md ファイルを編集するときは VS Code のプレビューを使用しているので大きな問題はない (強がり)
  • "GitHubで編集を提案" 機能を使用すると、出力された md ファイルに対して PR が来てしまいそう ?

のような問題が別途発生しそう

mitakemitake

現状のディレクトリ構成

.
├── README.md
├── _articles
│   ├── 7a8f978bd25bd3ae393d.md <- 実際に記述していく md ファイル
│   └── 91581c147627abcd56fe.md
├── articles
│   ├── 7a8f978bd25bd3ae393d.md <- pandoc によって出力された md ファイル
│   └── 91581c147627abcd56fe.md
├── books
└── scripts
    └── plantuml.py

記事編集フロー

  • _articles に記事 md ファイルを作成
  • 変換スクリプト実行
    • ls _articles | egrep .md | xargs -I@ pandoc -f markdown -t markdown -s _articles/@ -o articles/@ --filter scripts/plantuml.py
    • _articles 配下の md ファイルに対して plantuml 記述が画像タグに変換され、articles に出力される
  • zenn プレビューで確認
  • github へプッシュ