eslint-plugin-primer-react 4.0.3 → 4.0.4-rc.5058fcb

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 (46) hide show
  1. package/.changeset/README.md +3 -3
  2. package/.eslintrc.js +39 -0
  3. package/.github/dependabot.yml +11 -5
  4. package/.github/workflows/add-to-inbox.yml +33 -0
  5. package/.github/workflows/ci.yml +34 -18
  6. package/.github/workflows/release.yml +2 -2
  7. package/.github/workflows/release_canary.yml +8 -5
  8. package/.github/workflows/release_candidate.yml +4 -4
  9. package/.markdownlint-cli2.cjs +26 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierignore +3 -0
  12. package/CHANGELOG.md +7 -1
  13. package/README.md +4 -2
  14. package/docs/rules/a11y-explicit-heading.md +17 -7
  15. package/docs/rules/a11y-tooltip-interactive-trigger.md +6 -2
  16. package/docs/rules/direct-slot-children.md +49 -46
  17. package/docs/rules/new-color-css-vars-have-fallback.md +25 -0
  18. package/docs/rules/new-css-color-vars.md +19 -14
  19. package/docs/rules/no-deprecated-colors.md +91 -82
  20. package/docs/rules/no-system-props.md +12 -5
  21. package/package-lock.json +15583 -0
  22. package/package.json +22 -14
  23. package/src/configs/components.js +19 -19
  24. package/src/configs/recommended.js +9 -8
  25. package/src/index.js +4 -3
  26. package/src/rules/__tests__/a11y-explicit-heading.test.js +22 -25
  27. package/src/rules/__tests__/a11y-tooltip-interactive-trigger.test.js +43 -43
  28. package/src/rules/__tests__/direct-slot-children.test.js +36 -36
  29. package/src/rules/__tests__/new-color-css-vars.test.js +612 -44
  30. package/src/rules/__tests__/new-css-vars-have-fallback.test.js +31 -0
  31. package/src/rules/__tests__/no-deprecated-colors.test.js +66 -66
  32. package/src/rules/__tests__/no-system-props.test.js +51 -51
  33. package/src/rules/a11y-explicit-heading.js +16 -13
  34. package/src/rules/a11y-tooltip-interactive-trigger.js +21 -22
  35. package/src/rules/direct-slot-children.js +11 -11
  36. package/src/rules/new-color-css-vars-have-fallback.js +87 -0
  37. package/src/rules/new-color-css-vars.js +97 -83
  38. package/src/rules/no-deprecated-colors.js +15 -15
  39. package/src/rules/no-system-props.js +21 -21
  40. package/src/url.js +1 -1
  41. package/src/utils/__tests__/flatten-components.test.js +13 -13
  42. package/src/utils/css-variable-map.json +538 -184
  43. package/src/utils/flatten-components.js +11 -11
  44. package/src/utils/is-imported-from.js +1 -1
  45. package/src/utils/new-color-css-vars-map.json +326 -0
  46. /package/.github/{workflows/CODEOWNERS → CODEOWNERS} +0 -0
@@ -7,7 +7,7 @@ const isInteractive = child => {
7
7
  const childName = getJSXOpeningElementName(child.openingElement)
8
8
  return (
9
9
  ['button', 'summary', 'select', 'textarea', 'a', 'input', 'link', 'iconbutton', 'textinput'].includes(
10
- childName.toLowerCase()
10
+ childName.toLowerCase(),
11
11
  ) && !hasDisabledAttr(child)
12
12
  )
13
13
  }
@@ -22,10 +22,9 @@ const isAnchorTag = el => {
22
22
  return openingEl === 'a' || openingEl.toLowerCase() === 'link'
23
23
  }
24
24
 
