GithubHelp home page GithubHelp logo

coffeekup's Introduction

CoffeeKup <☕/>

Markup as CoffeeScript

CoffeeKup 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 CoffeeKup 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 coffeekup

To get the coffeekup command, install it globally:

npm install coffeekup -g

Or to use the latest version:

git clone [email protected]:mauricemach/coffeekup.git && cd coffeekup
cake build
npm link
cd ~/myproject
npm link coffeekup

Using

ck = require 'coffeekup'

ck.render -> h1 "You can feed me templates as functions."
ck.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('coffeekup').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 'coffeekup'

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

meryl.run
  templateExt: '.coffee'
  templateFunc: coffeekup.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:

$ coffeekup -h

Usage:
  coffeekup [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

coffeekup's People

Contributors

aeosynth avatar benekastah avatar brandonbloom avatar colinta avatar dvv avatar esamattis avatar mauricemach avatar mwl avatar rachel-carvalho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coffeekup's Issues

How to do subroutines?

I want to do something like this ...

labelAndInput = (lbl) -> 
    div lbl
    input type:text

template = ->
    div ->
        labelAndInput "hello"
        labelAndInput "world"

Everything I try is failing because of the lack of closure. Maybe I've just gotten so used to closures I've forgotten how to program without them. How do others accomplish this?

caching.

looks like expressjs is caching incorrectly -- it won't re-render the page with new data.

Beginner's Introduction To CoffeeKup

I bitched in an earlier thread that I couldn't find any docs to learn CoffeeKup. I offered to write some docs if anyone helped. Well I've decided to go ahead and write something and hope some of you help as I go along.

I've finished the first section. Please check it out at https://github.com/mark-hahn/coffeekup-intro. I am writing this as I figure out CoffeeKup so what you see is what I've learned so far. I will announce here when each section is finished unless someone objects. I will probably have a new section every couple of days

Please post your comments as issues on that project or as replies here and I will copy the reply comment over. Please be brutal in your comments. If you think it is boring, wrong, etc. just say so. Compliments will also be accepted.

layout.coffee?

Error: EBADF, Bad file descriptor '/Users/tyler/instantcoffee/views/layout.coffee'

why is it asking for layout.coffee?

JS error on coffeekup.org

Uncaught Error: When creating object "editor", there is no factory called "text_editor" available."
BespinEmbedded.js:7875

UserAgent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.28 Safari/534.10

Hope that helps

Allow parsing of XML files

It would be cool to use Coffeekup also for XML files (e.g. RSS or ATOM).
Because of the tag checking, this currently does not work:

doctype 'xml'
rss(version: '2.0') ->
  channel ->
    title 'Title'
    link 'URL'
    description '…'

    item ->
      title '…'
      link '…'

"coffeekup -w" quits on syntax error

this invocation should report the error and then go back into the watching state instead of bailing out completely. Some of us make syntax errors occasionally :)

Dynamic view helpers from express

Because of the eval-ing going on, I don't think dynamic view helpers can access stuff they'd normally be able to access, preventing me from using the default CSRF express tools w/ Coffeekup.

I'm going to probably write my own middleware as a result.

class / id shortcuts

