Skip to content

Commit baff140

Browse files
fix: handle bracketed spans inside link labels (#288)
Co-authored-by: Farnabaz <farnabaz@gmail.com>
1 parent b298811 commit baff140

4 files changed

Lines changed: 170 additions & 2 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
## Input
2+
3+
```md
4+
[[1]{} Document](#)
5+
6+
[[link-name]{.cls} more](https://example.com)
7+
```
8+
9+
## AST
10+
11+
```json
12+
13+
{
14+
"frontmatter":{
15+
16+
},
17+
"meta":{
18+
19+
},
20+
"nodes":[
21+
[
22+
"p",
23+
{
24+
25+
},
26+
[
27+
"a",
28+
{
29+
"href":"#"
30+
},
31+
[
32+
"span",
33+
{},
34+
"1"
35+
],
36+
" Document"
37+
]
38+
],
39+
[
40+
"p",
41+
{
42+
43+
},
44+
[
45+
"a",
46+
{
47+
"href":"https://example.com"
48+
},
49+
[
50+
"span",
51+
{
52+
"class": "cls"
53+
},
54+
"link-name"
55+
],
56+
" more"
57+
]
58+
]
59+
]
60+
}
61+
```
62+
63+
## HTML
64+
65+
```html
66+
<p><a href="#"><span>1</span> Document</a></p>
67+
<p><a href="https://example.com"><span class="cls">link-name</span> more</a></p>
68+
```
69+
70+
## Markdown
71+
72+
```md
73+
[[1]{} Document](#)
74+
75+
[[link-name]{.cls} more](https://example.com)
76+
```
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
## Input
2+
3+
```md
4+
[Document](#)
5+
6+
[[1] Document](#)
7+
8+
[[link-name] more](https://example.com)
9+
```
10+
11+
## AST
12+
13+
```json
14+
15+
{
16+
"frontmatter":{
17+
18+
},
19+
"meta":{
20+
21+
},
22+
"nodes":[
23+
[
24+
"p",
25+
{
26+
27+
},
28+
[
29+
"a",
30+
{
31+
"href":"#"
32+
},
33+
"Document"
34+
]
35+
],
36+
[
37+
"p",
38+
{
39+
40+
},
41+
[
42+
"a",
43+
{
44+
"href":"#"
45+
},
46+
"[1] Document"
47+
]
48+
],
49+
[
50+
"p",
51+
{
52+
53+
},
54+
[
55+
"a",
56+
{
57+
"href":"https://example.com"
58+
},
59+
"[link-name] more"
60+
]
61+
]
62+
]
63+
}
64+
```
65+
66+
## HTML
67+
68+
```html
69+
<p><a href="#">Document</a></p>
70+
<p><a href="#">[1] Document</a></p>
71+
<p><a href="https://example.com">[link-name] more</a></p>
72+
```
73+
74+
## Markdown
75+
76+
```md
77+
[Document](#)
78+
79+
[\[1\] Document](#)
80+
81+
[\[link-name\] more](https://example.com)
82+
```

packages/comark/src/internal/stringify/handlers/mdc.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ export async function mdc(node: ComarkElement, state: State, parent?: ComarkElem
3636
}
3737
content = content.trimEnd()
3838

39-
const attrs = attributeEntries.length > 0 ? comarkAttributes(attributes) : ''
39+
let attrs = attributeEntries.length > 0 ? comarkAttributes(attributes) : ''
4040

4141
if (tag === 'span') {
42+
if (!attrs && parent?.[0] == 'a') {
43+
// Add empty attributes syntax to end of spans inside Anchor links
44+
// This will force Comark to parse them as span and prevent conflict
45+
attrs ||= '{}'
46+
}
4247
return `[${content}]${attrs}` + (inline ? '' : state.context.blockSeparator)
4348
}
4449

packages/comark/src/plugins/syntax.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,12 @@ const markdownItInlineSpan: PluginSimple = (md) => {
449449
const nextChar = state.src[index + 1]
450450
if (nextChar === '(' || nextChar === '[') return false
451451

452-
if (silent) return true
452+
// Inside a link label, bare `[text]` stays literal (plain-markdown behavior,
453+
// e.g. `[[1] Document](#)`); only an explicit `[text]{attrs}` span matches
454+
if (state.linkLevel > 0 && nextChar !== '{') return false
455+
456+
// Returning `false` lets `parseLinkLabel`'s own depth tracking consume nested brackets and the outer link parse
457+
if (silent) return false
453458

454459
state.push('mdc_inline_span', 'span', 1)
455460

0 commit comments

Comments
 (0)