@atlaskit/eslint-plugin-design-system 8.33.0 → 8.36.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -0
  3. package/constellation/ensure-design-token-usage/usage.mdx +2 -2
  4. package/constellation/index/usage.mdx +1 -0
  5. package/constellation/use-primitives-text/usage.mdx +13 -3
  6. package/constellation/use-tokens-typography/usage.mdx +42 -0
  7. package/dist/cjs/ast-nodes/index.js +7 -0
  8. package/dist/cjs/ast-nodes/object-entry.js +27 -0
  9. package/dist/cjs/ast-nodes/object.js +1 -1
  10. package/dist/cjs/presets/all.codegen.js +2 -1
  11. package/dist/cjs/rules/ensure-design-token-usage/index.js +5 -4
  12. package/dist/cjs/rules/ensure-design-token-usage/rule-meta.js +1 -1
  13. package/dist/cjs/rules/ensure-design-token-usage/spacing.js +5 -1
  14. package/dist/cjs/rules/ensure-design-token-usage/utils.js +52 -42
  15. package/dist/cjs/rules/index.codegen.js +3 -1
  16. package/dist/cjs/rules/use-primitives/transformers/compiled-styled/find-valid-jsx-usage-to-transform.js +24 -1
  17. package/dist/cjs/rules/use-primitives/transformers/compiled-styled/index.js +2 -1
  18. package/dist/cjs/rules/use-primitives-text/config/index.js +2 -1
  19. package/dist/cjs/rules/use-primitives-text/transformers/common.js +10 -1
  20. package/dist/cjs/rules/use-primitives-text/transformers/emphasis-elements.js +6 -3
  21. package/dist/cjs/rules/use-primitives-text/transformers/paragraph-elements.js +19 -4
  22. package/dist/cjs/rules/use-primitives-text/transformers/span-elements.js +6 -4
  23. package/dist/cjs/rules/use-primitives-text/transformers/strong-elements.js +6 -3
  24. package/dist/cjs/rules/use-tokens-typography/config/index.js +26 -0
  25. package/dist/cjs/rules/use-tokens-typography/error-boundary.js +24 -0
  26. package/dist/cjs/rules/use-tokens-typography/index.js +44 -0
  27. package/dist/cjs/rules/use-tokens-typography/transformers/style-object.js +212 -0
  28. package/dist/cjs/rules/use-tokens-typography/utils.js +146 -0
  29. package/dist/es2019/ast-nodes/index.js +1 -0
  30. package/dist/es2019/ast-nodes/object-entry.js +22 -0
  31. package/dist/es2019/ast-nodes/object.js +1 -1
  32. package/dist/es2019/presets/all.codegen.js +2 -1
  33. package/dist/es2019/rules/ensure-design-token-usage/index.js +6 -5
  34. package/dist/es2019/rules/ensure-design-token-usage/rule-meta.js +1 -1
  35. package/dist/es2019/rules/ensure-design-token-usage/spacing.js +5 -1
  36. package/dist/es2019/rules/ensure-design-token-usage/utils.js +42 -38
  37. package/dist/es2019/rules/index.codegen.js +3 -1
  38. package/dist/es2019/rules/use-primitives/transformers/compiled-styled/find-valid-jsx-usage-to-transform.js +17 -3
  39. package/dist/es2019/rules/use-primitives/transformers/compiled-styled/index.js +2 -1
  40. package/dist/es2019/rules/use-primitives-text/config/index.js +2 -1
  41. package/dist/es2019/rules/use-primitives-text/transformers/common.js +9 -2
  42. package/dist/es2019/rules/use-primitives-text/transformers/emphasis-elements.js +7 -4
  43. package/dist/es2019/rules/use-primitives-text/transformers/paragraph-elements.js +20 -5
  44. package/dist/es2019/rules/use-primitives-text/transformers/span-elements.js +7 -5
  45. package/dist/es2019/rules/use-primitives-text/transformers/strong-elements.js +7 -4
  46. package/dist/es2019/rules/use-tokens-typography/config/index.js +20 -0
  47. package/dist/es2019/rules/use-tokens-typography/error-boundary.js +19 -0
  48. package/dist/es2019/rules/use-tokens-typography/index.js +36 -0
  49. package/dist/es2019/rules/use-tokens-typography/transformers/style-object.js +209 -0
  50. package/dist/es2019/rules/use-tokens-typography/utils.js +99 -0
  51. package/dist/esm/ast-nodes/index.js +1 -0
  52. package/dist/esm/ast-nodes/object-entry.js +22 -0
  53. package/dist/esm/ast-nodes/object.js +1 -1
  54. package/dist/esm/presets/all.codegen.js +2 -1
  55. package/dist/esm/rules/ensure-design-token-usage/index.js +6 -5
  56. package/dist/esm/rules/ensure-design-token-usage/rule-meta.js +1 -1
  57. package/dist/esm/rules/ensure-design-token-usage/spacing.js +5 -1
  58. package/dist/esm/rules/ensure-design-token-usage/utils.js +46 -38
  59. package/dist/esm/rules/index.codegen.js +3 -1
  60. package/dist/esm/rules/use-primitives/transformers/compiled-styled/find-valid-jsx-usage-to-transform.js +23 -2
  61. package/dist/esm/rules/use-primitives/transformers/compiled-styled/index.js +2 -1
  62. package/dist/esm/rules/use-primitives-text/config/index.js +2 -1
  63. package/dist/esm/rules/use-primitives-text/transformers/common.js +9 -2
  64. package/dist/esm/rules/use-primitives-text/transformers/emphasis-elements.js +7 -4
  65. package/dist/esm/rules/use-primitives-text/transformers/paragraph-elements.js +20 -5
  66. package/dist/esm/rules/use-primitives-text/transformers/span-elements.js +7 -5
  67. package/dist/esm/rules/use-primitives-text/transformers/strong-elements.js +7 -4
  68. package/dist/esm/rules/use-tokens-typography/config/index.js +20 -0
  69. package/dist/esm/rules/use-tokens-typography/error-boundary.js +18 -0
  70. package/dist/esm/rules/use-tokens-typography/index.js +38 -0
  71. package/dist/esm/rules/use-tokens-typography/transformers/style-object.js +206 -0
  72. package/dist/esm/rules/use-tokens-typography/utils.js +129 -0
  73. package/dist/types/ast-nodes/index.d.ts +1 -0
  74. package/dist/types/ast-nodes/object-entry.d.ts +6 -0
  75. package/dist/types/ast-nodes/object.d.ts +1 -1
  76. package/dist/types/index.codegen.d.ts +1 -0
  77. package/dist/types/presets/all.codegen.d.ts +2 -1
  78. package/dist/types/rules/ensure-design-token-usage/types.d.ts +1 -1
  79. package/dist/types/rules/ensure-design-token-usage/utils.d.ts +22 -22
  80. package/dist/types/rules/index.codegen.d.ts +1 -0
  81. package/dist/types/rules/use-primitives/config/index.d.ts +1 -1
  82. package/dist/types/rules/use-primitives/transformers/compiled-styled/find-valid-jsx-usage-to-transform.d.ts +3 -1
  83. package/dist/types/rules/use-primitives/transformers/compiled-styled/index.d.ts +1 -1
  84. package/dist/types/rules/use-primitives/transformers/emotion-css/index.d.ts +1 -2
  85. package/dist/types/rules/use-primitives-text/config/index.d.ts +1 -0
  86. package/dist/types/rules/use-primitives-text/transformers/common.d.ts +6 -0
  87. package/dist/types/rules/use-primitives-text/transformers/emphasis-elements.d.ts +2 -10
  88. package/dist/types/rules/use-primitives-text/transformers/paragraph-elements.d.ts +4 -12
  89. package/dist/types/rules/use-primitives-text/transformers/span-elements.d.ts +2 -10
  90. package/dist/types/rules/use-primitives-text/transformers/strong-elements.d.ts +2 -10
  91. package/dist/types/rules/use-tokens-typography/config/index.d.ts +6 -0
  92. package/dist/types/rules/use-tokens-typography/error-boundary.d.ts +11 -0
  93. package/dist/types/rules/use-tokens-typography/index.d.ts +3 -0
  94. package/dist/types/rules/use-tokens-typography/transformers/style-object.d.ts +31 -0
  95. package/dist/types/rules/use-tokens-typography/utils.d.ts +194 -0
  96. package/dist/types-ts4.5/ast-nodes/index.d.ts +1 -0
  97. package/dist/types-ts4.5/ast-nodes/object-entry.d.ts +6 -0
  98. package/dist/types-ts4.5/ast-nodes/object.d.ts +1 -1
  99. package/dist/types-ts4.5/index.codegen.d.ts +1 -0
  100. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
  101. package/dist/types-ts4.5/rules/ensure-design-token-usage/types.d.ts +1 -1
  102. package/dist/types-ts4.5/rules/ensure-design-token-usage/utils.d.ts +22 -22
  103. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
  104. package/dist/types-ts4.5/rules/use-primitives/config/index.d.ts +1 -1
  105. package/dist/types-ts4.5/rules/use-primitives/transformers/compiled-styled/find-valid-jsx-usage-to-transform.d.ts +3 -1
  106. package/dist/types-ts4.5/rules/use-primitives/transformers/compiled-styled/index.d.ts +1 -1
  107. package/dist/types-ts4.5/rules/use-primitives/transformers/emotion-css/index.d.ts +1 -2
  108. package/dist/types-ts4.5/rules/use-primitives-text/config/index.d.ts +1 -0
  109. package/dist/types-ts4.5/rules/use-primitives-text/transformers/common.d.ts +6 -0
  110. package/dist/types-ts4.5/rules/use-primitives-text/transformers/emphasis-elements.d.ts +2 -10
  111. package/dist/types-ts4.5/rules/use-primitives-text/transformers/paragraph-elements.d.ts +4 -12
  112. package/dist/types-ts4.5/rules/use-primitives-text/transformers/span-elements.d.ts +2 -10
  113. package/dist/types-ts4.5/rules/use-primitives-text/transformers/strong-elements.d.ts +2 -10
  114. package/dist/types-ts4.5/rules/use-tokens-typography/config/index.d.ts +6 -0
  115. package/dist/types-ts4.5/rules/use-tokens-typography/error-boundary.d.ts +11 -0
  116. package/dist/types-ts4.5/rules/use-tokens-typography/index.d.ts +3 -0
  117. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/style-object.d.ts +31 -0
  118. package/dist/types-ts4.5/rules/use-tokens-typography/utils.d.ts +194 -0
  119. package/package.json +1 -1
  120. package/dist/cjs/rules/ensure-design-token-usage/typography.js +0 -39
  121. package/dist/es2019/rules/ensure-design-token-usage/typography.js +0 -19
  122. package/dist/esm/rules/ensure-design-token-usage/typography.js +0 -33
  123. package/dist/types/rules/ensure-design-token-usage/typography.d.ts +0 -9
  124. package/dist/types-ts4.5/rules/ensure-design-token-usage/typography.d.ts +0 -9
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::bcb633b9d5c2def00d43b11139433c5c>>
3
+ * @codegen <<SignedSource::d90c2cf5e100daf98915f9467f2e5663>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -35,6 +35,7 @@ export default {
35
35
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
36
36
  '@atlaskit/design-system/use-primitives': 'warn',
37
37
  '@atlaskit/design-system/use-primitives-text': 'warn',
38
+ '@atlaskit/design-system/use-tokens-typography': 'warn',
38
39
  '@atlaskit/design-system/use-visually-hidden': 'error'
39
40
  }
