diff options
author | Samy Pessé <samypesse@gmail.com> | 2014-07-10 17:59:34 -0700 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2014-07-10 17:59:34 -0700 |
commit | a9f473260cdbf7944a8d95c4292a93897f9210eb (patch) | |
tree | 83e78b9028850606722da6ec66c45e453ee28693 | |
parent | 520045441b9401fadfba2b1b03696bd15b60027d (diff) | |
parent | d16577e8bf2e404cbc2cabb78fc1bf6c8a36d3ea (diff) | |
download | gitbook-a9f473260cdbf7944a8d95c4292a93897f9210eb.zip gitbook-a9f473260cdbf7944a8d95c4292a93897f9210eb.tar.gz gitbook-a9f473260cdbf7944a8d95c4292a93897f9210eb.tar.bz2 |
Merge pull request #356 from GitbookIO/feature/includes
Support importing code snippets
-rw-r--r-- | lib/parse/code_include.js | 20 | ||||
-rw-r--r-- | lib/parse/page.js | 12 | ||||
-rw-r--r-- | lib/parse/renderer.js | 13 | ||||
-rw-r--r-- | test/fixtures/INCLUDES.md | 29 | ||||
-rw-r--r-- | test/fixtures/included.c | 7 | ||||
-rw-r--r-- | test/includes.js | 38 |
6 files changed, 115 insertions, 4 deletions
diff --git a/lib/parse/code_include.js b/lib/parse/code_include.js new file mode 100644 index 0000000..f4656f1 --- /dev/null +++ b/lib/parse/code_include.js @@ -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; + }); +}; diff --git a/lib/parse/page.js b/lib/parse/page.js index 6cfd3ca..d714a15 100644 --- a/lib/parse/page.js +++ b/lib/parse/page.js @@ -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; @@ -74,15 +75,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, } diff --git a/lib/parse/renderer.js b/lib/parse/renderer.js index 397ab80..dcbc261 100644 --- a/lib/parse/renderer.js +++ b/lib/parse/renderer.js @@ -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'); @@ -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,15 @@ 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 + ); +}; + // Exports module.exports = GitBookRenderer; diff --git a/test/fixtures/INCLUDES.md b/test/fixtures/INCLUDES.md new file mode 100644 index 0000000..22e3a61 --- /dev/null +++ b/test/fixtures/INCLUDES.md @@ -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 ? +``` + +---- diff --git a/test/fixtures/included.c b/test/fixtures/included.c new file mode 100644 index 0000000..d9323e3 --- /dev/null +++ b/test/fixtures/included.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) { + printf("All is well\n"); + + return 0; +} diff --git a/test/includes.js b/test/includes.js new file mode 100644 index 0000000..69adc11 --- /dev/null +++ b/test/includes.js @@ -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()); + }); +}); |