@atlaskit/eslint-plugin-design-system 9.0.0 → 9.1.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,11 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 9.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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.
8
+
3
9
  ## 9.0.0
4
10
 
5
11
  ### Major Changes
@@ -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
  }
@@ -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
  }
@@ -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
  }
@@ -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;
@@ -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.1.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",