@wix/origami-lint 1.34.42 → 1.34.44
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.
|
@@ -35,7 +35,7 @@ const ITEM_PROPS = {
|
|
|
35
35
|
bottom: SIZE,
|
|
36
36
|
left: SIZE,
|
|
37
37
|
right: SIZE,
|
|
38
|
-
'z-index': { reads: (value) => value === 'auto' || /^calc\(\s*infinity\s*\)$/.test(value), allowed: 'calc(infinity), auto' },
|
|
38
|
+
'z-index': { reads: (value) => value === 'auto' || /^calc\(\s*infinity\s*\)$/.test(value), allowed: 'calc(infinity), auto, or a layer: 1, 51, 100000' },
|
|
39
39
|
'align-self': SELF_ALIGNMENT,
|
|
40
40
|
'justify-self': SELF_ALIGNMENT,
|
|
41
41
|
'scroll-snap-align': keywords('start', 'center', 'end', 'none'),
|
|
@@ -83,6 +83,12 @@ const CONTAINER_PROPS = {
|
|
|
83
83
|
/** A property allowed at the top of a rule with `@origami-target` blocks (isRootLayoutProperty): the element's own, item and spx properties, and the root-target container property. */
|
|
84
84
|
const isRootProperty = (prop) => prop in ELEMENT_PROPS || prop in ITEM_PROPS || SPX_PROPS.includes(prop) || CONTAINER_PROPS[prop]?.target === 'root';
|
|
85
85
|
const isLayoutProperty = (prop) => isRootProperty(prop) || prop in CONTAINER_PROPS;
|
|
86
|
+
/** The element's transformation in layout.css (isLayoutTransformationDeclaration): these properties, and a z-index at a zLayer's value (Z_INDEXES). */
|
|
87
|
+
const TRANSFORMATION_PROPS = ['opacity', 'transform', 'transform-origin', 'filter'];
|
|
88
|
+
const Z_LAYER_INDEXES = ['1', '51', '100000'];
|
|
89
|
+
const isTransformation = (prop, value) => TRANSFORMATION_PROPS.includes(prop) || (prop === 'z-index' && Z_LAYER_INDEXES.includes(value.trim()));
|
|
90
|
+
/** A rule's top-level declarations as the import reads its layout: without the transformation, which it takes out first (withoutTransformationsOf). */
|
|
91
|
+
const withoutTransformation = (declarations) => declarations.filter((decl) => !isTransformation(decl.prop, decl.value));
|
|
86
92
|
export default defineRule({
|
|
87
93
|
name: 'css-layout-properties',
|
|
88
94
|
checks: CHECKS,
|
|
@@ -104,7 +110,9 @@ function checkLayoutFile(input) {
|
|
|
104
110
|
const blocks = readLayoutRuleBlocks(root);
|
|
105
111
|
for (const block of blocks)
|
|
106
112
|
checkBlock(block, reportAt);
|
|
107
|
-
|
|
113
|
+
// The import takes the transformation out of each rule before it reads the layout (withoutTransformationsOf), so `z-index: 5; z-index: 51` keeps the 5 as layout
|
|
114
|
+
const scopes = mergeLayoutScopes(blocks.map((block) => ({ ...block, declarations: withoutTransformation(block.declarations) })));
|
|
115
|
+
checkTransformationValues(blocks, reportAt);
|
|
108
116
|
const defaultTypes = new Map();
|
|
109
117
|
for (const scope of scopes) {
|
|
110
118
|
const inherited = scope.media === null ? undefined : defaultTypes.get(scope.element);
|
|
@@ -115,7 +123,7 @@ function checkLayoutFile(input) {
|
|
|
115
123
|
}
|
|
116
124
|
/** Each property once per block (:498); a rule without targets holds layout properties (:505); with targets, root properties at the top (:512) and each container property in its target (:524). */
|
|
117
125
|
function checkBlock(block, reportAt) {
|
|
118
|
-
checkPropertiesOnce(block.declarations, `${block.element}'s rule`, reportAt);
|
|
126
|
+
checkPropertiesOnce(withoutTransformation(block.declarations), `${block.element}'s rule`, reportAt);
|
|
119
127
|
for (const [target, declarations] of block.targets)
|
|
120
128
|
checkPropertiesOnce(declarations, `${block.element}'s \`@origami-target ${target}\` block`, reportAt);
|
|
121
129
|
checkOwnRefWidth(block, reportAt);
|
|
@@ -134,7 +142,7 @@ function checkPropertiesOnce(declarations, where, reportAt) {
|
|
|
134
142
|
}
|
|
135
143
|
}
|
|
136
144
|
function checkLayoutPropertiesOnly({ element, declarations }, reportAt) {
|
|
137
|
-
for (const decl of declarations) {
|
|
145
|
+
for (const decl of withoutTransformation(declarations)) {
|
|
138
146
|
if (!isLayoutProperty(decl.prop))
|
|
139
147
|
reportAt(decl, 'non_layout_property', `${describeNonLayoutProperty(decl.prop, element)}.`);
|
|
140
148
|
}
|
|
@@ -147,7 +155,7 @@ function describeNonLayoutProperty(prop, element) {
|
|
|
147
155
|
return `\`${prop}\` on ${element} is not a layout property: move it to ${element}'s rule in style.css`;
|
|
148
156
|
}
|
|
149
157
|
function checkRootPropertiesAtTop({ element, declarations }, reportAt) {
|
|
150
|
-
for (const decl of declarations) {
|
|
158
|
+
for (const decl of withoutTransformation(declarations)) {
|
|
151
159
|
if (isRootProperty(decl.prop))
|
|
152
160
|
continue;
|
|
153
161
|
const container = CONTAINER_PROPS[decl.prop];
|
|
@@ -170,11 +178,22 @@ function checkTargetProperties(element, target, declarations, reportAt) {
|
|
|
170
178
|
reportAt(decl, 'property_in_wrong_target', `${element}'s \`${decl.prop}\` goes ${place}, not in ${target}.`);
|
|
171
179
|
}
|
|
172
180
|
else {
|
|
173
|
-
|
|
181
|
+
// A transformation is taken out at the top of the rule only (withoutTransformationsOf reads a rule's own declarations, not its targets)
|
|
182
|
+
const fix = isLayoutProperty(decl.prop) || TRANSFORMATION_PROPS.includes(decl.prop) ? `move it to the top of ${element}'s rule` : `move it to ${element}'s rule in style.css`;
|
|
174
183
|
reportAt(decl, 'non_container_target_property', `\`${decl.prop}\` in ${element}'s \`@origami-target ${target}\` block is not a container property: ${fix}.`);
|
|
175
184
|
}
|
|
176
185
|
}
|
|
177
186
|
}
|
|
187
|
+
/** A transformation at a rule's top has a value: the import reads each one by its last declaration per element and breakpoint (cssByNameOf), so an empty one before a value is not read. */
|
|
188
|
+
function checkTransformationValues(blocks, reportAt) {
|
|
189
|
+
const transformations = blocks.map((block) => ({ ...block, declarations: block.declarations.filter((decl) => isTransformation(decl.prop, decl.value)), targets: new Map() }));
|
|
190
|
+
for (const { element, values } of mergeLayoutScopes(transformations)) {
|
|
191
|
+
for (const [prop, decl] of values) {
|
|
192
|
+
if (decl.value.trim() === '')
|
|
193
|
+
reportAt(decl, 'missing_property_value', `${element}'s \`${prop}\` has no value: write a value or remove the declaration.`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
178
197
|
/** An element at one breakpoint: its spx reference (:417), its container type (:218), each value (:430, :437, :440, :447), a display for its targets (:451), grid-row with grid-column (:264). Returns the container type, for the breakpoints that inherit it. */
|
|
179
198
|
function checkScope(scope, inherited, reportAt) {
|
|
180
199
|
const { element, values } = scope;
|
|
@@ -187,8 +206,8 @@ function checkScope(scope, inherited, reportAt) {
|
|
|
187
206
|
reportAt(decl, 'missing_property_value', `${element}'s \`${prop}\` has no value: write a value or remove the declaration.`);
|
|
188
207
|
continue;
|
|
189
208
|
}
|
|
190
|
-
if (SPX_PROPS.includes(prop))
|
|
191
|
-
continue;
|
|
209
|
+
if (SPX_PROPS.includes(prop) || isTransformation(prop, value))
|
|
210
|
+
continue; // a transformation in a target block: checkTargetProperties reports it
|
|
192
211
|
const container = CONTAINER_PROPS[prop];
|
|
193
212
|
if (container && type && !container[type]) {
|
|
194
213
|
const [own, other] = type === 'grid' ? ['grid', 'flex'] : ['flex', 'grid'];
|
|
@@ -305,7 +324,8 @@ const getItems = ({ node, rulesApi }) => rulesApi.getItemElements(node).flatMap(
|
|
|
305
324
|
function checkContainerParent(child, parent, { report, rulesApi }) {
|
|
306
325
|
const byMedia = new Map();
|
|
307
326
|
for (const prop of Object.keys(ITEM_PROPS)) {
|
|
308
|
-
|
|
327
|
+
const layout = (child.css.layout[prop] ?? []).filter((decl) => isOnElement(decl) && !isTransformation(prop, decl.value)); // a zLayer z-index is no item property
|
|
328
|
+
for (const decl of layout)
|
|
309
329
|
byMedia.set(decl.media, [...(byMedia.get(decl.media) ?? []), { prop, decl }]);
|
|
310
330
|
}
|
|
311
331
|
for (const [media, declarations] of byMedia) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-lint",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.44",
|
|
4
4
|
"description": "Offline lint for an exported Origami site: lints the pages that changed since the last passing run",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"eslint": "^10.12.0",
|
|
27
27
|
"postcss": "^8.5.3",
|
|
28
28
|
"typescript": "^5.8.3 || ~6.0.3",
|
|
29
|
-
"@wix/origami-bi": "0.
|
|
29
|
+
"@wix/origami-bi": "0.18.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.0.0",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
]
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
|
-
"falconPackageHash": "
|
|
57
|
+
"falconPackageHash": "dd56bf015e4bd3779535e6af5723b0f06fe7f30031097ebd9e6a964e"
|
|
58
58
|
}
|