vivliostyle/vfm

HTML block with markdown heading causes wrong HTML sectioning

Closed this issue · 1 comments

Issue Details

HTMLブロックで記述した開始タグと終了タグとの間にマークダウンでの見出しがあると、間違ったセクション構造のHTML出力となります。

問題が起きる例:

TEST.md

# Heading 1

## Heading 2-1

<aside class="note">

### NOTE

This is a note.

</aside>

## Heading 2-2
  • VFM version
    • 2.1.0

Expected Behavior

"heading-2-2" のsectionは、"heading-2-1" と同じレベルのはずです。

  <body>
    <section class="level1" aria-labelledby="heading-1">
      <h1 id="heading-1">Heading 1</h1>
      <section class="level2" aria-labelledby="heading-2-1">
        <h2 id="heading-2-1">Heading 2-1</h2>
        <aside class="note">
          <section class="level3" aria-labelledby="note">
            <h3 id="note">NOTE</h3>
            <p>This is a note.</p>
          </section>
        </aside>
      </section>
      <section class="level2" aria-labelledby="heading-2-2">
        <h2 id="heading-2-2">Heading 2-2</h2>
      </section>
    </section>
  </body>

Actual Behavior

"heading-2-2" のsection開始タグの前に2つの終了タグが入ってしまい、前のセクション "heading-2-1" が閉じてさらに親のセクションのはずの "heading-1" まで閉じて、その兄弟要素になってしまっている。

  <body>
    <section class="level1" aria-labelledby="heading-1">
      <h1 id="heading-1">Heading 1</h1>
      <section class="level2" aria-labelledby="heading-2-1">
        <h2 id="heading-2-1">Heading 2-1</h2>
        <aside class="note">
          <section class="level3" aria-labelledby="note">
            <h3 id="note">NOTE</h3>
            <p>This is a note.</p>
          </section>
        </aside>
      </section>
    </section>
    <section class="level2" aria-labelledby="heading-2-2">
      <h2 id="heading-2-2">Heading 2-2</h2>
    </section>
  </body>

Debug log (Any)

Run vfm with DEBUG=vfm to see detailed log.

DEBUG=vfm vfm TEST.md
  vfm 
  vfm ### mdast ### +0ms
  vfm root[1]
  vfm └─0 section[3]
  vfm     │ data: {"hName":"section","hProperties":{"class":["level1"],"aria-labelledby":"heading-1"}}
  vfm     │ depth: 1
  vfm     ├─0 heading[1]
  vfm     │   │ depth: 1
  vfm     │   │ data: {"hProperties":{"id":"heading-1"},"id":"heading-1"}
  vfm     │   └─0 text "Heading 1"
  vfm     ├─1 section[3]
  vfm     │   │ data: {"hName":"section","hProperties":{"class":["level2"],"aria-labelledby":"heading-2-1"}}
  vfm     │   │ depth: 2
  vfm     │   ├─0 heading[1]
  vfm     │   │   │ depth: 2
  vfm     │   │   │ data: {"hProperties":{"id":"heading-2-1"},"id":"heading-2-1"}
  vfm     │   │   └─0 text "Heading 2-1"
  vfm     │   ├─1 html "<aside class=\"note\">"
  vfm     │   └─2 section[3]
  vfm     │       │ data: {"hName":"section","hProperties":{"class":["level3"],"aria-labelledby":"note"}}
  vfm     │       │ depth: 3
  vfm     │       ├─0 heading[1]
  vfm     │       │   │ depth: 3
  vfm     │       │   │ data: {"hProperties":{"id":"note"},"id":"note"}
  vfm     │       │   └─0 text "NOTE"
  vfm     │       ├─1 paragraph[1]
  vfm     │       │   └─0 text "This is a note."
  vfm     │       └─2 html "</aside>"
  vfm     └─2 section[1]
  vfm         │ data: {"hName":"section","hProperties":{"class":["level2"],"aria-labelledby":"heading-2-2"}}
  vfm         │ depth: 2
  vfm         └─0 heading[1]
  vfm             │ depth: 2
  vfm             │ data: {"hProperties":{"id":"heading-2-2"},"id":"heading-2-2"}
  vfm             └─0 text "Heading 2-2" +1ms
  vfm 
  vfm ### hast ### +4ms
  vfm root[2] (1:1-14:1, 0-103)
  vfm │ data: {"quirksMode":false}
  vfm ├─0 element<section>[2]
  vfm │   │ properties: {"className":["level1"],"ariaLabelledBy":["heading-1"]}
  vfm │   ├─0 element<h1>[1]
  vfm │   │   │ properties: {"id":"heading-1"}
  vfm │   │   └─0 text "Heading 1"
  vfm │   └─1 element<section>[2]
  vfm │       │ properties: {"className":["level2"],"ariaLabelledBy":["heading-2-1"]}
  vfm │       ├─0 element<h2>[1]
  vfm │       │   │ properties: {"id":"heading-2-1"}
  vfm │       │   └─0 text "Heading 2-1"
  vfm │       └─1 element<aside>[1] (1:1-1:9, 0-8)
  vfm │           │ properties: {"className":["note"]}
  vfm │           └─0 element<section>[2] (1:1, 0)
  vfm │               │ properties: {"className":["level3"],"ariaLabelledBy":["note"]}
  vfm │               ├─0 element<h3>[1]
  vfm │               │   │ properties: {"id":"note"}
  vfm │               │   └─0 text "NOTE"
  vfm │               └─1 element<p>[1]
  vfm │                   │ properties: {}
  vfm │                   └─0 text "This is a note."
  vfm └─1 element<section>[1]
  vfm     │ properties: {"className":["level2"],"ariaLabelledBy":["heading-2-2"]}
  vfm     └─0 element<h2>[1]
  vfm         │ properties: {"id":"heading-2-2"}
  vfm         └─0 text "Heading 2-2" +1ms
  vfm {} +3ms
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Heading 1</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <section class="level1" aria-labelledby="heading-1">
      <h1 id="heading-1">Heading 1</h1>
      <section class="level2" aria-labelledby="heading-2-1">
        <h2 id="heading-2-1">Heading 2-1</h2>
        <aside class="note">
          <section class="level3" aria-labelledby="note">
            <h3 id="note">NOTE</h3>
            <p>This is a note.</p>
          </section>
        </aside>
      </section>
    </section>
    <section class="level2" aria-labelledby="heading-2-2">
      <h2 id="heading-2-2">Heading 2-2</h2>
    </section>
  </body>
</html>

Fenced block #5 によって解決されると期待されている問題ですが、この問題はその前に解決したほうがよいかもしれないのでIssue登録しました。