\!{ author T. Nakagawa title 自作のWebページ用マークアップ言語 changelog 2021-04 製作
2021-11-20 ページ作成
\!} \2 はじめに これまでこのホームページを作成するのに,KompoZerやBlueGriffon等のHTMLエディターを使ってきました. WYSIWIGで編集することも,HTMLを直に編集することもできて便利なツールでしたが,不要なタグや空白が勝手に挿入されたり,HTML構文が不正なファイルが出力されることもあったりと使い勝手がいまいちでした. 普段はテキストエディターしか使わずTeXなどに慣れているので,WISIWIGやHTMLタグ直書きだとWebページ作成の効率が上がりませんでした. そこで,今後はできるだけシンプルなマークアップ言語で書いたファイルからHTMLページを生成してWebページを作成することにしました. 文書作成用のマークアップ言語としては歴史のあるroffを含めて数多くありますが,現在メジャーなものの一つにMarkdownがあります. Markdownはテキストファイルとして見た場合に比較的可読性が高いという利点がありますが,プログラミング言語のように文脈自由文法で文法が定義されておらずトークンの位置情報が意味を持つなど気持ちが悪い部分があります. リストの中に別のリストやテーブルが入るような入れ子構造や,どのような場合に文字がエスケープされるのかといった文法が明確になっていないと混乱することがあります. 既存の他の軽量マークアップ言語も調べましたが自分の目的にあった適当なものがないので,独自のマークアップ言語を定義してHTMLへのコンバータを作ることにしました. Markdownのようにテキストファイルでの見栄えは重視しませんが,できるだけシンプルな構文を持ちHTMLを直書きするよりも簡潔に表現できるようにしました. 要するに自分にとっての使いやすさを第一に考えて作っています. \2 文法と例 \3 概要 すべてのマークアップ用タグは\\xのように\\記号と1文字で表現されます. マークアップ用のタグにはインライン要素とブロック要素があります. インライン要素は文書中のどの位置でも使えます. ブロック要素は\\x{...\\x}のように波括弧を付けた開始タグと終了タグで範囲を囲んで複数行に書く方法と,\\xの直後にタブ文字を置いて1行に書く方法とがあります. テーブルなどのブロックの要素を複数行に書く場合でも,タブで区切ることで1行の中に複数の要素を記述できます. インラインタグとブロックタグにはそれぞれ通常タグとメタタグがあります. 通常タグは別のマークアップされた文書を要素に持ちますが,メタタグは生のHTML文書を要素に持ちHTMLタグなどもエスケープされません. このマークアップ言語ではいくつかの変数が定義されていて,文書中でその値を定義できます. 例えばページタイトルや著者名などです. これらはHTMLへの変換スクリプトの内部で参照されて利用されます. \3 タグ一覧 \-{ 通常ブロック要素 \|{ cl \\= 水平線 \\1~\\5 H1~H5見出し \\- 順序無しリスト \\+ 順序付きリスト \\* 記述リスト \\| テーブル \\& ブロック連結 \|} メタブロック要素 \|{ cl \\! 変数定義 \\^ 画像 \\" 引用 \\@ 生のHTML \|} 通常インライン要素 \|{ cl \\\\ \\文字自体 \\/ 改行 \\(テキスト\\) イタリック体 \\<テキスト\\> ボールド体 \|} メタインライン要素 \|{ cl \\[テキスト\\:リンク\\] リンク \\`生HTML\\' 生のHTML \|} 変数 \|{ cl author 著者名 title ページタイトル changelog 編集履歴 script スクリプト定義 subtitle ページサブタイトル \|} \-} \3 BNFによる文法の定義 \"{ <web_markup> ::= { <block_expr> } <block_expr> ::= <block1_tag> { "\t" <inline_expr> } "\n" | ; 通常ブロックタグの一行表記 <block1_tag> "{\n" { <block_expr> | <inline_expr> { "\t" <inline_expr> } "\n" } <block1_tag> "}\n" | ; 通常ブロックタグの複数行表記 <block2_tag> { "\t" <raw_expr> } "\n" | ; メタブロックタグの一行表記 <block2_tag> "{\n" { <raw_expr> { "\t" <raw_expr> } "\n" } <block2_tag> "}\n" | ; メタブロックタグの複数行表記 <paragraph> | ; 段落 "\n" ; 空行 <block1_tag> ::= "\=" | "\1" | "\2" | "\3" | "\4" | "\5" | "\-" | "\+" | "\*" | "\|" | "\&" <block2_tag> ::= "\!" | "\^" | '\"' | "\@" <paragraph> ::= <inline_expr> "\n" { <inline_expr> "\n" } <inline_expr> ::= { <inline_elem> } <inline_elem> ::= <raw_expr> | "\\" | "\/" | "\(" | "\)" | "\<" | "\>" | "\[" <raw_expr> "\:" <raw_expr> "\]" | "\`" <raw_expr> "\'" \"} \3 タグの説明 \*{ \<インライン要素\> \&{ \(入力\) \"{ \\文字が\(様々\)な\<ところ\>で\/使われます. これは\[リンク\:sample.png\]です. \`a<sup>b</sup><sub>c</sub>\' \"} \(出力\) \@
\\文字が\(様々\)な\<ところ\>で\/使われます. これは\[リンク\:sample.png\]です. \`abc\' \@
\&} \<\\=\> (水平線) \&{ 水平線を挿入します. \(入力\) \"{ 文書1 \= 文書2 \"} \(出力\) \@
文書1 \= 文書2 \@
\&} \<\\1~\\5\> (H1~H5見出し) \&{ HTMLのH1〜H5に対応する見出しを生成します. このタグは複数の要素を持つことができて,すべての要素を連結した内容をHタグで囲んだ結果を生成します. \(入力\) \"{ \2 これは \3 テスト です \4{ これも です \4} \"} \(出力\) \@
\2 これは \3 テスト です \4{ これも です \4} \@
\&} \<\\-, \\+\> (順序無しリスト,順序付きリスト) \&{ 順序無し・順序付きリストを生成します. このブロックはタブ文字または改行で区切られた複数の要素を持ちます. 空行の要素があるとその次の項目を
  • タグで囲まないため,リストの中にリストを入れる場合に使えます. \(入力\) \"{ \\- a b \\+{ AA \\-{ aa bb \\-} BB CC \\+} \"} \(出力\) \@
    \- a b \+{ AA \-{ aa bb \-} BB CC \+} \@
    \&} \<\\*\> (記述リスト) \&{ 記述リストを生成します. このブロックはタブ文字または改行で区切られた複数の要素を持ちますが,要素の数は2の倍数でなければなりません. リストの各項目の見出しと内容の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 \&{ \| c c \| c d \&} \-} \"} \(出力\) \@
    \-{ \| c a \| c b \&{ \| c c \| c d \&} \-} \@
    \&} \<\\!\> (変数定義) \&{ 変数の値を定義します. このブロックはタブ文字または改行で区切られた複数の要素を持ちますが,要素の数は2の倍数でなければなりません. 変数名と変数の値の2組の要素が連続します. HTML出力の際には,ここで定義した変数の値が使われます. このブロックはメタブロックであり,要素の値はエスケープされたりしないのでHTMLやJavaScriptなども直接記述できます. \(入力\) \"{ author MyName title MyTitle changelog 1月2日 ページ作成<br>2月3日 ページ更新<br> \"} \&} \<\\^\> (画像) \&{ ラベルのついたリンク付き画像を並べて表示します. このブロックはタブ文字または改行で区切られた複数の要素を持ちますが,要素の数は3の倍数でなければなりません. リンク先,サムネイル画像,ラベルの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ヶ月ほど使用してきましたが,Emacsを使って手軽にWebページを用意できるようになり手間を減らすことができました. また,変換スクリプトからは必ず正しいHTMLファイルが出力されるので,不正なHTML構文ができて気持ちが悪い思いをするこということもなくなりました. 参考までに,このページの生成に使われたマークアップファイルを\[ここ\:sample.txt\]に置いておきます. このマークアップ言語には自分が必要とする機能しかありませんが,例外的な記述が必要な場合は生HTMLを挿入して対応し,また足りなくて不便な機能が出てくればその都度追加していくつもりです.