Compare commits

...

49 Commits

Author SHA1 Message Date
Samy Pessé 7b4accb117 Bump version to 1.3.4 2014-11-25 18:55:33 +01:00
Samy Pessé d6437d31d4 Omit "generator" when building file with config file 2014-11-25 18:53:02 +01:00
Samy Pessé 3dd33f1f3c Merge pull request #502 from tonka3000/X-UA-Compatible-tag
add X-UA-Compatible meta tag for IE
2014-11-25 15:20:14 +01:00
Samy Pessé 3a0f00411b Fix #505: add glossary to ebook file 2014-11-24 22:08:19 +01:00
Samy Pessé 5b655bb29a Fx typo 2014-11-24 21:56:33 +01:00
Samy Pessé faf10605e8 Add hook finish:before 2014-11-24 21:41:50 +01:00
Samy Pessé 5c98b3350b Merge pull request #503 from jr0cket/ebook-command-fix
updated eBook generation commands - resolves #432
2014-11-22 16:41:19 +01:00
John Stevenson 6f4e1d10c1 made commands clearer by seperating output filename option 2014-11-22 14:47:12 +00:00
John Stevenson 870886599a updated eBook generation commands 2014-11-22 11:26:08 +00:00
Michael Aigner 1b9801b8a4 add X-UA-Compatible meta tag for IE (https://github.com/GitbookIO/gitbook/issues/501) 2014-11-20 10:16:40 +01:00
Samy Pessé 897463b22e Bump version to 1.3.3 2014-11-14 22:10:19 +01:00
Samy Pessé aa4894e94c Fix parsing of already lexed content 2014-11-14 22:09:30 +01:00
Samy Pessé 8a0180ae6b Bump version to 1.3.2 2014-11-14 18:53:57 +01:00
Samy Pessé d6776b98d3 Fix bundle task 2014-11-14 18:53:48 +01:00
Samy Pessé 6a04ba89a5 Update gitbook bundle 2014-11-14 18:53:39 +01:00
Samy Pessé 05eaeeb0d0 Fix #441: Improve validity of epub output 2014-11-13 08:34:35 +01:00
Samy Pessé 77043464b2 Fix #496: improve replacement of glossary terms in html 2014-11-12 22:10:38 +01:00
Samy Pessé b90f74a821 Merge pull request #494 from cnDelbert/master
Bug fix for issue#493: 2-level or more deep relative links go wrong when in win32
2014-11-12 19:06:33 +01:00
Aaron O'Mullan f804eb42ac Merge pull request #495 from romanlytkin/patch-1
Update README.md
2014-11-07 15:58:18 +01:00
romanlytkin 74fd8c159b Update README.md
Hi, i add 2 new plugins for gitbook, I hope it will be useful to someone.
2014-11-07 17:37:27 +03:00
Delbert a741ec1350 Bug fix for issue #493: 2-level or more deep relative links may go wrong when in win32 2014-11-06 15:50:59 +08:00
Samy Pessé 4b26c31b3b Remove unnecessary option "repo" from tests 2014-11-03 17:43:44 +01:00
Samy Pessé dfd487692a Adapt new page.parse api for tests 2014-11-03 17:40:38 +01:00
Samy Pessé 195374ecee Merge pull request #489 from codepiano/fork
bugfix,init page object's lexed attribute.
2014-11-03 17:29:54 +01:00
Samy Pessé 1659778a77 Bump version to 1.3.1 2014-11-03 16:58:37 +01:00
Samy Pessé 40c4035afb Fix #491: handle correctly url without path for links 2014-11-03 16:57:35 +01:00
codepiano 1502d65286 Merge branch 'master' of github.com:GitbookIO/gitbook into fork
Conflicts:
	lib/parse/page.js
2014-11-02 01:34:28 +08:00
Samy Pessé 0feb672d70 Bump version to 1.3.0 2014-11-01 15:36:10 +01:00
Samy Pessé 2a4ef5bbf4 Fix dependency in renderer 2014-11-01 15:21:16 +01:00
Samy Pessé c4540332a7 Bundle gitbook parser as a client side library 2014-11-01 15:09:58 +01:00
Samy Pessé 2104404cb3 Remove dependency for path in parser 2014-11-01 15:09:41 +01:00
Samy Pessé 002d685ebb Adapt include in page parsing to works on clientside 2014-11-01 15:00:13 +01:00
codepiano 9da10e2b25 bugfix,init page object's lexed attribute.
the page object's attribute 'lexed' is not correctly inited.so when
use page.lexed to generate the search index file,nothing will be
indexed.
2014-10-31 18:00:09 +08:00
Samy Pessé 1e4632080b Bump version to 1.2.0 2014-10-30 18:27:56 +01:00
Samy Pessé 5191106396 Update documentation in readme 2014-10-30 18:27:26 +01:00
Samy Pessé 6ab5cafaf3 Improve toc in ebook (Fixes #338, #322) 2014-10-30 18:14:06 +01:00
Samy Pessé d1c0cb9c71 Normalize template paths 2014-10-30 18:01:56 +01:00
Samy Pessé 38c750101c Fix #487: Use generated toc as base for ebook generation 2014-10-30 17:52:39 +01:00
Samy Pessé ba0f379a89 Add plugin infinitescroll 2014-10-30 16:19:19 +01:00
Samy Pessé 1d9509b3b6 Merge pull request #485 from citizenmatt/Nested_list_spacing
Fix bottom border on nested ul
2014-10-30 14:15:54 +01:00
Samy Pessé 3c8de4a8ab Add 'variables' to book.json doc 2014-10-29 17:20:30 +01:00
Samy Pessé 591d8fc9ee Use book.json to store variables 2014-10-29 17:19:19 +01:00
Samy Pessé d480e9cea4 Update highlight.js@8.3.0 2014-10-23 17:05:27 +02:00
Matt Ellis 32a71869da Fix bottom border on nested ul 2014-10-23 09:19:02 +01:00
Samy Pessé fdbfda64a6 Merge pull request #483 from dharmeshkakadia/patch-1
Corrected a small typo in Plugins description
2014-10-21 15:45:45 +02:00
Dharmesh Kakadia a6f48be39e Corrected a small typo in Plugins description 2014-10-21 00:47:37 +05:30
Aaron O'Mullan ce50b893e9 Merge pull request #482 from GitbookIO/feature/includes
Add include support, with variables and the whole shebang
2014-10-15 21:29:23 +02:00
Aaron O'Mullan 225ff27dd1 Fix small incompatibility mistake 2014-10-15 21:28:53 +02:00
Aaron O'Mullan 52e8361846 Add include support, with variables and the whole shebang
Fixes #462
2014-10-15 21:20:10 +02:00
44 changed files with 21110 additions and 168 deletions
+27
View File
@@ -1,5 +1,32 @@
# Release notes
## 1.3.4
- Add glossary to ebooks
- Fix autocover with new hook "finish:before"
- Add X-UA-Compatible meta tag for IE
## 1.3.3
- Fix parsing of lexed content using the client library
## 1.3.2
- ePub files are now passing validation from epubcheck
- Fix replacement of multiple glossary terms in a single sentence
- Fix on windows deep relative links
- Fix search indexer
## 1.3.1
- Fix error with links in markdown
## 1.3.0
- Bundle gitbook parsing library as a client side library in `gitbook.js` and `gitbook.min.js`
## 1.2.0
- Improvements on ebook generation
- Fix incorrect follow of links in ebook generation
- Move Table of Contents at the beginning of the ebook
- Update to last highlight.js (includes Swift)
- Includes of templates and variables (from book.json)
## 1.1.1
- Rewrite quiz logic to be more robust
- Improve integration of glossary
+34 -1
View File
@@ -6,6 +6,8 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks("grunt-bower-install-simple");
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Init GRUNT configuraton
grunt.initConfig({
@@ -77,6 +79,30 @@ module.exports = function (grunt) {
}
]
}
},
browserify: {
dist: {
files: {
'gitbook.js': [
'./lib/parse/index.js'
],
},
options: {
postBundleCB: function (err, src, next) {
return next(null, '(function () { var define = undefined; '+src+'; })();')
},
browserifyOptions: {
'standalone': "gitbook"
}
}
}
},
uglify: {
dist: {
files: {
'gitbook.min.js': ['gitbook.js']
}
}
}
});
@@ -90,7 +116,14 @@ module.exports = function (grunt) {
'copy:vendors'
]);
// Bundle the library
grunt.registerTask('bundle', [
'browserify',
'uglify'
]);
grunt.registerTask('default', [
'build'
'build',
'bundle'
]);
};
+11 -5
View File
@@ -74,6 +74,9 @@ Here are the options that can be stored in this file:
}
},
// Variables for templating
"variables": {},
// Links in template (null: default, false: remove, string: new value)
"links": {
// Custom links at top of sidebar
@@ -94,9 +97,6 @@ Here are the options that can be stored in this file:
// Options for PDF generation
"pdf": {
// Add toc at the end of the file
"toc": true,
// Add page numbers to the bottom of every page
"pageNumbers": false,
@@ -132,7 +132,10 @@ You can publish your books to our index by visiting [GitBook.io](http://www.gitb
GitBook can generate your book in the following formats:
* **Static Website**: This is the default format. It generates a complete interactive static website that can be, for example, hosted on GitHub Pages.
* **eBook**: A complete eBook with exercise solutions at the end of the book. Generate this format using: ```gitbook ebook ./myrepo```. You need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed. The output format could be **PDF**, **ePub** or **MOBI**.
* **eBook**: A complete eBook with exercise solutions at the end of the book. You need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed. You can specify the eBook filename with the `-o` option, otherwise `book` will be used.
* Generate a **PDF** using: `gitbook pdf ./myrepo`
* Generate a **ePub** using: `gitbook epub ./myrepo`
* Generate a **MOBI** using: `gitbook mobi ./myrepo`
* **JSON**: This format is used for debugging or extracting metadata from a book. Generate this format using: ```gitbook build ./myrepo -f json```.
## Book Format
@@ -209,7 +212,7 @@ The platform [GitBook.io](https://www.gitbook.io/) is like an "Heroku for books"
#### Plugins
Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
Plugins can be used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
##### Official plugins:
@@ -219,6 +222,7 @@ Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](ht
| [quizzes](https://github.com/GitbookIO/plugin-quizzes) | Add interactive quizzes to your book. |
| [mathjax](https://github.com/GitbookIO/plugin-mathjax) | Displays mathematical notation in the book. |
| [mixpanel](https://github.com/GitbookIO/plugin-mixpanel) | Mixpanel tracking for your book |
| [infinitescroll](https://github.com/GitbookIO/gitbook-plugin-infinitescroll) | Infinite Scrolling |
##### Other plugins:
@@ -235,6 +239,8 @@ Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](ht
| [Piwik Open Analytics](https://github.com/emmanuel-keller/gitbook-plugin-piwik) | Piwik Open Analytics tracking for your book |
| [Heading Anchors](https://github.com/rlmv/gitbook-plugin-anchors) | Add linkable Github-style anchors to headings |
| [JSBin](https://github.com/jcouyang/gitbook-plugin-jsbin) | Embedded jsbin frame into your book |
| [gitbook-grvis](https://github.com/romanlytkin/gitbook-grvis) | Gitbook GrViz plugin is used to select from markdown dot and converting it into a picture format svg |
| [gitbook-plantuml](https://github.com/romanlytkin/gitbook-plantuml) | Gitbook PlantUml plugin is used to select from markdown uml and converting it into a picture format svg |
#### Debugging
+20724
View File
File diff suppressed because one or more lines are too long
+10
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -38,6 +38,9 @@ var CONFIG = {
}
},
// Variables for templating
"variables": {},
// Set another theme with your own layout
// It's recommended to use plugins or add more options for default theme, though
// See https://github.com/GitbookIO/gitbook/issues/209
+3 -3
View File
@@ -39,7 +39,8 @@ Generator.prototype.finish = function() {
"--level2-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-2 ')]",
"--level3-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-3 ')]",
"--no-chapters-in-toc": true,
"--max-levels": "1000"
"--max-levels": "1",
"--breadth-first": true
};
if (format == "pdf") {
@@ -50,7 +51,6 @@ Generator.prototype.finish = function() {
"--margin-right": String(pdfOptions.margin.right),
"--margin-top": String(pdfOptions.margin.top),
"--margin-bottom": String(pdfOptions.margin.bottom),
"--pdf-add-toc": Boolean(pdfOptions.toc),
"--pdf-default-font-size": String(pdfOptions.fontSize),
"--pdf-mono-font-size": String(pdfOptions.fontSize),
"--paper-size": String(pdfOptions.paperSize),
@@ -62,7 +62,7 @@ Generator.prototype.finish = function() {
var command = [
"ebook-convert",
path.join(that.options.output, "index.html"),
path.join(that.options.output, "SUMMARY.html"),
path.join(that.options.output, "index."+format),
stringUtils.optionsToShellArgs(_options)
].join(" ");
+1
View File
@@ -74,4 +74,5 @@ module.exports = {
fs.exists(path, d.resolve);
return d.promise;
},
readFileSync: fs.readFileSync.bind(fs)
};
+5
View File
@@ -20,6 +20,11 @@ BaseGenerator.prototype.callHook = function(name, data) {
return this.plugins.hook(name, data);
};
// Sets up generator
BaseGenerator.prototype.load = function() {
return this.loadPlugins();
};
BaseGenerator.prototype.loadPlugins = function() {
var that = this;
+5 -2
View File
@@ -40,7 +40,7 @@ var loadGenerator = function(options) {
.then(function() {
var generator = new generators[options.generator](options);
return generator.loadPlugins()
return generator.load()
.then(_.constant(generator));
});
};
@@ -64,7 +64,7 @@ var generate = function(options) {
try {
var _config = require(path.resolve(options.input, options.configFile));
options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins'));
options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins', 'generator'));
}
catch(err) {
// No config file: not a big deal
@@ -297,6 +297,9 @@ var generateBook = function(options) {
})
// Finish generation
.then(function() {
return generator.callHook("finish:before");
})
.then(function() {
return generator.finish();
})
+3 -2
View File
@@ -29,8 +29,9 @@ Generator.prototype.convertFile = function(content, input) {
dir: path.dirname(input) || '/'
});
})
.then(function(sections) {
json.sections = sections;
.then(function(parsed) {
json.lexed = parsed.lexed;
json.sections = parsed.sections;
})
.then(function() {
return fs.writeFile(
+30 -2
View File
@@ -21,8 +21,26 @@ util.inherits(Generator, BaseGenerator);
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("page") || path.resolve(this.options.theme, 'templates/page.html')
this.plugins.template("ebook:page") || path.resolve(this.options.theme, 'templates/ebook/page.html')
);
this.summaryTemplate = swig.compileFile(
this.plugins.template("ebook:sumary") || path.resolve(this.options.theme, 'templates/ebook/summary.html')
);
this.glossaryTemplate = swig.compileFile(
this.plugins.template("ebook:glossary") || path.resolve(this.options.theme, 'templates/ebook/glossary.html')
);
};
// Generate table of contents
Generator.prototype.writeToc = function() {
var that = this;
var basePath = ".";
return this._writeTemplate(this.summaryTemplate, {
toc: parse.progress(this.options.navigation, "README.md").chapters,
basePath: basePath,
staticBase: path.join(basePath, "gitbook"),
}, path.join(this.options.output, "SUMMARY.html"));
};
Generator.prototype.finish = function() {
@@ -31,9 +49,19 @@ Generator.prototype.finish = function() {
var output = path.join(this.options.output, "index.html");
var progress = parse.progress(this.options.navigation, "README.md");
return Q()
// Write table of contents
.then(function() {
return that.writeToc();
})
// Write glossary
.then(function() {
return that.writeGlossary();
})
// Copy cover
.then(function() {
return that.copyCover();
+36 -26
View File
@@ -23,29 +23,29 @@ var Generator = function() {
};
util.inherits(Generator, BaseGenerator);
// Load all templates
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("site") || path.resolve(this.options.theme, 'templates/site.html')
);
this.langsTemplate = swig.compileFile(
this.plugins.template("langs") || path.resolve(this.options.theme, 'templates/langs.html')
);
this.glossaryTemplate = swig.compileFile(
this.plugins.template("glossary") || path.resolve(this.options.theme, 'templates/glossary.html')
);
};
// Load plugins
Generator.prototype.loadPlugins = function() {
// Add template loading to load
Generator.prototype.load = function() {
var that = this;
return BaseGenerator.prototype.loadPlugins.apply(this)
return BaseGenerator.prototype.load.apply(this)
.then(function() {
return that.loadTemplates();
});
};
// Load all templates
Generator.prototype.loadTemplates = function() {
this.template = swig.compileFile(
this.plugins.template("site:page") || path.resolve(this.options.theme, 'templates/book/page.html')
);
this.langsTemplate = swig.compileFile(
this.plugins.template("site:langs") || path.resolve(this.options.theme, 'templates/book/langs.html')
);
this.glossaryTemplate = swig.compileFile(
this.plugins.template("site:glossary") || path.resolve(this.options.theme, 'templates/book/glossary.html')
);
};
// Generate a template
Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) {
var that = this;
@@ -118,20 +118,25 @@ Generator.prototype.prepareFile = function(content, _input) {
return _callHook("page:before");
})
.then(function() {
// Lex page
return parse.lex(page.content);
})
.then(function(lexed) {
page.lexed = lexed;
// Lex, parse includes and get
// Get HTML generated sections
return parse.page(lexed, {
return parse.page(page.content, {
// Local files path
dir: path.dirname(_input) || '/',
// Output directory
outdir: path.dirname(_input) || '/',
// Includer for templating
includer: parse.includer(that.options.variables, [
path.dirname(_input) || '/',
path.join(that.options.input, '_includes'),
], path.join, fs.readFileSync)
});
})
.then(function(sections) {
page.sections = sections;
.then(function(parsed) {
page.lexed = parsed.lexed;
page.sections = parsed.sections;
// Use plugin hook
return _callHook("page");
@@ -149,7 +154,12 @@ Generator.prototype.convertFile = function(content, _input) {
if (_output == "README.html") _output = "index.html";
var output = path.join(this.options.output, _output);
var basePath = path.relative(path.dirname(output), this.options.output) || ".";
// Bug fix for issue #493 which would occur when relative-links are 2-level or more deep in win32
if (process.platform === 'win32') {
basePath = basePath.replace(/\\/g, '/');
}
return this.prepareFile(content, _input)
.then(function(page) {
// Index page in search
-20
View File
@@ -1,20 +0,0 @@
var fs = require('graceful-fs');
var path = require('path');
module.exports = function(code, folder) {
folder = folder || '';
return code.replace(/{{([\s\S]+?)}}/g, function(match, filename) {
// Normalize filename
var fname = path.join(folder, filename.trim());
// Try including snippet from FS
try {
// Trim trailing newlines/space of imported snippets
return fs.readFileSync(fname, 'utf8').trimRight();
} catch(err) {}
// If fails leave content as is
return match;
});
};
+12
View File
@@ -0,0 +1,12 @@
var _ = require('lodash');
module.exports = function(markdown, includer) {
// Memoized include function (to cache lookups)
var _include = _.memoize(includer);
return markdown.replace(/{{([\s\S]+?)}}/g, function(match, key) {
// If fails leave content as is
key = key.trim();
return _include(key) || match;
});
};
+15
View File
@@ -0,0 +1,15 @@
// Return a fs inclduer
module.exports = function(ctx, folders, resolveFile, readFile) {
return function(name) {
return ctx[name] ||
folders.map(function(folder) {
// Try including snippet from FS
try {
var fname = resolveFile(folder, name);
// Trim trailing newlines/space of imported snippets
return readFile(fname, 'utf8').trimRight();
} catch(err) {}
})
.filter(Boolean)[0];
}
};
+2 -1
View File
@@ -6,5 +6,6 @@ module.exports = {
lex: require('./lex'),
progress: require('./progress'),
navigation: require('./navigation'),
readme: require('./readme')
readme: require('./readme'),
includer: require('./includer')
};
+10 -11
View File
@@ -5,7 +5,7 @@ var hljs = require('highlight.js');
var lex = require('./lex');
var renderer = require('./renderer');
var codeInclude = require('./code_include');
var include = require('./include');
var lnormalize = require('../utils/lang').normalize;
@@ -51,8 +51,10 @@ function parsePage(src, options) {
options = options || {};
// Lex if not already lexed
return (_.isArray(src) ? src : lex(src))
.map(function(section) {
var parsed = {
lexed: (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
};
parsed.sections = parsed.lexed.map(function(section) {
// Transform given type
if(section.type === 'exercise') {
var nonCodeNodes = _.reject(section, {
@@ -74,20 +76,15 @@ function parsePage(src, options) {
// Main language
var lang = validLangs ? langs[0] : null;
// codeInclude shortcut
var ci = function(code) {
return codeInclude(code, options.dir);
};
return {
id: section.id,
type: section.type,
content: render(nonCodeNodes, options),
lang: lang,
code: {
base: ci(codeNodes[0].text),
solution: ci(codeNodes[1].text),
validation: ci(codeNodes[2].text),
base: codeNodes[0].text,
solution: codeNodes[1].text,
validation: codeNodes[2].text,
// Context is optional
context: codeNodes[3] ? codeNodes[3].text : null,
}
@@ -155,6 +152,8 @@ function parsePage(src, options) {
content: render(section, options)
};
});
return parsed;
}
// Exports
+4 -9
View File
@@ -1,11 +1,7 @@
var url = require('url');
var _ = require('lodash');
var inherits = require('util').inherits;
var links = require('../utils').links;
var codeInclude = require('./code_include');
var path = require('path');
var kramed = require('kramed');
var rendererId = 0;
@@ -52,11 +48,11 @@ GitBookRenderer.prototype.link = function(href, title, text) {
// Parsed version of the url
var parsed = url.parse(href);
var o = this._extra_options;
var extname = parsed.path? _.last(parsed.path.split(".")) : "";
// Relative link, rewrite it to point to github repo
if(links.isRelative(_href) && path.extname(parsed.path) == ".md") {
if(links.isRelative(_href) && extname == "md") {
_href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
_href = _href.replace(".md", ".html");
}
@@ -130,8 +126,7 @@ GitBookRenderer.prototype.listitem = function(text) {
GitBookRenderer.prototype.code = function(code, lang, escaped) {
return GitBookRenderer.super_.prototype.code.call(
this,
// Import code snippets
codeInclude(code, this._extra_options.dir),
code,
lang,
escaped
);
+2 -2
View File
@@ -11,8 +11,8 @@ function escapeShellArg(arg) {
function optionsToShellArgs(options) {
return _.chain(options)
.map(function(value, key) {
if (value == null || value == false) return null;
if (value == true) return key;
if (value == null || value === false) return null;
if (value === true) return key;
return key+"="+escapeShellArg(value);
})
.compact()
+5 -3
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "1.1.1",
"version": "1.3.4",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -16,7 +16,7 @@
"commander": "2.2.0",
"graceful-fs": "3.0.2",
"fs-extra": "0.10.0",
"highlight.js": "8.2.0",
"highlight.js": "8.3.0",
"tmp": "0.0.23",
"semver": "2.2.1",
"gaze": "~0.5.1",
@@ -35,7 +35,9 @@
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-requirejs": "0.4.1",
"grunt-bower-install-simple": "0.9.2"
"grunt-bower-install-simple": "0.9.2",
"grunt-browserify": "3.1.0",
"grunt-contrib-uglify": "0.6.0"
},
"scripts": {
"test": "export TESTING=true; mocha --reporter list"
+5 -1
View File
@@ -3,12 +3,13 @@ var path = require('path');
var assert = require('assert');
var page = require('../').parse.page;
var includer = require('../').parse.includer;
var FIXTURES_DIR = path.join(__dirname, './fixtures/');
function loadPage (name, options) {
var CONTENT = fs.readFileSync(FIXTURES_DIR + name + '.md', 'utf8');
return page(CONTENT, options);
return page(CONTENT, options).sections;
}
@@ -16,6 +17,9 @@ describe('Code includes', function() {
var LEXED = loadPage('INCLUDES', {
'dir': FIXTURES_DIR,
'includer': includer({}, [
FIXTURES_DIR
], path.join, fs.readFileSync)
});
var INCLUDED_C = fs.readFileSync(path.join(FIXTURES_DIR, 'included.c'), 'utf8');
+1 -10
View File
@@ -6,7 +6,7 @@ var page = require('../').parse.page;
function loadPage (name, options) {
var CONTENT = fs.readFileSync(path.join(__dirname, './fixtures/' + name + '.md'), 'utf8');
return page(CONTENT, options);
return page(CONTENT, options).sections;
}
var LEXED = loadPage('PAGE', {
@@ -80,9 +80,6 @@ describe('Page parsing', function() {
describe('Relative links', function() {
it('should replace link to .md by link to .html', function() {
var LEXED = loadPage('MARKDOWN_LINKS', {
// GitHub repo ID
repo: 'GitBookIO/javascript',
// Imaginary folder of markdown file
dir: 'course',
outdir: 'course'
@@ -96,9 +93,6 @@ describe('Relative links', function() {
describe('Relative images', function() {
it('should keep image relative with considering output directory in site format', function() {
var LEXED = loadPage('IMAGES', {
// GitHub repo ID
repo: 'GitBookIO/javascript',
// Imaginary folder of markdown file
dir: 'syntax',
outdir: 'syntax'
@@ -110,9 +104,6 @@ describe('Relative images', function() {
it('should keep image relative with considering output directory in page format', function() {
var LEXED = loadPage('IMAGES', {
// GitHub repo ID
repo: 'GitBookIO/javascript',
// Imaginary folder of markdown file
dir: 'syntax',
outdir: './'
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+51 -50
View File
@@ -31,21 +31,57 @@ define([
return d.promise();
}
$.fn.replaceText = function( search, replace, text_only ) {
return this.each(function(){
var node = this.firstChild,
val,
new_val,
// Elements to be removed at the end.
remove = [];
// Only continue if firstChild exists.
if ( node ) {
// Loop over all childNodes.
do {
// Only process text nodes.
if ( node.nodeType === 3 ) {
// The original node value.
val = node.nodeValue;
// The new value.
new_val = val.replace( search, replace );
// Only replace text if the new value is actually different!
if ( new_val !== val ) {
if ( !text_only && /</.test( new_val ) ) {
// The new value contains HTML, set it in a slower but far more
// robust way.
$(node).before( new_val );
// Don't remove the node yet, or the loop will lose its place.
remove.push( node );
} else {
// The new value contains no HTML, so it can be set in this
// very fast, simple way.
node.nodeValue = new_val;
}
}
}
} while ( node = node.nextSibling );
}
// Time to remove those elements!
remove.length && $(remove).remove();
});
};
var pregQuote = function( str ) {
// http://kevin.vanzonneveld.net
// + original by: booeyOH
// + improved by: Ates Goral (http://magnetiq.com)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// * example 1: preg_quote("$40");
// * returns 1: '\$40'
// * example 2: preg_quote("*RRRING* Hello?");
// * returns 2: '\*RRRING\* Hello\?'
// * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
// * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
};
@@ -58,48 +94,13 @@ define([
});
};
var matchText = function(node, regex, callback, excludeElements) {
excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
var child = node.firstChild;
if (!child) return;
do {
switch (child.nodeType) {
case 1:
if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
continue;
}
matchText(child, regex, callback, excludeElements);
break;
case 3:
child.data.replace(regex, function(all) {
var args = [].slice.call(arguments),
offset = args[args.length - 2],
newTextNode = child.splitText(offset);
newTextNode.data = newTextNode.data.substr(all.length);
callback.apply(window, [child].concat(args));
child = newTextNode;
});
break;
}
} while (child = child.nextSibling);
return node;
};
var replaceTerm = function($el, term) {
var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' );
matchText($el.get(0), r, function(node, match, offset) {
var span = document.createElement("span");
span.className = "glossary-term";
span.textContent = match;
span.setAttribute("data-glossary-term", term.id);
span.setAttribute("title", term.description);
node.parentNode.insertBefore(span, node.nextSibling);
$el.find("*").replaceText(r, function(match) {
return "<span class='glossary-term' data-glossary-term='"+term.id+"' title='"+term.description+"'>"+match+"</span>";
});
};
var prepare = function() {
+2 -1
View File
@@ -256,7 +256,8 @@
}
ol ol,
ol ul {
ol ul,
ul ul {
margin-top: 0;
margin-bottom: 0;
}
+6
View File
@@ -4,6 +4,12 @@
@import "ebook/highlight.less";
.page {
&.page-toc {
ol {
margin: 0px;
}
}
.book-chapter {
display: none;
}
@@ -1,4 +1,4 @@
{% extends "site.html" %}
{% extends "page.html" %}
{% block title %}Glossary | {{ title }}{% endblock %}
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "../layout.html" %}
{% block title %}{{ title }}{% endblock %}
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "../layout.html" %}
{% block head %}
{% parent %}
@@ -15,10 +15,10 @@
{% block content %}
<div class="book" data-level="{{ progress.current.level }}" data-basepath="{{ basePath }}" data-revision="{{ revision }}">
{% include "includes/book/summary.html" %}
{% include "includes/summary.html" %}
<div class="book-body">
<div class="body-inner">
{% include "includes/book/header.html" %}
{% include "includes/header.html" %}
<div class="page-wrapper" tabindex="-1">
<div class="page-inner">
{% block page_inner %}
@@ -27,9 +27,9 @@
{% if section.type == "normal" %}
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% elif section.type == "exercise" %}
{% include "./includes/book/exercise.html" with {section: section} %}
{% include "./includes/exercise.html" with {section: section} %}
{% elif section.type == "quiz" %}
{% include "./includes/book/quiz.html" with {section: section} %}
{% include "./includes/quiz.html" with {section: section} %}
{% endif %}
</section>
{% endfor %}
+15
View File
@@ -0,0 +1,15 @@
{% extends "./layout.html" %}
{% block title %}Glossary | {{ title }}{% endblock %}
{% block content %}
<div class="page page-toc">
<h1>Glossary</h1>
{% for item in glossaryIndex %}
<section class="normal glossary" id="{{ item.id }}">
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
<p>{{ item.description }}</p>
</section>
{% endfor %}
</div>
{% endblock %}
+22
View File
@@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html lang="en-US" {% block htmlTag %}{% endblock %}>
{{ htmlSnippet("html:start")|default("") }}
<head>
{{ htmlSnippet("head:start")|default("") }}
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="{% block description %}{% endblock %}">
<meta name="generator" content="GitBook {{ gitbook.version }}">
{% block head %}{% endblock %}
{{ htmlSnippet("head:end")|default("") }}
</head>
<body>
{{ htmlSnippet("body:start")|default("") }}
{% block style %}{% endblock %}
{% block content %}{% endblock %}
{% block javascript %}{% endblock %}
{{ htmlSnippet("body:end")|default("") }}
</body>
{{ htmlSnippet("html:end")|default("") }}
</html>
@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% extends "./layout.html" %}
{% block title %}{{ progress.current.title }} | {{ title }}{% endblock %}
@@ -17,20 +17,16 @@
<div class="page">
<h1 class="book-chapter book-chapter-{{ progress.current.level|lvl }}">{{ progress.current.title }}</h1>
{% for section in content %}
<section class="{{ section.type }}" id="section-{{ section.id }}">
<div class="{{ section.type }}" id="section-{{ section.id }}">
{% if section.type == "normal" %}
{% autoescape false %}{{ section.content }}{% endautoescape %}
{% elif section.type == "exercise" %}
{% include "./includes/page/exercise.html" with {section: section} %}
{% include "./includes/exercise.html" with {section: section} %}
{% elif section.type == "quiz" %}
{% include "./includes/page/quiz.html" with {section: section} %}
{% include "./includes/quiz.html" with {section: section} %}
{% endif %}
</section>
</div>
{% endfor %}
{% if progress.current.next and progress.current.next.path %}
<a href="{{ basePath }}/{{ progress.current.next.path|mdLink }}" />
{% endif %}
</div>
{% endblock %}
+50
View File
@@ -0,0 +1,50 @@
{% extends "./layout.html" %}
{% block title %}Table of Contents | {{ title }}{% endblock %}
{% block style %}
<link rel="stylesheet" href="{{ staticBase }}/print.css">
{% for resource in plugins.resources.css %}
{% if resource.url %}
<link rel="stylesheet" href="{{ resource.url }}">
{% else %}
<link rel="stylesheet" href="{{ staticBase }}/plugins/{{ resource.path }}">
{% endif %}
{% endfor %}
{% endblock %}
{% macro articles(_articles) %}
{% for item in _articles %}
{% set externalLink = item.path|isExternalLink %}
<li>
{% if item.path %}
{% if !externalLink %}
<a href="{{ basePath }}/{{ item.path|mdLink }}">{{ item.title }}</a>
{% else %}
<a target="_blank" href="{{ item.path }}">{{ item.title }}</a>
{% endif %}
{% else %}
{{ item.title }}
{% endif %}
{% if item.articles.length > 0 %}
<ol>
{{ articles(item.articles) }}
</ol>
{% endif %}
</li>
{% endfor %}
{% endmacro %}
{% block content %}
<div class="page page-toc">
<h1>Table of Contents</h1>
<ol>
{{ articles(summary.chapters) }}
{% if glossary.length > 0 %}
<li><a href="{{ basePath }}/GLOSSARY.html">Glossary</a></li>
{% endif %}
</ol>
</div>
{% endblock %}
+1
View File
@@ -4,6 +4,7 @@
<head>
{{ htmlSnippet("head:start")|default("") }}
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=11; IE=10; IE=9; IE=8; IE=7; IE=EDGE" />
<title>{% block title %}{% endblock %}</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="{% block description %}{% endblock %}">