Compare commits

..

No commits in common. "master" and "v0.1.0" have entirely different histories.

13 changed files with 19 additions and 1174 deletions

3
.gitignore vendored
View File

@ -4,6 +4,5 @@
*.orig *.orig
npm-debug.log npm-debug.log
node_modules/* node_modules/*
lib/
tmp/ tmp/
src/*.js
lib/*.js

View File

@ -22,7 +22,7 @@ lib:
$(cof_objects): $(cof_sources) $(cof_objects): $(cof_sources)
@mkdir -p $(@D) @mkdir -p $(@D)
$(foreach source, $(cof_sources), $(COFFEE) -o $(@D) -c $(source); ) $(COFFEE) -o $(@D) -c $<
$(peg_objects): $(peg_sources) $(peg_objects): $(peg_sources)
@mkdir -p $(@D) @mkdir -p $(@D)

View File

@ -36,13 +36,10 @@ a string or a number.
### If ### If
An "if:<name>" section can contain other objects, but the entirety of An "if:<name>" section can contain other objects, but the entirety of
the section is only rendered if the current context scope, and *only* the section is only rendered if the current context scope contains the
the current context scope, contains the current name, and the value current name, and the value associated with that name is "true" in a
associated with that name is "true" in a boolean context. You might boolean context. You might use to show someone's name, if the name
use to show someone's name, if the name field is populated, and show field is populated, and show nothing if it isn't.
nothing if it isn't. This is useful for detecting if the current
context has a field, but you don't want previous contexts' synonyms
showing up.
If your datasource returns: If your datasource returns:
@ -52,12 +49,6 @@ Then your template would use:
{if:name}Hello {name}!{/if:name} {if:name}Hello {name}!{/if:name}
### When
A "when:<name>" section is the same as the "if", but it will render if
the current context scope, and any previous context scope on the
stack, contains the current name.
### Block ### Block
A "block:<name>" section can contain other objects, but the entirety A "block:<name>" section can contain other objects, but the entirety

View File

@ -1,37 +0,0 @@
// Generated by CoffeeScript 1.6.1
(function() {
var fromFile, fs, parse, render, tumble;
tumble = require('./lexer').parse;
parse = require('./parser');
fs = require('fs');
render = function(str, options, callback) {
try {
return callback(null, parse(tumble(str), options));
} catch (err) {
return callback(err, null);
}
};
fromFile = function(path, options, callback) {
return fs.readFile(path, 'utf8', function(err, str) {
if (callback) {
if (err) {
return callback(err);
}
return callback(null, render(str, options, callback));
}
if (err) {
throw err;
}
});
};
fromFile.render = render;
module.exports = fromFile;
}).call(this);

View File

@ -1,850 +0,0 @@
module.exports = (function() {
/*
* Generated by PEG.js 0.7.0.
*
* http://pegjs.majda.cz/
*/
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
function SyntaxError(expected, found, offset, line, column) {
function buildMessage(expected, found) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\x08/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
var expectedDesc, foundDesc;
switch (expected.length) {
case 0:
expectedDesc = "end of input";
break;
case 1:
expectedDesc = expected[0];
break;
default:
expectedDesc = expected.slice(0, -1).join(", ")
+ " or "
+ expected[expected.length - 1];
}
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
}
this.expected = expected;
this.found = found;
this.offset = offset;
this.line = line;
this.column = column;
this.name = "SyntaxError";
this.message = buildMessage(expected, found);
}
peg$subclass(SyntaxError, Error);
function parse(input) {
var options = arguments.length > 1 ? arguments[1] : {},
peg$startRuleFunctions = { document: peg$parsedocument },
peg$startRuleFunction = peg$parsedocument,
peg$c0 = [],
peg$c1 = function(ps) { return { unit: "block", name: "document", content: ps }; },
peg$c2 = "tag_start",
peg$c3 = null,
peg$c4 = ":",
peg$c5 = "\":\"",
peg$c6 = function(b, n) { return is_valid_block_type(b); },
peg$c7 = "",
peg$c8 = function(b, n) { return {type: b, name: n }; },
peg$c9 = "/",
peg$c10 = "\"/\"",
peg$c11 = "tagname",
peg$c12 = /^[a-zA-Z]/,
peg$c13 = "[a-zA-Z]",
peg$c14 = function(t) { return t.join(''); },
peg$c15 = /^[a-zA-Z:\/]/,
peg$c16 = "[a-zA-Z:\\/]",
peg$c17 = "{",
peg$c18 = "\"{\"",
peg$c19 = "}",
peg$c20 = "\"}\"",
peg$c21 = "\n",
peg$c22 = "\"\\n\"",
peg$c23 = "\r\n",
peg$c24 = "\"\\r\\n\"",
peg$c25 = "\r",
peg$c26 = "\"\\r\"",
peg$c27 = "\u2028",
peg$c28 = "\"\\u2028\"",
peg$c29 = "\u2029",
peg$c30 = "\"\\u2029\"",
peg$c31 = "any character",
peg$c32 = function(c) {return c},
peg$c33 = function(bs) { return { unit: 'text', content: bs.join('') } },
peg$c34 = "variable",
peg$c35 = function(t) { return { unit: 'variable', name: t }; },
peg$c36 = function(t, ps, n) { return (t.type == n.type) && (t.name == n.name) },
peg$c37 = function(t, ps, n) { return {unit: 'block', type:t.type, name:t.name, content: ps } },
peg$currPos = 0,
peg$reportedPos = 0,
peg$cachedPos = 0,
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
peg$maxFailPos = 0,
peg$maxFailExpected = [],
peg$silentFails = 0,
peg$result;
if ("startRule" in options) {
if (!(options.startRule in peg$startRuleFunctions)) {
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
}
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
}
function text() {
return input.substring(peg$reportedPos, peg$currPos);
}
function offset() {
return peg$reportedPos;
}
function line() {
return peg$computePosDetails(peg$reportedPos).line;
}
function column() {
return peg$computePosDetails(peg$reportedPos).column;
}
function peg$computePosDetails(pos) {
function advance(details, startPos, endPos) {
var p, ch;
for (p = startPos; p < endPos; p++) {
ch = input.charAt(p);
if (ch === "\n") {
if (!details.seenCR) { details.line++; }
details.column = 1;
details.seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
details.line++;
details.column = 1;
details.seenCR = true;
} else {
details.column++;
details.seenCR = false;
}
}
}
if (peg$cachedPos !== pos) {
if (peg$cachedPos > pos) {
peg$cachedPos = 0;
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
}
advance(peg$cachedPosDetails, peg$cachedPos, pos);
peg$cachedPos = pos;
}
return peg$cachedPosDetails;
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
}
peg$maxFailExpected.push(expected);
}
function peg$cleanupExpected(expected) {
var i = 0;
expected.sort();
while (i < expected.length) {
if (expected[i - 1] === expected[i]) {
expected.splice(i, 1);
} else {
i++;
}
}
}
function peg$parsedocument() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsepart();
while (s2 !== null) {
s1.push(s2);
s2 = peg$parsepart();
}
if (s1 !== null) {
peg$reportedPos = s0;
s1 = peg$c1(s1);
}
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
return s0;
}
function peg$parsepart() {
var s0;
s0 = peg$parseblock();
if (s0 === null) {
s0 = peg$parsevariable();
if (s0 === null) {
s0 = peg$parsetext();
}
}
return s0;
}
function peg$parsetag_start() {
var s0, s1, s2, s3, s4, s5, s6;
peg$silentFails++;
s0 = peg$currPos;
s1 = peg$parseld();
if (s1 !== null) {
s2 = peg$parsetagname();
if (s2 !== null) {
if (input.charCodeAt(peg$currPos) === 58) {
s3 = peg$c4;
peg$currPos++;
} else {
s3 = null;
if (peg$silentFails === 0) { peg$fail(peg$c5); }
}
if (s3 !== null) {
s4 = peg$parsetagname();
if (s4 !== null) {
s5 = peg$parserd();
if (s5 !== null) {
peg$reportedPos = peg$currPos;
s6 = peg$c6(s2,s4);
if (s6) {
s6 = peg$c7;
} else {
s6 = peg$c3;
}
if (s6 !== null) {
peg$reportedPos = s0;
s1 = peg$c8(s2,s4);
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
peg$silentFails--;
if (s0 === null) {
s1 = null;
if (peg$silentFails === 0) { peg$fail(peg$c2); }
}
return s0;
}
function peg$parsetag_end() {
var s0, s1, s2, s3, s4, s5, s6;
s0 = peg$currPos;
s1 = peg$parseld();
if (s1 !== null) {
if (input.charCodeAt(peg$currPos) === 47) {
s2 = peg$c9;
peg$currPos++;
} else {
s2 = null;
if (peg$silentFails === 0) { peg$fail(peg$c10); }
}
if (s2 !== null) {
s3 = peg$parsetagname();
if (s3 !== null) {
if (input.charCodeAt(peg$currPos) === 58) {
s4 = peg$c4;
peg$currPos++;
} else {
s4 = null;
if (peg$silentFails === 0) { peg$fail(peg$c5); }
}
if (s4 !== null) {
s5 = peg$parsetagname();
if (s5 !== null) {
s6 = peg$parserd();
if (s6 !== null) {
peg$reportedPos = s0;
s1 = peg$c8(s3,s5);
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
return s0;
}
function peg$parsetagname() {
var s0, s1, s2;
peg$silentFails++;
s0 = peg$currPos;
s1 = [];
if (peg$c12.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = null;
if (peg$silentFails === 0) { peg$fail(peg$c13); }
}
if (s2 !== null) {
while (s2 !== null) {
s1.push(s2);
if (peg$c12.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = null;
if (peg$silentFails === 0) { peg$fail(peg$c13); }
}
}
} else {
s1 = peg$c3;
}
if (s1 !== null) {
peg$reportedPos = s0;
s1 = peg$c14(s1);
}
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
peg$silentFails--;
if (s0 === null) {
s1 = null;
if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
return s0;
}
function peg$parsetag() {
var s0, s1, s2, s3, s4, s5, s6;
s0 = peg$currPos;
s1 = peg$parseld();
if (s1 !== null) {
s2 = [];
s3 = peg$currPos;
s4 = peg$currPos;
peg$silentFails++;
s5 = peg$parserd();
peg$silentFails--;
if (s5 === null) {
s4 = peg$c7;
} else {
peg$currPos = s4;
s4 = peg$c3;
}
if (s4 !== null) {
s5 = peg$currPos;
peg$silentFails++;
s6 = peg$parseeol();
peg$silentFails--;
if (s6 === null) {
s5 = peg$c7;
} else {
peg$currPos = s5;
s5 = peg$c3;
}
if (s5 !== null) {
if (peg$c15.test(input.charAt(peg$currPos))) {
s6 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s6 = null;
if (peg$silentFails === 0) { peg$fail(peg$c16); }
}
if (s6 !== null) {
s4 = [s4, s5, s6];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c3;
}
} else {
peg$currPos = s3;
s3 = peg$c3;
}
} else {
peg$currPos = s3;
s3 = peg$c3;
}
if (s3 !== null) {
while (s3 !== null) {
s2.push(s3);
s3 = peg$currPos;
s4 = peg$currPos;
peg$silentFails++;
s5 = peg$parserd();
peg$silentFails--;
if (s5 === null) {
s4 = peg$c7;
} else {
peg$currPos = s4;
s4 = peg$c3;
}
if (s4 !== null) {
s5 = peg$currPos;
peg$silentFails++;
s6 = peg$parseeol();
peg$silentFails--;
if (s6 === null) {
s5 = peg$c7;
} else {
peg$currPos = s5;
s5 = peg$c3;
}
if (s5 !== null) {
if (peg$c15.test(input.charAt(peg$currPos))) {
s6 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s6 = null;
if (peg$silentFails === 0) { peg$fail(peg$c16); }
}
if (s6 !== null) {
s4 = [s4, s5, s6];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c3;
}
} else {
peg$currPos = s3;
s3 = peg$c3;
}
} else {
peg$currPos = s3;
s3 = peg$c3;
}
}
} else {
s2 = peg$c3;
}
if (s2 !== null) {
s3 = peg$parserd();
if (s3 !== null) {
s1 = [s1, s2, s3];
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
return s0;
}
function peg$parseld() {
var s0;
if (input.charCodeAt(peg$currPos) === 123) {
s0 = peg$c17;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c18); }
}
return s0;
}
function peg$parserd() {
var s0;
if (input.charCodeAt(peg$currPos) === 125) {
s0 = peg$c19;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c20); }
}
return s0;
}
function peg$parseeol() {
var s0;
if (input.charCodeAt(peg$currPos) === 10) {
s0 = peg$c21;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c22); }
}
if (s0 === null) {
if (input.substr(peg$currPos, 2) === peg$c23) {
s0 = peg$c23;
peg$currPos += 2;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c24); }
}
if (s0 === null) {
if (input.charCodeAt(peg$currPos) === 13) {
s0 = peg$c25;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c26); }
}
if (s0 === null) {
if (input.charCodeAt(peg$currPos) === 8232) {
s0 = peg$c27;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c28); }
}
if (s0 === null) {
if (input.charCodeAt(peg$currPos) === 8233) {
s0 = peg$c29;
peg$currPos++;
} else {
s0 = null;
if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
}
}
}
}
return s0;
}
function peg$parsetext() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = [];
s2 = peg$currPos;
s3 = peg$currPos;
peg$silentFails++;
s4 = peg$parsetag();
peg$silentFails--;
if (s4 === null) {
s3 = peg$c7;
} else {
peg$currPos = s3;
s3 = peg$c3;
}
if (s3 !== null) {
if (input.length > peg$currPos) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = null;
if (peg$silentFails === 0) { peg$fail(peg$c31); }
}
if (s4 !== null) {
peg$reportedPos = s2;
s3 = peg$c32(s4);
if (s3 === null) {
peg$currPos = s2;
s2 = s3;
} else {
s2 = s3;
}
} else {
peg$currPos = s2;
s2 = peg$c3;
}
} else {
peg$currPos = s2;
s2 = peg$c3;
}
if (s2 !== null) {
while (s2 !== null) {
s1.push(s2);
s2 = peg$currPos;
s3 = peg$currPos;
peg$silentFails++;
s4 = peg$parsetag();
peg$silentFails--;
if (s4 === null) {
s3 = peg$c7;
} else {
peg$currPos = s3;
s3 = peg$c3;
}
if (s3 !== null) {
if (input.length > peg$currPos) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = null;
if (peg$silentFails === 0) { peg$fail(peg$c31); }
}
if (s4 !== null) {
peg$reportedPos = s2;
s3 = peg$c32(s4);
if (s3 === null) {
peg$currPos = s2;
s2 = s3;
} else {
s2 = s3;
}
} else {
peg$currPos = s2;
s2 = peg$c3;
}
} else {
peg$currPos = s2;
s2 = peg$c3;
}
}
} else {
s1 = peg$c3;
}
if (s1 !== null) {
peg$reportedPos = s0;
s1 = peg$c33(s1);
}
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
return s0;
}
function peg$parsevariable() {
var s0, s1, s2, s3;
peg$silentFails++;
s0 = peg$currPos;
s1 = peg$parseld();
if (s1 !== null) {
s2 = peg$parsetagname();
if (s2 !== null) {
s3 = peg$parserd();
if (s3 !== null) {
peg$reportedPos = s0;
s1 = peg$c35(s2);
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
peg$silentFails--;
if (s0 === null) {
s1 = null;
if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
return s0;
}
function peg$parseblock() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parsetag_start();
if (s1 !== null) {
s2 = [];
s3 = peg$parsepart();
while (s3 !== null) {
s2.push(s3);
s3 = peg$parsepart();
}
if (s2 !== null) {
s3 = peg$parsetag_end();
if (s3 !== null) {
peg$reportedPos = peg$currPos;
s4 = peg$c36(s1,s2,s3);
if (s4) {
s4 = peg$c7;
} else {
s4 = peg$c3;
}
if (s4 !== null) {
peg$reportedPos = s0;
s1 = peg$c37(s1,s2,s3);
if (s1 === null) {
peg$currPos = s0;
s0 = s1;
} else {
s0 = s1;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
} else {
peg$currPos = s0;
s0 = peg$c3;
}
return s0;
}
var _VALID_BLOCK_TYPES = ['if', 'when', 'template', 'many', 'block'];
var _VBT_LENGTH = _VALID_BLOCK_TYPES.length;
function is_valid_block_type(b) {
for(var i = 0; i < _VBT_LENGTH; i++) {
if (_VALID_BLOCK_TYPES[i] == b) {
return true;
}
}
return false;
}
peg$result = peg$startRuleFunction();
if (peg$result !== null && peg$currPos === input.length) {
return peg$result;
} else {
peg$cleanupExpected(peg$maxFailExpected);
peg$reportedPos = Math.max(peg$currPos, peg$maxFailPos);
throw new SyntaxError(
peg$maxFailExpected,
peg$reportedPos < input.length ? input.charAt(peg$reportedPos) : null,
peg$reportedPos,
peg$computePosDetails(peg$reportedPos).line,
peg$computePosDetails(peg$reportedPos).column
);
}
}
return {
SyntaxError: SyntaxError,
parse : parse
};
})();

View File

@ -1,174 +0,0 @@
// Generated by CoffeeScript 1.6.1
(function() {
var Contexter, _;
_ = require('underscore');
Contexter = (function() {
function Contexter(content) {
this.content = content;
this.stack = [this.content];
this.templates = {};
this.depth = 0;
}
Contexter.prototype.has_any = function(name) {
return _.find(this.stack, function(o) {
return _.has(o, name);
});
};
Contexter.prototype.has_any_one = function(name) {
var p;
p = this.has_any(name);
if (p) {
return p[name];
} else {
return null;
}
};
Contexter.prototype.has = function(name) {
if (this.stack[0][name] != null) {
return this.stack[0][name];
} else {
return null;
}
};
Contexter.prototype.get = function(name, alt) {
var p;
if (alt == null) {
alt = '';
}
p = this.has_any_one(name);
if (p && (_.isString(p) || _.isNumber(p))) {
return p;
}
return this.render(name);
};
Contexter.prototype.once = function(obj, cb) {
var r;
this.stack.unshift(obj);
this.depth++;
if (this.depth > 10) {
throw new Error('recursion-error');
}
r = cb(this);
this.stack.shift();
this.depth--;
return r;
};
Contexter.prototype.when = function(name, cb) {
var p;
p = this.has_any_one(name);
if (p) {
return cb(this);
} else {
return '';
}
};
Contexter.prototype["if"] = function(name, cb) {
var p;
p = this.has(name);
if (p) {
return cb(this);
} else {
return '';
}
};
Contexter.prototype.block = function(name, cb) {
var p;
p = this.has_any_one(name);
if (p && _.isObject(p)) {
return this.once(p, cb);
} else {
return '';
}
};
Contexter.prototype.many = function(name, cb) {
var ps,
_this = this;
ps = this.has(name);
if (!(ps && _.isArray(ps))) {
return "";
}
return (_.map(ps, function(p) {
return _this.once(p, cb);
})).join('');
};
Contexter.prototype.template = function(name, cb) {
this.templates[name] = cb;
return "";
};
Contexter.prototype.render = function(name) {
var ret;
if ((this.templates[name] != null) && _.isFunction(this.templates[name])) {
this.depth++;
if (this.depth > 10) {
throw new Error('recursion-error');
}
ret = this.templates[name](this);
this.depth--;
return ret;
} else {
return "";
}
};
return Contexter;
})();
module.exports = function(ast, data) {
var cmd, context, o;
context = new Contexter(data);
cmd = function(o) {
switch (o.unit) {
case 'variable':
return function(context) {
return context.get(o.name);
};
case 'text':
return function(context) {
return o.content;
};
case 'block':
return function(context) {
return context[o.type](o.name, function(context) {
var p;
return ((function() {
var _i, _len, _ref, _results;
_ref = o.content;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
p = _ref[_i];
_results.push(cmd(p)(context));
}
return _results;
})()).join("");
});
};
}
};
return ((function() {
var _i, _len, _ref, _results;
_ref = ast.content;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
o = _ref[_i];
_results.push(cmd(o)(context));
}
return _results;
})()).join("");
};
}).call(this);

View File

@ -1,20 +0,0 @@
// Generated by CoffeeScript 1.6.1
(function() {
var engine, lexer, parse;
lexer = require('./lexer');
parse = require('./parser');
engine = require('./engine');
module.exports = {
tumble: lexer.parse,
parse: parse,
render: function(str, data) {
return parse(lexer.parse(str), data);
},
engine: engine
};
}).call(this);

View File

@ -1,7 +1,7 @@
{ {
"name": "tumble", "name": "Tumble",
"description": "Trivial reimplementation of Tumbler template parser/renderer", "description": "Trivial reimplementation of Tumbler template parser",
"version": "0.1.2", "version": "0.1.0",
"author": { "author": {
"name": "Kenneth \"Elf\" M. Sternberg", "name": "Kenneth \"Elf\" M. Sternberg",
"email": "elf.sternberg@gmail.com", "email": "elf.sternberg@gmail.com",
@ -9,12 +9,11 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/elfsternberg/tumble.git" "url": "ssh://elfstenberg@elfsternberg.com/home/elfsternberg/repos/tumble.git"
}, },
"licenses": [ "licenses": [
{ {
"type": "MIT", "type": "PRIVATE"
"url": "https://raw.github.com/elfsternberg/tumble/master/LICENSE"
} }
], ],
"main": "lib/tumble", "main": "lib/tumble",
@ -28,10 +27,9 @@
"underscore": "1.4.x" "underscore": "1.4.x"
}, },
"devDependencies": { "devDependencies": {
"coffeescript": "1.6.x",
"pegjs": "0.7.x", "pegjs": "0.7.x",
"mocha": "1.8.x", "mocha": "1.8.x",
"chai": "1.5.x" "chai": "1.5.x"
}, },
"keywords": ["template", "tumblr"] "keywords": []
} }

View File

@ -1,20 +0,0 @@
tumble = require('./lexer').parse;
parse = require('./parser');
fs = require 'fs'
render = (str, options, callback) ->
try
callback(null, parse(tumble(str), options))
catch err
callback(err, null)
fromFile = (path, options, callback) ->
fs.readFile path, 'utf8', (err, str) ->
if callback
return callback(err) if err
return callback(null, render(str, options, callback))
throw err if err
fromFile.render = render
module.exports = fromFile

View File

@ -1,4 +1,5 @@
_ = require 'underscore' _ = require 'underscore'
util = require 'util'
class Contexter class Contexter
@ -38,16 +39,10 @@ class Contexter
@depth-- @depth--
r r
when: (name, cb) ->
# Execute and return this specified block if and only if the
# requested context is valid.
p = @has_any_one(name)
if p then cb(@) else ''
if: (name, cb) -> if: (name, cb) ->
# Execute and return this specifiecd block if and only if the # Execute and return this specifiecd block if and only if the
# requested context is valid AND current # requested context is valid.
p = @has(name) p = @has_any_one(name)
if p then cb(@) else '' if p then cb(@) else ''
block: (name, cb) -> block: (name, cb) ->
@ -61,7 +56,8 @@ class Contexter
# the specified context if and only if the requested context # the specified context if and only if the requested context
# is valid and is iterable. # is valid and is iterable.
ps = @has(name) ps = @has(name)
return "" unless (ps and _.isArray(ps)) if not (ps and _.isArray(ps))
return ""
(_.map ps, (p) => @once(p, cb)).join('') (_.map ps, (p) => @once(p, cb)).join('')
template: (name, cb) -> template: (name, cb) ->
@ -70,16 +66,8 @@ class Contexter
return "" return ""
render: (name) -> render: (name) ->
if @templates[name]? and _.isFunction(@templates[name]) if @templates[name]? and _.isFunction(@templates[name]) then @templates[name](@) else ""
@depth++
throw new Error('recursion-error') if @depth > 10
ret = @templates[name](@)
@depth--
ret
else
""
# This is really the compiler at this point...
module.exports = (ast, data) -> module.exports = (ast, data) ->
context = new Contexter(data) context = new Contexter(data)

View File

@ -1,10 +0,0 @@
lexer = require './lexer'
parse = require './parser'
engine = require './engine'
module.exports = {
tumble: lexer.parse,
parse: parse,
render: (str, data) -> parse(lexer.parse(str), data)
engine: engine
}

View File

@ -1,18 +1,4 @@
// -*- mode: javascript -*- // -*- mode: javascript -*-
{
var _VALID_BLOCK_TYPES = ['if', 'when', 'template', 'many', 'block'];
var _VBT_LENGTH = _VALID_BLOCK_TYPES.length;
function is_valid_block_type(b) {
for(var i = 0; i < _VBT_LENGTH; i++) {
if (_VALID_BLOCK_TYPES[i] == b) {
return true;
}
}
return false;
}
}
document document
= ps:part* = ps:part*
@ -23,14 +9,8 @@ part
tag_start "tag_start" tag_start "tag_start"
= ld b:tagname ":" n:tagname rd = ld b:tagname ":" n:tagname rd
&{ return is_valid_block_type(b); }
{ return {type: b, name: n }; } { return {type: b, name: n }; }
block
= t:tag_start ps:part* n:tag_end
&{ return (t.type == n.type) && (t.name == n.name) }
{ return {unit: 'block', type:t.type, name:t.name, content: ps } }
tag_end tag_end
= ld '/' b:tagname ":" n:tagname rd = ld '/' b:tagname ":" n:tagname rd
{ return {type: b, name: n }; } { return {type: b, name: n }; }

View File

@ -6,7 +6,7 @@ util = require 'util'
fs = require 'fs' fs = require 'fs'
path = require 'path' path = require 'path'
tumble = require('../lib/lexer').parse; tumble = require('../lib/tumble').parse;
parse = require('../lib/parser'); parse = require('../lib/parser');
test_data = JSON.parse(fs.readFileSync(path.join(__dirname, 'data.json'), 'utf-8')) test_data = JSON.parse(fs.readFileSync(path.join(__dirname, 'data.json'), 'utf-8'))