# Test Setup: Set up an environment that'll work for both Node and Qunit tests. Ember = window?.Emblem || @Emblem || {} # These are needed for the full version ember to load properly LoadedEmber = LoadedEmber || {} Ember.Handlebars = LoadedEmber.Handlebars Ember.warn = LoadedEmber.warn if Emblem? # Qunit testing _equal = equal equals = equal = (a, b, msg) -> # Allow exec with missing message params _equal(a, b, msg || '') # In QUnit, we use module() instead of nonexistent suite() window.suite = module else # Setup for Node package testing Handlebars = require('handlebars') EmberHandlebars = require('./resources/ember-template-compiler.js').EmberHandlebars Emblem = require('../lib/emblem') # TODO: replace with real expect() `expect = function() {};` {equal, equals, ok, throws} = require("assert") unless CompilerContext? # Note that this doesn't have the same context separation as the rspec test. # Both should be run for full acceptance of the two libary modes. CompilerContext = compile: (template, options) -> Emblem.compile(Handlebars, template, options) supportsEachHelperDataKeywords = Handlebars.VERSION.slice(0, 3) >= 1.2 supportsSubexpressions = Handlebars.VERSION.slice(0, 3) >= 1.3 precompileEmber = (emblem) -> Emblem.precompile(EmberHandlebars, emblem).toString() shouldEmberPrecompileToHelper = (emblem, helper = 'bind-attr') -> result = precompileEmber emblem ok (result.match "helpers.#{helper}") or (result.match "helpers\\['#{helper}'\\]") result shouldCompileToString = (string, hashOrArray, expected) -> if hashOrArray.constructor == String shouldCompileToWithPartials(string, {}, false, hashOrArray, null, true) else shouldCompileToWithPartials(string, hashOrArray, false, expected, null, true) shouldCompileTo = (string, hashOrArray, expected, message) -> if hashOrArray.constructor == String shouldCompileToWithPartials(string, {}, false, hashOrArray, message) else shouldCompileToWithPartials(string, hashOrArray, false, expected, message) shouldCompileToWithPartials = (string, hashOrArray, partials, expected, message, strings) -> options = null if strings options = {} options.stringParams = true result = compileWithPartials(string, hashOrArray, partials, options) equal(result, expected, "'" + result + "' should === '" + expected + "': " + message) compileWithPartials = (string, hashOrArray, partials, options = {}) -> template = CompilerContext.compile(string, options) if Object::toString.call(hashOrArray) == "[object Array]" if helpers = hashOrArray[1] for prop of 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] template.apply(this, ary) shouldThrow = (fn, exMessage) -> caught = false try fn() catch e caught = true if exMessage ok e.message.match(exMessage), "exception message matched" ok(caught, "an exception was thrown") Handlebars.registerHelper 'echo', (param) -> "ECHO #{param}" suite "html one-liners" test "element only", -> shouldCompileTo "p", "

" test "with text", -> shouldCompileTo "p Hello", "

Hello

" test "with more complex text", -> shouldCompileTo "p Hello, how's it going with you today?", "

Hello, how's it going with you today?

" test "with trailing space", -> shouldCompileTo "p Hello ", "

Hello

