var CompilerContext, Ember, EmberHandlebars, Emblem, Handlebars, LoadedEmber, bindAttrHelper, compileWithPartials, equal, equals, ok, precompileEmber, runTextLineSuite, shouldCompileTo, shouldCompileToString, shouldCompileToWithPartials, shouldEmberPrecompileToHelper, shouldThrow, supportsEachHelperDataKeywords, supportsSubexpressions, throws, _equal, _ref, __hasProp = {}.hasOwnProperty; Ember = (typeof window !== "undefined" && window !== null ? window.Emblem : void 0) || this.Emblem || {}; LoadedEmber = LoadedEmber || {}; Ember.Handlebars = LoadedEmber.Handlebars; Ember.warn = LoadedEmber.warn; if (typeof Emblem !== "undefined" && Emblem !== null) { _equal = equal; equals = equal = function(a, b, msg) { return _equal(a, b, msg || ''); }; window.suite = module; } else { Handlebars = require('handlebars'); EmberHandlebars = require('./resources/ember-template-compiler.js').EmberHandlebars; Emblem = require('../lib/emblem'); expect = function() {};; _ref = require("assert"), equal = _ref.equal, equals = _ref.equals, ok = _ref.ok, throws = _ref.throws; } if (typeof CompilerContext === "undefined" || CompilerContext === null) { CompilerContext = { compile: function(template, options) { return Emblem.compile(Handlebars, template, options); } }; } supportsEachHelperDataKeywords = Handlebars.VERSION.slice(0, 3) >= 1.2; supportsSubexpressions = Handlebars.VERSION.slice(0, 3) >= 1.3; precompileEmber = function(emblem) { return Emblem.precompile(EmberHandlebars, emblem).toString(); }; shouldEmberPrecompileToHelper = function(emblem, helper) { var result; if (helper == null) { helper = 'bind-attr'; } result = precompileEmber(emblem); ok((result.match("helpers." + helper)) || (result.match("helpers\\['" + helper + "'\\]"))); return result; }; shouldCompileToString = function(string, hashOrArray, expected) { if (hashOrArray.constructor === String) { return shouldCompileToWithPartials(string, {}, false, hashOrArray, null, true); } else { return shouldCompileToWithPartials(string, hashOrArray, false, expected, null, true); } }; shouldCompileTo = function(string, hashOrArray, expected, message) { if (hashOrArray.constructor === String) { return shouldCompileToWithPartials(string, {}, false, hashOrArray, message); } else { return shouldCompileToWithPartials(string, hashOrArray, false, expected, message); } }; shouldCompileToWithPartials = function(string, hashOrArray, partials, expected, message, strings) { var options, result; options = null; if (strings) { options = {}; options.stringParams = true; } result = compileWithPartials(string, hashOrArray, partials, options); return equal(result, expected, "'" + result + "' should === '" + expected + "': " + message); }; compileWithPartials = function(string, hashOrArray, partials, options) { var ary, helpers, prop, template; if (options == null) { options = {}; } template = CompilerContext.compile(string, options); if (Object.prototype.toString.call(hashOrArray) === "[object Array]") { if (helpers = hashOrArray[1]) { for (prop in Handlebars.helpers) { helpers[prop] = helpers[prop] || Handlebars.helpers[prop]; } } ary = []; ary.push(hashOrArray[0]); ary.push({ helpers: hashOrArray[1], partials: hashOrArray[2] }); } else { ary = [hashOrArray]; } return template.apply(this, ary); }; shouldThrow = function(fn, exMessage) { var caught, e; caught = false; try { fn(); } catch (_error) { e = _error; caught = true; if (exMessage) { ok(e.message.match(exMessage), "exception message matched"); } } return ok(caught, "an exception was thrown"); }; Handlebars.registerHelper('echo', function(param) { return "ECHO " + param; }); suite("html one-liners"); test("element only", function() { return shouldCompileTo("p", "

"); }); test("with text", function() { return shouldCompileTo("p Hello", "

Hello

"); }); test("with more complex text", function() { return shouldCompileTo("p Hello, how's it going with you today?", "

Hello, how's it going with you today?

"); }); test("with trailing space", function() { return shouldCompileTo("p Hello ", "

Hello

"); }); suite("html multi-lines"); test("two lines", function() { var emblem; emblem = "p This is\n pretty cool."; return shouldCompileTo(emblem, "

This is pretty cool.

"); }); test("three lines", function() { var emblem; emblem = "p This is\n pretty damn\n cool."; return shouldCompileTo(emblem, "

This is pretty damn cool.

"); }); test("three lines w/ embedded html", function() { var emblem; emblem = "p This is\n pretty damn\n cool."; return shouldCompileTo(emblem, "

This is pretty damn cool.

"); }); test("indentation doesn't need to match starting inline content's", function() { var emblem; emblem = "span Hello,\n How are you?"; return shouldCompileTo(emblem, "Hello, How are you?"); }); test("indentation may vary between parent/child, must be consistent within inline-block", function() { var emblem; emblem = "div\n span Hello,\n How are you?\n Excellent.\n p asd"; shouldCompileTo(emblem, "
Hello, How are you? Excellent.

asd

"); emblem = "div\n span Hello,\n How are you?\n Excellent."; return shouldThrow(function() { return CompilerContext.compile(emblem); }); }); test("indentation may vary between parent/child, must be consistent within inline-block pt 2", function() { var emblem; emblem = "div\n span Hello,\n How are you?\n Excellent."; return shouldCompileTo(emblem, "
Hello, How are you? Excellent.
"); }); test("w/ mustaches", function() { var emblem; emblem = "div\n span Hello,\n {{foo}} are you?\n Excellent."; return shouldCompileTo(emblem, { foo: "YEAH" }, "
Hello, YEAH are you? Excellent.
"); }); test("w/ block mustaches", function() { var emblem; emblem = 'p Hello, #{ sally | Hello},\n and {{sally: span Hello}}!'; shouldCompileTo(emblem, '

Hello, Hello, and Hello!

'); emblem = 'p Hello, #{ sally: span: a Hello}!'; return shouldCompileTo(emblem, '

Hello, Hello!

'); }); test("with followup", function() { var emblem; emblem = "p This is\n pretty cool.\np Hello."; return shouldCompileTo(emblem, "

This is pretty cool.

Hello.

"); }); suite('#{} syntax'); test('acts like {{}}', function() { var emblem; emblem = 'span Yo #{foo}, I herd.'; return shouldCompileTo(emblem, { foo: '123' }, "Yo <span>123</span>, I herd."); }); test('can start inline content', function() { var emblem; emblem = 'span #{foo}, I herd.'; return shouldCompileTo(emblem, { foo: "dawg" }, "dawg, I herd."); }); test('can end inline content', function() { var emblem; emblem = 'span I herd #{foo}'; return shouldCompileTo(emblem, { foo: "dawg" }, "I herd dawg"); }); test("doesn't screw up parsing when # used in text nodes", function() { var emblem; emblem = 'span OMG #YOLO'; return shouldCompileTo(emblem, "OMG #YOLO"); }); test("# can be only thing on line", function() { var emblem; emblem = 'span #'; return shouldCompileTo(emblem, "#"); }); /* TODO: this test "can be escaped", -> emblem = ''' span #\\{yes} ''' shouldCompileTo emblem, '#{yes}' */ runTextLineSuite = function(ch) { var sct; sct = function(emblem, obj, expected) { if (expected == null) { expected = obj; obj = {}; } if (ch !== '`') { expected = expected.replace(/\n/g, ""); } if (ch === "'") { expected = expected.replace(/\t/g, " "); } else { expected = expected.replace(/\t/g, ""); } emblem = emblem.replace(/_/g, ch); return shouldCompileTo(emblem, obj, expected); }; suite("text lines starting with '" + ch + "'"); test("basic", function() { return sct("_ What what", "What what\n\t"); }); test("with html", function() { return sct('_ What what!', 'What what!\n\t'); }); test("multiline", function() { var emblem; emblem = "_ Blork\n Snork"; return sct(emblem, "Blork\nSnork\n\t"); }); test("triple multiline", function() { var emblem; emblem = "_ Blork\n Snork\n Bork"; return sct(emblem, "Blork\nSnork\nBork\n\t"); }); test("quadruple multiline", function() { var emblem; emblem = "_ Blork\n Snork\n Bork\n Fork"; return sct(emblem, "Blork\nSnork\nBork\nFork\n\t"); }); test("multiline w/ trailing whitespace", function() { var emblem; emblem = "_ Blork \n Snork"; return sct(emblem, "Blork \nSnork\n\t"); }); test("secondline", function() { var emblem; emblem = "_\n Good"; return sct(emblem, "Good\n\t"); }); test("secondline multiline", function() { var emblem; emblem = "_ \n Good\n Bork"; return sct(emblem, "Good\nBork\n\t"); }); test("with a mustache", function() { var emblem; emblem = "_ Bork {{foo}}!"; return sct(emblem, { foo: "YEAH" }, 'Bork YEAH!\n\t'); }); test("with mustaches", function() { var emblem; emblem = "_ Bork {{foo}} {{{bar}}}!"; return sct(emblem, { foo: "YEAH", bar: "NO" }, 'Bork YEAH NO!\n\t'); }); test("indented, then in a row", function() { var emblem; expect(0); return "PENDING"; emblem = "_ \n Good\n riddance2\n dude\n gnar\n foo"; return sct(emblem, "Good\n riddance2\n dude\n gnar\n foo\n\t"); }); test("indented, then in a row, then indented", function() { var emblem; expect(0); return "PENDING"; emblem = "_ \n Good\n riddance2\n dude\n gnar\n foo\n far\n faz"; return sct(emblem, "Good \n riddance2 \n dude \n gnar \n foo \n far \n faz \n\t"); }); test("uneven indentation megatest", function() { var emblem; expect(0); return "PENDING"; emblem = "_ \n Good\n riddance\n dude"; sct(emblem, "Good\n riddance\ndude\n\t"); emblem = "_ \n Good\n riddance3\n dude"; sct(emblem, "Good\n riddance3\n dude\n\t"); emblem = "_ Good\n riddance\n dude"; return sct(emblem, "Good\nriddance\n dude\n\t"); }); test("on each line", function() { var emblem; emblem = "pre\n _ This\n _ should\n _ hopefully\n _ work, and work well."; return sct(emblem, '
This\n\t  should\n\t hopefully\n\t   work, and work well.\n\t
'); }); return test("with blank", function() { var emblem; emblem = "pre\n _ This\n _ should\n _\n _ hopefully\n _ work, and work well."; return sct(emblem, '
This\n\t  should\n\t\n\t hopefully\n\t   work, and work well.\n\t
'); }); }; runTextLineSuite('|'); runTextLineSuite('`'); runTextLineSuite("'"); suite("text line starting with angle bracket"); test("can start with angle bracket html", function() { var emblem; emblem = "Hello"; return shouldCompileTo(emblem, "Hello"); }); test("can start with angle bracket html and go to multiple lines", function() { var emblem; emblem = "Hello dude, \n what's up?"; return shouldCompileTo(emblem, "Hello dude, what's up?"); }); suite("preprocessor"); test("it strips out preceding whitespace", function() { var emblem; emblem = "\np Hello"; return shouldCompileTo(emblem, "

Hello

"); }); test("it handles preceding indentation", function() { var emblem; emblem = " p Woot\n p Ha"; return shouldCompileTo(emblem, "

Woot

Ha

"); }); test("it handles preceding indentation and newlines", function() { var emblem; emblem = "\n p Woot\n p Ha"; return shouldCompileTo(emblem, "

Woot

Ha

"); }); test("it handles preceding indentation and newlines pt 2", function() { var emblem; emblem = " \n p Woot\n p Ha"; return shouldCompileTo(emblem, "

Woot

Ha

"); }); suite("comments"); test("it strips out single line '/' comments", function() { var emblem; emblem = "p Hello\n\n/ A comment\n\nh1 How are you?"; return shouldCompileTo(emblem, "

Hello

How are you?

"); }); test("it strips out multi-line '/' comments", function() { var emblem; emblem = "p Hello\n\n/ A comment\n that goes on to two lines\n even three!\n\nh1 How are you?"; return shouldCompileTo(emblem, "

Hello

How are you?

"); }); test("it strips out multi-line '/' comments without text on the first line", function() { var emblem; emblem = "p Hello\n\n/ \n A comment\n that goes on to two lines\n even three!\n\nh1 How are you?"; return shouldCompileTo(emblem, "

Hello

How are you?

"); }); test("mix and match with various indentation", function() { var emblem; emblem = "/ A test\np Hello\n\nspan\n / This is gnarly\n p Yessir nope.\n\n/ Nothin but comments\n so many comments.\n\n/\n p Should not show up"; return shouldCompileTo(emblem, "

Hello

Yessir nope.

"); }); test("uneven indentation", function() { var emblem; emblem = "/ nop\n nope\n nope"; return shouldCompileTo(emblem, ""); }); test("uneven indentation 2", function() { var emblem; emblem = "/ n\n no\n nop\n nope"; return shouldCompileTo(emblem, ""); }); test("uneven indentation 3", function() { var emblem; emblem = "/ n\n no\n nop\n nope"; return shouldCompileTo(emblem, ""); }); test("empty first line", function() { var emblem; emblem = "/ \n nop\n nope\n nope\n no"; return shouldCompileTo(emblem, ""); }); test("on same line as html content", function() { var emblem; emblem = ".container / This comment doesn't show up\n .row / Nor does this\n p Hello"; return shouldCompileTo(emblem, '

Hello

'); }); test("on same line as mustache content", function() { return shouldCompileTo('frank text="YES" text2="NO" / omg', 'WOO: YES NO'); }); test("on same line as colon syntax", function() { var emblem; emblem = "ul: li: span / omg\n | Hello"; return shouldCompileTo(emblem, ''); }); suite("indentation"); test("it doesn't throw when indenting after a line with inline content", function() { var emblem; emblem = "p Hello\n p invalid"; return shouldCompileTo(emblem, "

Hello p invalid

"); }); test("it throws on half dedent", function() { var emblem; emblem = "p\n span This is ok\n span This aint"; return shouldThrow(function() { return CompilerContext.compile(emblem); }); }); test("new indentation levels don't have to match parents'", function() { var emblem; emblem = "p \n span\n div\n span yes"; return shouldCompileTo(emblem, "

yes

"); }); suite("whitespace fussiness"); test("spaces after html elements", function() { shouldCompileTo("p \n span asd", "

asd

"); return shouldCompileTo("p \nspan \n\ndiv\nspan", "

"); }); test("spaces after mustaches", function() { return shouldCompileTo("each foo \n p \n span", { foo: [1, 2] }, "

"); }); suite("attribute shorthand"); test("id shorthand", function() { shouldCompileTo("#woot", '
'); return shouldCompileTo("span#woot", ''); }); test("class shorthand", function() { shouldCompileTo(".woot", '
'); shouldCompileTo("span.woot", ''); return shouldCompileTo("span.woot.loot", ''); }); test("class can come first", function() { shouldCompileTo(".woot#hello", '
'); shouldCompileTo("span.woot#hello", ''); shouldCompileTo("span.woot.loot#hello", ''); return shouldCompileTo("span.woot.loot#hello.boot", ''); }); suite("full attributes - tags with content"); test("class only", function() { return shouldCompileTo('p class="yes" Blork', '

Blork

'); }); test("id only", function() { return shouldCompileTo('p id="yes" Hyeah', '

Hyeah

'); }); test("class and id", function() { return shouldCompileTo('p id="yes" class="no" Blork', '

Blork

'); }); test("class and id and embedded html one-liner", function() { return shouldCompileTo('p id="yes" class="no" One asd!', '

One asd!

'); }); test("bracketed attributes", function() { var emblem; emblem = "p [\n id=\"yes\"\n class=\"no\" ]\n | Bracketed Attributes FTW!"; return shouldCompileTo(emblem, '

Bracketed Attributes FTW!

'); }); test("bracketed text", function() { var emblem; emblem = "p [ Bracketed text is cool ]"; return shouldCompileTo(emblem, '

[ Bracketed text is cool ]

'); }); test("bracketed text indented", function() { var emblem; emblem = "p\n | [ Bracketed text is cool ]"; return shouldCompileTo(emblem, '

[ Bracketed text is cool ]

'); }); test("nesting", function() { var emblem; emblem = "p class=\"hello\" data-foo=\"gnarly\"\n span Yes"; return shouldCompileTo(emblem, '

Yes

'); }); suite("full attributes - mixed quotes"); test("single empty", function() { return shouldCompileTo("p class=''", '

'); }); test("single full", function() { return shouldCompileTo("p class='woot yeah'", '

'); }); test("mixed", function() { return shouldCompileTo("p class='woot \"oof\" yeah'", '

'); }); suite("full attributes - tags without content"); test("empty", function() { return shouldCompileTo('p class=""', '

'); }); test("class only", function() { return shouldCompileTo('p class="yes"', '

'); }); test("id only", function() { return shouldCompileTo('p id="yes"', '

'); }); test("class and id", function() { return shouldCompileTo('p id="yes" class="no"', '

'); }); suite("full attributes w/ mustaches"); test("with mustache", function() { var emblem; shouldCompileTo('p class="foo {{yes}}"', { yes: "ALEX" }, '

'); shouldCompileTo('p class="foo {{yes}}" Hello', { yes: "ALEX" }, '

Hello

'); emblem = "p class=\"foo {{yes}}\"\n | Hello"; return shouldCompileTo(emblem, { yes: "ALEX" }, '

Hello

'); }); test("with mustache calling helper", function() { var emblem; shouldCompileTo('p class="foo {{{echo "YES"}}}"', '

'); shouldCompileTo('p class="foo #{echo "NO"} and {{{echo "YES"}}}" Hello', '

Hello

'); emblem = "p class=\"foo {{echo \"BORF\"}}\"\n | Hello"; return shouldCompileTo(emblem, '

Hello

'); }); suite("boolean attributes"); test("static", function() { shouldCompileTo('p borf=true', '

'); shouldCompileTo('p borf=true Woot', '

Woot

'); shouldCompileTo('p borf=false', '

'); shouldCompileTo('p borf=false Nork', '

Nork

'); return shouldCompileTo('option selected=true Thingeroo', ''); }); suite("html nested"); test("basic", function() { var emblem; emblem = "p\n span Hello\n strong Hi\ndiv\n p Hooray"; return shouldCompileTo(emblem, '

HelloHi

Hooray

'); }); test("empty nest", function() { var emblem; emblem = "p\n span\n strong\n i"; return shouldCompileTo(emblem, '

'); }); test("empty nest w/ attribute shorthand", function() { var emblem; emblem = "p.woo\n span#yes\n strong.no.yes\n i"; return shouldCompileTo(emblem, '

'); }); suite("simple mustache"); test("various one-liners", function() { var emblem; emblem = "= foo\narf\np = foo\nspan.foo\np data-foo=\"yes\" = goo"; return shouldCompileTo(emblem, { foo: "ASD", arf: "QWE", goo: "WER" }, 'ASDQWE

ASD

WER

'); }); test("double =='s un-escape", function() { var emblem; emblem = "== foo\nfoo\np == foo"; return shouldCompileTo(emblem, { foo: '123' }, '123<span>123</span>

123

'); }); test("nested combo syntax", function() { var emblem; emblem = "ul = each items\n li = foo"; return shouldCompileTo(emblem, { items: [ { foo: "YEAH" }, { foo: "BOI" } ] }, ''); }); suite("mustache helpers"); Handlebars.registerHelper('booltest', function(options) { var hash, result; hash = options.hash; result = hash.what === true ? "true" : hash.what === false ? "false" : "neither"; return result; }); Handlebars.registerHelper('hashtypetest', function(options) { var hash; hash = options.hash; return typeof hash.what; }); Handlebars.registerHelper('typetest', function(num, options) { return typeof num; }); Handlebars.registerHelper('frank', function() { var options; options = arguments[arguments.length - 1]; return "WOO: " + options.hash.text + " " + options.hash.text2; }); Handlebars.registerHelper('sally', function() { var content, options, param, params; options = arguments[arguments.length - 1]; params = Array.prototype.slice.call(arguments, 0, -1); param = params[0] || 'none'; if (options.fn) { content = options.fn(this); return new Handlebars.SafeString("" + content + ""); } else { content = param; return new Handlebars.SafeString("" + content + ""); } }); test("basic", function() { return shouldCompileTo('echo foo', { foo: "YES" }, 'ECHO YES'); }); test("hashed parameters should work", function() { return shouldCompileTo('frank text="YES" text2="NO"', 'WOO: YES NO'); }); Handlebars.registerHelper('concatenator', function() { var key, options, value; options = arguments[arguments.length - 1]; return new Handlebars.SafeString(((function() { var _ref1, _results; _ref1 = options.hash; _results = []; for (key in _ref1) { value = _ref1[key]; _results.push("'" + key + "'='" + value + "'"); } return _results; })()).sort().join(" ")); }); test("negative integers should work", function() { return shouldCompileTo('concatenator positive=100 negative=-100', "'negative'='-100' 'positive'='100'"); }); test("booleans", function() { shouldCompileToString('typetest true', 'boolean'); shouldCompileToString('typetest false', 'boolean'); shouldCompileTo('booltest what=false', 'false'); shouldCompileTo('booltest what=true', 'true'); shouldCompileTo('booltest what="false"', 'neither'); return shouldCompileTo('booltest what="true"', 'neither'); }); test("integers", function() { shouldCompileToString('typetest 200', 'number'); shouldCompileTo('hashtypetest what=1', 'number'); return shouldCompileTo('hashtypetest what=200', 'number'); }); test("nesting", function() { var emblem; emblem = "sally\n p Hello"; return shouldCompileTo(emblem, '

Hello

'); }); test("recursive nesting", function() { var emblem; emblem = "sally\n sally\n p Hello"; return shouldCompileTo(emblem, '

Hello

'); }); test("recursive nesting pt 2", function() { var emblem; emblem = "sally\n sally thing\n p Hello"; return shouldCompileTo(emblem, { thing: "woot" }, '

Hello

'); }); test("bracketed nested statement", function() { var emblem; emblem = "sally [\n 'foo'\n something=\"false\" ]\n | Bracketed helper attrs!"; return shouldCompileTo(emblem, 'Bracketed helper attrs!'); }); test("bracketed nested block", function() { var emblem; emblem = "sally [\n 'foo'\n something=\"false\" ]\n p Bracketed helper attrs!"; return shouldCompileTo(emblem, '

Bracketed helper attrs!

'); }); Handlebars.registerHelper('view', function(param, a, b, c) { var content, hashString, k, options, v, _ref1; options = arguments[arguments.length - 1]; content = param; if (options.fn) { content = options.fn(this); } hashString = ""; _ref1 = options.hash; for (k in _ref1) { if (!__hasProp.call(_ref1, k)) continue; v = _ref1[k]; hashString += " " + k + "=" + v; } if (!hashString) { hashString = " nohash"; } return new Handlebars.SafeString("<" + param + hashString + ">" + content + ""); }); suite("capitalized line-starter"); test("should invoke `view` helper by default", function() { var emblem; emblem = "SomeView"; return shouldEmberPrecompileToHelper(emblem, 'view'); }); test("should not invoke `view` helper for vanilla HB", function() { var emblem; emblem = "SomeView"; return shouldCompileToString(emblem, { SomeView: "ALEX" }, 'ALEX'); }); test("should support block mode", function() { var emblem; emblem = "SomeView\n p View content"; return shouldEmberPrecompileToHelper(emblem, 'view'); }); test("should not kick in if preceded by equal sign", function() { var emblem; emblem = "= SomeView"; return shouldCompileTo(emblem, { SomeView: 'erp' }, 'erp'); }); test("should not kick in explicit {{mustache}}", function() { var emblem; emblem = "p Yeah {{SomeView}}"; return shouldCompileTo(emblem, { SomeView: 'erp' }, '

Yeah erp

'); }); suite("bang syntax defaults to `unbound` helper syntax"); Handlebars.registerHelper('unbound', function() { var content, options, params, stringedParams; options = arguments[arguments.length - 1]; params = Array.prototype.slice.call(arguments, 0, -1); stringedParams = params.join(' '); content = options.fn ? options.fn(this) : stringedParams; return new Handlebars.SafeString("" + content + ""); }); test("bang helper defaults to `unbound` invocation", function() { var emblem; emblem = "foo! Yar\n= foo!"; return shouldCompileToString(emblem, 'foo Yarfoo'); }); test("bang helper works with blocks", function() { var emblem; emblem = "hey! you suck\n = foo!"; return shouldCompileToString(emblem, 'foo'); }); suite("question mark syntax defaults to `if` helper syntax"); test("? helper defaults to `if` invocation", function() { var emblem; emblem = "foo?\n p Yeah"; return shouldCompileTo(emblem, { foo: true }, '

Yeah

'); }); test("else works", function() { var emblem; emblem = "foo?\n p Yeah\nelse\n p No"; return shouldCompileTo(emblem, { foo: false }, '

No

'); }); test("compound", function() { var emblem; emblem = "p = foo? \n | Hooray\nelse\n | No\np = bar? \n | Hooray\nelse\n | No"; return shouldCompileTo(emblem, { foo: true, bar: false }, '

Hooray

No

'); }); test("compound", function() { var emblem; emblem = "p = foo? \n bar\nelse\n baz"; return shouldCompileTo(emblem, { foo: true, bar: "borf", baz: "narsty" }, '

borf

'); }); suite("conditionals"); test("simple if statement", function() { var emblem; emblem = "if foo\n | Foo\nif bar\n | Bar"; return shouldCompileTo(emblem, { foo: true, bar: false }, 'Foo'); }); test("if else ", function() { var emblem; emblem = "if foo\n | Foo\n if bar\n | Bar\n else\n | Woot\nelse\n | WRONG\nif bar\n | WRONG\nelse\n | Hooray"; return shouldCompileTo(emblem, { foo: true, bar: false }, 'FooWootHooray'); }); test("else with preceding `=`", function() { var emblem; emblem = "= if foo\n p Yeah\n= else\n p No\n= if bar\n p Yeah!\n= else\n p No!\n=if bar\n p Yeah!\n=else\n p No!"; return shouldCompileTo(emblem, { foo: true, bar: false }, '

Yeah

No!

No!

'); }); test("unless", function() { var emblem; emblem = "unless bar\n | Foo\n unless foo\n | Bar\n else\n | Woot\nelse\n | WRONG\nunless foo\n | WRONG\nelse\n | Hooray"; return shouldCompileTo(emblem, { foo: true, bar: false }, 'FooWootHooray'); }); test("else followed by newline doesn't gobble else content", function() { var emblem; emblem = "if something\n p something\nelse\n\n if nothing\n p nothing\n else\n p not nothing"; return shouldCompileTo(emblem, {}, '

not nothing

'); }); suite("class shorthand and explicit declaration is coalesced"); test("when literal class is used", function() { return shouldCompileTo('p.foo class="bar"', '

'); }); test("when ember expression is used with variable", function() { return shouldCompileTo('p.foo class=bar', { bar: 'baz' }, '

'); }); test("when ember expression is used with variable in braces", function() { var result; result = shouldEmberPrecompileToHelper('p.foo class={ bar }'); return ok(-1 !== result.indexOf('\'class\': (":foo bar")')); }); test("when ember expression is used with constant in braces", function() { var result; result = shouldEmberPrecompileToHelper('p.foo class={ :bar }'); return ok(-1 !== result.indexOf('\'class\': (":foo :bar")')); }); test("when ember expression is used with constant and variable in braces", function() { var result; result = shouldEmberPrecompileToHelper('p.foo class={ :bar bar }'); return ok(-1 !== result.indexOf('\'class\': (":foo :bar bar")')); }); test("when ember expression is used with bind-attr", function() { var result; result = shouldEmberPrecompileToHelper('p.foo{ bind-attr class="bar" }'); return ok(-1 !== result.indexOf('\'class\': (":foo bar")')); }); test("when ember expression is used with bind-attr and multiple attrs", function() { var result; result = shouldEmberPrecompileToHelper('p.foo{ bind-attr something=bind class="bar" }'); return ok(-1 !== result.indexOf('\'class\': (":foo bar")')); }); test("only with bind-attr helper", function() { var result; result = shouldEmberPrecompileToHelper('p.foo{ someHelper class="bar" }', 'someHelper'); ok(-1 !== result.indexOf('\'class\': ("bar")')); return ok(-1 !== result.indexOf('class=\\"foo\\"')); }); bindAttrHelper = function() { var bindingString, k, options, param, params, v, _ref1; options = arguments[arguments.length - 1]; params = Array.prototype.slice.call(arguments, 0, -1); bindingString = ""; _ref1 = options.hash; for (k in _ref1) { if (!__hasProp.call(_ref1, k)) continue; v = _ref1[k]; bindingString += " " + k + " to " + v; } if (!bindingString) { bindingString = " narf"; } param = params[0] || 'none'; return "bind-attr" + bindingString; }; Handlebars.registerHelper('bind-attr', bindAttrHelper); EmberHandlebars.registerHelper('bind-attr', bindAttrHelper); suite("bind-attr behavior for unquoted attribute values"); test("basic", function() { var emblem; emblem = 'p class=foo'; shouldCompileTo(emblem, { foo: "YEAH" }, '

'); return shouldEmberPrecompileToHelper(emblem); }); test("basic w/ underscore", function() { var emblem; emblem = 'p class=foo_urns'; shouldCompileTo(emblem, { foo_urns: "YEAH" }, '

'); return shouldEmberPrecompileToHelper(emblem); }); test("subproperties", function() { var emblem; emblem = 'p class=foo._death.woot'; shouldCompileTo(emblem, { foo: { _death: { woot: "YEAH" } } }, '

'); return shouldEmberPrecompileToHelper(emblem); }); test("multiple", function() { return shouldCompileTo('p class=foo id="yup" data-thinger=yeah Hooray', { foo: "FOO", yeah: "YEAH" }, '

Hooray

'); }); test("class bind-attr special syntax", function() { var emblem; emblem = 'p class=foo:bar:baz'; shouldEmberPrecompileToHelper(emblem); return shouldThrow((function() { return CompilerContext.compile(emblem); })); }); test("class bind-attr braced syntax w/ underscores and dashes", function() { var emblem; shouldEmberPrecompileToHelper('p class={f-oo:bar :b_az}'); shouldEmberPrecompileToHelper('p class={ f-oo:bar :b_az }'); shouldEmberPrecompileToHelper('p class={ f-oo:bar :b_az } Hello'); emblem = ".input-prepend class={ filterOn:input-append }\n span.add-on"; return shouldEmberPrecompileToHelper(emblem); }); test("exclamation modifier (vanilla)", function() { var emblem; emblem = 'p class=foo!'; return shouldCompileTo(emblem, { foo: "YEAH" }, '

'); }); test("exclamation modifier (ember)", function() { var emblem, result; emblem = 'p class=foo!'; result = precompileEmber(emblem); ok(result.match(/p class/)); return ok(result.match(/helpers\.unbound.*foo/)); }); suite("in-tag explicit mustache"); Handlebars.registerHelper('inTagHelper', function(p) { return p; }); test("single", function() { return shouldCompileTo('p{inTagHelper foo}', { foo: "ALEX" }, '

'); }); test("double", function() { return shouldCompileTo('p{inTagHelper foo}', { foo: "ALEX" }, '

'); }); test("triple", function() { return shouldCompileTo('p{inTagHelper foo}', { foo: "ALEX" }, '

'); }); Handlebars.registerHelper('insertClass', function(p) { return 'class="' + p + '"'; }); test("with singlestache", function() { return shouldCompileTo('p{insertClass foo} Hello', { foo: "yar" }, '

Hello

'); }); test("singlestache can be used in text nodes", function() { return shouldCompileTo('p Hello {dork}', '

Hello {dork}

'); }); test("with doublestache", function() { return shouldCompileTo('p{{insertClass foo}} Hello', { foo: "yar" }, '

Hello

'); }); test("with triplestache", function() { return shouldCompileTo('p{{{insertClass foo}}} Hello', { foo: "yar" }, '

Hello

'); }); test("multiple", function() { return shouldCompileTo('p{{{insertClass foo}}}{{{insertClass boo}}} Hello', { foo: "yar", boo: "nar" }, '

Hello

'); }); test("with nesting", function() { var emblem; emblem = "p{{bind-attr class=\"foo\"}}\n span Hello"; return shouldCompileTo(emblem, { foo: "yar" }, '

Hello

'); }); suite("actions"); Handlebars.registerHelper('action', function() { var hashString, k, options, params, paramsString, v, _ref1; options = arguments[arguments.length - 1]; params = Array.prototype.slice.call(arguments, 0, -1); hashString = ""; paramsString = params.join('|'); _ref1 = options.hash; for (k in _ref1) { if (!__hasProp.call(_ref1, k)) continue; v = _ref1[k]; hashString += " " + k + "=" + v; } if (!hashString) { hashString = " nohash"; } return "action " + paramsString + hashString; }); test("basic (click)", function() { var emblem; emblem = "button click=\"submitComment\" Submit Comment"; return shouldCompileToString(emblem, ''); }); test("basic (click) followed by attr", function() { var emblem; emblem = "button click=\"submitComment\" class=\"foo\" Submit Comment"; shouldCompileToString(emblem, ''); emblem = "button click=\"submitComment 'omg'\" class=\"foo\" Submit Comment"; return shouldCompileToString(emblem, ''); }); test("nested (mouseEnter)", function() { var emblem; emblem = "a mouseEnter='submitComment target=\"view\"'\n | Submit Comment"; return shouldCompileToString(emblem, 'Submit Comment'); }); test("nested (mouseEnter, doublequoted)", function() { var emblem; emblem = "a mouseEnter=\"submitComment target='view'\"\n | Submit Comment"; return shouldCompileToString(emblem, 'Submit Comment'); }); test("manual", function() { var emblem; emblem = "a{action submitComment target=\"view\"} Submit Comment"; return shouldCompileToString(emblem, 'Submit Comment'); }); test("manual nested", function() { var emblem; emblem = "a{action submitComment target=\"view\"}\n p Submit Comment"; return shouldCompileToString(emblem, '

Submit Comment

'); }); suite("haml style"); test("basic", function() { var emblem; emblem = "%borf"; return shouldCompileToString(emblem, ''); }); test("nested", function() { var emblem; emblem = "%borf\n %sporf Hello"; return shouldCompileToString(emblem, 'Hello'); }); test("capitalized", function() { var emblem; emblem = "%Alex alex\n%Alex\n %Woot"; return shouldCompileToString(emblem, 'alex'); }); test("funky chars", function() { var emblem; emblem = "%borf:narf\n%borf:narf Hello, {{foo}}.\n%alex = foo"; return shouldCompileToString(emblem, { foo: "Alex" }, 'Hello, Alex.Alex'); }); suite("line-based errors"); test("line number is provided for pegjs error", function() { var emblem; emblem = "p Hello\np Hello {{narf}"; return shouldThrow((function() { return CompilerContext.compile(emblem); }), "line 2"); }); test("single quote test", function() { var emblem; emblem = "button click='p' Frank\n \n/ form s='d target=\"App\"'\n label I'm a label!"; return shouldCompileToString(emblem, ''); }); test("double quote test", function() { var emblem; emblem = "button click=\"p\" Frank\n \n/ form s='d target=\"App\"'\n label I'm a label!"; return shouldCompileToString(emblem, ''); }); test("no quote test", function() { var emblem; emblem = "button click=p Frank\n \n/ form s='d target=\"App\"'\n label I'm a label!"; return shouldCompileToString(emblem, ''); }); suite("mustache DOM attribute shorthand"); test("tagName w/o space", function() { var emblem, result; emblem = "App.FunView%span"; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); return ok(result.match(/tagName.*span/)); }); test("tagName w/ space", function() { var emblem, result; emblem = "App.FunView %span"; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); return ok(result.match(/tagName.*span/)); }); test("tagName block", function() { var emblem; emblem = "view App.FunView%span\n p Hello"; return shouldCompileToString(emblem, '

Hello

'); }); test("class w/ space (needs space)", function() { var emblem, result; emblem = "App.FunView .bork"; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); return ok(result.match(/class.*bork/)); }); test("multiple classes", function() { var emblem, result; emblem = "App.FunView .bork.snork"; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); return ok(result.match(/class.*bork.*snork/)); }); test("elementId", function() { var emblem, result; emblem = "App.FunView#ohno"; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); return ok(result.match(/elementId.*ohno/)); }); test("mixed w/ hash`", function() { var emblem, result; emblem = "App.FunView .bork.snork funbags=\"yeah\""; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); ok(result.match(/class.*bork.*snork/)); ok(result.match(/hash/)); ok(result.match(/funbags/)); return ok(result.match(/yeah/)); }); test("mixture of all`", function() { var emblem, result; emblem = "App.FunView%alex#hell.bork.snork funbags=\"yeah\""; result = precompileEmber(emblem); ok(result.match(/helpers\.view/)); ok(result.match(/App\.FunView/)); ok(result.match(/tagName.*alex/)); ok(result.match(/elementId.*hell/)); ok(result.match(/class.*bork.*snork/)); ok(result.match(/hash/)); ok(result.match(/funbags/)); return ok(result.match(/yeah/)); }); suite("self-closing html tags"); test("br", function() { var emblem; emblem = "br"; return shouldCompileToString(emblem, '
'); }); test("br paragraph example", function() { var emblem; emblem = "p\n | LOL!\n br\n | BORF!"; return shouldCompileToString(emblem, '

LOL!
BORF!

'); }); test("input", function() { var emblem; emblem = "input type=\"text\""; return shouldCompileToString(emblem, ''); }); suite("ember."); test("should precompile with EmberHandlebars", function() { var emblem, result; emblem = "input type=\"text\""; result = Emblem.precompile(EmberHandlebars, 'p Hello').toString(); return ok(result.match('

Hello

')); }); suite("old school handlebars"); test("array", function() { var emblem, hash; emblem = 'goodbyes\n | #{text}! \n| cruel #{world}!'; hash = { goodbyes: [ { text: "goodbye" }, { text: "Goodbye" }, { text: "GOODBYE" } ], world: "world" }; shouldCompileToString(emblem, hash, "goodbye! Goodbye! GOODBYE! cruel world!"); hash = { goodbyes: [], world: "world" }; return shouldCompileToString(emblem, hash, "cruel world!"); }); Handlebars.registerPartial('hbPartial', '{{name}}'); test("calling handlebars partial", function() { var emblem; emblem = '> hbPartial\n| Hello #{> hbPartial}'; return shouldCompileToString(emblem, { id: 666, name: "Death" }, 'DeathHello Death'); }); Emblem.registerPartial(Handlebars, 'emblemPartial', 'a href="/people/{{id}}" = name'); Emblem.registerPartial(Handlebars, 'emblemPartialB', 'p Grr'); Emblem.registerPartial(Handlebars, 'emblemPartialC', 'p = a'); test("calling emblem partial", function() { return shouldCompileToString('> emblemPartial', { id: 666, name: "Death" }, 'Death'); }); test("calling emblem partial with context", function() { return shouldCompileToString('> emblemPartialC foo', { foo: { a: "YES" } }, '

YES

'); }); test("partials in mustaches", function() { var emblem; emblem = "| Hello, {{> emblemPartialC foo}}{{>emblemPartialB}}{{>emblemPartialB }}"; return shouldCompileToString(emblem, { foo: { a: "YES" } }, 'Hello,

YES

Grr

Grr

'); }); test("handlebars dot-separated paths with segment-literal notation", function() { var emblem; emblem = 'p = articles.[3]'; return shouldCompileTo(emblem, { articles: ['zero', 'one', 'two', 'three'] }, '

three

'); }); test("handlebars dot-separated paths with segment-literal notation, more nesting", function() { var emblem; emblem = 'p = articles.[3].[#comments].[0]'; return shouldCompileTo(emblem, { articles: [ {}, {}, {}, { '#comments': ['bazinga'] } ] }, '

bazinga

'); }); test("../path as inMustacheParam recognized correctly as pathIdNode instead of classShorthand", function() { var emblem; Handlebars.registerHelper('jumpToParent', function(link) { return new Handlebars.SafeString("Jump to parent top"); }); emblem = 'each children\n jumpToParent ../parentLink'; return shouldCompileTo(emblem, { parentLink: '#anchor', children: [{}] }, 'Jump to parent top'); }); test("block as #each", function() { var emblem; emblem = 'thangs\n p Woot #{yeah}'; return shouldCompileToString(emblem, { thangs: [ { yeah: 123 }, { yeah: 456 } ] }, '

Woot 123

Woot 456

'); }); if (supportsEachHelperDataKeywords) { suite("each block helper keywords prefixed by @"); test("#each with @index", function() { var emblem; emblem = 'thangs\n p #{@index} Woot #{yeah}'; return shouldCompileToString(emblem, { thangs: [ { yeah: 123 }, { yeah: 456 } ] }, '

0 Woot 123

1 Woot 456

'); }); test("#each with @key", function() { var emblem; emblem = 'each thangs\n p #{@key}: #{this}'; return shouldCompileTo(emblem, { thangs: { '@key': 123, 'works!': 456 } }, '

@key: 123

works!: 456

'); }); test("#each with @key, @index", function() { var emblem; emblem = 'each thangs\n p #{@index} #{@key}: #{this}'; return shouldCompileTo(emblem, { thangs: { '@key': 123, 'works!': 456 } }, '

0 @key: 123

1 works!: 456

'); }); test("#each with @key, @first", function() { var emblem; emblem = 'each thangs\n if @first\n p First item\n else\n p #{@key}: #{this}'; return shouldCompileTo(emblem, { thangs: { '@key': 123, 'works!': 456 } }, '

First item

works!: 456

'); }); } /* test "partial in block", -> emblem = """ ul = people > link """ data = people: [ { "name": "Alan", "id": 1 } { "name": "Yehuda", "id": 2 } ] shouldCompileToString emblem, data, '