Skip to content

Instantly share code, notes, and snippets.

@tmcw
Created March 25, 2016 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmcw/a993d269b1fe7efd253f to your computer and use it in GitHub Desktop.
Save tmcw/a993d269b1fe7efd253f to your computer and use it in GitHub Desktop.
var parseLatin = require('parse-latin');
var search = require('nlcst-search');
var toString = require('nlcst-to-string');
var glossary = require('./glossary.json');
/**
* Gross code alert! This particular section gets the job done but is
* not something I'm especially proud of or confident in. Refactors welcome.
*
* @param {Remark} remark - Instance.
* @param {Object?} [options] - Configuration.
* @return {Function} - Transformer.
*/
function glossaryLinker(remark) {
/**
* Transformer.
*
* @param {Node} tree - Root node.
*/
function transformer(tree) {
var linkedTerms = {};
var start = Date.now();
tree.children.filter(function(child) {
return child.type === 'paragraph';
}).forEach(function(node) {
for (var i = node.children.length - 1; i >= 0; i--) {
if (node.children[i].type === 'text') {
var links = [];
var lastEnd, lastStart;
var textValue = node.children[i].value;
search(parseLatin().parse(textValue), glossary, function(nodes, index, parent, pattern) {
console.log(pattern);
return;
if (linkedTerms[pattern] === true) {
return;
} else {
linkedTerms[pattern] = true;
}
// hack to avoid overlapping matches:
// Map Matching API should only match Map Matching API,
// not both that and API
if (lastEnd === nodes[nodes.length - 1].position.end.offset ||
lastStart === nodes[0].position.start.offset) {
return;
}
links.push({
node: node,
start: nodes[0].position.start.offset,
end: nodes[nodes.length - 1].position.end.offset,
text: toString(nodes),
url: glossary[pattern].url,
title: glossary[pattern].summary
});
lastEnd = nodes[nodes.length - 1].position.end.offset;
lastStart = nodes[0].position.start.offset;
});
if (links.length) {
// sort links in order from the start of the phrase
links.sort(function(a, b) {
return a.start - b.start;
});
var replacement = [];
var pointer = 0;
for (var j = 0; j < links.length; j++) {
// if the link doesn't start at the start of the text,
// grab that chunk of text
replacement.push({
type: 'text',
value: textValue.substring(pointer, links[j].end)
});
pointer += links[j].start - pointer;
// then grab the chunk of text used by the link.
replacement.push({
type: 'link',
url: links[j].url,
title: links[j].title,
data: {
htmlAttributes: {
class: 'auto-glossary-link',
rel: 'noreferrer',
target: '_blank'
}
},
children: [{
type: 'text',
value: '?'
}]
});
pointer += links[j].end - links[j].start;
}
replacement.push({
type: 'text',
value: textValue.substring(pointer)
});
node.children.splice.apply(node.children, [i, 1].concat(replacement));
}
}
}
});
return tree;
}
return transformer;
}
module.exports = glossaryLinker;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment