Browse Source

Fix two CommonMark divergences in link reference definitions (#1213)

pull/1215/head
bfs2021 2 days ago
parent
commit
cc9ead1ce6
  1. 12
      src/rules_block/reference.ts
  2. 47
      test/markdown-it/misc.test.mjs

12
src/rules_block/reference.ts

@ -90,6 +90,10 @@ export default function reference (state: StateBlock, startLine: number, _endLin
if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false }
// A link label can have at most 999 characters inside the square
// brackets (CommonMark spec, §6.3)
if (labelEnd - 1 > 999) { return false }
// [label]: destination 'title'
// ^^^ skip optional whitespace here
for (pos = labelEnd + 2; pos < max; pos++) {
@ -141,6 +145,12 @@ export default function reference (state: StateBlock, startLine: number, _endLin
}
}
// A title must be separated from the destination by whitespace
// (CommonMark spec, §4.7). Remember if we skipped any: `pos` can be
// overwritten by the multi-line title continuation below, which would
// otherwise bypass this check.
const separated = pos !== start
// [label]: destination 'title'
// ^^^^^^^ parse this
let titleRes = state.md.helpers.parseLinkTitle(str, pos, max)
@ -155,7 +165,7 @@ export default function reference (state: StateBlock, startLine: number, _endLin
}
let title
if (pos < max && start !== pos && titleRes.ok) {
if (pos < max && separated && titleRes.ok) {
title = titleRes.str
pos = titleRes.pos
} else {

47
test/markdown-it/misc.test.mjs

@ -564,3 +564,50 @@ describe('Token attributes', function () {
assert.strictEqual(t.attrGet('myattr'), 'myvalue')
})
})
describe('Reference definitions (CommonMark 0.31.2 divergence cases, #1213)', function () {
it('Should not parse labels longer than 999 characters', function () {
const md = markdownit({ html: true })
assert.strictEqual(
md.render('[' + 'x'.repeat(1000) + ']: /url'),
'<p>[' + 'x'.repeat(1000) + ']: /url</p>\n'
)
})
it('Should parse labels of exactly 999 characters', function () {
const md = markdownit({ html: true })
const label = 'x'.repeat(999)
assert.strictEqual(md.render(`[${label}]: /url`), '')
assert.strictEqual(
md.render(`[${label}]: /url\n\n[${label}]`),
'<p><a href="/url">' + 'x'.repeat(999) + '</a></p>\n'
)
})
it('Should not parse a multi-line title without whitespace before it', function () {
const md = markdownit({ html: true })
assert.strictEqual(
md.render('- [ref]: <url>"open\n close"'),
'<ul>\n<li>[ref]: <url>&quot;open\nclose&quot;</li>\n</ul>\n'
)
})
it('Should still parse a multi-line title separated by whitespace', function () {
const md = markdownit({ html: true })
assert.strictEqual(md.render('[ref]: /url "open\n close"'), '')
assert.strictEqual(
md.render('[ref]: /url "open\n close"\n\n[ref]'),
'<p><a href="/url" title="open\nclose">ref</a></p>\n'
)
})
it('Should not parse a title without whitespace on a single line', function () {
const md = markdownit({ html: true })
assert.strictEqual(md.render('[foo]: <bar>(baz)'), '<p>[foo]: <bar>(baz)</p>\n')
})
})

Loading…
Cancel
Save