Skip to content

Commit

Permalink
Update to markdown-it@5.x API
Browse files Browse the repository at this point in the history
  • Loading branch information
rlidwka committed Sep 30, 2015
1 parent 12efcb2 commit 14cce15
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 116 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,9 @@
2.0.0 / 2015-09-30
------------------

- Markdown-it 5.0.0 support. Use previous version for 4.x.


1.0.0 / 2015-03-12
------------------

Expand Down
206 changes: 92 additions & 114 deletions index.js
@@ -1,142 +1,120 @@
'use strict';


// parse sequence of markers,
// "start" should point at a valid marker
function scanDelims(state, start) {
var pos = start, lastChar, nextChar, count,
isLastWhiteSpace, isLastPunctChar,
isNextWhiteSpace, isNextPunctChar,
can_open = true,
can_close = true,
max = state.posMax,
marker = state.src.charCodeAt(start),
isWhiteSpace = state.md.utils.isWhiteSpace,
isPunctChar = state.md.utils.isPunctChar,
isMdAsciiPunct = state.md.utils.isMdAsciiPunct;

// treat beginning of the line as a whitespace
lastChar = start > 0 ? state.src.charCodeAt(start - 1) : 0x20;

while (pos < max && state.src.charCodeAt(pos) === marker) { pos++; }

if (pos >= max) {
can_open = false;
}
module.exports = function ins_plugin(md) {
// Insert each marker as a separate text token, and add it to delimiter list
//
function tokenize(state, silent) {
var i, scanned, token, len, ch,
start = state.pos,
marker = state.src.charCodeAt(start);

count = pos - start;
if (silent) { return false; }

// treat end of the line as a whitespace
nextChar = pos < max ? state.src.charCodeAt(pos) : 0x20;
if (marker !== 0x2B/* + */) { return false; }

isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
scanned = state.scanDelims(state.pos, true);
len = scanned.length;
ch = String.fromCharCode(marker);

isLastWhiteSpace = isWhiteSpace(lastChar);
isNextWhiteSpace = isWhiteSpace(nextChar);
if (len < 2) { return false; }

if (isNextWhiteSpace) {
can_open = false;
} else if (isNextPunctChar) {
if (!(isLastWhiteSpace || isLastPunctChar)) {
can_open = false;
if (len % 2) {
token = state.push('text', '', 0);
token.content = ch;
len--;
}
}

if (isLastWhiteSpace) {
can_close = false;
} else if (isLastPunctChar) {
if (!(isNextWhiteSpace || isNextPunctChar)) {
can_close = false;
for (i = 0; i < len; i += 2) {
token = state.push('text', '', 0);
token.content = ch + ch;

state.delimiters.push({
marker: marker,
jump: i,
token: state.tokens.length - 1,
level: state.level,
end: -1,
open: scanned.can_open,
close: scanned.can_close
});
}
}

return {
can_open: can_open,
can_close: can_close,
delims: count
};
}


function insert(state, silent) {
var startCount,
count,
tagCount,
found,
stack,
res,
token,
max = state.posMax,
start = state.pos,
marker = state.src.charCodeAt(start);

if (marker !== 0x2B/* + */) { return false; }
if (silent) { return false; } // don't run any pairs in validation mode

res = scanDelims(state, start);
startCount = res.delims;

if (!res.can_open) {
state.pos += startCount;
// Earlier we checked !silent, but this implementation does not need it
state.pending += state.src.slice(start, state.pos);
state.pos += scanned.length;

return true;
}

stack = Math.floor(startCount / 2);
if (stack <= 0) { return false; }
state.pos = start + startCount;

while (state.pos < max) {
if (state.src.charCodeAt(state.pos) === marker) {
res = scanDelims(state, state.pos);
count = res.delims;
tagCount = Math.floor(count / 2);
if (res.can_close) {
if (tagCount >= stack) {
state.pos += count - 2;
found = true;
break;
}
stack -= tagCount;
state.pos += count;

// Walk through delimiter list and replace text tokens with tags
//
function postProcess(state) {
var i, j,
startDelim,
endDelim,
token,
loneMarkers = [],
delimiters = state.delimiters,
max = state.delimiters.length;

for (i = 0; i < max; i++) {
startDelim = delimiters[i];

if (startDelim.marker !== 0x2B/* + */) {
continue;
}

if (res.can_open) { stack += tagCount; }
state.pos += count;
continue;
}
if (startDelim.end === -1) {
continue;
}

state.md.inline.skipToken(state);
}
endDelim = delimiters[startDelim.end];

if (!found) {
// parser failed to find ending tag, so it's not valid emphasis
state.pos = start;
return false;
}
token = state.tokens[startDelim.token];
token.type = 'ins_open';
token.tag = 'ins';
token.nesting = 1;
token.markup = '++';
token.content = '';

// found!
state.posMax = state.pos;
state.pos = start + 2;
token = state.tokens[endDelim.token];
token.type = 'ins_close';
token.tag = 'ins';
token.nesting = -1;
token.markup = '++';
token.content = '';

// Earlier we checked !silent, but this implementation does not need it
token = state.push('ins_open', 'ins', 1);
token.markup = String.fromCharCode(marker) + String.fromCharCode(marker);
if (state.tokens[endDelim.token - 1].type === 'text' &&
state.tokens[endDelim.token - 1].content === '+') {

state.md.inline.tokenize(state);
loneMarkers.push(endDelim.token - 1);
}
}

token = state.push('ins_close', 'ins', -1);
token.markup = String.fromCharCode(marker) + String.fromCharCode(marker);
// If a marker sequence has an odd number of characters, it's splitted
// like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the
// start of the sequence.
//
// So, we have to move all those markers after subsequent s_close tags.
//
while (loneMarkers.length) {
i = loneMarkers.pop();
j = i + 1;

while (j < state.tokens.length && state.tokens[j].type === 'ins_close') {
j++;
}

state.pos = state.posMax + 2;
state.posMax = max;
return true;
}
j--;

if (i !== j) {
token = state.tokens[j];
state.tokens[j] = state.tokens[i];
state.tokens[i] = token;
}
}
}

module.exports = function ins_plugin(md) {
md.inline.ruler.before('emphasis', 'ins', insert);
md.inline.ruler.before('emphasis', 'ins', tokenize);
md.inline.ruler2.before('emphasis', 'ins', postProcess);
};
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -29,7 +29,7 @@
"eslint-plugin-nodeca": "^1.0.0",
"istanbul": "*",
"lodash": "*",
"markdown-it": "4.0.0",
"markdown-it": "^5.0.0",
"markdown-it-testgen": "~0.1.0",
"mocha": "*",
"request": "*",
Expand Down
13 changes: 12 additions & 1 deletion test/fixtures/ins.txt
Expand Up @@ -26,7 +26,7 @@ x ++++foo++++
.
x +++foo+++
.
<p>x <ins>+foo+</ins></p>
<p>x +<ins>foo</ins>+</p>
.


Expand Down Expand Up @@ -108,6 +108,17 @@ test
++</p>
.


.
x ++a ++foo+++++++++++bar++ b++

x ++a ++foo++++++++++++bar++ b++
.
<p>x <ins>a <ins>foo</ins></ins>+++<ins><ins>bar</ins> b</ins></p>
<p>x <ins>a <ins>foo</ins></ins>++++<ins><ins>bar</ins> b</ins></p>
.


From CommonMark test suite, replacing `**` with our marker:

.
Expand Down

0 comments on commit 14cce15

Please sign in to comment.