" suite "html multi-lines" test "two lines", -> emblem = """ p This is pretty cool. """ shouldCompileTo emblem, "

This is pretty cool.

" test "three lines", -> emblem = """ p This is pretty damn cool. """ shouldCompileTo emblem, "

This is pretty damn cool.

" test "three lines w/ embedded html", -> emblem = """ p This is pretty damn cool. """ shouldCompileTo emblem, "

This is pretty damn cool.

" test "indentation doesn't need to match starting inline content's", -> emblem = """ span Hello, How are you? """ shouldCompileTo emblem, "Hello, How are you?" test "indentation may vary between parent/child, must be consistent within inline-block", -> emblem = """ div span Hello, How are you? Excellent. p asd """ shouldCompileTo emblem, "
Hello, How are you? Excellent.

asd

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

Hello, Hello, and Hello!

' emblem = ''' p Hello, #{ sally: span: a Hello}! ''' shouldCompileTo emblem, '

Hello, Hello!

' test "with followup", -> emblem = """ p This is pretty cool. p Hello. """ shouldCompileTo emblem, "

This is pretty cool.

Hello.

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

Hello

" test "it handles preceding indentation", -> emblem = " p Woot\n p Ha" shouldCompileTo emblem, "

Woot

Ha

" test "it handles preceding indentation and newlines", -> emblem = "\n p Woot\n p Ha" shouldCompileTo emblem, "

Woot

Ha

" test "it handles preceding indentation and newlines pt 2", -> emblem = " \n p Woot\n p Ha" shouldCompileTo emblem, "

Woot

Ha

" suite "comments" test "it strips out single line '/' comments", -> emblem = """ p Hello / A comment h1 How are you? """ shouldCompileTo emblem, "

Hello

How are you?

" test "it strips out multi-line '/' comments", -> emblem = """ p Hello / A comment that goes on to two lines even three! h1 How are you? """ shouldCompileTo emblem, "

Hello

How are you?

" test "it strips out multi-line '/' comments without text on the first line", -> emblem = """ p Hello / A comment that goes on to two lines even three! h1 How are you? """ shouldCompileTo emblem, "

Hello

How are you?

" test "mix and match with various indentation", -> emblem = """ / A test p Hello span / This is gnarly p Yessir nope. / Nothin but comments so many comments. / p Should not show up """ shouldCompileTo emblem, "

Hello

Yessir nope.

" test "uneven indentation", -> emblem = """ / nop nope nope """ shouldCompileTo emblem, "" test "uneven indentation 2", -> emblem = """ / n no nop nope """ shouldCompileTo emblem, "" test "uneven indentation 3", -> emblem = """ / n no nop nope """ shouldCompileTo emblem, "" test "empty first line", -> emblem = """ / nop nope nope no """ shouldCompileTo emblem, "" test "on same line as html content", -> emblem = """ .container / This comment doesn't show up .row / Nor does this p Hello """ shouldCompileTo emblem, '

Hello

' test "on same line as mustache content", -> shouldCompileTo 'frank text="YES" text2="NO" / omg', 'WOO: YES NO' test "on same line as colon syntax", -> emblem = """ ul: li: span / omg | Hello """ shouldCompileTo emblem, '' suite "indentation" # This test used to make sure the emblem code threw, but now we # support multi-line syntax. test "it doesn't throw when indenting after a line with inline content", -> emblem = """ p Hello p invalid """ shouldCompileTo emblem, "

Hello p invalid

" test "it throws on half dedent", -> emblem = """ p span This is ok span This aint """ shouldThrow -> CompilerContext.compile emblem test "new indentation levels don't have to match parents'", -> emblem = """ p span div span yes """ shouldCompileTo emblem, "

yes

" suite "whitespace fussiness" test "spaces after html elements", -> shouldCompileTo "p \n span asd", "

asd

" shouldCompileTo "p \nspan \n\ndiv\nspan", "

" test "spaces after mustaches", -> shouldCompileTo "each foo \n p \n span", { foo: [1,2] }, "

" suite "attribute shorthand" test "id shorthand", -> shouldCompileTo "#woot", '
' shouldCompileTo "span#woot", '' test "class shorthand", -> shouldCompileTo ".woot", '
' shouldCompileTo "span.woot", '' shouldCompileTo "span.woot.loot", '' test "class can come first", -> shouldCompileTo ".woot#hello", '
' shouldCompileTo "span.woot#hello", '' shouldCompileTo "span.woot.loot#hello", '' shouldCompileTo "span.woot.loot#hello.boot", '' suite "full attributes - tags with content" test "class only", -> shouldCompileTo 'p class="yes" Blork', '

Blork

' test "id only", -> shouldCompileTo 'p id="yes" Hyeah', '

Hyeah

' test "class and id", -> shouldCompileTo 'p id="yes" class="no" Blork', '

Blork

' test "class and id and embedded html one-liner", -> shouldCompileTo 'p id="yes" class="no" One asd!', '

One asd!

' test "bracketed attributes", -> emblem = """ p [ id="yes" class="no" ] | Bracketed Attributes FTW! """ shouldCompileTo emblem, '

Bracketed Attributes FTW!

' test "bracketed text", -> emblem = """ p [ Bracketed text is cool ] """ shouldCompileTo emblem, '

[ Bracketed text is cool ]

' test "bracketed text indented", -> emblem = """ p | [ Bracketed text is cool ] """ shouldCompileTo emblem, '

[ Bracketed text is cool ]

' test "nesting", -> emblem = """ p class="hello" data-foo="gnarly" span Yes """ shouldCompileTo emblem, '

Yes

' suite "full attributes - mixed quotes" test "single empty", -> shouldCompileTo "p class=''", '

' test "single full", -> shouldCompileTo "p class='woot yeah'", '

' test "mixed", -> shouldCompileTo "p class='woot \"oof\" yeah'", '

' suite "full attributes - tags without content" test "empty", -> shouldCompileTo 'p class=""', '

' test "class only", -> shouldCompileTo 'p class="yes"', '

' test "id only", -> shouldCompileTo 'p id="yes"', '

' test "class and id", -> shouldCompileTo 'p id="yes" class="no"', '

' suite "full attributes w/ mustaches" test "with mustache", -> shouldCompileTo 'p class="foo {{yes}}"', {yes: "ALEX"}, '

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

Hello

' emblem = """ p class="foo {{yes}}" | Hello """ shouldCompileTo emblem, {yes: "ALEX"}, '

Hello

' test "with mustache calling helper", -> shouldCompileTo 'p class="foo {{{echo "YES"}}}"', '

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

Hello

' emblem = """ p class="foo {{echo "BORF"}}" | Hello """ shouldCompileTo emblem, '

Hello

' suite "boolean attributes" test "static", -> shouldCompileTo 'p borf=true', '

' shouldCompileTo 'p borf=true Woot', '

Woot

' shouldCompileTo 'p borf=false', '

' shouldCompileTo 'p borf=false Nork', '

Nork

' shouldCompileTo 'option selected=true Thingeroo', '' #test "dynamic", -> ## TODO #shouldCompileTo 'p borf=foo', { foo: true }, '

' #shouldCompileTo 'p borf=foo', { foo: false }, '

' #shouldCompileTo 'p borf=foo Yeah', { foo: true }, '

Yeah

' #shouldCompileTo 'p borf=foo Naww', { foo: false }, '

Naww

' #shouldCompileTo 'p borf=foo Naww', { foo: null }, '

Naww

' #shouldCompileTo 'p borf=foo Naww', { foo: undefined }, '

Naww

' #shouldCompileTo 'p borf=foo Naww', { foo: 0 }, '

Naww

' suite "html nested" test "basic", -> emblem = """ p span Hello strong Hi div p Hooray """ shouldCompileTo emblem, '

HelloHi

Hooray

' test "empty nest", -> emblem = """ p span strong i """ shouldCompileTo emblem, '

' test "empty nest w/ attribute shorthand", -> emblem = """ p.woo span#yes strong.no.yes i """ shouldCompileTo emblem, '

