0.1.1 • Published 9 years ago

stache-backwards v0.1.1

Weekly downloads
2
License
MIT
Repository
github
Last release
9 years ago

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: '&lt;p&gt;'
}

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: '&lt;p&gt;'
}

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)