metalsmith-layouts
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -0,1 +1,5 @@ | ||
### 2.1.0 - January 25, 2018 | ||
* add a documentation link to the error messages | ||
* add debug for better debugging | ||
### 2.0.0 - January 10, 2018 | ||
@@ -6,3 +10,3 @@ * moved to jstransformers (and dropped consolidate) | ||
* `engine`: inferred automatically from the layout extension by jstransformer | ||
* `partials`: use metalsmith-register-partials instead | ||
* `partials`: use metalsmith-discover-partials (and metalsmith-discover-helpers) instead | ||
* `partialExtension`: no longer necessary | ||
@@ -9,0 +13,0 @@ * `rename`: use metalsmith-rename instead |
@@ -0,7 +1,26 @@ | ||
const debug = require('debug')('metalsmith-layouts'); | ||
const match = require('multimatch'); | ||
const path = require('path'); | ||
const isUtf8 = require('is-utf8'); | ||
const getTransformer = require('./get-transformer'); | ||
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]; | ||
} | ||
/** | ||
* Resolves layouts, in the following order: | ||
@@ -25,22 +44,25 @@ * 1. Layouts in the frontmatter | ||
function render({ file, metadata, settings, metalsmith }) { | ||
function render({ filename, files, metadata, settings, metalsmith }) { | ||
return new Promise(resolve => { | ||
const file = files[filename]; | ||
const layout = getLayout({ file, settings }); | ||
const extension = layout.split('.').pop(); | ||
debug(`rendering ${filename} with layout ${layout}`); | ||
// Stringify file contents | ||
// eslint-disable-next-line no-param-reassign | ||
file.contents = file.contents.toString(); | ||
let contents = file.contents.toString(); | ||
const transform = getTransformer(extension); | ||
const locals = Object.assign({}, metadata, file); | ||
const locals = Object.assign({}, metadata, file, { contents }); | ||
const layoutPath = path.join(metalsmith.path(settings.directory), layout); | ||
// Transform the contents | ||
// eslint-disable-next-line no-param-reassign | ||
file.contents = transform.renderFile(layoutPath, settings.engineOptions, locals).body; | ||
contents = transform.renderFile(layoutPath, settings.engineOptions, locals).body; | ||
// Update file with results | ||
// eslint-disable-next-line no-param-reassign | ||
file.contents = Buffer.from(file.contents); | ||
file.contents = Buffer.from(contents); | ||
debug(`done rendering ${filename}`); | ||
return resolve(); | ||
@@ -54,7 +76,11 @@ }); | ||
function validate({ file, settings }) { | ||
function validate({ filename, files, settings }) { | ||
const file = files[filename]; | ||
const layout = getLayout({ file, settings }); | ||
debug(`validating ${filename}`); | ||
// Files without a layout cannot be processed | ||
if (!layout) { | ||
debug(`validation failed, ${filename} does not have a layout set`); | ||
return false; | ||
@@ -65,2 +91,3 @@ } | ||
if (!layout.includes('.')) { | ||
debug(`validation failed, layout for ${filename} does not have an extension`); | ||
return false; | ||
@@ -71,2 +98,3 @@ } | ||
if (!isUtf8(file.contents)) { | ||
debug(`validation failed, ${filename} is not utf-8`); | ||
return false; | ||
@@ -77,3 +105,9 @@ } | ||
const extension = layout.split('.').pop(); | ||
return getTransformer(extension); | ||
const transformer = getTransformer(extension); | ||
if (!transformer) { | ||
debug(`validation failed, no jstransformer found for layout for ${filename}`); | ||
} | ||
return transformer; | ||
} | ||
@@ -96,3 +130,7 @@ | ||
if (!(typeof settings.pattern === 'string' || Array.isArray(settings.pattern))) { | ||
done(new Error('invalid pattern, the pattern option should be a string or array.')); | ||
done( | ||
new Error( | ||
'invalid pattern, the pattern option should be a string or array of strings. See https://www.npmjs.com/package/metalsmith-layouts#pattern' | ||
) | ||
); | ||
} | ||
@@ -104,7 +142,11 @@ | ||
// Filter files by validity | ||
const validFiles = matchedFiles.filter(filename => validate({ file: files[filename], settings })); | ||
const validFiles = matchedFiles.filter(filename => validate({ filename, files, settings })); | ||
// Let the user know when there are no files to process, usually caused by missing jstransformer | ||
// Let the user know when there are no files to process | ||
if (validFiles.length === 0) { | ||
done(new Error('no files to process, check whether you have a jstransformer installed.')); | ||
done( | ||
new Error( | ||
'no files to process. See https://www.npmjs.com/package/metalsmith-layouts#no-files-to-process' | ||
) | ||
); | ||
} | ||
@@ -114,10 +156,3 @@ | ||
Promise.all( | ||
validFiles.map(filename => | ||
render({ | ||
file: files[filename], | ||
metadata, | ||
settings, | ||
metalsmith | ||
}) | ||
) | ||
validFiles.map(filename => render({ filename, files, metadata, settings, metalsmith })) | ||
) | ||
@@ -124,0 +159,0 @@ .then(() => done()) |
@@ -8,7 +8,7 @@ { | ||
"repository": "git://github.com/ismay/metalsmith-layouts.git", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"scripts": { | ||
"precommit": "lint-staged", | ||
"lint:js": "eslint 'lib/**/*.js'", | ||
"lint:prettier": "prettier --list-different 'lib/**/*.js'", | ||
"lint:js": "eslint '**/*.js'", | ||
"lint:prettier": "prettier --list-different '**/*.js'", | ||
"test": "jest", | ||
@@ -44,2 +44,3 @@ "test:coverage": "jest --coverage && cat ./coverage/lcov.info | coveralls" | ||
"dependencies": { | ||
"debug": "^3.1.0", | ||
"inputformat-to-jstransformer": "^1.2.1", | ||
@@ -46,0 +47,0 @@ "is-utf8": "^0.2.1", |
177
README.md
@@ -31,2 +31,79 @@ # metalsmith-layouts | ||
## Options | ||
You can pass options to `metalsmith-layouts` with the [Javascript API](https://github.com/segmentio/metalsmith#api) or [CLI](https://github.com/segmentio/metalsmith#cli). The options are: | ||
* [default](#default): optional. The default layout to apply to files. | ||
* [directory](#directory): optional. The directory for the layouts. The default is `layouts`. | ||
* [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 layouts. The default is `{}`. | ||
### `default` | ||
The default layout to use. Can be overridden with the `layout` key in each file's YAML frontmatter, by passing either a layout or `false`. Passing `false` will skip the file entirely. | ||
If a `default` layout has been specified, `metalsmith-layouts` will apply layouts to all files, so you might want to ignore certain files with a pattern. Don't forget to specify the default template's file extension. So this `metalsmith.json`: | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"default": "default.hbs" | ||
} | ||
} | ||
} | ||
``` | ||
Will apply the `default.hbs` layout to all files, unless overridden in the frontmatter. | ||
### `directory` | ||
The directory where `metalsmith-layouts` looks for the layouts. By default this is `layouts`. So this `metalsmith.json`: | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"directory": "templates" | ||
} | ||
} | ||
} | ||
``` | ||
Will look for layouts in the `templates` directory, instead of in `layouts`. | ||
### `pattern` | ||
Only files that match this pattern will be processed. So this `metalsmith.json`: | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"pattern": "**/*.html" | ||
} | ||
} | ||
} | ||
``` | ||
Would process all files that have the `.html` extension. Beware that the extensions might be changed by other plugins in the build chain, preventing the pattern from matching. We use [multimatch](https://github.com/sindresorhus/multimatch) for the pattern matching. | ||
### `engineOptions` | ||
Use this to pass options to the jstransformer that's rendering your templates. So this `metalsmith.json`: | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"engineOptions": { | ||
"cache": false | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
Would pass `{ "cache": false }` to the used jstransformer. | ||
## Example | ||
@@ -36,3 +113,3 @@ | ||
``` | ||
```bash | ||
$ npm install --save metalsmith metalsmith-layouts | ||
@@ -43,3 +120,3 @@ ``` | ||
``` | ||
```bash | ||
$ npm install --save jstransformer-handlebars | ||
@@ -55,3 +132,3 @@ ``` | ||
``` | ||
```json | ||
{ | ||
@@ -94,3 +171,3 @@ "source": "src", | ||
``` | ||
```bash | ||
$ node_modules/.bin/metalsmith | ||
@@ -103,3 +180,3 @@ ``` | ||
``` | ||
```html | ||
<!DOCTYPE html> | ||
@@ -116,86 +193,36 @@ <html> | ||
## Options | ||
## FAQ | ||
You can pass options to `metalsmith-layouts` with the [Javascript API](https://github.com/segmentio/metalsmith#api) or [CLI](https://github.com/segmentio/metalsmith#cli). The options are: | ||
> I want to use handlebars partials and or helpers. | ||
* [default](#default): optional. The default layout to apply to files. | ||
* [directory](#directory): optional. The directory for the layouts. The default is `layouts`. | ||
* [pattern](#pattern): optional. Only files that match this pattern will be processed. The default is `**`. | ||
* [engineOptions](#engineOptions): optional. Use this to pass options to the jstransformer that's rendering your layouts. The default is `{}`. | ||
Use [metalsmith-discover-partials](https://www.npmjs.com/package/metalsmith-discover-partials) and [metalsmith-discover-helpers](https://www.npmjs.com/package/metalsmith-discover-helpers). | ||
### default | ||
> I want to change the extension of my templates. | ||
The default layout to use. Can be overridden with the `layout` key in each file's YAML frontmatter, by passing either a layout or `false`. Passing `false` will skip the file entirely. | ||
Use [metalsmith-rename](https://www.npmjs.com/package/metalsmith-rename). | ||
If a `default` layout has been specified, `metalsmith-layouts` will apply layouts to all files, so you might want to ignore certain files with a pattern. Don't forget to specify the default template's file extension. So this `metalsmith.json`: | ||
> My templating language requires a filename property to be set. | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"default": "default.hbs" | ||
} | ||
} | ||
} | ||
``` | ||
Use [metalsmith-filenames](https://www.npmjs.com/package/metalsmith-filenames). | ||
Will apply the `default.hbs` layout to all files, unless overridden in the frontmatter. | ||
## Errors and debugging | ||
### directory | ||
If you're encountering problems you can use [debug](https://www.npmjs.com/package/debug) to enable verbose logging. To enable `debug` prefix your build command with `DEBUG=metalsmith-layouts`. So if you normally run `metalsmith` to build, use `DEBUG=metalsmith-layouts metalsmith` (on windows the syntax is [slightly different](https://www.npmjs.com/package/debug#windows-note)). | ||
The directory where `metalsmith-layouts` looks for the layouts. By default this is `layouts`. So this `metalsmith.json`: | ||
### No files to process | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"directory": "templates" | ||
} | ||
} | ||
} | ||
``` | ||
There are several things that might cause you to get a `no files to process` error: | ||
Will look for layouts in the `templates` directory, instead of in `layouts`. | ||
* Your [pattern](#pattern) does not match any files | ||
* None of your files pass validation, validation fails for files that: | ||
* Have no layout | ||
* Have a layout without an extension | ||
* Are not utf-8 | ||
* Have a layout that needs a jstransformer that hasn't been installed | ||
### pattern | ||
## Credits | ||
Only files that match this pattern will be processed. So this `metalsmith.json`: | ||
* [Ian Storm Taylor](https://github.com/ianstormtaylor) for creating [metalsmith-templates](https://github.com/segmentio/metalsmith-templates), on which this plugin was based | ||
* [Rob Loach](https://github.com/RobLoach) for creating [metalsmith-jstransformer](https://github.com/RobLoach/metalsmith-jstransformer), which inspired our switch to jstransformers | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"pattern": "**/*.html" | ||
} | ||
} | ||
} | ||
``` | ||
Would process all files that have the `.html` extension. Beware that the extensions might be changed by other plugins in the build chain, preventing the pattern from matching. We use [multimatch](https://github.com/sindresorhus/multimatch) for the pattern matching. | ||
### engineOptions | ||
Use this to pass options to the jstransformer that's rendering your templates. So this `metalsmith.json`: | ||
```json | ||
{ | ||
"plugins": { | ||
"metalsmith-layouts": { | ||
"engineOptions": { | ||
"cache": false | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
Would pass `{ "cache": false }` to the used jstransformer. | ||
## Origins | ||
This plugin is a fork of the now deprecated [metalsmith-templates](https://github.com/segmentio/metalsmith-templates). Splitting up `metalsmith-templates` into two plugins was suggested by Ian Storm Taylor. The results are: | ||
* [metalsmith-in-place](https://github.com/ismay/metalsmith-in-place): render templating syntax in your source files. | ||
* [metalsmith-layouts](https://github.com/ismay/metalsmith-layouts): apply layouts to your source files. | ||
## License | ||
@@ -202,0 +229,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
27329
374
237
0
5
7
+ Addeddebug@^3.1.0
+ Addeddebug@3.2.7(transitive)
+ Addedms@2.1.3(transitive)