diff options
author | Samy Pesse <samypesse@gmail.com> | 2016-04-23 21:10:53 +0200 |
---|---|---|
committer | Samy Pesse <samypesse@gmail.com> | 2016-04-23 21:10:53 +0200 |
commit | a3df6c6f0c1068762f9d48cdff97ab5d4c583082 (patch) | |
tree | e43d732f7676430d0075814e11fcb4372803e9da /lib/output/modifiers/annotateText.js | |
parent | e1fa977b5b1b3c03790de6e2c21ee39ba55d9555 (diff) | |
download | gitbook-a3df6c6f0c1068762f9d48cdff97ab5d4c583082.zip gitbook-a3df6c6f0c1068762f9d48cdff97ab5d4c583082.tar.gz gitbook-a3df6c6f0c1068762f9d48cdff97ab5d4c583082.tar.bz2 |
Add assets inliner modifier for HTML
Diffstat (limited to 'lib/output/modifiers/annotateText.js')
-rw-r--r-- | lib/output/modifiers/annotateText.js | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/output/modifiers/annotateText.js b/lib/output/modifiers/annotateText.js new file mode 100644 index 0000000..2832f91 --- /dev/null +++ b/lib/output/modifiers/annotateText.js @@ -0,0 +1,94 @@ +var escape = require('escape-html'); + +// Selector to ignore +var ANNOTATION_IGNORE = '.no-glossary,code,pre,a,script,h1,h2,h3,h4,h5,h6'; + +function pregQuote( str ) { + return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1'); +} + +function replaceText($, el, search, replace, text_only ) { + return $(el).each(function(){ + var node = this.firstChild, + val, + new_val, + + // Elements to be removed at the end. + remove = []; + + // Only continue if firstChild exists. + if ( node ) { + + // Loop over all childNodes. + while (node) { + + // Only process text nodes. + if ( node.nodeType === 3 ) { + + // The original node value. + val = node.nodeValue; + + // The new value. + new_val = val.replace( search, replace ); + + // Only replace text if the new value is actually different! + if ( new_val !== val ) { + + if ( !text_only && /</.test( new_val ) ) { + // The new value contains HTML, set it in a slower but far more + // robust way. + $(node).before( new_val ); + + // Don't remove the node yet, or the loop will lose its place. + remove.push( node ); + } else { + // The new value contains no HTML, so it can be set in this + // very fast, simple way. + node.nodeValue = new_val; + } + } + } + + node = node.nextSibling; + } + } + + // Time to remove those elements! + if (remove.length) $(remove).remove(); + }); +} + +/** + Annotate text using a list of GlossaryEntry + + @param {List<GlossaryEntry>} + @param {HTMLDom} $ +*/ +function annotateText(entries, $) { + entries.forEach(function(entry) { + var entryId = entry.getID(); + var name = entry.getName(); + var description = entry.getDescription(); + + var searchRegex = new RegExp( '\\b(' + pregQuote(name.toLowerCase()) + ')\\b' , 'gi' ); + + $('*').each(function() { + var $this = $(this); + + if ( + $this.is(ANNOTATION_IGNORE) || + $this.parents(ANNOTATION_IGNORE).length > 0 + ) return; + + replaceText($, this, searchRegex, function(match) { + return '<a href="/GLOSSARY.html#' + entryId + '" ' + + 'class="glossary-term" title="' + escape(description) + '">' + + match + + '</a>'; + }); + }); + + }); +} + +module.exports = annotateText; |