@peter.naydenov/morph 3.3.0 → 3.3.2

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.
Files changed (45) hide show
  1. package/Changelog.md +6 -0
  2. package/build.architecture.png +0 -0
  3. package/dist/methods/actionData.d.ts +10 -0
  4. package/dist/methods/actionExtendedRender.d.ts +10 -0
  5. package/dist/methods/actionMix.d.ts +10 -0
  6. package/dist/methods/actionRender.d.ts +13 -0
  7. package/dist/methods/actionSave.d.ts +8 -0
  8. package/dist/methods/executeActions.d.ts +11 -0
  9. package/dist/methods/processCommands.d.ts +46 -0
  10. package/dist/methods/processPlaceholders.d.ts +27 -0
  11. package/dist/methods/render.d.ts +1 -1
  12. package/dist/morph.cjs +1 -1
  13. package/dist/morph.esm.mjs +1 -1
  14. package/dist/morph.umd.js +1 -1
  15. package/dist/src/main.d.ts +100 -0
  16. package/dist/src/methods/_actionSupply.d.ts +18 -0
  17. package/dist/src/methods/_chopTemplates.d.ts +22 -0
  18. package/dist/src/methods/_defineData.d.ts +25 -0
  19. package/dist/src/methods/_defineType.d.ts +15 -0
  20. package/dist/src/methods/_readTemplate.d.ts +24 -0
  21. package/dist/src/methods/_renderHolder.d.ts +17 -0
  22. package/dist/src/methods/_setupActions.d.ts +19 -0
  23. package/dist/src/methods/actionData.d.ts +10 -0
  24. package/dist/src/methods/actionExtendedRender.d.ts +10 -0
  25. package/dist/src/methods/actionMix.d.ts +10 -0
  26. package/dist/src/methods/actionRender.d.ts +13 -0
  27. package/dist/src/methods/actionSave.d.ts +8 -0
  28. package/dist/src/methods/build.d.ts +61 -0
  29. package/dist/src/methods/executeActions.d.ts +11 -0
  30. package/dist/src/methods/processCommands.d.ts +46 -0
  31. package/dist/src/methods/processPlaceholders.d.ts +27 -0
  32. package/dist/src/methods/render.d.ts +14 -0
  33. package/dist/src/methods/settings.d.ts +7 -0
  34. package/package.json +8 -8
  35. package/src/methods/actionData.js +30 -0
  36. package/src/methods/actionExtendedRender.js +28 -0
  37. package/src/methods/actionMix.js +66 -0
  38. package/src/methods/actionRender.js +86 -0
  39. package/src/methods/actionSave.js +9 -0
  40. package/src/methods/build.js +81 -444
  41. package/src/methods/executeActions.js +65 -0
  42. package/src/methods/processCommands.js +97 -0
  43. package/src/methods/processPlaceholders.js +155 -0
  44. package/src/methods/render.js +1 -1
  45. package/tsconfig.json +2 -1
