Browse Source

Fix backtick algorithm

now it more closely matches one in `cmark`
pull/745/head
Alex Kocharin 4 years ago
parent
commit
fece91e265
  1. 47
      lib/rules_inline/backticks.js
  2. 1
      lib/rules_inline/state_inline.js
  3. 8
      test/fixtures/markdown-it/commonmark_extras.txt

47
lib/rules_inline/backticks.js

@ -3,17 +3,8 @@
'use strict'; 'use strict';
function addCodeToken(state, marker, pos, matchStart) {
var token = state.push('code_inline', 'code', 0);
token.markup = marker;
token.content = state.src.slice(pos, matchStart)
.replace(/\n/g, ' ')
.replace(/^ (.+) $/, '$1');
}
module.exports = function backtick(state, silent) { module.exports = function backtick(state, silent) {
var start, max, marker, matchStart, matchEnd, startLength, endLength, var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,
pos = state.pos, pos = state.pos,
ch = state.src.charCodeAt(pos); ch = state.src.charCodeAt(pos);
@ -27,17 +18,11 @@ module.exports = function backtick(state, silent) {
while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; } while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }
marker = state.src.slice(start, pos); marker = state.src.slice(start, pos);
startLength = marker.length; openerLength = marker.length;
// Look for required marker length in the cache first if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) {
if (state.backticks[startLength] && state.backticks[startLength] > start) {
if (state.backticks[startLength] === Infinity) {
if (!silent) state.pending += marker; if (!silent) state.pending += marker;
state.pos += startLength; state.pos += openerLength;
} else {
if (!silent) addCodeToken(state, marker, pos, state.backticks[startLength]);
state.pos = matchEnd;
}
return true; return true;
} }
@ -50,27 +35,31 @@ module.exports = function backtick(state, silent) {
// scan marker length // scan marker length
while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; } while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }
endLength = matchEnd - matchStart; closerLength = matchEnd - matchStart;
if (endLength === marker.length) { if (closerLength === openerLength) {
// Found matching closer length. // Found matching closer length.
if (!silent) addCodeToken(state, marker, pos, matchStart); if (!silent) {
token = state.push('code_inline', 'code', 0);
token.markup = marker;
token.content = state.src.slice(pos, matchStart)
.replace(/\n/g, ' ')
.replace(/^ (.+) $/, '$1');
}
state.pos = matchEnd; state.pos = matchEnd;
return true; return true;
} }
// Some different length found, put it in cache just in case // Some different length found, put it in cache as upper limit of where closer can be found
if (!state.backticks[endLength] || state.backticks[endLength] <= start) { state.backticks[closerLength] = matchStart;
state.backticks[endLength] = matchStart;
}
// Scanned through the end, didn't find anything. Mark "no matches" for this length; // Scanned through the end, didn't find anything
if (matchEnd >= max) { if (matchEnd >= max) {
state.backticks[startLength] = Infinity; state.backticksScanned = true;
} }
} }
if (!silent) state.pending += marker; if (!silent) state.pending += marker;
state.pos += startLength; state.pos += openerLength;
return true; return true;
}; };

1
lib/rules_inline/state_inline.js

@ -34,6 +34,7 @@ function StateInline(src, md, env, outTokens) {
// backtick length => last seen position // backtick length => last seen position
this.backticks = {}; this.backticks = {};
this.backticksScanned = false;
} }

8
test/fixtures/markdown-it/commonmark_extras.txt

@ -304,6 +304,14 @@ Coverage. Unpaired nested backtick (silent mode)
. .
Coverage. Should continue scanning after closing "```" despite cache
.
```aaa``bbb``ccc```ddd``eee``
.
<p><code>aaa``bbb``ccc</code>ddd<code>eee</code></p>
.
Coverage. Entities. Coverage. Entities.
. .
*&* *&*

Loading…
Cancel
Save