summaryrefslogtreecommitdiffstats
path: root/lib/templating
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-04-25 14:44:49 +0200
committerSamy Pessé <samypesse@gmail.com>2016-04-25 14:44:49 +0200
commit4552ccd7d76a1bf958481e24a695dd3b68e6c232 (patch)
treed96ca1329846062007700b6a28d696f0f10f9e18 /lib/templating
parent525bcd8295f72ffa09d485f86c7adea2187cde55 (diff)
downloadgitbook-4552ccd7d76a1bf958481e24a695dd3b68e6c232.zip
gitbook-4552ccd7d76a1bf958481e24a695dd3b68e6c232.tar.gz
gitbook-4552ccd7d76a1bf958481e24a695dd3b68e6c232.tar.bz2
Add loader for themes
Diffstat (limited to 'lib/templating')
-rw-r--r--lib/templating/index.js3
-rw-r--r--lib/templating/themesLoader.js117
2 files changed, 119 insertions, 1 deletions
diff --git a/lib/templating/index.js b/lib/templating/index.js
index 4cdf6ef..a33965d 100644
--- a/lib/templating/index.js
+++ b/lib/templating/index.js
@@ -4,5 +4,6 @@ module.exports = {
renderFile: require('./renderFile'),
postRender: require('./postRender'),
- ConrefsLoader: require('./conrefsLoader')
+ ConrefsLoader: require('./conrefsLoader'),
+ ThemesLoader: require('./themesLoader')
};
diff --git a/lib/templating/themesLoader.js b/lib/templating/themesLoader.js
new file mode 100644
index 0000000..2b436a4
--- /dev/null
+++ b/lib/templating/themesLoader.js
@@ -0,0 +1,117 @@
+var Immutable = require('immutable');
+var nunjucks = require('nunjucks');
+var fs = require('fs');
+var path = require('path');
+
+var PathUtils = require('../utils/path');
+
+/**
+
+*/
+var ThemesLoader = nunjucks.Loader.extend({
+ init: function(searchPaths) {
+ this.searchPaths = Immutable.List(searchPaths)
+ .map(path.normalize);
+ },
+
+ /*
+ Read source of a resolved filepath
+ @param {String}
+ @return {Object}
+ */
+ getSource: function(fullpath) {
+ if (!fullpath) return null;
+
+ fullpath = this.resolve(null, fullpath);
+ var templateName = this.getTemplateName(fullpath);
+
+ if(!fullpath) {
+ return null;
+ }
+
+ var src = fs.readFileSync(fullpath, 'utf-8');
+
+ src = '{% do %}var template = template || {}; template.stack = template.stack || []; template.stack.push(template.self); template.self = ' + JSON.stringify(templateName) + '{% enddo %}\n' +
+ src +
+ '\n{% do %}template.self = template.stack.pop();{% enddo %}';
+
+ return {
+ src: src,
+ path: fullpath,
+ noCache: true
+ };
+ },
+
+ /*
+ Nunjucks calls "isRelative" to determine when to call "resolve".
+ We handle absolute paths ourselves in ".resolve" so we always return true
+ */
+ isRelative: function() {
+ return true;
+ },
+
+ /*
+ Get original search path containing a template
+ @param {String} filepath
+ @return {String} searchPath
+ */
+ getSearchPath: function(filepath) {
+ return this.searchPaths
+ .sortBy(function(s) {
+ return -s.length;
+ })
+ .find(function(basePath) {
+ return (filepath && filepath.indexOf(basePath) === 0);
+ });
+ },
+
+ /*
+ Get template name from a filepath
+ @param {String} filepath
+ @return {String} name
+ */
+ getTemplateName: function(filepath) {
+ var originalSearchPath = this.getSearchPath(filepath);
+ return originalSearchPath? path.relative(originalSearchPath, filepath) : null;
+ },
+
+ /*
+ Resolve a template from a current template
+ @param {String|null} from
+ @param {String} to
+ @return {String|null}
+ */
+ resolve: function(from, to) {
+ var searchPaths = this.searchPaths;
+
+ // Relative template like "./test.html"
+ if (PathUtils.isPureRelative(to) && from) {
+ return path.resolve(path.dirname(from), to);
+ }
+
+ // Determine in which search folder we currently are
+ var originalSearchPath = this.getSearchPath(from);
+ var originalFilename = this.getTemplateName(from);
+
+ // If we are including same file from a different search path
+ // Slice the search paths to avoid including from previous ones
+ if (originalFilename == to) {
+ var currentIndex = searchPaths.indexOf(originalSearchPath);
+ searchPaths = searchPaths.slice(currentIndex + 1);
+ }
+
+ // Absolute template to resolve in root folder
+ var resultFolder = searchPaths.find(function(basePath) {
+ var p = path.resolve(basePath, to);
+
+ return (
+ p.indexOf(basePath) === 0
+ && fs.existsSync(p)
+ );
+ });
+ if (!resultFolder) return null;
+ return path.resolve(resultFolder, to);
+ }
+});
+
+module.exports = ThemesLoader;