@atlaskit/eslint-plugin-design-system 10.8.2 → 10.10.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/CHANGELOG.md +17 -0
- package/README.md +1 -0
- package/constellation/consistent-css-prop-usage/usage.mdx +9 -0
- package/constellation/index/usage.mdx +1 -0
- package/constellation/no-custom-icons/usage.mdx +36 -0
- package/dist/cjs/presets/all.codegen.js +2 -1
- package/dist/cjs/rules/consistent-css-prop-usage/index.js +19 -2
- package/dist/cjs/rules/ensure-design-token-usage/index.js +199 -227
- package/dist/cjs/rules/index.codegen.js +3 -1
- package/dist/cjs/rules/no-custom-icons/checks/has-prop.js +12 -0
- package/dist/cjs/rules/no-custom-icons/checks/is-from-import-source.js +42 -0
- package/dist/cjs/rules/no-custom-icons/checks/is-imported-jsx-element.js +10 -0
- package/dist/cjs/rules/no-custom-icons/index.js +67 -0
- package/dist/cjs/rules/no-legacy-icons/index.js +11 -83
- package/dist/cjs/rules/use-tokens-typography/index.js +4 -8
- package/dist/cjs/rules/utils/error-boundary.js +58 -11
- package/dist/es2019/presets/all.codegen.js +2 -1
- package/dist/es2019/rules/consistent-css-prop-usage/index.js +19 -2
- package/dist/es2019/rules/ensure-design-token-usage/index.js +16 -30
- package/dist/es2019/rules/index.codegen.js +3 -1
- package/dist/es2019/rules/no-custom-icons/checks/has-prop.js +4 -0
- package/dist/es2019/rules/no-custom-icons/checks/is-from-import-source.js +23 -0
- package/dist/es2019/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
- package/dist/es2019/rules/no-custom-icons/index.js +61 -0
- package/dist/es2019/rules/no-legacy-icons/index.js +11 -65
- package/dist/es2019/rules/use-tokens-typography/index.js +3 -7
- package/dist/es2019/rules/utils/error-boundary.js +55 -11
- package/dist/esm/presets/all.codegen.js +2 -1
- package/dist/esm/rules/consistent-css-prop-usage/index.js +19 -2
- package/dist/esm/rules/ensure-design-token-usage/index.js +199 -227
- package/dist/esm/rules/index.codegen.js +3 -1
- package/dist/esm/rules/no-custom-icons/checks/has-prop.js +6 -0
- package/dist/esm/rules/no-custom-icons/checks/is-from-import-source.js +36 -0
- package/dist/esm/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
- package/dist/esm/rules/no-custom-icons/index.js +61 -0
- package/dist/esm/rules/no-legacy-icons/index.js +11 -83
- package/dist/esm/rules/use-tokens-typography/index.js +4 -8
- package/dist/esm/rules/utils/error-boundary.js +56 -10
- package/dist/types/index.codegen.d.ts +1 -0
- package/dist/types/presets/all.codegen.d.ts +2 -1
- package/dist/types/rules/consistent-css-prop-usage/types.d.ts +1 -0
- package/dist/types/rules/index.codegen.d.ts +1 -0
- package/dist/types/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
- package/dist/types/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
- package/dist/types/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
- package/dist/types/rules/no-custom-icons/index.d.ts +3 -0
- package/dist/types/rules/no-legacy-icons/index.d.ts +1 -2
- package/dist/types/rules/utils/error-boundary.d.ts +8 -5
- package/dist/types-ts4.5/index.codegen.d.ts +1 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
- package/dist/types-ts4.5/rules/consistent-css-prop-usage/types.d.ts +1 -0
- package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-custom-icons/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-legacy-icons/index.d.ts +1 -2
- package/dist/types-ts4.5/rules/utils/error-boundary.d.ts +8 -5
- package/package.json +1 -1
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
|
|
3
|
+
// Need to intersect type RuleListener with a generic function to allow use of Parameters<...> to be used
|
|
4
|
+
|
|
5
|
+
// Allow config to be to be easily passed from rules
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* ESLint rules should NEVER throw exceptions, because that breaks the VSCode ESLint server
|
|
3
9
|
* (and probably the IntelliJ one too), which causes linting to fail in a file.
|
|
@@ -5,15 +11,53 @@
|
|
|
5
11
|
* It also breaks CI, which was the reason this error boundary was added. It's a final
|
|
6
12
|
* catch all.
|
|
7
13
|
*/
|
|
8
|
-
export
|
|
9
|
-
config
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
export function errorBoundary(ruleOrRules, config = false) {
|
|
15
|
+
const failSilently = failSilentlyFromConfig(config);
|
|
16
|
+
if (isSingleRuleListener(ruleOrRules)) {
|
|
17
|
+
return wrapSingleRuleListener(ruleOrRules, failSilently);
|
|
18
|
+
}
|
|
19
|
+
return wrapRuleListener(ruleOrRules, failSilently);
|
|
20
|
+
}
|
|
21
|
+
function isSingleRuleListener(rule) {
|
|
22
|
+
return typeof rule === 'function';
|
|
23
|
+
}
|
|
24
|
+
function failSilentlyFromConfig(c) {
|
|
25
|
+
switch (typeof c) {
|
|
26
|
+
case 'undefined':
|
|
27
|
+
return false;
|
|
28
|
+
case 'boolean':
|
|
29
|
+
return c;
|
|
30
|
+
case 'object':
|
|
31
|
+
if ('failSilently' in c) {
|
|
32
|
+
var _c$failSilently;
|
|
33
|
+
return (_c$failSilently = c.failSilently) !== null && _c$failSilently !== void 0 ? _c$failSilently : false;
|
|
34
|
+
} else if ('config' in c) {
|
|
35
|
+
var _c$config$failSilentl;
|
|
36
|
+
return (_c$config$failSilentl = c.config.failSilently) !== null && _c$config$failSilentl !== void 0 ? _c$config$failSilentl : false;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
default:
|
|
40
|
+
throw new Error('Invalid config');
|
|
18
41
|
}
|
|
19
|
-
}
|
|
42
|
+
}
|
|
43
|
+
function wrapSingleRuleListener(rule, failSilently) {
|
|
44
|
+
return (...args) => {
|
|
45
|
+
try {
|
|
46
|
+
rule(...args);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
if (!failSilently) {
|
|
49
|
+
// eslint-disable-next-line no-console
|
|
50
|
+
console.warn(err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function wrapRuleListener(ruleListener, failSilently) {
|
|
56
|
+
return Object.entries(ruleListener).reduce((wrappedRuleListener, e) => {
|
|
57
|
+
const ruleName = e[0];
|
|
58
|
+
const rule = e[1];
|
|
59
|
+
return Object.assign(wrappedRuleListener, {
|
|
60
|
+
[ruleName]: wrapSingleRuleListener(rule, failSilently)
|
|
61
|
+
});
|
|
62
|
+
}, {});
|
|
63
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::ab43b6e1a867d07b9a27eae78d48834a>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
export default {
|
|
@@ -12,6 +12,7 @@ export default {
|
|
|
12
12
|
'@atlaskit/design-system/icon-label': 'warn',
|
|
13
13
|
'@atlaskit/design-system/no-banned-imports': 'error',
|
|
14
14
|
'@atlaskit/design-system/no-css-tagged-template-expression': 'error',
|
|
15
|
+
'@atlaskit/design-system/no-custom-icons': 'warn',
|
|
15
16
|
'@atlaskit/design-system/no-deprecated-apis': 'error',
|
|
16
17
|
'@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
|
|
17
18
|
'@atlaskit/design-system/no-deprecated-imports': 'error',
|
|
@@ -490,7 +490,8 @@ var defaultConfig = {
|
|
|
490
490
|
cssImportSource: CSS_IN_JS_IMPORTS.compiled,
|
|
491
491
|
xcssImportSource: CSS_IN_JS_IMPORTS.atlaskitPrimitives,
|
|
492
492
|
excludeReactComponents: false,
|
|
493
|
-
autoFix: true
|
|
493
|
+
autoFix: true,
|
|
494
|
+
shouldAlwaysCheckXcss: false
|
|
494
495
|
};
|
|
495
496
|
var rule = createLintRule({
|
|
496
497
|
meta: {
|
|
@@ -533,6 +534,9 @@ var rule = createLintRule({
|
|
|
533
534
|
excludeReactComponents: {
|
|
534
535
|
type: 'boolean'
|
|
535
536
|
},
|
|
537
|
+
shouldAlwaysCheckXcss: {
|
|
538
|
+
type: 'boolean'
|
|
539
|
+
},
|
|
536
540
|
autoFix: {
|
|
537
541
|
type: 'boolean'
|
|
538
542
|
}
|
|
@@ -547,7 +551,20 @@ var rule = createLintRule({
|
|
|
547
551
|
var node = nodeOriginal;
|
|
548
552
|
var name = node.name,
|
|
549
553
|
value = node.value;
|
|
550
|
-
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* We skip linting `xcss` attributes if:
|
|
557
|
+
*
|
|
558
|
+
* - excludeReactComponents === true
|
|
559
|
+
* - shouldAlwaysCheckXcss === false
|
|
560
|
+
*
|
|
561
|
+
* In the future we may want to remove `shouldAlwaysCheckXcss`
|
|
562
|
+
* and just always lint `xcss`, regardless of `excludeReactComponents`
|
|
563
|
+
*/
|
|
564
|
+
if (mergedConfig.excludeReactComponents && name.name === 'xcss' && !mergedConfig.shouldAlwaysCheckXcss) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (mergedConfig.excludeReactComponents && node.parent.type === 'JSXOpeningElement' && name.name === 'css') {
|
|
551
568
|
// e.g. <item.before />
|
|
552
569
|
if (node.parent.name.type === 'JSXMemberExpression') {
|
|
553
570
|
return;
|
|
@@ -29,26 +29,18 @@ var createWithConfig = function createWithConfig(initialConfig) {
|
|
|
29
29
|
failSilently: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.failSilently) || defaultConfig.failSilently
|
|
30
30
|
};
|
|
31
31
|
var tokenNode = null;
|
|
32
|
-
return {
|
|
32
|
+
return errorBoundary({
|
|
33
33
|
ImportDeclaration: function ImportDeclaration(node) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
}, {
|
|
39
|
-
config: config
|
|
40
|
-
});
|
|
34
|
+
if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
|
|
35
|
+
tokenNode = node;
|
|
36
|
+
}
|
|
41
37
|
},
|
|
42
38
|
// For expressions within template literals (e.g. `color: ${red}`) - color only
|
|
43
39
|
'TemplateLiteral > Identifier': function TemplateLiteralIdentifier(node) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return;
|
|
49
|
-
}, {
|
|
50
|
-
config: config
|
|
51
|
-
});
|
|
40
|
+
if (config.domains.includes('color')) {
|
|
41
|
+
return lintTemplateIdentifierForColor(node, context, config);
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
52
44
|
},
|
|
53
45
|
// const styles = css({ color: 'red', margin: '4px' }), styled.div({ color: 'red', margin: '4px' })
|
|
54
46
|
ObjectExpression: function (_ObjectExpression) {
|
|
@@ -60,263 +52,243 @@ var createWithConfig = function createWithConfig(initialConfig) {
|
|
|
60
52
|
};
|
|
61
53
|
return ObjectExpression;
|
|
62
54
|
}(function (parentNode) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var importSources = getImportSources(context);
|
|
55
|
+
var _context$getScope = context.getScope(),
|
|
56
|
+
references = _context$getScope.references;
|
|
57
|
+
/**
|
|
58
|
+
* NOTE: This rule doesn't have an `importSources` config option,
|
|
59
|
+
* so this will just be equal to DEFAULT_IMPORT_SOURCES (which is fine)
|
|
60
|
+
*/
|
|
61
|
+
var importSources = getImportSources(context);
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
// To force the correct node type
|
|
64
|
+
if (!isNodeOfType(parentNode, 'ObjectExpression')) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
// Return for nested objects - these get handled automatically so without returning we'd be doubling up
|
|
69
|
+
if (parentNode.parent.type === 'Property') {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (isDecendantOfXcssBlock(parentNode, references, importSources)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!isDecendantOfStyleBlock(parentNode) && !isDecendantOfType(parentNode, 'JSXExpressionContainer')) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
function findObjectStyles(node) {
|
|
79
|
+
if (!isNodeOfType(node, 'Property')) {
|
|
79
80
|
return;
|
|
80
81
|
}
|
|
81
|
-
if (
|
|
82
|
+
if (isNodeOfType(node.value, 'ObjectExpression')) {
|
|
83
|
+
return node.value.properties.forEach(findObjectStyles);
|
|
84
|
+
}
|
|
85
|
+
if (!isNodeOfType(node.key, 'Identifier') && !isNodeOfType(node.key, 'Literal')) {
|
|
82
86
|
return;
|
|
83
87
|
}
|
|
84
|
-
|
|
88
|
+
var propertyName = isNodeOfType(node.key, 'Identifier') ? node.key.name : String(node.key.value);
|
|
89
|
+
|
|
90
|
+
// Returns which domains to lint against based on rule's config and current property
|
|
91
|
+
var domains = getDomainsForProperty(propertyName, config.domains);
|
|
92
|
+
if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
|
|
85
93
|
return;
|
|
86
94
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
if (isNodeOfType(node.value, 'TemplateLiteral')) {
|
|
96
|
+
var value = getValueFromTemplateLiteralRaw(node.value, context);
|
|
97
|
+
if (Array.isArray(value) && value.some(isCalc)) {
|
|
98
|
+
return context.report({
|
|
99
|
+
node: node,
|
|
100
|
+
messageId: 'noCalcUsage',
|
|
101
|
+
data: {
|
|
102
|
+
payload: "".concat(propertyName)
|
|
103
|
+
}
|
|
104
|
+
});
|
|
96
105
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// Returns which domains to lint against based on rule's config and current property
|
|
100
|
-
var domains = getDomainsForProperty(propertyName, config.domains);
|
|
101
|
-
if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
|
|
106
|
+
if (node.value.expressions.some(isDecendantOfGlobalToken)) {
|
|
102
107
|
return;
|
|
103
108
|
}
|
|
104
|
-
if (isNodeOfType(node.value, 'TemplateLiteral')) {
|
|
105
|
-
var value = getValueFromTemplateLiteralRaw(node.value, context);
|
|
106
|
-
if (Array.isArray(value) && value.some(isCalc)) {
|
|
107
|
-
return context.report({
|
|
108
|
-
node: node,
|
|
109
|
-
messageId: 'noCalcUsage',
|
|
110
|
-
data: {
|
|
111
|
-
payload: "".concat(propertyName)
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (node.value.expressions.some(isDecendantOfGlobalToken)) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (domains.includes('color')) {
|
|
120
|
-
return lintObjectForColor(node, context, config);
|
|
121
|
-
}
|
|
122
|
-
if (domains.includes('spacing') || domains.includes('shape')) {
|
|
123
|
-
/**
|
|
124
|
-
* We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration.
|
|
125
|
-
*/
|
|
126
|
-
var fontSizeNode = getPropertyNodeFromParent('fontSize', parentNode);
|
|
127
|
-
var fontSize = fontSizeNode && getValueForPropertyNode(fontSizeNode, context);
|
|
128
|
-
return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
|
|
129
|
-
}
|
|
130
109
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
110
|
+
if (domains.includes('color')) {
|
|
111
|
+
return lintObjectForColor(node, context, config);
|
|
112
|
+
}
|
|
113
|
+
if (domains.includes('spacing') || domains.includes('shape')) {
|
|
114
|
+
/**
|
|
115
|
+
* We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration.
|
|
116
|
+
*/
|
|
117
|
+
var fontSizeNode = getPropertyNodeFromParent('fontSize', parentNode);
|
|
118
|
+
var fontSize = fontSizeNode && getValueForPropertyNode(fontSizeNode, context);
|
|
119
|
+
return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
parentNode.properties.forEach(findObjectStyles);
|
|
135
123
|
}),
|
|
136
124
|
// CSSTemplateLiteral and StyledTemplateLiteral
|
|
137
125
|
// const cssTemplateLiteral = css`color: red; padding: 12px`;
|
|
138
126
|
// const styledTemplateLiteral = styled.p`color: red; padding: 8px`;
|
|
139
127
|
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"],TaggedTemplateExpression[tag.callee.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyledTaggedTemplateExpressionTagCalleeNameStyled(node) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if
|
|
147
|
-
|
|
148
|
-
|
|
128
|
+
// To force the correct node type
|
|
129
|
+
if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
var processedCssLines = processCssNode(node, context);
|
|
133
|
+
if (!processedCssLines) {
|
|
134
|
+
// if we can't get a processed css we bail
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
var globalFontSize = getFontSizeValueInScope(processedCssLines);
|
|
138
|
+
var textForSource = context.getSourceCode().getText(node.quasi);
|
|
139
|
+
var allReplacedValues = [];
|
|
140
|
+
var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
|
|
141
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
142
|
+
resolvedCssLine = _ref2[0],
|
|
143
|
+
originalCssLine = _ref2[1];
|
|
144
|
+
var _resolvedCssLine$spli = resolvedCssLine.split(':'),
|
|
145
|
+
_resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
|
|
146
|
+
originalProperty = _resolvedCssLine$spli2[0],
|
|
147
|
+
resolvedCssValues = _resolvedCssLine$spli2[1];
|
|
148
|
+
var _originalCssLine$spli = originalCssLine.split(':'),
|
|
149
|
+
_originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
|
|
150
|
+
_ = _originalCssLine$spli2[0],
|
|
151
|
+
originalCssValues = _originalCssLine$spli2[1];
|
|
152
|
+
var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
|
|
153
|
+
var isFontFamily = /fontFamily/.test(propertyName);
|
|
154
|
+
var replacedValuesPerProperty = [originalProperty];
|
|
155
|
+
var domains = getDomainsForProperty(propertyName, config.domains);
|
|
156
|
+
if (domains.length === 0 || !resolvedCssValues) {
|
|
157
|
+
// in both of these cases no changes should be made to the current property
|
|
158
|
+
return currentSource;
|
|
149
159
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
var allReplacedValues = [];
|
|
153
|
-
var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
|
|
154
|
-
var _ref2 = _slicedToArray(_ref, 2),
|
|
155
|
-
resolvedCssLine = _ref2[0],
|
|
156
|
-
originalCssLine = _ref2[1];
|
|
157
|
-
var _resolvedCssLine$spli = resolvedCssLine.split(':'),
|
|
158
|
-
_resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
|
|
159
|
-
originalProperty = _resolvedCssLine$spli2[0],
|
|
160
|
-
resolvedCssValues = _resolvedCssLine$spli2[1];
|
|
161
|
-
var _originalCssLine$spli = originalCssLine.split(':'),
|
|
162
|
-
_originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
|
|
163
|
-
_ = _originalCssLine$spli2[0],
|
|
164
|
-
originalCssValues = _originalCssLine$spli2[1];
|
|
165
|
-
var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
|
|
166
|
-
var isFontFamily = /fontFamily/.test(propertyName);
|
|
167
|
-
var replacedValuesPerProperty = [originalProperty];
|
|
168
|
-
var domains = getDomainsForProperty(propertyName, config.domains);
|
|
169
|
-
if (domains.length === 0 || !resolvedCssValues) {
|
|
170
|
-
// in both of these cases no changes should be made to the current property
|
|
160
|
+
if (domains.includes('color')) {
|
|
161
|
+
if (includesTokenString(resolvedCssValues.trim())) {
|
|
171
162
|
return currentSource;
|
|
172
163
|
}
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
164
|
+
if (includesHardCodedColor(resolvedCssValues)) {
|
|
165
|
+
context.report({
|
|
166
|
+
messageId: 'hardCodedColor',
|
|
167
|
+
node: node
|
|
168
|
+
});
|
|
169
|
+
return currentSource;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (domains.includes('spacing') || domains.includes('shape')) {
|
|
173
|
+
if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
|
|
174
|
+
// no changes should be made to the current property
|
|
175
|
+
return currentSource;
|
|
184
176
|
}
|
|
185
|
-
if (domains.includes('spacing') || domains.includes('shape')) {
|
|
186
|
-
if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
|
|
187
|
-
// no changes should be made to the current property
|
|
188
|
-
return currentSource;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// gets the values from the associated property, numeric values or NaN
|
|
192
|
-
var processedNumericValues = getValueFromShorthand(resolvedCssValues);
|
|
193
|
-
var processedValues = splitShorthandValues(resolvedCssValues);
|
|
194
|
-
// only splits shorthand values but it does not transform NaNs so tokens are preserved
|
|
195
|
-
var originalValues = splitShorthandValues(originalCssValues);
|
|
196
|
-
|
|
197
|
-
// reconstructing the string
|
|
198
|
-
// should replace what it can and preserve the raw value for everything else
|
|
199
177
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
|
|
206
|
-
}).map(function (_ref3) {
|
|
207
|
-
var _ref4 = _slicedToArray(_ref3, 3),
|
|
208
|
-
numericOrNanValue = _ref4[0],
|
|
209
|
-
pxValue = _ref4[1],
|
|
210
|
-
originalValue = _ref4[2];
|
|
211
|
-
if (!originalValue) {
|
|
212
|
-
return originalValue;
|
|
213
|
-
}
|
|
214
|
-
if (isCalc(originalValue)) {
|
|
215
|
-
context.report({
|
|
216
|
-
node: node,
|
|
217
|
-
messageId: 'noCalcUsage',
|
|
218
|
-
data: {
|
|
219
|
-
payload: "".concat(propertyName)
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
return originalValue;
|
|
223
|
-
}
|
|
224
|
-
if (isTokenValueString(originalValue)) {
|
|
225
|
-
// if the value is already valid, nothing to report or replace
|
|
226
|
-
return originalValue;
|
|
227
|
-
}
|
|
178
|
+
// gets the values from the associated property, numeric values or NaN
|
|
179
|
+
var processedNumericValues = getValueFromShorthand(resolvedCssValues);
|
|
180
|
+
var processedValues = splitShorthandValues(resolvedCssValues);
|
|
181
|
+
// only splits shorthand values but it does not transform NaNs so tokens are preserved
|
|
182
|
+
var originalValues = splitShorthandValues(originalCssValues);
|
|
228
183
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return originalValue;
|
|
232
|
-
}
|
|
233
|
-
if (isNaN(numericOrNanValue) && !isFontFamily) {
|
|
234
|
-
// do not report if we have nothing to replace with
|
|
235
|
-
return originalValue;
|
|
236
|
-
}
|
|
184
|
+
// reconstructing the string
|
|
185
|
+
// should replace what it can and preserve the raw value for everything else
|
|
237
186
|
|
|
238
|
-
|
|
187
|
+
var replacementValue = processedNumericValues
|
|
188
|
+
// put together resolved value and original value on a tuple
|
|
189
|
+
.map(function (value, index) {
|
|
190
|
+
return [
|
|
191
|
+
// if emToPX conversion fails we'll default to original value
|
|
192
|
+
emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
|
|
193
|
+
}).map(function (_ref3) {
|
|
194
|
+
var _ref4 = _slicedToArray(_ref3, 3),
|
|
195
|
+
numericOrNanValue = _ref4[0],
|
|
196
|
+
pxValue = _ref4[1],
|
|
197
|
+
originalValue = _ref4[2];
|
|
198
|
+
if (!originalValue) {
|
|
199
|
+
return originalValue;
|
|
200
|
+
}
|
|
201
|
+
if (isCalc(originalValue)) {
|
|
239
202
|
context.report({
|
|
240
203
|
node: node,
|
|
241
|
-
messageId: '
|
|
204
|
+
messageId: 'noCalcUsage',
|
|
242
205
|
data: {
|
|
243
|
-
payload: "".concat(propertyName
|
|
206
|
+
payload: "".concat(propertyName)
|
|
244
207
|
}
|
|
245
208
|
});
|
|
209
|
+
return originalValue;
|
|
210
|
+
}
|
|
211
|
+
if (isTokenValueString(originalValue)) {
|
|
212
|
+
// if the value is already valid, nothing to report or replace
|
|
213
|
+
return originalValue;
|
|
214
|
+
}
|
|
246
215
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return replacementToken;
|
|
255
|
-
}).join(' ');
|
|
256
|
-
if (replacedValuesPerProperty.length > 1) {
|
|
257
|
-
// first value is the property name, so it will always have at least 1
|
|
258
|
-
allReplacedValues.push(replacedValuesPerProperty);
|
|
216
|
+
// do not replace 0 or auto with tokens
|
|
217
|
+
if (isZero(pxValue) || isAuto(pxValue)) {
|
|
218
|
+
return originalValue;
|
|
219
|
+
}
|
|
220
|
+
if (isNaN(numericOrNanValue) && !isFontFamily) {
|
|
221
|
+
// do not report if we have nothing to replace with
|
|
222
|
+
return originalValue;
|
|
259
223
|
}
|
|
260
224
|
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
225
|
+
// value is numeric or fontFamily, and needs replacing we'll report first
|
|
226
|
+
context.report({
|
|
227
|
+
node: node,
|
|
228
|
+
messageId: 'noRawSpacingValues',
|
|
229
|
+
data: {
|
|
230
|
+
payload: "".concat(propertyName, ":").concat(numericOrNanValue)
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// from here on we know value is numeric or a font family, so it might or might not have a token equivalent
|
|
235
|
+
var replacementNode = getTokenReplacement(propertyName, numericOrNanValue);
|
|
236
|
+
if (!replacementNode) {
|
|
237
|
+
return originalValue;
|
|
266
238
|
}
|
|
267
|
-
|
|
239
|
+
var replacementToken = '${' + replacementNode.toString() + '}';
|
|
240
|
+
replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
|
|
241
|
+
return replacementToken;
|
|
242
|
+
}).join(' ');
|
|
243
|
+
if (replacedValuesPerProperty.length > 1) {
|
|
244
|
+
// first value is the property name, so it will always have at least 1
|
|
245
|
+
allReplacedValues.push(replacedValuesPerProperty);
|
|
268
246
|
}
|
|
269
|
-
return currentSource;
|
|
270
|
-
}, textForSource);
|
|
271
|
-
if (completeSource !== textForSource) {
|
|
272
|
-
// means we found some replacement values, we'll give the option to fix them
|
|
273
247
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
248
|
+
// replace property:val with new property:val
|
|
249
|
+
var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
|
|
250
|
+
"".concat(originalProperty, ": ").concat(replacementValue));
|
|
251
|
+
if (!replacedCssLine) {
|
|
252
|
+
return currentSource;
|
|
253
|
+
}
|
|
254
|
+
return replacedCssLine;
|
|
281
255
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
256
|
+
return currentSource;
|
|
257
|
+
}, textForSource);
|
|
258
|
+
if (completeSource !== textForSource) {
|
|
259
|
+
// means we found some replacement values, we'll give the option to fix them
|
|
260
|
+
|
|
261
|
+
context.report({
|
|
262
|
+
node: node,
|
|
263
|
+
messageId: 'autofixesPossible',
|
|
264
|
+
fix: function fix(fixer) {
|
|
265
|
+
return (!tokenNode && config.applyImport ? [insertTokensImport(fixer)] : []).concat([fixer.replaceText(node.quasi, completeSource)]);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
285
269
|
},
|
|
286
270
|
// For inline JSX styles - literals (e.g. <Test color="red"/>) - color only
|
|
287
271
|
'JSXAttribute > Literal': function JSXAttributeLiteral(node) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return;
|
|
293
|
-
}, {
|
|
294
|
-
config: config
|
|
295
|
-
});
|
|
272
|
+
if (config.domains.includes('color')) {
|
|
273
|
+
return lintJSXLiteralForColor(node, context, config);
|
|
274
|
+
}
|
|
275
|
+
return;
|
|
296
276
|
},
|
|
297
277
|
// For inline JSX styles - members (e.g. <Test color={color.red}/>) - color only
|
|
298
278
|
'JSXExpressionContainer > MemberExpression': function JSXExpressionContainerMemberExpression(node) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return;
|
|
304
|
-
}, {
|
|
305
|
-
config: config
|
|
306
|
-
});
|
|
279
|
+
if (config.domains.includes('color')) {
|
|
280
|
+
return lintJSXMemberForColor(node, context, config);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
307
283
|
},
|
|
308
284
|
// For inline JSX styles - identifiers (e.g. <Test color={red}/>) - color only
|
|
309
285
|
'JSXExpressionContainer > Identifier': function JSXExpressionContainerIdentifier(node) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return;
|
|
315
|
-
}, {
|
|
316
|
-
config: config
|
|
317
|
-
});
|
|
286
|
+
if (config.domains.includes('color')) {
|
|
287
|
+
return lintJSXIdentifierForColor(node, context, config);
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
318
290
|
}
|
|
319
|
-
};
|
|
291
|
+
}, config);
|
|
320
292
|
};
|
|
321
293
|
};
|
|
322
294
|
var rule = createLintRule({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::402e6eb5433560b1032e5ed926bb5564>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
import consistentCssPropUsage from './consistent-css-prop-usage';
|
|
@@ -9,6 +9,7 @@ import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
|
|
|
9
9
|
import iconLabel from './icon-label';
|
|
10
10
|
import noBannedImports from './no-banned-imports';
|
|
11
11
|
import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
|
|
12
|
+
import noCustomIcons from './no-custom-icons';
|
|
12
13
|
import noDeprecatedApis from './no-deprecated-apis';
|
|
13
14
|
import noDeprecatedDesignTokenUsage from './no-deprecated-design-token-usage';
|
|
14
15
|
import noDeprecatedImports from './no-deprecated-imports';
|
|
@@ -50,6 +51,7 @@ export default {
|
|
|
50
51
|
'icon-label': iconLabel,
|
|
51
52
|
'no-banned-imports': noBannedImports,
|
|
52
53
|
'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
|
|
54
|
+
'no-custom-icons': noCustomIcons,
|
|
53
55
|
'no-deprecated-apis': noDeprecatedApis,
|
|
54
56
|
'no-deprecated-design-token-usage': noDeprecatedDesignTokenUsage,
|
|
55
57
|
'no-deprecated-imports': noDeprecatedImports,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
export function hasProp(node, propName) {
|
|
3
|
+
return isNodeOfType(node.openingElement, 'JSXOpeningElement') && node.openingElement.attributes.some(function (a) {
|
|
4
|
+
return a.type === 'JSXAttribute' && a.name.name === propName;
|
|
5
|
+
});
|
|
6
|
+
}
|