3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-13 04:08:29 +01:00

Answer architecture round 4: 0 🔴, 1 🟡 (0 misread); one image rule in shown-text for both writers, a link mark's href kept past a bad title, the card rule recorded

This commit is contained in:
2026-10-24 11:58:23 +02:00
committed by Lillem4n
parent 91457a83c8
commit 9ff53c1658
10 changed files with 115 additions and 50 deletions
+7 -3
View File
@@ -149,11 +149,12 @@ test('shows a carried node\'s content after a block it holds as a paragraph of i
assert.equal(shown(html(adfToHtml(document({ content: [paragraph(text('a')), text('b')], type: 'panel' })))), '<p>a</p><p>b</p>')
})
test('shows text a link marks in a carried node as a link', () => {
test('shows text a link marks in a carried node as a link, leaving out a title that is no string', () => {
const link: AdfMark = { attrs: { href: 'https://spec.commonmark.org/', title: 'The spec' }, type: 'link' }
const panel: AdfNode = { content: [paragraph(text('Read the '), text('CommonMark spec', link), text(' first.'))], type: 'panel' }
assert.equal(shown(html(adfToHtml(document(panel)))), '<p>Read the <a href="https://spec.commonmark.org/" title="The spec">CommonMark spec</a> first.</p>')
assert.equal(shown(html(adfToHtml(document(paragraph(text('x', { type: 'underline' }, link)))))), '<a href="https://spec.commonmark.org/" title="The spec">x</a>')
assert.equal(shown(html(adfToHtml(document(paragraph(text('x', { attrs: { href: 'https://spec.commonmark.org/', title: 5 }, type: 'link' })))))), '<a href="https://spec.commonmark.org/">x</a>')
})
test('shows a hard break, and a line feed in carried text outside a code block, as a line break', () => {
@@ -219,8 +220,11 @@ test('shows a carried image marked by a link to another target as that link, the
assert.equal(image({ alt: 'The moon', type: 'external', url: 'https://example.com/' }), '<p><a href="https://example.com/">The moon</a></p>')
const blank = shown(html(adfToHtml(document({ attrs: { layout: 'wide' }, content: [{ attrs: { type: 'external', url: 'https://example.com/moon.jpg' }, marks: [{ attrs: { href: ' ' }, type: 'link' }], type: 'media' }], type: 'mediaSingle' }))))
assert.equal(blank, '<p><a href=" ">https://example.com/moon.jpg</a> (<a href="https://example.com/moon.jpg">image</a>)</p>')
const inline: AdfNode = { attrs: { alt: 'The moon', type: 'external', url: 'https://example.com/moon.jpg' }, marks: [link], type: 'mediaInline' }
assert.equal(shown(html(adfToHtml(document(paragraph(inline))))), '<a href="https://example.com/">The moon</a> (<a href="https://example.com/moon.jpg">image</a>)')
const texted = shown(html(adfToHtml(document({ attrs: { layout: 'wide' }, content: [{ attrs: { alt: 'The moon', type: 'external', url: 'https://example.com/moon.jpg' }, marks: [link], text: 'Moon', type: 'media' }], type: 'mediaSingle' }))))
assert.equal(texted, '<p><a href="https://example.com/">Moon</a> (<a href="https://example.com/moon.jpg">image</a>)</p>')
const inline = (mark: AdfMark): string => shown(html(adfToHtml(document(paragraph({ attrs: { alt: 'The moon', type: 'external', url: 'https://example.com/moon.jpg' }, marks: [mark], type: 'mediaInline' })))))
assert.equal(inline(link), '<a href="https://example.com/">The moon</a> (<a href="https://example.com/moon.jpg">image</a>)')
assert.equal(inline({ attrs: { href: 'https://example.com/', title: 5 }, type: 'link' }), '<a href="https://example.com/">The moon</a> (<a href="https://example.com/moon.jpg">image</a>)')
})
test('links a carried card a link marks to that link\'s target alone', () => {
+17 -15
View File
@@ -1,10 +1,10 @@
import type { AdfNode } from '../../adf/document.ts'
import type { LinkAttrs } from '../../adf/mark-attributes.ts'
import { anchorOpener, jsonValue, languageClass, shownValue } from './escaping.ts'
import { carriedJson } from '../../adf/carried-json.ts'
import { largestNesting } from '../../nesting.ts'
import { linkAttrs, type LinkAttrs } from '../../adf/mark-attributes.ts'
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
import { partsShownText, referenceName, shownText, shownUrl, visibleText } from '../../adf/shown-text.ts'
import { nodeAttrs, nodeContent } from '../../adf/document.ts'
import { partsShownText, referenceName, shownImage, shownLink, shownText, shownUrl } from '../../adf/shown-text.ts'
import { success, type ConvertErrorPath, type Result } from '../../result.ts'
// The content a carry element shows of one block; `code` the code block holding it, if any.
@@ -51,23 +51,25 @@ function shownBlocks(root: AdfNode, codeLineFeed: string): ShownBlock[] {
// The node's own part of what its carry element shows.
function shownPiece(node: AdfNode, lineFeed: string): string {
if (node.type === 'hardBreak') return '<br>'
const mark = nodeMarks(node).find((held) => held.type === 'link')
const target = mark === undefined ? undefined : linkAttrs(nodeAttrs(mark))
const url = shownUrl(node)
if (['media', 'mediaInline'].includes(node.type) && target !== undefined && url !== undefined && target.href !== url) return linkedImage(node, target, url, lineFeed)
const link = target ?? (url === undefined ? undefined : { href: url })
const text = node.text ?? shownText(node)
if (['media', 'mediaInline'].includes(node.type)) return linkedImage(node, lineFeed)
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).
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 })})`
}
function linkedText(node: AdfNode, standIn: string | undefined, url: string | undefined, lineFeed: string): string {
const link = shownLink(node) ?? (url === undefined ? undefined : { href: url })
const text = node.text ?? standIn
if (text !== undefined) return linked(shownValue(text, lineFeed), link)
const name = referenceName(node)
return name === undefined ? '' : linked(`<em>(${shownValue(name, lineFeed)})</em>`, link)
}
// As portable markdown writes it inline (docs/decisions.md §The HTML dialect).
function linkedImage(media: AdfNode, target: LinkAttrs, url: string, lineFeed: string): string {
const text = visibleText(nodeAttrs(media)['alt']) ?? visibleText(target.href) ?? url
return `${linked(shownValue(text, lineFeed), target)} (${linked('image', { href: url })})`
}
// The shown HTML inside an `<a>` where it links and HTML can hold the link.
function linked(shown: string, link: LinkAttrs | undefined): string {
const anchor = link === undefined ? undefined : anchorOpener(link)