UNPKG

toffee

Version:

A NodeJs and browser-side templating language based on CoffeeScript with slicker tokens and syntax.

321 lines (297 loc) 12.2 kB
// Generated by CoffeeScript 1.12.7 (function() { var _ppEscape, errorTypes, path, toffeeError, util, extend = 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; }, hasProp = {}.hasOwnProperty; path = require("path"); util = require("util"); errorTypes = exports.errorTypes = { PARSER: 0, STR_INTERPOLATE: 1, COFFEE_COMPILE: 2, RUNTIME: 3 }; toffeeError = (function(superClass) { extend(toffeeError, superClass); function toffeeError(view, err_type, e) { this.errType = err_type; this.view = view; this.e = e; this.toffeeSrc = view.txt; switch (this.errType) { case errorTypes.PARSER: this.offensiveSrc = this.toffeeSrc; break; case errorTypes.STR_INTERPOLATE: this.offensiveSrc = this.toffeeSrc; break; case errorTypes.COFFEE_COMPILE: this.offensiveSrc = this.view.coffeeScript; break; case errorTypes.RUNTIME: this.offensiveSrc = this.view.javaScript; } this.toffeeSrcLines = this.toffeeSrc.split("\n"); this.offensiveSrcLines = this.offensiveSrc.split("\n"); } toffeeError.prototype.getConvertedError = function() { /* -------------------------------------- returns a JS style error, but with some extras { stack: array of lines message: error message line_range: line range in the toffee file filename: filename, if available; or null ...etc... } ------------------------------------------ */ var line, ref, ref1, ref2, res; res = { stack: [], message: "", type: this.errType, full_path: this.view.fileName, dir_name: path.dirname(this.view.fileName), file: path.basename(this.view.fileName), line_range: null }; if (((ref = this.e) != null ? ref.message : void 0) != null) { res.message = this.e.message; } if (((ref1 = this.e) != null ? (ref2 = ref1.location) != null ? ref2.first_line : void 0 : void 0) != null) { res.line_range = this._convertJsErrorRangeToToffeeRange(this.e.location); } switch (this.errType) { case errorTypes.PARSER: if (res.line_range == null) { line = this._extractOffensiveLineNo(this.e.message, /on line ([0-9]+)/); res.line_range = [line, line + 1]; } break; case errorTypes.STR_INTERPOLATE: res.line_range = [this.e.relayed_line_range[0], this.e.relayed_line_range[1]]; res.message = res.message.replace('starting on line NaN', this._lineRangeToPhrase(res.line_range)); res.message = res.message.replace('missing }', 'unclosed `\#{}`'); break; case errorTypes.COFFEE_COMPILE: if (res.line_range == null) { line = this._extractOffensiveLineNo(this.e.message, /on line ([0-9]+)/); res.line_range = this._convertOffensiveLineToToffeeRange(line); } if (res.message.indexOf('on line') !== -1) { res.message = res.message.replace(/on line [0-9]+/, this._lineRangeToPhrase(res.line_range)); } else { res.message += " " + this._lineRangeToPhrase(res.line_range); } break; case errorTypes.RUNTIME: if (res.line_range == null) { res.line_range = [0, 0]; } if (this.e.stack) { res.stack = this.e.stack.split("\n"); this._convertRuntimeStackLines(res); } } return res; }; toffeeError.prototype._convertRuntimeStackLines = function(converted_err) { /* a little more complicated, so extracted. Returns an array of dictionaries where there's extra info on each line in the stack. */ var at_pub_call, hit_pub_yet, i, in_src_file, k, len, line, lineno, lrange, m, results, rxx_inline, rxx_pub, stack; hit_pub_yet = false; stack = converted_err.stack; results = []; for (i = k = 0, len = stack.length; k < len; i = ++k) { line = stack[i]; rxx_pub = /Object[\.].*?pub[\s]\(undefined\:([0-9]+)\:[0-9]+|tmpl[\.]render[\.]tmpl[\.]pub.*\(.*\:([0-9]+)\:[0-9]+/; m = line.match(rxx_pub); in_src_file = false; lrange = [null, null]; at_pub_call = false; if ((m != null ? m.length : void 0) >= 2) { line = line.replace("undefined", converted_err.full_path); lineno = this._extractOffensiveLineNo(line, /([0-9]+)\:[0-9]+/); lrange = this._convertOffensiveLineToToffeeRange(lineno); line = line.replace(/\:[0-9]+\:[0-9]+/, ""); hit_pub_yet = true; in_src_file = true; at_pub_call = true; } rxx_inline = /at[\s]undefined\:([0-9]+)\:[0-9]+/; m = line.match(rxx_inline); if ((m != null ? m.length : void 0) >= 2) { line = line.replace("undefined", converted_err.full_path); lineno = this._extractOffensiveLineNo(line, /([0-9]+)\:[0-9]+/); lrange = this._convertOffensiveLineToToffeeRange(lineno); line = line.replace(/\:[0-9]+\:[0-9]+/, ""); in_src_file = true; } stack[i] = { line: line, above_pub_call: !hit_pub_yet, at_pub_call: at_pub_call, in_src_file: in_src_file, line_range: lrange }; if (stack[i].line_range[0] && !converted_err.line_range[0]) { results.push(converted_err.line_range = stack[i].line_range); } else { results.push(void 0); } } return results; }; toffeeError.prototype.getPrettyPrintText = function() { /* returns a TEXT only blob explaining the error */ var cerr, count, header, i, item, k, len, ref, ref1, res; cerr = this.getConvertedError(); header = cerr.dir_name + "/" + cerr.file + ": " + cerr.message; res = "ERROR\n=====\n" + header; if ((ref = cerr.stack) != null ? ref.length : void 0) { res += "\n\nSTACK\n=====\n"; count = 0; ref1 = cerr.stack; for (i = k = 0, len = ref1.length; k < len; i = ++k) { item = ref1[i]; if (i === 0) { res += (count++) + " " + item.line; } else if (item.in_src_file && (item.above_pub_call || item.at_pub_call)) { res += (count++) + " [" + (this._lineRangeToPhrase(item.line_range)) + "] " + cerr.dir_name + "/" + cerr.file; } else if (item.in_src_file) { continue; } else { res += "" + (count++) + item.line; } if (i < cerr.stack.length - 1) { res += "\n"; } } } res += "\n"; return res; }; toffeeError.prototype.getPrettyPrint = function() { /* returns an HTML blob explaining the error with lines highlighted */ var cerr, count, extra, header, i, item, j, k, l, len, line, padding, padding_len, ref, ref1, ref2, ref3, ref4, res; cerr = this.getConvertedError(); res = ""; header = cerr.dir_name + "/<span style=\"background-color:#fde\"><b>" + cerr.file + "</b>: " + (_ppEscape(cerr.message)) + "</span>"; res += "<div style=\"line-height:13px;border:1px solid #999;margin:10px;padding:10px;background-color:#fff;position:fixed;top:0;left:0;max-width:90%;z-index:9999;max-height:90%;overflow:scroll;\">\n \n<pre>" + header + "</pre>\n \n<hr />\n \n<div style=\"font-family:courier new;font-size:12px;color:#900;width:100%;\">"; if ((ref = cerr.stack) != null ? ref.length : void 0) { res += "<div style=\"border:1px solid #000;background-color:#eee;width:100%;\">"; count = 0; ref1 = cerr.stack; for (i = k = 0, len = ref1.length; k < len; i = ++k) { item = ref1[i]; if (i === 0) { res += "<div style=\"color:#333;width:100%\">" + (count++) + " " + item.line + "</div>"; } else if (item.in_src_file && (item.above_pub_call || item.at_pub_call)) { res += "<div style=\"color:#000;width:100%\">" + (count++) + " [" + (this._lineRangeToPhrase(item.line_range)) + "] " + cerr.dir_name + "/" + cerr.file + "</div>"; } else if (item.in_src_file) { continue; } else { res += "<div style=\"color:#999;width:100%\">" + (count++) + item.line + "</div>"; } } res += "</div>"; } for (i = l = ref2 = cerr.line_range[0] - 3, ref3 = cerr.line_range[1] + 1; ref2 <= ref3 ? l < ref3 : l > ref3; i = ref2 <= ref3 ? ++l : --l) { if ((i < 0) || i > this.toffeeSrcLines.length - 1) { continue; } line = _ppEscape(this.toffeeSrcLines[i]); padding_len = 5 - ("" + (i + 1)).length; padding = ((function() { var n, ref4, results; results = []; for (j = n = 0, ref4 = padding_len; 0 <= ref4 ? n < ref4 : n > ref4; j = 0 <= ref4 ? ++n : --n) { results.push("&nbsp;"); } return results; })()).join(""); if (((cerr.line_range[0] - 1) <= (ref4 = i) && ref4 < cerr.line_range[1])) { extra = "<span style=\"background-color:#fde\">"; } else { extra = "<span>"; } res += extra + "\n" + (i + 1) + ": " + padding + " " + line + "</span><br />"; } res += " \n</div>\n\n</div>"; return res; }; toffeeError.prototype._lineRangeToPhrase = function(lrange) { if (lrange[0] === lrange[1]) { return "on line " + lrange[0]; } else { return "between lines " + lrange[0] + " and " + lrange[1]; } }; toffeeError.prototype._extractOffensiveLineNo = function(msg, rxx) { var m; m = msg.match(rxx); if (!((m != null ? m.length : void 0) >= 2)) { return null; } return parseInt(m[1]); }; toffeeError.prototype._convertJsErrorRangeToToffeeRange = function(loc) { var range, range2; range = this._convertOffensiveLineToToffeeRange(loc.first_line); if (loc.last_line != null) { range2 = this._convertOffensiveLineToToffeeRange(loc.last_line); range[1] = range2[1]; } return range; }; toffeeError.prototype._convertOffensiveLineToToffeeRange = function(lineno) { /* Given the error line in a converted file, hunts for surrounding __toffee.lineno calls and returns a pair array with the error position range in the original toffee file. */ var next, next_matches, ol, prev, prev_matches, res, tl; ol = this.offensiveSrcLines; tl = this.toffeeSrcLines; if ((lineno == null) || isNaN(lineno)) { return [1, tl.length]; } prev = ol.slice(0, lineno).join("\n"); next = ol.slice(lineno).join("\n"); prev_matches = prev.match(/_ln[ ]*\(?[ ]*([0-9]+)/g); next_matches = next.match(/_ln[ ]*\(?[ ]*([0-9]+)/g); res = [1, tl.length]; if (prev_matches != null ? prev_matches.length : void 0) { res[0] = parseInt(prev_matches[prev_matches.length - 1].match(/[0-9]+/)[0]); } if (next_matches != null ? next_matches.length : void 0) { res[1] = parseInt(next_matches[0].match(/[0-9]+/)[0]); } return res; }; return toffeeError; })(Error); exports.toffeeError = toffeeError; _ppEscape = function(txt) { var i, m; txt = txt.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;'); m = txt.match(/^[\t ]*/); txt = txt.replace(m[0], ((function() { var k, ref, results; results = []; for (i = k = 0, ref = m[0].length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { results.push("&nbsp;"); } return results; })()).join("")); return txt; }; }).call(this);