mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-10-12 16:09:33 +00:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 67e7d77302 | |||
| 8cbd8b2b48 | |||
| 7c404dbf96 | |||
| c4a67b6f2f | |||
| 3b70347625 | |||
| bb0a7935e9 | |||
| 931e0c66c9 | |||
| 0212084862 | |||
| 9abbabbce3 | |||
| ac610487e8 | |||
| a9a0f89892 | |||
| 305f221077 | |||
| 53514f2602 | |||
| 00327778cb | |||
| 37fadec787 | |||
| ada11d0b59 | |||
| 4c90fdb7b2 | |||
| 98c133df3c | |||
| f86c27b090 | |||
| b5b8ed72a5 | |||
| 5beff86548 | |||
| dd395edae1 | |||
| d1c1d7b75b | |||
| 4a380e9279 | |||
| 878c105def | |||
| 74d628676b | |||
| 6fdd98ec3a | |||
| 2ed1be3533 | |||
| 0ac04e1584 | |||
| 2a38d33d8a | |||
| fb14caf5b3 | |||
| cf51772f54 | |||
| cc8516df83 | |||
| c6a624bc6b | |||
| 8be8b825ee | |||
| 56eb4a2897 | |||
| 7a461eaa61 | |||
| fd64c05809 | |||
| 6bce93d893 | |||
| c9db068227 | |||
| 8a6d36ac4d | |||
| 64622c5945 | |||
| 837813edb0 | |||
| 0d9d62f1a9 | |||
| f7e9abf984 | |||
| dd0579b60d | |||
| b5bb953e47 | |||
| ef4a8ea1b6 | |||
| 49cde96ee7 | |||
| 627be20e48 | |||
| e45bb84b02 | |||
| 4e8876c725 |
@@ -15,3 +15,4 @@ Contributors
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
- Nijiko Yonskai
|
- Nijiko Yonskai
|
||||||
|
- Herman Starikov
|
||||||
|
|||||||
+1
-5
@@ -24,7 +24,7 @@ module.exports = function (grunt) {
|
|||||||
requirejs: {
|
requirejs: {
|
||||||
compile: {
|
compile: {
|
||||||
options: {
|
options: {
|
||||||
name: "app",
|
name: "gitbook",
|
||||||
baseUrl: "theme/javascript/",
|
baseUrl: "theme/javascript/",
|
||||||
out: "theme/assets/app.js",
|
out: "theme/assets/app.js",
|
||||||
preserveLicenseComments: false,
|
preserveLicenseComments: false,
|
||||||
@@ -35,7 +35,6 @@ module.exports = function (grunt) {
|
|||||||
"lodash": 'vendors/lodash',
|
"lodash": 'vendors/lodash',
|
||||||
"requireLib": 'vendors/require',
|
"requireLib": 'vendors/require',
|
||||||
"Mousetrap": 'vendors/mousetrap',
|
"Mousetrap": 'vendors/mousetrap',
|
||||||
"mixpanel": 'vendors/mixpanel',
|
|
||||||
"lunr": path.join(__dirname, "node_modules/lunr/lunr")
|
"lunr": path.join(__dirname, "node_modules/lunr/lunr")
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
@@ -48,9 +47,6 @@ module.exports = function (grunt) {
|
|||||||
'Mousetrap': {
|
'Mousetrap': {
|
||||||
exports: 'Mousetrap'
|
exports: 'Mousetrap'
|
||||||
},
|
},
|
||||||
'mixpanel': {
|
|
||||||
exports: 'mixpanel'
|
|
||||||
},
|
|
||||||
'lunr': {
|
'lunr': {
|
||||||
exports: 'lunr'
|
exports: 'lunr'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ Apache License
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
Copyright 2014 FriendCode Inc.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ GitBook
|
|||||||
|
|
||||||
[](https://travis-ci.org/GitbookIO/gitbook)
|
[](https://travis-ci.org/GitbookIO/gitbook)
|
||||||
|
|
||||||
GitBook is a command line tool (and Node.js library) for building beautiful programming books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](http://gitbookio.github.io/javascript/).
|
GitBook is a command line tool (and Node.js library) for building beautiful programming books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](http://gitbookio.github.io/javascript/). An [editor](https://github.com/GitbookIO/editor) is available for Windows, Mac and Linux. You can follow [@GitBookIO](https://twitter.com/GitBookIO) on Twitter.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -36,9 +36,12 @@ Options for commands `build` and `serve` are:
|
|||||||
-o, --output <directory> Path to output directory, defaults to ./_book
|
-o, --output <directory> Path to output directory, defaults to ./_book
|
||||||
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json
|
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json
|
||||||
--githubHost <url> The url of the github host (defaults to https://github.com/)
|
--githubHost <url> The url of the github host (defaults to https://github.com/)
|
||||||
--theme <path> Path to theme directory
|
--plugins <plugins> List of plugins to use separated by ","
|
||||||
|
--pluginsConfig <json file> JSON File containing plugins configuration
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can publish your books to our index by visiting [GitBook.io](http://www.gitbook.io)
|
||||||
|
|
||||||
## Output Formats
|
## Output Formats
|
||||||
|
|
||||||
GitBook can generate your book in the following formats:
|
GitBook can generate your book in the following formats:
|
||||||
@@ -131,3 +134,16 @@ You can see a complete example with the [Learn Git](https://github.com/GitbookIO
|
|||||||
#### Ignoring files & folders
|
#### Ignoring files & folders
|
||||||
|
|
||||||
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip. (The format inside those files, follows the same convention as `.gitignore`)
|
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip. (The format inside those files, follows the same convention as `.gitignore`)
|
||||||
|
|
||||||
|
#### Plugins
|
||||||
|
|
||||||
|
Plugins can used to extend your book functionnalities. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more informations about how to build a plugin for gitbook.
|
||||||
|
|
||||||
|
##### Default plugins:
|
||||||
|
|
||||||
|
* [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
|
||||||
|
|
||||||
|
##### Other plugins:
|
||||||
|
|
||||||
|
* [Google Analytics](https://github.com/GitbookIO/plugin-ga): Google Analytics tracking for your book
|
||||||
|
|||||||
+27
-6
@@ -1,18 +1,37 @@
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var Q = require('q');
|
var Q = require('q');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
var generate = require("../lib/generate");
|
var generate = require("../lib/generate");
|
||||||
var parse = require("../lib/parse");
|
var parse = require("../lib/parse");
|
||||||
var fs = require('../lib/generate/fs');
|
|
||||||
var generators = require("../lib/generate").generators;
|
var generators = require("../lib/generate").generators;
|
||||||
|
|
||||||
|
var buildCommand = function(command) {
|
||||||
|
return command
|
||||||
|
.option('-o, --output <directory>', 'Path to output directory, defaults to ./_book')
|
||||||
|
.option('-f, --format <name>', 'Change generation format, defaults to site, availables are: '+_.keys(generators).join(", "))
|
||||||
|
.option('-t, --title <name>', 'Name of the book to generate, default is extracted from readme')
|
||||||
|
.option('-i, --intro <intro>', 'Description of the book to generate, default is extracted from readme')
|
||||||
|
.option('--plugins <plugins>', 'List of plugins to use separated by ","')
|
||||||
|
.option('--pluginsConfig <json file>', 'JSON File containing plugins configuration')
|
||||||
|
.option('-g, --github <repo_path>', 'ID of github repo like : username/repo')
|
||||||
|
.option('--githubHost <url>', 'The url of the github host (defaults to https://github.com/');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var makeBuildFunc = function(converter) {
|
var makeBuildFunc = function(converter) {
|
||||||
return function(dir, options) {
|
return function(dir, options) {
|
||||||
dir = dir || process.cwd();
|
dir = dir || process.cwd();
|
||||||
outputDir = options.output
|
outputDir = options.output;
|
||||||
|
|
||||||
|
// Read plugins config
|
||||||
|
var pluginsConfig = {};
|
||||||
|
if (options.pluginsConfig) {
|
||||||
|
pluginsConfig = JSON.parse(fs.readFileSync(options.pluginsConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
console.log('Starting build ...');
|
console.log('Starting build ...');
|
||||||
// Get repo's URL
|
// Get repo's URL
|
||||||
@@ -33,7 +52,8 @@ var makeBuildFunc = function(converter) {
|
|||||||
github: options.github || repoID,
|
github: options.github || repoID,
|
||||||
githubHost: options.githubHost,
|
githubHost: options.githubHost,
|
||||||
generator: options.format,
|
generator: options.format,
|
||||||
theme: options.theme
|
plugins: options.plugins,
|
||||||
|
pluginsConfig: pluginsConfig
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -42,9 +62,10 @@ var makeBuildFunc = function(converter) {
|
|||||||
return output;
|
return output;
|
||||||
}, utils.logError);
|
}, utils.logError);
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
folder: makeBuildFunc(generate.folder),
|
folder: makeBuildFunc(generate.folder),
|
||||||
file: makeBuildFunc(generate.file)
|
file: makeBuildFunc(generate.file),
|
||||||
|
command: buildCommand
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-15
@@ -17,22 +17,11 @@ var build = require('./build');
|
|||||||
prog
|
prog
|
||||||
.version(pkg.version);
|
.version(pkg.version);
|
||||||
|
|
||||||
var buildCommand = function(command) {
|
build.command(prog.command('build [source_dir]'))
|
||||||
return command
|
|
||||||
.option('-o, --output <directory>', 'Path to output directory, defaults to ./_book')
|
|
||||||
.option('-f, --format <name>', 'Change generation format, defaults to site, availables are: '+_.keys(generators).join(", "))
|
|
||||||
.option('-t, --title <name>', 'Name of the book to generate, default is extracted from readme')
|
|
||||||
.option('-i, --intro <intro>', 'Description of the book to generate, default is extracted from readme')
|
|
||||||
.option('-g, --github <repo_path>', 'ID of github repo like : username/repo')
|
|
||||||
.option('--githubHost <url>', 'The url of the github host (defaults to https://github.com/')
|
|
||||||
.option('--theme <path>', 'Path to theme directory');
|
|
||||||
};
|
|
||||||
|
|
||||||
buildCommand(prog.command('build [source_dir]'))
|
|
||||||
.description('Build a gitbook from a directory')
|
.description('Build a gitbook from a directory')
|
||||||
.action(build.folder);
|
.action(build.folder);
|
||||||
|
|
||||||
buildCommand(prog.command('serve [source_dir]'))
|
build.command(prog.command('serve [source_dir]'))
|
||||||
.description('Build then serve a gitbook from a directory')
|
.description('Build then serve a gitbook from a directory')
|
||||||
.option('-p, --port <port>', 'Port for server to listen on', 4000)
|
.option('-p, --port <port>', 'Port for server to listen on', 4000)
|
||||||
.action(function(dir, options) {
|
.action(function(dir, options) {
|
||||||
@@ -50,7 +39,7 @@ buildCommand(prog.command('serve [source_dir]'))
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
buildCommand(prog.command('pdf [source_dir]'))
|
build.command(prog.command('pdf [source_dir]'))
|
||||||
.description('Build a gitbook as a PDF')
|
.description('Build a gitbook as a PDF')
|
||||||
.option('-pf, --paperformat <format>', 'PDF paper format (default is A4): "5in*7.5in", "10cm*20cm", "A4", "Letter"')
|
.option('-pf, --paperformat <format>', 'PDF paper format (default is A4): "5in*7.5in", "10cm*20cm", "A4", "Letter"')
|
||||||
.action(function(dir, options) {
|
.action(function(dir, options) {
|
||||||
@@ -60,7 +49,7 @@ buildCommand(prog.command('pdf [source_dir]'))
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
buildCommand(prog.command('ebook [source_dir]'))
|
build.command(prog.command('ebook [source_dir]'))
|
||||||
.description('Build a gitbook as a eBook')
|
.description('Build a gitbook as a eBook')
|
||||||
.option('-c, --cover <path>', 'Cover image, default is cover.png if exists')
|
.option('-c, --cover <path>', 'Cover image, default is cover.png if exists')
|
||||||
.action(function(dir, options) {
|
.action(function(dir, options) {
|
||||||
|
|||||||
@@ -1,9 +1,30 @@
|
|||||||
|
var _ = require("lodash");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var Q = require("q");
|
var Q = require("q");
|
||||||
var fs = require("./fs");
|
var fs = require("./fs");
|
||||||
|
|
||||||
|
var Plugin = require("./plugin");
|
||||||
|
|
||||||
var BaseGenerator = function(options) {
|
var BaseGenerator = function(options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
|
this.options.plugins = Plugin.normalizeNames(this.options.plugins);
|
||||||
|
this.plugins = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
BaseGenerator.prototype.callHook = function(name) {
|
||||||
|
return this.plugins.hook(name, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
BaseGenerator.prototype.loadPlugins = function() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
return Plugin.fromList(this.options.plugins)
|
||||||
|
.then(function(_plugins) {
|
||||||
|
that.plugins = _plugins;
|
||||||
|
|
||||||
|
return that.callHook("init");
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseGenerator.prototype.convertFile = function(content, input) {
|
BaseGenerator.prototype.convertFile = function(content, input) {
|
||||||
|
|||||||
+13
-3
@@ -6,6 +6,7 @@ var tmp = require('tmp');
|
|||||||
|
|
||||||
var fs = require("./fs");
|
var fs = require("./fs");
|
||||||
var parse = require("../parse");
|
var parse = require("../parse");
|
||||||
|
var Plugin = require("./plugin");
|
||||||
|
|
||||||
var generators = {
|
var generators = {
|
||||||
"site": require("./site"),
|
"site": require("./site"),
|
||||||
@@ -42,7 +43,11 @@ var generate = function(options) {
|
|||||||
githubHost: 'https://github.com/',
|
githubHost: 'https://github.com/',
|
||||||
|
|
||||||
// Theming
|
// Theming
|
||||||
theme: path.resolve(__dirname, '../../theme')
|
theme: path.resolve(__dirname, '../../theme'),
|
||||||
|
|
||||||
|
// Plugins
|
||||||
|
plugins: [],
|
||||||
|
pluginsConfig: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!options.input) {
|
if (!options.input) {
|
||||||
@@ -70,9 +75,10 @@ var generate = function(options) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create the generator
|
// Create the generator and load plugins
|
||||||
.then(function() {
|
.then(function() {
|
||||||
generator = new generators[options.generator](options);
|
generator = new generators[options.generator](options);
|
||||||
|
return generator.loadPlugins();
|
||||||
})
|
})
|
||||||
|
|
||||||
// Detect multi-languages book
|
// Detect multi-languages book
|
||||||
@@ -163,6 +169,9 @@ var generate = function(options) {
|
|||||||
// Finish gneration
|
// Finish gneration
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return generator.finish();
|
return generator.finish();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
return generator.callHook("finish");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -234,5 +243,6 @@ var generateFile = function(options) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
generators: generators,
|
generators: generators,
|
||||||
folder: generate,
|
folder: generate,
|
||||||
file: generateFile
|
file: generateFile,
|
||||||
|
Plugin: Plugin
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,14 +25,18 @@ swig.setFilter('code', function(code, lang) {
|
|||||||
var Generator = function() {
|
var Generator = function() {
|
||||||
BaseGenerator.apply(this, arguments);
|
BaseGenerator.apply(this, arguments);
|
||||||
|
|
||||||
// Load base template
|
|
||||||
this.template = swig.compileFile(path.resolve(this.options.theme, 'templates/page.html'));
|
|
||||||
|
|
||||||
// List of pages content
|
// List of pages content
|
||||||
this.pages = {};
|
this.pages = {};
|
||||||
};
|
};
|
||||||
util.inherits(Generator, BaseGenerator);
|
util.inherits(Generator, BaseGenerator);
|
||||||
|
|
||||||
|
// Load all templates
|
||||||
|
Generator.prototype.loadTemplates = function() {
|
||||||
|
this.template = swig.compileFile(
|
||||||
|
this.plugins.template("page") || path.resolve(this.options.theme, 'templates/page.html')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Generator.prototype.convertFile = function(content, input) {
|
Generator.prototype.convertFile = function(content, input) {
|
||||||
var that = this;
|
var that = this;
|
||||||
var json = {
|
var json = {
|
||||||
@@ -46,6 +50,7 @@ Generator.prototype.convertFile = function(content, input) {
|
|||||||
repo: that.options.githubId,
|
repo: that.options.githubId,
|
||||||
dir: path.dirname(input) || '/',
|
dir: path.dirname(input) || '/',
|
||||||
outdir: './',
|
outdir: './',
|
||||||
|
singleFile: true
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(function(sections) {
|
.then(function(sections) {
|
||||||
|
|||||||
@@ -0,0 +1,180 @@
|
|||||||
|
var _ = require("lodash");
|
||||||
|
var Q = require("q");
|
||||||
|
var semver = require("semver");
|
||||||
|
var path = require("path");
|
||||||
|
var url = require("url");
|
||||||
|
var fs = require("./fs");
|
||||||
|
|
||||||
|
var pkg = require("../../package.json");
|
||||||
|
|
||||||
|
var RESOURCES = ["js", "css"];
|
||||||
|
|
||||||
|
var Plugin = function(name) {
|
||||||
|
this.name = name;
|
||||||
|
this.packageInfos = {};
|
||||||
|
this.infos = {};
|
||||||
|
|
||||||
|
_.each([
|
||||||
|
"gitbook-plugin-"+name,
|
||||||
|
"gitbook-theme-"+name,
|
||||||
|
"gitbook-"+name,
|
||||||
|
name,
|
||||||
|
], function(_name) {
|
||||||
|
if (this.load(_name)) return false;
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load from a name
|
||||||
|
Plugin.prototype.load = function(name) {
|
||||||
|
try {
|
||||||
|
this.packageInfos = require(name+"/package.json");
|
||||||
|
this.infos = require(name);
|
||||||
|
this.name = name;
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return resources
|
||||||
|
Plugin.prototype.getResources = function(resource) {
|
||||||
|
if (!this.infos.book || !this.infos.book[resource]) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return _.chain(this.infos.book[resource])
|
||||||
|
.map(function(resource) {
|
||||||
|
var parsed = url.parse(resource);
|
||||||
|
if (parsed.protocol) return {"url": resource}
|
||||||
|
else return { "path": this.name+"/"+resource };
|
||||||
|
}.bind(this))
|
||||||
|
.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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(path.dirname(require.resolve(this.name)), filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Resolve file path
|
||||||
|
Plugin.prototype.callHook = function(name, args) {
|
||||||
|
var hookFunc = this.infos.hooks? this.infos.hooks[name] : null;
|
||||||
|
args = _.isArray(args) ? args : [args];
|
||||||
|
|
||||||
|
if (!hookFunc) return Q();
|
||||||
|
|
||||||
|
return Q()
|
||||||
|
.then(function() {
|
||||||
|
return hookFunc.apply(null, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy plugin assets fodler
|
||||||
|
Plugin.prototype.copyAssets = function(out) {
|
||||||
|
if (!this.infos.book || !this.infos.book.assets) return Q();
|
||||||
|
return fs.copy(
|
||||||
|
this.resolveFile(this.infos.book.assets),
|
||||||
|
out
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Normalize a list of plugin name to use
|
||||||
|
Plugin.normalizeNames = function(names) {
|
||||||
|
// Normalize list to an array
|
||||||
|
names = _.isString(names) ? names.split(":") : (names || []);
|
||||||
|
|
||||||
|
// List plugins to remove
|
||||||
|
var toremove = _.chain(names)
|
||||||
|
.filter(function(name) {
|
||||||
|
return name.length > 0 && name[0] == "-";
|
||||||
|
})
|
||||||
|
.map(function(name) {
|
||||||
|
return name.slice(1)
|
||||||
|
})
|
||||||
|
.value();
|
||||||
|
|
||||||
|
// Merge with defaults
|
||||||
|
names = _.chain(names)
|
||||||
|
.concat(Plugin.defaults)
|
||||||
|
.uniq()
|
||||||
|
.value();
|
||||||
|
|
||||||
|
// Remove plugins starting with
|
||||||
|
names = _.filter(names, function(name) {
|
||||||
|
return !_.contains(toremove, name) && !(name.length > 0 && name[0] == "-");
|
||||||
|
});
|
||||||
|
|
||||||
|
return names;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract data from a list of plugin
|
||||||
|
Plugin.fromList = function(names) {
|
||||||
|
var failed = [];
|
||||||
|
|
||||||
|
// Load plugins
|
||||||
|
var plugins = _.map(names, function(name) {
|
||||||
|
var plugin = new Plugin(name);
|
||||||
|
if (!plugin.isValid()) failed.push(name);
|
||||||
|
return plugin;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")));
|
||||||
|
|
||||||
|
// Get all resources
|
||||||
|
var resources = _.chain(RESOURCES)
|
||||||
|
.map(function(resource) {
|
||||||
|
return [
|
||||||
|
resource,
|
||||||
|
_.chain(plugins)
|
||||||
|
.map(function(plugin) {
|
||||||
|
return plugin.getResources(resource);
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.value()
|
||||||
|
];
|
||||||
|
})
|
||||||
|
.object()
|
||||||
|
.value();
|
||||||
|
|
||||||
|
return Q({
|
||||||
|
'list': plugins,
|
||||||
|
'resources': resources,
|
||||||
|
'hook': function(name, args) {
|
||||||
|
return _.reduce(plugins, function(prev, plugin) {
|
||||||
|
return prev.then(function() {
|
||||||
|
return plugin.callHook(name, args);
|
||||||
|
})
|
||||||
|
}, Q());
|
||||||
|
},
|
||||||
|
'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]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default plugins
|
||||||
|
Plugin.defaults = [
|
||||||
|
"mixpanel",
|
||||||
|
"mathjax"
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = Plugin;
|
||||||
@@ -30,13 +30,28 @@ var Generator = function() {
|
|||||||
|
|
||||||
this.revision = Date.now();
|
this.revision = Date.now();
|
||||||
this.indexer = indexer();
|
this.indexer = indexer();
|
||||||
|
|
||||||
// Load base template
|
|
||||||
this.template = swig.compileFile(path.resolve(this.options.theme, 'templates/site.html'));
|
|
||||||
this.langsTemplate = swig.compileFile(path.resolve(this.options.theme, 'templates/langs.html'));
|
|
||||||
};
|
};
|
||||||
util.inherits(Generator, BaseGenerator);
|
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')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load plugins
|
||||||
|
Generator.prototype.loadPlugins = function() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
return BaseGenerator.prototype.loadPlugins.apply(this)
|
||||||
|
.then(function() {
|
||||||
|
return that.loadTemplates();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Generate a template
|
// Generate a template
|
||||||
Generator.prototype._writeTemplate = function(tpl, options, output) {
|
Generator.prototype._writeTemplate = function(tpl, options, output) {
|
||||||
@@ -54,7 +69,10 @@ Generator.prototype._writeTemplate = function(tpl, options, output) {
|
|||||||
githubHost: that.options.githubHost,
|
githubHost: that.options.githubHost,
|
||||||
|
|
||||||
summary: that.options.summary,
|
summary: that.options.summary,
|
||||||
allNavigation: that.options.navigation
|
allNavigation: that.options.navigation,
|
||||||
|
|
||||||
|
plugins: that.plugins,
|
||||||
|
pluginsConfig: JSON.stringify(that.options.pluginsConfig)
|
||||||
}, options));
|
}, options));
|
||||||
})
|
})
|
||||||
.then(function(html) {
|
.then(function(html) {
|
||||||
@@ -134,10 +152,19 @@ Generator.prototype.langsIndex = function(langs) {
|
|||||||
Generator.prototype.copyAssets = function() {
|
Generator.prototype.copyAssets = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
|
// Copy gitbook assets
|
||||||
return fs.copy(
|
return fs.copy(
|
||||||
path.join(that.options.theme, "assets"),
|
path.join(that.options.theme, "assets"),
|
||||||
path.join(that.options.output, "gitbook")
|
path.join(that.options.output, "gitbook")
|
||||||
);
|
)
|
||||||
|
// Copy plugins assets
|
||||||
|
.then(function() {
|
||||||
|
return Q.all(
|
||||||
|
_.map(that.plugins.list, function(plugin) {
|
||||||
|
return plugin.copyAssets(path.join(that.options.output, "gitbook/plugins/", plugin.name))
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dump search index to disk
|
// Dump search index to disk
|
||||||
|
|||||||
+30
-49
@@ -6,6 +6,12 @@ function clean(obj) {
|
|||||||
return obj && _.omit(obj, ['articles']);
|
return obj && _.omit(obj, ['articles']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function flattenChapters(chapters) {
|
||||||
|
return _.reduce(chapters, function(accu, chapter) {
|
||||||
|
return accu.concat([clean(chapter)].concat(chapter.articles));
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns from a summary a map of
|
// Returns from a summary a map of
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@@ -20,62 +26,37 @@ function navigation(summary, files) {
|
|||||||
// Support single files as well as list
|
// Support single files as well as list
|
||||||
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
||||||
|
|
||||||
// Mapping of prev/next for a give path
|
|
||||||
var mapping = {};
|
|
||||||
|
|
||||||
// Special README nav
|
// Special README nav
|
||||||
var README_NAV = {
|
var README_NAV = {
|
||||||
path: 'README.md',
|
path: 'README.md',
|
||||||
title: 'Introduction',
|
title: 'Introduction',
|
||||||
};
|
|
||||||
|
|
||||||
// Walk the chapter/article tree and create navigation entires
|
|
||||||
_.each(summary.chapters, function(chapter, idx, chapters) {
|
|
||||||
// Skip if no path
|
|
||||||
if(!chapter.path) return;
|
|
||||||
|
|
||||||
var currentChapter = clean(chapter);
|
|
||||||
var prevChapter = (idx-1 < 0) ? README_NAV : chapters[idx-1];
|
|
||||||
var nextChapter = (idx+1 >= chapters.length) ? null : chapters[idx+1];
|
|
||||||
|
|
||||||
var prev = (!prevChapter || _.isEmpty(prevChapter.articles)) ?
|
|
||||||
prevChapter : _.last(prevChapter.articles);
|
|
||||||
var next = (!chapter || _.isEmpty(chapter.articles)) ?
|
|
||||||
nextChapter : _.first(chapter.articles);
|
|
||||||
|
|
||||||
// Add chapter mapping
|
|
||||||
mapping[chapter.path] = {
|
|
||||||
title: chapter.title,
|
|
||||||
prev: clean(prev),
|
|
||||||
next: clean(next),
|
|
||||||
level: (idx+1).toString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check a chapter's articles
|
|
||||||
_.each(chapter.articles, function(article, _idx, articles) {
|
|
||||||
// Skip if no path
|
|
||||||
if(!article.path) return;
|
|
||||||
|
|
||||||
var prev = (_idx-1 < 0) ? currentChapter : clean(articles[_idx-1]);
|
|
||||||
var next = (_idx+1 >= articles.length) ? nextChapter : clean(articles[_idx+1]);
|
|
||||||
|
|
||||||
mapping[article.path] = {
|
|
||||||
title: article.title,
|
|
||||||
prev: clean(prev),
|
|
||||||
next: clean(next),
|
|
||||||
level: [idx+1, _idx+1].join('.'),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hack for README.html
|
|
||||||
mapping['README.md'] = {
|
|
||||||
title: README_NAV.title,
|
|
||||||
prev: null,
|
|
||||||
next: clean(summary.chapters[0]),
|
|
||||||
level: '0',
|
level: '0',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// List of all navNodes
|
||||||
|
var navNodes = [README_NAV].concat(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
|
// Filter for only files we want
|
||||||
if(files) {
|
if(files) {
|
||||||
return _.pick(mapping, files);
|
return _.pick(mapping, files);
|
||||||
|
|||||||
+27
-8
@@ -1,5 +1,7 @@
|
|||||||
var url = require('url');
|
var url = require('url');
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
|
var links = require('../utils').links;
|
||||||
|
|
||||||
|
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
@@ -38,23 +40,38 @@ GitBookRenderer.prototype._unsanitized = function(href) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GitBookRenderer.prototype.link = function(href, title, text) {
|
GitBookRenderer.prototype.link = function(href, title, text) {
|
||||||
|
// Our "fixed" href
|
||||||
|
var _href = href;
|
||||||
|
|
||||||
// Don't build if it looks malicious
|
// Don't build if it looks malicious
|
||||||
if (this.options.sanitize && this._unsanitized(href)) {
|
if (this.options.sanitize && this._unsanitized(href)) {
|
||||||
return '';
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parsed version of the url
|
// Parsed version of the url
|
||||||
var parsed = url.parse(href);
|
var parsed = url.parse(href);
|
||||||
|
|
||||||
var o = this._extra_options;
|
var o = this._extra_options;
|
||||||
|
|
||||||
// Relative link, rewrite it to point to github repo
|
// Relative link, rewrite it to point to github repo
|
||||||
if(!parsed.protocol && parsed.path && parsed.path[0] != '/' && o && o.repo && o.dir) {
|
if(links.isRelative(_href)) {
|
||||||
href = url.resolve('https://github.com/' + o.repo + '/blob/', [o.dir, href].join("/"));
|
if (path.extname(_href) == ".md") {
|
||||||
parsed = url.parse(href);
|
_href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
|
||||||
|
|
||||||
|
if (o.singleFile) {
|
||||||
|
_href = "#"+_href;
|
||||||
|
} else {
|
||||||
|
_href = _href.replace(".md", ".html");
|
||||||
|
}
|
||||||
|
} else if (o && o.repo && o.dir) {
|
||||||
|
href = url.resolve('https://github.com/' + o.repo + '/blob/', [o.dir, _href].join("/"));
|
||||||
|
parsed = url.parse(href);
|
||||||
|
_href = parsed.href;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate HTML for link
|
// Generate HTML for link
|
||||||
var out = '<a href="' + parsed.href + '"';
|
var out = '<a href="' + _href + '"';
|
||||||
// Title if no null
|
// Title if no null
|
||||||
if (title) {
|
if (title) {
|
||||||
out += ' title="' + title + '"';
|
out += ' title="' + title + '"';
|
||||||
@@ -78,9 +95,11 @@ GitBookRenderer.prototype.image = function(href, title, text) {
|
|||||||
var o = this._extra_options;
|
var o = this._extra_options;
|
||||||
|
|
||||||
// Relative image, rewrite it depending output
|
// Relative image, rewrite it depending output
|
||||||
if(!parsed.protocol && parsed.path && parsed.path[0] != '/' && o && o.dir && o.outdir) {
|
if(links.isRelative(href) && o && o.dir && o.outdir) {
|
||||||
var outdir = o.outdir.charAt(o.outdir.length - 1) === '/' ? o.outdir : o.outdir + '/';
|
// o.dir: directory parent of the file currently in rendering process
|
||||||
_href = url.resolve(outdir, [o.dir, href].join('/'));
|
// 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);
|
return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
lang: require('./lang'),
|
lang: require('./lang'),
|
||||||
|
links: require('./links')
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
var url = require('url');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// Return true if the link is relative
|
||||||
|
var isRelative = function(href) {
|
||||||
|
var parsed = url.parse(href);
|
||||||
|
|
||||||
|
return !parsed.protocol && parsed.path && parsed.path[0] != '/';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return _href;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isRelative: isRelative,
|
||||||
|
toAbsolute: toAbsolute
|
||||||
|
};
|
||||||
+20
-4
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "0.2.2",
|
"version": "0.3.1",
|
||||||
|
"homepage": "http://www.gitbook.io/",
|
||||||
"description": "Library and cmd utility to generate GitBooks",
|
"description": "Library and cmd utility to generate GitBooks",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15,7 +16,12 @@
|
|||||||
"commander": "2.2.0",
|
"commander": "2.2.0",
|
||||||
"fs-extra": "0.8.1",
|
"fs-extra": "0.8.1",
|
||||||
"highlight.js": "8.0.0",
|
"highlight.js": "8.0.0",
|
||||||
"tmp": "0.0.23"
|
"tmp": "0.0.23",
|
||||||
|
"semver": "2.2.1",
|
||||||
|
|
||||||
|
"gitbook-plugin": "0.0.2",
|
||||||
|
"gitbook-plugin-mixpanel": "0.0.2",
|
||||||
|
"gitbook-plugin-mathjax": "0.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "1.18.2",
|
"mocha": "1.18.2",
|
||||||
@@ -39,9 +45,19 @@
|
|||||||
"book",
|
"book",
|
||||||
"gitbook"
|
"gitbook"
|
||||||
],
|
],
|
||||||
"author": "Aaron O'Mullan <aaron.omullan@friendco.de>",
|
"author": "FriendCode <contact@friendco.de>",
|
||||||
"license": "Apache 2",
|
"license": "Apache 2",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/GitbookIO/gitbook/issues"
|
"url": "https://github.com/GitbookIO/gitbook/issues"
|
||||||
}
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Aaron O'Mullan",
|
||||||
|
"email": "aaron.omullan@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Samy Pessé",
|
||||||
|
"email": "samypesse@gmail.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# Images Test
|
||||||
|
|
||||||
|
This is a test for images path calculation. It supposed this fiel is in a syntax/ folder
|
||||||
|
|
||||||
|
### #
|
||||||
|
|
||||||
|
[](./preview.png)
|
||||||
|
|
||||||
|
### 2
|
||||||
|
|
||||||
|
[](./preview2.png)
|
||||||
|
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
# Nice course
|
||||||
|
|
||||||
|
Check out this other chapter [Test](test.md)
|
||||||
|
|
||||||
|
Check out this other chapter [Test](../before.md)
|
||||||
+61
-5
@@ -36,10 +36,6 @@ describe('Page parsing', function() {
|
|||||||
assert(LEXED[2].content);
|
assert(LEXED[2].content);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should make image URLs relative', function() {
|
|
||||||
assert(LEXED[2].content.indexOf('_book/assets/my-pretty-picture.png') !== -1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should gen code and content for exercise sections', function() {
|
it('should gen code and content for exercise sections', function() {
|
||||||
assert(LEXED[1].content);
|
assert(LEXED[1].content);
|
||||||
assert(LEXED[1].code);
|
assert(LEXED[1].code);
|
||||||
@@ -88,9 +84,69 @@ describe('Relative links', function() {
|
|||||||
repo: 'GitBookIO/javascript',
|
repo: 'GitBookIO/javascript',
|
||||||
|
|
||||||
// Imaginary folder of markdown file
|
// Imaginary folder of markdown file
|
||||||
dir: 'course'
|
dir: 'course',
|
||||||
|
outdir: './'
|
||||||
});
|
});
|
||||||
|
|
||||||
assert(LEXED[0].content.indexOf('https://github.com/GitBookIO/javascript/blob/src/something.cpp') !== -1);
|
assert(LEXED[0].content.indexOf('https://github.com/GitBookIO/javascript/blob/src/something.cpp') !== -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('test.html') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('../before.html') !== -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace link to .md by link to page in format single page', function() {
|
||||||
|
var LEXED = loadPage('MARKDOWN_LINKS', {
|
||||||
|
// GitHub repo ID
|
||||||
|
repo: 'GitBookIO/javascript',
|
||||||
|
|
||||||
|
// Imaginary folder of markdown file
|
||||||
|
dir: 'course',
|
||||||
|
outdir: './',
|
||||||
|
singleFile: true
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('#course/test.md') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('#before.md') !== -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('"preview.png"') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('"../preview2.png"') !== -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
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: './'
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('"syntax/preview.png"') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('"preview2.png"') !== -1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
var _ = require('lodash');
|
||||||
|
var path = require('path');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var Plugin = require('../').generate.Plugin;
|
||||||
|
|
||||||
|
describe('Plugin validation', function () {
|
||||||
|
var plugin = new Plugin("plugin");
|
||||||
|
|
||||||
|
it('should be valid', function() {
|
||||||
|
assert(plugin.isValid());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Plugin list of names', function () {
|
||||||
|
var firstDefault = _.first(Plugin.defaults);
|
||||||
|
|
||||||
|
it('should convert string to array', function() {
|
||||||
|
var _name = "test";
|
||||||
|
assert(_.contains(Plugin.normalizeNames(_name), _name));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should contains default plugins', function() {
|
||||||
|
assert(_.contains(Plugin.normalizeNames([]), firstDefault));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove name starting with -', function() {
|
||||||
|
assert(!_.contains(Plugin.normalizeNames(["-"+firstDefault]), firstDefault));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Plugin defaults loading', function () {
|
||||||
|
var ret = true;
|
||||||
|
|
||||||
|
beforeEach(function(done){
|
||||||
|
Plugin.fromList(Plugin.defaults)
|
||||||
|
.then(function(_r) {
|
||||||
|
ret = _r;
|
||||||
|
}, function(err) {
|
||||||
|
ret = null;
|
||||||
|
})
|
||||||
|
.fin(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should load defaults addons', function() {
|
||||||
|
assert(ret != null);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# GitBook Theme
|
|
||||||
|
|
||||||
For creating a theme for GitBook, just copy this folder. The theme folder should at least contains two folders: `assets` and `templates`.
|
|
||||||
|
|
||||||
The theme can be changed using the option ```--theme=<path>```
|
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
|||||||
|
define([
|
||||||
|
"jQuery"
|
||||||
|
], function($) {
|
||||||
|
var events = $({});
|
||||||
|
|
||||||
|
return events;
|
||||||
|
});
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
define([
|
define([
|
||||||
"jQuery",
|
"jQuery",
|
||||||
"utils/execute",
|
"utils/execute",
|
||||||
"utils/analytic",
|
"core/events",
|
||||||
"core/state"
|
"core/state"
|
||||||
], function($, execute, analytic, state){
|
], function($, execute, events, state){
|
||||||
// Bind an exercise
|
// Bind an exercise
|
||||||
var prepareExercise = function($exercise) {
|
var prepareExercise = function($exercise) {
|
||||||
var codeSolution = $exercise.find(".code-solution").text();
|
var codeSolution = $exercise.find(".code-solution").text();
|
||||||
@@ -19,7 +19,7 @@ define([
|
|||||||
$exercise.find(".action-submit").click(function(e) {
|
$exercise.find(".action-submit").click(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
analytic.track("exercise.submit", {type: "code"});
|
events.trigger("exercise.submit", {type: "code"});
|
||||||
|
|
||||||
execute("javascript", editor.getValue(), codeValidation, codeContext, function(err, result) {
|
execute("javascript", editor.getValue(), codeValidation, codeContext, function(err, result) {
|
||||||
$exercise.toggleClass("return-error", err != null);
|
$exercise.toggleClass("return-error", err != null);
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
define([
|
||||||
|
"jQuery",
|
||||||
|
"utils/storage"
|
||||||
|
], function($, storage) {
|
||||||
|
var fontState;
|
||||||
|
|
||||||
|
var togglePopover = function(e) {
|
||||||
|
var $dropdown = $("#font-settings-wrapper .dropdown-menu");
|
||||||
|
|
||||||
|
$dropdown.toggleClass("open");
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
var closePopover = function(e) {
|
||||||
|
var $dropdown = $("#font-settings-wrapper .dropdown-menu");
|
||||||
|
|
||||||
|
$dropdown.removeClass("open");
|
||||||
|
};
|
||||||
|
|
||||||
|
var enlargeFontSize = function(e){
|
||||||
|
var $bookBody = $(".book-body");
|
||||||
|
|
||||||
|
if (fontState.size < 4){
|
||||||
|
$bookBody.toggleClass("font-size-"+fontState.size, false);
|
||||||
|
fontState.size++;
|
||||||
|
|
||||||
|
$bookBody.toggleClass("font-size-"+fontState.size, true);
|
||||||
|
fontState.save();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var reduceFontSize = function(e){
|
||||||
|
var $bookBody = $(".book-body");
|
||||||
|
|
||||||
|
if (fontState.size > 0){
|
||||||
|
$bookBody.toggleClass("font-size-"+fontState.size);
|
||||||
|
fontState.size--;
|
||||||
|
|
||||||
|
$bookBody.toggleClass("font-size-"+fontState.size);
|
||||||
|
fontState.save();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var changeFontFamily = function(){
|
||||||
|
var $bookBody = $(".book-body");
|
||||||
|
var index = $(this).data("font");
|
||||||
|
|
||||||
|
$bookBody.toggleClass("font-family-"+fontState.family);
|
||||||
|
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")")
|
||||||
|
.removeClass("active");
|
||||||
|
|
||||||
|
fontState.family = index;
|
||||||
|
$bookBody.toggleClass("font-family-"+fontState.family);
|
||||||
|
$(this).addClass("active");
|
||||||
|
fontState.save();
|
||||||
|
};
|
||||||
|
|
||||||
|
var changeColorTheme = function(){
|
||||||
|
var $book = $(".book");
|
||||||
|
var index = $(this).data("theme");
|
||||||
|
|
||||||
|
if (fontState.theme !== 0)
|
||||||
|
$book.removeClass("color-theme-"+fontState.theme);
|
||||||
|
|
||||||
|
fontState.theme = index;
|
||||||
|
if (fontState.theme !== 0)
|
||||||
|
$book.addClass("color-theme-"+fontState.theme);
|
||||||
|
|
||||||
|
fontState.save();
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function() {
|
||||||
|
var $toggle, $bookBody, $dropdown, $book;
|
||||||
|
|
||||||
|
//Find DOM elements.
|
||||||
|
$book = $(".book");
|
||||||
|
$toggle = $(".book-header .toggle-font-settings");
|
||||||
|
$dropdown = $("#font-settings-wrapper .dropdown-menu");
|
||||||
|
$bookBody = $(".book-body");
|
||||||
|
|
||||||
|
//Instantiate font state object
|
||||||
|
fontState = storage.get("fontState", {
|
||||||
|
size:1,
|
||||||
|
family:0,
|
||||||
|
theme:0
|
||||||
|
});
|
||||||
|
fontState.save = function(){
|
||||||
|
storage.set("fontState",fontState);
|
||||||
|
};
|
||||||
|
|
||||||
|
$bookBody.addClass("font-size-"+fontState.size);
|
||||||
|
$bookBody.addClass("font-family-"+fontState.family);
|
||||||
|
|
||||||
|
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active");
|
||||||
|
|
||||||
|
if(fontState.theme !== 0)
|
||||||
|
$book.addClass("color-theme-"+fontState.theme);
|
||||||
|
|
||||||
|
//Add event listeners
|
||||||
|
$(document).on('click', "#enlarge-font-size", enlargeFontSize);
|
||||||
|
$(document).on('click', "#reduce-font-size", reduceFontSize);
|
||||||
|
|
||||||
|
$(document).on('click', "#font-settings-wrapper .font-family-list li", changeFontFamily);
|
||||||
|
$(document).on('click', "#font-settings-wrapper .color-theme-list button", changeColorTheme);
|
||||||
|
|
||||||
|
$(document).on('click', ".book-header .toggle-font-settings", togglePopover);
|
||||||
|
$(document).on('click', "#font-settings-wrapper .dropdown-menu", function(e){ e.stopPropagation(); });
|
||||||
|
$(document).on("click", closePopover);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,21 +1,23 @@
|
|||||||
define([
|
define([
|
||||||
"jQuery",
|
"jQuery",
|
||||||
"utils/analytic",
|
"core/events",
|
||||||
"core/state",
|
"core/state",
|
||||||
"core/search",
|
"core/search",
|
||||||
"core/progress",
|
"core/progress",
|
||||||
"core/exercise",
|
"core/exercise",
|
||||||
"core/quiz"
|
"core/quiz"
|
||||||
], function($, analytic, state, search, progress, exercises, quiz) {
|
], function($, events, state, search, progress, exercises, quiz) {
|
||||||
var prev, next;
|
var prev, next;
|
||||||
var githubCountStars, githubCountWatch;
|
var githubCountStars, githubCountWatch;
|
||||||
|
|
||||||
|
var usePushState = !navigator.userAgent.match('CriOS') && (typeof history.pushState !== "undefined");
|
||||||
|
|
||||||
var updateHistory = function(url, title) {
|
var updateHistory = function(url, title) {
|
||||||
history.pushState({ path: url }, title, url);
|
history.pushState({ path: url }, title, url);
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleNavigation = function(url, push) {
|
var handleNavigation = function(url, push) {
|
||||||
if (typeof history.pushState === "undefined") {
|
if (!usePushState) {
|
||||||
// Refresh the page to the new URL if pushState not supported
|
// Refresh the page to the new URL if pushState not supported
|
||||||
location.href = url;
|
location.href = url;
|
||||||
return
|
return
|
||||||
@@ -23,6 +25,8 @@ define([
|
|||||||
|
|
||||||
return $.get(url)
|
return $.get(url)
|
||||||
.done(function (html) {
|
.done(function (html) {
|
||||||
|
if (push) updateHistory(url, null);
|
||||||
|
|
||||||
html = html.replace( /<(\/?)(html|head|body)([^>]*)>/ig, function(a,b,c,d){
|
html = html.replace( /<(\/?)(html|head|body)([^>]*)>/ig, function(a,b,c,d){
|
||||||
return '<' + b + 'div' + ( b ? '' : ' data-element="' + c + '"' ) + d + '>';
|
return '<' + b + 'div' + ( b ? '' : ' data-element="' + c + '"' ) + d + '>';
|
||||||
});
|
});
|
||||||
@@ -49,8 +53,6 @@ define([
|
|||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
state.update($("html"));
|
state.update($("html"));
|
||||||
|
|
||||||
if (push) updateHistory(url, null);
|
|
||||||
preparePage();
|
preparePage();
|
||||||
})
|
})
|
||||||
.fail(function () {
|
.fail(function () {
|
||||||
@@ -108,7 +110,7 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send to mixpanel
|
// Send to mixpanel
|
||||||
analytic.track("page.view");
|
events.trigger("page.change");
|
||||||
};
|
};
|
||||||
|
|
||||||
var handlePagination = function (e) {
|
var handlePagination = function (e) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
define([
|
define([
|
||||||
"jQuery",
|
"jQuery",
|
||||||
"utils/execute",
|
"utils/execute",
|
||||||
"utils/analytic",
|
"core/events",
|
||||||
"core/state"
|
"core/state"
|
||||||
], function($, execute, analytic, state){
|
], function($, execute, events, state){
|
||||||
// Bind an exercise
|
// Bind an exercise
|
||||||
var prepareQuiz = function($quiz) {
|
var prepareQuiz = function($quiz) {
|
||||||
|
|
||||||
@@ -14,14 +14,17 @@ define([
|
|||||||
// Submit: test code
|
// Submit: test code
|
||||||
$quiz.find(".action-submit").click(function(e) {
|
$quiz.find(".action-submit").click(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
analytic.track("exercise.submit", {type: "quiz"});
|
events.trigger("exercise.submit", {type: "quiz"});
|
||||||
$quiz.find("tr.alert-danger,li.alert-danger").removeClass("alert-danger");
|
$quiz.find("tr.alert-danger,li.alert-danger").removeClass("alert-danger");
|
||||||
$quiz.find(".alert-success,.alert-danger").addClass("hidden");
|
$quiz.find(".alert-success,.alert-danger").addClass("hidden");
|
||||||
|
|
||||||
$quiz.find(".question").each(function(q) {
|
$quiz.find(".question").each(function(q) {
|
||||||
var result = true;
|
var result = true;
|
||||||
var $answers = $quiz.find(".question-answers").slice(q).find("input[type=radio], input[type=checkbox]");
|
|
||||||
$(this).find("input[type=radio],input[type=checkbox]").each(function(i) {
|
var $questions = $(this).find(".question-content").find("input[type=radio], input[type=checkbox]");
|
||||||
|
var $answers = $(this).find(".question-answers").find("input[type=radio], input[type=checkbox]");
|
||||||
|
|
||||||
|
$questions.each(function(i) {
|
||||||
var correct = $(this).is(":checked") === $answers.slice(i).first().is(":checked");
|
var correct = $(this).is(":checked") === $answers.slice(i).first().is(":checked");
|
||||||
result = result && correct;
|
result = result && correct;
|
||||||
if (!correct) {
|
if (!correct) {
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
require([
|
define([
|
||||||
"jQuery",
|
"jQuery",
|
||||||
"utils/storage",
|
"utils/storage",
|
||||||
"utils/analytic",
|
|
||||||
"utils/sharing",
|
"utils/sharing",
|
||||||
|
|
||||||
|
"core/events",
|
||||||
|
"core/font-settings",
|
||||||
"core/state",
|
"core/state",
|
||||||
"core/keyboard",
|
"core/keyboard",
|
||||||
"core/navigation",
|
"core/navigation",
|
||||||
"core/progress",
|
"core/progress",
|
||||||
"core/sidebar",
|
"core/sidebar",
|
||||||
"core/search"
|
"core/search"
|
||||||
], function($, storage, analytic, sharing, state, keyboard, navigation, progress, sidebar, search){
|
], function($, storage, sharing, events, fontSettings, state, keyboard, navigation, progress, sidebar, search){
|
||||||
$(document).ready(function() {
|
var start = function(config) {
|
||||||
var $book;
|
var $book;
|
||||||
$book = state.$book;
|
$book = state.$book;
|
||||||
|
|
||||||
@@ -34,5 +35,15 @@ require([
|
|||||||
|
|
||||||
// Init navigation
|
// Init navigation
|
||||||
navigation.init();
|
navigation.init();
|
||||||
});
|
|
||||||
|
//Init font settings
|
||||||
|
fontSettings.init();
|
||||||
|
|
||||||
|
events.trigger("start", config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
events: events
|
||||||
|
};
|
||||||
});
|
});
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
define([
|
|
||||||
"lodash",
|
|
||||||
"mixpanel"
|
|
||||||
], function(_, mixpanel) {
|
|
||||||
mixpanel.init("01eb2b950ae09a5fdb15a98dcc5ff20e", {
|
|
||||||
loaded: function() {
|
|
||||||
track("page.start");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var isAvailable = function() {
|
|
||||||
return (
|
|
||||||
typeof mixpanel !== "undefined" &&
|
|
||||||
typeof mixpanel.track === "function"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
var track = function(e, data) {
|
|
||||||
if (!isAvailable()) {
|
|
||||||
console.warn("tracking not available!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("track", e);
|
|
||||||
mixpanel.track(e, _.extend(data || {}, {
|
|
||||||
'domain': window.location.host
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
isAvailable: isAvailable,
|
|
||||||
track: track
|
|
||||||
};
|
|
||||||
});
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
|
|
||||||
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
left: 0px;
|
left: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
|
|
||||||
|
color: @page-color;
|
||||||
background: @body-background;
|
background: @body-background;
|
||||||
.transition(left 0.5s ease);
|
.transition(left 0.5s ease);
|
||||||
|
|
||||||
@@ -23,7 +24,6 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
.page-inner {
|
.page-inner {
|
||||||
font-family: @font-family-serif;
|
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0px auto;
|
margin: 0px auto;
|
||||||
|
|
||||||
@@ -33,8 +33,6 @@
|
|||||||
|
|
||||||
background: @page-background;
|
background: @page-background;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +55,28 @@
|
|||||||
min-height: calc(~"100% - 57px")
|
min-height: calc(~"100% - 57px")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.font-size-0{
|
||||||
|
font-size:@s-font-size;
|
||||||
|
}
|
||||||
|
&.font-size-1{
|
||||||
|
font-size:@m-font-size;
|
||||||
|
}
|
||||||
|
&.font-size-2{
|
||||||
|
font-size:@l-font-size;
|
||||||
|
}
|
||||||
|
&.font-size-3{
|
||||||
|
font-size:@xl-font-size;
|
||||||
|
}
|
||||||
|
&.font-size-4{
|
||||||
|
font-size:@xxl-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.font-family-0{
|
||||||
|
font-family: @font-family-serif;
|
||||||
|
}
|
||||||
|
&.font-family-1{
|
||||||
|
font-family: @font-family-sans;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.with-summary {
|
&.with-summary {
|
||||||
@@ -72,4 +92,30 @@
|
|||||||
.transition(none) !important;
|
.transition(none) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.color-theme-1{
|
||||||
|
.book-body {
|
||||||
|
color: @page-color-1;
|
||||||
|
background: @body-background-1;
|
||||||
|
.page-wrapper {
|
||||||
|
.page-inner {
|
||||||
|
section{
|
||||||
|
background: @page-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.color-theme-2{
|
||||||
|
.book-body {
|
||||||
|
color: @page-color-2;
|
||||||
|
background: @body-background-2;
|
||||||
|
.page-wrapper {
|
||||||
|
.page-inner {
|
||||||
|
section{
|
||||||
|
background: @page-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
.book-header{
|
||||||
|
#font-settings-wrapper{
|
||||||
|
position:relative;
|
||||||
|
.dropdown-menu{
|
||||||
|
background-color:@header-background;
|
||||||
|
border-color:@sidebar-divider-color;
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
.dropdown-caret{
|
||||||
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
left: -8px;
|
||||||
|
width: 10px;
|
||||||
|
height: 18px;
|
||||||
|
float: left;
|
||||||
|
overflow: hidden;
|
||||||
|
.caret-outer{
|
||||||
|
position: absolute;
|
||||||
|
border-bottom: 9px solid transparent;
|
||||||
|
border-top: 9px solid transparent;
|
||||||
|
border-right: 9px solid rgba(0,0,0,0.1);
|
||||||
|
height: auto;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
.caret-inner{
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: -1px;
|
||||||
|
top: 0;
|
||||||
|
left: 1px;
|
||||||
|
border-bottom: 9px solid transparent;
|
||||||
|
border-top: 9px solid transparent;
|
||||||
|
border-right: 9px solid @header-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button{
|
||||||
|
border: 0;
|
||||||
|
background-color:transparent;
|
||||||
|
color:@header-button-color;
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color;
|
||||||
|
background-color:@header-button-hover-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#enlarge-font-size{
|
||||||
|
width: 50%;
|
||||||
|
font-size:1.4em;
|
||||||
|
}
|
||||||
|
#reduce-font-size{
|
||||||
|
width: 50.5%;
|
||||||
|
font-size:1em;
|
||||||
|
}
|
||||||
|
.btn-group-xs{
|
||||||
|
.btn{
|
||||||
|
width: 33.7%;
|
||||||
|
padding: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-group{
|
||||||
|
margin: 0px 0;
|
||||||
|
|
||||||
|
.list-group-item{
|
||||||
|
cursor:pointer;
|
||||||
|
background-color:transparent;
|
||||||
|
border-color: @sidebar-divider-color;
|
||||||
|
border-width: 1px 0 !important;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color;
|
||||||
|
background-color:@header-button-hover-background !important;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color:@header-button-hover-color;
|
||||||
|
background-color:@header-button-hover-background !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.open{
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Theme 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
.color-theme-1{
|
||||||
|
#font-settings-wrapper{
|
||||||
|
.dropdown-menu{
|
||||||
|
background-color:@sidebar-background-1;
|
||||||
|
border-color:@sidebar-divider-color-1;
|
||||||
|
.dropdown-caret .caret-inner{
|
||||||
|
border-right: 9px solid @sidebar-background-1;
|
||||||
|
}
|
||||||
|
button{
|
||||||
|
color:@header-button-color-1;
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color-1;
|
||||||
|
background-color:@header-button-hover-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-group{
|
||||||
|
.list-group-item{
|
||||||
|
border-color:@sidebar-divider-color-1;
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color-1;
|
||||||
|
background-color:@header-button-hover-background-1 !important;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color:@header-button-hover-color-1;
|
||||||
|
background-color:@header-button-hover-background-1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Theme 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
.color-theme-2{
|
||||||
|
#font-settings-wrapper{
|
||||||
|
.dropdown-menu{
|
||||||
|
background-color:@sidebar-background-2;
|
||||||
|
border-color:@sidebar-divider-color-2;
|
||||||
|
.dropdown-caret .caret-inner{
|
||||||
|
border-right: 9px solid @sidebar-background-2;
|
||||||
|
}
|
||||||
|
button{
|
||||||
|
color:@header-button-color-2;
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color-2;
|
||||||
|
background-color:@header-button-hover-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-group{
|
||||||
|
.list-group-item{
|
||||||
|
border-color:@sidebar-divider-color-2;
|
||||||
|
&:hover{
|
||||||
|
color:@header-button-hover-color-2;
|
||||||
|
background-color:@header-button-hover-background-2 !important;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color:@header-button-hover-color-2;
|
||||||
|
background-color:@header-button-hover-background-2 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
font-family: @font-family-sans;
|
font-family: @font-family-sans;
|
||||||
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
line-height: @header-height;
|
line-height: @header-height;
|
||||||
.box-shadow(none) !important;
|
.box-shadow(none) !important;
|
||||||
|
position:relative;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -64,4 +65,30 @@
|
|||||||
.transition(none) !important;
|
.transition(none) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.color-theme-1{
|
||||||
|
.book-header{
|
||||||
|
color: @header-color-1;
|
||||||
|
background: @header-background-1;
|
||||||
|
.btn {
|
||||||
|
color: @header-button-color-1;
|
||||||
|
&:hover {
|
||||||
|
color: @header-button-hover-color-1;
|
||||||
|
background: @header-button-hover-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.color-theme-2{
|
||||||
|
.book-header{
|
||||||
|
color: @header-color-2;
|
||||||
|
background: @header-background-2;
|
||||||
|
.btn {
|
||||||
|
color: @header-button-color-2;
|
||||||
|
&:hover {
|
||||||
|
color: @header-button-hover-color-2;
|
||||||
|
background: @header-button-hover-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
/* http://jmblog.github.io/color-themes-for-highlightjs */
|
||||||
|
|
||||||
/* Tomorrow Comment */
|
/* Tomorrow Comment */
|
||||||
.hljs-comment {
|
.hljs-comment {
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal {
|
||||||
|
color:@page-color-1;
|
||||||
|
}
|
||||||
|
.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal {
|
||||||
|
color:@page-color-2;
|
||||||
|
}
|
||||||
.book .book-body .page-wrapper .page-inner section.normal {
|
.book .book-body .page-wrapper .page-inner section.normal {
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
background-color: white;
|
color:@page-color;
|
||||||
|
|
||||||
|
|
||||||
& > *:first-child {
|
& > *:first-child {
|
||||||
margin-top: 0 !important; }
|
margin-top: 0 !important; }
|
||||||
@@ -52,12 +57,12 @@
|
|||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: black; }
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
color: black; }
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 18px; }
|
font-size: 18px; }
|
||||||
@@ -69,7 +74,6 @@
|
|||||||
font-size: 14px; }
|
font-size: 14px; }
|
||||||
|
|
||||||
h6 {
|
h6 {
|
||||||
color: #777777;
|
|
||||||
font-size: 14px; }
|
font-size: 14px; }
|
||||||
|
|
||||||
p, blockquote, ul, ol, dl, table, pre {
|
p, blockquote, ul, ol, dl, table, pre {
|
||||||
|
|||||||
@@ -43,3 +43,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.book.color-theme-1 .book-body {
|
||||||
|
.navigation:hover{
|
||||||
|
background-color: @body-pagination-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.book.color-theme-2 .book-body {
|
||||||
|
.navigation:hover{
|
||||||
|
background-color: @body-pagination-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
height: @bar-height;
|
height: @bar-height;
|
||||||
@@ -82,3 +81,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.book.color-theme-1 .book-body {
|
||||||
|
.book-progress {
|
||||||
|
.bar {
|
||||||
|
background: @bar-background-1;
|
||||||
|
.inner {
|
||||||
|
background: @bar-progress-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chapters .chapter{
|
||||||
|
background: @bar-background-1;
|
||||||
|
&.done{
|
||||||
|
background: @bar-progress-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.book.color-theme-2 .book-body {
|
||||||
|
.book-progress {
|
||||||
|
.bar {
|
||||||
|
background: @bar-background-2;
|
||||||
|
.inner {
|
||||||
|
background: @bar-progress-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chapters .chapter{
|
||||||
|
background: @bar-background-2;
|
||||||
|
&.done{
|
||||||
|
background: @bar-progress-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -141,3 +141,91 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Theme 1
|
||||||
|
*/
|
||||||
|
.book.color-theme-1 {
|
||||||
|
.book-summary {
|
||||||
|
color: @sidebar-color-1;
|
||||||
|
background: @sidebar-background-1;
|
||||||
|
|
||||||
|
.book-search {
|
||||||
|
background: @sidebar-search-background-1;
|
||||||
|
|
||||||
|
input, input:focus {
|
||||||
|
border: 1px solid @sidebar-search-input-border-color-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.summary {
|
||||||
|
li {
|
||||||
|
&.divider {
|
||||||
|
background: @sidebar-divider-color-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.fa-check {
|
||||||
|
color: @sidebar-icon-color-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.done > a {
|
||||||
|
color: @sidebar-link-completed-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, span {
|
||||||
|
color: @sidebar-link-color-1;
|
||||||
|
background: @sidebar-link-background-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > a, a:hover {
|
||||||
|
color: @sidebar-link-hover-color-1;
|
||||||
|
background: @sidebar-link-hover-background-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Theme 2
|
||||||
|
*/
|
||||||
|
.book.color-theme-2{
|
||||||
|
.book-summary {
|
||||||
|
color: @sidebar-color-2;
|
||||||
|
background: @sidebar-background-2;
|
||||||
|
|
||||||
|
.book-search {
|
||||||
|
background: @sidebar-search-background-2;
|
||||||
|
|
||||||
|
input, input:focus {
|
||||||
|
border: 1px solid @sidebar-search-input-border-color-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.summary {
|
||||||
|
li {
|
||||||
|
&.divider {
|
||||||
|
background: @sidebar-divider-color-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.fa-check {
|
||||||
|
color: @sidebar-icon-color-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.done > a {
|
||||||
|
color: @sidebar-link-completed-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, span {
|
||||||
|
color: @sidebar-link-color-2;
|
||||||
|
background: @sidebar-link-background-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > a, a:hover {
|
||||||
|
color: @sidebar-link-hover-color-2;
|
||||||
|
background: @sidebar-link-hover-background-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
@import "book/languages.less";
|
@import "book/languages.less";
|
||||||
@import "book/header.less";
|
@import "book/header.less";
|
||||||
@import "book/summary.less";
|
@import "book/summary.less";
|
||||||
|
@import "book/font-settings.less";
|
||||||
@import "book/body.less";
|
@import "book/body.less";
|
||||||
@import "book/exercise.less";
|
@import "book/exercise.less";
|
||||||
@import "book/quiz.less";
|
@import "book/quiz.less";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
/* http://jmblog.github.io/color-themes-for-highlightjs */
|
||||||
|
|
||||||
/* Tomorrow Comment */
|
/* Tomorrow Comment */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
@sidebar-link-completed-weight: normal;
|
@sidebar-link-completed-weight: normal;
|
||||||
|
|
||||||
// Page
|
// Page
|
||||||
|
@page-color: black;
|
||||||
@page-background: white;
|
@page-background: white;
|
||||||
|
|
||||||
// Progress Bar
|
// Progress Bar
|
||||||
@@ -79,5 +80,94 @@
|
|||||||
@font-family-sans: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
@font-family-sans: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
@font-family-base: @font-family-serif;
|
@font-family-base: @font-family-serif;
|
||||||
|
|
||||||
|
|
||||||
@FontPath: '@{staticPath}/fonts';
|
@FontPath: '@{staticPath}/fonts';
|
||||||
@fa-font-path: "@{FontPath}/fontawesome";
|
@fa-font-path: "@{FontPath}/fontawesome";
|
||||||
|
|
||||||
|
@s-font-size: 1.2rem;
|
||||||
|
@m-font-size: 1.4rem;
|
||||||
|
@l-font-size: 1.6rem;
|
||||||
|
@xl-font-size: 2.2rem;
|
||||||
|
@xxl-font-size: 4.0rem;
|
||||||
|
|
||||||
|
/*
|
||||||
|
,--------.,--.
|
||||||
|
'--. .--'| ,---. ,---. ,--,--,--. ,---. ,---. .--.
|
||||||
|
| | | .-. || .-. :| || .-. :( .-' '--'
|
||||||
|
| | | | | |\ --.| | | |\ --..-' `).--.
|
||||||
|
`--' `--' `--' `----'`--`--`--' `----'`----' '--'
|
||||||
|
*/
|
||||||
|
// Header
|
||||||
|
@header-color-1: #AFA790;
|
||||||
|
@header-color-2: #7e888b;
|
||||||
|
@header-background-1: #ECE3C4;
|
||||||
|
@header-background-2: #1d1f21;
|
||||||
|
@header-button-color-1: #AFA790;
|
||||||
|
@header-button-color-2: #7e888b;
|
||||||
|
@header-button-hover-color-1: #73553C;
|
||||||
|
@header-button-hover-color-2: #C9C9C9;
|
||||||
|
@header-button-hover-background-1: #E2DABE;
|
||||||
|
@header-button-hover-background-2: #0B0D0E;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
@body-background-1: #F3EACB;
|
||||||
|
@body-background-2: #1d1f21;
|
||||||
|
@body-pagination-background-1: #FFFAEA;
|
||||||
|
@body-pagination-background-2: #33404D;
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
@sidebar-color-1: #AFA790;
|
||||||
|
@sidebar-color-2: hsl(207, 15%, 80%);
|
||||||
|
@sidebar-background-1: #F3EACB;
|
||||||
|
@sidebar-background-2: #111111;
|
||||||
|
|
||||||
|
@sidebar-search-background-1: transparent;
|
||||||
|
@sidebar-search-background-2: transparent;
|
||||||
|
@sidebar-search-input-border-color-1: #D6CFBA;
|
||||||
|
@sidebar-search-input-border-color-2: #c4cdd4;
|
||||||
|
|
||||||
|
@sidebar-divider-color-1: hsl(207, 15%, 85%);
|
||||||
|
@sidebar-divider-color-2: #1d1f21;
|
||||||
|
|
||||||
|
@sidebar-link-color-1: #877F6A;
|
||||||
|
@sidebar-link-color-2: hsl(207, 15%, 50%);
|
||||||
|
@sidebar-link-background-1: transparent;
|
||||||
|
@sidebar-link-background-2: transparent;
|
||||||
|
@sidebar-link-hover-color-1: #704214;
|
||||||
|
@sidebar-link-hover-color-2: hsl(207, 100%, 50%);
|
||||||
|
@sidebar-link-hover-background-1: transparent;
|
||||||
|
@sidebar-link-hover-background-2: transparent;
|
||||||
|
|
||||||
|
@sidebar-icon-color-1: @bar-progress-background;
|
||||||
|
@sidebar-icon-color-2: @bar-progress-background;
|
||||||
|
@sidebar-link-completed-1: hsl(207, 15%, 25%);
|
||||||
|
@sidebar-link-completed-2: hsl(207, 15%, 25%);
|
||||||
|
@sidebar-link-completed-weight-1: normal;
|
||||||
|
@sidebar-link-completed-weight-2: normal;
|
||||||
|
|
||||||
|
// Page
|
||||||
|
@page-color-1: #704214;
|
||||||
|
@page-color-2: #a4b1b1;
|
||||||
|
@page-background-1: #F3EACB;
|
||||||
|
@page-background-2: #1d1f21;
|
||||||
|
|
||||||
|
@bar-background-1: #F3EACB;
|
||||||
|
@bar-background-2: #1d1f21;
|
||||||
|
@bar-progress-background-1: #704214;
|
||||||
|
@bar-progress-background-2: hsl(120, 60%, 50%);
|
||||||
|
|
||||||
|
// Basics of a navbar
|
||||||
|
@navbar-default-border-1: #d5d5d5;
|
||||||
|
@navbar-default-border-2: #d5d5d5;
|
||||||
|
|
||||||
|
// Navbar brand label
|
||||||
|
@navbar-default-color-1: #333;
|
||||||
|
@navbar-default-color-2: #333;
|
||||||
|
@navbar-default-link-color-1: #333;
|
||||||
|
@navbar-default-link-color-2: #333;
|
||||||
|
@navbar-default-brand-color-1: @navbar-default-link-color;
|
||||||
|
@navbar-default-brand-color-2: @navbar-default-link-color;
|
||||||
|
@navbar-default-brand-hover-color-1: @navbar-default-link-color;
|
||||||
|
@navbar-default-brand-hover-color-2: @navbar-default-link-color;
|
||||||
|
@navbar-default-brand-hover-bg-1: transparent;
|
||||||
|
@navbar-default-brand-hover-bg-2: transparent;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<div class="dropdown-menu font-settings">
|
||||||
|
<div class="dropdown-caret">
|
||||||
|
<span class="caret-outer"></span>
|
||||||
|
<span class="caret-inner"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group btn-block">
|
||||||
|
<button id="reduce-font-size" class="btn btn-default">A</button>
|
||||||
|
<button id="enlarge-font-size" class="btn btn-default">A</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="list-group font-family-list">
|
||||||
|
<li class="list-group-item" data-font="0">Serif</li>
|
||||||
|
<li class="list-group-item" data-font="1">Sans</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="btn-group btn-group-xs btn-block color-theme-list">
|
||||||
|
<button type="button" class="btn btn-default" id="color-theme-preview-0" data-theme="0">White</button>
|
||||||
|
<button type="button" class="btn btn-default" id="color-theme-preview-1" data-theme="1">Sepia</button>
|
||||||
|
<button type="button" class="btn btn-default" id="color-theme-preview-2" data-theme="2">Night</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -5,6 +5,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="#" class="btn pull-left toggle-summary"><i class="fa fa-align-justify"></i></a>
|
<a href="#" class="btn pull-left toggle-summary"><i class="fa fa-align-justify"></i></a>
|
||||||
<a href="#" class="btn pull-left toggle-search"><i class="fa fa-search"></i></a>
|
<a href="#" class="btn pull-left toggle-search"><i class="fa fa-search"></i></a>
|
||||||
|
<span id="font-settings-wrapper">
|
||||||
|
<a href="#" class="btn pull-left toggle-font-settings"><i class="fa fa-font"></i>
|
||||||
|
</a>
|
||||||
|
{% include "./font-settings.html" %}
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- Actions Right -->
|
<!-- Actions Right -->
|
||||||
<a href="#" target="_blank" class="btn pull-right" data-sharing="google-plus"><i class="fa fa-google-plus"></i></a>
|
<a href="#" target="_blank" class="btn pull-right" data-sharing="google-plus"><i class="fa fa-google-plus"></i></a>
|
||||||
|
|||||||
@@ -35,10 +35,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% block content %}{% endblock %}
|
|
||||||
{% block style %}
|
{% block style %}
|
||||||
<link rel="stylesheet" href="{{ staticBase }}/style.css">
|
<link rel="stylesheet" href="{{ staticBase }}/style.css">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% block content %}{% endblock %}
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script>
|
||||||
|
|||||||
@@ -77,9 +77,11 @@
|
|||||||
<h1>{{ item.title }}</h1>
|
<h1>{{ item.title }}</h1>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
{% if pages[item.path] %}
|
||||||
<article>
|
<article>
|
||||||
{{ articleContent(pages[item.path].content) }}
|
{{ articleContent(pages[item.path].content) }}
|
||||||
</article>
|
</article>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if item.articles.length > 0 %}
|
{% if item.articles.length > 0 %}
|
||||||
{% for article in item.articles %}
|
{% for article in item.articles %}
|
||||||
|
|||||||
@@ -35,3 +35,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascript %}
|
||||||
|
{% parent %}
|
||||||
|
{% for resource in plugins.resources.js %}
|
||||||
|
{% if resource.url %}
|
||||||
|
<script src="{{ resource.url }}"></script>
|
||||||
|
{% else %}
|
||||||
|
<script src="{{ staticBase }}/plugins/{{ resource.path }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<script>
|
||||||
|
require(["gitbook"], function(gitbook) {
|
||||||
|
var config = {% autoescape false %}{{ pluginsConfig }}{% endautoescape %};
|
||||||
|
gitbook.start(config);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block style %}
|
||||||
|
{% parent %}
|
||||||
|
{% 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 %}
|
||||||
|
|||||||
Reference in New Issue
Block a user