From 5c60e00a90e949358094a66066d262cae5c4267c Mon Sep 17 00:00:00 2001 From: David Anson Date: Sat, 11 Apr 2020 12:33:28 -0700 Subject: [PATCH] Update MD037/no-space-in-emphasis to avoid crash, handle more scenarios. --- lib/md037.js | 39 +++++++++++++++----------- test/escaped-emphasis-markers.md | 12 ++++---- test/spaces_inside_emphasis_markers.md | 31 +++++++++++++++++++- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/lib/md037.js b/lib/md037.js index c6af84c9..d4112b8c 100644 --- a/lib/md037.js +++ b/lib/md037.js @@ -29,34 +29,31 @@ module.exports = { let match = null; let emphasisIndex = -1; let emphasisLength = 0; + let effectiveEmphasisLength = 0; // Match all emphasis-looking runs in the line... while ((match = emphasisRe.exec(line))) { const matchIndex = match.index + match[1].length; const matchLength = match[0].length - match[1].length; if (emphasisIndex === -1) { // New run + emphasisIndex = matchIndex + matchLength; emphasisLength = matchLength; - emphasisIndex = matchIndex + emphasisLength; - } else { - // Already in a run - if (matchLength !== emphasisLength) { - // Looks like a run within a run, reset to embedded run - emphasisLength += matchLength; - emphasisIndex = matchIndex + emphasisLength; - } - // Extract emphasized content + effectiveEmphasisLength = matchLength; + } else if (matchLength === effectiveEmphasisLength) { + // Close current run const content = line.substring(emphasisIndex, matchIndex); const leftSpace = leftSpaceRe.test(content); const rightSpace = rightSpaceRe.test(content); if (leftSpace || rightSpace) { // Report the violation const contextStart = emphasisIndex - emphasisLength; - const contextEnd = matchIndex + emphasisLength; + const contextEnd = matchIndex + effectiveEmphasisLength; const context = line.substring(contextStart, contextEnd); const column = contextStart + 1; const length = contextEnd - contextStart; - const marker = match[2] || match[3]; - const fixedText = `${marker}${content.trim()}${marker}`; + const leftMarker = line.substring(contextStart, emphasisIndex); + const rightMarker = match[2] || match[3]; + const fixedText = `${leftMarker}${content.trim()}${rightMarker}`; addErrorContext( onError, lineIndex + 1, @@ -71,11 +68,19 @@ module.exports = { } ); } - // Update the run - emphasisLength -= matchLength; - if (!emphasisLength) { - emphasisIndex = -1; - } + // Reset + emphasisIndex = -1; + emphasisLength = 0; + effectiveEmphasisLength = 0; + } else if (matchLength === 3) { + // Swap internal run length (1->2 or 2->1) + effectiveEmphasisLength = matchLength - effectiveEmphasisLength; + } else if (effectiveEmphasisLength === 3) { + // Downgrade internal run (3->1 or 3->2) + effectiveEmphasisLength -= matchLength; + } else { + // Upgrade to internal run (1->3 or 2->3) + effectiveEmphasisLength += matchLength; } } } diff --git a/test/escaped-emphasis-markers.md b/test/escaped-emphasis-markers.md index 70f1dba2..cbc74eec 100644 --- a/test/escaped-emphasis-markers.md +++ b/test/escaped-emphasis-markers.md @@ -18,16 +18,16 @@ Escaped underscores _ should \_ be ignored by MD037. ## Double-character markers, start -All should be reported because they are valid single-character -marker emphasis without spaces. +All *could* be reported because they are valid single-character +marker emphasis when no spaces are present. -Escaped asterisks \** should ** be ignored by MD037. {MD037} +Escaped asterisks \** should ** be ignored by MD037. -Escaped asterisks *\* should ** be ignored by MD037. {MD037} +Escaped asterisks *\* should ** be ignored by MD037. -Escaped underscores \__ should __ be ignored by MD037. {MD037} +Escaped underscores \__ should __ be ignored by MD037. -Escaped underscores _\_ should __ be ignored by MD037. {MD037} +Escaped underscores _\_ should __ be ignored by MD037. ## Double-character markers, end diff --git a/test/spaces_inside_emphasis_markers.md b/test/spaces_inside_emphasis_markers.md index b2dff3f8..ae3359bf 100644 --- a/test/spaces_inside_emphasis_markers.md +++ b/test/spaces_inside_emphasis_markers.md @@ -115,13 +115,42 @@ This is * an ambiguous * scenario {MD037} with *space * problems {MD037} throughout * the * content {MD037} -Uncommon scenarios from the CommonMark specification: +Uncommon scenarios from the CommonMark specification (and some variations): ***strong emph*** ***strong** in emph* ***emph* in strong** **in strong *emph*** *in emph **strong*** +*** strong emph*** {MD037} +*** strong** in emph* {MD037} +*** emph* in strong** {MD037} +** in strong *emph*** {MD037} + +***strong emph *** {MD037} +***strong** in emph * {MD037} +***emph* in strong ** {MD037} +**in strong *emph *** {MD037} +*in emph **strong *** {MD037} + +** *strong emph*** {MD037} +** *strong** in emph* {MD037} +** *emph* in strong** {MD037} +**in strong * emph*** (internal spaces are not detected) +*in emph ** strong*** (internal spaces are not detected) + +***strong emph* ** {MD037} +***strong ** in emph* (internal spaces are not detected) +***emph * in strong** (internal spaces are not detected) +**in strong *emph* ** {MD037} +*in emph **strong* ** {MD037} + +Text *emph***strong** text +Text * emph***strong** text {MD037} +Text *emph ***strong** text (internal spaces are not detected) +Text *emph*** strong** text (internal spaces are not detected) +Text *emph***strong ** text {MD037} + ```markdown Violations * are * allowed in code blocks where emphasis does not apply. ```