' suite "simple mustache" test "various one-liners", -> emblem = """ = foo arf p = foo span.foo p data-foo="yes" = goo """ shouldCompileTo emblem, { foo: "ASD", arf: "QWE", goo: "WER" }, 'ASDQWE

ASD

WER

' test "double =='s un-escape", -> emblem = """ == foo foo p == foo """ shouldCompileTo emblem, { foo: '123' }, '123<span>123</span>

123

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

Hello

' test "recursive nesting", -> emblem = """ sally sally p Hello """ shouldCompileTo emblem, '

Hello

' test "recursive nesting pt 2", -> emblem = """ sally sally thing p Hello """ shouldCompileTo emblem, { thing: "woot" }, '

Hello

' test "bracketed nested statement", -> emblem = """ sally [ 'foo' something="false" ] | Bracketed helper attrs! """ shouldCompileTo emblem, 'Bracketed helper attrs!' test "bracketed nested block", -> emblem = """ sally [ 'foo' something="false" ] p Bracketed helper attrs! """ shouldCompileTo emblem, '

Bracketed helper attrs!

' Handlebars.registerHelper 'view', (param, a, b, c) -> options = arguments[arguments.length - 1] content = param content = options.fn @ if options.fn hashString = "" for own k,v of options.hash hashString += " #{k}=#{v}" hashString = " nohash" unless hashString new Handlebars.SafeString """<#{param}#{hashString}>#{content}""" suite "capitalized line-starter" test "should invoke `view` helper by default", -> emblem = """ SomeView """ shouldEmberPrecompileToHelper emblem, 'view' #shouldCompileToString emblem, 'SomeView' test "should not invoke `view` helper for vanilla HB", -> emblem = """ SomeView """ shouldCompileToString emblem, {SomeView: "ALEX"}, 'ALEX' test "should support block mode", -> emblem = """ SomeView p View content """ #shouldCompileToString emblem, '

View content

' shouldEmberPrecompileToHelper emblem, 'view' test "should not kick in if preceded by equal sign", -> emblem = """ = SomeView """ shouldCompileTo emblem, { SomeView: 'erp' }, 'erp' test "should not kick in explicit {{mustache}}", -> emblem = """ p Yeah {{SomeView}} """ shouldCompileTo emblem, { SomeView: 'erp' }, '

Yeah erp

