From 07ffa72d92e5d0832566bd0e1e23f82479f8395c Mon Sep 17 00:00:00 2001 From: Markus Kohlhase Date: Wed, 25 Jan 2012 13:36:28 +0100 Subject: [PATCH] added support for SVG 1.1 tags (see #107) --- src/coffeekup.coffee | 76 ++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/coffeekup.coffee b/src/coffeekup.coffee index 339bf89..eeddf00 100644 --- a/src/coffeekup.coffee +++ b/src/coffeekup.coffee @@ -1,10 +1,10 @@ # **CoffeeKup** lets you to write HTML templates in 100% pure # [CoffeeScript](http://coffeescript.org). -# +# # You can run it on [node.js](http://nodejs.org) or the browser, or compile your # templates down to self-contained javascript functions, that will take in data # and options and return generated HTML on any JS runtime. -# +# # The concept is directly stolen from the amazing # [Markaby](http://markaby.rubyforge.org/) by Tim Fletcher and why the lucky # stiff. @@ -65,6 +65,19 @@ elements = select small span strong style sub summary sup table tbody td textarea tfoot th thead time title tr u ul video' + # Support for SVG 1.1 tags + svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion + animateTransform circle clipPath color-profile cursor defs desc ellipse + feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix + feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB + feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology + feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence + filter font font-face font-face-format font-face-name font-face-src + font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient + marker mask metadata missing-glyph mpath path pattern polygon polyline + radialGradient rect script set stop style svg switch symbol text textPath + title tref tspan use view vkern' + # Valid self-closing HTML 5 elements. void: 'area base br col command embed hr img input keygen link meta param source track wbr' @@ -86,14 +99,15 @@ merge_elements = (args...) -> # Public/customizable list of possible elements. # For each name in this list that is also present in the input template code, # a function with the same name will be added to the compiled template. -coffeekup.tags = merge_elements 'regular', 'obsolete', 'void', 'obsolete_void' +coffeekup.tags = merge_elements 'regular', 'obsolete', 'void', 'obsolete_void', + 'svg' # Public/customizable list of elements that should be rendered self-closed. coffeekup.self_closing = merge_elements 'void', 'obsolete_void' # This is the basic material from which compiled templates will be formed. # It will be manipulated in its string form at the `coffeekup.compile` function -# to generate the final template function. +# to generate the final template function. skeleton = (data = {}) -> # Whether to generate formatted HTML with indentation and line breaks, or # just the natural "faux-minified" output. @@ -106,7 +120,7 @@ skeleton = (data = {}) -> # Internal CoffeeKup stuff. __ck = buffer: [] - + esc: (txt) -> if data.autoescape then h(txt) else String(txt) @@ -124,15 +138,15 @@ skeleton = (data = {}) -> render_idclass: (str) -> classes = [] - + for i in str.split '.' if '#' in i id = i.replace '#', '' else classes.push i unless i is '' - + text " id=\"#{id}\"" if id - + if classes.length > 0 text " class=\"" for c in classes @@ -144,7 +158,7 @@ skeleton = (data = {}) -> for k, v of obj # `true` is rendered as `selected="selected"`. v = k if typeof v is 'boolean' and v - + # Functions are rendered in an executable form. v = "(#{v}).call(this);" if typeof v is 'function' @@ -174,22 +188,22 @@ skeleton = (data = {}) -> render_tag: (name, idclass, attrs, contents) -> @indent() - + text "<#{name}" @render_idclass(idclass) if idclass @render_attrs(attrs) if attrs - + if name in @self_closing text ' />' text '\n' if data.format else text '>' - + @render_contents(contents) text "" text '\n' if data.format - + null tag = (name, args...) -> @@ -225,11 +239,11 @@ skeleton = (data = {}) -> .replace(//g, '>') .replace(/"/g, '"') - + doctype = (type = 'default') -> text __ck.doctypes[type] text '\n' if data.format - + text = (txt) -> __ck.buffer.push String(txt) null @@ -237,7 +251,7 @@ skeleton = (data = {}) -> comment = (cmt) -> text "" text '\n' if data.format - + coffeescript = (param) -> switch typeof param # `coffeescript -> alert 'hi'` becomes: @@ -253,11 +267,11 @@ skeleton = (data = {}) -> when 'object' param.type = 'text/coffeescript' script param - + # Conditional IE comments. ie = (condition, contents) -> __ck.indent() - + text "" @@ -284,9 +298,9 @@ coffeekup.compile = (template, options = {}) -> # If an object `hardcode` is provided, insert the stringified value # of each variable directly in the function body. This is a less flexible but - # faster alternative to the standard method of using `with` (see below). + # faster alternative to the standard method of using `with` (see below). hardcoded_locals = '' - + if options.hardcode for k, v of options.hardcode if typeof v is 'function' @@ -298,11 +312,11 @@ coffeekup.compile = (template, options = {}) -> # all hundred-odd tags wasting space in the compiled function. tag_functions = '' tags_used = [] - + for t in coffeekup.tags if template.indexOf(t) > -1 or hardcoded_locals.indexOf(t) > -1 tags_used.push t - + tag_functions += "var #{tags_used.join ','};" for t in tags_used tag_functions += "#{t} = function(){return __ck.tag('#{t}', arguments);};" @@ -320,16 +334,16 @@ coffeekup.compile = (template, options = {}) -> code += "(#{template}).call(data);" code += '}' if options.locals code += "return __ck.buffer.join('');" - + new Function('data', code) cache = {} # Template in, HTML out. Accepts functions or strings as does `coffeekup.compile`. -# +# # Accepts an option `cache`, by default `false`. If set to `false` templates will # be recompiled each time. -# +# # `options` is just a convenience parameter to pass options separately from the # data, but the two will be merged and passed down to the compiler (which uses # `locals` and `hardcode`), and the template (which understands `locals`, `format` @@ -348,24 +362,24 @@ unless window? # Legacy adapters for when CoffeeKup expected data in the `context` attribute. simple: coffeekup.render meryl: coffeekup.render - + express: TemplateError: class extends Error constructor: (@message) -> Error.call this, @message Error.captureStackTrace this, arguments.callee name: 'TemplateError' - - compile: (template, data) -> + + compile: (template, data) -> # Allows `partial 'foo'` instead of `text @partial 'foo'`. data.hardcode ?= {} data.hardcode.partial = -> text @partial.apply @, arguments - + TemplateError = @TemplateError try tpl = coffeekup.compile(template, data) catch e then throw new TemplateError "Error compiling #{data.filename}: #{e.message}" - + return -> try tpl arguments... - catch e then throw new TemplateError "Error rendering #{data.filename}: #{e.message}" \ No newline at end of file + catch e then throw new TemplateError "Error rendering #{data.filename}: #{e.message}"