summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2015-01-19 09:47:36 +0100
committerSamy Pessé <samypesse@gmail.com>2015-01-19 09:47:36 +0100
commitec586dd3cdf06e9567f5d3e4961022ddc3c94778 (patch)
treecc7825ab73110b4e6fbedee404427b052edffa17 /lib
parent80432161708357bdcf0e00533d9e6d327636dab6 (diff)
downloadgitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.zip
gitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.tar.gz
gitbook-ec586dd3cdf06e9567f5d3e4961022ddc3c94778.tar.bz2
Clear folder
Diffstat (limited to 'lib')
-rw-r--r--lib/generate/config.js137
-rw-r--r--lib/generate/ebook/index.js92
-rw-r--r--lib/generate/fs.js92
-rw-r--r--lib/generate/generator.js87
-rw-r--r--lib/generate/index.js374
-rw-r--r--lib/generate/init.js69
-rw-r--r--lib/generate/json/index.js77
-rw-r--r--lib/generate/page/index.js84
-rw-r--r--lib/generate/plugin.js325
-rw-r--r--lib/generate/site/glossary_indexer.js101
-rw-r--r--lib/generate/site/index.js314
-rw-r--r--lib/generate/site/search_indexer.js71
-rw-r--r--lib/generate/template.js52
-rw-r--r--lib/index.js5
-rw-r--r--lib/parse/glossary.js48
-rw-r--r--lib/parse/include.js12
-rw-r--r--lib/parse/includer.js15
-rw-r--r--lib/parse/index.js11
-rw-r--r--lib/parse/is_exercise.js17
-rw-r--r--lib/parse/is_quiz.js87
-rw-r--r--lib/parse/langs.js25
-rw-r--r--lib/parse/lex.js79
-rw-r--r--lib/parse/navigation.js64
-rw-r--r--lib/parse/page.js160
-rw-r--r--lib/parse/progress.js47
-rw-r--r--lib/parse/readme.js45
-rw-r--r--lib/parse/renderer.js141
-rw-r--r--lib/parse/summary.js167
-rw-r--r--lib/utils/index.js4
-rw-r--r--lib/utils/lang.js19
-rw-r--r--lib/utils/links.js60
-rw-r--r--lib/utils/string.js26
32 files changed, 0 insertions, 2907 deletions
diff --git a/lib/generate/config.js b/lib/generate/config.js
deleted file mode 100644
index e198c91..0000000
--- a/lib/generate/config.js
+++ /dev/null
@@ -1,137 +0,0 @@
-var Q = require('q');
-var _ = require('lodash');
-var path = require('path');
-
-// Default configuration for gitbook
-var CONFIG = {
- // Folders to use for output
- // Caution: it overrides the value from the command line
- // It's not advised this option in the book.json
- "output": null,
-
- // Generator to use for building
- // Caution: it overrides the value from the command line
- // It's not advised this option in the book.json
- "generator": "site",
-
- // Configuration file to use
- "configFile": "book",
-
- // Book metadats (somes are extracted from the README by default)
- "title": null,
- "description": null,
- "isbn": null,
-
- // For ebook format, the extension to use for generation (default is detected from output extension)
- // "epub", "pdf", "mobi"
- // Caution: it overrides the value from the command line
- // It's not advised this option in the book.json
- "extension": null,
-
- // Plugins list, can contain "-name" for removing default plugins
- "plugins": [],
-
- // Global configuration for plugins
- "pluginsConfig": {
- "fontSettings": {
- "theme": null, //"sepia", "night" or "white",
- "family": "sans",// "serif" or "sans",
- "size": 2 // 1 - 4
- }
- },
-
- // 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
- "theme": path.resolve(__dirname, '../../theme'),
-
- // Links in template (null: default, false: remove, string: new value)
- "links": {
- // Custom links at top of sidebar
- "sidebar": {
- //"Custom link name": "https://customlink.com"
- },
-
- // Sharing links
- "sharing": {
- "google": null,
- "facebook": null,
- "twitter": null,
- "weibo": null,
- "all": null
- }
- },
-
- // CSS Styles
- "styles": {
- "website": "styles/website.css",
- "ebook": "styles/ebook.css",
- "pdf": "styles/pdf.css",
- "mobi": "styles/mobi.css",
- "epub": "styles/epub.css"
- },
-
- // 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,
-
- // Font size for the file content
- "fontSize": 12,
-
- // Paper size for the pdf
- // Choices are [u’a0’, u’a1’, u’a2’, u’a3’, u’a4’, u’a5’, u’a6’, u’b0’, u’b1’, u’b2’, u’b3’, u’b4’, u’b5’, u’b6’, u’legal’, u’letter’]
- "paperSize": "a4",
-
- // Margin (in pts)
- // Note: 72 pts equals 1 inch
- "margin": {
- "right": 62,
- "left": 62,
- "top": 36,
- "bottom": 36
- },
-
- //Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
- "headerTemplate": "",
-
- //Footer HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
- "footerTemplate": ""
- }
-};
-
-// Return complete configuration
-var defaultsConfig = function(options) {
- return _.merge(options || {}, CONFIG, _.defaults);
-};
-
-// Read configuration from book.json
-var readConfig = function(options) {
- options = defaultsConfig(options);
-
- return Q()
- .then(function() {
- try {
- var _config = require(path.resolve(options.input, options.configFile));
- options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins', 'generator'));
- }
- catch(err) {
- // No config file: not a big deal
- return Q();
- }
- })
- .thenResolve(options);
-};
-
-module.exports = {
- CONFIG: CONFIG,
- defaults: defaultsConfig,
- read: readConfig
-}
-
diff --git a/lib/generate/ebook/index.js b/lib/generate/ebook/index.js
deleted file mode 100644
index c74ffcd..0000000
--- a/lib/generate/ebook/index.js
+++ /dev/null
@@ -1,92 +0,0 @@
-var util = require("util");
-var path = require("path");
-var Q = require("q");
-var _ = require("lodash");
-var exec = require('child_process').exec;
-
-var fs = require('graceful-fs');
-var parse = require("../../parse");
-var BaseGenerator = require("../page");
-var stringUtils = require("../../utils/string");
-
-var Generator = function() {
- BaseGenerator.apply(this, arguments);
-
- // eBook format
- this.ebookFormat = this.options.extension || path.extname(this.options.output).replace("\.", "") || "pdf";
-
- // Styles to use
- this.styles = ["ebook", this.ebookFormat];
-};
-util.inherits(Generator, BaseGenerator);
-
-Generator.prototype.finish = function() {
- var that = this;
-
- return BaseGenerator.prototype.finish.apply(this)
- .then(function() {
- var d = Q.defer();
-
- if (!that.options.cover && fs.existsSync(path.join(that.options.output, "cover.jpg"))) {
- that.options.cover = path.join(that.options.output, "cover.jpg");
- }
-
- var _options = {
- "--cover": that.options.cover,
- "--title": that.options.title,
- "--comments": that.options.description,
- "--isbn": that.options.isbn,
- "--authors": that.options.author,
- "--publisher": "GitBook",
- "--chapter": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter ')]",
- "--chapter-mark": "pagebreak",
- "--page-breaks-before": "/",
- "--level1-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-1 ')]",
- "--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": "1",
- "--breadth-first": true
- };
-
- if (that.ebookFormat == "pdf") {
- var pdfOptions = that.options.pdf;
-
- _.extend(_options, {
- "--margin-left": String(pdfOptions.margin.left),
- "--margin-right": String(pdfOptions.margin.right),
- "--margin-top": String(pdfOptions.margin.top),
- "--margin-bottom": String(pdfOptions.margin.bottom),
- "--pdf-default-font-size": String(pdfOptions.fontSize),
- "--pdf-mono-font-size": String(pdfOptions.fontSize),
- "--paper-size": String(pdfOptions.paperSize),
- "--pdf-page-numbers": Boolean(pdfOptions.pageNumbers),
- "--pdf-header-template": String(pdfOptions.headerTemplate),
- "--pdf-footer-template": String(pdfOptions.footerTemplate)
- });
- }
-
- var command = [
- "ebook-convert",
- path.join(that.options.output, "SUMMARY.html"),
- path.join(that.options.output, "index."+that.ebookFormat),
- stringUtils.optionsToShellArgs(_options)
- ].join(" ");
-
- exec(command, function (error, stdout, stderr) {
- if (error) {
- if (error.code == 127) {
- error.message = "Need to install ebook-convert from Calibre";
- } else {
- error.message = error.message + " "+stdout;
- }
- return d.reject(error);
- }
- d.resolve();
- });
-
- return d.promise;
- });
-};
-
-module.exports = Generator;
diff --git a/lib/generate/fs.js b/lib/generate/fs.js
deleted file mode 100644
index 371051c..0000000
--- a/lib/generate/fs.js
+++ /dev/null
@@ -1,92 +0,0 @@
-var Q = require("q");
-var fs = require('graceful-fs');
-var fsExtra = require("fs-extra");
-var Ignore = require("fstream-ignore");
-
-var getFiles = function(path) {
- var d = Q.defer();
-
- // Our list of files
- var files = [];
-
- var ig = Ignore({
- path: path,
- ignoreFiles: ['.ignore', '.gitignore', '.bookignore']
- });
-
- // Add extra rules to ignore common folders
- ig.addIgnoreRules([
- // Skip Git stuff
- '.git/',
- '.gitignore',
-
- // Skip OS X meta data
- '.DS_Store',
-
- // Skip stuff installed by plugins
- 'node_modules',
-
- // Skip book outputs
- '*.pdf',
- '*.epub',
- '*.mobi',
-
- // Skip config files
- '.ignore',
- '.bookignore',
- 'book.json',
- ], '__custom_stuff');
-
- // Push each file to our list
- ig.on('child', function (c) {
- files.push(
- c.path.substr(c.root.path.length + 1) + (c.props.Directory === true ? '/' : '')
- );
- });
-
- ig.on('end', function() {
- // Normalize paths on Windows
- if(process.platform === 'win32') {
- return d.resolve(files.map(function(file) {
- return file.replace(/\\/g, '/');
- }));
- }
-
- // Simply return paths otherwise
- return d.resolve(files);
- });
-
- ig.on('error', d.reject);
-
- return d.promise;
-};
-
-module.exports = {
- list: getFiles,
- readFile: Q.denodeify(fs.readFile),
- //writeFile: Q.denodeify(fs.writeFile),
- writeFile: function(filename, data, options) {
- var d = Q.defer();
-
- try {
- fs.writeFileSync(filename, data, options)
- } catch(err) {
- d.reject(err);
- }
- d.resolve();
-
-
- return d.promise;
- },
- mkdirp: Q.denodeify(fsExtra.mkdirp),
- copy: Q.denodeify(fsExtra.copy),
- remove: Q.denodeify(fsExtra.remove),
- symlink: Q.denodeify(fsExtra.symlink),
- exists: function(path) {
- var d = Q.defer();
- fs.exists(path, d.resolve);
- return d.promise;
- },
- existsSync: fs.existsSync,
- readFileSync: fs.readFileSync.bind(fs)
-};
diff --git a/lib/generate/generator.js b/lib/generate/generator.js
deleted file mode 100644
index 4791c98..0000000
--- a/lib/generate/generator.js
+++ /dev/null
@@ -1,87 +0,0 @@
-var _ = require("lodash");
-var path = require("path");
-var Q = require("q");
-var fs = require("./fs");
-
-var Plugin = require("./plugin");
-
-var BaseGenerator = function(options) {
- this.options = options;
-
- // Base for assets in plugins
- this.pluginAssetsBase = "book";
-
- this.options.plugins = Plugin.normalizeNames(this.options.plugins);
- this.options.plugins = _.union(this.options.plugins, this.options.defaultsPlugins);
- this.plugins = [];
-};
-
-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;
-
- return Plugin.fromList(this.options.plugins, this.options.input, this, {
- assetsBase: this.pluginAssetsBase
- })
- .then(function(_plugins) {
- that.plugins = _plugins;
-
- return that.callHook("init");
- });
-};
-
-BaseGenerator.prototype.convertFile = function(content, input) {
- return Q.reject(new Error("Could not convert "+input));
-};
-
-BaseGenerator.prototype.transferFile = function(input) {
- return fs.copy(
- path.join(this.options.input, input),
- path.join(this.options.output, input)
- );
-};
-
-BaseGenerator.prototype.transferFolder = function(input) {
- return fs.mkdirp(
- path.join(this.options.output, input)
- );
-};
-
-BaseGenerator.prototype.copyCover = function() {
- var that = this;
-
- return Q.all([
- fs.copy(path.join(this.options.input, "cover.jpg"), path.join(this.options.output, "cover.jpg")),
- fs.copy(path.join(this.options.input, "cover_small.jpg"), path.join(this.options.output, "cover_small.jpg"))
- ])
- .fail(function() {
- // If orignally from multi-lang, try copy from originalInput
- if (!that.options.originalInput) return;
-
- return Q.all([
- fs.copy(path.join(that.options.originalInput, "cover.jpg"), path.join(that.options.output, "cover.jpg")),
- fs.copy(path.join(that.options.originalInput, "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg"))
- ]);
- })
- .fail(function(err) {
- return Q();
- });
-};
-
-BaseGenerator.prototype.langsIndex = function(langs) {
- return Q.reject(new Error("Langs index is not supported in this generator"));
-};
-
-BaseGenerator.prototype.finish = function() {
- return Q.reject(new Error("Could not finish generation"));
-};
-
-module.exports = BaseGenerator;
diff --git a/lib/generate/index.js b/lib/generate/index.js
deleted file mode 100644
index de1fc0e..0000000
--- a/lib/generate/index.js
+++ /dev/null
@@ -1,374 +0,0 @@
-var Q = require("q");
-var _ = require("lodash");
-var path = require("path");
-var tmp = require('tmp');
-
-var swig = require('./template');
-var fs = require("./fs");
-var parse = require("../parse");
-var Plugin = require("./plugin");
-var defaultConfig = require("./config");
-
-var generators = {
- "site": require("./site"),
- "page": require("./page"),
- "ebook": require("./ebook"),
- "json": require("./json")
-};
-
-var defaultDescription = "Book generated using GitBook";
-
-
-var containsFiles = function(dir, files) {
- return Q.all(_.map(files, function(file) {
- return fs.exists(path.join(dir, file));
- }))
- .then(_.all);
-};
-
-// Test if generator exists
-var checkGenerator = function(options) {
- if (!generators[options.generator]) {
- return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")+")"));
- }
- return Q();
-};
-
-// Create the generator and load plugins
-var loadGenerator = function(options) {
- return checkGenerator(options)
- .then(function() {
- var generator = new generators[options.generator](options);
-
- return generator.load()
- .then(_.constant(generator));
- });
-};
-
-
-
-var generate = function(options) {
- // Read config file
- return defaultConfig.read(options)
- .then(function(_options) {
- options = _options;
-
- // Validate options
- if (!options.input) {
- return Q.reject(new Error("Need option input (book input directory)"));
- }
-
- // Check files to get folder type (book, multilanguage book or neither)
- return checkGenerator(options);
- })
-
- // Read readme
- .then(function() {
- return fs.readFile(path.join(options.input, "README.md"), "utf-8")
- .then(function(_readme) {
- _readme = parse.readme(_readme);
-
- options.title = options.title || _readme.title;
- options.description = options.description || _readme.description || defaultDescription;
- });
- })
-
- // Detect multi-languages book
- .then(function() {
- return containsFiles(options.input, ['LANGS.md'])
- })
-
- .then(function(isMultiLang) {
- // Multi language book
- if(isMultiLang) {
- return generateMultiLang(options);
- }
-
- // Book
- return generateBook(options);
- });
-};
-
-/*
- * Generate a multilanguage book by generating a book for each folder.
- */
-var generateMultiLang = function(options) {
- var langsSummary;
- options.output = options.output || path.join(options.input, "_book");
-
- return checkGenerator(options)
-
- // Multi-languages book
- .then(function() {
- return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8")
- })
-
- // Clean output folder
- .then(function(_langsSummary) {
- langsSummary = _langsSummary;
- return fs.remove(options.output);
- })
- .then(function() {
- return fs.mkdirp(options.output);
- })
-
- // Generate sub-books
- .then(function() {
- options.langsSummary = parse.langs(langsSummary);
-
- // Generated a book for each valid entry
- return _.reduce(options.langsSummary.list, function(prev, entry) {
- return prev.then(function() {
- return generate(_.extend({}, options, {
- input: path.join(options.input, entry.path),
- output: path.join(options.output, entry.path),
- originalInput: options.input,
- originalOutput: options.output
- }));
- })
- }, Q());
- })
-
- .then(function() {
- return loadGenerator(options);
- })
-
- // Generate languages index
- .then(function(generator) {
- return generator.langsIndex(options.langsSummary);
- })
-
- // Copy cover file
- .then(function() {
- return Q.all([
- fs.copy(path.join(options.input, "cover.jpg"), path.join(options.output, "cover.jpg")),
- fs.copy(path.join(options.input, "cover_small.jpg"), path.join(options.output, "cover_small.jpg"))
- ])
- .fail(function() {
- return Q();
- })
- })
-
- // Return options to caller
- .then(_.constant(options));
-};
-
-/*
- * Use a specific generator to convert a gitbook to a site/pdf/ebook/
- * output is always a folder
- */
-var generateBook = function(options) {
- var files;
-
- options.output = options.output || path.join(options.input, "_book");
-
- // Check if it's a book
- return containsFiles(options.input, ['SUMMARY.md', 'README.md'])
-
- // Fail if not a book
- .then(function(isBook) {
- if(!isBook) {
- return Q.reject(new Error("Invalid gitbook repository, need SUMMARY.md and README.md"));
- }
- })
-
- // Clean output folder
- .then(function() {
- return fs.remove(options.output);
- })
-
- .then(function() {
- return fs.mkdirp(options.output);
- })
-
- // List all files in the repository
- .then(function() {
- return fs.list(options.input)
- .then(function(_files) {
- files = _files;
- });
- })
-
- .then(function() {
- return loadGenerator(options);
- })
-
- // Convert files
- .then(function(generator) {
- // Generate the book
- return Q()
-
- // Get summary
- .then(function() {
- var summary = {
- path: path.join(options.input, "SUMMARY.md")
- };
-
- var _callHook = function(name) {
- return generator.callHook(name, summary)
- .then(function(_summary) {
- summary = _summary;
- return summary;
- });
- };
-
- return fs.readFile(summary.path, "utf-8")
- .then(function(_content) {
- summary.content = _content;
- return _callHook("summary:before");
- })
- .then(function() {
- summary.content = parse.summary(summary.content);
- return _callHook("summary:after");
- })
- .then(function() {
- options.summary = summary.content;
- options.navigation = parse.navigation(options.summary);
- });
- })
-
- // Read glossary
- .then(function() {
- var glossary = {};
-
- var _callHook = function(name) {
- return generator.callHook(name, glossary)
- .then(function(_glossary) {
- glossary = _glossary;
- return glossary;
- });
- };
-
- return fs.readFile(path.join(options.input, "GLOSSARY.md"), "utf-8")
- .fail(function() {
- return "";
- })
- .then(function(_content) {
- glossary.content = _content;
- return _callHook("glossary:before");
- })
- .then(function() {
- glossary.content = parse.glossary(glossary.content);
- return _callHook("glossary:after");
- })
- .then(function() {
- options.glossary = glossary.content;
- });
- })
-
- // Skip processing some files
- .then(function() {
- files = _.filter(files, function (file) {
- return !(
- file === 'SUMMARY.md' ||
- file === 'GLOSSARY.md'
- );
- });
- })
-
- // Copy file and replace markdown file
- .then(function() {
- return Q.all(
- _.chain(files)
- .map(function(file) {
- if (!file) return;
-
- if (file[file.length -1] == "/") {
- return Q(generator.transferFolder(file));
- } else if (path.extname(file) == ".md" && options.navigation[file] != null) {
- return fs.readFile(path.join(options.input, file), "utf-8")
- .then(function(content) {
- return Q(generator.convertFile(content, file));
- });
- } else {
- return Q(generator.transferFile(file));
- }
- })
- .value()
- );
- })
-
- // Finish generation
- .then(function() {
- return generator.callHook("finish:before");
- })
- .then(function() {
- return generator.finish();
- })
- .then(function() {
- return generator.callHook("finish");
- });
- })
-
- // Return all options
- .then(function() {
- return options;
- });
-};
-
-/*
- * Extract files from generate output in a temporary folder
- */
-var generateFile = function(options) {
- options = _.defaults(options || {}, {
- input: null,
- output: null,
- extension: null
- });
-
- return Q.nfcall(tmp.dir)
- .then(function(tmpDir) {
- return generate(
- _.extend({},
- options,
- {
- output: tmpDir
- })
- )
- .then(function(_options) {
- var ext = options.extension;
- var outputFile = options.output || path.resolve(options.input, "book."+ext);
-
- var copyFile = function(lang) {
- var _outputFile = outputFile;
- var _tmpDir = tmpDir;
-
- if (lang) {
- _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
- _tmpDir = path.join(_tmpDir, lang);
- }
-
- return fs.copy(
- path.join(_tmpDir, "index."+ext),
- _outputFile
- );
- };
-
- // Multi-langs book
- return Q()
- .then(function() {
- if (_options.langsSummary) {
- return Q.all(
- _.map(_options.langsSummary.list, function(lang) {
- return copyFile(lang.lang);
- })
- );
- } else {
- return copyFile();
- }
- })
- .then(function() {
- return fs.remove(tmpDir);
- });
- });
- });
-};
-
-module.exports = {
- generators: generators,
- folder: generate,
- file: generateFile,
- book: generateBook,
- Plugin: Plugin,
- config: defaultConfig
-};
diff --git a/lib/generate/init.js b/lib/generate/init.js
deleted file mode 100644
index 705e6e7..0000000
--- a/lib/generate/init.js
+++ /dev/null
@@ -1,69 +0,0 @@
-var Q = require('q');
-var _ = require('lodash');
-
-var path = require('path');
-
-var fs = require('./fs');
-var parse = require('../parse');
-
-
-// Extract paths out of a summary
-function paths(summary) {
- return _.reduce(summary.chapters, function(accu, chapter) {
- return accu.concat(
- _.filter([chapter.path].concat(_.pluck(chapter.articles, 'path')))
- );
- }, []);
-}
-
-// Get the parent folders out of a group of files
-function folders(files) {
- return _.chain(files)
- .map(function(file) {
- return path.dirname(file);
- })
- .uniq()
- .value();
-}
-
-function initDir(dir) {
- return fs.readFile(path.join(dir, 'SUMMARY.md'), 'utf8')
- .then(function(src) {
- // Parse summary
- return parse.summary(src);
- })
- .then(function(summary) {
- // Extract paths from summary
- return paths(summary);
- })
- .then(function(paths) {
- // Convert to absolute paths
- return _.map(paths, function(file) {
- return path.resolve(file);
- });
- })
- .then(function(files) {
- // Create folders
- return Q.all(_.map(folders(files), function(folder) {
- return fs.mkdirp(folder);
- }))
- .then(_.constant(files));
- })
- .then(function(files) {
- // Create files that don't exist
- return Q.all(_.map(files, function(file) {
- return fs.exists(file)
- .then(function(exists) {
- if(exists) return;
- return fs.writeFile(file, '');
- });
- }));
- })
- .fail(function(err) {
- console.error(err.stack);
- });
-}
-
-
-// Exports
-module.exports = initDir;
diff --git a/lib/generate/json/index.js b/lib/generate/json/index.js
deleted file mode 100644
index a252ed3..0000000
--- a/lib/generate/json/index.js
+++ /dev/null
@@ -1,77 +0,0 @@
-var util = require("util");
-var path = require("path");
-var Q = require("q");
-var _ = require("lodash");
-
-var fs = require("../fs");
-var parse = require("../../parse");
-var BaseGenerator = require("../generator");
-
-
-var Generator = function() {
- BaseGenerator.apply(this, arguments);
-};
-util.inherits(Generator, BaseGenerator);
-
-Generator.prototype.transferFile = function(input) {
- // ignore
-};
-
-Generator.prototype.convertFile = function(content, input) {
- var that = this;
- var json = {
- progress: parse.progress(this.options.navigation, input)
- };
-
- return Q()
- .then(function() {
- return parse.page(content, {
- dir: path.dirname(input) || '/'
- });
- })
- .then(function(parsed) {
- json.lexed = parsed.lexed;
- json.sections = parsed.sections;
- })
- .then(function() {
- return fs.writeFile(
- path.join(that.options.output, input.replace(".md", ".json")),
- JSON.stringify(json, null, 4)
- );
- });
-};
-
-// Generate languages index
-// Contains the first languages readme and langs infos
-Generator.prototype.langsIndex = function(langs) {
- var that = this;
-
- if (langs.list.length == 0) return Q.reject("Need at least one language");
-
- var mainLang = _.first(langs.list).lang;
- console.log("Main language is", mainLang);
-
- return Q()
- .then(function() {
- return fs.readFile(
- path.join(that.options.output, mainLang, "README.json")
- );
- })
- .then(function(content) {
- var json = JSON.parse(content);
- _.extend(json, {
- langs: langs.list
- });
-
- return fs.writeFile(
- path.join(that.options.output, "README.json"),
- JSON.stringify(json, null, 4)
- );
- });
-};
-
-Generator.prototype.finish = function() {
- // ignore
-};
-
-module.exports = Generator;
diff --git a/lib/generate/page/index.js b/lib/generate/page/index.js
deleted file mode 100644
index 8054fe6..0000000
--- a/lib/generate/page/index.js
+++ /dev/null
@@ -1,84 +0,0 @@
-var _ = require("lodash");
-var util = require("util");
-var path = require("path");
-var Q = require("q");
-var swig = require("../template");
-
-var fs = require("../fs");
-var parse = require("../../parse");
-var BaseGenerator = require("../site");
-
-var Generator = function() {
- BaseGenerator.apply(this, arguments);
-
- // Styles to use
- this.styles = ["ebook"];
-
- // Base for assets in plugins
- this.pluginAssetsBase = "ebook";
-
- // List of pages content
- this.pages = {};
-};
-util.inherits(Generator, BaseGenerator);
-
-Generator.prototype.loadTemplates = function() {
- this.template = swig.compileFile(
- 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() {
- var that = this;
- var basePath = ".";
- 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();
- })
-
- // Copy assets
- .then(function() {
- return that.copyAssets();
- });
-};
-
-// Generate languages index
-Generator.prototype.langsIndex = function(langs) {
- return Q();
-};
-
-module.exports = Generator;
diff --git a/lib/generate/plugin.js b/lib/generate/plugin.js
deleted file mode 100644
index 5ca5e92..0000000
--- a/lib/generate/plugin.js
+++ /dev/null
@@ -1,325 +0,0 @@
-var _ = require("lodash");
-var Q = require("q");
-var semver = require("semver");
-var path = require("path");
-var url = require("url");
-var fs = require("./fs");
-var npmi = require('npmi');
-var resolve = require('resolve');
-
-var pkg = require("../../package.json");
-
-var RESOURCES = ["js", "css"];
-
-var Plugin = function(name, root, generator) {
- this.name = name;
- this.root = root;
- this.packageInfos = {};
- this.infos = {};
- this.generator = generator;
-
- // Bind methods
- _.bindAll(this);
-
- _.each([
- "gitbook-plugin-"+name,
- "gitbook-theme-"+name,
- "gitbook-"+name,
- name,
- ], function(_name) {
- if (this.load(_name, __dirname)) return false;
- if (this.load(_name, path.resolve(root))) return false;
- }, this);
-};
-
-// Load from a name
-Plugin.prototype.load = function(name, baseDir) {
- try {
- var res = resolve.sync(name+"/package.json", { basedir: baseDir });
-
- this.baseDir = path.dirname(res);
- this.packageInfos = require(res);
- this.infos = require(resolve.sync(name, { basedir: baseDir }));
- this.name = name;
-
- return true;
- } catch (e) {
- return false;
- }
-};
-
-Plugin.prototype.normalizeResource = function(resource) {
- // Parse the resource path
- var parsed = url.parse(resource);
-
- // This is a remote resource
- // so we will simply link to using it's URL
- if (parsed.protocol) {
- return {
- "url": resource
- };
- }
-
- // This will be copied over from disk
- // and shipped with the book's build
- return { "path": this.name+"/"+resource };
-};
-
-// Return resources
-Plugin.prototype._getResources = function(base) {
- base = base || "book";
- var book = this.infos[base];
-
- // Nothing specified, fallback to default
- if (!book) {
- return Q({});
- }
-
- // Dynamic function
- if(typeof book === "function") {
- // Call giving it the context of our generator
- return Q().then(book.bind(this.generator));
- }
-
- // Plain data object
- return Q(_.cloneDeep(book));
-};
-
-// Normalize resources and return them
-Plugin.prototype.getResources = function(base) {
- var that = this;
-
- return this._getResources(base)
- .then(function(resources) {
-
- _.each(RESOURCES, function(resourceType) {
- resources[resourceType] = (resources[resourceType] || []).map(that.normalizeResource);
- });
-
- return resources;
- });
-};
-
-// Test if it's a valid plugin
-Plugin.prototype.isValid = function() {
- return (
- this.packageInfos &&
- this.packageInfos.name &&
- this.packageInfos.engines &&
- this.packageInfos.engines.gitbook &&
- semver.satisfies(pkg.version, this.packageInfos.engines.gitbook)
- );
-};
-
-// Resolve file path
-Plugin.prototype.resolveFile = function(filename) {
- return path.resolve(this.baseDir, filename);
-};
-
-// Resolve file path
-Plugin.prototype.callHook = function(name, data) {
- // Our generator will be the context to apply
- var context = this.generator;
-
- var hookFunc = this.infos.hooks? this.infos.hooks[name] : null;
- data = data || {};
-
- if (!hookFunc) return Q(data);
-
- return Q()
- .then(function() {
- return hookFunc.apply(context, [data]);
- });
-};
-
-// Copy plugin assets fodler
-Plugin.prototype.copyAssets = function(out, options) {
- var that = this;
- options = _.defaults(options || {}, {
- base: "book"
- });
-
- return this.getResources(options.base)
- .get('assets')
- .then(function(assets) {
- // Assets are undefined
- if(!assets) return false;
-
- return fs.copy(
- that.resolveFile(assets),
- out
- ).then(_.constant(true));
- }, _.constant(false));
-};
-
-
-// Install a list of plugin
-Plugin.install = function(options) {
- // Normalize list of plugins
- var plugins = Plugin.normalizeList(options.plugins);
-
- // Install plugins one by one
- return _.reduce(plugins, function(prev, plugin) {
- return prev.then(function() {
- var fullname = "gitbook-plugin-"+plugin.name;
- console.log("Install plugin", plugin.name, "from npm ("+fullname+") with version", (plugin.version || "*"));
- return Q.nfcall(npmi, {
- 'name': fullname,
- 'version': plugin.version,
- 'path': options.input,
- 'npmLoad': {
- 'loglevel': 'silent',
- 'loaded': false,
- 'prefix': options.input
- }
- });
- });
- }, Q());
-};
-
-// Normalize a list of plugins to use
-Plugin.normalizeList = function(plugins) {
- // Normalize list to an array
- plugins = _.isString(plugins) ? plugins.split(",") : (plugins || []);
-
- // Divide as {name, version} to handle format like "myplugin@1.0.0"
- plugins = _.map(plugins, function(plugin) {
- var parts = plugin.split("@");
- return {
- 'name': parts[0],
- 'version': parts[1] // optional
- }
- });
-
- // List plugins to remove
- var toremove = _.chain(plugins)
- .filter(function(plugin) {
- return plugin.name.length > 0 && plugin.name[0] == "-";
- })
- .map(function(plugin) {
- return plugin.name.slice(1);
- })
- .value();
-
- // Merge with defaults
- plugins = _.chain(plugins)
- .concat(_.map(Plugin.defaults, function(plugin) {
- return { 'name': plugin }
- }))
- .uniq()
- .value();
-
- // Build final list
- plugins = _.filter(plugins, function(plugin) {
- return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
- });
-
- return plugins;
-};
-
-// Normalize a list of plugin name to use
-Plugin.normalizeNames = function(plugins) {
- return _.pluck(Plugin.normalizeList(plugins), "name");
-};
-
-// Extract data from a list of plugin
-Plugin.fromList = function(names, root, generator, options) {
- options = _.defaults(options || {}, {
- assetsBase: "book"
- });
-
- var failed = [];
-
- // Load plugins
- var plugins = _.map(names, function(name) {
- var plugin = new Plugin(name, root, generator);
- if (!plugin.isValid()) failed.push(name);
- return plugin;
- });
-
- if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")+". Run 'gitbook install' to install plugins from NPM."));
-
- // The raw resources extracted from each plugin
- var pluginResources;
-
- // Get resources of plugins
- return Q.all(_.map(plugins, function(plugin) {
- return plugin.getResources(options.assetsBase);
- }))
- // Extract resources out
- // css, js, etc ...
- .then(function(resources) {
- pluginResources = resources;
- // Group by resource types
- return _.chain(RESOURCES)
- .map(function(resourceType) {
- // Get resources from all the plugins for this current type
- return [
- // Key
- resourceType,
- // Value
- _.chain(resources)
- .pluck(resourceType)
- .compact()
- .flatten()
- .value()
- ];
- })
- .object()
- .value();
- })
- // Extract html snippets
- .then(function(resources) {
- // Map of html resources by name added by each plugin
- resources.html = pluginResources.reduce(function(accu, resource) {
- var html = (resource && resource.html) || {};
- _.each(html, function(code, key) {
- // Turn into function if not one already
- if (!_.isFunction(code)) code = _.constant(code);
- // Append
- accu[key] = (accu[key] || []).concat([code]);
- });
-
- return accu;
- }, {});
-
- return resources;
- })
- // Return big multi-plugin object
- .then(function(resources) {
- return {
- 'list': plugins,
- 'resources': resources,
- 'hook': function(name, data) {
- return _.reduce(plugins, function(prev, plugin) {
- return prev.then(function(ret) {
- return plugin.callHook(name, ret);
- });
- }, Q(data));
- },
- 'template': function(name) {
- var withTpl = _.find(plugins, function(plugin) {
- return (
- plugin.infos.templates &&
- plugin.infos.templates[name]
- );
- });
-
- if (!withTpl) return null;
- return withTpl.resolveFile(withTpl.infos.templates[name]);
- },
- 'html': function(tag, context, options) {
- return _.map(resources.html[tag] || [], function(code) {
- return code.call(context, options);
- }).join("\n");
- }
- };
- });
-};
-
-// Default plugins added to each books
-Plugin.defaults = [
- "mathjax"
-];
-
-module.exports = Plugin;
diff --git a/lib/generate/site/glossary_indexer.js b/lib/generate/site/glossary_indexer.js
deleted file mode 100644
index 46ac9a4..0000000
--- a/lib/generate/site/glossary_indexer.js
+++ /dev/null
@@ -1,101 +0,0 @@
-var _ = require("lodash");
-var kramed = require('kramed');
-var textRenderer = require('kramed-text-renderer');
-
-var entryId = require('../../parse/glossary').entryId;
-
-
-function Indexer(glossary) {
- if(!(this instanceof Indexer)) {
- return new Indexer(glossary);
- }
-
- _.bindAll(this);
-
- this.glossary = glossary || [];
-
- this.glossaryTerms = _.pluck(this.glossary, "id");
-
- // Regex for searching for terms through body
- this.termsRegex = new RegExp(
- // Match any of the terms
- "("+
- this.glossaryTerms.map(regexEscape).join('|') +
- ")",
-
- // Flags
- "gi"
- );
-
- // page url => terms
- this.idx = {
- /*
- "a/b.html": ["one word", "second word"]
- */
- };
-
- // term => page urls
- this.invertedIdx = {
- /*
- "word1": ["page1.html", "page2.html"]
- */
- };
-
- // Use text renderer
- this.renderer = textRenderer();
-}
-
-Indexer.prototype.text = function(nodes) {
- // Copy section
- var section = _.toArray(nodes);
-
- // kramed's Render expects this, we don't use it yet
- section.links = {};
-
- var options = _.extend({}, kramed.defaults, {
- renderer: this.renderer
- });
-
- return kramed.parser(section, options);
-};
-
-// Add page to glossary index
-Indexer.prototype.add = function(sections, url) {
- if(!(this.glossary && this.glossary.length > 0)) {
- return;
- }
-
- var textblob =
- _.where(sections, { type: 'normal' })
- .map(this.text)
- .join('\n');
-
- var matches = _(textblob.match(this.termsRegex) || [])
- .map(entryId)
- .uniq()
- .value();
-
- // Add idx for book
- this.idx[url] = matches;
-
- // Add to inverted idx
- matches.forEach(function(match) {
- if(!this.invertedIdx[match]) {
- this.invertedIdx[match] = [];
- }
- this.invertedIdx[match].push(url);
- }.bind(this));
-};
-
-// Dump index as a string
-Indexer.prototype.dump = function() {
- return JSON.stringify(this.idx);
-};
-
-
-function regexEscape(s) {
- return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
-}
-
-// Exports
-module.exports = Indexer;
diff --git a/lib/generate/site/index.js b/lib/generate/site/index.js
deleted file mode 100644
index dfdbf68..0000000
--- a/lib/generate/site/index.js
+++ /dev/null
@@ -1,314 +0,0 @@
-var util = require("util");
-var path = require("path");
-var Q = require("q");
-var _ = require("lodash");
-var swig = require("../template");
-
-var fs = require("../fs");
-var parse = require("../../parse");
-var BaseGenerator = require("../generator");
-var links = require("../../utils/links");
-var indexer = require('./search_indexer');
-var glossaryIndexer = require('./glossary_indexer');
-
-
-var Generator = function() {
- BaseGenerator.apply(this, arguments);
-
- // Attach methods to instance
- _.bindAll(this);
-
- this.styles = ["website"];
- this.revision = Date.now();
- this.indexer = indexer();
-};
-util.inherits(Generator, BaseGenerator);
-
-// Add template loading to load
-Generator.prototype.load = function() {
- var that = this;
-
- return BaseGenerator.prototype.load.apply(this)
- .then(function() {
- return that.loadStyles();
- })
- .then(function() {
- return that.loadTemplates();
- });
-};
-
-// Load all styles
-Generator.prototype.loadStyles = function() {
- var that = this;
- this.styles = _.chain(this.styles)
- .map(function(style) {
- var stylePath = that.options.styles[style];
- if (fs.existsSync(path.resolve(that.options.input, stylePath))) {
- return stylePath;
- }
- return null;
- })
- .compact()
- .value();
-};
-
-// Load all templates
-Generator.prototype.loadTemplates = function() {
- this.template = swig.compileFile(
- this.plugins.template("site:page") || path.resolve(this.options.theme, 'templates/website/page.html')
- );
- this.langsTemplate = swig.compileFile(
- this.plugins.template("site:langs") || path.resolve(this.options.theme, 'templates/website/langs.html')
- );
- this.glossaryTemplate = swig.compileFile(
- this.plugins.template("site:glossary") || path.resolve(this.options.theme, 'templates/website/glossary.html')
- );
-};
-
-// Generate a template
-Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) {
- var that = this;
-
- interpolate = interpolate || _.identity;
- return Q()
- .then(function(sections) {
- return tpl(_.extend({
- styles: that.styles,
-
- revision: that.revision,
-
- title: that.options.title,
- description: that.options.description,
-
- glossary: that.options.glossary,
-
- summary: that.options.summary,
- allNavigation: that.options.navigation,
-
- plugins: that.plugins,
- pluginsConfig: JSON.stringify(that.options.pluginsConfig),
- htmlSnippet: _.partialRight(that.plugins.html, that, options),
-
- options: that.options
- }, options));
- })
- .then(interpolate)
- .then(function(html) {
- return fs.writeFile(
- output,
- html
- );
- });
-};
-
-Generator.prototype.indexPage = function(lexed, pagePath) {
- // Setup glossary indexer if not yet setup
- if(!this.glossaryIndexer) {
- this.glossaryIndexer = glossaryIndexer(this.options.glossary);
- }
-
- this.indexer.add(lexed, pagePath);
- this.glossaryIndexer.add(lexed, pagePath);
- return Q();
-};
-
-// Convert a markdown file into a normalized data set
-Generator.prototype.prepareFile = function(content, _input) {
- var that = this;
-
- var input = path.join(this.options.input, _input);
-
- var page = {
- path: _input,
- rawPath: input,
- content: content,
- progress: parse.progress(this.options.navigation, _input)
- };
-
- var _callHook = function(name) {
- return that.callHook(name, page)
- .then(function(_page) {
- page = _page;
- return page;
- });
- };
-
- return Q()
- .then(function() {
- // Send content to plugins
- return _callHook("page:before");
- })
- .then(function() {
- // Lex, parse includes and get
- // Get HTML generated sections
- 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(parsed) {
- page.lexed = parsed.lexed;
- page.sections = parsed.sections;
-
- // Use plugin hook
- return _callHook("page");
- })
- .then(function() {
- return page;
- });
-};
-
-// Convert a markdown file to html
-Generator.prototype.convertFile = function(content, _input) {
- var that = this;
-
- var _output = _input.replace(".md", ".html");
- 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
- return that.indexPage(page.lexed, _output).thenResolve(page);
- })
- .then(function(page) {
- // Write file
- return that._writeTemplate(that.template, {
- progress: page.progress,
-
- _input: page.path,
- content: page.sections,
-
- basePath: basePath,
- staticBase: links.join(basePath, "gitbook"),
- }, output, function(html) {
- page.content = html;
-
- return that.callHook("page:after", page).get("content")
- });
- });
-};
-
-// Generate languages index
-Generator.prototype.langsIndex = function(langs) {
- var that = this;
- var basePath = ".";
-
- return this._writeTemplate(this.langsTemplate, {
- langs: langs.list,
-
- basePath: basePath,
- staticBase: path.join(basePath, "gitbook"),
- }, path.join(this.options.output, "index.html"))
- .then(function() {
- // Copy assets
- return that.copyAssets();
- });
-};
-
-// Generate glossary
-Generator.prototype.writeGlossary = function() {
- var that = this;
- var basePath = ".";
-
- // No glossary
- if (!this.glossaryIndexer) return Q();
-
- // Transform the glossary to get term, description, files
- var glossary = _.chain(this.glossaryIndexer.invertedIdx)
- .map(function(links, id) {
- var term = _.find(that.options.glossary, { 'id': id });
-
- return {
- id: id,
- name: term.name,
- description: term.description,
- files: _.chain(links)
- .map(function(link) {
- var name = link.slice(0, -5);
-
- if (name == "index") {
- name = "README";
- }
- return that.options.navigation[name+".md"];
- })
- .sortBy("percent")
- .value()
- }
- })
- .sortBy("name")
- .value();
-
- return this._writeTemplate(this.glossaryTemplate, {
- glossaryIndex: glossary,
- basePath: basePath,
- staticBase: path.join(basePath, "gitbook"),
- }, path.join(this.options.output, "GLOSSARY.html"));
-};
-
-// Copy assets
-Generator.prototype.copyAssets = function() {
- var that = this;
-
- // Copy gitbook assets
- return fs.copy(
- path.join(that.options.theme, "assets"),
- path.join(that.options.output, "gitbook")
- )
-
- // Copy plugins assets
- .then(function() {
- return Q.all(
- _.map(that.plugins.list, function(plugin) {
- var pluginAssets = path.join(that.options.output, "gitbook/plugins/", plugin.name);
- return plugin.copyAssets(pluginAssets, {
- base: that.pluginAssetsBase
- });
- })
- );
- });
-};
-
-// Dump search index to disk
-Generator.prototype.writeSearchIndex = function() {
- return fs.writeFile(
- path.join(this.options.output, 'search_index.json'),
- this.indexer.dump()
- );
-};
-
-// Dump glossary index to disk
-Generator.prototype.writeGlossaryIndex = function() {
- if (!this.glossaryIndexer) return Q();
-
- return fs.writeFile(
- path.join(this.options.output, 'glossary_index.json'),
- JSON.stringify(this.options.glossary)
- );
-};
-
-
-Generator.prototype.finish = function() {
- return this.copyAssets()
- .then(this.copyCover)
- .then(this.writeGlossary)
- .then(this.writeGlossaryIndex)
- .then(this.writeSearchIndex);
-};
-
-module.exports = Generator;
diff --git a/lib/generate/site/search_indexer.js b/lib/generate/site/search_indexer.js
deleted file mode 100644
index 7cfe29a..0000000
--- a/lib/generate/site/search_indexer.js
+++ /dev/null
@@ -1,71 +0,0 @@
-var Q = require("q");
-var _ = require("lodash");
-
-var lunr = require('lunr');
-var kramed = require('kramed');
-var textRenderer = require('kramed-text-renderer');
-
-
-function Indexer() {
- if(!(this instanceof Indexer)) {
- return new Indexer();
- }
-
- _.bindAll(this);
-
- // Setup lunr index
- this.idx = lunr(function () {
- this.ref('url');
-
- this.field('title', { boost: 10 });
- this.field('body');
- });
-
- this.renderer = textRenderer();
-}
-
-Indexer.prototype.text = function(nodes) {
- // Copy section
- var section = _.toArray(nodes);
-
- // kramed's Render expects this, we don't use it yet
- section.links = {};
-
- var options = _.extend({}, kramed.defaults, {
- renderer: this.renderer
- });
-
- return kramed.parser(section, options);
-};
-
-Indexer.prototype.addSection = function(path, section) {
- var url = [path, section.id].join('#');
-
- var title = this.text(
- _.filter(section, {'type': 'heading'})
- );
-
- var body = this.text(
- _.omit(section, {'type': 'heading'})
- );
-
- // Add to lunr index
- this.idx.add({
- url: url,
- title: title,
- body: body,
- });
-};
-
-Indexer.prototype.add = function(lexedPage, url) {
- var sections = lexedPage;
-
- _.map(sections, _.partial(this.addSection, url));
-};
-
-Indexer.prototype.dump = function() {
- return JSON.stringify(this.idx);
-};
-
-// Exports
-module.exports = Indexer;
diff --git a/lib/generate/template.js b/lib/generate/template.js
deleted file mode 100644
index acfa580..0000000
--- a/lib/generate/template.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var path = require("path");
-var swig = require('swig');
-var hljs = require('highlight.js');
-
-var links = require('../utils/').links;
-var pkg = require('../../package.json');
-
-swig.setDefaults({
- locals: {
- gitbook: {
- version: pkg.version
- }
- }
-});
-
-// Swig filter for returning the count of lines in a code section
-swig.setFilter('lines', function(content) {
- return content.split('\n').length;
-});
-
-// Swig filter for returning a link to the associated html file of a markdown file
-swig.setFilter('mdLink', function(link) {
- var link = link.replace(".md", ".html");
- if (link == "README.html") link = "index.html";
- return link;
-});
-
-// Swig filter: highlight coloration
-swig.setFilter('code', function(code, lang) {
- try {
- return hljs.highlight(lang, code).value;
- } catch(e) {
- return hljs.highlightAuto(code).value;
- }
-});
-
-// Convert a level into a deep level
-swig.setFilter('lvl', function(lvl) {
- return lvl.split(".").length;
-});
-
-// Join path
-swig.setFilter('pathJoin', function(base, _path) {
- return links.join(base, _path);
-});
-
-// Is a link an absolute link
-swig.setFilter('isExternalLink', function(link) {
- return links.isExternal(link);
-});
-
-module.exports = swig;
diff --git a/lib/index.js b/lib/index.js
deleted file mode 100644
index ba240ce..0000000
--- a/lib/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- parse: require('./parse/'),
- generate: require('./generate/')
-};
-
diff --git a/lib/parse/glossary.js b/lib/parse/glossary.js
deleted file mode 100644
index 549e9fd..0000000
--- a/lib/parse/glossary.js
+++ /dev/null
@@ -1,48 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-
-// Get all the pairs of header + paragraph in a list of nodes
-function groups(nodes) {
- // A list of next nodes
- var next = nodes.slice(1).concat(null);
-
- return _.reduce(nodes, function(accu, node, idx) {
- // Skip
- if(!(
- node.type === 'heading' &&
- (next[idx] && next[idx].type === 'paragraph')
- )) {
- return accu;
- }
-
- // Add group
- accu.push([
- node,
- next[idx]
- ]);
-
- return accu;
- }, []);
-}
-
-function parseGlossary(src) {
- var nodes = kramed.lexer(src);
-
- return groups(nodes)
- .map(function(pair) {
- // Simplify each group to a simple object with name/description
- return {
- name: pair[0].text,
- id: entryId(pair[0].text),
- description: pair[1].text,
- };
- });
-}
-
-// Normalizes a glossary entry's name to create an ID
-function entryId(name) {
- return name.toLowerCase();
-}
-
-module.exports = parseGlossary;
-module.exports.entryId = entryId;
diff --git a/lib/parse/include.js b/lib/parse/include.js
deleted file mode 100644
index 483b184..0000000
--- a/lib/parse/include.js
+++ /dev/null
@@ -1,12 +0,0 @@
-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;
- });
-};
diff --git a/lib/parse/includer.js b/lib/parse/includer.js
deleted file mode 100644
index f7f20e0..0000000
--- a/lib/parse/includer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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];
- }
-};
diff --git a/lib/parse/index.js b/lib/parse/index.js
deleted file mode 100644
index 23471af..0000000
--- a/lib/parse/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-module.exports = {
- summary: require('./summary'),
- glossary: require('./glossary'),
- langs: require('./langs'),
- page: require('./page'),
- lex: require('./lex'),
- progress: require('./progress'),
- navigation: require('./navigation'),
- readme: require('./readme'),
- includer: require('./includer')
-};
diff --git a/lib/parse/is_exercise.js b/lib/parse/is_exercise.js
deleted file mode 100644
index 74ed753..0000000
--- a/lib/parse/is_exercise.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var _ = require('lodash');
-
-function isExercise(nodes) {
- var codeType = { type: 'code' };
-
- // Number of code nodes in section
- var len = _.filter(nodes, codeType).length;
-
- return (
- // Got 3 or 4 code blocks
- (len === 3 || len === 4) &&
- // Ensure all nodes are at the end
- _.all(_.last(nodes, len), codeType)
- );
-}
-
-module.exports = isExercise;
diff --git a/lib/parse/is_quiz.js b/lib/parse/is_quiz.js
deleted file mode 100644
index 3322ff0..0000000
--- a/lib/parse/is_quiz.js
+++ /dev/null
@@ -1,87 +0,0 @@
-var _ = require('lodash');
-
-function isQuizNode(node) {
- return (/^[(\[][ x][)\]]/).test(node.text || node);
-}
-
-function isTableQuestion(nodes) {
- var block = questionBlock(nodes);
- return (
- block.length === 1 &&
- block[0].type === 'table' &&
- _.all(block[0].cells[0].slice(1), isQuizNode)
- );
-}
-
-function isListQuestion(nodes) {
- var block = questionBlock(nodes);
- // Counter of when we go in and out of lists
- var inlist = 0;
- // Number of lists we found
- var lists = 0;
- // Elements found outside a list
- var outsiders = 0;
- // Ensure that we have nothing except lists
- _.each(block, function(node) {
- if(node.type === 'list_start') {
- inlist++;
- } else if(node.type === 'list_end') {
- inlist--;
- lists++;
- } else if(inlist === 0) {
- // Found non list_start or list_end whilst outside a list
- outsiders++;
- }
- });
- return lists > 0 && outsiders === 0;
-}
-
-function isQuestion(nodes) {
- return isListQuestion(nodes) || isTableQuestion(nodes);
-}
-
-// Remove (optional) paragraph header node and blockquote
-function questionBlock(nodes) {
- return nodes.slice(
- nodes[0].type === 'paragraph' ? 1 : 0,
- _.findIndex(nodes, { type: 'blockquote_start' })
- );
-}
-
-function splitQuestions(nodes) {
- // Represents nodes in current question
- var buffer = [];
- return _.reduce(nodes, function(accu, node) {
- // Add node to buffer
- buffer.push(node);
-
- // Flush buffer once we hit the end of a question
- if(node.type === 'blockquote_end') {
- accu.push(buffer);
- // Clear buffer
- buffer = [];
- }
-
- return accu;
- }, []);
-}
-
-function isQuiz(nodes) {
- // Extract potential questions
- var questions = splitQuestions(
- // Skip quiz title if there
- nodes.slice(
- (nodes[0] && nodes[0].type) === 'paragraph' ? 1 : 0
- )
- );
-
- // Nothing that looks like questions
- if(questions.length === 0) {
- return false;
- }
-
- // Ensure all questions are correctly structured
- return _.all(questions, isQuestion);
-}
-
-module.exports = isQuiz;
diff --git a/lib/parse/langs.js b/lib/parse/langs.js
deleted file mode 100644
index 01b7c8c..0000000
--- a/lib/parse/langs.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var _ = require("lodash");
-var parseEntries = require("./summary").entries;
-
-
-var parseLangs = function(content) {
- var entries = parseEntries(content);
-
- return {
- list: _.chain(entries)
- .filter(function(entry) {
- return Boolean(entry.path);
- })
- .map(function(entry) {
- return {
- title: entry.title,
- path: entry.path,
- lang: entry.path.replace("/", "")
- };
- })
- .value()
- };
-};
-
-
-module.exports = parseLangs; \ No newline at end of file
diff --git a/lib/parse/lex.js b/lib/parse/lex.js
deleted file mode 100644
index 3391acf..0000000
--- a/lib/parse/lex.js
+++ /dev/null
@@ -1,79 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-
-var isExercise = require('./is_exercise');
-var isQuiz = require('./is_quiz');
-
-// Split a page up into sections (lesson, exercises, ...)
-function splitSections(nodes) {
- var section = [];
-
- return _.reduce(nodes, function(sections, el) {
- if(el.type === 'hr') {
- sections.push(section);
- section = [];
- } else {
- section.push(el);
- }
-
- return sections;
- }, []).concat([section]); // Add remaining nodes
-}
-
-// What is the type of this section
-function sectionType(nodes, idx) {
- if(isExercise(nodes)) {
- return 'exercise';
- } else if(isQuiz(nodes)) {
- return 'quiz';
- }
-
- return 'normal';
-}
-
-// Generate a uniqueId to identify this section in our code
-function sectionId(section, idx) {
- return _.uniqueId('gitbook_');
-}
-
-function lexPage(src) {
- // Lex file
- var nodes = kramed.lexer(src);
-
- return _.chain(splitSections(nodes))
- .map(function(section, idx) {
- // Detect section type
- section.type = sectionType(section, idx);
- return section;
- })
- .map(function(section, idx) {
- // Give each section an ID
- section.id = sectionId(section, idx);
- return section;
-
- })
- .filter(function(section) {
- return !_.isEmpty(section);
- })
- .reduce(function(sections, section) {
- var last = _.last(sections);
-
- // Merge normal sections together
- if(last && last.type === section.type && last.type === 'normal') {
- last.push.apply(last, [{'type': 'hr'}].concat(section));
- } else {
- // Add to list of sections
- sections.push(section);
- }
-
- return sections;
- }, [])
- .map(function(section) {
- section.links = nodes.links;
- return section;
- })
- .value();
-}
-
-// Exports
-module.exports = lexPage;
diff --git a/lib/parse/navigation.js b/lib/parse/navigation.js
deleted file mode 100644
index ae4eb9d..0000000
--- a/lib/parse/navigation.js
+++ /dev/null
@@ -1,64 +0,0 @@
-var _ = require('lodash');
-
-// Cleans up an article/chapter object
-// remove 'articles' attributes
-function clean(obj) {
- return obj && _.omit(obj, ['articles']);
-}
-
-function flattenChapters(chapters) {
- return _.reduce(chapters, function(accu, chapter) {
- return accu.concat([clean(chapter)].concat(flattenChapters(chapter.articles)));
- }, []);
-}
-
-// Returns from a summary a map of
-/*
- {
- "file/path.md": {
- prev: ...,
- next: ...,
- },
- ...
- }
-*/
-function navigation(summary, files) {
- // Support single files as well as list
- files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
-
- // List of all navNodes
- // Flatten chapters, then add in default README node if ndeeded etc ...
- var navNodes = flattenChapters(summary.chapters);
- var prevNodes = [null].concat(navNodes.slice(0, -1));
- var nextNodes = navNodes.slice(1).concat([null]);
-
- // Mapping of prev/next for a give path
- var mapping = _.chain(_.zip(navNodes, prevNodes, nextNodes))
- .map(function(nodes) {
- var current = nodes[0], prev = nodes[1], next = nodes[2];
-
- // Skip if no path
- if(!current.path) return null;
-
- return [current.path, {
- title: current.title,
- prev: prev,
- next: next,
- level: current.level,
- }];
- })
- .filter()
- .object()
- .value();
-
- // Filter for only files we want
- if(files) {
- return _.pick(mapping, files);
- }
-
- return mapping;
-}
-
-
-// Exports
-module.exports = navigation;
diff --git a/lib/parse/page.js b/lib/parse/page.js
deleted file mode 100644
index 5fb2081..0000000
--- a/lib/parse/page.js
+++ /dev/null
@@ -1,160 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-var hljs = require('highlight.js');
-
-var lex = require('./lex');
-var renderer = require('./renderer');
-
-var include = require('./include');
-var lnormalize = require('../utils/lang').normalize;
-
-
-
-// Render a section using our custom renderer
-function render(section, _options) {
- // Copy section
- var links = section.links || {};
- section = _.toArray(section);
- section.links = links;
-
- // Build options using defaults and our custom renderer
- var options = _.extend({}, kramed.defaults, {
- renderer: renderer(null, _options),
-
- // Synchronous highlighting with highlight.js
- highlight: function (code, lang) {
- if(!lang) return code;
-
- // Normalize lang
- lang = lnormalize(lang);
-
- try {
- return hljs.highlight(lang, code).value;
- } catch(e) { }
-
- return code;
- }
- });
-
- return kramed.parser(section, options);
-}
-
-function quizQuestion(node) {
- if (node.text) {
- node.text = node.text.replace(/^([\[(])x([\])])/, "$1 $2");
- } else {
- return node.replace(/^([\[(])x([\])])/, "$1 $2");
- }
-}
-
-function parsePage(src, options) {
- options = options || {};
-
- // Lex if not already lexed
- 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, {
- 'type': 'code'
- });
-
- var codeNodes = _.filter(section, {
- 'type': 'code'
- });
-
- // Languages in code blocks
- var langs = _.pluck(codeNodes, 'lang').map(lnormalize);
-
- // Check that they are all the same
- var validLangs = _.all(_.map(langs, function(lang) {
- return lang && lang === langs[0];
- }));
-
- // Main language
- var lang = validLangs ? langs[0] : null;
-
- return {
- id: section.id,
- type: section.type,
- content: render(nonCodeNodes, options),
- lang: lang,
- code: {
- base: codeNodes[0].text,
- solution: codeNodes[1].text,
- validation: codeNodes[2].text,
- // Context is optional
- context: codeNodes[3] ? codeNodes[3].text : null,
- }
- };
- } else if (section.type === 'quiz') {
- var quiz = [], question, foundFeedback = false;
- var nonQuizNodes = section[0].type === 'paragraph' && section[1].type !== 'list_start' ? [section[0]] : [];
- var quizNodes = section.slice(0);
- quizNodes.splice(0, nonQuizNodes.length);
-
- for (var i = 0; i < quizNodes.length; i++) {
- var node = quizNodes[i];
-
- if (question && (((node.type === 'list_end' || node.type === 'blockquote_end') && i === quizNodes.length - 1)
- || node.type === 'table' || (node.type === 'paragraph' && !foundFeedback))) {
- quiz.push({
- base: render(question.questionNodes, options),
- solution: render(question.solutionNodes, options),
- feedback: render(question.feedbackNodes, options)
- });
- }
-
- if (node.type === 'table' || (node.type === 'paragraph' && !foundFeedback)) {
- question = { questionNodes: [], solutionNodes: [], feedbackNodes: [] };
- }
-
- if (node.type === 'blockquote_start') {
- foundFeedback = true;
- } else if (node.type === 'blockquote_end') {
- foundFeedback = false;
- }
-
- if (node.type === 'table') {
- question.solutionNodes.push(_.cloneDeep(node));
- node.cells = node.cells.map(function(row) {
- return row.map(quizQuestion);
- });
- question.questionNodes.push(node);
- } else if (!/blockquote/.test(node.type)) {
- if (foundFeedback) {
- question.feedbackNodes.push(node);
- } else if (node.type === 'paragraph' || node.type === 'text'){
- question.solutionNodes.push(_.cloneDeep(node));
- quizQuestion(node);
- question.questionNodes.push(node);
- } else {
- question.solutionNodes.push(node);
- question.questionNodes.push(node);
- }
- }
- }
-
- return {
- id: section.id,
- type: section.type,
- content: render(nonQuizNodes, options),
- quiz: quiz
- };
- }
-
- // Render normal pages
- return {
- id: section.id,
- type: section.type,
- content: render(section, options)
- };
- });
-
- return parsed;
-}
-
-// Exports
-module.exports = parsePage;
diff --git a/lib/parse/progress.js b/lib/parse/progress.js
deleted file mode 100644
index 10a06d2..0000000
--- a/lib/parse/progress.js
+++ /dev/null
@@ -1,47 +0,0 @@
-var _ = require("lodash");
-
-// Returns from a navigation and a current file, a snapshot of current detailed state
-var calculProgress = function(navigation, current) {
- var n = _.size(navigation);
- var percent = 0, prevPercent = 0, currentChapter = null;
- var done = true;
-
- var chapters = _.chain(navigation)
- .map(function(nav, path) {
- nav.path = path;
- return nav;
- })
- .map(function(nav, i) {
- // Calcul percent
- nav.percent = (i * 100) / Math.max((n - 1), 1);
-
- // Is it done
- nav.done = done;
- if (nav.path == current) {
- currentChapter = nav;
- percent = nav.percent;
- done = false;
- } else if (done) {
- prevPercent = nav.percent;
- }
-
- return nav;
- })
- .value();
-
- return {
- // Previous percent
- prevPercent: prevPercent,
-
- // Current percent
- percent: percent,
-
- // List of chapter with progress
- chapters: chapters,
-
- // Current chapter
- current: currentChapter
- };
-}
-
-module.exports = calculProgress; \ No newline at end of file
diff --git a/lib/parse/readme.js b/lib/parse/readme.js
deleted file mode 100644
index 9d8f552..0000000
--- a/lib/parse/readme.js
+++ /dev/null
@@ -1,45 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-var textRenderer = require('kramed-text-renderer');
-
-function extractFirstNode(nodes, nType) {
- return _.chain(nodes)
- .filter(function(node) {
- return node.type == nType;
- })
- .pluck("text")
- .first()
- .value();
-}
-
-
-function parseReadme(src) {
- var nodes, title, description;
- var renderer = textRenderer();
-
- // Parse content
- nodes = kramed.lexer(src);
-
- title = extractFirstNode(nodes, "heading") || '';
- description = extractFirstNode(nodes, "paragraph") || '';
-
- var convert = _.compose(
- function(text) {
- return _.unescape(text.replace(/(\r\n|\n|\r)/gm, ""));
- },
- function(text) {
- return kramed.parse(text, _.extend({}, kramed.defaults, {
- renderer: renderer
- }));
- }
- );
-
- return {
- title: convert(title),
- description: convert(description)
- };
-}
-
-
-// Exports
-module.exports = parseReadme;
diff --git a/lib/parse/renderer.js b/lib/parse/renderer.js
deleted file mode 100644
index 5b6a79d..0000000
--- a/lib/parse/renderer.js
+++ /dev/null
@@ -1,141 +0,0 @@
-var url = require('url');
-var _ = require('lodash');
-var inherits = require('util').inherits;
-var links = require('../utils').links;
-var kramed = require('kramed');
-
-var rendererId = 0;
-
-function GitBookRenderer(options, extra_options) {
- if(!(this instanceof GitBookRenderer)) {
- return new GitBookRenderer(options, extra_options);
- }
- GitBookRenderer.super_.call(this, options);
-
- this._extra_options = extra_options;
- this.quizRowId = 0;
- this.id = rendererId++;
- this.quizIndex = 0;
-}
-inherits(GitBookRenderer, kramed.Renderer);
-
-GitBookRenderer.prototype._unsanitized = function(href) {
- var prot = '';
- try {
- prot = decodeURIComponent(unescape(href))
- .replace(/[^\w:]/g, '')
- .toLowerCase();
-
- } catch (e) {
- return true;
- }
-
- if(prot.indexOf('javascript:') === 0) {
- return true;
- }
-
- return false;
-};
-
-GitBookRenderer.prototype.link = function(href, title, text) {
- // Our "fixed" href
- var _href = href;
-
- // Don't build if it looks malicious
- if (this.options.sanitize && this._unsanitized(href)) {
- return 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) && extname == "md") {
- _href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
- _href = _href.replace(".md", ".html");
- }
-
- // Generate HTML for link
- var out = '<a href="' + _href + '"';
- // Title if no null
- if (title) {
- out += ' title="' + title + '"';
- }
- // Target blank if external
- if(parsed.protocol) {
- out += ' target="_blank"';
- }
- out += '>' + text + '</a>';
- return out;
-};
-
-GitBookRenderer.prototype.image = function(href, title, text) {
- // Our "fixed" href
- var _href = href;
-
- // Parsed version of the url
- var parsed = url.parse(href);
-
- // Options
- var o = this._extra_options;
-
- // Relative image, rewrite it depending output
- if(links.isRelative(href) && o && o.dir && o.outdir) {
- // o.dir: directory parent of the file currently in rendering process
- // o.outdir: directory parent from the html output
-
- _href = links.toAbsolute(_href, o.dir, o.outdir);
- }
-
- return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
-};
-
-GitBookRenderer.prototype.tablerow = function(content) {
- this.quizRowId += 1;
- return GitBookRenderer.super_.prototype.tablerow(content);
-};
-
-var fieldRegex = /^([(\[])([ x])[\])]/;
-GitBookRenderer.prototype._createCheckboxAndRadios = function(text) {
- var match = fieldRegex.exec(text);
- if (!match) {
- return text;
- }
- //fix radio input uncheck failed
- var quizFieldName='quiz-row-' + this.id + '-' + this.quizRowId ;
- var quizIdentifier = quizFieldName + '-' + this.quizIndex++;
- var field = "<input name='" + quizFieldName + "' id='" + quizIdentifier + "' type='";
- field += match[1] === '(' ? "radio" : "checkbox";
- field += match[2] === 'x' ? "' checked/>" : "'/>";
- var splittedText = text.split(fieldRegex);
- var length = splittedText.length;
- var label = '<label class="quiz-label" for="' + quizIdentifier + '">' + splittedText[length - 1] + '</label>';
- return text.replace(fieldRegex, field).replace(splittedText[length - 1], label);
-};
-
-GitBookRenderer.prototype.tablecell = function(content, flags) {
- return GitBookRenderer.super_.prototype.tablecell(this._createCheckboxAndRadios(content), flags);
-};
-
-GitBookRenderer.prototype.listitem = function(text) {
- return GitBookRenderer.super_.prototype.listitem(this._createCheckboxAndRadios(text));
-};
-
-GitBookRenderer.prototype.code = function(code, lang, escaped) {
- return GitBookRenderer.super_.prototype.code.call(
- this,
- code,
- lang,
- escaped
- );
-};
-
-GitBookRenderer.prototype.heading = function(text, level, raw) {
- var id = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w -]+/g, '').replace(/ /g, '-');
- return '<h' + level + ' id="' + id + '">' + text + '</h' + level + '>\n';
-};
-
-// Exports
-module.exports = GitBookRenderer;
diff --git a/lib/parse/summary.js b/lib/parse/summary.js
deleted file mode 100644
index 2fdec8a..0000000
--- a/lib/parse/summary.js
+++ /dev/null
@@ -1,167 +0,0 @@
-var _ = require('lodash');
-var kramed = require('kramed');
-
-
-// Utility function for splitting a list into groups
-function splitBy(list, starter, ender) {
- var starts = 0;
- var ends = 0;
- var group = [];
-
- // Groups
- return _.reduce(list, function(groups, value) {
- // Ignore start and end delimiters in resulted groups
- if(starter(value)) {
- starts++;
- } else if(ender(value)) {
- ends++;
- }
-
- // Add current value to group
- group.push(value);
-
- // We've got a matching
- if(starts === ends && starts !== 0) {
- // Add group to end groups
- // (remove starter and ender token)
- groups.push(group.slice(1, -1));
-
- // Reset group
- group = [];
- }
-
- return groups;
- }, []);
-}
-
-function listSplit(nodes, start_type, end_type) {
- return splitBy(nodes, function(el) {
- return el.type === start_type;
- }, function(el) {
- return el.type === end_type;
- });
-}
-
-// Get the biggest list
-// out of a list of kramed nodes
-function filterList(nodes) {
- return _.chain(nodes)
- .toArray()
- .rest(function(el) {
- // Get everything after list_start
- return el.type !== 'list_start';
- })
- .reverse()
- .rest(function(el) {
- // Get everything after list_end (remember we're reversed)
- return el.type !== 'list_end';
- })
- .reverse()
- .value().slice(1, -1);
-}
-
-function skipSpace(nodes) {
- return _.filter(nodes, function(node) {
- return node && node.type != 'space';
- });
-}
-
-function correctLoose(nodes) {
- return _.map(nodes, function(node) {
- // Return normal nodes
- if(!node || node.type != 'loose_item_start') {
- return node
- }
-
- // Correct loose items
- node.type = 'list_item_start';
-
- return node;
- })
-}
-
-// Parses an Article or Chapter title
-// supports extracting links
-function parseTitle(src, nums) {
- // Check if it's a link
- var matches = kramed.InlineLexer.rules.link.exec(src);
-
- var level = nums.join('.');
-
- // Not a link, return plain text
- if(!matches) {
- return {
- title: src,
- level: level,
- path: null,
- };
- }
-
- return {
- title: matches[1],
- level: level,
-
- // Normalize path
- // 1. Convert Window's "\" to "/"
- // 2. Remove leading "/" if exists
- path: matches[2].replace(/\\/g, '/').replace(/^\/+/, ''),
- };
-}
-
-function parseChapter(nodes, nums) {
- // Convert single number to an array
- nums = _.isArray(nums) ? nums : [nums];
-
- return _.extend(parseTitle(_.first(nodes).text, nums), {
- articles: _.map(listSplit(filterList(nodes), 'list_item_start', 'list_item_end'), function(nodes, i) {
- return parseChapter(nodes, nums.concat(i + 1));
- })
- });
-}
-
-function defaultChapterList(chapterList) {
- var first = _.first(chapterList);
-
- // Check if introduction node was specified in SUMMARY.md
- if (first) {
- var chapter = parseChapter(first, [0]);
-
- // Already have README node, we're good to go
- if(chapter.path === 'README.md') {
- return chapterList;
- }
- }
-
- // It wasn't specified, so add in default
- return [
- [ { type: 'text', text: '[Introduction](README.md)' } ]
- ].concat(chapterList);
-}
-
-function listGroups(src) {
- var nodes = kramed.lexer(src);
-
- // Get out groups of lists
- return listSplit(
- filterList(correctLoose(skipSpace(nodes))),
- 'list_item_start', 'list_item_end'
- );
-}
-
-function parseSummary(src) {
- // Split out chapter sections
- var chapters = defaultChapterList(listGroups(src));
-
- return {
- chapters: chapters.map(parseChapter)
- };
-}
-
-function parseEntries (src) {
- return listGroups(src).map(parseChapter);
-}
-
-
-// Exports
-module.exports = parseSummary;
-module.exports.entries = parseEntries;
diff --git a/lib/utils/index.js b/lib/utils/index.js
deleted file mode 100644
index dbc4087..0000000
--- a/lib/utils/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = {
- lang: require('./lang'),
- links: require('./links')
-};
diff --git a/lib/utils/lang.js b/lib/utils/lang.js
deleted file mode 100644
index 9da737b..0000000
--- a/lib/utils/lang.js
+++ /dev/null
@@ -1,19 +0,0 @@
-var MAP = {
- 'py': 'python',
- 'js': 'javascript',
- 'rb': 'ruby',
- 'csharp': 'cs',
-};
-
-function normalize(lang) {
- if(!lang) { return null; }
-
- var lower = lang.toLowerCase();
- return MAP[lower] || lower;
-}
-
-// Exports
-module.exports = {
- normalize: normalize,
- MAP: MAP
-};
diff --git a/lib/utils/links.js b/lib/utils/links.js
deleted file mode 100644
index b4d2fb7..0000000
--- a/lib/utils/links.js
+++ /dev/null
@@ -1,60 +0,0 @@
-var url = require('url');
-var path = require('path');
-
-// Is the link an external link
-var isExternal = function(href) {
- try {
- return Boolean(url.parse(href).protocol);
- } catch(err) { }
-
- return false;
-};
-
-// Return true if the link is relative
-var isRelative = function(href) {
- try {
- var parsed = url.parse(href);
-
- return !parsed.protocol && parsed.path && parsed.path[0] != '/';
- } catch(err) {}
-
- return true;
-};
-
-// Relative to absolute path
-// dir: directory parent of the file currently in rendering process
-// outdir: directory parent from the html output
-
-var toAbsolute = function(_href, dir, outdir) {
- // Absolute file in source
- _href = path.join(dir, _href);
-
- // make it relative to output
- _href = path.relative(outdir, _href);
-
- if (process.platform === 'win32') {
- _href = _href.replace(/\\/g, '/');
- }
-
- return _href;
-};
-
-// Join links
-
-var join = function() {
- var _href = path.join.apply(path, arguments);
-
- if (process.platform === 'win32') {
- _href = _href.replace(/\\/g, '/');
- }
-
- return _href;
-};
-
-
-module.exports = {
- isRelative: isRelative,
- isExternal: isExternal,
- toAbsolute: toAbsolute,
- join: join
-};
diff --git a/lib/utils/string.js b/lib/utils/string.js
deleted file mode 100644
index 54c4c66..0000000
--- a/lib/utils/string.js
+++ /dev/null
@@ -1,26 +0,0 @@
-var _ = require("lodash");
-
-function escapeShellArg(arg) {
- var ret = '';
-
- ret = arg.replace(/"/g, '\\"');
-
- return "\"" + ret + "\"";
-}
-
-function optionsToShellArgs(options) {
- return _.chain(options)
- .map(function(value, key) {
- if (value == null || value === false) return null;
- if (value === true) return key;
- return key+"="+escapeShellArg(value);
- })
- .compact()
- .value()
- .join(" ");
-}
-
-module.exports = {
- escapeShellArg: escapeShellArg,
- optionsToShellArgs: optionsToShellArgs
-};