@wix/zero-config-implementation 1.93.0 → 1.95.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.
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"registry": "https://registry.npmjs.org/",
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "1.
|
|
7
|
+
"version": "1.95.0",
|
|
8
8
|
"description": "Core library for extracting component manifests from JS and CSS files",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"main": "dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@wix/react-component-schema": "1.
|
|
42
|
+
"@wix/react-component-schema": "1.9.0",
|
|
43
43
|
"@wix/seo-service": "^1.9.0",
|
|
44
44
|
"@wix/services-manager": "^1.0.7",
|
|
45
45
|
"@wix/services-manager-react": "^1.0.8",
|
|
@@ -106,5 +106,5 @@
|
|
|
106
106
|
]
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
|
-
"falconPackageHash": "
|
|
109
|
+
"falconPackageHash": "831bcccde22937359efc18de9a5b8b4e52d3ca3fa6ebdbdd9bcb4a65"
|
|
110
110
|
}
|
|
@@ -107,6 +107,103 @@ describe('toEditorReactComponent display conversion', () => {
|
|
|
107
107
|
})
|
|
108
108
|
})
|
|
109
109
|
|
|
110
|
+
// CSS display values whose spelling differs from the enum's. Emitting one
|
|
111
|
+
// unmapped makes DevCenter reject the whole components override, permanently
|
|
112
|
+
// blocking Checkpoint for the project (ECL-18531).
|
|
113
|
+
describe('display value enum mapping', () => {
|
|
114
|
+
const { DISPLAY_VALUE } = CSS_PROPERTIES
|
|
115
|
+
const tagDefaults: [tag: string, cssDisplay: string, enumValue: string][] = [
|
|
116
|
+
['td', 'table-cell', DISPLAY_VALUE.tableCell],
|
|
117
|
+
['th', 'table-cell', DISPLAY_VALUE.tableCell],
|
|
118
|
+
['tr', 'table-row', DISPLAY_VALUE.tableRow],
|
|
119
|
+
['tbody', 'table-row-group', DISPLAY_VALUE.tableRowGroup],
|
|
120
|
+
['thead', 'table-header-group', DISPLAY_VALUE.tableHeaderGroup],
|
|
121
|
+
['tfoot', 'table-footer-group', DISPLAY_VALUE.tableFooterGroup],
|
|
122
|
+
['caption', 'table-caption', DISPLAY_VALUE.tableCaption],
|
|
123
|
+
['col', 'table-column', DISPLAY_VALUE.tableColumn],
|
|
124
|
+
['colgroup', 'table-column-group', DISPLAY_VALUE.tableColumnGroup],
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
it.each(tagDefaults)('maps a <%s> tag default (%s) onto its enum name', (tag, _cssDisplay, expectedEnumValue) => {
|
|
128
|
+
const rootElement = createElementWithDisplayMatcher(tag, matcherDataFromCss(''))
|
|
129
|
+
|
|
130
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
131
|
+
|
|
132
|
+
expect(result.editorElement?.cssProperties?.display).toEqual({
|
|
133
|
+
display: {
|
|
134
|
+
displayValues: [CSS_PROPERTIES.DISPLAY_VALUE.none, expectedEnumValue],
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('treats an explicit `display: table-cell` declaration the same as the tag default', () => {
|
|
140
|
+
const fromTag = toEditorReactComponent(
|
|
141
|
+
createComponent(createElementWithDisplayMatcher('td', matcherDataFromCss(''))),
|
|
142
|
+
)
|
|
143
|
+
const fromCss = toEditorReactComponent(
|
|
144
|
+
createComponent(createElementWithDisplayMatcher('div', matcherDataFromCss('display: table-cell'))),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
expect(fromCss.editorElement?.cssProperties?.display).toEqual(fromTag.editorElement?.cssProperties?.display)
|
|
148
|
+
expect(fromCss.editorElement?.cssProperties?.display).toEqual({
|
|
149
|
+
display: {
|
|
150
|
+
displayValues: [CSS_PROPERTIES.DISPLAY_VALUE.none, CSS_PROPERTIES.DISPLAY_VALUE.tableCell],
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('still maps kebab-case values that do have an enum representation', () => {
|
|
156
|
+
const rootElement = createElementWithDisplayMatcher('div', matcherDataFromCss('display: inline-block'))
|
|
157
|
+
|
|
158
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
159
|
+
|
|
160
|
+
expect(result.editorElement?.cssProperties?.display).toEqual({
|
|
161
|
+
display: {
|
|
162
|
+
displayValues: [CSS_PROPERTIES.DISPLAY_VALUE.none, CSS_PROPERTIES.DISPLAY_VALUE.inlineBlock],
|
|
163
|
+
},
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('never emits a display value outside the enum for any known tag default', () => {
|
|
168
|
+
const allowedValues = new Set<string>(Object.values(CSS_PROPERTIES.DISPLAY_VALUE))
|
|
169
|
+
|
|
170
|
+
for (const [tag] of tagDefaults) {
|
|
171
|
+
const rootElement = createElementWithDisplayMatcher(tag, matcherDataFromCss(''))
|
|
172
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
173
|
+
const emittedValues = result.editorElement?.cssProperties?.display?.display?.displayValues ?? []
|
|
174
|
+
|
|
175
|
+
expect(emittedValues.filter((displayValue) => !allowedValues.has(displayValue))).toEqual([])
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Completeness check driven by the enum itself, so a value added in a future
|
|
181
|
+
* `@wix/component-protocol` bump cannot sit unmapped — which is the gap that
|
|
182
|
+
* made ECL-18531 possible. Values whose CSS spelling already matches the enum
|
|
183
|
+
* name need no entry; those that differ must be mapped.
|
|
184
|
+
*
|
|
185
|
+
* Skips names containing `_`: `UNKNOWN_DisplayValue` and the deprecated
|
|
186
|
+
* snake_case aliases, none of which are CSS spellings.
|
|
187
|
+
*/
|
|
188
|
+
it('reaches every enum value from its CSS spelling', () => {
|
|
189
|
+
const toCssSpelling = (enumValue: string) => enumValue.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)
|
|
190
|
+
|
|
191
|
+
const unreachable = Object.values(CSS_PROPERTIES.DISPLAY_VALUE)
|
|
192
|
+
.filter((enumValue) => !enumValue.includes('_'))
|
|
193
|
+
.filter((enumValue) => {
|
|
194
|
+
const rootElement = createElementWithDisplayMatcher(
|
|
195
|
+
'div',
|
|
196
|
+
matcherDataFromCss(`display: ${toCssSpelling(enumValue)}`),
|
|
197
|
+
)
|
|
198
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
199
|
+
|
|
200
|
+
return result.editorElement?.cssProperties?.display?.display?.displayValues?.[1] !== enumValue
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
expect(unreachable).toEqual([])
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
110
207
|
it('omits the nearest matching ancestor class prefix from inner element display names', () => {
|
|
111
208
|
const rootElement = createSemanticElement({
|
|
112
209
|
traceId: 'trace-root',
|
|
@@ -166,6 +263,29 @@ describe('toEditorReactComponent display conversion', () => {
|
|
|
166
263
|
})
|
|
167
264
|
})
|
|
168
265
|
|
|
266
|
+
describe('toEditorReactComponent — cssProperties defaultValue', () => {
|
|
267
|
+
it('ignores the var() fallback when building a regular CSS property defaultValue', () => {
|
|
268
|
+
const extractorData = new Map<string, unknown>()
|
|
269
|
+
extractorData.set('css-matcher', matcherDataFromCss('background: var(wst-primary-background-color, tomato);'))
|
|
270
|
+
extractorData.set('css-properties', { relevant: [CSS_PROPERTIES.CSS_PROPERTY_TYPE.background] })
|
|
271
|
+
|
|
272
|
+
const rootElement: ExtractedElement = {
|
|
273
|
+
traceId: 'trace-root',
|
|
274
|
+
name: 'root',
|
|
275
|
+
tag: 'div',
|
|
276
|
+
attributes: {},
|
|
277
|
+
extractorData,
|
|
278
|
+
children: [],
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
282
|
+
|
|
283
|
+
expect(result.editorElement?.cssProperties?.background).toEqual({
|
|
284
|
+
defaultValue: 'var(--wst-primary-background-color)',
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
|
|
169
289
|
describe('toEditorReactComponent selector conversion', () => {
|
|
170
290
|
it.each([
|
|
171
291
|
['a', 'a___'],
|
|
@@ -16,6 +16,7 @@ import { IoError } from '../errors'
|
|
|
16
16
|
import { buildRefElementManifestKey } from '../extensions/ref-elements/path-utils'
|
|
17
17
|
import type { RefElementMatch } from '../extensions/ref-elements/types'
|
|
18
18
|
import type { ComponentInfoWithCss } from '../index'
|
|
19
|
+
import { stripVarFallback } from '../information-extractors/css/parse'
|
|
19
20
|
import type { MatchedCssData, RegisteredCustomProperty } from '../information-extractors/css/types'
|
|
20
21
|
import type {
|
|
21
22
|
CoupledComponentInfo,
|
|
@@ -541,20 +542,30 @@ function getMatchedPropertyValues(element: ExtractedElement): Map<string, string
|
|
|
541
542
|
return values
|
|
542
543
|
}
|
|
543
544
|
|
|
544
|
-
const
|
|
545
|
-
'inline-block': 'inlineBlock',
|
|
546
|
-
'inline-flex': 'inlineFlex',
|
|
547
|
-
'inline-grid': 'inlineGrid',
|
|
548
|
-
'inline-table': 'inlineTable',
|
|
549
|
-
'list-item': 'listItem',
|
|
550
|
-
'flow-root': 'flowRoot',
|
|
551
|
-
}
|
|
545
|
+
const { CSS_PROPERTY_TYPE, DISPLAY_VALUE } = CSS_PROPERTIES
|
|
552
546
|
|
|
553
|
-
|
|
554
|
-
|
|
547
|
+
type DisplayEnumValue = NonNullable<Display['displayValues']>[number]
|
|
548
|
+
|
|
549
|
+
const CSS_DISPLAY_TO_ENUM: Record<string, DisplayEnumValue> = {
|
|
550
|
+
'inline-block': DISPLAY_VALUE.inlineBlock,
|
|
551
|
+
'inline-flex': DISPLAY_VALUE.inlineFlex,
|
|
552
|
+
'inline-grid': DISPLAY_VALUE.inlineGrid,
|
|
553
|
+
'inline-table': DISPLAY_VALUE.inlineTable,
|
|
554
|
+
'list-item': DISPLAY_VALUE.listItem,
|
|
555
|
+
'flow-root': DISPLAY_VALUE.flowRoot,
|
|
556
|
+
'table-row-group': DISPLAY_VALUE.tableRowGroup,
|
|
557
|
+
'table-header-group': DISPLAY_VALUE.tableHeaderGroup,
|
|
558
|
+
'table-footer-group': DISPLAY_VALUE.tableFooterGroup,
|
|
559
|
+
'table-row': DISPLAY_VALUE.tableRow,
|
|
560
|
+
'table-cell': DISPLAY_VALUE.tableCell,
|
|
561
|
+
'table-column-group': DISPLAY_VALUE.tableColumnGroup,
|
|
562
|
+
'table-column': DISPLAY_VALUE.tableColumn,
|
|
563
|
+
'table-caption': DISPLAY_VALUE.tableCaption,
|
|
555
564
|
}
|
|
556
565
|
|
|
557
|
-
|
|
566
|
+
function toDisplayEnumValue(cssValue: string): DisplayEnumValue {
|
|
567
|
+
return (CSS_DISPLAY_TO_ENUM[cssValue] ?? cssValue) as DisplayEnumValue
|
|
568
|
+
}
|
|
558
569
|
|
|
559
570
|
function buildCssProperties(element: ExtractedElement | undefined): Record<string, CssPropertyItem> {
|
|
560
571
|
const result: Record<string, CssPropertyItem> = {}
|
|
@@ -570,7 +581,8 @@ function buildCssProperties(element: ExtractedElement | undefined): Record<strin
|
|
|
570
581
|
result[propName] = buildDisplayProperty(element)
|
|
571
582
|
continue
|
|
572
583
|
}
|
|
573
|
-
const
|
|
584
|
+
const resolvedValue = resolveLonghand(propName, cssPropertyValues)
|
|
585
|
+
const defaultValue = resolvedValue !== undefined ? stripVarFallback(resolvedValue) : undefined
|
|
574
586
|
result[propName] = {
|
|
575
587
|
...(defaultValue !== undefined && { defaultValue }),
|
|
576
588
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { parseCss, resolveCssPropertyValue } from './parse'
|
|
2
|
+
import { parseCss, resolveCssPropertyValue, stripVarFallback } from './parse'
|
|
3
3
|
|
|
4
4
|
describe('parseCss — getStateClasses', () => {
|
|
5
5
|
it('extracts a custom-class modifier with no paired pseudo', () => {
|
|
@@ -325,3 +325,21 @@ describe('resolveVarIdentifiers — CSS Modules @value compatibility', () => {
|
|
|
325
325
|
expect(contentProperty.value).toBe('"var(foo)"')
|
|
326
326
|
})
|
|
327
327
|
})
|
|
328
|
+
|
|
329
|
+
describe('stripVarFallback', () => {
|
|
330
|
+
it('removes a var() fallback, keeping only the variable reference', () => {
|
|
331
|
+
expect(stripVarFallback('var(--wst-primary-background-color, tomato)')).toBe('var(--wst-primary-background-color)')
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
it('leaves a var() with no fallback unchanged', () => {
|
|
335
|
+
expect(stripVarFallback('var(--x)')).toBe('var(--x)')
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it('strips a fallback embedded within a larger value', () => {
|
|
339
|
+
expect(stripVarFallback('1px solid var(--border-color, gray)')).toBe('1px solid var(--border-color)')
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('leaves a value with no var() unchanged', () => {
|
|
343
|
+
expect(stripVarFallback('10px')).toBe('10px')
|
|
344
|
+
})
|
|
345
|
+
})
|
|
@@ -373,6 +373,34 @@ function resolveVarIdentifiers(valueNode: CssNode, valueAliases: Map<string, str
|
|
|
373
373
|
return generate(valueNode)
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Removes the fallback argument from every var() call in a CSS value string. A var()
|
|
378
|
+
* fallback is not a meaningful "default value" for the editor to surface — only the
|
|
379
|
+
* variable reference itself is — so `var(--x, tomato)` becomes `var(--x)`.
|
|
380
|
+
*/
|
|
381
|
+
export function stripVarFallback(cssValue: string): string {
|
|
382
|
+
if (!cssValue.includes('var(')) return cssValue
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const valueAst = parse(cssValue, { context: 'value' })
|
|
386
|
+
walk(valueAst, {
|
|
387
|
+
visit: 'Function',
|
|
388
|
+
enter(functionNode: FunctionNode) {
|
|
389
|
+
if (functionNode.name !== 'var') return
|
|
390
|
+
const functionArguments = [...functionNode.children]
|
|
391
|
+
const firstCommaIndex = functionArguments.findIndex(
|
|
392
|
+
(argumentNode) => argumentNode.type === 'Operator' && argumentNode.value === ',',
|
|
393
|
+
)
|
|
394
|
+
if (firstCommaIndex === -1) return
|
|
395
|
+
functionNode.children.fromArray(functionArguments.slice(0, firstCommaIndex))
|
|
396
|
+
},
|
|
397
|
+
})
|
|
398
|
+
return generate(valueAst)
|
|
399
|
+
} catch {
|
|
400
|
+
return cssValue
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
376
404
|
/**
|
|
377
405
|
* Extracts all CSS custom property names referenced via var() by walking
|
|
378
406
|
* the declaration value AST for Function nodes named "var".
|