Skip to content
41 changes: 41 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src/environment.co
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class Environment
return eval t

({@utils ? require("./utils"), @filters ? require("./filters"), @parser ? new Parser!, @pre_compile_func ? "", @require_exp ? 'require'} ? {}) ->
@outputUndefinedVariable = false
@outputUndefinedVariableWithBrackets = false

getTemplateFromString: function (str)
try
Expand All @@ -28,7 +30,7 @@ class Environment
str = @pre_compile_func str if @pre_compile_func

ast = @parser.parse str, compilation_ctx
opts = {__indent__: 1, @utils, @filters}
opts = {__indent__: 1, @utils, @filters, @outputUndefinedVariable, @outputUndefinedVariableWithBrackets}

compilation_ctx = filters_used: {}
compilation_ctx <<< {@filters, @utils}
Expand Down
3 changes: 1 addition & 2 deletions src/expression.pegco
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

->
compilation_ctx = arguments[2] ? {}
compilation_ctx.filters ?= {}
Expand Down Expand Up @@ -320,7 +319,7 @@ tag_for
/ key:identifier COMMA value:identifier IN exp:expression ->
return key: key, value: value, condition: exp

tag_let
tag_set
= variable_name:identifier ASSIGN expression:expression ->
return variable_name: variable_name, expression: expression

Expand Down
25 changes: 18 additions & 7 deletions src/filters.co
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ exports import do
if value < 1024
return "#{value}"
if value < 1024 * 1024
val = val / 1024
val = value / 1024
unit = "Kb"
else if value < 1024 * 1024 * 1024
val = val / (1024 * 1024)
val = value / (1024 * 1024)
unit = "Mb"
else
val = val / (1024 * 1024 * 1024)
val = value / (1024 * 1024 * 1024)
unit = "Gb"

strval = "#{Math.round val}"
Expand All @@ -203,7 +203,7 @@ exports import do

$float: function (value)
res = parseFloat value
return 0.0 if res is NaN
return 0.0 if isNaN res
return res

$forceescape: function (value)
Expand Down Expand Up @@ -441,10 +441,21 @@ exports import do
obj = obj[a]
return obj

$reverse: function (arr)
new_arr = arr.splice 0
$reverse: function (arr, keep_array)
keep_array = keep_array or false
new_arr = arr
if \number is typeof arr
new_arr = new_arr.toString()
new_arr = new_arr.split("")
new_arr = new_arr.splice(0)
else if \string is typeof arr
new_arr = new_arr.split("")
new_arr = new_arr.splice(0)
else if arr instanceof Array
new_arr = new_arr.splice(0)
else throw new Error("Unsupported type \"" + typeof arr + "\" for reverse")
new_arr.reverse()
return new_arr
return (if (keep_array) then new_arr else new_arr.join(""))

$round: function (value, precision ? 0, method ? 'common')
if method is \common
Expand Down
30 changes: 29 additions & 1 deletion src/helpers.co
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,33 @@ function registerExtension (ext, filter)
# registerExtension \.pwi, (str) -> pwilang.parse str
# registerExtension \.pwx, (str) -> pwilang.parse str

exports import { registerExtension }
/**
* Register flag to output undefined variables
* @param output: flag to output undefined variable name
* @param withBrackets: flag to output undefined variable name with brackets
*/
function outputUndefinedVariable (output, withBrackets)
output ?= true
withBrackets ?= false

defaultEnvironment.outputUndefinedVariable = output
defaultEnvironment.outputUndefinedVariableWithBrackets = withBrackets

/**
* Options for JinJS
* @param opts: object where the properties are set
*/
function options (opts)
opts ?= {}

# Check if extensions passed
if opts.extensions
for index, extension in opts.extensions
registerExtension extension.ext, extension.filter

# Check if outputUndefinedVariable is defined
if opts.outputUndefinedVariable
outputUndefinedVariable opts.outputUndefinedVariable, opts.outputUndefinedVariableWithBrackets

exports import { registerExtension, outputUndefinedVariable, options }

4 changes: 2 additions & 2 deletions src/main.co
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{ defaultEnvironment, Environment } = require \./environment
{ registerExtension } = require \./helpers
{ registerExtension, outputUndefinedVariable, options } = require \./helpers
{ compile } = require \./express

exports <<< { defaultEnvironment, registerExtension, Environment, compile }
exports <<< { defaultEnvironment, registerExtension, outputUndefinedVariable, options, Environment, compile }

37 changes: 28 additions & 9 deletions src/nodes.co
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

{ parse:make_expression } = require \./expression

make_parse_rule = (rule_name) ->
return (contents, ctx) -> make_expression contents, rule_name, ctx

parse_for = make_parse_rule \tag_for
parse_let = make_parse_rule \tag_let
parse_set = make_parse_rule \tag_set
parse_macro = make_parse_rule \tag_macro
parse_extends = make_expression
parse_block = make_parse_rule \tag_block
Expand Down Expand Up @@ -108,7 +107,12 @@ class NodePrint extends Node
(specs) -> super ...