@@ -0,0 +1,65 @@
1
+ import actionRender from './actionRender.js'
2
+ import actionData from './actionData.js'
3
+ import actionMix from './actionMix.js'
4
+ import actionExtendedRender from './actionExtendedRender.js'
5
+ import _defineDataType from "./_defineType.js"
6
+ import { actionSave, actionOverwrite } from './actionSave.js'
7
+
8
+
9
+
10
+ function executeActions({ nestedData, actSetup, helpers, original, dependencies, memory, dElement, createUseHelper }) {
11
+ let currentDElement = dElement;
12
+
13
+ for (let step of actSetup) {
14
+ let
15
+ { type, name, level } = step
16
+ , levelData = nestedData[level] || []
17
+ ;
18
+
19
+ // If levelData is undefined, we can't loop. But it should be [] from _defineData?
20
+ // nestedData[level] might be undefined?
21
+ // build.js said: `let levelData = nestedData[level] || []`
22
+
23
+ levelData.forEach((theData, iData) => {
24
+ const context = {
25
+ helpers
26
+ , original
27
+ , dependencies
28
+ , memory
29
+ , useHelper: createUseHelper
30
+ , nestedData
31
+ , level
32
+ , iData
33
+ , extendArguments: { dependencies, memory }
34
+ }
35
+
36
+ switch (type) {
37
+ case 'render':
38
+ actionRender(step, theData, context)
39
+ break
40
+ case 'data':
41
+ actionData(step, theData, context)
42
+ break
43
+ case 'mix':
44
+ actionMix(step, theData, context)
45
+ break
46
+ case 'save':
47
+ actionSave(step, theData, context)
48
+ break
49
+ case 'overwrite':
50
+ currentDElement = actionOverwrite(step, theData)
51
+ break
52
+ case 'route':
53
+ // Deprecated, removed as per refactoring plan
54
+ break
55
+ case 'extendedRender':
56
+ actionExtendedRender(step, theData, context)
57
+ break
58
+ }
59
+ })
60
+ }
61
+
62
+ return currentDElement
63
+ }
64
+
65
+ export default executeActions
@@ -0,0 +1,97 @@
1
+
2
+ /**
3
+ * Handles debug commands for template inspection.
4
+ *
5
+ * @param {string} d - Debug instruction
6
+ * @param {object} context - Context object
7
+ * @param {object} context.handshake - Example data
8
+ * @param {object} context.helpers - Helper functions
9
+ * @param {array} context.placeholders - Placeholder definitions
10
+ * @param {array} context.cuts - Chopped template parts
11
+ * @returns {any} Debug result or error message
12
+ */
13
+ function handleDebug(d, { handshake, helpers, placeholders, cuts }) {
14
+ switch (d) {
15
+ case 'raw':
16
+ return cuts.join('')
17
+ case 'demo':
18
+ if (!handshake) return `Error: No handshake data.`
19
+ return handshake // Caller handles rendering handshake
20
+ case 'handshake':
21
+ if (!handshake) return `Error: No handshake data.`
22
+ return structuredClone(handshake)
23
+ case 'helpers':
24
+ return Object.keys(helpers).join(', ')
25
+ case 'placeholders':
26
+ return placeholders.map(h => cuts[h.index]).join(', ')
27
+ case 'count':
28
+ return placeholders.length
29
+ default:
30
+ return `Error: Wrong instruction "${d}". Available instructions: raw, demo, handshake, helpers, placeholders, count.`
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Handles the 'set' command to modify template properties.
36
+ *
37
+ * @param {object} d - Modification data
38
+ * @param {object} context - Context object
39
+ * @param {object} context.helpers - Current helper functions
40
+ * @param {object} context.handshake - Current handshake data
41
+ * @param {array} context.placeholders - Current placeholders
42
+ * @param {array} context.chop - Current chopped template
43
+ * @param {function} context.build - Build function
44
+ * @param {object} context.buildDependencies - Build dependencies
45
+ * @returns {function} Modified template function
46
+ */
47
+ function handleSet(d, { helpers, handshake, placeholders, chop, build, buildDependencies }) {
48
+ if (typeof d !== 'object' || !d) return `Error: 'set' command requires an object with placeholders, helpers, handshake.`
49
+
50
+ const newHelpers = { ...helpers, ...(d.helpers || {}) }
51
+ const newHandshake = handshake ? { ...handshake, ...(d.handshake || {}) } : d.handshake || {}
52
+ const newChop = [...chop]
53
+
54
+ if (d.placeholders) {
55
+ Object.entries(d.placeholders).forEach(([k, v]) => {
56
+ if (!isNaN(k)) {
57
+ let index = placeholders[k].index;
58
+ newChop[index] = v
59
+ }
60
+ else {
61
+ let plx = placeholders.find(p => p.name === k)
62
+ newChop[plx.index] = v
63
+ }
64
+ })
65
+ }
66
+
67
+ const newTemplateStr = newChop.join('');
68
+ const newTpl = {
69
+ template: newTemplateStr,
70
+ helpers: newHelpers,
71
+ handshake: newHandshake
72
+ }
73
+
74
+ const result = build(newTpl, false, buildDependencies)
75
+ return typeof result === 'function' ? result : () => result
76
+ }
77
+
78
+ /**
79
+ * Handles snippets command to select specific placeholders.
80
+ *
81
+ * @param {string} command - Snippets command
82
+ * @param {object} snippets - Snippets mapping
83
+ * @returns {array|null} Selected placeholders or null
84
+ */
85
+ function handleSnippets(command, snippets) {
86
+ if (command.includes(':')) {
87
+ let snippetNames = command.split(':')
88
+ .slice(1)[0]
89
+ .trim()
90
+ .split(',')
91
+ .map(t => t.trim())
92
+ return snippetNames.map(item => snippets[item])
93
+ }
94
+ return null // Indicates 'all snippets' or logic handled by caller
95
+ }
96
+
97
+ export { handleDebug, handleSet, handleSnippets }
@@ -0,0 +1,155 @@
1
+ import _defineData from "./_defineData.js"
2
+ import _defineDataType from "./_defineType.js"
3
+ import _actionSupply from "./_actionSupply.js"
4
+ import _setupActions from "./_setupActions.js"
5
+ import executeActions from "./executeActions.js"
6
+ import render from "./render.js"
7
+
8
+ /**
9
+ * Processes placeholders in the template with provided data and context.
10
+ *
11
+ * @param {object} params - Parameters object
12
+ * @param {array} params.d - Data array to process
13
+ * @param {array} params.chop - Chopped template parts
14
+ * @param {array} params.placeholders - Placeholder definitions
15
+ * @param {any} params.original - Original data context
16
+ * @param {object} params.helpers - Helper functions
17
+ * @param {object} params.dependencies - Injected dependencies
18
+ * @param {object} params.memory - Internal memory state
19
+ * @param {array} params.args - Additional arguments
20
+ * @param {boolean} params.onlySnippets - Whether to process only snippets
21
+ * @returns {array} Processed template parts
22
+ */
23
+ function processPlaceholders ({ d, chop, placeholders, original, helpers, dependencies, memory, args, onlySnippets }) {
24
+ const endData = []
25
+ // We need a factory for useHelper.
26
+ // It depends on 'currentData'. But here we are iterating 'd'.
27
+
28
+ // Helper factory to share with executeActions
29
+ const createUseHelperFactory = (currentData) => (targetName, targetData) => {
30
+ let
31
+ targetFn = helpers[targetName]
32
+ , isCompiledTemplate = targetFn && typeof targetFn === 'function' && targetFn.length >= 2
33
+ ;
34
+ if (!targetFn) return `( Error: Helper '${targetName}' is not available )`
35
+
36
+ if (isCompiledTemplate) {
37
+ try {
38
+ return targetFn('render', targetData || currentData, dependencies)
39
+ }
40
+ catch (e) {
41
+ return render(targetData || currentData, targetName, helpers, original, dependencies, ...args)
42
+ }
43
+ }
44
+ return render(targetData || currentData, targetName, helpers, original, dependencies, ...args)
45
+ }
46
+
47
+
48
+ d.forEach(dElement => {
49
+ let
50
+ cuts = structuredClone(chop)
51
+ , currentDElement = dElement // Can be updated by overwrite
52
+ ;
53
+
54
+ placeholders.forEach(holder => {
55
+ const
56
+ { index, data, action } = holder
57
+ , dataOnly = !action
58
+ , mem = structuredClone(memory)
59
+ ;
60
+ let info = currentDElement;
61
+
62
+ // Data Resolution
63
+ if (data && data.includes('/')) {
64
+ if (info.hasOwnProperty(data)) {
65
+ info = info[data]
66
+ }
67
+ else {
68
+ data.split('/').forEach(d => {
69
+ if (info.hasOwnProperty(d)) info = info[d]
70
+ else info = [] // Bug in original? info = [] then info['next'] crashes?
71
+ // Original: else info = []. 256.
72
+ // If info is [], next iteration info['key'] is undefined.
73
+ // So safe.
74
+ })
75
+ }
76
+ }
77
+ else if (data === '@all' || data === null || data === '@root') info = currentDElement
78
+ else if (data) info = info[data]
79
+
80
+
81
+ if (dataOnly) {
82
+ const type = _defineDataType(info);
83
+ switch (type) {
84
+ case 'function':
85
+ cuts[index] = info()
86
+ break
87
+ case 'primitive':
88
+ cuts[index] = info
89
+ break
90
+ case 'array':
91
+ if (_defineDataType(info[0]) === 'primitive') cuts[index] = info[0]
92
+ break
93
+ case 'object':
94
+ if (info.text) cuts[index] = info.text
95
+ break
96
+ }
97
+ }
98
+ else {
99
+ // Logic for data processing via actions
100
+ let
101
+ { dataDeepLevel, nestedData } = _defineData(info, action)
102
+ , actSetup = _actionSupply(_setupActions(action, dataDeepLevel), dataDeepLevel)
103
+ ;
104
+
105
+ const createUseHelper = createUseHelperFactory(info); // use info as context?
106
+ // In build.js it was `d` (the item from levelData).
107
+ // `executeActions` passes `theData` to `createUseHelper`.
108
+
109
+ currentDElement = executeActions({
110
+ nestedData
111
+ , actSetup
112
+ , helpers
113
+ , original
114
+ , dependencies
115
+ , memory
116
+ , dElement: currentDElement
117
+ , createUseHelper: createUseHelperFactory
118
+ })
119
+
120
+ // Flatten Step
121
+ if (nestedData instanceof Array && nestedData.length === 1 && nestedData[0] instanceof Array) nestedData = nestedData[0]
122
+ if (nestedData[0] == null) return
123
+
124
+ let
125
+ accType = _defineDataType(nestedData[0])
126
+ , fineData = nestedData[0]
127
+ ;
128
+
129
+ switch (accType) {
130
+ case 'primitive':
131
+ if (fineData == null) return
132
+ cuts[index] = fineData
133
+ break
134
+ case 'object':
135
+ if (fineData['text'] == null) return
136
+ cuts[index] = fineData['text']
137
+ break
138
+ case 'array':
139
+ const aType = _defineDataType(fineData[0])
140
+ if (aType === 'object') cuts[index] = fineData.map(x => x.text).join('')
141
+ else cuts[index] = fineData.join('')
142
+ break
143
+ }
144
+ }
145
+ }) // placeholders loop
146
+
147
+ if (onlySnippets) endData.push(placeholders.map(x => cuts[x.index]).join('<~>'))
148
+ else endData.push(cuts.join(''))
149
+
150
+ }) // d.forEach
151
+
152
+ return endData
153
+ }
154
+
155
+ export default processPlaceholders
@@ -13,7 +13,7 @@ import _renderHolder from './_renderHolder.js'
13
13
  * @param {object} dependencies - injected dependencies.
14
14
  * @param {...any} args - Additional arguments.
15
15
  *
16
- * @returns {any} The result of the rendering process.
16
+ * @returns {any} The result of the rendering process, or an error string if the helper is not available.
17
17
  */
18
18
  function render ( theData, name, helpers, original, dependencies, ...args) {
19
19
  const useHelper = ( targetName, targetData ) => render ( targetData || theData, targetName, helpers, original, dependencies, ...args )
package/tsconfig.json CHANGED
@@ -3,9 +3,10 @@
3
3
  "allowJs": true,
4
4
  "declaration": true,
5
5
  "emitDeclarationOnly": true,
6
+ "rootDir": "src",
6
7
  "outDir": "./dist",
7
8
  "module": "ESNext",
8
- "moduleResolution": "node",
9
+ "moduleResolution": "bundler",
9
10
  "target": "ES2020",
10
11
  "lib": ["ES2020"],
11
12
  "strict": false,