@peter.naydenov/morph 3.3.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/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/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 +1 -1
- package/package.json +1 -1
- 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 +81 -444
- 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 +1 -1
package/src/methods/build.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
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
|
-
import walk from '@peter.naydenov/walk'
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* @callback UseHelperFn
|
|
15
14
|
* @param {string} name - Name of the helper to call.
|
|
@@ -50,465 +49,103 @@ import walk from '@peter.naydenov/walk'
|
|
|
50
49
|
* @param {object} [buildDependencies] - Optional. External dependencies injected;
|
|
51
50
|
* @returns {function|tupleResult} - rendering function
|
|
52
51
|
*/
|
|
53
|
-
function build
|
|
54
|
-
let { hasError, placeholders, chop, helpers, handshake, snippets } = _readTemplate
|
|
55
|
-
|
|
52
|
+
function build ( tpl, extra = false, buildDependencies = {}) {
|
|
53
|
+
let { hasError, placeholders, chop, helpers, handshake, snippets } = _readTemplate(tpl);
|
|
54
|
+
|
|
56
55
|
if ( hasError ) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
else {
|
|
56
|
+
function fail() { return hasError }
|
|
57
|
+
return extra ? [false, fail] : fail
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
61
60
|
const originalPlaceholders = structuredClone(placeholders);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* Processes template rendering commands with provided data, dependencies, and optional post-processing functions.
|
|
65
|
-
*
|
|
66
|
-
* @function success
|
|
67
|
-
* @typedef { 'render' | 'debug' | 'snippets' | 'curry' | 'set' } Command
|
|
68
|
-
* @param {Command} [command='render'] - The command to execute. Supported commands: 'render', 'debug', 'snippets', 'curry', 'set', or 'snippets:<names>'.
|
|
69
|
-
* @param {Object|string} [d={}] - The data object to render, or a string instruction ('raw', 'demo', 'handshake', 'placeholders', 'count').
|
|
70
|
-
* @param {Object} [dependencies={}] - Additional dependencies to be merged with internal dependencies.
|
|
71
|
-
* @param {...any} args - Optional post-processing functions to apply to the rendered output.
|
|
72
|
-
* @returns {string|Array[]|function} The rendered template, snippets, data, or new function depending on the command and input.
|
|
73
|
-
*
|
|
74
|
-
* @throws {Error} If an unsupported command or instruction is provided.
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* // Render a template with data
|
|
78
|
-
* success('render', { name: 'Alice' }, { helperFn });
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* // Get raw template
|
|
82
|
-
* success('debug', 'raw');
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* // Get count of remaining placeholders
|
|
86
|
-
* success('debug', 'count');
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* // Render only specific snippets
|
|
90
|
-
* success('snippets:header,footer', { ... });
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* // Curry partial data and get new render function
|
|
94
|
-
* const curried = success('curry', { partial: 'data' });
|
|
95
|
-
* curried('render', { more: 'data' });
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* // Set placeholders and get modified template
|
|
99
|
-
* const modified = success('set', { placeholders: { key: 'value' } });
|
|
100
|
-
*/
|
|
101
|
-
function success(command = 'render', d = {}, dependencies = {}, ...args) {
|
|
61
|
+
|
|
62
|
+
function success ( command = 'render', d = {}, dependencies = {}, ...args ) {
|
|
102
63
|
const cuts = structuredClone(chop)
|
|
103
64
|
let onlySnippets = false;
|
|
65
|
+
|
|
66
|
+
// Command Validation
|
|
104
67
|
if (typeof command !== 'string') return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
105
68
|
if (!['render', 'debug', 'snippets', 'set', 'curry'].includes(command) && !command.startsWith('snippets')) return `Error: Wrong command "${command}". Available commands: render, debug, snippets, set, curry.`
|
|
106
69
|
|
|
107
|
-
|
|
70
|
+
|
|
71
|
+
// Handle Commands
|
|
72
|
+
if (command.startsWith('snippets')) {
|
|
108
73
|
onlySnippets = true
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.split(',')
|
|
113
|
-
.map(t => t.trim())
|
|
114
|
-
placeholders = snippetNames.map(item => snippets[item])
|
|
115
|
-
}
|
|
74
|
+
const subset = handleSnippets(command, snippets)
|
|
75
|
+
if (subset) placeholders = subset
|
|
76
|
+
}
|
|
116
77
|
else if (command === 'snippets') {
|
|
117
78
|
onlySnippets = true
|
|
118
|
-
|
|
79
|
+
}
|
|
119
80
|
else if (command === 'set') {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const newHandshake = handshake ? { ...handshake, ...(d.handshake || {}) } : d.handshake || {}
|
|
126
|
-
// Modify chop for placeholders
|
|
127
|
-
const newChop = [...chop]
|
|
128
|
-
if (d.placeholders) {
|
|
129
|
-
Object.entries(d.placeholders).forEach(([k, v]) => {
|
|
130
|
-
if (!isNaN(k)) { // If k is a number
|
|
131
|
-
let index = placeholders[k].index;
|
|
132
|
-
newChop[index] = v
|
|
133
|
-
} // if k is a number
|
|
134
|
-
else { // If k is a string
|
|
135
|
-
let plx = placeholders.find(p => p.name === k)
|
|
136
|
-
newChop[plx.index] = v
|
|
137
|
-
}
|
|
138
|
-
}) // placeholders
|
|
139
|
-
} // if d.placeholders
|
|
140
|
-
const newTemplateStr = newChop.join('');
|
|
141
|
-
const newTpl = {
|
|
142
|
-
template: newTemplateStr,
|
|
143
|
-
helpers: newHelpers,
|
|
144
|
-
handshake: newHandshake
|
|
145
|
-
}
|
|
146
|
-
const result = build(newTpl, false, buildDependencies)
|
|
147
|
-
return typeof result === 'function' ? result : () => result
|
|
148
|
-
} else if (command === 'curry') {
|
|
149
|
-
// Render the template with current data
|
|
150
|
-
const rendered = success('render', d, dependencies, ...args)
|
|
151
|
-
// Create new template with rendered as template, keep helpers and handshake
|
|
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 );
|
|
152
86
|
const newTpl = {
|
|
153
87
|
template: rendered,
|
|
154
88
|
helpers,
|
|
155
89
|
handshake
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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 ??
|
|
161
103
|
if (typeof d === 'string') {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
case 'handshake':
|
|
170
|
-
if (!handshake) return `Error: No handshake data.`
|
|
171
|
-
return structuredClone(handshake) // return a copy of handshake object
|
|
172
|
-
case 'helpers':
|
|
173
|
-
return Object.keys(helpers).join(', ')
|
|
174
|
-
case 'placeholders':
|
|
175
|
-
return placeholders.map(h => cuts[h.index]).join(', ')
|
|
176
|
-
case 'count':
|
|
177
|
-
return placeholders.length
|
|
178
|
-
default:
|
|
179
|
-
return `Error: Wrong instruction "${d}". Available instructions: raw, demo, handshake, helpers, placeholders, count.`
|
|
180
|
-
}
|
|
181
|
-
} // if d is string
|
|
182
|
-
|
|
183
|
-
const endData = [];
|
|
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
|
|
184
111
|
const memory = {};
|
|
185
|
-
|
|
186
112
|
let topLevelType = _defineDataType(d);
|
|
187
113
|
let deps = { ...buildDependencies, ...dependencies }
|
|
188
|
-
d = walk({ data: d }) // Creates copy of data to avoid mutation of the original
|
|
189
|
-
let original = walk({ data: d }) // Creates copy of data to avoid mutation of the original
|
|
190
114
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// If targetData provided, user that. If not, we can't easily know "current" data here outside loop.
|
|
194
|
-
// But each call site passes 'theData'.
|
|
195
|
-
// So useHelper actually needs to be a factory or passed with current data.
|
|
196
|
-
// Wait, in build.js we are iterating.
|
|
197
|
-
// We can define a generic useHelper here that takes (targetName, targetData).
|
|
198
|
-
// But if targetData is missing, it should default to the caller's data.
|
|
199
|
-
// The caller is the helper function.
|
|
200
|
-
// See implementation plan: "Implementation plan: useHelper(name, override). if override missing -> current data."
|
|
201
|
-
// In build.js loop:
|
|
202
|
-
// const paramUseHelper = (tName, tData) => render(tData || theData, tName, helpers, original, deps)
|
|
203
|
-
// We must define this INSIDE the loop or pass 'theData' to a factory.
|
|
204
|
-
// It's cleaner to define a factory here if possible, but 'theData' changes.
|
|
205
|
-
// So we will define a createUseHelper function here.
|
|
206
|
-
}
|
|
207
|
-
const createUseHelper = (currentData) => (targetName, targetData) => {
|
|
208
|
-
let
|
|
209
|
-
targetFn = helpers[targetName]
|
|
210
|
-
, isCompiledTemplate = targetFn && typeof targetFn === 'function' && targetFn.length >= 2 // success(command, d) has > 1 params
|
|
211
|
-
;
|
|
115
|
+
d = walk({ data: d })
|
|
116
|
+
let original = walk({ data: d })
|
|
212
117
|
|
|
213
|
-
if (!targetFn) return `{{ Error: Helper '${targetName}' is not available}}`
|
|
214
|
-
|
|
215
|
-
if (isCompiledTemplate) {
|
|
216
|
-
// It's likely a compiled template (success function)
|
|
217
|
-
// Try calling it with 'render' command
|
|
218
|
-
try {
|
|
219
|
-
return targetFn('render', targetData || currentData, dependencies)
|
|
220
|
-
}
|
|
221
|
-
catch (e) {
|
|
222
|
-
// Fallback if it wasn't a compiled template but just a function with arguments
|
|
223
|
-
return render(targetData || currentData, targetName, helpers, original, deps, ...args)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return render(targetData || currentData, targetName, helpers, original, deps, ...args)
|
|
227
|
-
}
|
|
228
118
|
if (topLevelType === 'null') return cuts.join('')
|
|
229
119
|
if (topLevelType !== 'array') d = [d]
|
|
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
|
-
else info = []
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
} // If data contains '/'
|
|
260
|
-
else if (data === '@all' || data === null || data === '@root') info = dElement
|
|
261
|
-
else if (data) info = info[data]
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (dataOnly) {
|
|
266
|
-
const type = _defineDataType(info);
|
|
267
|
-
switch (type) {
|
|
268
|
-
case 'function':
|
|
269
|
-
cuts[index] = info()
|
|
270
|
-
return
|
|
271
|
-
case 'primitive':
|
|
272
|
-
cuts[index] = info
|
|
273
|
-
return
|
|
274
|
-
case 'array':
|
|
275
|
-
if (_defineDataType(info[0]) === 'primitive') cuts[index] = info[0]
|
|
276
|
-
return
|
|
277
|
-
case 'object':
|
|
278
|
-
if (info.text) cuts[index] = info.text
|
|
279
|
-
return
|
|
280
|
-
} // switch
|
|
281
|
-
} // dataOnly
|
|
282
|
-
else { // Data and Actions or only Actions
|
|
283
|
-
let
|
|
284
|
-
{ dataDeepLevel, nestedData } = _defineData(info, action)
|
|
285
|
-
, actSetup = _actionSupply(_setupActions(action, dataDeepLevel), dataDeepLevel)
|
|
286
|
-
;
|
|
287
|
-
|
|
288
|
-
for (let step of actSetup) {
|
|
289
|
-
let
|
|
290
|
-
{ type, name, level } = step
|
|
291
|
-
, levelData = nestedData[level] || []
|
|
292
|
-
;
|
|
293
|
-
|
|
294
|
-
levelData.forEach((theData, iData) => {
|
|
295
|
-
|
|
296
|
-
let dataType = _defineDataType(theData)
|
|
297
|
-
|
|
298
|
-
switch (type) { // Action type 'route','data', 'render', or mix -> different operations
|
|
299
|
-
case 'route': // DEPRICATED in version 3.2.0. This functionality can be replaced with normal render functions
|
|
300
|
-
switch (dataType) {
|
|
301
|
-
case 'array':
|
|
302
|
-
theData.forEach((d, i) => {
|
|
303
|
-
if (d == null) return
|
|
304
|
-
const dType = _defineDataType(d)
|
|
305
|
-
const useHelper = createUseHelper(d);
|
|
306
|
-
const routeName = helpers[name]({ data: d, ...extendArguments, full: d, useHelper });
|
|
307
|
-
if (routeName == null) return
|
|
308
|
-
if (dType === 'object') theData[i]['text'] = render(d, routeName, helpers, original, deps)
|
|
309
|
-
else theData[i] = render(d, routeName, helpers, original, deps)
|
|
310
|
-
})
|
|
311
|
-
break
|
|
312
|
-
case 'object':
|
|
313
|
-
theData['text'] = render(theData, name, helpers, original, deps)
|
|
314
|
-
break
|
|
315
|
-
}
|
|
316
|
-
break
|
|
317
|
-
case 'save':
|
|
318
|
-
memory[name] = structuredClone(theData)
|
|
319
|
-
break
|
|
320
|
-
case 'overwrite':
|
|
321
|
-
dElement = structuredClone(theData)
|
|
322
|
-
break
|
|
323
|
-
case 'data':
|
|
324
|
-
switch (dataType) {
|
|
325
|
-
case 'array':
|
|
326
|
-
theData.forEach((d, i) => {
|
|
327
|
-
const useHelper = createUseHelper(d);
|
|
328
|
-
theData[i] = (d instanceof Function) ? helpers[name]({ data: d(), ...extendArguments, full: d, useHelper }) : helpers[name]({ data: d, ...extendArguments, full: d, useHelper })
|
|
329
|
-
})
|
|
330
|
-
break
|
|
331
|
-
case 'object':
|
|
332
|
-
const uhObj = createUseHelper(theData);
|
|
333
|
-
nestedData[level] = [helpers[name]({ data: theData, ...extendArguments, full: d, useHelper: uhObj })]
|
|
334
|
-
break
|
|
335
|
-
case 'function':
|
|
336
|
-
const fnData = theData();
|
|
337
|
-
const uhFn = createUseHelper(fnData);
|
|
338
|
-
nestedData[level] = [helpers[name]({ data: fnData, ...extendArguments, full: d, useHelper: uhFn })]
|
|
339
|
-
break
|
|
340
|
-
case 'primitive':
|
|
341
|
-
const uhPrim = createUseHelper(theData);
|
|
342
|
-
nestedData[level] = helpers[name]({ data: theData, ...extendArguments, full: d, useHelper: uhPrim })
|
|
343
|
-
break
|
|
344
|
-
} // switch dataType
|
|
345
|
-
|
|
346
|
-
break
|
|
347
|
-
case 'render':
|
|
348
|
-
const isRenderFunction = typeof helpers[name] === 'function'; // Render could be a function and template.
|
|
349
|
-
switch (dataType) {
|
|
350
|
-
case 'array':
|
|
351
|
-
if (isRenderFunction) theData.forEach((d, i) => {
|
|
352
|
-
if (d == null) return
|
|
353
|
-
const dType = _defineDataType(d);
|
|
354
|
-
const useHelper = createUseHelper(d);
|
|
355
|
-
const text = helpers[name]({ data: d, ...extendArguments, full: original, useHelper });
|
|
356
|
-
|
|
357
|
-
if (text == null) theData[i] = null
|
|
358
|
-
if (dType === 'object') d['text'] = text
|
|
359
|
-
else theData[i] = text
|
|
360
|
-
})
|
|
361
|
-
else theData.forEach((d, i) => {
|
|
362
|
-
if (d == null) return
|
|
363
|
-
const
|
|
364
|
-
dType = _defineDataType(d)
|
|
365
|
-
, text = render(d, name, helpers, original, deps)
|
|
366
|
-
;
|
|
367
|
-
if (text == null) theData[i] = null
|
|
368
|
-
else if (dType === 'object') d['text'] = text
|
|
369
|
-
else theData[i] = text
|
|
370
|
-
})
|
|
371
|
-
break
|
|
372
|
-
case 'function':
|
|
373
|
-
const fD = theData();
|
|
374
|
-
const useHelperFn = createUseHelper(fD);
|
|
375
|
-
nestedData[level] = helpers[name]({ data: fD, ...extendArguments, full: d, useHelper: useHelperFn })
|
|
376
|
-
break
|
|
377
|
-
case 'primitive':
|
|
378
|
-
if (isRenderFunction) {
|
|
379
|
-
const uhPrim = createUseHelper(theData);
|
|
380
|
-
nestedData[level] = helpers[name]({ data: theData, ...extendArguments, full: d, useHelper: uhPrim })
|
|
381
|
-
}
|
|
382
|
-
else nestedData[level] = render(theData, name, helpers, original, deps)
|
|
383
|
-
break
|
|
384
|
-
case 'object':
|
|
385
|
-
if (isRenderFunction) {
|
|
386
|
-
const uhO = createUseHelper(theData);
|
|
387
|
-
nestedData[level][iData]['text'] = helpers[name]({ data: theData, ...extendArguments, full: d, useHelper: uhO })
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
theData['text'] = render(theData, name, helpers, original, deps)
|
|
391
|
-
}
|
|
392
|
-
break
|
|
393
|
-
} // switch renderDataType
|
|
394
|
-
break;
|
|
395
|
-
case 'extendedRender':
|
|
396
|
-
// TODO: Test extendedRender
|
|
397
|
-
const isValid = typeof helpers[name] === 'function'; // Render could be
|
|
398
|
-
if (isValid) {
|
|
399
|
-
nestedData[0].forEach((d, i) => {
|
|
400
|
-
const uh = createUseHelper(d);
|
|
401
|
-
nestedData[0][i] = helpers[name]({ data: d, ...extendArguments, full: d, useHelper: uh })
|
|
402
|
-
})
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
// TODO: Error...
|
|
406
|
-
}
|
|
407
|
-
break
|
|
408
|
-
case 'mix':
|
|
409
|
-
if (name === '') { // when is anonymous mixing action
|
|
410
|
-
switch (dataType) {
|
|
411
|
-
case 'object':
|
|
412
|
-
let kTest = Object.keys(theData).find(k => k.includes('/')); // Check if keys are breadcrumbs
|
|
413
|
-
if (kTest) Object.entries(theData).forEach(([k, v]) => nestedData[level][k] = v['text'])
|
|
414
|
-
else nestedData[level] = theData['text']
|
|
415
|
-
for (let i = level - 1; i >= 0; i--) {
|
|
416
|
-
nestedData[i] = walk({ data: nestedData[i], objectCallback: check })
|
|
417
|
-
}
|
|
418
|
-
function check({ value, breadcrumbs }) {
|
|
419
|
-
if (nestedData[level][breadcrumbs]) return nestedData[level][breadcrumbs]
|
|
420
|
-
return value
|
|
421
|
-
} // check
|
|
422
|
-
break
|
|
423
|
-
case 'array':
|
|
424
|
-
theData.forEach((x, i) => {
|
|
425
|
-
if (i > 0) {
|
|
426
|
-
let xType = _defineDataType(x);
|
|
427
|
-
if (x == null) return
|
|
428
|
-
if (xType === 'object') theData[0] += `${x.text}`
|
|
429
|
-
else theData[0] += `${x}`
|
|
430
|
-
theData.toSpliced(i, 1)
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
let xxType = _defineDataType(x);
|
|
434
|
-
theData[0] = ''
|
|
435
|
-
if (xxType === null) return
|
|
436
|
-
else if (xxType === 'object') theData[0] = `${x.text}`
|
|
437
|
-
else theData[0] = `${x}`
|
|
438
|
-
}
|
|
439
|
-
})
|
|
440
|
-
theData.length = 1
|
|
441
|
-
break
|
|
442
|
-
} // switch dataType
|
|
443
|
-
} // if name === ''
|
|
444
|
-
else {
|
|
445
|
-
const dType = _defineDataType(d);
|
|
446
|
-
const useHelper = createUseHelper(d);
|
|
447
|
-
let val = helpers[name]({ data: theData, ...extendArguments, full: d, useHelper });
|
|
448
|
-
let valType = _defineDataType(val)
|
|
449
|
-
;
|
|
450
|
-
|
|
451
|
-
theData.forEach((x, i) => theData.splice(i, 1))
|
|
452
|
-
theData.length = 0
|
|
453
|
-
switch (valType) {
|
|
454
|
-
case 'primitive':
|
|
455
|
-
theData[0] = val
|
|
456
|
-
break
|
|
457
|
-
case 'array':
|
|
458
|
-
theData.push(...val)
|
|
459
|
-
break
|
|
460
|
-
} // switch valType
|
|
461
|
-
}
|
|
462
|
-
break
|
|
463
|
-
default:
|
|
464
|
-
break
|
|
465
|
-
}
|
|
466
|
-
}) // levelData
|
|
467
|
-
} // for step of actSetup
|
|
468
|
-
|
|
469
|
-
if (nestedData instanceof Array &&
|
|
470
|
-
nestedData.length === 1 &&
|
|
471
|
-
nestedData[0] instanceof Array
|
|
472
|
-
) nestedData = nestedData[0]
|
|
473
|
-
if (nestedData[0] == null) return
|
|
474
|
-
|
|
475
|
-
let
|
|
476
|
-
accType = _defineDataType(nestedData[0])
|
|
477
|
-
, fineData = nestedData[0]
|
|
478
|
-
;
|
|
479
|
-
|
|
480
|
-
switch (accType) {
|
|
481
|
-
case 'primitive':
|
|
482
|
-
if (fineData == null) return
|
|
483
|
-
cuts[index] = fineData
|
|
484
|
-
break
|
|
485
|
-
case 'object':
|
|
486
|
-
if (fineData['text'] == null) return
|
|
487
|
-
cuts[index] = fineData['text']
|
|
488
|
-
break
|
|
489
|
-
case 'array':
|
|
490
|
-
const aType = _defineDataType(fineData[0])
|
|
491
|
-
if (aType === 'object') cuts[index] = fineData.map(x => x.text).join('')
|
|
492
|
-
else cuts[index] = fineData.join('')
|
|
493
|
-
break
|
|
494
|
-
} // switch accType
|
|
495
|
-
} // else other
|
|
496
|
-
}) // forEach placeholders
|
|
497
|
-
|
|
498
|
-
if (onlySnippets) endData.push(placeholders.map(x => cuts[x.index]).join('<~>'))
|
|
499
|
-
else endData.push(cuts.join(''))
|
|
500
|
-
}) // forEach d
|
|
501
|
-
|
|
502
|
-
if (topLevelType === 'array') return endData
|
|
503
|
-
// Execute postprocess functions
|
|
504
|
-
if (args) return args.reduce((acc, fn) => {
|
|
505
|
-
if (typeof fn !== 'function') return acc
|
|
506
|
-
return fn(acc, deps)
|
|
507
|
-
}, endData.join(''))
|
|
508
|
-
else return endData.join('')
|
|
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 ( '' )
|
|
509
146
|
} // success func.
|
|
510
147
|
return extra ? [true, success] : success
|
|
511
|
-
}
|
|
148
|
+
}
|
|
512
149
|
} // build func.
|
|
513
150
|
|
|
514
151
|
|