Package detail

coffeecup

gradus3910.3.21

Markup as CoffeeScript.

template, view, coffeescript

readme

CoffeeCup <☕/>

Markup as CoffeeScript

This is a clone of @mauricemach CoffeeKup.

I am renaming and trying to keep this project alive.

CoffeeCup is a templating engine for node.js and browsers that lets you to write your HTML templates in 100% pure CoffeeScript.

It was created in celebration of whyday, as an application of the concept used in Markaby ("Markup as Ruby", by Tim Fletcher and why the lucky stiff) to CoffeeScript.

Here's what a template written for CoffeeCup looks like:

doctype 5
html ->
  head ->
    meta charset: 'utf-8'
    title "#{@title or 'Untitled'} | A completely plausible website"
    meta(name: 'description', content: @description) if @description?

    link rel: 'stylesheet', href: '/css/app.css'

    style '''
      body {font-family: sans-serif}
      header, nav, section, footer {display: block}
    '''

    script src: '/js/jquery.js'

    coffeescript ->
      $(document).ready ->
        alert 'Alerts suck!'
  body ->
    header ->
      h1 @title or 'Untitled'

      nav ->
        ul ->
          (li -> a href: '/', -> 'Home') unless @path is '/'
          li -> a href: '/chunky', -> 'Bacon!'
          switch @user.role
            when 'owner', 'admin'
              li -> a href: '/admin', -> 'Secret Stuff'
            when 'vip'
              li -> a href: '/vip', -> 'Exclusive Stuff'
            else
              li -> a href: '/commoners', -> 'Just Stuff'

    div '#myid.myclass.anotherclass', style: 'position: fixed', ->
      p 'Divitis kills! Inline styling too.'

    section ->
      # A helper function you built and included.
      breadcrumb separator: '>', clickable: yes

      h2 "Let's count to 10:"
      p i for i in [1..10]

      # Another hypothetical helper.
      form_to @post, ->
        textbox '#title', label: 'Title:'
        textbox '#author', label: 'Author:'
        submit 'Save'

    footer ->
      # CoffeeScript comments. Not visible in the output document.
      comment 'HTML comments.'
      p 'Bye!'

Interactive demo at coffeekup.org.

_why?

  • One language to rule them all. JavaScript is everywhere, thus so is CoffeeScript. Servers, browsers, even databases. If extending this to rendering logic and UI structure (server and client side) is desirable to you, CoffeeKup is your friend.

  • More specifically, one outstanding language. CoffeeScript is one hell of a clean, expressive, flexible and powerful language. It's hard to find such combination, especially if you need it to run in the browser too.

  • Not yet another specialized language to learn. Transferable knowledge FTW.

  • Embed your templates in CoffeeScript nicely. Templates are just functions, so they don't lose syntax highlighting and syntax checking when embedded in CoffeeScript apps.

  • Embed CoffeeScript in your templates nicely. In the same manner, you can write the contents of <script> blocks in CoffeeScript, and keep the highlighting. Perhaps more significantly, the CoffeeScript compiler doesn't have to be called just to convert these blocks to JS, as in other templating engines.

  • Extensive editor support. You benefit from the already existing list of excellent CoffeeScript text editor plugins.

  • Client-server consistency. The same template language and implementation in node.js or the browser.

  • Easily extendable into a higher level "DSL". Since all elements are just functions, it's very easy to define your own custom "tags", which will work and look the same as "native" ones.

  • HTML 5 ready. Boring legacy doctypes and elements also available.

  • Optional auto-escaping. You can also use the h helper on a case-by-case basis.

  • Optional formatting, with line breaks and indentation.

  • Pick your poison. Works with both CoffeeScript and JavaScript apps.

Why not?

CoffeeKup may not be your best choice in those cases:

  • You're after the cleanest syntax possible, above all. In this regard a specialized language such as Jade just can't be beaten.

  • You use divs and/or classes for everything. While in CoffeeKup you can do div '#id.class.class', specialized languages often have an even shorter syntax for that.

  • You want CoffeeScript for rendering logic, but you'd rather stick with HTML for markup. Then you're looking for Eco.

  • For your specific project/team/preferences, you think a limited and/or separate language for templating is actually beneficial.

Installing

Just grab node.js and npm and you're set:

npm install coffeecup

To get the coffeecup command, install it globally:

npm install coffeecup -g

Or to use the latest version:

git clone git@github.com:gradus/coffeecup.git && cd coffeecup
cake build
npm link
cd ~/myproject
npm link coffeecup

Using

cc = require 'coffeecup'

cc.render -> h1 "You can feed me templates as functions."
cc.render "h1 'Or strings. I am not too picky.'"

Defining variables:

template = ->
  h1 @title
  form method: 'post', action: 'login', ->
    textbox id: 'username'
    textbox id: 'password'
    button @title

helpers =
  textbox: (attrs) ->
    attrs.type = 'text'
    attrs.name = attrs.id
    input attrs

ck.render(template, title: 'Log In', hardcode: helpers)

Precompiling to functions:

template = ck.compile(template, locals: yes, hardcode: {zig: 'zag'})

template(foo: 'bar', locals: {ping: 'pong'})

With express:

app.set 'view engine', 'coffee'
app.register '.coffee', require('coffeecup').adapters.express

app.get '/', (req, res) ->
  # Will render views/index.coffee:
  res.render 'index', foo: 'bar'

With zappa:

get '/': ->
  @franks = ['miller', 'oz', 'sinatra', 'zappa']
  render 'index'

view index: ->
  for name in @franks
    a href: "http://en.wikipedia.org/wiki/Frank_#{name}", -> name

With meryl:

coffeekup = require 'coffeecup'

meryl.get '/', (req, resp) ->
  people = ['bob', 'alice', 'meryl']
  resp.render 'layout', content: 'index', context: {people: people}

meryl.run
  templateExt: '.coffee'
  templateFunc: coffeecup.adapters.meryl

On the browser:

<script src="template.js"></script>
<script>
  $('body').append(templates.template({foo: 'bar'}));
</script>

This is one of many browser deployment possibilities, pre-compiling your template on the server to a standalone function. To see all serving suggestions, check out regular, decaf and crème.

Command-line:

$ coffeecup -h

Usage:
  coffeecup [options] path/to/template.coffee

      --js           compile template to js function
  -n, --namespace    global object holding the templates (default: "templates")
  -w, --watch        watch templates for changes, and recompile
  -o, --output       set the directory for compiled html
  -p, --print        print the compiled html to stdout
  -f, --format       apply line breaks and indentation to html output
  -u, --utils        add helper locals (currently only "render")
  -v, --version      display CoffeeKup version
  -h, --help         display this help message

See /examples for complete versions (you have to run cake build first).

Please note that even though all examples are given in CoffeeScript, you can also use their plain JavaScript counterparts just fine.

Resources

Tools

  • html2coffeekup - Converts HTML to CoffeeKup templates.

  • htmlkup - Another HTML converter, stdin/stdout based.

  • ice - CoffeeKup and Eco in Rails (screencast).

  • coffee-world - Tool to watch and compile HTML with CoffeeKup, CSS with coffee-css and JS with CoffeeScript.

  • cupcake - Express app generator with CoffeeKup support.

Related projects

  • ck - "a smaller, faster coffeekup": Alternative, barebones implementation.

  • ckup - "Markup as Coco": Similar engine but for Coco ("Unfancy CoffeeScript").

  • Eco - "Embedded CoffeeScript templates": "EJS/ERB" for CoffeeScript.

  • timbits - "Widget framework based on Express and CoffeeScript".

  • coffee-css - "More CSS for CoffeeScript".

  • ccss - "CoffeeScript CSS".

Compatibility

Latest version tested with node 0.4.9 and CoffeeScript 1.1.1.

Special thanks

changelog

v0.3.21

  • Add support for html5 elements

v0.3.20

  • Add support for xml sitemap elements -- thanks @jking90

v0.3.19

  • Monkey patch makes "option value: '', 'title'" render correct html

v0.3.18

  • Switch coffee-script dependency expression to include minor version updates (for recent 1.4 update -- thanks @asalant)

v0.3.17

  • return compilation and render errors to express 3 (thanks @randypuro)

v0.3.16

  • Add support for Express 3 (thanks @shimaore)

v0.3.15

  • allow 0 to be rendered as value in render_attrs

v0.3.14

  • compiler Added multi-file support to the -j option (thanks @ilogico)
  • compiler --watch now works with multiple files (thanks @ilogico)

v0.3.13

  • fix ie browser issues

v0.3.12

  • add ability to support inline strings (thanks @viatropos)

v0.3.11

  • add stylus suport

