diff options
Diffstat (limited to 'lib/templating')
-rw-r--r-- | lib/templating/__tests__/conrefsLoader.js | 98 | ||||
-rw-r--r-- | lib/templating/__tests__/include.md | 1 | ||||
-rw-r--r-- | lib/templating/__tests__/postRender.js | 51 | ||||
-rw-r--r-- | lib/templating/__tests__/replaceShortcuts.js | 27 | ||||
-rw-r--r-- | lib/templating/conrefsLoader.js | 93 | ||||
-rw-r--r-- | lib/templating/index.js | 10 | ||||
-rw-r--r-- | lib/templating/listShortcuts.js | 31 | ||||
-rw-r--r-- | lib/templating/postRender.js | 53 | ||||
-rw-r--r-- | lib/templating/render.js | 44 | ||||
-rw-r--r-- | lib/templating/renderFile.js | 41 | ||||
-rw-r--r-- | lib/templating/replaceShortcuts.js | 39 | ||||
-rw-r--r-- | lib/templating/themesLoader.js | 115 |
12 files changed, 0 insertions, 603 deletions
diff --git a/lib/templating/__tests__/conrefsLoader.js b/lib/templating/__tests__/conrefsLoader.js deleted file mode 100644 index 196b513..0000000 --- a/lib/templating/__tests__/conrefsLoader.js +++ /dev/null @@ -1,98 +0,0 @@ -var path = require('path'); - -var TemplateEngine = require('../../models/templateEngine'); -var renderTemplate = require('../render'); -var ConrefsLoader = require('../conrefsLoader'); - -describe('ConrefsLoader', function() { - var dirName = __dirname + '/'; - var fileName = path.join(dirName, 'test.md'); - - describe('Git', function() { - var engine = TemplateEngine({ - loader: new ConrefsLoader(dirName) - }); - - it('should include content from git', function() { - return renderTemplate(engine, fileName, '{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('Hello from git'); - }); - }); - - it('should handle deep inclusion (1)', function() { - return renderTemplate(engine, fileName, '{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('First Hello. Hello from git'); - }); - }); - - it('should handle deep inclusion (2)', function() { - return renderTemplate(engine, fileName, '{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('First Hello. Hello from git'); - }); - }); - }); - - describe('Local', function() { - var engine = TemplateEngine({ - loader: new ConrefsLoader(dirName) - }); - - describe('Relative', function() { - it('should resolve basic relative filepath', function() { - return renderTemplate(engine, fileName, '{% include "include.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('Hello World'); - }); - }); - - it('should resolve basic parent filepath', function() { - return renderTemplate(engine, path.join(dirName, 'hello/test.md'), '{% include "../include.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('Hello World'); - }); - }); - }); - - describe('Absolute', function() { - it('should resolve absolute filepath', function() { - return renderTemplate(engine, fileName, '{% include "/include.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('Hello World'); - }); - }); - - it('should resolve absolute filepath when in a directory', function() { - return renderTemplate(engine, path.join(dirName, 'hello/test.md'), '{% include "/include.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('Hello World'); - }); - }); - }); - }); - - describe('transform', function() { - function transform(filePath, source) { - expect(filePath).toBeA('string'); - expect(source).toBeA('string'); - - expect(filePath).toBe(path.resolve(__dirname, 'include.md')); - expect(source).toBe('Hello World'); - - return 'test-' + source + '-endtest'; - } - var engine = TemplateEngine({ - loader: new ConrefsLoader(dirName, transform) - }); - - it('should transform included content', function() { - return renderTemplate(engine, fileName, '{% include "include.md" %}') - .then(function(out) { - expect(out.getContent()).toBe('test-Hello World-endtest'); - }); - }); - }); -}); - diff --git a/lib/templating/__tests__/include.md b/lib/templating/__tests__/include.md deleted file mode 100644 index 5e1c309..0000000 --- a/lib/templating/__tests__/include.md +++ /dev/null @@ -1 +0,0 @@ -Hello World
\ No newline at end of file diff --git a/lib/templating/__tests__/postRender.js b/lib/templating/__tests__/postRender.js deleted file mode 100644 index 131e29b..0000000 --- a/lib/templating/__tests__/postRender.js +++ /dev/null @@ -1,51 +0,0 @@ -var TemplateEngine = require('../../models/templateEngine'); -var TemplateBlock = require('../../models/templateBlock'); - -var renderTemplate = require('../render'); -var postRender = require('../postRender'); - -describe('postRender', function() { - var testPost; - var engine = TemplateEngine.create({ - blocks: [ - TemplateBlock.create('lower', function(blk) { - return blk.body.toLowerCase(); - }), - TemplateBlock.create('prefix', function(blk) { - return { - body: '_' + blk.body + '_', - post: function() { - testPost = true; - } - }; - }) - ] - }); - - it('should correctly replace block', function() { - return renderTemplate(engine, 'README.md', 'Hello {% lower %}Samy{% endlower %}') - .then(function(output) { - expect(output.getContent()).toMatch(/Hello \{\{\-([\S]+)\-\}\}/); - expect(output.getBlocks().size).toBe(1); - - return postRender(engine, output); - }) - .then(function(result) { - expect(result).toBe('Hello samy'); - }); - }); - - it('should correctly replace blocks', function() { - return renderTemplate(engine, 'README.md', 'Hello {% lower %}Samy{% endlower %}{% prefix %}Pesse{% endprefix %}') - .then(function(output) { - expect(output.getContent()).toMatch(/Hello \{\{\-([\S]+)\-\}\}\{\{\-([\S]+)\-\}\}/); - expect(output.getBlocks().size).toBe(2); - return postRender(engine, output); - }) - .then(function(result) { - expect(result).toBe('Hello samy_Pesse_'); - expect(testPost).toBe(true); - }); - }); - -}); diff --git a/lib/templating/__tests__/replaceShortcuts.js b/lib/templating/__tests__/replaceShortcuts.js deleted file mode 100644 index 216a1c8..0000000 --- a/lib/templating/__tests__/replaceShortcuts.js +++ /dev/null @@ -1,27 +0,0 @@ -var Immutable = require('immutable'); - -var TemplateBlock = require('../../models/templateBlock'); -var replaceShortcuts = require('../replaceShortcuts'); - -describe('replaceShortcuts', function() { - var blocks = Immutable.List([ - TemplateBlock.create('math', { - shortcuts: { - start: '$$', - end: '$$', - parsers: ['markdown'] - } - }) - ]); - - it('should correctly replace inline matches by block', function() { - var content = replaceShortcuts(blocks, 'test.md', 'Hello $$a = b$$'); - expect(content).toBe('Hello {% math %}a = b{% endmath %}'); - }); - - it('should correctly replace block matches', function() { - var content = replaceShortcuts(blocks, 'test.md', 'Hello\n$$\na = b\n$$\n'); - expect(content).toBe('Hello\n{% math %}\na = b\n{% endmath %}\n'); - }); -}); - diff --git a/lib/templating/conrefsLoader.js b/lib/templating/conrefsLoader.js deleted file mode 100644 index b3cdb3f..0000000 --- a/lib/templating/conrefsLoader.js +++ /dev/null @@ -1,93 +0,0 @@ -var path = require('path'); -var nunjucks = require('nunjucks'); - -var fs = require('../utils/fs'); -var Git = require('../utils/git'); -var LocationUtils = require('../utils/location'); -var PathUtils = require('../utils/path'); - - -/** - * Template loader resolving both: - * - relative url ("./test.md") - * - absolute url ("/test.md") - * - git url ("") - * - * @param {String} rootFolder - * @param {Function(filePath, source)} transformFn (optional) - * @param {Logger} logger (optional) - */ -var ConrefsLoader = nunjucks.Loader.extend({ - async: true, - - init: function(rootFolder, transformFn, logger) { - this.rootFolder = rootFolder; - this.transformFn = transformFn; - this.logger = logger; - this.git = new Git(); - }, - - getSource: function(sourceURL, callback) { - var that = this; - - this.git.resolve(sourceURL) - .then(function(filepath) { - // Is local file - if (!filepath) { - filepath = path.resolve(sourceURL); - } else { - if (that.logger) that.logger.debug.ln('resolve from git', sourceURL, 'to', filepath); - } - - // Read file from absolute path - return fs.readFile(filepath) - .then(function(source) { - source = source.toString('utf8'); - - if (that.transformFn) { - return that.transformFn(filepath, source); - } - - return source; - }) - .then(function(source) { - return { - src: source, - path: filepath - }; - }); - }) - .nodeify(callback); - }, - - resolve: function(from, to) { - // If origin is in the book, we enforce result file to be in the book - if (PathUtils.isInRoot(this.rootFolder, from)) { - - // Path of current template in the rootFolder (not absolute to fs) - var fromRelative = path.relative(this.rootFolder, from); - - // Resolve "to" to a filepath relative to rootFolder - var href = LocationUtils.toAbsolute(to, path.dirname(fromRelative), ''); - - // Return absolute path - return PathUtils.resolveInRoot(this.rootFolder, href); - } - - // If origin is in a git repository, we resolve file in the git repository - var gitRoot = this.git.resolveRoot(from); - if (gitRoot) { - return PathUtils.resolveInRoot(gitRoot, to); - } - - // If origin is not in the book (include from a git content ref) - return path.resolve(path.dirname(from), to); - }, - - // Handle all files as relative, so that nunjucks pass responsability to 'resolve' - isRelative: function(filename) { - return LocationUtils.isRelative(filename); - } -}); - -module.exports = ConrefsLoader; diff --git a/lib/templating/index.js b/lib/templating/index.js deleted file mode 100644 index bd74aca..0000000 --- a/lib/templating/index.js +++ /dev/null @@ -1,10 +0,0 @@ - -module.exports = { - render: require('./render'), - renderFile: require('./renderFile'), - postRender: require('./postRender'), - replaceShortcuts: require('./replaceShortcuts'), - - ConrefsLoader: require('./conrefsLoader'), - ThemesLoader: require('./themesLoader') -}; diff --git a/lib/templating/listShortcuts.js b/lib/templating/listShortcuts.js deleted file mode 100644 index 8d0a64a..0000000 --- a/lib/templating/listShortcuts.js +++ /dev/null @@ -1,31 +0,0 @@ -var Immutable = require('immutable'); -var parsers = require('../parsers'); - -/** - * Return a list of all shortcuts that can apply - * to a file for a TemplatEngine - * - * @param {List<TemplateBlock>} engine - * @param {String} filePath - * @return {List<TemplateShortcut>} - */ -function listShortcuts(blocks, filePath) { - var parser = parsers.getForFile(filePath); - - if (!parser) { - return Immutable.List(); - } - - return blocks - .map(function(block) { - return block.getShortcuts(); - }) - .filter(function(shortcuts) { - return ( - shortcuts && - shortcuts.acceptParser(parser.getName()) - ); - }); -} - -module.exports = listShortcuts; diff --git a/lib/templating/postRender.js b/lib/templating/postRender.js deleted file mode 100644 index f464f86..0000000 --- a/lib/templating/postRender.js +++ /dev/null @@ -1,53 +0,0 @@ -var Promise = require('../utils/promise'); - - -/** - * Replace position markers of blocks by body after processing - * This is done to avoid that markdown/asciidoc processer parse the block content - * - * @param {String} content - * @return {Object} {blocks: Set, content: String} - */ -function replaceBlocks(content, blocks) { - var newContent = content.replace(/\{\{\-\%([\s\S]+?)\%\-\}\}/g, function(match, key) { - var replacedWith = match; - - var block = blocks.get(key); - if (block) { - replacedWith = replaceBlocks(block.get('body'), blocks); - } - - return replacedWith; - }); - - return newContent; -} - -/** - * Post render a template: - * - Execute "post" for blocks - * - Replace block content - * - * @param {TemplateEngine} engine - * @param {TemplateOutput} content - * @return {Promise<String>} - */ -function postRender(engine, output) { - var content = output.getContent(); - var blocks = output.getBlocks(); - - var result = replaceBlocks(content, blocks); - - return Promise.forEach(blocks, function(block) { - var post = block.get('post'); - - if (!post) { - return; - } - - return post(); - }) - .thenResolve(result); -} - -module.exports = postRender; diff --git a/lib/templating/render.js b/lib/templating/render.js deleted file mode 100644 index 1a8b0cd..0000000 --- a/lib/templating/render.js +++ /dev/null @@ -1,44 +0,0 @@ -var Promise = require('../utils/promise'); -var timing = require('../utils/timing'); -var TemplateOutput = require('../models/templateOutput'); -var replaceShortcuts = require('./replaceShortcuts'); - -/** - * Render a template - * - * @param {TemplateEngine} engine - * @param {String} filePath: absolute path for the loader - * @param {String} content - * @param {Object} context (optional) - * @return {Promise<TemplateOutput>} - */ -function renderTemplate(engine, filePath, content, context) { - context = context || {}; - - // Mutable objects to contains all blocks requiring post-processing - var blocks = {}; - - // Create nunjucks environment - var env = engine.toNunjucks(blocks); - - // Replace shortcuts from plugin's blocks - content = replaceShortcuts(engine.getBlocks(), filePath, content); - - return timing.measure( - 'template.render', - - Promise.nfcall( - env.renderString.bind(env), - content, - context, - { - path: filePath - } - ) - .then(function(content) { - return TemplateOutput.create(content, blocks); - }) - ); -} - -module.exports = renderTemplate; diff --git a/lib/templating/renderFile.js b/lib/templating/renderFile.js deleted file mode 100644 index 8672e8b..0000000 --- a/lib/templating/renderFile.js +++ /dev/null @@ -1,41 +0,0 @@ -var Promise = require('../utils/promise'); -var error = require('../utils/error'); -var render = require('./render'); - -/** - * Render a template - * - * @param {TemplateEngine} engine - * @param {String} filePath - * @param {Object} context - * @return {Promise<TemplateOutput>} - */ -function renderTemplateFile(engine, filePath, context) { - var loader = engine.getLoader(); - - // Resolve the filePath - var resolvedFilePath = loader.resolve(null, filePath); - - return Promise() - .then(function() { - if (!loader.async) { - return loader.getSource(resolvedFilePath); - } - - var deferred = Promise.defer(); - loader.getSource(resolvedFilePath, deferred.makeNodeResolver()); - return deferred.promise; - }) - .then(function(result) { - if (!result) { - throw error.TemplateError(new Error('Not found'), { - filename: filePath - }); - } - - return render(engine, result.path, result.src, context); - }); - -} - -module.exports = renderTemplateFile; diff --git a/lib/templating/replaceShortcuts.js b/lib/templating/replaceShortcuts.js deleted file mode 100644 index 1cfdbf0..0000000 --- a/lib/templating/replaceShortcuts.js +++ /dev/null @@ -1,39 +0,0 @@ -var escapeStringRegexp = require('escape-string-regexp'); -var listShortcuts = require('./listShortcuts'); - -/** - * Apply a shortcut of block to a template - * @param {String} content - * @param {Shortcut} shortcut - * @return {String} - */ -function applyShortcut(content, shortcut) { - var start = shortcut.getStart(); - var end = shortcut.getEnd(); - - var tagStart = shortcut.getStartTag(); - var tagEnd = shortcut.getEndTag(); - - var regex = new RegExp( - escapeStringRegexp(start) + '([\\s\\S]*?[^\\$])' + escapeStringRegexp(end), - 'g' - ); - return content.replace(regex, function(all, match) { - return '{% ' + tagStart + ' %}' + match + '{% ' + tagEnd + ' %}'; - }); -} - -/** - * Replace shortcuts from blocks in a string - * - * @param {List<TemplateBlock>} engine - * @param {String} filePath - * @param {String} content - * @return {String} - */ -function replaceShortcuts(blocks, filePath, content) { - var shortcuts = listShortcuts(blocks, filePath); - return shortcuts.reduce(applyShortcut, content); -} - -module.exports = replaceShortcuts; diff --git a/lib/templating/themesLoader.js b/lib/templating/themesLoader.js deleted file mode 100644 index bae4c12..0000000 --- a/lib/templating/themesLoader.js +++ /dev/null @@ -1,115 +0,0 @@ -var Immutable = require('immutable'); -var nunjucks = require('nunjucks'); -var fs = require('fs'); -var path = require('path'); - -var PathUtils = require('../utils/path'); - - -var ThemesLoader = nunjucks.Loader.extend({ - init: function(searchPaths) { - this.searchPaths = Immutable.List(searchPaths) - .map(path.normalize); - }, - - /** - * Read source of a resolved filepath - * @param {String} - * @return {Object} - */ - getSource: function(fullpath) { - if (!fullpath) return null; - - fullpath = this.resolve(null, fullpath); - var templateName = this.getTemplateName(fullpath); - - if(!fullpath) { - return null; - } - - var src = fs.readFileSync(fullpath, 'utf-8'); - - src = '{% do %}var template = template || {}; template.stack = template.stack || []; template.stack.push(template.self); template.self = ' + JSON.stringify(templateName) + '{% enddo %}\n' + - src + - '\n{% do %}template.self = template.stack.pop();{% enddo %}'; - - return { - src: src, - path: fullpath, - noCache: true - }; - }, - - /** - * Nunjucks calls "isRelative" to determine when to call "resolve". - * We handle absolute paths ourselves in ".resolve" so we always return true - */ - isRelative: function() { - return true; - }, - - /** - * Get original search path containing a template - * @param {String} filepath - * @return {String} searchPath - */ - getSearchPath: function(filepath) { - return this.searchPaths - .sortBy(function(s) { - return -s.length; - }) - .find(function(basePath) { - return (filepath && filepath.indexOf(basePath) === 0); - }); - }, - - /** - * Get template name from a filepath - * @param {String} filepath - * @return {String} name - */ - getTemplateName: function(filepath) { - var originalSearchPath = this.getSearchPath(filepath); - return originalSearchPath? path.relative(originalSearchPath, filepath) : null; - }, - - /** - * Resolve a template from a current template - * @param {String|null} from - * @param {String} to - * @return {String|null} - */ - resolve: function(from, to) { - var searchPaths = this.searchPaths; - - // Relative template like "./test.html" - if (PathUtils.isPureRelative(to) && from) { - return path.resolve(path.dirname(from), to); - } - - // Determine in which search folder we currently are - var originalSearchPath = this.getSearchPath(from); - var originalFilename = this.getTemplateName(from); - - // If we are including same file from a different search path - // Slice the search paths to avoid including from previous ones - if (originalFilename == to) { - var currentIndex = searchPaths.indexOf(originalSearchPath); - searchPaths = searchPaths.slice(currentIndex + 1); - } - - // Absolute template to resolve in root folder - var resultFolder = searchPaths.find(function(basePath) { - var p = path.resolve(basePath, to); - - return ( - p.indexOf(basePath) === 0 - && fs.existsSync(p) - ); - }); - if (!resultFolder) return null; - return path.resolve(resultFolder, to); - } -}); - -module.exports = ThemesLoader; |