summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-02-14 22:49:55 +0100
committerSamy Pessé <samypesse@gmail.com>2016-02-14 22:49:55 +0100
commitfef822145d43d80dbbefa8712eab88ad7044d6c1 (patch)
tree611af2ef4292e9e9a918c2840db2a65b7efdd587
parentcfefa7d57992738373649dab16cbaf4754c3e5c7 (diff)
downloadgitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.zip
gitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.tar.gz
gitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.tar.bz2
Move conrefs to a separate mixin
-rw-r--r--lib/backbone/summary.js2
-rw-r--r--lib/book.js4
-rw-r--r--lib/output/base.js12
-rw-r--r--lib/output/conrefs.js47
-rw-r--r--lib/output/json.js2
-rw-r--r--lib/page/html.js8
-rw-r--r--lib/page/index.js6
-rw-r--r--lib/template/index.js2
-rw-r--r--lib/template/loader.js65
-rw-r--r--lib/utils/git.js4
-rw-r--r--package.json2
-rw-r--r--test/all.js1
-rw-r--r--test/conrefs.js49
-rw-r--r--test/page.js4
-rw-r--r--test/template.js49
15 files changed, 141 insertions, 116 deletions
diff --git a/lib/backbone/summary.js b/lib/backbone/summary.js
index 5775c8b..f4b9288 100644
--- a/lib/backbone/summary.js
+++ b/lib/backbone/summary.js
@@ -167,7 +167,7 @@ Summary.prototype.find = function(filter) {
};
// Return the first TOCArticle for a specific page (or path)
-Summary.prototype.getByPage = function(page) {
+Summary.prototype.getArticle = function(page) {
if (!_.isString(page)) page = page.path;
return this.find(function(article) {
diff --git a/lib/book.js b/lib/book.js
index 8c0d39b..cca1da5 100644
--- a/lib/book.js
+++ b/lib/book.js
@@ -10,7 +10,6 @@ var Glossary = require('./backbone/glossary');
var Summary = require('./backbone/summary');
var Langs = require('./backbone/langs');
var Page = require('./page');
-var TemplateEngine = require('./template');
var pathUtil = require('./utils/path');
var error = require('./utils/error');
var Promise = require('./utils/promise');
@@ -90,9 +89,6 @@ function Book(opts) {
// List of page in the book
this.pages = {};
- // Templating engine
- this.template = new TemplateEngine(this);
-
_.bindAll(this);
}
diff --git a/lib/output/base.js b/lib/output/base.js
index 8142761..fede3da 100644
--- a/lib/output/base.js
+++ b/lib/output/base.js
@@ -1,5 +1,6 @@
var _ = require('lodash');
var Ignore = require('ignore');
+var path = require('path');
var Promise = require('../utils/promise');
var PluginsManager = require('../plugins');
@@ -107,7 +108,7 @@ Output.prototype.prepare = function() {
// Write a page (parsable file), ex: markdown, etc
Output.prototype.onPage = function(page) {
- return page.parse(this);
+ return page.toHTML(this);
};
// Copy an asset file (non-parsable), ex: images, etc
@@ -134,9 +135,14 @@ Output.prototype.onOutputImage = function(page, imgFile) {
return page.relative(imgFile);
};
-// By default don;t resolve conrefs
-Output.prototype.onResolveTemplate = function(from, to) {
+// Read a template by its source URL
+Output.prototype.onGetTemplate = function(sourceUrl) {
+ throw new Error('template not found '+sourceUrl);
+};
+// Generate a source URL for a template
+Output.prototype.onResolveTemplate = function(from, to) {
+ return path.resolve(path.dirname(from), to);
};
// Finish the generation
diff --git a/lib/output/conrefs.js b/lib/output/conrefs.js
index 2883c7b..fb2d5bb 100644
--- a/lib/output/conrefs.js
+++ b/lib/output/conrefs.js
@@ -1,7 +1,9 @@
var util = require('util');
+var path = require('path');
var Output = require('./base');
var Git = require('../utils/git');
+var fs = require('../utils/fs');
var pathUtil = require('../utils/path');
/*
@@ -14,9 +16,52 @@ function ConrefsLoader() {
}
util.inherits(ConrefsLoader, Output);
-// Resolve an include in the template engine
+// Read a template by its source URL
+ConrefsLoader.prototype.onGetTemplate = function(sourceURL) {
+ var that = this;
+
+ return this.git.resolve(sourceURL)
+ .then(function(filepath) {
+ // Is local file
+ if (!filepath) {
+ filepath = that.book.resolve(sourceURL);
+ } else {
+ that.book.log.debug.ln('resolve from git', sourceURL, 'to', filepath);
+ }
+
+ // Read file from absolute path
+ return fs.readFile(filepath)
+ .then(function(source) {
+ return source.toString('utf8');
+ //return that.engine.interpolate(filepath, source);
+ })
+ .then(function(source) {
+ return {
+ src: source,
+ path: filepath
+ };
+ });
+ });
+};
+
+// Generate a source URL for a template
ConrefsLoader.prototype.onResolveTemplate = function(from, to) {
+ // If origin is in the book, we enforce result file to be in the book
+ if (this.book.isInBook(from)) {
+ return this.book.resolve(
+ this.book.relative(path.dirname(from)),
+ to
+ );
+ }
+
+ // If origin is in a git repository, we resolve file in the git repository
+ var gitRoot = this.git.resolveRoot(from);
+ if (gitRoot) {
+ return pathUtil.resolveInRoot(gitRoot, to);
+ }
+ // If origin is not in the book (include from a git content ref)
+ return path.resolve(path.dirname(from), to);
};
module.exports = ConrefsLoader;
diff --git a/lib/output/json.js b/lib/output/json.js
index 8cf2373..4ad5231 100644
--- a/lib/output/json.js
+++ b/lib/output/json.js
@@ -17,7 +17,7 @@ JSONOutput.prototype.onPage = function(page) {
var that = this;
// Parse the page
- return page.parse(this)
+ return page.toHTML(this)
// Write as json
.then(function() {
diff --git a/lib/page/html.js b/lib/page/html.js
index ea31a06..71b29b2 100644
--- a/lib/page/html.js
+++ b/lib/page/html.js
@@ -129,17 +129,19 @@ HTMLPipeline.prototype.transformHeadings = function() {
// Outline SVG from the HML
HTMLPipeline.prototype.transformSvgs = function() {
+ var that = this;
+
return this._transform('svg', function($svg) {
var content = [
'<?xml version="1.0" encoding="UTF-8"?>',
- renderDOM(this.$, $svg)
+ renderDOM(that.$, $svg)
].join('\n');
- return Promise(this.opts.onOutputSVG(content))
+ return Promise(that.opts.onOutputSVG(content))
.then(function(filename) {
if (!filename) return;
- $svg.replaceWith(this.$('<img>').attr('src', filename));
+ $svg.replaceWith(that.$('<img>').attr('src', filename));
});
});
};
diff --git a/lib/page/index.js b/lib/page/index.js
index 6911ce2..51416f0 100644
--- a/lib/page/index.js
+++ b/lib/page/index.js
@@ -106,7 +106,7 @@ Page.prototype.read = function() {
// Return templating context for this page
// This is used both for themes and page parsing
Page.prototype.getContext = function() {
- var article = this.book.summary.find(this);
+ var article = this.book.summary.getArticle(this);
return {
file: {
@@ -122,7 +122,7 @@ Page.prototype.getContext = function() {
};
// Parse the page and return its content
-Page.prototype.parse = function(output) {
+Page.prototype.toHTML = function(output) {
var that = this;
this.log.debug.ln('start parsing file', this.path);
@@ -137,7 +137,7 @@ Page.prototype.parse = function(output) {
// Render template
.then(function() {
- return that.book.template.renderString(that.content, that.getContext(), {
+ return output.template.renderString(that.content, that.getContext(), {
file: that.path
})
.then(that.update);
diff --git a/lib/template/index.js b/lib/template/index.js
index 3f74267..6074f51 100644
--- a/lib/template/index.js
+++ b/lib/template/index.js
@@ -27,7 +27,7 @@ function TemplateEngine(output) {
this.log = this.book.log;
// Create file loader
- this.loader = new Loader(this);
+ this.loader = new Loader(output);
// Create nunjucks instance
this.env = new nunjucks.Environment(
diff --git a/lib/template/loader.js b/lib/template/loader.js
index 5d30fb2..6b54015 100644
--- a/lib/template/loader.js
+++ b/lib/template/loader.js
@@ -1,74 +1,35 @@
-var path = require('path');
var nunjucks = require('nunjucks');
+var location = require('../utils/location');
-var Git = require('../utils/git');
-var pathUtil = require('../utils/path');
+/*
+Simple nunjucks loader which is passing the reponsability to the Output
+*/
-// The loader should handle relative and git url
var Loader = nunjucks.Loader.extend({
async: true,
- init: function(engine, opts) {
- this.engine = engine;
- this.book = engine.book;
- this.fs = engine.book.fs;
-
- this.git = new Git(this.fs.tmpdir());
+ init: function(output, opts) {
+ this.output = output;
},
getSource: function(sourceURL, callback) {
- var that = this;
-
- this.git.resolve(sourceURL)
- .then(function(filepath) {
- // Is local file
- if (!filepath) {
- filepath = that.book.resolve(sourceURL);
- } else {
- that.book.log.debug.ln('resolve from git', sourceURL, 'to', filepath);
- }
-
- // Read file from absolute path
- return that.fs.readAsString(filepath)
- .then(function(source) {
- return that.engine.interpolate(filepath, source);
- })
- .then(function(source) {
- return {
- src: source,
- path: filepath,
+ this.output.onGetTemplate(sourceURL)
+ .then(function(out) {
+ // We disable cache since content is modified (shortcuts, ...)
+ out.noCache = true;
- // We disable cache since content is modified (shortcuts, ...)
- noCache: true
- };
- });
+ return out;
})
.nodeify(callback);
},
resolve: function(from, to) {
- // If origin is in the book, we enforce result file to be in the book
- if (this.book.isInBook(from)) {
- return this.book.resolve(
- this.book.relative(path.dirname(from)),
- to
- );
- }
-
- // If origin is in a git repository, we resolve file in the git repository
- var gitRoot = this.git.resolveRoot(from);
- if (gitRoot) {
- return pathUtil.resolveInRoot(gitRoot, to);
- }
-
- // If origin is not in the book (include from a git content ref)
- return path.resolve(path.dirname(from), to);
+ return this.output.onResolveTemplate(from, to);
},
// Handle all files as relative, so that nunjucks pass responsability to 'resolve'
- // Only git urls are considered as absolute
isRelative: function(filename) {
- return !Git.isUrl(filename);
+ return location.isRelative(filename);
}
});
diff --git a/lib/utils/git.js b/lib/utils/git.js
index fc75ee3..52b1096 100644
--- a/lib/utils/git.js
+++ b/lib/utils/git.js
@@ -10,7 +10,7 @@ var fs = require('./fs');
var GIT_PREFIX = 'git+';
-function Git(tmpDir) {
+function Git() {
this.tmpDir;
this.cloned = {};
}
@@ -84,7 +84,7 @@ Git.prototype.resolveRoot = function(filepath) {
var relativeToGit, repoId;
// No git repo cloned, or file is not in a git repository
- if (!pathUtil.isInRoot(this.tmpDir, filepath)) return null;
+ if (!this.tmpDir || !pathUtil.isInRoot(this.tmpDir, filepath)) return null;
// Extract first directory (is the repo id)
relativeToGit = path.relative(this.tmpDir, filepath);
diff --git a/package.json b/package.json
index 1d0b520..69e91b7 100644
--- a/package.json
+++ b/package.json
@@ -64,7 +64,7 @@
"gitbook-markdown-css": "1.0.1"
},
"scripts": {
- "test": "node_modules/.bin/mocha --reporter spec --timeout 15000 ./test/all.js"
+ "test": "node_modules/.bin/mocha --reporter spec --bail --timeout 15000 ./test/all.js"
},
"repository": {
"type": "git",
diff --git a/test/all.js b/test/all.js
index 35957b4..2c87155 100644
--- a/test/all.js
+++ b/test/all.js
@@ -10,6 +10,7 @@ require('./parse');
require('./git');
require('./template');
+require('./conrefs');
// Output
require('./output-json');
diff --git a/test/conrefs.js b/test/conrefs.js
new file mode 100644
index 0000000..e75055c
--- /dev/null
+++ b/test/conrefs.js
@@ -0,0 +1,49 @@
+var mock = require('./mock');
+var ConrefsLoader = require('../lib/output/conrefs');
+
+
+describe('Conrefs Loader', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(ConrefsLoader, {
+ 'test.md': 'World'
+ })
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+
+ it('should include a local file', function() {
+ return output.template.renderString('Hello {% include "./test.md" %}')
+ .should.be.fulfilledWith('Hello World');
+ });
+
+ it('should include a git url', function() {
+ return output.template.renderString('Hello {% include "./test.md" %}')
+ .should.be.fulfilledWith('Hello World');
+ });
+
+ it('should reject file out of scope', function() {
+ return output.template.renderString('Hello {% include "../test.md" %}')
+ .should.be.rejected();
+ });
+
+ describe('Git Urls', function() {
+ it('should include a file from a git repo', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}')
+ .should.be.fulfilledWith('Hello from git');
+ });
+
+ it('should handle deep inclusion (1)', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}')
+ .should.be.fulfilledWith('First Hello. Hello from git');
+ });
+
+ it('should handle deep inclusion (2)', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}')
+ .should.be.fulfilledWith('First Hello. Hello from git');
+ });
+ });
+});
diff --git a/test/page.js b/test/page.js
index d844d13..8dbfe8b 100644
--- a/test/page.js
+++ b/test/page.js
@@ -54,7 +54,7 @@ describe('Page', function() {
it('should add a default ID to headings', function() {
var page = book.addPage('heading.md');
- return page.parse(output)
+ return page.toHTML(output)
.then(function() {
page.content.should.be.html({
'h1#hello': {
@@ -73,7 +73,7 @@ describe('Page', function() {
before(function() {
page = book.addPage('links.md');
- return page.parse(output);
+ return page.toHTML(output);
});
it('should replace links to page to .html', function() {
diff --git a/test/template.js b/test/template.js
index f338a84..536043d 100644
--- a/test/template.js
+++ b/test/template.js
@@ -1,63 +1,28 @@
var mock = require('./mock');
var pkg = require('../package.json');
+var Output = require('../lib/output/base');
describe('Template', function() {
- var book;
+ var output;
before(function() {
- return mock.setupDefaultBook({
+ return mock.outputDefaultBook(Output, {
'test.md': 'World'
})
- .then(function(_book) {
- book = _book;
- return book.parse();
+ .then(function(_output) {
+ output = _output;
});
});
describe('.renderString', function() {
it('should render a simple string', function() {
- return book.template.renderString('Hello World')
+ return output.template.renderString('Hello World')
.should.be.fulfilledWith('Hello World');
});
it('should render with variable', function() {
- return book.template.renderString('Version is {{ gitbook.version }}')
+ return output.template.renderString('Version is {{ gitbook.version }}')
.should.be.fulfilledWith('Version is '+pkg.version);
});
});
-
- describe('Conrefs Loader', function() {
- it('should include a local file', function() {
- return book.template.renderString('Hello {% include "./test.md" %}')
- .should.be.fulfilledWith('Hello World');
- });
-
- it('should include a git url', function() {
- return book.template.renderString('Hello {% include "./test.md" %}')
- .should.be.fulfilledWith('Hello World');
- });
-
- it('should reject file out of scope', function() {
- return book.template.renderString('Hello {% include "../test.md" %}')
- .should.be.rejected();
- });
-
- describe('Git Urls', function() {
- it('should include a file from a git repo', function() {
- return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}')
- .should.be.fulfilledWith('Hello from git');
- });
-
- it('should handle deep inclusion (1)', function() {
- return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}')
- .should.be.fulfilledWith('First Hello. Hello from git');
- });
-
- it('should handle deep inclusion (2)', function() {
- return book.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}')
- .should.be.fulfilledWith('First Hello. Hello from git');
- });
- });
- });
-
});