mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-21 01:53:26 +00:00
Switch parsers to a model
This commit is contained in:
+1
-2
@@ -1,4 +1,3 @@
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
var chokidar = require('chokidar');
|
||||
|
||||
@@ -20,7 +19,7 @@ function watch(dir) {
|
||||
];
|
||||
|
||||
// Watch all parsable files
|
||||
_.each(parsers.extensions, function(ext) {
|
||||
parsers.extensions.forEach(function(ext) {
|
||||
toWatch.push('**/*'+ext);
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ File.prototype.exists = function() {
|
||||
File.prototype.getType = function() {
|
||||
var parser = this.getParser();
|
||||
if (parser) {
|
||||
return parser.name;
|
||||
return parser.getName();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ Glossary.prototype.toText = function(parser) {
|
||||
});
|
||||
}
|
||||
|
||||
return parser.glossary.toText(entries.toJS());
|
||||
return parser.renderGlossary(entries.toJS());
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
var Immutable = require('immutable');
|
||||
var Promise = require('../utils/promise');
|
||||
|
||||
var Parser = Immutable.Record({
|
||||
name: String(),
|
||||
|
||||
// List of extensions that can be processed using this parser
|
||||
extensions: Immutable.List(),
|
||||
|
||||
// Parsing functions
|
||||
readme: Function(),
|
||||
langs: Function(),
|
||||
summary: Function(),
|
||||
glossary: Function(),
|
||||
page: Function(),
|
||||
inline: Function()
|
||||
});
|
||||
|
||||
Parser.prototype.getName = function() {
|
||||
return this.get('name');
|
||||
};
|
||||
|
||||
Parser.prototype.getExtensions = function() {
|
||||
return this.get('extensions');
|
||||
};
|
||||
|
||||
// PARSE
|
||||
|
||||
Parser.prototype.parseReadme = function(content) {
|
||||
var readme = this.get('readme');
|
||||
return Promise(readme(content));
|
||||
};
|
||||
|
||||
Parser.prototype.parseSummary = function(content) {
|
||||
var summary = this.get('summary');
|
||||
return Promise(summary(content));
|
||||
};
|
||||
|
||||
Parser.prototype.parseGlossary = function(content) {
|
||||
var glossary = this.get('glossary');
|
||||
return Promise(glossary(content));
|
||||
};
|
||||
|
||||
Parser.prototype.preparePage = function(content) {
|
||||
var page = this.get('page');
|
||||
return Promise(page.prepare(content));
|
||||
};
|
||||
|
||||
Parser.prototype.parsePage = function(content) {
|
||||
var page = this.get('page');
|
||||
return Promise(page(content));
|
||||
};
|
||||
|
||||
Parser.prototype.parseLanguages = function(content) {
|
||||
var langs = this.get('langs');
|
||||
return Promise(langs(content));
|
||||
};
|
||||
|
||||
Parser.prototype.parseInline = function(content) {
|
||||
var inline = this.get('inline');
|
||||
return Promise(inline(content));
|
||||
};
|
||||
|
||||
// TO TEXT
|
||||
|
||||
Parser.prototype.renderLanguages = function(content) {
|
||||
var langs = this.get('langs');
|
||||
return Promise(langs.toText(content));
|
||||
};
|
||||
|
||||
Parser.prototype.renderSummary = function(content) {
|
||||
var summary = this.get('summary');
|
||||
return Promise(summary.toText(content));
|
||||
};
|
||||
|
||||
Parser.prototype.renderGlossary = function(content) {
|
||||
var glossary = this.get('glossary');
|
||||
return Promise(glossary.toText(content));
|
||||
};
|
||||
|
||||
/**
|
||||
Test if this parser matches an extension
|
||||
|
||||
@param {String} ext
|
||||
@return {Boolean}
|
||||
*/
|
||||
Parser.prototype.matchExtension = function(ext) {
|
||||
var exts = this.getExtensions();
|
||||
return exts.includes(ext.toLowerCase());
|
||||
};
|
||||
|
||||
/**
|
||||
Create a new parser using a module (gitbook-markdown, etc)
|
||||
|
||||
@param {String} name
|
||||
@param {Array<String>} extensions
|
||||
@param {Object} module
|
||||
@return {Parser}
|
||||
*/
|
||||
Parser.create = function(name, extensions, module) {
|
||||
return new Parser({
|
||||
name: name,
|
||||
extensions: Immutable.List(extensions),
|
||||
readme: module.readme,
|
||||
langs: module.langs,
|
||||
summary: module.summary,
|
||||
glossary: module.glossary,
|
||||
page: module.page,
|
||||
inline: module.inline
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Parser;
|
||||
@@ -146,7 +146,7 @@ Summary.prototype.toText = function(parser) {
|
||||
});
|
||||
}
|
||||
|
||||
return parser.summary.toText({
|
||||
return parser.renderSummary({
|
||||
parts: parts.toJS()
|
||||
});
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ function generatePage(output, page) {
|
||||
|
||||
// Escape code blocks with raw tags
|
||||
.then(function(currentPage) {
|
||||
return parser.page.prepare(currentPage.getContent());
|
||||
return parser.preparePage(currentPage.getContent());
|
||||
})
|
||||
|
||||
// Render templating syntax
|
||||
@@ -48,7 +48,7 @@ function generatePage(output, page) {
|
||||
})
|
||||
|
||||
// Render page using parser (markdown -> HTML)
|
||||
.then(parser.page).get('content')
|
||||
.then(parser.parsePage.bind(parser)).get('content')
|
||||
|
||||
// Post processing for templating syntax
|
||||
.then(function(content) {
|
||||
|
||||
@@ -24,9 +24,22 @@ function parseFile(fs, file, type) {
|
||||
|
||||
return fs.readAsString(filepath)
|
||||
.then(function(content) {
|
||||
if (type === 'readme') {
|
||||
return parser.parseReadme(content);
|
||||
} else if (type === 'glossary') {
|
||||
return parser.parseGlossary(content);
|
||||
} else if (type === 'summary') {
|
||||
return parser.parseSummary(content);
|
||||
} else if (type === 'langs') {
|
||||
return parser.parseLanguages(content);
|
||||
} else {
|
||||
throw new Error('Parsing invalid type "' + type + '"');
|
||||
}
|
||||
})
|
||||
.then(function(result) {
|
||||
return [
|
||||
file,
|
||||
parser[type](content)
|
||||
result
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
+35
-44
@@ -1,69 +1,60 @@
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
var Immutable = require('immutable');
|
||||
|
||||
var markdownParser = require('gitbook-markdown');
|
||||
var asciidocParser = require('gitbook-asciidoc');
|
||||
|
||||
var Promise = require('./utils/promise');
|
||||
var Parser = require('./models/parser');
|
||||
|
||||
// This list is ordered by priority of parsers to use
|
||||
var PARSERS = [
|
||||
createParser(markdownParser, {
|
||||
name: 'markdown',
|
||||
extensions: ['.md', '.markdown', '.mdown']
|
||||
}),
|
||||
createParser(asciidocParser, {
|
||||
name: 'asciidoc',
|
||||
extensions: ['.adoc', '.asciidoc']
|
||||
})
|
||||
];
|
||||
var parsers = Immutable.List([
|
||||
Parser.create('markdown', ['.md', '.markdown', '.mdown'], markdownParser),
|
||||
Parser.create('asciidoc', ['.adoc', '.asciidoc'], asciidocParser)
|
||||
]);
|
||||
|
||||
/**
|
||||
Return a specific parser by its name
|
||||
|
||||
// Prepare and compose a parser
|
||||
function createParser(parser, base) {
|
||||
var nparser = base;
|
||||
|
||||
nparser.glossary = Promise.wrapfn(parser.glossary);
|
||||
nparser.glossary.toText = Promise.wrapfn(parser.glossary.toText);
|
||||
|
||||
nparser.summary = Promise.wrapfn(parser.summary);
|
||||
nparser.summary.toText = Promise.wrapfn(parser.summary.toText);
|
||||
|
||||
nparser.langs = Promise.wrapfn(parser.langs);
|
||||
nparser.langs.toText = Promise.wrapfn(parser.langs.toText);
|
||||
|
||||
nparser.readme = Promise.wrapfn(parser.readme);
|
||||
|
||||
nparser.page = Promise.wrapfn(parser.page);
|
||||
nparser.page.prepare = Promise.wrapfn(parser.page.prepare || _.identity);
|
||||
|
||||
nparser.inline = Promise.wrapfn(parser.inline);
|
||||
|
||||
return nparser;
|
||||
}
|
||||
|
||||
// Return a specific parser
|
||||
@param {String} name
|
||||
@return {Parser|undefined}
|
||||
*/
|
||||
function getParser(name) {
|
||||
return _.find(PARSERS, {
|
||||
name: name
|
||||
return parsers.find(function(parser) {
|
||||
return parser.getName() === name;
|
||||
});
|
||||
}
|
||||
|
||||
// Return a specific parser according to an extension
|
||||
/**
|
||||
Return a specific parser according to an extension
|
||||
|
||||
@param {String} ext
|
||||
@return {Parser|undefined}
|
||||
*/
|
||||
function getParserByExt(ext) {
|
||||
return _.find(PARSERS, function(input) {
|
||||
return input.name == ext || _.contains(input.extensions, ext);
|
||||
return parsers.find(function(parser) {
|
||||
return parser.matchExtension(ext);
|
||||
});
|
||||
}
|
||||
|
||||
// Return parser for a file
|
||||
/**
|
||||
Return parser for a file
|
||||
|
||||
@param {String} ext
|
||||
@return {Parser|undefined}
|
||||
*/
|
||||
function getParserForFile(filename) {
|
||||
return getParser(path.extname(filename));
|
||||
}
|
||||
|
||||
// List all parsable extensions
|
||||
var extensions = parsers
|
||||
.map(function(parser) {
|
||||
return parser.getExtensions();
|
||||
})
|
||||
.flatten();
|
||||
|
||||
module.exports = {
|
||||
all: PARSERS,
|
||||
extensions: _.flatten(_.pluck(PARSERS, 'extensions')),
|
||||
extensions: extensions,
|
||||
get: getParser,
|
||||
getByExt: getParserByExt,
|
||||
getForFile: getParserForFile
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
|
||||
// Module API
|
||||
require('./exports');
|
||||
|
||||
// Utilities
|
||||
require('./location');
|
||||
require('./paths');
|
||||
|
||||
// Parsing
|
||||
require('./locate');
|
||||
require('./config');
|
||||
require('./readme');
|
||||
require('./summary');
|
||||
require('./glossary');
|
||||
require('./langs');
|
||||
require('./parse');
|
||||
|
||||
require('./git');
|
||||
require('./plugins');
|
||||
require('./template');
|
||||
require('./conrefs');
|
||||
|
||||
// Page and HTML generation
|
||||
require('./page');
|
||||
|
||||
// Output
|
||||
require('./assets-inliner');
|
||||
require('./output-json');
|
||||
require('./output-website');
|
||||
require('./output-ebook');
|
||||
|
||||
require('./structure');
|
||||
require('./ignore');
|
||||
|
||||
// Misc
|
||||
require('./init');
|
||||
@@ -1,75 +0,0 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var _ = require('lodash');
|
||||
var cheerio = require('cheerio');
|
||||
var should = require('should');
|
||||
|
||||
// Assertions to test if an Output has generated a file
|
||||
should.Assertion.add('file', function(file, description) {
|
||||
var rootFolder;
|
||||
if (_.isFunction(this.obj.root)) {
|
||||
rootFolder = this.obj.root();
|
||||
} else {
|
||||
rootFolder = this.obj;
|
||||
}
|
||||
|
||||
this.params = {
|
||||
actual: rootFolder,
|
||||
operator: 'have file ' + file,
|
||||
message: description
|
||||
};
|
||||
|
||||
if (_.isFunction(this.obj.resolve)) {
|
||||
file = this.obj.resolve(file);
|
||||
} else {
|
||||
file = path.resolve(rootFolder, file);
|
||||
}
|
||||
|
||||
this.assert(fs.existsSync(file));
|
||||
});
|
||||
|
||||
should.Assertion.add('html', function(rules, description) {
|
||||
this.params = { actual: 'HTML string', operator: 'valid html', message: description };
|
||||
var $ = cheerio.load(this.obj);
|
||||
|
||||
_.each(rules, function(validations, query) {
|
||||
validations = _.defaults(validations || {}, {
|
||||
// Select a specific element in the list of matched elements
|
||||
index: null,
|
||||
|
||||
// Check that there is the correct count of elements
|
||||
count: 1,
|
||||
|
||||
// Check attribute values
|
||||
attributes: {},
|
||||
|
||||
// Trim inner text
|
||||
trim: false,
|
||||
|
||||
// Check inner text
|
||||
text: undefined
|
||||
});
|
||||
|
||||
var $el = $(query);
|
||||
|
||||
// Select correct element
|
||||
if (_.isNumber(validations.index)) $el = $($el.get(validations.index));
|
||||
|
||||
// Test number of elements
|
||||
$el.length.should.be.equal(validations.count);
|
||||
|
||||
// Test text
|
||||
if (validations.text !== undefined) {
|
||||
var text = $el.text();
|
||||
if (validations.trim) text = text.trim();
|
||||
text.should.be.equal(validations.text);
|
||||
}
|
||||
|
||||
// Test attributes
|
||||
_.each(validations.attributes, function(value, name) {
|
||||
var attr = $el.attr(name);
|
||||
should(attr).be.ok();
|
||||
attr.should.be.equal(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,86 +0,0 @@
|
||||
var cheerio = require('cheerio');
|
||||
var path = require('path');
|
||||
|
||||
var mock = require('./mock');
|
||||
var AssetsInliner = require('../lib/output/assets-inliner')();
|
||||
|
||||
describe('Assets Inliner Output', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
var SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1"><rect width="200" height="100" stroke="black" stroke-width="6" fill="green"/></svg>';
|
||||
|
||||
return mock.outputDefaultBook(AssetsInliner, {
|
||||
'README.md': '',
|
||||
|
||||
// SVGs
|
||||
'svg_file.md': '',
|
||||
'svg_inline.md': 'This is a svg: '+SVG,
|
||||
'test.svg': '<?xml version="1.0" encoding="UTF-8"?>' + SVG,
|
||||
|
||||
// Relative
|
||||
'folder/test.md': '',
|
||||
|
||||
// Remote images
|
||||
'remote_png.md': '',
|
||||
'remote_svg.md': '',
|
||||
|
||||
'SUMMARY.md': '* [svg inline](svg_inline.md)\n' +
|
||||
'* [svg file](svg_file.md)\n' +
|
||||
'* [remote png file](remote_png.md)\n' +
|
||||
'* [remote svg file](remote_svg.md)\n' +
|
||||
'* [relative image](folder/test.md)\n' +
|
||||
'\n\n'
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
function testImageInPage(filename) {
|
||||
var page = output.book.getPage(filename);
|
||||
var $ = cheerio.load(page.content);
|
||||
|
||||
// Is there an image?
|
||||
var $img = $('img');
|
||||
$img.length.should.equal(1);
|
||||
|
||||
// Does the file exists
|
||||
var src = $img.attr('src');
|
||||
|
||||
// Resolve the filename
|
||||
src = page.resolveLocal(src);
|
||||
|
||||
output.should.have.file(src);
|
||||
path.extname(src).should.equal('.png');
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
describe('SVG', function() {
|
||||
it('should correctly convert SVG files to PNG', function() {
|
||||
testImageInPage('svg_file.md');
|
||||
});
|
||||
|
||||
it('should correctly convert inline SVG to PNG', function() {
|
||||
testImageInPage('svg_inline.md');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Remote Assets', function() {
|
||||
it('should correctly download a PNG file', function() {
|
||||
testImageInPage('remote_png.md');
|
||||
});
|
||||
|
||||
it('should correctly download then convert a remote SVG to PNG', function() {
|
||||
testImageInPage('remote_svg.md');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Relative Images', function() {
|
||||
it('should correctly resolve image', function() {
|
||||
testImageInPage('folder/test.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
var should = require('should');
|
||||
var mock = require('./mock');
|
||||
var validator = require('../lib/config/validator');
|
||||
|
||||
describe('Configuration', function() {
|
||||
|
||||
describe('Validation', function() {
|
||||
it('should merge default', function() {
|
||||
validator.validate({}).should.have.property('gitbook').which.equal('*');
|
||||
});
|
||||
|
||||
it('should throw error for invalid configuration', function() {
|
||||
should.throws(function() {
|
||||
validator.validate({
|
||||
direction: 'invalid'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw error for non existing configuration', function() {
|
||||
validator.validate({
|
||||
style: {
|
||||
'pdf': 'test.css'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should validate plugins as an array', function() {
|
||||
validator.validate({
|
||||
plugins: ['hello']
|
||||
});
|
||||
});
|
||||
|
||||
it('should validate plugins as a string', function() {
|
||||
validator.validate({
|
||||
plugins: 'hello,world'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('No configuration', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook()
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.prepareConfig();
|
||||
});
|
||||
});
|
||||
|
||||
it('should signal that configuration is not defined', function() {
|
||||
book.config.exists().should.not.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('JSON file', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'book.json': { title: 'Hello World' }
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.prepareConfig();
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly extend configuration', function() {
|
||||
book.config.get('title', '').should.equal('Hello World');
|
||||
});
|
||||
});
|
||||
|
||||
describe('JS file', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'book.js': 'module.exports = { title: "Hello World" };'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.prepareConfig();
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly extend configuration', function() {
|
||||
book.config.get('title', '').should.equal('Hello World');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Multilingual', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'book.json': {
|
||||
title: 'Hello World',
|
||||
pluginsConfig: {
|
||||
'test': {
|
||||
'hello': true
|
||||
}
|
||||
}
|
||||
},
|
||||
'LANGS.md': '# Languages\n\n'
|
||||
+ '* [en](./en)\n'
|
||||
+ '* [fr](./fr)\n\n',
|
||||
'en/README.md': '# Hello',
|
||||
'fr/README.md': '# Bonjour',
|
||||
'en/book.json': { description: 'In english' },
|
||||
'fr/book.json': { description: 'En francais' }
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.parse();
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly extend configuration', function() {
|
||||
book.config.get('title', '').should.equal('Hello World');
|
||||
book.config.get('description', '').should.equal('');
|
||||
|
||||
var en = book.books[0];
|
||||
en.config.get('title', '').should.equal('Hello World');
|
||||
en.config.get('description', '').should.equal('In english');
|
||||
en.config.get('pluginsConfig.test.hello').should.equal(true);
|
||||
|
||||
var fr = book.books[1];
|
||||
fr.config.get('title', '').should.equal('Hello World');
|
||||
fr.config.get('description', '').should.equal('En francais');
|
||||
fr.config.get('pluginsConfig.test.hello').should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
var should = require('should');
|
||||
var gitbook = require('../');
|
||||
|
||||
describe('Exports', function() {
|
||||
it('should export the Book class', function() {
|
||||
should(gitbook.Book).be.a.Function();
|
||||
});
|
||||
|
||||
it('should export the list of commands', function() {
|
||||
should(gitbook.commands).be.an.Array();
|
||||
});
|
||||
});
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
var should = require('should');
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
|
||||
var Git = require('../lib/utils/git');
|
||||
|
||||
describe('Git', function() {
|
||||
|
||||
describe('URL parsing', function() {
|
||||
|
||||
it('should correctly validate git urls', function() {
|
||||
// HTTPS
|
||||
Git.isUrl('git+https://github.com/Hello/world.git').should.be.ok();
|
||||
|
||||
// SSH
|
||||
Git.isUrl('git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1').should.be.ok;
|
||||
|
||||
// Non valid
|
||||
Git.isUrl('https://github.com/Hello/world.git').should.not.be.ok();
|
||||
Git.isUrl('README.md').should.not.be.ok();
|
||||
});
|
||||
|
||||
it('should parse HTTPS urls', function() {
|
||||
var parts = Git.parseUrl('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md');
|
||||
|
||||
should.exist(parts);
|
||||
parts.host.should.be.equal('https://gist.github.com/69ea4542e4c8967d2fa7.git');
|
||||
should(parts.ref).be.equal(null);
|
||||
parts.filepath.should.be.equal('test.md');
|
||||
});
|
||||
|
||||
it('should parse HTTPS urls with a reference', function() {
|
||||
var parts = Git.parseUrl('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md#1.0.0');
|
||||
|
||||
should.exist(parts);
|
||||
parts.host.should.be.equal('https://gist.github.com/69ea4542e4c8967d2fa7.git');
|
||||
parts.ref.should.be.equal('1.0.0');
|
||||
parts.filepath.should.be.equal('test.md');
|
||||
});
|
||||
|
||||
it('should parse SSH urls', function() {
|
||||
var parts = Git.parseUrl('git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1');
|
||||
|
||||
should.exist(parts);
|
||||
parts.host.should.be.equal('git@github.com:GitbookIO/gitbook.git');
|
||||
parts.ref.should.be.equal('e1594cde2c32e4ff48f6c4eff3d3d461743d74e1');
|
||||
parts.filepath.should.be.equal('directory/README.md');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cloning and resolving', function() {
|
||||
it('should clone an HTTPS url', function() {
|
||||
var git = new Git(path.join(os.tmpdir(), 'test-git-'+Date.now()));
|
||||
return git.resolve('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md')
|
||||
.then(function(filename) {
|
||||
path.extname(filename).should.equal('.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
var should = require('should');
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Glossary', function() {
|
||||
it('should parse empty glossary', function() {
|
||||
return mock.setupDefaultBook({
|
||||
'GLOSSARY.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
|
||||
.then(function() {
|
||||
return book.glossary.load();
|
||||
})
|
||||
.then(function() {
|
||||
book.glossary.isEmpty().should.be.true();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Non-empty glossary', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'GLOSSARY.md': '# Glossary\n\n## Hello World\n\nThis is an entry'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.prepareConfig();
|
||||
})
|
||||
.then(function() {
|
||||
return book.glossary.load();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be empty', function() {
|
||||
book.glossary.isEmpty().should.be.false();
|
||||
});
|
||||
|
||||
describe('glossary.get', function() {
|
||||
it('should return an existing entry', function() {
|
||||
var entry = book.glossary.get('hello_world');
|
||||
should.exist(entry);
|
||||
|
||||
entry.name.should.equal('Hello World');
|
||||
entry.description.should.equal('This is an entry');
|
||||
entry.id.should.equal('hello_world');
|
||||
});
|
||||
|
||||
it('should undefined return non existing entry', function() {
|
||||
var entry = book.glossary.get('cool');
|
||||
should.not.exist(entry);
|
||||
});
|
||||
});
|
||||
|
||||
describe('glossary.find', function() {
|
||||
it('should return an existing entry', function() {
|
||||
var entry = book.glossary.find('HeLLo World');
|
||||
should.exist(entry);
|
||||
entry.id.should.equal('hello_world');
|
||||
});
|
||||
|
||||
it('should return undefined for non existing entry', function() {
|
||||
var entry = book.glossary.find('Hello');
|
||||
should.not.exist(entry);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
var WebsiteOutput = require('../lib/output/website');
|
||||
|
||||
describe('Ignore', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(WebsiteOutput, {
|
||||
'.ignore': 'test-1.js',
|
||||
'.gitignore': 'test-2.js\ntest-3.js',
|
||||
'.bookignore': '!test-3.js',
|
||||
'test-1.js': '1',
|
||||
'test-2.js': '2',
|
||||
'test-3.js': '3'
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should load rules from .ignore', function() {
|
||||
output.should.not.have.file('test-1.js');
|
||||
});
|
||||
|
||||
it('should load rules from .gitignore', function() {
|
||||
output.should.not.have.file('test-2.js');
|
||||
});
|
||||
|
||||
it('should load rules from .bookignore', function() {
|
||||
output.should.have.file('test-3.js');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
var Book = require('../lib/book');
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Init', function() {
|
||||
|
||||
it('should create file according to summary', function() {
|
||||
return mock.setupFS({
|
||||
'SUMMARY.md': '# Summary\n\n'
|
||||
+ '* [Hello](hello.md)\n'
|
||||
+ '* [Hello 2](hello 2.md)\n'
|
||||
})
|
||||
.then(function(rootFolder) {
|
||||
return Book.init(mock.fs, rootFolder, {
|
||||
log: function() {}
|
||||
})
|
||||
.then(function() {
|
||||
rootFolder.should.have.file('SUMMARY.md');
|
||||
rootFolder.should.have.file('README.md');
|
||||
rootFolder.should.have.file('hello.md');
|
||||
rootFolder.should.have.file('hello 2.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create file subfolder', function() {
|
||||
return mock.setupFS({
|
||||
'SUMMARY.md': '# Summary\n\n'
|
||||
+ '* [Hello](test/hello.md)\n'
|
||||
+ '* [Hello 2](test/test2/world.md)\n'
|
||||
})
|
||||
.then(function(rootFolder) {
|
||||
return Book.init(mock.fs, rootFolder, {
|
||||
log: function() {}
|
||||
})
|
||||
.then(function() {
|
||||
rootFolder.should.have.file('README.md');
|
||||
rootFolder.should.have.file('SUMMARY.md');
|
||||
rootFolder.should.have.file('test/hello.md');
|
||||
rootFolder.should.have.file('test/test2/world.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create SUMMARY if non-existant', function() {
|
||||
return mock.setupFS({})
|
||||
.then(function(rootFolder) {
|
||||
return Book.init(mock.fs, rootFolder, {
|
||||
log: function() {}
|
||||
})
|
||||
.then(function() {
|
||||
rootFolder.should.have.file('SUMMARY.md');
|
||||
rootFolder.should.have.file('README.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Langs', function() {
|
||||
it('should parse empty langs', function() {
|
||||
return mock.setupDefaultBook({
|
||||
'LANGS.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
|
||||
.then(function() {
|
||||
return book.langs.load();
|
||||
})
|
||||
|
||||
.then(function() {
|
||||
book.langs.count().should.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Non-empty languages list', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'LANGS.md': '# Languages\n\n'
|
||||
+ '* [en](./en)\n'
|
||||
+ '* [fr](./fr)\n\n'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
|
||||
return book.langs.load();
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly count languages', function() {
|
||||
book.langs.count().should.equal(2);
|
||||
});
|
||||
|
||||
it('should correctly define book as multilingual', function() {
|
||||
book.isMultilingual().should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
var path = require('path');
|
||||
var should = require('should');
|
||||
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Locate', function() {
|
||||
it('should use root folder if no .gitbook', function() {
|
||||
return mock.setupBook({
|
||||
'README.md': '# Hello'
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
.then(function() {
|
||||
should(book.originalRoot).not.be.ok();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use resolve using book.js root property', function() {
|
||||
return mock.setupBook({
|
||||
'README.md': '# Hello',
|
||||
'docs/README.md': '# Hello Book',
|
||||
'book.json': { root: './docs' }
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
.then(function() {
|
||||
should(book.originalRoot).be.ok();
|
||||
book.root.should.equal(path.resolve(book.originalRoot, 'docs'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,55 +0,0 @@
|
||||
var location = require('../lib/utils/location');
|
||||
|
||||
describe('Location', function() {
|
||||
it('should correctly test external location', function() {
|
||||
location.isExternal('http://google.fr').should.be.exactly(true);
|
||||
location.isExternal('https://google.fr').should.be.exactly(true);
|
||||
location.isExternal('test.md').should.be.exactly(false);
|
||||
location.isExternal('folder/test.md').should.be.exactly(false);
|
||||
location.isExternal('/folder/test.md').should.be.exactly(false);
|
||||
});
|
||||
|
||||
it('should correctly detect anchor location', function() {
|
||||
location.isAnchor('#test').should.be.exactly(true);
|
||||
location.isAnchor(' #test').should.be.exactly(true);
|
||||
location.isAnchor('https://google.fr#test').should.be.exactly(false);
|
||||
location.isAnchor('test.md#test').should.be.exactly(false);
|
||||
});
|
||||
|
||||
describe('.relative', function() {
|
||||
it('should resolve to a relative path (same folder)', function() {
|
||||
location.relative('links/', 'links/test.md').should.equal('test.md');
|
||||
});
|
||||
|
||||
it('should resolve to a relative path (parent folder)', function() {
|
||||
location.relative('links/', 'test.md').should.equal('../test.md');
|
||||
});
|
||||
|
||||
it('should resolve to a relative path (child folder)', function() {
|
||||
location.relative('links/', 'links/hello/test.md').should.equal('hello/test.md');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.toAbsolute', function() {
|
||||
it('should correctly transform as absolute', function() {
|
||||
location.toAbsolute('http://google.fr').should.be.equal('http://google.fr');
|
||||
location.toAbsolute('test.md', './', './').should.be.equal('test.md');
|
||||
location.toAbsolute('folder/test.md', './', './').should.be.equal('folder/test.md');
|
||||
});
|
||||
|
||||
it('should correctly handle windows path', function() {
|
||||
location.toAbsolute('folder\\test.md', './', './').should.be.equal('folder/test.md');
|
||||
});
|
||||
|
||||
it('should correctly handle absolute path', function() {
|
||||
location.toAbsolute('/test.md', './', './').should.be.equal('test.md');
|
||||
location.toAbsolute('/test.md', 'test', 'test').should.be.equal('../test.md');
|
||||
location.toAbsolute('/sub/test.md', 'test', 'test').should.be.equal('../sub/test.md');
|
||||
location.toAbsolute('/test.png', 'folder', '').should.be.equal('test.png');
|
||||
});
|
||||
|
||||
it('should correctly handle absolute path (windows)', function() {
|
||||
location.toAbsolute('\\test.png', 'folder', '').should.be.equal('test.png');
|
||||
});
|
||||
});
|
||||
});
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
var Q = require('q');
|
||||
var _ = require('lodash');
|
||||
var tmp = require('tmp');
|
||||
var path = require('path');
|
||||
|
||||
var Book = require('../').Book;
|
||||
var NodeFS = require('../lib/fs/node');
|
||||
var fs = require('../lib/utils/fs');
|
||||
|
||||
require('./assertions');
|
||||
|
||||
// Create filesystem instance for testing
|
||||
var nodeFS = new NodeFS();
|
||||
|
||||
function setupFS(files) {
|
||||
return Q.nfcall(tmp.dir.bind(tmp)).get(0)
|
||||
.then(function(rootFolder) {
|
||||
return _.chain(_.pairs(files))
|
||||
.sortBy(0)
|
||||
.reduce(function(prev, pair) {
|
||||
return prev.then(function() {
|
||||
var filename = path.resolve(rootFolder, pair[0]);
|
||||
var buf = pair[1];
|
||||
|
||||
if (_.isObject(buf)) buf = JSON.stringify(buf);
|
||||
if (_.isString(buf)) buf = new Buffer(buf, 'utf-8');
|
||||
|
||||
return fs.mkdirp(path.dirname(filename))
|
||||
.then(function() {
|
||||
return fs.writeFile(filename, buf);
|
||||
});
|
||||
});
|
||||
}, Q())
|
||||
.value()
|
||||
.then(function() {
|
||||
return rootFolder;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Setup a mock book for testing using a map of files
|
||||
function setupBook(files, opts) {
|
||||
opts = opts || {};
|
||||
opts.log = function() { };
|
||||
|
||||
return setupFS(files)
|
||||
.then(function(folder) {
|
||||
opts.fs = nodeFS;
|
||||
opts.root = folder;
|
||||
|
||||
return new Book(opts);
|
||||
});
|
||||
}
|
||||
|
||||
// Setup a book with default README/SUMMARY
|
||||
function setupDefaultBook(files, summary, opts) {
|
||||
var summaryContent = '# Summary \n\n' +
|
||||
_.map(summary, function(article) {
|
||||
return '* [' + article.title +'](' + article.path + ')';
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return setupBook(_.defaults(files || {}, {
|
||||
'README.md': 'Hello',
|
||||
'SUMMARY.md': summaryContent
|
||||
}), opts);
|
||||
}
|
||||
|
||||
// Prepare output for a book
|
||||
function setupOutput(Output, files, opts) {
|
||||
return setupBook(files, opts)
|
||||
.then(function(book) {
|
||||
// Parse the book
|
||||
return book.parse()
|
||||
|
||||
// Start generation
|
||||
.then(function() {
|
||||
return new Output(book);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Prepare output for a book
|
||||
function setupDefaultOutput(Output, files, summary, opts) {
|
||||
return setupDefaultBook(files, summary, opts)
|
||||
.then(function(book) {
|
||||
// Parse the book
|
||||
return book.parse()
|
||||
|
||||
// Start generation
|
||||
.then(function() {
|
||||
return new Output(book);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Output a book with a specific generator
|
||||
function outputDefaultBook(Output, files, summary, opts) {
|
||||
return setupDefaultOutput(Output, files, summary, opts)
|
||||
.then(function(output) {
|
||||
return output.generate()
|
||||
.thenResolve(output);
|
||||
});
|
||||
}
|
||||
|
||||
// Output a book with a specific generator
|
||||
function outputBook(Output, files, opts) {
|
||||
return setupOutput(Output, files, opts)
|
||||
.then(function(output) {
|
||||
return output.generate()
|
||||
.thenResolve(output);
|
||||
});
|
||||
}
|
||||
|
||||
// Log an error
|
||||
function logError(err) {
|
||||
console.log(err.stack || err);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fs: nodeFS,
|
||||
|
||||
setupFS: setupFS,
|
||||
|
||||
setupBook: setupBook,
|
||||
setupDefaultBook: setupDefaultBook,
|
||||
|
||||
setupOutput: setupOutput,
|
||||
setupDefaultOutput: setupDefaultOutput,
|
||||
|
||||
outputBook: outputBook,
|
||||
outputDefaultBook: outputDefaultBook,
|
||||
|
||||
logError: logError
|
||||
};
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-dep1",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"gitbook-plugin-dep2": "*"
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-dep2",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
var should = require('should');
|
||||
|
||||
module.exports = {
|
||||
blocks: {
|
||||
// Simple test
|
||||
hello: function(blk) {
|
||||
return 'Hello ' + blk.body + '!';
|
||||
},
|
||||
|
||||
// Test using the conetxt "this"
|
||||
testContext: function(s) {
|
||||
this.should.have.property('config');
|
||||
this.should.have.property('log');
|
||||
this.should.have.property('options');
|
||||
this.should.have.property('resolve').which.is.a.function;
|
||||
this.should.have.property('book').which.equal(this);
|
||||
|
||||
return 'Hello ' + s + '!';
|
||||
}
|
||||
}
|
||||
};
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-blocks",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
module.exports = {};
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-config",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
},
|
||||
"gitbook": {
|
||||
"properties": {
|
||||
"myProperty": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "This is a required property"
|
||||
},
|
||||
"myDefaultProperty": {
|
||||
"type": "string",
|
||||
"default": "hello",
|
||||
"title": "This is a required property"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
module.exports = {
|
||||
hooks: {
|
||||
page: function(page) {
|
||||
page.sections[0].content = 'Hello (sections) ' + page.content;
|
||||
return page;
|
||||
}
|
||||
}
|
||||
};
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-deprecated",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
var should = require('should');
|
||||
|
||||
module.exports = {
|
||||
filters: {
|
||||
// Simple test
|
||||
hello: function(s) {
|
||||
return 'Hello ' + s + '!';
|
||||
},
|
||||
|
||||
// Test using the conetxt "this"
|
||||
testContext: function(s) {
|
||||
this.should.have.property('config');
|
||||
this.should.have.property('log');
|
||||
this.should.have.property('options');
|
||||
this.should.have.property('resolve').which.is.a.function;
|
||||
this.should.have.property('book').which.equal(this);
|
||||
|
||||
return 'Hello ' + s + '!';
|
||||
}
|
||||
}
|
||||
};
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-filters",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
module.exports = {
|
||||
hooks: {
|
||||
'init': function() {
|
||||
global._hooks = [];
|
||||
global._hooks.push('init');
|
||||
},
|
||||
'finish': function() {
|
||||
global._hooks.push('finish');
|
||||
},
|
||||
'finish:before': function() {
|
||||
global._hooks.push('finish:before');
|
||||
},
|
||||
page: function(page) {
|
||||
page.content = 'Hello ' + page.content;
|
||||
return page;
|
||||
}
|
||||
}
|
||||
};
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-hooks",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
module.exports = {
|
||||
book: {
|
||||
assets: './assets',
|
||||
js: [
|
||||
'myfile.js',
|
||||
'https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js'
|
||||
],
|
||||
css: [
|
||||
'myfile.css'
|
||||
]
|
||||
}
|
||||
};
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "gitbook-plugin-test-resources",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"gitbook": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
var EbookOutput = require('../lib/output/ebook');
|
||||
|
||||
describe('Ebook Output', function() {
|
||||
describe('Sample Book', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(EbookOutput)
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate an index.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
|
||||
it('should correctly generate a SUMMARY.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
|
||||
it('should correctly copy assets', function() {
|
||||
output.should.have.file('gitbook/ebook.css');
|
||||
});
|
||||
|
||||
it('should correctly copy plugins', function() {
|
||||
output.should.have.file('gitbook/gitbook-plugin-highlight/ebook.css');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
var JSONOutput = require('../lib/output/json');
|
||||
|
||||
describe('JSON Output', function() {
|
||||
|
||||
describe('Sample book', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(JSONOutput)
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate a README.json', function() {
|
||||
output.should.have.file('README.json');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Multilingual Book', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputBook(JSONOutput, {
|
||||
'LANGS.md': '# Languages\n\n'
|
||||
+ '* [en](./en)\n'
|
||||
+ '* [fr](./fr)\n\n',
|
||||
'en/README.md': '# Hello',
|
||||
'fr/README.md': '# Bonjour'
|
||||
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate a README.json for each language', function() {
|
||||
output.should.have.file('en/README.json');
|
||||
output.should.have.file('fr/README.json');
|
||||
});
|
||||
|
||||
it('should correctly add languages list to all json', function() {
|
||||
var jsonFR = require(output.resolve('fr/README.json'));
|
||||
var jsonEN = require(output.resolve('en/README.json'));
|
||||
|
||||
jsonFR.should.have.property('languages')
|
||||
.with.property('list').with.lengthOf(2);
|
||||
jsonEN.should.have.property('languages')
|
||||
.with.property('list').with.lengthOf(2);
|
||||
});
|
||||
|
||||
it('should correctly generate a README.json for the whole book', function() {
|
||||
output.should.have.file('README.json');
|
||||
var json = require(output.resolve('README.json'));
|
||||
|
||||
json.book.language.should.equal('en');
|
||||
|
||||
json.should.have.property('languages')
|
||||
.with.property('list').with.lengthOf(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
var fs = require('fs');
|
||||
|
||||
var mock = require('./mock');
|
||||
var WebsiteOutput = require('../lib/output/website');
|
||||
|
||||
describe('Website Output', function() {
|
||||
|
||||
describe('Sample Book', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(WebsiteOutput)
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate an index.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
|
||||
it('should correctly copy assets', function() {
|
||||
output.should.have.file('gitbook/gitbook.js');
|
||||
output.should.have.file('gitbook/theme.js');
|
||||
output.should.have.file('gitbook/images/favicon.ico');
|
||||
});
|
||||
|
||||
it('should correctly copy plugins', function() {
|
||||
output.should.have.file('gitbook/gitbook-plugin-highlight/website.css');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Book with chapters', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(WebsiteOutput, {
|
||||
'hello/README.md': '# Hello',
|
||||
'hello/test.md': '# Test'
|
||||
}, [
|
||||
{
|
||||
title: 'Hello',
|
||||
path: 'hello/README.md'
|
||||
},
|
||||
{
|
||||
title: 'Test',
|
||||
path: 'hello/test.md'
|
||||
}
|
||||
])
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate an index.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
|
||||
it('should correctly generate files in folder', function() {
|
||||
output.should.have.file('hello/index.html');
|
||||
output.should.have.file('hello/test.html');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Multilingual Book', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputBook(WebsiteOutput, {
|
||||
'LANGS.md': '# Languages\n\n'
|
||||
+ '* [en](./en)\n'
|
||||
+ '* [fr](./fr)\n\n',
|
||||
'en/README.md': '# Hello',
|
||||
'fr/README.md': '# Bonjour'
|
||||
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly generate an index.html for each language', function() {
|
||||
output.should.have.file('en/index.html');
|
||||
output.should.have.file('fr/index.html');
|
||||
});
|
||||
|
||||
it('should correctly copy assets', function() {
|
||||
output.should.have.file('gitbook/gitbook.js');
|
||||
output.should.have.file('gitbook/theme.js');
|
||||
});
|
||||
|
||||
it('should not copy assets for each language', function() {
|
||||
output.should.have.not.file('en/gitbook/gitbook.js');
|
||||
output.should.have.not.file('fr/gitbook/gitbook.js');
|
||||
|
||||
output.should.have.not.file('en/gitbook/theme.js');
|
||||
output.should.have.not.file('fr/gitbook/theme.js');
|
||||
});
|
||||
|
||||
it('should correctly generate an index.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Theming', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(WebsiteOutput, {
|
||||
'_layouts/website/page.html': '{% extends "website/page.html" %}{% block body %}{{ super() }}<div id="theming-added"></div>{% endblock %}'
|
||||
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should extend default theme', function() {
|
||||
var readme = fs.readFileSync(output.resolve('index.html'), 'utf-8');
|
||||
|
||||
readme.should.be.html({
|
||||
'#theming-added': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-431
@@ -1,431 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
var Output = require('../lib/output/base');
|
||||
|
||||
describe('Page', function() {
|
||||
var book, output;
|
||||
|
||||
before(function() {
|
||||
return mock.setupDefaultBook({
|
||||
'README.md': ' # Hello World\n\nThis is a description',
|
||||
'heading.md': '# Hello\n\n## World',
|
||||
'description.md': '# This is a title\n\nThis is the short description.\n\nAnd the rest of the description.\n\n# Heading\n\nThis is not in the description',
|
||||
'frontmatter/description.md': '---\ndescription: Hello World\n---\n\n# This is a title\n\nThis is not the description',
|
||||
'frontmatter/var.md': '---\ntest: Hello World\n---\n\n{{ page.test }}',
|
||||
|
||||
'links.md': '[link](hello.md) [link 2](variables/page/next.md) [readme](README.md)',
|
||||
'links/relative.md': '[link](../hello.md) [link 2](/variables/page/next.md) [readme](../README.md)',
|
||||
|
||||
'images.md': '  ',
|
||||
'images/relative.md': ' ',
|
||||
|
||||
'annotations/simple.md': 'A magicien say abracadabra!',
|
||||
'annotations/code.md': 'A magicien say `abracadabra`!',
|
||||
'annotations/class.md': 'A magicien say <div class="no-glossary"><b>abracadabra</b>, right?</div>!',
|
||||
|
||||
'codes/simple.md': '```hello world```',
|
||||
'codes/lang.md': '```js\nhello world\n```',
|
||||
'codes/lang.adoc': '```js\nhello world\n```',
|
||||
|
||||
'folder/paths.md': '',
|
||||
|
||||
'variables/file/mtime.md': '{{ file.mtime }}',
|
||||
'variables/file/path.md': '{{ file.path }}',
|
||||
'variables/page/title.md': '{{ page.title }}',
|
||||
'variables/page/previous.md': '{{ page.previous.title }} {{ page.previous.path }}',
|
||||
'variables/page/next.md': '{{ page.next.title }} {{ page.next.path }}',
|
||||
'variables/page/dir/ltr.md': 'This is english: {{ page.dir }}',
|
||||
'variables/page/dir/rtl.md': 'بسيطة {{ page.dir }}',
|
||||
'variables/config/title.md': '{{ config.title}}',
|
||||
'variables/gitbook/generator.md': '{{ gitbook.generator }}',
|
||||
|
||||
'GLOSSARY.md': '# Glossary\n\n\n## abracadabra\n\nthis is the description',
|
||||
|
||||
'blocks/markdown.md': 'Hello <span>{% markdown %}**World**{% endmarkdown %}</span>',
|
||||
'blocks/asciidoc.md': 'Hello <span>{% asciidoc %}^super^script phrase{% endasciidoc %}</span>'
|
||||
}, [
|
||||
{
|
||||
title: 'Test page.next',
|
||||
path: 'variables/page/next.md'
|
||||
},
|
||||
{
|
||||
title: 'Test Variables',
|
||||
path: 'variables/page/title.md'
|
||||
},
|
||||
{
|
||||
title: 'Test page.previous',
|
||||
path: 'variables/page/previous.md'
|
||||
}
|
||||
])
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
output = new Output(book);
|
||||
|
||||
return book.parse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.resolveLocal', function() {
|
||||
it('should correctly resolve path to file', function() {
|
||||
var page = book.addPage('heading.md');
|
||||
|
||||
page.resolveLocal('test.png').should.equal('test.png');
|
||||
page.resolveLocal('/test.png').should.equal('test.png');
|
||||
page.resolveLocal('test/hello.png').should.equal('test/hello.png');
|
||||
page.resolveLocal('/test/hello.png').should.equal('test/hello.png');
|
||||
});
|
||||
|
||||
it('should correctly resolve path to file (2)', function() {
|
||||
var page = book.addPage('folder/paths.md');
|
||||
|
||||
page.resolveLocal('test.png').should.equal('folder/test.png');
|
||||
page.resolveLocal('/test.png').should.equal('test.png');
|
||||
page.resolveLocal('test/hello.png').should.equal('folder/test/hello.png');
|
||||
page.resolveLocal('/test/hello.png').should.equal('test/hello.png');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.relative', function() {
|
||||
it('should correctly resolve absolute path in the book', function() {
|
||||
var page = book.addPage('heading.md');
|
||||
page.relative('/test.png').should.equal('test.png');
|
||||
page.relative('test.png').should.equal('test.png');
|
||||
|
||||
var page2 = book.addPage('folder/paths.md');
|
||||
page2.relative('/test.png').should.equal('../test.png');
|
||||
page2.relative('test.png').should.equal('../test.png');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.resolve', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
page = book.addPage('links/relative.md');
|
||||
});
|
||||
|
||||
it('should resolve to a relative path (same folder)', function() {
|
||||
page.relative('links/test.md').should.equal('test.md');
|
||||
});
|
||||
|
||||
it('should resolve to a relative path (parent folder)', function() {
|
||||
page.relative('test.md').should.equal('../test.md');
|
||||
page.relative('hello/test.md').should.equal('../hello/test.md');
|
||||
});
|
||||
|
||||
it('should resolve to a relative path (child folder)', function() {
|
||||
page.relative('links/hello/test.md').should.equal('hello/test.md');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Headings', function() {
|
||||
it('should add a default ID to headings', function() {
|
||||
var page = book.addPage('heading.md');
|
||||
|
||||
return page.toHTML(output)
|
||||
.then(function() {
|
||||
page.content.should.be.html({
|
||||
'h1#hello': {
|
||||
count: 1
|
||||
},
|
||||
'h2#world': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Description', function() {
|
||||
it('should extract page description from content', function() {
|
||||
var page = book.addPage('description.md');
|
||||
|
||||
return page.toHTML(output)
|
||||
.then(function() {
|
||||
page.attributes.description.should.equal('This is the short description. And the rest of the description.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Font-Matter', function() {
|
||||
it('should extract page description from front matter', function() {
|
||||
var page = book.addPage('frontmatter/description.md');
|
||||
|
||||
return page.toHTML(output)
|
||||
.then(function() {
|
||||
page.attributes.description.should.equal('Hello World');
|
||||
});
|
||||
});
|
||||
|
||||
it('should extend page attributes with custom properties', function() {
|
||||
var page = book.addPage('frontmatter/var.md');
|
||||
|
||||
return page.toHTML(output)
|
||||
.then(function() {
|
||||
page.content.should.equal('<p>Hello World</p>\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Code Blocks', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
output.template.addBlock('code', function(blk) {
|
||||
return (blk.kwargs.language || '') + blk.body + 'test';
|
||||
});
|
||||
});
|
||||
|
||||
it('should apply "code" block', function() {
|
||||
page = book.addPage('codes/simple.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p><code>hello worldtest</code></p>\n');
|
||||
});
|
||||
|
||||
it('should add language as kwargs', function() {
|
||||
page = book.addPage('codes/lang.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<pre><code class="lang-js">jshello world\ntest</code></pre>\n');
|
||||
});
|
||||
|
||||
it('should add language as kwargs (asciidoc)', function() {
|
||||
page = book.addPage('codes/lang.adoc');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<div class="listingblock">\n<div class="content">\n<pre class="highlight"><code class="language-js" data-lang="js">jshello worldtest</code></pre>\n</div>\n</div>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Links', function() {
|
||||
describe('From base directory', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
page = book.addPage('links.md');
|
||||
return page.toHTML(output);
|
||||
});
|
||||
|
||||
it('should replace links to page to .html', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="variables/page/next.html"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should use directory urls when file is a README', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="./"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not replace links to file not in SUMMARY', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="hello.md"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('From sub-directory', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
page = book.addPage('links/relative.md');
|
||||
return page.toHTML(output);
|
||||
});
|
||||
|
||||
it('should replace links to page to .html', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="../variables/page/next.html"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should use directory urls when file is a README', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="../"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not replace links to file not in SUMMARY', function() {
|
||||
page.content.should.be.html({
|
||||
'a[href="../hello.md"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Images', function() {
|
||||
describe('From base directory', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
page = book.addPage('images.md');
|
||||
return page.toHTML(output);
|
||||
});
|
||||
|
||||
it('should resolve relative images', function() {
|
||||
page.content.should.be.html({
|
||||
'img[src="test.png"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve absolute images', function() {
|
||||
page.content.should.be.html({
|
||||
'img[src="test2.png"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should keep external images path', function() {
|
||||
page.content.should.be.html({
|
||||
'img[src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('From sub-directory', function() {
|
||||
var page;
|
||||
|
||||
before(function() {
|
||||
page = book.addPage('images/relative.md');
|
||||
return page.toHTML(output);
|
||||
});
|
||||
|
||||
it('should resolve relative images', function() {
|
||||
page.content.should.be.html({
|
||||
'img[src="test.png"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve absolute images', function() {
|
||||
page.content.should.be.html({
|
||||
'img[src="../test2.png"]': {
|
||||
count: 1
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Templating Context', function() {
|
||||
it('should set file.mtime', function() {
|
||||
var page = book.addPage('variables/file/mtime.md');
|
||||
return page.toHTML(output)
|
||||
.then(function(content) {
|
||||
// A date ends with "(CET)" or "(UTC)""
|
||||
content.should.endWith(')</p>\n');
|
||||
});
|
||||
});
|
||||
|
||||
it('should set file.path', function() {
|
||||
var page = book.addPage('variables/file/path.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>variables/file/path.md</p>\n');
|
||||
});
|
||||
|
||||
it('should set page.title when page is in summary', function() {
|
||||
var page = book.getPage('variables/page/title.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>Test Variables</p>\n');
|
||||
});
|
||||
|
||||
it('should set page.previous when possible', function() {
|
||||
var page = book.getPage('variables/page/previous.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>Test Variables variables/page/title.md</p>\n');
|
||||
});
|
||||
|
||||
it('should set page.next when possible', function() {
|
||||
var page = book.getPage('variables/page/next.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>Test Variables variables/page/title.md</p>\n');
|
||||
});
|
||||
|
||||
it('should set config.title', function() {
|
||||
var page = book.addPage('variables/config/title.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>Hello World</p>\n');
|
||||
});
|
||||
|
||||
it('should set gitbook.generator', function() {
|
||||
var page = book.addPage('variables/gitbook/generator.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>base</p>\n');
|
||||
});
|
||||
|
||||
describe('page.dir', function() {
|
||||
it('should detect ltr', function() {
|
||||
var page = book.addPage('variables/page/dir/ltr.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>This is english: ltr</p>\n');
|
||||
});
|
||||
|
||||
it('should detect rtl', function() {
|
||||
var page = book.addPage('variables/page/dir/rtl.md');
|
||||
return page.toHTML(output)
|
||||
.should.be.fulfilledWith('<p>بسيطة rtl</p>\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Annotations / Glossary', function() {
|
||||
it('should replace glossary terms', function() {
|
||||
return book.addPage('annotations/simple.md').toHTML(output)
|
||||
.should.finally.be.html({
|
||||
'.glossary-term': {
|
||||
count: 1,
|
||||
text: 'abracadabra',
|
||||
attributes: {
|
||||
title: 'this is the description',
|
||||
href: '../GLOSSARY.html#abracadabra'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not replace terms in code blocks', function() {
|
||||
return book.addPage('annotations/code.md').toHTML(output)
|
||||
.should.finally.be.html({
|
||||
'.glossary-term': {
|
||||
count: 0
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not replace terms in ".no-glossary"', function() {
|
||||
return book.addPage('annotations/class.md').toHTML(output)
|
||||
.should.finally.be.html({
|
||||
'.glossary-term': {
|
||||
count: 0
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Default Blocks', function() {
|
||||
it('should render block "markdown"', function() {
|
||||
return book.addPage('blocks/markdown.md').toHTML(output)
|
||||
.should.finally.equal('<p>Hello <span><strong>World</strong></span></p>\n');
|
||||
});
|
||||
|
||||
it('should render block "asciidoc"', function() {
|
||||
return book.addPage('blocks/asciidoc.md').toHTML(output)
|
||||
.should.finally.equal('<p>Hello <span><sup>super</sup>script phrase</span></p>\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Parsing', function() {
|
||||
it('should not fail without SUMMARY', function() {
|
||||
return mock.setupBook({
|
||||
'README.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.parse().should.be.fulfilled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail without README', function() {
|
||||
return mock.setupBook({
|
||||
'SUMMARY.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.parse().should.be.rejected;
|
||||
});
|
||||
});
|
||||
|
||||
it('should add GLOSSARY as a page', function() {
|
||||
return mock.setupDefaultBook({
|
||||
'GLOSSARY.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.parse()
|
||||
.then(function() {
|
||||
book.hasPage('GLOSSARY.md').should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Multilingual book', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupBook({
|
||||
'LANGS.md': '# Languages\n\n'
|
||||
+ '* [English](./en)\n'
|
||||
+ '* [French](./fr)\n\n',
|
||||
'en/README.md': '# English',
|
||||
'en/SUMMARY.md': '# Summary',
|
||||
'fr/README.md': '# French',
|
||||
'fr/SUMMARY.md': '# Summary'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
return book.parse();
|
||||
});
|
||||
});
|
||||
|
||||
it('should list language books', function() {
|
||||
book.isMultilingual().should.equal(true);
|
||||
book.books.should.have.lengthOf(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
var path = require('path');
|
||||
var pathUtils = require('../lib/utils/path');
|
||||
|
||||
describe('Paths', function() {
|
||||
|
||||
describe('setExtension', function() {
|
||||
it('should correctly change extension of filename', function() {
|
||||
pathUtils.setExtension('test.md', '.html').should.be.equal('test.html');
|
||||
pathUtils.setExtension('test.md', '.json').should.be.equal('test.json');
|
||||
});
|
||||
|
||||
it('should correctly change extension of path', function() {
|
||||
pathUtils.setExtension('hello/test.md', '.html').should.be.equal(path.normalize('hello/test.html'));
|
||||
pathUtils.setExtension('hello/test.md', '.json').should.be.equal(path.normalize('hello/test.json'));
|
||||
});
|
||||
});
|
||||
});
|
||||
-271
@@ -1,271 +0,0 @@
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
|
||||
var mock = require('./mock');
|
||||
var registry = require('../lib/plugins/registry');
|
||||
var Output = require('../lib/output/base');
|
||||
var PluginsManager = require('../lib/plugins');
|
||||
var BookPlugin = require('../lib/plugins/plugin');
|
||||
var JSONOutput = require('../lib/output/json');
|
||||
|
||||
var PLUGINS_ROOT = path.resolve(__dirname, 'node_modules');
|
||||
|
||||
function TestPlugin(book, name) {
|
||||
return new BookPlugin(book, name, path.resolve(PLUGINS_ROOT, 'gitbook-plugin-'+name));
|
||||
}
|
||||
|
||||
describe('Plugins', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupBook({})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Resolve Version', function() {
|
||||
it('should resolve a plugin version', function() {
|
||||
return registry.resolve('ga')
|
||||
.should.be.fulfilled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Installation', function() {
|
||||
it('should install a plugin from NPM without a specific version', function() {
|
||||
return registry.install(book, 'ga')
|
||||
.should.be.fulfilled();
|
||||
});
|
||||
|
||||
it('should install a plugin from NPM with a specific version', function() {
|
||||
return registry.install(book, 'ga', '1.0.0')
|
||||
.should.be.fulfilled();
|
||||
});
|
||||
|
||||
it('should correctly install all dependencies (if none)', function() {
|
||||
return mock.setupBook({})
|
||||
.then(function(book) {
|
||||
var plugins = new PluginsManager(book);
|
||||
return plugins.install()
|
||||
.should.be.fulfilledWith(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly install all dependencies (if any)', function() {
|
||||
return mock.setupBook({
|
||||
'book.json': {
|
||||
plugins: ['ga']
|
||||
}
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
.then(function() {
|
||||
var plugins = new PluginsManager(book);
|
||||
return plugins.install();
|
||||
});
|
||||
})
|
||||
.should.be.fulfilledWith(1);
|
||||
});
|
||||
|
||||
it('should correctly install dependencies from GitHub', function() {
|
||||
return mock.setupBook({
|
||||
'book.json': {
|
||||
plugins: ['ga@git+https://github.com/GitbookIO/plugin-ga#master']
|
||||
}
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
.then(function() {
|
||||
var plugins = new PluginsManager(book);
|
||||
return plugins.install();
|
||||
});
|
||||
})
|
||||
.should.be.fulfilledWith(1);
|
||||
});
|
||||
|
||||
// This test requires a SSH key, we only run it locally
|
||||
if (!process.env.CI) {
|
||||
it('should correctly install dependencies from GitHub via ssh', function() {
|
||||
return mock.setupBook({
|
||||
'book.json': {
|
||||
plugins: ['ga@git@github.com:GitbookIO/plugin-ga.git#master']
|
||||
}
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
.then(function() {
|
||||
var plugins = new PluginsManager(book);
|
||||
return plugins.install();
|
||||
});
|
||||
})
|
||||
.should.be.fulfilledWith(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Loading', function() {
|
||||
it('should load default plugins', function() {
|
||||
return mock.outputDefaultBook(Output)
|
||||
.then(function(output) {
|
||||
output.plugins.count().should.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Configuration', function() {
|
||||
it('should fail loading a plugin with an invalid configuration', function() {
|
||||
var plugin = TestPlugin(book, 'test-config');
|
||||
return plugin.load(PLUGINS_ROOT)
|
||||
.should.be.rejectedWith('Error with book\'s configuration: pluginsConfig.test-config.myProperty is required');
|
||||
});
|
||||
|
||||
it('should extend configuration with default properties', function() {
|
||||
return mock.setupBook({
|
||||
'book.json': {
|
||||
pluginsConfig: {
|
||||
'test-config': {
|
||||
'myProperty': 'world'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(function(book2) {
|
||||
return book2.prepareConfig()
|
||||
.then(function() {
|
||||
var plugin = TestPlugin(book2, 'test-config');
|
||||
return plugin.load(PLUGINS_ROOT);
|
||||
})
|
||||
.then(function() {
|
||||
book2.config.get('pluginsConfig.test-config.myDefaultProperty', '').should.equal('hello');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Resources', function() {
|
||||
var plugin;
|
||||
|
||||
before(function() {
|
||||
plugin = TestPlugin(book, 'test-resources');
|
||||
return plugin.load(PLUGINS_ROOT);
|
||||
});
|
||||
|
||||
|
||||
it('should list all resources for website', function() {
|
||||
return plugin.getResources('website')
|
||||
.then(function(resources) {
|
||||
resources.assets.should.equal('./assets');
|
||||
|
||||
resources.js.should.have.lengthOf(2);
|
||||
resources.js[0].path.should.equal('gitbook-plugin-test-resources/myfile.js');
|
||||
resources.js[1].url.should.equal('https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js');
|
||||
|
||||
resources.css.should.have.lengthOf(1);
|
||||
resources.css[0].path.should.equal('gitbook-plugin-test-resources/myfile.css');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Filters', function() {
|
||||
var plugin, filters;
|
||||
|
||||
before(function() {
|
||||
plugin = TestPlugin(book, 'test-filters');
|
||||
return plugin.load(PLUGINS_ROOT)
|
||||
|
||||
.then(function() {
|
||||
filters = plugin.getFilters();
|
||||
});
|
||||
});
|
||||
|
||||
it('should list all filters', function() {
|
||||
_.size(filters).should.equal(2);
|
||||
});
|
||||
|
||||
it('should correctly execute a filter', function() {
|
||||
filters.hello('World').should.equal('Hello World!');
|
||||
});
|
||||
|
||||
it('should correctly set contexts for filter', function() {
|
||||
filters.testContext('Hello');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Blocks', function() {
|
||||
var plugin, blocks;
|
||||
|
||||
before(function() {
|
||||
plugin = TestPlugin(book, 'test-blocks');
|
||||
return plugin.load(PLUGINS_ROOT)
|
||||
|
||||
.then(function() {
|
||||
blocks = plugin.getBlocks();
|
||||
});
|
||||
});
|
||||
|
||||
it('should list all blocks', function() {
|
||||
_.size(blocks).should.equal(2);
|
||||
});
|
||||
|
||||
it('should correctly normalize block', function() {
|
||||
blocks.hello.process({ body: 'World' }).should.equal('Hello World!');
|
||||
});
|
||||
|
||||
it('should correctly set contexts for filter', function() {
|
||||
blocks.testContext.process({ body: 'Hello' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('Hooks', function() {
|
||||
var plugin;
|
||||
|
||||
before(function() {
|
||||
plugin = TestPlugin(book, 'test-hooks');
|
||||
return plugin.load(PLUGINS_ROOT);
|
||||
});
|
||||
|
||||
it('can call a hook', function() {
|
||||
return plugin.hook('init')
|
||||
.then(function() {
|
||||
global._hooks.should.deepEqual(['init']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('Hook "page"', function() {
|
||||
var pluginDeprecated;
|
||||
|
||||
before(function() {
|
||||
pluginDeprecated = TestPlugin(book, 'test-deprecated');
|
||||
return pluginDeprecated.load(PLUGINS_ROOT);
|
||||
});
|
||||
|
||||
it('should update content using "content" property', function() {
|
||||
return mock.setupDefaultOutput(JSONOutput)
|
||||
.then(function(output) {
|
||||
output.plugins.load(plugin);
|
||||
|
||||
return output.generate()
|
||||
.then(function() {
|
||||
var json = require(output.resolve('README.json'));
|
||||
json.page.content.should.equal('Hello <p>Hello</p>\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update content using deprecated "sections" property', function() {
|
||||
return mock.setupDefaultOutput(JSONOutput)
|
||||
.then(function(output) {
|
||||
output.plugins.load(pluginDeprecated);
|
||||
|
||||
return output.generate()
|
||||
.then(function() {
|
||||
var json = require(output.resolve('README.json'));
|
||||
json.page.content.should.equal('Hello (sections) <p>Hello</p>\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
|
||||
describe('Readme', function() {
|
||||
it('should parse empty readme', function() {
|
||||
return mock.setupDefaultBook({
|
||||
'README.md': ''
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.prepareConfig()
|
||||
|
||||
.then(function() {
|
||||
return book.readme.load();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse readme', function() {
|
||||
return mock.setupDefaultBook({
|
||||
'README.md': '# Hello World\nThis is my book'
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.readme.load()
|
||||
.then(function() {
|
||||
book.readme.title.should.equal('Hello World');
|
||||
book.readme.description.should.equal('This is my book');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse AsciiDoc readme', function() {
|
||||
return mock.setupBook({
|
||||
'README.adoc': '# Hello World\n\nThis is my book\n'
|
||||
})
|
||||
.then(function(book) {
|
||||
return book.readme.load()
|
||||
.then(function() {
|
||||
book.readme.title.should.equal('Hello World');
|
||||
book.readme.description.should.equal('This is my book');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
var fs = require('fs');
|
||||
|
||||
var mock = require('./mock');
|
||||
var WebsiteOutput = require('../lib/output/website');
|
||||
|
||||
/*
|
||||
|
||||
Testing using configuration "structure" to use custom Readme/Summary/Glossary paths
|
||||
*/
|
||||
|
||||
describe('Structure', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputBook(WebsiteOutput, {
|
||||
'book.json': {
|
||||
structure: {
|
||||
readme: 'intro.md'
|
||||
}
|
||||
},
|
||||
'SUMMARY.md': '* [Test](test.md)',
|
||||
'intro.md': 'This is the intro',
|
||||
'test.md': 'Go to [intro](intro.md)'
|
||||
})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate index.html', function() {
|
||||
output.should.have.file('index.html');
|
||||
});
|
||||
|
||||
it('should generate test.html', function() {
|
||||
output.should.have.file('test.html');
|
||||
});
|
||||
|
||||
it('should correctly resolve link to Readme', function() {
|
||||
var readme = fs.readFileSync(output.resolve('test.html'), 'utf-8');
|
||||
|
||||
readme.should.be.html({
|
||||
'.page-inner a': {
|
||||
count: 1,
|
||||
text: 'intro',
|
||||
attributes: {
|
||||
href: './'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
-328
@@ -1,328 +0,0 @@
|
||||
var should = require('should');
|
||||
|
||||
var mock = require('./mock');
|
||||
|
||||
function mockSummary(files, summary) {
|
||||
return mock.setupDefaultBook(files, summary)
|
||||
.then(function(book) {
|
||||
return book.readme.load()
|
||||
.then(function() {
|
||||
return book.summary.load();
|
||||
})
|
||||
.thenResolve(book);
|
||||
});
|
||||
}
|
||||
|
||||
describe('Summary / Table of contents', function() {
|
||||
describe('Empty summary list', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should add README as first entry', function() {
|
||||
should(book.summary.getArticle('README.md')).be.ok();
|
||||
});
|
||||
|
||||
it('should correctly count articles', function() {
|
||||
book.summary.count().should.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Non-existant summary', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mock.setupBook({
|
||||
'README.md': 'Hello'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
|
||||
return book.readme.load()
|
||||
.then(function() {
|
||||
return book.summary.load();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should add README as first entry', function() {
|
||||
should(book.summary.getArticle('README.md')).be.ok();
|
||||
});
|
||||
|
||||
it('should correctly count articles', function() {
|
||||
book.summary.count().should.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Unicode summary', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({
|
||||
'SUMMARY.md': '# Summary\n\n'
|
||||
+ '* [Hello](./hello world.md)\n'
|
||||
+ '* [Spanish](./Descripción del problema.md)\n\n'
|
||||
+ '* [Chinese](读了这本书.md)\n\n'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should accept article with spaces', function() {
|
||||
should(book.summary.getArticle('hello world.md')).be.ok();
|
||||
});
|
||||
|
||||
it('should accept article with chinese filename', function() {
|
||||
should(book.summary.getArticle('读了这本书.md')).be.ok();
|
||||
});
|
||||
|
||||
it('should accept article with accents', function() {
|
||||
should(book.summary.getArticle('Descripción del problema.md')).be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Non-empty summary list', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({
|
||||
'SUMMARY.md': '# Summary\n\n'
|
||||
+ '* [Hello](./hello.md)\n'
|
||||
+ '* [World](./world.md)\n\n'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly count articles', function() {
|
||||
book.summary.count().should.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Levels', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({
|
||||
'SUMMARY.md': '# Summary\n\n'
|
||||
+ '* [Hello](./hello.md)\n'
|
||||
+ ' * [Hello 2](./hello2.md)\n'
|
||||
+ '* [World](./world.md)\n\n'
|
||||
+ '## Part 2\n\n'
|
||||
+ '* [Hello 3](./hello.md)\n'
|
||||
+ ' * [Hello 4](./hello2.md)\n'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly index levels', function() {
|
||||
book.summary.getArticleByLevel('0').title.should.equal('Introduction');
|
||||
book.summary.getArticleByLevel('1.1').title.should.equal('Hello');
|
||||
book.summary.getArticleByLevel('1.1.1').title.should.equal('Hello 2');
|
||||
book.summary.getArticleByLevel('1.2').title.should.equal('World');
|
||||
|
||||
book.summary.getArticleByLevel('2.1').title.should.equal('Hello 3');
|
||||
book.summary.getArticleByLevel('2.1.1').title.should.equal('Hello 4');
|
||||
});
|
||||
|
||||
it('should correctly calcul depth', function() {
|
||||
book.summary.getArticleByLevel('0').depth().should.equal(1);
|
||||
book.summary.getArticleByLevel('1.1').depth().should.equal(2);
|
||||
book.summary.getArticleByLevel('1.1.1').depth().should.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('External', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({}, [
|
||||
{
|
||||
title: 'Google',
|
||||
path: 'https://www.google.fr'
|
||||
}
|
||||
])
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly count articles', function() {
|
||||
book.summary.count().should.equal(2);
|
||||
});
|
||||
|
||||
it('should correctly signal it as external', function() {
|
||||
var article = book.summary.getArticleByLevel('1');
|
||||
|
||||
should(article).be.ok();
|
||||
should(article.path).not.be.ok();
|
||||
|
||||
article.title.should.equal('Google');
|
||||
article.ref.should.equal('https://www.google.fr');
|
||||
article.isExternal().should.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Next / Previous', function() {
|
||||
var book;
|
||||
|
||||
before(function() {
|
||||
return mockSummary({
|
||||
'SUMMARY.md': '# Summary\n\n' +
|
||||
'* [Hello](hello.md)\n' +
|
||||
'* [Hello 2](hello2.md)\n' +
|
||||
' * [Hello 3](hello3.md)\n' +
|
||||
' * [Hello 4](hello4.md)\n' +
|
||||
' * [Hello 5](hello5.md)\n' +
|
||||
'* [Hello 6](hello6.md)\n\n\n' +
|
||||
'### Part 2\n\n' +
|
||||
'* [Hello 7](hello7.md)\n' +
|
||||
' * [Hello 8](hello8.md)\n\n' +
|
||||
'### Part 3\n\n' +
|
||||
'* [Hello 9](hello9.md)\n' +
|
||||
'* [Hello 10](hello10.md)\n\n'
|
||||
})
|
||||
.then(function(_book) {
|
||||
book = _book;
|
||||
});
|
||||
});
|
||||
|
||||
it('should only return a next for the readme', function() {
|
||||
var article = book.summary.getArticle('README.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).not.be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
next.path.should.equal('hello.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a first level page', function() {
|
||||
var article = book.summary.getArticle('hello.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('README.md');
|
||||
next.path.should.equal('hello2.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a joint -> child', function() {
|
||||
var article = book.summary.getArticle('hello2.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello.md');
|
||||
next.path.should.equal('hello3.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a joint <- child', function() {
|
||||
var article = book.summary.getArticle('hello3.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello2.md');
|
||||
next.path.should.equal('hello4.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a children', function() {
|
||||
var article = book.summary.getArticle('hello4.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello3.md');
|
||||
next.path.should.equal('hello5.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a joint -> parent', function() {
|
||||
var article = book.summary.getArticle('hello5.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello4.md');
|
||||
next.path.should.equal('hello6.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a joint -> parts', function() {
|
||||
var article = book.summary.getArticle('hello6.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello5.md');
|
||||
next.path.should.equal('hello7.md');
|
||||
});
|
||||
|
||||
it('should return next/prev for a joint <- parts', function() {
|
||||
var article = book.summary.getArticle('hello7.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello6.md');
|
||||
next.path.should.equal('hello8.md');
|
||||
});
|
||||
|
||||
it('should return next and prev', function() {
|
||||
var article = book.summary.getArticle('hello8.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.ok();
|
||||
|
||||
prev.path.should.equal('hello7.md');
|
||||
next.path.should.equal('hello9.md');
|
||||
});
|
||||
|
||||
it('should return only prev for last', function() {
|
||||
var article = book.summary.getArticle('hello10.md');
|
||||
|
||||
var prev = article.prev();
|
||||
var next = article.next();
|
||||
|
||||
should(prev).be.ok();
|
||||
should(next).be.not.ok();
|
||||
|
||||
prev.path.should.equal('hello9.md');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
var mock = require('./mock');
|
||||
var Output = require('../lib/output/base');
|
||||
|
||||
describe('Template', function() {
|
||||
var output;
|
||||
|
||||
before(function() {
|
||||
return mock.outputDefaultBook(Output, {})
|
||||
.then(function(_output) {
|
||||
output = _output;
|
||||
});
|
||||
});
|
||||
|
||||
describe('.renderString', function() {
|
||||
it('should render a simple string', function() {
|
||||
return output.template.renderString('Hello World')
|
||||
.should.be.fulfilledWith('Hello World');
|
||||
});
|
||||
|
||||
it('should render with variable', function() {
|
||||
return output.template.renderString('Hello {{ world }}', { world: 'World'})
|
||||
.should.be.fulfilledWith('Hello World');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Blocks', function() {
|
||||
it('should correctly add a block', function() {
|
||||
output.template.addBlock('sayhello', function(blk) {
|
||||
return 'Hello ' + blk.body + '!';
|
||||
});
|
||||
|
||||
return output.template.renderString('{% sayhello %}World{% endsayhello %}')
|
||||
.should.be.fulfilledWith('Hello World!');
|
||||
});
|
||||
|
||||
it('should correctly add a block with args', function() {
|
||||
output.template.addBlock('sayhello_args', function(blk) {
|
||||
return 'Hello ' + blk.args[0] + '!';
|
||||
});
|
||||
|
||||
return output.template.renderString('{% sayhello_args "World" %}{% endsayhello_args %}')
|
||||
.should.be.fulfilledWith('Hello World!');
|
||||
});
|
||||
|
||||
it('should correctly add a block with kwargs', function() {
|
||||
output.template.addBlock('sayhello_kwargs', function(blk) {
|
||||
return 'Hello ' + blk.kwargs.name + '!';
|
||||
});
|
||||
|
||||
return output.template.renderString('{% sayhello_kwargs name="World" %}{% endsayhello_kwargs %}')
|
||||
.should.be.fulfilledWith('Hello World!');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user