@teleporthq/teleport-uidl-resolver 0.43.22 → 0.43.29

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 (47) hide show
  1. package/__tests__/style-set-definitions/index.ts +81 -0
  2. package/__tests__/unbound-expressions/expression-identifiers.ts +61 -0
  3. package/__tests__/unbound-expressions/index.ts +149 -0
  4. package/dist/cjs/resolver.d.ts.map +1 -1
  5. package/dist/cjs/resolver.js +6 -0
  6. package/dist/cjs/resolver.js.map +1 -1
  7. package/dist/cjs/resolvers/style-set-definitions/index.d.ts.map +1 -1
  8. package/dist/cjs/resolvers/style-set-definitions/index.js +14 -5
  9. package/dist/cjs/resolvers/style-set-definitions/index.js.map +1 -1
  10. package/dist/cjs/resolvers/unbound-expressions/ambient-identifiers.d.ts +21 -0
  11. package/dist/cjs/resolvers/unbound-expressions/ambient-identifiers.d.ts.map +1 -0
  12. package/dist/cjs/resolvers/unbound-expressions/ambient-identifiers.js +92 -0
  13. package/dist/cjs/resolvers/unbound-expressions/ambient-identifiers.js.map +1 -0
  14. package/dist/cjs/resolvers/unbound-expressions/expression-identifiers.d.ts +23 -0
  15. package/dist/cjs/resolvers/unbound-expressions/expression-identifiers.d.ts.map +1 -0
  16. package/dist/cjs/resolvers/unbound-expressions/expression-identifiers.js +205 -0
  17. package/dist/cjs/resolvers/unbound-expressions/expression-identifiers.js.map +1 -0
  18. package/dist/cjs/resolvers/unbound-expressions/index.d.ts +3 -0
  19. package/dist/cjs/resolvers/unbound-expressions/index.d.ts.map +1 -0
  20. package/dist/cjs/resolvers/unbound-expressions/index.js +198 -0
  21. package/dist/cjs/resolvers/unbound-expressions/index.js.map +1 -0
  22. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  23. package/dist/esm/resolver.d.ts.map +1 -1
  24. package/dist/esm/resolver.js +6 -0
  25. package/dist/esm/resolver.js.map +1 -1
  26. package/dist/esm/resolvers/style-set-definitions/index.d.ts.map +1 -1
  27. package/dist/esm/resolvers/style-set-definitions/index.js +14 -5
  28. package/dist/esm/resolvers/style-set-definitions/index.js.map +1 -1
  29. package/dist/esm/resolvers/unbound-expressions/ambient-identifiers.d.ts +21 -0
  30. package/dist/esm/resolvers/unbound-expressions/ambient-identifiers.d.ts.map +1 -0
  31. package/dist/esm/resolvers/unbound-expressions/ambient-identifiers.js +88 -0
  32. package/dist/esm/resolvers/unbound-expressions/ambient-identifiers.js.map +1 -0
  33. package/dist/esm/resolvers/unbound-expressions/expression-identifiers.d.ts +23 -0
  34. package/dist/esm/resolvers/unbound-expressions/expression-identifiers.d.ts.map +1 -0
  35. package/dist/esm/resolvers/unbound-expressions/expression-identifiers.js +201 -0
  36. package/dist/esm/resolvers/unbound-expressions/expression-identifiers.js.map +1 -0
  37. package/dist/esm/resolvers/unbound-expressions/index.d.ts +3 -0
  38. package/dist/esm/resolvers/unbound-expressions/index.d.ts.map +1 -0
  39. package/dist/esm/resolvers/unbound-expressions/index.js +194 -0
  40. package/dist/esm/resolvers/unbound-expressions/index.js.map +1 -0
  41. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +2 -2
  43. package/src/resolver.ts +7 -0
  44. package/src/resolvers/style-set-definitions/index.ts +14 -5
  45. package/src/resolvers/unbound-expressions/ambient-identifiers.ts +87 -0
  46. package/src/resolvers/unbound-expressions/expression-identifiers.ts +211 -0
  47. package/src/resolvers/unbound-expressions/index.ts +209 -0
