Pin what the doomed openers keep: the carry and the image literal brackets hold
CI / gate (push) Successful in 36s
CI / publish (push) Has been skipped

This commit is contained in:
2026-09-19 02:09:19 +02:00
parent 6e9e38776f
commit 9d5a8e4137
3 changed files with 10 additions and 2 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ it named converts.
| Input | `0.1.0` | `0.2.0` | | Input | `0.1.0` | `0.2.0` |
| --- | --- | --- | | --- | --- | --- |
| a link whose `href` or `title` no CommonMark escape spells, on emit | `unspellable-link` | spells `!adf:link[text]{attrs}` | | a link whose `href` or `title` no CommonMark escape spells, on emit | `unspellable-link` | spells `!adf:link[text]{attrs}` |
| a link whose text already holds one (`[<https://example.com/>](/v)`) | drops the outer link | leaves the outer brackets literal text | | a link whose text already holds one (`[a<https://example.com/>b](/v)`) | marks every node the inner link does not, splitting the outer link around it | leaves the outer brackets literal text |
| a leaf node given a body (`media`, `listBreak`) | `unsupported-node-shape` | `malformed-directive` | | a leaf node given a body (`media`, `listBreak`) | `unsupported-node-shape` | `malformed-directive` |
| a node with a block body written as a leaf (`panel`) | `unsupported-node-shape` | `malformed-directive` | | a node with a block body written as a leaf (`panel`) | `unsupported-node-shape` | `malformed-directive` |
| an empty node the `::taskItem` spelling row names, written as a leaf | parses | `malformed-directive` | | an empty node the `::taskItem` spelling row names, written as a leaf | parses | `malformed-directive` |
+1 -1
View File
@@ -39,7 +39,7 @@ type Run = { canClose: boolean; canOpen: boolean; character: string; index: numb
// `container` is `undefined` inside a directive's content slot, the emitter's `bracketed`. // `container` is `undefined` inside a directive's content slot, the emitter's `bracketed`.
type Scan = { type Scan = {
container: LineContainer | undefined container: LineContainer | undefined
// Pieces below this have been walked for openers to deactivate, so a nest of doomed brackets stays linear. // Pieces below this have been walked for openers to deactivate: one left active reaches closeLink, whose image and carry guards refuse what literal brackets hold fine.
deactivatedBefore: number deactivatedBefore: number
definitions: LinkDefinitions definitions: LinkDefinitions
openingSpellableLink: boolean openingSpellableLink: boolean
@@ -841,6 +841,14 @@ test('leaves the brackets of a link whose text already holds one the text they a
]) ])
}) })
// Literal brackets hold what no mark may, so the openers they doom give way before closeLink refuses a carry or an image inside them.
test('keeps the carry and the image the brackets a nested link leaves literal hold', () => {
assert.deepEqual(content(markdownToAdf('[[<http://x/>](/c)!adf:carry{json="{\\"type\\":\\"blockCard\\"}"}](/w)\n')), [
{ content: [text('[['), marked('http://x/', link('http://x/')), text('](/c)'), { type: 'blockCard' }, text('](/w)')], type: 'paragraph' },
])
assert.deepEqual(content(markdownToAdf('![![a [b](/c) ](/i)[![x](/y)[<http://x/>](/c)](/w)](/v)\n')), [image('/v', 'a b [x[http://x/](/c)](/w)')])
})
test('reads the reference links a definition resolves, and leaves the rest literal', () => { test('reads the reference links a definition resolves, and leaves the rest literal', () => {
assert.deepEqual(content(markdownToAdf('[a][r]\n\n[r]: /url\n')), [{ content: [marked('a', link('/url'))], type: 'paragraph' }]) assert.deepEqual(content(markdownToAdf('[a][r]\n\n[r]: /url\n')), [{ content: [marked('a', link('/url'))], type: 'paragraph' }])
assert.deepEqual(content(markdownToAdf('[a][]\n\n[a]: /url\n')), [{ content: [marked('a', link('/url'))], type: 'paragraph' }]) assert.deepEqual(content(markdownToAdf('[a][]\n\n[a]: /url\n')), [{ content: [marked('a', link('/url'))], type: 'paragraph' }])