mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-29 13:39:11 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6bce93d893 | |||
| c9db068227 | |||
| 8a6d36ac4d | |||
| 64622c5945 | |||
| 837813edb0 | |||
| 0d9d62f1a9 | |||
| f7e9abf984 | |||
| dd0579b60d | |||
| b5bb953e47 | |||
| ef4a8ea1b6 | |||
| 49cde96ee7 | |||
| 627be20e48 | |||
| e45bb84b02 | |||
| 4e8876c725 | |||
| 6d5be15ec9 | |||
| 1a8db646f2 | |||
| d3aba2c906 | |||
| 457a83282f | |||
| 48e94c937d | |||
| 6e613e9f71 | |||
| b698d43d7d | |||
| a36b9a6088 | |||
| 20acd89c8a | |||
| 7bed9a257d | |||
| 19c83aa5a8 | |||
| 52610d7d61 | |||
| 9e4b393b7a | |||
| a0ae34a3b7 | |||
| 413dc5d004 | |||
| c9eb27bfe7 | |||
| b78505c290 | |||
| 95f9ae83d0 | |||
| 9304289315 | |||
| 1b726ca293 | |||
| 656ca18929 |
@@ -35,7 +35,6 @@ module.exports = function (grunt) {
|
|||||||
"lodash": 'vendors/lodash',
|
"lodash": 'vendors/lodash',
|
||||||
"requireLib": 'vendors/require',
|
"requireLib": 'vendors/require',
|
||||||
"Mousetrap": 'vendors/mousetrap',
|
"Mousetrap": 'vendors/mousetrap',
|
||||||
"mixpanel": 'vendors/mixpanel',
|
|
||||||
"lunr": path.join(__dirname, "node_modules/lunr/lunr")
|
"lunr": path.join(__dirname, "node_modules/lunr/lunr")
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
@@ -48,9 +47,6 @@ module.exports = function (grunt) {
|
|||||||
'Mousetrap': {
|
'Mousetrap': {
|
||||||
exports: 'Mousetrap'
|
exports: 'Mousetrap'
|
||||||
},
|
},
|
||||||
'mixpanel': {
|
|
||||||
exports: 'mixpanel'
|
|
||||||
},
|
|
||||||
'lunr': {
|
'lunr': {
|
||||||
exports: 'lunr'
|
exports: 'lunr'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ GitBook
|
|||||||
|
|
||||||
[](https://travis-ci.org/GitbookIO/gitbook)
|
[](https://travis-ci.org/GitbookIO/gitbook)
|
||||||
|
|
||||||
GitBook is a command line tool (and Node.js library) for building beautiful programming books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](http://gitbookio.github.io/javascript/).
|
GitBook is a command line tool (and Node.js library) for building beautiful programming books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](http://gitbookio.github.io/javascript/). An [editor](https://github.com/GitbookIO/editor) is available for Windows, Mac and Linux. You can follow [@GitBookIO](https://twitter.com/GitBookIO) on Twitter.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -35,11 +35,12 @@ Options for commands `build` and `serve` are:
|
|||||||
-g, --github <repo_path> ID of github repo like : username/repo
|
-g, --github <repo_path> ID of github repo like : username/repo
|
||||||
-o, --output <directory> Path to output directory, defaults to ./_book
|
-o, --output <directory> Path to output directory, defaults to ./_book
|
||||||
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json
|
-f, --format <name> Change generation format, defaults to site, availables are: site, page, pdf, json
|
||||||
-i, --intro <intro> Description of the book to generate
|
|
||||||
--githubHost <url> The url of the github host (defaults to https://github.com/)
|
--githubHost <url> The url of the github host (defaults to https://github.com/)
|
||||||
--theme <path> Path to theme directory
|
--theme <path> Path to theme directory
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can publish your books to our index by visiting [GitBook.io](http://www.gitbook.io)
|
||||||
|
|
||||||
## Output Formats
|
## Output Formats
|
||||||
|
|
||||||
GitBook can generate your book in the following formats:
|
GitBook can generate your book in the following formats:
|
||||||
|
|||||||
+2
-1
@@ -16,7 +16,8 @@ var getFiles = function(path) {
|
|||||||
|
|
||||||
// Add extra rules to ignore common folders
|
// Add extra rules to ignore common folders
|
||||||
ig.addIgnoreRules([
|
ig.addIgnoreRules([
|
||||||
'.git/'
|
'.git/',
|
||||||
|
'.gitignore',
|
||||||
], '__custom_stuff');
|
], '__custom_stuff');
|
||||||
|
|
||||||
// Push each file to our list
|
// Push each file to our list
|
||||||
|
|||||||
+11
-2
@@ -129,6 +129,15 @@ var generate = function(options) {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Skip processing some files
|
||||||
|
.then(function() {
|
||||||
|
files = _.filter(files, function (file) {
|
||||||
|
return !(
|
||||||
|
file === 'SUMMARY.md'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
// Copy file and replace markdown file
|
// Copy file and replace markdown file
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return Q.all(
|
return Q.all(
|
||||||
@@ -177,7 +186,7 @@ var generateFile = function(options) {
|
|||||||
return Q.nfcall(tmp.dir)
|
return Q.nfcall(tmp.dir)
|
||||||
.then(function(tmpDir) {
|
.then(function(tmpDir) {
|
||||||
return generate(
|
return generate(
|
||||||
_.extend({},
|
_.extend({},
|
||||||
options,
|
options,
|
||||||
{
|
{
|
||||||
output: tmpDir
|
output: tmpDir
|
||||||
@@ -195,7 +204,7 @@ var generateFile = function(options) {
|
|||||||
_outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
|
_outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
|
||||||
_tmpDir = path.join(_tmpDir, lang);
|
_tmpDir = path.join(_tmpDir, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fs.copy(
|
return fs.copy(
|
||||||
path.join(_tmpDir, "index."+ext),
|
path.join(_tmpDir, "index."+ext),
|
||||||
_outputFile
|
_outputFile
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ function isQuiz(nodes) {
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
// List of questions
|
// List of questions
|
||||||
listIdx !== -1 && isQuizNode(quizNodes[listIdx + 1]) &&
|
listIdx !== -1 && isQuizNode(quizNodes[listIdx + 1]) ||
|
||||||
|
|
||||||
// Table of questions
|
// Table of questions
|
||||||
(
|
(
|
||||||
|
|||||||
+30
-49
@@ -6,6 +6,12 @@ function clean(obj) {
|
|||||||
return obj && _.omit(obj, ['articles']);
|
return obj && _.omit(obj, ['articles']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function flattenChapters(chapters) {
|
||||||
|
return _.reduce(chapters, function(accu, chapter) {
|
||||||
|
return accu.concat([clean(chapter)].concat(chapter.articles));
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns from a summary a map of
|
// Returns from a summary a map of
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@@ -20,62 +26,37 @@ function navigation(summary, files) {
|
|||||||
// Support single files as well as list
|
// Support single files as well as list
|
||||||
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
files = _.isArray(files) ? files : (_.isString(files) ? [files] : null);
|
||||||
|
|
||||||
// Mapping of prev/next for a give path
|
|
||||||
var mapping = {};
|
|
||||||
|
|
||||||
// Special README nav
|
// Special README nav
|
||||||
var README_NAV = {
|
var README_NAV = {
|
||||||
path: 'README.md',
|
path: 'README.md',
|
||||||
title: 'Introduction',
|
title: 'Introduction',
|
||||||
};
|
|
||||||
|
|
||||||
// Walk the chapter/article tree and create navigation entires
|
|
||||||
_.each(summary.chapters, function(chapter, idx, chapters) {
|
|
||||||
// Skip if no path
|
|
||||||
if(!chapter.path) return;
|
|
||||||
|
|
||||||
var currentChapter = clean(chapter);
|
|
||||||
var prevChapter = (idx-1 < 0) ? README_NAV : chapters[idx-1];
|
|
||||||
var nextChapter = (idx+1 >= chapters.length) ? null : chapters[idx+1];
|
|
||||||
|
|
||||||
var prev = (!prevChapter || _.isEmpty(prevChapter.articles)) ?
|
|
||||||
prevChapter : _.last(prevChapter.articles);
|
|
||||||
var next = (!chapter || _.isEmpty(chapter.articles)) ?
|
|
||||||
nextChapter : _.first(chapter.articles);
|
|
||||||
|
|
||||||
// Add chapter mapping
|
|
||||||
mapping[chapter.path] = {
|
|
||||||
title: chapter.title,
|
|
||||||
prev: clean(prev),
|
|
||||||
next: clean(next),
|
|
||||||
level: (idx+1).toString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check a chapter's articles
|
|
||||||
_.each(chapter.articles, function(article, _idx, articles) {
|
|
||||||
// Skip if no path
|
|
||||||
if(!article.path) return;
|
|
||||||
|
|
||||||
var prev = (_idx-1 < 0) ? currentChapter : clean(articles[_idx-1]);
|
|
||||||
var next = (_idx+1 >= articles.length) ? nextChapter : clean(articles[_idx+1]);
|
|
||||||
|
|
||||||
mapping[article.path] = {
|
|
||||||
title: article.title,
|
|
||||||
prev: clean(prev),
|
|
||||||
next: clean(next),
|
|
||||||
level: [idx+1, _idx+1].join('.'),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hack for README.html
|
|
||||||
mapping['README.md'] = {
|
|
||||||
title: README_NAV.title,
|
|
||||||
prev: null,
|
|
||||||
next: clean(summary.chapters[0]),
|
|
||||||
level: '0',
|
level: '0',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// List of all navNodes
|
||||||
|
var navNodes = [README_NAV].concat(flattenChapters(summary.chapters));
|
||||||
|
var prevNodes = [null].concat(navNodes.slice(0, -1));
|
||||||
|
var nextNodes = navNodes.slice(1).concat([null]);
|
||||||
|
|
||||||
|
// Mapping of prev/next for a give path
|
||||||
|
var mapping = _.chain(_.zip(navNodes, prevNodes, nextNodes))
|
||||||
|
.map(function(nodes) {
|
||||||
|
var current = nodes[0], prev = nodes[1], next = nodes[2];
|
||||||
|
|
||||||
|
// Skip if no path
|
||||||
|
if(!current.path) return null;
|
||||||
|
|
||||||
|
return [current.path, {
|
||||||
|
title: current.title,
|
||||||
|
prev: prev,
|
||||||
|
next: next,
|
||||||
|
level: current.level,
|
||||||
|
}];
|
||||||
|
})
|
||||||
|
.filter()
|
||||||
|
.object()
|
||||||
|
.value();
|
||||||
|
|
||||||
// Filter for only files we want
|
// Filter for only files we want
|
||||||
if(files) {
|
if(files) {
|
||||||
return _.pick(mapping, files);
|
return _.pick(mapping, files);
|
||||||
|
|||||||
+15
-12
@@ -8,17 +8,6 @@ var renderer = require('./renderer');
|
|||||||
var lnormalize = require('../utils/lang').normalize;
|
var lnormalize = require('../utils/lang').normalize;
|
||||||
|
|
||||||
|
|
||||||
// Synchronous highlighting with highlight.js
|
|
||||||
marked.setOptions({
|
|
||||||
highlight: function (code, lang) {
|
|
||||||
try {
|
|
||||||
return hljs.highlight(lang, code).value;
|
|
||||||
} catch(e) {
|
|
||||||
return hljs.highlightAuto(code).value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Render a section using our custom renderer
|
// Render a section using our custom renderer
|
||||||
function render(section, _options) {
|
function render(section, _options) {
|
||||||
@@ -30,7 +19,21 @@ function render(section, _options) {
|
|||||||
|
|
||||||
// Build options using defaults and our custom renderer
|
// Build options using defaults and our custom renderer
|
||||||
var options = _.extend({}, marked.defaults, {
|
var options = _.extend({}, marked.defaults, {
|
||||||
renderer: renderer(null, _options)
|
renderer: renderer(null, _options),
|
||||||
|
|
||||||
|
// Synchronous highlighting with highlight.js
|
||||||
|
highlight: function (code, lang) {
|
||||||
|
if(!lang) return code;
|
||||||
|
|
||||||
|
// Normalize lang
|
||||||
|
lang = lnormalize(lang);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return hljs.highlight(lang, code).value;
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return marked.parser(section, options);
|
return marked.parser(section, options);
|
||||||
|
|||||||
@@ -79,8 +79,14 @@ GitBookRenderer.prototype.image = function(href, title, text) {
|
|||||||
|
|
||||||
// Relative image, rewrite it depending output
|
// Relative image, rewrite it depending output
|
||||||
if(!parsed.protocol && parsed.path && parsed.path[0] != '/' && o && o.dir && o.outdir) {
|
if(!parsed.protocol && parsed.path && parsed.path[0] != '/' && o && o.dir && o.outdir) {
|
||||||
var outdir = o.outdir.charAt(o.outdir.length - 1) === '/' ? o.outdir : o.outdir + '/';
|
// o.dir: directory parent of the file currently in rendering process
|
||||||
_href = url.resolve(outdir, [o.dir, href].join('/'));
|
// o.outdir: directory parent from the html output
|
||||||
|
|
||||||
|
// Absolute file in source
|
||||||
|
_href = path.join(o.dir, _href);
|
||||||
|
|
||||||
|
// make it relative to output
|
||||||
|
_href = path.relative(o.outdir, _href);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
|
return GitBookRenderer.super_.prototype.image.call(this, _href, title, text);
|
||||||
|
|||||||
+14
-3
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "0.2.0",
|
"version": "0.2.3",
|
||||||
|
"homepage": "http://www.gitbook.io/",
|
||||||
"description": "Library and cmd utility to generate GitBooks",
|
"description": "Library and cmd utility to generate GitBooks",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -39,9 +40,19 @@
|
|||||||
"book",
|
"book",
|
||||||
"gitbook"
|
"gitbook"
|
||||||
],
|
],
|
||||||
"author": "Aaron O'Mullan <aaron.omullan@friendco.de>",
|
"author": "FriendCode <contact@friendco.de>",
|
||||||
"license": "Apache 2",
|
"license": "Apache 2",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/GitbookIO/gitbook/issues"
|
"url": "https://github.com/GitbookIO/gitbook/issues"
|
||||||
}
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Aaron O'Mullan",
|
||||||
|
"email": "aaron.omullan@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Samy Pessé",
|
||||||
|
"email": "samypesse@gmail.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 164 KiB |
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# Images Test
|
||||||
|
|
||||||
|
This is a test for images path calculation. It supposed this fiel is in a syntax/ folder
|
||||||
|
|
||||||
|
### #
|
||||||
|
|
||||||
|
[](./preview.png)
|
||||||
|
|
||||||
|
### 2
|
||||||
|
|
||||||
|
[](./preview2.png)
|
||||||
|
|
||||||
Vendored
+15
@@ -31,3 +31,18 @@ Some more nice content ....
|
|||||||
[Cool stuff](http://gitbook.io)
|
[Cool stuff](http://gitbook.io)
|
||||||
|
|
||||||
[Link to another Markdown file](./xyz/file.md)
|
[Link to another Markdown file](./xyz/file.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Quiz test 2: What does Gitbook support?
|
||||||
|
- [x] Table-based questions with radio buttons
|
||||||
|
- [x] Table-based questions with checkboxes
|
||||||
|
- [ ] Telepathy
|
||||||
|
- [x] List-based questions with checkboxes
|
||||||
|
- [x] List-based questions with radio buttons
|
||||||
|
- [ ] Moon-on-a-stick
|
||||||
|
|
||||||
|
> Gitbook supports table and list based quiz questions using either radio buttons or checkboxes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|||||||
+31
-4
@@ -28,6 +28,7 @@ describe('Page parsing', function() {
|
|||||||
assert.equal(QUIZ_LEXED[0].type, 'normal');
|
assert.equal(QUIZ_LEXED[0].type, 'normal');
|
||||||
assert.equal(QUIZ_LEXED[1].type, 'quiz');
|
assert.equal(QUIZ_LEXED[1].type, 'quiz');
|
||||||
assert.equal(QUIZ_LEXED[2].type, 'normal');
|
assert.equal(QUIZ_LEXED[2].type, 'normal');
|
||||||
|
assert.equal(QUIZ_LEXED[3].type, 'quiz');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should gen content for normal sections', function() {
|
it('should gen content for normal sections', function() {
|
||||||
@@ -35,10 +36,6 @@ describe('Page parsing', function() {
|
|||||||
assert(LEXED[2].content);
|
assert(LEXED[2].content);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should make image URLs relative', function() {
|
|
||||||
assert(LEXED[2].content.indexOf('_book/assets/my-pretty-picture.png') !== -1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should gen code and content for exercise sections', function() {
|
it('should gen code and content for exercise sections', function() {
|
||||||
assert(LEXED[1].content);
|
assert(LEXED[1].content);
|
||||||
assert(LEXED[1].code);
|
assert(LEXED[1].code);
|
||||||
@@ -93,3 +90,33 @@ describe('Relative links', function() {
|
|||||||
assert(LEXED[0].content.indexOf('https://github.com/GitBookIO/javascript/blob/src/something.cpp') !== -1);
|
assert(LEXED[0].content.indexOf('https://github.com/GitBookIO/javascript/blob/src/something.cpp') !== -1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Relative images', function() {
|
||||||
|
it('should keep image relative with considering output directory in site format', function() {
|
||||||
|
var LEXED = loadPage('IMAGES', {
|
||||||
|
// GitHub repo ID
|
||||||
|
repo: 'GitBookIO/javascript',
|
||||||
|
|
||||||
|
// Imaginary folder of markdown file
|
||||||
|
dir: 'syntax',
|
||||||
|
outdir: 'syntax'
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('"preview.png"') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('"../preview2.png"') !== -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should keep image relative with considering output directory in page format', function() {
|
||||||
|
var LEXED = loadPage('IMAGES', {
|
||||||
|
// GitHub repo ID
|
||||||
|
repo: 'GitBookIO/javascript',
|
||||||
|
|
||||||
|
// Imaginary folder of markdown file
|
||||||
|
dir: 'syntax',
|
||||||
|
outdir: './'
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(LEXED[0].content.indexOf('"syntax/preview.png"') !== -1);
|
||||||
|
assert(LEXED[0].content.indexOf('"preview2.png"') !== -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,3 +3,5 @@
|
|||||||
For creating a theme for GitBook, just copy this folder. The theme folder should at least contains two folders: `assets` and `templates`.
|
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>```
|
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
File diff suppressed because one or more lines are too long
@@ -10,12 +10,14 @@ define([
|
|||||||
var prev, next;
|
var prev, next;
|
||||||
var githubCountStars, githubCountWatch;
|
var githubCountStars, githubCountWatch;
|
||||||
|
|
||||||
|
var usePushState = !navigator.userAgent.match('CriOS') && (typeof history.pushState !== "undefined");
|
||||||
|
|
||||||
var updateHistory = function(url, title) {
|
var updateHistory = function(url, title) {
|
||||||
history.pushState({ path: url }, title, url);
|
history.pushState({ path: url }, title, url);
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleNavigation = function(url, push) {
|
var handleNavigation = function(url, push) {
|
||||||
if (typeof history.pushState === "undefined") {
|
if (!usePushState) {
|
||||||
// Refresh the page to the new URL if pushState not supported
|
// Refresh the page to the new URL if pushState not supported
|
||||||
location.href = url;
|
location.href = url;
|
||||||
return
|
return
|
||||||
@@ -23,6 +25,8 @@ define([
|
|||||||
|
|
||||||
return $.get(url)
|
return $.get(url)
|
||||||
.done(function (html) {
|
.done(function (html) {
|
||||||
|
if (push) updateHistory(url, null);
|
||||||
|
|
||||||
html = html.replace( /<(\/?)(html|head|body)([^>]*)>/ig, function(a,b,c,d){
|
html = html.replace( /<(\/?)(html|head|body)([^>]*)>/ig, function(a,b,c,d){
|
||||||
return '<' + b + 'div' + ( b ? '' : ' data-element="' + c + '"' ) + d + '>';
|
return '<' + b + 'div' + ( b ? '' : ' data-element="' + c + '"' ) + d + '>';
|
||||||
});
|
});
|
||||||
@@ -38,12 +42,17 @@ define([
|
|||||||
});
|
});
|
||||||
$("head").html(headContent);
|
$("head").html(headContent);
|
||||||
|
|
||||||
// Update header, body and summary
|
// Update header, body
|
||||||
$('.book-header').html($page.find('.book-header').html());
|
$('.book-header').html($page.find('.book-header').html());
|
||||||
$('.book-body').html($page.find('.book-body').html());
|
$('.book-body').html($page.find('.book-body').html());
|
||||||
$('.book-summary').html($page.find('.book-summary').html());
|
|
||||||
|
|
||||||
if (push) updateHistory(url, null);
|
// Update summary
|
||||||
|
var scrollPosition = $('.book-summary .summary').scrollTop();
|
||||||
|
$('.book-summary').html($page.find('.book-summary').html());
|
||||||
|
$('.book-summary .summary').scrollTop(scrollPosition);
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
state.update($("html"));
|
||||||
preparePage();
|
preparePage();
|
||||||
})
|
})
|
||||||
.fail(function () {
|
.fail(function () {
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ define([
|
|||||||
|
|
||||||
$quiz.find(".question").each(function(q) {
|
$quiz.find(".question").each(function(q) {
|
||||||
var result = true;
|
var result = true;
|
||||||
var $answers = $quiz.find(".question-answers").slice(q).find("input[type=radio], input[type=checkbox]");
|
|
||||||
$(this).find("input[type=radio],input[type=checkbox]").each(function(i) {
|
var $questions = $(this).find(".question-content").find("input[type=radio], input[type=checkbox]");
|
||||||
|
var $answers = $(this).find(".question-answers").find("input[type=radio], input[type=checkbox]");
|
||||||
|
|
||||||
|
$questions.each(function(i) {
|
||||||
var correct = $(this).is(":checked") === $answers.slice(i).first().is(":checked");
|
var correct = $(this).is(":checked") === $answers.slice(i).first().is(":checked");
|
||||||
result = result && correct;
|
result = result && correct;
|
||||||
if (!correct) {
|
if (!correct) {
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
define([
|
define([
|
||||||
"jQuery"
|
"jQuery"
|
||||||
], function() {
|
], function() {
|
||||||
var $book = $(".book");
|
var state = {};
|
||||||
|
|
||||||
return {
|
state.update = function(dom) {
|
||||||
'$book': $book,
|
var $book = $(dom.find(".book"));
|
||||||
|
|
||||||
'githubId': $book.data("github"),
|
state.$book = $book;
|
||||||
'level': $book.data("level"),
|
state.githubId = $book.data("github");
|
||||||
'basePath': $book.data("basepath"),
|
state.level = $book.data("level");
|
||||||
'revision': $book.data("revision")
|
state.basePath = $book.data("basepath");
|
||||||
|
state.revision = $book.data("revision");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state.update($);
|
||||||
|
|
||||||
|
return state;
|
||||||
});
|
});
|
||||||
@@ -1,13 +1,6 @@
|
|||||||
define([
|
define([
|
||||||
"lodash",
|
"lodash"
|
||||||
"mixpanel"
|
], function(_) {
|
||||||
], function(_, mixpanel) {
|
|
||||||
mixpanel.init("01eb2b950ae09a5fdb15a98dcc5ff20e", {
|
|
||||||
loaded: function() {
|
|
||||||
track("page.start");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var isAvailable = function() {
|
var isAvailable = function() {
|
||||||
return (
|
return (
|
||||||
typeof mixpanel !== "undefined" &&
|
typeof mixpanel !== "undefined" &&
|
||||||
@@ -15,9 +8,14 @@ define([
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
var track = function(e, data) {
|
var track = function(e, data, t) {
|
||||||
if (!isAvailable()) {
|
if (!isAvailable()) {
|
||||||
console.warn("tracking not available!");
|
console.warn("tracking not available!");
|
||||||
|
t = t || 500;
|
||||||
|
setTimeout(function() {
|
||||||
|
console.log(" -> retest tracking");
|
||||||
|
track(e, data, t*2);
|
||||||
|
}, t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("track", e);
|
console.log("track", e);
|
||||||
@@ -26,6 +24,11 @@ define([
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
mixpanel.init("01eb2b950ae09a5fdb15a98dcc5ff20e");
|
||||||
|
track("page.start");
|
||||||
|
}, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isAvailable: isAvailable,
|
isAvailable: isAvailable,
|
||||||
track: track
|
track: track
|
||||||
|
|||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
|
|
||||||
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
|
|
||||||
Executable → Regular
@@ -37,8 +37,6 @@
|
|||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
@import "variables.less";
|
@import "variables.less";
|
||||||
@import "fonts.less";
|
@import "fonts.less";
|
||||||
|
|
||||||
@import "highlight.less";
|
@import "book/highlight.less";
|
||||||
|
|
||||||
@import "book/languages.less";
|
@import "book/languages.less";
|
||||||
@import "book/header.less";
|
@import "book/header.less";
|
||||||
@import "book/summary.less";
|
@import "book/summary.less";
|
||||||
@@ -25,10 +24,6 @@
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control {
|
|
||||||
.box-shadow(none);
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
||||||
|
|
||||||
|
/* Tomorrow Comment */
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-title {
|
||||||
|
color: #8e908c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Red */
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-attribute,
|
||||||
|
.hljs-tag,
|
||||||
|
.hljs-regexp,
|
||||||
|
.ruby .hljs-constant,
|
||||||
|
.xml .hljs-tag .hljs-title,
|
||||||
|
.xml .hljs-pi,
|
||||||
|
.xml .hljs-doctype,
|
||||||
|
.html .hljs-doctype,
|
||||||
|
.css .hljs-id,
|
||||||
|
.css .hljs-class,
|
||||||
|
.css .hljs-pseudo {
|
||||||
|
color: #c82829;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Orange */
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-preprocessor,
|
||||||
|
.hljs-pragma,
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-literal,
|
||||||
|
.hljs-params,
|
||||||
|
.hljs-constant {
|
||||||
|
color: #f5871f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Yellow */
|
||||||
|
.ruby .hljs-class .hljs-title,
|
||||||
|
.css .hljs-rules .hljs-attribute {
|
||||||
|
color: #eab700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Green */
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-value,
|
||||||
|
.hljs-inheritance,
|
||||||
|
.hljs-header,
|
||||||
|
.ruby .hljs-symbol,
|
||||||
|
.xml .hljs-cdata {
|
||||||
|
color: #718c00;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Aqua */
|
||||||
|
.css .hljs-hexcolor {
|
||||||
|
color: #3e999f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Blue */
|
||||||
|
.hljs-function,
|
||||||
|
.python .hljs-decorator,
|
||||||
|
.python .hljs-title,
|
||||||
|
.ruby .hljs-function .hljs-title,
|
||||||
|
.ruby .hljs-title .hljs-keyword,
|
||||||
|
.perl .hljs-sub,
|
||||||
|
.javascript .hljs-title,
|
||||||
|
.coffeescript .hljs-title {
|
||||||
|
color: #4271ae;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tomorrow Purple */
|
||||||
|
.hljs-keyword,
|
||||||
|
.javascript .hljs-function {
|
||||||
|
color: #8959a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
background: white;
|
||||||
|
color: #4d4d4c;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coffeescript .javascript,
|
||||||
|
.javascript .xml,
|
||||||
|
.tex .hljs-formula,
|
||||||
|
.xml .javascript,
|
||||||
|
.xml .vbscript,
|
||||||
|
.xml .css,
|
||||||
|
.xml .hljs-cdata {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
@@ -1,8 +1,47 @@
|
|||||||
h1, h2 {
|
@import "vendors/bootstrap/bootstrap.less";
|
||||||
|
@import "vendors/fontawesome/font-awesome.less";
|
||||||
|
|
||||||
|
@import "mixins.less";
|
||||||
|
@import "variables.less";
|
||||||
|
@import "fonts.less";
|
||||||
|
|
||||||
|
@import "page/highlight.less";
|
||||||
|
|
||||||
|
|
||||||
|
@font-size-base: 13px;
|
||||||
|
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
font-smoothing: antialiased;
|
||||||
|
font-family: @font-family-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
page-break-after: avoid;
|
page-break-after: avoid;
|
||||||
page-break-before: auto;
|
page-break-before: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 { font-size: floor(@font-size-base * 2.15); }
|
||||||
|
h2 { font-size: floor(@font-size-base * 1.70); }
|
||||||
|
h3 { font-size: ceil(@font-size-base * 1.25); }
|
||||||
|
h4 { font-size: ceil(@font-size-base * 1); }
|
||||||
|
h5 { font-size: ceil(@font-size-base * 0.85); }
|
||||||
|
h6 { font-size: ceil(@font-size-base * 0.65); }
|
||||||
|
|
||||||
pre, blockquote {
|
pre, blockquote {
|
||||||
border: 1px solid #999;
|
border: 1px solid #999;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
@@ -26,41 +65,36 @@ section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&#summary {
|
&#summary {
|
||||||
text-align: center;
|
margin: 1.5cm;
|
||||||
|
|
||||||
ul {
|
h1 {
|
||||||
font-size: 0.5cm;
|
text-align: center;
|
||||||
line-height: 1.8em;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
list-style: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul {
|
ol {
|
||||||
> li {
|
list-style: none;
|
||||||
margin-bottom: 1cm;
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
margin-left: 1cm;
|
||||||
|
}
|
||||||
|
|
||||||
> a {
|
> ol {
|
||||||
font-size: 0.6cm;
|
> li {
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
margin: 1.5cm;
|
margin-bottom: 1.5cm;
|
||||||
|
|
||||||
/* Big centered title */
|
|
||||||
&.new-chapter {
|
&.new-chapter {
|
||||||
page-break-after: always;
|
page-break-after: always;
|
||||||
font-size: 0.6cm;
|
font-size: 0.6cm;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 3cm 0cm;
|
padding: 3cm 0cm;
|
||||||
|
|
||||||
border-top: 1px solid #ccc;
|
h1 {
|
||||||
|
font-size: floor(@font-size-base * 2.7);
|
||||||
@media print {
|
|
||||||
border: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,14 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% block content %}{% endblock %}
|
|
||||||
{% block style %}
|
{% block style %}
|
||||||
<link rel="stylesheet" href="{{ staticBase }}/style.css">
|
<link rel="stylesheet" href="{{ staticBase }}/style.css">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% block content %}{% endblock %}
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
|
<script 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/ace.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script>
|
||||||
<script src="{{ staticBase }}/jsrepl/jsrepl.js" id="jsrepl-script"></script>
|
<script src="{{ staticBase }}/jsrepl/jsrepl.js" id="jsrepl-script"></script>
|
||||||
|
|||||||
+47
-56
@@ -3,10 +3,32 @@
|
|||||||
{% block title %}{{ title }}{% endblock %}
|
{% block title %}{{ title }}{% endblock %}
|
||||||
|
|
||||||
{% block style %}
|
{% block style %}
|
||||||
{% parent %}
|
|
||||||
<link rel="stylesheet" href="{{ staticBase }}/print.css">
|
<link rel="stylesheet" href="{{ staticBase }}/print.css">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro articleContent(content) %}
|
||||||
|
{% for section in content %}
|
||||||
|
{% if section.type == "normal" %}
|
||||||
|
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
||||||
|
{% elif section.type == "exercise" %}
|
||||||
|
<div class="exercise">
|
||||||
|
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
||||||
|
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
||||||
|
<pre><code>{% autoescape false %}{{ section.code.base|code }}{% endautoescape %}</code></pre>
|
||||||
|
{% set exercise = exercise + 1 %}
|
||||||
|
</div>
|
||||||
|
{% elif section.type == "quiz" %}
|
||||||
|
<div class="quiz">
|
||||||
|
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
||||||
|
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
||||||
|
{% autoescape false %}{{ section.quiz.base }}{% endautoescape %}
|
||||||
|
{% set exercise = exercise + 1 %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% set exercise = 1 %}
|
{% set exercise = 1 %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{# Cover #}
|
{# Cover #}
|
||||||
@@ -19,87 +41,56 @@
|
|||||||
|
|
||||||
{# Summary #}
|
{# Summary #}
|
||||||
<section id="summary">
|
<section id="summary">
|
||||||
<h1>Summary</h1>
|
<h1>Table of Contents</h1>
|
||||||
|
<ol>
|
||||||
<ul class="summary">
|
|
||||||
<li>
|
<li>
|
||||||
<a href="#README.md">Introduction</a>
|
<a href="#README.md">
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% for item in summary.chapters %}
|
{% for item in summary.chapters %}
|
||||||
<li>
|
<li>
|
||||||
<a href="#{{ item.path }}">{{ item.level }}) {{ item.title }}</a>
|
<h2><span>{{ item.level }}.</span> <a href="#{{ item.path }}">{{ item.title }}</a></h2>
|
||||||
{% if item.articles.length > 0 %}
|
{% if item.articles.length > 0 %}
|
||||||
<ul>
|
<ol>
|
||||||
{% for article in item.articles %}
|
{% for article in item.articles %}
|
||||||
<li>
|
<li>
|
||||||
<a href="#{{ article.path }}">{{ article.level }}) {{ article.title }}</a>
|
<span>{{ article.level }}</span> <a href="#{{ article.path }}">{{ article.title }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ol>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{# Pages content #}
|
{# Pages content #}
|
||||||
<section>
|
<section>
|
||||||
<article id="README.md">
|
<article id="README.md">
|
||||||
{% for section in pages["README.md"].content %}
|
{{ articleContent(pages["README.md"].content) }}
|
||||||
{% if section.type == "normal" %}
|
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
|
||||||
{% elif section.type == "exercise" %}
|
|
||||||
<div class="exercise">
|
|
||||||
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
|
||||||
<pre><code>{% autoescape false %}{{ section.code.base|code }}{% endautoescape %}</code></pre>
|
|
||||||
{% set exercise = exercise + 1 %}
|
|
||||||
</div>
|
|
||||||
{% elif section.type == "quiz" %}
|
|
||||||
<div class="quiz">
|
|
||||||
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
|
||||||
{% autoescape false %}{{ section.quiz.base }}{% endautoescape %}
|
|
||||||
{% set exercise = exercise + 1 %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
{% for item in summary.chapters %}
|
{% for item in summary.chapters %}
|
||||||
{% if item.articles.length > 0 %}
|
|
||||||
<section>
|
<section>
|
||||||
<article id="{{ item.path }}" class="new-chapter">
|
<article id="{{ item.path }}" class="new-chapter">
|
||||||
<h1>{{ item.title }}</h1>
|
<h1>{{ item.title }}</h1>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{% for article in item.articles %}
|
<article>
|
||||||
{% if pages[article.path] %}
|
{{ articleContent(pages[item.path].content) }}
|
||||||
<article id="{{ article.path }}">
|
</article>
|
||||||
{% for section in pages[article.path].content %}
|
|
||||||
{% if section.type == "normal" %}
|
{% if item.articles.length > 0 %}
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
{% for article in item.articles %}
|
||||||
{% elif section.type == "exercise" %}
|
{% if pages[article.path] %}
|
||||||
<div class="exercise">
|
<article id="{{ article.path }}">
|
||||||
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
{{ articleContent(pages[article.path].content) }}
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
</article>
|
||||||
<pre><code>{% autoescape false %}{{ section.code.base|code }}{% endautoescape %}</code></pre>
|
{% endif %}
|
||||||
{% set exercise = exercise + 1 %}
|
{% endfor %}
|
||||||
</div>
|
{% endif %}
|
||||||
{% elif section.type == "quiz" %}
|
|
||||||
<div class="quiz">
|
|
||||||
<div class="exercise-header">Exercise #{{ exercise }}</div>
|
|
||||||
{% autoescape false %}{{ section.content }}{% endautoescape %}
|
|
||||||
{% autoescape false %}{{ section.quiz.base }}{% endautoescape %}
|
|
||||||
{% set exercise = exercise + 1 %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</article>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user