Compare commits

...

48 Commits

Author SHA1 Message Date
Aaron O'Mullan b9360de3e3 Bump version to 0.6.2 2014-07-30 00:22:49 -07:00
Aaron O'Mullan 9f241457bb Fix minor issues with new plugin additions 2014-07-29 23:45:54 -07:00
Aaron O'Mullan 60a7c28e66 Support generating a plugin's book info dynamically 2014-07-29 21:50:26 -07:00
Samy Pessé 5dff9b795e Fix #345: Improve navigation on dark theme 2014-07-29 21:33:47 -07:00
Aaron O'Mullan 0134677e0e Improve path normalization when parsing SUMMARY.md 2014-07-29 20:49:11 -07:00
Aaron O'Mullan 39ef4fa199 Add invalid paths in SUMMARY.md fixture
To test for correct path normalization
2014-07-29 20:46:14 -07:00
Samy Pessé b507a30301 Bump version to 0.6.1 2014-07-23 16:49:57 -07:00
Samy Pessé 539c2d0c57 Update plugin-mathjax@0.0.4 2014-07-23 16:28:38 -07:00
Samy Pessé aa6f3530f9 Fix readme spacing 2014-07-22 23:28:13 -07:00
Samy Pessé 98057af219 Merge pull request #372 from justanotheranonymoususer/patch-1
Update summary.html (fixed an HTML typo)
2014-07-20 14:04:12 -07:00
justanotheranonymoususer bb48c8233c Update summary.html 2014-07-20 23:57:56 +03:00
Aaron O'Mullan 8f14db64df Merge pull request #370 from nightwing/patch-1
Add keyboard shortcut for submitting exercise
2014-07-15 21:33:58 -07:00
Harutyun Amirjanyan 37d40dc66c Add keyboard shortcut for submitting exercise 2014-07-16 08:07:22 +04:00
Samy Pessé 6c96680cca Merge pull request #366 from shaform/ignore
Ignore config files by default in fs.list
2014-07-14 10:08:29 -07:00
Shaform 4e475857d5 Ignore config files by default in fs.list 2014-07-13 08:40:23 -07:00
Samy Pessé f8ff0453dd Merge pull request #359 from jcouyang/patch-1
add jsbin embedded plugin
2014-07-12 07:02:18 -07:00
Samy Pessé 3cc5c47535 Bump version to 0.6.0 2014-07-12 23:28:07 +02:00
Samy Pessé a2046814b4 Change command "git:push" to "publish" 2014-07-12 23:25:40 +02:00
Samy Pessé 82f814fdbd Fix #303: generate header id the same as github 2014-07-12 23:23:03 +02:00
Jichao Ouyang cd382dc8fc add jsbin embedded support 2014-07-12 21:42:52 +08:00
Samy Pessé 3842e5bf4a Merge pull request #358 from GitbookIO/featureplatform
Add base command git:push and git:remote
2014-07-11 17:42:16 -07:00
Samy Pessé f05b138fd6 Add base command git:push and git:remote 2014-07-12 09:23:15 +02:00
Samy Pessé 1b87cec893 Merge pull request #266 from shaform/ref_links
Add reference links support
2014-07-11 17:20:43 -07:00
Samy Pessé 4a894b1e18 Merge pull request #268 from rlmv/master
Fix page.path for plugins
2014-07-11 17:19:26 -07:00
Samy Pessé c7c98009e7 Merge pull request #347 from rlmv/custom_links
Add custom links to TOC
2014-07-11 17:15:37 -07:00
Samy Pessé 356322e0ed Merge pull request #353 from citizenmatt/active_page
Highlight active page in summary
2014-07-11 17:14:36 -07:00
Samy Pessé 7a47049367 Merge pull request #354 from citizenmatt/summary_hooks
Plugin hooks for summary data
2014-07-11 17:13:40 -07:00
Samy Pessé a9f473260c Merge pull request #356 from GitbookIO/feature/includes
Support importing code snippets
2014-07-10 17:59:34 -07:00
Aaron O'Mullan d16577e8bf Add tests for includes 2014-07-10 17:49:50 +02:00
Aaron O'Mullan 15b4053d6b Support code includes for exercises 2014-07-10 17:30:12 +02:00
Aaron O'Mullan 925a9b1388 Support importing code snippets
Allowing to keep code in separate files, which can be cleaner in a
quite a few scenarios
2014-07-11 01:22:07 +02:00
Matt Ellis fc942fdeca Hooks for summary data 2014-07-09 17:17:40 +01:00
Matt Ellis 75a6ecbf52 Highlight active page in summary 2014-07-09 16:06:55 +01:00
Aaron O'Mullan 520045441b Merge pull request #352 from citizenmatt/links_with_fragments
Convert links with fragments from md to html
2014-07-08 21:45:01 +02:00
Matt Ellis 00c3e966d3 Convert links with fragments from md to html 2014-07-08 16:25:39 +01:00
Samy Pessé 8b6ebe86b8 Merge pull request #348 from rlmv/anchors_readme
Add anchor plugin to README
2014-07-06 17:12:57 +02:00
Bo Marchman d5bd3453e1 add heading anchors plugin to readme 2014-07-02 23:49:07 -04:00
Bo Marchman ddacbbe73b update readme with custom links 2014-07-02 23:40:57 -04:00
Bo Marchman f7d52f0eff Add custom link capability
Users can add custom links at the top of the table of contents by
adding a links.custom object to book.json. Issue #304
2014-07-02 23:38:14 -04:00
Robert Marchman 39c50640ea pass 'rawPath' page path to plugins 2014-06-24 12:33:19 -04:00
Samy Pessé 16128c7e60 Bump version to 0.5.6 2014-06-24 12:35:13 +02:00
Samy Pessé 8b6a80cffb Fix error when chapters list is empty
Fix GitbookIO/gitbook.io#101 and GitbookIO/gitbook.io#102
2014-06-24 12:34:29 +02:00
Aaron O'Mullan 86f8a9d8fb Remove useless (and bad) sort on progress
Fixes bad ordering of chapters on gitbook.io
2014-06-20 03:40:47 -07:00
Aaron O'Mullan 790dfd601e Add csharp language highlight mapping
Fixes #327
2014-06-18 11:26:50 -07:00
Shaform 6bbefad24e Merge remote-tracking branch 'upstream/master' into ref_links 2014-06-17 22:08:46 +08:00
Shaform 1f4cf33dd0 Improve code syntax for links assignment 2014-05-28 06:57:50 +08:00
Shaform 7274aa6940 fix links error 2014-05-27 22:24:23 +08:00
Shaform 125e804cd5 Add reference links support
This commit resolves #184
2014-05-27 17:24:47 +08:00
27 changed files with 445 additions and 119 deletions
+5
View File
@@ -1,2 +1,7 @@
# Release notes
## 0.6.0
- Generate header id the same as github
- Custom links can be added at top of sidebar
- Summary can now be transformed by plugins
- Support importing code snippets
+7
View File
@@ -92,6 +92,11 @@ Here are the options that can be stored in this file:
"issues": null,
"contribute": null,
// Custom links at top of sidebar
"custom": {
"Custom link name": "https://customlink.com"
},
// Sharing links
"sharing": {
"google": null,
@@ -253,6 +258,8 @@ Plugins can used to extend your book's functionality. Read [GitbookIO/plugin](ht
* [Markdown within HTML](https://github.com/mrpotes/gitbook-plugin-nestedmd): Process markdown within HTML blocks - allows custom layout options for individual pages
* [Bootstrap JavaScript plugins](https://github.com/mrpotes/gitbook-plugin-bootstrapjs): Use the [Bootstrap JavaScript plugins](http://getbootstrap.com/javascript) in your online GitBook
* [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): Ebedded jsbin frame into your book
#### Debugging
+17
View File
@@ -14,6 +14,7 @@ var fs = require('../lib/generate/fs');
var utils = require('./utils');
var build = require('./build');
var Server = require('./server');
var platform = require("./platform");
// General options
prog
@@ -115,6 +116,22 @@ prog
return initDir(dir);
});
prog
.command('publish [source_dir]')
.description('Publish content to the associated gitbook.io book')
.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) {
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) {
prog.help();
+53
View File
@@ -0,0 +1,53 @@
var Q = require("q");
var utils = require("./utils");
var publish = function(folder) {
if (!folder) {
console.log("Need a repository folder");
return process.exit(-1);
}
utils.gitCmd("push", ["gitbook", "master"])
.then(function(out) {
console.log(out.stdout);
}, function(err) {
if (err.code == 128) {
console.log("No book on gitbook.io is configured with this git repository.");
console.log("Run 'gitbook git:remote username/book' to intialize this repository.");
} else {
console.log(err.message);
}
process.exit(-1);
});
};
var remote = function(folder, bookId) {
if (!folder || !bookId) {
console.log("Need a repository folder and a book id");
return process.exit(-1);
}
var url = "https://push.gitbook.io/"+bookId+".git";
var addRemote = function() {
return utils.gitCmd("remote", ["add", "gitbook", url]);
}
addRemote()
.fail(function(err) {
if (err.code == 128) {
return utils.gitCmd("remote", ["rm", "gitbook"]).then(addRemote);
}
return Q.reject(err);
})
.then(function(out) {
console.log("Book remote '"+url+"' added to the folder");
}, function(err) {
console.log(err.message);
process.exit(-1);
});
};
module.exports = {
publish: publish,
remote: remote
};
+23 -1
View File
@@ -1,6 +1,7 @@
var Q = require('q');
var _ = require('lodash');
var exec = require('child_process').exec;
var http = require('http');
var send = require('send');
@@ -36,9 +37,30 @@ function logError(err) {
return Q.reject(err);
};
function runGitCommand(command, args) {
var d = Q.defer(), child;
args = ["git", command].concat(args).join(" ");
child = exec(args, function (error, stdout, stderr) {
if (error !== null) {
error.stdout = stdout;
error.stderr = stderr;
d.reject(error);
} else {
d.resolve({
stdout: stdout,
stderr: stderr
})
}
});
return d.promise;
};
// Exports
module.exports = {
watch: watch,
logError: logError
logError: logError,
gitCmd: runGitCommand
};
+5
View File
@@ -30,6 +30,11 @@ var getFiles = function(path) {
'*.pdf',
'*.epub',
'*.mobi',
// Skip config files
'.ignore',
'.bookignore',
'book.json',
], '__custom_stuff');
// Push each file to our list
+2 -2
View File
@@ -14,13 +14,13 @@ var BaseGenerator = function(options) {
};
BaseGenerator.prototype.callHook = function(name, data) {
return this.plugins.hook(name, this, data);
return this.plugins.hook(name, data);
};
BaseGenerator.prototype.loadPlugins = function() {
var that = this;
return Plugin.fromList(this.options.plugins, this.options.input)
return Plugin.fromList(this.options.plugins, this.options.input, this)
.then(function(_plugins) {
that.plugins = _plugins;
+24 -6
View File
@@ -271,13 +271,31 @@ var generateBook = function(options) {
// Get summary
.then(function() {
return fs.readFile(path.join(options.input, "SUMMARY.md"), "utf-8")
.then(function(_summary) {
options.summary = parse.summary(_summary);
var summary = {
path: path.join(options.input, "SUMMARY.md")
};
// Parse navigation
options.navigation = parse.navigation(options.summary);
});
var _callHook = function(name) {
return generator.callHook(name, summary)
.then(function(_summary) {
summary = _summary;
return summary;
});
};
return fs.readFile(summary.path, "utf-8")
.then(function(_content) {
summary.content = _content;
return _callHook("summary:before");
})
.then(function() {
summary.content = parse.summary(summary.content);
return _callHook("summary:after");
})
.then(function() {
options.summary = summary.content;
options.navigation = parse.navigation(options.summary);
})
})
// Skip processing some files
+134 -78
View File
@@ -10,11 +10,15 @@ var pkg = require("../../package.json");
var RESOURCES = ["js", "css"];
var Plugin = function(name, root) {
var Plugin = function(name, root, generator) {
this.name = name;
this.root = root;
this.packageInfos = {};
this.infos = {};
this.generator = generator;
// Bind methods
_.bindAll(this);
_.each([
"gitbook-plugin-"+name,
@@ -43,28 +47,50 @@ Plugin.prototype.load = function(name, baseDir) {
}
};
// Return resources
Plugin.prototype.getResources = function(resource) {
if (!this.infos.book || !this.infos.book[resource]) {
return [];
Plugin.prototype.normalizeResource = function(resource) {
// Parse the resource path
var parsed = url.parse(resource);
// This is a remote resource
// so we will simply link to using it's URL
if (parsed.protocol) {
return {
"url": resource
};
}
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();
// This will be copied over from disk
// and shipped with the book's build
return { "path": this.name+"/"+resource };
};
// Return resources
Plugin.prototype.getResources = function() {
var book = this.infos.book;
// Nothing specified, fallback to default
if (!book) {
return Q({});
}
// Dynamic function
if(typeof book === "function") {
// Call giving it the context of our generator
return Q().then(book.bind(this.generator));
}
// Plain data object
return Q(book);
};
// 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)
this.packageInfos &&
this.packageInfos.name &&
this.packageInfos.engines &&
this.packageInfos.engines.gitbook &&
semver.satisfies(pkg.version, this.packageInfos.engines.gitbook)
);
};
@@ -74,7 +100,10 @@ Plugin.prototype.resolveFile = function(filename) {
};
// Resolve file path
Plugin.prototype.callHook = function(name, context, data) {
Plugin.prototype.callHook = function(name, data) {
// Our generator will be the context to apply
var context = this.generator;
var hookFunc = this.infos.hooks? this.infos.hooks[name] : null;
data = data || {};
@@ -86,18 +115,20 @@ Plugin.prototype.callHook = function(name, context, data) {
});
};
// Has assets
Plugin.prototype.hasAssets = function(out) {
return (this.infos.book && this.infos.book.assets);
};
// Copy plugin assets fodler
Plugin.prototype.copyAssets = function(out) {
if (!this.hasAssets()) return Q();
return fs.copy(
this.resolveFile(this.infos.book.assets),
out
);
var that = this;
return this.getResources().get('assets')
.then(function(assets) {
// Assets are undefined
if(!assets) return false;
return fs.copy(
that.resolveFile(assets),
out
).then(_.constant(true));
}, _.constant(false));
};
@@ -114,7 +145,7 @@ Plugin.normalizeNames = function(names) {
return name.length > 0 && name[0] == "-";
})
.map(function(name) {
return name.slice(1)
return name.slice(1);
})
.value();
@@ -133,69 +164,94 @@ Plugin.normalizeNames = function(names) {
};
// Extract data from a list of plugin
Plugin.fromList = function(names, root) {
Plugin.fromList = function(names, root, generator) {
var that = this;
var failed = [];
// Load plugins
var plugins = _.map(names, function(name) {
var plugin = new Plugin(name, root);
var plugin = new Plugin(name, root, generator);
if (!plugin.isValid()) failed.push(name);
return plugin;
});
if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")));
// 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();
resources.html = {}
// The raw resources extracted from each plugin
var pluginResources;
_.each(plugins, function(plugin) {
if (!plugin.infos.book || !plugin.infos.book.html) return;
var html = plugin.infos.book.html || {};
_.each(html, function(code, key) {
if (!_.isFunction(code)) code = _.constant(code);
if (!resources.html[key]) resources.html[key] = [];
resources.html[key].push(code);
// Get resources of plugins
return Q.all(_.map(plugins, function(plugin) {
return plugin.getResources();
}))
// Extract resources out
// css, js, etc ...
.then(function(resources) {
pluginResources = resources;
// Group by resource types
return _.chain(RESOURCES)
.map(function(resourceType) {
// Get resources from all the plugins for this current type
return [
// Key
resourceType,
// Value
_.chain(resources)
.pluck(resourceType)
.compact()
.flatten()
.value()
];
})
});
return Q({
'list': plugins,
'resources': resources,
'hook': function(name, context, data) {
return _.reduce(plugins, function(prev, plugin) {
return prev.then(function(ret) {
return plugin.callHook(name, context, ret);
})
}, Q(data));
},
'template': function(name) {
var withTpl = _.find(plugins, function(plugin) {
return (plugin.infos.templates
&& plugin.infos.templates[name]);
.object()
.value();
})
// Extract html snippets
.then(function(resources) {
// Map of html resources by name added by each plugin
resources.html = pluginResources.reduce(function(accu, resource) {
var html = (resource && resource.html) || {};
_.each(html, function(code, key) {
// Turn into function if not one already
if (!_.isFunction(code)) code = _.constant(code);
// Append
accu[key] = (accu[key] || []).concat([code]);
});
if (!withTpl) return null;
return withTpl.resolveFile(withTpl.infos.templates[name]);
},
'html': function(tag, context, options) {
return _.map(resources.html[tag] || [], function(code) {
return code.call(context, options);
}).join("\n");
}
return accu;
}, {});
return resources;
})
// Return big multi-plugin object
.then(function(resources) {
return {
'list': plugins,
'resources': resources,
'hook': function(name, data) {
return _.reduce(plugins, function(prev, plugin) {
return prev.then(function(ret) {
return plugin.callHook(name, ret);
});
}, Q(data));
},
'template': function(name) {
var withTpl = _.find(plugins, function(plugin) {
return (
plugin.infos.templates &&
plugin.infos.templates[name]
);
});
if (!withTpl) return null;
return withTpl.resolveFile(withTpl.infos.templates[name]);
},
'html': function(tag, context, options) {
return _.map(resources.html[tag] || [], function(code) {
return code.call(context, options);
}).join("\n");
}
};
});
};
+4 -3
View File
@@ -102,6 +102,7 @@ Generator.prototype.convertFile = function(content, _input) {
var page = {
path: _input,
rawPath: input, // path to raw md file
content: content,
progress: parse.progress(this.options.navigation, _input)
};
@@ -197,11 +198,11 @@ Generator.prototype.copyAssets = function() {
.then(function() {
return Q.all(
_.map(that.plugins.list, function(plugin) {
if (!plugin.hasAssets()) return Q();
var pluginAssets = path.join(that.options.output, "gitbook/plugins/", plugin.name);
return plugin.copyAssets(pluginAssets)
.then(function() {
.then(function(copiedStuff) {
// Nothing was copied
if(!copiedStuff) return;
return that.manifest.addFolder(pluginAssets, "gitbook/plugins/"+plugin.name);
});
})
+20
View File
@@ -0,0 +1,20 @@
var fs = require('fs');
var path = require('path');
module.exports = function(code, folder) {
folder = folder || '';
return code.replace(/{{([\s\S]+?)}}/g, function(match, filename) {
// Normalize filename
var fname = path.join(folder, filename.trim());
// Try including snippet from FS
try {
// Trim trailing newlines/space of imported snippets
return fs.readFileSync(fname, 'utf8').trimRight();
} catch(err) {}
// If fails leave content as is
return match;
});
};
+4
View File
@@ -118,6 +118,10 @@ function lexPage(src) {
return sections;
}, [])
.map(function(section) {
section.links = nodes.links;
return section;
})
.value();
}
+11 -6
View File
@@ -5,6 +5,7 @@ var hljs = require('highlight.js');
var lex = require('./lex');
var renderer = require('./renderer');
var codeInclude = require('./code_include');
var lnormalize = require('../utils/lang').normalize;
@@ -12,10 +13,9 @@ var lnormalize = require('../utils/lang').normalize;
// Render a section using our custom renderer
function render(section, _options) {
// Copy section
var links = section.links || {};
section = _.toArray(section);
// marked's Render expects this, we don't use it yet
section.links = {};
section.links = links;
// Build options using defaults and our custom renderer
var options = _.extend({}, marked.defaults, {
@@ -74,15 +74,20 @@ function parsePage(src, options) {
// Main language
var lang = validLangs ? langs[0] : null;
// codeInclude shortcut
var ci = function(code) {
return codeInclude(code, options.dir);
};
return {
id: section.id,
type: section.type,
content: render(nonCodeNodes),
lang: lang,
code: {
base: codeNodes[0].text,
solution: codeNodes[1].text,
validation: codeNodes[2].text,
base: ci(codeNodes[0].text),
solution: ci(codeNodes[1].text),
validation: ci(codeNodes[2].text),
// Context is optional
context: codeNodes[3] ? codeNodes[3].text : null,
}
-3
View File
@@ -11,9 +11,6 @@ var calculProgress = function(navigation, current) {
nav.path = path;
return nav;
})
.sortBy(function(nav) {
return parseFloat(nav.level);
})
.map(function(nav, i) {
// Calcul percent
nav.percent = (i * 100) / Math.max((n - 1), 1);
+18 -2
View File
@@ -1,6 +1,7 @@
var url = require('url');
var inherits = require('util').inherits;
var links = require('../utils').links;
var codeInclude = require('./code_include');
var path = require('path');
@@ -56,7 +57,7 @@ GitBookRenderer.prototype.link = function(href, title, text) {
// Relative link, rewrite it to point to github repo
if(links.isRelative(_href)) {
if (path.extname(_href) == ".md") {
if (path.extname(parsed.path) == ".md") {
_href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
if (o.singleFile) {
@@ -125,7 +126,7 @@ GitBookRenderer.prototype._createCheckboxAndRadios = function(text) {
var length = splittedText.length;
var label = '<label class="quiz-label" for="' + quizIdentifier + '">' + splittedText[length - 1] + '</label>';
return text.replace(fieldRegex, field).replace(splittedText[length - 1], label);
}
};
GitBookRenderer.prototype.tablecell = function(content, flags) {
return GitBookRenderer.super_.prototype.tablecell(this._createCheckboxAndRadios(content), flags);
@@ -135,5 +136,20 @@ GitBookRenderer.prototype.listitem = function(text) {
return GitBookRenderer.super_.prototype.listitem(this._createCheckboxAndRadios(text));
};
GitBookRenderer.prototype.code = function(code, lang, escaped) {
return GitBookRenderer.super_.prototype.code.call(
this,
// Import code snippets
codeInclude(code, this._extra_options.dir),
lang,
escaped
);
};
GitBookRenderer.prototype.heading = function(text, level, raw) {
var id = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w -]+/g, '').replace(/ /g, '-');
return '<h' + level + ' id="' + id + '">' + text + '</h' + level + '>\n';
};
// Exports
module.exports = GitBookRenderer;
+10 -6
View File
@@ -81,8 +81,10 @@ function parseTitle(src, nums) {
title: matches[1],
level: level,
// Replace .md references with .html
path: matches[2].replace(/\\/g, '/'),
// Normalize path
// 1. Convert Window's "\" to "/"
// 2. Remove leading "/" if exists
path: matches[2].replace(/\\/g, '/').replace(/^\/+/, ''),
};
}
@@ -100,11 +102,13 @@ function parseChapter(nodes, nums) {
function defaultChapterList(chapterList) {
var first = _.first(chapterList);
var chapter = parseChapter(first, [0]);
if (first) {
var chapter = parseChapter(first, [0]);
// Already have README node, we're good to go
if(chapter.path === 'README.md') {
return chapterList;
// Already have README node, we're good to go
if(chapter.path === 'README.md') {
return chapterList;
}
}
return [
+1
View File
@@ -2,6 +2,7 @@ var MAP = {
'py': 'python',
'js': 'javascript',
'rb': 'ruby',
'csharp': 'cs',
};
function normalize(lang) {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.5.5",
"version": "0.6.2",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -22,7 +22,7 @@
"resolve": "0.6.3",
"tiny-lr-fork": "0.0.5",
"gitbook-plugin": "0.0.2",
"gitbook-plugin-mathjax": "0.0.3",
"gitbook-plugin-mathjax": "0.0.4",
"gitbook-plugin-livereload": "0.0.1"
},
"devDependencies": {
+29
View File
@@ -0,0 +1,29 @@
# Beautiful chapter
Here is a nice included snippet :
```c
{{ included.c }}
```
----
An exercise using includes
```c
{{ included.c }}
Remove this extra code at the end
```
```c
{{ included.c }}
```
```c
{{ included.c }}
This validation code is wrong but who cares ?
```
----
+2 -2
View File
@@ -3,8 +3,8 @@
* [Chapter 1](chapter-1/README.md)
* [Article 1](chapter-1/ARTICLE1.md)
* [Article 2](chapter-1/ARTICLE2.md)
* [article 1.2.1](chapter-1/ARTICLE-1-2-1.md)
* [article 1.2.2](chapter-1/ARTICLE-1-2-2.md)
* [article 1.2.1](\chapter-1\ARTICLE-1-2-1.md)
* [article 1.2.2](/chapter-1/ARTICLE-1-2-2.md)
* [Chapter 2](chapter-2/README.md)
* [Chapter 3](chapter-3/README.md)
* [Chapter 4](chapter-4/README.md)
+7
View File
@@ -0,0 +1,7 @@
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("All is well\n");
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
var fs = require('fs');
var path = require('path');
var assert = require('assert');
var page = require('../').parse.page;
var FIXTURES_DIR = path.join(__dirname, './fixtures/');
function loadPage (name, options) {
var CONTENT = fs.readFileSync(FIXTURES_DIR + name + '.md', 'utf8');
return page(CONTENT, options);
}
describe('Code includes', function() {
var LEXED = loadPage('INCLUDES', {
'dir': FIXTURES_DIR,
});
var INCLUDED_C = fs.readFileSync(path.join(FIXTURES_DIR, 'included.c'), 'utf8');
it('should work for snippets', function() {
assert.equal(LEXED[0].type, 'normal');
// Has replaced include
assert.equal(
LEXED[0].content.indexOf('{{ included.c }}'),
-1
);
});
it('should work for exercises', function() {
assert.equal(LEXED[1].type, 'exercise');
// Solution is trimmed version of source
assert.equal(LEXED[1].code.solution, INCLUDED_C.trim());
});
});
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -18,6 +18,14 @@ define([
editor.setTheme("ace/theme/tomorrow");
editor.getSession().setUseWorker(false);
editor.getSession().setMode("ace/mode/javascript");
editor.commands.addCommand({
name: "submit",
bindKey: "Ctrl-Return|Cmd-Return",
exec: function() {
$exercise.find(".action-submit").click();
}
});
// Submit: test code
$exercise.find(".action-submit").click(function(e) {
@@ -52,4 +60,4 @@ define([
init: init,
prepare: prepareExercise
};
});
});
+7 -3
View File
@@ -49,10 +49,14 @@
}
}
.book.color-theme-1 .book-body {
.navigation:hover{
}
}
.book.color-theme-2 .book-body {
.navigation:hover{
.navigation {
color: rgba(255, 255, 255, 0.4);
&:hover {
color: rgba(255, 255, 255, 0.9);
}
}
}
+11 -2
View File
@@ -1,7 +1,7 @@
{% macro articles(_articles) %}
{% for item in _articles %}
{% set externalLink = item.path|isExternalLink %}
<li class="chapter {% if item._path == _input %}active{% endif %}" data-level="{{ item.level }}" {% if item.path && !externalLink %}data-path="{{ item.path|mdLink }}"{% endif %}>
<li class="chapter {% if item.path == _input %}active{% endif %}" data-level="{{ item.level }}" {% if item.path && !externalLink %}data-path="{{ item.path|mdLink }}"{% endif %}>
{% if item.path %}
{% if !externalLink %}
<a href="{{ basePath }}/{{ item.path|mdLink }}">
@@ -48,7 +48,7 @@
{% if options.links.issues !== false && (options.links.issues || githubId) %}
{% set _divider = true %}
<li>
<a href="{{ options.links.issues|default(githubHost+githubId+"/issues") }}" target="blank"class="issues-link">Questions and Issues</a>
<a href="{{ options.links.issues|default(githubHost+githubId+"/issues") }}" target="blank" class="issues-link">Questions and Issues</a>
</li>
{% endif %}
@@ -59,6 +59,15 @@
</li>
{% endif %}
{% if options.links.custom %}
{% for link in options.links.custom %}
{% set _divider = true %}
<li>
<a href="{{ options.links.custom[loop.key] }}" target="blank" class="custom-link">{{ loop.key }}</a>
</li>
{% endfor %}
{% endif %}
{% if _divider %}
<li class="divider"></li>
{% endif %}