@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({ rulesApi, report }) {
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.41",
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": "cd79205599adab600f2e5287c59ffd8f71d60a92c28f544cf5fe719f"
57
+ "falconPackageHash": "75ff158491c0d257f4c8c0c0a34a9cff8171ca1a8112cfe25b219155"
58
58
  }