@peter.naydenov/morph 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +7 -0
- package/LICENSE +21 -0
- package/Migration.guide.md +3 -0
- package/README.md +207 -0
- package/dist/morph.cjs +1 -0
- package/dist/morph.esm.mjs +1 -0
- package/dist/morph.umd.js +1 -0
- package/package.json +61 -0
- package/rollup.config.js +42 -0
- package/src/main.js +100 -0
- package/src/methods/_actionSupply.js +19 -0
- package/src/methods/_chopTemplates.js +60 -0
- package/src/methods/_defineData.js +32 -0
- package/src/methods/_defineType.js +16 -0
- package/src/methods/_readTemplate.js +78 -0
- package/src/methods/_renderHolder.js +26 -0
- package/src/methods/_setupActions.js +69 -0
- package/src/methods/build.js +239 -0
- package/src/methods/render.js +26 -0
- package/src/methods/settings.js +6 -0
- package/test/01-chop.test.js +24 -0
- package/test/02-build.test.js +470 -0
- package/test/03-storage.test.js +78 -0
- package/test/04-commands.js +73 -0
- package/test/05-data.test.js +168 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import morphAPI from '../src/main.js'
|
|
2
|
+
import { expect } from 'chai'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe ( 'transformer: build', () => {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
it ( 'Simple mustache like placeholders, no actions', () => {
|
|
10
|
+
// spaces inside placeholders are ignored
|
|
11
|
+
const myTpl = {
|
|
12
|
+
template: `Your name is {{ name }}. Your age is {{age}}.`
|
|
13
|
+
}
|
|
14
|
+
const templateFn = morphAPI.build ( myTpl )
|
|
15
|
+
const result = templateFn({
|
|
16
|
+
name: 'Peter'
|
|
17
|
+
, age: 50
|
|
18
|
+
})
|
|
19
|
+
expect ( result ).to.be.equal ( 'Your name is Peter. Your age is 50.' )
|
|
20
|
+
}) // it simple mustache like placeholders, no actions
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
it ( 'Mixing actions', () => {
|
|
24
|
+
// Mix action starts with '[]'. If no name after '[]' it will be like arr.join('').
|
|
25
|
+
// If name, it is the helper function used. In our case it is 'coma'.
|
|
26
|
+
const myTpl = {
|
|
27
|
+
template : `My friends are {{ names : []coma }}.`
|
|
28
|
+
, helpers : {
|
|
29
|
+
coma: (res) => res.join(', ')
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
33
|
+
const result = templateFn({ names: ['Peter', 'Ivan'] });
|
|
34
|
+
expect ( result ).to.be.equal ( 'My friends are Peter, Ivan.' );
|
|
35
|
+
}) // it mixing actions
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
it ( 'No placeholders', () => {
|
|
40
|
+
const myTpl = {
|
|
41
|
+
template : `My name is Peter.`
|
|
42
|
+
}
|
|
43
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
44
|
+
const result = templateFn(); // No data required
|
|
45
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' );
|
|
46
|
+
}) // it No placeholders
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
it ( 'Data action to change the result', () => {
|
|
51
|
+
const myTpl = {
|
|
52
|
+
// placeholder will be fullfiled with data[job], but data function 'jobPossible' will filter the result
|
|
53
|
+
template : `My job is {{ job : >jobPossible }}.`
|
|
54
|
+
, helpers : {
|
|
55
|
+
jobPossible: (text) => {
|
|
56
|
+
if ( text === 'Software Engineer' ) return 'hidden'
|
|
57
|
+
else return text
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
62
|
+
const result = templateFn({ job: 'Software Engineer' });
|
|
63
|
+
const result2 = templateFn({ job: 'doctor' });
|
|
64
|
+
|
|
65
|
+
expect ( result ).to.be.equal ( 'My job is hidden.' );
|
|
66
|
+
expect ( result2 ).to.be.equal ( 'My job is doctor.' );
|
|
67
|
+
}) // it data action to change the result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
it ( 'Keep a placeholder', () => {
|
|
72
|
+
const myTpl = {
|
|
73
|
+
// placeholder will be fullfiled with data[job], but data function 'jobPossible' will filter the result
|
|
74
|
+
template : `My job is {{ job : >jobPossible }}.`
|
|
75
|
+
, helpers : {
|
|
76
|
+
jobPossible: (text) => {
|
|
77
|
+
if ( text === 'Software Engineer' ) return null // null means: Do not render this field
|
|
78
|
+
else return text
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
83
|
+
const result = templateFn({ job: 'Software Engineer' });
|
|
84
|
+
expect ( result ).to.be.equal ( 'My job is {{ job : >jobPossible }}.' );
|
|
85
|
+
}) // it Keep placeholder
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
it ( 'Long chain with variaty of actions: Data, render, and mixing', () => {
|
|
90
|
+
const myTpl = {
|
|
91
|
+
template: `Hello, {{ name : ul, [], li, >fromList }}! {{ more }}`
|
|
92
|
+
, helpers: {
|
|
93
|
+
fromList: name => (['Peter', 'Ivan'].includes(name) ? name : 'stranger')
|
|
94
|
+
|
|
95
|
+
, ul : `<ul>{{text}}</ul>`
|
|
96
|
+
, li : `<li>{{text}}</li>`
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const templateFn = morphAPI.build ( myTpl )
|
|
100
|
+
const result = templateFn({
|
|
101
|
+
name: [ 'Peter', 'Stoyan' ]
|
|
102
|
+
, more: `extended version`
|
|
103
|
+
})
|
|
104
|
+
expect ( result ).to.be.equal ( 'Hello, <ul><li>Peter</li><li>stranger</li></ul>! extended version' )
|
|
105
|
+
}) // it Long chain with variaty of actions
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
it ( 'Data action on array of objects', () => {
|
|
110
|
+
const myTpl = {
|
|
111
|
+
template: `My friends: {{ friends : ul, [], li, >people }}`
|
|
112
|
+
, helpers: {
|
|
113
|
+
li: `<li>{{name}}: {{state}}</li>`,
|
|
114
|
+
ul: `<ul>{{text}}</ul>`,
|
|
115
|
+
people: (res) => {
|
|
116
|
+
if ( res.age < 30 ) res.state = 'young'
|
|
117
|
+
else res.state = 'old'
|
|
118
|
+
return res
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const templateFn = morphAPI.build ( myTpl )
|
|
123
|
+
const result = templateFn({
|
|
124
|
+
friends: [
|
|
125
|
+
{ name: 'Peter', age: 30 }
|
|
126
|
+
, { name: 'Ivan', age: 25 }
|
|
127
|
+
, { name: 'Stoyan', age: 35 }
|
|
128
|
+
]
|
|
129
|
+
})
|
|
130
|
+
expect ( result ).to.be.equal ( 'My friends: <ul><li>Peter: old</li><li>Ivan: young</li><li>Stoyan: old</li></ul>' )
|
|
131
|
+
}) // it data action on array of objects
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
it ( 'Data array', () => {
|
|
136
|
+
// If input data is an array, we render each element with the template
|
|
137
|
+
const myTpl = {
|
|
138
|
+
template: `My name is {{ name }}. My age is {{ age }}.`
|
|
139
|
+
}
|
|
140
|
+
const templateFn = morphAPI.build ( myTpl )
|
|
141
|
+
const result = templateFn([
|
|
142
|
+
{ name: 'Peter', age: 30 }
|
|
143
|
+
, { name: 'Ivan', age: 25 }
|
|
144
|
+
, { name: 'Stoyan', age: 35 }
|
|
145
|
+
])
|
|
146
|
+
// Result is array of rendered templates
|
|
147
|
+
expect ( result ).to.have.length ( 3 )
|
|
148
|
+
expect ( result[0] ).to.be.equal ( 'My name is Peter. My age is 30.' )
|
|
149
|
+
expect ( result[1] ).to.be.equal ( 'My name is Ivan. My age is 25.' )
|
|
150
|
+
expect ( result[2] ).to.be.equal ( 'My name is Stoyan. My age is 35.' )
|
|
151
|
+
}) // it data array
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
it ( 'Use all data: @all, @root', () => { // *** Address full data to placeholder -> @all
|
|
156
|
+
// Both are equivalent: @all === @root
|
|
157
|
+
const myTpl = {
|
|
158
|
+
template : `My name is {{ name }}. My web page is {{ @all : a, >morphWeb }}. Contact me on {{ @root : a , >morphMail }}.`
|
|
159
|
+
, helpers : {
|
|
160
|
+
a : `<a href="{{link}}">{{text}}</a>`
|
|
161
|
+
, morphWeb : ( data ) => {
|
|
162
|
+
data.link = data.web
|
|
163
|
+
data.text = data.web
|
|
164
|
+
return data
|
|
165
|
+
}
|
|
166
|
+
, morphMail: ( data ) => {
|
|
167
|
+
data.link = data.email
|
|
168
|
+
data.text = 'e-mail'
|
|
169
|
+
return data
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const templateFn = morphAPI.build ( myTpl )
|
|
174
|
+
const result = templateFn({
|
|
175
|
+
name : 'Peter'
|
|
176
|
+
, web : 'example.com'
|
|
177
|
+
, email : 'peter@example.com'
|
|
178
|
+
})
|
|
179
|
+
expect ( result ).to.be.equal ( 'My name is Peter. My web page is <a href="example.com">example.com</a>. Contact me on <a href="peter@example.com">e-mail</a>.' )
|
|
180
|
+
}) // it use all data @all
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
it ( 'Ignore rendering if data is null', () => {
|
|
185
|
+
// Ignore rendering [] lines that have missing data
|
|
186
|
+
const myTpl = {
|
|
187
|
+
template : `People and their jobs: {{ jobList : ul, [], li, >jobItems }}`
|
|
188
|
+
, helpers : {
|
|
189
|
+
ul : `<ul>{{text}}</ul>`
|
|
190
|
+
, li : `<li>{{name}} - {{job}}</li>`
|
|
191
|
+
, jobItems : ( data ) => { // It's a data function
|
|
192
|
+
// If data-function returns null, it will be ignored in template render
|
|
193
|
+
if ( !data.name || !data.job ) return null
|
|
194
|
+
else return data
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const data = {
|
|
199
|
+
jobList: [
|
|
200
|
+
{name: 'Peter', job: 'Software Engineer'}
|
|
201
|
+
, {name: 'Ivan' } // No job - ignored in template render
|
|
202
|
+
, {name: 'Stoyan', job: 'designer' }
|
|
203
|
+
]
|
|
204
|
+
};
|
|
205
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
206
|
+
const result = templateFn(data);
|
|
207
|
+
expect ( result ).to.be.equal ( 'People and their jobs: <ul><li>Peter - Software Engineer</li><li>Stoyan - designer</li></ul>' )
|
|
208
|
+
|
|
209
|
+
}) // it Ignore rendering if data is null
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
it ( 'Ignore rendering fields that have no data', () => {
|
|
214
|
+
const myTpl = {
|
|
215
|
+
template : `My name is {{ name }}.`
|
|
216
|
+
|
|
217
|
+
};
|
|
218
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
219
|
+
const result = templateFn({ person: 'Peter' });
|
|
220
|
+
expect ( result ).to.be.equal ( 'My name is {{ name }}.' )
|
|
221
|
+
}) // it Ignore rendering fields that have no data
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
it ( 'How to hide a placeholder', () => {
|
|
226
|
+
// Hide a placeholder - provide an empty string
|
|
227
|
+
const myTpl = {
|
|
228
|
+
template : `My name is {{ name }}.{{ extraData}}`
|
|
229
|
+
}
|
|
230
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
231
|
+
const result = templateFn({
|
|
232
|
+
name: 'Peter'
|
|
233
|
+
, extraData: '' // Provide an empty string to hide a placeholder
|
|
234
|
+
});
|
|
235
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' )
|
|
236
|
+
}) // it how to hide a placeholder
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
it ( 'Data as null or undefined', () => {
|
|
241
|
+
// If data is null or undefined, should return the template without any changes
|
|
242
|
+
const myTpl = {
|
|
243
|
+
template : `My name is {{ name }}.{{ extraData}}`
|
|
244
|
+
}
|
|
245
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
246
|
+
const result = templateFn( null );
|
|
247
|
+
expect ( result ).to.be.equal ( myTpl.template )
|
|
248
|
+
}) // it data as null or undefined
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
it ( 'Sequence of render processes with object', () => {
|
|
253
|
+
// Write result of render to field 'text' and preserve other existing fields
|
|
254
|
+
const myTpl = {
|
|
255
|
+
template : `Here is - {{ website: a, setText }}.`
|
|
256
|
+
, helpers : {
|
|
257
|
+
a : `<a href="{{link}}">{{text}}</a>`
|
|
258
|
+
, setText : `{{about}}: {{domain}}`
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
262
|
+
const result = templateFn({
|
|
263
|
+
website : {
|
|
264
|
+
domain: `example.com`
|
|
265
|
+
, about : `My portfolio`
|
|
266
|
+
, link : `http://example.com`
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
expect ( result ).to.be.equal ( 'Here is - <a href="http://example.com">My portfolio: example.com</a>.' )
|
|
270
|
+
}) // it sequence of render processes with object
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
it ( 'Action only', () => {
|
|
275
|
+
// Use helper functions to insert dynamic data from programming environment(state, variable, etc.)
|
|
276
|
+
// Templates that are using actions only, don't need a input data object. It's a dynamic data.
|
|
277
|
+
const myState = 'active'
|
|
278
|
+
const myTpl = {
|
|
279
|
+
template: `Profile {{ : state }}.`
|
|
280
|
+
, helpers: {
|
|
281
|
+
state: () => myState
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
285
|
+
const result = templateFn();
|
|
286
|
+
expect ( result ).to.be.equal ( 'Profile active.' )
|
|
287
|
+
}) // it action only
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
it ( 'Mixing a string', () => {
|
|
292
|
+
// Providing a string to a mixing function should not break the result.
|
|
293
|
+
const myTpl = {
|
|
294
|
+
template: `My name is {{ : [], >name }}`
|
|
295
|
+
, helpers: {
|
|
296
|
+
name: ( data ) => data.name
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
300
|
+
const result = templateFn({ name: 'Stoyan'});
|
|
301
|
+
expect ( result ).to.be.equal ( 'My name is Stoyan' )
|
|
302
|
+
}) // it mixing a string
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
it ( 'Broken template', () => {
|
|
307
|
+
// If template is broken, the result should be a string, representation of the error.
|
|
308
|
+
const myTpl = {
|
|
309
|
+
template : `My {{ {{ welcome }}`
|
|
310
|
+
};
|
|
311
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
312
|
+
const result = templateFn();
|
|
313
|
+
expect ( result ).to.be.equal ( 'Error: Nested placeholders. Close placeholder before open new one.' )
|
|
314
|
+
}) // it broken template
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
it ( 'Data only - object. Default field is "text"', () => {
|
|
319
|
+
// If provided data is object - default field is 'text'
|
|
320
|
+
const myTpl = {
|
|
321
|
+
template : `My name is {{ person }}.`
|
|
322
|
+
};
|
|
323
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
324
|
+
const result = templateFn({ person: { text: 'Ivan', age: 25 }});
|
|
325
|
+
expect ( result ).to.be.equal ( 'My name is Ivan.' )
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
it ( 'Data only - array. Should render first element', () => {
|
|
331
|
+
// If provided data is array - default field is the first element of the array
|
|
332
|
+
const myTpl = {
|
|
333
|
+
template : `My name is {{ person }}.`
|
|
334
|
+
};
|
|
335
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
336
|
+
const result = templateFn({ person: [ 'John', 'Milen', 'Vladislav' ]});
|
|
337
|
+
expect ( result ).to.be.equal ( 'My name is John.' )
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
it ( 'Auto mixing array results', () => {
|
|
343
|
+
// Auto mix if in the end of the action-list the result is still an array
|
|
344
|
+
const myTpl = {
|
|
345
|
+
template: `My friends are {{ friendsList: li }}.`
|
|
346
|
+
, helpers : {
|
|
347
|
+
li: `<li>{{ text }}</li>`
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
351
|
+
const result = templateFn({ friendsList: [ 'John', 'Milen', 'Vladislav' ]});
|
|
352
|
+
expect ( result ).to.be.equal ( 'My friends are <li>John</li><li>Milen</li><li>Vladislav</li>.' )
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
it ( 'Nested templates', () => {
|
|
358
|
+
// Use helper functions to render other templates
|
|
359
|
+
|
|
360
|
+
const secondaryTpl = { // Template for nesting
|
|
361
|
+
template : `My friends are {{ names }}.`
|
|
362
|
+
}
|
|
363
|
+
const secTemplateFn = morphAPI.build ( secondaryTpl );
|
|
364
|
+
|
|
365
|
+
const myTpl = { // Top level template
|
|
366
|
+
template : `My name is {{ name }}. {{ friends: friendListing, []coma }}`
|
|
367
|
+
, helpers: {
|
|
368
|
+
friendListing: ( d ) => {
|
|
369
|
+
return secTemplateFn ({ names : d }) // Nested template render
|
|
370
|
+
}
|
|
371
|
+
, coma: ( res ) => res.join(', ')
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
375
|
+
const result = templateFn({
|
|
376
|
+
name : 'Peter'
|
|
377
|
+
, friends: [ 'John', 'Milen', 'Vladislav' ]
|
|
378
|
+
});
|
|
379
|
+
expect ( result ).to.be.equal ( 'My name is Peter. My friends are John, Milen, Vladislav.' )
|
|
380
|
+
}) // it nested templates
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
it ( 'List - Data deep object', () => {
|
|
385
|
+
const myTpl = {
|
|
386
|
+
template : `My list: {{ list: ul , [], li, #, line }}.`
|
|
387
|
+
, helpers: {
|
|
388
|
+
line: `{{ name }} - {{ age }}`
|
|
389
|
+
, ul: `<ul>{{ text }}</ul>`
|
|
390
|
+
, li: `<li>{{ text }}</li>`
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
};
|
|
394
|
+
const data = {
|
|
395
|
+
list : [
|
|
396
|
+
'John'
|
|
397
|
+
, {
|
|
398
|
+
name: 'Milen'
|
|
399
|
+
, age: 25
|
|
400
|
+
}
|
|
401
|
+
, 'Vladislav'
|
|
402
|
+
, {
|
|
403
|
+
name: 'Stoyan'
|
|
404
|
+
, age: 30}
|
|
405
|
+
]
|
|
406
|
+
};
|
|
407
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
408
|
+
const result = templateFn ( data );
|
|
409
|
+
expect ( result ).to.be.equal ( 'My list: <ul><li>John</li><li>Milen - 25</li><li>Vladislav</li><li>Stoyan - 30</li></ul>.' )
|
|
410
|
+
}) // it list - data deep object
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
it ( 'Object - Data deep object', () => {
|
|
415
|
+
const myTpl = {
|
|
416
|
+
template : `Profile: {{ me: ul , [], li, #, line }}.`
|
|
417
|
+
, helpers: {
|
|
418
|
+
line: `({{ height}}cm,{{ weight}}kg)`
|
|
419
|
+
, ul: `<ul>{{ text }}</ul>`
|
|
420
|
+
, li: `<li>{{ name }} - {{stats}}</li>`
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
const data = {
|
|
424
|
+
me : {
|
|
425
|
+
name: 'Peter'
|
|
426
|
+
, stats : {
|
|
427
|
+
age: 50
|
|
428
|
+
, height: 180
|
|
429
|
+
, weight: 66
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
434
|
+
const result = templateFn ( data );
|
|
435
|
+
expect ( result ).to.be.equal ( 'Profile: <ul><li>Peter - (180cm,66kg)</li></ul>.' )
|
|
436
|
+
}) // it object - data deep object
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
it ( 'Use extra renders: "+" ', () => {
|
|
441
|
+
let touch = false;
|
|
442
|
+
const myTpl = {
|
|
443
|
+
template : `Profile: {{ me: +line }}.`
|
|
444
|
+
, helpers: {
|
|
445
|
+
line: ( x ) => {
|
|
446
|
+
expect ( x ).to.have.property ( 'stats' )
|
|
447
|
+
expect ( x ).to.have.property ( 'name' )
|
|
448
|
+
const { height, weight } = x.stats;
|
|
449
|
+
touch = true
|
|
450
|
+
return `${x.name} - (${height}cm,${weight}kg)`
|
|
451
|
+
} // line helper
|
|
452
|
+
} // helpers
|
|
453
|
+
};
|
|
454
|
+
const data = {
|
|
455
|
+
me : {
|
|
456
|
+
name: 'Peter'
|
|
457
|
+
, stats : {
|
|
458
|
+
age: 50
|
|
459
|
+
, height: 180
|
|
460
|
+
, weight: 66
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
const templateFn = morphAPI.build ( myTpl );
|
|
465
|
+
const result = templateFn ( data );
|
|
466
|
+
expect ( result ).to.be.equal ( 'Profile: Peter - (180cm,66kg).' )
|
|
467
|
+
expect ( touch ).to.be.true
|
|
468
|
+
}) // it use extra renders "+"
|
|
469
|
+
|
|
470
|
+
}) // Describe
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import morph from '../src/main.js'
|
|
2
|
+
import { expect } from 'chai'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe ( 'morph: storage', () => {
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
it ( 'Add template to default storage', () => {
|
|
10
|
+
const myTpl = {
|
|
11
|
+
template : `My name is {{ name }}.`
|
|
12
|
+
};
|
|
13
|
+
morph.add ( 'myTpl', morph.build ( myTpl ) );
|
|
14
|
+
const result = morph.get ( 'myTpl' )({ name: 'Peter' })
|
|
15
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' )
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
it ( 'Add template definition to default storage', () => {
|
|
21
|
+
morph.clear ()
|
|
22
|
+
const myTpl = {
|
|
23
|
+
template : `My name is {{ name }}.`
|
|
24
|
+
};
|
|
25
|
+
// Can we check if the template is already in the storage?
|
|
26
|
+
morph.add ( 'myName', myTpl );
|
|
27
|
+
const result = morph.get ( 'myName' )({ name: 'Peter' })
|
|
28
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' )
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
it ( 'Wrong template description', () => {
|
|
34
|
+
//
|
|
35
|
+
morph.clear ()
|
|
36
|
+
console.error = ( str ) => { // Override console.error to avoid console output
|
|
37
|
+
expect ( str ).to.be.equal ( 'Error: Template "fake" looks broken and is not added to storage.' )
|
|
38
|
+
}
|
|
39
|
+
const fakeTpl = { a: 12, b: 'Hello' };
|
|
40
|
+
morph.add ( 'fake', fakeTpl );
|
|
41
|
+
}) // it wrong template description
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
it ( 'Add component to default storage', () => {
|
|
46
|
+
morph.clear ()
|
|
47
|
+
const myTpl = { template: `My name is {{ name }}.` };
|
|
48
|
+
const myTplFn = morph.build ( myTpl );
|
|
49
|
+
morph.add ( 'myTpl', myTplFn );
|
|
50
|
+
const result = morph.get ( 'myTpl' )({ name: 'Peter' })
|
|
51
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' )
|
|
52
|
+
}) // it add component to default storage
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
it ( 'Add template definition to custom storage', () => {
|
|
57
|
+
// Using a custom named storage if preffer to organize templates somehow
|
|
58
|
+
morph.clear () // Clear the storage from previous tests
|
|
59
|
+
const myTpl = { template: `My name is {{ name }}.` };
|
|
60
|
+
morph.add ( 'myName', myTpl, 'hidden' ); // Provide a custom storage name as 3rd argument
|
|
61
|
+
|
|
62
|
+
let result = morph.get ('myName')({ name: 'Peter' });
|
|
63
|
+
// result of morph.get() is a function that returns a error.
|
|
64
|
+
// Error will popup as a rendering result
|
|
65
|
+
|
|
66
|
+
expect ( result ).to.be.equal ( 'Error: Template "myName" does not exist in storage "default".' )
|
|
67
|
+
result = morph.get ('myName', 'hidden')({ name: 'Peter' })
|
|
68
|
+
expect ( result ).to.be.equal ( 'My name is Peter.' )
|
|
69
|
+
|
|
70
|
+
let list = morph.list ();
|
|
71
|
+
expect ( list ).to.have.length ( 0 )
|
|
72
|
+
|
|
73
|
+
list = morph.list ('hidden');
|
|
74
|
+
expect ( list ).to.have.length ( 1 )
|
|
75
|
+
expect ( list[0] ).to.be.equal ( 'myName' )
|
|
76
|
+
}) // it add template definition to custom storage
|
|
77
|
+
|
|
78
|
+
}) // describe
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import morph from '../src/main.js'
|
|
2
|
+
import { expect } from 'chai'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe ( 'morph: commands', () => {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
it ( 'Request a template', () => {
|
|
11
|
+
// Command 'raw'
|
|
12
|
+
const myTpl = { template : `My name is {{ name }}.` };
|
|
13
|
+
morph.add ( 'myName', myTpl );
|
|
14
|
+
const result = morph.get ( 'myName' )('raw')
|
|
15
|
+
expect ( result ).to.be.equal ( 'My name is {{ name }}.' )
|
|
16
|
+
}) // it request a template
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
it ( 'Request a handshake', () => {
|
|
21
|
+
let demo = { name: 'Stoyan' }
|
|
22
|
+
const myTpl = {
|
|
23
|
+
template : `My name is {{ name }}.`
|
|
24
|
+
, handshake : demo
|
|
25
|
+
};
|
|
26
|
+
morph.add ( 'myName', myTpl );
|
|
27
|
+
const result = morph.get ( 'myName' )('handshake')
|
|
28
|
+
expect ( result ).to.be.deep.equal ( demo )
|
|
29
|
+
}) // it request a handshake
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
it ( 'Request a demo', () => {
|
|
34
|
+
// Render a template with the handshake
|
|
35
|
+
let demo = { name: 'Stoyan' }
|
|
36
|
+
const myTpl = {
|
|
37
|
+
template : `My name is {{ name }}.`
|
|
38
|
+
, handshake : demo
|
|
39
|
+
};
|
|
40
|
+
morph.add ( 'myName', myTpl );
|
|
41
|
+
const result = morph.get ( 'myName' )('demo')
|
|
42
|
+
expect ( result ).to.be.equal ( 'My name is Stoyan.' )
|
|
43
|
+
}) // it request a demo
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
it ( 'Wrong command to component', () => {
|
|
49
|
+
// Commands other than 'raw', 'handshake' and 'demo' should return an error.
|
|
50
|
+
let demo = { name: 'Stoyan' }
|
|
51
|
+
const myTpl = {
|
|
52
|
+
template : `My name is {{ name }}.`
|
|
53
|
+
, handshake : demo
|
|
54
|
+
};
|
|
55
|
+
morph.add ( 'myName', myTpl );
|
|
56
|
+
const result = morph.get ( 'myName' )('fake')
|
|
57
|
+
expect ( result ).to.be.equal ( 'Error: Wrong command "fake". Available commands: raw, demo, handshake, placeholders.' )
|
|
58
|
+
}) // it wrong command to component
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
it ( 'See placeholders', () => {
|
|
62
|
+
let demo = { name: 'Stoyan', age: 30 }
|
|
63
|
+
const myTpl = {
|
|
64
|
+
template : `My name is {{ name }}. Age {{ age }}.`
|
|
65
|
+
, handshake : demo
|
|
66
|
+
};
|
|
67
|
+
morph.add ( 'myName', myTpl );
|
|
68
|
+
const result = morph.get ( 'myName' )('placeholders')
|
|
69
|
+
expect ( result ).to.be.equal ( '{{ name }}, {{ age }}' )
|
|
70
|
+
}) // it see placeholders
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
}) // describe
|