devsite/node_modules/hamljs/haml.js

436 lines
13 KiB
JavaScript
Raw Permalink Normal View History

2024-07-08 01:49:38 +00:00
// Generated by uRequire v0.6.10 - template: 'AMD'
(function (window, global) {
var __isAMD = !!(typeof define === 'function' && define.amd),
__isNode = (typeof exports === 'object'),
__isWeb = !__isNode;
define(function (require, exports, module) {
var HAML = {};
HAML.version = "0.6.2";
HAML.cache = {};
HAML.errorContextLength = 15;
HAML.selfClosing = [
"meta",
"img",
"link",
"br",
"hr",
"input",
"area",
"base"
];
HAML.doctypes = {
"5": "<!DOCTYPE html>",
"xml": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>",
"default": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">",
"strict": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">",
"frameset": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">",
"1.1": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">",
"basic": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\" \"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd\">",
"mobile": "<!DOCTYPE html PUBLIC \"-//WAPFORUM//DTD XHTML Mobile 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd\">"
};
HAML.filters = {
plain: function (str, buf) {
buf.push(str);
},
cdata: function (str, buf) {
buf.push("<![CDATA[\n" + str + "\n]]>");
},
javascript: function (str, buf) {
buf.push("<script type=\"text/javascript\">\n//<![CDATA[\n" + str + "\n//]]></script>");
}
};
var HamlError = HAML.HamlError = function (msg) {
this.name = "HamlError";
this.message = msg;
Error.captureStackTrace(this, HAML.render);
};
HamlError.super_ = Error;
HamlError.prototype = Object.create(Error.prototype, {
constructor: {
value: HamlError,
enumerable: false,
writable: true,
configurable: true
}
});
var rules = {
indent: /^\n( *)(?! *-#)/,
conditionalComment: /^\/(\[[^\n]+\])/,
comment: /^\n? *\/ */,
silentComment: /^\n? *-#([^\n]*)/,
doctype: /^!!! *([^\n]*)/,
escape: /^\\(.)/,
filter: /^:(\w+) */,
each: /^\- *each *(\w+)(?: *, *(\w+))? * in ([^\n]+)/,
code: /^\-([^\n]+)/,
outputCode: /^!=([^\n]+)/,
escapeCode: /^=([^\n]+)/,
attrs: /^\{(.*?)\}/,
tag: /^%([-a-zA-Z][-a-zA-Z0-9:]*)/,
class: /^\.([\w\-]+)/,
id: /^\#([\w\-]+)/,
text: /^([^\n]+)/
};
function context(str) {
return String(str).substr(0, HAML.errorContextLength).replace(/\n/g, "\\n");
}
function tokenize(str) {
var captures, token, tokens = [], line = 1, lastIndents = 0, str = String(str).trim().replace(/\r\n|\r|\n *\n/g, "\n");
function error(msg) {
throw new HamlError("(Haml):" + line + " " + msg);
}
while (str.length) {
for (var type in rules)
if (captures = rules[type].exec(str)) {
token = {
type: type,
line: line,
match: captures[0],
val: captures.length > 2 ? captures.slice(1) : captures[1]
};
str = str.substr(captures[0].length);
if (type === "indent")
++line;
else
break;
var indents = token.val.length / 2;
if (indents % 1)
error("invalid indentation; got " + token.val.length + " spaces, should be multiple of 2");
else if (indents - 1 > lastIndents)
error("invalid indentation; got " + indents + ", when previous was " + lastIndents);
else if (lastIndents > indents)
while (lastIndents-- > indents)
tokens.push({
type: "outdent",
line: line
});
else if (lastIndents !== indents)
tokens.push({
type: "indent",
line: line
});
else
tokens.push({
type: "newline",
line: line
});
lastIndents = indents;
}
if (token) {
if (token.type !== "silentComment")
tokens.push(token);
token = null;
} else
error("near \"" + context(str) + "\"");
}
return tokens.concat({ type: "eof" });
}
var Parser = HAML.Parser = function (str, options) {
options = options || {};
this.tokens = tokenize(str);
this.xml = options.xml;
};
Parser.prototype = {
get peek() {
return this.tokens[0];
},
get advance() {
return this.current = this.tokens.shift();
},
get outdent() {
switch (this.peek.type) {
case "eof":
return;
case "outdent":
return this.advance;
default:
throw new HamlError("expected outdent, got " + this.peek.type);
}
},
get text() {
var text = this.advance.val.trim();
text = text.replace(/#\{(.*)\}/, "\" + $1 + \"");
this.buffer(text);
},
get block() {
this.advance;
while (this.peek.type !== "outdent" && this.peek.type !== "eof")
this.expr;
this.outdent;
},
get textBlock() {
var token, indents = 1;
this.advance;
while (this.peek.type !== "eof" && indents)
switch ((token = this.advance).type) {
case "newline":
this.buffer("\\n" + Array(indents).join(" ") + "");
break;
case "indent":
++indents;
this.buffer("\\n" + Array(indents).join(" ") + "");
break;
case "outdent":
--indents;
if (indents === 1)
this.buffer("\\n");
break;
default:
this.buffer(token.match.replace(/"/g, "\\\""));
}
},
get attrs() {
var attrs = [
"attrs",
"class",
"id"
], buf = [];
while (attrs.indexOf(this.peek.type) !== -1)
switch (this.peek.type) {
case "id":
buf.push("{ id: \"" + this.advance.val + "\" }");
break;
case "class":
buf.push("{ class: \"" + this.advance.val + "\" }");
break;
case "attrs":
buf.push("{ " + this.advance.val.replace(/(for) *:/gi, "\"$1\":") + " }");
}
return buf.length ? " \" + attrs([" + buf.join(", ") + "]) + \"" : "";
},
get tag() {
var tag = this.advance.val, selfClosing = !this.xml && HAML.selfClosing.indexOf(tag) !== -1;
this.buffer("\\n<" + tag + this.attrs + (selfClosing ? "/>" : ">"));
switch (this.peek.type) {
case "text":
this.text;
break;
case "conditionalComment":
this.conditionalComment;
break;
case "comment":
this.comment;
break;
case "outputCode":
this.outputCode;
break;
case "escapeCode":
this.escapeCode;
break;
case "indent":
this.block;
}
if (!selfClosing)
this.buffer("</" + tag + ">");
},
get outputCode() {
this.buffer(this.advance.val, false);
},
get escapeCode() {
this.buffer("escape(" + this.advance.val + ")", false);
},
get doctype() {
var doctype = this.advance.val.trim().toLowerCase() || "default";
if (doctype in HAML.doctypes)
this.buffer(HAML.doctypes[doctype].replace(/"/g, "\\\""));
else
throw new HamlError("doctype `" + doctype + "' does not exist");
},
get conditionalComment() {
var condition = this.advance.val;
this.buffer("<!--" + condition + ">");
this.peek.type === "indent" ? this.block : this.expr;
this.buffer("<![endif]-->");
},
get comment() {
this.advance;
this.buffer("<!-- ");
var buf = this.peek.type === "indent" ? this.block : this.expr;
this.buffer(" -->");
},
get code() {
var code = this.advance.val;
if (this.peek.type === "indent") {
this.buf.push(code);
this.buf.push("{");
this.block;
this.buf.push("}");
return;
}
this.buf.push(code);
},
get filter() {
var filter = this.advance.val;
if (!(filter in HAML.filters))
throw new HamlError("filter `" + filter + "' does not exist");
if (this.peek.type !== "indent")
throw new HamlError("filter `" + filter + "' expects a text block");
this.buf.push("HAML.filters." + filter + "(");
this.buf.push("(function(){");
this.buf.push("var buf = []");
this.textBlock;
this.buf.push("return buf.join(\"\")");
this.buf.push("}).call(this)");
this.buf.push(", buf)");
},
get iterate() {
var each = this.advance, key = each.val[1], vals = each.val[2], val = each.val[0];
if (this.peek.type !== "indent")
throw new HamlError("'- each' expects a block, but got " + this.peek.type);
this.buf.push("for (var " + (key || "index") + " in " + vals + ") {");
this.buf.push("var " + val + " = " + vals + "[" + (key || "index") + "];");
this.block;
this.buf.push("}");
},
get expr() {
switch (this.peek.type) {
case "id":
case "class":
this.tokens.unshift({
type: "tag",
val: "div"
});
return this.tag;
case "tag":
return this.tag;
case "text":
var buf = [];
while (this.peek.type === "text") {
buf.push(this.advance.val.trim());
if (this.peek.type === "newline")
this.advance;
}
return this.buffer(buf.join(" "));
case "each":
return this.iterate;
case "code":
return this.code;
case "escape":
return this.buffer(this.advance.val);
case "doctype":
return this.doctype;
case "filter":
return this.filter;
case "conditionalComment":
return this.conditionalComment;
case "comment":
return this.comment;
case "escapeCode":
return this.escapeCode;
case "outputCode":
return this.outputCode;
case "newline":
case "indent":
case "outdent":
this.advance;
return this.expr;
default:
throw new HamlError("unexpected " + this.peek.type);
}
},
get js() {
this.buf = [
"with (locals || {}) {",
" var buf = [];"
];
while (this.peek.type !== "eof")
this.expr;
this.buf.push(" return buf.join(\"\")");
this.buf.push("}");
return this.buf.join("\n");
},
buffer: function (str, quoted) {
if (typeof quoted === "undefined")
var quoted = true;
if (quoted)
this.buf.push(" buf.push(\"" + str + "\")");
else
this.buf.push(" buf.push(" + str + ")");
}
};
function escape(str) {
return String(str).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
}
function attrs(attrs) {
var finalAttrs = {}, classes = [], buf = [];
for (var i = 0, len = attrs.length; i < len; i++)
for (var attrName in attrs[i])
if (attrName === "class")
classes.push(attrs[i][attrName]);
else
finalAttrs[attrName] = attrs[i][attrName];
if (classes.length)
finalAttrs["class"] = classes.join(" ");
for (var key in finalAttrs)
if (typeof finalAttrs[key] === "boolean") {
if (finalAttrs[key] === true)
buf.push(key + "=\"" + key + "\"");
} else if (finalAttrs[key])
buf.push(key + "=\"" + escape(finalAttrs[key]) + "\"");
return buf.join(" ");
}
HAML.compile = function (str, options) {
var parser = new Parser(str, options);
var fn = new Function("locals, attrs, escape, HAML", parser.js);
return function (locals) {
return fn.apply(this, [
locals,
attrs,
escape,
HAML
]);
};
};
HAML.render = function (str, options) {
var parser, options = options || {};
if (options.cache && !options.filename)
throw new Error("filename option must be passed when cache is enabled");
return function () {
try {
var fn;
if (options.cache && HAML.cache[options.filename])
fn = HAML.cache[options.filename];
else {
parser = new Parser(str, options);
fn = Function("locals, attrs, escape, HAML", parser.js);
}
return (options.cache ? HAML.cache[options.filename] = fn : fn).call(options.context, options.locals, attrs, escape, HAML);
} catch (err) {
if (parser && err instanceof HamlError)
err.message = "(Haml):" + parser.peek.line + " " + err.message;
else if (!(err instanceof HamlError))
err.message = "(Haml): " + err.message;
if (options.filename)
err.message = err.message.replace("Haml", options.filename);
throw err;
}
}.call(options.context);
};
HAML.renderFile = function (filename, encoding, options, callback) {
var fs = require("fs");
options = options || {};
options.filename = options.filename || filename;
options.cache = options.hasOwnProperty("cache") ? options.cache : true;
if (HAML.cache[filename]) {
process.nextTick(function () {
callback(null, HAML.render(null, options));
});
} else {
fs.readFile(filename, encoding, function (err, str) {
if (err) {
callback(err);
} else {
callback(null, HAML.render(str, options));
}
});
}
};
module.exports = HAML;
return module.exports;
})
}).call(this, (typeof exports === 'object' ? global : window), (typeof exports === 'object' ? global : window))