25
- const isJSXValue = (attributes) => {
26
- const node = attributes.find(attribute => propName(attribute) === 'href');
27
- const isJSXExpression = node.value.type === 'JSXExpressionContainer' && node
28
- && typeof getPropValue(node) === 'string';
25
+ const isJSXValue = attributes => {
26
+ const node = attributes.find(attribute => propName(attribute) === 'href')
27
+ const isJSXExpression = node.value.type === 'JSXExpressionContainer' && node && typeof getPropValue(node) === 'string'
29
28
 
30
29
  return isJSXExpression
31
30
  }
@@ -34,8 +33,8 @@ const isInteractiveAnchor = child => {
34
33
  const hasHref = getJSXOpeningElementAttribute(child.openingElement, 'href')
35
34
  if (!hasHref) return false
36
35
  const href = getJSXOpeningElementAttribute(child.openingElement, 'href').value.value
37
- const hasJSXValue = isJSXValue(child.openingElement.attributes);
38
- const isAnchorInteractive = (typeof href === 'string' && href !== '' || hasJSXValue)
36
+ const hasJSXValue = isJSXValue(child.openingElement.attributes)
37
+ const isAnchorInteractive = (typeof href === 'string' && href !== '') || hasJSXValue
39
38
 
40
39
  return isAnchorInteractive
41
40
  }
@@ -73,18 +72,18 @@ const checks = [
73
72
  {
74
73
  id: 'nonInteractiveLink',
75
74
  filter: jsxElement => isAnchorTag(jsxElement),
76
- check: isInteractiveAnchor
75
+ check: isInteractiveAnchor,
77
76
  },
78
77
  {
79
78
  id: 'nonInteractiveInput',
80
79
  filter: jsxElement => isInputTag(jsxElement),
81
- check: isInteractiveInput
80
+ check: isInteractiveInput,
82
81
  },
83
82
  {
84
83
  id: 'nonInteractiveTrigger',
85
84
  filter: jsxElement => isOtherThanAnchorOrInput(jsxElement),
86
- check: isInteractive
87
- }
85
+ check: isInteractive,
86
+ },
88
87
  ]
89
88
 
90
89
  const checkTriggerElement = jsxNode => {
@@ -137,10 +136,10 @@ module.exports = {
137
136
  {
138
137
  properties: {
139
138
  skipImportCheck: {
140
- type: 'boolean'
141
- }
142
- }
143
- }
139
+ type: 'boolean',
140
+ },
141
+ },
142
+ },
144
143
  ],
145
144
  messages: {
146
145
  nonInteractiveTrigger:
@@ -149,8 +148,8 @@ module.exports = {
149
148
  'Anchor tags without an href attribute are not interactive, therefore they cannot be used as a trigger for a tooltip. Please add an href attribute or use an alternative interactive element instead',
150
149
  nonInteractiveInput:
151
150
  'Hidden or disabled inputs are not interactive and cannot be used as a trigger for a tooltip. Please use an alternate input type or use a different interactive element instead',
152
- singleChild: 'The `Tooltip` component expects a single React element as a child.'
153
- }
151
+ singleChild: 'The `Tooltip` component expects a single React element as a child.',
152
+ },
154
153
  },
155
154
  create(context) {
156
155
  return {
@@ -166,23 +165,23 @@ module.exports = {
166
165
  if (jsxNode.children.filter(child => child.type === 'JSXElement').length > 1) {
167
166
  context.report({
168
167
  node: jsxNode,
169
- messageId: 'singleChild'
168
+ messageId: 'singleChild',
170
169
  })
171
170
  } else {
172
171
  // Check if the child is interactive
173
172
  const errors = checkTriggerElement(jsxNode)
174
173
 
175
174
  if (errors) {
176
- for (const [key, value] of errors.entries()) {
175
+ for (const [_key, value] of errors.entries()) {
177
176
  context.report({
178
177
  node: jsxNode,
179
- messageId: value
178
+ messageId: value,
180
179
  })
181
180
  }
182
181
  }
183
182
  }
184
183
  }
185
- }
184
+ },
186
185
  }
