yaml-quote-requirements

このページは FormatArc のブログ記事が引用している実測の生データです。検索結果には表示されません (noindex)。

Files

FileSize
README.md1.7 KB
measure.mjs4.3 KB
package-lock.json673 B
package.json124 B
results.json12.3 KB

README.md

# yaml-quote-requirements

YAML のスカラー値で、どの文字がクォートなしだと壊れるかを実測する。値の**先頭**に置いた場合と
**途中**に置いた場合を分け、単クォートで足りるか二重クォートが要るかまで測る。

パーサーは `yaml` (eemeli)。`lib/tooling.ts` の yaml-to-json が使っている実装そのもので、
呼び出しも同じ `YAML.parse(input)` (オプションなし) に揃えてある。**js-yaml はこのプロジェクトの
依存に入っていない**ので、js-yaml を「FormatArc の変換ツールのパーサー」と書いてはならない。

パーサー別のエラー文字列そのものを比べたい場合は `../yaml-syntax-errors/` を見る。こちらは
「壊れるかどうか」と「クォートの要否」だけを測る別の測定である。

## 実行

```bash
cd scripts/benchmarks/yaml-quote-requirements
npm install
node measure.mjs      # 表を標準出力に出し、results.json を書く
```

## 出力

- `rows` — 21 文字 x 5 条件 (素の先頭 / 素の途中 / 単クォート先頭 / 単クォート途中 / 二重クォート先頭)
  - `ok-string` はその文字を含む文字列として正しく読めた
  - `error` はパースエラー
  - `wrong-value` はエラーにならずに別の値になった (`#` がコメント、`&` がアンカー、`!` がタグ)
- `followUps` — 先頭の `-` `?` `:` が「単独」と「直後にスペース」で挙動が分かれる境界、および
  クォート文字自身のエスケープ 14 ケース

記事側の参照箇所は `content/blog/{ja,en,es,pt}/yaml-syntax-guide.md` の「クォートが必要なとき」節。

results.json

