mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-27 12:39:08 +00:00
Compare commits
38 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 |
@@ -15,3 +15,4 @@ Contributors
|
||||
------------
|
||||
|
||||
- Nijiko Yonskai
|
||||
- Herman Starikov
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ module.exports = function (grunt) {
|
||||
requirejs: {
|
||||
compile: {
|
||||
options: {
|
||||
name: "app",
|
||||
name: "gitbook",
|
||||
baseUrl: "theme/javascript/",
|
||||
out: "theme/assets/app.js",
|
||||
preserveLicenseComments: false,
|
||||
|
||||
@@ -186,7 +186,7 @@ Apache License
|
||||
same "printed page" as the copyright notice for easier
|
||||
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");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -198,4 +198,4 @@ Apache License
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
limitations under the License.
|
||||
|
||||
@@ -36,7 +36,8 @@ Options for commands `build` and `serve` are:
|
||||
-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
|
||||
--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)
|
||||
@@ -133,3 +134,16 @@ You can see a complete example with the [Learn Git](https://github.com/GitbookIO
|
||||
#### 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`)
|
||||
|
||||
#### 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 Q = require('q');
|
||||
var _ = require('lodash');
|
||||
var fs = require('fs');
|
||||
|
||||
var utils = require('./utils');
|
||||
|
||||
var generate = require("../lib/generate");
|
||||
var parse = require("../lib/parse");
|
||||
var fs = require('../lib/generate/fs');
|
||||
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) {
|
||||
return function(dir, options) {
|
||||
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 ...');
|
||||
// Get repo's URL
|
||||
@@ -33,7 +52,8 @@ var makeBuildFunc = function(converter) {
|
||||
github: options.github || repoID,
|
||||
githubHost: options.githubHost,
|
||||
generator: options.format,
|
||||
theme: options.theme
|
||||
plugins: options.plugins,
|
||||
pluginsConfig: pluginsConfig
|
||||
})
|
||||
);
|
||||
})
|
||||
@@ -42,9 +62,10 @@ var makeBuildFunc = function(converter) {
|
||||
return output;
|
||||
}, utils.logError);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
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
|
||||
.version(pkg.version);
|
||||
|
||||
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('-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]'))
|
||||
build.command(prog.command('build [source_dir]'))
|
||||
.description('Build a gitbook from a directory')
|
||||
.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')
|
||||
.option('-p, --port <port>', 'Port for server to listen on', 4000)
|
||||
.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')
|
||||
.option('-pf, --paperformat <format>', 'PDF paper format (default is A4): "5in*7.5in", "10cm*20cm", "A4", "Letter"')
|
||||
.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')
|
||||
.option('-c, --cover <path>', 'Cover image, default is cover.png if exists')
|
||||
.action(function(dir, options) {
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
var _ = require("lodash");
|
||||
var path = require("path");
|
||||
var Q = require("q");
|
||||
var fs = require("./fs");
|
||||
|
||||
var Plugin = require("./plugin");
|
||||
|
||||
var BaseGenerator = function(options) {
|
||||
this.options = options;
|
||||
|
||||
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) {
|
||||
|
||||
+13
-3
@@ -6,6 +6,7 @@ var tmp = require('tmp');
|
||||
|
||||
var fs = require("./fs");
|
||||
var parse = require("../parse");
|
||||
var Plugin = require("./plugin");
|
||||
|
||||
var generators = {
|
||||
"site": require("./site"),
|
||||
@@ -42,7 +43,11 @@ var generate = function(options) {
|
||||
githubHost: 'https://github.com/',
|
||||
|
||||
// Theming
|
||||
theme: path.resolve(__dirname, '../../theme')
|
||||
theme: path.resolve(__dirname, '../../theme'),
|
||||
|
||||
// Plugins
|
||||
plugins: [],
|
||||
pluginsConfig: {}
|
||||
});
|
||||
|
||||
if (!options.input) {
|
||||
@@ -70,9 +75,10 @@ var generate = function(options) {
|
||||
})
|
||||
})
|
||||
|
||||
// Create the generator
|
||||
// Create the generator and load plugins
|
||||
.then(function() {
|
||||
generator = new generators[options.generator](options);
|
||||
return generator.loadPlugins();
|
||||
})
|
||||
|
||||
// Detect multi-languages book
|
||||
@@ -163,6 +169,9 @@ var generate = function(options) {
|
||||
// Finish gneration
|
||||
.then(function() {
|
||||
return generator.finish();
|
||||
})
|
||||
.then(function() {
|
||||
return generator.callHook("finish");
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -234,5 +243,6 @@ var generateFile = function(options) {
|
||||
module.exports = {
|
||||
generators: generators,
|
||||
folder: generate,
|
||||
file: generateFile
|
||||
file: generateFile,
|
||||
Plugin: Plugin
|
||||
};
|
||||
|
||||
@@ -25,14 +25,18 @@ swig.setFilter('code', function(code, lang) {
|
||||
var Generator = function() {
|
||||
BaseGenerator.apply(this, arguments);
|
||||
|
||||
// Load base template
|
||||
this.template = swig.compileFile(path.resolve(this.options.theme, 'templates/page.html'));
|
||||
|
||||
// List of pages content
|
||||
this.pages = {};
|
||||
};
|
||||
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) {
|
||||
var that = this;
|
||||
var json = {
|
||||
@@ -46,6 +50,7 @@ Generator.prototype.convertFile = function(content, input) {
|
||||
repo: that.options.githubId,
|
||||
dir: path.dirname(input) || '/',
|
||||
outdir: './',
|
||||
singleFile: true
|
||||
});
|
||||
})
|
||||
.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.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);
|
||||
|
||||
// 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
|
||||
Generator.prototype._writeTemplate = function(tpl, options, output) {
|
||||
@@ -54,7 +69,10 @@ Generator.prototype._writeTemplate = function(tpl, options, output) {
|
||||
githubHost: that.options.githubHost,
|
||||
|
||||
summary: that.options.summary,
|
||||
allNavigation: that.options.navigation
|
||||
allNavigation: that.options.navigation,
|
||||
|
||||
plugins: that.plugins,
|
||||
pluginsConfig: JSON.stringify(that.options.pluginsConfig)
|
||||
}, options));
|
||||
})
|
||||
.then(function(html) {
|
||||
@@ -134,10 +152,19 @@ Generator.prototype.langsIndex = function(langs) {
|
||||
Generator.prototype.copyAssets = function() {
|
||||
var that = this;
|
||||
|
||||
// Copy gitbook assets
|
||||
return fs.copy(
|
||||
path.join(that.options.theme, "assets"),
|
||||
path.join(that.options.output, "gitbook")
|
||||
);
|
||||
)
|
||||
// Copy plugins assets
|
||||
.then(function() {
|
||||
return Q.all(
|
||||
_.map(that.plugins.list, function(plugin) {
|
||||
return plugin.copyAssets(path.join(that.options.output, "gitbook/plugins/", plugin.name))
|
||||
})
|
||||
);
|
||||
})
|
||||
};
|
||||
|
||||
// Dump search index to disk
|
||||
|
||||
+24
-11
@@ -1,5 +1,7 @@
|
||||
var url = require('url');
|
||||
var inherits = require('util').inherits;
|
||||
var links = require('../utils').links;
|
||||
|
||||
|
||||
var path = require('path');
|
||||
|
||||
@@ -38,23 +40,38 @@ GitBookRenderer.prototype._unsanitized = function(href) {
|
||||
};
|
||||
|
||||
GitBookRenderer.prototype.link = function(href, title, text) {
|
||||
// Our "fixed" href
|
||||
var _href = href;
|
||||
|
||||
// Don't build if it looks malicious
|
||||
if (this.options.sanitize && this._unsanitized(href)) {
|
||||
return '';
|
||||
return text;
|
||||
}
|
||||
|
||||
// Parsed version of the url
|
||||
var parsed = url.parse(href);
|
||||
|
||||
var o = this._extra_options;
|
||||
|
||||
// Relative link, rewrite it to point to github repo
|
||||
if(!parsed.protocol && parsed.path && parsed.path[0] != '/' && o && o.repo && o.dir) {
|
||||
href = url.resolve('https://github.com/' + o.repo + '/blob/', [o.dir, href].join("/"));
|
||||
parsed = url.parse(href);
|
||||
if(links.isRelative(_href)) {
|
||||
if (path.extname(_href) == ".md") {
|
||||
_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
|
||||
var out = '<a href="' + parsed.href + '"';
|
||||
var out = '<a href="' + _href + '"';
|
||||
// Title if no null
|
||||
if (title) {
|
||||
out += ' title="' + title + '"';
|
||||
@@ -78,15 +95,11 @@ GitBookRenderer.prototype.image = function(href, title, text) {
|
||||
var o = this._extra_options;
|
||||
|
||||
// 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) {
|
||||
// o.dir: directory parent of the file currently in rendering process
|
||||
// o.outdir: directory parent from the html output
|
||||
|
||||
// Absolute file in source
|
||||
_href = path.join(o.dir, _href);
|
||||
|
||||
// make it relative to output
|
||||
_href = path.relative(o.outdir, _href);
|
||||
_href = links.toAbsolute(_href, o.dir, o.outdir);
|
||||
}
|
||||
|
||||
return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
module.exports = {
|
||||
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
|
||||
};
|
||||
+7
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gitbook",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.1",
|
||||
"homepage": "http://www.gitbook.io/",
|
||||
"description": "Library and cmd utility to generate GitBooks",
|
||||
"main": "lib/index.js",
|
||||
@@ -16,7 +16,12 @@
|
||||
"commander": "2.2.0",
|
||||
"fs-extra": "0.8.1",
|
||||
"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": {
|
||||
"mocha": "1.18.2",
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
# Nice course
|
||||
|
||||
Check out this other chapter [Test](test.md)
|
||||
|
||||
Check out this other chapter [Test](../before.md)
|
||||
+31
-1
@@ -84,11 +84,41 @@ describe('Relative links', function() {
|
||||
repo: 'GitBookIO/javascript',
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
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() {
|
||||
|
||||
@@ -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,7 +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>```
|
||||
|
||||
#### Warning! Theme system is going to change before version 1.0.0
|
||||
+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([
|
||||
"jQuery",
|
||||
"utils/execute",
|
||||
"utils/analytic",
|
||||
"core/events",
|
||||
"core/state"
|
||||
], function($, execute, analytic, state){
|
||||
], function($, execute, events, state){
|
||||
// Bind an exercise
|
||||
var prepareExercise = function($exercise) {
|
||||
var codeSolution = $exercise.find(".code-solution").text();
|
||||
@@ -19,7 +19,7 @@ define([
|
||||
$exercise.find(".action-submit").click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
analytic.track("exercise.submit", {type: "code"});
|
||||
events.trigger("exercise.submit", {type: "code"});
|
||||
|
||||
execute("javascript", editor.getValue(), codeValidation, codeContext, function(err, result) {
|
||||
$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,12 +1,12 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/analytic",
|
||||
"core/events",
|
||||
"core/state",
|
||||
"core/search",
|
||||
"core/progress",
|
||||
"core/exercise",
|
||||
"core/quiz"
|
||||
], function($, analytic, state, search, progress, exercises, quiz) {
|
||||
], function($, events, state, search, progress, exercises, quiz) {
|
||||
var prev, next;
|
||||
var githubCountStars, githubCountWatch;
|
||||
|
||||
@@ -110,7 +110,7 @@ define([
|
||||
}
|
||||
|
||||
// Send to mixpanel
|
||||
analytic.track("page.view");
|
||||
events.trigger("page.change");
|
||||
};
|
||||
|
||||
var handlePagination = function (e) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/execute",
|
||||
"utils/analytic",
|
||||
"core/events",
|
||||
"core/state"
|
||||
], function($, execute, analytic, state){
|
||||
], function($, execute, events, state){
|
||||
// Bind an exercise
|
||||
var prepareQuiz = function($quiz) {
|
||||
|
||||
@@ -14,7 +14,7 @@ define([
|
||||
// Submit: test code
|
||||
$quiz.find(".action-submit").click(function(e) {
|
||||
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(".alert-success,.alert-danger").addClass("hidden");
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
require([
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/storage",
|
||||
"utils/analytic",
|
||||
"utils/sharing",
|
||||
|
||||
"core/events",
|
||||
"core/font-settings",
|
||||
"core/state",
|
||||
"core/keyboard",
|
||||
"core/navigation",
|
||||
"core/progress",
|
||||
"core/sidebar",
|
||||
"core/search"
|
||||
], function($, storage, analytic, sharing, state, keyboard, navigation, progress, sidebar, search){
|
||||
$(document).ready(function() {
|
||||
], function($, storage, sharing, events, fontSettings, state, keyboard, navigation, progress, sidebar, search){
|
||||
var start = function(config) {
|
||||
var $book;
|
||||
$book = state.$book;
|
||||
|
||||
@@ -34,5 +35,15 @@ require([
|
||||
|
||||
// Init navigation
|
||||
navigation.init();
|
||||
});
|
||||
|
||||
//Init font settings
|
||||
fontSettings.init();
|
||||
|
||||
events.trigger("start", config);
|
||||
}
|
||||
|
||||
return {
|
||||
start: start,
|
||||
events: events
|
||||
};
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
define([
|
||||
"lodash"
|
||||
], function(_) {
|
||||
var isAvailable = function() {
|
||||
return (
|
||||
typeof mixpanel !== "undefined" &&
|
||||
typeof mixpanel.track === "function"
|
||||
);
|
||||
};
|
||||
|
||||
var track = function(e, data, t) {
|
||||
if (!isAvailable()) {
|
||||
console.warn("tracking not available!");
|
||||
t = t || 500;
|
||||
setTimeout(function() {
|
||||
console.log(" -> retest tracking");
|
||||
track(e, data, t*2);
|
||||
}, t);
|
||||
return;
|
||||
}
|
||||
console.log("track", e);
|
||||
mixpanel.track(e, _.extend(data || {}, {
|
||||
'domain': window.location.host
|
||||
}));
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
mixpanel.init("01eb2b950ae09a5fdb15a98dcc5ff20e");
|
||||
track("page.start");
|
||||
}, 0);
|
||||
|
||||
return {
|
||||
isAvailable: isAvailable,
|
||||
track: track
|
||||
};
|
||||
});
|
||||
@@ -6,6 +6,7 @@
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
|
||||
color: @page-color;
|
||||
background: @body-background;
|
||||
.transition(left 0.5s ease);
|
||||
|
||||
@@ -23,7 +24,6 @@
|
||||
outline: none;
|
||||
|
||||
.page-inner {
|
||||
font-family: @font-family-serif;
|
||||
max-width: 800px;
|
||||
margin: 0px auto;
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
background: @page-background;
|
||||
border-radius: 2px;
|
||||
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
@@ -57,6 +55,28 @@
|
||||
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 {
|
||||
@@ -72,4 +92,30 @@
|
||||
.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;
|
||||
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
@@ -24,6 +24,7 @@
|
||||
text-transform: uppercase;
|
||||
line-height: @header-height;
|
||||
.box-shadow(none) !important;
|
||||
position:relative;
|
||||
|
||||
&:hover {
|
||||
position: relative;
|
||||
@@ -64,4 +65,30 @@
|
||||
.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 */
|
||||
.hljs-comment {
|
||||
@@ -87,4 +87,4 @@
|
||||
.xml .css,
|
||||
.xml .hljs-cdata {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
padding: 25px;
|
||||
padding-top: 15px;
|
||||
background-color: white;
|
||||
|
||||
color:@page-color;
|
||||
|
||||
& > *:first-child {
|
||||
margin-top: 0 !important; }
|
||||
@@ -52,12 +57,12 @@
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
color: black; }
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #eee;
|
||||
color: black; }
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18px; }
|
||||
@@ -69,7 +74,6 @@
|
||||
font-size: 14px; }
|
||||
|
||||
h6 {
|
||||
color: #777777;
|
||||
font-size: 14px; }
|
||||
|
||||
p, blockquote, ul, ol, dl, table, pre {
|
||||
|
||||
@@ -42,4 +42,14 @@
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
.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;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
z-index: 10;
|
||||
|
||||
.bar {
|
||||
height: @bar-height;
|
||||
@@ -81,4 +80,36 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.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/header.less";
|
||||
@import "book/summary.less";
|
||||
@import "book/font-settings.less";
|
||||
@import "book/body.less";
|
||||
@import "book/exercise.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 */
|
||||
.hljs-comment,
|
||||
@@ -87,4 +87,4 @@
|
||||
.xml .css,
|
||||
.xml .hljs-cdata {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
@sidebar-link-completed-weight: normal;
|
||||
|
||||
// Page
|
||||
@page-color: black;
|
||||
@page-background: white;
|
||||
|
||||
// Progress Bar
|
||||
@@ -79,5 +80,94 @@
|
||||
@font-family-sans: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
@font-family-base: @font-family-serif;
|
||||
|
||||
|
||||
@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;
|
||||
|
||||
/*
|
||||
,--------.,--.
|
||||
'--. .--'| ,---. ,---. ,--,--,--. ,---. ,---. .--.
|
||||
| | | .-. || .-. :| || .-. :( .-' '--'
|
||||
| | | | | |\ --.| | | |\ --..-' `).--.
|
||||
`--' `--' `--' `----'`--`--`--' `----'`----' '--'
|
||||
*/
|
||||
// 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 %}
|
||||
<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>
|
||||
<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 -->
|
||||
<a href="#" target="_blank" class="btn pull-right" data-sharing="google-plus"><i class="fa fa-google-plus"></i></a>
|
||||
|
||||
@@ -40,9 +40,6 @@
|
||||
{% endblock %}
|
||||
{% block content %}{% endblock %}
|
||||
{% block javascript %}
|
||||
<script type="text/javascript">(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||[]);
|
||||
</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="{{ staticBase }}/jsrepl/jsrepl.js" id="jsrepl-script"></script>
|
||||
|
||||
@@ -77,9 +77,11 @@
|
||||
<h1>{{ item.title }}</h1>
|
||||
</article>
|
||||
|
||||
{% if pages[item.path] %}
|
||||
<article>
|
||||
{{ articleContent(pages[item.path].content) }}
|
||||
</article>
|
||||
{% endif %}
|
||||
|
||||
{% if item.articles.length > 0 %}
|
||||
{% for article in item.articles %}
|
||||
|
||||
@@ -35,3 +35,31 @@
|
||||
</div>
|
||||
</div>
|
||||
{% 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