summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pesse <samypesse@gmail.com>2016-05-05 11:00:05 +0200
committerSamy Pesse <samypesse@gmail.com>2016-05-05 11:00:05 +0200
commit34947b5e207e84ef43a8194c0ec7bac19dccf709 (patch)
tree06e687700d95590cae678f8bef381e8a62dc0129
parentc621380b664bcbef087df571b662e7a34e098168 (diff)
downloadgitbook-34947b5e207e84ef43a8194c0ec7bac19dccf709.zip
gitbook-34947b5e207e84ef43a8194c0ec7bac19dccf709.tar.gz
gitbook-34947b5e207e84ef43a8194c0ec7bac19dccf709.tar.bz2
Add mode TemplateOutput to represent {content + blocks} from template
-rw-r--r--lib/api/encodeGlobal.js10
-rw-r--r--lib/models/templateBlock.js54
-rw-r--r--lib/models/templateEngine.js4
-rw-r--r--lib/models/templateOutput.js44
-rw-r--r--lib/output/ebook/getPDFTemplate.js4
-rw-r--r--lib/output/ebook/onFinish.js4
-rw-r--r--lib/output/generatePage.js14
-rw-r--r--lib/output/website/onFinish.js4
-rw-r--r--lib/output/website/onPage.js4
-rw-r--r--lib/templating/postRender.js39
-rw-r--r--lib/templating/render.js16
-rw-r--r--lib/templating/renderFile.js2
-rw-r--r--lib/templating/replaceBlocks.js34
13 files changed, 132 insertions, 101 deletions
diff --git a/lib/api/encodeGlobal.js b/lib/api/encodeGlobal.js
index 8144883..1e7df36 100644
--- a/lib/api/encodeGlobal.js
+++ b/lib/api/encodeGlobal.js
@@ -108,6 +108,16 @@ function encodeGlobal(output) {
},
/**
+ Resolve a file from the output root
+
+ @param {String} fileName
+ @return {String}
+ */
+ resolve: function(fileName) {
+ return path.resolve(outputFolder, fileName);
+ },
+
+ /**
Convert a filepath into an url
@return {String}
*/
diff --git a/lib/models/templateBlock.js b/lib/models/templateBlock.js
index 2ec1328..200e048 100644
--- a/lib/models/templateBlock.js
+++ b/lib/models/templateBlock.js
@@ -8,8 +8,6 @@ var TemplateShortcut = require('./templateShortcut');
var NODE_ENDARGS = '%%endargs%%';
-var blockBodies = {};
-
var TemplateBlock = Immutable.Record({
// Name of block, also the start tag
name: String(),
@@ -26,9 +24,6 @@ var TemplateBlock = Immutable.Record({
// List of shortcuts to replace with this block
shortcuts: Immutable.Map(),
- // Function to execute in post processing
- post: null,
-
parse: true
}, 'TemplateBlock');
@@ -36,10 +31,6 @@ TemplateBlock.prototype.getName = function() {
return this.get('name');
};
-TemplateBlock.prototype.getPost = function() {
- return this.get('post');
-};
-
TemplateBlock.prototype.getParse = function() {
return this.get('parse');
};
@@ -85,7 +76,7 @@ TemplateBlock.prototype.getExtensionName = function() {
@return {Nunjucks.Extension}
*/
-TemplateBlock.prototype.toNunjucksExt = function(mainContext) {
+TemplateBlock.prototype.toNunjucksExt = function(mainContext, blocksOutput) {
var that = this;
var name = this.getName();
var endTag = this.getEndTag();
@@ -195,7 +186,7 @@ TemplateBlock.prototype.toNunjucksExt = function(mainContext) {
return that.applyBlock(mainBlock, ctx);
})
.then(function(result) {
- return that.blockResultToHtml(result);
+ return that.blockResultToHtml(result, blocksOutput);
})
.nodeify(callback);
};
@@ -221,19 +212,19 @@ TemplateBlock.prototype.applyBlock = function(inner, context) {
var r = processFn.call(context, inner);
if (Promise.isPromiseAlike(r)) {
- return r.then(this.handleBlockResult.bind(this));
+ return r.then(this.normalizeBlockResult.bind(this));
} else {
- return this.handleBlockResult(r);
+ return this.normalizeBlockResult(r);
}
};
/**
- Handle result from a block process function
+ Normalize result from a block process function
- @param {Object} result
+ @param {Object|String} result
@return {Object}
*/
-TemplateBlock.prototype.handleBlockResult = function(result) {
+TemplateBlock.prototype.normalizeBlockResult = function(result) {
if (is.string(result)) {
result = { body: result };
}
@@ -246,15 +237,17 @@ TemplateBlock.prototype.handleBlockResult = function(result) {
Convert a block result to HTML
@param {Object} result
+ @param {Object} blocksOutput: stored post processing blocks in this object
@return {String}
*/
-TemplateBlock.prototype.blockResultToHtml = function(result) {
+TemplateBlock.prototype.blockResultToHtml = function(result, blocksOutput) {
var parse = this.getParse();
var indexedKey;
- var toIndex = (!parse) || (this.getPost() !== undefined);
+ var toIndex = (!parse) || (result.post !== undefined);
if (toIndex) {
- indexedKey = TemplateBlock.indexBlockResult(result);
+ indexedKey = genKey();
+ blocksOutput[indexedKey] = result;
}
// Parsable block, just return it
@@ -268,29 +261,6 @@ TemplateBlock.prototype.blockResultToHtml = function(result) {
};
/**
- Index a block result, and return the indexed key
-
- @param {Object} blk
- @return {String}
-*/
-TemplateBlock.indexBlockResult = function(blk) {
- var key = genKey();
- blockBodies[key] = blk;
-
- return key;
-};
-
-/**
- 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 243bfc6..5724d55 100644
--- a/lib/models/templateEngine.js
+++ b/lib/models/templateEngine.js
@@ -67,7 +67,7 @@ TemplateEngine.prototype.getBlock = function(name) {
@return {Nunjucks.Environment}
*/
-TemplateEngine.prototype.toNunjucks = function() {
+TemplateEngine.prototype.toNunjucks = function(blocksOutput) {
var loader = this.getLoader();
var blocks = this.getBlocks();
var filters = this.getFilters();
@@ -101,7 +101,7 @@ TemplateEngine.prototype.toNunjucks = function() {
// Add blocks
blocks.forEach(function(block) {
var extName = block.getExtensionName();
- var Ext = block.toNunjucksExt(context);
+ var Ext = block.toNunjucksExt(context, blocksOutput);
env.addExtension(extName, new Ext());
});
diff --git a/lib/models/templateOutput.js b/lib/models/templateOutput.js
new file mode 100644
index 0000000..cd65a05
--- /dev/null
+++ b/lib/models/templateOutput.js
@@ -0,0 +1,44 @@
+var Immutable = require('immutable');
+
+var TemplateOutput = Immutable.Record({
+ // Text content of the template
+ content: String(),
+
+ // Map of blocks to replace / post process
+ blocks: Immutable.Map()
+}, 'TemplateOutput');
+
+TemplateOutput.prototype.getContent = function() {
+ return this.get('content');
+};
+
+TemplateOutput.prototype.getBlocks = function() {
+ return this.get('blocks');
+};
+
+/**
+ Update content of this output
+
+ @param {String} content
+ @return {TemplateContent}
+*/
+TemplateOutput.prototype.setContent = function(content) {
+ return this.set('content', content);
+};
+
+/**
+ Create a TemplateOutput from a text content
+ and an object containing block definition
+
+ @param {String} content
+ @param {Object} blocks
+ @return {TemplateOutput}
+*/
+TemplateOutput.create = function(content, blocks) {
+ return new TemplateOutput({
+ content: content,
+ blocks: Immutable.fromJS(blocks)
+ });
+};
+
+module.exports = TemplateOutput;
diff --git a/lib/output/ebook/getPDFTemplate.js b/lib/output/ebook/getPDFTemplate.js
index f7a450d..354cc29 100644
--- a/lib/output/ebook/getPDFTemplate.js
+++ b/lib/output/ebook/getPDFTemplate.js
@@ -30,8 +30,8 @@ function getPDFTemplate(output, type) {
return Templating.renderFile(engine, 'ebook/' + filePath, context)
// Inline css and assets
- .then(function(html) {
- return Promise.nfcall(juice.juiceResources, html, {
+ .then(function(tplOut) {
+ return Promise.nfcall(juice.juiceResources, tplOut.getContent(), {
webResources: {
relativeTo: outputRoot
}
diff --git a/lib/output/ebook/onFinish.js b/lib/output/ebook/onFinish.js
index f365bcb..7f21548 100644
--- a/lib/output/ebook/onFinish.js
+++ b/lib/output/ebook/onFinish.js
@@ -29,8 +29,8 @@ function writeSummary(output) {
return Templating.renderFile(engine, prefix + '/summary.html', context)
// Write it to the disk
- .then(function(html) {
- return writeFile(output, filePath, html);
+ .then(function(tplOut) {
+ return writeFile(output, filePath, tplOut.getContent());
});
}
diff --git a/lib/output/generatePage.js b/lib/output/generatePage.js
index 27b4eb1..7e4e454 100644
--- a/lib/output/generatePage.js
+++ b/lib/output/generatePage.js
@@ -47,12 +47,18 @@ function generatePage(output, page) {
return Templating.render(engine, filePath, content, context);
})
- // Render page using parser (markdown -> HTML)
- .then(parser.parsePage.bind(parser)).get('content')
+ .then(function(output) {
+ var content = output.getContent();
+
+ return parser.parsePage(content)
+ .then(function(result) {
+ return output.setContent(result.content);
+ });
+ })
// Post processing for templating syntax
- .then(function(content) {
- return Templating.postRender(engine, content);
+ .then(function(output) {
+ return Templating.postRender(engine, output);
})
// Return new page
diff --git a/lib/output/website/onFinish.js b/lib/output/website/onFinish.js
index e3560e2..5267458 100644
--- a/lib/output/website/onFinish.js
+++ b/lib/output/website/onFinish.js
@@ -27,8 +27,8 @@ function onFinish(output) {
return Templating.renderFile(engine, prefix + '/languages.html', context)
// Write it to the disk
- .then(function(html) {
- return writeFile(output, filePath, html);
+ .then(function(tplOut) {
+ return writeFile(output, filePath, tplOut.getContent());
});
}
diff --git a/lib/output/website/onPage.js b/lib/output/website/onPage.js
index 16a5c39..14c7b22 100644
--- a/lib/output/website/onPage.js
+++ b/lib/output/website/onPage.js
@@ -67,8 +67,8 @@ function onPage(output, page) {
return Templating.renderFile(engine, prefix + '/page.html', context)
// Write it to the disk
- .then(function(html) {
- return writeFile(output, filePath, html);
+ .then(function(tplOut) {
+ return writeFile(output, filePath, tplOut.getContent());
});
});
}
diff --git a/lib/templating/postRender.js b/lib/templating/postRender.js
index c4e82a5..2662814 100644
--- a/lib/templating/postRender.js
+++ b/lib/templating/postRender.js
@@ -1,5 +1,27 @@
var Promise = require('../utils/promise');
-var replaceBlocks = require('./replaceBlocks');
+
+
+/**
+ 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, blocks) {
+ var newContent = content.replace(/\{\{\-\%([\s\S]+?)\%\-\}\}/g, function(match, key) {
+ var replacedWith = match;
+
+ var block = blocks.get(key);
+ if (block) {
+ replacedWith = replaceBlocks(block.get('body'), blocks);
+ }
+
+ return replacedWith;
+ });
+
+ return newContent;
+}
/**
Post render a template:
@@ -7,22 +29,25 @@ var replaceBlocks = require('./replaceBlocks');
- Replace block content
@param {TemplateEngine} engine
- @param {String} content
+ @param {TemplateOutput} content
@return {Promise<String>}
*/
-function postRender(engine, content) {
+function postRender(engine, output) {
+ var content = output.getContent();
+ var blocks = output.getBlocks();
+
var result = replaceBlocks(content);
- return Promise.forEach(result.blocks, function(blockType) {
- var block = engine.getBlock(blockType);
- var post = block.getPost();
+ return Promise.forEach(blocks, function(block) {
+ var post = block.get('post');
+
if (!post) {
return;
}
return post();
})
- .thenResolve(result.content);
+ .thenResolve(result);
}
module.exports = postRender;
diff --git a/lib/templating/render.js b/lib/templating/render.js
index 22c0dc4..584890a 100644
--- a/lib/templating/render.js
+++ b/lib/templating/render.js
@@ -1,6 +1,6 @@
var Promise = require('../utils/promise');
var timing = require('../utils/timing');
-
+var TemplateOutput = require('../models/templateOutput');
var replaceShortcuts = require('./replaceShortcuts');
/**
@@ -10,16 +10,23 @@ var replaceShortcuts = require('./replaceShortcuts');
@param {String} filePath
@param {String} content
@param {Object} context
- @return {Promise<String>}
+ @return {Promise<TemplateOutput>}
*/
function renderTemplate(engine, filePath, content, context) {
context = context || {};
- var env = engine.toNunjucks();
+ // Mutable objects to contains all blocks requiring post-processing
+ var blocks = {};
+
+ // Create nunjucks environment
+ var env = engine.toNunjucks(blocks);
+
+ // Replace shortcuts from plugin's blocks
content = replaceShortcuts(engine, filePath, content);
return timing.measure(
'template.render',
+
Promise.nfcall(
env.renderString.bind(env),
content,
@@ -28,6 +35,9 @@ function renderTemplate(engine, filePath, content, context) {
path: filePath
}
)
+ .then(function(content) {
+ return TemplateOutput.create(content, blocks);
+ })
);
}
diff --git a/lib/templating/renderFile.js b/lib/templating/renderFile.js
index 9b74e5b..185bec1 100644
--- a/lib/templating/renderFile.js
+++ b/lib/templating/renderFile.js
@@ -8,7 +8,7 @@ var render = require('./render');
@param {TemplateEngine} engine
@param {String} filePath
@param {Object} context
- @return {Promise<String>}
+ @return {Promise<TemplateOutput>}
*/
function renderTemplateFile(engine, filePath, context) {
var loader = engine.getLoader();
diff --git a/lib/templating/replaceBlocks.js b/lib/templating/replaceBlocks.js
deleted file mode 100644
index 4b1c37f..0000000
--- a/lib/templating/replaceBlocks.js
+++ /dev/null
@@ -1,34 +0,0 @@
-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;