☕ CupOfJoe ☕
Table of Contents generated with DocToc
Work in Progress
Motivation
- Provide a straightforward way to leverage CoffeeScript syntax to build templates for languages like HTML
- without the magic involved in earlier approaches
- building on generic structures
- that are adaptable to a number of usages
- for example, to output a particular flavor of HTML
- own syntaxes may be defined by subclassing
CupOfJoe
Sample Applications
Notes
- Three steps:
- structure building
- structure expansion
- structure formatting
- good strategy to rather build one or more dedicated structure builders ('crammers') than to put too much logic into structure formatting
- structure expansion will elide all
null
s andundefined
s - may not use async functions, promises; everything is synchronous
- basic idea is building a list of nested lists
any argument to a call to
cram()
may be a function which will be called w/out arguments; if that function returns w/out havingcram()
med anything, its return value will be crammed unless it isnull
orundefined
(Note: might allownull
s in the future)do not write
# (A) c.cram 'p', -> # ^^^^^^ 1 c.cram null, "It is very ", ( c.cram 'em', "convenient" ), " to write" # ^^^^^^ 3 ^^^^^^ 2
do write
# (B) c.cram 'p', -> # ^^^^^^ 1 c.cram null, "It is very ", ( -> c.cram 'em', "convenient" ), " to write" # ^^^^^^ 2 ^^^^^^ 3
This is because in order to call a function, its arguments must first be evaluated, so calling order is (as indicated by the numbers in
(A)
) not in the order the function calls appear in the text (maybe a good argument [pun intended] in favor of Reverse Polish Notation).
(Almost) A Two-Dimensional Syntax (in a way)
cupofjoe = new ( require 'cupofjoe' ).Cupofjoe()
{ cram, expand } = cupofjoe.export()
cram 'two', 'three', 'four'
expand()
# => [ [ 'two', 'three', 'four', ], ]
cupofjoe = new ( require 'cupofjoe' ).Cupofjoe()
{ cram, expand } = cupofjoe.export()
cram 'two', ->
cram 'three'
cram 'four'
expand()
# => [ [ 'two', 'three', 'four', ], ]
Building Structures with Derived Crammers
cupofjoe = new ( require 'cupofjoe' ).Cupofjoe { flatten: true, }
{ cram, expand } = cupofjoe.export()
h = ( tagname, content... ) ->
return cram content... if ( not tagname? ) or ( tagname is 'text' )
return cram "<#{tagname}/>" if content.length is 0
return cram "<#{tagname}>", content..., "</#{tagname}>"
h 'paper', ->
h 'article', ->
h 'title', "Some Thoughts on Nested Data Structures"
h 'par', ->
h 'text', "An interesting "
h 'em', "fact"
h 'text', " about CupOfJoe is that you "
h 'em', "can"
h 'text', " nest with both sequences and function calls."
h 'conclusion', ->
h 'text', "With CupOfJoe, you don't need brackets."
html = expand().join ''
Output (reformatted for readability):
<paper>
<article>
<title>Some Thoughts on Nested Data Structures</title>
<par>
An interesting <em>fact</em> about CupOfJoe is that you
<em>can</em> nest with both sequences and function calls.
</par>
</article>
<conclusion>With CupOfJoe, you don't need brackets.</conclusion>
</paper>
Legacy
Markaby
⇓
CoffeeKup
⇓
CoffeeCup DryKup => kup
⇓
Teacup
⇓
CoffeNode-Teacup
⇓
CupOfJoe
kup
- https://github.com/snd/kup
- forget underpowered template languages - build HTML with the full power of coffeescript
DryKup
- https://github.com/mark-hahn/drykup
- A CoffeScript html generator compatible with CoffeeKup but without the magic.