vivliostyle / vfm

⬇️ Open and extendable Markdown syntax and toolchain.
https://vivliostyle.github.io/vfm/#/vfm
Other
71 stars 12 forks source link

Attributes on headings not parsed properly when the heading ends with an inline element #46

Open MurakamiShinyu opened 3 years ago

MurakamiShinyu commented 3 years ago

Issue Details

Expected Behavior

$ echo '# Heading *test* {#foo}' | vfm --partial
<section id="foo"><h1>Heading <em>test</em></h1></section>

$ echo '## Heading <span>Test</span>  {#test lang=en}' | vfm --partial
<section id="test" lang="en"><h2>Heading <span>Test</span></h2></section>

Actual Behavior

$ echo '# Heading *test* {#foo}' | vfm --partial
<section id="heading-test-foo"><h1>Heading <em>test</em> {#foo}</h1></section>

$ echo '## Heading <span>Test</span>  {#test lang=en}' | vfm --partial
<section id="heading-spantestspan--test-langen"><h2>Heading <span>Test</span>  {#test lang=en}</h2></section>

このように、見出しの内容の終わりに何かインライン要素が場合、属性の指定 {…} が処理されず、見出しの内容として出力されてしまいます。

MurakamiShinyu commented 3 years ago

Spec

Related spec discussion: https://github.com/vivliostyle/vfm/issues/9

akabekobeko commented 3 years ago

属性は remark-attr により処理される。その README には "Header (Atx)" として以下の記法を例示している。

### This is a title
{style="color:red;"}

or

### This is a title {style="color:yellow;"}

If option enableAtxHeaderInline is set to `true` (default value).

ひとつ目のヘッダー直後行へ属性を記述する方法であれば期待値どおりの動作をするようだ。以下、手元で追加 & 通過したテスト コード。

import { stripIndent } from 'common-tags';
import { buildProcessorTestingCode } from './utils';

it(
  'Header with inline elements',
  buildProcessorTestingCode(
    `# Heading *test*\n{#foo}`,
    stripIndent`
    root[1]
    └─0 heading[2]
        │ depth: 1
        │ data: {"hProperties":{"id":"foo"}}
        ├─0 text "Heading "
        └─1 emphasis[1]
            └─0 text "test"
    `,
    `<section id="foo"><h1>Heading <em>test</em></h1></section>`,
  ),
);

これで村上さんの指摘している問題に対処可能と思われるが VFM としては現状

となっており、この記法による回避策をユーザーが知るのは難しい。よってこれらを補う必要あり。

akabekobeko commented 3 years ago

ヘッダーに id 属性が指定された場合に <section> へ移動させているのは別件。上記テスト コードの MDAST 側を見てのとおりこの時点ではヘッダーに属しており、後処理で移動させている。本件としてはあくまで属性機能に関してのみ扱う。

akabekobeko commented 3 years ago

手元で既にそうしているが、テスト コードは index.test.ts ではなく独立した attr.test.ts として追加するのがよいだろう。その際、index.test.ts の既存テストは削除して新しいほうで網羅的に書く。

段階的に index.test.ts のテストは個別の記法へ移譲してゆきたい。これが担当すべきは index.ts 固有の処理であり、そこから呼び出されるものは実装となる *.ts と対応しているほうが運用面でも好ましいので少しずつそうしてゆく。

MurakamiShinyu commented 3 years ago

remark-attr で

### This is a title {style="color:yellow;"}

がOKなのに

### This is a **title** {style="color:yellow;"}

がダメというのは、remark-attr のバグといえるのでないでしょうか?

### This is a **title**{style="color:yellow;"}

<h3>This is a <strong style="color:yellow;">title</strong></h3>

のように、 **title**{…} が隣接している場合には **title** の属性になるということは理解できます。しかし、あいだにスペースがあるときに属性指定と認識されずにそのままテキストとして出力される (<h3>This is a <strong>title</strong> {style="color:yellow;"}</h3>) というのは正常な動作ではない感じがします。

akabekobeko commented 3 years ago

確かにバグな気もしますね。ただ実装がけっこう複雑でざっと読んだだけではそうなる原理がわかりませんでした。remark-attr に後で issue を登録して質問しようと思います。

akabekobeko commented 3 years ago

remark-attr に Issue として報告してみました。

MurakamiShinyu commented 3 years ago

@akabekobeko

{# header-3} remains as an attribute.

"remains as text content" でないでしょうか?

akabekobeko commented 3 years ago

うっかりしてました。直しておきました。

akabekobeko commented 3 years ago

2021/3/7 の開発者会議で本件について相談したところ、v1.0 としては見送ることになった。理由は以下。