-
Notifications
You must be signed in to change notification settings - Fork 2
/
ckup.co
129 lines (116 loc) · 4.25 KB
/
ckup.co
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# `ckup = require \ckup` in CommonJS, `self.Ckup` in browser etc.
ckup = exports ? @Ckup = {}
ckup import
VERSION: \0.1.8
render: (template, mixin) -> @renderer(template) mixin
# Creates
renderer: (template) ->
template = @compile template unless typeof template is \function
# a renderer function that
(mixin) ~>
# clones `ckup`
me = ^this
# with optional `mixin` properties,
me <<< mixin if mixin
# `.call`s `template` on the clone,
template.call me
# and returns the rendered string.
me._
# Compiles a Coco `code` into a template function,
# enabling `@`-less style using `with` hack.
compile: (code) ->
Function 'with(this)' + (Coco ? require \coco)compile "#code"
# `@_` holds the code being built.
_: ''
# Renders an object as CSS rules a la <https://github.com/aeosynth/ccss>.
css: (rules) ->
code = ''
rules.=call this if typeof rules is \function
for selector, children in rules
children.=call this if typeof children is \function
children <<<< kv for kv of []concat that if delete children.mixin
subrules = declarations = selectors = ''
for key, val in children
switch typeof val
case \string \number
# _$_-prefixed properties are expanded as vendor-prefixed.
if (key = @decamelize key)charAt() is \$
key.=slice 1
declarations += " -#v-#key: #val;\n" for v of @VENDORS
declarations += " #key: #val;\n"
default
ss = []; selectors ||= selector.split @COMMA
ss.push "#s #k" for s of selectors for k of key.split @COMMA
(subrules ||= {})[ss.join ', '] = val
declarations and code += "#selector {\n#declarations}\n"
subrules and code += @css subrules
code
COMMA : /\s*,\s*/
VENDORS : <[ webkit moz ms o ]>
# Turns a string HTML-safe.
quote: let re = /[&<>\"\']/g
function fn
switch it
case \& then '&'
case \< then '<'
case \> then '>'
case \" then '"'
case \' then '''
-> "#it"replace re, fn
decamelize: let re = /[A-Z]/g
function fn then \- + it.toLowerCase()
-> "#it"replace re, fn
# Appends a DTD declaration.
doctype : !-> @_ += "<!DOCTYPE #it>"
# Appends a text as is.
raw : !-> @_ += it
# Appends a text node.
text : !-> @_ += @quote it
# Appends an HTML entity.
entity : !-> @_ += "&#{ if typeof it is \number then \# + it else it };"
# Builds an HTML element.
#
# - `args`: A list of element content, which can be either of
# - an object containing key-value pairs of attributes
# - a function which will be called recursively
# - any existent value
# - `tailless`: Indicates end tag omission.
element: !(name, args, tailless) ->
code = \< + name; bodies = []
for arg of args
if typeof arg is \object
code += " #key=\"#{ @quote val }\"" for key, val in arg
else bodies.push arg
if tailless
@_ += "#code/>"
return
@_ += "#code\n>"
for body of bodies
body.=call this if typeof body is \function
@_ += body if body?
@_ += "</#name>"
# Shortcut to `@a {href: url}, txt`.
A: !(url, txt) ->
@element \a [...@@] <<< [href: url, txt or @quote url]
# Each tag-named method delegates to `@element`.
# ref. <http://dev.w3.org/html5/spec/Overview.html>
for tag of <[
a abbr address area article aside audio
b base bdi bdo blockquote body br button
canvas caption cite code col colgroup command
datalist dd del details dfn div dl dt em embed
fieldset figcaption figure footer form
h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins
kbd keygen label legend li link map mark menu meta meter nav noscript
object ol optgroup option output p param pre progress q rp rt ruby
s samp script section select small source span strong style sub summary sup
table tbody td textarea tfoot th thead time title tr track
u ul var video wbr
]> then let tailless = tag of /* void elements */ <[
area base br col command embed hr img input
keygen link meta param source track wbr
]>
# `@a href: url, ->` -> `@element \a, [href: url, ->]`
ckup[tag] = !-> @element tag, @@, tailless
## Aliases
ckup{quote: $, raw: R, text: T, entity: E, var: v} = ckup