@wix/origami-lint 1.34.41 → 1.34.42
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CONTENT_TARGET, createCssFileReporter, getLayoutLiteral, mergeLayoutScopes, OVERFLOW_TARGET, readLayoutRuleBlocks, SPX_PROPS, SPX_RESOLVER_TYPES } from "../../rules-api/index.js";
|
|
1
|
+
import { CONTENT_TARGET, createCssFileReporter, getLayoutLiteral, mergeLayoutScopes, OVERFLOW_TARGET, PREAMBLE_LAYER, readLayoutRuleBlocks, SPX_PROPS, SPX_RESOLVER_TYPES } from "../../rules-api/index.js";
|
|
2
2
|
import { defineRule } from "./define-rule.js";
|
|
3
|
-
const CHECKS = ['duplicate_property', 'non_layout_property', 'property_outside_target', 'property_in_wrong_target', 'non_container_target_property', 'missing_property_value', 'incompatible_container_property', 'invalid_layout_value', 'missing_container_display', 'missing_grid_column', 'invalid_spx_context', 'unsupported_flex_wrap', 'child_without_container_layout'];
|
|
3
|
+
const CHECKS = ['duplicate_property', 'non_layout_property', 'property_outside_target', 'property_in_wrong_target', 'non_container_target_property', 'missing_property_value', 'incompatible_container_property', 'invalid_layout_value', 'missing_container_display', 'missing_grid_column', 'invalid_spx_context', 'internal_spx_call', 'missing_spx_reference_width', 'unsupported_flex_wrap', 'child_without_container_layout'];
|
|
4
4
|
// ── the tables (propSpecs.ts) ──
|
|
5
5
|
const keywords = (...values) => ({ values, allowed: values.join(', ') });
|
|
6
6
|
const ANY = { allowed: 'any value' };
|
|
@@ -94,7 +94,9 @@ export default defineRule({
|
|
|
94
94
|
});
|
|
95
95
|
// ── the file: each rule block, then each element at each breakpoint ──
|
|
96
96
|
/** The page's layout.css: each rule block, then each element at each breakpoint. */
|
|
97
|
-
function checkLayoutFile(
|
|
97
|
+
function checkLayoutFile(input) {
|
|
98
|
+
checkInternalSpxCalls(input);
|
|
99
|
+
const { rulesApi, report } = input;
|
|
98
100
|
const root = rulesApi.page.css.files.layout;
|
|
99
101
|
if (!root)
|
|
100
102
|
return;
|
|
@@ -116,6 +118,7 @@ function checkBlock(block, reportAt) {
|
|
|
116
118
|
checkPropertiesOnce(block.declarations, `${block.element}'s rule`, reportAt);
|
|
117
119
|
for (const [target, declarations] of block.targets)
|
|
118
120
|
checkPropertiesOnce(declarations, `${block.element}'s \`@origami-target ${target}\` block`, reportAt);
|
|
121
|
+
checkOwnRefWidth(block, reportAt);
|
|
119
122
|
if (block.targets.size === 0)
|
|
120
123
|
return checkLayoutPropertiesOnly(block, reportAt);
|
|
121
124
|
checkRootPropertiesAtTop(block, reportAt);
|
|
@@ -192,6 +195,8 @@ function checkScope(scope, inherited, reportAt) {
|
|
|
192
195
|
reportAt(decl, 'incompatible_container_property', `${element} is a ${own} container (\`display: ${own}\`), and \`${prop}\` is a ${other} property: remove it, or use \`display: ${other}\`.`);
|
|
193
196
|
continue;
|
|
194
197
|
}
|
|
198
|
+
if (hasCssFunction(value, '--layout-spx'))
|
|
199
|
+
continue; // internal_spx_call reports it
|
|
195
200
|
if (prop === 'flex-wrap' && ownType === 'stack')
|
|
196
201
|
continue; // :218 reported it; an inherited flex reads it as a value (:437)
|
|
197
202
|
const spec = ELEMENT_PROPS[prop] ?? ITEM_PROPS[prop] ?? container?.spec;
|
|
@@ -221,6 +226,54 @@ function checkSpxReference({ element, values }, reportAt) {
|
|
|
221
226
|
return;
|
|
222
227
|
reportAt(first, 'invalid_spx_context', `${element}'s spx context is invalid: \`--spx-ref-width\` takes a plain number (1280, no px) and \`--spx-resolver-type\` takes scale or fixed.`);
|
|
223
228
|
}
|
|
229
|
+
/** A rule that uses `--spx()` sets its own `--spx-ref-width`: the build reads each call's width from its rule only (#579), so another
|
|
230
|
+
* rule's width doesn't count; an `@origami-target` block uses its holding rule's. */
|
|
231
|
+
function checkOwnRefWidth({ element, declarations, targets }, reportAt) {
|
|
232
|
+
if (declarations.some((decl) => decl.prop === '--spx-ref-width'))
|
|
233
|
+
return;
|
|
234
|
+
for (const decl of [...declarations, ...[...targets.values()].flat()]) {
|
|
235
|
+
if (hasCssFunction(decl.value, '--spx'))
|
|
236
|
+
reportAt(decl, 'missing_spx_reference_width', `${element} uses \`--spx()\` without \`--spx-ref-width\` in its rule: add \`--spx-ref-width\` to the same rule, like 1280.`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/** No hand-written `--layout-spx()` in layout.css, style.css or theme.css outside the preamble: the build writes it from each `--spx(N)`. */
|
|
240
|
+
function checkInternalSpxCalls({ rulesApi, report }) {
|
|
241
|
+
for (const kind of ['layout', 'style', 'theme']) {
|
|
242
|
+
const reportAt = createCssFileReporter(`${kind}.css`, report);
|
|
243
|
+
rulesApi.page.css.files[kind]?.walkDecls((decl) => {
|
|
244
|
+
if (rulesApi.getEnclosingAtRules(decl).some(({ name, params }) => name === 'layer' && params.trim() === PREAMBLE_LAYER))
|
|
245
|
+
return;
|
|
246
|
+
if (hasCssFunction(decl.value, '--layout-spx'))
|
|
247
|
+
reportAt(decl, 'internal_spx_call', '`--layout-spx()` is internal to the build: write `--spx(N)` instead.');
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** Whether a CSS value calls this function, outside comments and quoted strings. */
|
|
252
|
+
function hasCssFunction(value, functionName) {
|
|
253
|
+
let quote;
|
|
254
|
+
for (let index = 0; index < value.length; index++) {
|
|
255
|
+
const character = value[index];
|
|
256
|
+
if (quote) {
|
|
257
|
+
if (character === '\\')
|
|
258
|
+
index++;
|
|
259
|
+
else if (character === quote)
|
|
260
|
+
quote = undefined;
|
|
261
|
+
}
|
|
262
|
+
else if (character === '/' && value[index + 1] === '*') {
|
|
263
|
+
const end = value.indexOf('*/', index + 2);
|
|
264
|
+
if (end === -1)
|
|
265
|
+
return false;
|
|
266
|
+
index = end + 1;
|
|
267
|
+
}
|
|
268
|
+
else if (character === "'" || character === '"') {
|
|
269
|
+
quote = character;
|
|
270
|
+
}
|
|
271
|
+
else if (!/[\w-]/.test(value[index - 1] ?? '') && value.startsWith(`${functionName}(`, index)) {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
224
277
|
/** The container type the scope's own display gives (resolveContainerType): grid, or flex with no flex-wrap other than nowrap (:218). */
|
|
225
278
|
function checkContainerType({ element, values }, reportAt) {
|
|
226
279
|
const display = values.get('display')?.value.trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-lint",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.42",
|
|
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": {
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
]
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
|
-
"falconPackageHash": "
|
|
57
|
+
"falconPackageHash": "75ff158491c0d257f4c8c0c0a34a9cff8171ca1a8112cfe25b219155"
|
|
58
58
|
}
|