mdm

mermaid

GitHub、Markdown構文でフローチャートやクラス図、ガントチャートなどのダイアグラムを表示できる「Mermaid」をサポート開始

About Mermaid を見ると、javascriptで出来ているみたい。 GitHub、Mermaidを用いてMarkdownファイルに図表を挿入する方法を紹介 に、多少からくりが説明されてた。

最近はもうブラウザー上でなんでも出来ちゃうのね。標準入出力装置だからね。取り敢えずブラウザーに出力出来ればいいよとな。

でも、 Graphvizの再発明のような雰囲気だな。

Markdown

上の話は、どうでもよくて、オイラーには切実な問題がある。

rustを使っていると、木箱をgitからお取寄せになる。後で内容を確かめようと cargo vendor して、それぞれの木箱の中の説明書 README.md を見る亊になる。

こやつhtmlの元になる原稿だ。そのままではただのテキストなんで、変換器でhtmlにしないと、リンクを辿って飛んで行くとかが出来無い。

何とかしたいぞ。まずはmdファイルの書式確認だな。

GitHub Flavored Markdown Spec が、仕様書だ。こいつの至らない点を指摘してる人がおられた。 GitHub Flavored Markdown は何であって何でないか

そんじゃ、物は試しに、変換器をOpenBSDのportsの中で探してみる。合言葉はmarkdownぐらいでいいか。あるわあるわ、pythonのやつperlのやつrubyのやつとさまざまだ。こういう変換器は、インタープリタの格好の餌食なんだろうね。

オイラーは臍曲がりなんで、lua製をチョイスしてみた。

lua markdown

vbox$ lua /usr/local/share/lua/5.1/markdown.lua -h
Usage: markdown.lua [OPTION] [FILE]
Runs the markdown text markup to HTML converter on each file specified on the
command line. If no files are specified, runs on standard input.

No header:
    -n, --no-wrap        Don't wrap the output in <html>... tags.
Custom header:
    -e, --header FILE    Use content of FILE for header.
    -f, --footer FILE    Use content of FILE for footer.
Generated header:
    -c, --charset SET    Specifies charset (default utf-8).
    -i, --title TITLE    Specifies title (default from first <h1> tag).
    -s, --style STYLE    Specifies style sheet file (default default.css).
    -l, --inline-style   Include the style sheet file inline in the header.
Generated files:
    -a, --append         Append .html extension (instead of replacing).
Other options:
    -h, --help           Print this help text.
    -t, --test           Run the unit tests.

ファイル一つなんで、どこへでも持っていける。FreeBSDも何故か、lua(52,53)と、豪華に揃い 踏みしてたんで、お試し。

[sakae@fb ~/.cargo/registry/src/github.com-1285ae84e5963aae]$ wc */README.md|sort -n
       3       8      47 headers-core-0.2.0/README.md
       :
     449    2155   18023 tracing-0.1.29/README.md
     820    4392   30709 encoding_rs-0.8.30/README.md

やる気の無いREADME.mdから、これでもかって気合の入った物まで、様々。一番巨大なやつを試験してみる。

[sakae@fb /tmp]$ ./markdown.lua README.md
[sakae@fb /tmp]$ w3m README.html

これで、解決。以上終了、じゃつまんなので、rustでこれをやったら、どうなるか試してみるか。

mdm

名前firstって亊で、mdmって亊にする。これ、w3mのパクリ。w3(www) を m(miru)。

md を m(iru)ね。

目標は、下記のように使える変換器(兼表示器)を作る亊だ。

[sakae@fb /tmp]$ cat README.md | ./markdown.lua | w3m  -T text/html

こやつにmdmって名前を付けたい訳ね。これがunix流のtext文化ですよ。

sakae@deb:/tmp/t$ cat mdm
#!/bin/sh
cat README.md | \
markdown.lua  | \
w3m -T text/html

Debianにluaを入れた記念に、スクリプト化した。

catlog参照

