@atlaskit/eslint-plugin-design-system 9.0.0 → 9.2.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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 9.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#84330](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/84330) [`391be0d8e414`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/391be0d8e414) - - `prefer-primitives`: This rule is now deprecated. Please use `use-primitives` instead.
8
+ - `ensure-design-token-usage/preview`: This rule is now deprecated. Please use `use-tokens-space` instead.
9
+
10
+ ## 9.1.0
11
+
12
+ ### Minor Changes
13
+
14
+ - [#84334](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/84334) [`b2134858ba58`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/b2134858ba58) - The `use-tokens-typography` rule now applies token fallbacks that reference the constants exported via `@atlaskit/theme/typography`, rather than applying the fallback string inline.
15
+
3
16
  ## 9.0.0
4
17
 
5
18
  ### Major Changes
@@ -6,25 +6,31 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.default = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _ensureDesignTokenUsage = require("../ensure-design-token-usage");
10
9
  var _ruleMeta = _interopRequireDefault(require("../ensure-design-token-usage/rule-meta"));
11
10
  var _createRule = require("../utils/create-rule");
12
11
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
13
12
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
14
- var defaultConfig = {
15
- domains: ['spacing'],
16
- applyImport: true,
17
- shouldEnforceFallbacks: false
18
- };
19
13
  var rule = (0, _createRule.createLintRule)({
20
14
  meta: _objectSpread(_objectSpread({}, _ruleMeta.default), {}, {
21
15
  name: 'ensure-design-token-usage/preview',
16
+ deprecated: true,
17
+ replacedBy: ['@atlaskit/design-system/use-tokens-space'],
22
18
  docs: _objectSpread(_objectSpread({}, _ruleMeta.default.docs), {}, {
23
19
  description: 'Enforces usage of pre-release design tokens rather than hard-coded values.',
24
20
  recommended: false,
25
21
  severity: 'warn'
26
22
  })
27
23
  }),
28
- create: (0, _ensureDesignTokenUsage.createWithConfig)(defaultConfig)
24
+ create: function create() {
25
+ /**
26
+ * We can't just outright delete the ESLint rule, since:
27
+ * ```
28
+ * // eslint-disable @eslint-plugin/design-system/ensure-design-token-usage/preview
29
+ * ```
30
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
31
+ * we can change the implementation of the rule so that it never reports.
32
+ */
33
+ return {};
34
+ }
29
35
  });
30
36
  var _default = exports.default = rule;
@@ -4,17 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _eslintCodemodUtils = require("eslint-codemod-utils");
8
7
  var _createRule = require("../utils/create-rule");
9
- var _utils = require("./utils");
10
- // eslint-disable-next-line import/no-extraneous-dependencies
11
-
12
8
  var primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
13
9
  var rule = (0, _createRule.createLintRule)({
14
10
  meta: {
15
11
  name: 'prefer-primitives',
16
12
  type: 'suggestion',
17
13
  hasSuggestions: false,
14
+ deprecated: true,
15
+ replacedBy: ['@atlaskit/design-system/use-primitives'],
18
16
  docs: {
19
17
  description: '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.',
20
18
  recommended: false,
@@ -24,84 +22,16 @@ var rule = (0, _createRule.createLintRule)({
24
22
  preferPrimitives: "This \"{{element}}\" may be able to be replaced with a primitive component. See ".concat(primitiveDocsUrl, " for guidance.")
25
23
  }
26
24
  },
27
- create: function create(context) {
28
- return {
29
- // Look for HTML elements - <div>, <span>
30
- // Look for styled calls/templates - styled.div(...), styled.span`...`
31
- JSXOpeningElement: function JSXOpeningElement(node) {
32
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
33
- return;
34
- }
35
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node.name, 'JSXIdentifier')) {
36
- return;
37
- }
38
- var suggest = (0, _utils.shouldSuggest)(node === null || node === void 0 ? void 0 : node.parent);
39
- if (suggest) {
40
- context.report({
41
- node: node,
42
- messageId: 'preferPrimitives',
43
- data: {
44
- element: node.name.name
45
- }
46
- });
47
- }
48
- },
49
- // styled.x`` | styled2.x`` | styled.div()
50
- 'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': function MemberExpressionObjectNameStyledMemberExpressionObjectNameStyled2(node) {
51
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'MemberExpression')) {
52
- return;
53
- }
54
-
55
- // styled.div``
56
- if ((0, _eslintCodemodUtils.isNodeOfType)(node.property, 'Identifier')) {
57
- if (_utils.validPrimitiveElements.has(node.property.name)) {
58
- var styledIdentifier = node.object.name;
59
- var elementName = node.property.name;
60
-
61
- // Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
62
- var reportName = "".concat(styledIdentifier, ".").concat(elementName); // styled.div
63
-
64
- context.report({
65
- node: node,
66
- messageId: 'preferPrimitives',
67
- data: {
68
- element: reportName
69
- }
70
- });
71
- }
72
- }
73
- },
74
- // styled(X)``
75
- 'CallExpression[callee.name="styled"]': function CallExpressionCalleeNameStyled(node) {
76
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'CallExpression')) {
77
- return;
78
- }
79
-
80
- // styled('div')`` - We only care about 'div'/'span', ignore extending other components
81
- if ((0, _eslintCodemodUtils.isNodeOfType)(node.arguments[0], 'Literal')) {
82
- var argValue = node.arguments[0].raw;
83
- if (typeof argValue === 'string') {
84
- var suggest = _utils.validPrimitiveElements.has(argValue.replaceAll("'", '') // argValue will have '' around the element name, strip it out for this test
85
- );
86
- if (suggest) {
87
- var styledIdentifier = node.callee.name;
88
- var elementName = argValue;
89
-
90
- // Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
91
- var reportName = "".concat(styledIdentifier, "(").concat(elementName, ")"); // styled('div')
92
-
93
- context.report({
94
- node: node,
95
- messageId: 'preferPrimitives',
96
- data: {
97
- element: reportName
98
- }
99
- });
100
- }
101
- }
102
- }
103
- }
104
- };
25
+ create: function create() {
26
+ /**
27
+ * We can't just outright delete the ESLint rule, since:
28
+ * ```
29
+ * // eslint-disable @eslint-plugin/design-system/prefer-primitives
30
+ * ```
31
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
32
+ * we can change the implementation of the rule so that it never reports.
33
+ */
34
+ return {};
105
35
  }
106
36
  });
107
37
  var _default = exports.default = rule;
@@ -32,7 +32,9 @@ var StyleObject = exports.StyleObject = {
32
32
  }
33
33
  var fontSizeNode = refs.fontSizeNode,
34
34
  fontSizeRaw = refs.fontSizeRaw,
