|
|
@ -12,8 +12,7 @@ var skipSpaces = require('../helpers').skipSpaces; |
|
|
|
function skipBulletListMarker(state, startLine) { |
|
|
|
var marker, pos, max; |
|
|
|
|
|
|
|
|
|
|
|
if (state.tShift[startLine] > 3) { return -1; } |
|
|
|
if (state.tShift[startLine] - state.blkIndent > 3) { return -1; } |
|
|
|
|
|
|
|
pos = state.bMarks[startLine] + state.tShift[startLine]; |
|
|
|
max = state.eMarks[startLine]; |
|
|
@ -36,7 +35,7 @@ function skipBulletListMarker(state, startLine) { |
|
|
|
return pos; |
|
|
|
} |
|
|
|
|
|
|
|
// Search `\d+\.[\n ]`, returns next pos arter marker on success
|
|
|
|
// Search `\d+[.)][\n ]`, returns next pos arter marker on success
|
|
|
|
// or -1 on fail.
|
|
|
|
function skipOrderedListMarker(state, startLine) { |
|
|
|
var ch, |
|
|
@ -79,18 +78,16 @@ function skipOrderedListMarker(state, startLine) { |
|
|
|
module.exports = function list(state, startLine, endLine, silent) { |
|
|
|
var nextLine, |
|
|
|
indent, |
|
|
|
oldIndent, |
|
|
|
oldTight, |
|
|
|
start, |
|
|
|
posAfterMarker, |
|
|
|
max, |
|
|
|
indentAfterMarker, |
|
|
|
markerValue, |
|
|
|
isOrdered, |
|
|
|
lastLine, |
|
|
|
subState, |
|
|
|
subString, |
|
|
|
contentStart, |
|
|
|
listTokIdx, |
|
|
|
lineMax, |
|
|
|
endOfList; |
|
|
|
//rules_named = state.lexerBlock.rules_named;
|
|
|
|
|
|
|
@ -131,10 +128,10 @@ module.exports = function list(state, startLine, endLine, silent) { |
|
|
|
//
|
|
|
|
|
|
|
|
nextLine = startLine; |
|
|
|
lineMax = state.lineMax; |
|
|
|
endOfList = false; |
|
|
|
|
|
|
|
while (nextLine < endLine && !endOfList) { |
|
|
|
if (state.tShift[startLine] < state.blkIndent) { return -1; } |
|
|
|
if (isOrdered) { |
|
|
|
posAfterMarker = skipOrderedListMarker(state, nextLine); |
|
|
|
if (posAfterMarker < 0) { break; } |
|
|
@ -165,68 +162,39 @@ module.exports = function list(state, startLine, endLine, silent) { |
|
|
|
// ^^^^^ - calculating total length of this thing
|
|
|
|
indent = (posAfterMarker - state.bMarks[nextLine]) + indentAfterMarker; |
|
|
|
|
|
|
|
//
|
|
|
|
// Scan lines inside list items
|
|
|
|
//
|
|
|
|
lastLine = startLine; |
|
|
|
|
|
|
|
// Run sublexer & write tokens
|
|
|
|
state.tokens.push({ type: 'list_item_open' }); |
|
|
|
|
|
|
|
nextLine++; |
|
|
|
for (;;) { |
|
|
|
// if this line is indented more than with N spaces,
|
|
|
|
// it's the new paragraph of the same list item
|
|
|
|
if (nextLine < lineMax) { |
|
|
|
if (isEmpty(state, nextLine)) { |
|
|
|
nextLine++; |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (state.tShift[nextLine] >= indent) { |
|
|
|
if (nextLine < endLine) { lastLine = nextLine; } |
|
|
|
nextLine++; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (lastLine < 0) { break; } |
|
|
|
oldIndent = state.blkIndent; |
|
|
|
oldTight = state.tight; |
|
|
|
state.blkIndent = state.tShift[startLine] = indent; |
|
|
|
|
|
|
|
subString = state.src.slice(contentStart, state.eMarks[lastLine]) |
|
|
|
.replace(RegExp('^ {' + indent + '}', 'mg'), ''); |
|
|
|
if (lastLine < lineMax) { |
|
|
|
// TODO: we should slice up to next empty line, not up to the end of the document
|
|
|
|
// (or even better - up to the next valid token)
|
|
|
|
//
|
|
|
|
// This has no impact on the algorithm except for performance
|
|
|
|
subString += state.src.slice(state.eMarks[lastLine]); |
|
|
|
} |
|
|
|
state.lexerBlock.tokenize(state, startLine, endLine, true); |
|
|
|
|
|
|
|
// If any of list item is loose, mark list as loose
|
|
|
|
if (!state.tight || isEmpty(state, state.line - 1)) { |
|
|
|
state.tokens[listTokIdx].tight = false; |
|
|
|
} |
|
|
|
|
|
|
|
subState = state.clone(subString); |
|
|
|
state.lexerBlock.tokenize(subState, 0, lastLine - startLine + 1, true); |
|
|
|
nextLine = startLine = subState.line + startLine; |
|
|
|
lastLine = -1; |
|
|
|
contentStart = state.eMarks[startLine]; |
|
|
|
state.blkIndent = state.tShift[startLine] = oldIndent; |
|
|
|
state.tight = oldTight; |
|
|
|
|
|
|
|
// TODO: need to detect loose type.
|
|
|
|
// Problem: blocks. separated by empty lines can be member of sublists.
|
|
|
|
state.tokens.push({ type: 'list_item_close' }); |
|
|
|
|
|
|
|
// If any of list item is loose, mark list as loose
|
|
|
|
if (!subState.tight) { |
|
|
|
state.tokens[listTokIdx].tight = false; |
|
|
|
} |
|
|
|
nextLine = startLine = state.line; |
|
|
|
contentStart = state.bMarks[startLine]; |
|
|
|
|
|
|
|
if (nextLine >= endLine) { break; } |
|
|
|
if (nextLine >= endLine) { break; } |
|
|
|
|
|
|
|
if (isEmpty(state, nextLine)) { |
|
|
|
nextLine++; |
|
|
|
if (nextLine >= endLine || isEmpty(state, nextLine)) { |
|
|
|
// two newlines end the list
|
|
|
|
break; |
|
|
|
} |
|
|
|
if (isEmpty(state, nextLine)) { |
|
|
|
nextLine++; |
|
|
|
if (nextLine >= endLine || isEmpty(state, nextLine)) { |
|
|
|
// two newlines end the list
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
state.tokens.push({ type: 'list_item_close' }); |
|
|
|
} |
|
|
|
|
|
|
|
// Finilize list
|
|
|
|