From 6c57203ae5c7d85715e5c8a4e9055406f2822a6e Mon Sep 17 00:00:00 2001 From: David Anson Date: Thu, 10 Jan 2019 21:29:27 -0800 Subject: [PATCH] Use tokens (vs. RegExp) for identifying fenced code blocks (fixes #151, fixes #152, fixes #155). --- lib/shared.js | 39 ++++++++++++++++------------------- test/fenced-code-in-list.json | 6 ++++++ test/fenced-code-in-list.md | 35 +++++++++++++++++++++++++++++++ test/fenced-code-unmatched.md | 13 ++++++++++++ 4 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 test/fenced-code-in-list.json create mode 100644 test/fenced-code-in-list.md create mode 100644 test/fenced-code-unmatched.md diff --git a/lib/shared.js b/lib/shared.js index e7d063b3..73a547db 100644 --- a/lib/shared.js +++ b/lib/shared.js @@ -136,32 +136,26 @@ function makeTokenCache(params) { return; } - // Populate line metadata array + // Initialize line metadata array + // 0x7: inCode + // 0x6: onFence (start) + // 0x2: onFence (end) + // 0x1: code body + // 0x8: inTable const lineMetadata = new Array(params.lines.length); - let fenceStart = null; - let inFence = false; - // Find fenced code by pattern (parser ignores "``` close fence") - params.lines.forEach(function forLine(line, lineIndex) { - let metadata = 0; - const match = /^[ ]{0,3}(`{3,}|~{3,})/.exec(line); - const fence = match && match[1]; - if (fence && - (!inFence || (fence.substr(0, fenceStart.length) === fenceStart))) { - metadata = inFence ? 2 : 6; - fenceStart = inFence ? null : fence; - inFence = !inFence; - } else if (inFence) { - metadata = 1; + lineMetadata.fill(0); + filterTokens(params, "fence", function forToken(token) { + lineMetadata[token.map[0]] = 6; + lineMetadata[token.map[1] - 1] = 2; + for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) { + lineMetadata[i] = 1; } - lineMetadata[lineIndex] = metadata; }); - // Find code blocks normally filterTokens(params, "code_block", function forToken(token) { for (let i = token.map[0]; i < token.map[1]; i++) { lineMetadata[i] = 1; } }); - // Find tables normally filterTokens(params, "table_open", function forToken(token) { for (let i = token.map[0]; i < token.map[1]; i++) { lineMetadata[i] += 8; @@ -220,12 +214,15 @@ module.exports.forEachLine = function forEachLine(callback) { // Invoke callback tokenCache.params.lines.forEach(function forLine(line, lineIndex) { const metadata = tokenCache.lineMetadata[lineIndex]; + const inCode = !!(metadata & 7); + const onFence = (((metadata & 6) >> 1) || 2) - 2; + const inTable = !!(metadata & 8); callback( line, lineIndex, - !!(metadata & 7), - (((metadata & 6) >> 1) || 2) - 2, - !!(metadata & 8)); + inCode, + onFence, + inTable); }); }; diff --git a/test/fenced-code-in-list.json b/test/fenced-code-in-list.json new file mode 100644 index 00000000..b6ba1058 --- /dev/null +++ b/test/fenced-code-in-list.json @@ -0,0 +1,6 @@ +{ + "default": true, + "MD013": { + "code_blocks": false + } +} diff --git a/test/fenced-code-in-list.md b/test/fenced-code-in-list.md new file mode 100644 index 00000000..df8f5f08 --- /dev/null +++ b/test/fenced-code-in-list.md @@ -0,0 +1,35 @@ +# Heading + +- Item + + ```javascript + debugger; + + + debugger; + ``` + + text + +- Item + + - Subitem + + ```javascript + debugger; + + + debugger; + ``` + + text + + - Subitem + +- Item + + - Subitem + + ```javascript + debugger; debugger; debugger; debugger; debugger; debugger; debugger; debugger; debugger; debugger; + ``` diff --git a/test/fenced-code-unmatched.md b/test/fenced-code-unmatched.md new file mode 100644 index 00000000..20827215 --- /dev/null +++ b/test/fenced-code-unmatched.md @@ -0,0 +1,13 @@ +# Heading + +Text + +```code``` + +Text + +```javascript +var x = 5; +``` + +Text