Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b08ba69

Browse files
Define local vars that survive even inside #each loops
1 parent 7a7beba commit b08ba69

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

‎st.js‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
},
173173
};
174174
var TRANSFORM = {
175+
memory: {},
175176
transform: function(template, data, injection, serialized) {
176177
var selector = null;
177178
if (/#include/.test(JSON.stringify(template))) {
@@ -295,6 +296,23 @@
295296
if (fun) {
296297
if (fun.name === '#include') {
297298
// this was handled above (before the for loop) so just ignore
299+
} else if (fun.name === '#let') {
300+
if (Helper.is_array(template[key]) && template[key].length == 2) {
301+
var defs = template[key][0];
302+
var real_template = template[key][1];
303+
304+
// 1. Parse the first item to assign variables
305+
var parsed_keys = TRANSFORM.run(defs, data);
306+
307+
// 2. modify the data
308+
for(var parsed_key in parsed_keys) {
309+
TRANSFORM.memory[parsed_key] = parsed_keys[parsed_key];
310+
data[parsed_key] = parsed_keys[parsed_key];
311+
}
312+
313+
// 2. Pass it into TRANSFORM.run
314+
result = TRANSFORM.run(real_template, data);
315+
}
298316
} else if (fun.name === '#concat') {
299317
if (Helper.is_array(template[key])) {
300318
result = [];
@@ -326,12 +344,26 @@
326344
// will have snuck into the final result
327345
if(typeof data === 'object') {
328346
delete result["$index"];
347+
348+
// #let handling
349+
for (var declared_vars in TRANSFORM.memory) {
350+
delete result[declared_vars];
351+
}
329352
} else {
330353
delete String.prototype.$index;
331354
delete Number.prototype.$index;
332355
delete Function.prototype.$index;
333356
delete Array.prototype.$index;
334357
delete Boolean.prototype.$index;
358+
359+
// #let handling
360+
for (var declared_vars in TRANSFORM.memory) {
361+
delete String.prototype[declared_vars];
362+
delete Number.prototype[declared_vars];
363+
delete Function.prototype[declared_vars];
364+
delete Array.prototype[declared_vars];
365+
delete Boolean.prototype[declared_vars];
366+
}
335367
}
336368
}
337369
} else if (fun.name === '#each') {
@@ -345,12 +377,24 @@
345377
// temporarily set $index
346378
if(typeof newData[index] === 'object') {
347379
newData[index]["$index"] = index;
380+
// #let handling
381+
for (var declared_vars in TRANSFORM.memory) {
382+
newData[index][declared_vars] = TRANSFORM.memory[declared_vars];
383+
}
348384
} else {
349385
String.prototype.$index = index;
350386
Number.prototype.$index = index;
351387
Function.prototype.$index = index;
352388
Array.prototype.$index = index;
353389
Boolean.prototype.$index = index;
390+
// #let handling
391+
for (var declared_vars in TRANSFORM.memory) {
392+
String.prototype[declared_vars] = TRANSFORM.memory[declared_vars];
393+
Number.prototype[declared_vars] = TRANSFORM.memory[declared_vars];
394+
Function.prototype[declared_vars] = TRANSFORM.memory[declared_vars];
395+
Array.prototype[declared_vars] = TRANSFORM.memory[declared_vars];
396+
Boolean.prototype[declared_vars] = TRANSFORM.memory[declared_vars];
397+
}
354398
}
355399

356400
// run
@@ -359,12 +403,24 @@
359403
// clean up $index
360404
if(typeof newData[index] === 'object') {
361405
delete newData[index]["$index"];
406+
// #let handling
407+
for (var declared_vars in TRANSFORM.memory) {
408+
delete newData[index][declared_vars];
409+
}
362410
} else {
363411
delete String.prototype.$index;
364412
delete Number.prototype.$index;
365413
delete Function.prototype.$index;
366414
delete Array.prototype.$index;
367415
delete Boolean.prototype.$index;
416+
// #let handling
417+
for (var declared_vars in TRANSFORM.memory) {
418+
delete String.prototype[declared_vars];
419+
delete Number.prototype[declared_vars];
420+
delete Function.prototype[declared_vars];
421+
delete Array.prototype[declared_vars];
422+
delete Boolean.prototype[declared_vars];
423+
}
368424
}
369425

370426
if (loop_item) {
@@ -849,6 +905,9 @@
849905
if (key === '$root' || key === '$index') {
850906
return undefined;
851907
}
908+
if (key in TRANSFORM.memory) {
909+
return undefined;
910+
}
852911
if (typeof val === 'function') {
853912
return '(' + val.toString() + ')';
854913
} else {

‎test/unit/transform/let.js‎

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
var assert = require('assert');
2+
var st = require('../../../st.js');
3+
var _ = require("underscore");
4+
var stringify = require('json-stable-stringify');
5+
6+
var compare = function(actual, expected){
7+
assert.equal(stringify(actual), stringify(expected));
8+
};
9+
10+
/*****
11+
12+
#let API:
13+
14+
takes an array of 2 items as argument.
15+
16+
item 0: The variables to assign
17+
item 1: The template to transform
18+
19+
Warning: make sure to use unique variable names, otherwise you may override unexpected variables and it may fail.
20+
21+
*****/
22+
23+
describe('$parent', function(){
24+
it("without #let assignment the context is different therefore transform doesn't work", function() {
25+
let data = {
26+
"verbs": ["buy", "use", "break", "fix"],
27+
"object": "it"
28+
}
29+
let template = {
30+
"{{#each verbs}}": "{{this}} {{object}}"
31+
}
32+
let actual = st.TRANSFORM.transform(template,data);
33+
let expected = [
34+
'buy {{object}}',
35+
'use {{object}}',
36+
'break {{object}}',
37+
'fix {{object}}'
38+
];
39+
compare(actual, expected);
40+
})
41+
it("WITH #let assignment, variables exist all throughout the transform", function() {
42+
let data = {
43+
"verbs": ["buy", "use", "break", "fix"],
44+
"object": "it"
45+
}
46+
let template = {
47+
"{{#let}}": [{
48+
"object": "{{object}}"
49+
},
50+
{
51+
"{{#each verbs}}": "{{this}} {{object}}"
52+
}
53+
]
54+
}
55+
let actual = st.TRANSFORM.transform(template,data);
56+
let expected = [
57+
'buy it',
58+
'use it',
59+
'break it',
60+
'fix it'
61+
];
62+
compare(actual, expected);
63+
})
64+
it("works through multiple loops all the way to the leaf node", function() {
65+
let data = {
66+
"verses": [
67+
["buy", "use", "break", "fix"],
68+
["charge", "point", "zoom", "press"]
69+
],
70+
"object": "it"
71+
}
72+
let template = {
73+
"{{#let}}": [{
74+
"object": "{{object}}"
75+
},
76+
{
77+
"{{#each verses}}": {
78+
"{{#each this}}": "{{this}} {{object}}"
79+
}
80+
}
81+
]
82+
}
83+
let actual = st.TRANSFORM.transform(template,data);
84+
let expected = [
85+
[ 'buy it', 'use it', 'break it', 'fix it' ],
86+
[ 'charge it', 'point it', 'zoom it', 'press it' ]
87+
];
88+
compare(actual, expected);
89+
})
90+
it("using external library", function() {
91+
let data = {
92+
"items": [{
93+
"children": ["A", "A", "B", "C", "C", "D", "E", "E"]
94+
}, {
95+
"children": ["A", "A", "A", "A"]
96+
}]
97+
}
98+
let template = {
99+
"{{#let}}": [
100+
{
101+
"_": _
102+
},
103+
{
104+
"{{#each items}}": {
105+
"{{#each _.uniq(children)}}": {
106+
"text": "{{this}}"
107+
}
108+
}
109+
}
110+
]
111+
}
112+
let actual = st.TRANSFORM.transform(template,data);
113+
let expected = [
114+
[
115+
{ text: 'A' },
116+
{ text: 'B' },
117+
{ text: 'C' },
118+
{ text: 'D' },
119+
{ text: 'E' }
120+
],
121+
[
122+
{ text: 'A' }
123+
]
124+
]
125+
compare(actual, expected);
126+
})
127+
it("#each", function() {
128+
let data = {
129+
items: [{
130+
name: "Alice",
131+
items: ["A", "L", "I"]
132+
}, {
133+
name: "Bob",
134+
items: ["B", "O", "B"]
135+
}]
136+
}
137+
let template = {
138+
"{{#each items}}": {
139+
"{{#let}}": [
140+
{
141+
"$parent": "{{this}}",
142+
"$parent_index": "{{$index}}"
143+
},
144+
{
145+
"{{#each items}}": "{{$parent.name}} {{$parent_index.toString()}} {{this}}"
146+
}
147+
]
148+
}
149+
}
150+
var actual = st.TRANSFORM.transform(template,data);
151+
var expected = [
152+
["Alice 0 A", "Alice 0 L", "Alice 0 I"],
153+
["Bob 1 B", "Bob 1 O", "Bob 1 B"]
154+
]
155+
compare(actual, expected);
156+
})
157+
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /