vivliostyle / vfm

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

Should not output "null" for empty value of frontmatter properties #111

Closed MurakamiShinyu closed 3 years ago

MurakamiShinyu commented 3 years ago

Issue Details

Frontmatter にキーだけ書いて値が空の場合、HTMLでその値が出力されるところに "null" という文字列が出力される。 文字列 "null" は、HTMLにおいて特別な意味がないただの文字列であり、例えば <title>null</title> では "null" というタイトルということになってしまうので適切ではない。

例:

---
lang:
title:
author:
link:
  - rel:
    href:
---

<!doctype html>
<html lang="null">
  <head>
    <meta charset="utf-8">
    <title>null</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="null">
    <link rel="null" href="null">
  </head>
  <body></body>
</html>

Expected Behavior

文字列 "null" ではなく、空文字列になるべきだろう。上記の例なら次の出力になってほしい:

<!doctype html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="">
    <link rel="" href="">
  </head>
  <body></body>
</html>
akabekobeko commented 3 years ago

js-yaml の解析は Key だけある場合に null となるようです。これを判定することは可能です。ただしこの状態を空文字として出力すべきでしょうか?

例えば現在 idlang などのルートにある値を空文字にすると評価部分が if (value) のようになっているため、空文字も偽となって書き込みをスキップします。

空文字として書き込む仕様にするなら全ての値について振る舞いを決める必要があります。null が書き込まれること自体はバグですが、単に空文字として扱うだけでは修正にならないと考えています。

akabekobeko commented 3 years ago

空文字を許容する値については、それを仕様として明示する必要があります。それを持って判定部も単に if (value) とするのではなく空文字も許容するように修正することとなるでしょう。

src/plugins/document.ts の処理をお読みいただけると私の意図がわかりやすいと思います。

akabekobeko commented 3 years ago

手元で空文字変換して langid などオプショナルかつ直値になるもののテストを書いていてこの問題に気づきました。直値ではなく Array になるもの (link など) はその先で空文字をはじいていないため、結果として許容されることになります。

MurakamiShinyu commented 3 years ago

Markdownで原稿を作るプロジェクトによって、Markdownの雛形として、

---
lang:
title:
author:
hoge:
---

のように、値を空にしておいたものを使って、必要に応じてその値を埋める、というような使い方をすると思います。 その場合、値が空のままではエラーになるというのでは使いにくいので、空の値は空文字列 "" と同じ扱いでよいかと考えたのですが、むしろ該当する属性や要素を出力しないというのが、適切かもしれないですね。

akabekobeko commented 3 years ago

補足。js-yaml の変換結果を試したところ

でした。明示的に空文字を指定するための "" と暗黙的な空の値を区別する必要があるか?という話です。

akabekobeko commented 3 years ago

@MurakamiShinyu

むしろ該当する属性や要素を出力しないというのが、適切かもしれないですね。

はい。明示的な空文字を指定する方法がある以上、null の場合は読み込み時点で「評価しない = 未定義」とするほうがよさそうです。

ちなみに現時点だと「値なし = null」は

metadata[key] = `${data[key]}`;

のようにしているためエラーにならず、本 issue のように "null" となっています。これを未定義として扱うなら代入部分で判定してはじくように変更します。

akabekobeko commented 3 years ago

すみません↑に補足です。明示的に空文字を指定された場合、つまり key: "" をはじくか否かも決める必要があります。

となっています。これをそれぞれどのようにするか。

MurakamiShinyu commented 3 years ago

HTML仕様で Boolean attributes https://html.spec.whatwg.org/#boolean-attributes は、属性の名前だけ指定しても ="" を指定しても同じで true という意味になります。そのような属性を指定するのに key: "" が指定できることは必要です。これを key: だけの指定でも同じ意味にしても、自然な感じはします。

akabekobeko commented 3 years ago

それもありますね。key を指定している時点で値がなくても出力を期待しているともとれるので。

ここまでの議論を踏まえ、当初案の発展形で

  1. key:key: "" として扱う
  2. langid が null (これは 1 により書き込み側からは "" に見える) または空文字でも "" として出力する

とするのはどうでしょうか?

akabekobeko commented 3 years ago

ではそのようにします。ドキュメントにも記載予定です。

akabekobeko commented 3 years ago

112 にて対応、それを反映した 1.0.0-alpha.25 をリリースしたので本件は close します。