mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-26 20:27:00 +00:00
Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b76032bb1 | |||
| 85b09eda56 | |||
| c4be78a81f | |||
| e7309f71d2 | |||
| 6c979c9419 | |||
| 7fd7732345 | |||
| 960ef4d945 | |||
| 92523fb4b5 | |||
| 66bb46df22 | |||
| 0454710d3b | |||
| c9a31cc987 | |||
| f03c316274 | |||
| 001a4f91be | |||
| 44a3bfe296 | |||
| a9ce6f808d | |||
| e5c667e0fa | |||
| e36f274dbe | |||
| 2a88427e74 | |||
| ed48f5f3ee | |||
| 7b4accb117 | |||
| d6437d31d4 | |||
| 3dd33f1f3c | |||
| 3a0f00411b | |||
| 5b655bb29a | |||
| faf10605e8 | |||
| c52aecdbd5 | |||
| 5c98b3350b | |||
| 6f4e1d10c1 | |||
| 870886599a | |||
| 1b9801b8a4 | |||
| 897463b22e | |||
| aa4894e94c | |||
| 8a0180ae6b | |||
| d6776b98d3 | |||
| 6a04ba89a5 | |||
| 05eaeeb0d0 | |||
| 77043464b2 | |||
| b90f74a821 | |||
| f804eb42ac | |||
| 74fd8c159b | |||
| a741ec1350 | |||
| 4b26c31b3b | |||
| dfd487692a | |||
| 195374ecee | |||
| 1659778a77 | |||
| 40c4035afb | |||
| 1502d65286 | |||
| 9da10e2b25 |
+31
@@ -1,5 +1,36 @@
|
||||
# Release notes
|
||||
|
||||
## 1.5.0
|
||||
- Fix `serve` command, broken by `1.4.2`
|
||||
- Add nicer `dark` theme :)
|
||||
|
||||
## 1.4.2
|
||||
- Force `process.exit` after builds, to prevent (possibly) lingering plugins
|
||||
|
||||
## 1.4.1
|
||||
- Fix command 'install' without arguments
|
||||
|
||||
## 1.4.0
|
||||
- Add command `gitbook install` to install plugins from book.json
|
||||
- `package.json` is no longer necessary
|
||||
|
||||
## 1.3.4
|
||||
- Add glossary to ebooks
|
||||
- Fix autocover with new hook "finish:before"
|
||||
- Add X-UA-Compatible meta tag for IE
|
||||
|
||||
## 1.3.3
|
||||
- Fix parsing of lexed content using the client library
|
||||
|
||||
## 1.3.2
|
||||
- ePub files are now passing validation from epubcheck
|
||||
- Fix replacement of multiple glossary terms in a single sentence
|
||||
- Fix on windows deep relative links
|
||||
- Fix search indexer
|
||||
|
||||
## 1.3.1
|
||||
- Fix error with links in markdown
|
||||
|
||||
## 1.3.0
|
||||
- Bundle gitbook parsing library as a client side library in `gitbook.js` and `gitbook.min.js`
|
||||
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ module.exports = function (grunt) {
|
||||
|
||||
// Bundle the library
|
||||
grunt.registerTask('bundle', [
|
||||
'bower-install',
|
||||
'browserify',
|
||||
'uglify'
|
||||
]);
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ GitBook can be installed from **NPM** using:
|
||||
$ npm install gitbook -g
|
||||
```
|
||||
|
||||
Create the directories and files for a book from its [SUMMARY.md](https://github.com/GitbookIO/gitbook#book-format) file using
|
||||
```
|
||||
$ gitbook init
|
||||
```
|
||||
|
||||
You can serve a repository as a book using:
|
||||
|
||||
```
|
||||
@@ -52,9 +57,10 @@ Here are the options that can be stored in this file:
|
||||
// It's not advised this option in the book.json
|
||||
"generator": "site",
|
||||
|
||||
// Book title and description (defaults are extracted from the README)
|
||||
// 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"
|
||||
@@ -132,7 +138,10 @@ You can publish your books to our index by visiting [GitBook.io](http://www.gitb
|
||||
GitBook can generate your book in the following formats:
|
||||
|
||||
* **Static Website**: This is the default format. It generates a complete interactive static website that can be, for example, hosted on GitHub Pages.
|
||||
* **eBook**: A complete eBook with exercise solutions at the end of the book. Generate this format using: ```gitbook ebook ./myrepo```. You need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed. The output format could be **PDF**, **ePub** or **MOBI**.
|
||||
* **eBook**: A complete eBook with exercise solutions at the end of the book. You need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed. You can specify the eBook filename with the `-o` option, otherwise `book` will be used.
|
||||
* Generate a **PDF** using: `gitbook pdf ./myrepo`
|
||||
* Generate a **ePub** using: `gitbook epub ./myrepo`
|
||||
* Generate a **MOBI** using: `gitbook mobi ./myrepo`
|
||||
* **JSON**: This format is used for debugging or extracting metadata from a book. Generate this format using: ```gitbook build ./myrepo -f json```.
|
||||
|
||||
## Book Format
|
||||
@@ -211,6 +220,8 @@ The platform [GitBook.io](https://www.gitbook.io/) is like an "Heroku for books"
|
||||
|
||||
Plugins can be used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
|
||||
|
||||
Plugins needed to build a book can be installed using: `gitbook install ./`.
|
||||
|
||||
##### Official plugins:
|
||||
|
||||
| Name | Description |
|
||||
@@ -236,6 +247,8 @@ Plugins can be used to extend your book's functionality. Read [GitbookIO/plugin]
|
||||
| [Piwik Open Analytics](https://github.com/emmanuel-keller/gitbook-plugin-piwik) | Piwik Open Analytics tracking for your book |
|
||||
| [Heading Anchors](https://github.com/rlmv/gitbook-plugin-anchors) | Add linkable Github-style anchors to headings |
|
||||
| [JSBin](https://github.com/jcouyang/gitbook-plugin-jsbin) | Embedded jsbin frame into your book |
|
||||
| [gitbook-grvis](https://github.com/romanlytkin/gitbook-grvis) | Gitbook GrViz plugin is used to select from markdown dot and converting it into a picture format svg |
|
||||
| [gitbook-plantuml](https://github.com/romanlytkin/gitbook-plantuml) | Gitbook PlantUml plugin is used to select from markdown uml and converting it into a picture format svg |
|
||||
|
||||
#### Debugging
|
||||
|
||||
|
||||
@@ -44,13 +44,6 @@ var makeBuildFunc = function(converter) {
|
||||
.then(function(output) {
|
||||
console.log("Successfully built!");
|
||||
return output;
|
||||
})
|
||||
.fail(function(err) {
|
||||
// Log error
|
||||
utils.logError(err);
|
||||
|
||||
// Exit process with failure code
|
||||
process.exit(-1);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
+44
-22
@@ -7,11 +7,12 @@ var prog = require('commander');
|
||||
var tinylr = require('tiny-lr-fork');
|
||||
|
||||
var pkg = require('../package.json');
|
||||
var generators = require("../lib/generate").generators;
|
||||
var genbook = require("../lib/generate");
|
||||
var initDir = require("../lib/generate/init");
|
||||
var fs = require('../lib/generate/fs');
|
||||
|
||||
var utils = require('./utils');
|
||||
var action = utils.action;
|
||||
var build = require('./build');
|
||||
var Server = require('./server');
|
||||
var platform = require("./platform");
|
||||
@@ -22,13 +23,13 @@ prog
|
||||
|
||||
build.command(prog.command('build [source_dir]'))
|
||||
.description('Build a gitbook from a directory')
|
||||
.action(build.folder);
|
||||
.action(action(build.folder));
|
||||
|
||||
build.command(prog.command('serve [source_dir]'))
|
||||
.description('Build then serve a gitbook from a directory')
|
||||
.option('-p, --port <port>', 'Port for server to listen on', 4000)
|
||||
.option('--no-watch', 'Disable restart with file watching')
|
||||
.action(function(dir, options) {
|
||||
.action(action(function(dir, options) {
|
||||
var server = new Server();
|
||||
|
||||
// init livereload server
|
||||
@@ -41,9 +42,11 @@ build.command(prog.command('serve [source_dir]'))
|
||||
});
|
||||
|
||||
var generate = function() {
|
||||
if (server.isRunning()) console.log("Stopping server");
|
||||
if (server.isRunning()) {
|
||||
console.log("Stopping server");
|
||||
}
|
||||
|
||||
server.stop()
|
||||
return server.stop()
|
||||
.then(function() {
|
||||
return build.folder(dir, _.extend(options || {}, {
|
||||
defaultsPlugins: ["livereload"]
|
||||
@@ -77,59 +80,78 @@ build.command(prog.command('serve [source_dir]'))
|
||||
|
||||
console.log('Press CTRL+C to quit ...');
|
||||
console.log('')
|
||||
generate();
|
||||
});
|
||||
|
||||
return generate();
|
||||
}));
|
||||
|
||||
build.commandEbook(prog.command('install [source_dir]'))
|
||||
.description('Install plugins for a book')
|
||||
.action(action(function(dir, options) {
|
||||
dir = dir || process.cwd();
|
||||
|
||||
console.log("Install plugins in", dir);
|
||||
|
||||
return genbook.config.read({
|
||||
input: dir
|
||||
})
|
||||
.then(function(options) {
|
||||
return genbook.Plugin.install(options);
|
||||
})
|
||||
.then(function() {
|
||||
console.log("Successfully installed plugins!");
|
||||
});
|
||||
}));
|
||||
|
||||
build.commandEbook(prog.command('pdf [source_dir]'))
|
||||
.description('Build a gitbook as a PDF')
|
||||
.action(function(dir, options) {
|
||||
build.file(dir, _.extend(options, {
|
||||
.action(action(function(dir, options) {
|
||||
return build.file(dir, _.extend(options, {
|
||||
extension: "pdf",
|
||||
format: "ebook"
|
||||
}));
|
||||
});
|
||||
}));
|
||||
|
||||
build.commandEbook(prog.command('epub [source_dir]'))
|
||||
.description('Build a gitbook as a ePub book')
|
||||
.action(function(dir, options) {
|
||||
build.file(dir, _.extend(options, {
|
||||
.action(action(function(dir, options) {
|
||||
return build.file(dir, _.extend(options, {
|
||||
extension: "epub",
|
||||
format: "ebook"
|
||||
}));
|
||||
});
|
||||
}));
|
||||
|
||||
build.commandEbook(prog.command('mobi [source_dir]'))
|
||||
.description('Build a gitbook as a Mobi book')
|
||||
.action(function(dir, options) {
|
||||
build.file(dir, _.extend(options, {
|
||||
.action(action(function(dir, options) {
|
||||
return build.file(dir, _.extend(options, {
|
||||
extension: "mobi",
|
||||
format: "ebook"
|
||||
}));
|
||||
});
|
||||
}));
|
||||
|
||||
prog
|
||||
.command('init [source_dir]')
|
||||
.description('Create files and folders based on contents of SUMMARY.md')
|
||||
.action(function(dir) {
|
||||
.action(action(function(dir) {
|
||||
dir = dir || process.cwd();
|
||||
return initDir(dir);
|
||||
});
|
||||
}));
|
||||
|
||||
prog
|
||||
.command('publish [source_dir]')
|
||||
.description('Publish content to the associated gitbook.io book')
|
||||
.action(function(dir) {
|
||||
.action(action(function(dir) {
|
||||
dir = dir || process.cwd();
|
||||
return platform.publish(dir);
|
||||
});
|
||||
}));
|
||||
|
||||
prog
|
||||
.command('git:remote [source_dir] [book_id]')
|
||||
.description('Adds a git remote to a book repository')
|
||||
.action(function(dir, bookId) {
|
||||
.action(action(function(dir, bookId) {
|
||||
dir = dir || process.cwd();
|
||||
return platform.remote(dir, bookId);
|
||||
});
|
||||
}));
|
||||
|
||||
// Parse and fallback to help if no args
|
||||
if(_.isEmpty(prog.parse(process.argv).args) && process.argv.length === 2) {
|
||||
|
||||
@@ -30,6 +30,34 @@ function watch(dir) {
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
// exit wraps a promise
|
||||
// and forcefully quits the program when the promise is resolved
|
||||
function exit(promise) {
|
||||
promise
|
||||
.then(function() {
|
||||
// Prevent badly behaving plugins
|
||||
// from making the process hang
|
||||
process.exit(0);
|
||||
}, function(err) {
|
||||
// Log error
|
||||
logError(err);
|
||||
|
||||
// Exit process with failure code
|
||||
process.exit(-1);
|
||||
});
|
||||
}
|
||||
|
||||
// CLI action wrapper, calling exit when finished
|
||||
function action(f) {
|
||||
return function() {
|
||||
// Call func and get optional promise
|
||||
var p = f.apply(null, arguments);
|
||||
|
||||
// Exit process
|
||||
return exit(Q(p));
|
||||
}
|
||||
}
|
||||
|
||||
function logError(err) {
|
||||
var message = err.message || err;
|
||||
if (process.env.DEBUG != null) message = err.stack || message;
|
||||
@@ -60,6 +88,8 @@ function runGitCommand(command, args) {
|
||||
|
||||
// Exports
|
||||
module.exports = {
|
||||
exit: exit,
|
||||
action: action,
|
||||
watch: watch,
|
||||
logError: logError,
|
||||
gitCmd: runGitCommand
|
||||
|
||||
+9
-4
@@ -427,8 +427,10 @@ function parsePage(src, options) {
|
||||
options = options || {};
|
||||
|
||||
// Lex if not already lexed
|
||||
return (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
|
||||
.map(function(section) {
|
||||
var parsed = {
|
||||
lexed: (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
|
||||
};
|
||||
parsed.sections = parsed.lexed.map(function(section) {
|
||||
// Transform given type
|
||||
if(section.type === 'exercise') {
|
||||
var nonCodeNodes = _.reject(section, {
|
||||
@@ -526,6 +528,8 @@ function parsePage(src, options) {
|
||||
content: render(section, options)
|
||||
};
|
||||
});
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Exports
|
||||
@@ -628,6 +632,7 @@ module.exports = parseReadme;
|
||||
|
||||
},{"kramed":134,"kramed-text-renderer":133,"lodash":135}],13:[function(require,module,exports){
|
||||
var url = require('url');
|
||||
var _ = require('lodash');
|
||||
var inherits = require('util').inherits;
|
||||
var links = require('../utils').links;
|
||||
var kramed = require('kramed');
|
||||
@@ -677,7 +682,7 @@ GitBookRenderer.prototype.link = function(href, title, text) {
|
||||
// Parsed version of the url
|
||||
var parsed = url.parse(href);
|
||||
var o = this._extra_options;
|
||||
var extname = _.last(parsed.path.split("."));
|
||||
var extname = parsed.path? _.last(parsed.path.split(".")) : "";
|
||||
|
||||
// Relative link, rewrite it to point to github repo
|
||||
if(links.isRelative(_href) && extname == "md") {
|
||||
@@ -768,7 +773,7 @@ GitBookRenderer.prototype.heading = function(text, level, raw) {
|
||||
// Exports
|
||||
module.exports = GitBookRenderer;
|
||||
|
||||
},{"../utils":15,"kramed":134,"url":25,"util":27}],14:[function(require,module,exports){
|
||||
},{"../utils":15,"kramed":134,"lodash":135,"url":25,"util":27}],14:[function(require,module,exports){
|
||||
var _ = require('lodash');
|
||||
var kramed = require('kramed');
|
||||
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+28
-4
@@ -1,3 +1,4 @@
|
||||
var Q = require('q');
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
|
||||
@@ -16,9 +17,10 @@ var CONFIG = {
|
||||
// Configuration file to use
|
||||
"configFile": "book",
|
||||
|
||||
// Book title and description (defaults are extracted from the README)
|
||||
// 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"
|
||||
@@ -96,10 +98,32 @@ var CONFIG = {
|
||||
}
|
||||
};
|
||||
|
||||
// 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: function(options) {
|
||||
return _.merge(options || {}, CONFIG, _.defaults);
|
||||
}
|
||||
defaults: defaultsConfig,
|
||||
read: readConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ Generator.prototype.finish = function() {
|
||||
"--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 ')]",
|
||||
|
||||
+14
-1
@@ -64,7 +64,20 @@ var getFiles = function(path) {
|
||||
module.exports = {
|
||||
list: getFiles,
|
||||
readFile: Q.denodeify(fs.readFile),
|
||||
writeFile: Q.denodeify(fs.writeFile),
|
||||
//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),
|
||||
|
||||
+16
-20
@@ -48,28 +48,18 @@ var loadGenerator = function(options) {
|
||||
|
||||
|
||||
var generate = function(options) {
|
||||
// Set defaults to options
|
||||
options = defaultConfig.defaults(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 config file
|
||||
.then(function() {
|
||||
try {
|
||||
var _config = require(path.resolve(options.input, options.configFile));
|
||||
return defaultConfig.read(options)
|
||||
.then(function(_options) {
|
||||
options = _options;
|
||||
|
||||
options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins'));
|
||||
}
|
||||
catch(err) {
|
||||
// No config file: not a big deal
|
||||
return Q();
|
||||
// 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
|
||||
@@ -99,7 +89,9 @@ var generate = function(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");
|
||||
@@ -297,6 +289,9 @@ var generateBook = function(options) {
|
||||
})
|
||||
|
||||
// Finish generation
|
||||
.then(function() {
|
||||
return generator.callHook("finish:before");
|
||||
})
|
||||
.then(function() {
|
||||
return generator.finish();
|
||||
})
|
||||
@@ -375,4 +370,5 @@ module.exports = {
|
||||
file: generateFile,
|
||||
book: generateBook,
|
||||
Plugin: Plugin,
|
||||
config: defaultConfig
|
||||
};
|
||||
|
||||
@@ -29,8 +29,9 @@ Generator.prototype.convertFile = function(content, input) {
|
||||
dir: path.dirname(input) || '/'
|
||||
});
|
||||
})
|
||||
.then(function(sections) {
|
||||
json.sections = sections;
|
||||
.then(function(parsed) {
|
||||
json.lexed = parsed.lexed;
|
||||
json.sections = parsed.sections;
|
||||
})
|
||||
.then(function() {
|
||||
return fs.writeFile(
|
||||
|
||||
@@ -26,6 +26,9 @@ Generator.prototype.loadTemplates = function() {
|
||||
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
|
||||
@@ -46,7 +49,7 @@ Generator.prototype.finish = function() {
|
||||
var output = path.join(this.options.output, "index.html");
|
||||
|
||||
var progress = parse.progress(this.options.navigation, "README.md");
|
||||
|
||||
|
||||
return Q()
|
||||
|
||||
// Write table of contents
|
||||
@@ -54,6 +57,11 @@ Generator.prototype.finish = function() {
|
||||
return that.writeToc();
|
||||
})
|
||||
|
||||
// Write glossary
|
||||
.then(function() {
|
||||
return that.writeGlossary();
|
||||
})
|
||||
|
||||
// Copy cover
|
||||
.then(function() {
|
||||
return that.copyCover();
|
||||
|
||||
+57
-16
@@ -4,6 +4,7 @@ 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");
|
||||
@@ -152,33 +153,73 @@ Plugin.prototype.copyAssets = function(out, options) {
|
||||
};
|
||||
|
||||
|
||||
// Normalize a list of plugin name to use
|
||||
Plugin.normalizeNames = function(names) {
|
||||
// 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
|
||||
names = _.isString(names) ? names.split(",") : (names || []);
|
||||
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(names)
|
||||
.filter(function(name) {
|
||||
return name.length > 0 && name[0] == "-";
|
||||
var toremove = _.chain(plugins)
|
||||
.filter(function(plugin) {
|
||||
return plugin.name.length > 0 && plugin.name[0] == "-";
|
||||
})
|
||||
.map(function(name) {
|
||||
return name.slice(1);
|
||||
.map(function(plugin) {
|
||||
return plugin.name.slice(1);
|
||||
})
|
||||
.value();
|
||||
|
||||
// Merge with defaults
|
||||
names = _.chain(names)
|
||||
.concat(Plugin.defaults)
|
||||
plugins = _.chain(plugins)
|
||||
.concat(_.map(Plugin.defaults, function(plugin) {
|
||||
return { 'name': plugin }
|
||||
}))
|
||||
.uniq()
|
||||
.value();
|
||||
|
||||
// Remove plugins starting with
|
||||
names = _.filter(names, function(name) {
|
||||
return !_.contains(toremove, name) && !(name.length > 0 && name[0] == "-");
|
||||
// Build final list
|
||||
plugins = _.filter(plugins, function(plugin) {
|
||||
return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
|
||||
});
|
||||
|
||||
return names;
|
||||
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
|
||||
@@ -196,7 +237,7 @@ Plugin.fromList = function(names, root, generator, options) {
|
||||
return plugin;
|
||||
});
|
||||
|
||||
if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")));
|
||||
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;
|
||||
@@ -276,7 +317,7 @@ Plugin.fromList = function(names, root, generator, options) {
|
||||
});
|
||||
};
|
||||
|
||||
// Default plugins
|
||||
// Default plugins added to each books
|
||||
Plugin.defaults = [
|
||||
"mathjax"
|
||||
];
|
||||
|
||||
@@ -134,8 +134,9 @@ Generator.prototype.prepareFile = function(content, _input) {
|
||||
], path.join, fs.readFileSync)
|
||||
});
|
||||
})
|
||||
.then(function(sections) {
|
||||
page.sections = sections;
|
||||
.then(function(parsed) {
|
||||
page.lexed = parsed.lexed;
|
||||
page.sections = parsed.sections;
|
||||
|
||||
// Use plugin hook
|
||||
return _callHook("page");
|
||||
@@ -153,7 +154,12 @@ Generator.prototype.convertFile = function(content, _input) {
|
||||
if (_output == "README.html") _output = "index.html";
|
||||
var output = path.join(this.options.output, _output);
|
||||
var basePath = path.relative(path.dirname(output), this.options.output) || ".";
|
||||
|
||||
|
||||
// Bug fix for issue #493 which would occur when relative-links are 2-level or more deep in win32
|
||||
if (process.platform === 'win32') {
|
||||
basePath = basePath.replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
return this.prepareFile(content, _input)
|
||||
.then(function(page) {
|
||||
// Index page in search
|
||||
|
||||
+6
-2
@@ -51,8 +51,10 @@ function parsePage(src, options) {
|
||||
options = options || {};
|
||||
|
||||
// Lex if not already lexed
|
||||
return (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
|
||||
.map(function(section) {
|
||||
var parsed = {
|
||||
lexed: (_.isArray(src) ? src : lex(include(src, options.includer || function() { return undefined; })))
|
||||
};
|
||||
parsed.sections = parsed.lexed.map(function(section) {
|
||||
// Transform given type
|
||||
if(section.type === 'exercise') {
|
||||
var nonCodeNodes = _.reject(section, {
|
||||
@@ -150,6 +152,8 @@ function parsePage(src, options) {
|
||||
content: render(section, options)
|
||||
};
|
||||
});
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Exports
|
||||
|
||||
@@ -49,7 +49,7 @@ GitBookRenderer.prototype.link = function(href, title, text) {
|
||||
// Parsed version of the url
|
||||
var parsed = url.parse(href);
|
||||
var o = this._extra_options;
|
||||
var extname = _.last(parsed.path.split("."));
|
||||
var extname = parsed.path? _.last(parsed.path.split(".")) : "";
|
||||
|
||||
// Relative link, rewrite it to point to github repo
|
||||
if(links.isRelative(_href) && extname == "md") {
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gitbook",
|
||||
"version": "1.3.0",
|
||||
"version": "1.5.0",
|
||||
"homepage": "http://www.gitbook.io/",
|
||||
"description": "Library and cmd utility to generate GitBooks",
|
||||
"main": "lib/index.js",
|
||||
@@ -19,6 +19,7 @@
|
||||
"highlight.js": "8.3.0",
|
||||
"tmp": "0.0.23",
|
||||
"semver": "2.2.1",
|
||||
"npmi": "0.1.1",
|
||||
"gaze": "~0.5.1",
|
||||
"resolve": "0.6.3",
|
||||
"tiny-lr-fork": "0.0.5",
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ var FIXTURES_DIR = path.join(__dirname, './fixtures/');
|
||||
|
||||
function loadPage (name, options) {
|
||||
var CONTENT = fs.readFileSync(FIXTURES_DIR + name + '.md', 'utf8');
|
||||
return page(CONTENT, options);
|
||||
return page(CONTENT, options).sections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-10
@@ -6,7 +6,7 @@ var page = require('../').parse.page;
|
||||
|
||||
function loadPage (name, options) {
|
||||
var CONTENT = fs.readFileSync(path.join(__dirname, './fixtures/' + name + '.md'), 'utf8');
|
||||
return page(CONTENT, options);
|
||||
return page(CONTENT, options).sections;
|
||||
}
|
||||
|
||||
var LEXED = loadPage('PAGE', {
|
||||
@@ -80,9 +80,6 @@ describe('Page parsing', function() {
|
||||
describe('Relative links', function() {
|
||||
it('should replace link to .md by link to .html', function() {
|
||||
var LEXED = loadPage('MARKDOWN_LINKS', {
|
||||
// GitHub repo ID
|
||||
repo: 'GitBookIO/javascript',
|
||||
|
||||
// Imaginary folder of markdown file
|
||||
dir: 'course',
|
||||
outdir: 'course'
|
||||
@@ -96,9 +93,6 @@ describe('Relative links', function() {
|
||||
describe('Relative images', function() {
|
||||
it('should keep image relative with considering output directory in site format', function() {
|
||||
var LEXED = loadPage('IMAGES', {
|
||||
// GitHub repo ID
|
||||
repo: 'GitBookIO/javascript',
|
||||
|
||||
// Imaginary folder of markdown file
|
||||
dir: 'syntax',
|
||||
outdir: 'syntax'
|
||||
@@ -110,9 +104,6 @@ describe('Relative images', function() {
|
||||
|
||||
it('should keep image relative with considering output directory in page format', function() {
|
||||
var LEXED = loadPage('IMAGES', {
|
||||
// GitHub repo ID
|
||||
repo: 'GitBookIO/javascript',
|
||||
|
||||
// Imaginary folder of markdown file
|
||||
dir: 'syntax',
|
||||
outdir: './'
|
||||
|
||||
+10
-1
@@ -12,7 +12,7 @@ describe('Plugin validation', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Plugin list of names', function () {
|
||||
describe('Plugins list', function () {
|
||||
var firstDefault = _.first(Plugin.defaults);
|
||||
|
||||
it('should convert string to array', function() {
|
||||
@@ -27,6 +27,15 @@ describe('Plugin list of names', function () {
|
||||
it('should remove name starting with -', function() {
|
||||
assert(!_.contains(Plugin.normalizeNames(["-"+firstDefault]), firstDefault));
|
||||
});
|
||||
|
||||
it('should accept version', function() {
|
||||
var _name = "test@0.3.0,exercises@1.2.0,test2";
|
||||
var plugins = Plugin.normalizeList(_name);
|
||||
|
||||
assert(_.find(plugins, {'name': "test"}).version = "0.3.0");
|
||||
assert(_.find(plugins, {'name': "exercises"}).version = "1.2.0");
|
||||
assert(!_.find(plugins, {'name': "test2"}).version);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Plugin defaults loading', function () {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -31,21 +31,57 @@ define([
|
||||
return d.promise();
|
||||
}
|
||||
|
||||
$.fn.replaceText = function( search, replace, text_only ) {
|
||||
return this.each(function(){
|
||||
var node = this.firstChild,
|
||||
val,
|
||||
new_val,
|
||||
|
||||
// Elements to be removed at the end.
|
||||
remove = [];
|
||||
|
||||
// Only continue if firstChild exists.
|
||||
if ( node ) {
|
||||
|
||||
// Loop over all childNodes.
|
||||
do {
|
||||
|
||||
// Only process text nodes.
|
||||
if ( node.nodeType === 3 ) {
|
||||
|
||||
// The original node value.
|
||||
val = node.nodeValue;
|
||||
|
||||
// The new value.
|
||||
new_val = val.replace( search, replace );
|
||||
|
||||
// Only replace text if the new value is actually different!
|
||||
if ( new_val !== val ) {
|
||||
|
||||
if ( !text_only && /</.test( new_val ) ) {
|
||||
// The new value contains HTML, set it in a slower but far more
|
||||
// robust way.
|
||||
$(node).before( new_val );
|
||||
|
||||
// Don't remove the node yet, or the loop will lose its place.
|
||||
remove.push( node );
|
||||
} else {
|
||||
// The new value contains no HTML, so it can be set in this
|
||||
// very fast, simple way.
|
||||
node.nodeValue = new_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while ( node = node.nextSibling );
|
||||
}
|
||||
|
||||
// Time to remove those elements!
|
||||
remove.length && $(remove).remove();
|
||||
});
|
||||
};
|
||||
|
||||
var pregQuote = function( str ) {
|
||||
// http://kevin.vanzonneveld.net
|
||||
// + original by: booeyOH
|
||||
// + improved by: Ates Goral (http://magnetiq.com)
|
||||
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// + bugfixed by: Onno Marsman
|
||||
// * example 1: preg_quote("$40");
|
||||
// * returns 1: '\$40'
|
||||
// * example 2: preg_quote("*RRRING* Hello?");
|
||||
// * returns 2: '\*RRRING\* Hello\?'
|
||||
// * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
|
||||
// * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'
|
||||
|
||||
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
|
||||
};
|
||||
|
||||
@@ -58,48 +94,13 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
var matchText = function(node, regex, callback, excludeElements) {
|
||||
excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
|
||||
var child = node.firstChild;
|
||||
|
||||
if (!child) return;
|
||||
|
||||
do {
|
||||
switch (child.nodeType) {
|
||||
case 1:
|
||||
if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
|
||||
continue;
|
||||
}
|
||||
matchText(child, regex, callback, excludeElements);
|
||||
break;
|
||||
case 3:
|
||||
child.data.replace(regex, function(all) {
|
||||
var args = [].slice.call(arguments),
|
||||
offset = args[args.length - 2],
|
||||
newTextNode = child.splitText(offset);
|
||||
|
||||
newTextNode.data = newTextNode.data.substr(all.length);
|
||||
callback.apply(window, [child].concat(args));
|
||||
child = newTextNode;
|
||||
});
|
||||
break;
|
||||
}
|
||||
} while (child = child.nextSibling);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
var replaceTerm = function($el, term) {
|
||||
var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' );
|
||||
|
||||
matchText($el.get(0), r, function(node, match, offset) {
|
||||
var span = document.createElement("span");
|
||||
span.className = "glossary-term";
|
||||
span.textContent = match;
|
||||
span.setAttribute("data-glossary-term", term.id);
|
||||
span.setAttribute("title", term.description);
|
||||
node.parentNode.insertBefore(span, node.nextSibling);
|
||||
$el.find("*").replaceText(r, function(match) {
|
||||
return "<span class='glossary-term' data-glossary-term='"+term.id+"' title='"+term.description+"'>"+match+"</span>";
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var prepare = function() {
|
||||
|
||||
@@ -16,57 +16,123 @@
|
||||
}
|
||||
|
||||
.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal {
|
||||
color:@page-color-1;
|
||||
color: @page-color-1;
|
||||
|
||||
a {
|
||||
color: @page-link-color-1;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: @page-heading-color-1;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
border-color: @page-heading-border-color-1;
|
||||
}
|
||||
|
||||
h6 {
|
||||
color: @page-h6-color-1;
|
||||
}
|
||||
|
||||
hr {
|
||||
background-color: @page-hr-color-1;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-color: @page-blockquote-border-color-1;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
background: #fdf6e3;
|
||||
color: #657b83;
|
||||
border-color: darken(#fdf6e3, 15%);
|
||||
background: @page-pre-background-1;
|
||||
color: @page-pre-color-1;
|
||||
border-color: @page-pre-border-color-1;
|
||||
|
||||
@import "./highlight/sepia.less";
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: @page-highlight-background-1;
|
||||
}
|
||||
|
||||
table {
|
||||
th, td {
|
||||
border-color: darken(#fdf6e3, 25%);
|
||||
border-color: @page-table-header-border-color-1;
|
||||
}
|
||||
|
||||
tr {
|
||||
background: #fdf6e3;
|
||||
color: inherit;
|
||||
border-color: #444;
|
||||
color: @page-table-row-color-1;
|
||||
background-color: @page-table-row-background-1;
|
||||
border-color: @page-table-row-border-color-1;
|
||||
}
|
||||
|
||||
tr:nth-child(2n) {
|
||||
background-color: darken(#fdf6e3, 5%);
|
||||
background-color: @page-table-row-odd-background-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal {
|
||||
color:@page-color-2;
|
||||
color: @page-color-2;
|
||||
|
||||
a {
|
||||
color: @page-link-color-2;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: @page-heading-color-2;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
border-color: @page-heading-border-color-2;
|
||||
}
|
||||
|
||||
h6 {
|
||||
color: @page-h6-color-2;
|
||||
}
|
||||
|
||||
hr {
|
||||
background-color: @page-hr-color-2;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-color: @page-blockquote-border-color-2;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
background: black;
|
||||
color: #eaeaea;
|
||||
border-color: #000;
|
||||
color: @page-pre-color-2;
|
||||
background: @page-pre-background-2;
|
||||
border-color: @page-pre-border-color-2;
|
||||
|
||||
@import "./highlight/night.less";
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: @page-highlight-background-2;
|
||||
}
|
||||
|
||||
table {
|
||||
th, td {
|
||||
border-color: #444;
|
||||
border-color: @page-table-header-border-color-2;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: black;
|
||||
color: #eaeaea;
|
||||
border-color: #444;
|
||||
color: @page-table-row-color-2;
|
||||
background-color: @page-table-row-background-2;
|
||||
border-color: @page-table-row-border-color-2;
|
||||
}
|
||||
|
||||
tr:nth-child(2n) {
|
||||
background-color: #222;
|
||||
background-color: @page-table-row-odd-background-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
width: @sidebar-width;
|
||||
color: @sidebar-color;
|
||||
background: @sidebar-background;
|
||||
border-right: 1px solid @sidebar-border;
|
||||
border-right: @sidebar-border-right;
|
||||
|
||||
.transition(left @sidebar-transition-duration ease);
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
.book-summary {
|
||||
color: @sidebar-color-1;
|
||||
background: @sidebar-background-1;
|
||||
border-right: @sidebar-border-right-1;
|
||||
|
||||
.book-search {
|
||||
background: @sidebar-search-background-1;
|
||||
@@ -179,11 +180,13 @@
|
||||
a, span {
|
||||
color: @sidebar-link-color-1;
|
||||
background: @sidebar-link-background-1;
|
||||
font-weight: @sidebar-link-weight-1;
|
||||
}
|
||||
|
||||
&.active > a, a:hover {
|
||||
color: @sidebar-link-hover-color-1;
|
||||
background: @sidebar-link-hover-background-1;
|
||||
font-weight: @sidebar-link-hover-weight-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +200,7 @@
|
||||
.book-summary {
|
||||
color: @sidebar-color-2;
|
||||
background: @sidebar-background-2;
|
||||
border-right: @sidebar-border-right-2;
|
||||
|
||||
.book-search {
|
||||
background: @sidebar-search-background-2;
|
||||
@@ -224,11 +228,13 @@
|
||||
a, span {
|
||||
color: @sidebar-link-color-2;
|
||||
background: @sidebar-link-background-2;
|
||||
font-weight: @sidebar-link-weight-2;
|
||||
}
|
||||
|
||||
&.active > a, a:hover {
|
||||
color: @sidebar-link-hover-color-2;
|
||||
background: @sidebar-link-hover-background-2;
|
||||
font-weight: @sidebar-link-hover-weight-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
@sidebar-breakpoint: 600px;
|
||||
@sidebar-color: hsl(207, 15%, 25%);
|
||||
@sidebar-background: #fafafa;
|
||||
@sidebar-border: @header-border;
|
||||
@sidebar-border-right: 1px solid @header-border;
|
||||
|
||||
@sidebar-nested-padding: 20px;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
@sidebar-search-input-background: transparent;
|
||||
@sidebar-search-input-border-color: transparent;
|
||||
|
||||
@sidebar-divider-color: @sidebar-border;
|
||||
@sidebar-divider-color: @header-border;
|
||||
|
||||
@sidebar-link-color: @sidebar-color;
|
||||
@sidebar-link-background: transparent;
|
||||
@@ -103,12 +103,12 @@
|
||||
@FontPath: '@{staticPath}/fonts';
|
||||
@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;
|
||||
@default-font-size: @l-font-size;
|
||||
@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;
|
||||
@default-font-size: @l-font-size;
|
||||
|
||||
/*
|
||||
,--------.,--.
|
||||
@@ -123,9 +123,9 @@
|
||||
@header-background-1: transparent;
|
||||
@header-background-2: transparent;
|
||||
@header-button-color-1: #AFA790;
|
||||
@header-button-color-2: #7e888b;
|
||||
@header-button-color-2: hsl(230, 17%, 28%);
|
||||
@header-button-hover-color-1: #73553C;
|
||||
@header-button-hover-color-2: #C9C9C9;
|
||||
@header-button-hover-color-2: hsl(60, 100%, 98%);
|
||||
@header-button-hover-background-1: none;
|
||||
@header-button-hover-background-2: none;
|
||||
@header-dropdown-background-1: @sidebar-background-1;
|
||||
@@ -133,14 +133,16 @@
|
||||
|
||||
// Body
|
||||
@body-background-1: #F3EACB;
|
||||
@body-background-2: #1d1f21;
|
||||
@body-background-2: hsl(228, 21%, 14%);
|
||||
|
||||
// Sidebar
|
||||
@sidebar-transition-duration: 250ms;
|
||||
@sidebar-color-1: #AFA790;
|
||||
@sidebar-color-2: hsl(207, 15%, 80%);
|
||||
@sidebar-color-2: hsl(226, 20%, 78%);
|
||||
@sidebar-background-1: #111;
|
||||
@sidebar-background-2: #111;
|
||||
@sidebar-background-2: hsl(229, 20%, 22%);
|
||||
@sidebar-border-right-1: @sidebar-border-right;
|
||||
@sidebar-border-right-2: none;
|
||||
|
||||
@sidebar-search-background-1: transparent;
|
||||
@sidebar-search-background-2: transparent;
|
||||
@@ -148,51 +150,92 @@
|
||||
@sidebar-search-input-border-color-2: transparent;
|
||||
|
||||
@sidebar-divider-color-1: @sidebar-divider-color;
|
||||
@sidebar-divider-color-2: #1d1f21;
|
||||
@sidebar-divider-color-2: hsl(230, 19%, 19%);
|
||||
|
||||
@sidebar-link-color-1: #877F6A;
|
||||
@sidebar-link-color-2: hsl(207, 15%, 50%);
|
||||
@sidebar-link-color-2: hsl(226, 22%, 80%);
|
||||
@sidebar-link-background-1: transparent;
|
||||
@sidebar-link-background-2: transparent;
|
||||
@sidebar-link-weight-1: normal;
|
||||
@sidebar-link-weight-2: 600;
|
||||
@sidebar-link-hover-color-1: #704214;
|
||||
@sidebar-link-hover-color-2: hsl(207, 100%, 50%);
|
||||
@sidebar-link-hover-color-2: hsl(240, 5%, 96%);
|
||||
@sidebar-link-hover-background-1: transparent;
|
||||
@sidebar-link-hover-background-2: transparent;
|
||||
@sidebar-link-hover-background-2: hsl(233, 19%, 18%);
|
||||
@sidebar-link-hover-weight-1: normal;
|
||||
@sidebar-link-hover-weight-2: 600;
|
||||
|
||||
@sidebar-icon-color-1: hsl(120, 60%, 50%);
|
||||
@sidebar-icon-color-2: @sidebar-icon-color-1;
|
||||
@sidebar-link-completed-1: @sidebar-link-color-1;
|
||||
@sidebar-link-completed-2: @sidebar-link-color-2;
|
||||
@sidebar-link-completed-2: hsl(227, 13%, 44%);
|
||||
@sidebar-link-completed-weight-1: normal;
|
||||
@sidebar-link-completed-weight-2: normal;
|
||||
@sidebar-link-completed-weight-2: 600;
|
||||
|
||||
// Dropdown
|
||||
@dropdown-divider-color-1: @sidebar-divider-color-1;
|
||||
@dropdown-background-1: @sidebar-background-1;
|
||||
@dropdown-button-color-1: @header-button-color-1;
|
||||
@dropdown-border-color-1: @sidebar-divider-color-1;
|
||||
@dropdown-button-hover-color-1: @header-button-hover-color-1;
|
||||
|
||||
@dropdown-divider-color-2: @sidebar-divider-color-2;
|
||||
@dropdown-background-2: @sidebar-background-2;
|
||||
@dropdown-button-color-2: @header-button-color-2;
|
||||
@dropdown-border-color-1: @sidebar-divider-color-1;
|
||||
@dropdown-border-color-2: @sidebar-divider-color-2;
|
||||
@dropdown-button-hover-color-2: @header-button-hover-color-2;
|
||||
@dropdown-background-1: @sidebar-background-1;
|
||||
@dropdown-background-2: @sidebar-background-2;
|
||||
|
||||
@dropdown-button-color-1: @header-button-color-1;
|
||||
@dropdown-button-color-2: hsl(228, 13%, 44%);
|
||||
@dropdown-button-hover-color-1: @header-button-hover-color-1;
|
||||
@dropdown-button-hover-color-2: hsl(240, 5%, 96%);
|
||||
|
||||
// Page
|
||||
@page-color-1: #704214;
|
||||
@page-color-2: #a4b1b1;
|
||||
@page-background-1: #F3EACB;
|
||||
@page-background-2: #1d1f21;
|
||||
@page-color-1: #704214;
|
||||
@page-color-2: hsl(214, 29%, 80%);
|
||||
@page-background-1: @body-background-1;
|
||||
@page-background-2: @body-background-2;
|
||||
|
||||
@bar-background-1: #F3EACB;
|
||||
@bar-background-2: #1d1f21;
|
||||
@page-link-color-1: inherit;
|
||||
@page-link-color-2: hsl(193, 61%, 53%);
|
||||
|
||||
@page-heading-color-1: inherit;
|
||||
@page-heading-color-2: hsl(60, 100%, 99%);
|
||||
@page-heading-border-color-1: inherit;
|
||||
@page-heading-border-color-2: hsl(230, 17%, 26%);
|
||||
@page-h6-color-1: inherit;
|
||||
@page-h6-color-2: hsl(230, 17%, 26%);
|
||||
|
||||
@page-hr-color-1: inherit;
|
||||
@page-hr-color-2: hsl(230, 17%, 26%);
|
||||
|
||||
@page-blockquote-border-color-1: inherit;
|
||||
@page-blockquote-border-color-2: hsl(230, 17%, 26%);
|
||||
|
||||
@page-pre-color-1: #657b83;
|
||||
@page-pre-color-2: hsl(206, 43%, 73%);
|
||||
@page-pre-background-1: #fdf6e3;
|
||||
@page-pre-background-2: hsl(229, 20%, 22%);
|
||||
@page-pre-border-color-1: darken(#fdf6e3, 15%);
|
||||
@page-pre-border-color-2: hsl(229, 20%, 22%);
|
||||
@page-highlight-background-1: inherit;
|
||||
@page-highlight-background-2: hsl(233, 18%, 19%);
|
||||
|
||||
@page-table-header-border-color-1: darken(#fdf6e3, 25%);
|
||||
@page-table-header-border-color-2: hsl(230, 17%, 28%);
|
||||
@page-table-row-border-color-1: #444;
|
||||
@page-table-row-border-color-2: hsl(230, 17%, 28%);
|
||||
@page-table-row-color-1: inherit;
|
||||
@page-table-row-color-2: hsl(216, 24%, 77%);
|
||||
@page-table-row-background-1: #fdf6e3;
|
||||
@page-table-row-background-2: hsl(229, 19%, 22%);
|
||||
@page-table-row-odd-background-1: darken(#fdf6e3, 5%);
|
||||
@page-table-row-odd-background-2: hsl(229, 17%, 25%);
|
||||
|
||||
// Page Bar
|
||||
@bar-background-1: @page-background-1;
|
||||
@bar-background-2: @page-background-2;
|
||||
|
||||
// Navigation
|
||||
@navigation-color-1: @header-button-color-1;
|
||||
@navigation-color-2: @header-button-color-2;
|
||||
@navigation-color-2: hsl(224, 19%, 27%);
|
||||
@navigation-hover-color-1: @header-button-hover-color-1;
|
||||
@navigation-hover-color-2: @header-button-hover-color-2;
|
||||
@navigation-hover-color-2: hsl(60, 100%, 98%);
|
||||
|
||||
// Basics of a navbar
|
||||
@navbar-default-border-1: #d5d5d5;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{% extends "./layout.html" %}
|
||||
|
||||
{% block title %}Glossary | {{ title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page page-toc">
|
||||
<h1>Glossary</h1>
|
||||
{% for item in glossaryIndex %}
|
||||
<section class="normal glossary" id="{{ item.id }}">
|
||||
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
|
||||
<p>{{ item.description }}</p>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en-US" {% block htmlTag %}{% endblock %}>
|
||||
{{ htmlSnippet("html:start")|default("") }}
|
||||
<head>
|
||||
{{ htmlSnippet("head:start")|default("") }}
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="description" content="{% block description %}{% endblock %}">
|
||||
<meta name="generator" content="GitBook {{ gitbook.version }}">
|
||||
{% block head %}{% endblock %}
|
||||
{{ htmlSnippet("head:end")|default("") }}
|
||||
</head>
|
||||
<body>
|
||||
{{ htmlSnippet("body:start")|default("") }}
|
||||
{% block style %}{% endblock %}
|
||||
{% block content %}{% endblock %}
|
||||
{% block javascript %}{% endblock %}
|
||||
{{ htmlSnippet("body:end")|default("") }}
|
||||
</body>
|
||||
{{ htmlSnippet("html:end")|default("") }}
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "../layout.html" %}
|
||||
{% extends "./layout.html" %}
|
||||
|
||||
{% block title %}{{ progress.current.title }} | {{ title }}{% endblock %}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="page">
|
||||
<h1 class="book-chapter book-chapter-{{ progress.current.level|lvl }}">{{ progress.current.title }}</h1>
|
||||
{% for section in content %}
|
||||
<section class="{{ section.type }}" id="section-{{ section.id }}">
|
||||
<div class="{{ section.type }}" id="section-{{ section.id }}">
|
||||
{% if section.type == "normal" %}
|
||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
||||
{% elif section.type == "exercise" %}
|
||||
@@ -25,7 +25,7 @@
|
||||
{% elif section.type == "quiz" %}
|
||||
{% include "./includes/quiz.html" with {section: section} %}
|
||||
{% endif %}
|
||||
</section>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "../layout.html" %}
|
||||
{% extends "./layout.html" %}
|
||||
|
||||
{% block title %}Table of Contents | {{ title }}{% endblock %}
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
<h1>Table of Contents</h1>
|
||||
<ol>
|
||||
{{ articles(summary.chapters) }}
|
||||
|
||||
{% if glossary.length > 0 %}
|
||||
<li><a href="{{ basePath }}/GLOSSARY.html">Glossary</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<head>
|
||||
{{ htmlSnippet("head:start")|default("") }}
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=11; IE=10; IE=9; IE=8; IE=7; IE=EDGE" />
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="description" content="{% block description %}{% endblock %}">
|
||||
@@ -14,6 +15,9 @@
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="{{ staticBase }}/images/apple-touch-icon-precomposed-152.png">
|
||||
<link rel="shortcut icon" href="{{ staticBase }}/images/favicon.ico" type="image/x-icon">
|
||||
{% if options.isbn %}
|
||||
<meta name="identifier" content="{{ options.isbn }}" scheme="ISBN">
|
||||
{% endif %}
|
||||
{% block head %}{% endblock %}
|
||||
{{ htmlSnippet("head:end")|default("") }}
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user