Metalsmith(__dirname) .use(markdown()) .use(sass()) // ... .destination('./build') .build();
$ npm install -D metalsmith
. |– src/ |– content/ |– styles/ |_ scripts/ |– templates/ |_ build.js
var Metalsmith = require('metalsmith'); Metalsmith(__dirname) .destination('./build') .build();
This will move everything from __dirname/src to __dirname/build
src/index.md
--- title: Home --- ##My Page This is some content!
$ npm install -D metalsmith-markdown
var Metalsmith = require('metalsmith'), markdown = require('metalsmith-markdown'); Metalsmith(__dirname) .use(markdown()) .destination('./build') .build();
$ node build.js
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>{{ title }} | Metalsmith Page</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> </head> <body> <div class="main-wrapper"> {{{ contents }}} </div> </body> </html>
--- title: Home template: index.hbt ---
$ npm install -D metalsmith-templates handlebars
(uses consolidate.js)
build.js
// ... templates = require('metalsmith-templates'); Metalsmith(__dirname) .use(markdown()) .use(templates('handlebars')) // ...
. |_ src/ |_ contents/ |– posts/ |_ my-frist-post.md |_ pages/ |_ about.md
src/contents/posts/my-frist-post.md
--- title: My First Post template: post.hbt date: 2014-05-19 --- #My First Post Hey, I'm blogging!
src/contents/pages/about.md
--- title: About template: page.hbt --- ##About Awesome, witty content here!
$ npm install -D metalsmith-collections
// ... .use(collections({ blog: { pattern: '*/posts/*', oderBy: 'date', reverse: true }, pages: { pattern: '*/pages/*' } })) // ...
templates/home.hbt
<!-- ... --> <div class="main-wrapper"> {{#each collections.blog}} <article class="post"> <h3>{{title}}</h3> <p>{{{contents}}}</p> </article> {{/each}} </div> <!-- ... -->
$ npm install -D metalsmith-permalinks
// ... .use(permalinks({ pattern: ':collection/:title' })) // ...
{ 'path/to/file': { 'title': 'FROM_THE_TITLE_KEY', 'template': 'TEMPLATE_NAME', 'contents': <Buffer()>, 'mode': 'HEX_FILE_PERM_CODE' } }
.build(function(err) { if (err) { throw err; } });
var plugin = function(opts) { return function(files, metalsmith, done) { done(); }; };
var autoTemplate = function(opts) { var pattern = new RegExp(opts.pattern); return function(files, metalsmith, done) { for (var file in files) { if (pattern.test(file)) { var _f = files[file]; if (!_f.template) { _f.template = opts.templateName; } } } done(); }; };
//... .use(autoTemplate({ pattern: 'posts', templateName: 'post.hbt' })) //...
var metadata = metalsmith.metadata(), collections = metadata.collections;
$ npm install -D metalsmith-sass metalsmith-coffee
// ... .use(sass({ outputStyle: 'compressed' })) .use(coffee()) // ...
Metalsmith(__dirname) .use(collections({ blog: { pattern: '*/posts/*', oderBy: 'date', revers: true }, pages: { pattern: '*/pages/*' } })) .use(markdown()) .use(autoTemplate({ pattern: 'posts/', templateName: 'post.hbt' })) .use(permalinks({ pattern: ':collection/:title' })) .use(templates('handlebars')) .destination('./build') .build(function(err) { if (err) { throw err; } });
{ "source": "src", "destination": "build", "plugins": { "metalsmith-collections": { "blog": { "pattern": "*/posts/*", "oderBy": "date", "revers": true }, "pages": { "pattern": "*/pages/*" } }, "metalsmith-markdown": true, "metalsmith-autoTemplate": { "pattern": "posts/", "templateName": "post.hbt" }, "metalsmith-permalinks": ":collection/:title", "metalsmith-templates": "handlebars" } }
var clone = require('clone'); var defaults = require('defaults'); var each = require('async').each; var front = require('front-matter'); var fs = require('fs-extra'); var Mode = require('stat-mode'); var noop = function(){}; var path = require('path'); var readdir = require('recursive-readdir'); var rm = require('rimraf').sync; var utf8 = require('is-utf8'); var Ware = require('ware'); /** * Expose `Metalsmith`. */ module.exports = Metalsmith; /** * Initialize a new `Metalsmith` builder with a working `dir`. * * @param {String} dir */ function Metalsmith(dir){ if (!(this instanceof Metalsmith)) return new Metalsmith(dir); this.dir = path.resolve(dir); this.ware = new Ware(); this.data = {}; this.source('src'); this.destination('build'); this.clean(true); } /** * Add a `plugin` to the middleware stack. * * @param {Function} plugin * @return {Metalsmith} */ Metalsmith.prototype.use = function(plugin){ this.ware.use(plugin); return this; }; /** * Get or set the global `metadata` to pass to templates. * * @param {Object} metadata * @return {Object or Metalsmith} */ Metalsmith.prototype.metadata = function(metadata){ if (!arguments.length) return this.data; this.data = clone(metadata); return this; }; /** * Get or set the source directory. * * @param {String} path * @return {String or Metalsmith} */ Metalsmith.prototype.source = function(path){ if (!arguments.length) return this.join(this._src); this._src = path; return this; }; /** * Get or set the destination directory. * * @param {String} path * @return {String or Metalsmith} */ Metalsmith.prototype.destination = function(path){ if (!arguments.length) return this.join(this._dest); this._dest = path; return this; }; /** * Get or set whether the destination directory will be removed before writing. * @param {Boolean} clean * @return {Boolean or Metalsmith} */ Metalsmith.prototype.clean = function(clean){ if (!arguments.length) return this._clean; this._clean = clean; return this; }; /** * Join path `strs` with the working directory. * * @param {String} strs... * @return {String} */ Metalsmith.prototype.join = function(){ var strs = [].slice.call(arguments); strs.unshift(this.dir); return path.join.apply(path, strs); }; /** * Build with the current settings to the dest directory. * * @param {Function} fn */ Metalsmith.prototype.build = function(fn){ fn = fn || noop; var self = this; this.read(function(err, files){ if (err) return fn(err); self.run(files, function(err, files){ if (err) return fn(err); self.write(files, function(err){ fn(err, files); }); }); }); }; /** * Run a set of `files` through the middleware stack. * * @param {Object} files * @param {Function} fn */ Metalsmith.prototype.run = function(files, fn){ this.ware.run(files, this, fn); }; /** * Read the source directory, parsing front matter and call `fn(files)`. * * @param {Function} fn * @api private */ Metalsmith.prototype.read = function(fn){ var files = {}; var src = this.source(); readdir(src, function(err, arr){ if (err) return fn(err); each(arr, read, function(err){ fn(err, files); }); }); function read(file, done){ var name = path.relative(src, file); fs.stat(file, function(err, stats){ if (err) return done(err); fs.readFile(file, function(err, buffer){ if (err) return done(err); var file = {}; if (utf8(buffer)) { var parsed = front(buffer.toString()); file = parsed.attributes; file.contents = new Buffer(parsed.body); } else { file.contents = buffer; } file.mode = Mode(stats).toOctal(); files[name] = file; done(); }); }); } }; /** * Write a dictionary of `files` to the dest directory. * * @param {Object} files * @param {Function} fn * @api private */ Metalsmith.prototype.write = function(files, fn){ var dest = this.destination(); var clean = this.clean(); if (clean) rm(dest); each(Object.keys(files), write, fn); function write(file, done){ var data = files[file]; var out = path.join(dest, file); return fs.outputFile(out, data.contents, function(err){ if (err) done(err); if (!data.mode) return done(); fs.chmod(out, data.mode, done); }); } };