60 lines
1.7 KiB
JavaScript
60 lines
1.7 KiB
JavaScript
/**
|
|
* @param {MarkdownIt} md
|
|
* @param {{alias: Object.<string, string>}} opts
|
|
*/
|
|
function pluginInlineTag(md, opts={}) {
|
|
const alias = opts.alias || {};
|
|
const defaultTag = alias[''] || 'span';
|
|
md.inline.ruler.before('escape', 'inline_tag', (state, silent) => {
|
|
const {src, pos, posMax} = state;
|
|
const c0 = src.charCodeAt(pos);
|
|
let posS;
|
|
let tagName;
|
|
if (c0 === 0x25) { // %
|
|
const posC = src.indexOf('[', pos+1);
|
|
if (posC < 0) return false; // [
|
|
tagName = src.substring(pos+1, posC);
|
|
const atag = alias[tagName];
|
|
if (atag != null) tagName = atag;
|
|
if (!tagName.match(/[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9]?/)) return;
|
|
posS = posC+1;
|
|
} else if (c0 === 0x5b) { // [
|
|
posS = pos+1;
|
|
tagName = defaultTag;
|
|
} else return false;
|
|
// get inner text posMax
|
|
let level = 1;
|
|
let i = posS;
|
|
while (i < posMax) {
|
|
const c = src.charCodeAt(i);
|
|
if (c === 0x5c) i += 2; // \
|
|
else {
|
|
if (c === 0x5b) level++; // [
|
|
else if (c === 0x5d) { // ]
|
|
level--;
|
|
if (level === 0) break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
if (level !== 0) return false;
|
|
const posE = i;
|
|
// []{} without ()
|
|
if (c0 === 0x5b && src.charCodeAt(posE+1) !== 0x7b) return false;
|
|
// parse tag content if not silent
|
|
if (!silent) {
|
|
state.pos = posS;
|
|
state.posMax = posE;
|
|
if (!silent) state.push('tag_open', tagName, 1);
|
|
state.md.inline.tokenize(state, silent);
|
|
if (!silent) state.push('tag_close', tagName, -1);
|
|
// end
|
|
state.posMax = posMax;
|
|
}
|
|
// set state.pos only if silent
|
|
state.pos = posE+1;
|
|
return true;
|
|
});
|
|
};
|
|
|
|
module.exports = pluginInlineTag;
|