# Todo The plan, in order. Nothing is built. Design questions are settled in `AGENTS.md`; remaining spec detail is settled at its own milestone. ## Milestones - [x] **0 — Scaffold.** `package.json` per §6, `tsconfig.json`, `.npmrc` (`save-exact=true`), the Docker tooling, `renovate.json` (§9), and `.gitea/workflows/ci.yml` gating branches: `runs-on: docker-host`, actions pinned to semver tags. - [x] **1a — The directive grammar** (`spec/flavour.md`): inline/block/leaf directive forms, attributes, escaping, nesting, canonical form, the opaque-carry spelling, the raw-HTML input policy. - [x] **1b — Block node syntaxes** in `spec/flavour.md`: panel, expand/nestedExpand, the media family, the pipe-vs-directive table rule and the directive table form, task and decision lists, layout, extensions, syncBlock. - [ ] **1c — Inline node syntaxes and marks** in `spec/flavour.md`: mention, emoji, status, date, inlineCard, mediaInline; underline, subsup, textColor, border; the spelling for text nodes whose whitespace CommonMark cannot hold (literal newlines, leading or trailing spaces) — escape-based, never literal, since pipe cells trim and pad. At `mediaInline`, check real payloads for external-URL support — if it exists, revisit the media section's mid-text-image error and its "no slot" ground. - [ ] **1d — Corpus start** (§10): checked-in ADF ↔ canonical-markdown fixture pairs per spec'd node. - [ ] **2 — `adfToMarkdown`.** First real code — decide here where §10's coverage check lives. - [ ] **3 — `markdownToAdf`.** The CommonMark parser is the largest single component. The raw-HTML element mapping is empty until milestone 6, so at `0.1.0` every raw-HTML construct in input is an error result. - [ ] **4 — Round-trip property tests** over the corpus, both ways — the thing that proves 2 and 3. Generators emit editor-normal ADF (§2). - [ ] **5 — Release pipeline, ship `0.1.0`.** Publish-on-version-change (§9), `NPM_TOKEN` secret, the repo made public first (§6). `0.1.0` is the markdown round-trip: both markdown directions, the types, `isAdfDocument`. The build lands here: a build tsconfig emitting JS and `.d.ts` to `dist/` (the dev config's `allowImportingTsExtensions` forces `noEmit`, so the build config needs `rewriteRelativeImportExtensions`), plus `exports`/`files` in `package.json`. The maintainer's bump PR also removes `private: true`, the guard against any earlier publish. - [ ] **6 — The HTML dialect spec.** Element-by-element mapping, the `data-*` fidelity scheme, the opaque-carry form, and the documented foreign-element set `htmlToAdf` accepts. - [ ] **7 — HTML, ship `0.2.0`.** `adfToHtml`, `htmlToAdf`, the composed `markdownToHtml` / `htmlToMarkdown`. CommonMark spec suite runs against `markdownToHtml` from here (§10). - [ ] **8 — CLI.** A later goal, shaped around the personas once the library exists. ## The ADF inventory to cover From Atlassian's [structure reference](https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/) — not the whole schema: real payloads also carry `taskList`/`taskItem`, `decisionList`/`decisionItem`, `layoutSection`/`layoutColumn`, `blockCard`/`embedCard`, `extension`/`bodiedExtension`/`inlineExtension` and `placeholder`, none documented there. The documented set is the floor: the floor gets designed syntax, the rest rides the opaque carry (§3) until it does too. | | | | --- | --- | | Top-level block | `blockquote` `bodiedSyncBlock` `bulletList` `codeBlock` `expand` `heading` `mediaGroup` `mediaSingle` `multiBodiedExtension` `orderedList` `panel` `paragraph` `rule` `syncBlock` `table` | | Child block | `blockTaskItem` `extensionFrame` `listItem` `media` `nestedExpand` `tableCell` `tableHeader` `tableRow` | | Inline | `date` `emoji` `hardBreak` `inlineCard` `mediaInline` `mention` `status` `text` | | Marks | `border` `code` `em` `link` `strike` `strong` `subsup` `textColor` `underline` | Plain markdown covers `blockquote`, `bulletList`, `codeBlock`, `heading`, `orderedList`, `paragraph`, `rule`, `listItem`, `hardBreak`, `text`, and the `code`, `em`, `link`, `strike` and `strong` marks. Everything else is what the flavour is for.