# mark-hahn/coffeekup-intro

### Subversion checkout URL

You can clone with
or
.

# Changes for compatibility with pandoc to typeset pdf#4

Merged
merged 1 commit into from
+397 −15

### 2 participants

An attempt at a design (in the tex template) giving a pdf version of the introduction.
If you like it then I would like to link to it from the next revision of 'Smooth CoffeeScript'.

What's changed?

The spaces between ] and ( in links was removed. The spelling of Beginner's was changed to the more common form. Extra indentation was removed from one section and line breaks were inserted were the code sections would go beyond the margin.

Edit ,s/] (/](/g
Edit ,s/s's/'s/
Edit 108,112x/^ /c/ /
Edit 178 s/->/->\n /
Edit 55#52i/\n /
Edit 52#52i/\n /
Edit 45#54i/\n /
Edit 41#52i/\n /

The text is typeset with XeTeX using {Handwriting - Dakota} for headers, the body is in {Kozuka Gothic Pro}, and the code is rendered with {Inconsolata} --- all using a 10 point base to keep formatting issues to a minimum.

Edit ,>os bash --login -c 'markdown2pdf --strict --xetex --listings --template=/Users/eh/projects/coffeescript/coffeekup-template.tex -o coffeekup-intro.pdf 2>/dev/null; open coffeekup-intro.pdf'

If you like then you can also render the text as HTML:

Edit ,>os bash --login -c 'pandoc -f markdown -t html -s -o /tmp/test.html; open /tmp/test.html'

Hope you enjoy and feel free to change anything. You can consider my contribution to be in the public domain.

 autotelicum A pandoc compatible version for typeset pdf See coffeekup-intro-pandoc/coffeekup-notes ca034a2
merged commit 8c64e4b into mark-hahn:master
Owner

Thanks. How do you think I should publish it so you can link to it? Coffeekup wiki?

If you are happy with it as it is, then I can link directly to where it is now from the smooth website and from the text in the book:

A Beginner's Introduction to CoffeeKup by Mark Hahn

I think that would work with minimal maintenance. It is quite easy to make changes to the layout now I got a tex template for pandoc, much easier than lyx. So let me know if you would like anything different.

Commits on Sep 28, 2011
1. autotelicum authored
See coffeekup-intro-pandoc/coffeekup-notes
+ style="width:100px, height:100px, background-color: + purple, border: 5px green">
Any object (aka hash) used as an argument to a tag function is interpreted as a set of attributes. The hash keys are the attribute names and the hash values are the attribute values. In CoffeeScript hashes are created easily and they are perfect for CoffeeKup's attributes. Let's look at this more complicated example which ties everything we know together ... - div id:"another-ugly-box", style:"background-color: purple, border: 5px yellow", -> + div id:"another-ugly-box", style:"background-color: + purple, border: 5px yellow", -> span color:"green", "And I'm ugly text" -
+
And I'm ugly text
@@ -105,11 +109,11 @@ Cool Formatting If you are fluent in CoffeeScript, then this will be obvious, but there are cool ways to clean up the last example. There are two or three CoffeeScript features that can be used to turn the four-line example above into this one-liner ... - p "I want #{i} hamburgers" for i in [2..4] unless false - -

I want 2 hamburgers

-

I want 3 hamburgers

-

I want 4 hamburgers

+ p "I want #{i} hamburgers" for i in [2..4] unless false + +

I want 2 hamburgers

+

I want 3 hamburgers

+

I want 4 hamburgers

If you don't see how this works, then go do the next lesson in your CoffeeScript class. We'll be waiting here until you get back. @@ -175,7 +179,8 @@ So putting it all together (in the browser) ... Or if you are maniac who likes unreadable source files ... coffeekup = window.CoffeeKup - $('body').append coffeekup.render -> div style:'font-size:96px', 'Hello World' +$('body').append coffeekup.render -> + div style:'font-size:96px', 'Hello World' This tiny code will display those giant words. You might wonder though, how can we use the div function when it was never defined? Surely it isn't defined as a global by CoffeeKup? That would be uncool, and to be proper coding style it would need to be coffeekup.div, which kind of defeats the purpose of CoffeeKup. It also can't be a local which would have required an eval somewhere. @@ -244,9 +249,8 @@ No, seriously, I don't know what these are. (I do know who Zappa was. He was on Where To Go From Here --- -I'm sure I've missed some topics other than just helpers. Leave an issue on [this github] (https://github.com/mark-hahn/coffeekup-intro) if you think of any. Meanwhile, to keep up on the latest CoffeeKup developments, check in on CoffeeKup's [github page] (https://github.com/mauricemach/coffeekup). As I said before, currently the only discussion of CoffeeKup is on CoffeeKup's [issues page] (https://github.com/mauricemach/coffeekup/issues?sort=created&direction=desc). Someone should create a Google Group for CoffeeKup. +I'm sure I've missed some topics other than just helpers. Leave an issue on [this github](https://github.com/mark-hahn/coffeekup-intro) if you think of any. Meanwhile, to keep up on the latest CoffeeKup developments, check in on CoffeeKup's [github page](https://github.com/mauricemach/coffeekup). As I said before, currently the only discussion of CoffeeKup is on CoffeeKup's [issues page](https://github.com/mauricemach/coffeekup/issues?sort=created&direction=desc). Someone should create a Google Group for CoffeeKup. Credit Where Credit Is Due --- -Of course the most credit goes to Maurice Machado, aka [mauricemach] (https://github.com/mauricemach) who wrote CoffeeKup. Maurice (and we) are indebted to Tim Fletcher and Why The Lucky Stiff who wrote Markaby ("Markup as Ruby"), the predecessor and inspiration for CoffeeKup. Thanks to Loren Sands-Ramshaw for a clean-up pass. You can add yourself to this list by helping with this document. All it takes is a spelling correction. My biggest spelling correction came from Maurice, who pointed out that I spelled CoffeeKup as KoffeeKup everywhere. It figures that I'd mispell the thing I'm writing about. - +Of course the most credit goes to Maurice Machado, aka [mauricemach](https://github.com/mauricemach) who wrote CoffeeKup. Maurice (and we) are indebted to Tim Fletcher and Why The Lucky Stiff who wrote Markaby ("Markup as Ruby"), the predecessor and inspiration for CoffeeKup. Thanks to Loren Sands-Ramshaw for a clean-up pass. You can add yourself to this list by helping with this document. All it takes is a spelling correction. My biggest spelling correction came from Maurice, who pointed out that I spelled CoffeeKup as KoffeeKup everywhere. It figures that I'd mispell the thing I'm writing about.
183 coffeekup-intro-pandoc/coffeekup-intro.html
 @@ -0,0 +1,183 @@ + + + + + + + + +

A Beginner's Introduction to CoffeeKup

+

By Mark Hahn

+

CoffeeKup uses a simple scheme to provide a concise, expressive, easy-to-read, and time-saving HTML templating solution. It is based on the CoffeeScript language, with which you will need to be familiar. If you aren't already hooked on CoffeeScript then visit http://coffeescript.org first to find out what you are missing. Then come back here to also get hooked on CoffeeKup.

+

This introduction is for CoffeeKup beginners like myself (I'm learning it as I write this). Let's go through this together step by step. Once you complete this I suggest you go to CoffeeKup's github page to learn more. Currently the only discussion of CoffeeKup is on CoffeeKup's issues page.

+

Unlike most tutorials I will not need to help you install CoffeeKup to follow along with the examples. I will give the results of the template with each example. You might also want to bring up http://coffeekup.org in another window and paste these examples into the left pane. This will allow you to play around with the template and see the results immediately. (This also makes a great tool to use while you are writing your own CoffeeKup code).

+

Let's Get Started - Hello World

+

First our mandatory friend, Hello World. In each example the CoffeeKup template code appears first followed by the rendered HTML.

+
+    title 'Hello World'
+body ->
+
+    <title>Hello World</title>
+<body>
+</body>
+
+

First of all, note that the template code is real CoffeeScript code. CoffeeKup is CoffeeScript. Except for some important CoffeeScript code added invisibly to the top and bottom of the template, the CoffeeScript you write in the template is executed directly to render the output. This is very different from most template engines and is the reason CoffeeKup offers all the great features mentioned at the beginning.

+

So how did head -> become <head>? And where does the output come from? There is nothing like a write function in the template to send out the results. And how did </head> appear out of thin air? The secret ingredient in the coffee recipe is the extra code that was mentioned above.

+

The top part of the added code defines a lot of things, the most important of which are the functions who share their names with all the possible HTML tags. These functions, when executed, generate the associated HTML code and append it to a buffer, also defined in the invisible code, that accumulates all of the output HTML. When all of your template code has been executed, the buffer containing the complete HTML is then returned as output by an invisible return buffer statement added to the bottom of the template.

+

Let's walk through the execution of the Hello World template code. First the head function is called with one argument, a one-line function that calls title. The head function adds the <head> text to the buffer, then calls the title function which adds it's own HTML to the buffer, and finally adds the closing </head>.

+

The title function was called with "Hello World" as its only argument. In a case like this, the function only had to wrap <title> and </title> around the string it was passed and add the whole thing to the buffer. The body function did the same thing as the head function except that the function passed to it added nothing to the output buffer.

+

So the "tag" functions create all the resulting HTML by adding their arguments to the output buffer while executing the function arguments to create the nesting. Quite elegant, yes?

+

+

We know how to insert anything we want for the inner HTML of a tag. We need only include an arbitrary string as an argument to the tag function. But how do you put attributes inside the tag itself? Luckily that is very easy. Check this out ...

+
div id:"ugly-box", style:"width:90px, height:90px,
+         background-color: purple, border: 5px green"
+
+<div id="ugly-box"
+     style="width:100px, height:100px, background-color:
+         purple, border: 5px green">
+</div>
+
+

Any object (aka hash) used as an argument to a tag function is interpreted as a set of attributes. The hash keys are the attribute names and the hash values are the attribute values. In CoffeeScript hashes are created easily and they are perfect for CoffeeKup's attributes.

+

Let's look at this more complicated example which ties everything we know together ...

+
div id:"another-ugly-box", style:"background-color:
+     purple, border: 5px yellow", ->
+    span color:"green", "And I'm ugly text"
+
+<div id="another-ugly-box" style="background-color:
+     purple, border: 5px yellow">
+  <span color="green">And I'm ugly text</span>
+</div>
+
+

Now it is starting to look like real HTML you'd find on an ugly web page.

+

Lonely Text

+

At this point in my use of CoffeeKup I was starting to think I knew how to generate any HTML, but then I ran into a stumbling block. I needed to put some text between tags and not inside a tag. This is a hole in the CoffeeKup logic described so far, but the hole has been filled with a fake tag named text ...

+
span color:"red", "I'm bright red!"
+text "I'm boring black"
+span color:"blue", "I'm feeling blue"
+
+<span color="red">I'm bright red!</span>
+I'm boring black
+<span color="blue">I'm feeling blue</span>
+
+

The text tag (function) just adds whatever text is in its string argument to the output buffer. If we removed text from the beginning of the middle line, that line with only the string would be legal CoffeeScript, and the template would execute without error, but the text would be lost because there would be no function to add it to the output buffer.

+

Before we leave the discussion of general text I'd like to point something out. Whether it is a string argument to a real tag like div, or a string argument to the fake text tag, a string can contain any text, even HTML. We will learn how to use this to our advantage in the section Homemade Html.

+

Variables, Conditionals, and Loops

+

If this was all there was to CoffeeKup then it would already be quite useful as a way to write all your HTML in a concise way. No more adding all those nasty closing tags. But wait, there's more ...

+

As you might have guessed, because CoffeeKup is executing arbitrary CoffeeScript code, there are a lot of fancy things we can do other than just generate static HTML. Let's look at another example ...

+
if true
+    for i in [2..4]
+        p ->
+            text "I want #{i} hamburgers"
+
+<p>I want 2 hamburgers</p>
+<p>I want 3 hamburgers</p>
+<p>I want 4 hamburgers</p>
+
+

First note that the entire snippet is conditional on the if statement evaluating to true. If you changed true to false then this example would not output anything. This is easy to understand since code must execute to add things to the output buffer. This example is good at showing how CoffeeKup is just CoffeeScript code executing with no magic happening behind the scenes, except for the magical output buffer.

+

The for loop simply executes its block of code, which happens to output a paragraph of text. It executes it three times so that block of code added its HTML to the buffer three times.

+

Note also the use of the variable i in the text string. It is evaluated and added to the string, which is called interpolation. The syntax #{i} that mixes it in is straight CoffeeScript. Once again CoffeeKup got a cool feature for free from CoffeeScript. It looks almost like a more traditional template syntax such as mustache, which would have {{i}}. Remember that this CoffeeScript interpolation only works inside double quotes ", not single.

+

Variables can be defined and used freely in your CoffeeKup template. In a later section, Keeping Things In Context, we will see that variables can be used that are defined outside of the template.

+

Cool Formatting

+

If you are fluent in CoffeeScript, then this will be obvious, but there are cool ways to clean up the last example. There are two or three CoffeeScript features that can be used to turn the four-line example above into this one-liner ...

+
p "I want #{i} hamburgers" for i in [2..4] unless false
+
+<p>I want 2 hamburgers</p>
+<p>I want 3 hamburgers</p>
+<p>I want 4 hamburgers</p>
+
+

If you don't see how this works, then go do the next lesson in your CoffeeScript class. We'll be waiting here until you get back.

+

Tag Function Conjunction

+

Let's step back and look at how tag functions work with different types of arguments.

+

There are three types of arguments that can be passed to a tag function. They are an object (hash), a function, and simple types like strings, numbers, true, false, etc. You should know by now what each one of these does ...

+
+
• object: Any object that is an argument of a tag function specifies the attributes for that tag.

• +
• function: Executes code that adds HTML to the output buffer. The tag function adds its text like <script> to the output buffer, then runs the function, and then adds its closing text like </script> afterwards. The HTML that function argument adds to the output buffer is nested inside the begin/end tags, as inner HTML. So the nesting of tag functions creates the resulting HTML nesting.

• +
• string and friends: These are all converted to strings and directly added to the output buffer. You should know that, by default, HTML entity characters are not escaped. See the Homemade Html section.

• +
+

You might be wondering what the remaining type of javascript variable, the array, does. It is treated exactly like an object, which happens to create useless attributes ...

+
div ['a','b']
+
+<div 0="a" 1="b"></div>
+
+

Maybe some smart person will figure out a cool use for arrays in CoffeeKup.

+

Cool Running

+

So great, we have this CoffeeScript that executes and produces our html. But how do we actually get this to happen in our app? It's not going to happen by itself.

+

First we need to get the CoffeeKup module loaded. CoffeeKup (actually CoffeeScript) compiles to vanilla JavaScript so it can run anywhere JavaScript is available. I've only run it in Node and the Browser so let's consider those environments. Note that the same CoffeeKup JavaScript file runs without change in either environment thanks to some fancy footwork.

+

I'll assume you know how to install CoffeeKup. You should know how to install modules in node using npm and/or in the browser using the <script> tag. Then include it in your app ...

+
# in node
+coffeekup = require 'coffeekup'
+
+# in the browser
+coffeekup = window.CoffeeKup
+
+

The coffeekup namespace object you just created has the functions you need to run and a lot of other usefull stuff as properties. Of course you can use any name for the namespace object, but we'll stick with coffeekup here.

+

Next, we need to include our CoffeeKup template. This is just a function assigned to a var. Let's use a new simpler hello world example ...

+
helloTemplate = ->
+    div style:'font-size:96px', 'Hello World'
+
+

Even people my age are going to be able to read that.

+

Now we need to execute our template function using a special function, coffeekup.render. This renders the desired html.

+
helloHtml = coffeekup.render helloTemplate
+
+

That was easy. I'm sure you can figure out how to use the html in helloHtml. In node you do something like result.write helloHtml and in the browser you can stick it in the dom (where the sun never shines), $('body').append helloHtml. This assumes jQuery is present. If you don't have jQuery then don't look to me for help. I learned jQuery at the same time I learned JavaScript so I'm useless without it. + So putting it all together (in the browser) ... + coffeekup = window.CoffeeKup +helloTemplate = -> + div style:'font-size:96px', 'Hello World' +helloHtml = coffeekup.render helloTemplate +$('body').append helloHtml
+
+

Or if you are maniac who likes unreadable source files ...

+
coffeekup = window.CoffeeKup