metalsmith-jstransformer
Advanced tools
Comparing version 0.5.3 to 0.6.0
# Changelog | ||
## v0.6.0 | ||
- Merged in and deprecated [`metalsmith-jstransformer-layouts`](https://github.com/RobLoach/metalsmith-jstransformer-layouts) | ||
## v0.5.3 | ||
@@ -4,0 +8,0 @@ |
141
index.js
@@ -5,4 +5,5 @@ var jstransformer = require('jstransformer') | ||
var async = require('async') | ||
var path = require('path') | ||
var clone = require('clone') | ||
var match = require('minimatch').match | ||
var minimatch = require('minimatch') | ||
@@ -16,3 +17,3 @@ var transformers = {} | ||
*/ | ||
function getTransformer (name) { | ||
function getTransformer(name) { | ||
if (name in transformers) { | ||
@@ -29,14 +30,89 @@ return transformers[name] | ||
opts = opts || {} | ||
opts.pattern = opts.pattern || '[!_]*' | ||
opts.layoutPattern = opts.layoutPattern || 'layouts/**' | ||
var defaultLayout = opts.defaultLayout | ||
// Execute the plugin. | ||
return function (files, metalsmith, done) { | ||
// Retrieve all layouts. | ||
var templates = {} | ||
var filesKeys = Object.keys(files) | ||
var layouts = minimatch.match(filesKeys, opts.layoutPattern, {matchBase: true}) | ||
/** | ||
* Compile the given layout and store it in templates. | ||
*/ | ||
function compileLayout(layout, done) { | ||
// Find which JSTransformer to compile with. | ||
var transform = path.extname(layout).substring(1) | ||
transform = getTransformer(transform) | ||
if (transform) { | ||
// Retrieve the options for the JSTransformer. | ||
var options = extend({}, files[layout], { | ||
filename: path.join(metalsmith._directory, metalsmith._source, layout) | ||
}) | ||
// Compile the content. | ||
var content = files[layout].contents.toString() | ||
transform.compileAsync(content, options).then(function (results) { | ||
// Wire up the template for the layout. | ||
templates[layout] = results | ||
// Set the layout as the default layout, if desired. | ||
if (files[layout].defaultLayout) { | ||
defaultLayout = layout | ||
} | ||
// Finished compiling the layout into a template. | ||
done() | ||
}, function (err) { | ||
done(err) | ||
}) | ||
} else { | ||
done('The layout ' + layout + ' has an unsupported transform of ' + transform + '.') | ||
} | ||
} | ||
/** | ||
* Delete the given file from the files array. | ||
*/ | ||
function deleteFile(file, done) { | ||
if (file in files) { | ||
delete files[file] | ||
} | ||
done() | ||
} | ||
/** | ||
* Render the given file in its layout templates. | ||
*/ | ||
function renderContent(file, done) { | ||
// Only render content, skip rendering layouts. | ||
if (!(file in layouts)) { | ||
var layoutName = files[file].layout || defaultLayout | ||
while (layoutName && templates[layoutName]) { | ||
// Build the options/locals. | ||
var locals = extend({}, metalsmith.metadata(), files[layoutName], files[file], { | ||
contents: files[file].contents.toString(), | ||
filename: path.join(metalsmith._directory, metalsmith._source, layoutName) | ||
}) | ||
// Render the content using the template function and options. | ||
var output = templates[layoutName].fn(locals) | ||
files[file].contents = output | ||
// Allow for recursive explicit layouts. | ||
layoutName = files[layoutName].layout | ||
} | ||
} | ||
done() | ||
} | ||
/** | ||
* Process the given file. Call done() when done processing. | ||
*/ | ||
function processFile (file, done) { | ||
function processFile(file, done) { | ||
/** | ||
* Process the given extension on the file. | ||
*/ | ||
function processExtension (extension, done) { | ||
function processExtension(extension, done) { | ||
// Retrieve the transformer. | ||
@@ -46,3 +122,3 @@ var transformer = getTransformer(extension) | ||
// Process the extension until the transformation is done. | ||
if (transformer && !files[file].jstransformer_done) { | ||
if (transformer && !files[file].jstransformerDone) { | ||
// Construct the options. | ||
@@ -56,9 +132,9 @@ var options = extend({}, metalsmith.metadata(), files[file], { | ||
// Allow providing the default output format. | ||
files[file].jstransformer_outputFormat = transformer.outputFormat | ||
files[file].jstransformerOutputFormat = transformer.outputFormat | ||
// Remove an extension from the end. | ||
files[file].jstransformer_filepath.pop() | ||
files[file].jstransformerFilePath.pop() | ||
files[file].contents = new Buffer(result.body) | ||
done() | ||
}, function (err) { | ||
files[file].jstransformer_done = true | ||
files[file].jstransformerDone = true | ||
done(err) | ||
@@ -68,3 +144,3 @@ }) | ||
// The transformer isn't supported, skip the rest. | ||
files[file].jstransformer_done = true | ||
files[file].jstransformerDone = true | ||
done() | ||
@@ -76,3 +152,3 @@ } | ||
var extensions = file.split('.') | ||
files[file].jstransformer_filepath = clone(extensions) | ||
files[file].jstransformerFilePath = clone(extensions) | ||
extensions.reverse().pop() | ||
@@ -86,11 +162,11 @@ // Loop through the transformer series. | ||
*/ | ||
function renameFile (file, done) { | ||
function renameFile(file, done) { | ||
var filename = file | ||
// Check if there is a potential filepath change. | ||
if (files[file].jstransformer_filepath) { | ||
if (files[file].jstransformerFilePath) { | ||
// See if we should add the default output format. | ||
if (files[file].jstransformer_filepath.length === 1 && files[file].jstransformer_outputFormat) { | ||
files[file].jstransformer_filepath.push(files[file].jstransformer_outputFormat) | ||
if (files[file].jstransformerFilePath.length === 1 && files[file].jstransformerOutputFormat) { | ||
files[file].jstransformerFilePath.push(files[file].jstransformerOutputFormat) | ||
} | ||
filename = files[file].jstransformer_filepath.join('.') | ||
filename = files[file].jstransformerFilePath.join('.') | ||
} | ||
@@ -108,12 +184,31 @@ | ||
// Filter out all the files we are to ignore. | ||
var results = match(Object.keys(files), opts.pattern, { matchBase: true }) | ||
// Process each file. | ||
async.map(results, processFile, function (err) { | ||
// TODO: Clean up function chaining tree. | ||
// Compile all layouts. | ||
async.map(layouts, compileLayout, function (err) { | ||
if (err) { | ||
done(err) | ||
} else { | ||
// Now rename all the files. | ||
async.map(results, renameFile, done) | ||
// Render the content individually. | ||
async.map(filesKeys, processFile, function (err) { | ||
if (err) { | ||
done(err) | ||
} else { | ||
// Render the content within the layouts. | ||
async.map(filesKeys, renderContent, function (err) { | ||
if (err) { | ||
done(err) | ||
} else { | ||
// Delete the layout data. | ||
async.map(layouts, deleteFile, function (err) { | ||
if (err) { | ||
done(err) | ||
} else { | ||
// Now rename all the files. | ||
async.map(Object.keys(files), renameFile, done) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
@@ -120,0 +215,0 @@ }) |
{ | ||
"name": "metalsmith-jstransformer", | ||
"version": "0.5.3", | ||
"version": "0.6.0", | ||
"description": "Metalsmith JSTransformer Plugin", | ||
@@ -9,3 +9,5 @@ "files": [ | ||
"scripts": { | ||
"test": "mocha --no-timeouts && standard index.js test/index.js" | ||
"test": "npm run testit && npm run xo", | ||
"testit": "node test", | ||
"xo": "xo --space --no-semicolon" | ||
}, | ||
@@ -30,3 +32,3 @@ "repository": { | ||
"inputformat-to-jstransformer": "^1.1.2", | ||
"jstransformer": "0.0.*", | ||
"jstransformer": "0.0.4", | ||
"minimatch": "^3.0.0" | ||
@@ -38,9 +40,11 @@ }, | ||
"jstransformer-jade": "*", | ||
"jstransformer-markdown-it": "*", | ||
"jstransformer-nunjucks": "^0.2.0", | ||
"jstransformer-styl": "*", | ||
"jstransformer-uglify-js": "*", | ||
"jstransformer-markdown-it": "*", | ||
"metalsmith": "2.*", | ||
"mocha": "*", | ||
"standard": "5.*" | ||
"rimraf": "^2.5.0", | ||
"testit": "^2.0.2", | ||
"xo": "^0.12.1" | ||
} | ||
} |
@@ -19,3 +19,6 @@ # Metalsmith JSTransformer Plugin [![NPM version](https://img.shields.io/npm/v/metalsmith-jstransformer.svg)](https://www.npmjs.org/package/metalsmith-jstransformer) | ||
"plugins": { | ||
"metalsmith-jstransformer": {} | ||
"metalsmith-jstransformer": { | ||
"layoutPattern": "layouts/**", | ||
"defaultLayout": null | ||
} | ||
} | ||
@@ -32,13 +35,18 @@ } | ||
metalsmith.use(jstransformer()); | ||
metalsmith.use(jstransformer({ | ||
'layoutPattern': 'layouts/**', | ||
'defaultLayout': null | ||
})); | ||
``` | ||
## Usage | ||
## Convention | ||
Create files that you would like to act on with JSTransformers with file extensions representing the transformer to use, in the format `example.html.<transformer>`. For example, if you would like to process with Jade, you would name it `example.html.jade`. | ||
### Content File Names | ||
Use multiple transformers by appending additional file extension transformer names at the end. For example, to [HTML-Minifier](https://github.com/jstransformers/jstransformer-html-minifier) our Jade example above, you would use the filename `example.html.html-minifier.jade`. | ||
Create files that you would like to act on with JSTransformers with file extensions representing the transformer to use, in the format `example.html.<transformer>`. For example, if you would like to process with Jade, you would name it `src/example.html.jade`. | ||
### Example | ||
Use multiple transformers by appending additional file extension transformer names at the end. For example, to [HTML-Minifier](https://github.com/jstransformers/jstransformer-html-minifier) our Jade example above, you would use the filename `src/example.html.html-minifier.jade`. | ||
#### Example | ||
The following example uses [Jade](http://jade-lang.com), so we must additionally install [`jstransformer-jade`](http://npm.im/jstransformer-jade): | ||
@@ -48,3 +56,3 @@ | ||
#### `src/example.html.jade` | ||
##### `src/example.html.jade` | ||
@@ -64,3 +72,3 @@ ``` | ||
#### Result | ||
##### Result | ||
@@ -79,4 +87,62 @@ ``` html | ||
### Layouts | ||
Declare layouts for your content with the extension of the template engine to be used for the layout, in the `src/layouts/**` directory. | ||
#### Example | ||
The following example uses [Jade](http://jade-lang.com) and [Markdown-it](https://www.npmjs.com/package/markdown-it), so we must additionally install [`jstransformer-jade`](http://npm.im/jstransformer-jade) and [`jstransformer-markdown-it`](https://www.npmjs.com/package/jstransformer-markdown-it): | ||
npm install jstransformer-jade --save | ||
npm install jstransformer-markdown-it --save | ||
##### `src/layouts/default.jade` | ||
``` jade | ||
--- | ||
pretty: true | ||
--- | ||
doctype html | ||
html | ||
head | ||
title My Site | ||
body!= contents | ||
``` | ||
Within the metadata of content in your `src` directory, tell it which layout to use: | ||
##### `src/index.md` | ||
``` yaml | ||
--- | ||
layout: layouts/default.jade | ||
--- | ||
This is my **site**! | ||
``` | ||
#### Result | ||
``` html | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>My Site</title> | ||
</head> | ||
<body> | ||
<p>This is my <strong>site</strong>!</p> | ||
</body> | ||
</html> | ||
``` | ||
## Configuration | ||
### `.layoutPattern` | ||
The pattern used to find your layouts. Defaults to `layouts/**`. | ||
### `.defaultLayout` | ||
If provided, will be used as the default layout for content that doesn't have a layout explicitly defined. Defaults to `null`. | ||
## License | ||
MIT |
13568
188
144
11
Updatedjstransformer@0.0.4