@wix/zero-config-implementation 1.103.0 → 1.105.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.105.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",
|
|
@@ -106,5 +106,5 @@
|
|
|
106
106
|
]
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
|
-
"falconPackageHash": "
|
|
109
|
+
"falconPackageHash": "0c8ba866b638c1cacaeaecfc2e82c36a40e6307f5e3896c922c1dc25"
|
|
110
110
|
}
|
|
@@ -117,7 +117,7 @@ function applyResolvedTypeToDataItem(
|
|
|
117
117
|
return handleObjectType(dataItem, resolvedType, propUsages, propPath)
|
|
118
118
|
|
|
119
119
|
case 'union':
|
|
120
|
-
return handleUnionType(dataItem, resolvedType, propInfo)
|
|
120
|
+
return handleUnionType({ dataItem, resolvedType, propInfo, propUsages, propPath })
|
|
121
121
|
|
|
122
122
|
case 'function':
|
|
123
123
|
handleFunctionType(dataItem, propInfo, bindings)
|
|
@@ -290,11 +290,19 @@ function handleObjectType(
|
|
|
290
290
|
* Handles union types by detecting special patterns (boolean literals,
|
|
291
291
|
* string literal enums) or falling back to the first valid member type.
|
|
292
292
|
*/
|
|
293
|
-
function handleUnionType(
|
|
294
|
-
dataItem
|
|
295
|
-
resolvedType
|
|
296
|
-
propInfo
|
|
297
|
-
|
|
293
|
+
function handleUnionType({
|
|
294
|
+
dataItem,
|
|
295
|
+
resolvedType,
|
|
296
|
+
propInfo,
|
|
297
|
+
propUsages,
|
|
298
|
+
propPath,
|
|
299
|
+
}: {
|
|
300
|
+
dataItem: DataItem
|
|
301
|
+
resolvedType: ResolvedType
|
|
302
|
+
propInfo: PropInfo
|
|
303
|
+
propUsages?: TrackingStores['propUsages']
|
|
304
|
+
propPath?: string
|
|
305
|
+
}): Result<void, ParseErrorInstance> {
|
|
298
306
|
if (!resolvedType.types || resolvedType.types.length === 0) {
|
|
299
307
|
dataItem.dataType = DATA_TYPE.text
|
|
300
308
|
dataItem.text = {}
|
|
@@ -341,7 +349,7 @@ function handleUnionType(
|
|
|
341
349
|
// For other unions, use the first valid type
|
|
342
350
|
const firstValidType = validTypes[0]
|
|
343
351
|
if (firstValidType) {
|
|
344
|
-
return applyResolvedTypeToDataItem(dataItem, firstValidType, propInfo)
|
|
352
|
+
return applyResolvedTypeToDataItem(dataItem, firstValidType, propInfo, propUsages, propPath)
|
|
345
353
|
}
|
|
346
354
|
|
|
347
355
|
dataItem.dataType = DATA_TYPE.text
|
|
@@ -374,6 +374,48 @@ describe('toEditorReactComponent — cssProperties defaultValue', () => {
|
|
|
374
374
|
expect(result.editorElement?.cssProperties?.overflow).toEqual({ defaultValue: 'hidden' })
|
|
375
375
|
})
|
|
376
376
|
|
|
377
|
+
it("excludes margin from the root element but keeps it on inner elements (editor's layout positions the root on stage)", () => {
|
|
378
|
+
const marginProperties = [
|
|
379
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.margin,
|
|
380
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginTop,
|
|
381
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginRight,
|
|
382
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginBottom,
|
|
383
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginLeft,
|
|
384
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginInlineStart,
|
|
385
|
+
CSS_PROPERTIES.CSS_PROPERTY_TYPE.marginInlineEnd,
|
|
386
|
+
]
|
|
387
|
+
const createExtractorData = () => {
|
|
388
|
+
const extractorData = new Map<string, unknown>()
|
|
389
|
+
extractorData.set('css-matcher', matcherDataFromCss(''))
|
|
390
|
+
extractorData.set('css-properties', { relevant: marginProperties })
|
|
391
|
+
return extractorData
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const childElement: ExtractedElement = {
|
|
395
|
+
traceId: 'trace-icon',
|
|
396
|
+
name: 'icon',
|
|
397
|
+
tag: 'div',
|
|
398
|
+
attributes: {},
|
|
399
|
+
extractorData: createExtractorData(),
|
|
400
|
+
children: [],
|
|
401
|
+
}
|
|
402
|
+
const rootElement: ExtractedElement = {
|
|
403
|
+
traceId: 'trace-root',
|
|
404
|
+
name: 'root',
|
|
405
|
+
tag: 'div',
|
|
406
|
+
attributes: {},
|
|
407
|
+
extractorData: createExtractorData(),
|
|
408
|
+
children: [childElement],
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const result = toEditorReactComponent(createComponent(rootElement))
|
|
412
|
+
|
|
413
|
+
for (const property of marginProperties) {
|
|
414
|
+
expect(result.editorElement?.cssProperties?.[property]).toBeUndefined()
|
|
415
|
+
expect(result.editorElement?.elements?.icon?.inlineElement?.cssProperties?.[property]).toEqual({})
|
|
416
|
+
}
|
|
417
|
+
})
|
|
418
|
+
|
|
377
419
|
it('keeps width/height on inner (non-root) elements', () => {
|
|
378
420
|
const rootExtractorData = new Map<string, unknown>()
|
|
379
421
|
rootExtractorData.set('css-matcher', matcherDataFromCss(''))
|
|
@@ -576,9 +576,20 @@ function toDisplayEnumValue(cssValue: string): DisplayEnumValue {
|
|
|
576
576
|
return (CSS_DISPLAY_TO_ENUM[cssValue] ?? cssValue) as DisplayEnumValue
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
-
//
|
|
580
|
-
//
|
|
581
|
-
|
|
579
|
+
// CSS properties left out of the root element's own `cssProperties`:
|
|
580
|
+
// - `width`/`height`: root sizing is handled separately via layout config.
|
|
581
|
+
// - margins: the editor's layout positions the root on stage.
|
|
582
|
+
const ROOT_EXCLUDED_CSS_PROPERTIES = new Set<string>([
|
|
583
|
+
CSS_PROPERTY_TYPE.width,
|
|
584
|
+
CSS_PROPERTY_TYPE.height,
|
|
585
|
+
CSS_PROPERTY_TYPE.margin,
|
|
586
|
+
CSS_PROPERTY_TYPE.marginTop,
|
|
587
|
+
CSS_PROPERTY_TYPE.marginRight,
|
|
588
|
+
CSS_PROPERTY_TYPE.marginBottom,
|
|
589
|
+
CSS_PROPERTY_TYPE.marginLeft,
|
|
590
|
+
CSS_PROPERTY_TYPE.marginInlineStart,
|
|
591
|
+
CSS_PROPERTY_TYPE.marginInlineEnd,
|
|
592
|
+
])
|
|
582
593
|
|
|
583
594
|
function buildCssProperties(
|
|
584
595
|
element: ExtractedElement | undefined,
|
package/src/manifest-pipeline.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
|
|
3
3
|
import type { ComponentInfo } from './information-extractors/ts'
|
|
4
|
-
import type { PropInfo } from './information-extractors/ts/types'
|
|
4
|
+
import type { PropInfo, ResolvedType } from './information-extractors/ts/types'
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
type ExtractedElement,
|
|
@@ -227,10 +227,11 @@ function processElementPropsWrites(
|
|
|
227
227
|
if (!relativePath) continue
|
|
228
228
|
|
|
229
229
|
// Resolve the PropInfo for this leaf prop by walking the type tree
|
|
230
|
-
const
|
|
231
|
-
if (!
|
|
230
|
+
const resolvedProp = resolveInnerPropInfo(elementPropsInfo, relativePath)
|
|
231
|
+
if (!resolvedProp) continue
|
|
232
|
+
const { propInfo, relativePropPath } = resolvedProp
|
|
232
233
|
|
|
233
|
-
const elementPropsPath = extractParentElementPropsPath(
|
|
234
|
+
const elementPropsPath = extractParentElementPropsPath(relativePropPath)
|
|
234
235
|
if (!elementPropsPath) continue
|
|
235
236
|
const bindings = extractBindings(writeInfo)
|
|
236
237
|
|
|
@@ -248,7 +249,7 @@ function processElementPropsWrites(
|
|
|
248
249
|
entry.props[leafName] = {
|
|
249
250
|
...propInfo,
|
|
250
251
|
logicOnly: false,
|
|
251
|
-
propPath:
|
|
252
|
+
propPath: `props.elementProps.${relativePropPath}`,
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
}
|
|
@@ -262,29 +263,44 @@ function processElementPropsWrites(
|
|
|
262
263
|
* e.g., path "navbar.items" -> walk elementProps type -> navbar property -> items property
|
|
263
264
|
* Handles recursive nesting: "hamburgerMenu.elementProps.hamburgerCloseButton.label"
|
|
264
265
|
*/
|
|
265
|
-
function resolveInnerPropInfo(
|
|
266
|
+
function resolveInnerPropInfo(
|
|
267
|
+
elementPropsPropInfo: PropInfo,
|
|
268
|
+
relativePath: string,
|
|
269
|
+
): { propInfo: PropInfo; relativePropPath: string } | null {
|
|
266
270
|
const segments = relativePath.split('.')
|
|
267
|
-
let currentType = elementPropsPropInfo.resolvedType
|
|
271
|
+
let currentType = unwrapOptionalType(elementPropsPropInfo.resolvedType)
|
|
268
272
|
|
|
269
|
-
for (let
|
|
270
|
-
const segment = segments[
|
|
273
|
+
for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex++) {
|
|
274
|
+
const segment = segments[segmentIndex]
|
|
271
275
|
if (!currentType.properties) return null
|
|
272
276
|
|
|
273
277
|
const propInfo = currentType.properties[segment]
|
|
274
278
|
if (!propInfo) return null
|
|
275
279
|
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
280
|
+
// A11y is one semantic data item. Its tracked DOM writes point at fields
|
|
281
|
+
// such as next.a11y.ariaLabel, but the type has no property tree to descend.
|
|
282
|
+
// Keep the parent path so the builder can collect only the used attributes.
|
|
283
|
+
const propType = unwrapOptionalType(propInfo.resolvedType)
|
|
284
|
+
const isA11y = propType.kind === 'semantic' && propType.value === 'A11y'
|
|
285
|
+
if (segmentIndex === segments.length - 1 || isA11y) {
|
|
286
|
+
return { propInfo, relativePropPath: segments.slice(0, segmentIndex + 1).join('.') }
|
|
279
287
|
}
|
|
280
288
|
|
|
281
289
|
// Otherwise, descend into this property's resolved type
|
|
282
|
-
currentType =
|
|
290
|
+
currentType = propType
|
|
283
291
|
}
|
|
284
292
|
|
|
285
293
|
return null
|
|
286
294
|
}
|
|
287
295
|
|
|
296
|
+
function unwrapOptionalType(resolvedType: ResolvedType): ResolvedType {
|
|
297
|
+
if (resolvedType.kind !== 'union') return resolvedType
|
|
298
|
+
const definedTypes = resolvedType.types?.filter(
|
|
299
|
+
(member) => !(member.kind === 'primitive' && (member.value === 'undefined' || member.value === 'null')),
|
|
300
|
+
)
|
|
301
|
+
return definedTypes?.length === 1 ? definedTypes[0] : resolvedType
|
|
302
|
+
}
|
|
303
|
+
|
|
288
304
|
function extractBindings(
|
|
289
305
|
writeInfo: TrackingStores['propUsages'] extends Map<string, infer V> ? V : never,
|
|
290
306
|
): DOMBinding[] {
|