From a10a2684d98c636f9dd516b3a33ce6bc05eaf9a6 Mon Sep 17 00:00:00 2001 From: ismay Date: Sun, 7 Apr 2019 12:36:09 +0200 Subject: [PATCH] Allow async transforms --- lib/index.js | 108 +++++++++++++++++++++------------------------------ lib/util.js | 23 +++++++++++ 2 files changed, 68 insertions(+), 63 deletions(-) create mode 100644 lib/util.js diff --git a/lib/index.js b/lib/index.js index e89c89e..76a0853 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,79 +1,61 @@ const debug = require('debug')('metalsmith-in-place'); const match = require('multimatch'); const isUtf8 = require('is-utf8'); -const jstransformer = require('jstransformer'); -const toTransformer = require('inputformat-to-jstransformer'); +const { getTransformer } = require('./util'); /** - * Gets jstransformer for an extension, and caches them + * Engine, renders file contents with all available transformers */ -const cache = {}; - -function getTransformer(ext) { - if (ext in cache) { - return cache[ext]; - } +function render({ filename, files, metadata, engineOptions }) { + const [base, ...extensions] = filename.split('.'); + const file = files[filename]; - const transformer = toTransformer(ext); - cache[ext] = transformer ? jstransformer(transformer) : false; + debug(`rendering ${filename}`); - return cache[ext]; -} + const ext = extensions.pop(); + const transform = getTransformer(ext); + const locals = Object.assign({}, metadata, file); -/** - * Engine, renders file contents with all available transformers - */ + // Stop if the current extension can't be transformed + if (!transform) { + debug(`no transformer available for ${ext} extension for ${filename}`); + extensions.push(ext); + return Promise.resolve(); + } -function render({ filename, files, metadata, engineOptions }) { - return new Promise((resolve, reject) => { - const [base, ...extensions] = filename.split('.'); - const file = files[filename]; - - debug(`rendering ${filename}`); - - // Stringify file contents - file.contents = file.contents.toString(); - - // Go through all extensions - const extLength = extensions.length; - for (let i = 0; i < extLength; i += 1) { - const ext = extensions.pop(); - const transform = getTransformer(ext); - const locals = Object.assign({}, metadata, file); - - // Stop if the current extension can't be transformed - if (!transform) { - debug(`no transformer available for ${ext} extension for ${filename}`); - extensions.push(ext); - break; - } - - // If this is the last extension, replace it with a new one - if (extensions.length === 0) { - debug(`last extension reached, replacing last extension with ${transform.outputFormat}`); - extensions.push(transform.outputFormat); - } - - // Transform the contents - debug(`rendering ${ext} extension for ${filename}`); - try { - file.contents = transform.render(file.contents, engineOptions, locals).body; - } catch (err) { - err.message = `${filename}: ${err.message}`; - return reject(err); - } - } + // Stringify file contents + file.contents = file.contents.toString(); - // Store results and delete old file - file.contents = Buffer.from(file.contents); - const newName = [base, ...extensions].join('.'); - files[newName] = file; // eslint-disable-line no-param-reassign - delete files[filename]; // eslint-disable-line no-param-reassign + // If this is the last extension, replace it with a new one + if (extensions.length === 0) { + debug(`last extension reached, replacing last extension with ${transform.outputFormat}`); + extensions.push(transform.outputFormat); + } - debug(`done rendering ${filename}, renamed to ${newName}`); - return resolve(); - }); + // Transform the contents + debug(`rendering ${ext} extension for ${filename}`); + + return transform + .renderAsync(file.contents, engineOptions, locals) + .then(rendered => { + // Update contents and delete old file + file.contents = Buffer.from(rendered.body); + delete files[filename]; // eslint-disable-line no-param-reassign + + // Update files with the newly rendered file + const newName = [base, ...extensions].join('.'); + files[newName] = file; // eslint-disable-line no-param-reassign + + debug(`done rendering ${filename}, renamed to ${newName}`); + + // Keep rendering until there are no applicable transformers left + return render({ filename: newName, files, metadata, engineOptions }); + }) + .catch(err => { + err.message = `${filename}: ${err.message}`; // eslint-disable-line no-param-reassign + throw err; + }); } /** diff --git a/lib/util.js b/lib/util.js new file mode 100644 index 0000000..75a6401 --- /dev/null +++ b/lib/util.js @@ -0,0 +1,23 @@ +const jstransformer = require('jstransformer'); +const toTransformer = require('inputformat-to-jstransformer'); + +/** + * Gets jstransformer for an extension, and caches them + */ + +const cache = {}; + +function getTransformer(ext) { + if (ext in cache) { + return cache[ext]; + } + + const transformer = toTransformer(ext); + cache[ext] = transformer ? jstransformer(transformer) : false; + + return cache[ext]; +} + +module.exports = { + getTransformer +};