187
- }
186
+ },
188
187
  }
@@ -13,7 +13,7 @@ const slotParentToChildMap = {
13
13
  RadioGroup: ['RadioGroup.Label', 'RadioGroup.Caption', 'RadioGroup.Validation'],
14
14
  CheckboxGroup: ['CheckboxGroup.Label', 'CheckboxGroup.Caption', 'CheckboxGroup.Validation'],
15
15
  MarkdownEditor: ['MarkdownEditor.Toolbar', 'MarkdownEditor.Actions', 'MarkdownEditor.Label'],
16
- 'MarkdownEditor.Footer': ['MarkdownEditor.Actions', 'MarkdownEditor.FooterButton']
16
+ 'MarkdownEditor.Footer': ['MarkdownEditor.Actions', 'MarkdownEditor.FooterButton'],
17
17
  }
18
18
 
19
19
  const slotChildToParentMap = Object.entries(slotParentToChildMap).reduce((acc, [parent, children]) => {
@@ -34,14 +34,14 @@ module.exports = {
34
34
  {
35
35
  properties: {
36
36
  skipImportCheck: {
37
- type: 'boolean'
38
- }
39
- }
40
- }
37
+ type: 'boolean',
38
+ },
39
+ },
40
+ },
41
41
  ],
42
42
  messages: {
43
- directSlotChildren: '{{childName}} must be a direct child of {{parentName}}.'
44
- }
43
+ directSlotChildren: '{{childName}} must be a direct child of {{parentName}}.',
44
+ },
45
45
  },
46
46
  create(context) {
47
47
  const stack = []
@@ -67,8 +67,8 @@ module.exports = {
67
67
  messageId: 'directSlotChildren',
68
68
  data: {
69
69
  childName: name,
70
- parentName: expectedParentNames.length > 1 ? expectedParentNames.join(' or ') : expectedParentNames[0]
71
- }
70
+ parentName: expectedParentNames.length > 1 ? expectedParentNames.join(' or ') : expectedParentNames[0],
71
+ },
72
72
  })
73
73
  }
74
74
  }
@@ -81,7 +81,7 @@ module.exports = {
81
81
  JSXClosingElement() {
82
82
  // Pop the current element off the stack
83
83
  stack.pop()
84
- }
84
+ },
85
85
  }
86
- }
86
+ },
87
87
  }
