vivliostyle/vfm

<pre> タグのパースに失敗する

yamasy1549 opened this issue · 6 comments

Issue Details

  • VFM version
    • 1.0.0-alpha.17

Expected Behavior

https://vivliostyle.github.io/vfm/#/vfm#raw-html によれば、VFM では生の HTML をそのまま出力するので、以下の出力が期待されます。

$ echo '<pre>\n*    *    *\n   *    *    *\n</pre>' | vfm --partial

<pre>
*    *    *
   *    *    *
</pre>

Actual Behavior

しかし、<pre> タグを含んだ文字列をパースしようとするとエラーが出ます。

$ echo '<pre>\n*    *    *\n   *    *    *\n</pre>' | vfm --partial
/Users/yamasy1549/.config/yarn/global/node_modules/trough/wrap.js:33
        throw error
        ^

TypeError: Cannot read property 'title' of undefined
    at /Users/yamasy1549/.config/yarn/global/node_modules/@vivliostyle/vfm/lib/plugins/figure.js:64:136
    at overload (/Users/yamasy1549/.config/yarn/global/node_modules/unist-util-visit/index.js:27:12)
    at node (element<pre>) (/Users/yamasy1549/.config/yarn/global/node_modules/unist-util-visit-parents/index.js:56:27)
    at node (root) (/Users/yamasy1549/.config/yarn/global/node_modules/unist-util-visit-parents/index.js:67:75)
    at visitParents (/Users/yamasy1549/.config/yarn/global/node_modules/unist-util-visit-parents/index.js:29:26)
    at Object.visit [as default] (/Users/yamasy1549/.config/yarn/global/node_modules/unist-util-visit/index.js:22:3)
    at /Users/yamasy1549/.config/yarn/global/node_modules/@vivliostyle/vfm/lib/plugins/figure.js:60:31
    at wrapped (/Users/yamasy1549/.config/yarn/global/node_modules/trough/wrap.js:25:19)
    at next (/Users/yamasy1549/.config/yarn/global/node_modules/trough/index.js:57:24)
    at done (/Users/yamasy1549/.config/yarn/global/node_modules/trough/wrap.js:55:16)

以下のテストを実行したところ、

it('<pre>', () => {
  const actual = lib.stringify(`<pre>\n*    *    *\n   *    *    *\n</pre>`);
  const expected = `<pre>
*    *    *
*    *    *
</pre>`;
  expect(actual).toBe(expected);
});

問題が再現した。

 FAIL  tests/index.test.ts
  ● empty replace

    TypeError: Cannot read property 'title' of undefined

      62 |     // handle captioned code block
      63 |     const maybeCode = node.children?.[0] as HastNode | undefined;
    > 64 |     if (is(node, 'pre') && maybeCode?.properties.title) {
         |                                                  ^
      65 |       const maybeTitle = maybeCode?.properties?.title;
      66 |       delete maybeCode.properties.title;
      67 |       (parent as Parent).children[index] = h(

<pre> を HAST として処理する際、Markdown から変換されて title プロパティーが存在することを前提としていることが原因。後続の処理で maybeCode?.properties?.title としているが、これを if の時点でおこなうべき。

if (is(node, 'pre') && maybeCode?.properties?.title) {
  // if の判定で自明なので Optional Chaining 不要
  const maybeTitle = maybeCode.properties.title;
}

なお↑とは別件で <pre>\n* * *\n * * *\n</pre> を指定すると

<pre>
*    *    *
   *    *    *
</pre>

ではなく

<pre>*    *    *
   *    *    *
</pre>

になる。ここは remark の CommonMark/GFM 担当部分だが <pre> 開始の改行は処理しないのかもしれない。これも調べる。

CommonMark の動作検証

に指定したら

<pre>
*    *    *
   *    *    *
</pre>

になっていた。本件を修正後に別 issue としてこの問題を登録予定。

↑は #79 として登録したので本 issue はクラッシュ修正のみを扱う。

@yamasy1549
修正しました。VFM 1.0.0-alpha.18 以降に反映されますので、リリース後にご確認ください。問題がなければ issue の close をお願いします。

なお本件調査で別件 #79 を見つけました。これは別途、調査します。

@akabekobeko 修正ありがとうございます 🙏