From 03d0155d8770ba44ca22b5401f61e53840dc01cc Mon Sep 17 00:00:00 2001 From: mauricemach Date: Tue, 26 Jul 2011 07:35:39 -0300 Subject: [PATCH] Changed: now accepting all options at the "root" of the input object. --- docs/coffeekup.html | 77 ++++++++++++++++++++-------------------- docs/reference.md | 8 ++--- src/coffeekup.coffee | 83 +++++++++++++++++++++----------------------- test.coffee | 4 +-- 4 files changed, 81 insertions(+), 91 deletions(-) diff --git a/docs/coffeekup.html b/docs/coffeekup.html index 0b5a949..520b80b 100644 --- a/docs/coffeekup.html +++ b/docs/coffeekup.html @@ -56,25 +56,22 @@ coffeekup.self_closing = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'link', 'meta', 'param']

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.

skeleton = (data = {}) ->
-  data.options ?= {}

Whether to generate formatted HTML with indentation and line breaks, or -just the natural "faux-minified" output.

  data.options.format ?= off

Whether to autoescape all content or let you handle it on a case by case -basis with the h function.

  data.options.autoescape ?= off

Internal CoffeeKup stuff.

  __ck =
-    options: data.options
-  
+to generate the final template function. 

skeleton = (input = {}) ->

Whether to generate formatted HTML with indentation and line breaks, or +just the natural "faux-minified" output.

  input.format ?= off

Whether to autoescape all content or let you handle it on a case by case +basis with the h function.

  input.autoescape ?= off

Internal CoffeeKup stuff.

  __ck =
     buffer: []
       
     esc: (txt) ->
-      if @options.autoescape then h(txt) else String(txt)
+      if input.autoescape then h(txt) else String(txt)
 
     tabs: 0
 
     repeat: (string, count) -> Array(count + 1).join string
 
-    indent: -> text @repeat('  ', @tabs) if @options.format

Adapter to keep the builtin tag functions DRY.

    tag: (name, args) ->
+    indent: -> text @repeat('  ', @tabs) if input.format

Adapter to keep the builtin tag functions DRY.

    tag: (name, args) ->
       combo = [name]
       combo.push i for i in args
-      tag.apply data, combo
+      tag.apply input, combo
 
     render_idclass: (str) ->
       classes = []
@@ -103,13 +100,13 @@
         when 'string', 'number', 'boolean'
           text @esc(contents)
         when 'function'
-          text '\n' if @options.format
+          text '\n' if input.format
           @tabs++
-          result = contents.call data
+          result = contents.call input
           if typeof result is 'string'
             @indent()
             text @esc(result)
-            text '\n' if @options.format
+            text '\n' if input.format
           @tabs--
           @indent()
 
@@ -122,14 +119,14 @@
   
       if name in @self_closing
         text ' />'
-        text '\n' if @options.format
+        text '\n' if input.format
       else
         text '>'
   
         @render_contents(contents)
 
         text "</#{name}>"
-        text '\n' if @options.format
+        text '\n' if input.format
   
       null
 
@@ -161,7 +158,7 @@
     
   doctype = (type = 'default') ->
     text __ck.doctypes[type]
-    text '\n' if data.options.format
+    text '\n' if input.format
     
   text = (txt) ->
     __ck.buffer.push String(txt)
@@ -169,28 +166,28 @@
 
   comment = (cmt) ->
     text "<!--#{cmt}-->"
-    text '\n' if data.options.format
+    text '\n' if input.format
   
-  coffeescript = (input) ->
-    switch typeof input

coffeescript -> alert 'hi' becomes: + coffeescript = (param) -> + switch typeof param

coffeescript -> alert 'hi' becomes: <script>;(function () {return alert('hi');})();</script>

      when 'function'
-        script "#{__ck.coffeescript_helpers}(#{input}).call(this);"

coffeescript "alert 'hi'" becomes: + script "#{__ck.coffeescript_helpers}(#{param}).call(this);"

