From 9b43cb4fe96cb28a2446f6a62528235011bc8d2e Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 26 Oct 2026 12:58:17 +0100 Subject: [PATCH] =?UTF-8?q?Answer=20architecture=20round=205:=200=20?= =?UTF-8?q?=F0=9F=94=B4,=200=20=F0=9F=9F=A1=20(0=20misread);=20shownImage?= =?UTF-8?q?=20returns=20no=20textless=20state,=20item=20143=20and=20the=20?= =?UTF-8?q?card=20rule=20name=20their=20whole=20reach?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/decisions.md | 12 +++++++----- src/adf/shown-text.test.ts | 4 ++-- src/adf/shown-text.ts | 6 +++--- src/html/emit/carry-element.ts | 8 ++++---- src/markdown/portable/inline-reduction.ts | 8 +++++--- todo.md | 4 ++-- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/docs/decisions.md b/docs/decisions.md index f7ea5b0..7086a98 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -432,13 +432,15 @@ the shown code keeps the class its code block's own element takes. Inside a carry element, an image marked by a link to another target shows as portable markdown writes it inline (§A linked image standing inline in portable markdown, its link to another target, is written `[alt](href) ([image](url))`), so both targets stay; Goal 7 counts them as content. A link -marking a node that shows a note goes around the note. Recorded 2026-10-24 without a panel of its -own: it joins the second panel's `` to that portable spelling. +marking a node that shows a note goes around the note, and an image's own `text`, outside Atlassian's +schema, shows first, as every carried node's does. Recorded 2026-10-24 without a panel of its own: +it joins the second panel's `` to that portable spelling. Inside a carry element, a card a link marks links to the link's target, and shows its own URL as its -text where it has one, so both stay. A card showing only its name keeps its URL in `data-adf` alone, -until `todo.md` item 133 writes inline cards as their own elements, in 0.3.0. Recorded 2026-10-24 -without a panel of its own: it puts the second panel's `` around the text a card shows. +text where it has one, so both stay. A card showing only its name keeps its URL in `data-adf` alone. +Atlassian's schema gives no card a link mark, so only a hand-built document meets this; +`todo.md` item 133 ends it for inline cards, in 0.3.0. Recorded 2026-10-24 without a panel of its +own: it puts the second panel's `` around the text a card shows. ## No runtime dependencies diff --git a/src/adf/shown-text.test.ts b/src/adf/shown-text.test.ts index 37dbea7..ce1cd0c 100644 --- a/src/adf/shown-text.test.ts +++ b/src/adf/shown-text.test.ts @@ -48,9 +48,9 @@ test('shows an image a link to another target marks by its alt, else the target, assert.deepEqual(shownImage({ attrs: { type: 'external', url: moon }, type: 'media' }, ' '), { after: moon, link: undefined, text: moon }) }) -test('shows an image with no URL by its alt, else by no text, a note standing in its place', () => { +test('shows an image with no URL by its alt, else nothing, a note standing in its place', () => { assert.deepEqual(shownImage({ attrs: { alt: 'The moon', type: 'file' }, type: 'media' }, target), { after: undefined, link: undefined, text: 'The moon' }) - assert.deepEqual(shownImage({ attrs: { type: 'file' }, type: 'mediaInline' }, undefined), { after: undefined, link: undefined, text: undefined }) + assert.equal(shownImage({ attrs: { type: 'file' }, type: 'mediaInline' }, undefined), undefined) assert.deepEqual(shownImage({ attrs: { alt: 'The moon', type: 'external', url: ' ' }, type: 'media' }, undefined), { after: undefined, link: undefined, text: 'The moon' }) }) diff --git a/src/adf/shown-text.ts b/src/adf/shown-text.ts index 83df9f4..e7b1637 100644 --- a/src/adf/shown-text.ts +++ b/src/adf/shown-text.ts @@ -39,11 +39,11 @@ export function referenceName(node: AdfNode): string | undefined { } } -// What an image shows in place of itself, `href` the target of the link marking it, if any: `text`, else a note; `link`, its URL, which `text` links to where no link marks it; `after`, its URL, shown after a link going elsewhere. -export function shownImage(media: AdfNode, href: string | undefined): { after: string | undefined; link: string | undefined; text: string | undefined } { +// What an image shows in place of itself, `href` the target of the link marking it, if any: `text`; `link`, its URL, which `text` links to where no link marks it; `after`, its URL, shown after a link going elsewhere. `undefined` where it shows no text, so a note stands in its place. +export function shownImage(media: AdfNode, href: string | undefined): { after: string | undefined; link: string | undefined; text: string } | undefined { const alt = visibleText(nodeAttrs(media)['alt']) const url = shownUrl(media) - if (url === undefined) return { after: undefined, link: undefined, text: alt } + if (url === undefined) return alt === undefined ? undefined : { after: undefined, link: undefined, text: alt } if (href === undefined) return { after: undefined, link: url, text: alt ?? url } if (href === url) return { after: undefined, link: undefined, text: alt ?? url } return { after: url, link: undefined, text: alt ?? visibleText(href) ?? url } diff --git a/src/html/emit/carry-element.ts b/src/html/emit/carry-element.ts index 4ef55d4..09bd93b 100644 --- a/src/html/emit/carry-element.ts +++ b/src/html/emit/carry-element.ts @@ -55,11 +55,11 @@ function shownPiece(node: AdfNode, lineFeed: string): string { return linkedText(node, shownText(node), shownUrl(node), lineFeed) } -// As portable markdown writes it inline, except that a link around a note stays (docs/decisions.md §The HTML dialect). +// As portable markdown writes it inline, except that a link around a note stays and an image's own `text`, outside ADF's schema, shows first (docs/decisions.md §The HTML dialect). function linkedImage(media: AdfNode, lineFeed: string): string { - const { after, link, text } = shownImage(media, shownLink(media)?.href) - const shown = linkedText(media, text, link, lineFeed) - return after === undefined ? shown : `${shown} (${linked('image', { href: after })})` + const image = shownImage(media, shownLink(media)?.href) + const shown = linkedText(media, image?.text, image?.link, lineFeed) + return image?.after === undefined ? shown : `${shown} (${linked('image', { href: image.after })})` } function linkedText(node: AdfNode, standIn: string | undefined, url: string | undefined, lineFeed: string): string { diff --git a/src/markdown/portable/inline-reduction.ts b/src/markdown/portable/inline-reduction.ts index 396fd36..0c73a70 100644 --- a/src/markdown/portable/inline-reduction.ts +++ b/src/markdown/portable/inline-reduction.ts @@ -59,14 +59,16 @@ function cardLeaves(card: AdfNode, marks: readonly AdfMark[], container: LineCon return linkedLeaves(shownText(card) ?? href, href, marks, container) } -function linkedLeaves(text: string | undefined, href: string, marks: readonly AdfMark[], container: LineContainer): AdfNode[] { +function linkedLeaves(text: string, href: string, marks: readonly AdfMark[], container: LineContainer): AdfNode[] { return textLeaves(text, [...marks.filter((mark) => mark.type !== 'link'), { attrs: { href }, type: 'link' }], container) } // An image standing inline is a link to it: the reader builds no node for an inline image, reading it as its alt text linked, and inside a link as the link's text, then (image). function mediaLeaves(media: AdfNode, marks: readonly AdfMark[], container: LineContainer): AdfNode[] { - const { after, link, text } = shownImage(media, shownLink(media)?.href) - const shown = link === undefined ? textLeaves(text, marks, container, referenceName(media)) : linkedLeaves(text, link, marks, container) + const image = shownImage(media, shownLink(media)?.href) + if (image === undefined) return textLeaves(undefined, marks, container, referenceName(media)) + const { after, link, text } = image + const shown = link === undefined ? textLeaves(text, marks, container) : linkedLeaves(text, link, marks, container) return after === undefined ? shown : [...shown, ...imageAside((word) => linkedLeaves(word, after, marks, container))] } diff --git a/todo.md b/todo.md index f5a163a..c8b48fc 100644 --- a/todo.md +++ b/todo.md @@ -29,7 +29,7 @@ | 68 | 0.4.0 | | defect | **Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.** | 2 | 1 | 2 | 3 | 3 | 1 by 2 | 13.1 | | 127 | 0.4.0 | | principle | **Hold what `entity-references.test.ts`, `json-text.test.ts` and `result.test.ts` check by asserting outcomes, so none reads source text.** | 2 | 2 | 1 | 3 | 3 | code health by 2 | 13.1 | | 144 | 0.4.0 | | | **Give every container `docker-runner.sh` and `publish.sh` start a memory limit and an equal swap limit, sized from the largest a gate leg measurably needs.** | 1 | 1 | 1 | 1 | 2 | code health by 1 | 8.7 | -| 143 | 0.4.0 | | defect | **Keep the link around a note in `adfToPortableMarkdown`, so a linked stored image with no alt writes its note linked.** | 2 | 1 | 2 | 3 | 3 | 7 by 1 | 6.5 | +| 143 | 0.4.0 | | defect | **Keep, in `adfToPortableMarkdown`, the link around a note and the target of a link marking a card, so a linked stored image or card writes every target.** | 2 | 1 | 2 | 3 | 3 | 7 by 1 | 6.5 | | 112 | 0.4.0 | | | **Pad a GFM pipe table's short rows with empty cells, read its body rows holding no pipe, and read a one-column table without leading pipes in `portableMarkdownToAdf`.** | 2 | 1 | 2 | 3 | 3 | 4 by 4 | 6.2 | | 80 | 0.4.0 | | | **Name the node's path and the attribute key when `not-an-adf-document` refuses a node inside the document.** | 2 | 1 | 2 | 3 | 3 | 6 by 4 | 6.0 | | 81 | 0.4.0 | | | **Fail the gate unless the README's error tables list exactly the codes `ConvertErrorCode` holds.** | 1 | 1 | 1 | 1 | 2 | 3 by 2 | 4.2 | @@ -221,7 +221,7 @@ item 60, 2026-10-22. strings near V8's longest, about 512 MB each, so measure each leg's peak before picking the limit: one too small fails the gate. -### 143. Keep the link around a note in `adfToPortableMarkdown`, so a linked stored image with no alt writes its note linked. +### 143. Keep, in `adfToPortableMarkdown`, the link around a note and the target of a link marking a card, so a linked stored image or card writes every target. `noteLeaves` (`src/markdown/portable/inline-reduction.ts`) drops the node's marks, so a stored image a link marks writes `_(image not included)_` without the link's target, which Goal 7 counts as