diff --git a/spec/atom/app-spec.coffee b/spec/atom/app-spec.coffee
new file mode 100644
index 000000000..03e5bc06a
--- /dev/null
+++ b/spec/atom/app-spec.coffee
@@ -0,0 +1,11 @@
+App = require 'views/app'
+
+describe "App", ->
+ view = null
+
+ beforeEach ->
+ view = App.buildView()
+
+
+
+
diff --git a/spec/spec-suite.coffee b/spec/spec-suite.coffee
index b92ec40f1..4e5e11efa 100644
--- a/spec/spec-suite.coffee
+++ b/spec/spec-suite.coffee
@@ -1,4 +1,2 @@
-describe "a test", ->
- it "should run", ->
- (expect 1).toEqual 2
+require 'template-spec'
diff --git a/spec/stdlib/template-spec.coffee b/spec/stdlib/template-spec.coffee
new file mode 100644
index 000000000..1a139ffd0
--- /dev/null
+++ b/spec/stdlib/template-spec.coffee
@@ -0,0 +1,20 @@
+Template = require 'template'
+
+describe "Template", ->
+ describe "toView", ->
+ Foo = null
+
+ beforeEach ->
+ class Foo extends Template
+ content: ->
+ div ->
+ h1 @title
+
+ afterEach ->
+ delete window.Foo
+
+ it "builds a jquery object based on the content method and extends it with the viewProperties", ->
+ view = Foo.buildView(title: "Hello World")
+ expect(view.find('h1').text()).toEqual "Hello World"
+
+
diff --git a/src/stdlib/template.coffee b/src/stdlib/template.coffee
new file mode 100644
index 000000000..8ce3a4b31
--- /dev/null
+++ b/src/stdlib/template.coffee
@@ -0,0 +1,11 @@
+$ = require 'jquery'
+coffeekup = require 'coffeekup'
+
+module.exports =
+class Template
+ @buildView: (attributes) ->
+ (new this).buildView(attributes)
+
+ buildView: (attributes) ->
+ $(coffeekup.render(@content, attributes))
+
diff --git a/vendor/coffeekup.coffee b/vendor/coffeekup.coffee
new file mode 100644
index 000000000..4156a4c9d
--- /dev/null
+++ b/vendor/coffeekup.coffee
@@ -0,0 +1,367 @@
+# **CoffeeKup** lets you to write HTML templates in 100% pure
+# [CoffeeScript](http://coffeescript.org).
+#
+# You can run it on [node.js](http://nodejs.org) or the browser, or compile your
+# templates down to self-contained javascript functions, that will take in data
+# and options and return generated HTML on any JS runtime.
+#
+# The concept is directly stolen from the amazing
+# [Markaby](http://markaby.rubyforge.org/) by Tim Fletcher and why the lucky
+# stiff.
+
+coffeekup = module.exports
+coffee = require 'coffee-script'
+
+coffeekup.version = '0.3.1edge'
+
+# Values available to the `doctype` function inside a template.
+# Ex.: `doctype 'strict'`
+coffeekup.doctypes =
+ 'default': ''
+ '5': ''
+ 'xml': ''
+ 'transitional': ''
+ 'strict': ''
+ 'frameset': ''
+ '1.1': '',
+ 'basic': ''
+ 'mobile': ''
+ 'ce': ''
+
+# CoffeeScript-generated JavaScript may contain anyone of these; but when we
+# take a function to string form to manipulate it, and then recreate it through
+# the `Function()` constructor, it loses access to its parent scope and
+# consequently to any helpers it might need. So we need to reintroduce these
+# inside any "rewritten" function.
+coffeescript_helpers = """
+ var __slice = Array.prototype.slice;
+ var __hasProp = Object.prototype.hasOwnProperty;
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ var __extends = 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; };
+ var __indexOf = Array.prototype.indexOf || function(item) {
+ for (var i = 0, l = this.length; i < l; i++) {
+ if (this[i] === item) return i;
+ } return -1; };
+""".replace /\n/g, ''
+
+# Private HTML element reference.
+# Please mind the gap (1 space at the beginning of each subsequent line).
+elements =
+ # Valid HTML 5 elements requiring a closing tag.
+ # Note: the `var` element is out for obvious reasons, please use `tag 'var'`.
+ regular: '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
+ fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup
+ html i iframe ins kbd label legend li map mark menu meter nav noscript object
+ ol optgroup option output p pre progress q rp rt ruby s samp script section
+ select small span strong style sub summary sup table tbody td textarea tfoot
+ th thead time title tr u ul video'
+
+ # Valid self-closing HTML 5 elements.
+ void: 'area base br col command embed hr img input keygen link meta param
+ source track wbr'
+
+ obsolete: 'applet acronym bgsound dir frameset noframes isindex listing
+ nextid noembed plaintext rb strike xmp big blink center font marquee multicol
+ nobr spacer tt'
+
+ obsolete_void: 'basefont frame'
+
+# Create a unique list of element names merging the desired groups.
+merge_elements = (args...) ->
+ result = []
+ for a in args
+ for element in elements[a].split ' '
+ result.push element unless element in result
+ result
+
+# Public/customizable list of possible elements.
+# For each name in this list that is also present in the input template code,
+# a function with the same name will be added to the compiled template.
+coffeekup.tags = merge_elements 'regular', 'obsolete', 'void', 'obsolete_void'
+
+# Public/customizable list of elements that should be rendered self-closed.
+coffeekup.self_closing = merge_elements 'void', 'obsolete_void'
+
+# This is the basic material from which compiled templates will be formed.
+# It will be manipulated in its string form at the `coffeekup.compile` function
+# to generate the final template function.
+skeleton = (data = {}) ->
+ # Whether to generate formatted HTML with indentation and line breaks, or
+ # just the natural "faux-minified" output.
+ data.format ?= off
+
+ # Whether to autoescape all content or let you handle it on a case by case
+ # basis with the `h` function.
+ data.autoescape ?= off
+
+ # Internal CoffeeKup stuff.
+ __ck =
+ buffer: []
+
+ esc: (txt) ->
+ if data.autoescape then h(txt) else String(txt)
+
+ tabs: 0
+
+ repeat: (string, count) -> Array(count + 1).join string
+
+ indent: -> text @repeat(' ', @tabs) if data.format
+
+ # Adapter to keep the builtin tag functions DRY.
+ tag: (name, args) ->
+ combo = [name]
+ combo.push i for i in args
+ tag.apply data, combo
+
+ render_idclass: (str) ->
+ classes = []
+
+ for i in str.split '.'
+ if '#' in i
+ id = i.replace '#', ''
+ else
+ classes.push i unless i is ''
+
+ text " id=\"#{id}\"" if id
+
+ if classes.length > 0
+ text " class=\""
+ for c in classes
+ text ' ' unless c is classes[0]
+ text c
+ text '"'
+
+ render_attrs: (obj, prefix = '') ->
+ for k, v of obj
+ # `true` is rendered as `selected="selected"`.
+ v = k if typeof v is 'boolean' and v
+
+ # Functions are rendered in an executable form.
+ v = "(#{v}).call(this);" if typeof v is 'function'
+
+ # Prefixed attribute.
+ if typeof v is 'object' and v not instanceof Array
+ # `data: {icon: 'foo'}` is rendered as `data-icon="foo"`.
+ @render_attrs(v, prefix + k + '-')
+ # `undefined`, `false` and `null` result in the attribute not being rendered.
+ else if v
+ # strings, numbers, arrays and functions are rendered "as is".
+ text " #{prefix + k}=\"#{@esc(v)}\""
+
+ render_contents: (contents) ->
+ switch typeof contents
+ when 'string', 'number', 'boolean'
+ text @esc(contents)
+ when 'function'
+ text '\n' if data.format
+ @tabs++
+ result = contents.call data
+ if typeof result is 'string'
+ @indent()
+ text @esc(result)
+ text '\n' if data.format
+ @tabs--
+ @indent()
+
+ render_tag: (name, idclass, attrs, contents) ->
+ @indent()
+
+ text "<#{name}"
+ @render_idclass(idclass) if idclass
+ @render_attrs(attrs) if attrs
+
+ if name in @self_closing
+ text ' />'
+ text '\n' if data.format
+ else
+ text '>'
+
+ @render_contents(contents)
+
+ text "#{name}>"
+ text '\n' if data.format
+
+ null
+
+ tag = (name, args...) ->
+ for a in args
+ switch typeof a
+ when 'function'
+ contents = a
+ when 'object'
+ attrs = a
+ when 'number', 'boolean'
+ contents = a
+ when 'string'
+ if args.length is 1
+ contents = a
+ else
+ if a is args[0]
+ idclass = a
+ else
+ contents = a
+
+ __ck.render_tag(name, idclass, attrs, contents)
+
+ yield = (f) ->
+ temp_buffer = []
+ old_buffer = __ck.buffer
+ __ck.buffer = temp_buffer
+ f()
+ __ck.buffer = old_buffer
+ temp_buffer.join ''
+
+ h = (txt) ->
+ String(txt).replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+
+ doctype = (type = 'default') ->
+ text __ck.doctypes[type]
+ text '\n' if data.format
+
+ text = (txt) ->
+ __ck.buffer.push String(txt)
+ null
+
+ comment = (cmt) ->
+ text ""
+ text '\n' if data.format
+
+ coffeescript = (param) ->
+ switch typeof param
+ # `coffeescript -> alert 'hi'` becomes:
+ # ``
+ when 'function'
+ script "#{__ck.coffeescript_helpers}(#{param}).call(this);"
+ # `coffeescript "alert 'hi'"` becomes:
+ # ``
+ when 'string'
+ script type: 'text/coffeescript', -> param
+ # `coffeescript src: 'script.coffee'` becomes:
+ # ``
+ when 'object'
+ param.type = 'text/coffeescript'
+ script param
+
+ # Conditional IE comments.
+ ie = (condition, contents) ->
+ __ck.indent()
+
+ text ""
+ text '\n' if data.format
+
+ null
+
+# Stringify the skeleton and unwrap it from its enclosing `function(){}`, then
+# add the CoffeeScript helpers.
+skeleton = String(skeleton)
+ .replace(/function\s*\(.*\)\s*\{/, '')
+ .replace(/return null;\s*\}$/, '')
+
+skeleton = coffeescript_helpers + skeleton
+
+# Compiles a template into a standalone JavaScript function.
+coffeekup.compile = (template, options = {}) ->
+ # The template can be provided as either a function or a CoffeeScript string
+ # (in the latter case, the CoffeeScript compiler must be available).
+ if typeof template is 'function' then template = String(template)
+ else if typeof template is 'string' and coffee?
+ template = coffee.compile template, bare: yes
+ template = "function(){#{template}}"
+
+ # If an object `hardcode` is provided, insert the stringified value
+ # of each variable directly in the function body. This is a less flexible but
+ # faster alternative to the standard method of using `with` (see below).
+ hardcoded_locals = ''
+
+ if options.hardcode
+ for k, v of options.hardcode
+ if typeof v is 'function'
+ # Make sure these functions have access to `data` as `@/this`.
+ hardcoded_locals += "var #{k} = function(){return (#{v}).apply(data, arguments);};"
+ else hardcoded_locals += "var #{k} = #{JSON.stringify v};"
+
+ # Add a function for each tag this template references. We don't want to have
+ # all hundred-odd tags wasting space in the compiled function.
+ tag_functions = ''
+ tags_used = []
+
+ for t in coffeekup.tags
+ if template.indexOf(t) > -1 or hardcoded_locals.indexOf(t) > -1
+ tags_used.push t
+
+ tag_functions += "var #{tags_used.join ','};"
+ for t in tags_used
+ tag_functions += "#{t} = function(){return __ck.tag('#{t}', arguments);};"
+
+ # Main function assembly.
+ code = tag_functions + hardcoded_locals + skeleton
+
+ code += "__ck.doctypes = #{JSON.stringify coffeekup.doctypes};"
+ code += "__ck.coffeescript_helpers = #{JSON.stringify coffeescript_helpers};"
+ code += "__ck.self_closing = #{JSON.stringify coffeekup.self_closing};"
+
+ # If `locals` is set, wrap the template inside a `with` block. This is the
+ # most flexible but slower approach to specifying local variables.
+ code += 'with(data.locals){' if options.locals
+ code += "(#{template}).call(data);"
+ code += '}' if options.locals
+ code += "return __ck.buffer.join('');"
+
+ new Function('data', code)
+
+cache = {}
+
+# Template in, HTML out. Accepts functions or strings as does `coffeekup.compile`.
+#
+# Accepts an option `cache`, by default `false`. If set to `false` templates will
+# be recompiled each time.
+#
+# `options` is just a convenience parameter to pass options separately from the
+# data, but the two will be merged and passed down to the compiler (which uses
+# `locals` and `hardcode`), and the template (which understands `locals`, `format`
+# and `autoescape`).
+coffeekup.render = (template, data = {}, options = {}) ->
+ data[k] = v for k, v of options
+ data.cache ?= off
+
+ if data.cache and cache[template]? then tpl = cache[template]
+ else if data.cache then tpl = cache[template] = coffeekup.compile(template, data)
+ else tpl = coffeekup.compile(template, data)
+ tpl(data)
+
+unless window?
+ coffeekup.adapters =
+ # Legacy adapters for when CoffeeKup expected data in the `context` attribute.
+ simple: coffeekup.render
+ meryl: coffeekup.render
+
+ express:
+ TemplateError: class extends Error
+ constructor: (@message) ->
+ Error.call this, @message
+ Error.captureStackTrace this, arguments.callee
+ name: 'TemplateError'
+
+ compile: (template, data) ->
+ # Allows `partial 'foo'` instead of `text @partial 'foo'`.
+ data.hardcode ?= {}
+ data.hardcode.partial = ->
+ text @partial.apply @, arguments
+
+ TemplateError = @TemplateError
+ try tpl = coffeekup.compile(template, data)
+ catch e then throw new TemplateError "Error compiling #{data.filename}: #{e.message}"
+
+ return ->
+ try tpl arguments...
+ catch e then throw new TemplateError "Error rendering #{data.filename}: #{e.message}"