src_aurelia-bodylight-plugin/src/elements/markdown-it-abbr-ext.js
// Enclose abbreviations in <abbr> tags
// in Markdown *[abbr]: abbreviation
// extended to contain more content and link to e.g. wikipedia to more information
// *[CPR]: cardiopulmonary resustitation|cardiopulmonary resustitation is used to safe live|https://en.wikipedia.org/cpr
'use strict';
export default sub_plugin;
//module.exports = function sub_plugin(md) {
function sub_plugin(md) {
var escapeRE = md.utils.escapeRE,
arrayReplaceAt = md.utils.arrayReplaceAt;
// ASCII characters in Cc, Sc, Sm, Sk categories we should terminate on;
// you can check character classes here:
// http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
var OTHER_CHARS = ' \r\n$+<=>^`|~';
var UNICODE_PUNCT_RE = md.utils.lib.ucmicro.P.source;
var UNICODE_SPACE_RE = md.utils.lib.ucmicro.Z.source;
function abbr_def(state, startLine, endLine, silent) {
var label, title, ch, labelStart, labelEnd,
pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
if (pos + 2 >= max) { return false; }
if (state.src.charCodeAt(pos++) !== 0x2A/* * */) { return false; }
if (state.src.charCodeAt(pos++) !== 0x5B/* [ */) { return false; }
labelStart = pos;
for (; pos < max; pos++) {
ch = state.src.charCodeAt(pos);
if (ch === 0x5B /* [ */) {
return false;
} else if (ch === 0x5D /* ] */) {
labelEnd = pos;
break;
} else if (ch === 0x5C /* \ */) {
pos++;
}
}
if (labelEnd < 0 || state.src.charCodeAt(labelEnd + 1) !== 0x3A/* : */) {
return false;
}
if (silent) { return true; }
label = state.src.slice(labelStart, labelEnd).replace(/\\(.)/g, '$1');
var abbrcontent,abbrcontentsplit,datacontent,datawiki;
abbrcontent = state.src.slice(labelEnd + 2, max).trim();
abbrcontentsplit = abbrcontent.split('|'); //content is split by | first is title, second is more content to be shown third is url
title = abbrcontentsplit[0].trim();
datacontent = (abbrcontentsplit.length>1)?abbrcontentsplit[1].trim():'';
datawiki = (abbrcontentsplit.length>2)?abbrcontentsplit[2].trim():'';
if (label.length === 0) { return false; }
if (title.length === 0) { return false; }
if (!state.env.abbreviations) { state.env.abbreviations = {}; }
// prepend ':' to avoid conflict with Object.prototype members
if (typeof state.env.abbreviations[':' + label] === 'undefined') {
state.env.abbreviations[':' + label] = {'title':title,'content':datacontent,'url':datawiki};
}
state.line = startLine + 1;
return true;
}
function abbr_replace(state) {
var i, j, l, tokens, token, text, nodes, pos, reg, m, regText, regSimple,
currentToken,
blockTokens = state.tokens;
if (!state.env.abbreviations) { return; }
regSimple = new RegExp('(?:' +
Object.keys(state.env.abbreviations).map(function (x) {
return x.substr(1);
}).sort(function (a, b) {
return b.length - a.length;
}).map(escapeRE).join('|') +
')');
regText = '(^|' + UNICODE_PUNCT_RE + '|' + UNICODE_SPACE_RE +
'|[' + OTHER_CHARS.split('').map(escapeRE).join('') + '])'
+ '(' + Object.keys(state.env.abbreviations).map(function (x) {
return x.substr(1);
}).sort(function (a, b) {
return b.length - a.length;
}).map(escapeRE).join('|') + ')'
+ '($|' + UNICODE_PUNCT_RE + '|' + UNICODE_SPACE_RE +
'|[' + OTHER_CHARS.split('').map(escapeRE).join('') + '])';
reg = new RegExp(regText, 'g');
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--) {
currentToken = tokens[i];
if (currentToken.type !== 'text') { continue; }
pos = 0;
text = currentToken.content;
reg.lastIndex = 0;
nodes = [];
// fast regexp run to determine whether there are any abbreviated words
// in the current token
if (!regSimple.test(text)) { continue; }
while ((m = reg.exec(text))) {
if (m.index > 0 || m[1].length > 0) {
token = new state.Token('text', '', 0);
token.content = text.slice(pos, m.index + m[1].length);
nodes.push(token);
}
token = new state.Token('abbr_open', 'abbr', 1);
var temp = state.env.abbreviations[':' + m[2]];
token.attrs = [ [ 'title', temp.title],
['data-content',temp.content],
['data-wiki',temp.url] ];
nodes.push(token);
token = new state.Token('text', '', 0);
token.content = m[2];
nodes.push(token);
token = new state.Token('abbr_close', 'abbr', -1);
nodes.push(token);
token = new state.Token('span_open','span',1);
token.attrs = [['class', 'abbr_dialog']]
nodes.push(token);
token = new state.Token('html_inline', '', 0);
token.content = temp.content;
nodes.push(token);
token = new state.Token('br_openclose','br',0);
nodes.push(token);
token = new state.Token('a_open','a',1);
token.attrs = [['src',temp.url]];
nodes.push(token);
token = new state.Token('text','',0);
token.content = temp.url;
nodes.push(token);
token = new state.Token('a_close','a',-1);
nodes.push(token);
token = new state.Token('span_close','span',-1);
nodes.push(token);
reg.lastIndex -= m[3].length;
pos = reg.lastIndex;
}
if (!nodes.length) { continue; }
if (pos < text.length) {
token = new state.Token('text', '', 0);
token.content = text.slice(pos);
nodes.push(token);
}
// replace current node
blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
}
}
}
md.block.ruler.before('reference', 'abbr_def', abbr_def, { alt: [ 'paragraph', 'reference' ] });
md.core.ruler.after('linkify', 'abbr_replace', abbr_replace);
};