{
  "measuredAt": "2026-08-15T01:23:19.017Z",
  "environment": {
    "node": "v26.3.1",
    "parser": "yaml (eemeli) 2.8.3 — YAML.parse with defaults",
    "note": "Same parser and options as lib/tooling.ts yaml-to-json (import YAML from \"yaml\"; YAML.parse(input))."
  },
  "rows": [
    {
      "char": "-",
      "name": "hyphen",
      "startPlain": {
        "outcome": "ok-string"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": ":",
      "name": "colon",
      "startPlain": {
        "outcome": "ok-string"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": ": ",
      "name": "colon+space",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Nested mappings are not allowed in compact mappings at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Nested mappings are not allowed in compact mappings at line 1, column 6:"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "#",
      "name": "hash",
      "startPlain": {
        "outcome": "wrong-value",
        "detail": "null"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": " #",
      "name": "space+hash",
      "startPlain": {
        "outcome": "wrong-value",
        "detail": "null"
      },
      "midPlain": {
        "outcome": "wrong-value",
        "detail": "\"val\""
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "[",
      "name": "open bracket",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Flow sequence in block collection must be sufficiently indented and end with a ] at line 1, column 12:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "]",
      "name": "close bracket",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Unexpected flow-seq-end token in YAML stream: \"]\" at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "{",
      "name": "open brace",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Flow map in block collection must be sufficiently indented and end with a } at line 1, column 12:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "}",
      "name": "close brace",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Unexpected flow-map-end token in YAML stream: \"}\" at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": ",",
      "name": "comma",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Plain value cannot start with flow indicator character , at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "&",
      "name": "ampersand",
      "startPlain": {
        "outcome": "wrong-value",
        "detail": "null"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "*",
      "name": "asterisk",
      "startPlain": {
        "outcome": "error",
        "detail": "ReferenceError: Unresolved alias (the anchor must be set before the alias): value"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "!",
      "name": "exclamation",
      "startPlain": {
        "outcome": "wrong-value",
        "detail": "\"\""
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "|",
      "name": "pipe",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Block scalar header includes extra characters: |value at line 1, column 7:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": ">",
      "name": "greater than",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Block scalar header includes extra characters: >value at line 1, column 7:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "%",
      "name": "percent",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Plain value cannot start with directive indicator character % at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "@",
      "name": "at",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Plain value cannot start with reserved character @ at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "`",
      "name": "backtick",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Plain value cannot start with reserved character ` at line 1, column 6:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "?",
      "name": "question",
      "startPlain": {
        "outcome": "ok-string"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    },
    {
      "char": "\"",
      "name": "double quote",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Missing closing \"quote at line 1, column 12:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "ok-string"
      },
      "midSingleQuoted": {
        "outcome": "ok-string"
      },
      "startDoubleQuoted": {
        "outcome": "error",
        "detail": "YAMLParseError: Unexpected scalar at node end at line 1, column 8:"
      }
    },
    {
      "char": "'",
      "name": "single quote",
      "startPlain": {
        "outcome": "error",
        "detail": "YAMLParseError: Missing closing 'quote at line 1, column 12:"
      },
      "midPlain": {
        "outcome": "ok-string"
      },
      "startSingleQuoted": {
        "outcome": "error",
        "detail": "YAMLParseError: Unexpected scalar at node end at line 1, column 8:"
      },
      "midSingleQuoted": {
        "outcome": "error",
        "detail": "YAMLParseError: Unexpected scalar at node end at line 1, column 11:"
      },
      "startDoubleQuoted": {
        "outcome": "ok-string"
      }
    }
  ],
  "followUps": [
    {
      "label": "hyphen+space at start",
      "doc": "key: - value",
      "want": "- value",
      "result": "error: YAMLParseError Unexpected block-seq-ind on same line with key at line 1, column 6:"
    },
    {
      "label": "hyphen no space at start",
      "doc": "key: -value",
      "want": "-value",
      "result": "ok-string"
    },
    {
      "label": "question+space at start",
      "doc": "key: ? value",
      "want": "? value",
      "result": "error: YAMLParseError Nested mappings are not allowed in compact mappings at line 1, column 6:"
    },
    {
      "label": "question no space at start",
      "doc": "key: ?value",
      "want": "?value",
      "result": "ok-string"
    },
    {
      "label": "colon+space mid",
      "doc": "key: a: b",
      "want": "a: b",
      "result": "error: YAMLParseError Nested mappings are not allowed in compact mappings at line 1, column 6:"
    },
    {
      "label": "colon no space mid",
      "doc": "key: a:b",
      "want": "a:b",
      "result": "ok-string"
    },
    {
      "label": "hash after space mid",
      "doc": "key: a #b",
      "want": "a #b",
      "result": "wrong-value \"a\""
    },
    {
      "label": "hash no space mid",
      "doc": "key: a#b",
      "want": "a#b",
      "result": "ok-string"
    },
    {
      "label": "single quote doubled",
      "doc": "key: 'it''s'",
      "want": "it's",
      "result": "ok-string"
    },
    {
      "label": "single quote in double quotes",
      "doc": "key: \"it's\"",
      "want": "it's",
      "result": "ok-string"
    },
    {
      "label": "double quote in single quotes",
      "doc": "key: 'say \"hi\"'",
      "want": "say \"hi\"",
      "result": "ok-string"
    },
    {
      "label": "double quote backslash-escaped",
      "doc": "key: \"say \\\"hi\\\"\"",
      "want": "say \"hi\"",
      "result": "ok-string"
    },
    {
      "label": "backslash-n in double quotes",
      "doc": "key: \"a\\nb\"",
      "want": "a\nb",
      "result": "ok-string"
    },
    {
      "label": "backslash-n in single quotes",
      "doc": "key: 'a\\nb'",
      "want": "a\\nb",
      "result": "ok-string"
    }
  ]
}