@atlaskit/eslint-plugin-design-system 13.29.2 → 13.30.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 +23 -0
- package/README.md +1 -1
- package/dist/cjs/rules/no-deprecated-imports/checks.js +10 -8
- package/dist/cjs/rules/no-deprecated-imports/handlers/icon.js +22 -28
- package/dist/cjs/rules/use-character-counter-field/index.js +12 -5
- package/dist/cjs/rules/use-tokens-typography/transformers/style-object.js +3 -5
- package/dist/cjs/rules/use-tokens-typography/utils.js +22 -9
- package/dist/es2019/rules/no-deprecated-imports/checks.js +10 -8
- package/dist/es2019/rules/no-deprecated-imports/handlers/icon.js +22 -22
- package/dist/es2019/rules/use-character-counter-field/index.js +11 -4
- package/dist/es2019/rules/use-tokens-typography/transformers/style-object.js +3 -3
- package/dist/es2019/rules/use-tokens-typography/utils.js +17 -7
- package/dist/esm/rules/no-deprecated-imports/checks.js +10 -8
- package/dist/esm/rules/no-deprecated-imports/handlers/icon.js +22 -28
- package/dist/esm/rules/use-character-counter-field/index.js +11 -4
- package/dist/esm/rules/use-tokens-typography/transformers/style-object.js +3 -5
- package/dist/esm/rules/use-tokens-typography/utils.js +19 -6
- package/dist/types/rules/use-character-counter-field/index.d.ts +2 -1
- package/dist/types/rules/use-tokens-typography/utils.d.ts +3 -11
- package/dist/types-ts4.5/rules/use-character-counter-field/index.d.ts +2 -1
- package/dist/types-ts4.5/rules/use-tokens-typography/utils.d.ts +3 -11
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-design-system
|
|
2
2
|
|
|
3
|
+
## 13.30.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`24edc07c201e2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/24edc07c201e2) -
|
|
8
|
+
`use-tokens-typography` now only matches and supports tokens from the refreshed typography theme.
|
|
9
|
+
Changes include:
|
|
10
|
+
- `font.body.UNSAFE_small` will no longer be suggested in autofixes.
|
|
11
|
+
- Both 11px and 12px will now be autofixed to the `font.body.small` token.
|
|
12
|
+
- Heading tokens will only be suggested if bold font weights (700 or 653) are used.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
|
|
18
|
+
## 13.29.3
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- [`da8c77a7aa301`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/da8c77a7aa301) -
|
|
23
|
+
Update the use-character-counter-field rule to include guidance for when to use the standalone
|
|
24
|
+
character counter component
|
|
25
|
+
|
|
3
26
|
## 13.29.2
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ module.exports = {
|
|
|
98
98
|
| <a href="./packages/design-system/eslint-plugin/src/rules/no-utility-icons/README.md">no-utility-icons</a> | Disallow use of deprecated utility icons, in favor of core icons with `size="small"`. | Yes | Yes | Yes |
|
|
99
99
|
| <a href="./packages/design-system/eslint-plugin/src/rules/prefer-primitives/README.md">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
|
|
100
100
|
| <a href="./packages/design-system/eslint-plugin/src/rules/use-button-group-label/README.md">use-button-group-label</a> | Ensures button groups are described to assistive technology by a direct label or by another element. | Yes | | Yes |
|
|
101
|
-
| <a href="./packages/design-system/eslint-plugin/src/rules/use-character-counter-field/README.md">use-character-counter-field</a> | Suggests using CharacterCounterField when Textfield or Textarea components have maxLength or minLength props
|
|
101
|
+
| <a href="./packages/design-system/eslint-plugin/src/rules/use-character-counter-field/README.md">use-character-counter-field</a> | Suggests using CharacterCounterField or CharacterCounter when Textfield or Textarea components have maxLength or minLength props. | Yes | | |
|
|
102
102
|
| <a href="./packages/design-system/eslint-plugin/src/rules/use-correct-field/README.md">use-correct-field</a> | Ensure makers use appropriate field component for their respective form elements. | Yes | Yes | Yes |
|
|
103
103
|
| <a href="./packages/design-system/eslint-plugin/src/rules/use-cx-function-in-xcss/README.md">use-cx-function-in-xcss</a> | Enforces cx function use to combine styles in xcss. | Yes | Yes | Yes |
|
|
104
104
|
| <a href="./packages/design-system/eslint-plugin/src/rules/use-datetime-picker-calendar-button/README.md">use-datetime-picker-calendar-button</a> | Encourages makers to use calendar button in Atlassian Design System's date picker and datetime picker components. | Yes | Yes | Yes |
|
|
@@ -14,6 +14,14 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
14
14
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
15
15
|
var createChecks = exports.createChecks = function createChecks(context) {
|
|
16
16
|
var deprecatedIconHandler = (0, _icon.getDeprecationIconHandler)(context);
|
|
17
|
+
var cachedConfig = function (_context$options$) {
|
|
18
|
+
var config = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || (0, _getDeprecatedConfig.getConfig)('imports');
|
|
19
|
+
if (!(0, _types.isDeprecatedImportConfig)(config)) {
|
|
20
|
+
throw new Error('Config is invalid for deprecated imports');
|
|
21
|
+
}
|
|
22
|
+
return config;
|
|
23
|
+
}();
|
|
24
|
+
var deprecatedImportSources = new Set(Object.keys(cachedConfig));
|
|
17
25
|
var throwErrors = function throwErrors() {
|
|
18
26
|
deprecatedIconHandler.throwErrors();
|
|
19
27
|
};
|
|
@@ -33,20 +41,14 @@ var createChecks = exports.createChecks = function createChecks(context) {
|
|
|
33
41
|
* @private
|
|
34
42
|
*/
|
|
35
43
|
function checkRestrictedPathAndReport(_ref) {
|
|
36
|
-
var _context$options$;
|
|
37
44
|
var importSource = _ref.importSource,
|
|
38
45
|
type = _ref.type,
|
|
39
46
|
node = _ref.node,
|
|
40
47
|
importNames = _ref.importNames;
|
|
41
|
-
|
|
42
|
-
// TODO: JFP-2823 - this type cast was added due to Jira's ESLint v9 migration
|
|
43
|
-
((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || (0, _getDeprecatedConfig.getConfig)('imports');
|
|
44
|
-
if (!(0, _types.isDeprecatedImportConfig)(restrictedPathMessages)) {
|
|
45
|
-
throw new Error('Config is invalid for deprecated imports');
|
|
46
|
-
}
|
|
47
|
-
if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
|
|
48
|
+
if (!deprecatedImportSources.has(importSource)) {
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
51
|
+
var restrictedPathMessages = cachedConfig;
|
|
50
52
|
var config = restrictedPathMessages[importSource];
|
|
51
53
|
var handler = getHandler(importSource);
|
|
52
54
|
if (handler) {
|
|
@@ -24,6 +24,7 @@ var getDeprecationIconHandler = exports.getDeprecationIconHandler = function get
|
|
|
24
24
|
var identifiers = new Map();
|
|
25
25
|
var importErrors = {};
|
|
26
26
|
var exportErrors = {};
|
|
27
|
+
var iconNameToImportSource = new Map();
|
|
27
28
|
var getConfigFlag = function getConfigFlag(key, defaultValue) {
|
|
28
29
|
if (context.options && context.options.length > 0 && context.options[0] && context.options[0].hasOwnProperty(key)) {
|
|
29
30
|
return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
|
|
@@ -40,6 +41,7 @@ var getDeprecationIconHandler = exports.getDeprecationIconHandler = function get
|
|
|
40
41
|
importSource = _ref.importSource,
|
|
41
42
|
config = _ref.config;
|
|
42
43
|
if (config.message) {
|
|
44
|
+
var _node$specifiers$;
|
|
43
45
|
var myError = {
|
|
44
46
|
node: node,
|
|
45
47
|
messageId: _constants.pathWithCustomMessageId,
|
|
@@ -50,6 +52,10 @@ var getDeprecationIconHandler = exports.getDeprecationIconHandler = function get
|
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
importErrors[node.source.value] = myError;
|
|
55
|
+
var importIconName = (_node$specifiers$ = node.specifiers[0]) === null || _node$specifiers$ === void 0 || (_node$specifiers$ = _node$specifiers$.local) === null || _node$specifiers$ === void 0 ? void 0 : _node$specifiers$.name;
|
|
56
|
+
if (importIconName) {
|
|
57
|
+
iconNameToImportSource.set(importIconName, importSource);
|
|
58
|
+
}
|
|
53
59
|
}
|
|
54
60
|
};
|
|
55
61
|
var createExportError = function createExportError(_ref2) {
|
|
@@ -166,20 +172,14 @@ var getDeprecationIconHandler = exports.getDeprecationIconHandler = function get
|
|
|
166
172
|
if (!('openingElement' in node) || !(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
|
|
167
173
|
return;
|
|
168
174
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
var _jsxElements$get;
|
|
178
|
-
(_jsxElements$get = jsxElements.get(importSource)) === null || _jsxElements$get === void 0 || _jsxElements$get.push(node);
|
|
179
|
-
} else {
|
|
180
|
-
jsxElements.set(importSource, [node]);
|
|
181
|
-
}
|
|
182
|
-
break;
|
|
175
|
+
var iconName = node.openingElement.name.name;
|
|
176
|
+
var importSource = iconNameToImportSource.get(iconName);
|
|
177
|
+
if (importSource) {
|
|
178
|
+
if (jsxElements.has(importSource)) {
|
|
179
|
+
var _jsxElements$get;
|
|
180
|
+
(_jsxElements$get = jsxElements.get(importSource)) === null || _jsxElements$get === void 0 || _jsxElements$get.push(node);
|
|
181
|
+
} else {
|
|
182
|
+
jsxElements.set(importSource, [node]);
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
};
|
|
@@ -187,20 +187,14 @@ var getDeprecationIconHandler = exports.getDeprecationIconHandler = function get
|
|
|
187
187
|
if (node.type !== 'Identifier' || node.parent.type !== 'JSXExpressionContainer') {
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
var _identifiers$get;
|
|
199
|
-
(_identifiers$get = identifiers.get(importSource)) === null || _identifiers$get === void 0 || _identifiers$get.push(node);
|
|
200
|
-
} else {
|
|
201
|
-
identifiers.set(importSource, [node]);
|
|
202
|
-
}
|
|
203
|
-
break;
|
|
190
|
+
var iconName = node.name;
|
|
191
|
+
var importSource = iconNameToImportSource.get(iconName);
|
|
192
|
+
if (importSource) {
|
|
193
|
+
if (identifiers.has(importSource)) {
|
|
194
|
+
var _identifiers$get;
|
|
195
|
+
(_identifiers$get = identifiers.get(importSource)) === null || _identifiers$get === void 0 || _identifiers$get.push(node);
|
|
196
|
+
} else {
|
|
197
|
+
identifiers.set(importSource, [node]);
|
|
204
198
|
}
|
|
205
199
|
}
|
|
206
200
|
};
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.ruleName = exports.
|
|
6
|
+
exports.ruleName = exports.messageOutsideForm = exports.messageInsideForm = exports.default = void 0;
|
|
7
7
|
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
8
8
|
var _jsxElement = require("../../ast-nodes/jsx-element");
|
|
9
9
|
var _createRule = require("../utils/create-rule");
|
|
10
10
|
var TEXTFIELD_PACKAGE = '@atlaskit/textfield';
|
|
11
11
|
var TEXTAREA_PACKAGE = '@atlaskit/textarea';
|
|
12
12
|
var FORM_PACKAGE = '@atlaskit/form';
|
|
13
|
-
var
|
|
13
|
+
var messageInsideForm = exports.messageInsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea inside a Form, use `CharacterCounterField` from `@atlaskit/form` instead of Field and remove the props from the Textfield/Textarea. This ensures accessibility through real time feedback and aligns with the design system. Read more about [character counter fields](https://atlassian.design/components/form/examples#charactercounterfield)';
|
|
14
|
+
var messageOutsideForm = exports.messageOutsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea, use `CharacterCounter` from `@atlaskit/form` alongside your input for real-time character count feedback. This ensures accessibility through screen reader announcements and visual feedback. Read more about [standalone character counter](https://atlassian.design/components/form/examples#standalone-charactercounter)';
|
|
14
15
|
var ruleName = exports.ruleName = __dirname.split('/').slice(-1)[0];
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -58,12 +59,13 @@ var rule = (0, _createRule.createLintRule)({
|
|
|
58
59
|
name: ruleName,
|
|
59
60
|
type: 'suggestion',
|
|
60
61
|
docs: {
|
|
61
|
-
description: 'Suggests using CharacterCounterField when Textfield or Textarea components have maxLength or minLength props
|
|
62
|
+
description: 'Suggests using CharacterCounterField or CharacterCounter when Textfield or Textarea components have maxLength or minLength props.',
|
|
62
63
|
recommended: true,
|
|
63
64
|
severity: 'warn'
|
|
64
65
|
},
|
|
65
66
|
messages: {
|
|
66
|
-
useCharacterCounterField:
|
|
67
|
+
useCharacterCounterField: messageInsideForm,
|
|
68
|
+
useCharacterCounter: messageOutsideForm
|
|
67
69
|
}
|
|
68
70
|
},
|
|
69
71
|
create: function create(context) {
|
|
@@ -124,12 +126,17 @@ var rule = (0, _createRule.createLintRule)({
|
|
|
124
126
|
var hasMaxLength = _jsxElement.JSXElementHelper.getAttributeByName(node, 'maxLength');
|
|
125
127
|
var hasMinLength = _jsxElement.JSXElementHelper.getAttributeByName(node, 'minLength');
|
|
126
128
|
if (hasMaxLength || hasMinLength) {
|
|
127
|
-
//
|
|
129
|
+
// Use different messages based on whether inside Form context or not
|
|
128
130
|
if (isInsideFormOrField(node, formComponentNames)) {
|
|
129
131
|
context.report({
|
|
130
132
|
node: node,
|
|
131
133
|
messageId: 'useCharacterCounterField'
|
|
132
134
|
});
|
|
135
|
+
} else {
|
|
136
|
+
context.report({
|
|
137
|
+
node: node,
|
|
138
|
+
messageId: 'useCharacterCounter'
|
|
139
|
+
});
|
|
133
140
|
}
|
|
134
141
|
}
|
|
135
142
|
}
|
|
@@ -95,12 +95,10 @@ var StyleObject = exports.StyleObject = {
|
|
|
95
95
|
matchingTokens = (0, _utils2.findTypographyTokenForValues)(fontSizeValue, lineHeightValue);
|
|
96
96
|
if (matchingTokens.length) {
|
|
97
97
|
// If we have multiple matching tokens, try matching fontWeight
|
|
98
|
-
var
|
|
99
|
-
|
|
100
|
-
});
|
|
101
|
-
if (matchingTokensWithWeight.length) {
|
|
98
|
+
var matchingTokenWithWeight = (0, _utils2.findFontWeightTokenForValue)(fontWeightValue, matchingTokens);
|
|
99
|
+
if (matchingTokenWithWeight) {
|
|
102
100
|
// Possibly narrowed down tokens
|
|
103
|
-
matchingTokens =
|
|
101
|
+
matchingTokens = [matchingTokenWithWeight];
|
|
104
102
|
} else {
|
|
105
103
|
// Ended up with 0 matches by matching fontWeight
|
|
106
104
|
// return body token and add fontWeight manually
|
|
@@ -40,12 +40,16 @@ var isFontFamily = exports.isFontFamily = function isFontFamily(node) {
|
|
|
40
40
|
var isCodeFontFamily = exports.isCodeFontFamily = function isCodeFontFamily(node) {
|
|
41
41
|
return (0, _eslintCodemodUtils.isNodeOfType)(node, 'CallExpression') && (0, _eslintCodemodUtils.isNodeOfType)(node.callee, 'Identifier') && (node.callee.name === 'codeFontFamily' || node.callee.name === 'getCodeFontFamily');
|
|
42
42
|
};
|
|
43
|
-
var typographyValueToToken = exports.typographyValueToToken = _tokensRaw.
|
|
43
|
+
var typographyValueToToken = exports.typographyValueToToken = _tokensRaw.typography
|
|
44
44
|
// we're filtering here to remove the `font` tokens.
|
|
45
45
|
.filter(function (t) {
|
|
46
46
|
return t.attributes.group === 'typography';
|
|
47
47
|
}).filter(function (t) {
|
|
48
48
|
return t.cleanName.includes('font.heading') || t.cleanName.includes('font.body');
|
|
49
|
+
})
|
|
50
|
+
// Filtering out UNSAFE tokens that were meant for migrations, these tokens are deprecated and will be removed in the future
|
|
51
|
+
.filter(function (t) {
|
|
52
|
+
return !t.cleanName.includes('UNSAFE');
|
|
49
53
|
}).map(function (currentToken) {
|
|
50
54
|
var _typographyPalette$fi, _typographyPalette$fi2, _typographyPalette$fi3;
|
|
51
55
|
var individualValues = {
|
|
@@ -72,7 +76,7 @@ var typographyValueToToken = exports.typographyValueToToken = _tokensRaw.typogra
|
|
|
72
76
|
};
|
|
73
77
|
});
|
|
74
78
|
function isValidTypographyToken(tokenName) {
|
|
75
|
-
return _tokensRaw.
|
|
79
|
+
return _tokensRaw.typography.filter(function (t) {
|
|
76
80
|
return t.attributes.group === 'typography';
|
|
77
81
|
}).filter(function (t) {
|
|
78
82
|
return t.cleanName.includes('font.heading') || t.cleanName.includes('font.body') || t.cleanName.includes('font.code');
|
|
@@ -81,6 +85,10 @@ function isValidTypographyToken(tokenName) {
|
|
|
81
85
|
});
|
|
82
86
|
}
|
|
83
87
|
function findTypographyTokenForValues(fontSize, lineHeight) {
|
|
88
|
+
// Match 11px to 12px as this is what happened when transitioning from legacy to refreshed typography
|
|
89
|
+
if (fontSize === '11px') {
|
|
90
|
+
fontSize = '12px';
|
|
91
|
+
}
|
|
84
92
|
var matchingTokens = typographyValueToToken.filter(function (token) {
|
|
85
93
|
return token.values.fontSize === fontSize;
|
|
86
94
|
})
|
|
@@ -90,24 +98,29 @@ function findTypographyTokenForValues(fontSize, lineHeight) {
|
|
|
90
98
|
});
|
|
91
99
|
return matchingTokens;
|
|
92
100
|
}
|
|
93
|
-
var fontWeightTokens = exports.fontWeightTokens = _tokensRaw.
|
|
101
|
+
var fontWeightTokens = exports.fontWeightTokens = _tokensRaw.typography.filter(function (token) {
|
|
94
102
|
return token.attributes.group === 'fontWeight';
|
|
95
103
|
}).map(function (token) {
|
|
96
104
|
return {
|
|
97
105
|
tokenName: token.cleanName,
|
|
98
106
|
tokenValue: token.value,
|
|
99
|
-
values: {
|
|
107
|
+
values: {
|
|
108
|
+
fontWeight: token.value
|
|
109
|
+
}
|
|
100
110
|
};
|
|
101
111
|
});
|
|
102
112
|
function findFontWeightTokenForValue(fontWeight) {
|
|
113
|
+
var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : fontWeightTokens;
|
|
103
114
|
if (fontWeight === 'normal') {
|
|
104
115
|
fontWeight = '400';
|
|
105
116
|
}
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
|
|
118
|
+
// Match bold and 700 to 653 to match with bold weight refreshed typography
|
|
119
|
+
if (fontWeight === 'bold' || fontWeight === '700') {
|
|
120
|
+
fontWeight = '653';
|
|
108
121
|
}
|
|
109
|
-
return
|
|
110
|
-
return token.
|
|
122
|
+
return tokens.find(function (token) {
|
|
123
|
+
return token.values.fontWeight === fontWeight;
|
|
111
124
|
});
|
|
112
125
|
}
|
|
113
126
|
var fontWeightMap = exports.fontWeightMap = {
|
|
@@ -117,7 +130,7 @@ var fontWeightMap = exports.fontWeightMap = {
|
|
|
117
130
|
bold: '700'
|
|
118
131
|
};
|
|
119
132
|
var defaultFontWeight = exports.defaultFontWeight = fontWeightMap.regular;
|
|
120
|
-
var fontFamilyTokens = exports.fontFamilyTokens = _tokensRaw.
|
|
133
|
+
var fontFamilyTokens = exports.fontFamilyTokens = _tokensRaw.typography.filter(function (token) {
|
|
121
134
|
return token.attributes.group === 'fontFamily';
|
|
122
135
|
});
|
|
123
136
|
function findFontFamilyValueForToken(tokenName) {
|
|
@@ -5,6 +5,14 @@ import { importNameWithCustomMessageId, pathWithCustomMessageId } from './consta
|
|
|
5
5
|
import { getDeprecationIconHandler } from './handlers/icon';
|
|
6
6
|
export const createChecks = context => {
|
|
7
7
|
const deprecatedIconHandler = getDeprecationIconHandler(context);
|
|
8
|
+
const cachedConfig = (_context$options$ => {
|
|
9
|
+
const config = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('imports');
|
|
10
|
+
if (!isDeprecatedImportConfig(config)) {
|
|
11
|
+
throw new Error('Config is invalid for deprecated imports');
|
|
12
|
+
}
|
|
13
|
+
return config;
|
|
14
|
+
})();
|
|
15
|
+
const deprecatedImportSources = new Set(Object.keys(cachedConfig));
|
|
8
16
|
const throwErrors = () => {
|
|
9
17
|
deprecatedIconHandler.throwErrors();
|
|
10
18
|
};
|
|
@@ -29,16 +37,10 @@ export const createChecks = context => {
|
|
|
29
37
|
node,
|
|
30
38
|
importNames
|
|
31
39
|
}) {
|
|
32
|
-
|
|
33
|
-
const restrictedPathMessages =
|
|
34
|
-
// TODO: JFP-2823 - this type cast was added due to Jira's ESLint v9 migration
|
|
35
|
-
((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('imports');
|
|
36
|
-
if (!isDeprecatedImportConfig(restrictedPathMessages)) {
|
|
37
|
-
throw new Error('Config is invalid for deprecated imports');
|
|
38
|
-
}
|
|
39
|
-
if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
|
|
40
|
+
if (!deprecatedImportSources.has(importSource)) {
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
43
|
+
const restrictedPathMessages = cachedConfig;
|
|
42
44
|
const config = restrictedPathMessages[importSource];
|
|
43
45
|
const handler = getHandler(importSource);
|
|
44
46
|
if (handler) {
|
|
@@ -13,6 +13,7 @@ export const getDeprecationIconHandler = context => {
|
|
|
13
13
|
const identifiers = new Map();
|
|
14
14
|
const importErrors = {};
|
|
15
15
|
const exportErrors = {};
|
|
16
|
+
const iconNameToImportSource = new Map();
|
|
16
17
|
const getConfigFlag = (key, defaultValue) => {
|
|
17
18
|
if (context.options && context.options.length > 0 && context.options[0] && context.options[0].hasOwnProperty(key)) {
|
|
18
19
|
return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
|
|
@@ -28,6 +29,7 @@ export const getDeprecationIconHandler = context => {
|
|
|
28
29
|
config
|
|
29
30
|
}) => {
|
|
30
31
|
if (config.message) {
|
|
32
|
+
var _node$specifiers$, _node$specifiers$$loc;
|
|
31
33
|
const myError = {
|
|
32
34
|
node,
|
|
33
35
|
messageId: pathWithCustomMessageId,
|
|
@@ -38,6 +40,10 @@ export const getDeprecationIconHandler = context => {
|
|
|
38
40
|
}
|
|
39
41
|
};
|
|
40
42
|
importErrors[node.source.value] = myError;
|
|
43
|
+
const importIconName = (_node$specifiers$ = node.specifiers[0]) === null || _node$specifiers$ === void 0 ? void 0 : (_node$specifiers$$loc = _node$specifiers$.local) === null || _node$specifiers$$loc === void 0 ? void 0 : _node$specifiers$$loc.name;
|
|
44
|
+
if (importIconName) {
|
|
45
|
+
iconNameToImportSource.set(importIconName, importSource);
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
};
|
|
43
49
|
const createExportError = ({
|
|
@@ -121,17 +127,14 @@ export const getDeprecationIconHandler = context => {
|
|
|
121
127
|
if (!('openingElement' in node) || !isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
122
128
|
return;
|
|
123
129
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
jsxElements.set(importSource, [node]);
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
130
|
+
const iconName = node.openingElement.name.name;
|
|
131
|
+
const importSource = iconNameToImportSource.get(iconName);
|
|
132
|
+
if (importSource) {
|
|
133
|
+
if (jsxElements.has(importSource)) {
|
|
134
|
+
var _jsxElements$get;
|
|
135
|
+
(_jsxElements$get = jsxElements.get(importSource)) === null || _jsxElements$get === void 0 ? void 0 : _jsxElements$get.push(node);
|
|
136
|
+
} else {
|
|
137
|
+
jsxElements.set(importSource, [node]);
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
};
|
|
@@ -139,17 +142,14 @@ export const getDeprecationIconHandler = context => {
|
|
|
139
142
|
if (node.type !== 'Identifier' || node.parent.type !== 'JSXExpressionContainer') {
|
|
140
143
|
return;
|
|
141
144
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
identifiers.set(importSource, [node]);
|
|
151
|
-
}
|
|
152
|
-
break;
|
|
145
|
+
const iconName = node.name;
|
|
146
|
+
const importSource = iconNameToImportSource.get(iconName);
|
|
147
|
+
if (importSource) {
|
|
148
|
+
if (identifiers.has(importSource)) {
|
|
149
|
+
var _identifiers$get;
|
|
150
|
+
(_identifiers$get = identifiers.get(importSource)) === null || _identifiers$get === void 0 ? void 0 : _identifiers$get.push(node);
|
|
151
|
+
} else {
|
|
152
|
+
identifiers.set(importSource, [node]);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
};
|
|
@@ -4,7 +4,8 @@ import { createLintRule } from '../utils/create-rule';
|
|
|
4
4
|
const TEXTFIELD_PACKAGE = '@atlaskit/textfield';
|
|
5
5
|
const TEXTAREA_PACKAGE = '@atlaskit/textarea';
|
|
6
6
|
const FORM_PACKAGE = '@atlaskit/form';
|
|
7
|
-
export const
|
|
7
|
+
export const messageInsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea inside a Form, use `CharacterCounterField` from `@atlaskit/form` instead of Field and remove the props from the Textfield/Textarea. This ensures accessibility through real time feedback and aligns with the design system. Read more about [character counter fields](https://atlassian.design/components/form/examples#charactercounterfield)';
|
|
8
|
+
export const messageOutsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea, use `CharacterCounter` from `@atlaskit/form` alongside your input for real-time character count feedback. This ensures accessibility through screen reader announcements and visual feedback. Read more about [standalone character counter](https://atlassian.design/components/form/examples#standalone-charactercounter)';
|
|
8
9
|
export const ruleName = __dirname.split('/').slice(-1)[0];
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -52,12 +53,13 @@ const rule = createLintRule({
|
|
|
52
53
|
name: ruleName,
|
|
53
54
|
type: 'suggestion',
|
|
54
55
|
docs: {
|
|
55
|
-
description: 'Suggests using CharacterCounterField when Textfield or Textarea components have maxLength or minLength props
|
|
56
|
+
description: 'Suggests using CharacterCounterField or CharacterCounter when Textfield or Textarea components have maxLength or minLength props.',
|
|
56
57
|
recommended: true,
|
|
57
58
|
severity: 'warn'
|
|
58
59
|
},
|
|
59
60
|
messages: {
|
|
60
|
-
useCharacterCounterField:
|
|
61
|
+
useCharacterCounterField: messageInsideForm,
|
|
62
|
+
useCharacterCounter: messageOutsideForm
|
|
61
63
|
}
|
|
62
64
|
},
|
|
63
65
|
create(context) {
|
|
@@ -116,12 +118,17 @@ const rule = createLintRule({
|
|
|
116
118
|
const hasMaxLength = JSXElementHelper.getAttributeByName(node, 'maxLength');
|
|
117
119
|
const hasMinLength = JSXElementHelper.getAttributeByName(node, 'minLength');
|
|
118
120
|
if (hasMaxLength || hasMinLength) {
|
|
119
|
-
//
|
|
121
|
+
// Use different messages based on whether inside Form context or not
|
|
120
122
|
if (isInsideFormOrField(node, formComponentNames)) {
|
|
121
123
|
context.report({
|
|
122
124
|
node,
|
|
123
125
|
messageId: 'useCharacterCounterField'
|
|
124
126
|
});
|
|
127
|
+
} else {
|
|
128
|
+
context.report({
|
|
129
|
+
node,
|
|
130
|
+
messageId: 'useCharacterCounter'
|
|
131
|
+
});
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
}
|
|
@@ -91,10 +91,10 @@ export const StyleObject = {
|
|
|
91
91
|
matchingTokens = findTypographyTokenForValues(fontSizeValue, lineHeightValue);
|
|
92
92
|
if (matchingTokens.length) {
|
|
93
93
|
// If we have multiple matching tokens, try matching fontWeight
|
|
94
|
-
let
|
|
95
|
-
if (
|
|
94
|
+
let matchingTokenWithWeight = findFontWeightTokenForValue(fontWeightValue, matchingTokens);
|
|
95
|
+
if (matchingTokenWithWeight) {
|
|
96
96
|
// Possibly narrowed down tokens
|
|
97
|
-
matchingTokens =
|
|
97
|
+
matchingTokens = [matchingTokenWithWeight];
|
|
98
98
|
} else {
|
|
99
99
|
// Ended up with 0 matches by matching fontWeight
|
|
100
100
|
// return body token and add fontWeight manually
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { callExpression, identifier, isNodeOfType, literal, memberExpression, property } from 'eslint-codemod-utils';
|
|
2
2
|
import { typographyPalette } from '@atlaskit/tokens/palettes-raw';
|
|
3
|
-
import {
|
|
3
|
+
import { typography as typographyTokens } from '@atlaskit/tokens/tokens-raw';
|
|
4
4
|
import { Import, Root } from '../../ast-nodes';
|
|
5
5
|
export const typographyProperties = ['fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
|
|
6
6
|
export const isTypographyProperty = propertyName => {
|
|
@@ -12,7 +12,9 @@ export const isFontFamily = node => isNodeOfType(node, 'CallExpression') && isNo
|
|
|
12
12
|
export const isCodeFontFamily = node => isNodeOfType(node, 'CallExpression') && isNodeOfType(node.callee, 'Identifier') && (node.callee.name === 'codeFontFamily' || node.callee.name === 'getCodeFontFamily');
|
|
13
13
|
export const typographyValueToToken = typographyTokens
|
|
14
14
|
// we're filtering here to remove the `font` tokens.
|
|
15
|
-
.filter(t => t.attributes.group === 'typography').filter(t => t.cleanName.includes('font.heading') || t.cleanName.includes('font.body'))
|
|
15
|
+
.filter(t => t.attributes.group === 'typography').filter(t => t.cleanName.includes('font.heading') || t.cleanName.includes('font.body'))
|
|
16
|
+
// Filtering out UNSAFE tokens that were meant for migrations, these tokens are deprecated and will be removed in the future
|
|
17
|
+
.filter(t => !t.cleanName.includes('UNSAFE')).map(currentToken => {
|
|
16
18
|
var _typographyPalette$fi, _typographyPalette$fi2, _typographyPalette$fi3;
|
|
17
19
|
const individualValues = {
|
|
18
20
|
fontSize: (_typographyPalette$fi = typographyPalette.find(baseToken => baseToken.path.slice(-1)[0] ===
|
|
@@ -35,6 +37,10 @@ export function isValidTypographyToken(tokenName) {
|
|
|
35
37
|
return typographyTokens.filter(t => t.attributes.group === 'typography').filter(t => t.cleanName.includes('font.heading') || t.cleanName.includes('font.body') || t.cleanName.includes('font.code')).find(t => t.cleanName === tokenName);
|
|
36
38
|
}
|
|
37
39
|
export function findTypographyTokenForValues(fontSize, lineHeight) {
|
|
40
|
+
// Match 11px to 12px as this is what happened when transitioning from legacy to refreshed typography
|
|
41
|
+
if (fontSize === '11px') {
|
|
42
|
+
fontSize = '12px';
|
|
43
|
+
}
|
|
38
44
|
let matchingTokens = typographyValueToToken.filter(token => token.values.fontSize === fontSize)
|
|
39
45
|
// If lineHeight == 1, we don't match to a token
|
|
40
46
|
.filter(() => lineHeight === '1' ? false : true);
|
|
@@ -44,17 +50,21 @@ export const fontWeightTokens = typographyTokens.filter(token => token.attribute
|
|
|
44
50
|
return {
|
|
45
51
|
tokenName: token.cleanName,
|
|
46
52
|
tokenValue: token.value,
|
|
47
|
-
values: {
|
|
53
|
+
values: {
|
|
54
|
+
fontWeight: token.value
|
|
55
|
+
}
|
|
48
56
|
};
|
|
49
57
|
});
|
|
50
|
-
export function findFontWeightTokenForValue(fontWeight) {
|
|
58
|
+
export function findFontWeightTokenForValue(fontWeight, tokens = fontWeightTokens) {
|
|
51
59
|
if (fontWeight === 'normal') {
|
|
52
60
|
fontWeight = '400';
|
|
53
61
|
}
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
|
|
63
|
+
// Match bold and 700 to 653 to match with bold weight refreshed typography
|
|
64
|
+
if (fontWeight === 'bold' || fontWeight === '700') {
|
|
65
|
+
fontWeight = '653';
|
|
56
66
|
}
|
|
57
|
-
return
|
|
67
|
+
return tokens.find(token => token.values.fontWeight === fontWeight);
|
|
58
68
|
}
|
|
59
69
|
export const fontWeightMap = {
|
|
60
70
|
regular: '400',
|
|
@@ -8,6 +8,14 @@ import { importNameWithCustomMessageId, pathWithCustomMessageId } from './consta
|
|
|
8
8
|
import { getDeprecationIconHandler } from './handlers/icon';
|
|
9
9
|
export var createChecks = function createChecks(context) {
|
|
10
10
|
var deprecatedIconHandler = getDeprecationIconHandler(context);
|
|
11
|
+
var cachedConfig = function (_context$options$) {
|
|
12
|
+
var config = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('imports');
|
|
13
|
+
if (!isDeprecatedImportConfig(config)) {
|
|
14
|
+
throw new Error('Config is invalid for deprecated imports');
|
|
15
|
+
}
|
|
16
|
+
return config;
|
|
17
|
+
}();
|
|
18
|
+
var deprecatedImportSources = new Set(Object.keys(cachedConfig));
|
|
11
19
|
var throwErrors = function throwErrors() {
|
|
12
20
|
deprecatedIconHandler.throwErrors();
|
|
13
21
|
};
|
|
@@ -27,20 +35,14 @@ export var createChecks = function createChecks(context) {
|
|
|
27
35
|
* @private
|
|
28
36
|
*/
|
|
29
37
|
function checkRestrictedPathAndReport(_ref) {
|
|
30
|
-
var _context$options$;
|
|
31
38
|
var importSource = _ref.importSource,
|
|
32
39
|
type = _ref.type,
|
|
33
40
|
node = _ref.node,
|
|
34
41
|
importNames = _ref.importNames;
|
|
35
|
-
|
|
36
|
-
// TODO: JFP-2823 - this type cast was added due to Jira's ESLint v9 migration
|
|
37
|
-
((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('imports');
|
|
38
|
-
if (!isDeprecatedImportConfig(restrictedPathMessages)) {
|
|
39
|
-
throw new Error('Config is invalid for deprecated imports');
|
|
40
|
-
}
|
|
41
|
-
if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
|
|
42
|
+
if (!deprecatedImportSources.has(importSource)) {
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
45
|
+
var restrictedPathMessages = cachedConfig;
|
|
44
46
|
var config = restrictedPathMessages[importSource];
|
|
45
47
|
var handler = getHandler(importSource);
|
|
46
48
|
if (handler) {
|
|
@@ -17,6 +17,7 @@ export var getDeprecationIconHandler = function getDeprecationIconHandler(contex
|
|
|
17
17
|
var identifiers = new Map();
|
|
18
18
|
var importErrors = {};
|
|
19
19
|
var exportErrors = {};
|
|
20
|
+
var iconNameToImportSource = new Map();
|
|
20
21
|
var getConfigFlag = function getConfigFlag(key, defaultValue) {
|
|
21
22
|
if (context.options && context.options.length > 0 && context.options[0] && context.options[0].hasOwnProperty(key)) {
|
|
22
23
|
return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
|
|
@@ -33,6 +34,7 @@ export var getDeprecationIconHandler = function getDeprecationIconHandler(contex
|
|
|
33
34
|
importSource = _ref.importSource,
|
|
34
35
|
config = _ref.config;
|
|
35
36
|
if (config.message) {
|
|
37
|
+
var _node$specifiers$;
|
|
36
38
|
var myError = {
|
|
37
39
|
node: node,
|
|
38
40
|
messageId: pathWithCustomMessageId,
|
|
@@ -43,6 +45,10 @@ export var getDeprecationIconHandler = function getDeprecationIconHandler(contex
|
|
|
43
45
|
}
|
|
44
46
|
};
|
|
45
47
|
importErrors[node.source.value] = myError;
|
|
48
|
+
var importIconName = (_node$specifiers$ = node.specifiers[0]) === null || _node$specifiers$ === void 0 || (_node$specifiers$ = _node$specifiers$.local) === null || _node$specifiers$ === void 0 ? void 0 : _node$specifiers$.name;
|
|
49
|
+
if (importIconName) {
|
|
50
|
+
iconNameToImportSource.set(importIconName, importSource);
|
|
51
|
+
}
|
|
46
52
|
}
|
|
47
53
|
};
|
|
48
54
|
var createExportError = function createExportError(_ref2) {
|
|
@@ -159,20 +165,14 @@ export var getDeprecationIconHandler = function getDeprecationIconHandler(contex
|
|
|
159
165
|
if (!('openingElement' in node) || !isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
|
|
160
166
|
return;
|
|
161
167
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
var _jsxElements$get;
|
|
171
|
-
(_jsxElements$get = jsxElements.get(importSource)) === null || _jsxElements$get === void 0 || _jsxElements$get.push(node);
|
|
172
|
-
} else {
|
|
173
|
-
jsxElements.set(importSource, [node]);
|
|
174
|
-
}
|
|
175
|
-
break;
|
|
168
|
+
var iconName = node.openingElement.name.name;
|
|
169
|
+
var importSource = iconNameToImportSource.get(iconName);
|
|
170
|
+
if (importSource) {
|
|
171
|
+
if (jsxElements.has(importSource)) {
|
|
172
|
+
var _jsxElements$get;
|
|
173
|
+
(_jsxElements$get = jsxElements.get(importSource)) === null || _jsxElements$get === void 0 || _jsxElements$get.push(node);
|
|
174
|
+
} else {
|
|
175
|
+
jsxElements.set(importSource, [node]);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
};
|
|
@@ -180,20 +180,14 @@ export var getDeprecationIconHandler = function getDeprecationIconHandler(contex
|
|
|
180
180
|
if (node.type !== 'Identifier' || node.parent.type !== 'JSXExpressionContainer') {
|
|
181
181
|
return;
|
|
182
182
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
var _identifiers$get;
|
|
192
|
-
(_identifiers$get = identifiers.get(importSource)) === null || _identifiers$get === void 0 || _identifiers$get.push(node);
|
|
193
|
-
} else {
|
|
194
|
-
identifiers.set(importSource, [node]);
|
|
195
|
-
}
|
|
196
|
-
break;
|
|
183
|
+
var iconName = node.name;
|
|
184
|
+
var importSource = iconNameToImportSource.get(iconName);
|
|
185
|
+
if (importSource) {
|
|
186
|
+
if (identifiers.has(importSource)) {
|
|
187
|
+
var _identifiers$get;
|
|
188
|
+
(_identifiers$get = identifiers.get(importSource)) === null || _identifiers$get === void 0 || _identifiers$get.push(node);
|
|
189
|
+
} else {
|
|
190
|
+
identifiers.set(importSource, [node]);
|
|
197
191
|
}
|
|
198
192
|
}
|
|
199
193
|
};
|
|
@@ -4,7 +4,8 @@ import { createLintRule } from '../utils/create-rule';
|
|
|
4
4
|
var TEXTFIELD_PACKAGE = '@atlaskit/textfield';
|
|
5
5
|
var TEXTAREA_PACKAGE = '@atlaskit/textarea';
|
|
6
6
|
var FORM_PACKAGE = '@atlaskit/form';
|
|
7
|
-
export var
|
|
7
|
+
export var messageInsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea inside a Form, use `CharacterCounterField` from `@atlaskit/form` instead of Field and remove the props from the Textfield/Textarea. This ensures accessibility through real time feedback and aligns with the design system. Read more about [character counter fields](https://atlassian.design/components/form/examples#charactercounterfield)';
|
|
8
|
+
export var messageOutsideForm = 'When using `maxLength` or `minLength` props with Textfield/Textarea, use `CharacterCounter` from `@atlaskit/form` alongside your input for real-time character count feedback. This ensures accessibility through screen reader announcements and visual feedback. Read more about [standalone character counter](https://atlassian.design/components/form/examples#standalone-charactercounter)';
|
|
8
9
|
export var ruleName = __dirname.split('/').slice(-1)[0];
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -52,12 +53,13 @@ var rule = createLintRule({
|
|
|
52
53
|
name: ruleName,
|
|
53
54
|
type: 'suggestion',
|
|
54
55
|
docs: {
|
|
55
|
-
description: 'Suggests using CharacterCounterField when Textfield or Textarea components have maxLength or minLength props
|
|
56
|
+
description: 'Suggests using CharacterCounterField or CharacterCounter when Textfield or Textarea components have maxLength or minLength props.',
|
|
56
57
|
recommended: true,
|
|
57
58
|
severity: 'warn'
|
|
58
59
|
},
|
|
59
60
|
messages: {
|
|
60
|
-
useCharacterCounterField:
|
|
61
|
+
useCharacterCounterField: messageInsideForm,
|
|
62
|
+
useCharacterCounter: messageOutsideForm
|
|
61
63
|
}
|
|
62
64
|
},
|
|
63
65
|
create: function create(context) {
|
|
@@ -118,12 +120,17 @@ var rule = createLintRule({
|
|
|
118
120
|
var hasMaxLength = JSXElementHelper.getAttributeByName(node, 'maxLength');
|
|
119
121
|
var hasMinLength = JSXElementHelper.getAttributeByName(node, 'minLength');
|
|
120
122
|
if (hasMaxLength || hasMinLength) {
|
|
121
|
-
//
|
|
123
|
+
// Use different messages based on whether inside Form context or not
|
|
122
124
|
if (isInsideFormOrField(node, formComponentNames)) {
|
|
123
125
|
context.report({
|
|
124
126
|
node: node,
|
|
125
127
|
messageId: 'useCharacterCounterField'
|
|
126
128
|
});
|
|
129
|
+
} else {
|
|
130
|
+
context.report({
|
|
131
|
+
node: node,
|
|
132
|
+
messageId: 'useCharacterCounter'
|
|
133
|
+
});
|
|
127
134
|
}
|
|
128
135
|
}
|
|
129
136
|
}
|
|
@@ -90,12 +90,10 @@ export var StyleObject = {
|
|
|
90
90
|
matchingTokens = findTypographyTokenForValues(fontSizeValue, lineHeightValue);
|
|
91
91
|
if (matchingTokens.length) {
|
|
92
92
|
// If we have multiple matching tokens, try matching fontWeight
|
|
93
|
-
var
|
|
94
|
-
|
|
95
|
-
});
|
|
96
|
-
if (matchingTokensWithWeight.length) {
|
|
93
|
+
var matchingTokenWithWeight = findFontWeightTokenForValue(fontWeightValue, matchingTokens);
|
|
94
|
+
if (matchingTokenWithWeight) {
|
|
97
95
|
// Possibly narrowed down tokens
|
|
98
|
-
matchingTokens =
|
|
96
|
+
matchingTokens = [matchingTokenWithWeight];
|
|
99
97
|
} else {
|
|
100
98
|
// Ended up with 0 matches by matching fontWeight
|
|
101
99
|
// return body token and add fontWeight manually
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { callExpression, identifier, isNodeOfType, literal, memberExpression, property } from 'eslint-codemod-utils';
|
|
2
2
|
import { typographyPalette } from '@atlaskit/tokens/palettes-raw';
|
|
3
|
-
import {
|
|
3
|
+
import { typography as typographyTokens } from '@atlaskit/tokens/tokens-raw';
|
|
4
4
|
import { Import, Root } from '../../ast-nodes';
|
|
5
5
|
export var typographyProperties = ['fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
|
|
6
6
|
export var isTypographyProperty = function isTypographyProperty(propertyName) {
|
|
@@ -24,6 +24,10 @@ export var typographyValueToToken = typographyTokens
|
|
|
24
24
|
return t.attributes.group === 'typography';
|
|
25
25
|
}).filter(function (t) {
|
|
26
26
|
return t.cleanName.includes('font.heading') || t.cleanName.includes('font.body');
|
|
27
|
+
})
|
|
28
|
+
// Filtering out UNSAFE tokens that were meant for migrations, these tokens are deprecated and will be removed in the future
|
|
29
|
+
.filter(function (t) {
|
|
30
|
+
return !t.cleanName.includes('UNSAFE');
|
|
27
31
|
}).map(function (currentToken) {
|
|
28
32
|
var _typographyPalette$fi, _typographyPalette$fi2, _typographyPalette$fi3;
|
|
29
33
|
var individualValues = {
|
|
@@ -59,6 +63,10 @@ export function isValidTypographyToken(tokenName) {
|
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
65
|
export function findTypographyTokenForValues(fontSize, lineHeight) {
|
|
66
|
+
// Match 11px to 12px as this is what happened when transitioning from legacy to refreshed typography
|
|
67
|
+
if (fontSize === '11px') {
|
|
68
|
+
fontSize = '12px';
|
|
69
|
+
}
|
|
62
70
|
var matchingTokens = typographyValueToToken.filter(function (token) {
|
|
63
71
|
return token.values.fontSize === fontSize;
|
|
64
72
|
})
|
|
@@ -74,18 +82,23 @@ export var fontWeightTokens = typographyTokens.filter(function (token) {
|
|
|
74
82
|
return {
|
|
75
83
|
tokenName: token.cleanName,
|
|
76
84
|
tokenValue: token.value,
|
|
77
|
-
values: {
|
|
85
|
+
values: {
|
|
86
|
+
fontWeight: token.value
|
|
87
|
+
}
|
|
78
88
|
};
|
|
79
89
|
});
|
|
80
90
|
export function findFontWeightTokenForValue(fontWeight) {
|
|
91
|
+
var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : fontWeightTokens;
|
|
81
92
|
if (fontWeight === 'normal') {
|
|
82
93
|
fontWeight = '400';
|
|
83
94
|
}
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
|
|
96
|
+
// Match bold and 700 to 653 to match with bold weight refreshed typography
|
|
97
|
+
if (fontWeight === 'bold' || fontWeight === '700') {
|
|
98
|
+
fontWeight = '653';
|
|
86
99
|
}
|
|
87
|
-
return
|
|
88
|
-
return token.
|
|
100
|
+
return tokens.find(function (token) {
|
|
101
|
+
return token.values.fontWeight === fontWeight;
|
|
89
102
|
});
|
|
90
103
|
}
|
|
91
104
|
export var fontWeightMap = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const messageInsideForm = "When using `maxLength` or `minLength` props with Textfield/Textarea inside a Form, use `CharacterCounterField` from `@atlaskit/form` instead of Field and remove the props from the Textfield/Textarea. This ensures accessibility through real time feedback and aligns with the design system. Read more about [character counter fields](https://atlassian.design/components/form/examples#charactercounterfield)";
|
|
3
|
+
export declare const messageOutsideForm = "When using `maxLength` or `minLength` props with Textfield/Textarea, use `CharacterCounter` from `@atlaskit/form` alongside your input for real-time character count feedback. This ensures accessibility through screen reader announcements and visual feedback. Read more about [standalone character counter](https://atlassian.design/components/form/examples#standalone-charactercounter)";
|
|
3
4
|
export declare const ruleName: string;
|
|
4
5
|
declare const rule: Rule.RuleModule;
|
|
5
6
|
export default rule;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
2
|
import { type CallExpression, type Directive, type EslintNode, type ImportDeclaration, type ModuleDeclaration, type Property, type Statement, type StringableASTNode } from 'eslint-codemod-utils';
|
|
3
|
-
import {
|
|
3
|
+
import { typography as typographyTokens } from '@atlaskit/tokens/tokens-raw';
|
|
4
4
|
export declare const typographyProperties: string[];
|
|
5
5
|
export declare const isTypographyProperty: (propertyName: string) => boolean;
|
|
6
6
|
export declare const isFontSize: (node: EslintNode) => node is CallExpression;
|
|
@@ -52,16 +52,8 @@ export declare function isValidTypographyToken(tokenName: string): {
|
|
|
52
52
|
cleanName: string;
|
|
53
53
|
} | undefined;
|
|
54
54
|
export declare function findTypographyTokenForValues(fontSize: string, lineHeight?: string): TokenValueMap[];
|
|
55
|
-
export declare const fontWeightTokens:
|
|
56
|
-
|
|
57
|
-
tokenValue: string;
|
|
58
|
-
values: {};
|
|
59
|
-
}[];
|
|
60
|
-
export declare function findFontWeightTokenForValue(fontWeight: string): {
|
|
61
|
-
tokenName: string;
|
|
62
|
-
tokenValue: string;
|
|
63
|
-
values: {};
|
|
64
|
-
} | undefined;
|
|
55
|
+
export declare const fontWeightTokens: TokenValueMap[];
|
|
56
|
+
export declare function findFontWeightTokenForValue(fontWeight: string, tokens?: TokenValueMap[]): TokenValueMap | undefined;
|
|
65
57
|
export declare const fontWeightMap: FontWeightMap;
|
|
66
58
|
export type FontWeightMap = {
|
|
67
59
|
regular: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const messageInsideForm = "When using `maxLength` or `minLength` props with Textfield/Textarea inside a Form, use `CharacterCounterField` from `@atlaskit/form` instead of Field and remove the props from the Textfield/Textarea. This ensures accessibility through real time feedback and aligns with the design system. Read more about [character counter fields](https://atlassian.design/components/form/examples#charactercounterfield)";
|
|
3
|
+
export declare const messageOutsideForm = "When using `maxLength` or `minLength` props with Textfield/Textarea, use `CharacterCounter` from `@atlaskit/form` alongside your input for real-time character count feedback. This ensures accessibility through screen reader announcements and visual feedback. Read more about [standalone character counter](https://atlassian.design/components/form/examples#standalone-charactercounter)";
|
|
3
4
|
export declare const ruleName: string;
|
|
4
5
|
declare const rule: Rule.RuleModule;
|
|
5
6
|
export default rule;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
2
|
import { type CallExpression, type Directive, type EslintNode, type ImportDeclaration, type ModuleDeclaration, type Property, type Statement, type StringableASTNode } from 'eslint-codemod-utils';
|
|
3
|
-
import {
|
|
3
|
+
import { typography as typographyTokens } from '@atlaskit/tokens/tokens-raw';
|
|
4
4
|
export declare const typographyProperties: string[];
|
|
5
5
|
export declare const isTypographyProperty: (propertyName: string) => boolean;
|
|
6
6
|
export declare const isFontSize: (node: EslintNode) => node is CallExpression;
|
|
@@ -52,16 +52,8 @@ export declare function isValidTypographyToken(tokenName: string): {
|
|
|
52
52
|
cleanName: string;
|
|
53
53
|
} | undefined;
|
|
54
54
|
export declare function findTypographyTokenForValues(fontSize: string, lineHeight?: string): TokenValueMap[];
|
|
55
|
-
export declare const fontWeightTokens:
|
|
56
|
-
|
|
57
|
-
tokenValue: string;
|
|
58
|
-
values: {};
|
|
59
|
-
}[];
|
|
60
|
-
export declare function findFontWeightTokenForValue(fontWeight: string): {
|
|
61
|
-
tokenName: string;
|
|
62
|
-
tokenValue: string;
|
|
63
|
-
values: {};
|
|
64
|
-
} | undefined;
|
|
55
|
+
export declare const fontWeightTokens: TokenValueMap[];
|
|
56
|
+
export declare function findFontWeightTokenForValue(fontWeight: string, tokens?: TokenValueMap[]): TokenValueMap | undefined;
|
|
65
57
|
export declare const fontWeightMap: FontWeightMap;
|
|
66
58
|
export type FontWeightMap = {
|
|
67
59
|
regular: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-design-system",
|
|
3
3
|
"description": "The essential plugin for use with the Atlassian Design System.",
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.30.0",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"publishConfig": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@atlaskit/eslint-utils": "^2.0.0",
|
|
42
42
|
"@atlaskit/icon": "^29.3.0",
|
|
43
43
|
"@atlaskit/icon-lab": "^5.13.0",
|
|
44
|
-
"@atlaskit/tokens": "^9.
|
|
44
|
+
"@atlaskit/tokens": "^9.1.0",
|
|
45
45
|
"@babel/runtime": "^7.0.0",
|
|
46
46
|
"@typescript-eslint/utils": "^7.1.0",
|
|
47
47
|
"ajv": "^6.12.6",
|