@wix/origami-lint 1.34.27 → 1.34.29
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/dist/rules/index.js +2 -1
- package/dist/rules/project/home-page-folder.js +3 -3
- package/dist/rules/site-app/apply-and-presets.js +13 -13
- package/dist/rules/site-app/bindings.js +135 -68
- package/dist/rules/site-app/breakpoints.js +6 -6
- package/dist/rules/site-app/css-file-nesting.js +13 -13
- package/dist/rules/site-app/css-layout-properties.js +14 -15
- package/dist/rules/site-app/css-selectors.js +18 -18
- package/dist/rules/site-app/global-styles.js +19 -19
- package/dist/rules/site-app/no-free-code.js +3 -3
- package/dist/rules/site-app/page-structure.js +11 -11
- package/dist/rules/site-app/slot-attributes.js +4 -4
- package/dist/rules/site-app/slot-placement.js +3 -3
- package/dist/rules/site-app/theme-font-ids.js +7 -49
- package/dist/rules/site-app/theme-font-known.js +30 -0
- package/dist/rules/site-app/theme-root.js +7 -8
- package/dist/rules-api/index.js +2 -2
- package/dist/rules-api/rules-api.js +2 -1
- package/dist/shared/constants.js +4 -0
- package/dist/shared/css.js +54 -0
- package/package.json +2 -2
package/dist/rules/index.js
CHANGED
|
@@ -12,8 +12,9 @@ import pageStructure from "./site-app/page-structure.js";
|
|
|
12
12
|
import slotAttributes from "./site-app/slot-attributes.js";
|
|
13
13
|
import slotPlacement from "./site-app/slot-placement.js";
|
|
14
14
|
import themeFontIds from "./site-app/theme-font-ids.js";
|
|
15
|
+
import themeFontKnown from "./site-app/theme-font-known.js";
|
|
15
16
|
import themeRoot from "./site-app/theme-root.js";
|
|
16
17
|
import noFreeCode from "./site-app/no-free-code.js";
|
|
17
18
|
// Execution registries combine already-checked rules; only this boundary erases their individual key unions.
|
|
18
|
-
export const ruleRegistry = [allowedImports, noFreeCode, pageStructure, noAbsoluteSection, themeFontIds, slotAttributes, themeRoot, breakpoints, cssFileNesting, globalStyles, applyAndPresets, bindings, dataValues, cssLayoutProperties, cssSelectors, slotPlacement];
|
|
19
|
+
export const ruleRegistry = [allowedImports, noFreeCode, pageStructure, noAbsoluteSection, themeFontIds, themeFontKnown, slotAttributes, themeRoot, breakpoints, cssFileNesting, globalStyles, applyAndPresets, bindings, dataValues, cssLayoutProperties, cssSelectors, slotPlacement];
|
|
19
20
|
export { defineRule } from "./site-app/define-rule.js";
|
|
@@ -6,9 +6,9 @@ import { PAGES_FOLDER, POPUPS_FOLDER } from "../../shared/site-files-tree-mappin
|
|
|
6
6
|
import { defineProjectRule } from "./define-project-rule.js";
|
|
7
7
|
const CHECKS = ['missing_home', 'multiple_home_folders', 'nested_home_folder', 'popup_in_parentheses'];
|
|
8
8
|
const EXPECTED_ONE_HOME = `Expected exactly one home page folder "pages/(<slug>)" in ${PAGES_FOLDER}`;
|
|
9
|
-
export const NO_HOME = `${EXPECTED_ONE_HOME}; found 0. Name the home page's folder in parentheses, directly under ${PAGES_FOLDER}, like ${PAGES_FOLDER}/(home)
|
|
10
|
-
export const moreHomes = (count, folder) => `${EXPECTED_ONE_HOME}; found ${count}. Keep the parentheses on the home page's folder only: rename ${folder} to ${withoutParentheses(folder)}
|
|
11
|
-
export const onlyHomeInParentheses = (folder) => `Only the home page is written in parentheses, directly under ${PAGES_FOLDER}/. Rename ${folder} to ${withoutParentheses(folder)}
|
|
9
|
+
export const NO_HOME = `${EXPECTED_ONE_HOME}; found 0. Name the home page's folder in parentheses, directly under ${PAGES_FOLDER}, like ${PAGES_FOLDER}/(home). The import stops without it.`;
|
|
10
|
+
export const moreHomes = (count, folder) => `${EXPECTED_ONE_HOME}; found ${count}. Keep the parentheses on the home page's folder only: rename ${folder} to ${withoutParentheses(folder)}.`;
|
|
11
|
+
export const onlyHomeInParentheses = (folder) => `Only the home page is written in parentheses, directly under ${PAGES_FOLDER}/. Rename ${folder} to ${withoutParentheses(folder)}.`;
|
|
12
12
|
/** A home page's folder: its name in parentheses, `(home)`. */
|
|
13
13
|
const HOME_FOLDER = /^\(.+\)$/;
|
|
14
14
|
export default defineProjectRule({
|
|
@@ -59,7 +59,7 @@ function checkElementRule(node, breakpoint, media, reportInFile) {
|
|
|
59
59
|
const declarations = children.filter((child) => child.type === 'decl');
|
|
60
60
|
const values = declarations.filter((declaration) => !isPresetProperty(declaration.prop));
|
|
61
61
|
if (apply && values.length > 0) {
|
|
62
|
-
reportInFile(values[0], 'apply_with_declarations', `${where}: \`${describeAtRule(apply)}\` can't share a rule with style declarations (${describeProperties(values)}). Put them in the global style (\`@mixin ${apply.params.trim()}\` in theme.css), or under another breakpoint or state; only \`--preset…\` may stay beside the \`@apply
|
|
62
|
+
reportInFile(values[0], 'apply_with_declarations', `${where}: \`${describeAtRule(apply)}\` can't share a rule with style declarations (${describeProperties(values)}). Put them in the global style (\`@mixin ${apply.params.trim()}\` in theme.css), or under another breakpoint or state; only \`--preset…\` may stay beside the \`@apply\`.`);
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
65
|
return { node, selector: node.selector, breakpoint, media, apply, presets: declarations.filter((declaration) => isPresetProperty(declaration.prop)), values };
|
|
@@ -83,7 +83,7 @@ function checkMixinRule(node, mixin, reportInFile) {
|
|
|
83
83
|
return;
|
|
84
84
|
const declarations = children.filter((child) => child.type === 'decl');
|
|
85
85
|
if (declarations.length > 0)
|
|
86
|
-
return reportInFile(declarations[0], 'apply_with_declarations', `${where}: \`${describeAtRule(apply)}\` can't share a rule with declarations (${describeProperties(declarations)}). Move them into \`@mixin ${apply.params.trim()}
|
|
86
|
+
return reportInFile(declarations[0], 'apply_with_declarations', `${where}: \`${describeAtRule(apply)}\` can't share a rule with declarations (${describeProperties(declarations)}). Move them into \`@mixin ${apply.params.trim()}\`.`);
|
|
87
87
|
if (!isApplyWritten(apply))
|
|
88
88
|
reportApplyForm(apply, where, reportInFile);
|
|
89
89
|
}
|
|
@@ -93,7 +93,7 @@ function checkSelectorRules(group, componentClasses, reportInFile) {
|
|
|
93
93
|
const picks = group.flatMap((rule) => rule.presets.flatMap((declaration) => checkPresetName(declaration, where, reportInFile)));
|
|
94
94
|
if (isInnerPartRule(group[0].selector, componentClasses)) {
|
|
95
95
|
for (const { declaration } of picks.filter(({ path }) => path.length > 0)) {
|
|
96
|
-
reportInFile(declaration, 'nested_part_preset', `${where}: \`${declaration.prop}\` can't be set on an inner part's rule, which picks only the part's own preset (\`--preset\`). Write it on the component's own rule, with the part's whole path: \`--preset-<part>-${declaration.prop.slice('--preset-'.length)}
|
|
96
|
+
reportInFile(declaration, 'nested_part_preset', `${where}: \`${declaration.prop}\` can't be set on an inner part's rule, which picks only the part's own preset (\`--preset\`). Write it on the component's own rule, with the part's whole path: \`--preset-<part>-${declaration.prop.slice('--preset-'.length)}\`.`);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
for (const rules of groupByBreakpoint(group)) {
|
|
@@ -102,12 +102,12 @@ function checkSelectorRules(group, componentClasses, reportInFile) {
|
|
|
102
102
|
const breakpointDescription = rules[0].media ? `in \`${describeAtRule(rules[0].media)}\`` : 'outside any @media';
|
|
103
103
|
const applies = rules.filter((rule) => rule.apply);
|
|
104
104
|
for (const rule of applies.slice(1)) {
|
|
105
|
-
reportInFile(rule.apply, 'duplicate_apply', `${where}: two \`@apply\` for this selector ${breakpointDescription} (\`${describeAtRule(applies[0].apply)}\` on line ${getLine(applies[0].apply)}, \`${describeAtRule(rule.apply)}\`): keep one
|
|
105
|
+
reportInFile(rule.apply, 'duplicate_apply', `${where}: two \`@apply\` for this selector ${breakpointDescription} (\`${describeAtRule(applies[0].apply)}\` on line ${getLine(applies[0].apply)}, \`${describeAtRule(rule.apply)}\`): keep one.`);
|
|
106
106
|
}
|
|
107
107
|
const ruleWithValues = rules.find((rule) => rule.values.length > 0);
|
|
108
108
|
if (applies.length > 0 && ruleWithValues) {
|
|
109
109
|
const { apply } = applies[0];
|
|
110
|
-
reportInFile(ruleWithValues.values[0], 'apply_with_declarations', `${where} has both \`${describeAtRule(apply)}\` (line ${getLine(apply)}) and style declarations ${breakpointDescription}: keep one, or move the declarations into the global style (\`@mixin ${apply.params.trim()}\` in theme.css)
|
|
110
|
+
reportInFile(ruleWithValues.values[0], 'apply_with_declarations', `${where} has both \`${describeAtRule(apply)}\` (line ${getLine(apply)}) and style declarations ${breakpointDescription}: keep one, or move the declarations into the global style (\`@mixin ${apply.params.trim()}\` in theme.css).`);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -123,12 +123,12 @@ function checkApplyTargets(elementRules, declaredIds, kind, reportInFile) {
|
|
|
123
123
|
// the build strips a trailing `()`; the import doesn't, and reads `btn()` as the id (astParser.ts MIXIN_ID_PATTERN)
|
|
124
124
|
const called = id.endsWith('()') ? id.slice(0, -2) : null;
|
|
125
125
|
if (called !== null && declaredIds.has(called)) {
|
|
126
|
-
reportInFile(apply, 'invalid_apply_target', `rule \`${selector.trim()}\`: \`@apply --${id}\` reads as the global style \`${id}\`, which the site doesn't have: write \`@apply --${called}\`, without the parentheses
|
|
126
|
+
reportInFile(apply, 'invalid_apply_target', `rule \`${selector.trim()}\`: \`@apply --${id}\` reads as the global style \`${id}\`, which the site doesn't have: write \`@apply --${called}\`, without the parentheses.`);
|
|
127
127
|
continue;
|
|
128
128
|
}
|
|
129
129
|
const nearMiss = [...declaredIds].find((declared) => isOneEditAway(id, declared));
|
|
130
130
|
const fix = nearMiss ? `Did you mean \`@apply --${nearMiss}\`? Otherwise apply` : 'Apply';
|
|
131
|
-
reportInFile(apply, 'missing_apply_target', `rule \`${selector.trim()}\`: \`@apply --${id}\` names no global style: no \`@mixin --${id}\` in theme.css${kind === 'style' ? ' or style.css' : ''}. ${fix} one theme.css declares, or declare \`@mixin --${id}\` in theme.css
|
|
131
|
+
reportInFile(apply, 'missing_apply_target', `rule \`${selector.trim()}\`: \`@apply --${id}\` names no global style: no \`@mixin --${id}\` in theme.css${kind === 'style' ? ' or style.css' : ''}. ${fix} one theme.css declares, or declare \`@mixin --${id}\` in theme.css.`);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
/** A `--preset-<path>` names each part as a CSS identifier (CONV-styleParser.ts:62); returns the pick, or none after reporting. */
|
|
@@ -138,7 +138,7 @@ function checkPresetName(declaration, where, reportInFile) {
|
|
|
138
138
|
const path = decodePresetPath(declaration.prop.slice('--preset-'.length));
|
|
139
139
|
if (path.every(isSafeCssIdentifier))
|
|
140
140
|
return [{ declaration, path }];
|
|
141
|
-
reportInFile(declaration, 'invalid_preset_name', `${where}: \`${declaration.prop}\` doesn't name an inner part: write \`--preset-<part>\`, each part a CSS identifier, parts joined by \`-\` and a \`-\` inside a part's name written \`--\` (\`close-button\` → \`--preset-close--button\`)
|
|
141
|
+
reportInFile(declaration, 'invalid_preset_name', `${where}: \`${declaration.prop}\` doesn't name an inner part: write \`--preset-<part>\`, each part a CSS identifier, parts joined by \`-\` and a \`-\` inside a part's name written \`--\` (\`close-button\` → \`--preset-close--button\`).`);
|
|
142
142
|
return [];
|
|
143
143
|
}
|
|
144
144
|
/** The last pick of each path at one breakpoint is the one the import reads: it has a value (CONV-styleParser.ts:88). */
|
|
@@ -150,7 +150,7 @@ function checkPresetValues(picks, where, reportInFile) {
|
|
|
150
150
|
continue;
|
|
151
151
|
seen.add(key);
|
|
152
152
|
if (!declaration.value.trim())
|
|
153
|
-
reportInFile(declaration, 'missing_preset_value', `${where}: \`${declaration.prop}\` has no value. Write a preset name, or remove the declaration to use no preset
|
|
153
|
+
reportInFile(declaration, 'missing_preset_value', `${where}: \`${declaration.prop}\` has no value. Write a preset name, or remove the declaration to use no preset.`);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
@@ -170,7 +170,7 @@ function checkOneSelectorPerElement(groups, reportInFile) {
|
|
|
170
170
|
if (stylingRule) {
|
|
171
171
|
const first = firstStylingRules.get(target.join(' '));
|
|
172
172
|
if (first && first.selector !== stylingRule.selector) {
|
|
173
|
-
reportInFile(stylingRule.node, 'duplicate_default_style', `\`${stylingRule.selector.trim()}\` and \`${first.selector.trim()}\` (line ${getLine(first.node)}) are one element, and both set its default style: write it under one selector
|
|
173
|
+
reportInFile(stylingRule.node, 'duplicate_default_style', `\`${stylingRule.selector.trim()}\` and \`${first.selector.trim()}\` (line ${getLine(first.node)}) are one element, and both set its default style: write it under one selector.`);
|
|
174
174
|
}
|
|
175
175
|
else if (!first)
|
|
176
176
|
firstStylingRules.set(target.join(' '), stylingRule);
|
|
@@ -187,7 +187,7 @@ function checkOneSelectorPerElement(groups, reportInFile) {
|
|
|
187
187
|
if (!first)
|
|
188
188
|
firstPicks.set(key, { selector: group[0].selector, declaration });
|
|
189
189
|
else
|
|
190
|
-
reportInFile(declaration, 'duplicate_preset', `${describePresetOwner(key)}'s preset is picked twice: \`${first.declaration.prop}\` on \`${first.selector.trim()}\` (line ${getLine(first.declaration)}) and \`${declaration.prop}\` on \`${group[0].selector.trim()}\`. Keep one
|
|
190
|
+
reportInFile(declaration, 'duplicate_preset', `${describePresetOwner(key)}'s preset is picked twice: \`${first.declaration.prop}\` on \`${first.selector.trim()}\` (line ${getLine(first.declaration)}) and \`${declaration.prop}\` on \`${group[0].selector.trim()}\`. Keep one.`);
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
@@ -319,12 +319,12 @@ function groupByBreakpoint(rules) {
|
|
|
319
319
|
// ── reporting ──
|
|
320
320
|
/** Reports the second `@apply` of one rule (CONV-astParser.ts:99); returns null, as the rule isn't read further. */
|
|
321
321
|
function reportTwoApplies(applies, where, why, reportInFile) {
|
|
322
|
-
reportInFile(applies[1], 'duplicate_apply', `${where}: ${applies.length} \`@apply\` in one rule (${applies.map((apply) => `\`${describeAtRule(apply)}\``).join(', ')}). Keep one: ${why}
|
|
322
|
+
reportInFile(applies[1], 'duplicate_apply', `${where}: ${applies.length} \`@apply\` in one rule (${applies.map((apply) => `\`${describeAtRule(apply)}\``).join(', ')}). Keep one: ${why}.`);
|
|
323
323
|
return null;
|
|
324
324
|
}
|
|
325
325
|
/** Reports an `@apply` that isn't one dashed id with no block (CONV-astParser.ts:41); returns null, as the rule isn't read further. */
|
|
326
326
|
function reportApplyForm(apply, where, reportInFile) {
|
|
327
|
-
reportInFile(apply, 'invalid_apply_form', `${where}: \`${describeAtRule(apply)}\` must name one global style by its dashed id. Write \`@apply --<global-style-id>;\`, with no block after it
|
|
327
|
+
reportInFile(apply, 'invalid_apply_form', `${where}: \`${describeAtRule(apply)}\` must name one global style by its dashed id. Write \`@apply --<global-style-id>;\`, with no block after it.`);
|
|
328
328
|
return null;
|
|
329
329
|
}
|
|
330
330
|
/** A pick's key → the element it picks the preset of: '.comp-x|label' → '`label` of `.comp-x`'; '.comp-x' → '`.comp-x`'. */
|