@@ -75,6 +75,87 @@ describe('Resolves style-sheet', () => {
75
75
  )
76
76
  })
77
77
 
78
+ it('Keeps valid CSS selector keys (incl. attribute selectors) and drops JS-fragment keys', () => {
79
+ const styleSet: Record<string, UIDLStyleSetDefinition> = {
80
+ 'input-group': {
81
+ type: 'reusable-project-style-map' as const,
82
+ content: { display: staticNode('block') },
83
+ className: 'input-group',
84
+ },
85
+ 'input-group label': {
86
+ type: 'reusable-project-style-map' as const,
87
+ content: { display: staticNode('block') },
88
+ className: 'input-group',
89
+ subselectors: ' label',
90
+ },
91
+ 'input-group input[type="number"]': {
92
+ type: 'reusable-project-style-map' as const,
93
+ content: { width: staticNode('100%') },
94
+ className: 'input-group',
95
+ subselectors: ' input[type="number"]',
96
+ },
97
+ 'input-group input[type="range"]': {
98
+ type: 'reusable-project-style-map' as const,
99
+ content: { width: staticNode('100%') },
100
+ className: 'input-group',
101
+ subselectors: ' input[type="range"]',
102
+ },
103
+ // Combinators, pseudo-functions, universal and id selectors are valid CSS
104
+ 'card > span': {
105
+ type: 'reusable-project-style-map' as const,
106
+ content: { display: staticNode('block') },
107
+ className: 'card',
108
+ subselectors: ' > span',
109
+ },
110
+ 'card + .card': {
111
+ type: 'reusable-project-style-map' as const,
112
+ content: { display: staticNode('block') },
113
+ className: 'card',
114
+ subselectors: ' + .card',
115
+ },
116
+ 'list li:nth-child(2n+1)': {
117
+ type: 'reusable-project-style-map' as const,
118
+ content: { display: staticNode('block') },
119
+ className: 'list',
120
+ subselectors: ' li:nth-child(2n+1)',
121
+ },
122
+ 'card:not(.active)': {
123
+ type: 'reusable-project-style-map' as const,
124
+ content: { display: staticNode('block') },
125
+ className: 'card',
126
+ subselectors: ':not(.active)',
127
+ },
128
+ '#main .card': {
129
+ type: 'reusable-project-style-map' as const,
130
+ content: { display: staticNode('block') },
131
+ className: 'main',
132
+ subselectors: ' .card',
133
+ },
134
+ // JS-fragment / invalid keys that must be dropped
135
+ "'coin'": { type: 'reusable-project-style-map' as const, content: {} },
136
+ '{{': { type: 'reusable-project-style-map' as const, content: {} },
137
+ '||': { type: 'reusable-project-style-map' as const, content: {} },
138
+ "t('coin')": { type: 'reusable-project-style-map' as const, content: {} },
139
+ ['$' + '{expr}']: { type: 'reusable-project-style-map' as const, content: {} },
140
+ 'a && b': { type: 'reusable-project-style-map' as const, content: {} },
141
+ '<div>': { type: 'reusable-project-style-map' as const, content: {} },
142
+ }
143
+
144
+ const result = resolveStyleSetDefinitions(styleSet, {})
145
+
146
+ expect(Object.keys(result)).toEqual([
147
+ 'input-group',
148
+ 'input-group label',
149
+ 'input-group input[type="number"]',
150
+ 'input-group input[type="range"]',
151
+ 'card > span',
152
+ 'card + .card',
153
+ 'list li:nth-child(2n+1)',
154
+ 'card:not(.active)',
155
+ '#main .card',
156
+ ])
157
+ })
158
+
78
159
  it(`Resolver doesn't throw any error even if conditions are not passed`, () => {
79
160
  const styleSet: Record<string, UIDLStyleSetDefinition> = {
80
161
  primaryButton: {
@@ -0,0 +1,61 @@
1
+ import { extractRootIdentifiers } from '../../src/resolvers/unbound-expressions/expression-identifiers'
2
+
3
+ const roots = (expression: string): string[] =>
4
+ Array.from(extractRootIdentifiers(expression)).sort()
5
+
6
+ describe('extractRootIdentifiers', () => {
7
+ it('returns the leading identifier of a member expression', () => {
8
+ expect(roots('cat.name')).toEqual(['cat'])
9
+ expect(roots('loc.location_id')).toEqual(['loc'])
10
+ })
11
+
12
+ it('ignores property names accessed via dot and optional chaining', () => {
13
+ expect(roots('item?.id')).toEqual(['item'])
14
+ expect(roots('props.inventoryItem?.name')).toEqual(['props'])
15
+ expect(roots('event.target.value')).toEqual(['event'])
16
+ })
17
+
18
+ it('does not treat words inside string literals as identifiers', () => {
19
+ expect(roots('item?.name || "Item"')).toEqual(['item'])
20
+ expect(roots("tx?.transaction_type || 'Adjustment'")).toEqual(['tx'])
21
+ })
22
+
23
+ it('handles quoted JSON blobs without leaking string keys/values', () => {
24
+ const expression =
25
+ 'JSON.stringify([{"type":"condition","source":"id","destination":params[\'id\'],"operand":"="}])'
26
+ expect(roots(expression)).toEqual(['JSON', 'params'])
27
+ })
28
+
29
+ it('extracts identifiers from template-literal interpolations only', () => {
30
+ // tslint:disable no-invalid-template-strings
31
+ expect(roots('`/edit-inventory-item/${item?.id}`')).toEqual(['item'])
32
+ expect(roots('`/edit-inventory-item/[id]`')).toEqual([])
33
+ expect(roots('`${cat.name} - ${loc.city}`').sort()).toEqual(['cat', 'loc'])
34
+ // tslint:enable no-invalid-template-strings
35
+ })
36
+
37
+ it('collects call-argument references but not property method names', () => {
38
+ expect(roots('Math.max(a, b)').sort()).toEqual(['Math', 'a', 'b'])
39
+ })
40
+
41
+ it('does not treat unquoted object-literal keys as references', () => {
42
+ expect(roots('{ active: item.active }')).toEqual(['item'])
43
+ expect(roots('{ a: cat.name, b: loc.id }').sort()).toEqual(['cat', 'loc'])
44
+ })
45
+
46
+ it('keeps ternary branches and object shorthand values as references', () => {
47
+ expect(roots('flag ? yes : no').sort()).toEqual(['flag', 'no', 'yes'])
48
+ expect(roots('{ item, index }').sort()).toEqual(['index', 'item'])
49
+ })
50
+
51
+ it('ignores keywords and literals', () => {
52
+ expect(roots('typeof cat === "object"')).toEqual(['cat'])
53
+ expect(roots('true')).toEqual([])
54
+ expect(roots('null')).toEqual([])
55
+ })
56
+
57
+ it('returns an empty set for empty or non-string input', () => {
58
+ expect(roots('')).toEqual([])
59
+ expect(Array.from(extractRootIdentifiers(undefined as unknown as string))).toEqual([])
60
+ })
61
+ })
@@ -0,0 +1,149 @@
1
+ import { ComponentUIDL, UIDLElementNode, UIDLNode } from '@teleporthq/teleport-types'
2
+ import { resolveUnboundExpressions } from '../../src/resolvers/unbound-expressions'
3
+
4
+ const expr = (content: string): UIDLNode => ({ type: 'expr', content } as UIDLNode)
5
+
6
+ const optionWith = (child: UIDLNode): UIDLElementNode => ({
7
+ type: 'element',
8
+ content: {
9
+ elementType: 'option',
10
+ attrs: { value: { type: 'static', content: '' } },
11
+ children: [child],
12
+ },
13
+ })
14
+
15
+ const buildComponent = (node: UIDLElementNode): ComponentUIDL =>
16
+ ({
17
+ name: 'AddInventoryItem',
18
+ node,
19
+ propDefinitions: {
20
+ inventoryItem: { type: 'object', defaultValue: {} },
21
+ },
22
+ stateDefinitions: {
23
+ categoryOptions: { type: 'array', defaultValue: [] },
24
+ },
25
+ } as unknown as ComponentUIDL)
26
+
27
+ describe('resolveUnboundExpressions', () => {
28
+ it('neutralises an orphaned option expression that references an unbound iterator', () => {
29
+ const option = optionWith(expr('cat.name'))
30
+ const uidl = buildComponent({
31
+ type: 'element',
32
+ content: { elementType: 'select', children: [option] },
33
+ })
34
+
35
+ resolveUnboundExpressions(uidl)
36
+
37
+ expect(option.content.children[0]).toEqual({ type: 'static', content: '' })
38
+ })
39
+
40
+ it('keeps expressions that reference an in-scope repeater iterator', () => {
41
+ const boundExpr = expr('item?.id')
42
+ const repeater: UIDLNode = {
43
+ type: 'cms-list-repeater',
44
+ content: {
45
+ elementType: 'fragment',
46
+ name: 'list',
47
+ key: 'list',
48
+ renderPropIdentifier: 'item',
49
+ nodes: {
50
+ list: {
51
+ type: 'element',
52
+ content: { elementType: 'div', children: [boundExpr] },
53
+ },
54
+ },
55
+ },
56
+ } as UIDLNode
57
+ const uidl = buildComponent({
58
+ type: 'element',
59
+ content: { elementType: 'container', children: [repeater] },
60
+ })
61
+
62
+ resolveUnboundExpressions(uidl)
63
+
64
+ expect(boundExpr).toEqual({ type: 'expr', content: 'item?.id' })
65
+ })
66
+
67
+ it('flags a repeater iterator referenced outside of its subtree', () => {
68
+ const escaped = optionWith(expr('item?.id'))
69
+ const repeater: UIDLNode = {
70
+ type: 'cms-list-repeater',
71
+ content: {
72
+ elementType: 'fragment',
73
+ name: 'list',
74
+ key: 'list',
75
+ renderPropIdentifier: 'item',
76
+ nodes: {
77
+ list: { type: 'element', content: { elementType: 'div', children: [] } },
78
+ },
79
+ },
80
+ } as UIDLNode
81
+ const uidl = buildComponent({
82
+ type: 'element',
83
+ content: { elementType: 'container', children: [repeater, escaped] },
84
+ })
85
+
86
+ resolveUnboundExpressions(uidl)
87
+
88
+ expect(escaped.content.children[0]).toEqual({ type: 'static', content: '' })
89
+ })
90
+
91
+ it('keeps expressions that reference props, state, globals and event', () => {
92
+ const propsExpr = expr('props.inventoryItem?.name')
93
+ const stateExpr = expr('categoryOptions')
94
+ const globalExpr = expr('JSON.stringify(params)')
95
+ const eventExpr = expr('event.target.value')
96
+ const uidl = buildComponent({
97
+ type: 'element',
98
+ content: {
99
+ elementType: 'container',
100
+ children: [propsExpr, stateExpr, globalExpr, eventExpr],
101
+ },
102
+ })
103
+
104
+ resolveUnboundExpressions(uidl)
105
+
106
+ expect(propsExpr).toEqual({ type: 'expr', content: 'props.inventoryItem?.name' })
107
+ expect(stateExpr).toEqual({ type: 'expr', content: 'categoryOptions' })
108
+ expect(globalExpr).toEqual({ type: 'expr', content: 'JSON.stringify(params)' })
109
+ expect(eventExpr).toEqual({ type: 'expr', content: 'event.target.value' })
110
+ })
111
+
112
+ it('neutralises an unbound expression used as an attribute value', () => {
113
+ const element: UIDLElementNode = {
114
+ type: 'element',
115
+ content: {
116
+ elementType: 'div',
117
+ attrs: {
118
+ 'data-item-id': { type: 'expr', content: 'cat.id' },
119
+ title: { type: 'static', content: 'ok' },
120
+ },
121
+ children: [],
122
+ },
123
+ }
124
+ const uidl = buildComponent(element)
125
+
126
+ resolveUnboundExpressions(uidl)
127
+
128
+ expect(element.content.attrs!['data-item-id']).toEqual({ type: 'static', content: '' })
129
+ expect(element.content.attrs!.title).toEqual({ type: 'static', content: 'ok' })
130
+ })
131
+
132
+ it('preserves surrounding static text when neutralising mixed content', () => {
133
+ const span: UIDLElementNode = {
134
+ type: 'element',
135
+ content: {
136
+ elementType: 'span',
137
+ children: [{ type: 'static', content: 'Hello ' }, expr('cat.name')],
138
+ },
139
+ }
140
+ const uidl = buildComponent(span)
141
+
142
+ resolveUnboundExpressions(uidl)
143
+
144
+ expect(span.content.children).toEqual([
145
+ { type: 'static', content: 'Hello ' },
146
+ { type: 'static', content: '' },
147
+ ])
148
+ })
149
+ })
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,WAAW,EACX,OAAO,EACP,gBAAgB,EAEjB,MAAM,4BAA4B,CAAA;AAMnC;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,OAAO,CAMd;gBAEW,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE;IAQlC,UAAU,CAAC,OAAO,EAAE,OAAO;IAI3B,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,gBAA6C;IAmCxF,cAAc,CACnB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,gBAA6C;CAYzD"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,WAAW,EACX,OAAO,EACP,gBAAgB,EAEjB,MAAM,4BAA4B,CAAA;AAOnC;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,OAAO,CAMd;gBAEW,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE;IAQlC,UAAU,CAAC,OAAO,EAAE,OAAO;IAI3B,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,gBAA6C;IAyCxF,cAAc,CACnB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,gBAA6C;CAYzD"}
@@ -40,6 +40,7 @@ var abilities_1 = require("./resolvers/abilities");
40
40
  var style_set_definitions_1 = require("./resolvers/style-set-definitions");
41
41
  var referenced_styles_1 = require("./resolvers/referenced-styles");
42
42
  var embed_node_1 = require("./resolvers/embed-node");
43
+ var unbound_expressions_1 = require("./resolvers/unbound-expressions");
43
44
  /**
44
45
  * The resolver takes the input UIDL and converts all the abstract node types into
45
46
  * concrete node types, based on the mappings you provide
@@ -80,6 +81,11 @@ var Resolver = /** @class */ (function () {
80
81
  (0, embed_node_1.resolveHtmlNode)(uidl, newOptions);
81
82
  utils.resolveNode(uidl.node, newOptions);
82
83
  utils.resolveNodeInPropDefinitions(uidl, newOptions);
84
+ // Guard against `expr` nodes that reference an out-of-scope identifier
85
+ // (e.g. an orphaned `<option>{{ cat.name }}</option>` whose repeater was
86
+ // never generated). Left untouched they compile to `ReferenceError`s that
87
+ // fail the static export / `next build`.
88
+ (0, unbound_expressions_1.resolveUnboundExpressions)(uidl);
83
89
  utils.createNodesLookup(uidl, lookup);
84
90
  utils.generateUniqueKeys(uidl, lookup);
85
91
  utils.ensureDataSourceUniqueness(uidl.node);
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/style-set-definitions/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EAGvB,MAAM,4BAA4B,CAAA;AAsBnC,eAAO,MAAM,0BAA0B,cAC1B,OAAO,MAAM,EAAE,sBAAsB,CAAC,WACxC,gBAAgB,KACxB,OAAO,MAAM,EAAE,sBAAsB,CA8CvC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/style-set-definitions/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EAGvB,MAAM,4BAA4B,CAAA;AA+BnC,eAAO,MAAM,0BAA0B,cAC1B,OAAO,MAAM,EAAE,sBAAsB,CAAC,WACxC,gBAAgB,KACxB,OAAO,MAAM,EAAE,sBAAsB,CA8CvC,CAAA"}
@@ -32,11 +32,20 @@ var isValidStyleSetKey = function (key) {
32
32
  if (sanitized === null || sanitized.length === 0) {
33
33
  return false;
34
34
  }
35
- // Allow compound CSS selectors like "base-class.modifier" or "base-class.modifier .child-class"
36
- // These are valid CSS and used for state-dependent styling (e.g., dashboard-sidebar.collapsed)
37
- // Also allow pseudo-selectors like "class:hover" and "class:focus-within"
38
- // Reject characters that indicate JS expression fragments or are truly invalid
39
- if (/['"{}|()!@#$%^&*+=<>?/\\]/.test(key)) {
35
+ // Allow real CSS selector syntax used in style-set keys:
36
+ // - compound selectors: "base-class.modifier", "base-class.modifier .child-class"
37
+ // - combinators: "card > span", "card + span", "card ~ span", "list *"
38
+ // - pseudo-selectors / functions: "class:hover", "row:nth-child(2n+1)", "card:not(.active)"
39
+ // - id selectors: "#main .card"
40
+ // - attribute selectors: 'input-group input[type="number"]'
41
+ // Attribute-selector brackets can legitimately contain quotes and "=", so they are stripped
42
+ // before the JS-fragment check below. The remaining blacklist still rejects expression/template
43
+ // fragments such as "'coin'", "{{", "||", "${x}" or "a && b".
44
+ var keyWithoutAttributeSelectors = key.replace(/\[[^\]]*\]/g, '');
45
+ // Reject characters that indicate JS expression fragments or are truly invalid CSS selectors.
46
+ // Note: ( ) * + > # are intentionally NOT rejected so pseudo-functions, combinators, the
47
+ // universal selector and id selectors keep working.
48
+ if (/['"{}|!@$%^&=<?/\\]/.test(keyWithoutAttributeSelectors)) {
40
49
  return false;
41
50
  }
42
51
  // Reject keys that start with a digit
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/resolvers/style-set-definitions/index.ts"],"names":[],"mappings":";AAAA;;;EAGE;;;;;;;;;;;;;;;;;;;;;;;AAEF,+DAAyD;AAOzD,qCAA6C;AAE7C,IAAM,kBAAkB,GAAG,UAAC,GAAW;IACrC,IAAM,SAAS,GAAG,6BAAW,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;IAC1D,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;QAChD,OAAO,KAAK,CAAA;KACb;IACD,gGAAgG;IAChG,+FAA+F;IAC/F,0EAA0E;IAC1E,+EAA+E;IAC/E,IAAI,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACzC,OAAO,KAAK,CAAA;KACb;IACD,sCAAsC;IACtC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACnB,OAAO,KAAK,CAAA;KACb;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEM,IAAM,0BAA0B,GAAG,UACxC,SAAsD,EACtD,OAAyB;IADzB,0BAAA,EAAA,cAAsD;IAGtD,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,UAAC,GAA2C,EAAE,OAAO;QACxF,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE;YAChC,OAAO,GAAG,CAAA;SACX;QACD,IAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;QAC3B,IAAA,KAAkC,QAAQ,WAA3B,EAAf,UAAU,mBAAG,EAAE,KAAA,EAAE,KAAiB,QAAQ,QAAb,EAAZ,OAAO,mBAAG,EAAE,KAAA,CAAa;QAElD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,GAAG,CAAC,OAAO,CAAC,yBACP,QAAQ,KACX,OAAO,EAAE,IAAA,uBAAe,EAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,GAC5D,CAAA;YACD,OAAO,GAAG,CAAA;SACX;QAEK,IAAA,KAA+B,UAAU,CAAC,MAAM,CACpD,UAAC,EAA4E,EAAE,IAAI;gBAAjF,KAAK,QAAA,EAAE,KAAK,QAAA;YACZ,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE;gBAC/B,KAAK,CAAC,IAAI,uBACL,IAAI,KACP,OAAO,EAAE,IAAA,uBAAe,EAAC,IAAI,CAAC,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,IACvD,CAAA;aACH;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE;gBACjC,KAAK,CAAC,IAAI,uBACL,IAAI,KACP,OAAO,EAAE,IAAA,uBAAe,EAAC,IAAI,CAAC,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,IACvD,CAAA;aACH;YACD,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC,EACD,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,EAjBM,WAAW,QAAA,EAAE,aAAa,QAiBhC,CAAA;QAED,GAAG,CAAC,OAAO,CAAC,yBACP,QAAQ,KACX,OAAO,EAAE,IAAA,uBAAe,EAAC,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,EAClD,UAAU,kCACL,aAAa,SACb,WAAW,CAAC,IAAI,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAjC,CAAiC,CAAC,UAEnE,CAAA;QAED,OAAO,GAAG,CAAA;IACZ,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC,CAAA;AAjDY,QAAA,0BAA0B,8BAiDtC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/resolvers/style-set-definitions/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Root identifiers that are always in scope inside a generated component and
3
+ * therefore can never be an "unbound" reference:
4
+ *
5
+ * - values the code generator injects into the render scope (`props`, `state`,
6
+ * `event`, `params`, `context`, `metadata`, and common map callback vars),
7
+ * - standard JavaScript globals / built-ins.
8
+ *
9
+ * Iterator variables introduced by repeaters (`item`, `kpi`, ...) are NOT
10
+ * listed here — they are tracked positionally as the walker descends into a
11
+ * repeater's subtree, so an iterator reference that escapes its repeater is
12
+ * still correctly flagged as unbound.
13
+ */
14
+ export declare const AMBIENT_IDENTIFIERS: Set<string>;
15
+ /**
16
+ * Identifiers emitted by the code generator itself (hoisted constants, internal
17
+ * helpers) are prefixed with `_` or `$`. Treat them as bound so we never touch
18
+ * generator-authored expressions.
19
+ */
20
+ export declare const isGeneratorInternalIdentifier: (identifier: string) => boolean;
21
+ //# sourceMappingURL=ambient-identifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ambient-identifiers.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/unbound-expressions/ambient-identifiers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,aAiE9B,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,eAAgB,MAAM,KAAG,OACT,CAAA"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isGeneratorInternalIdentifier = exports.AMBIENT_IDENTIFIERS = void 0;
4
+ /**
5
+ * Root identifiers that are always in scope inside a generated component and
6
+ * therefore can never be an "unbound" reference:
7
+ *
8
+ * - values the code generator injects into the render scope (`props`, `state`,
9
+ * `event`, `params`, `context`, `metadata`, and common map callback vars),
10
+ * - standard JavaScript globals / built-ins.
11
+ *
12
+ * Iterator variables introduced by repeaters (`item`, `kpi`, ...) are NOT
13
+ * listed here — they are tracked positionally as the walker descends into a
14
+ * repeater's subtree, so an iterator reference that escapes its repeater is
15
+ * still correctly flagged as unbound.
16
+ */
17
+ exports.AMBIENT_IDENTIFIERS = new Set([
18
+ // Code-generator provided render-scope values
19
+ 'props',
20
+ 'state',
21
+ 'context',
22
+ 'ctx',
23
+ 'metadata',
24
+ 'record',
25
+ // Event handler / map callback parameters
26
+ 'event',
27
+ 'evt',
28
+ 'e',
29
+ 'params',
30
+ 'index',
31
+ 'idx',
32
+ 'key',
33
+ 'i',
34
+ // Browser globals
35
+ 'window',
36
+ 'document',
37
+ 'navigator',
38
+ 'location',
39
+ 'history',
40
+ 'screen',
41
+ 'localStorage',
42
+ 'sessionStorage',
43
+ 'console',
44
+ 'fetch',
45
+ 'URL',
46
+ 'URLSearchParams',
47
+ // Language built-ins
48
+ 'globalThis',
49
+ 'undefined',
50
+ 'NaN',
51
+ 'Infinity',
52
+ 'JSON',
53
+ 'Math',
54
+ 'Object',
55
+ 'Array',
56
+ 'String',
57
+ 'Number',
58
+ 'Boolean',
59
+ 'Date',
60
+ 'RegExp',
61
+ 'Map',
62
+ 'Set',
63
+ 'WeakMap',
64
+ 'WeakSet',
65
+ 'Promise',
66
+ 'Symbol',
67
+ 'BigInt',
68
+ 'Error',
69
+ 'TypeError',
70
+ 'Function',
71
+ 'Proxy',
72
+ 'Reflect',
73
+ 'Intl',
74
+ 'parseInt',
75
+ 'parseFloat',
76
+ 'isNaN',
77
+ 'isFinite',
78
+ 'encodeURIComponent',
79
+ 'decodeURIComponent',
80
+ 'encodeURI',
81
+ 'decodeURI',
82
+ ]);
83
+ /**
84
+ * Identifiers emitted by the code generator itself (hoisted constants, internal
85
+ * helpers) are prefixed with `_` or `$`. Treat them as bound so we never touch
86
+ * generator-authored expressions.
87
+ */
88
+ var isGeneratorInternalIdentifier = function (identifier) {
89
+ return identifier.startsWith('_') || identifier.startsWith('$');
90
+ };
91
+ exports.isGeneratorInternalIdentifier = isGeneratorInternalIdentifier;
92
+ //# sourceMappingURL=ambient-identifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ambient-identifiers.js","sourceRoot":"","sources":["../../../../src/resolvers/unbound-expressions/ambient-identifiers.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACU,QAAA,mBAAmB,GAAG,IAAI,GAAG,CAAS;IACjD,8CAA8C;IAC9C,OAAO;IACP,OAAO;IACP,SAAS;IACT,KAAK;IACL,UAAU;IACV,QAAQ;IACR,0CAA0C;IAC1C,OAAO;IACP,KAAK;IACL,GAAG;IACH,QAAQ;IACR,OAAO;IACP,KAAK;IACL,KAAK;IACL,GAAG;IACH,kBAAkB;IAClB,QAAQ;IACR,UAAU;IACV,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IACR,cAAc;IACd,gBAAgB;IAChB,SAAS;IACT,OAAO;IACP,KAAK;IACL,iBAAiB;IACjB,qBAAqB;IACrB,YAAY;IACZ,WAAW;IACX,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,MAAM;IACN,QAAQ;IACR,KAAK;IACL,KAAK;IACL,SAAS;IACT,SAAS;IACT,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,WAAW;IACX,UAAU;IACV,OAAO;IACP,SAAS;IACT,MAAM;IACN,UAAU;IACV,YAAY;IACZ,OAAO;IACP,UAAU;IACV,oBAAoB;IACpB,oBAAoB;IACpB,WAAW;IACX,WAAW;CACZ,CAAC,CAAA;AAEF;;;;GAIG;AACI,IAAM,6BAA6B,GAAG,UAAC,UAAkB;IAC9D,OAAA,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;AAAxD,CAAwD,CAAA;AAD7C,QAAA,6BAA6B,iCACgB"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Extracts the "root" reference identifiers used by a UIDL `expr` node so the
3
+ * resolver can tell whether an expression references a variable that is not in
4
+ * scope (and would therefore throw a `ReferenceError` at render time).
5
+ *
6
+ * A root reference is an identifier that is READ as a variable — e.g. `cat` in
7
+ * `cat.name`, `item` in `` `/edit/${item?.id}` ``, or `params` in
8
+ * `params['id']`. Property names (the `name` in `cat.name`), string-literal
9
+ * contents, and language keywords are NOT roots.
10
+ *
11
+ * The extractor is a small hand-written lexer rather than a full parser so the
12
+ * resolver package stays dependency-free. It only needs to be correct enough to
13
+ * find the leading identifier of every member/call/index expression while
14
+ * ignoring string and template-literal text — which is exactly what
15
+ * distinguishes a genuine unbound reference from an incidental word inside a
16
+ * quoted JSON blob such as
17
+ * `JSON.stringify([{ "type": "condition", "source": "id" }])`.
18
+ */
19
+ /**
20
+ * Returns the set of root reference identifiers read by an expression string.
21
+ */
22
+ export declare const extractRootIdentifiers: (expression: string) => Set<string>;
23
+ //# sourceMappingURL=expression-identifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression-identifiers.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/unbound-expressions/expression-identifiers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwLH;;GAEG;AACH,eAAO,MAAM,sBAAsB,eAAgB,MAAM,KAAG,IAAI,MAAM,CAMrE,CAAA"}