@effected/markdown 0.6.2 → 0.6.3

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.
package/Markdown.js CHANGED
@@ -192,6 +192,54 @@ var Markdown = class Markdown {
192
192
  * contract — but is not a byte-level round-trip of any original source;
193
193
  * surgical editing goes through the offset-splice edit layer instead.
194
194
  *
195
+ * **The canonical form is a stability commitment, so a test may assert
196
+ * against these bytes.** There are no options to configure and therefore
197
+ * nothing to drift, the choices below are pinned by byte-level tests, and
198
+ * the engine is cross-checked against commonmark.js over the full
199
+ * CommonMark 0.31.2 corpus. Changing any of them is a **breaking** change
200
+ * to this package, never a patch. A consumer asserting on rendered
201
+ * markdown should serialize through here rather than through a third-party
202
+ * stringifier whose defaults are free to move.
203
+ *
204
+ * The canonical choices a byte-level assertion depends on, for a node
205
+ * carrying no fidelity field:
206
+ *
207
+ * | Construct | Canonical form |
208
+ * | --- | --- |
209
+ * | Heading | ATX (`## x`), at every depth |
210
+ * | Thematic break | `***` |
211
+ * | Bullet list marker | `-` |
212
+ * | Ordered list delimiter | `.`, flipping to `)` to separate an immediately adjacent sibling list |
213
+ * | Emphasis / strong | `*` / `**` |
214
+ * | Code block | fenced when the node carries a `lang` or a `fenceChar`, with the fence grown past any interior backtick run; otherwise indented — **except where indenting would not re-parse as a code block**, which forces a fence (see below) |
215
+ * | Block separation | exactly one blank line |
216
+ * | Document | a single trailing newline |
217
+ *
218
+ * A node carrying a fidelity field overrides the corresponding row —
219
+ * `headingStyle: "setext"`, `markerChar`, `fenceChar`, `delimiter` — which
220
+ * is how a parsed document re-serializes in its author's spelling. The
221
+ * rows describe a synthesized node, which is the case a test asserting on
222
+ * generated markdown actually has.
223
+ *
224
+ * **Representability wins over the table.** The canonical form never emits
225
+ * text that would re-parse as something else, so a row yields where the two
226
+ * conflict. The case that reaches a consumer is the indented code block: an
227
+ * indented block directly after a list is absorbed as list content, so a
228
+ * `Code` node with neither `lang` nor `fenceChar` emits **fenced** in that
229
+ * position and indented everywhere else. A byte-level assertion over
230
+ * synthesized code blocks therefore depends on the preceding sibling.
231
+ *
232
+ * **The posture that makes this a non-issue**, and the one a consumer
233
+ * building trees for byte-level assertion should adopt: set `fenceChar` on
234
+ * every `Code` node that carries neither a `lang` nor one already, in a
235
+ * post-decode walk that reaches nested nodes. The choice then leaves the
236
+ * emitter entirely and no output depends on a node's neighbours.
237
+ *
238
+ * To *normalize* a document to different choices — a `-` list rewritten to
239
+ * `*`, setext headings rewritten to ATX — use `MarkdownFormat` with
240
+ * `MarkdownFormattingOptions`. That is the configurable surface; this one
241
+ * deliberately is not.
242
+ *
195
243
  * Failure is rare by design, symmetric with parse: only a hardening-guard
196
244
  * trip on a tree nesting past the depth cap fails, and only synthesized
197
245
  * or decoded trees can nest that far.
@@ -220,6 +268,18 @@ var Markdown = class Markdown {
220
268
  * {@link Markdown.stringifyResult} — synchronous callers can use that
221
269
  * variant directly.
222
270
  *
271
+ * @remarks
272
+ * The canonical form is a **stability commitment** and safe to assert
273
+ * against byte-for-byte; the choices it makes, and the reason changing one
274
+ * is a breaking change, are documented on
275
+ * {@link Markdown.stringifyResult}.
276
+ *
277
+ * **Fidelity fields must be set on the DECODED tree.** `Mdast.fromMdast`
278
+ * admits spec mdast and strips everything outside it, so a `fenceChar`,
279
+ * `headingStyle`, `markerChar` or `delimiter` placed on a plain mdast tree
280
+ * before admission is silently dropped and the canonical default applies.
281
+ * Set them on the nodes that come back.
282
+ *
223
283
  * @param root - The document tree to serialize.
224
284
  * @returns An `Effect` that succeeds with markdown source, or fails with
225
285
  * {@link MarkdownStringifyError}.
package/Mdast.js CHANGED
@@ -361,6 +361,14 @@ var Mdast = class Mdast {
361
361
  * decode into the {@link Frontmatter} capture. Unknown node types fail
362
362
  * typed.
363
363
  *
364
+ * **This package's fidelity fields are among the fields dropped**, because
365
+ * they are not spec mdast. A `fenceChar`, `headingStyle`, `markerChar` or
366
+ * `delimiter` set on the tree BEFORE admission is silently discarded, and
367
+ * the node then serializes with the canonical default — set them on the
368
+ * decoded nodes this returns instead. The drop is correct (the boundary
369
+ * admits spec mdast and nothing else) but it is silent, which is why it is
370
+ * called out here.
371
+ *
364
372
  * @param input - A plain mdast tree, typically a `root`.
365
373
  * @returns A `Result` succeeding with the decoded {@link Root}, or
366
374
  * failing with {@link MdastDecodeError} carrying the structured issue.
package/README.md CHANGED
@@ -261,6 +261,33 @@ if (Result.isSuccess(parsed)) {
261
261
 
262
262
  `Mdast.fromMdast` goes the other way as a checked admission boundary: it validates a foreign tree and synthesizes zero-width sentinel positions where one is absent or incomplete. Trees admitted that way serve tree-level workflows and canonical `stringify`; offset-splice editing needs the real positions only a parse produces.
263
263
 
264
+ ## The canonical form is stable
265
+
266
+ `Markdown.stringify` takes no options. It emits one canonical form, that form is pinned by byte-level tests, the engine behind it is cross-checked against commonmark.js over the full CommonMark 0.31.2 corpus, and **changing any of it is a breaking change to this package rather than a patch**. So a test may assert on these bytes, and a pipeline that needs stable rendered markdown should serialize through here instead of a third-party stringifier whose defaults are free to move between releases.
267
+
268
+ For a node carrying no fidelity field:
269
+
270
+ | Construct | Canonical form |
271
+ | --- | --- |
272
+ | Heading | ATX (`## x`), at every depth |
273
+ | Thematic break | `***` |
274
+ | Bullet list marker | `-` |
275
+ | Ordered list delimiter | `.`, flipping to `)` to separate an immediately adjacent sibling list |
276
+ | Emphasis / strong | `*` / `**` |
277
+ | Code block | fenced when the node carries a `lang` or a `fenceChar`, with the fence grown past any interior backtick run; otherwise indented — except where indenting would not re-parse as a code block, which forces a fence |
278
+ | Block separation | exactly one blank line |
279
+ | Document | a single trailing newline |
280
+
281
+ **Representability wins over the table.** The canonical form never emits text that would re-parse as something else, so a row yields where the two conflict. The case that reaches a consumer is the indented code block: an indented block directly after a list is absorbed as list content, so a `Code` node with neither `lang` nor `fenceChar` emits fenced in that position and indented everywhere else. A byte-level assertion over synthesized code blocks therefore depends on the preceding sibling.
282
+
283
+ The posture that makes this a non-issue — and the one to adopt if you build trees and assert on their bytes — is to set `fenceChar` on every `Code` node carrying neither a `lang` nor one already, in a post-decode walk that reaches nested nodes. The choice then leaves the emitter entirely and no output depends on a node's neighbours.
284
+
285
+ Fidelity fields must be set on the **decoded** tree: `Mdast.fromMdast` admits spec mdast and strips everything outside it, so a `fenceChar` placed on a plain mdast tree before admission is silently dropped.
286
+
287
+ A node that carries a fidelity field overrides the matching row — `headingStyle`, `markerChar`, `fenceChar`, `delimiter` — which is how a parsed document re-serializes in its author's spelling. The table describes a synthesized node, which is what a test asserting on generated markdown actually holds.
288
+
289
+ To *normalize* an existing document to different choices, use `MarkdownFormat` with `MarkdownFormattingOptions`. That is the configurable surface; this one deliberately is not.
290
+
264
291
  ## Features
265
292
 
266
293
  - `Markdown` — `parse`/`stringify` as `Effect`s with typed `MarkdownParseError`/`MarkdownStringifyError` channels, the pure `parseResult`/`stringifyResult` twins for synchronous callers, and the `MarkdownFromString` two-way codec.
package/index.d.ts CHANGED
@@ -946,6 +946,54 @@ declare class Markdown {
946
946
  * contract — but is not a byte-level round-trip of any original source;
947
947
  * surgical editing goes through the offset-splice edit layer instead.
948
948
  *
949
+ * **The canonical form is a stability commitment, so a test may assert
950
+ * against these bytes.** There are no options to configure and therefore
951
+ * nothing to drift, the choices below are pinned by byte-level tests, and
952
+ * the engine is cross-checked against commonmark.js over the full
953
+ * CommonMark 0.31.2 corpus. Changing any of them is a **breaking** change
954
+ * to this package, never a patch. A consumer asserting on rendered
955
+ * markdown should serialize through here rather than through a third-party
956
+ * stringifier whose defaults are free to move.
957
+ *
958
+ * The canonical choices a byte-level assertion depends on, for a node
959
+ * carrying no fidelity field:
960
+ *
961
+ * | Construct | Canonical form |
962
+ * | --- | --- |
963
+ * | Heading | ATX (`## x`), at every depth |
964
+ * | Thematic break | `***` |
965
+ * | Bullet list marker | `-` |
966
+ * | Ordered list delimiter | `.`, flipping to `)` to separate an immediately adjacent sibling list |
967
+ * | Emphasis / strong | `*` / `**` |
968
+ * | Code block | fenced when the node carries a `lang` or a `fenceChar`, with the fence grown past any interior backtick run; otherwise indented — **except where indenting would not re-parse as a code block**, which forces a fence (see below) |
969
+ * | Block separation | exactly one blank line |
970
+ * | Document | a single trailing newline |
971
+ *
972
+ * A node carrying a fidelity field overrides the corresponding row —
973
+ * `headingStyle: "setext"`, `markerChar`, `fenceChar`, `delimiter` — which
974
+ * is how a parsed document re-serializes in its author's spelling. The
975
+ * rows describe a synthesized node, which is the case a test asserting on
976
+ * generated markdown actually has.
977
+ *
978
+ * **Representability wins over the table.** The canonical form never emits
979
+ * text that would re-parse as something else, so a row yields where the two
980
+ * conflict. The case that reaches a consumer is the indented code block: an
981
+ * indented block directly after a list is absorbed as list content, so a
982
+ * `Code` node with neither `lang` nor `fenceChar` emits **fenced** in that
983
+ * position and indented everywhere else. A byte-level assertion over
984
+ * synthesized code blocks therefore depends on the preceding sibling.
985
+ *
986
+ * **The posture that makes this a non-issue**, and the one a consumer
987
+ * building trees for byte-level assertion should adopt: set `fenceChar` on
988
+ * every `Code` node that carries neither a `lang` nor one already, in a
989
+ * post-decode walk that reaches nested nodes. The choice then leaves the
990
+ * emitter entirely and no output depends on a node's neighbours.
991
+ *
992
+ * To *normalize* a document to different choices — a `-` list rewritten to
993
+ * `*`, setext headings rewritten to ATX — use `MarkdownFormat` with
994
+ * `MarkdownFormattingOptions`. That is the configurable surface; this one
995
+ * deliberately is not.
996
+ *
949
997
  * Failure is rare by design, symmetric with parse: only a hardening-guard
950
998
  * trip on a tree nesting past the depth cap fails, and only synthesized
951
999
  * or decoded trees can nest that far.
@@ -960,6 +1008,18 @@ declare class Markdown {
960
1008
  * {@link Markdown.stringifyResult} — synchronous callers can use that
961
1009
  * variant directly.
962
1010
  *
1011
+ * @remarks
1012
+ * The canonical form is a **stability commitment** and safe to assert
1013
+ * against byte-for-byte; the choices it makes, and the reason changing one
1014
+ * is a breaking change, are documented on
1015
+ * {@link Markdown.stringifyResult}.
1016
+ *
1017
+ * **Fidelity fields must be set on the DECODED tree.** `Mdast.fromMdast`
1018
+ * admits spec mdast and strips everything outside it, so a `fenceChar`,
1019
+ * `headingStyle`, `markerChar` or `delimiter` placed on a plain mdast tree
1020
+ * before admission is silently dropped and the canonical default applies.
1021
+ * Set them on the nodes that come back.
1022
+ *
963
1023
  * @param root - The document tree to serialize.
964
1024
  * @returns An `Effect` that succeeds with markdown source, or fails with
965
1025
  * {@link MarkdownStringifyError}.
@@ -2344,6 +2404,14 @@ declare class Mdast {
2344
2404
  * decode into the {@link Frontmatter} capture. Unknown node types fail
2345
2405
  * typed.
2346
2406
  *
2407
+ * **This package's fidelity fields are among the fields dropped**, because
2408
+ * they are not spec mdast. A `fenceChar`, `headingStyle`, `markerChar` or
2409
+ * `delimiter` set on the tree BEFORE admission is silently discarded, and
2410
+ * the node then serializes with the canonical default — set them on the
2411
+ * decoded nodes this returns instead. The drop is correct (the boundary
2412
+ * admits spec mdast and nothing else) but it is silent, which is why it is
2413
+ * called out here.
2414
+ *
2347
2415
  * @param input - A plain mdast tree, typically a `root`.
2348
2416
  * @returns A `Result` succeeding with the decoded {@link Root}, or
2349
2417
  * failing with {@link MdastDecodeError} carrying the structured issue.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/markdown",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "private": false,
5
5
  "description": "CommonMark and GFM markdown parse, edit and transform schemas for Effect",
6
6
  "keywords": [