Open MurakamiShinyu opened 4 years ago
I'd like to change the issue title "Fenced divs" to "Fenced blocks" because I want to extend it for HTML semantic elements.
Examples:
:::::: section {.classA #idA role="doc-abstract" aria-label="Abstract"}
The **Abstract** section has a summary of the principal ideas,
concepts and conclusions of the work.
::::::
will be converted to:
<section id="idA" class="classA" role="doc-abstract" aria-label="Abstract">
<p>The <strong>Abstract</strong> section has a summary of the principal ideas,
concepts and conclusions of the work.</p>
</section>
and
:::::: aside {role="doc-tip"}
### Tip
Helpful information that clarifies some aspect of the content
or assists in its comprehension.
::::::
will be converted to:
<aside role="doc-tip">
<h3>Tip</h3>
<p>Helpful information that clarifies some aspect of the content
or assists in its comprehension.</p>
</aside>
Update: syntax changed ::: {section .classA #idA…}
to ::: section {.classA #idA…}
because the tag name inside the curly braces might make confusion with attribute name without value specified.
Testing with pandoc, I found that ::: aside
is converted to <div class="aside">
(not <aside>
), but ::: section
is converted to <section>
(not <div class="section">
). This behavior is different from what the pandoc document says: "a single unbraced word, which will be treated as a class name". I want to fix this inconsistency.
Proposal: the unbraced word is treated as element name if it is a valid HTML element name, otherwise treated as a class name (same as {.className}
).
One of my concerns is that attribute list which we should allow (Obviously ::: {script="alert('XSS')"}
have to be omitted), but this spec seems to be very useful!
I had the same concern @spring-raining had. And that's why only classes are allowed in the original spec of walled blocks.
Too many freedoms sometimes could be harmful.
I like the naming of Fenced blocks
from @MurakamiShinyu. It sounds natural.
Proposal: the unbraced word is treated as element name if it is a valid HTML element name, otherwise treated as a class name (same as {.className}).
I prefer unbraced word is always considered as an element name, and braced words are considered as attributes (classes, IDs and attributes). It is consistent behavior. magical behavior would be useful, indeed. But it sometimes confuses readers.
I agree that relying on "valid HTML element names" is not a good idea. It will change by HTML spec updates. And also we should consider about Custom elements.
So here is my take.
# Chapter 2
:::author
uetchy
:::
<h1>Chapter 2</h1>
<div class="author">
<p>uetchy</p>
</div>
.author {
padding: 5px;
border: 1px solid black;
border-radius: 4px;
}
role
supportSince we care about WCAG, role
property must have special treatment. so here it is. @
is used because of its resemblance to a roll. any thoughts?
:::@doc-tip
### Tip
:::
<aside role="doc-tip">
<h3>Tip</h3>
</aside>
[role="doc-tip"] {
background-color: yellow;
}
Maybe we need fine-grained control over these blocks, yet it's not so often. but it's always good to leave an option to users, isn't it?
:::alertbox {style="text-decoration: uppercase"}
Users beware!
:::
:::{#fig:signup}
1. Go to webiste
2. Click on `signup` button
:::
<div class="alertbox" style="text-decoration: uppercase">
<p>Users beware!</p>
</div>
<div id="signup" data-ref="fig">
<ul>
<li>Go to website</li>
<li>Click on <code>signup</code> button</li>
</ul>
</div>
latter uses cross-ref syntax.
What will be happen on VFM when omitting open/close notation?
Pattern A:
:::author
I forgot to close.
Pattern B:
I forgot to open.
:::
VFM just ignores them.
OK, so...
:::div1
alpha
:::::div2
beta
::::::::
Just FYI: The fenced code block in commonmark is closed by the end of the document if no closing code-fence found. https://spec.commonmark.org/0.29/#example-96
Fenced blocks は、Prior Art である Pandoc の fenced_divs と互換性があるとよい。
https://pandoc.org/MANUAL.html#extension-fenced_divs
{#identifier .class .class key=value key=value}
例:
::::: {#special .sidebar}
Here is a paragraph.
And another.
:::::
↓
<div id="special" class="sidebar">
<p>Here is a paragraph.</p>
<p>And another.</p>
</div>
次はネストの例。開始のフェンスには属性指定があることで終了のフェンスと区別される(3つ以上連続するコロンの数は関係ない):
::: Warning ::::::
This is a warning.
::: Danger
This is a warning within a warning.
:::
::::::::::::::::::
↓
<div class="Warning">
<p>This is a warning.</p>
<div class="Danger">
<p>This is a warning within a warning.</p>
</div>
</div>
内容が空の fenced div を試すと:
:::empty
:::
↓
<div class="empty"></div>
しかし、現状の vfm パーサーの実装では、Pandoc のドキュメントにある次の例が処理できない:
::::: {#special .sidebar}
Here is a paragraph.
And another.
:::::
↓
<p>::::: {#special .sidebar} Here is a paragraph.</p>
<p>And another. :::::</p>
Fenced blockへの {…}
での属性指定は未サポート。ではクラス名だけを書く記法ではどうか:
::::: sidebar
Here is a paragraph.
And another.
:::::
↓
<p>::::: sidebar Here is a paragraph.</p>
<p>And another. :::::</p>
どうも連続するコロンの数が3つよりも多いと fenced block として処理されないようである。コロンを3つに直したら:
::: sidebar
Here is a paragraph.
And another.
:::
↓
<div class="sidebar">
<p>Here is a paragraph.</p>
<p>And another.</p>
</div>
ネストの例ではどうか。
::: Warning ::::::
This is a warning.
::: Danger
This is a warning within a warning.
:::
::::::::::::::::::
↓
<p>::: Warning :::::: This is a warning.</p>
<div class="Danger"><p>This is a warning within a warning.</p></div>
<p>::::::::::::::::::</p>
これを次のように直したところ現状の vfm で処理できるようになった:
::: Warning
This is a warning.
:::: Danger
This is a warning within a warning.
::::
:::
↓
<div class="Warning">
<p>This is a warning.</p>
<div class="Danger">
<p>This is a warning within a warning.</p>
</div>
</div>
内容が空の Fenced block を試すと、Fenced block として処理されない:
:::empty
:::
↓
<p>:::empty :::</p>
現状の vfm のパーサーでは
{…}
での属性指定が未サポート:::
::: Fenced :::::::::::
のようにフェンスらしくできない)Pandoc では、fenced div 内が見出しではじまる場合、fenced div で div ではなく section 要素が生成される。
例:
::: appendix
## Appendix A {#aaa .bbb data-ccc=ddd}
This is an appendix.
:::
↓
<section id="aaa" class="bbb appendix" data-ccc="ddd">
<h2 class="bbb" data-ccc="ddd">Appendix A</h2>
<p>This is an appendix.</p>
</section>
pandocに --section-divs
オプションを指定した場合の結果は:
<section id="aaa" class="level2 bbb appendix" data-ccc="ddd">
<h2 class="bbb" data-ccc="ddd">Appendix A</h2>
<p>This is an appendix.</p>
</section>
--section-divs
オプションの有無にかかわらず、fenced div内が見出しではじまる場合は section 要素で囲まれ、見出しに指定された属性はsection要素にコピーされる。
class属性に levelN
(N は見出しのレベル) が追加されることだけ --section-divs
指定があると違う。
::: appendix
## Appendix A {#aaa .bbb data-ccc=ddd}
This is an appendix.
:::
↓
<div class="appendix">
<section id="aaa" class="bbb" data-ccc="ddd">
<h2>Appendix A</h2>
<p>This is an appendix.</p>
</section>
</div>
vfm では見出しで自動的に section 要素が作られるが、Fenced block の div 要素の中にその section 要素ができる。あまりスマートでない。
現在の VFM の独自拡張で次のような記法で DPUB-ARIA の role 属性を指定できる:
:::@appendix
# Appendix A
:::
↓
<section role="doc-appendix" id="appendix-a">
<h1>Appendix A</h1>
</section>
この独自拡張仕様の見直しについては spec: WAI-ARIA role syntax (#28) にコメントする。 その要点は以下:
@
をプレフィックスする記法(例: @appendix
)は廃止したい::: appendix
または {.appendix}
→ <section class="appendix" role="doc-appendix">
[role="doc-appendix"]
ではなく .appendix
を使うこと)
(このコメントは長過ぎだったので次のコメント https://github.com/vivliostyle/vfm/issues/5#issuecomment-777996312 に移動)
昨日の開発者会議を受けた #67 のとおり、本機能は v2 へ見送ります。
VFM v2 は remark-parse
v9 対応を想定しているので、その際は本機能を自前で実装せずに Pandoc 互換となる以下を採用するのがよさそう。
(前のコメント https://github.com/vivliostyle/vfm/issues/5#issuecomment-768119623 が長過ぎだったので分割した)
Pandoc の fenced_divs では、基本は div 要素が作られ、最初の要素が見出しであれば div の代わりに section 要素が作られる。
これをさらに拡張して、ほかの HTML 要素名も指定可能にしたい。
拡張案:
:::
のあとの名前が HTML 要素名として有効なもの(例: header, footer, main, nav, article, aside, section)の場合、その名前を HTML 要素名とクラス名の両方にする:::
のあとに HTML 要素名、そのあとに波括弧囲みの属性指定 {…}
という構文も可能にする例:
::: aside
Hello
:::
↓
<aside class="aside">
<p>Hello</p>
</aside>
属性の指定もある場合:
::: article {#aaa .bbb data-ccc="ddd"}
# The Article
:::
↓
<article id="aaa" class="article bbb" data-ccc="ddd">
<h1>The Article</h1>
</article>
波括弧囲みのクラス名指定だけの場合はそれを HTML 要素名にはしない:
::: {.aside}
Hello
:::
↓
<div class="aside">
<p>Hello</p>
</div>
::: {.aside}
# Hello
:::
↓
<section class="aside" id="hello">
<h1>Hello</h1>
</section>
Fenced block の :::
のあとの名前を HTML 要素名にすると不正な HTML になるような場合には、その名前を HTML 要素名とはしないでクラス名にする
::: span
# Hello
:::
↓
<section class="span" id="hello">
<h1>Hello</h1>
</section>
Fenced block の :::
のあとの名前が HTML 要素名で、その内容に段落(p)要素を持つことができないものである場合、Fenced block 内のテキストを段落要素にしないでインラインのテキストの扱いにする
::: small
This is a small notice.
:::
↓
<small class="small">This is a small notice.</small>
Fenced block の終了の :::
のあとに任意で /名前
を書けるようにすることで、ネストした fenced block の開始と終了のペアを分かりやすくできたらよいかもしれない。例:
::: aside
:::: Warning
This is a warning.
::::: Danger
This is a warning within a warning.
::::: /Danger
:::: /Warning
::: /aside
@akabekobeko
VFM v2 は
remark-parse
v9 対応を想定しているので、その際は本機能を自前で実装せずに Pandoc 互換となる以下を採用するのがよさそう。
remark-fenced-divs の readme に次の記述:
If you don't need Pandoc compatibility you should consider using remark-directive.
remark-fenced-divs あるいは remark-directive を検討するとよさそうですね。
:::main{#readme}
で
<main id="readme">
になります。これは私の HTML 要素名を明示的に指定可能にする拡張案 と似ています。私の案では、
:::main{#readme}
は
<main class="main" id="readme">
となるのですが、要素名と同じものをclassにも出力するのは実績がある Pandoc となるべく互換にしようとしたためです。 しかし、remark-directive の拡張が多くの人が利用する標準になっていくのであれば、Pandoc互換にこだわる必要はありません。
この記法は #67 により v1.0 では見送りとなりました。v2.0 で検討する場合は↑の @MurakamiShinyu さんコメントにあるとおり parser 変更があるため Pandoc 互換の benabel/remark-fenced-divs を検討予定です。
v2.0 で検討する場合は↑の @MurakamiShinyu さんコメントにあるとおり parser 変更があるため Pandoc 互換の benabel/remark-fenced-divs を検討予定です。
Pandoc 互換ではない remarkjs/remark-directive も検討するとよいです。
はい。両方を候補にしましょう。ただし択一にしたいですね。
Pandoc の fenced_divs では、基本は div 要素が作られ、最初の要素が見出しであれば div の代わりに section 要素が作られる。 これをさらに拡張して、ほかの HTML 要素名も指定可能にしたい。
MarkdownはHTMLの軽量マークアップ言語であり、HTMLによるドキュメント生成において比較的頻繁に用いられるセマンティックタグやタグ構造を、ドキュメントの執筆者にとって見やすく、書きやすいように設計されたものです。
:::main ... :::
がその哲学に則っているかというとどうでしょう。多くのMarkdownユーザーにとって一般的でないし、他のMarkdown拡張と互換性がない上、<main>
~</main>
と書くのと記述量として大差がありません。
単純にPandoc互換を目的とするなら、Pandoc記法のサブセットにすべきかと。
Fenced blocksによって解決されると期待されている問題:
Pandoc 互換ではない remarkjs/remark-directive も検討するとよいです。
はい。両方を候補にしましょう。ただし択一にしたいですね。
Pandoc互換の https://github.com/benabel/remark-fenced-divs は、"ARCHIVED: This plugin has never been completely adapted for remark 13+." となっているので、今後 remark 13+ に移行予定のvfmには使えなさそう。
vfm v1→v2の仕様変更で、見出しのsection囲みでの属性の扱いについてPandoc互換をやめていることもあるし、Pandoc互換よりも remarkjs のエコシステムでポピュラーで使いやすいものを採用するのがよさそう。
Adopt fenced divs from Pandoc's Markdown, that allows special fenced syntax for
div
blocks. See the spec: Pandoc Extension: fenced_divsDiscussion
This "fenced divs" syntax is very similar to the walled block in the current VFM draft. I prefer "fenced divs" because:
:::
is better than===
, because===
is used for setext heading underline and will make confusion.