diff options
author | Samy Pessé <samypesse@gmail.com> | 2015-01-22 19:09:03 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2015-01-22 19:09:03 +0100 |
commit | 9e172549d162ce6ec2d0e454db997418a2b9795f (patch) | |
tree | e31811c32a9b3d418a7d70a66a84d5caeb6f7175 | |
parent | 0ba36c6f4ed316cc157c701abe4728d64da231b4 (diff) | |
download | gitbook-9e172549d162ce6ec2d0e454db997418a2b9795f.zip gitbook-9e172549d162ce6ec2d0e454db997418a2b9795f.tar.gz gitbook-9e172549d162ce6ec2d0e454db997418a2b9795f.tar.bz2 |
Mark glossary terms in html parsed
-rw-r--r-- | lib/book.js | 3 | ||||
-rw-r--r-- | lib/utils/page.js | 71 | ||||
-rw-r--r-- | test/fixtures/test0/GLOSSARY.md | 6 | ||||
-rw-r--r-- | test/json.js | 11 |
4 files changed, 88 insertions, 3 deletions
diff --git a/lib/book.js b/lib/book.js index 639adef..036844f 100644 --- a/lib/book.js +++ b/lib/book.js @@ -327,7 +327,8 @@ Book.prototype.parsePage = function(filename) { page.sections = pageUtil.normalize(page.sections, { navigation: that.navigation, base: path.dirname(filename) || './', - output: path.dirname(filename) || './' + output: path.dirname(filename) || './', + glossary: that.glossary }); return page; diff --git a/lib/utils/page.js b/lib/utils/page.js index 00e4757..8fa704d 100644 --- a/lib/utils/page.js +++ b/lib/utils/page.js @@ -4,6 +4,60 @@ var cheerio = require('cheerio'); var links = require('./links'); +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. + do { + // 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; + } + } + } + + } while ( node = node.nextSibling ); + } + + // Time to remove those elements! + remove.length && $(remove).remove(); + }); +}; + +function pregQuote( str ) { + return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"); +}; + + // Adapt an html snippet to be relative to a base folder function normalizeHtml(src, options) { var $ = cheerio.load(src); @@ -38,9 +92,21 @@ function normalizeHtml(src, options) { $(this).attr("href", href); }); + // Replace glossayr terms + _.each(options.glossary, function(term) { + var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' ); + + $("*").each(function() { + replaceText($, this, r, function(match) { + return "<span class='glossary-term' data-glossary-term='"+term.id+"' title='"+term.description+"'>"+match+"</span>"; + }); + }); + }); + return $.html(); }; + // Adapt page content to be relative to a base folder function normalizePage(sections, options) { options = _.defaults(options || {}, { @@ -51,7 +117,10 @@ function normalizePage(sections, options) { base: "./", // Directory parent from the html output - output: "./" + output: "./", + + // Glossary terms + glossary: [] }); return _.map(sections, function(section) { diff --git a/test/fixtures/test0/GLOSSARY.md b/test/fixtures/test0/GLOSSARY.md new file mode 100644 index 0000000..ad07f86 --- /dev/null +++ b/test/fixtures/test0/GLOSSARY.md @@ -0,0 +1,6 @@ +# Glossary + +## Description + +This is the dexcription of a description. + diff --git a/test/json.js b/test/json.js index 1af2517..1620d00 100644 --- a/test/json.js +++ b/test/json.js @@ -5,7 +5,16 @@ var assert = require('assert'); var fs = require("fs"); describe('JSON generator', function () { - it('should correctly generate a book to json', function(done) { + it('should correctly generate a book to json with glossary', function(done) { + testGeneration(books[0], "json", function(output) { + assert(fs.existsSync(path.join(output, "README.json"))); + + var readme = JSON.parse(fs.readFileSync(path.join(output, "README.json"))); + assert(readme.sections[0].content.indexOf('class="glossary-term"') > 0); + }, done); + }); + + it('should correctly generate a book to json with sub folders', function(done) { testGeneration(books[1], "json", function(output) { assert(!fs.existsSync(path.join(output, "README.json"))); assert(fs.existsSync(path.join(output, "intro.json"))); |