mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-23 02:53:29 +00:00
Add loader for themes
This commit is contained in:
@@ -104,6 +104,16 @@ Book.prototype.getRoot = function() {
|
||||
return fs.getRoot();
|
||||
};
|
||||
|
||||
/**
|
||||
Return root for content of the book
|
||||
|
||||
@return {String}
|
||||
*/
|
||||
Book.prototype.getContentRoot = function() {
|
||||
var fs = this.getContentFS();
|
||||
return fs.getRoot();
|
||||
};
|
||||
|
||||
/**
|
||||
Check if a file is ignore (should not being parsed, etc)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ var defaultFilters = require('../constants/defaultFilters');
|
||||
function createTemplateEngine(output) {
|
||||
var plugins = output.getPlugins();
|
||||
var book = output.getBook();
|
||||
var rootFolder = book.getRoot();
|
||||
var rootFolder = book.getContentRoot();
|
||||
var logger = book.getLogger();
|
||||
|
||||
var filters = plugins
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
var Templating = require('../../templating');
|
||||
var TemplateEngine = require('../../models/templateEngine');
|
||||
var listSearchPaths = require('./listSearchPaths');
|
||||
|
||||
/**
|
||||
Create templating engine to render themes
|
||||
@@ -7,8 +9,11 @@ var TemplateEngine = require('../../models/templateEngine');
|
||||
@return {TemplateEngine}
|
||||
*/
|
||||
function createTemplateEngine(output) {
|
||||
return new TemplateEngine({
|
||||
var searchPaths = listSearchPaths(output);
|
||||
var loader = new Templating.ThemesLoader(searchPaths);
|
||||
|
||||
return new TemplateEngine({
|
||||
loader: loader
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
/**
|
||||
List search paths for templates / i18n, etc
|
||||
|
||||
@param {Output} output
|
||||
@return {List<String>}
|
||||
*/
|
||||
function listSearchPaths(output) {
|
||||
var book = output.getBook();
|
||||
var plugins = output.getPlugins();
|
||||
|
||||
var searchPaths = plugins
|
||||
.valueSeq()
|
||||
.map(function(plugin) {
|
||||
return plugin.getPath();
|
||||
})
|
||||
.toList();
|
||||
|
||||
return searchPaths.unshift(book.getContentRoot());
|
||||
}
|
||||
|
||||
|
||||
module.exports = listSearchPaths;
|
||||
@@ -11,7 +11,7 @@ function onAsset(output, asset) {
|
||||
var book = output.getBook();
|
||||
var options = output.getOptions();
|
||||
|
||||
var rootFolder = book.getRoot();
|
||||
var rootFolder = book.getContentRoot();
|
||||
var outputFolder = options.get('root');
|
||||
|
||||
var filePath = path.resolve(rootFolder, asset);
|
||||
|
||||
@@ -4,5 +4,6 @@ module.exports = {
|
||||
renderFile: require('./renderFile'),
|
||||
postRender: require('./postRender'),
|
||||
|
||||
ConrefsLoader: require('./conrefsLoader')
|
||||
ConrefsLoader: require('./conrefsLoader'),
|
||||
ThemesLoader: require('./themesLoader')
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
+13
-2
@@ -42,7 +42,7 @@ function resolveInRoot(root) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Chnage extension
|
||||
// Chnage extension of a file
|
||||
function setExtension(filename, ext) {
|
||||
return path.join(
|
||||
path.dirname(filename),
|
||||
@@ -50,9 +50,20 @@ function setExtension(filename, ext) {
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Return true if a filename is relative.
|
||||
|
||||
@param {String}
|
||||
@return {Boolean}
|
||||
*/
|
||||
function isPureRelative(filename) {
|
||||
return (filename.indexOf('./') === 0 || filename.indexOf('../') === 0);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isInRoot: isInRoot,
|
||||
resolveInRoot: resolveInRoot,
|
||||
normalize: normalizePath,
|
||||
setExtension: setExtension
|
||||
setExtension: setExtension,
|
||||
isPureRelative: isPureRelative
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user