stache-backwards
v0.1.1
Published
This is an experiment in using a syntax like mustache / handlebars templates as a data storage format. (What I would call "reverse templating" -- but I see people already using that term to mean something else.) That is, instead of render content from an
Downloads
6
Readme
Intro
This is an experiment in using a syntax like mustache / handlebars templates as a data storage format. (What I would call "reverse templating" -- but I see people already using that term to mean something else.) That is, instead of render content from an object into a template, extract content out of a template-like document into a key-value hash object. Why this instead of something like JSON? Easier to read and edit, multiline, basically no escaping. And YAML? That was the closest existing thing I could think of, but I don't like that indentation is significant and I prefer a more straightforward way to indicate whether or not the content should be HTML-escaped.
"Data" storage really means content storage. The prototypical use case is to store multiple snippets of HTML (or similar content) in a file. For example, multiple chunks of content that correspond to the placeholders in a template representing a page can be stored in a single, easily readable and editable text file.
Example
Input:
{{{{content key="section_id"}}}}about{{{{/content}}}}
{{{{content key="head"}}}}
<link rel="stylesheet" href="about.css" media="all" />
{{{{/content}}}}
{{{{content key="primary"}}}}
<p>
This is some content.
</p>
{{{{/content}}}}
Output:
{
section_id: 'about',
head: '<link rel="stylesheet" href="about.css" media="all" />\n',
primary: '\n<p>\nThis is some content.\n</p>\n\n'
}
Design
The original idea was to use a format like this:
Input:
{{a}}<p>{{/a}}
or
{{#a}}<p>{{/a}}
Output:
{
a: '<p>'
}
Input:
{{{a}}}<p>{{{/a}}}
or
{{{#a}}}<p>{{{/a}}}
Output:
{
a: '<p>'
}
But then I realized I could get Handlebars to do the heavy lifting of implementing this by using its raw block helper syntax:
Input:
{{{{content key="a"}}}}<p>{{{{/content}}}}
Output:
{
a: '<p>'
}
Input:
{{{{content key="a" escape="html"}}}}<p>{{{{/content}}}}
Output:
{
a: '<p>'
}
This even handles embedding Handlebars templates within the snippets. (With the caveat that Handlebars does not currently support nesting raw blocks. See wycats/handlebars.js#1056.) It's unfortunate that it requires so many {{{{
chars, and there may be undesirable performance implications, but it's great for a proof of concept.
Input
This will process input like the following:
{!--
Sets a property named `a`.
In other words, targetObject.a will equal "A".
--}
{{{{content key="a"}}}}A{{{/content}}}}
{!--
Sets a property of `a` named `b`.
In other words, targetObject.a.b will equal "B".
--}
{{{{content path="a.b"}}}}B{{{/content}}}}
{!--
Will HTML-escape the value.
--}
{{{{content key="a" escape="html"}}}}A&B{{{/content}}}}
Usage
$ npm install stache-backwards
var
stache_back = require('stache-backwards').handlebars,
data;
data = stache_back.extract({template: input});
API
/**
* Extracts content from a template.
*
* @param object opts Options
* @param object|undefined opts.handlebars Instance of handlebars to use.
* @param string|function opts.template Template to extract from. String or
* return value of handlebars.compile().
* @param object|undefined opts.target Object to populate with content.
* @param string|undefined opts.blockName Name of the handlebars block (helper).
* @return object Hash of the content.
*/
handlebars.extract(opts)