Created
March 25, 2016 13:33
-
-
Save tmcw/a993d269b1fe7efd253f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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