@@ -0,0 +1,87 @@
1
+ const cssVars = require('../utils/new-color-css-vars-map')
2
+
3
+ const reportError = (propertyName, valueNode, context) => {
4
+ // performance optimisation: exit early
5
+ if (valueNode.type !== 'Literal' && valueNode.type !== 'TemplateElement') return
6
+ // get property value
7
+ const value = valueNode.type === 'Literal' ? valueNode.value : valueNode.value.cooked
8
+ // return if value is not a string
9
+ if (typeof value !== 'string') return
10
+ // return if value does not include variable
11
+ if (!value.includes('var(')) return
12
+
13
+ const varRegex = /var\([^(),)]+\)/g
14
+
15
+ const match = value.match(varRegex)
16
+ // return if no matches
17
+ if (!match) return
18
+ const vars = match.flatMap(match =>
19
+ match
20
+ .slice(4, -1)
21
+ .trim()
22
+ .split(/\s*,\s*/g),
23
+ )
24
+ for (const cssVar of vars) {
25
+ // return if no repalcement exists
26
+ if (!cssVars?.includes(cssVar)) return
27
+ // report the error
28
+ context.report({
29
+ node: valueNode,
30
+ message: `Expected a fallback value for CSS variable ${cssVar}. New color variables fallbacks, check primer.style/primitives to find the correct value.`,
31
+ })
32
+ }
33
+ }
34
+
35
+ const reportOnObject = (node, context) => {
36
+ const propertyName = node.key.name
37
+ if (node.value?.type === 'Literal') {
38
+ reportError(propertyName, node.value, context)
39
+ } else if (node.value?.type === 'ConditionalExpression') {
40
+ reportError(propertyName, node.value.consequent, context)
41
+ reportError(propertyName, node.value.alternate, context)
42
+ }
43
+ }
44
+
45
+ const reportOnProperty = (node, context) => {
46
+ const propertyName = node.name.name
47
+ if (node.value?.type === 'Literal') {
48
+ reportError(propertyName, node.value, context)
49
+ } else if (node.value?.type === 'JSXExpressionContainer' && node.value.expression?.type === 'ConditionalExpression') {
50
+ reportError(propertyName, node.value.expression.consequent, context)
51
+ reportError(propertyName, node.value.expression.alternate, context)
52
+ }
53
+ }
54
+
55
+ const reportOnValue = (node, context) => {
56
+ if (node?.type === 'Literal') {
57
+ reportError(undefined, node, context)
58
+ } else if (node?.type === 'JSXExpressionContainer' && node.expression?.type === 'ConditionalExpression') {
59
+ reportError(undefined, node.value.expression.consequent, context)
60
+ reportError(undefined, node.value.expression.alternate, context)
61
+ }
62
+ }
63
+
64
+ const reportOnTemplateElement = (node, context) => {
65
+ reportError(undefined, node, context)
66
+ }
67
+
68
+ module.exports = {
69
+ meta: {
70
+ type: 'suggestion',
71
+ },
72
+ /** @param {import('eslint').Rule.RuleContext} context */
73
+ create(context) {
74
+ return {
75
+ // sx OR style property on elements
76
+ ['JSXAttribute:matches([name.name=sx], [name.name=style]) ObjectExpression Property']: node =>
77
+ reportOnObject(node, context),
78
+ // property on element like stroke or fill
79
+ ['JSXAttribute[name.name!=sx][name.name!=style]']: node => reportOnProperty(node, context),
80
+ // variable that is a value
81
+ [':matches(VariableDeclarator, ReturnStatement) > Literal']: node => reportOnValue(node, context),
82
+ // variable that is a value
83
+ [':matches(VariableDeclarator, ReturnStatement) > TemplateElement']: node =>
84
+ reportOnTemplateElement(node, context),
85
+ }
86
+ },
87
+ }
@@ -1,106 +1,120 @@
1
1
  const cssVars = require('../utils/css-variable-map.json')
2
2
 
