\!{ author T. Nakagawa title 自作のWebページ用マークアップ言語 changelog 2021-04 製作
2021-11-20 ページ作成
2025-01-31 GitHubのREADME.mdに対応
\!} \2 はじめに これまで自分のホームページを作成するのに、KompoZerやBlueGriffon等のHTMLエディターを使ってきました。 WYSIWIGで編集することも、HTMLを直に編集することもできて便利なツールでしたが、不要なタグや空白が勝手に挿入されたり、HTML構文が不正なファイルが出力されることもあったりと使い勝手がいまいちでした。 普段はテキストエディターしか使わずTeXなどに慣れているので、WISIWIGやHTMLタグ直書きだとWebページ作成の効率が上がりませんでした。 そこで、今後はできるだけシンプルなマークアップ言語で書いたファイルからHTMLページを生成してWebページを作成することにしました。 文書作成用のマークアップ言語は色々ありますが、現在メジャーなものの一つにMarkdownがあります。 Markdownはテキストファイルとして見た場合に比較的可読性が高いという利点がありますが、プログラミング言語のように文脈自由文法で文法が定義されておらずトークンの位置情報が意味を持つなど気持ちが悪い部分があります。 リストの中に別のリストやテーブルが入るような入れ子構造や、どのような場合に文字がエスケープされるのかといった文法が明確になっていないと混乱することがあります。 既存の他の軽量マークアップ言語も調べましたが自分の目的にあった適当なものがないので、独自のマークアップ言語を定義してHTMLへのコンバータを作ることにしました。 テキストファイルでの見栄えは重視しませんが、できるだけシンプルな構文を持ちHTMLを直書きするよりも簡潔に表現できるようにしました。 要するに自分にとっての使いやすさを第一に考えて作っています。 \2 文法と例 \3 概要 すべてのマークアップ用タグは\\xのように\\記号と1つの文字で表現されます。 マークアップ用のタグにはインライン要素とブロック要素があります。 インライン要素は文書中のどの位置でも使えます。 ブロック要素は\\x{...\\x}のように波括弧を付けた開始タグと終了タグで範囲を囲んで複数行に書く方法と、\\xの直後にタブ文字を置いて1行に書く方法とがあります。 テーブルなどのブロックの要素を複数行に書く場合でも、タブで区切ることで1行の中に複数の要素を記述できます。 ブロック要素には通常ブロック要素とメタブロック要素があります。 通常ブロックはその内部にマークアップされた文書を持ちますが、メタブロックは生のHTML文書を持ちHTMLタグなどはエスケープされません。 パラグラフは、連続する行で構成されて空行で終了します。 連続した行の改行は削除して連結されるため、日本語の場合は複数行があっても不要な空白が入ることはありませんが、英語の場合は文頭や文末に明示的にスペースを入れる必要があります。 \3 タグ一覧 \|{ cl \<通常ブロック要素\> \\= 水平線 \\1~\\5 H1~H5見出し \\- 順序無しリスト \\+ 順序付きリスト \\* 記述リスト \\| テーブル \\& ブロック連結 \\! 変数定義 \\^ 画像 \<メタブロック要素\> \\" 引用 \\@ 生のHTML \<インライン要素\> \\\\ \\文字 \\/ 改行 \\(テキスト\\) イタリック体 \\<テキスト\\> ボールド体 \\[ラベル\\] ページ内ラベル \\[リンクテキスト\\:リンク先\\] リンク \\{変数名\\} 変数参照 \\`生HTML\\' 生のHTML \|} \3 内部変数 このマークアップ言語では変数を定義することができます。 文書中でその値を参照することもできますが、以下の変数はスクリプト内でHTMLを出力する際に参照されます。 \|{ cl author 著者名 changelog 編集履歴 home ホームページのURL thumbnail_height 画像サムネイルの高さ \|} \3 BNFによる文法の定義 \"{ <document> ::= { LF | <block_expr> | <paragraph> } <paragraph> ::= <inline_expr> LF { <inline_expr> LF } LF ; 段落 <block_expr> ::= <block1_tag> { TAB <inline_expr> } LF | ; 通常ブロックタグの一行表記 <block1_tag> "{" LF { <block_expr> | <inline_expr> { TAB <inline_expr> } LF } <block1_tag> "}" LF | ; 通常ブロックタグの複数行表記 <block2_tag> { TAB <raw_expr> } LF | ; メタブロックタグの一行表記 <block2_tag> "{" LF { <raw_expr> LF } <block2_tag> "}" LF ; メタブロックタグの複数行表記 <block1_tag> ::= "\=" | "\1" | "\2" | "\3" | "\4" | "\5" | "\-" | "\+" | "\*" | "\|" | "\&" | "\!" | "\^" <block2_tag> ::= '\"' | "\@" <inline_expr> ::= { <inline_elem> } <inline_elem> ::= <raw_expr> | "\\" | "\/" | "\(" | "\)" | "\<" | "\>" | "\[" <raw_expr> "\]" | "\[" <raw_expr> "\:" <raw_expr> "\]" | "\{" <raw_expr> "\}" | "\`" <raw_expr> "\'" <raw_expr> ::= <String of any characters> \"} \3 タグの説明 \*{ \<インライン要素\> \&{ \(入力\) \"{ \\文字が\(様々\)な\<ところ\>で\/使われます。これは\[リンク\:sample.png\]と\[label\]ラベルです。\`a<sup>b</sup><sub>c</sub>\' \"} \(出力\) \@
\\文字が\(様々\)な\<ところ\>で\/使われます。これは\[リンク\:sample.png\]とラベルです。\`abc\' \@
\&} \<\\=\> (水平線) \&{ 水平線を挿入します。\/\/ \(入力\) \"{ 文書1 \= 文書2 \"} \(出力\) \@
文書1 \= 文書2 \@
\&} \<\\1~\\5\> (H1~H5見出し) \&{ HTMLのH1〜H5に対応する見出しを生成します。\/\/ \(入力\) \"{ \2 これは \3{ テストです \3} \"} \(出力\) \@
\2 これは \3{ テストです \3} \@
\&} \<\\-, \\+\> (順序無しリスト、順序付きリスト) \&{ 順序無し・順序付きリストを生成します。 このブロックはタブ文字または改行で区切られた複数の要素を持ちます。\/\/ \(入力\) \"{ \- a b \+{ AA \-{ aa bb \-} BB CC \+} \"} \(出力\) \@
\- a b \+{ AA \-{ aa bb \-} BB CC \+} \@
\&} \<\\*\> (記述リスト) \&{ 記述リストを生成します。 このブロックはタブ文字または改行で区切られた複数の要素を持ちますが、要素の数は2の倍数でなければなりません。 リストの各項目の見出しと内容が交互に並びます。\/\/ \(入力\) \"{ \*{ a aa b bb c cc d dd \*} \"} \(出力\) \@
\*{ a aa b bb c cc d dd \*} \@
\&} \<\\|\> (テーブル) \&{ テーブルを作成します。 このブロックはタブ文字または改行で区切られた複数の要素を持ちますが、要素の数は(1 + 行数 * 列数)でなければなりません。 最初の要素は、列数と同じ長さのl, c, rの3文字からなる文字列で、テーブルの各列のフォーマット(それぞれ左詰め、センタリング、右詰め)を指定します。\/\/ \(入力\) \"{ \|{ lcr aaa bbb ccc d e f \|} \"} \(出力\) \@
\|{ lcr aaa bbb ccc d e f \|} \@
\&} \<\\&\> (ブロック連結) \&{ 複数のブロックを一つのブロックとしてまとめます。 リストやテーブルに複数のブロックをまとめて入れたい場合などに使います。\/\/ \(入力\) \"{ \-{ \| c a \&{ \| c b \^ sample.png \&} \&{ \| c c \| c d \&} \-} \"} \(出力\) \@
\-{ \| c a \&{ \| c b \^ sample.png \&} \&{ \| c c \| c d \&} \-} \@
\&} \<\\!\> (変数定義) \&{ 変数の値を定義します。 このブロックはタブ文字または改行で区切られた複数の要素を持ちますが、要素の数は2の倍数でなければなりません。 変数名と変数の値が交互に並びます。 HTML出力の際には、ここで定義した変数の値が使われます。 このブロックはメタブロックであり、要素の値はエスケープされたりしないのでHTMLやJavaScriptなども直接記述できます。\/\/ \(入力\) \"{ \!{ x 123 \!} x=\{x\} \"} \(出力\) \@
\!{ x 123 \!} x=123 \@
\&} \<\\^\> (画像) \&{ 画像を表示します。 このブロックはタブ文字または改行で区切られた1つ以上の要素を持ちます。 要素数が1つの場合は画像をセンタリングして表示します。 要素数が3の倍数の場合はリンク先、サムネイル画像、ラベルをそれぞれ意味し、ラベルのついたリンク付き画像を並べて表示します。 \/\/ \(入力\) \"{ \^{ sample.png sample.png ラベル1 ../ sample.png ラベル2 \^} \"} \(出力\) \@
\^{ sample.png sample.png ラベル1 ../ sample.png ラベル2 \^} \@
\&} \<\\"\> (引用) \&{ 整形済みのテキストを表示します。\/\/ \(入力\) \"{ \"{ ab\(c\) de<i>f</i> \"} \"} \(出力\) \@
\"{ ab\(c\) def \"} \@
\&} \<\\@\> (生のHTML) \&{ HTMLのソースを直接記述します。 \&} \*} \2 HTMLへのコンバーター Pythonで再帰下降構文解析を行い、このWebマークアップ用言語からHTMLファイルを生成するコンバーターを書きました。 スクリプトは\[ここ\:https://github.com/middle-river/wml2html\]に置いてあります。 \2 使用例など このホームページの作成に7ヶ月ほど使用してきましたが、テキストエディターを使って手軽にWebページを用意できるようになり手間を減らすことができました。 また変換スクリプトからは必ず正しいHTMLファイルが出力されるので、不正なHTML構文を持つページができることもなくなりました。 参考までに、このページの生成に使われたマークアップファイルを\[ここ\:README.wml\]に置いておきます。 このマークアップ言語には自分が必要とする最低限の機能しかありませんが、例外的な記述が必要な場合は生のHTMLを挿入して対応し、足りなくてどうしても不便な機能が出てくればその都度追加していくつもりです。 \2 GitHubのREADME.mdの生成 (2025/01追記) これまで利用してきたWebホスティングサービスからコンテンツの一部をGitHubに移行することにしました。 それに際して、このマークアップ言語からREADME.mdを生成することにしました。 GitHubのREADME.mdはMarkdownで書かれますが、Markdownは厳格な文法を持っていないため扱いにくいので、GitHubのREADME.mdに含めることができる制限されたHTMLを生成することにしました。 GitHubで扱うことができるHTMLについては、\[GitHub Flavored Markdown Spec\:https://github.github.com/gfm/\]に記述されています。 例えば、style属性は無効になるのでalign属性を使用したり、コロン(:)を実体参照(:)に置き換えてhttp://等で始まるURLがリンク化されるのを防いだり、
タグの前に空行を出力してHTMLブロックが途中で終了しないようにするなどの処理を行っています。
ただし、
タグに対応していないため画像のキャプションが見やすく表示されないなどの制限があります。