mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-21 01:53:26 +00:00
Move conrefs to a separate mixin
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -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
|
||||
|
||||
+47
-2
@@ -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
|
||||
ConrefsLoader.prototype.onResolveTemplate = function(from, to) {
|
||||
// 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;
|
||||
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
+5
-3
@@ -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));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
+13
-52
@@ -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.output.onGetTemplate(sourceURL)
|
||||
.then(function(out) {
|
||||
// We disable cache since content is modified (shortcuts, ...)
|
||||
out.noCache = true;
|
||||
|
||||
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,
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+1
-1
@@ -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",
|
||||
|
||||
@@ -10,6 +10,7 @@ require('./parse');
|
||||
|
||||
require('./git');
|
||||
require('./template');
|
||||
require('./conrefs');
|
||||
|
||||
// Output
|
||||
require('./output-json');
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
+7
-42
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user