summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/book.js3
-rw-r--r--lib/utils/page.js71
-rw-r--r--test/fixtures/test0/GLOSSARY.md6
-rw-r--r--test/json.js11
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")));