diff --git a/mustache.js b/mustache.js index 09523c7..ea88e98 100644 --- a/mustache.js +++ b/mustache.js @@ -118,6 +118,10 @@ var Mustache = (function(undefined) { return text.replace(escapeCompiledRegex, '\\$1'); } + function is_newline(token) { + return token.match(/\r?\n/); + } + function is_function(a) { return a && typeof a === 'function'; } @@ -130,6 +134,10 @@ var Mustache = (function(undefined) { return Object.prototype.toString.call(a) === '[object Array]'; } + function create_error(line, character, message) { + return new Error('(' + line + ',' + character + '): ' + message); + } + /* END Helpers */ /* BEGIN Compiler */ @@ -153,6 +161,13 @@ var Mustache = (function(undefined) { } else { state.parser.text(state, token); } + + if (is_newline(token)) { + state.character = 1; + state.line++; + } else { + state.character+=token.length; + } } if (!noReturn) { @@ -193,10 +208,10 @@ var Mustache = (function(undefined) { tokenizer = new RegExp(parts.join('|')); } - var code = []; var state = { - template: template || '' + line: 1, character: 1 + , template: template || '' , partials: partials || {} , openTag: openTag , closeTag: closeTag @@ -251,7 +266,7 @@ var Mustache = (function(undefined) { for (i=0, n=optionPairs.length; i': partial, @@ -487,7 +502,7 @@ var Mustache = (function(undefined) { var matches = token.match(new RegExp(escape_regex(state.openTag) + '=(\\S*?)\\s*(\\S*?)=' + escape_regex(state.closeTag))); if ((matches || []).length!==3) { - throw new Error('Malformed change delimiter token: ' + token); + throw create_error(state.line, state.character, 'Malformed change delimiter token: "' + token + '".'); } var new_state = create_compiler_state( @@ -543,7 +558,7 @@ var Mustache = (function(undefined) { delete state.section; state.parser = default_parser; } else { - throw new Error('Unexpected section end tag "' + variable + '". Expected: ' + state.section.variable); + throw create_error(state.line, state.character, 'Unexpected section end tag "' + variable + '", expected "' + state.section.variable + '".'); } } diff --git a/test/unit.js b/test/unit.js index 64359d0..e372e08 100644 --- a/test/unit.js +++ b/test/unit.js @@ -52,7 +52,7 @@ test("Parser", function() { {} ); }, function(e) { - return e.message === 'Malformed change delimiter token: {{=tag1}}'; + return e.message === '(1,1): Malformed change delimiter token: "{{=tag1}}".'; }, 'Malformed tags should be handled correctly.' ); @@ -387,7 +387,7 @@ test("'>' (Partials)", function() { {partal: ''} ); }, function(e) { - return e.message === "Unknown partial 'partial'"; + return e.message === '(1,1): Unknown partial "partial".'; }, 'Missing partials should be handled correctly.' ); @@ -477,7 +477,7 @@ test("'%' (Pragmas)", function() { ); }, function(e) { - return e.message === 'This implementation of mustache does not implement the "I-HAVE-THE-GREATEST-MUSTACHE" pragma'; + return e.message === '(1,1): This implementation of mustache does not implement the "I-HAVE-THE-GREATEST-MUSTACHE" pragma.'; }, 'Notification of unimplemented pragmas' );