@wix/zero-config-implementation 1.96.0 → 1.97.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.97.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": "0b3ebaeffed6f192d5ccd84f8598e0e524b0edb36eb3ca0961bab4c7"
|
|
110
110
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DATA } from '@wix/react-component-schema'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import type { PropWriteInfo, TrackingStores } from '../information-extractors/react/types'
|
|
4
|
+
import { collectUsedA11yAttributes } from './a11y-builder'
|
|
5
|
+
|
|
6
|
+
function propUsagesFor(propPaths: string[]): TrackingStores['propUsages'] {
|
|
7
|
+
const emptyWriteInfo = (): PropWriteInfo => ({ elements: new Map(), attributes: new Map() })
|
|
8
|
+
return new Map(propPaths.map((propPath) => [propPath, emptyWriteInfo()]))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe('collectUsedA11yAttributes', () => {
|
|
12
|
+
it('returns an empty array when propUsages or propPath is unavailable', () => {
|
|
13
|
+
expect(collectUsedA11yAttributes(undefined, 'props.a11y')).toEqual([])
|
|
14
|
+
expect(collectUsedA11yAttributes(propUsagesFor(['props.a11y.role']), undefined)).toEqual([])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('returns an empty array when no accessibility fields are recorded', () => {
|
|
18
|
+
expect(collectUsedA11yAttributes(propUsagesFor([]), 'props.a11y')).toEqual([])
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('allows only the current editor-configurable fields', () => {
|
|
22
|
+
const allAttributes = Object.values(DATA.A11Y_ATTRIBUTES).map((attribute) => `props.a11y.${attribute}`)
|
|
23
|
+
|
|
24
|
+
expect(collectUsedA11yAttributes(propUsagesFor(allAttributes), 'props.a11y')).toEqual(['ariaLabel', 'tag'])
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('keeps allowed fields in schema order', () => {
|
|
28
|
+
const propUsages = propUsagesFor(['props.a11y.tag', 'props.a11y.role', 'props.a11y.ariaLabel'])
|
|
29
|
+
|
|
30
|
+
expect(collectUsedA11yAttributes(propUsages, 'props.a11y')).toEqual(['ariaLabel', 'tag'])
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import { DATA } from '@wix/react-component-schema'
|
|
2
2
|
import type { TrackingStores } from '../information-extractors/react'
|
|
3
3
|
|
|
4
|
+
type A11yAttribute = (typeof DATA.A11Y_ATTRIBUTES)[keyof typeof DATA.A11Y_ATTRIBUTES]
|
|
5
|
+
|
|
6
|
+
const EDITOR_CONFIGURABLE_A11Y_ATTRIBUTES: ReadonlySet<A11yAttribute> = new Set([
|
|
7
|
+
DATA.A11Y_ATTRIBUTES.ariaLabel,
|
|
8
|
+
DATA.A11Y_ATTRIBUTES.tag,
|
|
9
|
+
])
|
|
10
|
+
|
|
4
11
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* unavailable, returns an empty array — per the schema, an empty list means
|
|
9
|
-
* "all possible A11Y values", which is a safe default.
|
|
12
|
+
* Returns the editor-configurable attributes the component reads, in schema
|
|
13
|
+
* order. The caller must omit the a11y data item when this returns an empty
|
|
14
|
+
* list because the manifest schema interprets an empty list as all attributes.
|
|
10
15
|
*/
|
|
11
16
|
export function collectUsedA11yAttributes(
|
|
12
17
|
propUsages: TrackingStores['propUsages'] | undefined,
|
|
13
18
|
propPath: string | undefined,
|
|
14
|
-
):
|
|
19
|
+
): A11yAttribute[] {
|
|
15
20
|
if (!propUsages || !propPath) return []
|
|
16
21
|
|
|
17
|
-
const
|
|
22
|
+
const usedAttributes: A11yAttribute[] = []
|
|
18
23
|
for (const attribute of Object.values(DATA.A11Y_ATTRIBUTES)) {
|
|
19
|
-
if (attribute
|
|
24
|
+
if (!EDITOR_CONFIGURABLE_A11Y_ATTRIBUTES.has(attribute)) continue
|
|
20
25
|
if (propUsages.has(`${propPath}.${attribute}`)) {
|
|
21
|
-
|
|
26
|
+
usedAttributes.push(attribute)
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
|
-
|
|
29
|
+
|
|
30
|
+
return usedAttributes
|
|
25
31
|
}
|
|
@@ -54,6 +54,45 @@ function createComponent(rootElement: ExtractedElement): ComponentInfoWithCss {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
function createComponentWithA11yUsages(propPaths: string[]): ComponentInfoWithCss {
|
|
58
|
+
return {
|
|
59
|
+
...createComponent(createElementWithDisplayMatcher('div', matcherDataFromCss(''))),
|
|
60
|
+
props: {
|
|
61
|
+
a11y: {
|
|
62
|
+
name: 'a11y',
|
|
63
|
+
type: 'A11y',
|
|
64
|
+
required: false,
|
|
65
|
+
resolvedType: { kind: 'semantic', value: 'A11y', source: '@wix/editor-react-types' },
|
|
66
|
+
propPath: 'props.a11y',
|
|
67
|
+
logicOnly: false,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
propUsages: new Map(propPaths.map((propPath) => [propPath, { elements: new Map(), attributes: new Map() }])),
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
describe('toEditorReactComponent accessibility conversion', () => {
|
|
75
|
+
it('omits the a11y item when the component reads only component-owned fields', () => {
|
|
76
|
+
const component = createComponentWithA11yUsages(['props.a11y.role', 'props.a11y.tabIndex'])
|
|
77
|
+
|
|
78
|
+
expect(toEditorReactComponent(component).editorElement?.data?.a11y).toBeUndefined()
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('emits only the allowed fields when reads are mixed', () => {
|
|
82
|
+
const component = createComponentWithA11yUsages([
|
|
83
|
+
'props.a11y.role',
|
|
84
|
+
'props.a11y.ariaLabel',
|
|
85
|
+
'props.a11y.ariaExpanded',
|
|
86
|
+
'props.a11y.tag',
|
|
87
|
+
])
|
|
88
|
+
|
|
89
|
+
expect(toEditorReactComponent(component).editorElement?.data?.a11y).toMatchObject({
|
|
90
|
+
dataType: 'a11y',
|
|
91
|
+
a11y: { attributes: ['ariaLabel', 'tag'] },
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
57
96
|
function createSemanticElement({
|
|
58
97
|
traceId,
|
|
59
98
|
name,
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
ElementItem,
|
|
11
11
|
States,
|
|
12
12
|
} from '@wix/react-component-schema'
|
|
13
|
-
import { CSS_PROPERTIES, ELEMENTS } from '@wix/react-component-schema'
|
|
13
|
+
import { CSS_PROPERTIES, DATA, ELEMENTS } from '@wix/react-component-schema'
|
|
14
14
|
import { camelCase } from 'case-anything'
|
|
15
15
|
import { IoError } from '../errors'
|
|
16
16
|
import { buildRefElementManifestKey } from '../extensions/ref-elements/path-utils'
|
|
@@ -184,6 +184,7 @@ function buildData(
|
|
|
184
184
|
|
|
185
185
|
const result = buildDataItem(prop, defaultValue, propUsages, prop.propPath)
|
|
186
186
|
if (result.isErr()) throw result.error
|
|
187
|
+
if (result.value.dataType === DATA.DATA_TYPE.a11y && !result.value.a11y?.attributes?.length) continue
|
|
187
188
|
// ActiveItemIndex props default to 0 when no default is specified
|
|
188
189
|
if (prop.activeItemIndexTarget && result.value.defaultValue === undefined) {
|
|
189
190
|
result.value.defaultValue = 0
|