Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow async transforms #166

Merged
merged 1 commit into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 45 additions & 63 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -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;
});
}

/**
Expand Down
23 changes: 23 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
@@ -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
};