@gallop.software/canon 2.4.0 → 2.6.0
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/eslint/configs/recommended.d.ts +2 -0
- package/dist/eslint/configs/recommended.js +5 -1
- package/dist/eslint/index.d.ts +8 -0
- package/dist/eslint/index.js +8 -2
- package/dist/eslint/rules/no-arbitrary-colors.d.ts +5 -0
- package/dist/eslint/rules/no-arbitrary-colors.js +80 -0
- package/dist/eslint/rules/no-inline-styles.d.ts +5 -0
- package/dist/eslint/rules/no-inline-styles.js +34 -0
- package/package.json +1 -1
- package/schema.json +12 -2
|
@@ -9,5 +9,7 @@ declare const recommendedRules: {
|
|
|
9
9
|
readonly 'gallop/prefer-typography-components': "warn";
|
|
10
10
|
readonly 'gallop/prefer-layout-components': "warn";
|
|
11
11
|
readonly 'gallop/background-image-rounded': "warn";
|
|
12
|
+
readonly 'gallop/no-inline-styles': "warn";
|
|
13
|
+
readonly 'gallop/no-arbitrary-colors': "warn";
|
|
12
14
|
};
|
|
13
15
|
export default recommendedRules;
|
|
@@ -15,6 +15,10 @@ const recommendedRules = {
|
|
|
15
15
|
'gallop/prefer-layout-components': 'warn',
|
|
16
16
|
// Background images must have rounded="rounded-none"
|
|
17
17
|
'gallop/background-image-rounded': 'warn',
|
|
18
|
+
// No inline styles, use Tailwind exclusively
|
|
19
|
+
'gallop/no-inline-styles': 'warn',
|
|
20
|
+
// Use defined color tokens, not arbitrary colors
|
|
21
|
+
'gallop/no-arbitrary-colors': 'warn',
|
|
18
22
|
};
|
|
19
23
|
export default recommendedRules;
|
|
20
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb21tZW5kZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZXNsaW50L2NvbmZpZ3MvcmVjb21tZW5kZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRztJQUN2QixxQ0FBcUM7SUFDckMseUJBQXlCLEVBQUUsTUFBTTtJQUVqQyx1Q0FBdUM7SUFDdkMsZ0NBQWdDLEVBQUUsTUFBTTtJQUV4Qyw0REFBNEQ7SUFDNUQsK0JBQStCLEVBQUUsTUFBTTtJQUV2Qyx1REFBdUQ7SUFDdkQscUNBQXFDLEVBQUUsTUFBTTtJQUU3Qyx3REFBd0Q7SUFDeEQsaUNBQWlDLEVBQUUsTUFBTTtJQUV6QyxxREFBcUQ7SUFDckQsaUNBQWlDLEVBQUUsTUFBTTtJQUV6Qyw2Q0FBNkM7SUFDN0MseUJBQXlCLEVBQUUsTUFBTTtJQUVqQyxpREFBaUQ7SUFDakQsNEJBQTRCLEVBQUUsTUFBTTtDQUM1QixDQUFBO0FBRVYsZUFBZSxnQkFBZ0IsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUmVjb21tZW5kZWQgY29uZmlndXJhdGlvbiBmb3IgRVNMaW50IGZsYXQgY29uZmlnXG4gKiBBIHNlbnNpYmxlIGRlZmF1bHQgZm9yIGFueSBHYWxsb3AtYmFzZWQgdGVtcGxhdGVcbiAqL1xuY29uc3QgcmVjb21tZW5kZWRSdWxlcyA9IHtcbiAgLy8gQmxvY2tzIHNob3VsZCBiZSBzZXJ2ZXIgY29tcG9uZW50c1xuICAnZ2FsbG9wL25vLWNsaWVudC1ibG9ja3MnOiAnd2FybicsXG5cbiAgLy8gU2VjdGlvbiBhbHJlYWR5IHByb3ZpZGVzIGNvbnRhaW5tZW50XG4gICdnYWxsb3Avbm8tY29udGFpbmVyLWluLXNlY3Rpb24nOiAnd2FybicsXG5cbiAgLy8gVXNlIGNvbXBvbmVudCBwcm9wcyBpbnN0ZWFkIG9mIGNsYXNzTmFtZSBmb3Igc3R5bGUgdmFsdWVzXG4gICdnYWxsb3AvcHJlZmVyLWNvbXBvbmVudC1wcm9wcyc6ICd3YXJuJyxcblxuICAvLyBVc2UgVHlwb2dyYXBoeSBjb21wb25lbnRzIGluc3RlYWQgb2YgcmF3IHAvc3BhbiB0YWdzXG4gICdnYWxsb3AvcHJlZmVyLXR5cG9ncmFwaHktY29tcG9uZW50cyc6ICd3YXJuJyxcblxuICAvLyBVc2UgR3JpZC9Db2x1bW5zIGluc3RlYWQgb2YgcmF3IGRpdiB3aXRoIGdyaWQgY2xhc3Nlc1xuICAnZ2FsbG9wL3ByZWZlci1sYXlvdXQtY29tcG9uZW50cyc6ICd3YXJuJyxcblxuICAvLyBCYWNrZ3JvdW5kIGltYWdlcyBtdXN0IGhhdmUgcm91bmRlZD1cInJvdW5kZWQtbm9uZVwiXG4gICdnYWxsb3AvYmFja2dyb3VuZC1pbWFnZS1yb3VuZGVkJzogJ3dhcm4nLFxuXG4gIC8vIE5vIGlubGluZSBzdHlsZXMsIHVzZSBUYWlsd2luZCBleGNsdXNpdmVseVxuICAnZ2FsbG9wL25vLWlubGluZS1zdHlsZXMnOiAnd2FybicsXG5cbiAgLy8gVXNlIGRlZmluZWQgY29sb3IgdG9rZW5zLCBub3QgYXJiaXRyYXJ5IGNvbG9yc1xuICAnZ2FsbG9wL25vLWFyYml0cmFyeS1jb2xvcnMnOiAnd2FybicsXG59IGFzIGNvbnN0XG5cbmV4cG9ydCBkZWZhdWx0IHJlY29tbWVuZGVkUnVsZXNcbiJdfQ==
|
package/dist/eslint/index.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ declare const plugin: {
|
|
|
16
16
|
'prefer-typography-components': import("eslint").Rule.RuleModule;
|
|
17
17
|
'prefer-layout-components': import("eslint").Rule.RuleModule;
|
|
18
18
|
'background-image-rounded': import("eslint").Rule.RuleModule;
|
|
19
|
+
'no-inline-styles': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noInlineStyles", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
20
|
+
name: string;
|
|
21
|
+
};
|
|
22
|
+
'no-arbitrary-colors': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noArbitraryColors", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
23
|
+
name: string;
|
|
24
|
+
};
|
|
19
25
|
};
|
|
20
26
|
/**
|
|
21
27
|
* Recommended rule configurations - spread into your ESLint config
|
|
@@ -28,6 +34,8 @@ declare const plugin: {
|
|
|
28
34
|
readonly 'gallop/prefer-typography-components': "warn";
|
|
29
35
|
readonly 'gallop/prefer-layout-components': "warn";
|
|
30
36
|
readonly 'gallop/background-image-rounded': "warn";
|
|
37
|
+
readonly 'gallop/no-inline-styles': "warn";
|
|
38
|
+
readonly 'gallop/no-arbitrary-colors': "warn";
|
|
31
39
|
};
|
|
32
40
|
};
|
|
33
41
|
export default plugin;
|
package/dist/eslint/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import preferComponentProps from './rules/prefer-component-props.js';
|
|
|
4
4
|
import preferTypographyComponents from './rules/prefer-typography-components.js';
|
|
5
5
|
import preferLayoutComponents from './rules/prefer-layout-components.js';
|
|
6
6
|
import backgroundImageRounded from './rules/background-image-rounded.js';
|
|
7
|
+
import noInlineStyles from './rules/no-inline-styles.js';
|
|
8
|
+
import noArbitraryColors from './rules/no-arbitrary-colors.js';
|
|
7
9
|
/**
|
|
8
10
|
* All Canon ESLint rules with recommended severity levels
|
|
9
11
|
*/
|
|
@@ -14,11 +16,13 @@ const recommended = {
|
|
|
14
16
|
'gallop/prefer-typography-components': 'warn',
|
|
15
17
|
'gallop/prefer-layout-components': 'warn',
|
|
16
18
|
'gallop/background-image-rounded': 'warn',
|
|
19
|
+
'gallop/no-inline-styles': 'warn',
|
|
20
|
+
'gallop/no-arbitrary-colors': 'warn',
|
|
17
21
|
};
|
|
18
22
|
const plugin = {
|
|
19
23
|
meta: {
|
|
20
24
|
name: 'eslint-plugin-gallop',
|
|
21
|
-
version: '2.
|
|
25
|
+
version: '2.6.0',
|
|
22
26
|
},
|
|
23
27
|
rules: {
|
|
24
28
|
'no-client-blocks': noClientBlocks,
|
|
@@ -27,6 +31,8 @@ const plugin = {
|
|
|
27
31
|
'prefer-typography-components': preferTypographyComponents,
|
|
28
32
|
'prefer-layout-components': preferLayoutComponents,
|
|
29
33
|
'background-image-rounded': backgroundImageRounded,
|
|
34
|
+
'no-inline-styles': noInlineStyles,
|
|
35
|
+
'no-arbitrary-colors': noArbitraryColors,
|
|
30
36
|
},
|
|
31
37
|
/**
|
|
32
38
|
* Recommended rule configurations - spread into your ESLint config
|
|
@@ -35,4 +41,4 @@ const plugin = {
|
|
|
35
41
|
recommended,
|
|
36
42
|
};
|
|
37
43
|
export default plugin;
|
|
38
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXNsaW50L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sY0FBYyxNQUFNLDZCQUE2QixDQUFBO0FBQ3hELE9BQU8sb0JBQW9CLE1BQU0sb0NBQW9DLENBQUE7QUFDckUsT0FBTyxvQkFBb0IsTUFBTSxtQ0FBbUMsQ0FBQTtBQUNwRSxPQUFPLDBCQUEwQixNQUFNLHlDQUF5QyxDQUFBO0FBQ2hGLE9BQU8sc0JBQXNCLE1BQU0scUNBQXFDLENBQUE7QUFDeEUsT0FBTyxzQkFBc0IsTUFBTSxxQ0FBcUMsQ0FBQTtBQUN4RSxPQUFPLGNBQWMsTUFBTSw2QkFBNkIsQ0FBQTtBQUN4RCxPQUFPLGlCQUFpQixNQUFNLGdDQUFnQyxDQUFBO0FBRTlEOztHQUVHO0FBQ0gsTUFBTSxXQUFXLEdBQUc7SUFDbEIseUJBQXlCLEVBQUUsTUFBTTtJQUNqQyxnQ0FBZ0MsRUFBRSxNQUFNO0lBQ3hDLCtCQUErQixFQUFFLE1BQU07SUFDdkMscUNBQXFDLEVBQUUsTUFBTTtJQUM3QyxpQ0FBaUMsRUFBRSxNQUFNO0lBQ3pDLGlDQUFpQyxFQUFFLE1BQU07SUFDekMseUJBQXlCLEVBQUUsTUFBTTtJQUNqQyw0QkFBNEIsRUFBRSxNQUFNO0NBQzVCLENBQUE7QUFFVixNQUFNLE1BQU0sR0FBRztJQUNiLElBQUksRUFBRTtRQUNKLElBQUksRUFBRSxzQkFBc0I7UUFDNUIsT0FBTyxFQUFFLE9BQU87S0FDakI7SUFDRCxLQUFLLEVBQUU7UUFDTCxrQkFBa0IsRUFBRSxjQUFjO1FBQ2xDLHlCQUF5QixFQUFFLG9CQUFvQjtRQUMvQyx3QkFBd0IsRUFBRSxvQkFBb0I7UUFDOUMsOEJBQThCLEVBQUUsMEJBQTBCO1FBQzFELDBCQUEwQixFQUFFLHNCQUFzQjtRQUNsRCwwQkFBMEIsRUFBRSxzQkFBc0I7UUFDbEQsa0JBQWtCLEVBQUUsY0FBYztRQUNsQyxxQkFBcUIsRUFBRSxpQkFBaUI7S0FDekM7SUFDRDs7O09BR0c7SUFDSCxXQUFXO0NBQ1osQ0FBQTtBQUVELGVBQWUsTUFBTSxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5vQ2xpZW50QmxvY2tzIGZyb20gJy4vcnVsZXMvbm8tY2xpZW50LWJsb2Nrcy5qcydcbmltcG9ydCBub0NvbnRhaW5lckluU2VjdGlvbiBmcm9tICcuL3J1bGVzL25vLWNvbnRhaW5lci1pbi1zZWN0aW9uLmpzJ1xuaW1wb3J0IHByZWZlckNvbXBvbmVudFByb3BzIGZyb20gJy4vcnVsZXMvcHJlZmVyLWNvbXBvbmVudC1wcm9wcy5qcydcbmltcG9ydCBwcmVmZXJUeXBvZ3JhcGh5Q29tcG9uZW50cyBmcm9tICcuL3J1bGVzL3ByZWZlci10eXBvZ3JhcGh5LWNvbXBvbmVudHMuanMnXG5pbXBvcnQgcHJlZmVyTGF5b3V0Q29tcG9uZW50cyBmcm9tICcuL3J1bGVzL3ByZWZlci1sYXlvdXQtY29tcG9uZW50cy5qcydcbmltcG9ydCBiYWNrZ3JvdW5kSW1hZ2VSb3VuZGVkIGZyb20gJy4vcnVsZXMvYmFja2dyb3VuZC1pbWFnZS1yb3VuZGVkLmpzJ1xuaW1wb3J0IG5vSW5saW5lU3R5bGVzIGZyb20gJy4vcnVsZXMvbm8taW5saW5lLXN0eWxlcy5qcydcbmltcG9ydCBub0FyYml0cmFyeUNvbG9ycyBmcm9tICcuL3J1bGVzL25vLWFyYml0cmFyeS1jb2xvcnMuanMnXG5cbi8qKlxuICogQWxsIENhbm9uIEVTTGludCBydWxlcyB3aXRoIHJlY29tbWVuZGVkIHNldmVyaXR5IGxldmVsc1xuICovXG5jb25zdCByZWNvbW1lbmRlZCA9IHtcbiAgJ2dhbGxvcC9uby1jbGllbnQtYmxvY2tzJzogJ3dhcm4nLFxuICAnZ2FsbG9wL25vLWNvbnRhaW5lci1pbi1zZWN0aW9uJzogJ3dhcm4nLFxuICAnZ2FsbG9wL3ByZWZlci1jb21wb25lbnQtcHJvcHMnOiAnd2FybicsXG4gICdnYWxsb3AvcHJlZmVyLXR5cG9ncmFwaHktY29tcG9uZW50cyc6ICd3YXJuJyxcbiAgJ2dhbGxvcC9wcmVmZXItbGF5b3V0LWNvbXBvbmVudHMnOiAnd2FybicsXG4gICdnYWxsb3AvYmFja2dyb3VuZC1pbWFnZS1yb3VuZGVkJzogJ3dhcm4nLFxuICAnZ2FsbG9wL25vLWlubGluZS1zdHlsZXMnOiAnd2FybicsXG4gICdnYWxsb3Avbm8tYXJiaXRyYXJ5LWNvbG9ycyc6ICd3YXJuJyxcbn0gYXMgY29uc3RcblxuY29uc3QgcGx1Z2luID0ge1xuICBtZXRhOiB7XG4gICAgbmFtZTogJ2VzbGludC1wbHVnaW4tZ2FsbG9wJyxcbiAgICB2ZXJzaW9uOiAnMi42LjAnLFxuICB9LFxuICBydWxlczoge1xuICAgICduby1jbGllbnQtYmxvY2tzJzogbm9DbGllbnRCbG9ja3MsXG4gICAgJ25vLWNvbnRhaW5lci1pbi1zZWN0aW9uJzogbm9Db250YWluZXJJblNlY3Rpb24sXG4gICAgJ3ByZWZlci1jb21wb25lbnQtcHJvcHMnOiBwcmVmZXJDb21wb25lbnRQcm9wcyxcbiAgICAncHJlZmVyLXR5cG9ncmFwaHktY29tcG9uZW50cyc6IHByZWZlclR5cG9ncmFwaHlDb21wb25lbnRzLFxuICAgICdwcmVmZXItbGF5b3V0LWNvbXBvbmVudHMnOiBwcmVmZXJMYXlvdXRDb21wb25lbnRzLFxuICAgICdiYWNrZ3JvdW5kLWltYWdlLXJvdW5kZWQnOiBiYWNrZ3JvdW5kSW1hZ2VSb3VuZGVkLFxuICAgICduby1pbmxpbmUtc3R5bGVzJzogbm9JbmxpbmVTdHlsZXMsXG4gICAgJ25vLWFyYml0cmFyeS1jb2xvcnMnOiBub0FyYml0cmFyeUNvbG9ycyxcbiAgfSxcbiAgLyoqXG4gICAqIFJlY29tbWVuZGVkIHJ1bGUgY29uZmlndXJhdGlvbnMgLSBzcHJlYWQgaW50byB5b3VyIEVTTGludCBjb25maWdcbiAgICogQGV4YW1wbGUgcnVsZXM6IHsgLi4uZ2FsbG9wLnJlY29tbWVuZGVkIH1cbiAgICovXG4gIHJlY29tbWVuZGVkLFxufVxuXG5leHBvcnQgZGVmYXVsdCBwbHVnaW5cbiJdfQ==
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getCanonUrl, getCanonPattern } from '../utils/canon.js';
|
|
3
|
+
const RULE_NAME = 'no-arbitrary-colors';
|
|
4
|
+
const pattern = getCanonPattern(RULE_NAME);
|
|
5
|
+
const createRule = ESLintUtils.RuleCreator(() => getCanonUrl(RULE_NAME));
|
|
6
|
+
// Patterns that indicate arbitrary color values in Tailwind classes
|
|
7
|
+
const COLOR_PREFIXES = [
|
|
8
|
+
'bg',
|
|
9
|
+
'text',
|
|
10
|
+
'border',
|
|
11
|
+
'ring',
|
|
12
|
+
'outline',
|
|
13
|
+
'shadow',
|
|
14
|
+
'accent',
|
|
15
|
+
'caret',
|
|
16
|
+
'fill',
|
|
17
|
+
'stroke',
|
|
18
|
+
'decoration',
|
|
19
|
+
'divide',
|
|
20
|
+
'from',
|
|
21
|
+
'via',
|
|
22
|
+
'to',
|
|
23
|
+
];
|
|
24
|
+
// Regex to match arbitrary color values like bg-[#fff], text-[rgb(...)], border-[hsl(...)]
|
|
25
|
+
const ARBITRARY_COLOR_REGEX = new RegExp(`\\b(${COLOR_PREFIXES.join('|')})-\\[(?:#[0-9a-fA-F]{3,8}|rgb[a]?\\(|hsl[a]?\\(|color\\(|oklch\\(|oklab\\()`, 'i');
|
|
26
|
+
// Also match var() references to non-color custom properties in color contexts
|
|
27
|
+
const ARBITRARY_VAR_COLOR_REGEX = new RegExp(`\\b(${COLOR_PREFIXES.join('|')})-\\[var\\(--(?!color-)`, 'i');
|
|
28
|
+
export default createRule({
|
|
29
|
+
name: RULE_NAME,
|
|
30
|
+
meta: {
|
|
31
|
+
type: 'suggestion',
|
|
32
|
+
docs: {
|
|
33
|
+
description: pattern?.summary || 'Use defined color tokens, not arbitrary color values',
|
|
34
|
+
},
|
|
35
|
+
messages: {
|
|
36
|
+
noArbitraryColors: `[Canon ${pattern?.id || '020'}] Avoid arbitrary color values. Use defined Tailwind color tokens (e.g., bg-accent, text-contrast) instead of hardcoded colors. See: ${pattern?.title || 'No Arbitrary Colors'} pattern.`,
|
|
37
|
+
},
|
|
38
|
+
schema: [],
|
|
39
|
+
},
|
|
40
|
+
defaultOptions: [],
|
|
41
|
+
create(context) {
|
|
42
|
+
return {
|
|
43
|
+
JSXAttribute(node) {
|
|
44
|
+
// Only check className attributes
|
|
45
|
+
if (node.name.type !== 'JSXIdentifier' ||
|
|
46
|
+
node.name.name !== 'className') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Get the className value
|
|
50
|
+
let classValue = '';
|
|
51
|
+
if (node.value?.type === 'Literal' && typeof node.value.value === 'string') {
|
|
52
|
+
classValue = node.value.value;
|
|
53
|
+
}
|
|
54
|
+
else if (node.value?.type === 'JSXExpressionContainer' &&
|
|
55
|
+
node.value.expression.type === 'Literal' &&
|
|
56
|
+
typeof node.value.expression.value === 'string') {
|
|
57
|
+
classValue = node.value.expression.value;
|
|
58
|
+
}
|
|
59
|
+
else if (node.value?.type === 'JSXExpressionContainer' &&
|
|
60
|
+
node.value.expression.type === 'TemplateLiteral') {
|
|
61
|
+
// Extract string parts from template literal
|
|
62
|
+
classValue = node.value.expression.quasis
|
|
63
|
+
.map((quasi) => quasi.value.raw)
|
|
64
|
+
.join(' ');
|
|
65
|
+
}
|
|
66
|
+
if (!classValue)
|
|
67
|
+
return;
|
|
68
|
+
// Check for arbitrary color values
|
|
69
|
+
if (ARBITRARY_COLOR_REGEX.test(classValue) ||
|
|
70
|
+
ARBITRARY_VAR_COLOR_REGEX.test(classValue)) {
|
|
71
|
+
context.report({
|
|
72
|
+
node,
|
|
73
|
+
messageId: 'noArbitraryColors',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tYXJiaXRyYXJ5LWNvbG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lc2xpbnQvcnVsZXMvbm8tYXJiaXRyYXJ5LWNvbG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDdEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUVoRSxNQUFNLFNBQVMsR0FBRyxxQkFBcUIsQ0FBQTtBQUN2QyxNQUFNLE9BQU8sR0FBRyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUE7QUFFMUMsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQTtBQUl4RSxvRUFBb0U7QUFDcEUsTUFBTSxjQUFjLEdBQUc7SUFDckIsSUFBSTtJQUNKLE1BQU07SUFDTixRQUFRO0lBQ1IsTUFBTTtJQUNOLFNBQVM7SUFDVCxRQUFRO0lBQ1IsUUFBUTtJQUNSLE9BQU87SUFDUCxNQUFNO0lBQ04sUUFBUTtJQUNSLFlBQVk7SUFDWixRQUFRO0lBQ1IsTUFBTTtJQUNOLEtBQUs7SUFDTCxJQUFJO0NBQ0wsQ0FBQTtBQUVELDJGQUEyRjtBQUMzRixNQUFNLHFCQUFxQixHQUFHLElBQUksTUFBTSxDQUN0QyxPQUFPLGNBQWMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLDZFQUE2RSxFQUM1RyxHQUFHLENBQ0osQ0FBQTtBQUVELCtFQUErRTtBQUMvRSxNQUFNLHlCQUF5QixHQUFHLElBQUksTUFBTSxDQUMxQyxPQUFPLGNBQWMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLHlCQUF5QixFQUN4RCxHQUFHLENBQ0osQ0FBQTtBQUVELGVBQWUsVUFBVSxDQUFpQjtJQUN4QyxJQUFJLEVBQUUsU0FBUztJQUNmLElBQUksRUFBRTtRQUNKLElBQUksRUFBRSxZQUFZO1FBQ2xCLElBQUksRUFBRTtZQUNKLFdBQVcsRUFDVCxPQUFPLEVBQUUsT0FBTyxJQUFJLHNEQUFzRDtTQUM3RTtRQUNELFFBQVEsRUFBRTtZQUNSLGlCQUFpQixFQUFFLFVBQVUsT0FBTyxFQUFFLEVBQUUsSUFBSSxLQUFLLHdJQUF3SSxPQUFPLEVBQUUsS0FBSyxJQUFJLHFCQUFxQixXQUFXO1NBQzVPO1FBQ0QsTUFBTSxFQUFFLEVBQUU7S0FDWDtJQUNELGNBQWMsRUFBRSxFQUFFO0lBQ2xCLE1BQU0sQ0FBQyxPQUFPO1FBQ1osT0FBTztZQUNMLFlBQVksQ0FBQyxJQUFJO2dCQUNmLGtDQUFrQztnQkFDbEMsSUFDRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxlQUFlO29CQUNsQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxXQUFXLEVBQzlCLENBQUM7b0JBQ0QsT0FBTTtnQkFDUixDQUFDO2dCQUVELDBCQUEwQjtnQkFDMUIsSUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFBO2dCQUVuQixJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxLQUFLLFNBQVMsSUFBSSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUMzRSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUE7Z0JBQy9CLENBQUM7cUJBQU0sSUFDTCxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksS0FBSyx3QkFBd0I7b0JBQzdDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxTQUFTO29CQUN4QyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssS0FBSyxRQUFRLEVBQy9DLENBQUM7b0JBQ0QsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQTtnQkFDMUMsQ0FBQztxQkFBTSxJQUNMLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxLQUFLLHdCQUF3QjtvQkFDN0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxLQUFLLGlCQUFpQixFQUNoRCxDQUFDO29CQUNELDZDQUE2QztvQkFDN0MsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU07eUJBQ3RDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUM7eUJBQy9CLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtnQkFDZCxDQUFDO2dCQUVELElBQUksQ0FBQyxVQUFVO29CQUFFLE9BQU07Z0JBRXZCLG1DQUFtQztnQkFDbkMsSUFDRSxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO29CQUN0Qyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQzFDLENBQUM7b0JBQ0QsT0FBTyxDQUFDLE1BQU0sQ0FBQzt3QkFDYixJQUFJO3dCQUNKLFNBQVMsRUFBRSxtQkFBbUI7cUJBQy9CLENBQUMsQ0FBQTtnQkFDSixDQUFDO1lBQ0gsQ0FBQztTQUNGLENBQUE7SUFDSCxDQUFDO0NBQ0YsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRVNMaW50VXRpbHMgfSBmcm9tICdAdHlwZXNjcmlwdC1lc2xpbnQvdXRpbHMnXG5pbXBvcnQgeyBnZXRDYW5vblVybCwgZ2V0Q2Fub25QYXR0ZXJuIH0gZnJvbSAnLi4vdXRpbHMvY2Fub24uanMnXG5cbmNvbnN0IFJVTEVfTkFNRSA9ICduby1hcmJpdHJhcnktY29sb3JzJ1xuY29uc3QgcGF0dGVybiA9IGdldENhbm9uUGF0dGVybihSVUxFX05BTUUpXG5cbmNvbnN0IGNyZWF0ZVJ1bGUgPSBFU0xpbnRVdGlscy5SdWxlQ3JlYXRvcigoKSA9PiBnZXRDYW5vblVybChSVUxFX05BTUUpKVxuXG50eXBlIE1lc3NhZ2VJZHMgPSAnbm9BcmJpdHJhcnlDb2xvcnMnXG5cbi8vIFBhdHRlcm5zIHRoYXQgaW5kaWNhdGUgYXJiaXRyYXJ5IGNvbG9yIHZhbHVlcyBpbiBUYWlsd2luZCBjbGFzc2VzXG5jb25zdCBDT0xPUl9QUkVGSVhFUyA9IFtcbiAgJ2JnJyxcbiAgJ3RleHQnLFxuICAnYm9yZGVyJyxcbiAgJ3JpbmcnLFxuICAnb3V0bGluZScsXG4gICdzaGFkb3cnLFxuICAnYWNjZW50JyxcbiAgJ2NhcmV0JyxcbiAgJ2ZpbGwnLFxuICAnc3Ryb2tlJyxcbiAgJ2RlY29yYXRpb24nLFxuICAnZGl2aWRlJyxcbiAgJ2Zyb20nLFxuICAndmlhJyxcbiAgJ3RvJyxcbl1cblxuLy8gUmVnZXggdG8gbWF0Y2ggYXJiaXRyYXJ5IGNvbG9yIHZhbHVlcyBsaWtlIGJnLVsjZmZmXSwgdGV4dC1bcmdiKC4uLildLCBib3JkZXItW2hzbCguLi4pXVxuY29uc3QgQVJCSVRSQVJZX0NPTE9SX1JFR0VYID0gbmV3IFJlZ0V4cChcbiAgYFxcXFxiKCR7Q09MT1JfUFJFRklYRVMuam9pbignfCcpfSktXFxcXFsoPzojWzAtOWEtZkEtRl17Myw4fXxyZ2JbYV0/XFxcXCh8aHNsW2FdP1xcXFwofGNvbG9yXFxcXCh8b2tsY2hcXFxcKHxva2xhYlxcXFwoKWAsXG4gICdpJ1xuKVxuXG4vLyBBbHNvIG1hdGNoIHZhcigpIHJlZmVyZW5jZXMgdG8gbm9uLWNvbG9yIGN1c3RvbSBwcm9wZXJ0aWVzIGluIGNvbG9yIGNvbnRleHRzXG5jb25zdCBBUkJJVFJBUllfVkFSX0NPTE9SX1JFR0VYID0gbmV3IFJlZ0V4cChcbiAgYFxcXFxiKCR7Q09MT1JfUFJFRklYRVMuam9pbignfCcpfSktXFxcXFt2YXJcXFxcKC0tKD8hY29sb3ItKWAsXG4gICdpJ1xuKVxuXG5leHBvcnQgZGVmYXVsdCBjcmVhdGVSdWxlPFtdLCBNZXNzYWdlSWRzPih7XG4gIG5hbWU6IFJVTEVfTkFNRSxcbiAgbWV0YToge1xuICAgIHR5cGU6ICdzdWdnZXN0aW9uJyxcbiAgICBkb2NzOiB7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgcGF0dGVybj8uc3VtbWFyeSB8fCAnVXNlIGRlZmluZWQgY29sb3IgdG9rZW5zLCBub3QgYXJiaXRyYXJ5IGNvbG9yIHZhbHVlcycsXG4gICAgfSxcbiAgICBtZXNzYWdlczoge1xuICAgICAgbm9BcmJpdHJhcnlDb2xvcnM6IGBbQ2Fub24gJHtwYXR0ZXJuPy5pZCB8fCAnMDIwJ31dIEF2b2lkIGFyYml0cmFyeSBjb2xvciB2YWx1ZXMuIFVzZSBkZWZpbmVkIFRhaWx3aW5kIGNvbG9yIHRva2VucyAoZS5nLiwgYmctYWNjZW50LCB0ZXh0LWNvbnRyYXN0KSBpbnN0ZWFkIG9mIGhhcmRjb2RlZCBjb2xvcnMuIFNlZTogJHtwYXR0ZXJuPy50aXRsZSB8fCAnTm8gQXJiaXRyYXJ5IENvbG9ycyd9IHBhdHRlcm4uYCxcbiAgICB9LFxuICAgIHNjaGVtYTogW10sXG4gIH0sXG4gIGRlZmF1bHRPcHRpb25zOiBbXSxcbiAgY3JlYXRlKGNvbnRleHQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgSlNYQXR0cmlidXRlKG5vZGUpIHtcbiAgICAgICAgLy8gT25seSBjaGVjayBjbGFzc05hbWUgYXR0cmlidXRlc1xuICAgICAgICBpZiAoXG4gICAgICAgICAgbm9kZS5uYW1lLnR5cGUgIT09ICdKU1hJZGVudGlmaWVyJyB8fFxuICAgICAgICAgIG5vZGUubmFtZS5uYW1lICE9PSAnY2xhc3NOYW1lJ1xuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgY2xhc3NOYW1lIHZhbHVlXG4gICAgICAgIGxldCBjbGFzc1ZhbHVlID0gJydcblxuICAgICAgICBpZiAobm9kZS52YWx1ZT8udHlwZSA9PT0gJ0xpdGVyYWwnICYmIHR5cGVvZiBub2RlLnZhbHVlLnZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNsYXNzVmFsdWUgPSBub2RlLnZhbHVlLnZhbHVlXG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgbm9kZS52YWx1ZT8udHlwZSA9PT0gJ0pTWEV4cHJlc3Npb25Db250YWluZXInICYmXG4gICAgICAgICAgbm9kZS52YWx1ZS5leHByZXNzaW9uLnR5cGUgPT09ICdMaXRlcmFsJyAmJlxuICAgICAgICAgIHR5cGVvZiBub2RlLnZhbHVlLmV4cHJlc3Npb24udmFsdWUgPT09ICdzdHJpbmcnXG4gICAgICAgICkge1xuICAgICAgICAgIGNsYXNzVmFsdWUgPSBub2RlLnZhbHVlLmV4cHJlc3Npb24udmFsdWVcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBub2RlLnZhbHVlPy50eXBlID09PSAnSlNYRXhwcmVzc2lvbkNvbnRhaW5lcicgJiZcbiAgICAgICAgICBub2RlLnZhbHVlLmV4cHJlc3Npb24udHlwZSA9PT0gJ1RlbXBsYXRlTGl0ZXJhbCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gRXh0cmFjdCBzdHJpbmcgcGFydHMgZnJvbSB0ZW1wbGF0ZSBsaXRlcmFsXG4gICAgICAgICAgY2xhc3NWYWx1ZSA9IG5vZGUudmFsdWUuZXhwcmVzc2lvbi5xdWFzaXNcbiAgICAgICAgICAgIC5tYXAoKHF1YXNpKSA9PiBxdWFzaS52YWx1ZS5yYXcpXG4gICAgICAgICAgICAuam9pbignICcpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNsYXNzVmFsdWUpIHJldHVyblxuXG4gICAgICAgIC8vIENoZWNrIGZvciBhcmJpdHJhcnkgY29sb3IgdmFsdWVzXG4gICAgICAgIGlmIChcbiAgICAgICAgICBBUkJJVFJBUllfQ09MT1JfUkVHRVgudGVzdChjbGFzc1ZhbHVlKSB8fFxuICAgICAgICAgIEFSQklUUkFSWV9WQVJfQ09MT1JfUkVHRVgudGVzdChjbGFzc1ZhbHVlKVxuICAgICAgICApIHtcbiAgICAgICAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICAgICAgICBub2RlLFxuICAgICAgICAgICAgbWVzc2FnZUlkOiAnbm9BcmJpdHJhcnlDb2xvcnMnLFxuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfVxuICB9LFxufSlcbiJdfQ==
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getCanonUrl, getCanonPattern } from '../utils/canon.js';
|
|
3
|
+
const RULE_NAME = 'no-inline-styles';
|
|
4
|
+
const pattern = getCanonPattern(RULE_NAME);
|
|
5
|
+
const createRule = ESLintUtils.RuleCreator(() => getCanonUrl(RULE_NAME));
|
|
6
|
+
export default createRule({
|
|
7
|
+
name: RULE_NAME,
|
|
8
|
+
meta: {
|
|
9
|
+
type: 'suggestion',
|
|
10
|
+
docs: {
|
|
11
|
+
description: pattern?.summary || 'No inline styles, use Tailwind exclusively',
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noInlineStyles: `[Canon ${pattern?.id || '008'}] Avoid inline style attribute. Use Tailwind CSS classes instead. See: ${pattern?.title || 'Tailwind Only'} pattern.`,
|
|
15
|
+
},
|
|
16
|
+
schema: [],
|
|
17
|
+
},
|
|
18
|
+
defaultOptions: [],
|
|
19
|
+
create(context) {
|
|
20
|
+
return {
|
|
21
|
+
JSXAttribute(node) {
|
|
22
|
+
// Check if attribute is "style"
|
|
23
|
+
if (node.name.type === 'JSXIdentifier' &&
|
|
24
|
+
node.name.name === 'style') {
|
|
25
|
+
context.report({
|
|
26
|
+
node,
|
|
27
|
+
messageId: 'noInlineStyles',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8taW5saW5lLXN0eWxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lc2xpbnQvcnVsZXMvbm8taW5saW5lLXN0eWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDdEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUVoRSxNQUFNLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQTtBQUNwQyxNQUFNLE9BQU8sR0FBRyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUE7QUFFMUMsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQTtBQUl4RSxlQUFlLFVBQVUsQ0FBaUI7SUFDeEMsSUFBSSxFQUFFLFNBQVM7SUFDZixJQUFJLEVBQUU7UUFDSixJQUFJLEVBQUUsWUFBWTtRQUNsQixJQUFJLEVBQUU7WUFDSixXQUFXLEVBQUUsT0FBTyxFQUFFLE9BQU8sSUFBSSw0Q0FBNEM7U0FDOUU7UUFDRCxRQUFRLEVBQUU7WUFDUixjQUFjLEVBQUUsVUFBVSxPQUFPLEVBQUUsRUFBRSxJQUFJLEtBQUssMEVBQTBFLE9BQU8sRUFBRSxLQUFLLElBQUksZUFBZSxXQUFXO1NBQ3JLO1FBQ0QsTUFBTSxFQUFFLEVBQUU7S0FDWDtJQUNELGNBQWMsRUFBRSxFQUFFO0lBQ2xCLE1BQU0sQ0FBQyxPQUFPO1FBQ1osT0FBTztZQUNMLFlBQVksQ0FBQyxJQUFJO2dCQUNmLGdDQUFnQztnQkFDaEMsSUFDRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxlQUFlO29CQUNsQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxPQUFPLEVBQzFCLENBQUM7b0JBQ0QsT0FBTyxDQUFDLE1BQU0sQ0FBQzt3QkFDYixJQUFJO3dCQUNKLFNBQVMsRUFBRSxnQkFBZ0I7cUJBQzVCLENBQUMsQ0FBQTtnQkFDSixDQUFDO1lBQ0gsQ0FBQztTQUNGLENBQUE7SUFDSCxDQUFDO0NBQ0YsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRVNMaW50VXRpbHMgfSBmcm9tICdAdHlwZXNjcmlwdC1lc2xpbnQvdXRpbHMnXG5pbXBvcnQgeyBnZXRDYW5vblVybCwgZ2V0Q2Fub25QYXR0ZXJuIH0gZnJvbSAnLi4vdXRpbHMvY2Fub24uanMnXG5cbmNvbnN0IFJVTEVfTkFNRSA9ICduby1pbmxpbmUtc3R5bGVzJ1xuY29uc3QgcGF0dGVybiA9IGdldENhbm9uUGF0dGVybihSVUxFX05BTUUpXG5cbmNvbnN0IGNyZWF0ZVJ1bGUgPSBFU0xpbnRVdGlscy5SdWxlQ3JlYXRvcigoKSA9PiBnZXRDYW5vblVybChSVUxFX05BTUUpKVxuXG50eXBlIE1lc3NhZ2VJZHMgPSAnbm9JbmxpbmVTdHlsZXMnXG5cbmV4cG9ydCBkZWZhdWx0IGNyZWF0ZVJ1bGU8W10sIE1lc3NhZ2VJZHM+KHtcbiAgbmFtZTogUlVMRV9OQU1FLFxuICBtZXRhOiB7XG4gICAgdHlwZTogJ3N1Z2dlc3Rpb24nLFxuICAgIGRvY3M6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiBwYXR0ZXJuPy5zdW1tYXJ5IHx8ICdObyBpbmxpbmUgc3R5bGVzLCB1c2UgVGFpbHdpbmQgZXhjbHVzaXZlbHknLFxuICAgIH0sXG4gICAgbWVzc2FnZXM6IHtcbiAgICAgIG5vSW5saW5lU3R5bGVzOiBgW0Nhbm9uICR7cGF0dGVybj8uaWQgfHwgJzAwOCd9XSBBdm9pZCBpbmxpbmUgc3R5bGUgYXR0cmlidXRlLiBVc2UgVGFpbHdpbmQgQ1NTIGNsYXNzZXMgaW5zdGVhZC4gU2VlOiAke3BhdHRlcm4/LnRpdGxlIHx8ICdUYWlsd2luZCBPbmx5J30gcGF0dGVybi5gLFxuICAgIH0sXG4gICAgc2NoZW1hOiBbXSxcbiAgfSxcbiAgZGVmYXVsdE9wdGlvbnM6IFtdLFxuICBjcmVhdGUoY29udGV4dCkge1xuICAgIHJldHVybiB7XG4gICAgICBKU1hBdHRyaWJ1dGUobm9kZSkge1xuICAgICAgICAvLyBDaGVjayBpZiBhdHRyaWJ1dGUgaXMgXCJzdHlsZVwiXG4gICAgICAgIGlmIChcbiAgICAgICAgICBub2RlLm5hbWUudHlwZSA9PT0gJ0pTWElkZW50aWZpZXInICYmXG4gICAgICAgICAgbm9kZS5uYW1lLm5hbWUgPT09ICdzdHlsZSdcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgIG1lc3NhZ2VJZDogJ25vSW5saW5lU3R5bGVzJyxcbiAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH1cbiAgfSxcbn0pXG4iXX0=
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"file": "patterns/008-tailwind-only.md",
|
|
118
118
|
"category": "styling",
|
|
119
119
|
"status": "stable",
|
|
120
|
-
"enforcement": "
|
|
121
|
-
"rule":
|
|
120
|
+
"enforcement": "eslint",
|
|
121
|
+
"rule": "gallop/no-inline-styles",
|
|
122
122
|
"summary": "No inline styles, use Tailwind exclusively"
|
|
123
123
|
},
|
|
124
124
|
{
|
|
@@ -230,6 +230,16 @@
|
|
|
230
230
|
"enforcement": "eslint",
|
|
231
231
|
"rule": "gallop/background-image-rounded",
|
|
232
232
|
"summary": "Background images must have rounded=\"rounded-none\""
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "020",
|
|
236
|
+
"title": "No Arbitrary Colors",
|
|
237
|
+
"file": "patterns/020-no-arbitrary-colors.md",
|
|
238
|
+
"category": "styling",
|
|
239
|
+
"status": "stable",
|
|
240
|
+
"enforcement": "eslint",
|
|
241
|
+
"rule": "gallop/no-arbitrary-colors",
|
|
242
|
+
"summary": "Use defined color tokens, not arbitrary color values"
|
|
233
243
|
}
|
|
234
244
|
],
|
|
235
245
|
"guarantees": [
|