{I"
class:ETI"BundledAsset; FI"logical_path; TI"clientside-haml.js; FI"
pathname; TI"^/Applications/XAMPP/xamppfiles/htdocs/polyblock/app/assets/javascripts/clientside-haml.js; FI"content_type; TI"application/javascript; TI"
mtime; Tl+URI"length; Ti-:I"digest; TI"%b154f4303a3f6f8c662a436c3eb7f281; FI"source; TI"-:// Generated by CoffeeScript 1.6.2
/*
clientside HAML compiler for Javascript and Coffeescript (Version 5)
Copyright 2011-12, Ronald Holshausen (https://github.com/uglyog)
Released under the MIT License (http://www.opensource.org/licenses/MIT)
*/
(function() {
var Buffer, CodeGenerator, CoffeeCodeGenerator, HamlRuntime, JsCodeGenerator, ProductionJsCodeGenerator, Tokeniser, filters, haml, root, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
root = this;
/*
Haml runtime functions. These are used both by the compiler and the generated template functions
*/
HamlRuntime = {
/*
Taken from underscore.string.js escapeHTML, and replace the apos entity with character 39 so that it renders
correctly in IE7
*/
escapeHTML: function(str) {
return String(str || '').replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, "'");
},
/*
Provides the implementation to preserve the whitespace as per the HAML reference
*/
perserveWhitespace: function(str) {
var i, out, re, result;
re = /<[a-zA-Z]+>[^<]*<\/[a-zA-Z]+>/g;
out = '';
i = 0;
result = re.exec(str);
if (result) {
while (result) {
out += str.substring(i, result.index);
out += result[0].replace(/\n/g, '
');
i = result.index + result[0].length;
result = re.exec(str);
}
out += str.substring(i);
} else {
out = str;
}
return out;
},
/*
Generates a error message including the current line in the source where the error occurred
*/
templateError: function(lineNumber, characterNumber, currentLine, error) {
var i, message;
message = error + " at line " + lineNumber + " and character " + characterNumber + ":\n" + currentLine + '\n';
i = 0;
while (i < characterNumber - 1) {
message += '-';
i++;
}
message += '^';
return message;
},
/*
Generates the attributes for the element by combining all the various sources together
*/
generateElementAttributes: function(context, id, classes, objRefFn, attrList, attrFunction, lineNumber, characterNumber, currentLine, handleError) {
var attr, attributes, className, e, ex, hash, html, object, objectId, value;
if (handleError == null) {
handleError = this._raiseError;
}
attributes = {};
attributes = this.combineAttributes(attributes, 'id', id);
if (classes.length > 0 && classes[0].length > 0) {
attributes = this.combineAttributes(attributes, 'class', classes);
}
if (attrList != null) {
for (attr in attrList) {
if (!__hasProp.call(attrList, attr)) continue;
value = attrList[attr];
attributes = this.combineAttributes(attributes, attr, value);
}
}
if (objRefFn != null) {
try {
object = objRefFn.call(context, context);
if (object != null) {
objectId = null;
if (object.id != null) {
objectId = object.id;
} else if (object.get) {
objectId = object.get('id');
}
attributes = this.combineAttributes(attributes, 'id', objectId);
className = null;
if (object['class']) {
className = object['class'];
} else if (object.get) {
className = object.get('class');
}
attributes = this.combineAttributes(attributes, 'class', className);
}
} catch (_error) {
e = _error;
handleError(haml.HamlRuntime.templateError(lineNumber, characterNumber, currentLine, "Error evaluating object reference - " + e));
}
}
if (attrFunction != null) {
try {
hash = attrFunction.call(context, context);
if (hash != null) {
hash = this._flattenHash(null, hash);
for (attr in hash) {
if (!__hasProp.call(hash, attr)) continue;
value = hash[attr];
attributes = this.combineAttributes(attributes, attr, value);
}
}
} catch (_error) {
ex = _error;
handleError(haml.HamlRuntime.templateError(lineNumber, characterNumber, currentLine, "Error evaluating attribute hash - " + ex));
}
}
html = '';
if (attributes) {
for (attr in attributes) {
if (!__hasProp.call(attributes, attr)) continue;
if (haml.hasValue(attributes[attr])) {
if ((attr === 'id' || attr === 'for') && attributes[attr] instanceof Array) {
html += ' ' + attr + '="' + _(attributes[attr]).flatten().join('-') + '"';
} else if (attr === 'class' && attributes[attr] instanceof Array) {
html += ' ' + attr + '="' + _(attributes[attr]).flatten().join(' ') + '"';
} else {
html += ' ' + attr + '="' + haml.attrValue(attr, attributes[attr]) + '"';
}
}
}
}
return html;
},
/*
Returns a white space string with a length of indent * 2
*/
indentText: function(indent) {
var i, text;
text = '';
i = 0;
while (i < indent) {
text += ' ';
i++;
}
return text;
},
/*
Combines the attributes in the attributres hash with the given attribute and value
ID, FOR and CLASS attributes will expand to arrays when multiple values are provided
*/
combineAttributes: function(attributes, attrName, attrValue) {
var classes;
if (haml.hasValue(attrValue)) {
if (attrName === 'id' && attrValue.toString().length > 0) {
if (attributes && attributes.id instanceof Array) {
attributes.id.unshift(attrValue);
} else if (attributes && attributes.id) {
attributes.id = [attributes.id, attrValue];
} else if (attributes) {
attributes.id = attrValue;
} else {
attributes = {
id: attrValue
};
}
} else if (attrName === 'for' && attrValue.toString().length > 0) {
if (attributes && attributes['for'] instanceof Array) {
attributes['for'].unshift(attrValue);
} else if (attributes && attributes['for']) {
attributes['for'] = [attributes['for'], attrValue];
} else if (attributes) {
attributes['for'] = attrValue;
} else {
attributes = {
'for': attrValue
};
}
} else if (attrName === 'class') {
classes = [];
if (attrValue instanceof Array) {
classes = classes.concat(attrValue);
} else {
classes.push(attrValue);
}
if (attributes && attributes['class']) {
attributes['class'] = attributes['class'].concat(classes);
} else if (attributes) {
attributes['class'] = classes;
} else {
attributes = {
'class': classes
};
}
} else if (attrName !== 'id') {
attributes || (attributes = {});
attributes[attrName] = attrValue;
}
}
return attributes;
},
/*
Flattens a deeply nested hash into a single hash by combining the keys with a minus
*/
_flattenHash: function(rootKey, object) {
var attr, flattenedValue, key, keys, newKey, newValue, result, value;
result = {};
if (this._isHash(object)) {
for (attr in object) {
if (!__hasProp.call(object, attr)) continue;
value = object[attr];
keys = [];
if (rootKey != null) {
keys.push(rootKey);
}
keys.push(attr);
key = keys.join('-');
flattenedValue = this._flattenHash(key, value);
if (this._isHash(flattenedValue)) {
for (newKey in flattenedValue) {
if (!__hasProp.call(flattenedValue, newKey)) continue;
newValue = flattenedValue[newKey];
result[newKey] = newValue;
}
} else {
result[key] = flattenedValue;
}
}
} else if (rootKey != null) {
result[rootKey] = object;
} else {
result = object;
}
return result;
},
_isHash: function(object) {
return (object != null) && typeof object === 'object' && !(object instanceof Array || object instanceof Date);
},
_logError: function(message) {
return typeof console !== "undefined" && console !== null ? console.log(message) : void 0;
},
_raiseError: function(message) {
throw new Error(message);
},
/*
trims the first number of characters from a string
*/
trim: function(str, chars) {
return str.substring(chars);
}
};
/*
HAML Tokiniser: This class is responsible for parsing the haml source into tokens
*/
Tokeniser = (function() {
Tokeniser.prototype.currentLineMatcher = /[^\n]*/g;
Tokeniser.prototype.tokenMatchers = {
whitespace: /[ \t]+/g,
element: /%[a-zA-Z][a-zA-Z0-9]*/g,
idSelector: /#[a-zA-Z_\-][a-zA-Z0-9_\-]*/g,
classSelector: /\.[a-zA-Z0-9_\-]+/g,
identifier: /[a-zA-Z][a-zA-Z0-9\-]*/g,
quotedString: /[\'][^\'\n]*[\']/g,
quotedString2: /[\"][^\"\n]*[\"]/g,
comment: /\-#/g,
escapeHtml: /\&=/g,
unescapeHtml: /\!=/g,
objectReference: /\[[a-zA-Z_@][a-zA-Z0-9_]*\]/g,
doctype: /!!!/g,
continueLine: /\|\s*\n/g,
filter: /:\w+/g
};
function Tokeniser(options) {
var errorFn, successFn, template,
_this = this;
this.buffer = null;
this.bufferIndex = null;
this.prevToken = null;
this.token = null;
if (options.templateId != null) {
template = document.getElementById(options.templateId);
if (template) {
this.buffer = template.text;
this.bufferIndex = 0;
} else {
throw "Did not find a template with ID '" + options.templateId + "'";
}
} else if (options.template != null) {
this.buffer = options.template;
this.bufferIndex = 0;
} else if (options.templateUrl != null) {
errorFn = function(jqXHR, textStatus, errorThrown) {
throw "Failed to fetch haml template at URL " + options.templateUrl + ": " + textStatus + " " + errorThrown;
};
successFn = function(data) {
_this.buffer = data;
return _this.bufferIndex = 0;
};
jQuery.ajax({
url: options.templateUrl,
success: successFn,
error: errorFn,
dataType: 'text',
async: false,
beforeSend: function(xhr) {
return xhr.withCredentials = true;
}
});
}
}
/*
Try to match a token with the given regexp
*/
Tokeniser.prototype.matchToken = function(matcher) {
var result;
matcher.lastIndex = this.bufferIndex;
result = matcher.exec(this.buffer);
if ((result != null ? result.index : void 0) === this.bufferIndex) {
return result[0];
}
};
/*
Match a multi-character token
*/
Tokeniser.prototype.matchMultiCharToken = function(matcher, token, tokenStr) {
var matched, _ref;
if (!this.token) {
matched = this.matchToken(matcher);
if (matched) {
this.token = token;
this.token.tokenString = (_ref = typeof tokenStr === "function" ? tokenStr(matched) : void 0) != null ? _ref : matched;
this.token.matched = matched;
return this.advanceCharsInBuffer(matched.length);
}
}
};
/*
Match a single character token
*/
Tokeniser.prototype.matchSingleCharToken = function(ch, token) {
if (!this.token && this.buffer.charAt(this.bufferIndex) === ch) {
this.token = token;
this.token.tokenString = ch;
this.token.matched = ch;
return this.advanceCharsInBuffer(1);
}
};
/*
Match and return the next token in the input buffer
*/
Tokeniser.prototype.getNextToken = function() {
var ch, ch1, str;
if (isNaN(this.bufferIndex)) {
throw haml.HamlRuntime.templateError(this.lineNumber, this.characterNumber, this.currentLine, "An internal parser error has occurred in the HAML parser");
}
this.prevToken = this.token;
this.token = null;
if (this.buffer === null || this.buffer.length === this.bufferIndex) {
this.token = {
eof: true,
token: 'EOF'
};
} else {
this.initLine();
if (!this.token) {
ch = this.buffer.charCodeAt(this.bufferIndex);
ch1 = this.buffer.charCodeAt(this.bufferIndex + 1);
if (ch === 10 || (ch === 13 && ch1 === 10)) {
this.token = {
eol: true,
token: 'EOL'
};
if (ch === 13 && ch1 === 10) {
this.advanceCharsInBuffer(2);
this.token.matched = String.fromCharCode(ch) + String.fromCharCode(ch1);
} else {
this.advanceCharsInBuffer(1);
this.token.matched = String.fromCharCode(ch);
}
this.characterNumber = 0;
this.currentLine = this.getCurrentLine();
}
}
this.matchMultiCharToken(this.tokenMatchers.whitespace, {
ws: true,
token: 'WS'
});
this.matchMultiCharToken(this.tokenMatchers.continueLine, {
continueLine: true,
token: 'CONTINUELINE'
});
this.matchMultiCharToken(this.tokenMatchers.element, {
element: true,
token: 'ELEMENT'
}, function(matched) {
return matched.substring(1);
});
this.matchMultiCharToken(this.tokenMatchers.idSelector, {
idSelector: true,
token: 'ID'
}, function(matched) {
return matched.substring(1);
});
this.matchMultiCharToken(this.tokenMatchers.classSelector, {
classSelector: true,
token: 'CLASS'
}, function(matched) {
return matched.substring(1);
});
this.matchMultiCharToken(this.tokenMatchers.identifier, {
identifier: true,
token: 'IDENTIFIER'
});
this.matchMultiCharToken(this.tokenMatchers.doctype, {
doctype: true,
token: 'DOCTYPE'
});
this.matchMultiCharToken(this.tokenMatchers.filter, {
filter: true,
token: 'FILTER'
}, function(matched) {
return matched.substring(1);
});
if (!this.token) {
str = this.matchToken(this.tokenMatchers.quotedString);
if (!str) {
str = this.matchToken(this.tokenMatchers.quotedString2);
}
if (str) {
this.token = {
string: true,
token: 'STRING',
tokenString: str.substring(1, str.length - 1),
matched: str
};
this.advanceCharsInBuffer(str.length);
}
}
this.matchMultiCharToken(this.tokenMatchers.comment, {
comment: true,
token: 'COMMENT'
});
this.matchMultiCharToken(this.tokenMatchers.escapeHtml, {
escapeHtml: true,
token: 'ESCAPEHTML'
});
this.matchMultiCharToken(this.tokenMatchers.unescapeHtml, {
unescapeHtml: true,
token: 'UNESCAPEHTML'
});
this.matchMultiCharToken(this.tokenMatchers.objectReference, {
objectReference: true,
token: 'OBJECTREFERENCE'
}, function(matched) {
return matched.substring(1, matched.length - 1);
});
if (!this.token && this.buffer && this.buffer.charAt(this.bufferIndex) === '{') {
this.matchJavascriptHash();
}
this.matchSingleCharToken('(', {
openBracket: true,
token: 'OPENBRACKET'
});
this.matchSingleCharToken(')', {
closeBracket: true,
token: 'CLOSEBRACKET'
});
this.matchSingleCharToken('=', {
equal: true,
token: 'EQUAL'
});
this.matchSingleCharToken('/', {
slash: true,
token: 'SLASH'
});
this.matchSingleCharToken('!', {
exclamation: true,
token: 'EXCLAMATION'
});
this.matchSingleCharToken('-', {
minus: true,
token: 'MINUS'
});
this.matchSingleCharToken('&', {
amp: true,
token: 'AMP'
});
this.matchSingleCharToken('<', {
lt: true,
token: 'LT'
});
this.matchSingleCharToken('>', {
gt: true,
token: 'GT'
});
this.matchSingleCharToken('~', {
tilde: true,
token: 'TILDE'
});
if (this.token === null) {
this.token = {
unknown: true,
token: 'UNKNOWN',
matched: this.buffer.charAt(this.bufferIndex)
};
this.advanceCharsInBuffer(1);
}
}
return this.token;
};
/*
Look ahead a number of tokens and return the token found
*/
Tokeniser.prototype.lookAhead = function(numberOfTokens) {
var bufferIndex, characterNumber, currentLine, currentToken, i, lineNumber, prevToken, token;
token = null;
if (numberOfTokens > 0) {
currentToken = this.token;
prevToken = this.prevToken;
currentLine = this.currentLine;
lineNumber = this.lineNumber;
characterNumber = this.characterNumber;
bufferIndex = this.bufferIndex;
i = 0;
while (i++ < numberOfTokens) {
token = this.getNextToken();
}
this.token = currentToken;
this.prevToken = prevToken;
this.currentLine = currentLine;
this.lineNumber = lineNumber;
this.characterNumber = characterNumber;
this.bufferIndex = bufferIndex;
}
return token;
};
/*
Initilise the line and character counters
*/
Tokeniser.prototype.initLine = function() {
if (!this.currentLine && this.currentLine !== "") {
this.currentLine = this.getCurrentLine();
this.lineNumber = 1;
return this.characterNumber = 0;
}
};
/*
Returns the current line in the input buffer
*/
Tokeniser.prototype.getCurrentLine = function(index) {
var line;
this.currentLineMatcher.lastIndex = this.bufferIndex + (index != null ? index : 0);
line = this.currentLineMatcher.exec(this.buffer);
if (line) {
return line[0];
} else {
return '';
}
};
/*
Returns an error string filled out with the line and character counters
*/
Tokeniser.prototype.parseError = function(error) {
return haml.HamlRuntime.templateError(this.lineNumber, this.characterNumber, this.currentLine, error);
};
/*
Skips to the end of the line and returns the string that was skipped
*/
Tokeniser.prototype.skipToEOLorEOF = function() {
var contents, line, text;
text = '';
if (!(this.token.eof || this.token.eol)) {
if (this.token.matched != null) {
text += this.token.matched;
}
this.currentLineMatcher.lastIndex = this.bufferIndex;
line = this.currentLineMatcher.exec(this.buffer);
if (line && line.index === this.bufferIndex) {
contents = (_.str || _).rtrim(line[0]);
if ((_.str || _).endsWith(contents, '|')) {
text += contents.substring(0, contents.length - 1);
this.advanceCharsInBuffer(contents.length - 1);
this.getNextToken();
text += this.parseMultiLine();
} else {
text += line[0];
this.advanceCharsInBuffer(line[0].length);
this.getNextToken();
}
}
}
return text;
};
/*
Parses a multiline code block and returns the parsed text
*/
Tokeniser.prototype.parseMultiLine = function() {
var contents, line, text;
text = '';
while (this.token.continueLine) {
this.currentLineMatcher.lastIndex = this.bufferIndex;
line = this.currentLineMatcher.exec(this.buffer);
if (line && line.index === this.bufferIndex) {
contents = (_.str || _).rtrim(line[0]);
if ((_.str || _).endsWith(contents, '|')) {
text += contents.substring(0, contents.length - 1);
this.advanceCharsInBuffer(contents.length - 1);
}
this.getNextToken();
}
}
return text;
};
/*
Advances the input buffer pointer by a number of characters, updating the line and character counters
*/
Tokeniser.prototype.advanceCharsInBuffer = function(numChars) {
var ch, ch1, i;
i = 0;
while (i < numChars) {
ch = this.buffer.charCodeAt(this.bufferIndex + i);
ch1 = this.buffer.charCodeAt(this.bufferIndex + i + 1);
if (ch === 13 && ch1 === 10) {
this.lineNumber++;
this.characterNumber = 0;
this.currentLine = this.getCurrentLine(i);
i++;
} else if (ch === 10) {
this.lineNumber++;
this.characterNumber = 0;
this.currentLine = this.getCurrentLine(i);
} else {
this.characterNumber++;
}
i++;
}
return this.bufferIndex += numChars;
};
/*
Returns the current line and character counters
*/
Tokeniser.prototype.currentParsePoint = function() {
return {
lineNumber: this.lineNumber,
characterNumber: this.characterNumber,
currentLine: this.currentLine
};
};
/*
Pushes back the current token onto the front of the input buffer
*/
Tokeniser.prototype.pushBackToken = function() {
if (!this.token.eof) {
this.bufferIndex -= this.token.matched.length;
return this.token = this.prevToken;
}
};
/*
Is the current token an end of line or end of input buffer
*/
Tokeniser.prototype.isEolOrEof = function() {
return this.token.eol || this.token.eof;
};
/*
Match a Javascript Hash {...}
*/
Tokeniser.prototype.matchJavascriptHash = function() {
var braceCount, ch, chCode, characterNumberStart, currentIndent, i, lineNumberStart;
currentIndent = this.calculateCurrentIndent();
i = this.bufferIndex + 1;
characterNumberStart = this.characterNumber;
lineNumberStart = this.lineNumber;
braceCount = 1;
while (i < this.buffer.length && (braceCount > 1 || this.buffer.charAt(i) !== '}')) {
ch = this.buffer.charAt(i);
chCode = this.buffer.charCodeAt(i);
if (ch === '{') {
braceCount++;
i++;
} else if (ch === '}') {
braceCount--;
i++;
} else if (chCode === 10 || chCode === 13) {
i++;
} else {
i++;
}
}
if (i === this.buffer.length) {
this.characterNumber = characterNumberStart + 1;
this.lineNumber = lineNumberStart;
throw this.parseError('Error parsing attribute hash - Did not find a terminating "}"');
} else {
this.token = {
attributeHash: true,
token: 'ATTRHASH',
tokenString: this.buffer.substring(this.bufferIndex, i + 1),
matched: this.buffer.substring(this.bufferIndex, i + 1)
};
return this.advanceCharsInBuffer(i - this.bufferIndex + 1);
}
};
/*
Calculate the indent value of the current line
*/
Tokeniser.prototype.calculateCurrentIndent = function() {
var result;
this.tokenMatchers.whitespace.lastIndex = 0;
result = this.tokenMatchers.whitespace.exec(this.currentLine);
if ((result != null ? result.index : void 0) === 0) {
return this.calculateIndent(result[0]);
} else {
return 0;
}
};
/*
Calculate the indent level of the provided whitespace
*/
Tokeniser.prototype.calculateIndent = function(whitespace) {
var i, indent;
indent = 0;
i = 0;
while (i < whitespace.length) {
if (whitespace.charCodeAt(i) === 9) {
indent += 2;
} else {
indent++;
}
i++;
}
return Math.floor((indent + 1) / 2);
};
return Tokeniser;
})();
/*
Provides buffering between the generated javascript and html contents
*/
Buffer = (function() {
function Buffer(generator) {
this.generator = generator;
this.buffer = '';
this.outputBuffer = '';
}
Buffer.prototype.append = function(str) {
if ((this.generator != null) && this.buffer.length === 0) {
this.generator.mark();
}
if ((str != null ? str.length : void 0) > 0) {
return this.buffer += str;
}
};
Buffer.prototype.appendToOutputBuffer = function(str) {
if ((str != null ? str.length : void 0) > 0) {
this.flush();
return this.outputBuffer += str;
}
};
Buffer.prototype.flush = function() {
var _ref;
if (((_ref = this.buffer) != null ? _ref.length : void 0) > 0) {
this.outputBuffer += this.generator.generateFlush(this.buffer);
}
return this.buffer = '';
};
Buffer.prototype.output = function() {
return this.outputBuffer;
};
Buffer.prototype.trimWhitespace = function() {
var ch, i;
if (this.buffer.length > 0) {
i = this.buffer.length - 1;
while (i > 0) {
ch = this.buffer.charAt(i);
if (this._isWhitespace(ch)) {
i--;
} else if (i > 1 && (ch === 'n' || ch === 't') && (this.buffer.charAt(i - 1) === '\\')) {
i -= 2;
} else {
break;
}
}
if (i > 0 && i < this.buffer.length - 1) {
return this.buffer = this.buffer.substring(0, i + 1);
} else if (i === 0 && this._isWhitespace(this.buffer.charAt(0))) {
return this.buffer = '';
}
}
};
Buffer.prototype._isWhitespace = function(ch) {
return ch === ' ' || ch === '\t' || ch === '\n';
};
return Buffer;
})();
/*
Common code shared across all code generators
*/
CodeGenerator = (function() {
function CodeGenerator() {}
CodeGenerator.prototype.embeddedCodeBlockMatcher = /#{([^}]*)}/g;
return CodeGenerator;
})();
/*
Code generator that generates a Javascript function body
*/
JsCodeGenerator = (function(_super) {
__extends(JsCodeGenerator, _super);
function JsCodeGenerator(options) {
this.options = options;
this.outputBuffer = new haml.Buffer(this);
}
/*
Append a line with embedded javascript code
*/
JsCodeGenerator.prototype.appendEmbeddedCode = function(indentText, expression, escapeContents, perserveWhitespace, currentParsePoint) {
this.outputBuffer.flush();
this.outputBuffer.appendToOutputBuffer(indentText + 'try {\n');
this.outputBuffer.appendToOutputBuffer(indentText + ' var value = eval("' + (_.str || _).trim(expression).replace(/"/g, '\\"').replace(/\\n/g, '\\\\n') + '");\n');
this.outputBuffer.appendToOutputBuffer(indentText + ' value = value === null ? "" : value;');
if (escapeContents) {
this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(haml.HamlRuntime.escapeHTML(String(value)));\n');
} else if (perserveWhitespace) {
this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(haml.HamlRuntime.perserveWhitespace(String(value)));\n');
} else {
this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(String(value));\n');
}
this.outputBuffer.appendToOutputBuffer(indentText + '} catch (e) {\n');
this.outputBuffer.appendToOutputBuffer(indentText + ' handleError(haml.HamlRuntime.templateError(' + currentParsePoint.lineNumber + ', ' + currentParsePoint.characterNumber + ', "' + this.escapeCode(currentParsePoint.currentLine) + '",\n');
this.outputBuffer.appendToOutputBuffer(indentText + ' "Error evaluating expression - " + e));\n');
return this.outputBuffer.appendToOutputBuffer(indentText + '}\n');
};
/*
Initilising the output buffer with any variables or code
*/
JsCodeGenerator.prototype.initOutput = function() {
var _ref;
if ((_ref = this.options) != null ? _ref.tolerateFaults : void 0) {
this.outputBuffer.appendToOutputBuffer(' var handleError = haml.HamlRuntime._logError;');
} else {
this.outputBuffer.appendToOutputBuffer(' var handleError = haml.HamlRuntime._raiseError;');
}
return this.outputBuffer.appendToOutputBuffer('var html = [];\nvar hashFunction = null, hashObject = null, objRef = null, objRefFn = null;\nwith (context || {}) {');
};
/*
Flush and close the output buffer and return the contents
*/
JsCodeGenerator.prototype.closeAndReturnOutput = function() {
this.outputBuffer.flush();
return this.outputBuffer.output() + ' }\n return html.join("");\n';
};
/*
Append a line of code to the output buffer
*/
JsCodeGenerator.prototype.appendCodeLine = function(line, eol) {
this.outputBuffer.flush();
this.outputBuffer.appendToOutputBuffer(HamlRuntime.indentText(this.indent));
this.outputBuffer.appendToOutputBuffer(line);
return this.outputBuffer.appendToOutputBuffer(eol);
};
/*
Does the current line end with a function declaration?
*/
JsCodeGenerator.prototype.lineMatchesStartFunctionBlock = function(line) {
return line.match(/function\s*\((,?\s*\w+)*\)\s*\{\s*$/);
};
/*
Does the current line end with a starting code block
*/
JsCodeGenerator.prototype.lineMatchesStartBlock = function(line) {
return line.match(/\{\s*$/);
};
/*
Generate the code to close off a code block
*/
JsCodeGenerator.prototype.closeOffCodeBlock = function(tokeniser) {
if (!(tokeniser.token.minus && tokeniser.matchToken(/\s*\}/g))) {
this.outputBuffer.flush();
return this.outputBuffer.appendToOutputBuffer(HamlRuntime.indentText(this.indent) + '}\n');
}
};
/*
Generate the code to close off a function parameter
*/
JsCodeGenerator.prototype.closeOffFunctionBlock = function(tokeniser) {
if (!(tokeniser.token.minus && tokeniser.matchToken(/\s*\}/g))) {
this.outputBuffer.flush();
return this.outputBuffer.appendToOutputBuffer(HamlRuntime.indentText(this.indent) + '});\n');
}
};
/*
Generate the code for dynamic attributes ({} form)
*/
JsCodeGenerator.prototype.generateCodeForDynamicAttributes = function(id, classes, attributeList, attributeHash, objectRef, currentParsePoint) {
this.outputBuffer.flush();
if (attributeHash.length > 0) {
attributeHash = this.replaceReservedWordsInHash(attributeHash);
this.outputBuffer.appendToOutputBuffer(' hashFunction = function () { return eval("hashObject = ' + attributeHash.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"); };\n');
} else {
this.outputBuffer.appendToOutputBuffer(' hashFunction = null;\n');
}
if (objectRef.length > 0) {
this.outputBuffer.appendToOutputBuffer(' objRefFn = function () { return eval("objRef = ' + objectRef.replace(/"/g, '\\"') + '"); };\n');
} else {
this.outputBuffer.appendToOutputBuffer(' objRefFn = null;\n');
}
return this.outputBuffer.appendToOutputBuffer(' html.push(haml.HamlRuntime.generateElementAttributes(context, "' + id + '", ["' + classes.join('","') + '"], objRefFn, ' + JSON.stringify(attributeList) + ', hashFunction, ' + currentParsePoint.lineNumber + ', ' + currentParsePoint.characterNumber + ', "' + this.escapeCode(currentParsePoint.currentLine) + '", handleError));\n');
};
/*
Clean any reserved words in the given hash
*/
JsCodeGenerator.prototype.replaceReservedWordsInHash = function(hash) {
var reservedWord, resultHash, _i, _len, _ref;
resultHash = hash;
_ref = ['class', 'for'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
reservedWord = _ref[_i];
resultHash = resultHash.replace(reservedWord + ':', '"' + reservedWord + '":');
}
return resultHash;
};
/*
Escape the line so it is safe to put into a javascript string
*/
JsCodeGenerator.prototype.escapeCode = function(jsStr) {
return jsStr.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
};
/*
Generate a function from the function body
*/
JsCodeGenerator.prototype.generateJsFunction = function(functionBody) {
var e;
try {
return new Function('context', functionBody);
} catch (_error) {
e = _error;
throw "Incorrect embedded code has resulted in an invalid Haml function - " + e + "\nGenerated Function:\n" + functionBody;
}
};
/*
Generate the code required to support a buffer flush
*/
JsCodeGenerator.prototype.generateFlush = function(bufferStr) {
return ' html.push("' + this.escapeCode(bufferStr) + '");\n';
};
/*
Set the current indent level
*/
JsCodeGenerator.prototype.setIndent = function(indent) {
return this.indent = indent;
};
/*
Save the current indent level if required
*/
JsCodeGenerator.prototype.mark = function() {};
/*
Append the text contents to the buffer, expanding any embedded code
*/
JsCodeGenerator.prototype.appendTextContents = function(text, shouldInterpolate, currentParsePoint, options) {
if (options == null) {
options = {};
}
if (shouldInterpolate && text.match(/#{[^}]*}/)) {
return this.interpolateString(text, currentParsePoint, options);
} else {
return this.outputBuffer.append(this.processText(text, options));
}
};
/*
Interpolate any embedded code in the text
*/
JsCodeGenerator.prototype.interpolateString = function(text, currentParsePoint, options) {
var index, precheedingChar, precheedingChar2, result;
index = 0;
result = this.embeddedCodeBlockMatcher.exec(text);
while (result) {
if (result.index > 0) {
precheedingChar = text.charAt(result.index - 1);
}
if (result.index > 1) {
precheedingChar2 = text.charAt(result.index - 2);
}
if (precheedingChar === '\\' && precheedingChar2 !== '\\') {
if (result.index !== 0) {
this.outputBuffer.append(this.processText(text.substring(index, result.index - 1), options));
}
this.outputBuffer.append(this.processText(result[0]), options);
} else {
this.outputBuffer.append(this.processText(text.substring(index, result.index)), options);
this.appendEmbeddedCode(HamlRuntime.indentText(this.indent + 1), result[1], options.escapeHTML, options.perserveWhitespace, currentParsePoint);
}
index = this.embeddedCodeBlockMatcher.lastIndex;
result = this.embeddedCodeBlockMatcher.exec(text);
}
if (index < text.length) {
return this.outputBuffer.append(this.processText(text.substring(index), options));
}
};
/*
process text based on escape and preserve flags
*/
JsCodeGenerator.prototype.processText = function(text, options) {
if (options != null ? options.escapeHTML : void 0) {
return haml.HamlRuntime.escapeHTML(text);
} else if (options != null ? options.perserveWhitespace : void 0) {
return haml.HamlRuntime.perserveWhitespace(text);
} else {
return text;
}
};
return JsCodeGenerator;
})(CodeGenerator);
/*
Code generator that generates javascript code without runtime evaluation
*/
ProductionJsCodeGenerator = (function(_super) {
__extends(ProductionJsCodeGenerator, _super);
function ProductionJsCodeGenerator() {
_ref = ProductionJsCodeGenerator.__super__.constructor.apply(this, arguments);
return _ref;
}
/*
Append a line with embedded javascript code
*/
ProductionJsCodeGenerator.prototype.appendEmbeddedCode = function(indentText, expression, escapeContents, perserveWhitespace, currentParsePoint) {
this.outputBuffer.flush();
this.outputBuffer.appendToOutputBuffer(indentText + ' value = ' + (_.str || _).trim(expression) + ';\n');
this.outputBuffer.appendToOutputBuffer(indentText + ' value = value === null ? "" : value;');
if (escapeContents) {
return this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(haml.HamlRuntime.escapeHTML(String(value)));\n');
} else if (perserveWhitespace) {
return this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(haml.HamlRuntime.perserveWhitespace(String(value)));\n');
} else {
return this.outputBuffer.appendToOutputBuffer(indentText + ' html.push(String(value));\n');
}
};
/*
Generate the code for dynamic attributes ({} form)
*/
ProductionJsCodeGenerator.prototype.generateCodeForDynamicAttributes = function(id, classes, attributeList, attributeHash, objectRef, currentParsePoint) {
this.outputBuffer.flush();
if (attributeHash.length > 0) {
attributeHash = this.replaceReservedWordsInHash(attributeHash);
this.outputBuffer.appendToOutputBuffer(' hashFunction = function () { return ' + attributeHash + '; };\n');
} else {
this.outputBuffer.appendToOutputBuffer(' hashFunction = null;\n');
}
if (objectRef.length > 0) {
this.outputBuffer.appendToOutputBuffer(' objRefFn = function () { return ' + objectRef + '; };\n');
} else {
this.outputBuffer.appendToOutputBuffer(' objRefFn = null;\n');
}
return this.outputBuffer.appendToOutputBuffer(' html.push(haml.HamlRuntime.generateElementAttributes(context, "' + id + '", ["' + classes.join('","') + '"], objRefFn, ' + JSON.stringify(attributeList) + ', hashFunction, ' + currentParsePoint.lineNumber + ', ' + currentParsePoint.characterNumber + ', "' + this.escapeCode(currentParsePoint.currentLine) + '"));\n');
};
/*
Initilising the output buffer with any variables or code
*/
ProductionJsCodeGenerator.prototype.initOutput = function() {
return this.outputBuffer.appendToOutputBuffer(' var html = [];\n' + ' var hashFunction = null, hashObject = null, objRef = null, objRefFn = null, value= null;\n with (context || {}) {\n');
};
return ProductionJsCodeGenerator;
})(JsCodeGenerator);
/*
Code generator that generates a coffeescript function body
*/
CoffeeCodeGenerator = (function(_super) {
__extends(CoffeeCodeGenerator, _super);
function CoffeeCodeGenerator(options) {
this.options = options;
this.outputBuffer = new haml.Buffer(this);
}
CoffeeCodeGenerator.prototype.appendEmbeddedCode = function(indentText, expression, escapeContents, perserveWhitespace, currentParsePoint) {
var indent;
this.outputBuffer.flush();
indent = this.calcCodeIndent();
this.outputBuffer.appendToOutputBuffer(indent + "try\n");
this.outputBuffer.appendToOutputBuffer(indent + " exp = CoffeeScript.compile('" + expression.replace(/'/g, "\\'").replace(/\\n/g, '\\\\n') + "', bare: true)\n");
this.outputBuffer.appendToOutputBuffer(indent + " value = eval(exp)\n");
this.outputBuffer.appendToOutputBuffer(indent + " value ?= ''\n");
if (escapeContents) {
this.outputBuffer.appendToOutputBuffer(indent + " html.push(haml.HamlRuntime.escapeHTML(String(value)))\n");
} else if (perserveWhitespace) {
this.outputBuffer.appendToOutputBuffer(indent + " html.push(haml.HamlRuntime.perserveWhitespace(String(value)))\n");
} else {
this.outputBuffer.appendToOutputBuffer(indent + " html.push(String(value))\n");
}
this.outputBuffer.appendToOutputBuffer(indent + "catch e \n");
this.outputBuffer.appendToOutputBuffer(indent + " handleError new Error(haml.HamlRuntime.templateError(" + currentParsePoint.lineNumber + ", " + currentParsePoint.characterNumber + ", '" + this.escapeCode(currentParsePoint.currentLine) + "',\n");
return this.outputBuffer.appendToOutputBuffer(indent + " 'Error evaluating expression - ' + e))\n");
};
CoffeeCodeGenerator.prototype.initOutput = function() {
var _ref1;
if ((_ref1 = this.options) != null ? _ref1.tolerateFaults : void 0) {
this.outputBuffer.appendToOutputBuffer('handleError = haml.HamlRuntime._logError\n');
} else {
this.outputBuffer.appendToOutputBuffer('handleError = haml.HamlRuntime._raiseError\n');
}
return this.outputBuffer.appendToOutputBuffer('html = []\n');
};
CoffeeCodeGenerator.prototype.closeAndReturnOutput = function() {
this.outputBuffer.flush();
return this.outputBuffer.output() + 'return html.join("")\n';
};
CoffeeCodeGenerator.prototype.appendCodeLine = function(line, eol) {
this.outputBuffer.flush();
this.outputBuffer.appendToOutputBuffer(this.calcCodeIndent());
this.outputBuffer.appendToOutputBuffer((_.str || _).trim(line));
this.outputBuffer.appendToOutputBuffer(eol);
return this.prevCodeIndent = this.indent;
};
CoffeeCodeGenerator.prototype.lineMatchesStartFunctionBlock = function(line) {
return line.match(/\) [\-=]>\s*$/);
};
CoffeeCodeGenerator.prototype.lineMatchesStartBlock = function(line) {
return true;
};
CoffeeCodeGenerator.prototype.closeOffCodeBlock = function(tokeniser) {
return this.outputBuffer.flush();
};
CoffeeCodeGenerator.prototype.closeOffFunctionBlock = function(tokeniser) {
return this.outputBuffer.flush();
};
CoffeeCodeGenerator.prototype.generateCodeForDynamicAttributes = function(id, classes, attributeList, attributeHash, objectRef, currentParsePoint) {
var indent;
this.outputBuffer.flush();
indent = this.calcCodeIndent();
if (attributeHash.length > 0) {
attributeHash = this.replaceReservedWordsInHash(attributeHash);
this.outputBuffer.appendToOutputBuffer(indent + "hashFunction = () -> s = CoffeeScript.compile('" + attributeHash.replace(/'/g, "\\'").replace(/\n/g, '\\n') + "', bare: true); eval 'hashObject = ' + s\n");
} else {
this.outputBuffer.appendToOutputBuffer(indent + "hashFunction = null\n");
}
if (objectRef.length > 0) {
this.outputBuffer.appendToOutputBuffer(indent + "objRefFn = () -> s = CoffeeScript.compile('" + objectRef.replace(/'/g, "\\'") + "', bare: true); eval 'objRef = ' + s\n");
} else {
this.outputBuffer.appendToOutputBuffer(indent + "objRefFn = null\n");
}
return this.outputBuffer.appendToOutputBuffer(indent + "html.push(haml.HamlRuntime.generateElementAttributes(this, '" + id + "', ['" + classes.join("','") + "'], objRefFn ? null, " + JSON.stringify(attributeList) + ", hashFunction ? null, " + currentParsePoint.lineNumber + ", " + currentParsePoint.characterNumber + ", '" + this.escapeCode(currentParsePoint.currentLine) + "', handleError))\n");
};
CoffeeCodeGenerator.prototype.replaceReservedWordsInHash = function(hash) {
var reservedWord, resultHash, _i, _len, _ref1;
resultHash = hash;
_ref1 = ['class', 'for'];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
reservedWord = _ref1[_i];
resultHash = resultHash.replace(reservedWord + ':', "'" + reservedWord + "':");
}
return resultHash;
};
/*
Escapes the string for insertion into the generated code. Embedded code blocks in strings must not be escaped
*/
CoffeeCodeGenerator.prototype.escapeCode = function(str) {
var index, outString, precheedingChar, precheedingChar2, result;
outString = '';
index = 0;
result = this.embeddedCodeBlockMatcher.exec(str);
while (result) {
if (result.index > 0) {
precheedingChar = str.charAt(result.index - 1);
}
if (result.index > 1) {
precheedingChar2 = str.charAt(result.index - 2);
}
if (precheedingChar === '\\' && precheedingChar2 !== '\\') {
if (result.index !== 0) {
outString += this._escapeText(str.substring(index, result.index - 1));
}
outString += this._escapeText('\\' + result[0]);
} else {
outString += this._escapeText(str.substring(index, result.index));
outString += result[0];
}
index = this.embeddedCodeBlockMatcher.lastIndex;
result = this.embeddedCodeBlockMatcher.exec(str);
}
if (index < str.length) {
outString += this._escapeText(str.substring(index));
}
return outString;
};
CoffeeCodeGenerator.prototype._escapeText = function(text) {
return text.replace(/\\/g, '\\\\').replace(/'/g, '\\\'').replace(/"/g, '\\\"').replace(/\n/g, '\\n').replace(/(^|[^\\]{2})\\\\#{/g, '$1\\#{');
};
/*
Generates the javascript function by compiling the given code with coffeescript compiler
*/
CoffeeCodeGenerator.prototype.generateJsFunction = function(functionBody) {
var e, fn;
try {
fn = CoffeeScript.compile(functionBody, {
bare: true
});
return new Function(fn);
} catch (_error) {
e = _error;
throw "Incorrect embedded code has resulted in an invalid Haml function - " + e + "\nGenerated Function:\n" + fn;
}
};
CoffeeCodeGenerator.prototype.generateFlush = function(bufferStr) {
return this.calcCodeIndent() + "html.push('" + this.escapeCode(bufferStr) + "')\n";
};
CoffeeCodeGenerator.prototype.setIndent = function(indent) {
return this.indent = indent;
};
CoffeeCodeGenerator.prototype.mark = function() {
return this.prevIndent = this.indent;
};
CoffeeCodeGenerator.prototype.calcCodeIndent = function() {
var codeIndent, i, _i, _ref1, _ref2, _ref3;
codeIndent = 0;
for (i = _i = 0, _ref1 = this.indent; 0 <= _ref1 ? _i <= _ref1 : _i >= _ref1; i = 0 <= _ref1 ? ++_i : --_i) {
if (((_ref2 = this.elementStack[i]) != null ? _ref2.block : void 0) || ((_ref3 = this.elementStack[i]) != null ? _ref3.fnBlock : void 0)) {
codeIndent += 1;
}
}
return HamlRuntime.indentText(codeIndent);
};
/*
Append the text contents to the buffer (interpolating embedded code not required for coffeescript)
*/
CoffeeCodeGenerator.prototype.appendTextContents = function(text, shouldInterpolate, currentParsePoint, options) {
var prefix, suffix;
if (shouldInterpolate && text.match(/#{[^}]*}/)) {
this.outputBuffer.flush();
prefix = suffix = '';
if (options != null ? options.escapeHTML : void 0) {
prefix = 'haml.HamlRuntime.escapeHTML(';
suffix = ')';
} else if (options != null ? options.perserveWhitespace : void 0) {
prefix = 'haml.HamlRuntime.perserveWhitespace(';
suffix = ')';
}
return this.outputBuffer.appendToOutputBuffer(this.calcCodeIndent() + 'html.push(' + prefix + '"' + this.escapeCode(text) + '"' + suffix + ')\n');
} else {
if (options != null ? options.escapeHTML : void 0) {
text = haml.HamlRuntime.escapeHTML(text);
}
if (options != null ? options.perserveWhitespace : void 0) {
text = haml.HamlRuntime.perserveWhitespace(text);
}
return this.outputBuffer.append(text);
}
};
return CoffeeCodeGenerator;
})(CodeGenerator);
/*
HAML filters are functions that take 3 parameters
contents: The contents block for the filter an array of lines of text
generator: The current generator for the compiled function
indent: The current indent level
currentParsePoint: line and character counters for the current parse point in the input buffer
*/
filters = {
/*
Plain filter, just renders the text in the block
*/
plain: function(contents, generator, indent, currentParsePoint) {
var line, _i, _len;
for (_i = 0, _len = contents.length; _i < _len; _i++) {
line = contents[_i];
generator.appendTextContents(haml.HamlRuntime.indentText(indent - 1) + line + '\n', true, currentParsePoint);
}
return true;
},
/*
Wraps the filter block in a javascript tag
*/
javascript: function(contents, generator, indent, currentParsePoint) {
var line, _i, _len;
generator.outputBuffer.append(haml.HamlRuntime.indentText(indent) + "\n");
},
/*
Wraps the filter block in a style tag
*/
css: function(contents, generator, indent, currentParsePoint) {
var line, _i, _len;
generator.outputBuffer.append(haml.HamlRuntime.indentText(indent) + "\n");
},
/*
Wraps the filter block in a CDATA tag
*/
cdata: function(contents, generator, indent, currentParsePoint) {
var line, _i, _len;
generator.outputBuffer.append(haml.HamlRuntime.indentText(indent) + "\n");
},
/*
Preserve filter, preserved blocks of text aren't indented, and newlines are replaced with the HTML escape code for newlines
*/
preserve: function(contents, generator, indent, currentParsePoint) {
var line;
generator.appendTextContents(haml.HamlRuntime.indentText(indent), false, currentParsePoint);
return generator.appendTextContents(((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = contents.length; _i < _len; _i++) {
line = contents[_i];
_results.push(haml.HamlRuntime.trim(line, 2));
}
return _results;
})()).join('
') + '\n', true, currentParsePoint);
},
/*
Escape filter, renders the text in the block with html escaped
*/
escaped: function(contents, generator, indent, currentParsePoint) {
var line, _i, _len;
for (_i = 0, _len = contents.length; _i < _len; _i++) {
line = contents[_i];
generator.appendTextContents(haml.HamlRuntime.indentText(indent - 1) + line + '\n', true, currentParsePoint, {
escapeHTML: true
});
}
return true;
}
};
/*
Main haml compiler implemtation
*/
haml = {
/*
Compiles the haml provided in the parameters to a Javascipt function
Parameter:
String: Looks for a haml template in dom with this ID
Option Hash: The following options determines how haml sources and compiles the template
source - This contains the template in string form
sourceId - This contains the element ID in the dom which contains the haml source
sourceUrl - This contains the URL where the template can be fetched from
outputFormat - This determines what is returned, and has the following values:
string - The javascript source code
function - A javascript function (default)
generator - Which code generator to use
javascript (default)
coffeescript
productionjavascript
tolerateErrors - switch the compiler into fault tolerant mode (defaults to false)
Returns a javascript function
*/
compileHaml: function(options) {
var codeGenerator, result, tokinser;
if (typeof options === 'string') {
return this._compileHamlTemplate(options, new haml.JsCodeGenerator());
} else {
codeGenerator = (function() {
switch (options.generator) {
case 'coffeescript':
return new haml.CoffeeCodeGenerator(options);
case 'productionjavascript':
return new haml.ProductionJsCodeGenerator(options);
default:
return new haml.JsCodeGenerator(options);
}
})();
if (options.source != null) {
tokinser = new haml.Tokeniser({
template: options.source
});
} else if (options.sourceId != null) {
tokinser = new haml.Tokeniser({
templateId: options.sourceId
});
} else if (options.sourceUrl != null) {
tokinser = new haml.Tokeniser({
templateUrl: options.sourceUrl
});
} else {
throw "No template source specified for compileHaml. You need to provide a source, sourceId or sourceUrl option";
}
result = this._compileHamlToJs(tokinser, codeGenerator, options);
if (options.outputFormat !== 'string') {
return codeGenerator.generateJsFunction(result);
} else {
return "function (context) {\n" + result + "}\n";
}
}
},
/*
Compiles the haml in the script block with ID templateId using the coffeescript generator
Returns a javascript function
*/
compileCoffeeHaml: function(templateId) {
return this._compileHamlTemplate(templateId, new haml.CoffeeCodeGenerator());
},
/*
Compiles the haml in the passed in string
Returns a javascript function
*/
compileStringToJs: function(string) {
var codeGenerator, result;
codeGenerator = new haml.JsCodeGenerator();
result = this._compileHamlToJs(new haml.Tokeniser({
template: string
}), codeGenerator);
return codeGenerator.generateJsFunction(result);
},
/*
Compiles the haml in the passed in string using the coffeescript generator
Returns a javascript function
*/
compileCoffeeHamlFromString: function(string) {
var codeGenerator, result;
codeGenerator = new haml.CoffeeCodeGenerator();
result = this._compileHamlToJs(new haml.Tokeniser({
template: string
}), codeGenerator);
return codeGenerator.generateJsFunction(result);
},
/*
Compiles the haml in the passed in string
Returns the javascript function source
This is mainly used for precompiling the haml templates so they can be packaged.
*/
compileHamlToJsString: function(string) {
var result;
result = 'function (context) {\n';
result += this._compileHamlToJs(new haml.Tokeniser({
template: string
}), new haml.JsCodeGenerator());
return result += '}\n';
},
_compileHamlTemplate: function(templateId, codeGenerator) {
var fn, result;
haml.cache || (haml.cache = {});
if (haml.cache[templateId]) {
return haml.cache[templateId];
}
result = this._compileHamlToJs(new haml.Tokeniser({
templateId: templateId
}), codeGenerator);
fn = codeGenerator.generateJsFunction(result);
haml.cache[templateId] = fn;
return fn;
},
_compileHamlToJs: function(tokeniser, generator, options) {
var e, indent;
if (options == null) {
options = {};
}
generator.elementStack = [];
generator.initOutput();
tokeniser.getNextToken();
while (!tokeniser.token.eof) {
if (!tokeniser.token.eol) {
try {
indent = this._whitespace(tokeniser);
generator.setIndent(indent);
if (tokeniser.token.eol) {
generator.outputBuffer.append(HamlRuntime.indentText(indent) + tokeniser.token.matched);
tokeniser.getNextToken();
} else if (tokeniser.token.doctype) {
this._doctype(tokeniser, indent, generator);
} else if (tokeniser.token.exclamation) {
this._ignoredLine(tokeniser, indent, generator.elementStack, generator);
} else if (tokeniser.token.equal || tokeniser.token.escapeHtml || tokeniser.token.unescapeHtml || tokeniser.token.tilde) {
this._embeddedJs(tokeniser, indent, generator.elementStack, {
innerWhitespace: true
}, generator);
} else if (tokeniser.token.minus) {
this._jsLine(tokeniser, indent, generator.elementStack, generator);
} else if (tokeniser.token.comment || tokeniser.token.slash) {
this._commentLine(tokeniser, indent, generator.elementStack, generator);
} else if (tokeniser.token.amp) {
this._escapedLine(tokeniser, indent, generator.elementStack, generator);
} else if (tokeniser.token.filter) {
this._filter(tokeniser, indent, generator, options);
} else {
this._templateLine(tokeniser, generator.elementStack, indent, generator, options);
}
} catch (_error) {
e = _error;
this._handleError(options, {
skipTo: true
}, tokeniser, e);
}
} else {
generator.outputBuffer.append(tokeniser.token.matched);
tokeniser.getNextToken();
}
}
this._closeElements(0, generator.elementStack, tokeniser, generator);
return generator.closeAndReturnOutput();
},
_doctype: function(tokeniser, indent, generator) {
var contents, params;
if (tokeniser.token.doctype) {
generator.outputBuffer.append(HamlRuntime.indentText(indent));
tokeniser.getNextToken();
if (tokeniser.token.ws) {
tokeniser.getNextToken();
}
contents = tokeniser.skipToEOLorEOF();
if (contents && contents.length > 0) {
params = contents.split(/\s+/);
switch (params[0]) {
case 'XML':
if (params.length > 1) {
generator.outputBuffer.append("");
} else {
generator.outputBuffer.append("");
}
break;
case 'Strict':
generator.outputBuffer.append('');
break;
case 'Frameset':
generator.outputBuffer.append('');
break;
case '5':
generator.outputBuffer.append('');
break;
case '1.1':
generator.outputBuffer.append('');
break;
case 'Basic':
generator.outputBuffer.append('');
break;
case 'Mobile':
generator.outputBuffer.append('');
break;
case 'RDFa':
generator.outputBuffer.append('');
}
} else {
generator.outputBuffer.append('');
}
generator.outputBuffer.append(this._newline(tokeniser));
return tokeniser.getNextToken();
}
},
_filter: function(tokeniser, indent, generator, options) {
var filter, filterBlock, i, line;
if (tokeniser.token.filter) {
filter = tokeniser.token.tokenString;
if (!haml.filters[filter]) {
this._handleError(options, {
skipTo: indent
}, tokeniser, tokeniser.parseError("Filter '" + filter + "' not registered. Filter functions need to be added to 'haml.filters'."));
return;
}
tokeniser.skipToEOLorEOF();
tokeniser.getNextToken();
i = haml._whitespace(tokeniser);
filterBlock = [];
while (!tokeniser.token.eof && i > indent) {
tokeniser.pushBackToken();
line = tokeniser.skipToEOLorEOF();
filterBlock.push(HamlRuntime.trim(line, 2 * indent));
tokeniser.getNextToken();
i = haml._whitespace(tokeniser);
}
haml.filters[filter](filterBlock, generator, indent, tokeniser.currentParsePoint());
return tokeniser.pushBackToken();
}
},
_commentLine: function(tokeniser, indent, elementStack, generator) {
var contents, i;
if (tokeniser.token.comment) {
tokeniser.skipToEOLorEOF();
tokeniser.getNextToken();
i = this._whitespace(tokeniser);
while (!tokeniser.token.eof && i > indent) {
tokeniser.skipToEOLorEOF();
tokeniser.getNextToken();
i = this._whitespace(tokeniser);
}
if (i > 0) {
return tokeniser.pushBackToken();
}
} else if (tokeniser.token.slash) {
haml._closeElements(indent, elementStack, tokeniser, generator);
generator.outputBuffer.append(HamlRuntime.indentText(indent));
generator.outputBuffer.append("' + elementStack[indent].eol);
} else if (elementStack[indent].htmlConditionalComment) {
generator.outputBuffer.append(HamlRuntime.indentText(indent) + '' + elementStack[indent].eol);
} else if (elementStack[indent].block) {
generator.closeOffCodeBlock(tokeniser);
} else if (elementStack[indent].fnBlock) {
generator.closeOffFunctionBlock(tokeniser);
} else {
innerWhitespace = !elementStack[indent].tagOptions || elementStack[indent].tagOptions.innerWhitespace;
if (innerWhitespace) {
generator.outputBuffer.append(HamlRuntime.indentText(indent));
} else {
generator.outputBuffer.trimWhitespace();
}
generator.outputBuffer.append('' + elementStack[indent].tag + '>');
outerWhitespace = !elementStack[indent].tagOptions || elementStack[indent].tagOptions.outerWhitespace;
if (haml._parentInnerWhitespace(elementStack, indent) && outerWhitespace) {
generator.outputBuffer.append('\n');
}
}
elementStack[indent] = null;
return generator.mark();
}
},
_closeElements: function(indent, elementStack, tokeniser, generator) {
var i, _results;
i = elementStack.length - 1;
_results = [];
while (i >= indent) {
_results.push(this._closeElement(i--, elementStack, tokeniser, generator));
}
return _results;
},
_openElement: function(currentParsePoint, indent, identifier, id, classes, objectRef, attributeList, attributeHash, elementStack, tagOptions, generator) {
var element, parentInnerWhitespace, tagOuterWhitespace;
element = identifier.length === 0 ? "div" : identifier;
parentInnerWhitespace = this._parentInnerWhitespace(elementStack, indent);
tagOuterWhitespace = !tagOptions || tagOptions.outerWhitespace;
if (!tagOuterWhitespace) {
generator.outputBuffer.trimWhitespace();
}
if (indent > 0 && parentInnerWhitespace && tagOuterWhitespace) {
generator.outputBuffer.append(HamlRuntime.indentText(indent));
}
generator.outputBuffer.append('<' + element);
if (attributeHash.length > 0 || objectRef.length > 0) {
generator.generateCodeForDynamicAttributes(id, classes, attributeList, attributeHash, objectRef, currentParsePoint);
} else {
generator.outputBuffer.append(HamlRuntime.generateElementAttributes(null, id, classes, null, attributeList, null, currentParsePoint.lineNumber, currentParsePoint.characterNumber, currentParsePoint.currentLine));
}
if (tagOptions.selfClosingTag) {
generator.outputBuffer.append("/>");
if (tagOptions.outerWhitespace) {
return generator.outputBuffer.append("\n");
}
} else {
generator.outputBuffer.append(">");
elementStack[indent] = {
tag: element,
tagOptions: tagOptions
};
if (tagOptions.innerWhitespace) {
return generator.outputBuffer.append("\n");
}
}
},
_isSelfClosingTag: function(tag) {
return tag === 'meta' || tag === 'img' || tag === 'link' || tag === 'script' || tag === 'br' || tag === 'hr';
},
_tagHasContents: function(indent, tokeniser) {
var nextToken;
if (!tokeniser.isEolOrEof()) {
return true;
} else {
nextToken = tokeniser.lookAhead(1);
return nextToken.ws && nextToken.tokenString.length / 2 > indent;
}
},
_parentInnerWhitespace: function(elementStack, indent) {
return indent === 0 || (!elementStack[indent - 1] || !elementStack[indent - 1].tagOptions || elementStack[indent - 1].tagOptions.innerWhitespace);
},
_lineHasElement: function(identifier, id, classes) {
return identifier.length > 0 || id.length > 0 || classes.length > 0;
},
hasValue: function(value) {
return (value != null) && value !== false;
},
attrValue: function(attr, value) {
if (attr === 'selected' || attr === 'checked' || attr === 'disabled') {
return attr;
} else {
return value;
}
},
_whitespace: function(tokeniser) {
var indent;
indent = 0;
if (tokeniser.token.ws) {
indent = tokeniser.calculateIndent(tokeniser.token.tokenString);
tokeniser.getNextToken();
}
return indent;
},
_element: function(tokeniser) {
var identifier;
identifier = '';
if (tokeniser.token.element) {
identifier = tokeniser.token.tokenString;
tokeniser.getNextToken();
}
return identifier;
},
_eolOrEof: function(tokeniser) {
if (tokeniser.token.eol || tokeniser.token.continueLine) {
return tokeniser.getNextToken();
} else if (!tokeniser.token.eof) {
throw tokeniser.parseError("Expected EOL or EOF");
}
},
_idSelector: function(tokeniser) {
var id;
id = '';
if (tokeniser.token.idSelector) {
id = tokeniser.token.tokenString;
tokeniser.getNextToken();
}
return id;
},
_classSelector: function(tokeniser) {
var classes;
classes = [];
while (tokeniser.token.classSelector) {
classes.push(tokeniser.token.tokenString);
tokeniser.getNextToken();
}
return classes;
},
_newline: function(tokeniser) {
if (tokeniser.token.eol) {
return tokeniser.token.matched;
} else if (tokeniser.token.continueLine) {
return tokeniser.token.matched.substring(1);
} else {
return "\n";
}
},
_handleError: function(options, action, tokeniser, error) {
if (options != null ? options.tolerateFaults : void 0) {
console.log(error);
if (action != null ? action.skipTo : void 0) {
return this._skipToNextLineWithIndent(tokeniser, action.skipTo);
}
} else {
throw error;
}
},
_skipToNextLineWithIndent: function(tokeniser, indent) {
var lineIndent;
tokeniser.skipToEOLorEOF();
tokeniser.getNextToken();
lineIndent = this._whitespace(tokeniser);
while (lineIndent > indent) {
tokeniser.skipToEOLorEOF();
tokeniser.getNextToken();
lineIndent = this._whitespace(tokeniser);
}
return tokeniser.pushBackToken();
}
};
haml.Tokeniser = Tokeniser;
haml.Buffer = Buffer;
haml.JsCodeGenerator = JsCodeGenerator;
haml.ProductionJsCodeGenerator = ProductionJsCodeGenerator;
haml.CoffeeCodeGenerator = CoffeeCodeGenerator;
haml.HamlRuntime = HamlRuntime;
haml.filters = filters;
if ((typeof module !== "undefined" && module !== null ? module.exports : void 0) != null) {
module.exports = haml;
} else {
root.haml = haml;
}
}).call(this);
/*
//@ sourceMappingURL=haml.map
*/
;
; TI"required_assets_digest; TI"%b6dc3e5c68279dfc1f81c045d42bc022; FI"
_version; TI"%a56df69ef97ba4d9f1a23bf9b0add58a; F