@deneb-ui/cli 2.0.87 → 2.0.89

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 (55) hide show
  1. package/bin/index.js +31 -5
  2. package/package.json +2 -2
  3. package/src/arc/__tests__/acceptance-gates.test.cjs +62 -0
  4. package/src/arc/__tests__/arc.test.cjs +922 -0
  5. package/src/arc/__tests__/canonical.test.cjs +57 -0
  6. package/src/arc/__tests__/classification.test.cjs +54 -0
  7. package/src/arc/__tests__/corpus.test.cjs +144 -0
  8. package/src/arc/__tests__/explain-blocked.test.cjs +192 -0
  9. package/src/arc/__tests__/fuzz.test.cjs +106 -0
  10. package/src/arc/__tests__/interaction.test.cjs +85 -0
  11. package/src/arc/__tests__/visual-regression.test.cjs +99 -0
  12. package/src/arc/acceptance-gates.cjs +119 -0
  13. package/src/arc/canonical-paths.cjs +142 -23
  14. package/src/arc/corpus-verifier.cjs +295 -0
  15. package/src/arc/data-classification.cjs +182 -0
  16. package/src/arc/data-flow.cjs +62 -2
  17. package/src/arc/explain-blocked.cjs +388 -0
  18. package/src/arc/fuzz-engine.cjs +604 -0
  19. package/src/arc/index.cjs +148 -2
  20. package/src/arc/interaction-verifier.cjs +185 -0
  21. package/src/arc/ir-builder.cjs +170 -12
  22. package/src/arc/planner.cjs +16 -1
  23. package/src/arc/residual.cjs +22 -0
  24. package/src/arc/rsc-boundary.cjs +105 -4
  25. package/src/arc/runtime-validator.cjs +65 -0
  26. package/src/arc/semantic.cjs +12 -1
  27. package/src/arc/transformer.cjs +14 -2745
  28. package/src/arc/transforms/assets/tailwind-bg.cjs +38 -0
  29. package/src/arc/transforms/collections/list.cjs +474 -0
  30. package/src/arc/transforms/components/child-card.cjs +268 -0
  31. package/src/arc/transforms/components/compound-content.cjs +49 -0
  32. package/src/arc/transforms/components/reusable-component.cjs +173 -0
  33. package/src/arc/transforms/element-transform.cjs +192 -0
  34. package/src/arc/transforms/healing/conditionals.cjs +295 -0
  35. package/src/arc/transforms/healing/sanitizer.cjs +401 -0
  36. package/src/arc/transforms/index.cjs +195 -0
  37. package/src/arc/transforms/primitives/action.cjs +76 -0
  38. package/src/arc/transforms/primitives/text.cjs +65 -0
  39. package/src/arc/transforms/routing/page-key.cjs +84 -0
  40. package/src/arc/transforms/routing/shared-layout.cjs +294 -0
  41. package/src/arc/transforms/runtime/provider.cjs +230 -0
  42. package/src/arc/transforms/transform-context.cjs +118 -0
  43. package/src/arc/types/acceptance.d.ts +50 -0
  44. package/src/arc/types/canonical.d.ts +50 -0
  45. package/src/arc/types/classification.d.ts +42 -0
  46. package/src/arc/types/corpus.d.ts +52 -0
  47. package/src/arc/types/explain-blocked.d.ts +41 -0
  48. package/src/arc/types/fuzz.d.ts +74 -0
  49. package/src/arc/types/interaction.d.ts +43 -0
  50. package/src/arc/types/ir.d.ts +114 -0
  51. package/src/arc/types/rsc.d.ts +39 -0
  52. package/src/arc/types/visual-regression.d.ts +49 -0
  53. package/src/arc/visual-regression.cjs +195 -0
  54. package/src/arc/workspace.cjs +233 -0
  55. package/src/tools/deneb-template-validator.cjs +17 -17
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ findJsxAttribute,
5
+ siteDataBinding,
6
+ b,
7
+ } = require('../../ast.cjs');
8
+ const { replaceAttrValue, ensurePreviewPath } = require('../transform-context.cjs');
9
+
10
+ function extractTailwindBg(node, transform) {
11
+ const classAttr = findJsxAttribute(node, 'className') || findJsxAttribute(node, 'class');
12
+ if (classAttr && classAttr.value) {
13
+ if (classAttr.value.type === 'StringLiteral' || classAttr.value.type === 'Literal') {
14
+ const cleaned = String(classAttr.value.value).replace(/\bbg-\[url\([^)]+\)\]\s*/g, '').trim();
15
+ classAttr.value = b.stringLiteral(cleaned);
16
+ }
17
+ }
18
+ const urlParts = transform.field.split('.');
19
+ const styleExpr = b.objectExpression([
20
+ b.property(
21
+ 'init',
22
+ b.identifier('backgroundImage'),
23
+ b.templateLiteral(
24
+ [
25
+ b.templateElement({ raw: 'url(', cooked: 'url(' }, false),
26
+ b.templateElement({ raw: ')', cooked: ')' }, true),
27
+ ],
28
+ [siteDataBinding(urlParts, transform.fallback || transform.bgUrl || '', 'image')]
29
+ )
30
+ ),
31
+ ]);
32
+ replaceAttrValue(node, 'style', styleExpr);
33
+ ensurePreviewPath(node, transform.field);
34
+ }
35
+
36
+ module.exports = {
37
+ extractTailwindBg,
38
+ };
@@ -0,0 +1,474 @@
1
+ 'use strict';
2
+
3
+ const recast = require('recast');
4
+ const {
5
+ locKey,
6
+ getJsxName,
7
+ hasJsxAttribute,
8
+ jsxTemplatePathAttr,
9
+ siteDataListBinding,
10
+ extractItemMemberName,
11
+ unwrapExpr,
12
+ b,
13
+ } = require('../../ast.cjs');
14
+ const { BROAD_CONTENT_CONTAINERS } = require('../../fivora-contract.cjs');
15
+ const { findElementByLoc, isModuleLevel, findEnclosingFunction } = require('../transform-context.cjs');
16
+
17
+ function buildCompositeKeyAttribute(binding, indexName) {
18
+ const fields = ['id', 'slug', 'title', 'name'];
19
+ let expr = b.memberExpression(b.identifier(binding), b.identifier(fields[0]), false);
20
+ for (let i = 1; i < fields.length; i++) {
21
+ expr = b.logicalExpression(
22
+ '||',
23
+ expr,
24
+ b.memberExpression(b.identifier(binding), b.identifier(fields[i]), false)
25
+ );
26
+ }
27
+ expr = b.logicalExpression('||', expr, b.identifier(indexName));
28
+ return b.jsxAttribute(b.jsxIdentifier('key'), b.jsxExpressionContainer(expr));
29
+ }
30
+
31
+ function findListContainer(mapCallPath) {
32
+ let current = mapCallPath.parent;
33
+ while (current) {
34
+ const node = current.node || current.value;
35
+ if (node?.type === 'JSXElement') return node;
36
+ current = current.parentPath || current.parent;
37
+ }
38
+ return null;
39
+ }
40
+
41
+ function findMapCall(ast, loc) {
42
+ let found = null;
43
+ recast.types.visit(ast, {
44
+ visitCallExpression(pathNode) {
45
+ const callee = pathNode.node.callee;
46
+ if (
47
+ !found &&
48
+ callee?.type === 'MemberExpression' &&
49
+ !callee.computed &&
50
+ callee.property?.name === 'map'
51
+ ) {
52
+ let hit = false;
53
+ recast.types.visit(pathNode.node, {
54
+ visitJSXElement(inner) {
55
+ if (locKey(inner.node) === loc) {
56
+ hit = true;
57
+ return false;
58
+ }
59
+ this.traverse(inner);
60
+ },
61
+ });
62
+ if (hit) {
63
+ found = pathNode;
64
+ return false;
65
+ }
66
+ }
67
+ this.traverse(pathNode);
68
+ },
69
+ });
70
+ return found;
71
+ }
72
+
73
+ function itemMemberName(expr, binding) {
74
+ return extractItemMemberName(expr, binding);
75
+ }
76
+
77
+ function isDirectItemExpr(expr, binding) {
78
+ if (!expr) return false;
79
+ const unwrapped = unwrapExpr(expr);
80
+ return Boolean(
81
+ unwrapped &&
82
+ (unwrapped.type === 'Identifier' || unwrapped.type === 'JSXIdentifier') &&
83
+ unwrapped.name === binding
84
+ );
85
+ }
86
+
87
+ function wrapItemFieldInSpan(node, textChild, listPath, indexName, property) {
88
+ const nextChildren = [];
89
+ for (const child of node.children || []) {
90
+ if (child === textChild) {
91
+ nextChildren.push(
92
+ b.jsxElement(
93
+ b.jsxOpeningElement(
94
+ b.jsxIdentifier('span'),
95
+ [jsxTemplatePathAttr('data-preview-field-path', listPath, indexName, `.${property}`)],
96
+ false
97
+ ),
98
+ b.jsxClosingElement(b.jsxIdentifier('span')),
99
+ [child],
100
+ false
101
+ )
102
+ );
103
+ } else {
104
+ nextChildren.push(child);
105
+ }
106
+ }
107
+ node.children = nextChildren;
108
+ }
109
+
110
+ function markItemFields(callback, { listPath, binding, indexName }) {
111
+ recast.types.visit(callback, {
112
+ visitJSXElement(pathNode) {
113
+ const node = pathNode.node;
114
+
115
+ for (const attr of node.openingElement.attributes || []) {
116
+ if (attr.type !== 'JSXAttribute' || !attr.value) continue;
117
+ const attrName = attr.name?.name;
118
+ if (attrName !== 'src' && attrName !== 'href') continue;
119
+ const property = itemMemberName(attr.value.expression, binding);
120
+ if (!property) continue;
121
+ if (!hasJsxAttribute(node, 'data-preview-field-path')) {
122
+ node.openingElement.attributes.push(
123
+ jsxTemplatePathAttr('data-preview-field-path', listPath, indexName, `.${property}`)
124
+ );
125
+ }
126
+ }
127
+
128
+ const textChild = (node.children || []).find(
129
+ (child) => child.type === 'JSXExpressionContainer' && itemMemberName(child.expression, binding)
130
+ );
131
+ if (textChild && !hasJsxAttribute(node, 'data-preview-field-path')) {
132
+ const property = itemMemberName(textChild.expression, binding);
133
+ const tagName = getJsxName(node);
134
+ if (BROAD_CONTENT_CONTAINERS.has(tagName) || BROAD_CONTENT_CONTAINERS.has(String(tagName).toLowerCase())) {
135
+ wrapItemFieldInSpan(node, textChild, listPath, indexName, property);
136
+ } else {
137
+ node.openingElement.attributes.push(
138
+ jsxTemplatePathAttr('data-preview-field-path', listPath, indexName, `.${property}`)
139
+ );
140
+ }
141
+ }
142
+
143
+ this.traverse(pathNode);
144
+ },
145
+ });
146
+ }
147
+
148
+ function markComponentRefItemsStatic(callback, binding) {
149
+ recast.types.visit(callback, {
150
+ visitJSXElement(pathNode) {
151
+ const name = pathNode.node.openingElement && pathNode.node.openingElement.name;
152
+ if (
153
+ name &&
154
+ name.type === 'JSXMemberExpression' &&
155
+ name.object &&
156
+ (name.object.type === 'Identifier' || name.object.type === 'JSXIdentifier') &&
157
+ name.object.name === binding
158
+ ) {
159
+ if (!hasJsxAttribute(pathNode.node, 'data-preview-static') && !hasJsxAttribute(pathNode.node, 'data-preview-field-path')) {
160
+ pathNode.node.openingElement.attributes.push(
161
+ b.jsxAttribute(b.jsxIdentifier('data-preview-static'), b.stringLiteral('component-ref'))
162
+ );
163
+ }
164
+ }
165
+ this.traverse(pathNode);
166
+ },
167
+ });
168
+ }
169
+
170
+ function wrapPrimitiveItemFieldInSpan(node, textChild, listPath, indexName) {
171
+ const nextChildren = [];
172
+ for (const child of node.children || []) {
173
+ if (child === textChild) {
174
+ nextChildren.push(
175
+ b.jsxElement(
176
+ b.jsxOpeningElement(
177
+ b.jsxIdentifier('span'),
178
+ [jsxTemplatePathAttr('data-preview-field-path', listPath, indexName, '')],
179
+ false
180
+ ),
181
+ b.jsxClosingElement(b.jsxIdentifier('span')),
182
+ [child],
183
+ false
184
+ )
185
+ );
186
+ } else {
187
+ nextChildren.push(child);
188
+ }
189
+ }
190
+ node.children = nextChildren;
191
+ }
192
+
193
+ function markPrimitiveItemFields(callback, { listPath, binding, indexName }) {
194
+ recast.types.visit(callback, {
195
+ visitJSXElement(pathNode) {
196
+ const node = pathNode.node;
197
+ const textChild = (node.children || []).find(
198
+ (child) => child.type === 'JSXExpressionContainer' && isDirectItemExpr(child.expression, binding)
199
+ );
200
+ if (textChild && !hasJsxAttribute(node, 'data-preview-field-path')) {
201
+ const tagName = getJsxName(node);
202
+ if (
203
+ node.children.length === 1 &&
204
+ (tagName === 'span' || tagName === 'p' || tagName === 'li') &&
205
+ !hasJsxAttribute(node, 'data-preview-item-path')
206
+ ) {
207
+ node.openingElement.attributes.push(
208
+ jsxTemplatePathAttr('data-preview-field-path', listPath, indexName, '')
209
+ );
210
+ } else {
211
+ wrapPrimitiveItemFieldInSpan(node, textChild, listPath, indexName);
212
+ }
213
+ }
214
+ this.traverse(pathNode);
215
+ },
216
+ });
217
+ }
218
+
219
+ function mergeDefaultItemRefsBinding(pathParts, defaultName) {
220
+ const listExpr = siteDataListBinding(pathParts, b.identifier(defaultName));
221
+ return b.callExpression(
222
+ b.memberExpression(listExpr, b.identifier('map'), false),
223
+ [
224
+ b.arrowFunctionExpression(
225
+ [b.identifier('item'), b.identifier('index')],
226
+ b.objectExpression([
227
+ b.spreadElement(
228
+ b.logicalExpression(
229
+ '??',
230
+ b.memberExpression(b.identifier(defaultName), b.identifier('index'), true),
231
+ b.objectExpression([])
232
+ )
233
+ ),
234
+ b.spreadElement(b.identifier('item')),
235
+ ])
236
+ ),
237
+ ]
238
+ );
239
+ }
240
+
241
+ function bindArrayDeclaration(ast, mapCallPath, listPath, isClient = false, mergeDefaultRefs = false, isTypeScript = false) {
242
+ const arrayName = mapCallPath.node.callee.object?.name;
243
+ if (!arrayName) return false;
244
+ let bound = false;
245
+
246
+ recast.types.visit(ast, {
247
+ visitVariableDeclarator(pathNode) {
248
+ const node = pathNode.node;
249
+ if (bound || node.id?.type !== 'Identifier' || node.id.name !== arrayName) {
250
+ this.traverse(pathNode);
251
+ return;
252
+ }
253
+ if (node.init?.type !== 'ArrayExpression') {
254
+ this.traverse(pathNode);
255
+ return;
256
+ }
257
+
258
+ if (isClient && isModuleLevel(pathNode)) {
259
+ const defaultName = 'DEFAULT_' + arrayName;
260
+ node.id.name = defaultName;
261
+ const fnPath = findEnclosingFunction(mapCallPath);
262
+ if (fnPath && fnPath.node.body?.type === 'BlockStatement') {
263
+ const body = fnPath.node.body.body;
264
+ const already = body.some((stmt) => recast.print(stmt).code.includes(`const ${arrayName} =`));
265
+ if (!already) {
266
+ const localId = b.identifier(arrayName);
267
+ if (isTypeScript) {
268
+ localId.typeAnnotation = b.tsTypeAnnotation(b.tsArrayType(b.tsAnyKeyword()));
269
+ }
270
+ const localDecl = b.variableDeclaration('const', [
271
+ b.variableDeclarator(
272
+ localId,
273
+ mergeDefaultRefs
274
+ ? mergeDefaultItemRefsBinding(listPath.split('.'), defaultName)
275
+ : siteDataListBinding(listPath.split('.'), b.identifier(defaultName))
276
+ ),
277
+ ]);
278
+ const hookIdx = body.findIndex((stmt) => recast.print(stmt).code.includes('useSiteData'));
279
+ if (hookIdx >= 0) {
280
+ body.splice(hookIdx + 1, 0, localDecl);
281
+ } else {
282
+ body.unshift(localDecl);
283
+ }
284
+ }
285
+ }
286
+ bound = true;
287
+ return false;
288
+ }
289
+
290
+ if (isTypeScript && node.id?.type === 'Identifier' && !node.id.typeAnnotation) {
291
+ node.id.typeAnnotation = b.tsTypeAnnotation(b.tsArrayType(b.tsAnyKeyword()));
292
+ }
293
+ node.init = siteDataListBinding(listPath.split('.'), node.init);
294
+ bound = true;
295
+ return false;
296
+ },
297
+ });
298
+
299
+ if (!bound) {
300
+ recast.types.visit(ast, {
301
+ visitImportDeclaration(pathNode) {
302
+ if (bound) return false;
303
+ const node = pathNode.node;
304
+ const spec = (node.specifiers || []).find(
305
+ (s) => (s.local?.name || s.imported?.name) === arrayName
306
+ );
307
+ if (!spec) {
308
+ this.traverse(pathNode);
309
+ return;
310
+ }
311
+
312
+ const defaultName = 'DEFAULT_' + arrayName;
313
+ if (spec.type === 'ImportSpecifier') {
314
+ spec.local = b.identifier(defaultName);
315
+ } else if (spec.type === 'ImportDefaultSpecifier') {
316
+ spec.local = b.identifier(defaultName);
317
+ }
318
+
319
+ const fnPath = findEnclosingFunction(mapCallPath);
320
+ if (fnPath && fnPath.node.body?.type === 'BlockStatement') {
321
+ const body = fnPath.node.body.body;
322
+ const already = body.some(
323
+ (stmt) =>
324
+ recast.print(stmt).code.includes(`const ${arrayName} =`) ||
325
+ recast.print(stmt).code.includes(`const ${arrayName}:`)
326
+ );
327
+ if (!already) {
328
+ const localId = b.identifier(arrayName);
329
+ if (isTypeScript) {
330
+ localId.typeAnnotation = b.tsTypeAnnotation(b.tsArrayType(b.tsAnyKeyword()));
331
+ }
332
+ const localDecl = b.variableDeclaration('const', [
333
+ b.variableDeclarator(
334
+ localId,
335
+ mergeDefaultRefs
336
+ ? mergeDefaultItemRefsBinding(listPath.split('.'), defaultName)
337
+ : siteDataListBinding(listPath.split('.'), b.identifier(defaultName))
338
+ ),
339
+ ]);
340
+ const hookIdx = body.findIndex((stmt) => recast.print(stmt).code.includes('useSiteData'));
341
+ if (hookIdx >= 0) {
342
+ body.splice(hookIdx + 1, 0, localDecl);
343
+ } else {
344
+ body.unshift(localDecl);
345
+ }
346
+ }
347
+ }
348
+ bound = true;
349
+ return false;
350
+ },
351
+ });
352
+ }
353
+
354
+ return bound;
355
+ }
356
+
357
+ function applyCollectionTransform(ast, transform, isClient = false, isTypeScript = false) {
358
+ const listPath = transform.listField;
359
+ const binding = transform.itemParam;
360
+ if (!listPath || !binding) return false;
361
+
362
+ const mapCall = findMapCall(ast, transform.loc);
363
+ if (!mapCall) return false;
364
+
365
+ const callback = (mapCall.node.arguments || [])[0];
366
+ if (!callback) return false;
367
+
368
+ let indexName = transform.indexParam;
369
+ if (!indexName) {
370
+ if (callback.params && callback.params.length >= 2 && callback.params[1]?.type === 'Identifier') {
371
+ indexName = callback.params[1].name;
372
+ } else {
373
+ indexName = callback.params.some((p) => p?.name === 'index') ? 'denebIndex' : 'index';
374
+ const indexId = b.identifier(indexName);
375
+ if (isTypeScript) {
376
+ indexId.typeAnnotation = b.tsTypeAnnotation(b.tsNumberKeyword());
377
+ }
378
+ callback.params.push(indexId);
379
+ }
380
+ }
381
+
382
+ if (isTypeScript && callback.params && callback.params.length > 0) {
383
+ const itemParam = callback.params[0];
384
+ if (itemParam && !itemParam.typeAnnotation) {
385
+ itemParam.typeAnnotation = b.tsTypeAnnotation(b.tsAnyKeyword());
386
+ }
387
+ if (callback.params.length >= 2) {
388
+ const idxParam = callback.params[1];
389
+ if (idxParam && !idxParam.typeAnnotation) {
390
+ idxParam.typeAnnotation = b.tsTypeAnnotation(b.tsNumberKeyword());
391
+ }
392
+ }
393
+ }
394
+
395
+ const itemRoot = findElementByLoc(ast, transform.loc);
396
+ if (!itemRoot) return false;
397
+
398
+ const rootTagName = getJsxName(itemRoot.node);
399
+ const isCustomChild = /^[A-Z]/.test(rootTagName);
400
+
401
+ if (isCustomChild) {
402
+ if (!hasJsxAttribute(itemRoot.node, 'previewItemPath')) {
403
+ itemRoot.node.openingElement.attributes.push(
404
+ jsxTemplatePathAttr('previewItemPath', listPath, indexName)
405
+ );
406
+ }
407
+ if (!hasJsxAttribute(itemRoot.node, 'index')) {
408
+ itemRoot.node.openingElement.attributes.push(
409
+ b.jsxAttribute(b.jsxIdentifier('index'), b.jsxExpressionContainer(b.identifier(indexName)))
410
+ );
411
+ }
412
+ }
413
+
414
+ if (!hasJsxAttribute(itemRoot.node, 'data-preview-item-path')) {
415
+ itemRoot.node.openingElement.attributes.push(
416
+ jsxTemplatePathAttr('data-preview-item-path', listPath, indexName)
417
+ );
418
+ }
419
+ if (!hasJsxAttribute(itemRoot.node, 'data-preview-style-target')) {
420
+ itemRoot.node.openingElement.attributes.push(
421
+ jsxTemplatePathAttr('data-preview-style-target', listPath, indexName, '.card')
422
+ );
423
+ itemRoot.node.openingElement.attributes.push(
424
+ b.jsxAttribute(b.jsxIdentifier('data-preview-style-type'), b.stringLiteral('card'))
425
+ );
426
+ }
427
+ if (!hasJsxAttribute(itemRoot.node, 'key')) {
428
+ itemRoot.node.openingElement.attributes.push(
429
+ buildCompositeKeyAttribute(binding, indexName)
430
+ );
431
+ }
432
+
433
+ if (transform.isPrimitiveArray) {
434
+ markPrimitiveItemFields(callback, { listPath, binding, indexName });
435
+ } else {
436
+ markItemFields(callback, { listPath, binding, indexName });
437
+ }
438
+ if (!isCustomChild) {
439
+ markComponentRefItemsStatic(callback, binding);
440
+ }
441
+
442
+ const container = findListContainer(mapCall);
443
+ if (container && !hasJsxAttribute(container, 'data-preview-list-path')) {
444
+ container.openingElement.attributes.push(
445
+ b.jsxAttribute(b.jsxIdentifier('data-preview-list-path'), b.stringLiteral(listPath))
446
+ );
447
+ }
448
+ if (container && !hasJsxAttribute(container, 'data-preview-style-target')) {
449
+ container.openingElement.attributes.push(
450
+ b.jsxAttribute(b.jsxIdentifier('data-preview-style-target'), b.stringLiteral(`${listPath}.grid`))
451
+ );
452
+ container.openingElement.attributes.push(
453
+ b.jsxAttribute(b.jsxIdentifier('data-preview-style-type'), b.stringLiteral('grid'))
454
+ );
455
+ }
456
+
457
+ return bindArrayDeclaration(ast, mapCall, listPath, isClient, Boolean(transform.hasComponentRef), isTypeScript);
458
+ }
459
+
460
+ module.exports = {
461
+ applyCollectionTransform,
462
+ buildCompositeKeyAttribute,
463
+ findMapCall,
464
+ markItemFields,
465
+ wrapItemFieldInSpan,
466
+ markComponentRefItemsStatic,
467
+ itemMemberName,
468
+ isDirectItemExpr,
469
+ markPrimitiveItemFields,
470
+ wrapPrimitiveItemFieldInSpan,
471
+ findListContainer,
472
+ bindArrayDeclaration,
473
+ mergeDefaultItemRefsBinding,
474
+ };