楽しい々カタログを眺める時間。mdのフォーマットを解析するプログラムなんて自分で作ると終らなくなるんで、楽しようと言う魂胆。

Lib.rs で探しましょ。検索語は、markdown。更に絞るなら、html なんて語句を追加すればよい。以下は、適当そうなものを選んだ例だ。

ああ、検索は、crates.ioもお忘れなく。

最近、 Google検索は死につつあるなんて記事を読んだよ。rustの場合のカタログ検索は、どちらがGoogle相当なのだろうか?

markdown.rs

markdown.rs

cargo search markdown して、先頭に出て来る有名なや。

comrak

comrak

A 100% CommonMark-compatible GitHub Flavored Markdown parser and formatter

人気があるみたいで多数DLされてる。けど、色々な木箱のやっかいになり過ぎの感じがするぞ。

markdown-to-html

markdown-to-html

今回の目的には似わないけど、流行のWASMとかYewとか言うweb frameworkを使っていて、リナだったら、楽しめそう。

mini-markdown

minimarkdown

pure rustで書かれた半製品。Libs.rsのトップ画面にあるカテゴリー分類でVisualizationの部分に登場してたぞ。ビルボードの赤丸上昇中みたいだな。

cargo-registry-markdown

cargo-registry-markdown

上で出て来た、comrakを使ったライブラリィー。テスト部分が参考になるかな。

markdown2html-converter

markdown2html-converter

そのものずばりの名前が付いている。やはりcomrakを使ってる。comrakはこの分野のデファクト・スタンダードなのか。

select mini-markdown

市場調査では色々と見付かったけど、余計な木箱が必要無いという理由で、 mini_markdown を使ってみる亊にする。

本来なら、テストコードの参考にtestを参照するのが筋だろうけど、そんなに難しいインターフェースではなさそうなので、いきなり実験コードを作ってみる。

実験基盤で動作確認

Cargo.toml mini_markdown = "0.2.7" を追加する。そして、main.rs

use mini_markdown::parse;
use mini_markdown::lex;

pub fn render(source: &str) -> String {
    parse(&lex(source))
}

