Skip to content

Instantly share code, notes, and snippets.

@peterbraden
Created May 28, 2014 15:24
Show Gist options
  • Save peterbraden/ce13490c0f1f30d89de0 to your computer and use it in GitHub Desktop.
Save peterbraden/ce13490c0f1f30d89de0 to your computer and use it in GitHub Desktop.
Atomic Design Ideas

molecule

Atomic Design building block

You're building with Atomic Design:

myPage.js

var Template = require('molecule');

var myPage = new Template({
  name : 'My Page'
, templateFile: './template.html'
})

myPage.render({foo:bar}, function(err, html){
  ...
});

template.html: (Dust syntax)

<html>
  {@module id=".myhead" /}
  {@module id="./examplebody" /}
</html>
  • Modules are npm modules
  • They can also point to a local js file.

./examplebody/index.js:

var Molecule = require('molecule')

var myHead = new Molecule({
  template: "<head>{title}</head>"
, name : "head"
})

Etc. Etc.

Atoms, Organisms and Templates are just Molecules.

/**
* Molecular Design. (Atomic design, but technically everything is a molecule)
*/
var dust = require('dustjs-linkedin')
, fs = require('fs')
, path = require('path')
, callsite = require('callsite')
var Molecule = module.exports = function(opts){
this.template = opts.template
if (opts.templateFile){
this.templateFile = resolveTemplate(opts.templateFile);
this.template = fs.readFileSync(this.templateFile, 'utf8')
}
this.name = opts.name || "Unnamed Molecule";
}
Molecule.prototype.render = function(opts, cb){
var molecule = this;
// Dust helper: @module is a node module (another molecule)
dust.helpers.module = function(chunk, context, bodies, params){
var module = params.id
, templateDir = path.dirname(molecule.templateFile)
, m
, ctx = params;
/*
* This is a little ugly - essentially we want to 'require' in
* the context of the template. If the module is relative then
* we need to fix the path, as we're in node_modules.
*
* There is probably a better way to do this.
*/
if (module.charAt(0) === '.'){
module = path.join(templateDir, module)
m = require(module)
} else {
// Must be in first level of node_modules...
m = require(path.join(process.cwd(), 'node_modules', module))
}
Object.keys(params).forEach(function(k){
ctx[k] = params[k]
})
return chunk.map(function(chunk){
m.render(ctx, function(err, res){
if (err){
throw err;
}
chunk.end(res)
})
})
}
if (!this.template){
return cb(new Error("Cannot render: Molecule has no template"));
}
if (!cb){
throw new Error("render(opts, cb) requires a callback");
}
console.log("# Rendering", this.name)
var compiled = dust.compile(this.template, this.name);
dust.loadSource(compiled);
return dust.render(this.name, opts, cb);
}
var resolveTemplate = function(template){
// Try and be smart about resolving template
if (fs.existsSync(template)){
return template
}
if (fs.existsSync(path.join(process.cwd(), template))){
// Relative to cwd
return path.join(process.cwd(), template)
}
if (fs.existsSync(path.join(__dirname, template))){
// Relative to Molecule.js... unlikely
return path.join(__dirname, template)
}
// Relative to init caller -- most likely, but slowest
var caller = callsite()[2].getFileName()
, fn = path.join(path.dirname(caller), template);
if (fs.existsSync(fn)){
return fn;
}
throw new Error("Couldn't find template file:" + template)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment