json-to-spec 19.1.0

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 (217) hide show
  1. package/README.md +118 -0
  2. package/docs/demo.html +426 -0
  3. package/docs/dist/min.js +164 -0
  4. package/docs/dist/v1/min.js +124 -0
  5. package/docs/dist/v17/min.js +355 -0
  6. package/docs/dist/v18/min.js +160 -0
  7. package/docs/dist/v19/min.js +164 -0
  8. package/docs/dist/v2/min.js +129 -0
  9. package/docs/dist/v3/min.js +201 -0
  10. package/docs/index.html +248 -0
  11. package/docs/pages/architecture.html +115 -0
  12. package/docs/pages/how-it-works.html +125 -0
  13. package/docs/pages/what-not.html +100 -0
  14. package/docs/pages/what.html +105 -0
  15. package/docs/pages/why.html +88 -0
  16. package/docs/samples/form.html +265 -0
  17. package/docs/samples/index.html +112 -0
  18. package/docs/samples/table.html +306 -0
  19. package/index.js +2 -0
  20. package/package.json +50 -0
  21. package/samples/dataList/index.html +31 -0
  22. package/samples/dataList/index.js +62 -0
  23. package/samples/dataList/input/data.json +5043 -0
  24. package/samples/dataList/input/structure.json +38 -0
  25. package/samples/dataList copy/index.html +30 -0
  26. package/samples/dataList copy/index.js +61 -0
  27. package/samples/dataList copy/input/data.json +35307 -0
  28. package/samples/dataList copy/input/structure.json +18 -0
  29. package/samples/form/index.html +29 -0
  30. package/samples/form/index.js +64 -0
  31. package/samples/form/input/data.json +9 -0
  32. package/samples/form/input/structure.json +192 -0
  33. package/samples/form-/data.json +42 -0
  34. package/samples/form-/structure.json +110 -0
  35. package/samples/select/index.html +31 -0
  36. package/samples/select/index.js +61 -0
  37. package/samples/select/input/data.json +35287 -0
  38. package/samples/select/input/select.json +18 -0
  39. package/samples/select/input/structure.json +47 -0
  40. package/samples/table/index.html +29 -0
  41. package/samples/table/index.js +61 -0
  42. package/samples/table/input/data.json +35287 -0
  43. package/samples/table/input/structure copy.json +47 -0
  44. package/samples/table/input/structure.json +86 -0
  45. package/samples/table/input/table.json +135 -0
  46. package/samples/table-/data.json +68 -0
  47. package/samples/table-/structure.json +235 -0
  48. package/src/index.js +2 -0
  49. package/src/v10/index.js +96 -0
  50. package/src/v10/instructionEngine/compile/compileTree.js +191 -0
  51. package/src/v10/instructionEngine/compileTree.js +1 -0
  52. package/src/v10/instructionEngine/expandIteration.js +1 -0
  53. package/src/v10/instructionEngine/index.js +29 -0
  54. package/src/v10/instructionEngine/interpolate.js +2 -0
  55. package/src/v10/instructionEngine/iteration/expandIteration.js +95 -0
  56. package/src/v10/instructionEngine/operation/operation.js +237 -0
  57. package/src/v10/instructionEngine/other/other.js +150 -0
  58. package/src/v10/instructionEngine/pipeline/pipeline.js +47 -0
  59. package/src/v10/instructionEngine/replace/replace.js +173 -0
  60. package/src/v10/instructionEngine/resolve/resolvePath.js +18 -0
  61. package/src/v10/instructionEngine/resolve/resolveTokenValue.js +22 -0
  62. package/src/v10/instructionEngine/resolvePath.js +1 -0
  63. package/src/v10/instructionEngine/resolveTokenValue.js +1 -0
  64. package/src/v10/instructionEngine/story/storyInjector.js +50 -0
  65. package/src/v10/instructionEngine/storyInjector.js +1 -0
  66. package/src/v10/instructionEngine/value/interpolate.js +38 -0
  67. package/src/v11/index.js +116 -0
  68. package/src/v11/iterate.js +270 -0
  69. package/src/v11/replace.js +169 -0
  70. package/src/v11/resolvePath.js +29 -0
  71. package/src/v12/index.js +122 -0
  72. package/src/v12/iterate/bindFormValues.js +74 -0
  73. package/src/v12/iterate/expandIteration.js +181 -0
  74. package/src/v12/iterate/index.js +10 -0
  75. package/src/v12/iterate/iterate.js +56 -0
  76. package/src/v12/iterate/iterateNode.js +86 -0
  77. package/src/v12/iterate/resolveCollection.js +37 -0
  78. package/src/v12/iterate.js +270 -0
  79. package/src/v12/replace.js +169 -0
  80. package/src/v12/resolvePath.js +29 -0
  81. package/src/v13/index.js +110 -0
  82. package/src/v13/iterate/bindFormValues.js +74 -0
  83. package/src/v13/iterate/expandIteration.js +188 -0
  84. package/src/v13/iterate/index.js +9 -0
  85. package/src/v13/iterate/iterate.js +32 -0
  86. package/src/v13/iterate/iterateNode.js +86 -0
  87. package/src/v13/iterate/resolveCollection.js +37 -0
  88. package/src/v13/iterate/walk.js +90 -0
  89. package/src/v13/iterate.js +270 -0
  90. package/src/v13/replace.js +169 -0
  91. package/src/v13/resolvePath.js +29 -0
  92. package/src/v14/index.js +112 -0
  93. package/src/v14/iterate/bindFormValues.js +74 -0
  94. package/src/v14/iterate/expandIteration.js +188 -0
  95. package/src/v14/iterate/index.js +9 -0
  96. package/src/v14/iterate/iterate.js +32 -0
  97. package/src/v14/iterate/resolveCollection.js +37 -0
  98. package/src/v14/iterate/walk/walk copy 2.js +114 -0
  99. package/src/v14/iterate/walk/walk copy.js +90 -0
  100. package/src/v14/iterate/walk/walk.js +98 -0
  101. package/src/v14/iterate.js +270 -0
  102. package/src/v14/replace/index.js +16 -0
  103. package/src/v14/replace/walk.js +90 -0
  104. package/src/v14/replace.js +153 -0
  105. package/src/v14/resolvePath.js +29 -0
  106. package/src/v15/index.js +123 -0
  107. package/src/v15/iterate/bindFormValues.js +74 -0
  108. package/src/v15/iterate/expandIteration.js +188 -0
  109. package/src/v15/iterate/index.js +9 -0
  110. package/src/v15/iterate/iterate.js +32 -0
  111. package/src/v15/iterate/resolveCollection.js +37 -0
  112. package/src/v15/iterate/walk/walk copy 2.js +114 -0
  113. package/src/v15/iterate/walk/walk copy.js +90 -0
  114. package/src/v15/iterate/walk/walk.js +195 -0
  115. package/src/v15/iterate.js +270 -0
  116. package/src/v15/replace/index.js +16 -0
  117. package/src/v15/replace/walk.js +90 -0
  118. package/src/v15/replace.js +155 -0
  119. package/src/v15/resolvePath.js +29 -0
  120. package/src/v16/index.js +129 -0
  121. package/src/v16/iterate/bindFormValues.js +74 -0
  122. package/src/v16/iterate/expandIteration.js +188 -0
  123. package/src/v16/iterate/index.js +9 -0
  124. package/src/v16/iterate/iterate.js +32 -0
  125. package/src/v16/iterate/resolveCollection.js +37 -0
  126. package/src/v16/iterate/walk/walk copy 2.js +114 -0
  127. package/src/v16/iterate/walk/walk copy.js +90 -0
  128. package/src/v16/iterate/walk/walk.js +196 -0
  129. package/src/v16/iterate.js +270 -0
  130. package/src/v16/replace/index.js +16 -0
  131. package/src/v16/replace/walk.js +90 -0
  132. package/src/v16/replace.js +155 -0
  133. package/src/v16/resolvePath.js +29 -0
  134. package/src/v17/index.js +119 -0
  135. package/src/v17/iterate/bindFormValues.js +74 -0
  136. package/src/v17/iterate/expandIteration.js +188 -0
  137. package/src/v17/iterate/index.js +9 -0
  138. package/src/v17/iterate/iterate.js +32 -0
  139. package/src/v17/iterate/resolveCollection.js +37 -0
  140. package/src/v17/iterate/walk/iterateDo.js +42 -0
  141. package/src/v17/iterate/walk/replaceWithData.js +60 -0
  142. package/src/v17/iterate/walk/walk.js +94 -0
  143. package/src/v17/iterate.js +270 -0
  144. package/src/v17/replace/index.js +16 -0
  145. package/src/v17/replace/walk.js +90 -0
  146. package/src/v17/replace.js +160 -0
  147. package/src/v17/resolvePath.js +29 -0
  148. package/src/v18/index.js +66 -0
  149. package/src/v18/meta.js +7 -0
  150. package/src/v18/registerGlobal.js +17 -0
  151. package/src/v18/replace.js +18 -0
  152. package/src/v18/resolvePath.js +29 -0
  153. package/src/v18/walk/iterate/v1/index.js +42 -0
  154. package/src/v18/walk/iterate/v2/index.js +32 -0
  155. package/src/v18/walk/iterate/v3/index.js +46 -0
  156. package/src/v18/walk/iterate/v4/createChildren.js +24 -0
  157. package/src/v18/walk/iterate/v4/index.js +25 -0
  158. package/src/v18/walk/replaceWithData/v1/index.js +42 -0
  159. package/src/v18/walk/replaceWithData/v1/replaceCommon.js +21 -0
  160. package/src/v18/walk/replaceWithData/v2/index.js +105 -0
  161. package/src/v18/walk/replaceWithData/v2/replaceCommon.js +21 -0
  162. package/src/v18/walk/replaceWithData/v3/index.js +15 -0
  163. package/src/v18/walk/replaceWithData/v3/replaceAttributes.js +29 -0
  164. package/src/v18/walk/replaceWithData/v3/replaceCommon.js +23 -0
  165. package/src/v18/walk/replaceWithData/v3/replaceNodeValue.js +27 -0
  166. package/src/v18/walk/walk.js +94 -0
  167. package/src/v19/index.js +55 -0
  168. package/src/v19/meta.js +7 -0
  169. package/src/v19/registerGlobal.js +17 -0
  170. package/src/v19/replace.js +18 -0
  171. package/src/v19/resolvePath.js +29 -0
  172. package/src/v19/walk/iterate/v1/index.js +42 -0
  173. package/src/v19/walk/iterate/v2/index.js +32 -0
  174. package/src/v19/walk/iterate/v3/index.js +46 -0
  175. package/src/v19/walk/iterate/v4/createChildren.js +27 -0
  176. package/src/v19/walk/iterate/v4/index.js +25 -0
  177. package/src/v19/walk/replaceWithData/v1/index.js +42 -0
  178. package/src/v19/walk/replaceWithData/v1/replaceCommon.js +21 -0
  179. package/src/v19/walk/replaceWithData/v2/index.js +105 -0
  180. package/src/v19/walk/replaceWithData/v2/replaceCommon.js +21 -0
  181. package/src/v19/walk/replaceWithData/v3/index.js +15 -0
  182. package/src/v19/walk/replaceWithData/v3/replaceAttributes.js +29 -0
  183. package/src/v19/walk/replaceWithData/v3/replaceCommon.js +23 -0
  184. package/src/v19/walk/replaceWithData/v3/replaceNodeValue.js +27 -0
  185. package/src/v19/walk/walk.js +97 -0
  186. package/src/v8/index.js +69 -0
  187. package/src/v8/instructionEngine/compile/compileTree.js +191 -0
  188. package/src/v8/instructionEngine/compileTree.js +1 -0
  189. package/src/v8/instructionEngine/expandIteration.js +1 -0
  190. package/src/v8/instructionEngine/index.js +16 -0
  191. package/src/v8/instructionEngine/interpolate.js +2 -0
  192. package/src/v8/instructionEngine/iteration/expandIteration.js +95 -0
  193. package/src/v8/instructionEngine/resolve/resolvePath.js +18 -0
  194. package/src/v8/instructionEngine/resolve/resolveTokenValue.js +22 -0
  195. package/src/v8/instructionEngine/resolvePath.js +1 -0
  196. package/src/v8/instructionEngine/resolveTokenValue.js +1 -0
  197. package/src/v8/instructionEngine/story/storyInjector.js +50 -0
  198. package/src/v8/instructionEngine/storyInjector.js +1 -0
  199. package/src/v8/instructionEngine/value/interpolate.js +38 -0
  200. package/src/v9/index.js +96 -0
  201. package/src/v9/instructionEngine/compile/compileTree.js +191 -0
  202. package/src/v9/instructionEngine/compileTree.js +1 -0
  203. package/src/v9/instructionEngine/expandIteration.js +1 -0
  204. package/src/v9/instructionEngine/index.js +29 -0
  205. package/src/v9/instructionEngine/interpolate.js +2 -0
  206. package/src/v9/instructionEngine/iteration/expandIteration.js +95 -0
  207. package/src/v9/instructionEngine/operation/operation.js +237 -0
  208. package/src/v9/instructionEngine/other/other.js +150 -0
  209. package/src/v9/instructionEngine/pipeline/pipeline.js +47 -0
  210. package/src/v9/instructionEngine/replace/replace.js +173 -0
  211. package/src/v9/instructionEngine/resolve/resolvePath.js +18 -0
  212. package/src/v9/instructionEngine/resolve/resolveTokenValue.js +22 -0
  213. package/src/v9/instructionEngine/resolvePath.js +1 -0
  214. package/src/v9/instructionEngine/resolveTokenValue.js +1 -0
  215. package/src/v9/instructionEngine/story/storyInjector.js +50 -0
  216. package/src/v9/instructionEngine/storyInjector.js +1 -0
  217. package/src/v9/instructionEngine/value/interpolate.js +38 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Recursively binds form field values into
