Compare commits

...

33 Commits

Author SHA1 Message Date
Samy Pessé 7b4accb117 Bump version to 1.3.4 2014-11-25 18:55:33 +01:00
Samy Pessé d6437d31d4 Omit "generator" when building file with config file 2014-11-25 18:53:02 +01:00
Samy Pessé 3dd33f1f3c Merge pull request #502 from tonka3000/X-UA-Compatible-tag
add X-UA-Compatible meta tag for IE
2014-11-25 15:20:14 +01:00
Samy Pessé 3a0f00411b Fix #505: add glossary to ebook file 2014-11-24 22:08:19 +01:00
Samy Pessé 5b655bb29a Fx typo 2014-11-24 21:56:33 +01:00
Samy Pessé faf10605e8 Add hook finish:before 2014-11-24 21:41:50 +01:00
Samy Pessé 5c98b3350b Merge pull request #503 from jr0cket/ebook-command-fix
updated eBook generation commands - resolves #432
2014-11-22 16:41:19 +01:00
John Stevenson 6f4e1d10c1 made commands clearer by seperating output filename option 2014-11-22 14:47:12 +00:00
John Stevenson 870886599a updated eBook generation commands 2014-11-22 11:26:08 +00:00
Michael Aigner 1b9801b8a4 add X-UA-Compatible meta tag for IE (https://github.com/GitbookIO/gitbook/issues/501) 2014-11-20 10:16:40 +01:00
Samy Pessé 897463b22e Bump version to 1.3.3 2014-11-14 22:10:19 +01:00
Samy Pessé aa4894e94c Fix parsing of already lexed content 2014-11-14 22:09:30 +01:00
Samy Pessé 8a0180ae6b Bump version to 1.3.2 2014-11-14 18:53:57 +01:00
Samy Pessé d6776b98d3 Fix bundle task 2014-11-14 18:53:48 +01:00
Samy Pessé 6a04ba89a5 Update gitbook bundle 2014-11-14 18:53:39 +01:00
Samy Pessé 05eaeeb0d0 Fix #441: Improve validity of epub output 2014-11-13 08:34:35 +01:00
Samy Pessé 77043464b2 Fix #496: improve replacement of glossary terms in html 2014-11-12 22:10:38 +01:00
Samy Pessé b90f74a821 Merge pull request #494 from cnDelbert/master
Bug fix for issue#493: 2-level or more deep relative links go wrong when in win32
2014-11-12 19:06:33 +01:00
Aaron O'Mullan f804eb42ac Merge pull request #495 from romanlytkin/patch-1
Update README.md
2014-11-07 15:58:18 +01:00
romanlytkin 74fd8c159b Update README.md
Hi, i add 2 new plugins for gitbook, I hope it will be useful to someone.
2014-11-07 17:37:27 +03:00
Delbert a741ec1350 Bug fix for issue #493: 2-level or more deep relative links may go wrong when in win32 2014-11-06 15:50:59 +08:00
Samy Pessé 4b26c31b3b Remove unnecessary option "repo" from tests 2014-11-03 17:43:44 +01:00
Samy Pessé dfd487692a Adapt new page.parse api for tests 2014-11-03 17:40:38 +01:00
Samy Pessé 195374ecee Merge pull request #489 from codepiano/fork
bugfix,init page object's lexed attribute.
2014-11-03 17:29:54 +01:00
Samy Pessé 1659778a77 Bump version to 1.3.1 2014-11-03 16:58:37 +01:00
Samy Pessé 40c4035afb Fix #491: handle correctly url without path for links 2014-11-03 16:57:35 +01:00
codepiano 1502d65286 Merge branch 'master' of github.com:GitbookIO/gitbook into fork
Conflicts:
	lib/parse/page.js
2014-11-02 01:34:28 +08:00
Samy Pessé 0feb672d70 Bump version to 1.3.0 2014-11-01 15:36:10 +01:00
Samy Pessé 2a4ef5bbf4 Fix dependency in renderer 2014-11-01 15:21:16 +01:00
Samy Pessé c4540332a7 Bundle gitbook parser as a client side library 2014-11-01 15:09:58 +01:00
Samy Pessé 2104404cb3 Remove dependency for path in parser 2014-11-01 15:09:41 +01:00
Samy Pessé 002d685ebb Adapt include in page parsing to works on clientside 2014-11-01 15:00:13 +01:00
codepiano 9da10e2b25 bugfix,init page object's lexed attribute.
the page object's attribute 'lexed' is not correctly inited.so when
use page.lexed to generate the search index file,nothing will be
indexed.
2014-10-31 18:00:09 +08:00
25 changed files with 20964 additions and 128 deletions
+20
View File
@@ -1,5 +1,25 @@
# Release notes
## 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.2.0
- Improvements on ebook generation
- Fix incorrect follow of links in ebook generation
+34 -1
View File
@@ -6,6 +6,8 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks("grunt-bower-install-simple");
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Init GRUNT configuraton
grunt.initConfig({
@@ -77,6 +79,30 @@ module.exports = function (grunt) {
}
]
}
},
browserify: {
dist: {
files: {
'gitbook.js': [
'./lib/parse/index.js'
],
},
options: {
postBundleCB: function (err, src, next) {
return next(null, '(function () { var define = undefined; '+src+'; })();')
},
browserifyOptions: {
'standalone': "gitbook"
}
}
}
},
uglify: {
dist: {
files: {
'gitbook.min.js': ['gitbook.js']
}
}
}
});
@@ -90,7 +116,14 @@ module.exports = function (grunt) {
'copy:vendors'
]);
// Bundle the library
grunt.registerTask('bundle', [
'browserify',
'uglify'
]);
grunt.registerTask('default', [
'build'
'build',
'bundle'
]);
};
+6 -1
View File
@@ -132,7 +132,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
@@ -236,6 +239,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
+20724
View File
File diff suppressed because one or more lines are too long
+10
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -74,4 +74,5 @@ module.exports = {
fs.exists(path, d.resolve);
return d.promise;
},
readFileSync: fs.readFileSync.bind(fs)
};
+4 -1
View File
@@ -64,7 +64,7 @@ var generate = function(options) {
try {
var _config = require(path.resolve(options.input, options.configFile));
options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins'));
options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins', 'generator'));
}
catch(err) {
// No config file: not a big deal
@@ -297,6 +297,9 @@ var generateBook = function(options) {
})
// Finish generation
.then(function() {
return generator.callHook("finish:before");
})
.then(function() {
return generator.finish();
})
+3 -2
View File
@@ -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(
+9 -1
View File
@@ -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();
+16 -7
View File
@@ -123,16 +123,20 @@ Generator.prototype.prepareFile = function(content, _input) {
return parse.page(page.content, {
// Local files path
dir: path.dirname(_input) || '/',
// Project's include folder
includes_dir: path.join(that.options.input, '_includes'),
// Output directory
outdir: path.dirname(_input) || '/',
// Templating variables
variables: that.options.variables,
// Includer for templating
includer: parse.includer(that.options.variables, [
path.dirname(_input) || '/',
path.join(that.options.input, '_includes'),
], 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");
@@ -150,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
+3 -39
View File
@@ -1,48 +1,12 @@
var _ = require('lodash');
var fs = require('graceful-fs');
var path = require('path');
// Include helper
function importInclude(name, paths) {
return paths
.map(function(folder) {
// Try including snippet from FS
try {
var fname = path.join(folder, name);
// Trim trailing newlines/space of imported snippets
return fs.readFileSync(fname, 'utf8').trimRight();
} catch(err) {}
})
.filter(Boolean)[0];
}
function includer(ctx, folders) {
return function(key) {
key = key.trim();
return ctx[key] || importInclude(key, folders);
};
}
module.exports = function(markdown, folder, ctx) {
// List of folders to search for includes
var folders = [];
// Handle folder arg (string or array)
if(_.isString(folder)) {
folders = [folder];
} else if(_.isArray(folder)) {
folders = folder;
}
// variable context
ctx = ctx || {};
module.exports = function(markdown, includer) {
// Memoized include function (to cache lookups)
var _include = _.memoize(includer(ctx, folders));
var _include = _.memoize(includer);
return markdown.replace(/{{([\s\S]+?)}}/g, function(match, key) {
// If fails leave content as is
key = key.trim();
return _include(key) || match;
});
};
+15
View File
@@ -0,0 +1,15 @@
// Return a fs inclduer
module.exports = function(ctx, folders, resolveFile, readFile) {
return function(name) {
return ctx[name] ||
folders.map(function(folder) {
// Try including snippet from FS
try {
var fname = resolveFile(folder, name);
// Trim trailing newlines/space of imported snippets
return readFile(fname, 'utf8').trimRight();
} catch(err) {}
})
.filter(Boolean)[0];
}
};
+2 -1
View File
@@ -6,5 +6,6 @@ module.exports = {
lex: require('./lex'),
progress: require('./progress'),
navigation: require('./navigation'),
readme: require('./readme')
readme: require('./readme'),
includer: require('./includer')
};
+6 -2
View File
@@ -51,8 +51,10 @@ function parsePage(src, options) {
options = options || {};
// Lex if not already lexed
return (_.isArray(src) ? src : lex(include(src, [options.dir, options.includes_dir], options.variables)))
.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
+3 -5
View File
@@ -1,9 +1,7 @@
var url = require('url');
var _ = require('lodash');
var inherits = require('util').inherits;
var links = require('../utils').links;
var path = require('path');
var kramed = require('kramed');
var rendererId = 0;
@@ -50,11 +48,11 @@ GitBookRenderer.prototype.link = function(href, title, text) {
// Parsed version of the url
var parsed = url.parse(href);
var o = this._extra_options;
var extname = parsed.path? _.last(parsed.path.split(".")) : "";
// Relative link, rewrite it to point to github repo
if(links.isRelative(_href) && path.extname(parsed.path) == ".md") {
if(links.isRelative(_href) && extname == "md") {
_href = links.toAbsolute(_href, o.dir || "./", o.outdir || "./");
_href = _href.replace(".md", ".html");
}
+4 -2
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "1.2.0",
"version": "1.3.4",
"homepage": "http://www.gitbook.io/",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
@@ -35,7 +35,9 @@
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-less": "~0.5.0",
"grunt-contrib-requirejs": "0.4.1",
"grunt-bower-install-simple": "0.9.2"
"grunt-bower-install-simple": "0.9.2",
"grunt-browserify": "3.1.0",
"grunt-contrib-uglify": "0.6.0"
},
"scripts": {
"test": "export TESTING=true; mocha --reporter list"
+5 -1
View File
@@ -3,12 +3,13 @@ var path = require('path');
var assert = require('assert');
var page = require('../').parse.page;
var includer = require('../').parse.includer;
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;
}
@@ -16,6 +17,9 @@ describe('Code includes', function() {
var LEXED = loadPage('INCLUDES', {
'dir': FIXTURES_DIR,
'includer': includer({}, [
FIXTURES_DIR
], path.join, fs.readFileSync)
});
var INCLUDED_C = fs.readFileSync(path.join(FIXTURES_DIR, 'included.c'), 'utf8');
+1 -10
View File
@@ -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: './'
+1 -1
View File
File diff suppressed because one or more lines are too long
+51 -50
View File
@@ -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() {
+15
View File
@@ -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 %}
+22
View File
@@ -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>
+3 -3
View File
@@ -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 %}
+5 -1
View File
@@ -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 %}
+1
View File
@@ -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 %}">