3
+ const reportError = (propertyName, valueNode, context, suggestFix = true) => {
4
+ // performance optimisation: exit early
5
+ if (valueNode.type !== 'Literal' && valueNode.type !== 'TemplateElement') return
6
+ // get property value
7
+ const value = valueNode.type === 'Literal' ? valueNode.value : valueNode.value.cooked
8
+ // return if value is not a string
9
+ if (typeof value !== 'string') return
10
+ // return if value does not include variable
11
+ if (!value.includes('var(')) return
12
+
13
+ const varRegex = /var\([^)]+\)/g
14
+
15
+ const match = value.match(varRegex)
16
+ if (!match) return
17
+ const vars = match.flatMap(match =>
18
+ match
19
+ .slice(4, -1)
20
+ .trim()
21
+ .split(/\s*,\s*/g),
22
+ )
23
+
24
+ for (const cssVar of vars) {
25
+ // get the array of objects for the variable name (e.g. --color-fg-primary)
26
+ const cssVarObjects = cssVars[cssVar]
27
+ // get the object that contains the property name or the first one (default)
28
+ const varObjectForProp = propertyName
29
+ ? cssVarObjects?.find(prop => prop.props.includes(propertyName))
30
+ : cssVarObjects?.[0]
31
+ // return if no replacement exists
32
+ if (!varObjectForProp?.replacement) return
33
+ // report the error
34
+ context.report({
35
+ node: valueNode,
36
+ message: `Replace var(${cssVar}) with var(${varObjectForProp.replacement}, var(${cssVar}))`,
37
+ fix: suggestFix
38
+ ? fixer => {
39
+ const fixedString = value.replaceAll(cssVar, `${varObjectForProp.replacement}, var(${cssVar})`)
40
+ return fixer.replaceText(valueNode, valueNode.type === 'Literal' ? `'${fixedString}'` : fixedString)
41
+ }
42
+ : undefined,
43
+ })
44
+ }
45
+ }
46
+
47
+ const reportOnObject = (node, context) => {
48
+ const propertyName = node.key.name
49
+ if (node.value?.type === 'Literal') {
50
+ reportError(propertyName, node.value, context)
51
+ } else if (node.value?.type === 'ConditionalExpression') {
52
+ reportError(propertyName, node.value.consequent, context)
53
+ reportError(propertyName, node.value.alternate, context)
54
+ }
55
+ }
56
+
57
+ const reportOnProperty = (node, context) => {
58
+ const propertyName = node.name.name
59
+ if (node.value?.type === 'Literal') {
60
+ reportError(propertyName, node.value, context)
61
+ } else if (node.value?.type === 'JSXExpressionContainer' && node.value.expression?.type === 'ConditionalExpression') {
62
+ reportError(propertyName, node.value.expression.consequent, context)
63
+ reportError(propertyName, node.value.expression.alternate, context)
64
+ }
65
+ }
66
+
67
+ const reportOnValue = (node, context) => {
68
+ if (node?.type === 'Literal') {
69
+ reportError(undefined, node, context)
70
+ } else if (node?.type === 'JSXExpressionContainer' && node.expression?.type === 'ConditionalExpression') {
71
+ reportError(undefined, node.value.expression.consequent, context)
72
+ reportError(undefined, node.value.expression.alternate, context)
73
+ }
74
+ }
75
+
76
+ const reportOnTemplateElement = (node, context) => {
77
+ reportError(undefined, node, context, false)
78
+ }
79
+
3
80
  module.exports = {
4
81
  meta: {
5
82
  type: 'suggestion',
6
83
  hasSuggestions: true,
7
84
  fixable: 'code',
8
85
  docs: {
9
- description: 'Upgrade legacy CSS variables to Primitives v8 in sx prop'
86
+ description: 'Upgrade legacy CSS variables to Primitives v8 in sx prop',
10
87
  },
11
88
  schema: [
12
89
  {
13
90
  type: 'object',
14
91
  properties: {
15
92
  skipImportCheck: {
16
- type: 'boolean'
93
+ type: 'boolean',
17
94
  },
18
95
  checkAllStrings: {
19
- type: 'boolean'
20
- }
96
+ type: 'boolean',
97
+ },
21
98
  },
22
- additionalProperties: false
23
- }
24
- ]
99
+ additionalProperties: false,
100
+ },
101
+ ],
25
102
  },
26
103
  /** @param {import('eslint').Rule.RuleContext} context */