Are you planning on adding hash (#) and dot (.) as id / class shortcuts? Although hash might not work since that's coffeescript's comment character.

dynamic_locals not documented

I think I had to use dynamic_locals to get locals to work correctly with recursion. Does this ring a bell?

Anyways, I found a nifty option parameter that did the trick, so I figured this would be nice in the docs.

I'm compiling coffee on the server side (@1.0.0) and running CK on the client.

Streaming able ?

Correct me if I'm wrong.

As far as I can tell CoffeeKup will never be able to stream the template results because to be able to return the results the top level function must return, and that happens only when all the template finished computing.

Is there anything that can be done to enable streaming support? Will CoffeeKup ever be able to stream results?

self closing / obsolete tags

hello, I'm playing around with a ck rewrite, and I wanted to get everything correct this time so I went looking at the official sources. my results:

void (self closing)

area base br col command embed hr img input keygen link meta param source track wbr

complete set of elements, minus self closing

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 var video

obsolete

applet acronym bgsound dir frame frameset noframes isindex listing nextid noembed plaintext rb strike xmp basefont big blink center font marquee multicol nobr spacer tt

precompilation to function: (locals) -> html

Hi! Good work. I like this philosophy.
I would like to use Coffeekup on clientside with Sammy framework, but precompiling coffekup templates on server to pure functions like in haml-js:
Haml(haml) -> template(locals) -> html.
Is it possible?

the 'h' function

/&(?!\w+;)/g should be replaced with /&/g in the 'h' function.

the current implementation will lead to strange bugs and possibly fringe security issues.

Not working on 0.4.0

Tried on fresh ubuntu 10.10 using node.js 0.4.0, installed with npm.
Running $coffeekup fails with this:
Error: Cannot find module 'coffeekup'
at Function._resolveFilename (module.js:289:11)
at Function._load (module.js:241:25)
at require (module.js:317:19)
at Object. (/usr/local/lib/node/.npm/coffeekup/0.2.2/package/bin/coffeekup.coffee:3:15)
at Object. (/usr/local/lib/node/.npm/coffeekup/0.2.2/package/bin/coffeekup.coffee:76:4)
at Module._compile (module.js:373:26)
at Object.run (/usr/local/lib/node/.npm/coffee-script/1.0.1/package/lib/coffee-script.js:55:19)
at /usr/local/lib/node/.npm/coffee-script/1.0.1/package/lib/command.js:115:29
at /usr/local/lib/node/.npm/coffee-script/1.0.1/package/lib/command.js:85:26
at [object Object]. (fs.js:86:5)

Trying to require it as module gives similar output.

@body undefined in context

Hi,
first of all, thanks for coffeekup!
I created a small express project with coffeekup templates. It works fine, except that @Body is always undefined in the layout.coffee context.

I'm using express 1.0.7, coffeescript 1.0.1 and coffeekup 0.2.2

Howto mix tags and text?

Hi,
If i write

p ->
    "You can redistribute it and/or modify it under the terms of the "
    a href: "http://www.gnu.org/licenses/agpl-3.0.html", rel: "license", -> "GNU Affero General Public License"
    "."

I get

<p><a href="http://www.gnu.org/licenses/agpl-3.0.html" rel="license">GNU Affero General Public License</a>.</p>

As you can see, the first string gets lost somewhere. As inline links are a quite common thing, i wonder if there is a way to do this in coffescript?

thanks

Nesting divs on occasion?

I couldn't figure out an elegant way to pull this off. Is there a better way?

My goal is to create rows. I'm doing this within a larger for loop, looping over an array of objects.

for item in items
    i++
    if i is 1
        text "<div class='row'>"

    div ".item #{sizeClass}" + (if i % itemsPerRow is 0 then ".last" else ""), ->
            a href:"#", class: "bigButton", -> item.name

    if i % itemsPerRow is 0
        text "</div><div class='row'>"
    else if items.length is i
        text "</div>"

Extension mechanism

Provide a sort of plugin system so that people can develop extensions that can be distributed and consumed easily.

cannot render layouts

I cannot get layouts to render. It finds the views/layout.coffee file, but errors with:

TypeError: string is not a function
at String.CALL_NON_FUNCTION (native)
at Object.anonymous (eval at (/usr/local/lib/node/.npm/coffeekup/0.1.7/package/lib/coffeekup.js:139:25))
at Object.render (/usr/local/lib/node/.npm/coffeekup/0.1.7/package/lib/coffeekup.js:144:21)
at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.0rc4/package/lib/express/view.js:293:26)
at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.0rc4/package/lib/express/view.js:303:14)
at Object. (server.coffee (compiled):33:16)
at pass (/usr/local/lib/node/.npm/connect/0.2.7/package/lib/connect/middleware/router.js:72:27)
at Object.router as handle
at next (/usr/local/lib/node/.npm/connect/0.2.7/package/lib/connect/index.js:264:23)
at /usr/local/lib/node/.npm/connect/0.2.7/package/lib/connect/middleware/session.js:140:15

