4.3: a bare backtick run escapes wherever a later string of its length forms around an escape
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"text": "`` ``",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"type": "code"
|
||||
}
|
||||
],
|
||||
"text": "a",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"type": "paragraph"
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"type": "underline"
|
||||
}
|
||||
],
|
||||
"text": "``",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"text": "``",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"type": "code"
|
||||
}
|
||||
],
|
||||
"text": "a",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"type": "paragraph"
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"text": "``\\`",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"type": "code"
|
||||
}
|
||||
],
|
||||
"text": "`",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"text": "`",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"type": "paragraph"
|
||||
}
|
||||
],
|
||||
"type": "doc",
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
\`\` \`\``a`
|
||||
|
||||
:underline[\`\`]\`\``a`
|
||||
|
||||
\`\`\\\``` ` ``\`
|
||||
+4
-2
@@ -54,8 +54,10 @@ normalizes to it through the round-trip.
|
||||
- Entity references in input decode to their characters; output backslash-escapes only where text
|
||||
would otherwise parse as syntax, scanning the assembled line rather than each text node: escape
|
||||
the leading delimiter of a construct that would otherwise open, re-scan from there, and repeat.
|
||||
A backtick run escapes whole, and a lone backtick escapes wherever an escaped one follows it in
|
||||
the same inline content: CommonMark reads no escape inside a code span, so `` \` `` closes one.
|
||||
A backtick run escapes whole, and a bare one escapes wherever a later backtick string of its
|
||||
length forms around an escape in the same inline content — an escaped backtick alone, one joined
|
||||
to the bare run after it, or a bare run an escape splits off: CommonMark reads no escape inside a
|
||||
code span, so such a string still closes one.
|
||||
Where a paragraph opens with what reads as a link reference definition, which resolves before
|
||||
any inline construct binds (a `]` inside a code span or `{attrs}` counts), an opening text `[`
|
||||
escapes and an opening link's nodes ride the carry.
|
||||
|
||||
@@ -103,17 +103,33 @@ function escapedIndexes(scan: string, escapings: readonly InlineEscaping[], cont
|
||||
escaped.add(index)
|
||||
}
|
||||
}
|
||||
escapeLoneBackticks(scan, escapings, escaped)
|
||||
escapeClosedRuns(scan, escapings, escaped)
|
||||
return escaped
|
||||
}
|
||||
|
||||
// CommonMark reads no escape inside a code span, so an escaped backtick still closes one a bare lone backtick before it opens.
|
||||
function escapeLoneBackticks(scan: string, escapings: readonly InlineEscaping[], escaped: Set<number>): void {
|
||||
let escapedAfter = false
|
||||
for (let index = scan.length - 1; index >= 0; index -= 1) {
|
||||
if (scan.charAt(index) !== '`') continue
|
||||
if (escapedAfter && escapings[index] !== 'none' && scan.charAt(index - 1) !== '`' && scan.charAt(index + 1) !== '`') escaped.add(index)
|
||||
if (escaped.has(index)) escapedAfter = true
|
||||
// CommonMark reads no escape inside a code span, so a backtick string an escape forms or splits off still closes one an earlier bare run opens.
|
||||
function escapeClosedRuns(scan: string, escapings: readonly InlineEscaping[], escaped: Set<number>): void {
|
||||
const formed = new Set<number>()
|
||||
let end = scan.length - 1
|
||||
while (end >= 0) {
|
||||
if (scan.charAt(end) !== '`') {
|
||||
end -= 1
|
||||
continue
|
||||
}
|
||||
let start = end
|
||||
while (scan.charAt(start - 1) === '`') start -= 1
|
||||
let segmentEnd = end
|
||||
for (let index = end; index > start; index -= 1) {
|
||||
if (!escaped.has(index)) continue
|
||||
formed.add(segmentEnd - index + 1)
|
||||
segmentEnd = index - 1
|
||||
}
|
||||
if (segmentEnd !== end || escaped.has(start)) formed.add(segmentEnd - start + 1)
|
||||
else if (escapings[start] !== 'none' && formed.has(end - start + 1)) {
|
||||
for (let index = start; index <= end; index += 1) escaped.add(index)
|
||||
formed.add(1)
|
||||
}
|
||||
end = start - 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user