Hoextdown ライブラリ (マークダウン処理)

  • KJ
  • 2014/11/14

Version: 3.0.3

Fenced Code スタイルのスクリプトタグと PHP 等のスクリプトタグ出力を追加

Hoextdown に新たに次の処理を追加しました。

Fenced Code スタイルによるスクリプトタグの出力

HOEDOWN_HTML_FENCED_CODE_SCRIPT オプションを有効にすると Fenced Code スタイルで HTML のスクリプトタグ (<script..>) を出力することができます。

Fenced Code スタイルで言語指定部分を script@ から始めるとスクリプトタグの表示になります。(@ より後の部分はスクリプトタグの type になります)

次のようなマークダウンテキストを定義した場合

 ``` script@text/javascript
 alert("Example");
 ```

Fenced Code を有効にして処理すると

<pre><code class="language-script@text/javascript">alert(&quot;Example&quot;);
</code></pre>

のようになりますが、さらに HOEDOWN_HTML_FENCED_CODE_SCRIPT も有効にした場合は

<script type="text/javascript">
alert("Example");
</script>

のようになります。

HOEDOWN_HTML_FENCED_CODE_SCRIPT を機能させるためには HOEDOWN_EXT_FENCED_CODE オプションも同時に指定する必要があります。

何のためか

個人的に UML 図等もマークダウンと共にテキストで処理したいと思ったからです。

JUMLY を用いればテキストで表現できそうだったのですがマークダウン内にスクリプトタグを書くのは嫌だなと思い、Fenced Code スタイルで表現することにさせました。

JUMLY の入力サンプルは次のようになります。

 ``` script@text/jumly+sequence
 @found "You", ->
   @message "get", "JUMLY"
 ```

JUMLY 以外には応用はできそうなのでどこかで使う機会はあるかなと思っています。

PHP 等 (<?..?>) のスクリプトタグの生出力

HOEDOWN_HTML_SCRIPT_TAGS オプションを有効にすると <??> で囲まれた部分をそのまま表示することができます。

次のようなマークダウンテキストを定義した場合

This is <?php echo "an example" ?> test.

<?php echo "PHP Example"; ?>

通常は

<p>This is &lt;?php echo &quot;an example&quot; ?&gt; test.</p>

<p>&lt;?php echo &quot;PHP Example&quot;; ?&gt;</p>

のように <? 部分はエスケープ処理されて出力されます。

HOEDOWN_HTML_SCRIPT_TAGS を有効にした場合は

<p>This is <?php echo "an example" ?> test.</p>

<?php echo "PHP Example"; ?>

のようにエスケープションされずにそのまま出力されます。

何のためか

示した例を見ても分かる通り、PHP でマークダウン処理を行うためにこのライブラリを用いることを考えているおり、テンプレートでマークダウンを書く時に PHP コードをどうしても埋め込む必要があったので実装しました。

以前追加したユーザーブロック処理も同じことを考えてのことでしたが処理コードを追加しなければならないので今回改めて新しい処理を追加しました。

Version: 2.0.0.2

Header ID, ユーザーブロック処理を追加

Hoextdown に新たに Header ID の出力とユーザーブロック処理を追加しました。

実際にこのライブラリは Markdown Template Engine for Phalcon のマークダウン処理に用いています。

Header ID 出力

Header ID の出力を行うために新たに HOEDOWN_HTML_HEADER_ID という html フラグを追加しました。

出力を行うためにはこのフラグを定義します。

HOEDOWN_HTML_HEADER_ID が有効になった場合、次のようなマークダウンファイルは

# Header 1

ヘッダタグに ID 属性が付与されるようになります。

ID はヘッダ内容から生成されます。

<h1 id="header-1">Header 1</h1>

ヘッダ内容が同じ場合は -1, -2, ... と番号が末尾に付与されます。

markdown

# Header

# Header

# Header

html

<h1 id="header">Header</h1>

<h1 id="header-1">Header</h1>

<h1 id="header-2">Header</h1>

日本語の場合も同じように処理されます。

markdown

# 日本語

# 日本語

html

<h1 id="日本語">日本語</h1>

<h1 id="日本語-1">日本語</h1>

ユーザーブロック処理

ユーザーブロック処理は PHP のコード等のように通常のマークダウンフォーマット以外の処理は判別できるように追加しました。

PHP のコードを追加した場合の例を以下に示しておきます。

markdown

# PHP

<?php echo 'Test'; ?>

のようなマークダウンファイルが合った場合、普通に処理すると

html

<h1>PHP</h1>

<p>&lt;?php echo &#39;Test&#39;; ?&gt;</p>

のように <, > 等はエスケープ処理されて出力されます。

これをユーザーブロック処理を用いて PHP コード部分はそのまま出力するようにしてみます。

コードブロック判定

ユーザーブロック処理はまず、コードブロックの判定関数を定義します。

size_t is_php_block(uint8_t *data, size_t size, void *opaque)
{
    size_t i = 0;

    if (size < 7 || strncasecmp((char *)data, "<?php", 5) != 0) {
        return 0;
    }
    i = 5;
    while (i < size) {
        if (strncasecmp((char *)data+i, "?>", 2) == 0) {
            return i + 2;
        }
        ++i;
    }

    return 0;
}

コードブロックの判定関数は document.h に定義されている hoedown_is_user_block 型に定義します。

戻り値はコードブロック部分の長さになります。

関数を定義したら hoedown_document_new の 4 つ目の引数に指定して処理します。

document = hoedown_document_new(renderer, extensions, max_nesting, is_php_block);

これを実行すると出力は次のようになります。

html

<h1>PHP</h1>
<?php echo 'Test'; ?>

コードブロックレンダリング

コードブロックのレンダリングは document.hhoedown_renderer にある void (*user_block)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque) を指定することで処理できます。

例えば、PHP コードの前に PHP code block: を出力するようにする場合は user_block 関数として次のようなものに定義し、

static void
php_block(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
{
    if (text) {
        HOEDOWN_BUFPUTSL(ob, "PHP code block: ");
        hoedown_buffer_put(ob, text->data, text->size);
    }
}

hoedown_rendereruser_block を指定して実行します。

renderer->user_block = php_block;
document = hoedown_document_new(renderer, extensions, max_nesting, is_php_block);

出力は次のようになります。

html

<h1>PHP</h1>
PHP code block: <?php echo 'Test'; ?>

その他

Hoextdown は他にも次の処理ができるようになっています。

ビルド

ビルドは Hoextdown から Archive ファイルをダウンロードするか git clone してから make を実行するだけです。

$ git clone --depth=1 https://github.com/kjdev/hoextdown.git
$ cd hoextdown
$ make
$ make test

make すると hoedown (バイナリファイル)が出来るのでこのコマンドの引数にファイルを指定したり、標準入力にマークダウンテキストを与えることで処理されます。

$ ./hoedown README.md
...
$ echo '# Header' | ./hoedown
<h1>Header</h1>

実行オプション等は --help にて確認してください。

$ echo '# Header' | ./hoedown --header-id
<h1 id="header">Header</h1>

ダウンロード

リポジトリ

github.com/kjdev/hoextdown

ソースファイル

hoextdown-master.tar.gz

RPM パッケージ

CentOS 6

hoextdown-3.0.0.3

hoextdown-devel-3.0.0.3

CentOS 7

hoextdown-3.0.0.3

hoextdown-devel-3.0.0.3

Fedora 20

hoextdown-3.0.0.3

hoextdown-devel-3.0.0.3