polytypo 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 406f25967b3adc0d3dca2c77838e8e59d861ede74e42959c01efcb732d08c419
4
- data.tar.gz: '03389980598eee3542f48d15f23b1501a83cfd88e79bcc56ad2044db034ba40b'
3
+ metadata.gz: ccb6d56b095a38220c09cb15089edea24d1805b97a2db708f2d9528f5496d563
4
+ data.tar.gz: e3302e7bc38ffaa8605de7b46bec1160dd0fab40013179eec5fe4423458c0c2f
5
5
  SHA512:
6
- metadata.gz: ab38ef48178c5d64b8261830d13d96b66b2941ebf229f6bcc8161ef66ee94f6bbbce4479d2ed98183530aea9f67a945383e7feaeb1d4b69923f4ead8dc4bea9b
7
- data.tar.gz: a3545f797663af489eba433bf8a6d30cd0e23af1bde436834c502f746ddafd31e5caee4eda322d01b175c3de3d1faf6f18fd54616dd9fe81c40032a6a2760a36
6
+ metadata.gz: fe0ecd00e6252bc23a36c198b8320a23eb031b85ab418ef40f482afb4ae888ee9bb0e4b858a0d4d97cda2ed5f263152478e028d0162e4dd8be3a1162c8e95244
7
+ data.tar.gz: e464ca53c2c8f4d7e15bcb3209520ca68e30b2237fd7994aad179dc50a6a691b6363780718d4c15f3c184e6eba4d7e6d67bde3594502d2b44ddc7757ee2f0f19
@@ -1 +1 @@
1
- 1.7.0
1
+ 1.8.0
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "cs",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "de-CH",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "de-DE",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "el",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "en-GB",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "en-US",
4
4
  "cases": [
5
5
  {
@@ -2712,6 +2712,384 @@
2712
2712
  "in": "(c)'. and (c)'s",
2713
2713
  "out": "©'. and ©’s",
2714
2714
  "note": "symbols.md §5's I₆ discharge, deletion half (spec 1.5.0): §3.2 step 6 deletes the U+0029 that case 2a reads. Both directions in one case. The first mark does not convert — its right neighbour is U+002E, not ALNUM — and after the replacement its left neighbour is the emitted sign, which is in no class, so it does not convert on a second pass either. The second mark converts here, one rule before symbols shortens the span, and is U+2019 by the time symbols runs, which its own S2 guard accepts. Through spec 1.4.0 the second mark stayed straight."
2715
+ },
2716
+ {
2717
+ "id": "en-us-yaml-plain-apostrophe",
2718
+ "rule": "apostrophe",
2719
+ "mode": "yaml",
2720
+ "keys": [
2721
+ "description"
2722
+ ],
2723
+ "in": "description: it's one of theirs\n",
2724
+ "out": "description: it’s one of theirs\n",
2725
+ "note": "modes.md §3.8.6 and §7.11: an apostrophe is ordinary content in a plain scalar — nothing about it is syntactic, so the scan claims the value and `apostrophe` curls it. The style matrix's first cell: the single-quoted bail is about how the source spells the character, not about the character."
2726
+ },
2727
+ {
2728
+ "id": "en-us-yaml-double-quoted-apostrophe",
2729
+ "rule": "apostrophe",
2730
+ "mode": "yaml",
2731
+ "keys": [
2732
+ "description"
2733
+ ],
2734
+ "in": "description: \"it's one of theirs\"\n",
2735
+ "out": "description: \"it’s one of theirs\"\n",
2736
+ "note": "modes.md §3.8.6: inside a double-quoted scalar an apostrophe needs no escape, so the content and the source are the same characters and the scan claims it. Compare en-us-yaml-single-quoted-escape-untouched, the same sentence in the one style that has to double the mark."
2737
+ },
2738
+ {
2739
+ "id": "en-us-yaml-block-scalar-apostrophe",
2740
+ "rule": "apostrophe",
2741
+ "mode": "yaml",
2742
+ "keys": [
2743
+ "description"
2744
+ ],
2745
+ "in": "description: |-\n it's one of theirs\n",
2746
+ "out": "description: |-\n it’s one of theirs\n",
2747
+ "note": "modes.md §3.8.5: a block scalar has no quoting and therefore no escaping, so an apostrophe in it is content like any other. Together with the plain and double-quoted cases this pins that only one of the four styles declines, which is what makes §7.13's measured cost a property of that style rather than of the mark."
2748
+ },
2749
+ {
2750
+ "id": "en-us-markdown-commonmark-frontmatter-keys-plain-apostrophe",
2751
+ "rule": "apostrophe",
2752
+ "mode": "markdown",
2753
+ "dialect": "commonmark",
2754
+ "frontmatterKeys": [
2755
+ "title"
2756
+ ],
2757
+ "in": "---\ntitle: it's one of theirs\n---\n\nBody it's here.\n",
2758
+ "out": "---\ntitle: it’s one of theirs\n---\n\nBody it’s here.\n",
2759
+ "note": "modes.md §3.7.4 inherits §3.8.6 whole, so the style matrix holds inside a frontmatter block too: a plain scalar's apostrophe converts, while the single-quoted form does not (en-us-markdown-commonmark-frontmatter-keys-single-quote-bail)."
2760
+ },
2761
+ {
2762
+ "id": "en-us-markdown-commonmark-frontmatter-opener-trailing-space",
2763
+ "rule": "quotes",
2764
+ "mode": "markdown",
2765
+ "dialect": "commonmark",
2766
+ "in": "--- \ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2767
+ "out": "--- \ntitle: \"Une note\"\n---\n\nBody has “quotes” here.\n",
2768
+ "note": "modes.md §3.7.3a step 2: the rest of the opening delimiter line may be U+0020 and U+0009 and nothing else, so a fence with trailing whitespace still opens a block. Measured before it was specified: two runtimes typeset the metadata here and two skipped it, and the wider reading wins because a miss is invisible where typeset metadata is damage."
2769
+ },
2770
+ {
2771
+ "id": "en-us-markdown-commonmark-frontmatter-closer-trailing-space",
2772
+ "rule": "quotes",
2773
+ "mode": "markdown",
2774
+ "dialect": "commonmark",
2775
+ "in": "---\ntitle: \"Une note\"\n--- \n\nBody has \"quotes\" here.\n",
2776
+ "out": "---\ntitle: \"Une note\"\n--- \n\nBody has “quotes” here.\n",
2777
+ "note": "modes.md §3.7.3a step 3: the same rule for the closing delimiter line. Whitespace an editor left behind does not turn a metadata block into prose."
2778
+ },
2779
+ {
2780
+ "id": "en-us-markdown-commonmark-frontmatter-opener-trailing-tab",
2781
+ "rule": "quotes",
2782
+ "mode": "markdown",
2783
+ "dialect": "commonmark",
2784
+ "in": "---\t\ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2785
+ "out": "---\t\ntitle: \"Une note\"\n---\n\nBody has “quotes” here.\n",
2786
+ "note": "modes.md §3.7.3a step 2 names U+0009 as well as U+0020, because a tab is what a fence picks up from an editor that indents with tabs, and leaving it out would have made the rule depend on which whitespace character the author cannot see."
2787
+ },
2788
+ {
2789
+ "id": "en-us-markdown-commonmark-frontmatter-dots-closer",
2790
+ "rule": "quotes",
2791
+ "mode": "markdown",
2792
+ "dialect": "commonmark",
2793
+ "in": "---\ntitle: \"Une note\"\n...\n\nBody has \"quotes\" here.\n",
2794
+ "out": "---\ntitle: “Une note”\n…\n\nBody has “quotes” here.\n",
2795
+ "note": "modes.md §3.7.3a step 3: `...` closes a YAML document but does not close a frontmatter block, so there is no block and the metadata line is prose. All four runtimes already agree; the fixture is what keeps them agreeing."
2796
+ },
2797
+ {
2798
+ "id": "en-us-markdown-commonmark-frontmatter-after-blank-line",
2799
+ "rule": "quotes",
2800
+ "mode": "markdown",
2801
+ "dialect": "commonmark",
2802
+ "in": "\n---\ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2803
+ "out": "\n---\ntitle: “Une note”\n---\n\nBody has “quotes” here.\n",
2804
+ "note": "modes.md §3.7.3a step 1: the document must begin with the delimiter. One blank line before it and the construct is a thematic break, which is what all four runtimes already do."
2805
+ },
2806
+ {
2807
+ "id": "en-us-markdown-commonmark-frontmatter-opener-with-text",
2808
+ "rule": "quotes",
2809
+ "mode": "markdown",
2810
+ "dialect": "commonmark",
2811
+ "in": "--- yaml\ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2812
+ "out": "--- yaml\ntitle: “Une note”\n---\n\nBody has “quotes” here.\n",
2813
+ "note": "modes.md §3.7.3a step 2: anything on the opening line that is not U+0020 or U+0009 means there is no block. The wider reading widens the whitespace, not the syntax."
2814
+ },
2815
+ {
2816
+ "id": "en-us-markdown-commonmark-frontmatter-closer-indented",
2817
+ "rule": "quotes",
2818
+ "mode": "markdown",
2819
+ "dialect": "commonmark",
2820
+ "in": "---\ntitle: \"Une note\"\n ---\n\nBody has \"quotes\" here.\n",
2821
+ "out": "---\ntitle: “Une note”\n ---\n\nBody has “quotes” here.\n",
2822
+ "note": "modes.md §3.7.3a step 3: a closer is a line, not something searched for inside one, so one space of indentation disqualifies it and the document has no block. Without that clause the step reads as \"a line containing the delimiter\" and two implementations of it disagree."
2823
+ },
2824
+ {
2825
+ "id": "en-us-markdown-commonmark-frontmatter-opener-indented",
2826
+ "rule": "quotes",
2827
+ "mode": "markdown",
2828
+ "dialect": "commonmark",
2829
+ "in": " ---\ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2830
+ "out": " ---\ntitle: “Une note”\n---\n\nBody has “quotes” here.\n",
2831
+ "note": "modes.md §3.7.3a step 1: the document must begin with the delimiter, so one space before it is enough to make the construct a thematic break instead."
2832
+ },
2833
+ {
2834
+ "id": "en-us-markdown-commonmark-frontmatter-four-dashes",
2835
+ "rule": "quotes",
2836
+ "mode": "markdown",
2837
+ "dialect": "commonmark",
2838
+ "in": "----\ntitle: \"Une note\"\n----\n\nBody has \"quotes\" here.\n",
2839
+ "out": "----\ntitle: “Une note”\n----\n\nBody has “quotes” here.\n",
2840
+ "note": "modes.md §3.7.3a step 2: the rest of the delimiter line may be U+0020 and U+0009, and a fourth dash is neither. The widened rule widens the whitespace, not the delimiter."
2841
+ },
2842
+ {
2843
+ "id": "en-us-markdown-commonmark-frontmatter-mixed-delimiters",
2844
+ "rule": "quotes",
2845
+ "mode": "markdown",
2846
+ "dialect": "commonmark",
2847
+ "in": "---\ntitle: \"Une note\"\n+++\n\nBody has \"quotes\" here.\n",
2848
+ "out": "---\ntitle: “Une note”\n+++\n\nBody has “quotes” here.\n",
2849
+ "note": "modes.md §3.7.3a step 3: the closer is the same delimiter as the opener, so a `+++` line does not close a `---` block and the document has none."
2850
+ },
2851
+ {
2852
+ "id": "en-us-markdown-commonmark-frontmatter-empty-block",
2853
+ "rule": "quotes",
2854
+ "mode": "markdown",
2855
+ "dialect": "commonmark",
2856
+ "in": "---\n---\n\nBody has \"quotes\" here.\n",
2857
+ "out": "---\n---\n\nBody has “quotes” here.\n",
2858
+ "note": "modes.md §3.7.3a: an opener immediately followed by a closer is a block with no content — the second line is the first later line that is the delimiter — so there is nothing to skip and nothing for `frontmatterKeys` to name, and the body converts either way."
2859
+ },
2860
+ {
2861
+ "id": "en-us-markdown-commonmark-frontmatter-byte-order-mark",
2862
+ "rule": "quotes",
2863
+ "mode": "markdown",
2864
+ "dialect": "commonmark",
2865
+ "in": "---\ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2866
+ "out": "---\ntitle: \"Une note\"\n---\n\nBody has “quotes” here.\n",
2867
+ "note": "modes.md §3.7.3a step 1: a single leading U+FEFF is stepped over before the scan begins, so a file some editors write with a byte-order mark still has its metadata skipped. Measured on 1.7.0, two runtimes read the mark as content and typeset the block — the same split, on the same damaging side, as the trailing space."
2868
+ },
2869
+ {
2870
+ "id": "en-us-markdown-commonmark-frontmatter-byte-order-mark-trailing-space",
2871
+ "rule": "quotes",
2872
+ "mode": "markdown",
2873
+ "dialect": "commonmark",
2874
+ "in": "--- \ntitle: \"Une note\"\n---\n\nBody has \"quotes\" here.\n",
2875
+ "out": "--- \ntitle: \"Une note\"\n---\n\nBody has “quotes” here.\n",
2876
+ "note": "modes.md §3.7.3a steps 1 and 2 composed: the two clauses that were each a two-against-two divergence, in one document, which is the file a Windows editor produces without being asked."
2877
+ },
2878
+ {
2879
+ "id": "en-us-markdown-commonmark-frontmatter-masks-the-parser",
2880
+ "rule": "quotes",
2881
+ "mode": "markdown",
2882
+ "dialect": "commonmark",
2883
+ "in": "---\nx: |\n ```\n---\n\n```\ncode \"q\" here\n```\n\nBody \"q\" here.\n",
2884
+ "out": "---\nx: |\n ```\n---\n\n```\ncode \"q\" here\n```\n\nBody “q” here.\n",
2885
+ "note": "modes.md §3.7.3a: the parser is handed the block masked out, so a fence inside a metadata value cannot pair with the body's own fence. Without masking the two code blocks swap roles — the body's code is typeset and its prose is skipped — which no span-level check can see, because the damage is in what the parser concluded."
2886
+ },
2887
+ {
2888
+ "id": "en-us-markdown-commonmark-frontmatter-masks-the-parser-trailing-space",
2889
+ "rule": "quotes",
2890
+ "mode": "markdown",
2891
+ "dialect": "commonmark",
2892
+ "in": "--- \nx: |\n ```\n---\n\n```\ncode \"q\" here\n```\n\nBody \"q\" here.\n",
2893
+ "out": "--- \nx: |\n ```\n---\n\n```\ncode \"q\" here\n```\n\nBody “q” here.\n",
2894
+ "note": "modes.md §3.7.3a: the same document with a trailing space on the fence, which is where the widened locator and the masking rule compose — a runtime that gets either one wrong typesets the code block."
2895
+ },
2896
+ {
2897
+ "id": "en-us-markdown-commonmark-frontmatter-crlf-trailing-space",
2898
+ "rule": "quotes",
2899
+ "mode": "markdown",
2900
+ "dialect": "commonmark",
2901
+ "in": "--- \r\ntitle: \"Une note\"\r\n---\r\n\r\nBody has \"quotes\" here.\r\n",
2902
+ "out": "--- \r\ntitle: \"Une note\"\r\n---\r\n\r\nBody has “quotes” here.\r\n",
2903
+ "note": "modes.md §3.7.3a steps 2 and 5 composed: a runtime that splits lines on U+000A alone sees `--- \\r`, decides U+000D is not whitespace it admits, and loses the block. That is the most ordinary Windows file there is."
2904
+ },
2905
+ {
2906
+ "id": "en-us-markdown-commonmark-frontmatter-crlf-closer-trailing-space",
2907
+ "rule": "quotes",
2908
+ "mode": "markdown",
2909
+ "dialect": "commonmark",
2910
+ "in": "---\r\ntitle: \"Une note\"\r\n--- \r\n\r\nBody has \"quotes\" here.\r\n",
2911
+ "out": "---\r\ntitle: \"Une note\"\r\n--- \r\n\r\nBody has “quotes” here.\r\n",
2912
+ "note": "modes.md §3.7.3a steps 3 and 5: the same composition on the closing delimiter."
2913
+ },
2914
+ {
2915
+ "id": "en-us-markdown-commonmark-frontmatter-keys-trailing-space-opener",
2916
+ "rule": "quotes",
2917
+ "mode": "markdown",
2918
+ "dialect": "commonmark",
2919
+ "frontmatterKeys": [
2920
+ "title"
2921
+ ],
2922
+ "in": "--- \ntitle: He said \"hello\" once\nslug: \"he-said-hello\"\n---\n\nBody \"quotes\" here.\n",
2923
+ "out": "--- \ntitle: He said “hello” once\nslug: \"he-said-hello\"\n---\n\nBody “quotes” here.\n",
2924
+ "note": "modes.md §3.7.4 with §3.7.3a: every other locator case takes the skip path, where a wrong extent only costs prose. Here it costs an offset — a port computing the content start as \"four code points in\" is right for every bare fence and wrong for this one, and the spans it emits land on the wrong characters."
2925
+ },
2926
+ {
2927
+ "id": "en-us-markdown-commonmark-frontmatter-toml-trailing-space",
2928
+ "rule": "quotes",
2929
+ "mode": "markdown",
2930
+ "dialect": "commonmark",
2931
+ "in": "+++ \ntitle = \"Une note\"\n+++\n\nBody has \"quotes\" here.\n",
2932
+ "out": "+++ \ntitle = \"Une note\"\n+++\n\nBody has “quotes” here.\n",
2933
+ "note": "modes.md §3.7.3a: the widening is about whitespace, not about the delimiter, so it applies to a TOML block exactly as to a YAML one — the block is skipped whole either way, which is what §7.13 records."
2934
+ },
2935
+ {
2936
+ "id": "en-us-markdown-commonmark-frontmatter-closer-trailing-tab",
2937
+ "rule": "quotes",
2938
+ "mode": "markdown",
2939
+ "dialect": "commonmark",
2940
+ "in": "---\ntitle: \"Une note\"\n---\t\n\nBody has \"quotes\" here.\n",
2941
+ "out": "---\ntitle: \"Une note\"\n---\t\n\nBody has “quotes” here.\n",
2942
+ "note": "modes.md §3.7.3a step 3 names U+0009 as well as U+0020 for the closing line, and the opener case alone would not catch a port that admitted tabs in one place only."
2943
+ },
2944
+ {
2945
+ "id": "en-us-markdown-commonmark-frontmatter-only-an-opener",
2946
+ "rule": "quotes",
2947
+ "mode": "markdown",
2948
+ "dialect": "commonmark",
2949
+ "in": "--- \n",
2950
+ "out": "--- \n",
2951
+ "note": "modes.md §3.7.3a step 4 with nothing after the fence: there is no later line, so there is no block, and a one-line document comes back byte for byte. The degenerate case a scan written as \"find the next delimiter\" gets wrong by running off the end."
2952
+ },
2953
+ {
2954
+ "id": "en-us-markdown-mdx-frontmatter-trailing-space",
2955
+ "rule": "quotes",
2956
+ "mode": "markdown",
2957
+ "dialect": "mdx",
2958
+ "in": "--- \ntitle: \"Une note\"\n---\n\n<Callout>Body \"quotes\" here</Callout>\n",
2959
+ "out": "--- \ntitle: \"Une note\"\n---\n\n<Callout>Body “quotes” here</Callout>\n",
2960
+ "note": "modes.md §3.7.3a is dialect-independent: the locator is a scan over the source and knows nothing about JSX. Pinned in `mdx` because the claim spans both dialects and every other locator case is `commonmark`."
2961
+ },
2962
+ {
2963
+ "id": "en-us-markdown-commonmark-frontmatter-final-cr-no-newline",
2964
+ "rule": "quotes",
2965
+ "mode": "markdown",
2966
+ "dialect": "commonmark",
2967
+ "in": "---\r\ntitle: \"Une note\"\r\n---\r",
2968
+ "out": "---\r\ntitle: \"Une note\"\r\n---\r",
2969
+ "note": "modes.md §3.7.3a step 5: a file whose last line is the closing fence followed by U+000D and no U+000A still closes its block — end of input ends a line, and the U+000D belongs to the terminator. A literal reading of §3.8.4's LF-only model loses the block here and hands the metadata to the rules, which is why step 5 states the Markdown line model instead of borrowing the YAML one."
2970
+ },
2971
+ {
2972
+ "id": "en-us-markdown-commonmark-frontmatter-lone-cr-line-endings",
2973
+ "rule": "quotes",
2974
+ "mode": "markdown",
2975
+ "dialect": "commonmark",
2976
+ "in": "---\rtitle: \"Une note\"\r---\r\rBody has \"quotes\" here.\r",
2977
+ "out": "---\rtitle: \"Une note\"\r---\r\rBody has “quotes” here.\r",
2978
+ "note": "modes.md §3.7.3a step 5: lone U+000D line endings are line endings in CommonMark, so a document written with them has a frontmatter block like any other. The content inside it is still read with §3.8.4's LF-only model, because that half is YAML — the two line models are different on purpose and the note in step 5 says so."
2979
+ },
2980
+ {
2981
+ "id": "en-us-markdown-commonmark-frontmatter-masks-an-unclosed-construct",
2982
+ "rule": "quotes",
2983
+ "mode": "markdown",
2984
+ "dialect": "commonmark",
2985
+ "in": "---\nx: |\n ```\n---\n\nBody \"q\" here.\n",
2986
+ "out": "---\nx: |\n ```\n---\n\nBody “q” here.\n",
2987
+ "note": "modes.md §3.7.3a: the shorter mask witness, and the sharper one — a construct merely OPENED inside a metadata value, with nothing in the body to pair with. Unmasked, the lone fence swallows the rest of the document into a code block and the body converts nothing at all. Measured on 1.7.0, that is what one runtime does."
2988
+ },
2989
+ {
2990
+ "id": "en-us-markdown-commonmark-frontmatter-keys-lone-cr-is-inert",
2991
+ "rule": "quotes",
2992
+ "mode": "markdown",
2993
+ "dialect": "commonmark",
2994
+ "frontmatterKeys": [
2995
+ "title"
2996
+ ],
2997
+ "in": "---\rtitle: a \"b\"\rslug: \"x\"\r---\r\rBody \"c\" here.\r",
2998
+ "out": "---\rtitle: a \"b\"\rslug: \"x\"\r---\r\rBody “c” here.\r",
2999
+ "note": "modes.md §3.7.3a step 5 and §7.13: the block is found by CommonMark's line model, and the content is then read by §3.8.4's LF-only one, which sees a two-line block as a single line and yields no span. So the option is inert here — nothing machine-read is typeset, the block is still skipped, and the body converts. Pinned because it is a silence, and a silence nobody pinned is a silence nobody notices."
3000
+ },
3001
+ {
3002
+ "id": "en-us-markdown-commonmark-frontmatter-keys-lone-cr-one-key",
3003
+ "rule": "quotes",
3004
+ "mode": "markdown",
3005
+ "dialect": "commonmark",
3006
+ "frontmatterKeys": [
3007
+ "title"
3008
+ ],
3009
+ "in": "---\rtitle: a \"b\"\r---\r\rBody \"c\" here.\r",
3010
+ "out": "---\rtitle: a \"b\"\r---\r\rBody “c” here.\r",
3011
+ "note": "modes.md §3.7.4: a block whose content carries a U+000D not followed by U+000A yields no spans, however few lines it has. An earlier draft let a one-line block through and declined a two-line one, which made the rule depend on a line count rather than on the character; the two-line case is en-us-markdown-commonmark-frontmatter-keys-lone-cr-is-inert and this is the other side of it."
3012
+ },
3013
+ {
3014
+ "id": "en-us-markdown-commonmark-lone-cr-no-block",
3015
+ "rule": "ellipsis",
3016
+ "mode": "markdown",
3017
+ "dialect": "commonmark",
3018
+ "in": "Wait for it... he said \"hi\"\rand then \"left\".\r",
3019
+ "out": "Wait for it… he said “hi”\rand then “left”.\r",
3020
+ "note": "modes.md §3.7.3a step 5 makes a lone U+000D a line ending the locator understands, so a document written that way reaches the body walk like any other. Pinned because the failure mode is not an error but silent offset corruption: one runtime reported byte columns for such a document and another raised POLYTYPO_MALFORMED_INPUT, a code §3.7.2 reserves for mdx."
3021
+ },
3022
+ {
3023
+ "id": "en-us-markdown-commonmark-byte-order-mark-no-block",
3024
+ "rule": "ellipsis",
3025
+ "mode": "markdown",
3026
+ "dialect": "commonmark",
3027
+ "in": "Wait for it... he said \"hi\"\n",
3028
+ "out": "Wait for it… he said “hi”\n",
3029
+ "note": "modes.md §3.7.3a step 1 steps over a leading U+FEFF, and a document carrying a mark but no block must convert exactly as the same document without one. Measured across the four runtimes that implement the mode: three convert and one returns the document unchanged, so this pins the majority and names the fourth as the defect."
3030
+ },
3031
+ {
3032
+ "id": "en-us-markdown-commonmark-frontmatter-keys-astral-in-the-block",
3033
+ "rule": "apostrophe",
3034
+ "mode": "markdown",
3035
+ "dialect": "commonmark",
3036
+ "frontmatterKeys": [
3037
+ "title"
3038
+ ],
3039
+ "in": "---\ntitle: café 😀 it's ok\n---\n\nBody \"q\" here...\n",
3040
+ "out": "---\ntitle: café 😀 it’s ok\n---\n\nBody “q” here…\n",
3041
+ "note": "modes.md §3.7.3a's mask is one U+0020 per index unit, not per code point: a runtime that indexes bytes and masks an astral character to a single space shortens its input by three and shifts every body offset after it. The trailing ellipsis is what a shift eats first, so this case fails loudly rather than subtly."
3042
+ },
3043
+ {
3044
+ "id": "en-us-markdown-commonmark-frontmatter-keys-lone-cr-costs-one-line",
3045
+ "rule": "quotes",
3046
+ "mode": "markdown",
3047
+ "dialect": "commonmark",
3048
+ "frontmatterKeys": [
3049
+ "title",
3050
+ "slug"
3051
+ ],
3052
+ "in": "---\ntitle: \"a\rb\"\nslug: c \"d\"\n---\n\nBody \"q\" here.\n",
3053
+ "out": "---\ntitle: \"a\rb\"\nslug: c “d”\n---\n\nBody “q” here.\n",
3054
+ "note": "modes.md §3.7.4's U+000D bail is per line, not per block: `title`'s value carries a stray carriage return and is declined, `slug`'s line converts, and the body converts. The other side of the lone-U+000D document cases, which lose everything because such a document is one §3.8.4 line. Implementers: the per-line test has to run to the next line's start rather than to the line's end, or a block whose only line ends in U+000D looks clean — that is the one reading under which both this case and -keys-lone-cr-one-key pass."
3055
+ },
3056
+ {
3057
+ "id": "en-us-markdown-commonmark-frontmatter-keys-lone-cr-ends-the-content",
3058
+ "rule": "quotes",
3059
+ "mode": "markdown",
3060
+ "dialect": "commonmark",
3061
+ "frontmatterKeys": [
3062
+ "title",
3063
+ "slug"
3064
+ ],
3065
+ "in": "---\ntitle: a \"b\"\nslug: c \"d\"\n\r---\n\nBody \"q\" here.\n",
3066
+ "out": "---\ntitle: a “b”\nslug: c \"d\"\n\r---\n\nBody “q” here.\n",
3067
+ "note": "modes.md §3.7.4: the content's last line is a lone U+000D, and `title` converts while `slug` does not. What this case discriminates is an implementation that substitutes the U+000D for another declining character: that converts both keys. What it does NOT discriminate is the per-line filter itself — measured in three ports, `slug` is already silent before the filter runs, because the trailing line is blank and joins `slug`'s value run, which §3.8.6's continuation bail declines. The cases that exercise the filter are -keys-lone-cr-one-key and -keys-lone-cr-costs-one-line."
3068
+ },
3069
+ {
3070
+ "id": "en-us-markdown-commonmark-frontmatter-keys-lone-cr-in-a-value-run",
3071
+ "rule": "dashes",
3072
+ "mode": "markdown",
3073
+ "dialect": "commonmark",
3074
+ "frontmatterKeys": [
3075
+ "summary",
3076
+ "title"
3077
+ ],
3078
+ "in": "---\nsummary: a\rb\n title: c -- d\n---\n\nBody \"q\" here.\n",
3079
+ "out": "---\nsummary: a\rb\n title: c -- d\n---\n\nBody “q” here.\n",
3080
+ "note": "modes.md §3.7.4: the decline drops the spans the content scan produced for that line and does not alter the content the scan was given. Here the U+000D sits on a listed key whose value run continues onto a more-indented line, so the scan yields nothing for the block at all — `title` is inside `summary`'s value run, not a key of its own. Substituting the U+000D for U+0009 instead converts `c -- d` and is the divergence this case exists to fail."
3081
+ },
3082
+ {
3083
+ "id": "en-us-markdown-commonmark-frontmatter-byte-order-mark-and-lone-cr",
3084
+ "rule": "quotes",
3085
+ "mode": "markdown",
3086
+ "dialect": "commonmark",
3087
+ "frontmatterKeys": [
3088
+ "title"
3089
+ ],
3090
+ "in": "---\rtitle: a \"b\"\r---\r\rBody \"q\".\r",
3091
+ "out": "---\rtitle: a \"b\"\r---\r\rBody “q”.\r",
3092
+ "note": "modes.md §3.7.3a steps 1 and 5 composed: a byte-order mark in front of a document whose lines end with lone U+000D. Each clause is pinned alone and their combination is where one runtime lost the body entirely — found by an adversarial pass over a finished port, not by any fixture then in the suite. The block is located and skipped, its content is declined for the U+000D, and the body converts."
2715
3093
  }
2716
3094
  ]
