toffee
Version:
A NodeJs and browser-side templating language based on CoffeeScript with slicker tokens and syntax.
599 lines (543 loc) • 27.3 kB
JavaScript
// Generated by CoffeeScript 1.12.7
(function() {
var TAB_SPACES, coffee, e, errorHandler, errorTypes, getBundleHeaders, getCommonHeaders, getCommonHeadersJs, parser, ref, ref1, spaces, states, tabs, toffeeError, util, utils, view, vm;
parser = require('./toffee_lang').parser;
ref = require('./errorHandler'), errorHandler = ref.errorHandler, toffeeError = ref.toffeeError, errorTypes = ref.errorTypes;
ref1 = require('./consts'), states = ref1.states, TAB_SPACES = ref1.TAB_SPACES;
utils = require('./utils');
vm = require('vm');
util = require('util');
try {
coffee = require("iced-coffee-script");
} catch (error) {
e = error;
coffee = require("coffee-script");
}
spaces = function(n) {
var i;
return ((function() {
var j, ref2, results;
results = [];
for (i = j = 0, ref2 = n; 0 <= ref2 ? j < ref2 : j > ref2; i = 0 <= ref2 ? ++j : --j) {
results.push(" ");
}
return results;
})()).join("");
};
tabs = function(n) {
var i;
return ((function() {
var j, ref2, results;
results = [];
for (i = j = 0, ref2 = n; 0 <= ref2 ? j < ref2 : j > ref2; i = 0 <= ref2 ? ++j : --j) {
results.push(spaces(TAB_SPACES));
}
return results;
})()).join("");
};
getCommonHeaders = function(tab_level, include_bundle_headers, auto_escape) {
/*
each view will use this, or if they're bundled together,
it'll only be used once.
include_bundle_headers: includes some functions needed for browser use
*/
var __;
__ = tabs(tab_level);
return "\n\n" + __ + "if not toffee? then toffee = {}\n" + __ + "if not toffee.templates then toffee.templates = {}\n\n" + __ + "toffee.states = " + (JSON.stringify(states)) + "\n\n" + __ + "toffee.__json = (locals, o, opts) ->\n" + __ + " opts or= {}\n" + __ + " opts.indent or= \"\"\n" + __ + " if not o?\n" + __ + " return \"null\"\n" + __ + " else\n" + __ + " return \"\" + JSON.stringify(o,null,opts.indent)\n" + __ + " .replace(/</g,'\\\\u003C').replace(/>/g,'\\\\u003E')\n" + __ + " .replace(/&/g,'\\\\u0026').replace(/\\u2028/g, '\\\\u2028')\n" + __ + " .replace(/\\u2029/g, '\\\\u2029')\n" + __ + " .replace(/\\u200e/g, '\\\\u200e') # LEFT-TO-RIGHT MARK\n" + __ + " .replace(/\\u200f/g, '\\\\u200f') # RIGHT-TO-LEFT MARK\n" + __ + " .replace(/\\u202a/g, '\\\\u202a') # LEFT-TO-RIGHT EMBEDDING\n" + __ + " .replace(/\\u202b/g, '\\\\u202b') # RIGHT-TO-LEFT EMBEDDING\n" + __ + " .replace(/\\u202c/g, '\\\\u202c') # POP DIRECTIONAL FORMATTING\n" + __ + " .replace(/\\u202d/g, '\\\\u202d') # LEFT-TO-RIGHT OVERRIDE\n" + __ + " .replace(/\\u202e/g, '\\\\u202e') # RIGHT-TO-LEFT OVERRIDE\n" + __ + " .replace(/\\u206a/g, '\\\\u206a') # INHIBIT SYMMETRIC SWAPPING\n" + __ + " .replace(/\\u206b/g, '\\\\u206b') # ACTIVATE SYMMETRIC SWAPPING\n" + __ + " .replace(/\\u206c/g, '\\\\u206c') # INHIBIT ARABIC FORM SHAPING\n" + __ + " .replace(/\\u206d/g, '\\\\u206d') # ACTIVATE ARABIC FORM SHAPING\n" + __ + " .replace(/\\u206e/g, '\\\\u206e') # NATIONAL DIGIT SHAPES\n" + __ + " .replace(/\\u206f/g, '\\\\u206f') # NOMINAL DIGIT SHAPES\n" + __ + " .replace(/\\u2066/g, '\\\\u2066') # LEFT-TO-RIGHT ISOLATE (LRI)\n" + __ + " .replace(/\\u2067/g, '\\\\u2067') # RIGHT-TO-LEFT ISOLATE (RLI)\n" + __ + " .replace(/\\u2068/g, '\\\\u2068') # FIRST STRONG ISOLATE (FSI)\n" + __ + " .replace(/\\u2069/g, '\\\\u2069') # POP DIRECTIONAL ISOLATE (PDI)\n\n\n" + __ + "toffee.__raw = (locals, o) -> o\n\n" + __ + "toffee.__html = (locals, o) ->\n" + __ + " (\"\"+o).replace(/&/g, '&')\n" + __ + " .replace(/</g, '<').replace(/>/g, '>')\n" + __ + " .replace(/\"/g, '"')\n" + __ + " .replace(/\\u200e/g, '') # LEFT-TO-RIGHT MARK\n" + __ + " .replace(/\\u200f/g, '') # RIGHT-TO-LEFT MARK\n" + __ + " .replace(/\\u202a/g, '') # LEFT-TO-RIGHT EMBEDDING\n" + __ + " .replace(/\\u202b/g, '') # RIGHT-TO-LEFT EMBEDDING\n" + __ + " .replace(/\\u202c/g, '') # POP DIRECTIONAL FORMATTING\n" + __ + " .replace(/\\u202d/g, '') # LEFT-TO-RIGHT OVERRIDE\n" + __ + " .replace(/\\u202e/g, '') # RIGHT-TO-LEFT OVERRIDE\n" + __ + " .replace(/\\u206a/g, '') # INHIBIT SYMMETRIC SWAPPING\n" + __ + " .replace(/\\u206b/g, '') # ACTIVATE SYMMETRIC SWAPPING\n" + __ + " .replace(/\\u206c/g, '') # INHIBIT ARABIC FORM SHAPING\n" + __ + " .replace(/\\u206d/g, '') # ACTIVATE ARABIC FORM SHAPING\n" + __ + " .replace(/\\u206e/g, '') # NATIONAL DIGIT SHAPES\n" + __ + " .replace(/\\u206f/g, '') # NOMINAL DIGIT SHAPES\n" + __ + " .replace(/\\u2066/g, '') # LEFT-TO-RIGHT ISOLATE (LRI)\n" + __ + " .replace(/\\u2067/g, '') # RIGHT-TO-LEFT ISOLATE (RLI)\n" + __ + " .replace(/\\u2068/g, '') # FIRST STRONG ISOLATE (FSI)\n" + __ + " .replace(/\\u2069/g, '') # POP DIRECTIONAL ISOLATE (PDI)\n\n\n" + __ + "toffee.__escape = (locals, o) ->\n" + __ + " if locals.__toffee.autoEscape? then ae = locals.__toffee.autoEscape\n" + __ + " else if " + (auto_escape != null) + " then ae = " + auto_escape + "\n" + __ + " else ae = true\n" + __ + " if ae\n" + __ + " if o is undefined then return ''\n" + __ + " if o? and (typeof o) is \"object\" then return locals.json o\n" + __ + " return locals.html o\n" + __ + " return o\n\n" + __ + "toffee.__augmentLocals = (locals, bundle_path) ->\n" + __ + " _l = locals\n" + __ + " _t = _l.__toffee = {out: []}\n" + __ + " if not _l.print? then _l.print = (o) -> toffee.__print _l, o\n" + __ + " if not _l.json? then _l.json = (o, opts) -> toffee.__json _l, o, opts\n" + __ + " if not _l.raw? then _l.raw = (o) -> toffee.__raw _l, o\n" + __ + " if not _l.html? then _l.html = (o) -> toffee.__html _l, o\n" + __ + " if not _l.escape? then _l.escape = (o) -> toffee.__escape _l, o\n" + __ + " if not _l.partial? then _l.partial = (path, vars) -> toffee.__partial toffee.templates[\"\#{bundle_path}\"], _l, path, vars\n" + __ + " if not _l.snippet? then _l.snippet = (path, vars) -> toffee.__snippet toffee.templates[\"\#{bundle_path}\"], _l, path, vars\n" + __ + " if not _l.load? then _l.load = (path, vars) -> toffee.__load toffee.templates[\"\#{bundle_path}\"], _l, path, vars\n" + __ + " _t.print = _l.print\n" + __ + " _t.json = _l.json\n" + __ + " _t.raw = _l.raw\n" + __ + " _t.html = _l.html\n" + __ + " _t.escape = _l.escape\n" + __ + " _t.partial = _l.partial\n" + __ + " _t.snippet = _l.snippet\n" + __ + " _t.load = _l.load\n\n" + (include_bundle_headers ? getBundleHeaders(tab_level) : "");
};
getBundleHeaders = function(tab_level) {
/*
header stuff
only needed when compiling to a JS file
*/
var __;
__ = tabs(tab_level);
return "\n\n" + __ + "toffee.__print = (locals, o) ->\n" + __ + " if locals.__toffee.state is toffee.states.COFFEE\n" + __ + " locals.__toffee.out.push o\n" + __ + " return ''\n" + __ + " else\n" + __ + " return \"\#{o}\"\n\n" + __ + "toffee.__normalize = (path) ->\n" + __ + " if (not path?) or path is \"/\"\n" + __ + " return path\n" + __ + " else\n" + __ + " parts = path.split \"/\"\n" + __ + " np = []\n" + __ + " # make sure path always starts with '/'\n" + __ + " if parts[0]\n" + __ + " np.push ''\n" + __ + " for part in parts\n" + __ + " if part is \"..\"\n" + __ + " if np.length > 1\n" + __ + " np.pop()\n" + __ + " else\n" + __ + " np.push part\n" + __ + " else\n" + __ + " if part isnt \".\"\n" + __ + " np.push part\n" + __ + " path = np.join \"/\"\n" + __ + " if not path then path = \"/\"\n" + __ + " return path\n\n" + __ + "toffee.__partial = (parent_tmpl, parent_locals, path, vars) ->\n" + __ + " path = toffee.__normalize parent_tmpl.bundlePath + \"/../\" + path\n" + __ + " return toffee.__inlineInclude path, vars, parent_locals\n\n" + __ + "toffee.__snippet = (parent_tmpl, parent_locals, path, vars) ->\n" + __ + " path = toffee.__normalize parent_tmpl.bundlePath + \"/../\" + path\n" + __ + " vars = if vars? then vars else {}\n" + __ + " vars.__toffee = vars.__toffee or {}\n" + __ + " vars.__toffee.noInheritance = true\n" + __ + " return toffee.__inlineInclude path, vars, parent_locals\n\n" + __ + "toffee.__load = (parent_tmpl, parent_locals, path, vars) ->\n" + __ + " path = toffee.__normalize parent_tmpl.bundlePath + \"/../\" + path\n" + __ + " vars = if vars? then vars else {}\n" + __ + " vars.__toffee = vars.__toffee or {}\n" + __ + " vars.__toffee.repress = true\n" + __ + " return toffee.__inlineInclude path, vars, parent_locals\n\n" + __ + "toffee.__inlineInclude = (path, locals, parent_locals) ->\n" + __ + " options = locals or {}\n" + __ + " options.passback = {}\n" + __ + " options.__toffee = options.__toffee or {}\n" + __ + "\n" + __ + " # we need to make a shallow copy of parent variables\n" + __ + " reserved = {}\n" + __ + " reserved[k] = true for k in [\"passback\", \"load\", \"print\", \"partial\", \"snippet\", \"layout\", \"__toffee\", \"postProcess\"]\n" + __ + " if not options.__toffee.noInheritance\n" + __ + " for k,v of parent_locals when not locals?[k]?\n" + __ + " if not reserved[k]?\n" + __ + " options[k] = v\n" + __ + "\n" + __ + " if not toffee.templates[path]\n" + __ + " return \"Inline toffee include: Could not find \#{path}\"\n" + __ + " else\n" + __ + " res = toffee.templates[path].pub options\n" + __ + " for k,v of options.passback\n" + __ + " parent_locals[k] = v\n" + __ + " return res";
};
getCommonHeadersJs = function(include_bundle_headers, auto_escape) {
var ch, js;
ch = getCommonHeaders(0, include_bundle_headers, auto_escape);
js = coffee.compile(ch, {
bare: true
});
return js;
};
view = (function() {
function view(txt, options) {
/*
important options:
cb: if this is set, compilation will happen async and cb will be executed when it's ready
*/
options = options || {};
this.fileName = options.fileName || options.filename || null;
this.bundlePath = options.bundlePath || "/";
this.browserMode = options.browserMode || false;
this.verbose = options.verbose || false;
this.fsError = options.fsError || false;
this.prettyPrintErrors = options.prettyPrintErrors != null ? options.prettyPrintErrors : true;
this.prettyLogErrors = options.prettyLogErrors != null ? options.prettyLogErrors : false;
this.autoEscape = options.autoEscape != null ? options.autoEscape : false;
this.additionalErrorHandler = options.additionalErrorHandler || null;
this.txt = txt;
this.tokenObj = null;
this.coffeeScript = null;
this.javaScript = null;
this.fun = null;
this.error = null;
if (options.cb) {
this._prepAsync(txt, options.ctx, ((function(_this) {
return function() {
return options.cb(_this);
};
})(this)));
}
}
view.prototype._prepAsync = function(txt, ctx, cb) {
/*
Only once it's fully compiled does it callback.
Defers via setTimeouts in each stage in the compile process
for CPU friendliness. This is a lot prettier with iced-coffee-script.
*/
var v;
ctx = ctx || vm.createContext({});
this._log("Prepping " + (this.fileName != null ? this.fileName : 'unknown') + " async.");
this._toTokenObj();
v = this;
return setTimeout(function() {
v.toCoffee();
return setTimeout(function() {
v.toJavaScript();
return setTimeout(function() {
v._toFun(ctx);
v._log("Done async prep of " + (v.fileName != null ? v.fileName : 'unknown') + ". Calling back.");
return cb();
}, 0);
}, 0);
}, 0);
};
view.prototype._log = function(o) {
var ref2;
if (this.verbose) {
if ((ref2 = typeof o) === "string" || ref2 === "number" || ref2 === "boolean") {
return console.log("toffee: " + o);
} else {
return console.log("toffee: " + (util.inspect(o)));
}
}
};
view.prototype._cleanTabs = function(obj) {
/*
replaces tabs with spaces in their coffee regions
*/
var item, j, len, ref2, ref3, results;
if ((ref2 = obj[0]) === "TOFFEE_ZONE" || ref2 === "COFFEE_ZONE") {
ref3 = obj[1];
results = [];
for (j = 0, len = ref3.length; j < len; j++) {
item = ref3[j];
results.push(this._cleanTabs(item));
}
return results;
} else if (obj[0] === "COFFEE") {
return obj[1] = obj[1].replace(/\t/g, tabs(1));
}
};
view.prototype.run = function(options, ctx) {
/*
returns [err, str]
*/
var fun, j, len, line, pair, ref2, res, txt;
ctx = ctx || vm.createContext({});
fun = this._toFun(ctx);
res = null;
if (!this.error) {
try {
res = fun(options);
} catch (error) {
e = error;
this.error = new toffeeError(this, errorTypes.RUNTIME, e);
}
}
if (this.error) {
if (this.prettyLogErrors) {
txt = this.error.getPrettyPrintText();
ref2 = txt.split("\n");
for (j = 0, len = ref2.length; j < len; j++) {
line = ref2[j];
console.log("toffee err: " + line);
}
}
if (this.additionalErrorHandler) {
this.additionalErrorHandler(this.error.getPrettyPrintText(), this.error.getPrettyPrint(), this.fileName, options);
}
if (this.prettyPrintErrors) {
pair = [null, this.error.getPrettyPrint()];
} else {
pair = [this.error.e, null];
}
if (this.error.errType === errorTypes.RUNTIME) {
this.error = null;
}
} else {
pair = [null, res];
}
return pair;
};
view.prototype._toTokenObj = function() {
/*
compiles Toffee to token array
*/
if (this.tokenObj == null) {
try {
this.tokenObj = parser.parse(this.txt);
} catch (error) {
e = error;
this.error = new toffeeError(this, errorTypes.PARSER, e);
}
if (this.error == null) {
this._cleanTabs(this.tokenObj);
}
}
return this.tokenObj;
};
view.prototype._toFun = function(ctx) {
var d, txt;
if (this.fun == null) {
txt = this.toJavaScript();
if (!this.error) {
d = Date.now();
vm.runInContext(txt, ctx);
this.fun = ctx['_TMPL_'];
this._log(this.fileName + " compiled to scriptObj in " + (Date.now() - d) + "ms");
}
}
return this.fun;
};
view.prototype.toJavaScript = function() {
var c, d, opts;
if (this.javaScript == null) {
c = this.toCoffee();
if (!this.error) {
d = Date.now();
try {
opts = {
bare: true
};
if (this.browserMode) {
opts.bare = false;
}
this.javaScript = coffee.compile(c, opts);
} catch (error) {
e = error;
this.error = new toffeeError(this, errorTypes.COFFEE_COMPILE, e);
}
this._log(this.fileName + " compiled to JavaScript in " + (Date.now() - d) + "ms");
}
}
return this.javaScript;
};
view.prototype.toCoffee = function() {
var d, res, tobj;
if (this.coffeeScript == null) {
tobj = this._toTokenObj();
if (!this.error) {
d = Date.now();
res = this._coffeeHeaders();
try {
res += this._toCoffeeRecurse(tobj, TAB_SPACES * (1 + this._globalTabLevel()), 0, {})[0];
res += this._coffeeFooters();
this.coffeeScript = res;
} catch (error) {
e = error;
console.log(e);
this.error;
}
this._log(this.fileName + " compiled to CoffeeScript in " + (Date.now() - d) + "ms");
}
}
return this.coffeeScript;
};
view.prototype._printLineNo = function(n, ind) {
if ((this.lastLineNo != null) && (n === this.lastLineNo)) {
return "";
} else {
this.lastLineNo = n;
return "\n" + (spaces(ind)) + "_ln " + n;
}
};
view.prototype._snippetHasEscapeOverride = function(str) {
var j, len, ref2, ref3, token;
ref2 = ['print', ' snippet', 'load', 'partial', 'raw', 'html', 'json', '__toffee.raw', '__toffee.html', '__toffee.json'];
for (j = 0, len = ref2.length; j < len; j++) {
token = ref2[j];
if (str.slice(0, token.length) === token) {
if ((str.length > token.length) && ((ref3 = str[token.length]) === ' ' || ref3 === '\t' || ref3 === '\n' || ref3 === '(')) {
return true;
}
}
}
return false;
};
view.prototype._snippetIsSoloToken = function(str) {
/*
if the inside is something like #{ foo } not #{ foo.bar } or other complex thing.
*/
if (str.match(/^[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*$/)) {
return true;
}
return false;
};
view.prototype._toCoffeeRecurse = function(obj, indent_level, indent_baseline, state_carry) {
var c, chunk, delta, i, i_delta, ind, interp, item, j, k, l, lbreak, len, len1, len2, len3, line, lineno, lines, m, part, ref2, ref3, ref4, ref5, res, s, t_int, temp_indent_level, zone_baseline;
res = "";
i_delta = 0;
switch (obj[0]) {
case "TOFFEE_ZONE":
if (state_carry.last_coffee_ends_with_newline === false) {
indent_level += TAB_SPACES;
}
res += "\n" + (spaces(indent_level)) + "_ts " + states.TOFFEE;
ref2 = obj[1];
for (j = 0, len = ref2.length; j < len; j++) {
item = ref2[j];
ref3 = this._toCoffeeRecurse(item, indent_level, indent_baseline, state_carry), s = ref3[0], delta = ref3[1];
res += s;
}
break;
case "COFFEE_ZONE":
res += "\n" + (spaces(indent_level)) + "_ts " + states.COFFEE;
zone_baseline = this._getZoneBaseline(obj[1]);
temp_indent_level = indent_level;
ref4 = obj[1];
for (k = 0, len1 = ref4.length; k < len1; k++) {
item = ref4[k];
ref5 = this._toCoffeeRecurse(item, temp_indent_level, zone_baseline, state_carry), s = ref5[0], delta = ref5[1];
res += s;
temp_indent_level = indent_level + delta;
}
break;
case "TOFFEE":
ind = indent_level;
res += "\n" + (spaces(ind)) + "_ts " + states.TOFFEE;
lineno = obj[2];
try {
t_int = utils.interpolateString(obj[1]);
} catch (error) {
e = error;
e.relayed_line_range = [lineno, lineno + obj[1].split("\n").length];
this.error = new toffeeError(this, errorTypes.STR_INTERPOLATE, e);
throw e;
}
for (l = 0, len2 = t_int.length; l < len2; l++) {
part = t_int[l];
if (part[0] === "TOKENS") {
res += this._printLineNo(lineno, ind);
interp = part[1].replace(/(^[\n \t]+)|([\n \t]+)$/g, '');
interp = interp.replace(/[\u2028\u2029]/g, '\n');
if (this._snippetIsSoloToken(interp)) {
chunk = "\#{if " + interp + "? then escape " + interp + " else ''}";
} else if (this._snippetHasEscapeOverride(interp)) {
chunk = "\#{" + interp + "}";
} else {
chunk = "\#{escape(" + interp + ")}";
}
res += "\n" + (spaces(ind)) + "_to " + (this._quoteStr(chunk));
lineno += part[1].split("\n").length - 1;
} else {
lines = part[1].split(/[\n\u2028\u2029]/);
for (i = m = 0, len3 = lines.length; m < len3; i = ++m) {
line = lines[i];
res += this._printLineNo(lineno, ind);
lbreak = i !== lines.length - 1 ? "\n" : "";
chunk = this._escapeForStr("" + line + lbreak);
if (chunk.length) {
res += "\n" + (spaces(ind)) + "_to " + (this._quoteStr(chunk + lbreak));
}
if (i < lines.length - 1) {
lineno++;
}
}
}
}
res += this._printLineNo(obj[2] + (obj[1].split('\n').length - 1), ind);
res += "\n" + (spaces(ind)) + "_ts " + states.COFFEE;
break;
case "COFFEE":
c = obj[1];
c = c.replace(/[\u2028\u2029]/g, '\n');
res += "\n" + (this._reindent(c, indent_level, indent_baseline));
i_delta = this._getIndentationDelta(c, indent_baseline);
state_carry.last_coffee_ends_with_newline = this._doesEndWithNewline(c);
break;
default:
throw "Bad parsing. " + obj + " not handled.";
return ["", 0];
}
return [res, i_delta];
};
view.prototype._quoteStr = function(s) {
/*
returns a triple-quoted string, dividing into single quoted
start and stops, if the string begins with double quotes, since
coffee doesn't want to let us escape those.
*/
var follow, lead, res;
lead = "";
follow = "";
while (s.length && (s[0] === '"')) {
s = s.slice(1);
lead += '"';
}
while (s.length && (s.slice(-1) === '"')) {
s = s.slice(0, -1);
follow += '"';
}
res = '';
if (lead.length) {
res += "\'" + lead + "\' + ";
}
res += '"""' + s + '"""';
if (follow.length) {
res += "+ \'" + follow + "\'";
}
return res;
};
view.prototype._doesEndWithNewline = function(s) {
var parts;
parts = s.split("\n");
if ((parts.length > 1) && parts[parts.length - 1].match(/^[\t ]*$/)) {
return true;
} else {
return false;
}
};
view.prototype._escapeForStr = function(s) {
/*
escapes a string so it can make it into coffeescript
triple quotes without losing whitespace, etc.
*/
s = s.replace(/\\/g, '\\\\');
s = s.replace(/\n/g, '\\n');
s = s.replace(/\t/g, '\\t');
return s;
};
view.prototype._getZoneBaseline = function(obj_arr) {
var ib, j, len, obj;
for (j = 0, len = obj_arr.length; j < len; j++) {
obj = obj_arr[j];
if (obj[0] === "COFFEE") {
ib = this._getIndentationBaseline(obj[1]);
if (ib != null) {
return ib;
}
}
}
return 0;
};
view.prototype._getIndentationBaseline = function(coffee) {
var i, j, len, line, lines, res;
res = null;
lines = coffee.split("\n");
if (lines.length) {
for (i = j = 0, len = lines.length; j < len; i = ++j) {
line = lines[i];
if ((!line.match(/^[ ]*$/)) || i === (lines.length - 1)) {
res = line.match(/[ ]*/)[0].length;
break;
}
}
}
if (res == null) {
res = coffee.length;
}
return res;
};
view.prototype._getIndentationDelta = function(coffee, baseline) {
/*
given an arbitrarily indented set of coffeescript, returns the delta
between the first and last lines, in chars.
Ignores leading/trailing whitespace lines
If passed a baseline, uses that instead of own.
*/
var lines, res, y, y_l;
if (baseline == null) {
baseline = this._getIndentationBaseline(coffee);
}
if (baseline == null) {
res = 0;
} else {
lines = coffee.split("\n");
if (lines.length < 1) {
res = 0;
} else {
y = lines[lines.length - 1];
y_l = y.match(/[ ]*/)[0].length;
res = y_l - baseline;
}
}
return res;
};
view.prototype._reindent = function(coffee, indent_level, indent_baseline) {
var indent, line, lines, res, rxx, strip;
lines = coffee.split('\n');
while (lines.length && lines[0].match(/^[ ]*$/)) {
lines = lines.slice(1);
}
if (!lines.length) {
return '';
}
rxx = /^[ ]*/;
strip = indent_baseline;
indent = spaces(indent_level);
res = ((function() {
var j, len, results;
results = [];
for (j = 0, len = lines.length; j < len; j++) {
line = lines[j];
results.push("" + indent + line.slice(strip));
}
return results;
})()).join("\n");
return res;
};
view.prototype._globalTabLevel = function() {
if (this.browserMode) {
return 0;
} else {
return 1;
}
};
view.prototype._globalTabs = function() {
return tabs(this._globalTabLevel());
};
view.prototype._coffeeHeaders = function() {
var __, ___;
__ = this._globalTabs();
___ = tabs(1);
return (this.browserMode ? '' : '_TMPL_ = (__toffee_run_input) ->' + (getCommonHeaders(1, false, this.autoEscape))) + "\n" + __ + "# browser mode = " + this.browserMode + "\n" + __ + "tmpl = toffee.templates[\"" + this.bundlePath + "\"] =\n" + __ + " bundlePath: \"" + this.bundlePath + "\"\n" + __ + "tmpl.render = tmpl.pub = (__locals) ->\n" + __ + ___ + "__locals = __locals or {}\n" + __ + ___ + "__repress = __locals.__toffee?.repress\n" + __ + ___ + "_to = (x) -> __locals.__toffee.out.push x\n" + __ + ___ + "_ln = (x) -> __locals.__toffee.lineno = x\n" + __ + ___ + "_ts = (x) -> __locals.__toffee.state = x\n" + __ + ___ + "toffee.__augmentLocals __locals, \"" + this.bundlePath + "\"\n\n" + __ + ___ + "`with (__locals) {`\n" + __ + ___ + "__toffee.out = []";
};
view.prototype._coffeeFooters = function() {
var __, ___;
__ = this._globalTabs();
___ = tabs(1);
return "\n\n" + __ + ___ + "__toffee.res = __toffee.out.join \"\"\n" + __ + ___ + "if postProcess?\n" + __ + ___ + ___ + "__toffee.res = postProcess __toffee.res\n" + __ + ___ + "if (not __repress) then return __toffee.res else return \"\"\n" + __ + "`true; } /* closing JS 'with' */ `\n" + __ + "# sometimes we want to execute the whole thing in a sandbox\n" + __ + "# and just output results\n" + __ + "if __toffee_run_input?\n" + __ + ___ + "return tmpl.pub __toffee_run_input";
};
return view;
})();
exports.view = view;
exports.getCommonHeaders = getCommonHeaders;
exports.getCommonHeadersJs = getCommonHeadersJs;
exports.expressCompile = function(txt, options) {
var v;
v = new view(txt, options);
return function(vars) {
var res;
res = v.run(vars);
if (res[0]) {
return res[0];
} else {
return res[1];
}
};
};
}).call(this);