You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
/** internal |
|
* class ParserBlock |
|
* |
|
* Block-level tokenizer. |
|
**/ |
|
'use strict'; |
|
|
|
|
|
var Ruler = require('./ruler'); |
|
|
|
|
|
var _rules = [ |
|
// First 2 params - rule name & source. Secondary array - list of rules, |
|
// which can be terminated by this one. |
|
[ 'table', require('./rules_block/table'), [ 'paragraph', 'reference' ] ], |
|
[ 'code', require('./rules_block/code') ], |
|
[ 'fence', require('./rules_block/fence'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ], |
|
[ 'blockquote', require('./rules_block/blockquote'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ], |
|
[ 'hr', require('./rules_block/hr'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ], |
|
[ 'list', require('./rules_block/list'), [ 'paragraph', 'reference', 'blockquote' ] ], |
|
[ 'reference', require('./rules_block/reference') ], |
|
[ 'html_block', require('./rules_block/html_block'), [ 'paragraph', 'reference', 'blockquote' ] ], |
|
[ 'heading', require('./rules_block/heading'), [ 'paragraph', 'reference', 'blockquote' ] ], |
|
[ 'lheading', require('./rules_block/lheading') ], |
|
[ 'paragraph', require('./rules_block/paragraph') ] |
|
]; |
|
|
|
|
|
/** |
|
* new ParserBlock() |
|
**/ |
|
function ParserBlock() { |
|
/** |
|
* ParserBlock#ruler -> Ruler |
|
* |
|
* [[Ruler]] instance. Keep configuration of block rules. |
|
**/ |
|
this.ruler = new Ruler(); |
|
|
|
for (var i = 0; i < _rules.length; i++) { |
|
this.ruler.push(_rules[i][0], _rules[i][1], { alt: (_rules[i][2] || []).slice() }); |
|
} |
|
} |
|
|
|
|
|
// Generate tokens for input range |
|
// |
|
ParserBlock.prototype.tokenize = function (state, startLine, endLine) { |
|
var ok, i, |
|
rules = this.ruler.getRules(''), |
|
len = rules.length, |
|
line = startLine, |
|
hasEmptyLines = false, |
|
maxNesting = state.md.options.maxNesting; |
|
|
|
while (line < endLine) { |
|
state.line = line = state.skipEmptyLines(line); |
|
if (line >= endLine) { break; } |
|
|
|
// Termination condition for nested calls. |
|
// Nested calls currently used for blockquotes & lists |
|
if (state.sCount[line] < state.blkIndent) { break; } |
|
|
|
// If nesting level exceeded - skip tail to the end. That's not ordinary |
|
// situation and we should not care about content. |
|
if (state.level >= maxNesting) { |
|
state.line = endLine; |
|
break; |
|
} |
|
|
|
// Try all possible rules. |
|
// On success, rule should: |
|
// |
|
// - update `state.line` |
|
// - update `state.tokens` |
|
// - return true |
|
|
|
for (i = 0; i < len; i++) { |
|
ok = rules[i](state, line, endLine, false); |
|
if (ok) { break; } |
|
} |
|
|
|
// set state.tight if we had an empty line before current tag |
|
// i.e. latest empty line should not count |
|
state.tight = !hasEmptyLines; |
|
|
|
// paragraph might "eat" one newline after it in nested lists |
|
if (state.isEmpty(state.line - 1)) { |
|
hasEmptyLines = true; |
|
} |
|
|
|
line = state.line; |
|
|
|
if (line < endLine && state.isEmpty(line)) { |
|
hasEmptyLines = true; |
|
line++; |
|
state.line = line; |
|
} |
|
} |
|
}; |
|
|
|
|
|
/** |
|
* ParserBlock.parse(str, md, env, outTokens) |
|
* |
|
* Process input string and push block tokens into `outTokens` |
|
**/ |
|
ParserBlock.prototype.parse = function (src, md, env, outTokens) { |
|
var state; |
|
|
|
if (!src) { return; } |
|
|
|
state = new this.State(src, md, env, outTokens); |
|
|
|
this.tokenize(state, state.line, state.lineMax); |
|
}; |
|
|
|
|
|
ParserBlock.prototype.State = require('./rules_block/state_block'); |
|
|
|
|
|
module.exports = ParserBlock;
|
|
|