@peter.naydenov/morph 3.2.0 → 3.3.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 +5 -0
- package/README.md +32 -12
- package/build.architecture.png +0 -0
- package/dist/methods/actionData.d.ts +10 -0
- package/dist/methods/actionExtendedRender.d.ts +10 -0
- package/dist/methods/actionMix.d.ts +10 -0
- package/dist/methods/actionRender.d.ts +13 -0
- package/dist/methods/actionSave.d.ts +8 -0
- package/dist/methods/build.d.ts +28 -2
- package/dist/methods/executeActions.d.ts +11 -0
- package/dist/methods/processCommands.d.ts +46 -0
- package/dist/methods/processPlaceholders.d.ts +27 -0
- package/dist/methods/render.d.ts +9 -20
- package/package.json +1 -1
- package/src/methods/_renderHolder.js +13 -7
- package/src/methods/actionData.js +30 -0
- package/src/methods/actionExtendedRender.js +28 -0
- package/src/methods/actionMix.js +66 -0
- package/src/methods/actionRender.js +86 -0
- package/src/methods/actionSave.js +9 -0
- package/src/methods/build.js +123 -404
- package/src/methods/executeActions.js +65 -0
- package/src/methods/processCommands.js +97 -0
- package/src/methods/processPlaceholders.js +155 -0
- package/src/methods/render.js +23 -49
package/src/methods/build.js
CHANGED
|
@@ -1,19 +1,36 @@
|
|
|
1
|
-
import _chopTemplate
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import _chopTemplate from "./_chopTemplates.js"
|
|
2
|
+
import _readTemplate from "./_readTemplate.js"
|
|
3
|
+
import _defineDataType from "./_defineType.js"
|
|
4
|
+
import walk from '@peter.naydenov/walk'
|
|
5
|
+
import processPlaceholders from './processPlaceholders.js'
|
|
6
|
+
import {
|
|
7
|
+
handleDebug
|
|
8
|
+
, handleSet
|
|
9
|
+
, handleSnippets } from './processCommands.js'
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @callback UseHelperFn
|
|
14
|
+
* @param {string} name - Name of the helper to call.
|
|
15
|
+
* @param {any} [data] - Optional data override.
|
|
16
|
+
* @returns {any} Result of the helper call.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @callback HelperFn
|
|
21
|
+
* @param {object} args
|
|
22
|
+
* @param {any} args.data - The data context.
|
|
23
|
+
* @param {object} args.dependencies - Injected dependencies.
|
|
24
|
+
* @param {any} [args.full] - Full data context.
|
|
25
|
+
* @param {UseHelperFn} [args.useHelper] - Function to call other helpers.
|
|
26
|
+
* @param {object} [args.memory] - internal memory state.
|
|
27
|
+
* @returns {any} Rendered output.
|
|
28
|
+
*/
|
|
12
29
|
|
|
13
30
|
/**
|
|
14
31
|
* @typedef {Object} Template
|
|
15
32
|
* @property {string} template - Data to be rendered;
|
|
16
|
-
* @property {
|
|
33
|
+
* @property {Object.<string, HelperFn|string>} [helpers] - Optional. Object with helper functions or simple templates for this template;
|
|
17
34
|
* @property {object} [handshake] - Optional. Example for data to be rendered with;
|
|
18
35
|
*/
|
|
19
36
|
|
|
@@ -32,401 +49,103 @@ import walk from '@peter.naydenov/walk'
|
|
|
32
49
|
* @param {object} [buildDependencies] - Optional. External dependencies injected;
|
|
33
50
|
* @returns {function|tupleResult} - rendering function
|
|
34
51
|
*/
|
|
35
|
-
function build
|
|
36
|
-
let { hasError, placeholders, chop, helpers, handshake, snippets } = _readTemplate
|
|
37
|
-
|
|
38
|
-
if ( hasError ) {
|
|
39
|
-
function fail () { return hasError }
|
|
40
|
-
return extra ? [ false, fail ] : fail
|
|
41
|
-
}
|
|
42
|
-
else { // If NO Error:
|
|
43
|
-
const originalPlaceholders = structuredClone ( placeholders );
|
|
44
|
-
// *** Template recognition complete. Start building the rendering function -->
|
|
45
|
-
/**
|
|
46
|
-
* Processes template rendering commands with provided data, dependencies, and optional post-processing functions.
|
|
47
|
-
*
|
|
48
|
-
* @function success
|
|
49
|
-
* @typedef { 'render' | 'debug' | 'snippets' | 'curry' | 'set' } Command
|
|
50
|
-
* @param {Command} [command='render'] - The command to execute. Supported commands: 'render', 'debug', 'snippets', 'curry', 'set', or 'snippets:<names>'.
|
|
51
|
-
* @param {Object|string} [d={}] - The data object to render, or a string instruction ('raw', 'demo', 'handshake', 'placeholders', 'count').
|
|
52
|
-
* @param {Object} [dependencies={}] - Additional dependencies to be merged with internal dependencies.
|
|
53
|
-
* @param {...any} args - Optional post-processing functions to apply to the rendered output.
|
|
54
|
-
* @returns {string|Array[]|function} The rendered template, snippets, data, or new function depending on the command and input.
|
|
55
|
-
*
|
|
56
|
-
* @throws {Error} If an unsupported command or instruction is provided.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* // Render a template with data
|
|
60
|
-
* success('render', { name: 'Alice' }, { helperFn });
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* // Get raw template
|
|
64
|
-
* success('debug', 'raw');
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* // Get count of remaining placeholders
|
|
68
|
-
* success('debug', 'count');
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* // Render only specific snippets
|
|
72
|
-
* success('snippets:header,footer', { ... });
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* // Curry partial data and get new render function
|
|
76
|
-
* const curried = success('curry', { partial: 'data' });
|
|
77
|
-
* curried('render', { more: 'data' });
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* // Set placeholders and get modified template
|
|
81
|
-
* const modified = success('set', { placeholders: { key: 'value' } });
|
|
82
|
-
*/
|
|
83
|
-
function success ( command='render', d={}, dependencies={}, ...args ) {
|
|
84
|
-
const cuts = structuredClone ( chop )
|
|
85
|
-
let onlySnippets = false;
|
|
86
|
-
if ( typeof command !== 'string' ) return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
87
|
-
if ( ![ 'render', 'debug', 'snippets', 'set', 'curry'].includes ( command ) && !command.startsWith('snippets') ) return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
88
|
-
|
|
89
|
-
if ( command.startsWith ( 'snippets') && command.includes ( ':' ) ) {
|
|
90
|
-
onlySnippets = true
|
|
91
|
-
let snippetNames = command.split ( ':' )
|
|
92
|
-
.slice ( 1 )[0]
|
|
93
|
-
.trim()
|
|
94
|
-
.split ( ',' )
|
|
95
|
-
.map ( t => t.trim() )
|
|
96
|
-
placeholders = snippetNames.map ( item => snippets [ item ])
|
|
97
|
-
}
|
|
98
|
-
else if ( command === 'snippets' ) {
|
|
99
|
-
onlySnippets = true
|
|
100
|
-
}
|
|
101
|
-
else if ( command === 'set' ) {
|
|
102
|
-
if ( typeof d !== 'object' || !d ) return `Error: 'set' command requires an object with placeholders, helpers, handshake.`
|
|
103
|
-
// Merge helpers
|
|
104
|
-
const newHelpers = { ...helpers, ...(d.helpers || {}) }
|
|
105
|
-
|
|
106
|
-
// Merge handshake
|
|
107
|
-
const newHandshake = handshake ? { ...handshake, ...(d.handshake || {}) } : d.handshake || {}
|
|
108
|
-
// Modify chop for placeholders
|
|
109
|
-
const newChop = [...chop]
|
|
110
|
-
if ( d.placeholders ) {
|
|
111
|
-
Object.entries ( d.placeholders ).forEach ( ([k,v]) => {
|
|
112
|
-
if ( !isNaN(k) ) { // If k is a number
|
|
113
|
-
let index = placeholders[k].index;
|
|
114
|
-
newChop[index] = v
|
|
115
|
-
} // if k is a number
|
|
116
|
-
else { // If k is a string
|
|
117
|
-
let plx = placeholders.find ( p => p.name === k )
|
|
118
|
-
newChop[ plx.index ] = v
|
|
119
|
-
}
|
|
120
|
-
}) // placeholders
|
|
121
|
-
} // if d.placeholders
|
|
122
|
-
const newTemplateStr = newChop.join ( '' );
|
|
123
|
-
const newTpl = {
|
|
124
|
-
template: newTemplateStr,
|
|
125
|
-
helpers: newHelpers,
|
|
126
|
-
handshake: newHandshake
|
|
127
|
-
}
|
|
128
|
-
const result = build ( newTpl, false, buildDependencies )
|
|
129
|
-
return typeof result === 'function' ? result : () => result
|
|
130
|
-
} else if ( command === 'curry' ) {
|
|
131
|
-
// Render the template with current data
|
|
132
|
-
const rendered = success('render', d, dependencies, ...args)
|
|
133
|
-
// Create new template with rendered as template, keep helpers and handshake
|
|
134
|
-
const newTpl = {
|
|
135
|
-
template: rendered,
|
|
136
|
-
helpers,
|
|
137
|
-
handshake
|
|
138
|
-
}
|
|
139
|
-
const newFn = build(newTpl, false, buildDependencies)
|
|
140
|
-
return newFn
|
|
141
|
-
} else placeholders = structuredClone ( originalPlaceholders ) // Reset placeholders if not snippets
|
|
142
|
-
|
|
143
|
-
if ( typeof d === 'string' ) {
|
|
144
|
-
switch ( d ) {
|
|
145
|
-
case 'raw':
|
|
146
|
-
return cuts.join ( '' ) // Original template with placeholders
|
|
147
|
-
case 'demo':
|
|
148
|
-
if ( !handshake ) return `Error: No handshake data.`
|
|
149
|
-
d = handshake // Render with handshake object
|
|
150
|
-
break
|
|
151
|
-
case 'handshake':
|
|
152
|
-
if ( !handshake ) return `Error: No handshake data.`
|
|
153
|
-
return structuredClone (handshake) // return a copy of handshake object
|
|
154
|
-
case 'helpers' :
|
|
155
|
-
return Object.keys ( helpers ).join ( ', ' )
|
|
156
|
-
case 'placeholders':
|
|
157
|
-
return placeholders.map ( h => cuts[h.index] ).join ( ', ')
|
|
158
|
-
case 'count':
|
|
159
|
-
return placeholders.length
|
|
160
|
-
default:
|
|
161
|
-
return `Error: Wrong instruction "${d}". Available instructions: raw, demo, handshake, helpers, placeholders, count.`
|
|
162
|
-
}
|
|
163
|
-
} // if d is string
|
|
164
|
-
|
|
165
|
-
const endData = [];
|
|
166
|
-
const memory = {};
|
|
52
|
+
function build ( tpl, extra = false, buildDependencies = {}) {
|
|
53
|
+
let { hasError, placeholders, chop, helpers, handshake, snippets } = _readTemplate(tpl);
|
|
167
54
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
switch ( dataType ) {
|
|
263
|
-
case 'array':
|
|
264
|
-
theData.forEach ( (d,i) => theData[i] = ( d instanceof Function ) ? helpers[name]({ data:d(), ...extendArguments, full: d }) : helpers[name]( {data:d, ...extendArguments, full: d}) )
|
|
265
|
-
break
|
|
266
|
-
case 'object':
|
|
267
|
-
nestedData[level] = [helpers[name]( {data:theData,...extendArguments, full: d } )]
|
|
268
|
-
break
|
|
269
|
-
case 'function':
|
|
270
|
-
nestedData[level] = [helpers[name]( {data:theData(),...extendArguments, full: d } )]
|
|
271
|
-
break
|
|
272
|
-
case 'primitive':
|
|
273
|
-
nestedData[level] = helpers[name]( {data:theData,...extendArguments, full: d } )
|
|
274
|
-
break
|
|
275
|
-
} // switch dataType
|
|
276
|
-
|
|
277
|
-
break
|
|
278
|
-
case 'render':
|
|
279
|
-
const isRenderFunction = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
280
|
-
switch ( dataType ) {
|
|
281
|
-
case 'array':
|
|
282
|
-
if ( isRenderFunction ) theData.forEach ( (d,i) => {
|
|
283
|
-
if ( d == null ) return
|
|
284
|
-
const dType = _defineDataType ( d );
|
|
285
|
-
const text = helpers[name]( {data:d, ...extendArguments, full: original });
|
|
286
|
-
|
|
287
|
-
if ( text == null ) theData[i] = null
|
|
288
|
-
if ( dType === 'object' ) d['text'] = text
|
|
289
|
-
else theData[i] = text
|
|
290
|
-
})
|
|
291
|
-
else theData.forEach ( (d,i) => {
|
|
292
|
-
if ( d == null ) return
|
|
293
|
-
const
|
|
294
|
-
dType = _defineDataType ( d )
|
|
295
|
-
, text = render ( d, name, helpers, original, deps )
|
|
296
|
-
;
|
|
297
|
-
if ( text == null ) theData[i] = null
|
|
298
|
-
else if ( dType === 'object' ) d['text'] = text
|
|
299
|
-
else theData[i] = text
|
|
300
|
-
})
|
|
301
|
-
break
|
|
302
|
-
case 'function':
|
|
303
|
-
nestedData[level] = helpers[name]( {data:theData(), ...extendArguments, full: d} )
|
|
304
|
-
break
|
|
305
|
-
case 'primitive':
|
|
306
|
-
if ( isRenderFunction ) nestedData[level] = helpers[name]({ data:theData, ...extendArguments, full: d} )
|
|
307
|
-
else nestedData[level] = render ( theData, name, helpers, original, deps )
|
|
308
|
-
break
|
|
309
|
-
case 'object':
|
|
310
|
-
if ( isRenderFunction ) nestedData[level][iData]['text'] = helpers[name]({ data:theData, ...extendArguments, full: d })
|
|
311
|
-
else {
|
|
312
|
-
theData [ 'text' ] = render ( theData, name, helpers, original, deps )
|
|
313
|
-
}
|
|
314
|
-
break
|
|
315
|
-
} // switch renderDataType
|
|
316
|
-
break;
|
|
317
|
-
case 'extendedRender':
|
|
318
|
-
// TODO: Test extendedRender
|
|
319
|
-
const isValid = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
320
|
-
if ( isValid ) {
|
|
321
|
-
nestedData[0].forEach ( (d,i) => nestedData[0][i] = helpers[name]({ data:d, ...extendArguments, full: d }) )
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
// TODO: Error...
|
|
325
|
-
}
|
|
326
|
-
break
|
|
327
|
-
case 'mix':
|
|
328
|
-
if ( name === '' ) { // when is anonymous mixing action
|
|
329
|
-
switch ( dataType ) {
|
|
330
|
-
case 'object':
|
|
331
|
-
let kTest = Object.keys ( theData ).find ( k => k.includes ( '/' ) ); // Check if keys are breadcrumbs
|
|
332
|
-
if ( kTest ) Object.entries( theData ).forEach( ([k,v]) => nestedData[level][k] = v['text'] )
|
|
333
|
-
else nestedData[level] = theData['text']
|
|
334
|
-
for ( let i=level-1; i >= 0; i-- ) {
|
|
335
|
-
nestedData[i] = walk ({data:nestedData[i], objectCallback:check})
|
|
336
|
-
}
|
|
337
|
-
function check ({ value, breadcrumbs }) {
|
|
338
|
-
if ( nestedData[level][breadcrumbs] ) return nestedData[level][breadcrumbs]
|
|
339
|
-
return value
|
|
340
|
-
} // check
|
|
341
|
-
break
|
|
342
|
-
case 'array':
|
|
343
|
-
theData.forEach ( (x,i) => {
|
|
344
|
-
if ( i > 0 ) {
|
|
345
|
-
let xType = _defineDataType ( x );
|
|
346
|
-
if ( x == null ) return
|
|
347
|
-
if ( xType === 'object' ) theData[0] += `${x.text}`
|
|
348
|
-
else theData[0] += `${x}`
|
|
349
|
-
theData.toSpliced(i,1)
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
let xxType = _defineDataType ( x );
|
|
353
|
-
theData[0] = ''
|
|
354
|
-
if ( xxType === null ) return
|
|
355
|
-
else if ( xxType === 'object' ) theData[0] = `${x.text}`
|
|
356
|
-
else theData[0] = `${x}`
|
|
357
|
-
}
|
|
358
|
-
})
|
|
359
|
-
theData.length = 1
|
|
360
|
-
break
|
|
361
|
-
} // switch dataType
|
|
362
|
-
} // if name === ''
|
|
363
|
-
else {
|
|
364
|
-
let
|
|
365
|
-
val = helpers[name]({ data:theData, ...extendArguments, full: d })
|
|
366
|
-
, valType = _defineDataType ( val )
|
|
367
|
-
;
|
|
368
|
-
|
|
369
|
-
theData.forEach ( ( x, i ) => theData.splice ( i, 1) )
|
|
370
|
-
theData.length = 0
|
|
371
|
-
switch ( valType ) {
|
|
372
|
-
case 'primitive':
|
|
373
|
-
theData[0] = val
|
|
374
|
-
break
|
|
375
|
-
case 'array':
|
|
376
|
-
theData.push ( ...val )
|
|
377
|
-
break
|
|
378
|
-
} // switch valType
|
|
379
|
-
}
|
|
380
|
-
break
|
|
381
|
-
default:
|
|
382
|
-
break
|
|
383
|
-
}
|
|
384
|
-
}) // levelData
|
|
385
|
-
} // for step of actSetup
|
|
386
|
-
|
|
387
|
-
if ( nestedData instanceof Array &&
|
|
388
|
-
nestedData.length === 1 &&
|
|
389
|
-
nestedData[0] instanceof Array
|
|
390
|
-
) nestedData = nestedData[0]
|
|
391
|
-
if ( nestedData[0] == null ) return
|
|
392
|
-
|
|
393
|
-
let
|
|
394
|
-
accType = _defineDataType ( nestedData[0] )
|
|
395
|
-
, fineData = nestedData[0]
|
|
396
|
-
;
|
|
397
|
-
|
|
398
|
-
switch ( accType ) {
|
|
399
|
-
case 'primitive':
|
|
400
|
-
if ( fineData == null ) return
|
|
401
|
-
cuts[index] = fineData
|
|
402
|
-
break
|
|
403
|
-
case 'object':
|
|
404
|
-
if (fineData['text'] == null ) return
|
|
405
|
-
cuts[index] = fineData['text']
|
|
406
|
-
break
|
|
407
|
-
case 'array':
|
|
408
|
-
const aType = _defineDataType ( fineData[0] )
|
|
409
|
-
if ( aType === 'object' ) cuts[index] = fineData.map ( x => x.text ).join ( '')
|
|
410
|
-
else cuts[index] = fineData.join ( '' )
|
|
411
|
-
break
|
|
412
|
-
} // switch accType
|
|
413
|
-
} // else other
|
|
414
|
-
}) // forEach placeholders
|
|
415
|
-
|
|
416
|
-
if ( onlySnippets ) endData.push ( placeholders.map ( x => cuts[x.index] ).join ( '<~>' ) )
|
|
417
|
-
else endData.push ( cuts.join ( '' ))
|
|
418
|
-
}) // forEach d
|
|
419
|
-
|
|
420
|
-
if ( topLevelType === 'array' ) return endData
|
|
421
|
-
// Execute postprocess functions
|
|
422
|
-
if (args) return args.reduce ( (acc, fn) => {
|
|
423
|
-
if ( typeof fn !== 'function' ) return acc
|
|
424
|
-
return fn ( acc, deps )
|
|
425
|
-
}, endData.join ( '' ) )
|
|
426
|
-
else return endData.join ( '' )
|
|
427
|
-
} // success func.
|
|
428
|
-
return extra ? [ true, success ] : success
|
|
429
|
-
} // if no error
|
|
55
|
+
if ( hasError ) {
|
|
56
|
+
function fail() { return hasError }
|
|
57
|
+
return extra ? [false, fail] : fail
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const originalPlaceholders = structuredClone(placeholders);
|
|
61
|
+
|
|
62
|
+
function success ( command = 'render', d = {}, dependencies = {}, ...args ) {
|
|
63
|
+
const cuts = structuredClone(chop)
|
|
64
|
+
let onlySnippets = false;
|
|
65
|
+
|
|
66
|
+
// Command Validation
|
|
67
|
+
if (typeof command !== 'string') return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
68
|
+
if (!['render', 'debug', 'snippets', 'set', 'curry'].includes(command) && !command.startsWith('snippets')) return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// Handle Commands
|
|
72
|
+
if (command.startsWith('snippets')) {
|
|
73
|
+
onlySnippets = true
|
|
74
|
+
const subset = handleSnippets(command, snippets)
|
|
75
|
+
if (subset) placeholders = subset
|
|
76
|
+
}
|
|
77
|
+
else if (command === 'snippets') {
|
|
78
|
+
onlySnippets = true
|
|
79
|
+
}
|
|
80
|
+
else if (command === 'set') {
|
|
81
|
+
return handleSet(d, { helpers, handshake, placeholders, chop, build, buildDependencies })
|
|
82
|
+
}
|
|
83
|
+
else if (command === 'curry') {
|
|
84
|
+
// Curry logic
|
|
85
|
+
const rendered = success ( 'render', d, dependencies, ...args );
|
|
86
|
+
const newTpl = {
|
|
87
|
+
template: rendered,
|
|
88
|
+
helpers,
|
|
89
|
+
handshake
|
|
90
|
+
};
|
|
91
|
+
return build ( newTpl, false, buildDependencies )
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
placeholders = structuredClone ( originalPlaceholders )
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
// Handle 'DEBUG' (if d is string and command render/debug?)
|
|
99
|
+
// Original logic: if (typeof d === 'string').
|
|
100
|
+
// Wait, success('debug', 'raw') -> command='debug', d='raw'.
|
|
101
|
+
// success('render', 'demo') -> command='render', d='demo'.
|
|
102
|
+
// So any string d is treated as instruction ??
|
|
103
|
+
if (typeof d === 'string') {
|
|
104
|
+
const res = handleDebug(d, { handshake, helpers, placeholders, cuts })
|
|
105
|
+
// If handleDebug returns string/number/object, return it.
|
|
106
|
+
// Unless d='demo' which returns handshake object, then we proceed to render?
|
|
107
|
+
if (d === 'demo' && typeof res === 'object') d = res
|
|
108
|
+
else return res
|
|
109
|
+
}
|
|
110
|
+
// Proceed to Rendering
|
|
111
|
+
const memory = {};
|
|
112
|
+
let topLevelType = _defineDataType(d);
|
|
113
|
+
let deps = { ...buildDependencies, ...dependencies }
|
|
114
|
+
|
|
115
|
+
d = walk({ data: d })
|
|
116
|
+
let original = walk({ data: d })
|
|
117
|
+
|
|
118
|
+
if (topLevelType === 'null') return cuts.join('')
|
|
119
|
+
if (topLevelType !== 'array') d = [d]
|
|
120
|
+
if (topLevelType === 'null') return cuts.join('') // Redundant check?
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
const endData = processPlaceholders({
|
|
124
|
+
d
|
|
125
|
+
, chop
|
|
126
|
+
, placeholders
|
|
127
|
+
, original
|
|
128
|
+
, helpers
|
|
129
|
+
, dependencies: deps
|
|
130
|
+
, memory
|
|
131
|
+
, args
|
|
132
|
+
, onlySnippets
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if ( topLevelType === 'array' ) return endData
|
|
137
|
+
|
|
138
|
+
// Post-process
|
|
139
|
+
if (args) {
|
|
140
|
+
return args.reduce ( ( acc, fn ) => {
|
|
141
|
+
if (typeof fn !== 'function') return acc
|
|
142
|
+
return fn ( acc, deps )
|
|
143
|
+
}, endData.join(''))
|
|
144
|
+
}
|
|
145
|
+
else return endData.join ( '' )
|
|
146
|
+
} // success func.
|
|
147
|
+
return extra ? [true, success] : success
|
|
148
|
+
}
|
|
430
149
|
} // build func.
|
|
431
150
|
|
|
432
151
|
|