40
41
  };
@@ -8,7 +8,7 @@ import { lintJSXIdentifierForColor, lintJSXLiteralForColor, lintJSXMemberForColo
8
8
  import { errorBoundary } from './error-boundary';
9
9
  import ruleMeta from './rule-meta';
10
10
  import { lintObjectForSpacing } from './spacing';
11
- import { convertHyphenatedNameToCamelCase, emToPixels, getDomainsForProperty, getFontSizeFromNode, getFontSizeValueInScope, getTokenReplacement, getValueFromShorthand, getValueFromTemplateLiteralRaw, includesTokenString, insertTokensImport, isAuto, isCalc, isTokenValueString, isValidSpacingValue, isZero, processCssNode, splitShorthandValues } from './utils';
11
+ import { convertHyphenatedNameToCamelCase, emToPixels, getDomainsForProperty, getFontSizeValueInScope, getPropertyNodeFromParent, getTokenReplacement, getValueForPropertyNode, getValueFromShorthand, getValueFromTemplateLiteralRaw, includesTokenString, insertTokensImport, isAuto, isCalc, isTokenValueString, isValidSpacingValue, isZero, processCssNode, splitShorthandValues } from './utils';
12
12
  const defaultConfig = {
13
13
  domains: ['color', 'spacing'],
14
14
  applyImport: true,
@@ -89,11 +89,12 @@ const createWithConfig = initialConfig => context => {
89
89
  if (domains.includes('color')) {
90
90
  return lintObjectForColor(node, context, config);
91
91
  }
92
- if (domains.includes('spacing') || domains.includes('shape') || domains.includes('typography')) {
92
+ if (domains.includes('spacing') || domains.includes('shape')) {
93
93
  /**
94
- * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
94
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration.
95
95
  */
96
- const fontSize = getFontSizeFromNode(parentNode, context);
96
+ const fontSizeNode = getPropertyNodeFromParent('fontSize', parentNode);
97
+ const fontSize = fontSizeNode && getValueForPropertyNode(fontSizeNode, context);
97
98
  return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
98
99
  }
99
100
  }
@@ -140,7 +141,7 @@ const createWithConfig = initialConfig => context => {
140
141
  return currentSource;
141
142
  }
142
143
  }
143
- if (domains.includes('spacing') || domains.includes('typography') || domains.includes('shape')) {
144
+ if (domains.includes('spacing') || domains.includes('shape')) {
144
145
  if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
145
146
  // no changes should be made to the current property
146
147
  return currentSource;
@@ -1,4 +1,4 @@
1
- const domainsToLint = ['color', 'spacing', 'typography', 'shape'];
1
+ const domainsToLint = ['color', 'spacing', 'shape'];
2
2
  const ruleMeta = {
3
3
  name: 'ensure-design-token-usage',
4
4
  hasSuggestions: true,
@@ -64,7 +64,8 @@ export const lintObjectForSpacing = (node, context, ruleConfig, fontSize, tokenN
64
64
  payload: `${propertyName}:${pixelValue}`
65
65
  },
66
66
  fix: fixer => {
67
- const replacementNode = getTokenReplacement(propertyName, pixelValue);
67
+ // Casting due to possibility of pixelValue being string | number from emToPixels
68
+ const replacementNode = pixelValue && getTokenReplacement(propertyName, pixelValue);
68
69
  if (!replacementNode) {
69
70
  return null;
70
71
  }
@@ -110,6 +111,8 @@ export const lintObjectForSpacing = (node, context, ruleConfig, fontSize, tokenN
110
111
  if (!allResolvableValues) {
111
112
  return null;
112
113
  }
114
+
115
+ // Casting due to possibility of value being string | number
113
116
  const valuesWithTokenReplacement = valuesForProperty.filter(value => findTokenNameByPropertyValue(propertyName, value)).filter(value => value !== 0);
114
117
  if (valuesWithTokenReplacement.length === 0) {
115
118
  // all values could be replaceable but that just means they're numeric
@@ -139,6 +142,7 @@ export const lintObjectForSpacing = (node, context, ruleConfig, fontSize, tokenN
139
142
  const pixelValueString = `${pixelValue}px`;
140
143
  // if there is a token we take it, otherwise we go with the original value
141
144
 
145
+ // Casting due to possibility of value being string | number
142
146
  return findTokenNameByPropertyValue(propertyName, value) ? `\${${getTokenNodeForValue(propertyName, pixelValueString)}}` : originalValues[index];
143
147
  }).join(' ')}\``)]);
144
148
  }
@@ -5,7 +5,6 @@ import { spacing as spacingScale } from '@atlaskit/tokens/tokens-raw';
5
5
  import { findIdentifierInParentScope } from '../utils/find-in-parent';
6
6
  import { isColorCssPropertyName, isCurrentSurfaceCustomPropertyName } from '../utils/is-color';
7
7
  import { borderWidthValueToToken, isBorderRadius, isBorderSizeProperty, isShapeProperty, radiusValueToToken } from './shape';
8
- import { isCodeFontFamily, isFontFamily, isFontSize, isFontSizeSmall, isTypographyProperty, typographyValueToToken } from './typography';
9
8
  const properties = ['padding', 'paddingBlock', 'paddingInline', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'marginInline', 'marginInlineStart', 'marginInlineEnd', 'marginBlock', 'marginBlockStart', 'marginBlockEnd', 'margin', 'gap', 'rowGap', 'gridRowGap', 'columnGap', 'gridColumnGap', 'top', 'left', 'right', 'bottom', 'inlineStart', 'inlineEnd', 'blockStart', 'blockEnd', 'outline-offset'];
10
9
  const spacingValueToToken = Object.fromEntries(spacingScale.map(token => [token.value, token.cleanName]));
11
10
  export function insertTokensImport(fixer) {
@@ -31,8 +30,10 @@ export const splitShorthandValues = str => {
31
30
  };
32
31
  export const getValueFromShorthand = str => {
33
32
  const valueString = String(str);
34
- const fontFamily = /(sans-serif$)|(monospace$)/;
35
- if (fontFamily.test(valueString)) {
33
+ const fontFamily = /(Charlie)|(sans-serif$)|(monospace$)/;
34
+ const fontWeightString = /(regular$)|(medium$)|(semibold$)|(bold$)/;
35
+ const fontStyleString = /(inherit$)|(normal$)|(italic$)/;
36
+ if (fontFamily.test(valueString) || fontWeightString.test(valueString) || fontStyleString.test(valueString)) {
36
37
  return [valueString];
37
38
  }
38
39
  // If we want to filter out NaN just add .filter(Boolean)
@@ -57,6 +58,8 @@ const getRawExpressionForToken = (node, context) => {
57
58
  }).join(', ')})}`;
58
59
  return call;
59
60
  };
61
+ const isFontSize = node => isNodeOfType(node, 'CallExpression') && isNodeOfType(node.callee, 'Identifier') && (node.callee.name === 'fontSize' || node.callee.name === 'getFontSize');
62
+ const isFontSizeSmall = node => isNodeOfType(node, 'CallExpression') && isNodeOfType(node.callee, 'Identifier') && node.callee.name === 'fontSizeSmall';
60
63
  const getValueFromCallExpression = (node, context) => {
61
64
  if (!isNodeOfType(node, 'CallExpression')) {
62
65
  return null;
@@ -73,12 +76,6 @@ const getValueFromCallExpression = (node, context) => {
73
76
  if (isFontSizeSmall(node)) {
74
77
  return 11;
75
78
  }
76
- if (isFontFamily(node)) {
77
- return `-apple-system, BlinkMacSystemFont, \'Segoe UI\', \'Roboto\', \'Oxygen\', \'Ubuntu\', \'Fira Sans\', \'Droid Sans\', \'Helvetica Neue\', sans-serif`;
78
- }
79
- if (isCodeFontFamily(node)) {
80
- return `\'SFMono-Medium\', \'SF Mono\', \'Segoe UI Mono\', \'Roboto Mono\', \'Ubuntu Mono\', Menlo, Consolas, Courier, monospace`;
81
- }
82
79
  if (isToken(node)) {
83
80
  return getRawExpressionForToken(node, context);
84
81
  }
