From ca7f9ca1ce17a7a5d02dfb661067c35188e733a0 Mon Sep 17 00:00:00 2001 From: ismay Date: Sun, 14 Apr 2019 13:23:37 +0200 Subject: [PATCH 1/2] Add set filename option --- lib/index.js | 37 +++++++++++-------- lib/index.test.js | 17 +++++++++ package.json | 1 + .../fixtures/set-filename/expected/index.html | 1 + test/fixtures/set-filename/src/index.pug | 4 ++ test/fixtures/set-filename/templates/base.pug | 4 ++ 6 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 test/fixtures/set-filename/expected/index.html create mode 100644 test/fixtures/set-filename/src/index.pug create mode 100644 test/fixtures/set-filename/templates/base.pug diff --git a/lib/index.js b/lib/index.js index 67d6ed5..4850e6d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,3 +1,4 @@ +const path = require('path'); const debug = require('debug')('metalsmith-in-place'); const match = require('multimatch'); const isUtf8 = require('is-utf8'); @@ -7,9 +8,11 @@ const getTransformer = require('./get-transformer'); * Engine, renders file contents with all available transformers */ -function render({ filename, files, metadata, engineOptions }) { +function render({ filename, files, metalsmith, settings }) { const [base, ...extensions] = filename.split('.'); const file = files[filename]; + const engineOptions = Object.assign({}, settings.engineOptions); + const metadata = metalsmith.metadata(); debug(`rendering ${filename}`); @@ -24,7 +27,7 @@ function render({ filename, files, metadata, engineOptions }) { } // Stringify file contents - file.contents = file.contents.toString(); + const contents = file.contents.toString(); // If this is the last extension, replace it with a new one if (extensions.length === 0) { @@ -32,24 +35,30 @@ function render({ filename, files, metadata, engineOptions }) { extensions.push(transform.outputFormat); } + // Check if the filename should be set in the engine options + if (settings.setFilename) { + debug(`setting filename in the engine options`); + engineOptions.filename = path.join(metalsmith.source(), filename); + } + // Transform the contents debug(`rendering ${ext} extension for ${filename}`); return transform - .renderAsync(file.contents, engineOptions, locals) + .renderAsync(contents, engineOptions, locals) .then(rendered => { - // Update contents and delete old file - file.contents = Buffer.from(rendered.body); + // Delete old file 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 + files[newName].contents = Buffer.from(rendered.body); // 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 }); + return render({ filename: newName, files, metalsmith, settings }); }) .catch(err => { err.message = `${filename}: ${err.message}`; // eslint-disable-line no-param-reassign @@ -95,10 +104,10 @@ module.exports = options => (files, metalsmith, done) => { const defaults = { pattern: '**', engineOptions: {}, - suppressNoFilesError: false + suppressNoFilesError: false, + setFilename: false }; const settings = Object.assign({}, defaults, options); - const metadata = metalsmith.metadata(); // Check whether the pattern option is valid if (!(typeof settings.pattern === 'string' || Array.isArray(settings.pattern))) { @@ -116,22 +125,18 @@ module.exports = options => (files, metalsmith, done) => { // Let the user know when there are no files to process, usually caused by missing jstransformer if (validFiles.length === 0) { - const msg = + const message = 'no files to process. See https://www.npmjs.com/package/metalsmith-in-place#no-files-to-process'; if (settings.suppressNoFilesError) { - debug(msg); + debug(message); done(); } else { - done(new Error(msg)); + done(new Error(message)); } } // Map all files that should be processed to an array of promises and call done when finished - Promise.all( - validFiles.map(filename => - render({ filename, files, metadata, engineOptions: settings.engineOptions }) - ) - ) + Promise.all(validFiles.map(filename => render({ filename, files, metalsmith, settings }))) .then(() => done()) .catch(/* istanbul ignore next */ error => done(error)); }; diff --git a/lib/index.test.js b/lib/index.test.js index 03e251e..12f12c3 100644 --- a/lib/index.test.js +++ b/lib/index.test.js @@ -236,4 +236,21 @@ describe('metalsmith-in-place', () => { done(); }); }); + + it('should accept an option to set the filename in engine options', done => { + const base = path.join(process.cwd(), 'test', 'fixtures', 'set-filename'); + const actual = path.join(base, 'build'); + const expected = path.join(base, 'expected'); + const metalsmith = new Metalsmith(base); + + rimraf.sync(actual); + + return metalsmith.use(plugin({ setFilename: true })).build(err => { + if (err) { + return done(err); + } + expect(() => equal(actual, expected)).not.toThrow(); + return done(); + }); + }); }); diff --git a/package.json b/package.json index 75783ef..2653b01 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "inputformat-to-jstransformer": "^1.2.1", "is-utf8": "^0.2.1", "jstransformer": "^1.0.0", + "jstransformer-pug": "^0.3.0", "multimatch": "^3.0.0" } } diff --git a/test/fixtures/set-filename/expected/index.html b/test/fixtures/set-filename/expected/index.html new file mode 100644 index 0000000..a688c05 --- /dev/null +++ b/test/fixtures/set-filename/expected/index.html @@ -0,0 +1 @@ +

This is a heading

\ No newline at end of file diff --git a/test/fixtures/set-filename/src/index.pug b/test/fixtures/set-filename/src/index.pug new file mode 100644 index 0000000..fd3634f --- /dev/null +++ b/test/fixtures/set-filename/src/index.pug @@ -0,0 +1,4 @@ +extends ../templates/base.pug + +block content + h1 This is a heading diff --git a/test/fixtures/set-filename/templates/base.pug b/test/fixtures/set-filename/templates/base.pug new file mode 100644 index 0000000..95055ba --- /dev/null +++ b/test/fixtures/set-filename/templates/base.pug @@ -0,0 +1,4 @@ + +html(lang="en") + body + block content From 2fc047618d32823e85fd2b33a8a5038ec4241647 Mon Sep 17 00:00:00 2001 From: ismay Date: Sun, 14 Apr 2019 13:55:28 +0200 Subject: [PATCH 2/2] Update readme --- README.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7b446f0..b1deeb6 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ You can pass options to `metalsmith-in-place` with the [Javascript API](https:// * [pattern](#pattern): optional. Only files that match this pattern will be processed. Accepts a string or an array of strings. The default is `**`. * [engineOptions](#engineoptions): optional. Use this to pass options to the jstransformer that's rendering your files. The default is `{}`. * [suppressNoFilesError](#suppressnofileserror): optional. The no-files-to-process error will be suppressed. The default is `false`. +* [setFilename](#setfilename): optional. Some templating engines, like [pug](https://github.com/pugjs/pug), need a `filename` property to be present in the options to be able to process relative includes, extends, etc. Setting this option to `true` will add the current filename to the options passed to each jstransformer. The default is `false`. ### `pattern` @@ -71,9 +72,39 @@ Would pass `{ "cache": false }` to each used jstransformer. ### `suppressNoFilesError` -`metalsmith-in-place` throws [an error](#no-files-to-process) if it can’t find any files to process. If you’re doing any kind of incremental builds via something like `metalsmith-watch`, this is problematic as you’re likely only rebuilding files that have changed. This flag allows you to suppress that error ([more info](https://github.com/metalsmith/metalsmith-in-place/pull/151)). +`metalsmith-in-place` exits with [an error](#no-files-to-process) if it can’t find any files to process. If you’re doing any kind of incremental builds via something like `metalsmith-watch`, this is problematic as you’re likely only rebuilding files that have changed. This flag allows you to suppress that error. So this `metalsmith.json`: -Note that if you have [debugging](#errors-and-debugging) turned on, you’ll see a message denoting that no files are present for processing. +```json +{ + "source": "src", + "destination": "build", + "plugins": { + "metalsmith-in-place": { + "suppressNoFilesError": true + } + } +} +``` + +Would suppress the error if there aren't any files to process. Note that when this option is turned on, if you're logging [debug messages](#errors-and-debugging), you’ll still see a message denoting when there aren't any files for metalsmith-layouts to process. + +### `setFilename` + +Set this option to `true` if you want to pass the current filename to each jstransformer. The default is `false`. So this `metalsmith.json`: + +```json +{ + "source": "src", + "destination": "build", + "plugins": { + "metalsmith-in-place": { + "setFilename": true + } + } +} +``` + +Would overwrite `engineOptions.filename` with the absolute path for the file that's currently being processed, and pass that to the jstransformer. For now we're just passing `filename`, but if you encounter a jstransformer that requires a different property, like `path` or something else, let us know and we can add it. ## Errors and debugging