stylelint-plugin-grid 1.0.1 → 1.0.3
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/README.md +30 -22
- package/dist/_internal/grid-placement-analysis.d.ts +20 -0
- package/dist/_internal/grid-placement-analysis.d.ts.map +1 -0
- package/dist/_internal/grid-placement-analysis.js +59 -0
- package/dist/_internal/grid-placement-analysis.js.map +1 -0
- package/dist/_internal/grid-template-analysis.d.ts +2 -0
- package/dist/_internal/grid-template-analysis.d.ts.map +1 -1
- package/dist/_internal/grid-template-analysis.js +4 -0
- package/dist/_internal/grid-template-analysis.js.map +1 -1
- package/dist/_internal/rules-registry.d.ts.map +1 -1
- package/dist/_internal/rules-registry.js +16 -0
- package/dist/_internal/rules-registry.js.map +1 -1
- package/dist/plugin.cjs +893 -285
- package/dist/plugin.cjs.map +4 -4
- package/dist/rules/no-conflicting-placement.d.ts +8 -0
- package/dist/rules/no-conflicting-placement.d.ts.map +1 -0
- package/dist/rules/no-conflicting-placement.js +70 -0
- package/dist/rules/no-conflicting-placement.js.map +1 -0
- package/dist/rules/no-ineffective-container-properties.d.ts +8 -0
- package/dist/rules/no-ineffective-container-properties.d.ts.map +1 -0
- package/dist/rules/no-ineffective-container-properties.js +97 -0
- package/dist/rules/no-ineffective-container-properties.js.map +1 -0
- package/dist/rules/no-invalid-repeat-count.d.ts +8 -0
- package/dist/rules/no-invalid-repeat-count.d.ts.map +1 -0
- package/dist/rules/no-invalid-repeat-count.js +75 -0
- package/dist/rules/no-invalid-repeat-count.js.map +1 -0
- package/dist/rules/no-invalid-span.d.ts +8 -0
- package/dist/rules/no-invalid-span.d.ts.map +1 -0
- package/dist/rules/no-invalid-span.js +49 -0
- package/dist/rules/no-invalid-span.js.map +1 -0
- package/dist/rules/no-reversed-placement-lines.d.ts +8 -0
- package/dist/rules/no-reversed-placement-lines.d.ts.map +1 -0
- package/dist/rules/no-reversed-placement-lines.js +129 -0
- package/dist/rules/no-reversed-placement-lines.js.map +1 -0
- package/dist/rules/no-zero-grid-lines.d.ts +8 -0
- package/dist/rules/no-zero-grid-lines.d.ts.map +1 -0
- package/dist/rules/no-zero-grid-lines.js +48 -0
- package/dist/rules/no-zero-grid-lines.js.map +1 -0
- package/dist/rules/prefer-minmax-zero-fr.d.ts +8 -0
- package/dist/rules/prefer-minmax-zero-fr.d.ts.map +1 -0
- package/dist/rules/prefer-minmax-zero-fr.js +56 -0
- package/dist/rules/prefer-minmax-zero-fr.js.map +1 -0
- package/dist/rules/require-explicit-tracks-with-areas.d.ts +12 -0
- package/dist/rules/require-explicit-tracks-with-areas.d.ts.map +1 -0
- package/dist/rules/require-explicit-tracks-with-areas.js +65 -0
- package/dist/rules/require-explicit-tracks-with-areas.js.map +1 -0
- package/docs/rules/configs/grid-all.md +23 -15
- package/docs/rules/configs/grid-recommended.md +16 -10
- package/docs/rules/configs/index.md +23 -15
- package/docs/rules/consistent-area-naming.md +5 -5
- package/docs/rules/getting-started.md +8 -8
- package/docs/rules/no-conflicting-placement.md +59 -0
- package/docs/rules/no-dense-auto-flow.md +8 -8
- package/docs/rules/no-ineffective-container-properties.md +63 -0
- package/docs/rules/no-invalid-areas.md +11 -11
- package/docs/rules/no-invalid-auto-repeat.md +8 -8
- package/docs/rules/no-invalid-minmax.md +8 -8
- package/docs/rules/no-invalid-repeat-count.md +56 -0
- package/docs/rules/no-invalid-span.md +55 -0
- package/docs/rules/no-mismatched-template-rows.md +8 -8
- package/docs/rules/no-overlapping-areas.md +4 -4
- package/docs/rules/no-reversed-placement-lines.md +56 -0
- package/docs/rules/no-unknown-areas.md +4 -4
- package/docs/rules/no-unused-areas.md +5 -5
- package/docs/rules/no-zero-grid-lines.md +53 -0
- package/docs/rules/prefer-gap-properties.md +10 -10
- package/docs/rules/prefer-minmax-zero-fr.md +49 -0
- package/docs/rules/require-explicit-rows-with-column-flow.md +10 -10
- package/docs/rules/require-explicit-tracks-with-areas.md +80 -0
- package/docs/rules/validate-area-shapes.md +10 -10
- package/docs/rules/validate-track-counts.md +10 -10
- package/package.json +15 -7
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import stylelint, {} from "stylelint";
|
|
2
|
+
import { setHas } from "ts-extras";
|
|
3
|
+
import { createStylelintRule, } from "../_internal/create-stylelint-rule.js";
|
|
4
|
+
import { splitTopLevelWhitespace } from "../_internal/grid-template-analysis.js";
|
|
5
|
+
import { createRuleDocsUrl, createRuleName, } from "../_internal/plugin-constants.js";
|
|
6
|
+
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
|
7
|
+
const ruleName = createRuleName("prefer-minmax-zero-fr");
|
|
8
|
+
const messages = ruleMessages(ruleName, {
|
|
9
|
+
rejected: (track) => `Wrap bare flexible column track \`${track}\` in \`minmax(0, ${track})\` to avoid content-driven overflow.`,
|
|
10
|
+
});
|
|
11
|
+
const docs = {
|
|
12
|
+
description: "Prefer `minmax(0, <flex>)` for bare flexible CSS Grid column tracks.",
|
|
13
|
+
recommended: false,
|
|
14
|
+
url: createRuleDocsUrl("prefer-minmax-zero-fr"),
|
|
15
|
+
};
|
|
16
|
+
const ignoredTrackKeywords = new Set([
|
|
17
|
+
"masonry",
|
|
18
|
+
"none",
|
|
19
|
+
"subgrid",
|
|
20
|
+
]);
|
|
21
|
+
const flexTrackPattern = /^\+?(?:\d+|\d*\.\d+)fr$/v;
|
|
22
|
+
function isBareFlexibleTrack(token) {
|
|
23
|
+
const normalizedToken = token.toLowerCase();
|
|
24
|
+
return (!setHas(ignoredTrackKeywords, normalizedToken) &&
|
|
25
|
+
flexTrackPattern.test(normalizedToken));
|
|
26
|
+
}
|
|
27
|
+
const ruleFunction = (primary) => (root, result) => {
|
|
28
|
+
if (!validateOptions(result, ruleName, {
|
|
29
|
+
actual: primary,
|
|
30
|
+
possible: [true],
|
|
31
|
+
})) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
root.walkDecls("grid-template-columns", (declaration) => {
|
|
35
|
+
for (const token of splitTopLevelWhitespace(declaration.value)) {
|
|
36
|
+
if (isBareFlexibleTrack(token)) {
|
|
37
|
+
report({
|
|
38
|
+
message: messages.rejected(token),
|
|
39
|
+
node: declaration,
|
|
40
|
+
result,
|
|
41
|
+
ruleName,
|
|
42
|
+
word: token,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
/** Public Stylelint rule definition. */
|
|
49
|
+
const rule = createStylelintRule({
|
|
50
|
+
docs,
|
|
51
|
+
messages,
|
|
52
|
+
rule: ruleFunction,
|
|
53
|
+
ruleName,
|
|
54
|
+
});
|
|
55
|
+
export default rule;
|
|
56
|
+
//# sourceMappingURL=prefer-minmax-zero-fr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-minmax-zero-fr.js","sourceRoot":"","sources":["../../src/rules/prefer-minmax-zero-fr.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAiB,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,EACH,mBAAmB,GAEtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EACH,iBAAiB,EACjB,cAAc,GACjB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC;AAElE,MAAM,QAAQ,GAAG,cAAc,CAAC,uBAAuB,CAAC,CAAC;AACzD,MAAM,QAAQ,GAA4C,YAAY,CAClE,QAAQ,EACR;IACI,QAAQ,EAAE,CAAC,KAAa,EAAU,EAAE,CAChC,qCAAqC,KAAK,qBAAqB,KAAK,uCAAuC;CAClH,CACJ,CAAC;AAEF,MAAM,IAAI,GAAG;IACT,WAAW,EACP,sEAAsE;IAC1E,WAAW,EAAE,KAAK;IAClB,GAAG,EAAE,iBAAiB,CAAC,uBAAuB,CAAC;CACzC,CAAC;AAEX,MAAM,oBAAoB,GAAwB,IAAI,GAAG,CAAC;IACtD,SAAS;IACT,MAAM;IACN,SAAS;CACZ,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD,SAAS,mBAAmB,CAAC,KAAa;IACtC,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAE5C,OAAO,CACH,CAAC,MAAM,CAAC,oBAAoB,EAAE,eAAe,CAAC;QAC9C,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CACzC,CAAC;AACN,CAAC;AAED,MAAM,YAAY,GACd,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;IAC1B,IACI,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE;QAC/B,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,CAAC,IAAI,CAAC;KACnB,CAAC,EACJ,CAAC;QACC,OAAO;IACX,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,uBAAuB,EAAE,CAAC,WAAW,EAAE,EAAE;QACpD,KAAK,MAAM,KAAK,IAAI,uBAAuB,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC;oBACH,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACjC,IAAI,EAAE,WAAW;oBACjB,MAAM;oBACN,QAAQ;oBACR,IAAI,EAAE,KAAK;iBACd,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEN,wCAAwC;AACxC,MAAM,IAAI,GACN,mBAAmB,CAAsC;IACrD,IAAI;IACJ,QAAQ;IACR,IAAI,EAAE,YAAY;IAClB,QAAQ;CACX,CAAC,CAAC;AAEP,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type StylelintPluginRule } from "../_internal/create-stylelint-rule.js";
|
|
2
|
+
type SecondaryOptions = Readonly<{
|
|
3
|
+
columns?: boolean;
|
|
4
|
+
rows?: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
declare const messages: {
|
|
7
|
+
rejected: (propertyName: string) => string;
|
|
8
|
+
};
|
|
9
|
+
/** Public Stylelint rule definition. */
|
|
10
|
+
declare const rule: StylelintPluginRule<boolean, SecondaryOptions | undefined, typeof messages>;
|
|
11
|
+
export default rule;
|
|
12
|
+
//# sourceMappingURL=require-explicit-tracks-with-areas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-explicit-tracks-with-areas.d.ts","sourceRoot":"","sources":["../../src/rules/require-explicit-tracks-with-areas.ts"],"names":[],"mappings":"AAGA,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,uCAAuC,CAAC;AAc/C,KAAK,gBAAgB,GAAG,QAAQ,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH,QAAA,MAAM,QAAQ,EAAE;IAAE,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;CAM3D,CAAC;AAwEF,wCAAwC;AACxC,QAAA,MAAM,IAAI,EAAE,mBAAmB,CAC3B,OAAO,EACP,gBAAgB,GAAG,SAAS,EAC5B,OAAO,QAAQ,CAQlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import stylelint, {} from "stylelint";
|
|
2
|
+
import { isEmpty } from "ts-extras";
|
|
3
|
+
import { createStylelintRule, } from "../_internal/create-stylelint-rule.js";
|
|
4
|
+
import { collectGridTemplateAreas, findSiblingDeclaration, } from "../_internal/grid-template-analysis.js";
|
|
5
|
+
import { createRuleDocsUrl, createRuleName, } from "../_internal/plugin-constants.js";
|
|
6
|
+
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
|
7
|
+
const ruleName = createRuleName("require-explicit-tracks-with-areas");
|
|
8
|
+
const messages = ruleMessages(ruleName, {
|
|
9
|
+
rejected: (propertyName) => `Pair \`grid-template-areas\` with \`${propertyName}\` in the same block so named areas have explicit track sizing.`,
|
|
10
|
+
});
|
|
11
|
+
const docs = {
|
|
12
|
+
description: "Require explicit track sizing alongside CSS Grid named area templates.",
|
|
13
|
+
recommended: false,
|
|
14
|
+
url: createRuleDocsUrl("require-explicit-tracks-with-areas"),
|
|
15
|
+
};
|
|
16
|
+
const ruleFunction = (primary, secondary) => (root, result) => {
|
|
17
|
+
if (!validateOptions(result, ruleName, {
|
|
18
|
+
actual: primary,
|
|
19
|
+
possible: [true],
|
|
20
|
+
}, {
|
|
21
|
+
actual: secondary,
|
|
22
|
+
optional: true,
|
|
23
|
+
possible: {
|
|
24
|
+
columns: [true, false],
|
|
25
|
+
rows: [true, false],
|
|
26
|
+
},
|
|
27
|
+
})) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const requireColumns = secondary?.columns ?? true;
|
|
31
|
+
const requireRows = secondary?.rows ?? false;
|
|
32
|
+
for (const template of collectGridTemplateAreas(root)) {
|
|
33
|
+
if (isEmpty(template.diagnostics)) {
|
|
34
|
+
if (requireColumns &&
|
|
35
|
+
!findSiblingDeclaration(template.declaration, "grid-template-columns")) {
|
|
36
|
+
report({
|
|
37
|
+
message: messages.rejected("grid-template-columns"),
|
|
38
|
+
node: template.declaration,
|
|
39
|
+
result,
|
|
40
|
+
ruleName,
|
|
41
|
+
word: template.declaration.prop,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (requireRows &&
|
|
45
|
+
!findSiblingDeclaration(template.declaration, "grid-template-rows")) {
|
|
46
|
+
report({
|
|
47
|
+
message: messages.rejected("grid-template-rows"),
|
|
48
|
+
node: template.declaration,
|
|
49
|
+
result,
|
|
50
|
+
ruleName,
|
|
51
|
+
word: template.declaration.prop,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
/** Public Stylelint rule definition. */
|
|
58
|
+
const rule = createStylelintRule({
|
|
59
|
+
docs,
|
|
60
|
+
messages,
|
|
61
|
+
rule: ruleFunction,
|
|
62
|
+
ruleName,
|
|
63
|
+
});
|
|
64
|
+
export default rule;
|
|
65
|
+
//# sourceMappingURL=require-explicit-tracks-with-areas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-explicit-tracks-with-areas.js","sourceRoot":"","sources":["../../src/rules/require-explicit-tracks-with-areas.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAiB,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACH,mBAAmB,GAEtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACH,wBAAwB,EACxB,sBAAsB,GACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACH,iBAAiB,EACjB,cAAc,GACjB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC;AAElE,MAAM,QAAQ,GAAG,cAAc,CAAC,oCAAoC,CAAC,CAAC;AAOtE,MAAM,QAAQ,GAAmD,YAAY,CACzE,QAAQ,EACR;IACI,QAAQ,EAAE,CAAC,YAAoB,EAAU,EAAE,CACvC,uCAAuC,YAAY,iEAAiE;CAC3H,CACJ,CAAC;AAEF,MAAM,IAAI,GAAG;IACT,WAAW,EACP,wEAAwE;IAC5E,WAAW,EAAE,KAAK;IAClB,GAAG,EAAE,iBAAiB,CAAC,oCAAoC,CAAC;CACtD,CAAC;AAEX,MAAM,YAAY,GACd,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;IACrC,IACI,CAAC,eAAe,CACZ,MAAM,EACN,QAAQ,EACR;QACI,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,CAAC,IAAI,CAAC;KACnB,EACD;QACI,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE;YACN,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;YACtB,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;SACtB;KACJ,CACJ,EACH,CAAC;QACC,OAAO;IACX,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC;IAClD,MAAM,WAAW,GAAG,SAAS,EAAE,IAAI,IAAI,KAAK,CAAC;IAE7C,KAAK,MAAM,QAAQ,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,IACI,cAAc;gBACd,CAAC,sBAAsB,CACnB,QAAQ,CAAC,WAAW,EACpB,uBAAuB,CAC1B,EACH,CAAC;gBACC,MAAM,CAAC;oBACH,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC;oBACnD,IAAI,EAAE,QAAQ,CAAC,WAAW;oBAC1B,MAAM;oBACN,QAAQ;oBACR,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI;iBAClC,CAAC,CAAC;YACP,CAAC;YAED,IACI,WAAW;gBACX,CAAC,sBAAsB,CACnB,QAAQ,CAAC,WAAW,EACpB,oBAAoB,CACvB,EACH,CAAC;gBACC,MAAM,CAAC;oBACH,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC;oBAChD,IAAI,EAAE,QAAQ,CAAC,WAAW;oBAC1B,MAAM;oBACN,QAAQ;oBACR,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI;iBAClC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEN,wCAAwC;AACxC,MAAM,IAAI,GAIN,mBAAmB,CACnB;IACI,IAAI;IACJ,QAAQ;IACR,IAAI,EAAE,YAAY;IAClB,QAAQ;CACX,CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -25,18 +25,26 @@ split grid containers and items across files may prefer
|
|
|
25
25
|
|
|
26
26
|
**Fix legend:** 🔧 = autofixable · — = report only
|
|
27
27
|
|
|
28
|
-
| Rule
|
|
29
|
-
|
|
|
30
|
-
| [`consistent-area-naming`](../consistent-area-naming.md)
|
|
31
|
-
| [`no-
|
|
32
|
-
| [`no-
|
|
33
|
-
| [`no-
|
|
34
|
-
| [`no-invalid-
|
|
35
|
-
| [`no-
|
|
36
|
-
| [`no-
|
|
37
|
-
| [`no-
|
|
38
|
-
| [`no-
|
|
39
|
-
| [`
|
|
40
|
-
| [`
|
|
41
|
-
| [`
|
|
42
|
-
| [`
|
|
28
|
+
| Rule | Fix | Description |
|
|
29
|
+
| ---------------------------------------------------------------------------------------- | :-: | ------------------------------------------------------------------------------------------------------------------------ |
|
|
30
|
+
| [`consistent-area-naming`](../consistent-area-naming.md) | — | Require consistent naming for `grid-template-areas` and single-name `grid-area` identifiers. |
|
|
31
|
+
| [`no-conflicting-placement`](../no-conflicting-placement.md) | — | Disallow same-block CSS Grid placement declarations that write the same placement slot. |
|
|
32
|
+
| [`no-dense-auto-flow`](../no-dense-auto-flow.md) | — | Disallow `grid-auto-flow: dense` because it can reorder auto-placed grid items visually. |
|
|
33
|
+
| [`no-ineffective-container-properties`](../no-ineffective-container-properties.md) | — | Disallow CSS Grid container declarations in blocks whose final literal display value is not grid-capable. |
|
|
34
|
+
| [`no-invalid-areas`](../no-invalid-areas.md) | — | Disallow malformed `grid-template-areas` declarations. |
|
|
35
|
+
| [`no-invalid-auto-repeat`](../no-invalid-auto-repeat.md) | — | Disallow definitely invalid CSS Grid auto-repeat track sizes. |
|
|
36
|
+
| [`no-invalid-minmax`](../no-invalid-minmax.md) | — | Disallow flexible `fr` values as the minimum argument in CSS Grid `minmax()` track sizes. |
|
|
37
|
+
| [`no-invalid-repeat-count`](../no-invalid-repeat-count.md) | — | Disallow invalid fixed repeat counts in CSS Grid track templates. |
|
|
38
|
+
| [`no-invalid-span`](../no-invalid-span.md) | — | Disallow non-positive `span` counts in CSS Grid placement declarations. |
|
|
39
|
+
| [`no-mismatched-template-rows`](../no-mismatched-template-rows.md) | — | Require `grid-template-rows` track count to match `grid-template-areas` row count. |
|
|
40
|
+
| [`no-overlapping-areas`](../no-overlapping-areas.md) | — | Disallow multiple selectors assigning the same single-name `grid-area` value in one stylesheet. |
|
|
41
|
+
| [`no-reversed-placement-lines`](../no-reversed-placement-lines.md) | — | Disallow reversed or zero-width numeric CSS Grid placement line ranges. |
|
|
42
|
+
| [`no-unknown-areas`](../no-unknown-areas.md) | — | Disallow single-name `grid-area` references that do not match any named area declared in the same stylesheet. |
|
|
43
|
+
| [`no-unused-areas`](../no-unused-areas.md) | — | Disallow named template areas that are never referenced by a single-name `grid-area` declaration in the same stylesheet. |
|
|
44
|
+
| [`no-zero-grid-lines`](../no-zero-grid-lines.md) | — | Disallow line `0` in CSS Grid placement declarations. |
|
|
45
|
+
| [`prefer-gap-properties`](../prefer-gap-properties.md) | 🔧 | Prefer modern `gap`, `row-gap`, and `column-gap` properties over legacy grid gap aliases. |
|
|
46
|
+
| [`prefer-minmax-zero-fr`](../prefer-minmax-zero-fr.md) | — | Prefer `minmax(0, <flex>)` for bare flexible CSS Grid column tracks. |
|
|
47
|
+
| [`require-explicit-rows-with-column-flow`](../require-explicit-rows-with-column-flow.md) | — | Require explicit row sizing when a rule uses `grid-auto-flow: column`. |
|
|
48
|
+
| [`require-explicit-tracks-with-areas`](../require-explicit-tracks-with-areas.md) | — | Require explicit track sizing alongside CSS Grid named area templates. |
|
|
49
|
+
| [`validate-area-shapes`](../validate-area-shapes.md) | — | Require every named grid template area to form one contiguous rectangle. |
|
|
50
|
+
| [`validate-track-counts`](../validate-track-counts.md) | — | Require template row and column track counts to match `grid-template-areas` dimensions. |
|
|
@@ -25,13 +25,19 @@ after checking the same-file assumptions documented in
|
|
|
25
25
|
|
|
26
26
|
**Fix legend:** 🔧 = autofixable · — = report only
|
|
27
27
|
|
|
28
|
-
| Rule
|
|
29
|
-
|
|
|
30
|
-
| [`no-
|
|
31
|
-
| [`no-
|
|
32
|
-
| [`no-invalid-
|
|
33
|
-
| [`no-
|
|
34
|
-
| [`no-
|
|
35
|
-
| [`
|
|
36
|
-
| [`
|
|
37
|
-
| [`
|
|
28
|
+
| Rule | Fix | Description |
|
|
29
|
+
| ---------------------------------------------------------------------------------- | :-: | ------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| [`no-conflicting-placement`](../no-conflicting-placement.md) | — | Disallow same-block CSS Grid placement declarations that write the same placement slot. |
|
|
31
|
+
| [`no-ineffective-container-properties`](../no-ineffective-container-properties.md) | — | Disallow CSS Grid container declarations in blocks whose final literal display value is not grid-capable. |
|
|
32
|
+
| [`no-invalid-areas`](../no-invalid-areas.md) | — | Disallow malformed `grid-template-areas` declarations. |
|
|
33
|
+
| [`no-invalid-auto-repeat`](../no-invalid-auto-repeat.md) | — | Disallow definitely invalid CSS Grid auto-repeat track sizes. |
|
|
34
|
+
| [`no-invalid-minmax`](../no-invalid-minmax.md) | — | Disallow flexible `fr` values as the minimum argument in CSS Grid `minmax()` track sizes. |
|
|
35
|
+
| [`no-invalid-repeat-count`](../no-invalid-repeat-count.md) | — | Disallow invalid fixed repeat counts in CSS Grid track templates. |
|
|
36
|
+
| [`no-invalid-span`](../no-invalid-span.md) | — | Disallow non-positive `span` counts in CSS Grid placement declarations. |
|
|
37
|
+
| [`no-mismatched-template-rows`](../no-mismatched-template-rows.md) | — | Require `grid-template-rows` track count to match `grid-template-areas` row count. |
|
|
38
|
+
| [`no-reversed-placement-lines`](../no-reversed-placement-lines.md) | — | Disallow reversed or zero-width numeric CSS Grid placement line ranges. |
|
|
39
|
+
| [`no-unknown-areas`](../no-unknown-areas.md) | — | Disallow single-name `grid-area` references that do not match any named area declared in the same stylesheet. |
|
|
40
|
+
| [`no-zero-grid-lines`](../no-zero-grid-lines.md) | — | Disallow line `0` in CSS Grid placement declarations. |
|
|
41
|
+
| [`prefer-gap-properties`](../prefer-gap-properties.md) | 🔧 | Prefer modern `gap`, `row-gap`, and `column-gap` properties over legacy grid gap aliases. |
|
|
42
|
+
| [`validate-area-shapes`](../validate-area-shapes.md) | — | Require every named grid template area to form one contiguous rectangle. |
|
|
43
|
+
| [`validate-track-counts`](../validate-track-counts.md) | — | Require template row and column track counts to match `grid-template-areas` dimensions. |
|
|
@@ -29,18 +29,26 @@ config after confirming they match your project's file boundaries.
|
|
|
29
29
|
|
|
30
30
|
**Config legend:** ✅ = enabled · — = not enabled
|
|
31
31
|
|
|
32
|
-
| Rule
|
|
33
|
-
|
|
|
34
|
-
| [`consistent-area-naming`](../consistent-area-naming.md)
|
|
35
|
-
| [`no-
|
|
36
|
-
| [`no-
|
|
37
|
-
| [`no-
|
|
38
|
-
| [`no-invalid-
|
|
39
|
-
| [`no-
|
|
40
|
-
| [`no-
|
|
41
|
-
| [`no-
|
|
42
|
-
| [`no-
|
|
43
|
-
| [`
|
|
44
|
-
| [`
|
|
45
|
-
| [`
|
|
46
|
-
| [`
|
|
32
|
+
| Rule | Fix | [`grid-all`](./grid-all.md) | [`grid-recommended`](./grid-recommended.md) | Description |
|
|
33
|
+
| ---------------------------------------------------------------------------------------- | :-: | :-------------------------: | :-----------------------------------------: | ------------------------------------------------------------------------------------------------------------------------ |
|
|
34
|
+
| [`consistent-area-naming`](../consistent-area-naming.md) | — | ✅ | — | Require consistent naming for `grid-template-areas` and single-name `grid-area` identifiers. |
|
|
35
|
+
| [`no-conflicting-placement`](../no-conflicting-placement.md) | — | ✅ | ✅ | Disallow same-block CSS Grid placement declarations that write the same placement slot. |
|
|
36
|
+
| [`no-dense-auto-flow`](../no-dense-auto-flow.md) | — | ✅ | — | Disallow `grid-auto-flow: dense` because it can reorder auto-placed grid items visually. |
|
|
37
|
+
| [`no-ineffective-container-properties`](../no-ineffective-container-properties.md) | — | ✅ | ✅ | Disallow CSS Grid container declarations in blocks whose final literal display value is not grid-capable. |
|
|
38
|
+
| [`no-invalid-areas`](../no-invalid-areas.md) | — | ✅ | ✅ | Disallow malformed `grid-template-areas` declarations. |
|
|
39
|
+
| [`no-invalid-auto-repeat`](../no-invalid-auto-repeat.md) | — | ✅ | ✅ | Disallow definitely invalid CSS Grid auto-repeat track sizes. |
|
|
40
|
+
| [`no-invalid-minmax`](../no-invalid-minmax.md) | — | ✅ | ✅ | Disallow flexible `fr` values as the minimum argument in CSS Grid `minmax()` track sizes. |
|
|
41
|
+
| [`no-invalid-repeat-count`](../no-invalid-repeat-count.md) | — | ✅ | ✅ | Disallow invalid fixed repeat counts in CSS Grid track templates. |
|
|
42
|
+
| [`no-invalid-span`](../no-invalid-span.md) | — | ✅ | ✅ | Disallow non-positive `span` counts in CSS Grid placement declarations. |
|
|
43
|
+
| [`no-mismatched-template-rows`](../no-mismatched-template-rows.md) | — | ✅ | ✅ | Require `grid-template-rows` track count to match `grid-template-areas` row count. |
|
|
44
|
+
| [`no-overlapping-areas`](../no-overlapping-areas.md) | — | ✅ | — | Disallow multiple selectors assigning the same single-name `grid-area` value in one stylesheet. |
|
|
45
|
+
| [`no-reversed-placement-lines`](../no-reversed-placement-lines.md) | — | ✅ | ✅ | Disallow reversed or zero-width numeric CSS Grid placement line ranges. |
|
|
46
|
+
| [`no-unknown-areas`](../no-unknown-areas.md) | — | ✅ | ✅ | Disallow single-name `grid-area` references that do not match any named area declared in the same stylesheet. |
|
|
47
|
+
| [`no-unused-areas`](../no-unused-areas.md) | — | ✅ | — | Disallow named template areas that are never referenced by a single-name `grid-area` declaration in the same stylesheet. |
|
|
48
|
+
| [`no-zero-grid-lines`](../no-zero-grid-lines.md) | — | ✅ | ✅ | Disallow line `0` in CSS Grid placement declarations. |
|
|
49
|
+
| [`prefer-gap-properties`](../prefer-gap-properties.md) | 🔧 | ✅ | ✅ | Prefer modern `gap`, `row-gap`, and `column-gap` properties over legacy grid gap aliases. |
|
|
50
|
+
| [`prefer-minmax-zero-fr`](../prefer-minmax-zero-fr.md) | — | ✅ | — | Prefer `minmax(0, <flex>)` for bare flexible CSS Grid column tracks. |
|
|
51
|
+
| [`require-explicit-rows-with-column-flow`](../require-explicit-rows-with-column-flow.md) | — | ✅ | — | Require explicit row sizing when a rule uses `grid-auto-flow: column`. |
|
|
52
|
+
| [`require-explicit-tracks-with-areas`](../require-explicit-tracks-with-areas.md) | — | ✅ | — | Require explicit track sizing alongside CSS Grid named area templates. |
|
|
53
|
+
| [`validate-area-shapes`](../validate-area-shapes.md) | — | ✅ | ✅ | Require every named grid template area to form one contiguous rectangle. |
|
|
54
|
+
| [`validate-track-counts`](../validate-track-counts.md) | — | ✅ | ✅ | Require template row and column track counts to match `grid-template-areas` dimensions. |
|
|
@@ -10,7 +10,7 @@ The default style is `kebab-case`. Secondary option `style` also accepts
|
|
|
10
10
|
|
|
11
11
|
```css
|
|
12
12
|
.layout {
|
|
13
|
-
|
|
13
|
+
grid-template-areas: "mainContent";
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ The default style is `kebab-case`. Secondary option `style` also accepts
|
|
|
18
18
|
|
|
19
19
|
```css
|
|
20
20
|
.layout {
|
|
21
|
-
|
|
21
|
+
grid-template-areas: "main-content";
|
|
22
22
|
}
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -26,9 +26,9 @@ The default style is `kebab-case`. Secondary option `style` also accepts
|
|
|
26
26
|
|
|
27
27
|
```js
|
|
28
28
|
export default {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
rules: {
|
|
30
|
+
"grid/consistent-area-naming": [true, { style: "snake-case" }],
|
|
31
|
+
},
|
|
32
32
|
};
|
|
33
33
|
```
|
|
34
34
|
|
|
@@ -23,7 +23,7 @@ Or extend a subpath config from a larger Stylelint config:
|
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
25
|
export default {
|
|
26
|
-
|
|
26
|
+
extends: ["stylelint-plugin-grid/configs/grid-recommended"],
|
|
27
27
|
};
|
|
28
28
|
```
|
|
29
29
|
|
|
@@ -31,12 +31,12 @@ Enable individual rules when you need a tighter policy:
|
|
|
31
31
|
|
|
32
32
|
```js
|
|
33
33
|
export default {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
plugins: ["stylelint-plugin-grid"],
|
|
35
|
+
rules: {
|
|
36
|
+
"grid/no-invalid-areas": true,
|
|
37
|
+
"grid/validate-area-shapes": true,
|
|
38
|
+
"grid/no-unused-areas": true,
|
|
39
|
+
},
|
|
40
40
|
};
|
|
41
41
|
```
|
|
42
42
|
|
|
@@ -52,4 +52,4 @@ assumptions in `grid/no-unused-areas`, `grid/no-overlapping-areas`, and
|
|
|
52
52
|
- [Current status](./guides/current-status.md) documents what the rules skip on
|
|
53
53
|
purpose.
|
|
54
54
|
- [`grid/no-invalid-areas`](./no-invalid-areas.md) is the first rule to understand
|
|
55
|
-
because stricter template rules depend on parseable rows.
|
|
55
|
+
because stricter template rules depend on parseable rows.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# no-conflicting-placement
|
|
2
|
+
|
|
3
|
+
Disallow same-block CSS Grid placement declarations that write the same
|
|
4
|
+
placement slot.
|
|
5
|
+
|
|
6
|
+
Grid placement shorthands and longhands override shared row and column slots.
|
|
7
|
+
Keeping competing declarations in one block usually leaves stale CSS behind and
|
|
8
|
+
makes later edits risky. Use one placement strategy per block.
|
|
9
|
+
|
|
10
|
+
## Incorrect
|
|
11
|
+
|
|
12
|
+
```css
|
|
13
|
+
.item {
|
|
14
|
+
grid-area: sidebar;
|
|
15
|
+
grid-column: 2 / 4;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
.item {
|
|
21
|
+
grid-column: 1 / 3;
|
|
22
|
+
grid-column-start: 2;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Correct
|
|
27
|
+
|
|
28
|
+
```css
|
|
29
|
+
.item {
|
|
30
|
+
grid-area: sidebar;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
.item {
|
|
36
|
+
grid-row: 1 / 3;
|
|
37
|
+
grid-column: 2 / 4;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Stylelint Config
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
export default {
|
|
45
|
+
plugins: ["stylelint-plugin-grid"],
|
|
46
|
+
rules: {
|
|
47
|
+
"grid/no-conflicting-placement": true,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Related Rules
|
|
53
|
+
|
|
54
|
+
- [`no-reversed-placement-lines`](./no-reversed-placement-lines.md) checks
|
|
55
|
+
numeric placement ranges.
|
|
56
|
+
- [`no-zero-grid-lines`](./no-zero-grid-lines.md) rejects line `0` in placement
|
|
57
|
+
values.
|
|
58
|
+
- [`grid-recommended`](./configs/grid-recommended.md) enables this rule by
|
|
59
|
+
default.
|
|
@@ -15,13 +15,13 @@ implicit grid syntax make a conservative static check much noisier.
|
|
|
15
15
|
|
|
16
16
|
```css
|
|
17
17
|
.cards {
|
|
18
|
-
|
|
18
|
+
grid-auto-flow: dense;
|
|
19
19
|
}
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
```css
|
|
23
23
|
.cards {
|
|
24
|
-
|
|
24
|
+
grid-auto-flow: column dense;
|
|
25
25
|
}
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -29,13 +29,13 @@ implicit grid syntax make a conservative static check much noisier.
|
|
|
29
29
|
|
|
30
30
|
```css
|
|
31
31
|
.cards {
|
|
32
|
-
|
|
32
|
+
grid-auto-flow: row;
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
```css
|
|
37
37
|
.cards {
|
|
38
|
-
|
|
38
|
+
grid-auto-flow: column;
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
@@ -43,10 +43,10 @@ implicit grid syntax make a conservative static check much noisier.
|
|
|
43
43
|
|
|
44
44
|
```js
|
|
45
45
|
export default {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
plugins: ["stylelint-plugin-grid"],
|
|
47
|
+
rules: {
|
|
48
|
+
"grid/no-dense-auto-flow": true,
|
|
49
|
+
},
|
|
50
50
|
};
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# no-ineffective-container-properties
|
|
2
|
+
|
|
3
|
+
Disallow CSS Grid container declarations in blocks whose final literal
|
|
4
|
+
`display` value is not grid-capable.
|
|
5
|
+
|
|
6
|
+
Properties such as `grid-template-columns` and `grid-auto-flow` only define a
|
|
7
|
+
grid container when the element computes to `display: grid` or
|
|
8
|
+
`display: inline-grid`. If the same block ends with `display: contents`,
|
|
9
|
+
`display: flex`, or another known non-grid value, those declarations are
|
|
10
|
+
ineffective.
|
|
11
|
+
|
|
12
|
+
## Incorrect
|
|
13
|
+
|
|
14
|
+
```css
|
|
15
|
+
.layout {
|
|
16
|
+
display: contents;
|
|
17
|
+
grid-template-columns: 1fr 1fr;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
.layout {
|
|
23
|
+
display: grid;
|
|
24
|
+
display: flex;
|
|
25
|
+
grid-template-areas: "main side";
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Correct
|
|
30
|
+
|
|
31
|
+
```css
|
|
32
|
+
.layout {
|
|
33
|
+
display: grid;
|
|
34
|
+
grid-template-columns: minmax(0, 1fr) 16rem;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
.layout {
|
|
40
|
+
display: var(--layout-display);
|
|
41
|
+
grid-template-areas: "main";
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Stylelint Config
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
export default {
|
|
49
|
+
plugins: ["stylelint-plugin-grid"],
|
|
50
|
+
rules: {
|
|
51
|
+
"grid/no-ineffective-container-properties": true,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Related Rules
|
|
57
|
+
|
|
58
|
+
- [`validate-track-counts`](./validate-track-counts.md) compares explicit track
|
|
59
|
+
counts with named area templates.
|
|
60
|
+
- [`require-explicit-tracks-with-areas`](./require-explicit-tracks-with-areas.md)
|
|
61
|
+
requires explicit track sizing for named area templates.
|
|
62
|
+
- [`grid-recommended`](./configs/grid-recommended.md) enables this rule by
|
|
63
|
+
default.
|
|
@@ -12,15 +12,15 @@ This rule reports:
|
|
|
12
12
|
|
|
13
13
|
```css
|
|
14
14
|
.layout {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
grid-template-areas:
|
|
16
|
+
"header header"
|
|
17
|
+
"nav";
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
```css
|
|
22
22
|
.layout {
|
|
23
|
-
|
|
23
|
+
grid-template-areas: "main 1bad";
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -28,9 +28,9 @@ This rule reports:
|
|
|
28
28
|
|
|
29
29
|
```css
|
|
30
30
|
.layout {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
grid-template-areas:
|
|
32
|
+
"header header"
|
|
33
|
+
"nav main";
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -38,10 +38,10 @@ This rule reports:
|
|
|
38
38
|
|
|
39
39
|
```js
|
|
40
40
|
export default {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
plugins: ["stylelint-plugin-grid"],
|
|
42
|
+
rules: {
|
|
43
|
+
"grid/no-invalid-areas": true,
|
|
44
|
+
},
|
|
45
45
|
};
|
|
46
46
|
```
|
|
47
47
|
|
|
@@ -13,13 +13,13 @@ reporting runtime-dependent values such as `var()` and `env()`.
|
|
|
13
13
|
|
|
14
14
|
```css
|
|
15
15
|
.cards {
|
|
16
|
-
|
|
16
|
+
grid-template-columns: repeat(auto-fit, 1fr);
|
|
17
17
|
}
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
```css
|
|
21
21
|
.cards {
|
|
22
|
-
|
|
22
|
+
grid-template-columns: repeat(auto-fill, minmax(auto, 1fr));
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -27,13 +27,13 @@ reporting runtime-dependent values such as `var()` and `env()`.
|
|
|
27
27
|
|
|
28
28
|
```css
|
|
29
29
|
.cards {
|
|
30
|
-
|
|
30
|
+
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
|
31
31
|
}
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
```css
|
|
35
35
|
.cards {
|
|
36
|
-
|
|
36
|
+
grid-template-columns: repeat(auto-fill, [card] minmax(0, 1fr));
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
@@ -41,10 +41,10 @@ reporting runtime-dependent values such as `var()` and `env()`.
|
|
|
41
41
|
|
|
42
42
|
```js
|
|
43
43
|
export default {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
plugins: ["stylelint-plugin-grid"],
|
|
45
|
+
rules: {
|
|
46
|
+
"grid/no-invalid-auto-repeat": true,
|
|
47
|
+
},
|
|
48
48
|
};
|
|
49
49
|
```
|
|
50
50
|
|