Fix line endings in nested labels
Closes GH-13.
This commit is contained in:
parent
ed6c0bbfcd
commit
68d01105ec
2 changed files with 79 additions and 45 deletions
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* @typedef {import('micromark-util-types').Effects} Effects
|
* @typedef {import('micromark-util-types').Effects} Effects
|
||||||
* @typedef {import('micromark-util-types').State} State
|
* @typedef {import('micromark-util-types').State} State
|
||||||
|
* @typedef {import('micromark-util-types').Token} Token
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ok as assert} from 'uvu/assert'
|
import {ok as assert} from 'uvu/assert'
|
||||||
|
@ -35,6 +36,8 @@ export function factoryLabel(
|
||||||
) {
|
) {
|
||||||
let size = 0
|
let size = 0
|
||||||
let balance = 0
|
let balance = 0
|
||||||
|
/** @type {Token|undefined} */
|
||||||
|
let previous
|
||||||
|
|
||||||
return start
|
return start
|
||||||
|
|
||||||
|
@ -59,43 +62,28 @@ export function factoryLabel(
|
||||||
}
|
}
|
||||||
|
|
||||||
effects.enter(stringType)
|
effects.enter(stringType)
|
||||||
return atBreak(code)
|
return lineStart(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {State} */
|
/** @type {State} */
|
||||||
function atBreak(code) {
|
function lineStart(code) {
|
||||||
if (code === codes.eof || size > constants.linkReferenceSizeMax) {
|
if (code === codes.rightSquareBracket && !balance) {
|
||||||
return nok(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code === codes.rightSquareBracket && !balance--) {
|
|
||||||
return atClosingBrace(code)
|
return atClosingBrace(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markdownLineEnding(code)) {
|
const token = effects.enter(types.chunkText, {
|
||||||
if (disallowEol) {
|
contentType: constants.contentTypeText,
|
||||||
return nok(code)
|
previous
|
||||||
}
|
})
|
||||||
|
if (previous) previous.next = token
|
||||||
effects.enter(types.lineEnding)
|
previous = token
|
||||||
effects.consume(code)
|
return data(code)
|
||||||
effects.exit(types.lineEnding)
|
|
||||||
return atBreak
|
|
||||||
}
|
|
||||||
|
|
||||||
effects.enter(types.chunkText, {contentType: constants.contentTypeText})
|
|
||||||
return label(code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {State} */
|
/** @type {State} */
|
||||||
function label(code) {
|
function data(code) {
|
||||||
if (
|
if (code === codes.eof || size > constants.linkReferenceSizeMax) {
|
||||||
code === codes.eof ||
|
return nok(code)
|
||||||
markdownLineEnding(code) ||
|
|
||||||
size > constants.linkReferenceSizeMax
|
|
||||||
) {
|
|
||||||
effects.exit(types.chunkText)
|
|
||||||
return atBreak(code)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -110,8 +98,33 @@ export function factoryLabel(
|
||||||
return atClosingBrace(code)
|
return atClosingBrace(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (markdownLineEnding(code)) {
|
||||||
|
if (disallowEol) {
|
||||||
|
return nok(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
effects.consume(code)
|
||||||
|
effects.exit(types.chunkText)
|
||||||
|
return lineStart
|
||||||
|
}
|
||||||
|
|
||||||
effects.consume(code)
|
effects.consume(code)
|
||||||
return code === codes.backslash ? labelEscape : label
|
return code === codes.backslash ? dataEscape : data
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {State} */
|
||||||
|
function dataEscape(code) {
|
||||||
|
if (
|
||||||
|
code === codes.leftSquareBracket ||
|
||||||
|
code === codes.backslash ||
|
||||||
|
code === codes.rightSquareBracket
|
||||||
|
) {
|
||||||
|
effects.consume(code)
|
||||||
|
size++
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
return data(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {State} */
|
/** @type {State} */
|
||||||
|
@ -123,19 +136,4 @@ export function factoryLabel(
|
||||||
effects.exit(type)
|
effects.exit(type)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {State} */
|
|
||||||
function labelEscape(code) {
|
|
||||||
if (
|
|
||||||
code === codes.leftSquareBracket ||
|
|
||||||
code === codes.backslash ||
|
|
||||||
code === codes.rightSquareBracket
|
|
||||||
) {
|
|
||||||
effects.consume(code)
|
|
||||||
size++
|
|
||||||
return label
|
|
||||||
}
|
|
||||||
|
|
||||||
return label(code)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1278,7 +1278,43 @@ test('content', (t) => {
|
||||||
t.equal(
|
t.equal(
|
||||||
micromark(':abbr[\na\r]', options({abbr})),
|
micromark(':abbr[\na\r]', options({abbr})),
|
||||||
'<p><abbr>\na\r</abbr></p>',
|
'<p><abbr>\na\r</abbr></p>',
|
||||||
'should support EOLs at the edges of a label'
|
'should support EOLs at the edges of a label (1)'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[\n]', options({abbr})),
|
||||||
|
'<p><abbr>\n</abbr></p>',
|
||||||
|
'should support EOLs at the edges of a label (2)'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[a\n:abbr[b]\nc]', options({abbr})),
|
||||||
|
'<p><abbr>a\n<abbr>b</abbr>\nc</abbr></p>',
|
||||||
|
'should support EOLs around nested directives'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[:abbr[\n]]', options({abbr})),
|
||||||
|
'<p><abbr><abbr>\n</abbr></abbr></p>',
|
||||||
|
'should support EOLs inside nested directives (1)'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[:abbr[a\nb]]', options({abbr})),
|
||||||
|
'<p><abbr><abbr>a\nb</abbr></abbr></p>',
|
||||||
|
'should support EOLs inside nested directives (2)'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[:abbr[\nb\n]]', options({abbr})),
|
||||||
|
'<p><abbr><abbr>\nb\n</abbr></abbr></p>',
|
||||||
|
'should support EOLs inside nested directives (3)'
|
||||||
|
)
|
||||||
|
|
||||||
|
t.equal(
|
||||||
|
micromark(':abbr[:abbr[\\\n]]', options({abbr})),
|
||||||
|
'<p><abbr><abbr><br />\n</abbr></abbr></p>',
|
||||||
|
'should support EOLs inside nested directives (4)'
|
||||||
)
|
)
|
||||||
|
|
||||||
t.equal(
|
t.equal(
|
||||||
|
|
Loading…
Add table
Reference in a new issue