@atlaskit/eslint-plugin-design-system 8.37.2 → 8.38.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 (74) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -0
  3. package/constellation/index/usage.mdx +1 -0
  4. package/constellation/use-tokens-space/usage.mdx +30 -0
  5. package/dist/cjs/ast-nodes/object-entry.js +35 -0
  6. package/dist/cjs/ast-nodes/object.js +12 -0
  7. package/dist/cjs/presets/all.codegen.js +2 -1
  8. package/dist/cjs/rules/index.codegen.js +3 -1
  9. package/dist/cjs/rules/use-primitives/utils/validate-styles.js +11 -2
  10. package/dist/cjs/rules/use-tokens-space/index.js +54 -0
  11. package/dist/cjs/rules/use-tokens-space/transformers/index.js +12 -0
  12. package/dist/cjs/rules/use-tokens-space/transformers/style-property/index.js +130 -0
  13. package/dist/cjs/rules/use-tokens-space/transformers/style-property/style-map.js +80 -0
  14. package/dist/cjs/rules/use-tokens-space/transformers/style-property/supported.js +14 -0
  15. package/dist/cjs/rules/use-tokens-space/transformers/style-property/upsert-import-declaration.js +37 -0
  16. package/dist/cjs/rules/use-tokens-space/utils/index.js +12 -0
  17. package/dist/cjs/rules/use-tokens-space/utils/is-string-or-number.js +9 -0
  18. package/dist/es2019/ast-nodes/object-entry.js +37 -3
  19. package/dist/es2019/ast-nodes/object.js +12 -0
  20. package/dist/es2019/presets/all.codegen.js +2 -1
  21. package/dist/es2019/rules/index.codegen.js +3 -1
  22. package/dist/es2019/rules/use-primitives/utils/validate-styles.js +11 -2
  23. package/dist/es2019/rules/use-tokens-space/index.js +38 -0
  24. package/dist/es2019/rules/use-tokens-space/transformers/index.js +1 -0
  25. package/dist/es2019/rules/use-tokens-space/transformers/style-property/index.js +121 -0
  26. package/dist/es2019/rules/use-tokens-space/transformers/style-property/style-map.js +152 -0
  27. package/dist/es2019/rules/use-tokens-space/transformers/style-property/supported.js +8 -0
  28. package/dist/es2019/rules/use-tokens-space/transformers/style-property/upsert-import-declaration.js +30 -0
  29. package/dist/es2019/rules/use-tokens-space/utils/index.js +1 -0
  30. package/dist/es2019/rules/use-tokens-space/utils/is-string-or-number.js +3 -0
  31. package/dist/esm/ast-nodes/object-entry.js +37 -3
  32. package/dist/esm/ast-nodes/object.js +12 -0
  33. package/dist/esm/presets/all.codegen.js +2 -1
  34. package/dist/esm/rules/index.codegen.js +3 -1
  35. package/dist/esm/rules/use-primitives/utils/validate-styles.js +11 -2
  36. package/dist/esm/rules/use-tokens-space/index.js +48 -0
  37. package/dist/esm/rules/use-tokens-space/transformers/index.js +1 -0
  38. package/dist/esm/rules/use-tokens-space/transformers/style-property/index.js +120 -0
  39. package/dist/esm/rules/use-tokens-space/transformers/style-property/style-map.js +73 -0
  40. package/dist/esm/rules/use-tokens-space/transformers/style-property/supported.js +8 -0
  41. package/dist/esm/rules/use-tokens-space/transformers/style-property/upsert-import-declaration.js +29 -0
  42. package/dist/esm/rules/use-tokens-space/utils/index.js +1 -0
  43. package/dist/esm/rules/use-tokens-space/utils/is-string-or-number.js +3 -0
  44. package/dist/types/ast-nodes/object-entry.d.ts +12 -2
  45. package/dist/types/ast-nodes/object.d.ts +1 -0
  46. package/dist/types/index.codegen.d.ts +1 -0
  47. package/dist/types/presets/all.codegen.d.ts +2 -1
  48. package/dist/types/rules/index.codegen.d.ts +5 -4
  49. package/dist/types/rules/use-tokens-space/index.d.ts +3 -0
  50. package/dist/types/rules/use-tokens-space/transformers/index.d.ts +1 -0
  51. package/dist/types/rules/use-tokens-space/transformers/style-property/index.d.ts +26 -0
  52. package/dist/types/rules/use-tokens-space/transformers/style-property/style-map.d.ts +7 -0
  53. package/dist/types/rules/use-tokens-space/transformers/style-property/supported.d.ts +6 -0
  54. package/dist/types/rules/use-tokens-space/transformers/style-property/upsert-import-declaration.d.ts +14 -0
  55. package/dist/types/rules/use-tokens-space/utils/index.d.ts +1 -0
  56. package/dist/types/rules/use-tokens-space/utils/is-string-or-number.d.ts +1 -0
  57. package/dist/types/rules/use-visually-hidden/constants.d.ts +1 -1
  58. package/dist/types/rules/utils/create-rule.d.ts +1 -1
  59. package/dist/types-ts4.5/ast-nodes/object-entry.d.ts +12 -2
  60. package/dist/types-ts4.5/ast-nodes/object.d.ts +1 -0
  61. package/dist/types-ts4.5/index.codegen.d.ts +1 -0
  62. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
  63. package/dist/types-ts4.5/rules/index.codegen.d.ts +5 -4
  64. package/dist/types-ts4.5/rules/use-tokens-space/index.d.ts +3 -0
  65. package/dist/types-ts4.5/rules/use-tokens-space/transformers/index.d.ts +1 -0
  66. package/dist/types-ts4.5/rules/use-tokens-space/transformers/style-property/index.d.ts +26 -0
  67. package/dist/types-ts4.5/rules/use-tokens-space/transformers/style-property/style-map.d.ts +7 -0
  68. package/dist/types-ts4.5/rules/use-tokens-space/transformers/style-property/supported.d.ts +6 -0
  69. package/dist/types-ts4.5/rules/use-tokens-space/transformers/style-property/upsert-import-declaration.d.ts +14 -0
  70. package/dist/types-ts4.5/rules/use-tokens-space/utils/index.d.ts +1 -0
  71. package/dist/types-ts4.5/rules/use-tokens-space/utils/is-string-or-number.d.ts +1 -0
  72. package/dist/types-ts4.5/rules/use-visually-hidden/constants.d.ts +1 -1
  73. package/dist/types-ts4.5/rules/utils/create-rule.d.ts +1 -1
  74. package/package.json +3 -3