compile: function (opts, ctx)
return "_res += ((_ref = #{make_expression @contents, ctx}) !== undefined && _ref !== null ? _ref : '').toString();"
output = ''
if (opts.outputUndefinedVariableWithBrackets)
output = "{{#{@contents}}}"
else if (opts.outputUndefinedVariable)
output = @contents
return "_res += ((_ref = #{make_expression @contents, ctx}) !== undefined && _ref !== null ? _ref : '#{output}').toString();"

class NodeTag extends Node
@tag = \__tag__
Expand Down Expand Up @@ -242,13 +246,13 @@ class NodeAbspath extends NodeTag
/**
*
*/
class NodeLet extends NodeTag
@tag = \let
class NodeSet extends NodeTag
@tag = \set

(specs) -> super ...

compile: function (opts, ctx)
{ variable_name, expression } = parse_let @contents, ctx
{ variable_name, expression } = parse_set @contents, ctx

ctx[variable_name] = true # The variable name is now accessible to the rest of the template.
return res = "var #{variable_name} = ($$.#{variable_name} = #{expression});"
Expand Down Expand Up @@ -452,6 +456,19 @@ class NodeIf extends NodeTagContainer
}"""
return res

/**
* Raw Node
*/
class NodeRaw extends NodeTagContainer
@tag = \raw
@until = \endraw

(specs) ->
super ...

compile : function (opts, ctx)
console.dir @
return "_res += 'ffs';";

class NodeElseFor extends NodeTagContainer
@tag = \else
Expand Down Expand Up @@ -542,13 +559,14 @@ class NodeFor extends NodeTagContainer
"""

exports <<< {
NodeIf, NodeDo, NodeLet, NodeFor, NodeMacro, NodeList, NodeBasic,
NodeIf, NodeDo, NodeSet, NodeFor, NodeMacro, NodeList, NodeBasic,
NodePrint, NodeComment, NodeExtends, NodeInclude, NodeImport, NodeFromImport,
NodeContinue, NodeCall
NodeContinue, NodeCall, NodeRaw
default_nodes: do
\if : NodeIf
\do : NodeDo
\let : NodeLet
\set : NodeSet
\let : NodeSet #Deprecated
\for : NodeFor
\macro : NodeMacro
\extends : NodeExtends
Expand All @@ -560,5 +578,6 @@ exports <<< {
\continue : NodeContinue
\break : NodeBreak
\call : NodeCall
\raw : NodeRaw
}

18 changes: 9 additions & 9 deletions test/parser.co
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ suite = require \vows .describe "Expressions Test Suite"


suite.addBatch do
"The {% let %} tag": do
topic: parse "{% let toto = 1 %}TXT"
"The {% set %} tag": do
topic: parse "{% set toto = 1 %}TXT"

"Lets us assign to a variable that is later exported": (res) ->
equal res.ctx.toto, 1
Expand All @@ -73,10 +73,10 @@ suite.addBatch do
equal res.txt, 'TXT'

"does not let us assign to reserved-words variables": (res) ->
parseError -> _parse "{% let instanceof = 3 %}"
parseError -> _parse "{% set instanceof = 3 %}"

"can have their results even across new lines": ->
res = _parse "{% let toto\n=\n 1 %}{{ toto }}"
res = _parse "{% set toto\n=\n 1 %}{{ toto }}"
equal res.txt, "1"

##
Expand Down Expand Up @@ -340,7 +340,7 @@ suite.addBatch do
equal res.txt, 'foo'

"gets to modify the context": ->
included = compile "{% let foo = 'bar' %}"
included = compile "{% set foo = 'bar' %}"
res = _parse "{% include included %}{{ foo }}", foo: "foo", included: included
equal res.txt, 'bar'

Expand Down Expand Up @@ -382,22 +382,22 @@ suite.addBatch do
"The {% import %} tag": do

"allows us to import variables from another template to another": ->
imported = compile "{% let foo = 'bar' %}"
imported = compile "{% set foo = 'bar' %}"
res = _parse "{% from imported import foo %}{{ foo }}", imported: imported
equal res.txt, 'bar'

"allows us to import a whole template as a module": ->
imported = compile "{% let foo = 'bar' %}"
imported = compile "{% set foo = 'bar' %}"
res = _parse "{% import imported as imp %}{{ imp.foo }}", imported: imported
equal res.txt, 'bar'

"by default does not expose the current context to the imported module": ->
imported = compile "{% let foo = 'bar' %}"
imported = compile "{% set foo = 'bar' %}"
res = _parse "{% import imported as toto %}{{ foo }}", imported: imported, foo: 'foo'
equal res.txt, 'foo'

"can pass the context to the imported template": ->
imported = compile "{% let foo = bar + 'foo' %}"
imported = compile "{% set foo = bar + 'foo' %}"
res = _parse "{% import imported as toto with context %}{{ toto.foo }}", imported: imported, bar: 'bar'
equal res.txt, 'barfoo'

Expand Down
2 changes: 1 addition & 1 deletion test/templates/test-include.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% let variable = "bloup" %}
{% set variable = "bloup" %}
{% macro test () %}
Yoyo {{ variable }}
{% endmacro %}
Expand Down