diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc9ca39 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +COFFEE = ./node_modules/.bin/coffee + +SRC = $(wildcard src/*.coffee) +DST = $(SRC:src/%.coffee=lib/%.js) + + +all: compile + + +compile: $(DST) + +test: compile + node_modules/.bin/nodeunit test + +lib/%.js: src/%.coffee + @mkdir -p $(@D) + $(COFFEE) -bpc $< > $@ diff --git a/package.json b/package.json index 939d5d2..d5d0317 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "leco", "description": "Le Embedded CoffeeScript templates", "author": "Instant Communication Ltd", - "version": "1.0.1", + "version": "1.0.2", "licenses": { "type": "ISC", "url": "http://github.com/piranha/leco/raw/master/LICENSE" @@ -12,8 +12,11 @@ "coffee-script": "1.6.2", "underscore": "1.4.4" }, + "devDependencies" { + "nodeunit": "0.8.0" + }, "scripts": { - "prepublish": "coffee -o lib -c src/*.coffee" + "prepublish": "make" }, "bin": "./bin/leco", "main": "./lib/leco.js" diff --git a/src/helpers.coffee b/src/helpers.coffee index 8184f25..7108364 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -15,6 +15,6 @@ exports.safe = (value) -> return '' if value.templateSafe return value - value = value.toString() + value = new String(value.toString()) value.templateSafe = true return value diff --git a/src/transformer.coffee b/src/transformer.coffee index 0347e69..356e9bc 100644 --- a/src/transformer.coffee +++ b/src/transformer.coffee @@ -80,7 +80,14 @@ processCode = (value, writer) -> if value == 'end' return ['', false] if value.match /(-|=)>/ - value = value.replace(/(->|=>)$/, '((out) $1') + # generate a function, so it looks like this: + # (arg) => + # ((out) => + # out.push "some template with arg" + # out + # )([]).join("") + # This can be used as a callback with helpers + value = value.replace(/(->|=>)$/, '$1 ((out) $1') return [value, 'out)([]).join("")'] else if value[value.length - 1] == ':' return [value.slice(0, value.length - 1), true] @@ -93,7 +100,7 @@ getDefaultTokenMap = (helpersName) -> ['out.push ' + JSON.stringify(value), false] out: (value, writer) -> [value, indent] = processCode(value, writer) - ["out.push #{helpersName}.safe #{value}", indent] + ["out.push #{value}", indent] escape: (value, writer) -> [value, indent] = processCode(value, writer) ["out.push #{helpersName}.escape #{value}", indent] diff --git a/test/fixtures/capture.eco b/test/fixtures/capture.eco new file mode 100644 index 0000000..82ee6e5 --- /dev/null +++ b/test/fixtures/capture.eco @@ -0,0 +1,10 @@ +<% renderItem = (item) -> %> +
+ <%= item.name %> + $<%= item.price %> +
+<% end %> + +<% for item in @items: %> + <%= renderItem item %> +<% end %> diff --git a/test/fixtures/capture.out b/test/fixtures/capture.out new file mode 100644 index 0000000..a1e4877 --- /dev/null +++ b/test/fixtures/capture.out @@ -0,0 +1,17 @@ + + + + +
+ Caprese + $5.25 +
+ + + +
+ Artichoke + $6.25 +
+ + diff --git a/test/fixtures/hello.coffee b/test/fixtures/hello.coffee new file mode 100644 index 0000000..1cde34b --- /dev/null +++ b/test/fixtures/hello.coffee @@ -0,0 +1,8 @@ +(ctx) -> + ((out) -> + out.push "Hello, " + out.push helpers.escape @name + out.push ".\nI'M SHOUTING AT YOU, " + out.push helpers.escape @name.toUpperCase() + out.push "!\n" + out).call(ctx, []).join("") diff --git a/test/fixtures/hello.eco b/test/fixtures/hello.eco new file mode 100644 index 0000000..472befe --- /dev/null +++ b/test/fixtures/hello.eco @@ -0,0 +1,2 @@ +Hello, <%= @name %>. +I'M SHOUTING AT YOU, <%= @name.toUpperCase() %>! diff --git a/test/fixtures/hello.out b/test/fixtures/hello.out new file mode 100644 index 0000000..f16f4c7 --- /dev/null +++ b/test/fixtures/hello.out @@ -0,0 +1,2 @@ +Hello, Sam. +I'M SHOUTING AT YOU, SAM! diff --git a/test/fixtures/hello.tok b/test/fixtures/hello.tok new file mode 100644 index 0000000..c0383a3 --- /dev/null +++ b/test/fixtures/hello.tok @@ -0,0 +1 @@ +[["literal","Hello, "],["escape"," @name "],["literal",".\nI'M SHOUTING AT YOU, "],["escape"," @name.toUpperCase() "],["literal","!\n"]] diff --git a/test/fixtures/helpers.coffee b/test/fixtures/helpers.coffee new file mode 100644 index 0000000..438a20e --- /dev/null +++ b/test/fixtures/helpers.coffee @@ -0,0 +1,19 @@ +(ctx) -> + ((out) -> + for item in @items + out.push "\n " + out.push helpers.escape @contentTag "div", class: "item", => ((out) => + out.push "\n " + out.push helpers.escape @contentTag "span", class: "price", -> ((out) -> + out.push "$" + out.push helpers.escape item.price + out)([]).join("") + out.push "\n " + out.push helpers.escape @contentTag "span", class: "name", -> ((out) -> + out.push helpers.escape item.name + out)([]).join("") + out.push "\n " + out)([]).join("") + out.push "\n" + out.push "\n" + out).call(ctx, []).join("") diff --git a/test/fixtures/helpers.eco b/test/fixtures/helpers.eco new file mode 100644 index 0000000..73a035c --- /dev/null +++ b/test/fixtures/helpers.eco @@ -0,0 +1,6 @@ +<% for item in @items: %> + <%= @contentTag "div", class: "item", => %> + <%= @contentTag "span", class: "price", -> %>$<%= item.price %><% end %> + <%= @contentTag "span", class: "name", -> %><%= item.name %><% end %> + <% end %> +<% end %> diff --git a/test/fixtures/helpers.out b/test/fixtures/helpers.out new file mode 100644 index 0000000..f059e83 --- /dev/null +++ b/test/fixtures/helpers.out @@ -0,0 +1,11 @@ + +
+ $5.25 + Caprese +
+ +
+ $6.25 + Artichoke +
+ diff --git a/test/fixtures/helpers.tok b/test/fixtures/helpers.tok new file mode 100644 index 0000000..66d70c9 --- /dev/null +++ b/test/fixtures/helpers.tok @@ -0,0 +1 @@ +[["literal",""],["code"," for item in @items: "],["literal","\n "],["escape"," @contentTag \"div\", class: \"item\", => "],["literal","\n "],["escape"," @contentTag \"span\", class: \"price\", -> "],["literal","$"],["escape"," item.price "],["literal",""],["code"," end "],["literal","\n "],["escape"," @contentTag \"span\", class: \"name\", -> "],["literal",""],["escape"," item.name "],["literal",""],["code"," end "],["literal","\n "],["code"," end "],["literal","\n"],["code"," end "],["literal","\n"]] diff --git a/test/fixtures/projects.coffee b/test/fixtures/projects.coffee new file mode 100644 index 0000000..20297f7 --- /dev/null +++ b/test/fixtures/projects.coffee @@ -0,0 +1,17 @@ +(ctx) -> + ((out) -> + if @projects.length + out.push "\n " + for project in @projects + out.push "\n " + out.push helpers.escape project.name + out.push "\n " + out.push project.description + out.push "\n " + out.push "\n" + else + out.push "\n No projects\n" + out.push "\n" + out).call(ctx, []).join("") diff --git a/test/fixtures/projects.eco b/test/fixtures/projects.eco new file mode 100644 index 0000000..8fa7fba --- /dev/null +++ b/test/fixtures/projects.eco @@ -0,0 +1,8 @@ +<% if @projects.length: %> + <% for project in @projects: %> + <%= project.name %> + <%- project.description %> + <% end %> +<% else: %> + No projects +<% end %> diff --git a/test/fixtures/projects.out b/test/fixtures/projects.out new file mode 100644 index 0000000..8703b7a --- /dev/null +++ b/test/fixtures/projects.out @@ -0,0 +1,12 @@ + + + PowerTMS Active Shipments Page Redesign + + + SCU Intranet +

On hold

+ + Sales Template + + + diff --git a/test/fixtures/projects.tok b/test/fixtures/projects.tok new file mode 100644 index 0000000..9878309 --- /dev/null +++ b/test/fixtures/projects.tok @@ -0,0 +1 @@ +[["literal",""],["code"," if @projects.length: "],["literal","\n "],["code"," for project in @projects: "],["literal","\n "],["escape"," project.name "],["literal","\n "],["out"," project.description "],["literal","\n "],["code"," end "],["literal","\n"],["code"," else: "],["literal","\n No projects\n"],["code"," end "],["literal","\n"]] diff --git a/test/test_render.coffee b/test/test_render.coffee new file mode 100644 index 0000000..78de28a --- /dev/null +++ b/test/test_render.coffee @@ -0,0 +1,39 @@ +{tokenize, transform, helpers} = require '../lib/leco' +fs = require 'fs' +CoffeeScript = require 'coffee-script' + + +read = (x) -> fs.readFileSync(__dirname + '/fixtures/' + x).toString() +f = (x) -> read(x + '.out') +t = (x, ctx) -> + tokens = tokenize(read(x + '.eco')) + tpl = transform(tokens, {}, helpers) + CoffeeScript.eval(tpl)(ctx) + + +module.exports = + 'transforming fixtures/hello.eco': (test) -> + test.deepEqual f('hello'), t('hello', name: 'Sam') + test.done() + + 'transforming fixtures/projects.eco': (test) -> + result = t('projects', projects: [ + { name: "PowerTMS Active Shipments Page Redesign", url: "/projects/1" }, + { name: "SCU Intranet", url: "/projects/2", description: "

On hold

" }, + { name: "Sales Template", url: "/projects/3" } + ]) + test.deepEqual f('projects'), result + test.done() + + 'transforming fixtures/helpers.eco': (test) -> + result = t('helpers', + items: [ + { name: "Caprese", price: "5.25"}, + { name: "Artichoke", price: "6.25" } + ] + contentTag: (tagName, attributes, callback) -> + attrs = (" #{name}=\"#{value}\"" for name, value of attributes) + helpers.safe "<#{tagName}#{attrs.join("")}>#{callback()}" + ) + test.deepEqual f('helpers'), result + test.done() diff --git a/test/test_tokenizer.coffee b/test/test_tokenizer.coffee new file mode 100644 index 0000000..09117d0 --- /dev/null +++ b/test/test_tokenizer.coffee @@ -0,0 +1,19 @@ +{tokenize} = require '../lib/leco' +fs = require 'fs' + +read = (x) -> fs.readFileSync(__dirname + '/fixtures/' + x).toString() +f = (x) -> JSON.parse(read(x + '.tok')) +t = (x) -> tokenize(read(x + '.eco')) + +module.exports = + 'tokenizing fixtures/hello.eco': (test) -> + test.deepEqual f('hello'), t('hello') + test.done() + + 'tokenizing fixtures/projects.eco': (test) -> + test.deepEqual f('projects'), t('projects') + test.done() + + 'tokenizing fixtures/helpers.eco': (test) -> + test.deepEqual f('helpers'), t('helpers') + test.done() diff --git a/test/test_transformer.coffee b/test/test_transformer.coffee new file mode 100644 index 0000000..714c392 --- /dev/null +++ b/test/test_transformer.coffee @@ -0,0 +1,19 @@ +{tokenize, transform} = require '../lib/leco' +fs = require 'fs' + +read = (x) -> fs.readFileSync(__dirname + '/fixtures/' + x).toString() +f = (x) -> read(x + '.coffee') +t = (x) -> transform(tokenize(read(x + '.eco'))) + +module.exports = + 'transforming fixtures/hello.eco': (test) -> + test.deepEqual f('hello'), t('hello') + test.done() + + 'transforming fixtures/projects.eco': (test) -> + test.deepEqual f('projects'), t('projects') + test.done() + + 'transforming fixtures/helpers.eco': (test) -> + test.deepEqual f('helpers'), t('helpers') + test.done()