fn main() {
    let mds = "
# My first code
```
fn add(x: i32, y: i32) -> i32 { x + y }
```

Is it ok?
[MIT](https://choosealicense.com/licenses/mit/)
";
    let html = render(mds);
    println!("{}", html);
}

mdsの長ったらしい文字列は、最小のREADME.mdを模したものだ。結果は、

ob$ cargo r
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/mdm`
<h1 id="my-first-code">My first code</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre cl
ass="highlight"><code>fn add&#40;x: i32, y: i32&#41; -&gt; i32 &lbrace; x + y &r
brace;
</code></pre></div></div>
<p>Is it ok?
<a href="https://choosealicense.com/licenses/mit/" referrerpolicy="no-referrer">MIT</a></p>

htmlに仕立てる

上の結果では、見栄えが解らないので、前後に太ったhtmlの括弧を挟んであげる。

println!("<html><head><title>README.md</title></head><body>");
println!("{}", html);
println!("</body></head>");

そして、この結果をw3mに喰わせてみる。

ob$ target/debug/mdm | w3m -T text/html

w3mは、こんな風に表示してきた。

My first code

fn add(x: i32, y: i32) -> i32 &lbrace; x + y &rbrace;

Is it ok? MIT

惜しいな、波括弧の表現が、時代の流れに追従出来無くて、そのまま表示されちゃってる。 まて、 emacsに備付のブラウザー eww が有るじゃない。こちらでも確かめてみる。

M-x eww-open-fileRET
File: /tmp/mdm/zzz.html

結果はw3mと一緒だった。

これはもう、脳内変換してくださいって亊かな。 それに欲を言うと、コード部分を、それと分るようにしたいな。簡単に改造出来るか?

第1版

世間の荒波に揉まれない亊には、満足する物にはならないだろう。ってな亊で、決めうちでREADME.mdを読み込んで、それをhtmlファイルに変換するように作ってみた。出力はstdoutに流れてくるので、パイプでw3mに接ぐなり、一旦ファイルに落して、firefoxに喰わせるなりすればよい。

use mini_markdown::lex;
use mini_markdown::parse;

pub fn readfile() -> String {
    std::fs::read_to_string("README.md").expect("Need README.md")
}

pub fn render(source: &str) -> String {
    parse(&lex(source))
}

fn main() {
    let mds = readfile();
    let html = render(&mds);
    println!("<html><head><title>README.md</title></head><body>");
    println!("{}", html);
    println!("</body></head>");
}

出来上がったアプリのサイズが、とんでもなく大きいのが気になる。こんなものなのか。

sakae@deb:/tmp/mdm$ ls -l target/debug/mdm target/release/mdm
-rwxr-xr-x 2 sakae sakae 4826016 Feb 24 07:53 target/debug/mdm*
-rwxr-xr-x 2 sakae sakae 3506268 Feb 24 08:16 target/release/mdm*

problem

ちょいと問題点を2通、挙げておく。

mini_markdown/README.md をhtml化すると、前半部分(Syntax/Italic text当たりまで)が、正しくパースされない。

serde_json-1.0.78/README.md とか cc-1.0.73/README.md をhtml化しようとすると、ハングアップする。

DIY

木箱になってる mini_markdown を、取り込んで、自由に改造してみたい。その為にlib.rsとlexer.rsを下記のように配置とlib.rsの名前変更を行う。

ob$ tree src/
src/
|-- main.rs            ;; need modfy
|-- mini_markdown      ;; make new dir
|   `-- lexer.rs       ;; cp from mini_markdown
`-- mini_markdown.rs   ;; rename lib.rs and modfy (org mini_markdown)

main.rsの修整。

ob$ diff -u /home/sakae/mdm/src/main.rs src/main.rs
--- /home/sakae/mdm/src/main.rs Wed Feb 23 16:22:37 2022
+++ src/main.rs Thu Feb 24 14:35:48 2022
@@ -1,6 +1,6 @@
-use mini_markdown::parse;
-use mini_markdown::lex;
+mod mini_markdown;
+use crate::mini_markdown::parse;
+use crate::mini_markdown::lex;

それから mini_markdown.rs (org lib.rs)の修整。

--- /home/sakae/mini_markdown/src/lib.rs        Tue Feb 22 16:35:06 2022
+++ src/mini_markdown.rs        Thu Feb 24 14:42:47 2022
@@ -1,5 +1,5 @@
 pub mod lexer;
-use crate::lexer::*;
+use crate::mini_markdown::lexer::*;

src/mini_markdown.rs:388:8 render は不必要なので、コメントアウトする。 そして、CUIなブラウザーで見やすいように修整。(簡易diff -uで失礼)

-                "<div class=\"language-{} highlighter-rouge\"><div class=\"high
light\"><pre class=\"highlight\"><code>{}</code></pre></div></div>",
+                "<div class=\"language-{} highlighter-rouge\"><div class=\"high
light\"><pre class=\"highlight\">======<br><code>{}</code>------</pre></div></di
v>",

-        .replace('{', "&lbrace;")
-        .replace('}', "&rbrace;")
+//        .replace('{', "&lbrace;")
+//        .replace('}', "&rbrace;")

修整結果。w3mの画面ダンプ

My first code

======
fn add(x: i32, y: i32) -> i32 { x + y }
------

Is it ok? MIT

希望の通り、コード部分は、それと分るように区分けできた。波括弧も復活。サニタイズをこれでもかって具合にやってるけど、ローカルで使うんで許してね。

WASI

WASI tutorial

Wasmtime

WebAssemblyランタイム比較(Lucet, Wasmer, Wasmtime)

流行してるみたいだから、ちょっかい出してみるか。折角rust組に入っているんだからね。


This year's Index

Home