35
- tokensImportNode = refs.tokensImportNode;
35
+ tokensImportNode = refs.tokensImportNode,
36
+ themeImportNode = refs.themeImportNode,
37
+ shouldAddFallbackImport = refs.shouldAddFallbackImport;
36
38
  var fontSizeValue = (0, _utils.normaliseValue)('fontSize', fontSizeRaw);
37
39
 
38
40
  // -- Font weight --
@@ -123,6 +125,8 @@ var StyleObject = exports.StyleObject = {
123
125
  matchingToken: matchingToken,
124
126
  nodesToReplace: nodesToReplace,
125
127
  tokensImportNode: tokensImportNode,
128
+ themeImportNode: themeImportNode,
129
+ shouldAddFallbackImport: shouldAddFallbackImport,
126
130
  fontWeightReplacement: fontWeightReplacement,
127
131
  fontFamilyReplacement: fontFamilyReplacement,
128
132
  fontStyleReplacement: fontStyleReplacement
@@ -169,20 +173,47 @@ var StyleObject = exports.StyleObject = {
169
173
  success: false
170
174
  };
171
175
  }
172
- var importDeclaration = _astNodes.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
176
+ var tokensImportDeclaration = _astNodes.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
173
177
 
174
178
  // If there is more than one `@atlaskit/tokens` import, then it becomes difficult to determine which import to transform
175
- if (importDeclaration.length > 1) {
179
+ if (tokensImportDeclaration.length > 1) {
176
180
  return {
177
181
  success: false
178
182
  };
179
183
  }
184
+
185
+ // This exists purely because we're not inlining the fallback values
186
+ // and instead referencing a `fontFallback` object that exists in @atlaskit/theme/typography.
187
+ // This is a temporary measure until fallbacks are no longer required
188
+ var shouldAddFallbackImport = 'full';
189
+ var themeImportDeclaration = _astNodes.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/theme/typography');
190
+ if (themeImportDeclaration.length) {
191
+ // Import exists, check if specifier exists
192
+ shouldAddFallbackImport = 'specifier';
193
+ var fallbackImport = themeImportDeclaration[0].specifiers.find(function (specifier) {
194
+ // @atlaskit/theme/typography has no default export so we can safely narrow this type
195
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(specifier, 'ImportSpecifier')) {
196
+ return false;
197
+ }
198
+ if (specifier.imported.name === 'fontFallback') {
199
+ return true;
200
+ }
201
+ return false;
202
+ });
203
+
204
+ // Exact import already exists, no need to add
205
+ if (fallbackImport) {
206
+ shouldAddFallbackImport = false;
207
+ }
208
+ }
180
209
  return {
181
210
  success: true,
182
211
  refs: {
183
212
  fontSizeNode: fontSizeNode,
184
213
  fontSizeRaw: fontSizeRaw,
185
- tokensImportNode: importDeclaration[0]
214
+ tokensImportNode: tokensImportDeclaration[0],
215
+ themeImportNode: themeImportDeclaration[0],
216
+ shouldAddFallbackImport: shouldAddFallbackImport
186
217
  }
187
218
  };
188
219
  },
