|
|
|
// Enclose abbreviations in <abbr> tags
|
|
|
|
//
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
var PUNCT_CHARS = ' \n()[]\'".,!?-';
|
|
|
|
|
|
|
|
|
|
|
|
// from Google closure library
|
|
|
|
// http://closure-library.googlecode.com/git-history/docs/local_closure_goog_string_string.js.source.html#line1021
|
|
|
|
function regEscape(s) {
|
|
|
|
return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = function abbr2(state) {
|
|
|
|
var i, j, l, tokens, token, text, nodes, pos, level, reg, m, regText,
|
|
|
|
blockTokens = state.tokens;
|
|
|
|
|
|
|
|
if (!state.env.abbreviations) { return; }
|
|
|
|
if (!state.env.abbrRegExp) {
|
|
|
|
regText = '(^|[' + PUNCT_CHARS.split('').map(regEscape).join('') + '])'
|
|
|
|
+ '(' + Object.keys(state.env.abbreviations).map(function (x) {
|
|
|
|
return x.substr(1);
|
|
|
|
}).sort(function (a, b) {
|
|
|
|
return b.length - a.length;
|
|
|
|
}).map(regEscape).join('|') + ')'
|
|
|
|
+ '($|[' + PUNCT_CHARS.split('').map(regEscape).join('') + '])';
|
|
|
|
state.env.abbrRegExp = new RegExp(regText, 'g');
|
|
|
|
}
|
|
|
|
reg = state.env.abbrRegExp;
|
|
|
|
|
|
|
|
for (j = 0, l = blockTokens.length; j < l; j++) {
|
|
|
|
if (blockTokens[j].type !== 'inline') { continue; }
|
|
|
|
tokens = blockTokens[j].children;
|
|
|
|
|
|
|
|
// We scan from the end, to keep position when new tags added.
|
|
|
|
for (i = tokens.length - 1; i >= 0; i--) {
|
|
|
|
token = tokens[i];
|
|
|
|
if (token.type !== 'text') { continue; }
|
|
|
|
|
|
|
|
pos = 0;
|
|
|
|
text = token.content;
|
|
|
|
reg.lastIndex = 0;
|
|
|
|
level = token.level;
|
|
|
|
nodes = [];
|
|
|
|
|
|
|
|
while ((m = reg.exec(text))) {
|
|
|
|
if (reg.lastIndex > pos) {
|
|
|
|
nodes.push({
|
|
|
|
type: 'text',
|
|
|
|
content: text.slice(pos, m.index + m[1].length),
|
|
|
|
level: level
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
nodes.push({
|
|
|
|
type: 'abbr_open',
|
|
|
|
title: state.env.abbreviations[':' + m[2]],
|
|
|
|
level: level++
|
|
|
|
});
|
|
|
|
nodes.push({
|
|
|
|
type: 'text',
|
|
|
|
content: m[2],
|
|
|
|
level: level
|
|
|
|
});
|
|
|
|
nodes.push({
|
|
|
|
type: 'abbr_close',
|
|
|
|
level: --level
|
|
|
|
});
|
|
|
|
pos = reg.lastIndex - m[3].length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nodes.length) { continue; }
|
|
|
|
|
|
|
|
if (pos < text.length) {
|
|
|
|
nodes.push({
|
|
|
|
type: 'text',
|
|
|
|
content: text.slice(pos),
|
|
|
|
level: level
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// replace current node
|
|
|
|
blockTokens[j].children = tokens = [].concat(tokens.slice(0, i), nodes, tokens.slice(i + 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|