Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed https://markdown-it.github.io/
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.
 
 
 

141 lines
2.5 KiB

// Inline lexer
'use strict';
////////////////////////////////////////////////////////////////////////////////
// Lexer rules
var rules = [];
// Pure text
rules.push(function text(state, str, begin, end) {
state.tokens.push({
type: 'text',
content: str.slice(begin, end).replace(/^ {1,}/mg, '')
});
state.pos = end;
return true;
});
////////////////////////////////////////////////////////////////////////////////
// Lexer class
function functionName(fn) {
var ret = fn.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}
function findByName(self, name) {
for (var i = 0; i < self.rules.length; i++) {
if (functionName(self.rules[i]) === name) {
return i;
}
}
return -1;
}
// Block Lexer class
//
function LexerInline() {
this.rules = [];
for (var i = 0; i < rules.length; i++) {
this.after(null, rules[i]);
}
}
// Replace/delete lexer function
//
LexerInline.prototype.at = function (name, fn) {
var index = findByName(name);
if (index === -1) {
throw new Error('Lexer rule not found: ' + name);
}
if (fn) {
this.rules[index] = fn;
} else {
this.rules = this.rules.slice(0, index).concat(this.rules.slice(index + 1));
}
};
// Add function to lexer chain before one with given name.
// Or add to start, if name not defined
//
LexerInline.prototype.before = function (name, fn) {
if (!name) {
this.rules.unshift(fn);
return;
}
var index = findByName(name);
if (index === -1) {
throw new Error('Lexer rule not found: ' + name);
}
this.rules.splice(index, 0, fn);
};
// Add function to lexer chain after one with given name.
// Or add to end, if name not defined
//
LexerInline.prototype.after = function (name, fn) {
if (!name) {
this.rules.push(fn);
return;
}
var index = findByName(name);
if (index === -1) {
throw new Error('Lexer rule not found: ' + name);
}
this.rules.splice(index + 1, 0, fn);
};
// Generate tokens for input range
//
LexerInline.prototype.tokenize = function (state, str) {
var ok, i,
rules = this.rules,
len = this.rules.length,
pos = 0,
end = str.length;
while (pos < end) {
// Try all possible rules.
// On success, rule should:
//
// - update `state.pos`
// - update `state.tokens`
// - return true
for (i = 0; i < len; i++) {
ok = rules[i](state, str, pos, end);
if (ok) { break; }
}
if (ok) {
pos = state.pos;
continue;
}
}
state.pos = end;
};
module.exports = LexerInline;