27
104
  create(context) {
28
- const styledSystemProps = [
29
- 'bg',
30
- 'backgroundColor',
31
- 'color',
32
- 'borderColor',
33
- 'borderTopColor',
34
- 'borderRightColor',
35
- 'borderBottomColor',
36
- 'borderLeftColor',
37
- 'border',
38
- 'boxShadow',
39
- 'caretColor'
40
- ]
41
-
42
105
  return {
43
- /** @param {import('eslint').Rule.Node} node */
44
- JSXAttribute(node) {
45
- if (node.name.name === 'sx') {
46
- if (node.value.expression.type === 'ObjectExpression') {
47
- // example: sx={{ color: 'fg.default' }} or sx={{ ':hover': {color: 'fg.default'} }}
48
- const rawText = context.sourceCode.getText(node.value)
49
- checkForVariables(node.value, rawText)
50
- } else if (node.value.expression.type === 'Identifier') {
51
- // example: sx={baseStyles}
52
- const variableScope = context.sourceCode.getScope(node.value.expression)
53
- const variable = variableScope.set.get(node.value.expression.name)
54
-
55
- // if variable is not defined in scope, give up (could be imported from different file)
56
- if (!variable) return
57
-
58
- const variableDeclarator = variable.identifiers[0].parent
59
- const rawText = context.sourceCode.getText(variableDeclarator)
60
- checkForVariables(variableDeclarator, rawText)
61
- } else {
62
- // worth a try!
63
- const rawText = context.sourceCode.getText(node.value)
64
- checkForVariables(node.value, rawText)
65
- }
66
- } else if (
67
- styledSystemProps.includes(node.name.name) &&
68
- node.value &&
69
- node.value.type === 'Literal' &&
70
- typeof node.value.value === 'string'
71
- ) {
72
- checkForVariables(node.value, node.value.value)
73
- }
74
- }
106
+ // sx OR style property on elements
107
+ ['JSXAttribute:matches([name.name=sx], [name.name=style]) ObjectExpression Property']: node =>
108
+ reportOnObject(node, context),
109
+ // variable that is an object
110
+ [':matches(VariableDeclarator, ReturnStatement, ConditionalExpression, ArrowFunctionExpression, CallExpression) > ObjectExpression Property, :matches(VariableDeclarator, ReturnStatement, ConditionalExpression, ArrowFunctionExpression, CallExpression) > ObjectExpression Property > ObjectExpression Property']:
111
+ node => reportOnObject(node, context),
112
+ // property on element like stroke or fill
113
+ ['JSXAttribute[name.name!=sx][name.name!=style]']: node => reportOnProperty(node, context),
114
+ // variable that is a value
115
+ [':matches(VariableDeclarator, ReturnStatement) > Literal']: node => reportOnValue(node, context),
116
+ // variable that is a value
117
+ ['VariableDeclarator TemplateElement']: node => reportOnTemplateElement(node, context),
75
118
  }
76
-
77
- function checkForVariables(node, rawText) {
78
- // performance optimisation: exit early
79
- if (!rawText.includes('var')) return
80
-
81
- Object.keys(cssVars).forEach(cssVar => {
82
- if (Array.isArray(cssVars[cssVar])) {
83
- cssVars[cssVar].forEach(cssVarObject => {
84
- const regex = new RegExp(`var\\(${cssVar}\\)`, 'g')
85
- if (
86
- cssVarObject.props.some(prop => rawText.includes(prop)) &&
87
- regex.test(rawText) &&
88
- !rawText.includes(cssVarObject.replacement)
89
- ) {
90
- const fixedString = rawText.replace(regex, `var(${cssVarObject.replacement}, var(${cssVar}))`)
91
- if (!rawText.includes(fixedString)) {
92
- context.report({
93
- node,
94
- message: `Replace var(${cssVar}) with var(${cssVarObject.replacement}, var(${cssVar}))`,
95
- fix: function(fixer) {
96
- return fixer.replaceText(node, node.type === 'Literal' ? `"${fixedString}"` : fixedString)
97
- }
98
- })
99
- }
100
- }
101
- })
102
- }
103
- })
104
- }
105
- }
119
+ },
106
120
  }
@@ -17,15 +17,15 @@ module.exports = {
17
17
  type: 'object',
18
18
  properties: {
19
19
  skipImportCheck: {
20
- type: 'boolean'
20
+ type: 'boolean',
21
21
  },
22
22
  checkAllStrings: {
23
- type: 'boolean'
24
- }
23
+ type: 'boolean',
24
+ },
25
25
  },
26
- additionalProperties: false
27
- }
28
- ]
26
+ additionalProperties: false,
27
+ },
28
+ ],
29
29
  },
