36a - §1–§6's decisions move to docs/decisions.md, indexed from AGENTS.md
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# Decisions
|
||||
|
||||
## Plain markdown is a flavour of the grammar
|
||||
|
||||
2026-09-27, the maintainer. Goal 2. Valid while the plain flavour's spellings are ones the markdown
|
||||
grammar can read and write.
|
||||
|
||||
The lossy pair is the plain flavour: the markdown grammar's reader and writer with the flavour set,
|
||||
its spellings — alerts, callouts, task markers, `==` — read and written there, so a marker line and
|
||||
a backslash reach them intact; what the flavour cannot spell reduces ADF→ADF ahead of the writer.
|
||||
|
||||
## The round-trip is the product
|
||||
|
||||
2026-08-23, the maintainer. Goal 1. Valid while a consumer saves back through the lossless pair.
|
||||
|
||||
`markdownToAdf(adfToMarkdown(doc))` and `htmlToAdf(adfToHtml(doc))` must equal `doc` — anything
|
||||
less silently destroys content an editor could not represent, in a document it did not author.
|
||||
When losslessness and readability conflict, losslessness wins. Round-trip equality is a property
|
||||
tested over a corpus, not a claim made in prose.
|
||||
|
||||
## Markdown in is a canonical fixpoint
|
||||
|
||||
2026-08-23, the maintainer. Goals 1 and 3. Valid while markdown input may be written by hand.
|
||||
|
||||
The other direction is a canonical fixpoint, not byte-identity: human markdown normalizes, the way
|
||||
back yields the library's canonical spelling, and that spelling round-trips byte-identically —
|
||||
where there is a way back. CommonMark spells some things the flavour has no escape for — a
|
||||
paragraph opening with a code span whose backticks read back as a fence — so a parse succeeding
|
||||
does not imply a spellable document; `corpus/commonmark-spec/exceptions.json` names those.
|
||||
|
||||
## Equality is editor-normal
|
||||
|
||||
2026-08-24, the maintainer. Goal 1. Valid while markdown cannot tell apart the ADF shapes this
|
||||
merges.
|
||||
|
||||
"Equals" is structural equality over editor-normal ADF — adjacent text nodes with identical marks
|
||||
and no attributes merged, JSON number semantics, an empty attrs object, marks array or content
|
||||
array the absent key — the only domain markdown can restore.
|
||||
|
||||
## Unknown nodes ride the carry
|
||||
|
||||
2026-08-23, extended to misplaced known nodes 2026-08-26, the maintainer. Goal 1. Valid while ADF
|
||||
gains node types faster than this library spells them.
|
||||
|
||||
An unknown ADF node is carried opaquely — raw JSON rides a dedicated syntax in both formats and
|
||||
restores to a deep-equal node. The round-trip holds for documents newer than the library. So does
|
||||
a known node no section spells where it stands: a markdown serializer spells a node by type without
|
||||
checking its position, and refusing loses a document ADF itself keeps in an `unsupportedBlock`.
|
||||
Where a container's own spelling cannot hold the child it has — a `bulletList` outside `listItem`,
|
||||
a `codeBlock` outside text — the error result names that instead.
|
||||
|
||||
## Foreign HTML is refused by name
|
||||
|
||||
2026-08-23, the maintainer. Goals 1 and 6. Valid until the HTML dialect's element set lands
|
||||
(`todo.md`, 6).
|
||||
|
||||
An unmappable foreign HTML element is an error result naming the element — never a silent drop.
|
||||
|
||||
## Names stay text
|
||||
|
||||
2026-08-23, the maintainer. Goal 7. Valid while resolving a name to an id needs I/O.
|
||||
|
||||
A bare `@name` or `:smile:` in typed text stays a text node. Only directives produce
|
||||
mention/emoji/media nodes; resolving names to ids is the consumer's job.
|
||||
|
||||
## Directives under `!adf:`
|
||||
|
||||
2026-08-23, prefixed `!adf:` 2026-09-16, the maintainer. Goals 3 and 4. Valid while prose does not
|
||||
write `!adf:`.
|
||||
|
||||
Directives are one grammar for everything markdown lacks, namespaced under `!adf:`:
|
||||
`!adf:panel info` … `!adf:/panel` blocks, `!adf:mention[@Mikael]{id=5b10a2}` inline, `\!adf:` the
|
||||
one escape. Not CommonMark's generic-directives proposal: its `:::` claims a form prose writes, and
|
||||
its fence-length discipline ties a container's opener to its own body, where closing from the
|
||||
opener nests by itself and leaf versus container falls out of the node's content model.
|
||||
|
||||
## CommonMark is a subset
|
||||
|
||||
2026-08-23, the maintainer. Goal 3. Valid while the carve-outs stay the flavour's only claims.
|
||||
|
||||
Plain CommonMark is a subset, with carve-outs (`spec/flavour.md`): literal text shaped like a
|
||||
directive, a pipe table or a `~~` pair is claimed — plus one image gap.
|
||||
|
||||
## Tables
|
||||
|
||||
2026-08-23, the maintainer. Goal 4. Valid while a pipe table holds only one header row and inline
|
||||
cells.
|
||||
|
||||
One header row plus plain inline cells → pipe table; anything richer → directive form.
|
||||
|
||||
## Links
|
||||
|
||||
2026-09-13, nesting 2026-09-17, the maintainer. Goals 1 and 4. Valid while CommonMark's link
|
||||
syntax is what readers edit.
|
||||
|
||||
`[text](url "title")`, or `<url>` for a bare autolink-shaped text, wherever CommonMark spells the
|
||||
mark; `!adf:link[text]{attrs}` where it does not — an attribute CommonMark cannot hold, an `href` or
|
||||
`title` no canonical escape spells, a paragraph opening whose CommonMark spelling would read as a
|
||||
link reference definition — and a directive link CommonMark could spell is refused. No link wraps a
|
||||
link — the bracket form goes literal, the directive form refused — which is CommonMark's prose
|
||||
where its reference implementation nests one `<a>` in another.
|
||||
|
||||
## Ids stay site-local
|
||||
|
||||
2026-08-23, the maintainer. Goal 1. Valid while ADF ids are minted per site.
|
||||
|
||||
Identity-bearing nodes carry their ids in attributes; a document is only portable within its site —
|
||||
accepted.
|
||||
|
||||
## The HTML dialect
|
||||
|
||||
2026-08-23, the maintainer. Goals 4 and 7. Valid while HTML output is read by consumers styling it
|
||||
themselves.
|
||||
|
||||
The HTML dialect mirrors the markdown flavour: semantic elements, stable `adf-*` classes, `data-*`
|
||||
for what HTML cannot express, text always escaped. No stylesheet ships.
|
||||
|
||||
## No runtime dependencies
|
||||
|
||||
2026-08-23, the maintainer. Goal 7. Valid while Goal 7 names no runtime dependencies.
|
||||
|
||||
`dependencies` is empty. A runtime dependency enters only through an entry here stating why ~20
|
||||
lines of own code cannot do the job, who maintains it, and what auditing it costs. So the CommonMark
|
||||
and HTML parsers are written in this repo.
|
||||
|
||||
## Standards ship as data
|
||||
|
||||
2026-08-30, the CommonMark suite 2026-09-05 and ADF's schemas 2026-09-13, the maintainer. Goals 1
|
||||
and 7. Valid while each table's upstream package is CommonJS-only or heavy.
|
||||
|
||||
A table a standard fixes is data rather than a dependency: HTML5's 2125 semicolon-terminated
|
||||
character references ship packed in their own module, so entity decoding is complete without one.
|
||||
The CommonMark spec suite is the same shape of data and ships vendored at `corpus/commonmark-spec/`
|
||||
rather than as the `commonmark-spec` dev dependency — that package is CommonJS-only, and Renovate
|
||||
auto-bumping a spec version would silently point the vendored exception list's example numbers at a
|
||||
renumbered suite. A spec bump is a deliberate re-pin, exceptions re-derived by hand beside it.
|
||||
Atlassian's ADF JSON Schemas ship vendored the same way, at `spec/adf-schema/`, rather than as the
|
||||
`@atlaskit/adf-schema` dev dependency — CommonJS-only, some fifty packages with React among them,
|
||||
and a release most days for Renovate to automerge — re-pinned by hand when a payload or a report
|
||||
shows the need.
|
||||
|
||||
## fast-check
|
||||
|
||||
2026-09-14, the maintainer. Goal 1. Valid while a failing generated document needs shrinking by
|
||||
hand otherwise.
|
||||
|
||||
`fast-check` earns its place as a devDependency shrinking a failing generated document to the
|
||||
nodes that break it.
|
||||
|
||||
## Any ES2022 engine
|
||||
|
||||
2026-09-01, the maintainer. Goal 7. Valid while ES2022 is the floor browsers and servers share.
|
||||
|
||||
The library runs on any ES2022 engine, not only Node — a browser as readily as a server. The
|
||||
shipped source is ECMAScript and nothing else: no host import, no host global, no DOM.
|
||||
`tsconfig.build.json` is that gate, typechecking and emitting the shipped files alone, so
|
||||
`node:fs`, `process` and an ES2024 method are compile errors here rather than a consumer's crash
|
||||
there. The standard is the line, never an engine list: one implementing it in part — Hermes is the
|
||||
live doubt, on the Unicode property escapes emphasis matching leans on and on lookbehind — is out
|
||||
of scope rather than a bug. Node's test runner, the corpus reads and the build are the repo's own,
|
||||
never the library's, and `engines.node` states the floor the shipped JavaScript needs — `>=18` —
|
||||
never the higher one those repo-only tools want.
|
||||
|
||||
## ESM only
|
||||
|
||||
2026-08-23, the maintainer. Goal 7. Valid while every supported engine loads ES modules.
|
||||
|
||||
No CommonJS build, no dual-package hazard.
|
||||
|
||||
## One built entrypoint
|
||||
|
||||
2026-08-23, the maintainer. Goal 7. Valid while Node refuses to type-strip under `node_modules`.
|
||||
|
||||
Built JavaScript, `.d.ts` beside it. Do not add a TypeScript-source entrypoint — Node refuses to
|
||||
type-strip under `node_modules` (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`), so it cannot serve
|
||||
an npm consumer.
|
||||
|
||||
## Public on npm
|
||||
|
||||
2026-08-23, the maintainer. Goal 7 and the Audience. Valid while the audience installs from public
|
||||
npm.
|
||||
|
||||
Published to public npmjs as `@larvit/adf-codec`. Public source: the Gitea repo goes public,
|
||||
LICENSE in place, before the first publish.
|
||||
Reference in New Issue
Block a user