coffeescript "alert 'hi'" becomes: <script type="text/coffeescript">alert 'hi'</script>

      when 'string'
-        script type: 'text/coffeescript', -> input

coffeescript src: 'script.coffee' becomes: + script type: 'text/coffeescript', -> param

coffeescript src: 'script.coffee' becomes: <script type="text/coffeescript" src="script.coffee"></script>

      when 'object'
-        input.type = 'text/coffeescript'
-        script input
+        param.type = 'text/coffeescript'
+        script param
   

Conditional IE comments.

  ie = (condition, contents) ->
     __ck.indent()
     
     text "<!--[if #{condition}]>"
     __ck.render_contents(contents)
     text "<![endif]-->"
-    text '\n' if data.options.format
+    text '\n' if input.format
 
   null

Stringify the skeleton and unwrap it from its enclosing function(){}, then add the CoffeeScript helpers.

skeleton = String(skeleton)
-  .replace(/function\s*\(data\)\s*\{/, '')
+  .replace(/function\s*\(.*\)\s*\{/, '')
   .replace(/return null;\s*\}$/, '')
 
 skeleton = coffeescript_helpers + skeleton

Compiles a template into a standalone JavaScript function.

coffeekup.compile = (template, options = {}) ->

The template can be provided as either a function or a CoffeeScript string @@ -203,7 +200,7 @@ if options.hardcode for k, v of options.hardcode - if typeof v is 'function'

Make sure these functions have access to data as @/this.

        hardcoded_locals += "var #{k} = function(){return (#{v}).apply(data, arguments);};"
+      if typeof v is 'function'

Make sure these functions have access to input as @/this.

        hardcoded_locals += "var #{k} = function(){return (#{v}).apply(input, arguments);};"
       else hardcoded_locals += "var #{k} = #{JSON.stringify v};"

Add a function for each tag this template references. We don't want to have all hundred-odd tags wasting space in the compiled function.

  tag_functions = ''
   tags_used = []
@@ -219,38 +216,38 @@
   code += "__ck.doctypes = #{JSON.stringify coffeekup.doctypes};"
   code += "__ck.coffeescript_helpers = #{JSON.stringify coffeescript_helpers};"
   code += "__ck.self_closing = #{JSON.stringify coffeekup.self_closing};"

If locals is set, wrap the template inside a with block. This is the -most flexible but slower approach to specifying local variables.

  code += 'with(data.locals){' if options.locals
-  code += "(#{template}).call(data);"
+most flexible but slower approach to specifying local variables.

  code += 'with(input.locals){' if options.locals
+  code += "(#{template}).call(input);"
   code += '}' if options.locals
   code += "return __ck.buffer.join('');"
 
-  new Function('data', code)
+  new Function('input', code)
 
 cache = {}

Template in, HTML out. Accepts functions or strings as does coffeekup.compile.

-

Accepts an option cache, by default true. If set to false templates will +

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 the options -format and autoescape).

coffeekup.render = (template, data = {}, options = {}) ->
-  data[k] = v for k, v of options
-  data.cache ?= off
+locals and hardcode), and the template (which understands locals, format
+and autoescape).

coffeekup.render = (template, input = {}, options = {}) ->
+  input[k] = v for k, v of options
+  input.cache ?= off
 
-  if data.cache and cache[template]? then tpl = cache[template]
-  else if data.cache then tpl = cache[template] = coffeekup.compile(template, data)
-  else tpl = coffeekup.compile(template, data)
-  tpl(data)
+  if input.cache and cache[template]? then tpl = cache[template]
+  else if input.cache then tpl = cache[template] = coffeekup.compile(template, input)
+  else tpl = coffeekup.compile(template, input)
+  tpl(input)
 
 unless window?
   coffeekup.adapters =

Legacy adapters for when CoffeeKup expected data in the context attribute.

    simple: coffeekup.render
     meryl: coffeekup.render
     

Allows partial 'foo' instead of text @partial 'foo'.

    express:
