diff options
author | Samy Pessé <samypesse@gmail.com> | 2016-02-14 22:49:55 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-02-14 22:49:55 +0100 |
commit | fef822145d43d80dbbefa8712eab88ad7044d6c1 (patch) | |
tree | 611af2ef4292e9e9a918c2840db2a65b7efdd587 | |
parent | cfefa7d57992738373649dab16cbaf4754c3e5c7 (diff) | |
download | gitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.zip gitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.tar.gz gitbook-fef822145d43d80dbbefa8712eab88ad7044d6c1.tar.bz2 |
Move conrefs to a separate mixin
-rw-r--r-- | lib/backbone/summary.js | 2 | ||||
-rw-r--r-- | lib/book.js | 4 | ||||
-rw-r--r-- | lib/output/base.js | 12 | ||||
-rw-r--r-- | lib/output/conrefs.js | 47 | ||||
-rw-r--r-- | lib/output/json.js | 2 | ||||
-rw-r--r-- | lib/page/html.js | 8 | ||||
-rw-r--r-- | lib/page/index.js | 6 | ||||
-rw-r--r-- | lib/template/index.js | 2 | ||||
-rw-r--r-- | lib/template/loader.js | 65 | ||||
-rw-r--r-- | lib/utils/git.js | 4 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | test/all.js | 1 | ||||
-rw-r--r-- | test/conrefs.js | 49 | ||||
-rw-r--r-- | test/page.js | 4 | ||||
-rw-r--r-- | test/template.js | 49 |
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'); - }); - }); - }); - }); |