@effected/markdown 0.6.1 → 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 +60 -0
- package/Mdast.js +8 -0
- package/README.md +27 -0
- package/index.d.ts +68 -0
- package/package.json +2 -2
- package/tsdoc-metadata.json +1 -1
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.
|
|
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": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@effected/jsonc": "^0.7.0",
|
|
43
43
|
"@effected/toml": "^0.5.0",
|
|
44
|
-
"@effected/yaml": "^0.
|
|
44
|
+
"@effected/yaml": "^0.11.0",
|
|
45
45
|
"effect": "4.0.0-rc.109"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|