An element that contains another element isn't a function. I don't see any reason to make it one.
If you want a templating language, why not use one, rather than having an unnecessary 'space dash greater than' to indicate elements are contained within each other?
Element A containing Element B can be generated by function A taking Element B.
The CoffeScript program converts a set syntax/grammar into JavaScript; but the syntax is just syntax, and its clean, smart design lends itself well for compiling code other than JavaScript, just as JSON is a useful serialization format in other langs. There are benefits in using the same syntax for representing structure, content, and presentation, as long as the concerns are still properly separated.
In that line of thinking, it's also raised a new question in my mind. CoffeeKup seems to be optimized for baking logic into the template. It is not too different, but too much like most "templating" languages for me to completely get behind it.
This is however, a really cool project that's well executed. I'm just hoping that the idea of further separating logic from templates takes hold (something like mustache, perhaps).
webpage = kup.render ->
doctype 5
html ->
head ->
meta charset: 'utf-8'
title 'My drawing | My awesome website'
style '''
body {font-family: sans-serif}
header , nav, section , footer {display: block}
'''
coffeescript ->
draw = (ctx, x, y) ->
circle = (ctx, x, y) ->
ctx.beginPath()
ctx.arc x, y, 100, 0, 2*Math.PI, false
ctx.stroke()
ctx.strokeStyle = 'rgba(255,40,20,0.7)'
circle ctx, x, y
for angle in [0...2*Math.PI] by 1/3*Math.PI
circle ctx, x+100*Math.cos(angle),
y+100*Math.sin(angle)
window.onload = ->
canvas = document.getElementById 'drawCanvas'
context = canvas.getContext '2d'
draw context , 300, 200
body ->
header -> h1 'Seed of Life'
canvas id: 'drawCanvas', width: 600, height: 400
http = require 'http'
server = http.createServer (req, res) ->
show "#{req.client.remoteAddress} #{req.method} #{req.url}"
res.writeHead 200, 'Content -Type': 'text/html'
res.write webpage
res.end()
server.listen 3389
show 'Server running at'
show server.address()
Notice something missing?- There's no separate file for the HTML template
- There's no separate file for the javascript inside
- There's no separate file for the web server
It's just "node circles.coffee" and you're good to go. CoffeeKup makes this sort of one-shot webapp experiment scripts particularly easy. Now you don't need an entire folder for each of your sandbox projects.
Even more added points: it can be refactored like any other code.
edit: also, I think having one entire application expressed with only language (coffeescript vs html+css+javascript) is an advantage.
But personally, Coffeescript -> Javascript -> HTML sounds way too indirect for my taste.
I've seen this patter a few too many times at work now: the new frontend guy loves HAML, and he uses it on a project, and the next couple guys that help maintain it hate it and rewrite everything in straight up HTML.
What we actually need are editors in which you can set you language (haml, slim, less etc), and then those are compiled and saved, in realtime to html, erb, css etc.
Not having used too much Coffee Script yet, I don't know what the transformation from CS -> JS -> CS would result in, but I believe HAML -> HTML -> HAML would be pretty much 1:1, and html2haml already produces pretty much exactly the same haml I would have produced if I had done the conversion manually.
I'm interested because I was thinking about trying it. I've been wondering about the maintenance implications though.
The things I most often see people doing wrong are trying to format body text with Haml and putting excessive logic in your Haml templates (which is something to look out for anyway, even if you use erb, slim, or whatever).
Someone else comes along and has to set up a Ruby environment and learn a new syntax (for layout and templating) just to add a new element to the page. That gets frustrating really quickly.
Haml and its like are not a nightmare at all. I do appreciate the elegance of the resulting code and this offers a lot of benefits. It's just hard to get everyone to buy into it on a team.
I haven't looked at this too much, but I also find that templating languages often try to implement some elements of higher level programming languages, but often end up not having some of the features I want (I'm thinking specifically about liquid right now and it's apparent inability to let the designer declare arrays on their own, and its sort of awkward "filter" mechanism instead of just sticking to function calls, syntactically)
edit: well, actually, nevermind - now that I think about it liquid and haml/erb/etc are different things - liquid is trying to be a programming language and haml/erb are templating markups used with existing programming languages. I guess what I like about this is that it's just one consistent language - the markup parts and the dynamic parts are done via the same thing, as opposed to having a programming language embedded in a markup language
With the traction Coffeescript is getting I wouldn't be surprised to see it eventually execute directly inside v8 or similar, bypassing the javascript compilation altogether.
Although I doubt that any of the browsers will ever support it directly, porting coffeescript to run directly on top of Jaegermonkey or v8 wouldn't be too hard, since there is a direct translation from coffeescript to javascript. You would only need a new front end--if you emit Spidermonkey/Hydrogen bytecode, the relevant engine can JIT it.
On a slightly related note, a friend of mine is working on this: https://wiki.mozilla.org/DevTools/Features/SourceMap
Which, while not compiling directly, will allow you to map the generated JS directly back to the coffeescript source.
Hydrogen is not a bytecode, it is highlevel intermediate representation for optimizing compiler generated from AST. There is currently: 1) no frontend in V8 that accepts hydrogen in some serialized form; 2) no way to generate non-optimized (non-specialized) code from hydrogen which is quite crucial to make adaptive optimization pipeline running.
Also it'd be the only way for me to be sure my CS is compiled by the proper compiler version.
Taking a second look at CoffeeKup made me appreciate what the project is doing, clearly abstracting away useless syntax with the same good'ole functions.
It's also way less code than Haml. CoffeeKup's src folder is 240 lines of code.
(Nothing personal, just a reflection...)
https://github.com/jed/fab/blob/browser/demo.html
(I'm biased, but am a fan of making markup "just code".)
After opening it in Firefox, i find it ironic that something that has to do with web standards is so broken in a major browser.
<div class="content">
Please add that to the example on the landing page. renderTemplate: ->
"div":
"span .some-class":
_: ["Hello, "]
"strong #dyn_id":
_: ["#{@getName()}!"]
"subTemplate":
foo: bar
subTemplate: (args) ->
blockquote:
_: args.foo
getName: ->
"user name from DB or whatever"
(Then hand-rolled my own very simple JSON-to-HTML "renderer" in 20 minutes plus generating a CS class file to be compiled to JS for each template -- all really simple stuff.)Looks scary coming from years of HTML coding right? But HTML looked scary at first too.
Now: stylesheets are Stylus, templates and logic are CoffeeScript both server-side and client-side. I haven't been such a happy coder for a decade. Config files are a simplified Stylus/Coffee-like format that gets transformed to JSON. I'm actually using the CoffeeScript compiler here so in effect each config file gets transformed into a node.js "module". That means they could be turned into config "scripts" if necessary.
What I loved about Lisp in theory: code is data, data is code. Only the parens sucked for me. Now we're approaching this ideal again, slowly and emergently but surely. :)
So I think there is a lot of value to these hack projects even if Facebook isn't going to roll it out in it's next update.
Engineering is like art... we all look at what each other is doing, get inspired and move the entire discipline forward.
What I love about that is you never know when you are going to inspire something, not with a project, but maybe just with a particularly nice snippet of code or data model that is SO intuitive, they feel compelled to work it into something.
Equally cool, you never know when YOU will get inspired. I know I've honestly read class definitions or parser implementations that were so intuitive and elegant that I have developed a compulsion to go code something that uses the same technique because it is so pretty.
I don't know why, but I think that is what makes this line of work so great. It's technical AND artistic... and it doesn't always make practical sense ;)
...except for the problem of too many layers of indirection.—David Wheeler
Thank you for that. I've been looking for this concise a statement to make in debates I've had in the past.
This is one of the reasons I found Google's Go so refreshing, it actually removed layers of abstraction bypassing even libc while providing a clean and portable interface to write my programs. Instead of making the stack of abstractions even higher as for example Java does, they cut it to the root.
Simplicity equals elegance in my mind. If I can fit the whole product/platform in my mind, I am again powerful and not just a victim of the tyranny of over-abstraction and overwhelming APIs (yes I'm looking at you Java and C#).