Skip to content

Instantly share code, notes, and snippets.

@unstoppablecarl
Last active September 4, 2015 20:52
Show Gist options
  • Save unstoppablecarl/d864d662c3f1a1688a91 to your computer and use it in GitHub Desktop.
Save unstoppablecarl/d864d662c3f1a1688a91 to your computer and use it in GitHub Desktop.

What makes metalsmith so simple and powerful is the simplicity of the files object. The files object is the current state of the files being processed by metalsmith. At any time the files object can be output to the destination dir using only the object key for the file path and the file object's contents property for the file contents.

There are cases where a key for the current file's path on each file object is nessisary. This has become essential for the metalsmith-navigation plugin I created.

The lifecycle of a metalsmith plugin should be roughly like this:

  • When inspecting file objects:

    • Do so as if this was their initial and only state (how the current state was achieved should be irrelevant).
    • The files object keys (the file path that will be output for that file) should be the only place this file's path is maintained.
  • When executing

    • Modify metalsmith.metadata() and files objects how ever you like.
  • When done execution:

    • Properties assigned to file objects or metalsmith.metadata() by the plugin:
      • Not Intended to be used by other plugins:
        • Should be removed.
        • Modified files object keys (file paths) and contents property of file objects should be returned to a usable state.
      • Intended to be used by other plugins:
        • Should be documented and maintained consistently for backward compatibility.
        • Should have namespaced and or configurable property names to avoid collision with other plugins.
    • Data intended to reference specific files should not reference them by file path which can change. Reference files by their object.
      • Doing this durring execution is fine, other plugins should not be expected to rely on data structured this way.
    • The state of the files object should be such that it is ready to be output immediately without futher action or modification.
  • Ideally if a plugin has behavior that breaks these rules it should be designed such that the behavior is opt in via configuration.

This readme is a cleaned up version of this comment metalsmith/metalsmith#58 (comment)

var metalSmith = require('metalsmith');
var myPlugin = function(files, metalsmith, done){
/*
files param looks like this
{
'path/to/file.html': {
// yaml front matter data from md file here (foo and whatever)
foo: 'bar',
whatever: 99,
contents: 'file string contents in a buffer',
},
'path/to/file2.html': {
// yaml front matter data from md file here (foo and whatever)
foo: 'bar',
whatever: 99,
contents: 'file string contents in a buffer',
},
}
*/
// manipulate files object here
for(var key in files){
}
// manipulate metadata here
var metadata = metalsmith.metadata();
// if there is a problem
if(problem){
throw new Error('something when wrong');
}
// call this when done, besure to only call it when async is done
done();
};
metalSmith(__dirname)
.use(myPlugin)
/*
at the build step each property in the files object is written to a file in the destination dir
using the property key as its file path and files[filePath].contents as its file contents
*/
.build(function(err) {
// don't forget this or you will not see any errors
if (err) {
throw err;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment