stylelint-plugin-gestalt 151.2.4

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # stylelint-plugin-gestalt
2
+
3
+ THIS PACKAGE IS NOT READY FOR CONSUMTION
package/package.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "stylelint-plugin-gestalt",
3
+ "version": "151.2.4",
4
+ "license": "Apache-2.0",
5
+ "homepage": "https://gestalt.pinterest.systems/",
6
+ "description": "THIS PACKAGE IS NOT READY FOR CONSUMTION StyleLint rules for Pinterest's design language Gestalt",
7
+ "keywords": [
8
+ "stylelint",
9
+ "stylelint plugin",
10
+ "gestalt",
11
+ "pinterest"
12
+ ]
13
+ }
@@ -0,0 +1,3 @@
1
+ .button {
2
+ border-color: var(--color-gray-roboflow-420);
3
+ }
@@ -0,0 +1,5 @@
1
+ .button {
2
+ &::before {
3
+ box-shadow: 0 0 0 4px var(--color-gray-roboflow-420);
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ .button {
2
+ border-radius: var(--rounding-140);
3
+ }
@@ -0,0 +1,3 @@
1
+ .button {
2
+ border-color: var(--color-gray-roboflow-400);
3
+ }
@@ -0,0 +1,5 @@
1
+ .button {
2
+ &::before {
3
+ box-shadow: 0 0 0 4px var(--color-gray-roboflow-400);
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ .button {
2
+ border-color: var(--button-color);
3
+ }
@@ -0,0 +1,3 @@
1
+ .button {
2
+ border-radius: var(--rounding-100);
3
+ }
@@ -0,0 +1,8 @@
1
+ import path from 'path';
2
+
3
+ export const getPathFormatterByRuleName = (ruleName) => (testPath) =>
4
+ `./__fixtures__/${ruleName}/${testPath}.css`;
5
+
6
+ export function getTestByPath(codePath) {
7
+ return path.resolve(__dirname, '..', codePath);
8
+ }
package/src/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /* eslint-disable import/no-import-module-exports */
2
+ import noInvalidDesignTokens from './no-invalid-design-tokens';
3
+
4
+ module.exports = {
5
+ rules: {
6
+ 'stylelint-gestalt-plugin/no-foo': true,
7
+ },
8
+ };
9
+
10
+ module.exports = {
11
+ rules: {
12
+ 'no-invalid-design-tokens': noInvalidDesignTokens,
13
+ },
14
+ };
15
+ /* eslint-enable import/no-import-module-exports */
@@ -0,0 +1,53 @@
1
+ const tokens = require('gestalt-design-tokens/dist/js/classic/constants');
2
+ const stylelint = require('stylelint');
3
+
4
+ const {
5
+ createPlugin,
6
+ utils: { report, ruleMessages, validateOptions },
7
+ } = stylelint;
8
+
9
+ const ruleName = 'stylelint-gestalt-plugin/no-invalid-design-tokens';
10
+
11
+ const messages = ruleMessages(ruleName, {
12
+ rejected: (tokenName) => `This design token is invalid: ${tokenName}`,
13
+ });
14
+
15
+ const meta = {
16
+ url: 'https://gestalt.pinterest.systems/get_started/developers/eslint_plugin',
17
+ };
18
+
19
+ const ruleFunction = (primary) => (root, result) => {
20
+ const validOptions = validateOptions(result, ruleName, {
21
+ actual: primary,
22
+ possible: [true],
23
+ });
24
+
25
+ const tokensValues = Object.entries(tokens);
26
+
27
+ if (!validOptions) return; // If the options are invalid, don't lint
28
+
29
+ root.walkDecls((ruleNode) => {
30
+ const regex = /(var\(--(color|rounding|font|opacity|elevation|spacing)-[a-zA-Z0-9-]+?\))/;
31
+
32
+ const match = ruleNode.value.match(regex);
33
+
34
+ if (!match) return;
35
+
36
+ const isValidGestaltToken = tokensValues.some(([, value]) => match[0] === value);
37
+
38
+ if (isValidGestaltToken) return;
39
+
40
+ report({
41
+ result,
42
+ ruleName,
43
+ message: messages.rejected(match[0]),
44
+ node: ruleNode,
45
+ });
46
+ });
47
+ };
48
+
49
+ module.exports.ruleName = ruleName;
50
+ module.exports.messages = messages;
51
+ module.exports.meta = meta;
52
+
53
+ module.exports = createPlugin(ruleName, ruleFunction);
@@ -0,0 +1,157 @@
1
+ import stylelint from 'stylelint';
2
+ import { getPathFormatterByRuleName, getTestByPath } from './helpers/testHelpers';
3
+ import rule from './no-invalid-design-tokens';
4
+
5
+ const fileName = 'no-invalid-design-tokens';
6
+ const pathFormatter = getPathFormatterByRuleName(fileName);
7
+
8
+ const validNonGestalt = getTestByPath(pathFormatter('valid-non-gestalt'));
9
+ const validCodeColor = getTestByPath(pathFormatter('valid-color'));
10
+ const validCodeComposedColor = getTestByPath(pathFormatter('valid-composed-color'));
11
+ const validCodeRounding = getTestByPath(pathFormatter('valid-rounding'));
12
+ const invalidCodeColor = getTestByPath(pathFormatter('invalid-color'));
13
+ const invalidCodeComposedColor = getTestByPath(pathFormatter('invalid-composed-color'));
14
+
15
+ const invalidCodeRounding = getTestByPath(pathFormatter('invalid-rounding'));
16
+
17
+ const { lint } = stylelint;
18
+
19
+ it('valid non-Gestalt token', async () => {
20
+ const {
21
+ results: [{ warnings, parseErrors }],
22
+ } = await lint({
23
+ files: [validNonGestalt],
24
+ config: {
25
+ plugins: rule,
26
+ rules: {
27
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
28
+ },
29
+ },
30
+ });
31
+
32
+ expect(parseErrors).toHaveLength(0);
33
+ expect(warnings).toHaveLength(0);
34
+ });
35
+
36
+ it('valid color', async () => {
37
+ const {
38
+ results: [{ warnings, parseErrors }],
39
+ } = await lint({
40
+ files: [validCodeColor],
41
+ config: {
42
+ plugins: rule,
43
+ rules: {
44
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
45
+ },
46
+ },
47
+ });
48
+
49
+ expect(parseErrors).toHaveLength(0);
50
+ expect(warnings).toHaveLength(0);
51
+ });
52
+
53
+ it('valid composed color', async () => {
54
+ const {
55
+ results: [{ warnings, parseErrors }],
56
+ } = await lint({
57
+ files: [validCodeComposedColor],
58
+ config: {
59
+ plugins: rule,
60
+ rules: {
61
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
62
+ },
63
+ },
64
+ });
65
+
66
+ expect(parseErrors).toHaveLength(0);
67
+ expect(warnings).toHaveLength(0);
68
+ });
69
+
70
+ it('valid rounding', async () => {
71
+ const {
72
+ results: [{ warnings, parseErrors }],
73
+ } = await lint({
74
+ files: [validCodeRounding],
75
+ config: {
76
+ plugins: rule,
77
+ rules: {
78
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
79
+ },
80
+ },
81
+ });
82
+
83
+ expect(parseErrors).toHaveLength(0);
84
+ expect(warnings).toHaveLength(0);
85
+ });
86
+
87
+ it('invalid color', async () => {
88
+ const {
89
+ results: [{ warnings, parseErrors }],
90
+ } = await lint({
91
+ files: [invalidCodeColor],
92
+ config: {
93
+ plugins: rule,
94
+ rules: {
95
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
96
+ },
97
+ },
98
+ });
99
+
100
+ const [{ text, line }] = warnings;
101
+
102
+ expect(parseErrors).toHaveLength(0);
103
+ expect(warnings).toHaveLength(1);
104
+
105
+ expect(text).toBe(
106
+ 'This design token is invalid: var(--color-gray-roboflow-420) (stylelint-gestalt-plugin/no-invalid-design-tokens)',
107
+ );
108
+ expect(line).toBe(2);
109
+ });
110
+
111
+ it('invalid composed color', async () => {
112
+ const {
113
+ results: [{ warnings, parseErrors }],
114
+ } = await lint({
115
+ files: [invalidCodeComposedColor],
116
+ config: {
117
+ plugins: rule,
118
+ rules: {
119
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
120
+ },
121
+ },
122
+ });
123
+
124
+ const [{ text, line }] = warnings;
125
+
126
+ expect(parseErrors).toHaveLength(0);
127
+ expect(warnings).toHaveLength(1);
128
+
129
+ expect(text).toBe(
130
+ 'This design token is invalid: var(--color-gray-roboflow-420) (stylelint-gestalt-plugin/no-invalid-design-tokens)',
131
+ );
132
+ expect(line).toBe(3);
133
+ });
134
+
135
+ it('invalid rounding', async () => {
136
+ const {
137
+ results: [{ warnings, parseErrors }],
138
+ } = await lint({
139
+ files: [invalidCodeRounding],
140
+ config: {
141
+ plugins: rule,
142
+ rules: {
143
+ 'stylelint-gestalt-plugin/no-invalid-design-tokens': true,
144
+ },
145
+ },
146
+ });
147
+
148
+ const [{ text, line }] = warnings;
149
+
150
+ expect(parseErrors).toHaveLength(0);
151
+ expect(warnings).toHaveLength(1);
152
+
153
+ expect(text).toBe(
154
+ 'This design token is invalid: var(--rounding-140) (stylelint-gestalt-plugin/no-invalid-design-tokens)',
155
+ );
156
+ expect(line).toBe(2);
157
+ });