diff --git a/spec/stdlib/template/builder-spec.coffee b/spec/stdlib/template/builder-spec.coffee index b3cc0d5d3..c5ab6584f 100644 --- a/spec/stdlib/template/builder-spec.coffee +++ b/spec/stdlib/template/builder-spec.coffee @@ -6,6 +6,31 @@ describe "Builder", -> beforeEach -> builder = new Builder + describe "tag class methods", -> + it "calls render, assuming the arguments to the current method as the first tag", -> + fragment = + Builder.div -> + @ol class: 'cool-list', => + @li() + @li() + + expect(fragment).toMatchSelector('div') + expect(fragment.find('ol.cool-list')).toExist() + expect(fragment.find('li').length).toBe 2 + + describe "@render", -> + it "runs the given function in a fresh builder instance and returns the resulting view fragment", -> + fragment = + Builder.render -> + @div => + @ol class: 'cool-list', => + @li() + @li() + + expect(fragment).toMatchSelector('div') + expect(fragment.find('ol.cool-list')).toExist() + expect(fragment.find('li').length).toBe 2 + describe ".tag(name, args...)", -> it "can generate simple tags", -> builder.tag 'div' diff --git a/src/stdlib/template/builder.coffee b/src/stdlib/template/builder.coffee index 7ac94a3a0..fa68e447c 100644 --- a/src/stdlib/template/builder.coffee +++ b/src/stdlib/template/builder.coffee @@ -6,6 +6,11 @@ Text = require 'template/text' module.exports = class Builder + @render: (fn) -> + builder = new this + fn.call(builder) + builder.toFragment() + @elements: normal: 'a abbr address article aside audio b bdi bdo blockquote body button canvas caption cite code colgroup datalist dd del details dfn div dl dt em @@ -18,6 +23,25 @@ class Builder void: 'area base br col command embed hr img input keygen link meta param source track wbr'.split /\s+/ + @allElements: -> + @elements.normal.concat(@elements.void) + + @buildTagClassMethod: (tagName) -> + this[tagName] = (args...) -> + @render -> + argsWithBoundFunctions = args.map (arg) => + if _.isFunction(arg) + _.bind(arg, this) + else + arg + @tag(tagName, argsWithBoundFunctions...) + + @buildTagInstanceMethod: (tagName) -> + @prototype[tagName] = (args...) -> @tag(tagName, args...) + + @allElements().forEach (tagName) => @buildTagClassMethod(tagName) + @allElements().forEach (tagName) => @buildTagInstanceMethod(tagName) + constructor: -> @reset() @@ -37,7 +61,7 @@ class Builder @document.push(new OpenTag(name, options.attributes)) if @elementIsVoid(name) if (options.text? or options.content?) - throw new Error("Self-closing tag #{tag} cannot have text or content") + throw new Error("Self-closing tag #{name} cannot have text or content") else options.content?() @text(options.text) if options.text