-      compile: (template, data) -> 
-        data.hardcode =
+      compile: (template, input) -> 
+        input.hardcode =
           partial: ->
             text @partial.apply @, arguments
-        coffeekup.compile(template, data)
+        coffeekup.compile(template, input)
 
 
\ No newline at end of file diff --git a/docs/reference.md b/docs/reference.md index 0b758f5..d02ff00 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -28,15 +28,13 @@ All attributes in `input` will be available to the template at `@` (`this`). Som - `locals`: if the template was compiled with the `locals` option, it will pass this variable to the `with` statement, putting all its attributes to the local scope. -- `options`: an object containing rendering options: +- `format`: `false` by default. Whether to generate formatted HTML with indentation and line breaks, or just the natural "faux-minified" output. - - `format`: `false` by default. Whether to generate formatted HTML with indentation and line breaks, or just the natural "faux-minified" output. - - - `autoescape`: `false` by default. Whether to autoescape all content or let you handle it on a case by case basis with the `h` function. +- `autoescape`: `false` by default. Whether to autoescape all content or let you handle it on a case by case basis with the `h` function. ### render -`CoffeeKup.render(template, data, options)` +`CoffeeKup.render(template, input, options)` Compiles the template provided, runs it, and returns the resulting HTML string. diff --git a/src/coffeekup.coffee b/src/coffeekup.coffee index 1e57be0..3ce25fa 100644 --- a/src/coffeekup.coffee +++ b/src/coffeekup.coffee @@ -70,37 +70,33 @@ coffeekup.self_closing = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr' # 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. -skeleton = (data = {}) -> - data.options ?= {} - +skeleton = (input = {}) -> # Whether to generate formatted HTML with indentation and line breaks, or # just the natural "faux-minified" output. - data.options.format ?= off + input.format ?= off # Whether to autoescape all content or let you handle it on a case by case # basis with the `h` function. - data.options.autoescape ?= off + input.autoescape ?= off # Internal CoffeeKup stuff. __ck = - options: data.options - buffer: [] esc: (txt) -> - if @options.autoescape then h(txt) else String(txt) + if input.autoescape then h(txt) else String(txt) tabs: 0 repeat: (string, count) -> Array(count + 1).join string - indent: -> text @repeat(' ', @tabs) if @options.format + indent: -> text @repeat(' ', @tabs) if input.format # Adapter to keep the builtin tag functions DRY. tag: (name, args) -> combo = [name] combo.push i for i in args - tag.apply data, combo + tag.apply input, combo render_idclass: (str) -> classes = [] @@ -135,13 +131,13 @@ skeleton = (data = {}) -> when 'string', 'number', 'boolean' text @esc(contents) when 'function' - text '\n' if @options.format + text '\n' if input.format @tabs++ - result = contents.call data + result = contents.call input if typeof result is 'string' @indent() text @esc(result) - text '\n' if @options.format + text '\n' if input.format @tabs-- @indent() @@ -154,14 +150,14 @@ skeleton = (data = {}) -> if name in @self_closing text ' />' - text '\n' if @options.format + text '\n' if input.format else text '>' @render_contents(contents) text "" - text '\n' if @options.format + text '\n' if input.format null @@ -193,7 +189,7 @@ skeleton = (data = {}) -> doctype = (type = 'default') -> text __ck.doctypes[type] - text '\n' if data.options.format + text '\n' if input.format text = (txt) -> __ck.buffer.push String(txt) @@ -201,23 +197,23 @@ skeleton = (data = {}) -> comment = (cmt) -> text "" - text '\n' if data.options.format + text '\n' if input.format - coffeescript = (input) -> - switch typeof input + coffeescript = (param) -> + switch typeof param # `coffeescript -> alert 'hi'` becomes: # `` when 'function' - script "#{__ck.coffeescript_helpers}(#{input}).call(this);" + script "#{__ck.coffeescript_helpers}(#{param}).call(this);" # `coffeescript "alert 'hi'"` becomes: # `` when 'string' - script type: 'text/coffeescript', -> input + script type: 'text/coffeescript', -> param # `coffeescript src: 'script.coffee'` becomes: # `` when 'object' - input.type = 'text/coffeescript' - script input + param.type = 'text/coffeescript' + script param # Conditional IE comments. ie = (condition, contents) -> @@ -226,14 +222,14 @@ skeleton = (data = {}) -> text "" - text '\n' if data.options.format + text '\n' if input.format null # Stringify the skeleton and unwrap it from its enclosing `function(){}`, then # add the CoffeeScript helpers. skeleton = String(skeleton) - .replace(/function\s*\(data\)\s*\{/, '') + .replace(/function\s*\(.*\)\s*\{/, '') .replace(/return null;\s*\}$/, '') skeleton = coffeescript_helpers + skeleton @@ -255,8 +251,8 @@ coffeekup.compile = (template, options = {}) -> if options.hardcode for k, v of options.hardcode if typeof v is 'function' - # Make sure these functions have access to `data` as `@/this`. - hardcoded_locals += "var #{k} = function(){return (#{v}).apply(data, arguments);};" + # Make sure these functions have access to `input` as `@/this`. + hardcoded_locals += "var #{k} = function(){return (#{v}).apply(input, arguments);};" else hardcoded_locals += "var #{k} = #{JSON.stringify v};" # Add a function for each tag this template references. We don't want to have @@ -281,33 +277,32 @@ coffeekup.compile = (template, options = {}) -> # If `locals` is set, wrap the template inside a `with` block. This is the # most flexible but slower approach to specifying local variables. - code += 'with(data.locals){' if options.locals - code += "(#{template}).call(data);" + code += 'with(input.locals){' if options.locals + code += "(#{template}).call(input);" code += '}' if options.locals code += "return __ck.buffer.join('');" - new Function('data', code) + new Function('input', code) cache = {} # Template in, HTML out. Accepts functions or strings as does `coffeekup.compile`. # -# Accepts an option `cache`, by default `true`. If set to `false` templates will +# 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 the options -# `format` and `autoescape`). -# -coffeekup.render = (template, data = {}, options = {}) -> - data[k] = v for k, v of options - data.cache ?= off +# `locals` and `hardcode`), and the template (which understands `locals`, `format` +# and `autoescape`). +coffeekup.render = (template, input = {}, options = {}) -> + input[k] = v for k, v of options + input.cache ?= off - if data.cache and cache[template]? then tpl = cache[template] - else if data.cache then tpl = cache[template] = coffeekup.compile(template, data) - else tpl = coffeekup.compile(template, data) - tpl(data) + if input.cache and cache[template]? then tpl = cache[template] + else if input.cache then tpl = cache[template] = coffeekup.compile(template, input) + else tpl = coffeekup.compile(template, input) + tpl(input) unless window? coffeekup.adapters = @@ -317,8 +312,8 @@ unless window? # Allows `partial 'foo'` instead of `text @partial 'foo'`. express: - compile: (template, data) -> - data.hardcode = + compile: (template, input) -> + input.hardcode = partial: -> text @partial.apply @, arguments - coffeekup.compile(template, data) \ No newline at end of file + coffeekup.compile(template, input) \ No newline at end of file diff --git a/test.coffee b/test.coffee index a8dc9dc..81148cd 100644 --- a/test.coffee +++ b/test.coffee @@ -114,7 +114,7 @@ tests = 'Autoescaping': template: "h1 \"\"" expected: "

<script>alert('"pwned" by c&a &copy;')</script>

" - params: {options: {autoescape: yes}} + params: {autoescape: yes} 'ID/class shortcut (combo)': template: "div '#myid.myclass1.myclass2', 'foo'" @@ -159,7 +159,7 @@ tests = ''' - params: {options: {format: yes}} + params: {format: yes} ck = require './src/coffeekup' render = ck.render