@@ -281,7 +278,7 @@ export const convertHyphenatedNameToCamelCase = prop => {
281
278
 
282
279
  /**
283
280
  * @param node
284
- * @returns The furthest parent node that is on the same line as the input node
281
+ * @returns The furthest parent node that is on the same line as the input node.
285
282
  */
286
283
  export const findParentNodeForLine = node => {
287
284
  var _node$loc, _node$parent$loc;
@@ -296,14 +293,13 @@ export const findParentNodeForLine = node => {
296
293
  };
297
294
 
298
295
  /**
299
- * Returns an array of domains that are relevant to the provided property based on the rule options
296
+ * Returns an array of domains that are relevant to the provided property based on the rule options.
300
297
  * @param propertyName camelCase CSS property
301
- * @param targetOptions Array containing the types of properties that should be included in the rule
298
+ * @param targetOptions Array containing the types of properties that should be included in the rule.
302
299
  * @example
303
300
  * ```
304
301
  * propertyName: padding, targetOptions: ['spacing'] -> returns ['spacing']
305
- * propertyName: fontWeight, targetOptions: ['spacing', 'typography'] -> returns ['typography']
306
- * propertyName: backgroundColor, targetOptions: ['spacing', 'typography'] -> returns []
302
+ * propertyName: backgroundColor, targetOptions: ['spacing'] -> returns []
307
303
  * propertyName: backgroundColor, targetOptions: ['color', 'spacing'] -> returns ['color']
308
304
  * ```
309
305
  */
@@ -318,15 +314,12 @@ export function getDomainsForProperty(propertyName, targetOptions) {
318
314
  if (isShapeProperty(propertyName) && targetOptions.includes('shape')) {
319
315
  domains.push('shape');
320
316
  }
321
- if (isTypographyProperty(propertyName) && targetOptions.includes('typography')) {
322
- domains.push('typography');
323
- }
324
317
  return domains;
325
318
  }
326
319
 
327
320
  /**
328
321
  * Function that removes JS comments from a string of code,
329
- * sometimes makers will have single or multiline comments in their tagged template literals styles, this can mess with our parsing logic
322
+ * sometimes makers will have single or multiline comments in their tagged template literals styles, this can mess with our parsing logic.
330
323
  */
331
324
  export function cleanComments(str) {
332
325
  return str.replace(/\/\*([\s\S]*?)\*\//g, '').replace(/\/\/(.*)/g, '');
@@ -334,11 +327,11 @@ export function cleanComments(str) {
334
327
 
335
328
  /**
336
329
  * Returns an array of tuples representing a processed css within `TaggedTemplateExpression` node.
337
- * each element of the array is a tuple `[string, string]`,
330
+ * Each element of the array is a tuple `[string, string]`,
338
331
  * where the first element is the processed css line with computed values
339
- * and the second element of the tuple is the original css line from source
340
- * @param node TaggedTemplateExpression node
341
- * @param context Rule.RuleContext
332
+ * and the second element of the tuple is the original css line from source.
333
+ * @param node TaggedTemplateExpression node.
334
+ * @param context Rule.RuleContext.
342
335
  * @example
343
336
  * ```
344
337
  * `[['padding: 8', 'padding: ${gridSize()}'], ['margin: 6', 'margin: 6px' ]]`
@@ -403,7 +396,7 @@ export function getFontSizeValueInScope(cssProperties) {
403
396
 
404
397
  /**
405
398
  * Attempts to remove all non-essential words & characters from a style block.
406
- * Including selectors and queries
399
+ * Including selectors and queries.
407
400
  * @param styleString string of css properties
408
401
  */
409
402
  export function splitCssProperties(styleString) {
@@ -418,8 +411,8 @@ export function splitCssProperties(styleString) {
418
411
  }
419
412
 
420
413
  /**
421
- * returns whether the current string is a token value
422
- * @param originalVaue string representing a css property value e.g 1em, 12px
414
+ * Returns whether the current string is a token value.
415
+ * @param originalVaue string representing a css property value e.g 1em, 12px.
423
416
  */
424
417
  export function isTokenValueString(originalValue) {
425
418
  return originalValue.startsWith('${token(') && originalValue.endsWith('}');
@@ -433,19 +426,27 @@ export function includesTokenString(originalValue) {
433
426
  *
434
427
  * -> for pixels this '8px'
435
428
  * -> for weights '400'
436
- * -> for family 'Arial'
429
+ * -> for family 'Arial'.
437
430
  *
438
431
  * @internal
439
432
  */
440
433
  export function normaliseValue(propertyName, value) {
441
- const isFontWeightOrFamily = /fontWeight|fontFamily/.test(propertyName);
434
+ const isFontStringProperty = /fontWeight|fontFamily|fontStyle/.test(propertyName);
435
+ const isLineHeight = /lineHeight/.test(propertyName);
442
436
  const propertyValue = typeof value === 'string' ? value.trim() : value;
443
- const lookupValue = isFontWeightOrFamily ? propertyValue : typeof propertyValue === 'string' ? propertyValue : `${propertyValue}px`;
437
+ let lookupValue;
438
+ if (isFontStringProperty) {
439
+ lookupValue = `${propertyValue}`;
440
+ } else if (isLineHeight) {
441
+ lookupValue = value === 1 ? `${propertyValue}` : `${propertyValue}px`;
442
+ } else {
443
+ lookupValue = typeof propertyValue === 'string' ? propertyValue : `${propertyValue}px`;
444
+ }
444
445
  return lookupValue;
445
446
  }
446
447
  export function findTokenNameByPropertyValue(propertyName, value) {
447
448
  const lookupValue = normaliseValue(propertyName, value);
448
- const tokenName = isShapeProperty(propertyName) ? isBorderSizeProperty(propertyName) ? borderWidthValueToToken[lookupValue] : radiusValueToToken[lookupValue] : isTypographyProperty(propertyName) ? typographyValueToToken[propertyName][lookupValue] : spacingValueToToken[lookupValue];
449
+ const tokenName = isShapeProperty(propertyName) ? isBorderSizeProperty(propertyName) ? borderWidthValueToToken[lookupValue] : radiusValueToToken[lookupValue] : spacingValueToToken[lookupValue];
449
450
  if (!tokenName) {
450
451
  return undefined;
451
452
  }
@@ -454,9 +455,9 @@ export function findTokenNameByPropertyValue(propertyName, value) {
454
455
 
455
456
  /**
456
457
  * Returns a stringifiable node with the token expression corresponding to its matching token.
457
- * if no token found for the pair the function returns undefined
458
- * @param propertyName string camelCased css property
459
- * @param value the computed value e.g '8px' -> '8'
458
+ * If no token found for the pair the function returns undefined.
459
+ * @param propertyName string camelCased css property.
460
+ * @param value The computed value e.g '8px' -> '8'.
460
461
  */
461
462
  export function getTokenReplacement(propertyName, value) {
462
463
  const tokenName = findTokenNameByPropertyValue(propertyName, value);
@@ -466,17 +467,20 @@ export function getTokenReplacement(propertyName, value) {
466
467
  const fallbackValue = normaliseValue(propertyName, value);
467
468
  return getTokenNodeForValue(propertyName, fallbackValue);
468
469
  }
469
- export function getFontSizeFromNode(parentNode, context) {
470
- const fontSizeNode = parentNode.properties.find(node => {
470
+ export function getPropertyNodeFromParent(property, parentNode) {
471
+ const propertyNode = parentNode.properties.find(node => {
471
472
  if (!isNodeOfType(node, 'Property')) {
472
473
  return;
473
474
  }
474
475
  if (!isNodeOfType(node.key, 'Identifier')) {
475
476
  return;
476
477
  }
477
- return node.key.name === 'fontSize';
478
+ return node.key.name === property;
478
479
  });
479
- const fontSizeValue = isNodeOfType(fontSizeNode, 'Property') ? getValue(fontSizeNode.value, context) : null;
480
- const fontSize = Array.isArray(fontSizeValue) ? fontSizeValue[0] : fontSizeValue;
481
- return fontSize;
480
+ return propertyNode;
481
+ }
482
+ export function getValueForPropertyNode(propertyNode, context) {
483
+ const propertyValueRaw = isNodeOfType(propertyNode, 'Property') ? getValue(propertyNode.value, context) : null;
484
+ const propertyValue = Array.isArray(propertyValueRaw) ? propertyValueRaw[0] : propertyValueRaw;
485
+ return propertyValue;
482
486
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::23062a8759ba919facf30a402e5546bd>>
3
+ * @codegen <<SignedSource::c283cd7ede5e813a9119cd707d339273>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -32,6 +32,7 @@ import useHeadingLevelInSpotlightCard from './use-heading-level-in-spotlight-car
32
32
  import useHrefInLinkItem from './use-href-in-link-item';
33
33
  import usePrimitives from './use-primitives';
34
34
  import usePrimitivesText from './use-primitives-text';
35
+ import useTokensTypography from './use-tokens-typography';
35
36
  import useVisuallyHidden from './use-visually-hidden';
36
37
  export default {
37
38
  'consistent-css-prop-usage': consistentCssPropUsage,
@@ -63,5 +64,6 @@ export default {
63
64
  'use-href-in-link-item': useHrefInLinkItem,
64
65
  'use-primitives': usePrimitives,
65
66
  'use-primitives-text': usePrimitivesText,
67
+ 'use-tokens-typography': useTokensTypography,
66
68
  'use-visually-hidden': useVisuallyHidden
67
69
  };
@@ -1,10 +1,13 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
-
2
+ const JSX_IDENTIFIER = 'JSXIdentifier';
3
3
  /**
4
4
  * Given a component name finds its JSX usages and performs some
5
5
  * additional validations to ensure transformation can be done correctly
6
+ *
7
+ * anyOrder: if true, the order of the references doesn't matter (JSX or style declaration)
6
8
  */
7
- export const findValidJsxUsageToTransform = (componentName, scope) => {
9
+ export const findValidJsxUsageToTransform = (componentName, scope, anyOrder = false) => {
10
+ var _variableDeclaration$;
8
11
  const variableDeclaration = scope.variables.find(v => v.name === componentName);
9
12
  if (!variableDeclaration) {
10
13
  return;
@@ -18,7 +21,18 @@ export const findValidJsxUsageToTransform = (componentName, scope) => {
18
21
  if (variableDeclaration.references.length !== 2) {
19
22
  return;
20
23
  }
21
- const jsxUsage = variableDeclaration.references[1].identifier;
24
+ let jsxUsage = (_variableDeclaration$ = variableDeclaration.references[1]) === null || _variableDeclaration$ === void 0 ? void 0 : _variableDeclaration$.identifier;
25
+ if (anyOrder) {
26
+ const [firstIdentifier, secondIdentifier] = variableDeclaration.references.map(ref => ref === null || ref === void 0 ? void 0 : ref.identifier);
27
+ // Check if the first reference is a JSXOpeningElement and the second is not or vice versa
28
+ if (isNodeOfType(firstIdentifier, JSX_IDENTIFIER) && !isNodeOfType(secondIdentifier, JSX_IDENTIFIER)) {
29
+ jsxUsage = firstIdentifier;
30
+ } else if (isNodeOfType(secondIdentifier, JSX_IDENTIFIER) && !isNodeOfType(firstIdentifier, JSX_IDENTIFIER)) {
31
+ jsxUsage = secondIdentifier;
32
+ } else {
33
+ return;
34
+ }
35
+ }
22
36
  if (!isNodeOfType(jsxUsage, 'JSXIdentifier')) {
23
37
  return;
24
38
  }
@@ -57,7 +57,8 @@ export const CompiledStyled = {
57
57
  success: false
58
58
  };
59
59
  }
60
- const styledComponentJsxRef = findValidJsxUsageToTransform(styledComponentVariableRef.id.name, context.getScope());
60
+ const anyOrder = config.patterns.includes('jsx-order-fix');
61
+ const styledComponentJsxRef = findValidJsxUsageToTransform(styledComponentVariableRef.id.name, context.getScope(), anyOrder);
61
62
  if (!styledComponentJsxRef) {
62
63
  return {
63
64
  success: false
@@ -1,5 +1,6 @@
1
1
  const defaults = {
2
- patterns: ['paragraph-elements', 'span-elements', 'strong-elements', 'emphasis-elements']
2
+ patterns: ['paragraph-elements', 'span-elements', 'strong-elements', 'emphasis-elements'],
3
+ inheritColor: false
3
4
  };
4
5
  export const getConfig = overrides => {
5
6
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
@@ -1,6 +1,5 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
2
  import * as ast from '../../../ast-nodes';
3
-
4
3
  // Rename data-testid prop to testId if present
5
4
  export function updateTestIdAttributeFix(node, fixer) {
6
5
  const testIdAttr = ast.JSXElement.getAttributeByName(node, 'data-testid');
@@ -8,10 +7,18 @@ export function updateTestIdAttributeFix(node, fixer) {
8
7
  return ast.JSXAttribute.updateName(testIdAttr, 'testId', fixer);
9
8
  }
10
9
  }
10
+
11
+ // Add color="inherit" prop depending on config
12
+ export function addColorInheritAttributeFix(node, config, fixer) {
13
+ if (!config.inheritColor) {
14
+ return;
15
+ }
16
+ return ast.JSXElement.addAttribute(node, 'color', 'inherit', fixer);
17
+ }
11
18
  export const allowedAttrs = ['id', 'data-testid', 'key'];
12
19
 
13
20
  // Only allow elements with strings as children
14
- // The use of `FormattedMessage` component and `formatMessage` are allowed as these are used for i18n
21
+ // The use of `<FormattedMessage ... />` component and `{formatMessage(...)}` are allowed as these are used for i18n
15
22
  export function hasTextChildrenOnly(node) {
16
23
  var _node$children;
17
24
  return (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.every(child => {
@@ -3,7 +3,7 @@
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import * as ast from '../../../ast-nodes';
5
5
  import { upsertImportDeclaration } from '../../use-primitives/transformers/emotion-css/upsert-import-declaration';
6
- import { allowedAttrs, updateTestIdAttributeFix } from './common';
6
+ import { addColorInheritAttributeFix, allowedAttrs, updateTestIdAttributeFix } from './common';
7
7
  export const EmphasisElements = {
8
8
  lint(node, {
9
9
  context,
@@ -26,7 +26,8 @@ export const EmphasisElements = {
26
26
  suggest: [{
27
27
  desc: `Convert to Text`,
28
28
  fix: EmphasisElements._fix(node, {
29
- context
29
+ context,
30
+ config
30
31
  })
31
32
  }]
32
33
  });
@@ -56,7 +57,8 @@ export const EmphasisElements = {
56
57
  return true;
57
58
  },
58
59
  _fix(node, {
59
- context
60
+ context,
61
+ config
60
62
  }) {
61
63
  return fixer => {
62
64
  const importFix = upsertImportDeclaration({
@@ -65,8 +67,9 @@ export const EmphasisElements = {
65
67
  }, context, fixer);
66
68
  const elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
67
69
  const asAttributeFix = ast.JSXElement.addAttribute(node, 'as', 'em', fixer);
70
+ const colorAttributeFix = addColorInheritAttributeFix(node, config, fixer);
68
71
  const testAttributeFix = updateTestIdAttributeFix(node, fixer);
69
- return [importFix, ...elementNameFixes, asAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
72
+ return [importFix, ...elementNameFixes, asAttributeFix, colorAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
70
73
  };
71
74
  }
72
75
  };
@@ -3,7 +3,7 @@
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import * as ast from '../../../ast-nodes';
5
5
  import { upsertImportDeclaration } from '../../use-primitives/transformers/emotion-css/upsert-import-declaration';
6
- import { allowedAttrs, updateTestIdAttributeFix } from './common';
6
+ import { addColorInheritAttributeFix, allowedAttrs, updateTestIdAttributeFix } from './common';
7
7
  export const ParagraphElements = {
8
8
  lint(node, {
9
9
  context,
@@ -44,6 +44,7 @@ export const ParagraphElements = {
44
44
  desc: 'Convert to Text and Stack',
45
45
  fix: ParagraphElements._fixMultiple(node, {
46
46
  context,
47
+ config,
47
48
  refs
48
49
  })
49
50
  }]
@@ -55,7 +56,8 @@ export const ParagraphElements = {
55
56
  suggest: [{
56
57
  desc: 'Convert to Text',
57
58
  fix: ParagraphElements._fixSingle(node, {
58
- context
59
+ context,
60
+ config
59
61
  })
60
62
  }]
61
63
  });
@@ -122,6 +124,13 @@ export const ParagraphElements = {
122
124
  }
123
125
  };
124
126
  }
127
+ } else if (!ast.JSXElement.hasAllowedAttrsOnly(node, allowedAttrs)) {
128
+ return {
129
+ success: false,
130
+ refs: {
131
+ siblings
132
+ }
133
+ };
125
134
  }
126
135
  const importDeclaration = ast.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/primitives');
127
136
 
@@ -142,7 +151,8 @@ export const ParagraphElements = {
142
151
  };
143
152
  },
144
153
  _fixSingle(node, {
145
- context
154
+ context,
155
+ config
146
156
  }) {
147
157
  return fixer => {
148
158
  const importFix = upsertImportDeclaration({
@@ -150,13 +160,16 @@ export const ParagraphElements = {
150
160
  specifiers: ['Text']
151
161
  }, context, fixer);
152
162
  const elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
163
+ const asAttributeFix = ast.JSXElement.addAttribute(node, 'as', 'p', fixer);
164
+ const colorAttributeFix = addColorInheritAttributeFix(node, config, fixer);
153
165
  const testAttributeFix = updateTestIdAttributeFix(node, fixer);
154
- return [importFix, ...elementNameFixes, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
166
+ return [importFix, ...elementNameFixes, asAttributeFix, colorAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
155
167
  };
156
168
  },
157
169
 
158
170
  _fixMultiple(node, {
159
171
  context,
172
+ config,
160
173
  refs
161
174
  }) {
162
175
  return fixer => {
@@ -172,8 +185,10 @@ export const ParagraphElements = {
172
185
  const siblingFixes = refs.siblings.map(sibling => {
173
186
  if (isNodeOfType(sibling, 'JSXElement')) {
174
187
  const elementNameFixes = ast.JSXElement.updateName(sibling, 'Text', fixer);
188
+ const asAttributeFix = ast.JSXElement.addAttribute(sibling, 'as', 'p', fixer);
189
+ const colorAttributeFix = addColorInheritAttributeFix(sibling, config, fixer);
175
190
  const testAttributeFix = updateTestIdAttributeFix(sibling, fixer);
176
- return [...elementNameFixes, testAttributeFix];
191
+ return [...elementNameFixes, asAttributeFix, colorAttributeFix, testAttributeFix];
177
192
  }
178
193
  return undefined;
179
194
  }).flat();
@@ -3,7 +3,7 @@
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import * as ast from '../../../ast-nodes';
5
5
  import { upsertImportDeclaration } from '../../use-primitives/transformers/emotion-css/upsert-import-declaration';
6
- import { allowedAttrs, hasTextChildrenOnly, updateTestIdAttributeFix } from './common';
6
+ import { addColorInheritAttributeFix, allowedAttrs, hasTextChildrenOnly, updateTestIdAttributeFix } from './common';
7
7
  export const SpanElements = {
8
8
  lint(node, {
9
9
  context,
@@ -26,7 +26,8 @@ export const SpanElements = {
26
26
  suggest: [{
27
27
  desc: `Convert to Text`,
28
28
  fix: SpanElements._fix(node, {
29
- context
29
+ context,
30
+ config
30
31
  })
31
32
  }]
32
33
  });
@@ -61,7 +62,8 @@ export const SpanElements = {
61
62
  return true;
62
63
  },
63
64
  _fix(node, {
64
- context
65
+ context,
66
+ config
65
67
  }) {
66
68
  return fixer => {
67
69
  const importFix = upsertImportDeclaration({
@@ -69,9 +71,9 @@ export const SpanElements = {
69
71
  specifiers: ['Text']
70
72
  }, context, fixer);
71
73
  const elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
72
- const variantAttributeFix = ast.JSXElement.addAttribute(node, 'variant', 'ui', fixer);
74
+ const colorAttributeFix = addColorInheritAttributeFix(node, config, fixer);
73
75
  const testAttributeFix = updateTestIdAttributeFix(node, fixer);
74
- return [importFix, ...elementNameFixes, variantAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
76
+ return [importFix, ...elementNameFixes, colorAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
75
77
  };
76
78
  }
77
79
  };
@@ -3,7 +3,7 @@
3
3
  import { isNodeOfType } from 'eslint-codemod-utils';
4
4
  import * as ast from '../../../ast-nodes';
5
5
  import { upsertImportDeclaration } from '../../use-primitives/transformers/emotion-css/upsert-import-declaration';
6
- import { allowedAttrs, updateTestIdAttributeFix } from './common';
6
+ import { addColorInheritAttributeFix, allowedAttrs, updateTestIdAttributeFix } from './common';
7
7
  export const StrongElements = {
8
8
  lint(node, {
9
9
  context,
@@ -26,7 +26,8 @@ export const StrongElements = {
26
26
  suggest: [{
27
27
  desc: `Convert to Text`,
28
28
  fix: StrongElements._fix(node, {
29
- context
29
+ context,
30
+ config
30
31
  })
31
32
  }]
32
33
  });
@@ -56,7 +57,8 @@ export const StrongElements = {
56
57
  return true;
57
58
  },
58
59
  _fix(node, {
59
- context
60
+ context,
61
+ config
60
62
  }) {
61
63
  return fixer => {
62
64
  const importFix = upsertImportDeclaration({
@@ -65,8 +67,9 @@ export const StrongElements = {
65
67
  }, context, fixer);
66
68
  const elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
67
69
  const asAttributeFix = ast.JSXElement.addAttribute(node, 'as', 'strong', fixer);
70
+ const colorAttributeFix = addColorInheritAttributeFix(node, config, fixer);
68
71
  const testAttributeFix = updateTestIdAttributeFix(node, fixer);
69
- return [importFix, ...elementNameFixes, asAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
72
+ return [importFix, ...elementNameFixes, asAttributeFix, colorAttributeFix, testAttributeFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
70
73
  };
71
74
  }
72
75
  };
@@ -0,0 +1,20 @@
1
+ export const ruleSchema = {
2
+ type: 'array',
3
+ items: {
4
+ type: 'object',
5
+ properties: {
6
+ failSilently: {
7
+ type: 'boolean'
8
+ }
9
+ }
10
+ }
11
+ };
12
+ const defaultConfig = {
13
+ failSilently: false
14
+ };
15
+ export const getConfig = overrides => {
16
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
17
+ // start with an empty object, then merge in the defaults, then merge in overrides.
18
+ // The empty object is returned, as well as modified in place
19
+ return Object.assign({}, defaultConfig, overrides);
20
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ESLint rules should NEVER throw exceptions, because that breaks the VSCode ESLint server
3
+ * (and probably the IntelliJ one too), which causes linting to fail in a file.
4
+ *
5
+ * It also breaks CI, which was the reason this error boundary was added. It's a final
6
+ * catch all.
7
+ */
8
+ export const errorBoundary = (func, {
9
+ config
10
+ }) => {
11
+ try {
12
+ func();
13
+ } catch (err) {
14
+ if (!config.failSilently) {
15
+ // eslint-disable-next-line no-console
16
+ console.warn(err);
17
+ }
18
+ }
19
+ };