2717
3095
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "es",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "fi",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "fr-CA",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "fr",
4
4
  "cases": [
5
5
  {
@@ -948,6 +948,61 @@
948
948
  "in": "Le «mot»'s résumé.",
949
949
  "out": "Le « mot »’s résumé.",
950
950
  "note": "The one configuration where a rule running AFTER apostrophe touches a CLOSEDELIM neighbour, so nbsp.md §5's I₆ discharge has a witness rather than only prose. N1/N2 put fr's inner no-break space on the glyph's INNER side, so the U+00BB that case 2a reads stays immediately left of the mark and the verdict is identical before and after the insertion. Synthetic rather than natural French — a possessive 's is not French — and deliberately so, in the standing quotes.md §6 gives its own adversarial de-CH witness: what is being pinned is the rule interaction, not an idiom."
951
+ },
952
+ {
953
+ "id": "fr-yaml-plain-elision",
954
+ "rule": "apostrophe",
955
+ "mode": "yaml",
956
+ "keys": [
957
+ "description"
958
+ ],
959
+ "in": "description: l'idee et l'autre\n",
960
+ "out": "description: l’idee et l’autre\n",
961
+ "note": "modes.md §3.8.6 in a locale where the apostrophe is elision rather than possession: the same cell as en-us-yaml-plain-apostrophe, and §8 item 4's requirement that a construct be pinned in more than one locale rather than the same English output with the locale field changed."
962
+ },
963
+ {
964
+ "id": "fr-yaml-single-quoted-escape-untouched",
965
+ "rule": "apostrophe",
966
+ "mode": "yaml",
967
+ "keys": [
968
+ "description"
969
+ ],
970
+ "in": "description: 'l''idee et l''autre'\n",
971
+ "out": "description: 'l''idee et l''autre'\n",
972
+ "note": "modes.md §3.8.6: two consecutive U+0027 in a single-quoted scalar yield no spans, in every locale — the source spells the content with more characters than it has, and that is a property of YAML, not of the language. This is the cell §7.13 measures at 1040 of 1858 values on a real corpus."
973
+ },
974
+ {
975
+ "id": "fr-yaml-single-quoted-no-escape",
976
+ "rule": "dashes",
977
+ "mode": "yaml",
978
+ "keys": [
979
+ "description"
980
+ ],
981
+ "in": "description: 'deux -- trois'\n",
982
+ "out": "description: 'deux — trois'\n",
983
+ "note": "modes.md §3.8.6: a single-quoted scalar with nothing doubled inside it is claimed like any other. The style itself never disables the mode — only the doubling does, which is what the neighbouring case pins."
984
+ },
985
+ {
986
+ "id": "fr-markdown-commonmark-frontmatter-opener-trailing-space",
987
+ "rule": "nbsp",
988
+ "mode": "markdown",
989
+ "dialect": "commonmark",
990
+ "in": "--- \ntitle: Une note : suite\n---\n\nEst-ce vrai ?\n",
991
+ "out": "--- \ntitle: Une note : suite\n---\n\nEst-ce vrai ?\n",
992
+ "note": "modes.md §3.7.3a in the locale that makes the cost visible: without the trailing-space clause this block is prose, and `fr` puts a narrow no-break space in front of the colon of a machine-read field — the exact damage §3.7.3 exists to prevent, reached by one invisible character at the end of a fence."
993
+ },
994
+ {
995
+ "id": "fr-markdown-commonmark-frontmatter-keys-lone-cr-costs-one-line",
996
+ "rule": "quotes",
997
+ "mode": "markdown",
998
+ "dialect": "commonmark",
999
+ "frontmatterKeys": [
1000
+ "title",
1001
+ "slug"
1002
+ ],
1003
+ "in": "---\ntitle: \"a\rb\"\nslug: c \"d\"\n---\n\nBody \"q\" here.\n",
1004
+ "out": "---\ntitle: \"a\rb\"\nslug: c « d »\n---\n\nBody « q » here.\n",
1005
+ "note": "modes.md §3.7.4 per-line U+000D bail in a locale whose quotation marks carry their own spacing, so the declined line and the converted one are visibly different constructions rather than the same English output relabelled (§8 item 4)."
951
1006
  }
952
1007
  ]
953
1008
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "it",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "cases": [
4
4
  {
5
5
  "id": "exact-en-us",
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "nl",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "pl",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "pt-BR",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "pt-PT",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "ru",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "sv",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "tr",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "locale": "uk",
4
4
  "cases": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  {
2
- "spec": "1.7.0",
2
+ "spec": "1.8.0",
3
3
  "$comment": "Locale resolution input. Algorithm is specified in spec/rules/locale-resolution.md and is identical in every runtime — never delegate it to a platform locale-negotiation library. \"spec\" here must track spec/VERSION exactly — it is not itself the global version source; scripts/validate-spec.mjs enforces the match.",
4
4
  "locales": [
5
5
  "en-US",