Use tokens (vs. RegExp) for identifying fenced code blocks (fixes #151, fixes #152, fixes #155).

This commit is contained in:
David Anson 2019-01-10 21:29:27 -08:00
parent 5be7104dab
commit 6c57203ae5
4 changed files with 72 additions and 21 deletions

View file

@ -136,32 +136,26 @@ function makeTokenCache(params) {
return; 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); const lineMetadata = new Array(params.lines.length);
let fenceStart = null; lineMetadata.fill(0);
let inFence = false; filterTokens(params, "fence", function forToken(token) {
// Find fenced code by pattern (parser ignores "``` close fence") lineMetadata[token.map[0]] = 6;
params.lines.forEach(function forLine(line, lineIndex) { lineMetadata[token.map[1] - 1] = 2;
let metadata = 0; for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) {
const match = /^[ ]{0,3}(`{3,}|~{3,})/.exec(line); lineMetadata[i] = 1;
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[lineIndex] = metadata;
}); });
// Find code blocks normally
filterTokens(params, "code_block", function forToken(token) { filterTokens(params, "code_block", function forToken(token) {
for (let i = token.map[0]; i < token.map[1]; i++) { for (let i = token.map[0]; i < token.map[1]; i++) {
lineMetadata[i] = 1; lineMetadata[i] = 1;
} }
}); });
// Find tables normally
filterTokens(params, "table_open", function forToken(token) { filterTokens(params, "table_open", function forToken(token) {
for (let i = token.map[0]; i < token.map[1]; i++) { for (let i = token.map[0]; i < token.map[1]; i++) {
lineMetadata[i] += 8; lineMetadata[i] += 8;
@ -220,12 +214,15 @@ module.exports.forEachLine = function forEachLine(callback) {
// Invoke callback // Invoke callback
tokenCache.params.lines.forEach(function forLine(line, lineIndex) { tokenCache.params.lines.forEach(function forLine(line, lineIndex) {
const metadata = tokenCache.lineMetadata[lineIndex]; const metadata = tokenCache.lineMetadata[lineIndex];
const inCode = !!(metadata & 7);
const onFence = (((metadata & 6) >> 1) || 2) - 2;
const inTable = !!(metadata & 8);
callback( callback(
line, line,
lineIndex, lineIndex,
!!(metadata & 7), inCode,
(((metadata & 6) >> 1) || 2) - 2, onFence,
!!(metadata & 8)); inTable);
}); });
}; };

View file

@ -0,0 +1,6 @@
{
"default": true,
"MD013": {
"code_blocks": false
}
}

View file

@ -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;
```

View file

@ -0,0 +1,13 @@
# Heading
Text
```code```
Text
```javascript
var x = 5;
```
Text