@@ -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::c283cd7ede5e813a9119cd707d339273>>
3
+ * @codegen <<SignedSource::d1c25758089a050334359276ede0ca3a>>
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 useTokensSpace from './use-tokens-space';
35
36
  import useTokensTypography from './use-tokens-typography';
36
37
  import useVisuallyHidden from './use-visually-hidden';
37
38
  export default {
@@ -64,6 +65,7 @@ export default {
64
65
  'use-href-in-link-item': useHrefInLinkItem,
65
66
  'use-primitives': usePrimitives,
66
67
  'use-primitives-text': usePrimitivesText,
68
+ 'use-tokens-space': useTokensSpace,
67
69
  'use-tokens-typography': useTokensTypography,
68
70
  'use-visually-hidden': useVisuallyHidden
69
71
  };
@@ -86,7 +86,6 @@ const isTokenCall = node => {
86
86
  return false;
87
87
  }
88
88
  const token = ast.FunctionCall.getArgumentAtPos(node, 0);
89
- const fallback = ast.FunctionCall.getArgumentAtPos(node, 1);
90
89
  if (!token || token.type !== 'Literal') {
91
90
  return false;
92
91
  }
@@ -97,7 +96,17 @@ const isTokenCall = node => {
97
96
  }
98
97
 
99
98
  // Not all `token()` calls have a fall back. This is fine, but if there is a fallback, make sure it's the same as the fallback xcss will use
100
- if (fallback && fallback.type === 'Literal') {
99
+ if (node.arguments.length === 2) {
100
+ const fallback = ast.FunctionCall.getArgumentAtPos(node, 1);
101
+
102
+ // `getArgumentAtPos` is only able to understand `Literal` and `ObjectExpression` statements
103
+ // If there are 2 args, but `fallback` is undefined, then the fallback is something wild, like `token('space.100, `${gridSize * rem(3)`})`
104
+ if (!fallback) {
105
+ return false;
106
+ }
107
+ if (fallback.type !== 'Literal') {
108
+ return false;
109
+ }
101
110
  if (spaceTokenMap[fallback.value] !== token.value) {
102
111
  return false;
103
112
  }
@@ -0,0 +1,38 @@
1
+ import { createLintRule } from '../utils/create-rule';
2
+ import { StyleProperty } from './transformers';
3
+ const rule = createLintRule({
4
+ meta: {
5
+ name: 'use-tokens-space',
6
+ type: 'problem',
7
+ fixable: 'code',
8
+ hasSuggestions: true,
9
+ docs: {
10
+ description: 'Enforces usage of space design tokens rather than hard-coded values.',
11
+ recommended: false,
12
+ severity: 'error'
13
+ },
14
+ messages: {
15
+ noRawSpacingValues: 'The use of spacing primitives or tokens is preferred over the direct application of spacing properties.'
16
+ }
17
+ },
18
+ create(context) {
19
+ return {
20
+ 'CallExpression[callee.name="css"] ObjectExpression Property': node => StyleProperty.lint(node, {
21
+ context
22
+ }),
23
+ 'CallExpression[callee.name="keyframes"] ObjectExpression Property': node => StyleProperty.lint(node, {
24
+ context
25
+ }),
26
+ 'CallExpression[callee.name="cssMap"] ObjectExpression Property': node => StyleProperty.lint(node, {
27
+ context
28
+ }),
29
+ 'CallExpression[callee.object.name=styled] ObjectExpression Property': node => StyleProperty.lint(node, {
30
+ context
31
+ }),
32
+ 'CallExpression[callee.object.name=styled2] ObjectExpression Property': node => StyleProperty.lint(node, {
33
+ context
34
+ })
35
+ };
36
+ }
37
+ });
38
+ export default rule;
@@ -0,0 +1 @@
1
+ export { StyleProperty } from './style-property';
@@ -0,0 +1,121 @@
1
+ /* eslint-disable @repo/internal/react/require-jsdoc */
2
+
3
+ import { isNodeOfType } from 'eslint-codemod-utils';
4
+ import * as ast from '../../../../ast-nodes';
5
+ import { isStringOrNumber } from '../../utils';
6
+ import { styleMap } from './style-map';
7
+ import supported from './supported';
8
+ import { upsertImportDeclaration } from './upsert-import-declaration';
9
+ const messageId = 'noRawSpacingValues';
10
+ export const StyleProperty = {
11
+ lint(node, {
12
+ context
13
+ }) {
14
+ // Check whether all criteria needed to make a transformation are met
15
+ const {
16
+ success,
17
+ ref
18
+ } = StyleProperty._check(node);
19
+ if (!success) {
20
+ return;
21
+ }
22
+ context.report({
23
+ node: ref.node.value,
24
+ messageId,
25
+ fix: ref.token ? StyleProperty._fix(ref, context) : undefined
26
+ });
27
+ },
28
+ _check(node) {
29
+ if (!isNodeOfType(node, 'Property')) {
30
+ return {
31
+ success: false,
32
+ ref: undefined
33
+ };
34
+ }
35
+
36
+ /**
37
+ * Currently, we support values like:
38
+ * ```
39
+ * {
40
+ * padding: '8px', // value.type is Literal
41
+ * margin: -8, // value.type is UnaryExpression
42
+ * }
43
+ * ```
44
+ */
45
+ if (!(isNodeOfType(node.value, 'Literal') || isNodeOfType(node.value, 'UnaryExpression'))) {
46
+ return {
47
+ success: false,
48
+ ref: undefined
49
+ };
50
+ }
51
+ const {
52
+ value: property
53
+ } = ast.ObjectEntry.getProperty(node);
54
+
55
+ // Bail if the property is not `padding`, `margin`, etc
56
+ if (!property || !styleMap[property]) {
57
+ return {
58
+ success: false,
59
+ ref: undefined
60
+ };
61
+ }
62
+ const value = ast.ObjectEntry.getValue(node);
63
+
64
+ // This is mainly useful as a type guard, so the checks after don't have to have duplicate checks for other types.
65
+ if (!isStringOrNumber(value)) {
66
+ return {
67
+ success: false,
68
+ ref: undefined
69
+ };
70
+ }
71
+
72
+ // ignore CSS vars. See: https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo/pull-requests/74844/overview?commentId=6741571
73
+ if (value.toString().startsWith('var(')) {
74
+ return {
75
+ success: false,
76
+ ref: undefined
77
+ };
78
+ }
79
+
80
+ // There are valid values to ignore, such as `margin: auto`
81
+ if (supported.values.ignore.includes(value)) {
82
+ return {
83
+ success: false,
84
+ ref: undefined
85
+ };
86
+ }
87
+
88
+ // Don't report on stuff like `padding: '8px 16px'`.
89
+ // We may iterate to handle values like this in future.
90
+ if (value.toString().includes(' ')) {
91
+ return {
92
+ success: false,
93
+ ref: undefined
94
+ };
95
+ }
96
+ const ref = {
97
+ node,
98
+ token: styleMap[property][value],
99
+ fallback: value
100
+ };
101
+ return {
102
+ success: true,
103
+ ref
104
+ };
105
+ },
106
+ /**
107
+ * All required validation steps have been taken care of before this
108
+ * transformer is called, so it just goes ahead providing all necessary fixes
109
+ */
110
+ _fix(ref, context) {
111
+ return fixer => {
112
+ const importFix = upsertImportDeclaration({
113
+ module: '@atlaskit/tokens',
114
+ specifiers: ['token']
115
+ }, context, fixer);
116
+ const tokenCall = ref.fallback ? `token('${ref.token}', '${ref.fallback}')` : `token('${ref.token}')`;
117
+ const tokenFix = fixer.replaceText(ref.node.value, tokenCall);
118
+ return [importFix, tokenFix].filter(fix => Boolean(fix)); // Some of the transformers can return arrays with undefined, so filter them out
119
+ };
120
+ }
121
+ };
@@ -0,0 +1,152 @@
1
+ // TODO: https://product-fabric.atlassian.net/browse/DSP-16054
2
+ const tokenMap = {
3
+ '-2px': 'space.negative.025',
4
+ '-4px': 'space.negative.050',
5
+ '-6px': 'space.negative.075',
6
+ '-8px': 'space.negative.100',
7
+ '-12px': 'space.negative.150',
8
+ '-16px': 'space.negative.200',
9
+ '-20px': 'space.negative.250',
10
+ '-24px': 'space.negative.300',
11
+ '-32px': 'space.negative.400',
12
+ [-2]: 'space.negative.025',
13
+ [-4]: 'space.negative.050',
14
+ [-6]: 'space.negative.075',
15
+ [-8]: 'space.negative.100',
16
+ [-12]: 'space.negative.150',
17
+ [-16]: 'space.negative.200',
18
+ [-20]: 'space.negative.250',
19
+ [-24]: 'space.negative.300',
20
+ [-32]: 'space.negative.400',
21
+ // '0px': 'space.0', // Don't map 0 to match the implementation of `ensure-design-token-usage`
22
+ '2px': 'space.025',
23
+ '4px': 'space.050',
24
+ '6px': 'space.075',
25
+ '8px': 'space.100',
26
+ '12px': 'space.150',
27
+ '16px': 'space.200',
28
+ '20px': 'space.250',
29
+ '24px': 'space.300',
30
+ '32px': 'space.400',
31
+ '40px': 'space.500',
32
+ '48px': 'space.600',
33
+ '64px': 'space.800',
34
+ '80px': 'space.1000',
35
+ // 0: 'space.0', // Don't map 0 to match the implementation of `ensure-design-token-usage`
36
+ 2: 'space.025',
37
+ 4: 'space.050',
38
+ 6: 'space.075',
39
+ 8: 'space.100',
40
+ 12: 'space.150',
41
+ 16: 'space.200',
42
+ 20: 'space.250',
43
+ 24: 'space.300',
44
+ 32: 'space.400',
45
+ 40: 'space.500',
46
+ 48: 'space.600',
47
+ 64: 'space.800',
48
+ 80: 'space.1000',
49
+ '-0.125rem': 'space.negative.025',
50
+ '-0.25rem': 'space.negative.050',
51
+ '-0.375rem': 'space.negative.075',
52
+ '-0.5rem': 'space.negative.100',
53
+ '-0.75rem': 'space.negative.150',
54
+ '-1rem': 'space.negative.200',
55
+ '-1.25rem': 'space.negative.250',
56
+ '-1.5rem': 'space.negative.300',
57
+ '-2rem': 'space.negative.400',
58
+ '0.125rem': 'space.025',
59
+ '0.25rem': 'space.050',
60
+ '0.375rem': 'space.075',
61
+ '0.5rem': 'space.100',
62
+ '0.75rem': 'space.150',
63
+ '1rem': 'space.200',
64
+ '1.25rem': 'space.250',
65
+ '1.5rem': 'space.300',
66
+ '2rem': 'space.400',
67
+ '2.5rem': 'space.500',
68
+ '3rem': 'space.600',
69
+ '4rem': 'space.800',
70
+ '5rem': 'space.1000',
71
+ '-0.125em': 'space.negative.025',
72
+ '-0.25em': 'space.negative.050',
73
+ '-0.375em': 'space.negative.075',
74
+ '-0.5em': 'space.negative.100',
75
+ '-0.75em': 'space.negative.150',
76
+ '-1em': 'space.negative.200',
77
+ '-1.25em': 'space.negative.250',
78
+ '-1.5em': 'space.negative.300',
79
+ '-2em': 'space.negative.400',
80
+ '0.125em': 'space.025',
81
+ '0.25em': 'space.050',
82
+ '0.375em': 'space.075',
83
+ '0.5em': 'space.100',
84
+ '0.75em': 'space.150',
85
+ '1em': 'space.200',
86
+ '1.25em': 'space.250',
87
+ '1.5em': 'space.300',
88
+ '2em': 'space.400',
89
+ '2.5em': 'space.500',
90
+ '3em': 'space.600',
91
+ '4em': 'space.800',
92
+ '5em': 'space.1000'
93
+ };
94
+ export const styleMap = {
95
+ 'column-gap': tokenMap,
96
+ columnGap: tokenMap,
97
+ gap: tokenMap,
98
+ 'grid-column-gap': tokenMap,
99
+ 'grid-row-gap': tokenMap,
100
+ gridColumnGap: tokenMap,
101
+ gridRowGap: tokenMap,
102
+ 'margin-block-end': tokenMap,
103
+ 'margin-block-start': tokenMap,
104
+ 'margin-block': tokenMap,
105
+ 'margin-bottom': tokenMap,
106
+ 'margin-inline-end': tokenMap,
107
+ 'margin-inline-start': tokenMap,
108
+ 'margin-inline': tokenMap,
109
+ 'margin-left': tokenMap,
110
+ 'margin-right': tokenMap,
111
+ 'margin-top': tokenMap,
112
+ 'outline-offset': tokenMap,
113
+ outlineOffset: tokenMap,
114
+ 'padding-block-end': tokenMap,
115
+ 'padding-block-start': tokenMap,
116
+ 'padding-block': tokenMap,
117
+ 'padding-bottom': tokenMap,
118
+ 'padding-inline-end': tokenMap,
119
+ 'padding-inline-start': tokenMap,
120
+ 'padding-inline': tokenMap,
121
+ 'padding-left': tokenMap,
122
+ 'padding-right': tokenMap,
123
+ 'padding-top': tokenMap,
124
+ 'row-gap': tokenMap,
125
+ rowGap: tokenMap,
126
+ margin: tokenMap,
127
+ marginBlock: tokenMap,
128
+ marginBlockEnd: tokenMap,
129
+ marginBlockStart: tokenMap,
130
+ marginBottom: tokenMap,
131
+ marginInline: tokenMap,
132
+ marginInlineEnd: tokenMap,
133
+ marginInlineStart: tokenMap,
134
+ marginLeft: tokenMap,
135
+ marginRight: tokenMap,
136
+ marginTop: tokenMap,
137
+ padding: tokenMap,
138
+ paddingBlock: tokenMap,
139
+ paddingBlockEnd: tokenMap,
140
+ paddingBlockStart: tokenMap,
141
+ paddingBottom: tokenMap,
142
+ paddingInline: tokenMap,
143
+ paddingInlineEnd: tokenMap,
144
+ paddingInlineStart: tokenMap,
145
+ paddingLeft: tokenMap,
146
+ paddingRight: tokenMap,
147
+ paddingTop: tokenMap
148
+ // bottom: tokenMap,
149
+ // left: tokenMap,
150
+ // right: tokenMap,
151
+ // top: tokenMap,
152
+ };
@@ -0,0 +1,8 @@
1
+ export default {
2
+ values: {
3
+ ignore: ['auto', 'initial', 'inherit', 'unset', 'revert', 'revert-layer', 'none',
4
+ // outline-offset can be set to none
5
+ // Currently the DST opinion is that 0 is valid. It doesn't need to be converted to `space.0`
6
+ 0, '0', '0px', '0em', '0rem']
7
+ }
8
+ };
@@ -0,0 +1,30 @@
1
+ import * as ast from '../../../../ast-nodes';
2
+
3
+ /**
4
+ * Currently this is defined here because it's not very general purpose.
5
+ * If we were to move this to `ast-nodes`, half the implementation would be in `Root`,
6
+ * and the other half would be in `Import`.
7
+ *
8
+ * TODO: Refactor and move to `ast-nodes`
9
+ *
10
+ * Note: It does not handle default imports, namespace imports, or aliased imports.
11
+ */
12
+ export const upsertImportDeclaration = ({
13
+ module,
14
+ specifiers
15
+ }, context, fixer) => {
16
+ // Find any imports that match the packageName
17
+ const root = context.getSourceCode().ast.body;
18
+ const importDeclarations = ast.Root.findImportsByModule(root, module);
19
+
20
+ // The import doesn't exist yet, we can just insert a whole new one
21
+ if (importDeclarations.length === 0) {
22
+ return ast.Root.insertImport(root, {
23
+ module,
24
+ specifiers
25
+ }, fixer);
26
+ }
27
+
28
+ // The import exists so, modify the existing one
29
+ return ast.Import.insertNamedSpecifiers(importDeclarations[0], specifiers, fixer);
30
+ };
@@ -0,0 +1 @@
1
+ export { isStringOrNumber } from './is-string-or-number';
@@ -0,0 +1,3 @@
1
+ export const isStringOrNumber = value => {
2
+ return typeof value === 'string' || typeof value === 'number';
3
+ };
@@ -1,5 +1,40 @@
1
+ /* eslint-disable @repo/internal/react/require-jsdoc */
2
+
1
3
  import { isNodeOfType } from 'eslint-codemod-utils';
2
- var ObjectEntry = {
4
+ export var ObjectEntry = {
5
+ getProperty: function getProperty(node) {
6
+ if (isNodeOfType(node.key, 'Identifier')) {
7
+ return {
8
+ type: 'Identifier',
9
+ value: node.key.name
10
+ };
11
+ }
12
+ if (isNodeOfType(node.key, 'Literal') && node.key.value) {
13
+ return {
14
+ type: 'Literal',
15
+ value: node.key.value.toString()
16
+ };
17
+ }
18
+ return {
19
+ type: undefined,
20
+ value: undefined
21
+ };
22
+ },
23
+ getValue: function getValue(node) {
24
+ // The value is a number, like `-3`
25
+ if (isNodeOfType(node.value, 'UnaryExpression') && isNodeOfType(node.value.argument, 'Literal') && node.value.argument.raw) {
26
+ if (node.value.operator === '-') {
27
+ return -1 * Number.parseInt(node.value.argument.raw);
28
+ }
29
+ return Number.parseInt(node.value.argument.raw);
30
+ }
31
+
32
+ // The value is a string, like `'4px'`
33
+ if (isNodeOfType(node.value, 'Literal') && node.value.value) {
34
+ return node.value.value;
35
+ }
36
+ return undefined;
37
+ },
3
38
  deleteEntry: function deleteEntry(node, context, fixer) {
4
39
  var _lastToken;
5
40
  // context.getSourceCode() is deprecated in favour of context.sourceCode, however this returns undefined for some reason
@@ -31,5 +66,4 @@ var ObjectEntry = {
31
66
  return node.key.name;
32
67
  }
33
68
  }
34
- };
35
- export { ObjectEntry };
69
+ };
@@ -99,6 +99,18 @@ var ASTObjectExpression = {
99
99
  key: identifier(key),
100
100
  value: literal(value)
101
101
  }).toString(), ", "));