@@ -191,14 +222,24 @@ var StyleObject = exports.StyleObject = {
191
222
  var matchingToken = refs.matchingToken,
192
223
  nodesToReplace = refs.nodesToReplace,
193
224
  tokensImportNode = refs.tokensImportNode,
225
+ themeImportNode = refs.themeImportNode,
226
+ shouldAddFallbackImport = refs.shouldAddFallbackImport,
194
227
  fontWeightReplacement = refs.fontWeightReplacement,
195
228
  fontFamilyReplacement = refs.fontFamilyReplacement,
196
229
  fontStyleReplacement = refs.fontStyleReplacement;
197
230
  var fontSizeNode = nodesToReplace[0];
198
- return (!tokensImportNode ? [(0, _utils.insertTokensImport)(fixer)] : []).concat(nodesToReplace.map(function (node, index) {
231
+ var root = context.getSourceCode().ast.body;
232
+ var fallbackImport;
233
+ if (shouldAddFallbackImport === 'full') {
234
+ fallbackImport = (0, _utils2.insertFallbackImportFull)(root, fixer);
235
+ } else if (shouldAddFallbackImport === 'specifier') {
236
+ fallbackImport = (0, _utils2.insertFallbackImportSpecifier)(fixer, themeImportNode);
237
+ }
238
+ var fallbackName = (matchingToken.tokenName === 'font.body' ? 'font.body.medium' : matchingToken.tokenName).replace('font', 'fontFallback');
239
+ return (!tokensImportNode ? [(0, _utils2.insertTokensImport)(root, fixer)] : []).concat(fallbackImport ? [fallbackImport] : [], nodesToReplace.map(function (node, index) {
199
240
  // Replace first node with token, delete remaining nodes. Guaranteed to be fontSize
200
241
  if (index === 0) {
201
- return fixer.replaceText(node, "".concat((0, _utils2.getTokenProperty)('font', matchingToken.tokenName, matchingToken.tokenValue)));
242
+ return fixer.replaceText(node, "".concat((0, _utils2.getTokenProperty)('font', matchingToken.tokenName, fallbackName, true)));
202
243
  }
203
244
 
204
245
  // We don't replace fontWeight/fontFamily/fontStyle here in case it occurs before the font property.
@@ -11,6 +11,9 @@ exports.findTypographyTokenForValues = findTypographyTokenForValues;
11
11
  exports.fontWeightTokens = exports.fontWeightMap = exports.fontFamilyTokens = void 0;
12
12
  exports.getLiteralProperty = getLiteralProperty;
13
13
  exports.getTokenProperty = getTokenProperty;
14
+ exports.insertFallbackImportFull = insertFallbackImportFull;
15
+ exports.insertFallbackImportSpecifier = insertFallbackImportSpecifier;
16
+ exports.insertTokensImport = insertTokensImport;
14
17
  exports.isTypographyProperty = exports.isFontSizeSmall = exports.isFontSize = exports.isFontFamily = exports.isCodeFontFamily = void 0;
15
18
  exports.isValidPropertyNode = isValidPropertyNode;
16
19
  exports.notUndefined = notUndefined;
@@ -18,6 +21,7 @@ exports.typographyValueToToken = exports.typographyProperties = void 0;
18
21
  var _eslintCodemodUtils = require("eslint-codemod-utils");
19
22
  var _palettesRaw = require("@atlaskit/tokens/palettes-raw");
20
23
  var _tokensRaw = require("@atlaskit/tokens/tokens-raw");
24
+ var _astNodes = require("../../ast-nodes");
21
25
  var typographyProperties = exports.typographyProperties = ['fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
22
26
  var isTypographyProperty = exports.isTypographyProperty = function isTypographyProperty(propertyName) {
23
27
  return typographyProperties.includes(propertyName);
@@ -115,21 +119,38 @@ function isValidPropertyNode(node) {
115
119
  }
116
120
  return true;
117
121
  }
118
- function getTokenNode(tokenName, tokenValue) {
122
+ function getTokenNode(tokenName, tokenValue, isFallbackMember) {
123
+ var fallback;
124
+ if (isFallbackMember) {
125
+ fallback = createMemberExpressionFromArray(tokenValue.split('.'));
126
+ } else {
127
+ fallback = (0, _eslintCodemodUtils.literal)(tokenValue);
128
+ }
119
129
  return (0, _eslintCodemodUtils.callExpression)({
120
130
  callee: (0, _eslintCodemodUtils.identifier)({
121
131
  name: 'token'
122
132
  }),
123
133
  arguments: [(0, _eslintCodemodUtils.literal)({
124
134
  value: "'".concat(tokenName, "'")
125
- }), (0, _eslintCodemodUtils.literal)(tokenValue)],
135
+ }), fallback],
126
136
  optional: false
127
137
  });
128
138
  }
139
+ function createMemberExpressionFromArray(array) {
140
+ if (array.length === 1) {
141
+ return (0, _eslintCodemodUtils.identifier)(array[0]);
142
+ }
143
+ var property = array.pop();
144
+ return (0, _eslintCodemodUtils.memberExpression)({
145
+ object: createMemberExpressionFromArray(array),
146
+ property: (0, _eslintCodemodUtils.identifier)(property)
147
+ });
148
+ }
129
149
  function getTokenProperty(propertyName, tokenName, tokenFallback) {
150
+ var isFallbackMember = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
130
151
  return (0, _eslintCodemodUtils.property)({
131
152
  key: (0, _eslintCodemodUtils.identifier)(propertyName),
132
- value: getTokenNode(tokenName, tokenFallback)
153
+ value: getTokenNode(tokenName, tokenFallback, isFallbackMember)
133
154
  });
134
155
  }
135
156
  function getLiteralProperty(propertyName, propertyValue) {
@@ -143,4 +164,19 @@ function convertPropertyNodeToStringableNode(node) {
143
164
  key: node.key,
144
165
  value: node.value
145
166
  });
167
+ }
168
+ function insertTokensImport(root, fixer) {
169
+ return _astNodes.Root.insertImport(root, {
170
+ module: '@atlaskit/tokens',
171
+ specifiers: ['token']
172
+ }, fixer);
173
+ }
174
+ function insertFallbackImportFull(root, fixer) {
175
+ return _astNodes.Root.insertImport(root, {
176
+ module: '@atlaskit/theme/typography',
177
+ specifiers: ['fontFallback']
178
+ }, fixer);
179
+ }
180
+ function insertFallbackImportSpecifier(fixer, themeImportNode) {
181
+ return _astNodes.Import.insertNamedSpecifiers(themeImportNode, ['fontFallback'], fixer);
146
182
  }
@@ -1,15 +1,11 @@
1
- import { createWithConfig } from '../ensure-design-token-usage';
2
1
  import ruleMeta from '../ensure-design-token-usage/rule-meta';
3
2
  import { createLintRule } from '../utils/create-rule';
4
- const defaultConfig = {
5
- domains: ['spacing'],
6
- applyImport: true,
7
- shouldEnforceFallbacks: false
8
- };
9
3
  const rule = createLintRule({
10
4
  meta: {
11
5
  ...ruleMeta,
12
6
  name: 'ensure-design-token-usage/preview',
7
+ deprecated: true,
8
+ replacedBy: ['@atlaskit/design-system/use-tokens-space'],
13
9
  docs: {
14
10
  ...ruleMeta.docs,
15
11
  description: 'Enforces usage of pre-release design tokens rather than hard-coded values.',
@@ -17,6 +13,16 @@ const rule = createLintRule({
17
13
  severity: 'warn'
18
14
  }
19
15
  },
20
- create: createWithConfig(defaultConfig)
16
+ create() {
17
+ /**
18
+ * We can't just outright delete the ESLint rule, since:
19
+ * ```
20
+ * // eslint-disable @eslint-plugin/design-system/ensure-design-token-usage/preview
21
+ * ```
22
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
23
+ * we can change the implementation of the rule so that it never reports.
24
+ */
25
+ return {};
26
+ }
21
27
  });
22
28
  export default rule;
@@ -1,14 +1,12 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- import { isNodeOfType } from 'eslint-codemod-utils';
4
1
  import { createLintRule } from '../utils/create-rule';
5
- import { shouldSuggest, validPrimitiveElements } from './utils';
6
2
  const primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
7
3
  const rule = createLintRule({
8
4
  meta: {
9
5
  name: 'prefer-primitives',
10
6
  type: 'suggestion',
11
7
  hasSuggestions: false,
8
+ deprecated: true,
9
+ replacedBy: ['@atlaskit/design-system/use-primitives'],
12
10
  docs: {
13
11
  description: '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.',
14
12
  recommended: false,
@@ -18,85 +16,16 @@ const rule = createLintRule({
18
16
  preferPrimitives: `This "{{element}}" may be able to be replaced with a primitive component. See ${primitiveDocsUrl} for guidance.`
19
17
  }
20
18
  },
21
- create(context) {
22
- return {
23
- // Look for HTML elements - <div>, <span>
24
- // Look for styled calls/templates - styled.div(...), styled.span`...`
25
-
26
- JSXOpeningElement(node) {
27
- if (!isNodeOfType(node, 'JSXOpeningElement')) {
28
- return;
29
- }
30
- if (!isNodeOfType(node.name, 'JSXIdentifier')) {
31
- return;
32
- }
33
- const suggest = shouldSuggest(node === null || node === void 0 ? void 0 : node.parent);
34
- if (suggest) {
35
- context.report({
36
- node: node,
37
- messageId: 'preferPrimitives',
38
- data: {
39
- element: node.name.name
40
- }
41
- });
42
- }
43
- },
44
- // styled.x`` | styled2.x`` | styled.div()
45
- 'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': node => {
46
- if (!isNodeOfType(node, 'MemberExpression')) {
47
- return;
48
- }
49
-
50
- // styled.div``
51
- if (isNodeOfType(node.property, 'Identifier')) {
52
- if (validPrimitiveElements.has(node.property.name)) {
53
- const styledIdentifier = node.object.name;
54
- const elementName = node.property.name;
55
-
56
- // Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
57
- const reportName = `${styledIdentifier}.${elementName}`; // styled.div
58
-
59
- context.report({
60
- node: node,
61
- messageId: 'preferPrimitives',
62
- data: {
63
- element: reportName
64
- }
65
- });
66
- }
67
- }
68
- },
69
- // styled(X)``
70
- 'CallExpression[callee.name="styled"]': node => {
71
- if (!isNodeOfType(node, 'CallExpression')) {
72
- return;
73
- }
74
-
75
- // styled('div')`` - We only care about 'div'/'span', ignore extending other components
76
- if (isNodeOfType(node.arguments[0], 'Literal')) {
77
- const argValue = node.arguments[0].raw;
78
- if (typeof argValue === 'string') {
79
- const suggest = validPrimitiveElements.has(argValue.replaceAll(`'`, '') // argValue will have '' around the element name, strip it out for this test
80
- );
81
- if (suggest) {
82
- const styledIdentifier = node.callee.name;
83
- const elementName = argValue;
84
-
85
- // Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
86
- const reportName = `${styledIdentifier}(${elementName})`; // styled('div')
87
-
88
- context.report({
89
- node: node,
90
- messageId: 'preferPrimitives',
91
- data: {
92
- element: reportName
93
- }
94
- });
95
- }
96
- }
97
- }
98
- }
99
- };
19
+ create() {
20
+ /**
21
+ * We can't just outright delete the ESLint rule, since:
22
+ * ```
23
+ * // eslint-disable @eslint-plugin/design-system/prefer-primitives
24
+ * ```
25
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
26
+ * we can change the implementation of the rule so that it never reports.
27
+ */
28
+ return {};
100
29
  }
101
30
  });
102
31
  export default rule;
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import { Object as ASTObject, ObjectEntry, Root } from '../../../ast-nodes';
5
- import { getValueForPropertyNode, insertTokensImport, normaliseValue } from '../../ensure-design-token-usage/utils';
5
+ import { getValueForPropertyNode, normaliseValue } from '../../ensure-design-token-usage/utils';
6
6
  import { isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfType } from '../../utils/is-node';
7
- import { convertPropertyNodeToStringableNode, defaultFontWeight, findFontFamilyValueForToken, findFontWeightTokenForValue, findTypographyTokenForValues, fontWeightMap, getLiteralProperty, getTokenProperty, isValidPropertyNode, notUndefined } from '../utils';
7
+ import { convertPropertyNodeToStringableNode, defaultFontWeight, findFontFamilyValueForToken, findFontWeightTokenForValue, findTypographyTokenForValues, fontWeightMap, getLiteralProperty, getTokenProperty, insertFallbackImportFull, insertFallbackImportSpecifier, insertTokensImport, isValidPropertyNode, notUndefined } from '../utils';
8
8
  export const StyleObject = {
9
9
  lint(node, {
10
10
  context
@@ -29,7 +29,9 @@ export const StyleObject = {
29
29
  const {
30
30
  fontSizeNode,
31
31
  fontSizeRaw,
32
- tokensImportNode
32
+ tokensImportNode,
33
+ themeImportNode,
34
+ shouldAddFallbackImport
33
35
  } = refs;
34
36
  const fontSizeValue = normaliseValue('fontSize', fontSizeRaw);
35
37
 
@@ -117,6 +119,8 @@ export const StyleObject = {
117
119
  matchingToken,
118
120
  nodesToReplace,
119
121
  tokensImportNode,
122
+ themeImportNode,
123
+ shouldAddFallbackImport,
120
124
  fontWeightReplacement,
121
125
  fontFamilyReplacement,
122
126
  fontStyleReplacement
@@ -164,20 +168,47 @@ export const StyleObject = {
164
168
  success: false
165
169
  };
166
170
  }
167
- const importDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
171
+ const tokensImportDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
168
172
 
169
173
  // If there is more than one `@atlaskit/tokens` import, then it becomes difficult to determine which import to transform
170
- if (importDeclaration.length > 1) {
174
+ if (tokensImportDeclaration.length > 1) {
171
175
  return {
172
176
  success: false
173
177
  };
174
178
  }
179
+
180
+ // This exists purely because we're not inlining the fallback values
181
+ // and instead referencing a `fontFallback` object that exists in @atlaskit/theme/typography.
182
+ // This is a temporary measure until fallbacks are no longer required
183
+ let shouldAddFallbackImport = 'full';
184
+ const themeImportDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/theme/typography');
185
+ if (themeImportDeclaration.length) {
186
+ // Import exists, check if specifier exists
187
+ shouldAddFallbackImport = 'specifier';
188
+ const fallbackImport = themeImportDeclaration[0].specifiers.find(specifier => {
189
+ // @atlaskit/theme/typography has no default export so we can safely narrow this type
190
+ if (!isNodeOfType(specifier, 'ImportSpecifier')) {
191
+ return false;
192
+ }
193
+ if (specifier.imported.name === 'fontFallback') {
194
+ return true;
195
+ }
196
+ return false;
197
+ });
198
+
199
+ // Exact import already exists, no need to add
200
+ if (fallbackImport) {
201
+ shouldAddFallbackImport = false;
202
+ }
203
+ }
175
204
  return {
176
205
  success: true,
177
206
  refs: {
178
207
  fontSizeNode,
179
208
  fontSizeRaw,
180
- tokensImportNode: importDeclaration[0]
209
+ tokensImportNode: tokensImportDeclaration[0],
210
+ themeImportNode: themeImportDeclaration[0],
211
+ shouldAddFallbackImport
181
212
  }
182
213
  };
183
214
  },
@@ -187,15 +218,25 @@ export const StyleObject = {
187
218
  matchingToken,
188
219
  nodesToReplace,
189
220
  tokensImportNode,
221
+ themeImportNode,
222
+ shouldAddFallbackImport,
190
223
  fontWeightReplacement,
191
224
  fontFamilyReplacement,
192
225
  fontStyleReplacement
193
226
  } = refs;
194
227
  const fontSizeNode = nodesToReplace[0];
195
- return (!tokensImportNode ? [insertTokensImport(fixer)] : []).concat(nodesToReplace.map((node, index) => {
228
+ const root = context.getSourceCode().ast.body;
229
+ let fallbackImport;
230
+ if (shouldAddFallbackImport === 'full') {
231
+ fallbackImport = insertFallbackImportFull(root, fixer);
232
+ } else if (shouldAddFallbackImport === 'specifier') {
233
+ fallbackImport = insertFallbackImportSpecifier(fixer, themeImportNode);
234
+ }
235
+ const fallbackName = (matchingToken.tokenName === 'font.body' ? 'font.body.medium' : matchingToken.tokenName).replace('font', 'fontFallback');
236
+ return (!tokensImportNode ? [insertTokensImport(root, fixer)] : []).concat(fallbackImport ? [fallbackImport] : [], nodesToReplace.map((node, index) => {
196
237
  // Replace first node with token, delete remaining nodes. Guaranteed to be fontSize
197
238
  if (index === 0) {
198
- return fixer.replaceText(node, `${getTokenProperty('font', matchingToken.tokenName, matchingToken.tokenValue)}`);
239
+ return fixer.replaceText(node, `${getTokenProperty('font', matchingToken.tokenName, fallbackName, true)}`);
199
240
  }
200
241
 
201
242
  // We don't replace fontWeight/fontFamily/fontStyle here in case it occurs before the font property.
@@ -1,6 +1,7 @@
1
- import { callExpression, identifier, isNodeOfType, literal, property } from 'eslint-codemod-utils';
1
+ import { callExpression, identifier, isNodeOfType, literal, memberExpression, property } from 'eslint-codemod-utils';
2
2
  import { typographyPalette } from '@atlaskit/tokens/palettes-raw';
3
3
  import { typographyAdg3 as typographyTokens } from '@atlaskit/tokens/tokens-raw';
4
+ import { Import, Root } from '../../ast-nodes';
4
5
  export const typographyProperties = ['fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
5
6
  export const isTypographyProperty = propertyName => {
6
7
  return typographyProperties.includes(propertyName);
@@ -68,21 +69,37 @@ export function isValidPropertyNode(node) {
68
69
  }
69
70
  return true;
70
71
  }
71
- function getTokenNode(tokenName, tokenValue) {
72
+ function getTokenNode(tokenName, tokenValue, isFallbackMember) {
73
+ let fallback;
74
+ if (isFallbackMember) {
75
+ fallback = createMemberExpressionFromArray(tokenValue.split('.'));
76
+ } else {
77
+ fallback = literal(tokenValue);
78
+ }
72
79
  return callExpression({
73
80
  callee: identifier({
74
81
  name: 'token'
75
82
  }),
76
83
  arguments: [literal({
77
84
  value: `'${tokenName}'`
78
- }), literal(tokenValue)],
85
+ }), fallback],
79
86
  optional: false
80
87
  });
81
88
  }
82
- export function getTokenProperty(propertyName, tokenName, tokenFallback) {
89
+ function createMemberExpressionFromArray(array) {
90
+ if (array.length === 1) {
91
+ return identifier(array[0]);
92
+ }
93
+ const property = array.pop();
94
+ return memberExpression({
95
+ object: createMemberExpressionFromArray(array),
96
+ property: identifier(property)
97
+ });
98
+ }
99
+ export function getTokenProperty(propertyName, tokenName, tokenFallback, isFallbackMember = false) {
83
100
  return property({
84
101
  key: identifier(propertyName),
85
- value: getTokenNode(tokenName, tokenFallback)
102
+ value: getTokenNode(tokenName, tokenFallback, isFallbackMember)
86
103
  });
87
104
  }
88
105
  export function getLiteralProperty(propertyName, propertyValue) {
@@ -96,4 +113,19 @@ export function convertPropertyNodeToStringableNode(node) {
96
113
  key: node.key,
97
114
  value: node.value
98
115
  });
116
+ }
117
+ export function insertTokensImport(root, fixer) {
118
+ return Root.insertImport(root, {
119
+ module: '@atlaskit/tokens',
120
+ specifiers: ['token']
121
+ }, fixer);
122
+ }
123
+ export function insertFallbackImportFull(root, fixer) {
124
+ return Root.insertImport(root, {
125
+ module: '@atlaskit/theme/typography',
126
+ specifiers: ['fontFallback']
127
+ }, fixer);
128
+ }
129
+ export function insertFallbackImportSpecifier(fixer, themeImportNode) {
130
+ return Import.insertNamedSpecifiers(themeImportNode, ['fontFallback'], fixer);
99
131
  }
@@ -1,23 +1,29 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
- import { createWithConfig } from '../ensure-design-token-usage';
5
4
  import ruleMeta from '../ensure-design-token-usage/rule-meta';
6
5
  import { createLintRule } from '../utils/create-rule';
7
- var defaultConfig = {
8
- domains: ['spacing'],
9
- applyImport: true,
10
- shouldEnforceFallbacks: false
11
- };
12
6
  var rule = createLintRule({
13
7
  meta: _objectSpread(_objectSpread({}, ruleMeta), {}, {
14
8
  name: 'ensure-design-token-usage/preview',
9
+ deprecated: true,
10
+ replacedBy: ['@atlaskit/design-system/use-tokens-space'],
15
11
  docs: _objectSpread(_objectSpread({}, ruleMeta.docs), {}, {
16
12
  description: 'Enforces usage of pre-release design tokens rather than hard-coded values.',
17
13
  recommended: false,
18
14
  severity: 'warn'
19
15
  })
20
16
  }),
21
- create: createWithConfig(defaultConfig)
17
+ create: function create() {
18
+ /**
19
+ * We can't just outright delete the ESLint rule, since:
20
+ * ```
21
+ * // eslint-disable @eslint-plugin/design-system/ensure-design-token-usage/preview
22
+ * ```
23
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
24
+ * we can change the implementation of the rule so that it never reports.
25
+ */
26
+ return {};
27
+ }
22
28
  });
23
29
  export default rule;
@@ -1,14 +1,12 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- import { isNodeOfType } from 'eslint-codemod-utils';
4
1
  import { createLintRule } from '../utils/create-rule';
5
- import { shouldSuggest, validPrimitiveElements } from './utils';
6
2
  var primitiveDocsUrl = 'https://go.atlassian.com/dst-prefer-primitives';
7
3
  var rule = createLintRule({
8
4
  meta: {
9
5
  name: 'prefer-primitives',
10
6
  type: 'suggestion',
11
7
  hasSuggestions: false,
8
+ deprecated: true,
9
+ replacedBy: ['@atlaskit/design-system/use-primitives'],
12
10
  docs: {
13
11
  description: '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.',
14
12
  recommended: false,
@@ -18,84 +16,16 @@ var rule = createLintRule({
18
16
  preferPrimitives: "This \"{{element}}\" may be able to be replaced with a primitive component. See ".concat(primitiveDocsUrl, " for guidance.")
19
17
  }
20
18
  },
21
- create: function create(context) {
22
- return {
23
- // Look for HTML elements - <div>, <span>
24
- // Look for styled calls/templates - styled.div(...), styled.span`...`
25
- JSXOpeningElement: function JSXOpeningElement(node) {
26
- if (!isNodeOfType(node, 'JSXOpeningElement')) {
27
- return;
28
- }
29
- if (!isNodeOfType(node.name, 'JSXIdentifier')) {
30
- return;
31
- }
32
- var suggest = shouldSuggest(node === null || node === void 0 ? void 0 : node.parent);
33
- if (suggest) {
34
- context.report({
35
- node: node,
36
- messageId: 'preferPrimitives',
37
- data: {
38
- element: node.name.name
39
- }
40
- });
41
- }
42
- },
43
- // styled.x`` | styled2.x`` | styled.div()
44
- 'MemberExpression[object.name="styled"],MemberExpression[object.name="styled2"]': function MemberExpressionObjectNameStyledMemberExpressionObjectNameStyled2(node) {
45
- if (!isNodeOfType(node, 'MemberExpression')) {
46
- return;
47
- }
48
-
49
- // styled.div``
50
- if (isNodeOfType(node.property, 'Identifier')) {
51
- if (validPrimitiveElements.has(node.property.name)) {
52
- var styledIdentifier = node.object.name;
53
- var elementName = node.property.name;
54
-
55
- // Including the `styled.` portion in the message to help makers understand it's not just the `div` element that should be replaced
56
- var reportName = "".concat(styledIdentifier, ".").concat(elementName); // styled.div
57
-
58
- context.report({
59
- node: node,
60
- messageId: 'preferPrimitives',
61
- data: {
62
- element: reportName
63
- }
64
- });
65
- }
66
- }
67
- },
68
- // styled(X)``
69
- 'CallExpression[callee.name="styled"]': function CallExpressionCalleeNameStyled(node) {
70
- if (!isNodeOfType(node, 'CallExpression')) {
71
- return;
72
- }
73
-
74
- // styled('div')`` - We only care about 'div'/'span', ignore extending other components
75
- if (isNodeOfType(node.arguments[0], 'Literal')) {
76
- var argValue = node.arguments[0].raw;
77
- if (typeof argValue === 'string') {
78
- var suggest = validPrimitiveElements.has(argValue.replaceAll("'", '') // argValue will have '' around the element name, strip it out for this test
79
- );
80
- if (suggest) {
81
- var styledIdentifier = node.callee.name;
82
- var elementName = argValue;
83
-
84
- // Including the `styled()` portion in the message to help makers understand it's not just the `div` element that should be replaced
85
- var reportName = "".concat(styledIdentifier, "(").concat(elementName, ")"); // styled('div')
86
-
87
- context.report({
88
- node: node,
89
- messageId: 'preferPrimitives',
90
- data: {
91
- element: reportName
92
- }
93
- });
94
- }
95
- }
96
- }
97
- }
98
- };
19
+ create: function create() {
20
+ /**
21
+ * We can't just outright delete the ESLint rule, since:
22
+ * ```
23
+ * // eslint-disable @eslint-plugin/design-system/prefer-primitives
24
+ * ```
25
+ * will cause CI to fail if the rule definition doesn't exist. So, instead
26
+ * we can change the implementation of the rule so that it never reports.
27
+ */
28
+ return {};
99
29
  }
100
30
  });
101
31
  export default rule;
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import { Object as ASTObject, ObjectEntry, Root } from '../../../ast-nodes';
5
- import { getValueForPropertyNode, insertTokensImport, normaliseValue } from '../../ensure-design-token-usage/utils';
5
+ import { getValueForPropertyNode, normaliseValue } from '../../ensure-design-token-usage/utils';
6
6
  import { isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfType } from '../../utils/is-node';
7
- import { convertPropertyNodeToStringableNode, defaultFontWeight, findFontFamilyValueForToken, findFontWeightTokenForValue, findTypographyTokenForValues, fontWeightMap, getLiteralProperty, getTokenProperty, isValidPropertyNode, notUndefined } from '../utils';
7
+ import { convertPropertyNodeToStringableNode, defaultFontWeight, findFontFamilyValueForToken, findFontWeightTokenForValue, findTypographyTokenForValues, fontWeightMap, getLiteralProperty, getTokenProperty, insertFallbackImportFull, insertFallbackImportSpecifier, insertTokensImport, isValidPropertyNode, notUndefined } from '../utils';
8
8
  export var StyleObject = {
9
9
  lint: function lint(node, _ref) {
10
10
  var context = _ref.context;
@@ -26,7 +26,9 @@ export var StyleObject = {
26
26
  }
27
27
  var fontSizeNode = refs.fontSizeNode,
28
28
  fontSizeRaw = refs.fontSizeRaw,
29
- tokensImportNode = refs.tokensImportNode;
29
+ tokensImportNode = refs.tokensImportNode,
30
+ themeImportNode = refs.themeImportNode,
31
+ shouldAddFallbackImport = refs.shouldAddFallbackImport;
30
32
  var fontSizeValue = normaliseValue('fontSize', fontSizeRaw);
31
33
 
32
34
  // -- Font weight --
@@ -117,6 +119,8 @@ export var StyleObject = {
117
119
  matchingToken: matchingToken,
118
120
  nodesToReplace: nodesToReplace,
119
121
  tokensImportNode: tokensImportNode,
122
+ themeImportNode: themeImportNode,
123
+ shouldAddFallbackImport: shouldAddFallbackImport,
120
124
  fontWeightReplacement: fontWeightReplacement,
121
125
  fontFamilyReplacement: fontFamilyReplacement,
122
126
  fontStyleReplacement: fontStyleReplacement
@@ -163,20 +167,47 @@ export var StyleObject = {
163
167
  success: false
164
168
  };
165
169
  }
166
- var importDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
170
+ var tokensImportDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/tokens');
167
171
 
168
172
  // If there is more than one `@atlaskit/tokens` import, then it becomes difficult to determine which import to transform
169
- if (importDeclaration.length > 1) {
173
+ if (tokensImportDeclaration.length > 1) {
170
174
  return {
171
175
  success: false
172
176
  };
173
177
  }
178
+
179
+ // This exists purely because we're not inlining the fallback values
180
+ // and instead referencing a `fontFallback` object that exists in @atlaskit/theme/typography.
181
+ // This is a temporary measure until fallbacks are no longer required
182
+ var shouldAddFallbackImport = 'full';
183
+ var themeImportDeclaration = Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/theme/typography');
184
+ if (themeImportDeclaration.length) {
185
+ // Import exists, check if specifier exists
186
+ shouldAddFallbackImport = 'specifier';
187
+ var fallbackImport = themeImportDeclaration[0].specifiers.find(function (specifier) {
188
+ // @atlaskit/theme/typography has no default export so we can safely narrow this type
189
+ if (!isNodeOfType(specifier, 'ImportSpecifier')) {
190
+ return false;
191
+ }
192
+ if (specifier.imported.name === 'fontFallback') {
193
+ return true;
194
+ }
195
+ return false;
196
+ });
197
+
198
+ // Exact import already exists, no need to add
199
+ if (fallbackImport) {
200
+ shouldAddFallbackImport = false;
201
+ }
202
+ }
174
203
  return {
175
204
  success: true,
176
205
  refs: {
177
206
  fontSizeNode: fontSizeNode,
178
207
  fontSizeRaw: fontSizeRaw,
179
- tokensImportNode: importDeclaration[0]
208
+ tokensImportNode: tokensImportDeclaration[0],
209
+ themeImportNode: themeImportDeclaration[0],
210
+ shouldAddFallbackImport: shouldAddFallbackImport
180
211
  }
181
212
  };
182
213
  },
@@ -185,14 +216,24 @@ export var StyleObject = {
185
216
  var matchingToken = refs.matchingToken,
186
217
  nodesToReplace = refs.nodesToReplace,
187
218
  tokensImportNode = refs.tokensImportNode,
219
+ themeImportNode = refs.themeImportNode,
220
+ shouldAddFallbackImport = refs.shouldAddFallbackImport,
188
221
  fontWeightReplacement = refs.fontWeightReplacement,
189
222
  fontFamilyReplacement = refs.fontFamilyReplacement,
190
223
  fontStyleReplacement = refs.fontStyleReplacement;
191
224
  var fontSizeNode = nodesToReplace[0];
192
- return (!tokensImportNode ? [insertTokensImport(fixer)] : []).concat(nodesToReplace.map(function (node, index) {
225
+ var root = context.getSourceCode().ast.body;
226
+ var fallbackImport;
227
+ if (shouldAddFallbackImport === 'full') {
228
+ fallbackImport = insertFallbackImportFull(root, fixer);
229
+ } else if (shouldAddFallbackImport === 'specifier') {
230
+ fallbackImport = insertFallbackImportSpecifier(fixer, themeImportNode);
231
+ }
232
+ var fallbackName = (matchingToken.tokenName === 'font.body' ? 'font.body.medium' : matchingToken.tokenName).replace('font', 'fontFallback');
233
+ return (!tokensImportNode ? [insertTokensImport(root, fixer)] : []).concat(fallbackImport ? [fallbackImport] : [], nodesToReplace.map(function (node, index) {
193
234
  // Replace first node with token, delete remaining nodes. Guaranteed to be fontSize
194
235
  if (index === 0) {
195
- return fixer.replaceText(node, "".concat(getTokenProperty('font', matchingToken.tokenName, matchingToken.tokenValue)));
236
+ return fixer.replaceText(node, "".concat(getTokenProperty('font', matchingToken.tokenName, fallbackName, true)));
196
237
  }
197
238
 
198
239
  // We don't replace fontWeight/fontFamily/fontStyle here in case it occurs before the font property.
@@ -1,6 +1,7 @@
1
- import { callExpression, identifier, isNodeOfType, literal, property } from 'eslint-codemod-utils';
1
+ import { callExpression, identifier, isNodeOfType, literal, memberExpression, property } from 'eslint-codemod-utils';
2
2
  import { typographyPalette } from '@atlaskit/tokens/palettes-raw';
3
3
  import { typographyAdg3 as typographyTokens } from '@atlaskit/tokens/tokens-raw';
4
+ import { Import, Root } from '../../ast-nodes';
4
5
  export var typographyProperties = ['fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
5
6
  export var isTypographyProperty = function isTypographyProperty(propertyName) {
6
7
  return typographyProperties.includes(propertyName);
@@ -98,21 +99,38 @@ export function isValidPropertyNode(node) {
98
99
  }
99
100
  return true;
100
101
  }
101
- function getTokenNode(tokenName, tokenValue) {
102
+ function getTokenNode(tokenName, tokenValue, isFallbackMember) {
103
+ var fallback;
104
+ if (isFallbackMember) {
105
+ fallback = createMemberExpressionFromArray(tokenValue.split('.'));
106
+ } else {
107
+ fallback = literal(tokenValue);
108
+ }
102
109
  return callExpression({
103
110
  callee: identifier({
104
111
  name: 'token'
105
112
  }),
106
113
  arguments: [literal({
107
114
  value: "'".concat(tokenName, "'")
108
- }), literal(tokenValue)],
115
+ }), fallback],
109
116
  optional: false
110
117
  });
111
118
  }
119
+ function createMemberExpressionFromArray(array) {
120
+ if (array.length === 1) {
121
+ return identifier(array[0]);
122
+ }
123
+ var property = array.pop();
124
+ return memberExpression({
125
+ object: createMemberExpressionFromArray(array),
126
+ property: identifier(property)
127
+ });
128
+ }
112
129
  export function getTokenProperty(propertyName, tokenName, tokenFallback) {
130
+ var isFallbackMember = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
113
131
  return property({
114
132
  key: identifier(propertyName),
115
- value: getTokenNode(tokenName, tokenFallback)
133
+ value: getTokenNode(tokenName, tokenFallback, isFallbackMember)
116
134
  });
117
135
  }
118
136
  export function getLiteralProperty(propertyName, propertyValue) {
@@ -126,4 +144,19 @@ export function convertPropertyNodeToStringableNode(node) {
126
144
  key: node.key,
127
145
  value: node.value
128
146
  });
147
+ }
148
+ export function insertTokensImport(root, fixer) {
149
+ return Root.insertImport(root, {
150
+ module: '@atlaskit/tokens',
151
+ specifiers: ['token']
152
+ }, fixer);
153
+ }
154
+ export function insertFallbackImportFull(root, fixer) {
155
+ return Root.insertImport(root, {
156
+ module: '@atlaskit/theme/typography',
157
+ specifiers: ['fontFallback']
158
+ }, fixer);
159
+ }
160
+ export function insertFallbackImportSpecifier(fixer, themeImportNode) {
161
+ return Import.insertNamedSpecifiers(themeImportNode, ['fontFallback'], fixer);
129
162
  }
@@ -1,3 +1,2 @@
1
- import type { Rule } from 'eslint';
2
- declare const rule: Rule.RuleModule;
1
+ declare const rule: import("eslint").Rule.RuleModule;
3
2
  export default rule;
@@ -8,6 +8,8 @@ interface Refs {
8
8
  fontSizeNode: Property;
9
9
  fontSizeRaw: string | number;
10
10
  tokensImportNode: ImportDeclaration | undefined;
11
+ themeImportNode: ImportDeclaration | undefined;
12
+ shouldAddFallbackImport: 'full' | 'specifier' | false;
11
13
  }
12
14
  type Check = {
13
15
  success: boolean;
@@ -17,6 +19,8 @@ interface FixerRefs {
17
19
  matchingToken: TokenValueMap;
18
20
  nodesToReplace: Property[];
19
21
  tokensImportNode: ImportDeclaration | undefined;
22
+ themeImportNode: ImportDeclaration | undefined;
23
+ shouldAddFallbackImport: Refs['shouldAddFallbackImport'];
20
24
  fontWeightReplacement: StringableASTNode<Property> | undefined;
21
25
  fontFamilyReplacement: StringableASTNode<Property> | undefined;
22
26
  fontStyleReplacement: StringableASTNode<Property> | undefined;
@@ -1,4 +1,5 @@
1
- import { CallExpression, EslintNode, Property } from 'eslint-codemod-utils';
1
+ import type { Rule } from 'eslint';
2
+ import { CallExpression, Directive, EslintNode, ImportDeclaration, ModuleDeclaration, Property, Statement, StringableASTNode } from 'eslint-codemod-utils';
2
3
  export declare const typographyProperties: string[];
3
4
  export declare const isTypographyProperty: (propertyName: string) => boolean;
4
5
  export declare const isFontSize: (node: EslintNode) => node is CallExpression;
@@ -189,6 +190,9 @@ export declare const fontFamilyTokens: ({
189
190
  export declare function findFontFamilyValueForToken(tokenName: string): string;
190
191
  export declare function notUndefined<V>(value: V | undefined): value is V;
191
192
  export declare function isValidPropertyNode(node: Property): boolean;
192
- export declare function getTokenProperty(propertyName: string, tokenName: string, tokenFallback: string): import("eslint-codemod-utils").StringableASTNode<Property>;
193
- export declare function getLiteralProperty(propertyName: string, propertyValue: string): import("eslint-codemod-utils").StringableASTNode<Property>;
194
- export declare function convertPropertyNodeToStringableNode(node: Property): import("eslint-codemod-utils").StringableASTNode<Property>;
193
+ export declare function getTokenProperty(propertyName: string, tokenName: string, tokenFallback: string, isFallbackMember?: boolean): StringableASTNode<Property>;
194
+ export declare function getLiteralProperty(propertyName: string, propertyValue: string): StringableASTNode<Property>;
195
+ export declare function convertPropertyNodeToStringableNode(node: Property): StringableASTNode<Property>;
196
+ export declare function insertTokensImport(root: (Directive | Statement | ModuleDeclaration)[], fixer: Rule.RuleFixer): Rule.Fix;
197
+ export declare function insertFallbackImportFull(root: (Directive | Statement | ModuleDeclaration)[], fixer: Rule.RuleFixer): Rule.Fix;
198
+ export declare function insertFallbackImportSpecifier(fixer: Rule.RuleFixer, themeImportNode: ImportDeclaration): Rule.Fix | undefined;
@@ -1,3 +1,2 @@
1
- import type { Rule } from 'eslint';
2
- declare const rule: Rule.RuleModule;
1
+ declare const rule: import("eslint").Rule.RuleModule;
3
2
  export default rule;
@@ -8,6 +8,8 @@ interface Refs {
8
8
  fontSizeNode: Property;
9
9
  fontSizeRaw: string | number;
10
10
  tokensImportNode: ImportDeclaration | undefined;
11
+ themeImportNode: ImportDeclaration | undefined;
12
+ shouldAddFallbackImport: 'full' | 'specifier' | false;
11
13
  }
12
14
  type Check = {
13
15
  success: boolean;
@@ -17,6 +19,8 @@ interface FixerRefs {
17
19
  matchingToken: TokenValueMap;
18
20
  nodesToReplace: Property[];
19
21
  tokensImportNode: ImportDeclaration | undefined;
22
+ themeImportNode: ImportDeclaration | undefined;
23
+ shouldAddFallbackImport: Refs['shouldAddFallbackImport'];
20
24
  fontWeightReplacement: StringableASTNode<Property> | undefined;
21
25
  fontFamilyReplacement: StringableASTNode<Property> | undefined;
22
26
  fontStyleReplacement: StringableASTNode<Property> | undefined;
@@ -1,4 +1,5 @@
1
- import { CallExpression, EslintNode, Property } from 'eslint-codemod-utils';
1
+ import type { Rule } from 'eslint';
2
+ import { CallExpression, Directive, EslintNode, ImportDeclaration, ModuleDeclaration, Property, Statement, StringableASTNode } from 'eslint-codemod-utils';
2
3
  export declare const typographyProperties: string[];
3
4
  export declare const isTypographyProperty: (propertyName: string) => boolean;
4
5
  export declare const isFontSize: (node: EslintNode) => node is CallExpression;
@@ -189,6 +190,9 @@ export declare const fontFamilyTokens: ({
189
190
  export declare function findFontFamilyValueForToken(tokenName: string): string;
190
191
  export declare function notUndefined<V>(value: V | undefined): value is V;
191
192
  export declare function isValidPropertyNode(node: Property): boolean;
192
- export declare function getTokenProperty(propertyName: string, tokenName: string, tokenFallback: string): import("eslint-codemod-utils").StringableASTNode<Property>;
193
- export declare function getLiteralProperty(propertyName: string, propertyValue: string): import("eslint-codemod-utils").StringableASTNode<Property>;
194
- export declare function convertPropertyNodeToStringableNode(node: Property): import("eslint-codemod-utils").StringableASTNode<Property>;
193
+ export declare function getTokenProperty(propertyName: string, tokenName: string, tokenFallback: string, isFallbackMember?: boolean): StringableASTNode<Property>;
194
+ export declare function getLiteralProperty(propertyName: string, propertyValue: string): StringableASTNode<Property>;
195
+ export declare function convertPropertyNodeToStringableNode(node: Property): StringableASTNode<Property>;
196
+ export declare function insertTokensImport(root: (Directive | Statement | ModuleDeclaration)[], fixer: Rule.RuleFixer): Rule.Fix;
197
+ export declare function insertFallbackImportFull(root: (Directive | Statement | ModuleDeclaration)[], fixer: Rule.RuleFixer): Rule.Fix;
198
+ export declare function insertFallbackImportSpecifier(fixer: Rule.RuleFixer, themeImportNode: ImportDeclaration): Rule.Fix | undefined;
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": "9.0.0",
4
+ "version": "9.2.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@atlaskit/ds-lib": "^2.2.0",
51
- "@atlaskit/theme": "^12.6.0",
51
+ "@atlaskit/theme": "^12.7.0",
52
52
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
53
53
  "@atlassian/codegen": "*",
54
54
  "@atlassian/eslint-utils": "^0.4.0",