30
30
  create(context) {
31
31
  // If `skipImportCheck` is true, this rule will check for deprecated colors
@@ -89,7 +89,7 @@ module.exports = {
89
89
  path.node,
90
90
  name,
91
91
  str => [param, key, str].join('.'),
92
- str => str
92
+ str => str,
93
93
  )
94
94
  }
95
95
 
@@ -132,9 +132,9 @@ module.exports = {
132
132
  if (['colors', 'shadows'].includes(key) && Object.keys(deprecations).includes(name)) {
133
133
  replaceDeprecatedColor(context, argument, name, str => [key, str].join('.'))
134
134
  }
135
- }
135
+ },
136
136
  }
137
- }
137
+ },
138
138
  }
139
139
 
140
140
  function isThemeGet(identifier, scope, skipImportCheck = false) {
@@ -156,7 +156,7 @@ function replaceDeprecatedColor(
156
156
  node,
157
157
  deprecatedName,
158
158
  transformName = str => str,
159
- transformReplacementValue = str => JSON.stringify(str)
159
+ transformReplacementValue = str => JSON.stringify(str),
160
160
  ) {
161
161
  const replacement = deprecations[deprecatedName]
162
162
 
@@ -165,8 +165,8 @@ function replaceDeprecatedColor(
165
165
  context.report({
166
166
  node,
167
167
  message: `"${transformName(
168
- deprecatedName
169
- )}" is deprecated. Go to https://primer.style/primitives or reach out in the #primer channel on Slack to find a suitable replacement.`
168
+ deprecatedName,
169
+ )}" is deprecated. Go to https://primer.style/primitives or reach out in the #primer channel on Slack to find a suitable replacement.`,
170
170
  })
171
171
  } else if (Array.isArray(replacement)) {
172
172
  // Multiple possible replacements
@@ -177,8 +177,8 @@ function replaceDeprecatedColor(
177
177
  desc: `Use "${transformName(replacementValue)}" instead.`,
178
178
  fix(fixer) {
179
179
  return fixer.replaceText(node, transformReplacementValue(transformName(replacementValue)))
180
- }
181
- }))
180
+ },
181
+ })),
182
182
  })
183
183
  } else {
184
184
  // One replacement
@@ -187,7 +187,7 @@ function replaceDeprecatedColor(
187
187
  message: `"${transformName(deprecatedName)}" is deprecated. Use "${transformName(replacement)}" instead.`,
188
188
  fix(fixer) {
189
189
  return fixer.replaceText(node, transformReplacementValue(transformName(replacement)))
190
- }
190
+ },
191
191
  })
192
192
  }
193
193
  }
@@ -5,7 +5,7 @@ const {some, last} = require('lodash')
5
5
 
6
6
  // Components for which we allow all styled system props
7
7
  const alwaysExcludedComponents = new Set([
8
- 'BaseStyles' // BaseStyles will be deprecated eventually
8
+ 'BaseStyles', // BaseStyles will be deprecated eventually
9
9
  ])
10
10
 
11
11
  // Excluded by default, but optionally included:
@@ -40,7 +40,7 @@ const excludedComponentProps = new Map([
40
40
  ['PageLayout.Pane', new Set(['padding', 'position', 'width'])],
41
41
  ['PageLayout.Content', new Set(['padding', 'width'])],
42
42
  ['ProgressBar', new Set(['bg'])],
43
- ['PointerBox', new Set(['bg'])]
43
+ ['PointerBox', new Set(['bg'])],
44
44
  ])
45
45
 
46
46
  const alwaysExcludedProps = new Set(['variant', 'size'])
@@ -53,17 +53,17 @@ module.exports = {
53
53
  {
54
54
  properties: {
55
55
  skipImportCheck: {
56
- type: 'boolean'
56
+ type: 'boolean',
57
57
  },
58
58
  includeUtilityComponents: {
59
- type: 'boolean'
60
- }
61
- }
62
- }
59
+ type: 'boolean',
60
+ },
61
+ },
62
+ },
63
63
  ],