102
+ },
103
+ recurse: function recurse(node, callback) {
104
+ node.properties.forEach(function (entry) {
105
+ // Call the callback first, in case the user wants to do something with SpreadElements
106
+ callback(entry);
107
+ if (!isNodeOfType(entry, 'Property')) {
108
+ return;
109
+ }
110
+ if (isNodeOfType(entry.value, 'ObjectExpression')) {
111
+ ASTObjectExpression.recurse(entry.value, callback);
112
+ }
113
+ });
102
114
  }
103
115
  };
104
116
  export { ASTObjectExpression as Object };
@@ -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::d90c2cf5e100daf98915f9467f2e5663>>
3
+ * @codegen <<SignedSource::d95217b658f807294de3c81123068bf1>>
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-space': 'error',
38
39
  '@atlaskit/design-system/use-tokens-typography': 'warn',
39
40
  '@atlaskit/design-system/use-visually-hidden': 'error'
40
41
  }
@@ -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::c283cd7ede5e813a9119cd707d339273>>
3
+ * @codegen <<SignedSource::d1c25758089a050334359276ede0ca3a>>
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 useTokensSpace from './use-tokens-space';
35
36
  import useTokensTypography from './use-tokens-typography';
36
37
  import useVisuallyHidden from './use-visually-hidden';