3
+ * input, textarea, select and option nodes.
4
+ */
5
+ const bindFormValues = ({ inNode, inItem, inData }) => {
6
+ const localNode = inNode;
7
+ const localItem = inItem;
8
+ const localData = inData;
9
+
10
+ if (!localNode || typeof localNode !== "object") {
11
+ return localNode;
12
+ }
13
+
14
+ if (localNode.attributes) {
15
+ const isFormField = [
16
+ "input",
17
+ "textarea",
18
+ "select",
19
+ "option"
20
+ ].includes(localNode.tagName?.toLowerCase());
21
+
22
+ if (isFormField) {
23
+ const fieldName =
24
+ localItem.field ||
25
+ localItem.columnName ||
26
+ localItem.name;
27
+
28
+ if (
29
+ localItem.value !== undefined &&
30
+ localItem.value !== null
31
+ ) {
32
+ localNode.attributes.value = String(localItem.value);
33
+
34
+ if (
35
+ localNode.tagName === "textarea" &&
36
+ !localNode.textContent
37
+ ) {
38
+ localNode.textContent = String(localItem.value);
39
+ }
40
+ } else if (
41
+ fieldName &&
42
+ localData[fieldName] !== undefined &&
43
+ localData[fieldName] !== null
44
+ ) {
45
+ localNode.attributes.value = String(
46
+ localData[fieldName]
47
+ );
48
+
49
+ if (
50
+ localNode.tagName === "textarea" &&
51
+ !localNode.textContent
52
+ ) {
53
+ localNode.textContent = String(
54
+ localData[fieldName]
55
+ );
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ if (Array.isArray(localNode.children)) {
62
+ localNode.children.forEach(child => {
63
+ bindFormValues({
64
+ inNode: child,
65
+ inItem: localItem,
66
+ inData: localData
67
+ });
68
+ });
69
+ }
70
+
71
+ return localNode;
72
+ };
73
+
74
+ export default bindFormValues;
@@ -0,0 +1,188 @@
1
+ import resolveCollection from "./resolveCollection.js";
2
+ import bindFormValues from "./bindFormValues.js";
3
+ import { replaceNode } from "../replace.js";
4
+
5
+ /**
6
+ * Expands a single iteration directive into an array of
7
+ * specification nodes.
8
+ */
9
+ const expandIteration = ({
10
+ inNode,
11
+ inContext,
12
+ inData,
13
+ walk
14
+ }) => {
15
+ const localNode = inNode;
16
+ const localContext = inContext;
17
+ const localData = inData;
18
+
19
+ const instruction = localNode && (
20
+ localNode.jsonToSpec ||
21
+ (localNode.operation ? localNode : null)
22
+ );
23
+
24
+ if (!instruction) return undefined;
25
+
26
+ const operationType = instruction.operation;
27
+
28
+ if (
29
+ operationType !== "iterate" &&
30
+ !instruction.source &&
31
+ !instruction.$iterate
32
+ ) {
33
+ return undefined;
34
+ }
35
+
36
+ const sourceKey =
37
+ instruction.source ||
38
+ instruction.iterateOn ||
39
+ instruction.$iterate;
40
+
41
+ const collection = resolveCollection({
42
+ inNode: localNode,
43
+ inContext: localContext,
44
+ inData: localData
45
+ }) || [];
46
+
47
+ if (!Array.isArray(collection)) {
48
+ if (localNode && localNode.tagName) {
49
+ const cloned = { ...localNode };
50
+ delete cloned.jsonToSpec;
51
+ cloned.children = [];
52
+ return cloned;
53
+ }
54
+
55
+ return [];
56
+ }
57
+
58
+ const template =
59
+ instruction.template ||
60
+ instruction.item ||
61
+ {};
62
+
63
+ const filter = instruction.filter;
64
+
65
+ const filtered = collection.filter(item => {
66
+ if (!item || typeof item !== "object") {
67
+ return true;
68
+ }
69
+
70
+ if (filter && typeof filter === "object") {
71
+ for (const [key, value] of Object.entries(filter)) {
72
+ if (item[key] !== value) {
73
+ return false;
74
+ }
75
+ }
76
+ }
77
+
78
+ if (item.isVisible === false) {
79
+ return false;
80
+ }
81
+
82
+ return true;
83
+ });
84
+
85
+ const expandedChildren = [];
86
+
87
+ filtered.forEach((item, index) => {
88
+ const itemContext = {
89
+ ...localContext,
90
+ item,
91
+ ...(typeof item === "object" && item !== null ? item : {}),
92
+ $index: index,
93
+ $number: index + 1
94
+ };
95
+
96
+ if (
97
+ sourceKey === "rows" ||
98
+ sourceKey.endsWith(".rows") ||
99
+ sourceKey === "items" ||
100
+ sourceKey.endsWith("Rows")
101
+ ) {
102
+ itemContext.row = item;
103
+ }
104
+
105
+ if (
106
+ localContext.row &&
107
+ (item.field || item.columnName || item.name)
108
+ ) {
109
+ const fieldKey =
110
+ item.field ||
111
+ item.columnName ||
112
+ item.name;
113
+
114
+ const cellValue = localContext.row[fieldKey];
115
+
116
+ if (cellValue !== undefined) {
117
+ itemContext.cellValue = cellValue;
118
+ itemContext.value = cellValue;
119
+
120
+ if (
121
+ typeof item === "object" &&
122
+ item !== null &&
123
+ item.value === undefined
124
+ ) {
125
+ item.value = cellValue;
126
+ }
127
+ }
128
+ }
129
+
130
+ const rawTemplate =
131
+ typeof template === "object" &&
132
+ template !== null
133
+ ? JSON.parse(JSON.stringify(template))
134
+ : {
135
+ tagName: "span",
136
+ textContent: template
137
+ };
138
+
139
+ const iteratedTemplate = walk({
140
+ inNode: rawTemplate,
141
+ inContext: itemContext,
142
+ inData: localData,
143
+ inOperation: ({ inNode, inContext, inData }) => {
144
+ return expandIteration({
145
+ inNode,
146
+ inContext,
147
+ inData,
148
+ walk
149
+ });
150
+ }
151
+ });
152
+
153
+ const replacedTemplate = replaceNode({
154
+ inNode: iteratedTemplate,
155
+ inContext: itemContext,
156
+ inData: localData
157
+ });
158
+
159
+ bindFormValues({
160
+ inNode: replacedTemplate,
161
+ inItem: item,
162
+ inData: localData
163
+ });
164
+
165
+ if (Array.isArray(replacedTemplate)) {
166
+ expandedChildren.push(...replacedTemplate);
167
+ } else if (
168
+ replacedTemplate !== null &&
169
+ replacedTemplate !== undefined
170
+ ) {
171
+ expandedChildren.push(replacedTemplate);
172
+ }
173
+ });
174
+
175
+ if (localNode && localNode.tagName) {
176
+ const cloned = { ...localNode };
177
+
178
+ delete cloned.jsonToSpec;
179
+
180
+ cloned.children = expandedChildren;
181
+
182
+ return cloned;
183
+ }
184
+
185
+ return expandedChildren;
186
+ };
187
+
188
+ export default expandIteration;
@@ -0,0 +1,9 @@
1
+ import iterate from "./iterate.js";
2
+
3
+ export {
4
+ iterate
5
+ };
6
+
7
+ export const operation = iterate;
8
+
9
+ export default iterate;
@@ -0,0 +1,32 @@
1
+ import walk from "./walk/walk.js";
2
+ import expandIteration from "./expandIteration.js";
3
+
4
+ /**
5
+ * Iterates a structure by walking the tree
6
+ * and applying the iteration operation to each node.
7
+ */
8
+ const iterate = ({
9
+ inStructure,
10
+ inData = {},
11
+ inContext = {}
12
+ } = {}) => {
13
+ return walk({
14
+ inNode: inStructure,
15
+ inData,
16
+ inContext,
17
+ inOperation: ({ inNode, inContext, inData }) => {
18
+ return expandIteration({
19
+ inNode,
20
+ inContext,
21
+ inData,
22
+ walk
23
+ });
24
+ }
25
+ });
26
+ };
27
+
28
+ export {
29
+ iterate
30
+ };
31
+
32
+ export default iterate;
@@ -0,0 +1,37 @@
1
+ import resolvePath from "../resolvePath.js";
2
+
3
+ /**
4
+ * Resolves the collection array targeted by an iteration instruction.
5
+ */
6
+ const resolveCollection = ({ inNode, inContext, inData }) => {
7
+ const localNode = inNode;
8
+ const localContext = inContext;
9
+ const localData = inData;
10
+
11
+ const instruction = localNode && (
12
+ localNode.jsonToSpec ||
13
+ (localNode.operation ? localNode : null)
14
+ );
15
+
16
+ if (!instruction) return undefined;
17
+
18
+ const sourceKey =
19
+ instruction.source ||
20
+ instruction.iterateOn ||
21
+ instruction.$iterate;
22
+
23
+ if (!sourceKey) return undefined;
24
+
25
+ return resolvePath({
26
+ inData: localData,
27
+ inPath: sourceKey
28
+ })
29
+ || (localData && localData[sourceKey])
30
+ || resolvePath({
31
+ inData: localContext,
32
+ inPath: sourceKey
33
+ })
34
+ || (localContext && localContext[sourceKey]);
35
+ };
36
+
37
+ export default resolveCollection;
@@ -0,0 +1,114 @@
1
+
2
+ /**
3
+ * Applies the supplied operation to the current node.
4
+ */
5
+ const applyOperation = ({
6
+ inNode,
7
+ inContext = {},
8
+ inData = {},
9
+ inOperation
10
+ } = {}) => {
11
+ if (typeof inOperation !== "function") {
12
+ return inNode;
13
+ }
14
+
15
+ const operatedNode = inOperation({
16
+ inNode,
17
+ inContext,
18
+ inData
19
+ });
20
+
21
+ return operatedNode === undefined
22
+ ? inNode
23
+ : operatedNode;
24
+ };
25
+
26
+ /**
27
+ * Recursively walks a JSON structure.
28
+ *
29
+ * The walker knows only how to traverse.
30
+ * The supplied operation decides what to do with each node.
31
+ */
32
+ const walk = ({
33
+ inNode,
34
+ inContext = {},
35
+ inData = {},
36
+ inOperation
37
+ } = {}) => {
38
+ const localNode = inNode;
39
+ const localContext = inContext;
40
+ const localData = inData;
41
+
42
+ if (localNode === null || localNode === undefined) {
43
+ return localNode;
44
+ }
45
+
46
+ if (Array.isArray(localNode)) {
47
+ const results = [];
48
+
49
+ for (const child of localNode) {
50
+ const result = walk({
51
+ inNode: child,
52
+ inContext: localContext,
53
+ inData: localData,
54
+ inOperation
55
+ });
56
+
57
+ if (Array.isArray(result)) {
58
+ results.push(...result);
59
+ } else if (result !== null && result !== undefined) {
60
+ results.push(result);
61
+ }
62
+ }
63
+
64
+ return results;
65
+ }
66
+
67
+ if (typeof localNode !== "object") {
68
+ return localNode;
69
+ }
70
+
71
+ const localOperatedNode = applyOperation({
72
+ inNode: localNode,
73
+ inContext: localContext,
74
+ inData: localData,
75
+ inOperation
76
+ });
77
+
78
+ if (localOperatedNode === null) {
79
+ return null;
80
+ }
81
+
82
+ if (Array.isArray(localOperatedNode)) {
83
+ return walk({
84
+ inNode: localOperatedNode,
85
+ inContext: localContext,
86
+ inData: localData,
87
+ inOperation
88
+ });
89
+ }
90
+
91
+ if (typeof localOperatedNode !== "object") {
92
+ return localOperatedNode;
93
+ }
94
+
95
+ const clone = { ...localOperatedNode };
96
+
97
+ if (Array.isArray(clone.children)) {
98
+ clone.children = walk({
99
+ inNode: clone.children,
100
+ inContext: localContext,
101
+ inData: localData,
102
+ inOperation
103
+ });
104
+ }
105
+
106
+ return clone;
107
+ };
108
+
109
+ export {
110
+ walk,
111
+ applyOperation
112
+ };
113
+
114
+ export default walk;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Recursively walks a JSON structure.
3
+ *
4
+ * The walker knows only how to traverse.
5
+ * The supplied operation decides what to do with each node.
6
+ */
7
+ const walk = ({
8
+ inNode,
9
+ inContext = {},
10
+ inData = {},
11
+ inOperation
12
+ } = {}) => {
13
+ const localNode = inNode;
14
+ const localContext = inContext;
15
+ const localData = inData;
16
+
17
+ if (localNode === null || localNode === undefined) {
18
+ return localNode;
19
+ }
20
+
21
+ if (Array.isArray(localNode)) {
22
+ const results = [];
23
+
24
+ for (const child of localNode) {
25
+ const result = walk({
26
+ inNode: child,
27
+ inContext: localContext,
28
+ inData: localData,
29
+ inOperation
30
+ });
31
+
32
+ if (Array.isArray(result)) {
33
+ results.push(...result);
34
+ } else if (result !== null && result !== undefined) {
35
+ results.push(result);
36
+ }
37
+ }
38
+
39
+ return results;
40
+ }
41
+
42
+ if (typeof localNode !== "object") {
43
+ return localNode;
44
+ }
45
+
46
+ const operatedNode = typeof inOperation === "function"
47
+ ? inOperation({
48
+ inNode: localNode,
49
+ inContext: localContext,
50
+ inData: localData
51
+ })
52
+ : localNode;
53
+
54
+ const localOperatedNode =
55
+ operatedNode === undefined
56
+ ? localNode
57
+ : operatedNode;
58
+
59
+ if (localOperatedNode === null) {
60
+ return null;
61
+ }
62
+
63
+ if (Array.isArray(localOperatedNode)) {
64
+ return walk({
65
+ inNode: localOperatedNode,
66
+ inContext: localContext,
67
+ inData: localData,
68
+ inOperation
69
+ });
70
+ }
71
+
72
+ if (typeof localOperatedNode !== "object") {
73
+ return localOperatedNode;
74
+ }
75
+
76
+ const clone = { ...localOperatedNode };
77
+
78
+ if (Array.isArray(clone.children)) {
79
+ clone.children = walk({
80
+ inNode: clone.children,
81
+ inContext: localContext,
82
+ inData: localData,
83
+ inOperation
84
+ });
85
+ }
86
+
87
+ return clone;
88
+ };
89
+
90
+ export default walk;
@@ -0,0 +1,98 @@
1
+ const replaceWithData = ({
2
+ inNode,
3
+ inData,
4
+ } = {}) => {
5
+ const localNode = inNode;
6
+ const localData = inData;
7
+
8
+ if ("textContent" in inNode) {
9
+ if (inNode.textContent.includes("${")) {
10
+ const dataKey = inNode.textContent
11
+ .replace(/^\$\{/, "")
12
+ .replace(/\}$/, "");
13
+
14
+ if (dataKey.includes(".")) {
15
+ const keysOfArray = dataKey.split(".");
16
+
17
+ const value = keysOfArray.reduce(
18
+ (current, key) => current?.[key],
19
+ inData
20
+ );
21
+
22
+ inNode.textContent = value;
23
+ };
24
+ };
25
+ };
26
+ };
27
+
28
+ const forArray = ({ inNode, inData }) => {
29
+ const localNode = inNode;
30
+ const localData = inData;
31
+
32
+ if (Array.isArray(localNode)) {
33
+ const results = [];
34
+
35
+ for (const child of localNode) {
36
+ const result = walk({
37
+ inNode: child,
38
+ inData
39
+ });
40
+
41
+ if (Array.isArray(result)) {
42
+ results.push(...result);
43
+ } else if (result !== null && result !== undefined) {
44
+ results.push(result);
45
+ };
46
+ };
47
+
48
+ return results;
49
+ };
50
+ };
51
+
52
+ /**
53
+ * Recursively walks a JSON structure.
54
+ *
55
+ * The walker knows only how to traverse.
56
+ * The supplied operation decides what to do with each node.
57
+ */
58
+ const walk = ({
59
+ inNode,
60
+ inData = {},
61
+ inOperation
62
+ } = {}) => {
63
+ const localNode = inNode;
64
+ const localData = inData;
65
+
66
+ if (localNode === null || localNode === undefined) {
67
+ return localNode;
68
+ }
69
+
70
+ if (Array.isArray(localNode)) {
71
+ return forArray({ inNode: localNode, inData });
72
+ };
73
+
74
+ if ("children" in localNode) {
75
+ if (Array.isArray(localNode?.children)) {
76
+ localNode.children = forArray({
77
+ inNode: localNode?.children,
78
+ inData
79
+ });
80
+ };
81
+ };
82
+
83
+ if (typeof localNode !== "object") {
84
+ return localNode;
85
+ };
86
+
87
+ if (typeof localNode === "object") {
88
+ replaceWithData({ inNode, inData });
89
+ };
90
+
91
+ return localNode;
92
+ };
93
+
94
+ export {
95
+ walk
96
+ };
97
+
98
+ export default walk;