' # TODO test overriding the default helper name (instead of always "view") suite "bang syntax defaults to `unbound` helper syntax" Handlebars.registerHelper 'unbound', -> options = arguments[arguments.length - 1] params = Array::slice.call arguments, 0, -1 stringedParams = params.join(' ') content = if options.fn then options.fn @ else stringedParams new Handlebars.SafeString """#{content}""" test "bang helper defaults to `unbound` invocation", -> emblem = """ foo! Yar = foo! """ shouldCompileToString emblem, 'foo Yarfoo' test "bang helper works with blocks", -> emblem = """ hey! you suck = foo! """ shouldCompileToString emblem, 'foo' suite "question mark syntax defaults to `if` helper syntax" test "? helper defaults to `if` invocation", -> emblem = """ foo? p Yeah """ shouldCompileTo emblem, { foo: true }, '

Yeah

' test "else works", -> emblem = """ foo? p Yeah else p No """ shouldCompileTo emblem, { foo: false }, '

No

' test "compound", -> emblem = """ p = foo? | Hooray else | No p = bar? | Hooray else | No """ shouldCompileTo emblem, { foo: true, bar: false }, '

Hooray

No

' test "compound", -> emblem = """ p = foo? bar else baz """ shouldCompileTo emblem, { foo: true, bar: "borf", baz: "narsty" }, '

borf

' suite "conditionals" test "simple if statement", -> emblem = """ if foo | Foo if bar | Bar """ shouldCompileTo emblem, {foo: true, bar: false}, 'Foo' test "if else ", -> emblem = """ if foo | Foo if bar | Bar else | Woot else | WRONG if bar | WRONG else | Hooray """ shouldCompileTo emblem, {foo: true, bar: false}, 'FooWootHooray' test "else with preceding `=`", -> emblem = """ = if foo p Yeah = else p No = if bar p Yeah! = else p No! =if bar p Yeah! =else p No! """ shouldCompileTo emblem, {foo: true, bar: false}, '

Yeah

No!

No!

' test "unless", -> emblem = """ unless bar | Foo unless foo | Bar else | Woot else | WRONG unless foo | WRONG else | Hooray """ shouldCompileTo emblem, {foo: true, bar: false}, 'FooWootHooray' test "else followed by newline doesn't gobble else content", -> emblem = """ if something p something else if nothing p nothing else p not nothing """ shouldCompileTo emblem, {}, '

not nothing

' suite "class shorthand and explicit declaration is coalesced" test "when literal class is used", -> shouldCompileTo 'p.foo class="bar"', '

' test "when ember expression is used with variable", -> shouldCompileTo 'p.foo class=bar', {bar: 'baz'}, '

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

' shouldEmberPrecompileToHelper emblem test "basic w/ underscore", -> emblem = 'p class=foo_urns' shouldCompileTo emblem, {foo_urns: "YEAH"}, '

' shouldEmberPrecompileToHelper emblem test "subproperties", -> emblem = 'p class=foo._death.woot' shouldCompileTo emblem, {foo: { _death: { woot: "YEAH" } }}, '

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

Hooray

' test "class bind-attr special syntax", -> emblem = 'p class=foo:bar:baz' shouldEmberPrecompileToHelper emblem shouldThrow (-> CompilerContext.compile emblem) test "class bind-attr braced syntax w/ underscores and dashes", -> 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 } span.add-on """ shouldEmberPrecompileToHelper emblem test "exclamation modifier (vanilla)", -> emblem = 'p class=foo!' # exclamation is no-op in vanilla HB shouldCompileTo emblem, {foo:"YEAH"}, '

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

' test "double", -> shouldCompileTo 'p{inTagHelper foo}', {foo: "ALEX"}, '

' test "triple", -> shouldCompileTo 'p{inTagHelper foo}', {foo: "ALEX"}, '

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

Hello

' test "singlestache can be used in text nodes", -> shouldCompileTo 'p Hello {dork}', '

Hello {dork}

' test "with doublestache", -> shouldCompileTo 'p{{insertClass foo}} Hello', {foo: "yar"}, '

Hello

' test "with triplestache", -> shouldCompileTo 'p{{{insertClass foo}}} Hello', {foo: "yar"}, '

Hello

' test "multiple", -> shouldCompileTo 'p{{{insertClass foo}}}{{{insertClass boo}}} Hello', {foo: "yar", boo: "nar"}, '

Hello

' test "with nesting", -> emblem = """ p{{bind-attr class="foo"}} span Hello """ shouldCompileTo emblem, {foo: "yar"}, '

Hello