v0.3.10 (2012-4-14):

  • fixed bug with switch statement

v0.3.9 (2012-4-13):

  • add stylus support (thanks @srackham)
  • locked coffeescript at 1.2.0

v0.3.6 (2012-4-01):

  • added support for SVG 1.1 tags
  • fixed Cannot find module 'optparse'
  • add uglify.js as dependency
  • add safe helper
  • works with coffeescript 1.2.x
  • works with latest stable version of node 0.6.14
  • moved skeleton into separate file
  • rewrote all tests in mocha
  • add creamer/flatiron examples

v0.3.1 (2011-09-29):

  • Fixed #71: indexOf not supported in IE7 (thanks @jaekwon).
  • Added better error reporting to express adapter. [benekastah]
  • Added yield: see /docs/reference.md. Closes #16 (thanks @pyrotechnick, @colinta and @smathy).
  • Added prefixed attributes: data: {icon: 'foo.png'} renders as data-icon="foo.png". [colinta]
  • Added functions as attribute values: onclick: -> alert 'hi'. Closes #79 (thanks @smathy).

v0.3.0 (2011-09-04):

  • Fixed #64 (hardcode option masked in express adapter). [smathy]
  • Added missing elements from the HTML 5 spec (both valid and obsolete). Closes #66 (thanks @aeosynth).
  • Added compile to js option to CLI. Closes #58. [rachel-carvalho]
  • Fixed #69 (coffeekup -w only compiles upon first change). [rachel-carvalho]

v0.3.0beta (2011-07-27):

  • Added documentation: API reference at /docs/reference.md and annotated source at /docs/coffeekup.html.

  • Added id/class shortcuts: div '#id.class.class2', 'contents' (thanks @aeosynth and @payload).

  • Added IE conditional comments: ie 'lt IE8', -> 'IE 7 or less stuff' (thanks @aeosynth).

  • Added ck.adapters.express which allows partial 'foo' instead of text @partial 'foo' - see /examples/express (thanks @cushman).

  • Added coffeescript src: 'file.coffee' and coffeescript 'string' - see reference (thanks @henrikh).

  • Changed the template param format to align with Express and other templating engines. Now tpl(foo: 'bar') makes foo accessible as h1 @foo. context is not used anymore.

  • tpl(locals: {foo: 'bar'}) now always implemented through the with keyword (past behavior with dynamic_locals: true).

  • tpl(hardcode: {foo: 'bar'}) will hardcode foo into the compiled template's body (past behavior with dynamic_locals: false).

  • Fixed: coffeescript -> code() now correctly adds CoffeeScript helpers to the output.

  • Changed: using .call(this); instead of (); in js generated by coffeescript.

  • Fixed: correctly handle numbers and booleans when used as tag contents or attribute values.

  • Fixed #50: "coffeekup -w quits on syntax error".

  • Added: doctypes now editable at coffeekup.doctypes, tags at coffeekup.tags, and self-closing tags at coffeekup.self_closing.

  • Added the ce doctype.

  • Changed: using doctypes['default'] instead of doctypes['5'] by default.

  • Changed: in coffeekup.render, option cache is now false by default.

  • Added a third optional param to render. You can pass an object with options and they will be merged with the main object param.

  • Removed ck_* locals, now all implementation inside the __ck object.

v0.2.3 (2011-05-06):

  • Compatible with npm 1.x.
  • Converting any ampersands (instead of /&(?!\w+;/) to & when escaping html.
  • New CLI option -o / --output [DIR] (specifies a directory to compile into).
  • Self-closing tags are now: 'area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'link', 'meta' and 'param'.

v0.2.2 (2011-01-05):

  • Updated to CoffeeScript 1.0.0 and node 0.2.6/0.3.3.

v0.2.1 (2010-11-23):

  • Updated to CoffeeScript 0.9.5 and node 0.2.5/0.3.1.
  • Fixed string templates compilation in opera.

v0.2.0 (2010-11-09):

  • Huge performance gains, now among the fastest. See cake benchmark.
  • Compile templates into standalone functions with coffeekup.compile.
  • Option format to add line breaks and indentation to output.
  • Escape HTML automatically with the autoescape option, or manually with the h local.
  • CLI behaviour closer to CoffeeScript's: compiles to filename.html by default, can watch and recompile with -w.
  • CLI -u/--utils option to make build-time utility locals available to templates (currently only render).