37
38
  export default {
@@ -64,6 +65,7 @@ export default {
64
65
  'use-href-in-link-item': useHrefInLinkItem,
65
66
  'use-primitives': usePrimitives,
66
67
  'use-primitives-text': usePrimitivesText,
68
+ 'use-tokens-space': useTokensSpace,
67
69
  'use-tokens-typography': useTokensTypography,
68
70
  'use-visually-hidden': useVisuallyHidden
69
71
  };
@@ -84,7 +84,6 @@ var isTokenCall = function isTokenCall(node) {
84
84
  return false;
85
85
  }
86
86
  var token = ast.FunctionCall.getArgumentAtPos(node, 0);
87
- var fallback = ast.FunctionCall.getArgumentAtPos(node, 1);
88
87
  if (!token || token.type !== 'Literal') {
89
88
  return false;
90
89
  }
@@ -95,7 +94,17 @@ var isTokenCall = function isTokenCall(node) {
95
94
  }
96
95
 
97
96
  // Not all `token()` calls have a fall back. This is fine, but if there is a fallback, make sure it's the same as the fallback xcss will use
98
- if (fallback && fallback.type === 'Literal') {
97
+ if (node.arguments.length === 2) {
98
+ var fallback = ast.FunctionCall.getArgumentAtPos(node, 1);
99
+
100
+ // `getArgumentAtPos` is only able to understand `Literal` and `ObjectExpression` statements
101
+ // If there are 2 args, but `fallback` is undefined, then the fallback is something wild, like `token('space.100, `${gridSize * rem(3)`})`
102
+ if (!fallback) {
103
+ return false;
104
+ }
105
+ if (fallback.type !== 'Literal') {
106
+ return false;
107
+ }
99
108
  if (spaceTokenMap[fallback.value] !== token.value) {
100
109
  return false;
101
110
  }
@@ -0,0 +1,48 @@
1
+ import { createLintRule } from '../utils/create-rule';
2
+ import { StyleProperty } from './transformers';
3
+ var rule = createLintRule({
4
+ meta: {
5
+ name: 'use-tokens-space',
6
+ type: 'problem',
7
+ fixable: 'code',
8
+ hasSuggestions: true,
9
+ docs: {
10
+ description: 'Enforces usage of space design tokens rather than hard-coded values.',
11
+ recommended: false,
12
+ severity: 'error'
13
+ },
14
+ messages: {
15
+ noRawSpacingValues: 'The use of spacing primitives or tokens is preferred over the direct application of spacing properties.'
16
+ }
17
+ },
18
+ create: function create(context) {
19
+ return {
20
+ 'CallExpression[callee.name="css"] ObjectExpression Property': function CallExpressionCalleeNameCssObjectExpressionProperty(node) {
21
+ return StyleProperty.lint(node, {
22
+ context: context
23
+ });
24
+ },
25
+ 'CallExpression[callee.name="keyframes"] ObjectExpression Property': function CallExpressionCalleeNameKeyframesObjectExpressionProperty(node) {
26
+ return StyleProperty.lint(node, {
27
+ context: context
28
+ });
29
+ },
30
+ 'CallExpression[callee.name="cssMap"] ObjectExpression Property': function CallExpressionCalleeNameCssMapObjectExpressionProperty(node) {
31
+ return StyleProperty.lint(node, {
32
+ context: context
33
+ });
34
+ },
35
+ 'CallExpression[callee.object.name=styled] ObjectExpression Property': function CallExpressionCalleeObjectNameStyledObjectExpressionProperty(node) {
36
+ return StyleProperty.lint(node, {
37
+ context: context
38
+ });
39
+ },
40
+ 'CallExpression[callee.object.name=styled2] ObjectExpression Property': function CallExpressionCalleeObjectNameStyled2ObjectExpressionProperty(node) {
41
+ return StyleProperty.lint(node, {
42
+ context: context
43
+ });
44
+ }
45
+ };
46
+ }
47
+ });
48
+ export default rule;
@@ -0,0 +1 @@
1
+ export { StyleProperty } from './style-property';