1{
2  "overview": "Lambdas are a special-cased data type for use in interpolations and\nsections.\n\nWhen used as the data value for an Interpolation tag, the lambda MUST be\ntreatable as an arity 0 function, and invoked as such.  The returned value\nMUST be rendered against the default delimiters, then interpolated in place\nof the lambda.\n\nWhen used as the data value for a Section tag, the lambda MUST be treatable\nas an arity 1 function, and invoked as such (passing a String containing the\nunprocessed section contents).  The returned value MUST be rendered against\nthe current delimiters, then interpolated in place of the section.\n",
3  "tests": [
4    {
5      "expected": "Hello, world!",
6      "data": {
7        "lambda": {
8          "python": "lambda: \"world\"",
9          "perl": "sub { \"world\" }",
10          "php": "return \"world\";",
11          "ruby": "proc { \"world\" }",
12          "js": "function() { return \"world\" }"
13          "R": "function() { \"world\" }"
14        }
15      },
16      "name": "Interpolation",
17      "template": "Hello, {{lambda}}!",
18      "desc": "A lambda's return value should be interpolated."
19    },
20    {
21      "expected": "Hello, world!",
22      "data": {
23        "planet": "world",
24        "lambda": {
25          "python": "lambda: \"{{planet}}\"",
26          "perl": "sub { \"{{planet}}\" }",
27          "php": "return \"{{planet}}\";",
28          "ruby": "proc { \"{{planet}}\" }",
29          "js": "function() { return \"{{planet}}\" }"
30          "R": "function() { \"{{planet}}\" }"
31        }
32      },
33      "name": "Interpolation - Expansion",
34      "template": "Hello, {{lambda}}!",
35      "desc": "A lambda's return value should be parsed."
36    },
37    {
38      "expected": "Hello, (|planet| => world)!",
39      "data": {
40        "planet": "world",
41        "lambda": {
42          "python": "lambda: \"|planet| => {{planet}}\"",
43          "perl": "sub { \"|planet| => {{planet}}\" }",
44          "php": "return \"|planet| => {{planet}}\";",
45          "ruby": "proc { \"|planet| => {{planet}}\" }",
46          "js": "function() { return \"|planet| => {{planet}}\" }"
47          "R": "function() { \"|planet| => {{planet}}\" }"
48        }
49      },
50      "name": "Interpolation - Alternate Delimiters",
51      "template": "{{= | | =}}\nHello, (|&lambda|)!",
52      "desc": "A lambda's return value should parse with the default delimiters."
53    },
54    {
55      "expected": "1 == 2 == 3",
56      "data": {
57        "lambda": {
58          "python": "lambda: globals().update(calls=globals().get(\"calls\",0)+1) or calls",
59          "perl": "sub { no strict; $calls += 1 }",
60          "php": "global $calls; return ++$calls;",
61          "ruby": "proc { $calls ||= 0; $calls += 1 }",
62          "js": "function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }"
63          "R": "function(){if (!exists(\"x\")) x <<- 0; x <<- x + 1; x}"
64        }
65      },
66      "name": "Interpolation - Multiple Calls",
67      "template": "{{lambda}} == {{{lambda}}} == {{lambda}}",
68      "desc": "Interpolated lambdas should not be cached."
69    },
70    {
71      "expected": "<&gt;>",
72      "data": {
73        "lambda": {
74          "python": "lambda: \">\"",
75          "perl": "sub { \">\" }",
76          "php": "return \">\";",
77          "ruby": "proc { \">\" }",
78          "js": "function() { return \">\" }"
79          "R": "function() { \">\"}"
80        }
81      },
82      "name": "Escaping",
83      "template": "<{{lambda}}{{{lambda}}}",
84      "desc": "Lambda results should be appropriately escaped."
85    },
86    {
87      "expected": "<yes>",
88      "data": {
89        "x": "Error!",
90        "lambda": {
91          "python": "lambda text: text == \"{{x}}\" and \"yes\" or \"no\"",
92          "perl": "sub { $_[0] eq \"{{x}}\" ? \"yes\" : \"no\" }",
93          "php": "return ($text == \"{{x}}\") ? \"yes\" : \"no\";",
94          "ruby": "proc { |text| text == \"{{x}}\" ? \"yes\" : \"no\" }",
95          "js": "function(txt) { return (txt == \"{{x}}\" ? \"yes\" : \"no\") }"
96          "R": "function(txt) { ifelse(txt == \"{{x}}\",\"yes\",\"no\") }"
97        }
98      },
99      "name": "Section",
100      "template": "<{{#lambda}}{{x}}{{/lambda}}>",
101      "desc": "Lambdas used for sections should receive the raw section string."
102    },
103    {
104      "expected": "<-Earth->",
105      "data": {
106        "planet": "Earth",
107        "lambda": {
108          "python": "lambda text: \"%s{{planet}}%s\" % (text, text)",
109          "perl": "sub { $_[0] . \"{{planet}}\" . $_[0] }",
110          "php": "return $text . \"{{planet}}\" . $text;",
111          "ruby": "proc { |text| \"#{text}{{planet}}#{text}\" }",
112          "js": "function(txt) { return txt + \"{{planet}}\" + txt }"
113          "R": "function(txt) { paste(txt, \"{{planet}}\", txt, sep=\"\"}"
114        }
115      },
116      "name": "Section - Expansion",
117      "template": "<{{#lambda}}-{{/lambda}}>",
118      "desc": "Lambdas used for sections should have their results parsed."
119    },
120    {
121      "expected": "<-{{planet}} => Earth->",
122      "data": {
123        "planet": "Earth",
124        "lambda": {
125          "python": "lambda text: \"%s{{planet}} => |planet|%s\" % (text, text)",
126          "perl": "sub { $_[0] . \"{{planet}} => |planet|\" . $_[0] }",
127          "php": "return $text . \"{{planet}} => |planet|\" . $text;",
128          "ruby": "proc { |text| \"#{text}{{planet}} => |planet|#{text}\" }",
129          "js": "function(txt) { return txt + \"{{planet}} => |planet|\" + txt }"
130        }
131      },
132      "name": "Section - Alternate Delimiters",
133      "template": "{{= | | =}}<|#lambda|-|/lambda|>",
134      "desc": "Lambdas used for sections should parse with the current delimiters."
135    },
136    {
137      "expected": "__FILE__ != __LINE__",
138      "data": {
139        "lambda": {
140          "python": "lambda text: \"__%s__\" % (text)",
141          "perl": "sub { \"__\" . $_[0] . \"__\" }",
142          "php": "return \"__\" . $text . \"__\";",
143          "ruby": "proc { |text| \"__#{text}__\" }",
144          "js": "function(txt) { return \"__\" + txt + \"__\" }"
145        }
146      },
147      "name": "Section - Multiple Calls",
148      "template": "{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}",
149      "desc": "Lambdas used for sections should not be cached."
150    },
151    {
152      "expected": "<>",
153      "data": {
154        "static": "static",
155        "lambda": {
156          "python": "lambda text: 0",
157          "perl": "sub { 0 }",
158          "php": "return false;",
159          "ruby": "proc { |text| false }",
160          "js": "function(txt) { return false }"
161        }
162      },
163      "name": "Inverted Section",
164      "template": "<{{^lambda}}{{static}}{{/lambda}}>",
165      "desc": "Lambdas used for inverted sections should be considered truthy."
166    }
167  ]
168}