Support interpolated CoffeeKup

h2 -> "Spinning the #{span -> 'Real-time'} Web"

currently compiles to

<h2><span>Real-time</span>Spinning the null Web</h2>

It would be nice to support this as I often find myself wanting to "span" things up within long paragraphs without breaking it up too much.

__bind not generated in coffeescript

In my coffeescript code, within my coffeekup template, => does not generate the __bind function within the script tag.

For example:

coffeescript ->
    foo = ->
        bar = 1
        baz = =>
            console.log bar

    foo().baz()

Exception thrown is Uncaught ReferenceError: __bind is not defined

The output is

;(function () {
    var foo;
    foo = function() {
        var bar, baz;
        bar = 1;
        return baz = __bind(function() {
            return console.log(bar);
        }, this);
    };
    return foo().baz();
})();

Compile on the fly

Hi,

Do you think it is possible to have coffekup compile automatically like coffee -cw ?
I also would like to know if it is possible in this way to render template in a template ?

e.g :
html ->
head ->
@render 'mytemplate.coffee'

Many thanks for coffeekup

Samuel

`hardcode` option masked in express adapter

The code to allow partial 'view' instead of requiring text @partial 'view' overwrites the options.hardcode hash, so if you have other helpers that you want to pass in from express/zappa then you can't.

Patch coming.

Helper bug: ck_repeat

Check helper in IE. As far as I can remember Array(count).join(string) different in different browsers:

ck_repeat = function(string, count) {
  return Array(count + 1).join(string);
}; 

noWrap

Please, replace 'noWrap' with wrap: false to obey the recent changes to coffeescript

html5 input required syntax

Hey guys

this might be an issue with me not knowing coffeescript syntax properly yet (or coffeekup), but here's my question:

I'm playing with html5 forms (http://diveintohtml5.org/forms.html), and want to play with features like "required" in

input id: 'q' #works fine
but how do I add a value-less parameter like "required"?

I've tried:
input id: 'q', required: '' # <- with an empty string
But coffeekup ignores the required parameter

Thanks for the help & coffeekup, coffeescript, mongoose, express, node are all blowing my mind!

Word "input" prevents rendering.

If the word "input" is used anywhere in a template, rendering any passed variables (local or context) fail.

I believe this stems from this commit, where you changed the word "data" to "input".

03d0155

previously:

So I have a var called @person with a bunch of details, like "firstname" for instance.

If I use this code:
p @person.firstname

The text correctly outputs the firstname. If I add a form in, like this:

p @person.firstname
form name: "input"

then I get an error:
TypeError: Cannot read property 'firstname' of undefined
at Function. (eval at (/home/hosting/checkoutly/code/node_modules/coffeekup/lib/coffeekup.js:303:12))
at Object.anonymous (eval at (/home/hosting/checkoutly/code/node_modules/coffeekup/lib/coffeekup.js:303:12))

-> everywhere is ugly

don't you think so? can't we a) use indentation and b) use some other symbol when we can't get by with indentation alone?

Where are the docs?

CK looks nice. I'd really like to try it but I can't find docs anywhere. My google searches reached some discussion that mentions the docs.

Some help?

Parsing error

h2 ->
  h3 -> 'foo'
  'bar'

correctly gives:

<h2>
  <h3>
    foo
  </h3>
  bar
</h2>

but when the text is placed first:

h2 ->
  'bar'
  h3 -> 'foo'

it does not appear in the output:

<h2>
  <h3>
    foo
  </h3>
</h2>

CoffeeKup Syntax Highlighting

I don't see any coffeekup specific syntax highlighters for any editor. Are their any available? Sorry if this is wrong place to post this, didn't see anywhere else more appropriate.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.