Skip to content

Commit

Permalink
Fix backtick algorithm
Browse files Browse the repository at this point in the history
now it more closely matches one in `cmark`
  • Loading branch information
rlidwka committed Nov 20, 2020
1 parent b1651b1 commit fece91e
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 31 deletions.
51 changes: 20 additions & 31 deletions lib/rules_inline/backticks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,8 @@
'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) {
var start, max, marker, matchStart, matchEnd, startLength, endLength,
var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,
pos = state.pos,
ch = state.src.charCodeAt(pos);

Expand All @@ -27,17 +18,11 @@ module.exports = function backtick(state, silent) {
while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }

marker = state.src.slice(start, pos);
startLength = marker.length;

// Look for required marker length in the cache first
if (state.backticks[startLength] && state.backticks[startLength] > start) {
if (state.backticks[startLength] === Infinity) {
if (!silent) state.pending += marker;
state.pos += startLength;
} else {
if (!silent) addCodeToken(state, marker, pos, state.backticks[startLength]);
state.pos = matchEnd;
}
openerLength = marker.length;

if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) {
if (!silent) state.pending += marker;
state.pos += openerLength;
return true;
}

Expand All @@ -50,27 +35,31 @@ module.exports = function backtick(state, silent) {
// scan marker length
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.
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;
return true;
}

// Some different length found, put it in cache just in case
if (!state.backticks[endLength] || state.backticks[endLength] <= start) {
state.backticks[endLength] = matchStart;
}
// Some different length found, put it in cache as upper limit of where closer can be found
state.backticks[closerLength] = 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) {
state.backticks[startLength] = Infinity;
state.backticksScanned = true;
}
}

if (!silent) state.pending += marker;
state.pos += startLength;
state.pos += openerLength;
return true;
};
1 change: 1 addition & 0 deletions lib/rules_inline/state_inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function StateInline(src, md, env, outTokens) {

// backtick length => last seen position
this.backticks = {};
this.backticksScanned = false;
}


Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/markdown-it/commonmark_extras.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
.
*&*
Expand Down

0 comments on commit fece91e

Please sign in to comment.