@player-ui/player 0.8.0-next.0 → 0.8.0-next.10

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 (48) hide show
  1. package/dist/Player.native.js +469 -4094
  2. package/dist/Player.native.js.map +1 -1
  3. package/dist/cjs/index.cjs +293 -407
  4. package/dist/cjs/index.cjs.map +1 -1
  5. package/dist/index.legacy-esm.js +291 -409
  6. package/dist/index.mjs +291 -409
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +4 -8
  9. package/src/binding/__tests__/resolver.test.ts +4 -4
  10. package/src/binding-grammar/{ebnf → __tests__/ebnf}/index.ts +2 -2
  11. package/src/binding-grammar/__tests__/parser.test.ts +2 -2
  12. package/src/binding-grammar/{parsimmon → __tests__/parsimmon}/index.ts +2 -2
  13. package/src/binding-grammar/index.ts +0 -2
  14. package/src/plugins/default-view-plugin.ts +4 -0
  15. package/src/view/__tests__/view.immutable.test.ts +8 -1
  16. package/src/view/__tests__/view.test.ts +59 -1
  17. package/src/view/parser/__tests__/parser.test.ts +16 -1
  18. package/src/view/parser/index.ts +46 -262
  19. package/src/view/parser/utils.ts +23 -3
  20. package/src/view/plugins/__tests__/__snapshots__/asset.test.ts.snap +215 -0
  21. package/src/view/plugins/__tests__/__snapshots__/multi-node.test.ts.snap +67 -0
  22. package/src/view/plugins/__tests__/__snapshots__/template.test.ts.snap +56 -54
  23. package/src/view/plugins/__tests__/applicability.test.ts +24 -16
  24. package/src/view/plugins/__tests__/asset.test.ts +140 -0
  25. package/src/view/plugins/__tests__/multi-node.test.ts +38 -0
  26. package/src/view/plugins/__tests__/template.test.ts +48 -388
  27. package/src/view/plugins/applicability.ts +39 -23
  28. package/src/view/plugins/asset.ts +42 -0
  29. package/src/view/plugins/index.ts +3 -1
  30. package/src/view/plugins/multi-node.ts +73 -0
  31. package/src/view/plugins/switch.ts +81 -50
  32. package/src/view/plugins/{template-plugin.ts → template.ts} +38 -24
  33. package/src/view/resolver/__tests__/edgecases.test.ts +14 -1
  34. package/src/view/view.ts +2 -7
  35. package/types/binding-grammar/index.d.ts +0 -2
  36. package/types/view/parser/index.d.ts +6 -11
  37. package/types/view/parser/utils.d.ts +11 -2
  38. package/types/view/plugins/applicability.d.ts +1 -0
  39. package/types/view/plugins/asset.d.ts +8 -0
  40. package/types/view/plugins/index.d.ts +3 -1
  41. package/types/view/plugins/multi-node.d.ts +8 -0
  42. package/types/view/plugins/switch.d.ts +2 -1
  43. package/types/view/plugins/{template-plugin.d.ts → template.d.ts} +2 -2
  44. package/types/binding-grammar/ebnf/index.d.ts +0 -4
  45. package/types/binding-grammar/ebnf/types.d.ts +0 -75
  46. package/types/binding-grammar/parsimmon/index.d.ts +0 -4
  47. /package/src/binding-grammar/{ebnf → __tests__/ebnf}/binding.ebnf +0 -0
  48. /package/src/binding-grammar/{ebnf → __tests__/ebnf}/types.ts +0 -0
@@ -1,9 +1,7 @@
1
- import { omit, setIn } from "timm";
1
+ import { setIn } from "timm";
2
2
  import { SyncBailHook, SyncWaterfallHook } from "tapable-ts";
3
- import type { Template } from "@player-ui/types";
4
3
  import type { AnyAssetType, Node } from "./types";
5
4
  import { NodeType } from "./types";
6
- import { getNodeID, hasAsync } from "./utils";
7
5
 
8
6
  export * from "./types";
9
7
  export * from "./utils";
@@ -17,6 +15,12 @@ export interface ParseObjectOptions {
17
15
  templateDepth?: number;
18
16
  }
19
17
 