' suite "actions" Handlebars.registerHelper 'action', -> options = arguments[arguments.length - 1] params = Array::slice.call arguments, 0, -1 hashString = "" paramsString = params.join('|') # TODO: bad because it relies on hash ordering? # is this guaranteed? guess it doesn't rreeeeeally # matter since order's not being tested. for own k,v of options.hash hashString += " #{k}=#{v}" hashString = " nohash" unless hashString "action #{paramsString}#{hashString}" test "basic (click)", -> emblem = """ button click="submitComment" Submit Comment """ shouldCompileToString emblem, '' test "basic (click) followed by attr", -> emblem = """ button click="submitComment" class="foo" Submit Comment """ shouldCompileToString emblem, '' emblem = """ button click="submitComment 'omg'" class="foo" Submit Comment """ shouldCompileToString emblem, '' test "nested (mouseEnter)", -> emblem = """ a mouseEnter='submitComment target="view"' | Submit Comment """ shouldCompileToString emblem, 'Submit Comment' test "nested (mouseEnter, doublequoted)", -> emblem = """ a mouseEnter="submitComment target='view'" | Submit Comment """ shouldCompileToString emblem, 'Submit Comment' test "manual", -> emblem = """ a{action submitComment target="view"} Submit Comment """ shouldCompileToString emblem, 'Submit Comment' test "manual nested", -> emblem = """ a{action submitComment target="view"} p Submit Comment """ shouldCompileToString emblem, '

Submit Comment

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

Hello

' test "class w/ space (needs space)", -> emblem = """ App.FunView .bork """ result = precompileEmber emblem ok result.match /helpers\.view/ ok result.match /App\.FunView/ ok result.match /class.*bork/ test "multiple classes", -> emblem = """ App.FunView .bork.snork """ result = precompileEmber emblem ok result.match /helpers\.view/ ok result.match /App\.FunView/ ok result.match /class.*bork.*snork/ test "elementId", -> emblem = """ App.FunView#ohno """ result = precompileEmber emblem ok result.match /helpers\.view/ ok result.match /App\.FunView/ ok result.match /elementId.*ohno/ test "mixed w/ hash`", -> 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/ ok result.match /yeah/ test "mixture of all`", -> 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/ ok result.match /yeah/ suite "self-closing html tags" test "br", -> emblem = """ br """ shouldCompileToString emblem, '
' test "br paragraph example", -> emblem = """ p | LOL! br | BORF! """ shouldCompileToString emblem, '

LOL!
BORF!

' test "input", -> emblem = """ input type="text" """ shouldCompileToString emblem, '' suite "ember." test "should precompile with EmberHandlebars", -> emblem = """ input type="text" """ result = Emblem.precompile(EmberHandlebars, 'p Hello').toString() ok result.match '

Hello

' suite "old school handlebars" test "array", -> emblem = ''' goodbyes | #{text}! | cruel #{world}! ''' hash = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"} shouldCompileToString emblem, hash, "goodbye! Goodbye! GOODBYE! cruel world!" hash = {goodbyes: [], world: "world"} shouldCompileToString emblem, hash, "cruel world!" Handlebars.registerPartial('hbPartial', '{{name}}') test "calling handlebars partial", -> emblem = ''' > hbPartial | Hello #{> hbPartial} ''' 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", -> shouldCompileToString '> emblemPartial', { id: 666, name: "Death" }, 'Death' test "calling emblem partial with context", -> shouldCompileToString '> emblemPartialC foo', { foo: { a: "YES" } }, '

YES

' test "partials in mustaches", -> emblem = """ | Hello, {{> emblemPartialC foo}}{{>emblemPartialB}}{{>emblemPartialB }} """ shouldCompileToString emblem, { foo: { a: "YES" } }, 'Hello,

YES

Grr

Grr

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

three

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

bazinga

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

Woot 123

Woot 456

' if supportsEachHelperDataKeywords suite "each block helper keywords prefixed by @" test "#each with @index", -> emblem = ''' thangs p #{@index} Woot #{yeah} ''' shouldCompileToString emblem, { thangs: [{yeah: 123}, {yeah:456}] }, '

0 Woot 123

1 Woot 456

' test "#each with @key", -> emblem = ''' each thangs p #{@key}: #{this} ''' shouldCompileTo emblem, { thangs: {'@key': 123, 'works!':456} }, '

@key: 123

works!: 456

' test "#each with @key, @index", -> emblem = ''' each thangs p #{@index} #{@key}: #{this} ''' shouldCompileTo emblem, { thangs: {'@key': 123, 'works!':456} }, '

0 @key: 123

1 works!: 456

' test "#each with @key, @first", -> emblem = ''' each thangs if @first p First item else p #{@key}: #{this} ''' 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, '