64
64
  messages: {
65
- noSystemProps: 'Styled-system props are deprecated ({{ componentName }} called with props: {{ propNames }})'
66
- }
65
+ noSystemProps: 'Styled-system props are deprecated ({{ componentName }} called with props: {{ propNames }})',
66
+ },
67
67
  },
68
68
  create(context) {
69
69
  // If `skipImportCheck` is true, this rule will check for deprecated styled system props
@@ -74,7 +74,7 @@ module.exports = {
74
74
 
75
75
  const excludedComponents = new Set([
76
76
  ...alwaysExcludedComponents,
77
- ...(includeUtilityComponents ? [] : utilityComponents)
77
+ ...(includeUtilityComponents ? [] : utilityComponents),
78
78
  ])
79
79
 
80
80
  return {
@@ -113,11 +113,11 @@ module.exports = {
113
113
  messageId: 'noSystemProps',
114
114
  data: {
115
115
  componentName,
116
- propNames: systemProps.map(a => a.name.name).join(', ')
116
+ propNames: systemProps.map(a => a.name.name).join(', '),
117
117
  },
118
118
  fix(fixer) {
119
119
  const existingSxProp = jsxNode.attributes.find(
120
- attribute => attribute.type === 'JSXAttribute' && attribute.name.name === 'sx'
120
+ attribute => attribute.type === 'JSXAttribute' && attribute.name.name === 'sx',
121
121
  )
122
122
  const systemPropstylesMap = stylesMapFromPropNodes(systemProps, context)
123
123
  if (existingSxProp && existingSxProp.value.expression.type !== 'ObjectExpression') {
@@ -137,19 +137,19 @@ module.exports = {
137
137
  ? // Update an existing sx prop
138
138
  fixer.insertTextAfter(
139
139
  last(existingSxProp.value.expression.properties),
140
- `, ${objectEntriesStringFromStylesMap(stylesToAdd)}`
140
+ `, ${objectEntriesStringFromStylesMap(stylesToAdd)}`,
141
141
  )
142
142
  : // Insert new sx prop
143
- fixer.insertTextAfter(last(jsxNode.attributes), sxPropTextFromStylesMap(systemPropstylesMap))
143
+ fixer.insertTextAfter(last(jsxNode.attributes), sxPropTextFromStylesMap(systemPropstylesMap)),
144
144
  ]
145
- : [])
145
+ : []),
146
146
  ]
147
- }
147
+ },
148
148
  })
149
149
  }
150
- }
150
+ },
151
151
  }
152
- }
152
+ },
153
153
  }
154
154
 
155
155
  const sxPropTextFromStylesMap = styles => {
@@ -165,8 +165,8 @@ const stylesMapFromPropNodes = (systemProps, context) => {
165
165
  return new Map(
166
166
  systemProps.map(a => [
167
167
  a.name.name,
168
- a.value === null ? 'true' : a.value.raw || context.getSourceCode().getText(a.value.expression)
169
- ])
168
+ a.value === null ? 'true' : a.value.raw || context.getSourceCode().getText(a.value.expression),
169
+ ]),
170
170
  )
171
171
  }
172
172
 
@@ -183,6 +183,6 @@ const excludeSxEntriesFromStyleMap = (stylesMap, sxProp) => {
183
183
  return new Map(
184
184
  [...stylesMap].filter(([key]) => {
185
185
  return !some(sxProp.value.expression.properties, p => p.type === 'Property' && p.key.name === key)
186
- })
186
+ }),
187
187
  )
188
188
  }
package/src/url.js CHANGED
@@ -7,4 +7,4 @@ module.exports = ({id}) => {
7
7
  url.hash = ''
8
8
  url.pathname += `/blob/v${version}/docs/rules/${rule}.md`
9
9
  return url.toString()
10
- }
10
+ }