18
+ export interface ParseObjectChildOptions {
19
+ key: string;
20
+ path: Node.PathSegment[];
21
+ parentObj: object;
22
+ }
23
+
20
24
  interface NestedObj {
21
25
  /** The values of a nested local object */
22
26
  children: Node.Child[];
@@ -52,16 +56,14 @@ export class Parser {
52
56
  [Node.Node | undefined | null, object]
53
57
  >(),
54
58
 
55
- determineNodeType: new SyncBailHook<[object | string], NodeType>(),
56
-
57
59
  parseNode: new SyncBailHook<
58
60
  [
59
61
  obj: object,
60
62
  nodeType: Node.ChildrenTypes,
61
63
  parseOptions: ParseObjectOptions,
62
- determinedNodeType: NodeType | null,
64
+ childOptions?: ParseObjectChildOptions,
63
65
  ],
64
- Node.Node
66
+ Node.Node | Node.Child[]
65
67
  >(),
66
68
  };
67
69
 
@@ -75,27 +77,6 @@ export class Parser {
75
77
  return viewNode as Node.View;
76
78
  }
77
79
 
78
- private parseAsync(
79
- obj: object,
80
- type: Node.ChildrenTypes,
81
- options: ParseObjectOptions,
82
- ): Node.Node | null {
83
- const parsedAsync = this.parseObject(omit(obj, "async"), type, options);
84
- const parsedNodeId = getNodeID(parsedAsync);
85
- if (parsedAsync !== null && parsedNodeId) {
86
- return this.createASTNode(
87
- {
88
- id: parsedNodeId,
89
- type: NodeType.Async,
90
- value: parsedAsync,
91
- },
92
- obj,
93
- );
94
- }
95
-
96
- return null;
97
- }
98
-
99
80
  public createASTNode(node: Node.Node | null, value: any): Node.Node | null {
100
81
  const tapped = this.hooks.onCreateASTNode.call(node, value);
101
82
 
@@ -106,47 +87,21 @@ export class Parser {
106
87
  return tapped;
107
88
  }
108
89
 
109
- /**
110
- * Checks if there are templated values in the object
111
- *
112
- * @param obj - The Parsed Object to check to see if we have a template array type for
113
- * @param localKey - The key being checked
114
- */
115
- private hasTemplateValues(obj: any, localKey: string) {
116
- return (
117
- Object.hasOwnProperty.call(obj, "template") &&
118
- Array.isArray(obj?.template) &&
119
- obj.template.length &&
120
- obj.template.find((tmpl: any) => tmpl.output === localKey)
121
- );
122
- }
123
-
124
- private hasSwitchKey(localKey: string) {
125
- return localKey === ("staticSwitch" || "dynamicSwitch");
126
- }
127
-
128
90
  public parseObject(
129
91
  obj: object,
130
92
  type: Node.ChildrenTypes = NodeType.Value,
131
93
  options: ParseObjectOptions = { templateDepth: 0 },
132
94
  ): Node.Node | null {
133
- const nodeType = this.hooks.determineNodeType.call(obj);
134
-
135
- if (nodeType !== undefined) {
136
- const parsedNode = this.hooks.parseNode.call(
137
- obj,
138
- type,
139
- options,
140
- nodeType,
141
- );
142
- if (parsedNode) {
143
- return parsedNode;
144
- }
95
+ const parsedNode = this.hooks.parseNode.call(
96
+ obj,
97
+ type,
98
+ options,
99
+ ) as Node.Node | null;
100
+
101
+ if (parsedNode || parsedNode === null) {
102
+ return parsedNode;
145
103
  }
146
104
 
147
- /**
148
- *
149
- */
150
105
  const parseLocalObject = (
151
106
  currentValue: any,
152
107
  objToParse: unknown,
@@ -178,209 +133,39 @@ export class Parser {
178
133
  };
179
134
 
180
135
  const newValue = objEntries.reduce((accumulation, current): NestedObj => {
181
- const { children, ...rest } = accumulation;
136
+ let { value } = accumulation;
137
+ const { children } = accumulation;
182
138
  const [localKey, localValue] = current;
183
- if (localKey === "asset" && typeof localValue === "object") {
184
- const assetAST = this.parseObject(
185
- localValue,
186
- NodeType.Asset,
187
- options,
188
- );
189
-
190
- if (assetAST) {
191
- return {
192
- ...rest,
193
- children: [
194
- ...children,
195
- {
196
- path: [...path, "asset"],
197
- value: assetAST,
198
- },
199
- ],
200
- };
201
- }
202
- } else if (
203
- this.hooks.determineNodeType.call(localKey) === NodeType.Template &&
204
- Array.isArray(localValue)
205
- ) {
206
- const templateChildren = localValue
207
- .map((template: Template) => {
208
- const templateAST = this.hooks.onCreateASTNode.call(
209
- {
210
- type: NodeType.Template,
211
- depth: options.templateDepth ?? 0,
212
- data: template.data,
213
- template: template.value,
214
- dynamic: template.dynamic ?? false,
215
- },
216
- template,
217
- );
218
-
219
- if (templateAST?.type === NodeType.MultiNode) {
220
- templateAST.values.forEach((v) => {
221
- // eslint-disable-next-line no-param-reassign
222
- v.parent = templateAST;
223
- });
224
- }
225
-
226
- if (templateAST) {
227
- return {
228
- path: [...path, template.output],
229
- value: templateAST,
230
- };
231
- }
232
-
233
- // eslint-disable-next-line no-useless-return
234
- return;
235
- })
236
- .filter((element) => !!element);
237
-
238
- return {
239
- ...rest,
240
- children: [...children, ...templateChildren],
241
- } as NestedObj;
242
- } else if (
243
- (localValue &&
244
- this.hooks.determineNodeType.call(localValue) ===
245
- NodeType.Switch) ||
246
- this.hasSwitchKey(localKey)
247
- ) {
248
- const localSwitch = this.hooks.parseNode.call(
249
- this.hasSwitchKey(localKey)
250
- ? { [localKey]: localValue }
251
- : localValue,
252
- NodeType.Value,
253
- options,
254
- NodeType.Switch,
255
- );
256
139
 
257
- if (
258
- localSwitch &&
259
- localSwitch.type === NodeType.Value &&
260
- localSwitch.children?.length === 1 &&
261
- localSwitch.value === undefined
262
- ) {
263
- const firstChild = localSwitch.children[0];
264
-
265
- return {
266
- ...rest,
267
- children: [
268
- ...children,
269
- {
270
- path: [...path, localKey, ...firstChild.path],
271
- value: firstChild.value,
272
- },
273
- ],
274
- };
275
- }
276
-
277
- if (localSwitch) {
278
- return {
279
- ...rest,
280
- children: [
281
- ...children,
282
- {
283
- path: [...path, localKey],
284
- value: localSwitch,
285
- },
286
- ],
287
- };
288
- }
289
- } else if (localValue && hasAsync(localValue)) {
290
- const localAsync = this.parseAsync(
291
- localValue,
292
- NodeType.Value,
293
- options,
294
- );
295
- if (localAsync) {
296
- children.push({
297
- path: [...path, localKey],
298
- value: localAsync,
299
- });
300
- }
301
- } else if (localValue && Array.isArray(localValue)) {
302
- const childValues = localValue
303
- .map((childVal) =>
304
- this.parseObject(childVal, NodeType.Value, options),
305
- )
306
- .filter((child): child is Node.Node => !!child);
307
-
308
- if (childValues.length > 0) {
309
- const multiNode = this.hooks.onCreateASTNode.call(
310
- {
311
- type: NodeType.MultiNode,
312
- override: !this.hasTemplateValues(localObj, localKey),
313
- values: childValues,
314
- },
315
- localValue,
316
- );
317
-
318
- if (multiNode?.type === NodeType.MultiNode) {
319
- multiNode.values.forEach((v) => {
320
- // eslint-disable-next-line no-param-reassign
321
- v.parent = multiNode;
322
- });
323
- }
324
- if (multiNode) {
325
- return {
326
- ...rest,
327
- children: [
328
- ...children,
329
- {
330
- path: [...path, localKey],
331
- value: multiNode,
332
- },
333
- ],
334
- };
335
- }
336
- }
140
+ const newChildren = this.hooks.parseNode.call(
141
+ localValue,
142
+ NodeType.Value,
143
+ options,
144
+ {
145
+ path,
146
+ key: localKey,
147
+ parentObj: localObj,
148
+ },
149
+ ) as Node.Child[];
150
+
151
+ if (newChildren) {
152
+ children.push(...newChildren);
337
153
  } else if (localValue && typeof localValue === "object") {
338
- const determineNodeType =
339
- this.hooks.determineNodeType.call(localValue);
154
+ const result = parseLocalObject(accumulation.value, localValue, [
155
+ ...path,
156
+ localKey,
157
+ ]);
340
158
 
341
- if (determineNodeType === NodeType.Applicability) {
342
- const parsedNode = this.hooks.parseNode.call(
343
- localValue,
344
- NodeType.Value,
345
- options,
346
- determineNodeType,
347
- );
348
- if (parsedNode) {
349
- return {
350
- ...rest,
351
- children: [
352
- ...children,
353
- {
354
- path: [...path, localKey],
355
- value: parsedNode,
356
- },
357
- ],
358
- };
359
- }
360
- } else {
361
- const result = parseLocalObject(accumulation.value, localValue, [
362
- ...path,
363
- localKey,
364
- ]);
365
- return {
366
- value: result.value,
367
- children: [...children, ...result.children],
368
- };
369
- }
159
+ value = result.value;
160
+ children.push(...result.children);
370
161
  } else {
371
- const value = setIn(
372
- accumulation.value,
373
- [...path, localKey],
374
- localValue,
375
- );
376
-
377
- return {
378
- children,
379
- value,
380
- };
162
+ value = setIn(accumulation.value, [...path, localKey], localValue);
381
163
  }
382
164
 
383
- return accumulation;
165
+ return {
166
+ value,
167
+ children,
168
+ };
384
169
  }, defaultValue);
385
170
 
386
171
  return newValue;
@@ -389,18 +174,17 @@ export class Parser {
389
174
  const { value, children } = parseLocalObject(undefined, obj);
390
175
 
391
176
  const baseAst =
392
- value === undefined && children.length === 0
177
+ value === undefined && !children.length
393
178
  ? undefined
394
179
  : {
395
180
  type,
396
181
  value,
397
182
  };
398
183
 
399
- if (baseAst !== undefined && children.length > 0) {
400
- const parent = baseAst as Node.BaseWithChildren<any>;
184
+ if (baseAst && children.length) {
185
+ const parent: Node.BaseWithChildren<any> = baseAst;
401
186
  parent.children = children;
402
187
  children.forEach((child) => {
403
- // eslint-disable-next-line no-param-reassign
404
188
  child.value.parent = parent;
405
189
  });
406
190
  }
@@ -1,8 +1,28 @@
1
1
  import type { Node } from "./types";
2
2
 
3
- /** Check to see if the object contains async */
4
- export function hasAsync(obj: object): boolean {
5
- return Object.prototype.hasOwnProperty.call(obj, "async");
3
+ /**
4
+ * Checks if there are templated values in the object
5
+ *
6
+ * @param obj - The Parsed Object to check to see if we have a template array type for
7
+ * @param localKey - The key being checked
8
+ */
9
+ export function hasTemplateValues(obj: any, localKey: string) {
10
+ return (
11
+ Object.hasOwnProperty.call(obj, "template") &&
12
+ Array.isArray(obj?.template) &&
13
+ obj.template.length &&
14
+ obj.template.find((tmpl: any) => tmpl.output === localKey)
15
+ );
16
+ }
17
+
18
+ /** Check to see if the string is a valid switch key */
19
+ export function hasSwitchKey(localKey: string) {
20
+ return localKey === "staticSwitch" || localKey === "dynamicSwitch";
21
+ }
22
+
23
+ /** Check to see if the string is a valid template key */
24
+ export function hasTemplateKey(localKey: string) {
25
+ return localKey === "template";
6
26
  }
7
27
 
8
28
  /** Get the ID of the Node if there is one */
@@ -0,0 +1,215 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`asset > applicability 1`] = `
4
+ {
5
+ "children": [
6
+ {
7
+ "path": [
8
+ "asset",
9
+ ],
10
+ "value": {
11
+ "children": [
12
+ {
13
+ "path": [
14
+ "values",
15
+ ],
16
+ "value": {
17
+ "override": true,
18
+ "parent": [Circular],
19
+ "type": "multi-node",
20
+ "values": [
21
+ {
22
+ "expression": "{{foo}}",
23
+ "parent": [Circular],
24
+ "type": "applicability",
25
+ "value": {
26
+ "parent": [Circular],
27
+ "type": "value",
28
+ "value": {
29
+ "value": "foo",
30
+ },
31
+ },
32
+ },
33
+ {
34
+ "parent": [Circular],
35
+ "type": "value",
36
+ "value": {
37
+ "value": "bar",
38
+ },
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ ],
44
+ "parent": [Circular],
45
+ "type": "asset",
46
+ "value": undefined,
47
+ },
48
+ },
49
+ ],
50
+ "type": "value",
51
+ "value": undefined,
52
+ }
53
+ `;
54
+
55
+ exports[`asset > multi-node 1`] = `
56
+ {
57
+ "children": [
58
+ {
59
+ "path": [
60
+ "asset",
61
+ ],
62
+ "value": {
63
+ "children": [
64
+ {
65
+ "path": [
66
+ "values",
67
+ ],
68
+ "value": {
69
+ "override": true,
70
+ "parent": [Circular],
71
+ "type": "multi-node",
72
+ "values": [
73
+ {
74
+ "children": [
75
+ {
76
+ "path": [
77
+ "asset",
78
+ ],
79
+ "value": {
80
+ "parent": [Circular],
81
+ "type": "asset",
82
+ "value": {
83
+ "id": "value-1",
84
+ "type": "text",
85
+ "value": "First value in the collection",
86
+ },
87
+ },
88
+ },
89
+ ],
90
+ "parent": [Circular],
91
+ "type": "value",
92
+ "value": undefined,
93
+ },
94
+ ],
95
+ },
96
+ },
97
+ ],
98
+ "parent": [Circular],
99
+ "type": "asset",
100
+ "value": {
101
+ "id": "foo",
102
+ "type": "collection",
103
+ },
104
+ },
105
+ },
106
+ ],
107
+ "type": "value",
108
+ "value": undefined,
109
+ }
110
+ `;
111
+
112
+ exports[`asset > object 1`] = `
113
+ {
114
+ "children": [
115
+ {
116
+ "path": [
117
+ "asset",
118
+ ],
119
+ "value": {
120
+ "parent": [Circular],
121
+ "type": "asset",
122
+ "value": {
123
+ "type": "bar",
124
+ },
125
+ },
126
+ },
127
+ ],
128
+ "type": "value",
129
+ "value": undefined,
130
+ }
131
+ `;
132
+
133
+ exports[`asset > switch 1`] = `
134
+ {
135
+ "children": [
136
+ {
137
+ "path": [
138
+ "title",
139
+ "asset",
140
+ ],
141
+ "value": {
142
+ "parent": [Circular],
143
+ "type": "asset",
144
+ "value": {
145
+ "id": "test",
146
+ "type": "text",
147
+ "value": "test-text.",
148
+ },
149
+ },
150
+ },
151
+ ],
152
+ "type": "value",
153
+ "value": {
154
+ "id": "toughView",
155
+ "type": "view",
156
+ },
157
+ }
158
+ `;
159
+
160
+ exports[`asset > template 1`] = `
161
+ {
162
+ "children": [
163
+ {
164
+ "path": [
165
+ "asset",
166
+ ],
167
+ "value": {
168
+ "children": [
169
+ {
170
+ "path": [
171
+ "values",
172
+ ],
173
+ "value": {
174
+ "override": false,
175
+ "parent": [Circular],
176
+ "type": "multi-node",
177
+ "values": [
178
+ {
179
+ "parent": [Circular],
180
+ "type": "value",
181
+ "value": {
182
+ "value": "{{foo.bar.0}}",
183
+ },
184
+ },
185
+ {
186
+ "parent": [Circular],
187
+ "type": "value",
188
+ "value": {
189
+ "value": "{{foo.bar.1}}",
190
+ },
191
+ },
192
+ {
193
+ "parent": [Circular],
194
+ "type": "value",
195
+ "value": {
196
+ "value": "{{foo.bar.2}}",
197
+ },
198
+ },
199
+ ],
200
+ },
201
+ },
202
+ ],
203
+ "parent": [Circular],
204
+ "type": "asset",
205
+ "value": {
206
+ "id": "foo",
207
+ "type": "collection",
208
+ },
209
+ },
210
+ },
211
+ ],
212
+ "type": "value",
213
+ "value": undefined,
214
+ }
215
+ `;
@@ -0,0 +1,67 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`multi-node > multi-node collection 1`] = `
4
+ {
5
+ "children": [
6
+ {
7
+ "path": [
8
+ "values",
9
+ ],
10
+ "value": {
11
+ "override": true,
12
+ "parent": [Circular],
13
+ "type": "multi-node",
14
+ "values": [
15
+ {
16
+ "children": [
17
+ {
18
+ "path": [
19
+ "asset",
20
+ ],
21
+ "value": {
22
+ "parent": [Circular],
23
+ "type": "asset",
24
+ "value": {
25
+ "id": "value-1",
26
+ "type": "text",
27
+ "value": "First value in the collection",
28
+ },
29
+ },
30
+ },
31
+ ],
32
+ "parent": [Circular],
33
+ "type": "value",
34
+ "value": undefined,
35
+ },
36
+ {
37
+ "children": [
38
+ {
39
+ "path": [
40
+ "asset",
41
+ ],
42
+ "value": {
43
+ "parent": [Circular],
44
+ "type": "asset",
45
+ "value": {
46
+ "id": "value-2",
47
+ "type": "text",
48
+ "value": "Second value in the collection",
49
+ },
50
+ },
51
+ },
52
+ ],
53
+ "parent": [Circular],
54
+ "type": "value",
55
+ "value": undefined,
56
+ },
57
+ ],
58
+ },
59
+ },
60
+ ],
61
+ "type": "value",
62
+ "value": {
63
+ "id": "foo",
64
+ "type": "collection",
65
+ },
66
+ }
67
+ `;