summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-04-25 13:52:56 +0200
committerSamy Pessé <samypesse@gmail.com>2016-04-25 13:52:56 +0200
commit4aed2cf65240abb26384d7d86ccb27b171e6bb9a (patch)
tree949ede45c93c37215c44bd1b190248d7669501b0 /lib
parent244fb0ca28f29ac429f58e0e885d21cc6c40beba (diff)
downloadgitbook-4aed2cf65240abb26384d7d86ccb27b171e6bb9a.zip
gitbook-4aed2cf65240abb26384d7d86ccb27b171e6bb9a.tar.gz
gitbook-4aed2cf65240abb26384d7d86ccb27b171e6bb9a.tar.bz2
Add post processing for templates
Diffstat (limited to 'lib')
-rw-r--r--lib/models/templateBlock.js23
-rw-r--r--lib/models/templateEngine.js13
-rw-r--r--lib/output/generatePage.js7
-rw-r--r--lib/templating/index.js3
-rw-r--r--lib/templating/postRender.js28
-rw-r--r--lib/templating/replaceBlocks.js34
6 files changed, 106 insertions, 2 deletions
diff --git a/lib/models/templateBlock.js b/lib/models/templateBlock.js
index cce636e..4094b89 100644
--- a/lib/models/templateBlock.js
+++ b/lib/models/templateBlock.js
@@ -9,12 +9,24 @@ var NODE_ENDARGS = '%%endargs%%';
var blockBodies = {};
var TemplateBlock = Immutable.Record({
+ // Name of block, also the start tag
name: String(),
+
+ // End tag, default to "end<name>"
end: String(),
+
+ // Function to process the block content
process: Function(),
+
+ // List of String, for inner block tags
blocks: Immutable.List(),
+
+ // List of shortcuts to replace with this block
shortcuts: Immutable.List(),
+
+ // Function to execute in post processing
post: null,
+
parse: true
}, 'TemplateBlock');
@@ -208,6 +220,7 @@ TemplateBlock.prototype.handleBlockResult = function(result) {
if (is.string(result)) {
result = { body: result };
}
+ result.name = this.getName();
return result;
};
@@ -251,6 +264,16 @@ TemplateBlock.indexBlockResult = function(blk) {
};
/**
+ Get a block results indexed for a specific key
+
+ @param {String} key
+ @return {Object|undefined}
+*/
+TemplateBlock.getBlockResultByKey = function(key) {
+ return blockBodies[key];
+};
+
+/**
Create a template block from a function or an object
@param {String} blockName
diff --git a/lib/models/templateEngine.js b/lib/models/templateEngine.js
index 9a18bd4..28322ea 100644
--- a/lib/models/templateEngine.js
+++ b/lib/models/templateEngine.js
@@ -43,6 +43,19 @@ TemplateEngine.prototype.getContext = function() {
};
/**
+ Return a block by its name (or undefined)
+
+ @param {String} name
+ @return {TemplateBlock}
+*/
+TemplateEngine.prototype.getBlock = function(name) {
+ var blocks = this.getBlocks();
+ return blocks.find(function(block) {
+ return block.getName() === name;
+ });
+};
+
+/**
Return a nunjucks environment from this configuration
@return {Nunjucks.Environment}
diff --git a/lib/output/generatePage.js b/lib/output/generatePage.js
index 4507f2e..113bf22 100644
--- a/lib/output/generatePage.js
+++ b/lib/output/generatePage.js
@@ -14,6 +14,7 @@ var createTemplateEngine = require('./createTemplateEngine');
*/
function generatePage(output, page) {
var book = output.getBook();
+ var engine = createTemplateEngine(output);
return Parse.parsePage(book, page)
.then(function(resultPage) {
@@ -34,13 +35,17 @@ function generatePage(output, page) {
// Render templating syntax
.then(function(content) {
- var engine = createTemplateEngine(output);
return Templating.render(engine, filePath, content);
})
// Render page using parser (markdown -> HTML)
.then(parser.page).get('content')
+ // Post processing for templating syntax
+ .then(function(content) {
+ return Templating.postRender(engine, content);
+ })
+
// Return new page
.then(function(content) {
return resultPage.set('content', content);
diff --git a/lib/templating/index.js b/lib/templating/index.js
index 312146a..3a8f989 100644
--- a/lib/templating/index.js
+++ b/lib/templating/index.js
@@ -1,4 +1,5 @@
module.exports = {
- render: require('./render')
+ render: require('./render'),
+ postRender: require('./postRender')
};
diff --git a/lib/templating/postRender.js b/lib/templating/postRender.js
new file mode 100644
index 0000000..6928e82
--- /dev/null
+++ b/lib/templating/postRender.js
@@ -0,0 +1,28 @@
+var Promise = require('../utils/promise');
+var replaceBlocks = require('./replaceBlocks');
+
+/**
+ Post render a template:
+ - Execute "post" for blocks
+ - Replace block content
+
+ @param {TemplateEngine} engine
+ @param {String} content
+ @return {Promise<String>}
+*/
+function postRender(engine, content) {
+ var result = replaceBlocks(content);
+
+ return Promise.forEach(result.blocks, function(blockType) {
+ var block = engine.getBlock();
+ var post = block.getPost();
+ if (!post) {
+ return;
+ }
+
+ return post();
+ })
+ .thenResolve(result.content);
+}
+
+module.exports = postRender;
diff --git a/lib/templating/replaceBlocks.js b/lib/templating/replaceBlocks.js
new file mode 100644
index 0000000..4b1c37f
--- /dev/null
+++ b/lib/templating/replaceBlocks.js
@@ -0,0 +1,34 @@
+var Immutable = require('immutable');
+var TemplateBlock = require('../models/templateBlock');
+
+/**
+ Replace position markers of blocks by body after processing
+ This is done to avoid that markdown/asciidoc processer parse the block content
+
+ @param {String} content
+ @return {Object} {blocks: Set, content: String}
+*/
+function replaceBlocks(content) {
+ var blockTypes = new Immutable.Set();
+ var newContent = content.replace(/\{\{\-\%([\s\S]+?)\%\-\}\}/g, function(match, key) {
+ var replacedWith = match;
+
+ var block = TemplateBlock.getBlockResultByKey(key);
+ if (block) {
+ var result = replaceBlocks(block.body);
+
+ blockTypes = blockTypes.add(block.name);
+ blockTypes = blockTypes.concat(result.blocks);
+ replacedWith = result.content;
+ }
+
+ return replacedWith;
+ });
+
+ return {
+ content: newContent,
+ blocks: blockTypes
+ };
+}
+
+module.exports = replaceBlocks;