From b2b124277ac66049331f691aeaf422761a867db8 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sat, 31 Oct 2026 03:56:44 +0100 Subject: [PATCH] =?UTF-8?q?Answer=20prose=20round=201:=200=20=F0=9F=94=B4,?= =?UTF-8?q?=206=20=F0=9F=9F=A1=20(0=20misread);=20reword=20the=20spanning?= =?UTF-8?q?=20comments,=20spec=20and=20changelog=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 14 ++++++++------ spec/flavour.md | 10 ++++++---- src/markdown/emit/skipped-nodes.ts | 4 ++-- src/markdown/portable/inline-reduction.ts | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e1ff6..9543c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,12 +33,14 @@ `!adf:border[x]{color="#091e42" size=2}` is `unsupported-node-shape`, and only a `mediaInline` takes `border`. `adfToLosslessMarkdown` writes text holding `border` as `!adf:carry{json="…"}`. `MIGRATION.md` says how to convert stored markdown. -- `adfToLosslessMarkdown` and `adfToPortableMarkdown` write an emphasis or a link once across the - hard breaks between two texts it marks: `_One\` then `Two_`, where they wrote `_One_\` then - `_Two_`. They write an emphasis once across code spans, as ``**Run `npm ci` first**``, and - `adfToLosslessMarkdown` also across mentions, emoji, dates, statuses, inline cards and inline - media, as `**Ping !adf:mention[@A]{id=x} now**`, and a link across those but inline media. Each - reads back as before; a line that would read back otherwise is written as before. +- `adfToLosslessMarkdown` and `adfToPortableMarkdown` write an `em`, `strike`, `strong` or `link` + mark once across the hard breaks between two texts it marks: `_One\` then `Two_`, where they + wrote `_One_\` then `_Two_`. They write an `em`, `strike` or `strong` mark once around a code + span: ``**Run `npm ci` first**``. `adfToLosslessMarkdown` also writes those three once across + mentions, emoji, dates, statuses, inline cards and inline media, as + `**Ping !adf:mention[@A]{id=x} now**`, and a link once across mentions, emoji, dates, statuses + and inline cards. The markdown reads back to the same ADF as before. Where the joined line would + not, the writers write the line as before. - Every reader keeps the URL and title of an image inside a link's text, where it dropped them: after the link comes `(image)`, which links to the image, so `[look at ![the moon](moon.png "Full") tonight](/moon)` reads as diff --git a/spec/flavour.md b/spec/flavour.md index f412ac1..a829464 100644 --- a/spec/flavour.md +++ b/spec/flavour.md @@ -564,10 +564,12 @@ marks array in order, outermost first: `_!adf:underline[x]_` gives marks `[em, u the array, not a set — and opens each spelling once over the longest run of adjacent inline nodes carrying an identical mark, attributes included, at that depth: `attrs: {}` differs from no `attrs`, and a directive spells it `{attrs=empty}`. A run breaks at every node the emitter carries, so no -emitted carry sits inside a mark spelling. An emphasis or link run also spans the nodes between two -it marks that take no mark of its type, where the line reads back so: `_One\` then `Two_` is one -`em` over two texts and the hard break between, ``**Run `npm ci` first**`` one `strong` around -plain code. `adfToPortableMarkdown` spans hard breaks and code spans the same way. +emitted carry sits inside a mark spelling. An `em`, `strike`, `strong` or `link` run also spans a +node between two of its nodes when that node cannot hold the run's mark. It does so only where the +spanned line reads back to the same marks; otherwise the run breaks there. So `_One\` then `Two_` +is one `em` run over two texts, the hard break between them unmarked, and +``**Run `npm ci` first**`` is one `strong` run around unmarked code. `adfToPortableMarkdown` spans +hard breaks and code spans the same way. An inline node whose marks no nesting spells — a node holding a mark Atlassian's schema withholds from it, a mark type the first list above does not hold, an attrs key its spelling does not list, a value that is not the diff --git a/src/markdown/emit/skipped-nodes.ts b/src/markdown/emit/skipped-nodes.ts index 4f5251d..b6397f3 100644 --- a/src/markdown/emit/skipped-nodes.ts +++ b/src/markdown/emit/skipped-nodes.ts @@ -6,13 +6,13 @@ import { takesMark } from '../../adf/inline-nodes.ts' type Carries = (node: AdfNode, index: number) => boolean -// The nodes, each that an emphasis or link run skips between two nodes it marks holding the run's mark at the run's depth, or `nodes` itself where no run skips one. +// Lends each emphasis or link run's mark to the nodes inside the run that cannot hold it; returns `nodes` itself where no run skips a node. export function spanSkippedNodes(nodes: readonly AdfNode[], carries: Carries): readonly AdfNode[] { const spanned = [...nodes] return spanRuns(spanned, 0, spanned.length, 0, carries) ? spanned : nodes } -// Groups the runs as `inlineRuns` does, then lends each run's mark to the nodes it skips; returns whether it lent any. +// Groups the runs as `inlineRuns` does. function spanRuns(spanned: AdfNode[], first: number, end: number, depth: number, carries: Carries): boolean { if (depth > largestNesting) return false let lent = false diff --git a/src/markdown/portable/inline-reduction.ts b/src/markdown/portable/inline-reduction.ts index ea7939e..ad92bd4 100644 --- a/src/markdown/portable/inline-reduction.ts +++ b/src/markdown/portable/inline-reduction.ts @@ -166,7 +166,7 @@ export function trimmedEdges(leaves: readonly AdfNode[]): AdfNode[] { // Terminates: a pass that changes a leaf drops whitespace from the leaf's edge or takes a mark off that whitespace, and merging adds no whitespace or mark. for (let current = leaves; ; ) { const merged = withoutEdgeBreaks(mergeAdjacentText(current, joinsWhenEditorNormal)) - // Whitespace beside a code span a run spans keeps the run's mark, where the line written spanned reads it. + // Whitespace beside a code span inside a run keeps the run's mark, since the writer spans the run across the code. const spanned = spanSkippedNodes(merged, () => false) let changed = false const trimmed: AdfNode[] = []