@hypersolid-dev/eslint-config 4.0.0 → 6.0.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 (70) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +54 -7
  3. package/dist/base.js +65 -7
  4. package/dist/jest.d.ts +3 -0
  5. package/dist/jest.js +56 -0
  6. package/dist/plugins/hypersolid.d.ts +3 -0
  7. package/dist/plugins/hypersolid.js +38 -0
  8. package/dist/plugins/props-destructuring.js +14 -13
  9. package/dist/plugins/react-native-a11y/index.js +4 -2
  10. package/dist/plugins/react-native-a11y/rules/accessibility-actions-need-handler.js +2 -2
  11. package/dist/plugins/react-native-a11y/rules/accessibility-hint.js +6 -4
  12. package/dist/plugins/react-native-a11y/rules/accessibility-label.js +10 -6
  13. package/dist/plugins/react-native-a11y/rules/accessibility-role.js +6 -4
  14. package/dist/plugins/react-native-a11y/rules/accessibility-value-needs-range.js +25 -27
  15. package/dist/plugins/react-native-a11y/rules/adjustable-needs-value.js +16 -18
  16. package/dist/plugins/react-native-a11y/rules/gate-announce-for-accessibility.js +14 -10
  17. package/dist/plugins/react-native-a11y/rules/input-purpose.js +10 -6
  18. package/dist/plugins/react-native-a11y/rules/no-aria-legacy-mix.js +20 -22
  19. package/dist/plugins/react-native-a11y/rules/no-deprecated-accessibility-focus.js +12 -14
  20. package/dist/plugins/react-native-a11y/rules/no-dropped-aria-on-text.js +2 -2
  21. package/dist/plugins/react-native-a11y/rules/no-font-scaling-disabled.js +24 -26
  22. package/dist/plugins/react-native-a11y/rules/no-ineffective-accessibility-props.js +34 -36
  23. package/dist/plugins/react-native-a11y/rules/no-invalid-accessibility-state.js +31 -33
  24. package/dist/plugins/react-native-a11y/rules/no-nested-focus-stops.js +2 -2
  25. package/dist/plugins/react-native-a11y/rules/no-press-in-activation.js +2 -2
  26. package/dist/plugins/react-native-a11y/rules/no-unnamed-interactive.js +6 -4
  27. package/dist/plugins/react-native-a11y/rules/require-invert-colors-opt-out.js +8 -6
  28. package/dist/plugins/react-native-a11y/rules/require-modal-a11y-on-sheets.js +7 -5
  29. package/dist/plugins/react-native-a11y/utils/get-amount-of-text-children.js +19 -13
  30. package/dist/plugins/react-native-a11y/utils/get-element-name.js +1 -1
  31. package/dist/plugins/rules/boolean-guard.d.ts +30 -0
  32. package/dist/plugins/rules/boolean-guard.js +143 -0
  33. package/dist/plugins/rules/comment-style.d.ts +26 -0
  34. package/dist/plugins/rules/comment-style.js +167 -0
  35. package/dist/plugins/rules/effect-takes-callback.d.ts +20 -0
  36. package/dist/plugins/rules/effect-takes-callback.js +106 -0
  37. package/dist/plugins/rules/jsdoc-for-props.d.ts +18 -0
  38. package/dist/plugins/rules/jsdoc-for-props.js +57 -0
  39. package/dist/plugins/rules/no-callback-payload.d.ts +21 -0
  40. package/dist/plugins/rules/no-callback-payload.js +217 -0
  41. package/dist/plugins/rules/no-markup-variable.d.ts +22 -0
  42. package/dist/plugins/rules/no-markup-variable.js +123 -0
  43. package/dist/plugins/rules/no-unnecessary-use-callback.d.ts +24 -0
  44. package/dist/plugins/rules/no-unnecessary-use-callback.js +117 -0
  45. package/dist/plugins/rules/regex-pattern-const.d.ts +19 -0
  46. package/dist/plugins/rules/regex-pattern-const.js +82 -0
  47. package/dist/plugins/rules/test-id-default.d.ts +4 -0
  48. package/dist/plugins/rules/test-id-default.js +182 -0
  49. package/dist/plugins/rules/test-id-format.d.ts +4 -0
  50. package/dist/plugins/rules/test-id-format.js +118 -0
  51. package/dist/plugins/rules/test-id-from-props.d.ts +4 -0
  52. package/dist/plugins/rules/test-id-from-props.js +90 -0
  53. package/dist/plugins/rules/undefined-check.d.ts +5 -0
  54. package/dist/plugins/rules/undefined-check.js +64 -0
  55. package/dist/plugins/rules/webview-allow-list.d.ts +5 -0
  56. package/dist/plugins/rules/webview-allow-list.js +105 -0
  57. package/dist/plugins/utils/comments.d.ts +15 -0
  58. package/dist/plugins/utils/comments.js +15 -0
  59. package/dist/plugins/utils/component-name.d.ts +11 -0
  60. package/dist/plugins/utils/component-name.js +32 -0
  61. package/dist/plugins/utils/create-rule.d.ts +5 -0
  62. package/dist/plugins/utils/create-rule.js +4 -0
  63. package/dist/plugins/utils/expressions.d.ts +52 -0
  64. package/dist/plugins/utils/expressions.js +290 -0
  65. package/dist/plugins/utils/types.d.ts +20 -0
  66. package/dist/plugins/utils/types.js +91 -0
  67. package/dist/react-native.js +93 -12
  68. package/dist/shared.d.ts +22 -3
  69. package/dist/shared.js +202 -75
  70. package/package.json +13 -3
@@ -18,32 +18,30 @@ const accessibilityValueNeedsRange = createRule({
18
18
  },
19
19
  schema: [],
20
20
  },
21
- create(context) {
22
- return {
23
- JSXOpeningElement(node) {
24
- const attribute = getProperty(node, "accessibilityValue");
25
- if (attribute?.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
26
- return;
27
- }
28
- const { expression } = attribute.value;
29
- // A value built elsewhere cannot be read here
30
- if (expression.type !== AST_NODE_TYPES.ObjectExpression) {
31
- return;
32
- }
33
- // A spread may carry the range, and cannot be read from here
34
- if (expression.properties.some((property) => property.type === AST_NODE_TYPES.SpreadElement)) {
35
- return;
36
- }
37
- const keys = keysOf(expression);
38
- if (!keys.includes("now") || keys.includes("text")) {
39
- return;
40
- }
41
- if (keys.includes("min") && keys.includes("max")) {
42
- return;
43
- }
44
- context.report({ node: attribute, messageId: "valueWithoutRange" });
45
- },
46
- };
47
- },
21
+ create: (context) => ({
22
+ JSXOpeningElement: (node) => {
23
+ const attribute = getProperty(node, "accessibilityValue");
24
+ if (attribute?.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
25
+ return;
26
+ }
27
+ const { expression } = attribute.value;
28
+ // A value built elsewhere cannot be read here
29
+ if (expression.type !== AST_NODE_TYPES.ObjectExpression) {
30
+ return;
31
+ }
32
+ // A spread may carry the range, and cannot be read from here
33
+ if (expression.properties.some((property) => property.type === AST_NODE_TYPES.SpreadElement)) {
34
+ return;
35
+ }
36
+ const keys = keysOf(expression);
37
+ if (!keys.includes("now") || keys.includes("text")) {
38
+ return;
39
+ }
40
+ if (keys.includes("min") && keys.includes("max")) {
41
+ return;
42
+ }
43
+ context.report({ node: attribute, messageId: "valueWithoutRange" });
44
+ },
45
+ }),
48
46
  });
49
47
  export default accessibilityValueNeedsRange;
@@ -18,23 +18,21 @@ const adjustableNeedsValue = createRule({
18
18
  },
19
19
  schema: [],
20
20
  },
21
- create(context) {
22
- return {
23
- JSXOpeningElement(node) {
24
- const role = getLiteralPropertyValue(node, ["accessibilityRole", "role"]);
25
- if (typeof role !== "string" || !ROLES_NEEDING_VALUE.has(role)) {
26
- return;
27
- }
28
- if (hasSpreadProps(node) || hasProperty(node, VALUE_PROPS)) {
29
- return;
30
- }
31
- context.report({
32
- node,
33
- messageId: "missingAccessibilityValue",
34
- data: { role },
35
- });
36
- },
37
- };
38
- },
21
+ create: (context) => ({
22
+ JSXOpeningElement: (node) => {
23
+ const role = getLiteralPropertyValue(node, ["accessibilityRole", "role"]);
24
+ if (typeof role !== "string" || !ROLES_NEEDING_VALUE.has(role)) {
25
+ return;
26
+ }
27
+ if (hasSpreadProps(node) || hasProperty(node, VALUE_PROPS)) {
28
+ return;
29
+ }
30
+ context.report({
31
+ node,
32
+ messageId: "missingAccessibilityValue",
33
+ data: { role },
34
+ });
35
+ },
36
+ }),
39
37
  });
40
38
  export default adjustableNeedsValue;
@@ -28,20 +28,22 @@ const gateAnnounceForAccessibility = createRule({
28
28
  },
29
29
  schema: [],
30
30
  },
31
- create(context) {
32
- // A bare announce is the legitimate cross-platform pattern. The double
33
- // announcement only happens where a live region covers Android already, so
34
- // that pairing is the trigger rather than the call on its own.
31
+ create: (context) => {
32
+ /**
33
+ * A bare announce is the legitimate cross-platform pattern. The double
34
+ * announcement only happens where a live region covers Android already, so
35
+ * that pairing is the trigger rather than the call on its own.
36
+ */
35
37
  let hasLiveRegion = false;
36
38
  const announces = [];
37
39
  const platformChecks = [];
38
40
  return {
39
- JSXOpeningElement(node) {
41
+ JSXOpeningElement: (node) => {
40
42
  if (getProperty(node, LIVE_REGION_PROPS)) {
41
43
  hasLiveRegion = true;
42
44
  }
43
45
  },
44
- MemberExpression(node) {
46
+ MemberExpression: (node) => {
45
47
  if (node.property.type !== AST_NODE_TYPES.Identifier) {
46
48
  return;
47
49
  }
@@ -56,13 +58,15 @@ const gateAnnounceForAccessibility = createRule({
56
58
  platformChecks.push(node);
57
59
  }
58
60
  },
59
- "Program:exit"() {
61
+ "Program:exit": () => {
60
62
  if (!hasLiveRegion) {
61
63
  return;
62
64
  }
63
- // ponytail: any Platform.OS in the same function counts as the gate.
64
- // Lenient on purpose — a guard clause, a switch and a named boolean are
65
- // all real gates, and none of them is an ancestor of the call.
65
+ /**
66
+ * ponytail: any Platform.OS in the same function counts as the gate.
67
+ * Lenient on purpose — a guard clause, a switch and a named boolean are
68
+ * all real gates, and none of them is an ancestor of the call.
69
+ */
66
70
  const gatedScopes = new Set(platformChecks.map((check) => enclosingScope(check)));
67
71
  for (const announce of announces) {
68
72
  if (gatedScopes.has(enclosingScope(announce))) {
@@ -42,13 +42,13 @@ const inputPurpose = createRule({
42
42
  },
43
43
  ],
44
44
  },
45
- create(context) {
45
+ create: (context) => {
46
46
  const components = getComponents({
47
47
  context,
48
48
  defaultComponents: TEXT_INPUTS,
49
49
  });
50
50
  return {
51
- JSXOpeningElement(node) {
51
+ JSXOpeningElement: (node) => {
52
52
  const componentName = getElementName(node);
53
53
  if (componentName === undefined) {
54
54
  return;
@@ -56,12 +56,16 @@ const inputPurpose = createRule({
56
56
  if (!components.includes(componentName)) {
57
57
  return;
58
58
  }
59
- // The missing token may arrive through the spread; an explicit one is
60
- // already wrong whatever the spread carries
59
+ /**
60
+ * The missing token may arrive through the spread; an explicit one is
61
+ * already wrong whatever the spread carries
62
+ */
61
63
  const autoComplete = getProperty(node, "autoComplete");
62
64
  const textContentType = getProperty(node, "textContentType");
63
- // One fix either way, so one finding: the sharper message where only
64
- // the iOS half is already set
65
+ /**
66
+ * One fix either way, so one finding: the sharper message where only
67
+ * the iOS half is already set
68
+ */
65
69
  if (!autoComplete && !hasSpreadProps(node)) {
66
70
  context.report(textContentType
67
71
  ? { node: textContentType, messageId: "missingAutoComplete" }
@@ -30,28 +30,26 @@ const noAriaLegacyMix = createRule({
30
30
  },
31
31
  schema: [],
32
32
  },
33
- create(context) {
34
- return {
35
- JSXOpeningElement(node) {
36
- for (const [alias, legacy] of Object.entries(ALIAS_TO_LEGACY)) {
37
- if (!getProperty(node, alias)) {
38
- continue;
39
- }
40
- const stateKey = STATE_ALIAS_KEYS[alias] ?? VALUE_ALIAS_KEYS[alias];
41
- // A grouped prop only clashes on the key the alias maps onto
42
- const isClashes = stateKey
43
- ? hasStateKey(node, legacy, stateKey)
44
- : getProperty(node, legacy) !== undefined;
45
- if (isClashes) {
46
- context.report({
47
- node,
48
- messageId: "ariaLegacyMix",
49
- data: { alias, legacy },
50
- });
51
- }
33
+ create: (context) => ({
34
+ JSXOpeningElement: (node) => {
35
+ for (const [alias, legacy] of Object.entries(ALIAS_TO_LEGACY)) {
36
+ if (!getProperty(node, alias)) {
37
+ continue;
52
38
  }
53
- },
54
- };
55
- },
39
+ const stateKey = STATE_ALIAS_KEYS[alias] ?? VALUE_ALIAS_KEYS[alias];
40
+ // A grouped prop only clashes on the key the alias maps onto
41
+ const isClashes = stateKey
42
+ ? hasStateKey(node, legacy, stateKey)
43
+ : getProperty(node, legacy) !== undefined;
44
+ if (isClashes) {
45
+ context.report({
46
+ node,
47
+ messageId: "ariaLegacyMix",
48
+ data: { alias, legacy },
49
+ });
50
+ }
51
+ }
52
+ },
53
+ }),
56
54
  });
57
55
  export default noAriaLegacyMix;
@@ -13,19 +13,17 @@ const noDeprecatedAccessibilityFocus = createRule({
13
13
  },
14
14
  schema: [],
15
15
  },
16
- create(context) {
17
- return {
18
- // Matched on the property so an aliased import is caught too
19
- MemberExpression(node) {
20
- if (node.property.type === AST_NODE_TYPES.Identifier &&
21
- node.property.name === "setAccessibilityFocus") {
22
- context.report({
23
- node,
24
- messageId: "deprecatedSetAccessibilityFocus",
25
- });
26
- }
27
- },
28
- };
29
- },
16
+ create: (context) => ({
17
+ // Matched on the property so an aliased import is caught too
18
+ MemberExpression: (node) => {
19
+ if (node.property.type === AST_NODE_TYPES.Identifier &&
20
+ node.property.name === "setAccessibilityFocus") {
21
+ context.report({
22
+ node,
23
+ messageId: "deprecatedSetAccessibilityFocus",
24
+ });
25
+ }
26
+ },
27
+ }),
30
28
  });
31
29
  export default noDeprecatedAccessibilityFocus;
@@ -36,13 +36,13 @@ const noDroppedAriaOnText = createRule({
36
36
  },
37
37
  ],
38
38
  },
39
- create(context) {
39
+ create: (context) => {
40
40
  const components = getComponents({
41
41
  context,
42
42
  defaultComponents: TEXTS,
43
43
  });
44
44
  return {
45
- JSXOpeningElement(node) {
45
+ JSXOpeningElement: (node) => {
46
46
  const componentName = getElementName(node);
47
47
  if (componentName === undefined) {
48
48
  return;
@@ -19,31 +19,29 @@ const noFontScalingDisabled = createRule({
19
19
  },
20
20
  schema: [],
21
21
  },
22
- create(context) {
23
- return {
24
- JSXOpeningElement(node) {
25
- const allowFontScaling = getProperty(node, "allowFontScaling");
26
- if (allowFontScaling &&
27
- getLiteralPropertyValue(node, "allowFontScaling") === false) {
28
- context.report({
29
- node: allowFontScaling,
30
- messageId: "fontScalingDisabled",
31
- });
32
- }
33
- const cap = getProperty(node, "maxFontSizeMultiplier");
34
- const multiplier = getLiteralPropertyValue(node, "maxFontSizeMultiplier");
35
- if (cap &&
36
- typeof multiplier === "number" &&
37
- multiplier !== NO_MAXIMUM &&
38
- multiplier < MINIMUM_MULTIPLIER) {
39
- context.report({
40
- node: cap,
41
- messageId: "fontScalingCapped",
42
- data: { multiplier, minimum: MINIMUM_MULTIPLIER },
43
- });
44
- }
45
- },
46
- };
47
- },
22
+ create: (context) => ({
23
+ JSXOpeningElement: (node) => {
24
+ const allowFontScaling = getProperty(node, "allowFontScaling");
25
+ if (allowFontScaling &&
26
+ getLiteralPropertyValue(node, "allowFontScaling") === false) {
27
+ context.report({
28
+ node: allowFontScaling,
29
+ messageId: "fontScalingDisabled",
30
+ });
31
+ }
32
+ const cap = getProperty(node, "maxFontSizeMultiplier");
33
+ const multiplier = getLiteralPropertyValue(node, "maxFontSizeMultiplier");
34
+ if (cap &&
35
+ typeof multiplier === "number" &&
36
+ multiplier !== NO_MAXIMUM &&
37
+ multiplier < MINIMUM_MULTIPLIER) {
38
+ context.report({
39
+ node: cap,
40
+ messageId: "fontScalingCapped",
41
+ data: { multiplier, minimum: MINIMUM_MULTIPLIER },
42
+ });
43
+ }
44
+ },
45
+ }),
48
46
  });
49
47
  export default noFontScalingDisabled;
@@ -31,46 +31,44 @@ const noIneffectiveAccessibilityProps = createRule({
31
31
  },
32
32
  schema: [],
33
33
  },
34
- create(context) {
35
- return {
36
- JSXOpeningElement(node) {
37
- const role = getLiteralPropertyValue(node, ["accessibilityRole", "role"]);
38
- if (role === "listitem") {
39
- context.report({ node, messageId: "listItemRole" });
34
+ create: (context) => ({
35
+ JSXOpeningElement: (node) => {
36
+ const role = getLiteralPropertyValue(node, ["accessibilityRole", "role"]);
37
+ if (role === "listitem") {
38
+ context.report({ node, messageId: "listItemRole" });
39
+ }
40
+ if (role === "alert") {
41
+ context.report({ node, messageId: "alertRole" });
42
+ }
43
+ const isHidden = isDefinitelyHidden(node);
44
+ if (isHidden && hasLabelProperty(node)) {
45
+ context.report({ node, messageId: "hiddenWithLabel" });
46
+ }
47
+ if (getLiteralPropertyValue(node, "accessible") === false) {
48
+ const name = getElementName(node);
49
+ if (isHidden) {
50
+ context.report({ node, messageId: "hiddenWithAccessibleFalse" });
40
51
  }
41
- if (role === "alert") {
42
- context.report({ node, messageId: "alertRole" });
43
- }
44
- const isHidden = isDefinitelyHidden(node);
45
- if (isHidden && hasLabelProperty(node)) {
46
- context.report({ node, messageId: "hiddenWithLabel" });
47
- }
48
- if (getLiteralPropertyValue(node, "accessible") === false) {
49
- const name = getElementName(node);
50
- if (isHidden) {
51
- context.report({ node, messageId: "hiddenWithAccessibleFalse" });
52
- }
53
- else if (name !== undefined &&
54
- DEFAULTS_TO_INACCESSIBLE.has(name) &&
55
- // A spread may carry the `accessible` this one is overriding.
56
- !hasSpreadProps(node)) {
57
- context.report({
58
- node,
59
- messageId: "accessibleFalseIsDefault",
60
- data: { name },
61
- });
62
- }
63
- }
64
- const labelledBy = getProperty(node, LABELLED_BY_PROPS);
65
- if (labelledBy && !hasLabelProperty(node)) {
52
+ else if (name !== undefined &&
53
+ DEFAULTS_TO_INACCESSIBLE.has(name) &&
54
+ // A spread may carry the `accessible` this one is overriding.
55
+ !hasSpreadProps(node)) {
66
56
  context.report({
67
57
  node,
68
- messageId: "labelledByWithoutLabel",
69
- data: { prop: labelledBy.name.name },
58
+ messageId: "accessibleFalseIsDefault",
59
+ data: { name },
70
60
  });
71
61
  }
72
- },
73
- };
74
- },
62
+ }
63
+ const labelledBy = getProperty(node, LABELLED_BY_PROPS);
64
+ if (labelledBy && !hasLabelProperty(node)) {
65
+ context.report({
66
+ node,
67
+ messageId: "labelledByWithoutLabel",
68
+ data: { prop: labelledBy.name.name },
69
+ });
70
+ }
71
+ },
72
+ }),
75
73
  });
76
74
  export default noIneffectiveAccessibilityProps;
@@ -44,39 +44,37 @@ const noInvalidAccessibilityState = createRule({
44
44
  },
45
45
  schema: [],
46
46
  },
47
- create(context) {
48
- return {
49
- JSXOpeningElement(node) {
50
- const attribute = getProperty(node, "accessibilityState");
51
- if (attribute?.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
52
- return;
47
+ create: (context) => ({
48
+ JSXOpeningElement: (node) => {
49
+ const attribute = getProperty(node, "accessibilityState");
50
+ if (attribute?.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
51
+ return;
52
+ }
53
+ const { expression } = attribute.value;
54
+ // An object literal here is already rejected by the React Native types
55
+ if (expression.type !== AST_NODE_TYPES.Identifier) {
56
+ return;
57
+ }
58
+ const resolved = resolveObjectBinding(context.sourceCode.getScope(expression), expression);
59
+ if (!resolved) {
60
+ return;
61
+ }
62
+ for (const property of resolved.properties) {
63
+ if (property.type !== AST_NODE_TYPES.Property ||
64
+ property.key.type !== AST_NODE_TYPES.Identifier ||
65
+ ACCESSIBILITY_STATE_KEYS.includes(property.key.name)) {
66
+ continue;
53
67
  }
54
- const { expression } = attribute.value;
55
- // An object literal here is already rejected by the React Native types
56
- if (expression.type !== AST_NODE_TYPES.Identifier) {
57
- return;
58
- }
59
- const resolved = resolveObjectBinding(context.sourceCode.getScope(expression), expression);
60
- if (!resolved) {
61
- return;
62
- }
63
- for (const property of resolved.properties) {
64
- if (property.type !== AST_NODE_TYPES.Property ||
65
- property.key.type !== AST_NODE_TYPES.Identifier ||
66
- ACCESSIBILITY_STATE_KEYS.includes(property.key.name)) {
67
- continue;
68
- }
69
- context.report({
70
- node: property,
71
- messageId: "invalidStateKey",
72
- data: {
73
- key: property.key.name,
74
- supported: ACCESSIBILITY_STATE_KEYS.join(", "),
75
- },
76
- });
77
- }
78
- },
79
- };
80
- },
68
+ context.report({
69
+ node: property,
70
+ messageId: "invalidStateKey",
71
+ data: {
72
+ key: property.key.name,
73
+ supported: ACCESSIBILITY_STATE_KEYS.join(", "),
74
+ },
75
+ });
76
+ }
77
+ },
78
+ }),
81
79
  });
82
80
  export default noInvalidAccessibilityState;
@@ -30,7 +30,7 @@ const noNestedFocusStops = createRule({
30
30
  },
31
31
  ],
32
32
  },
33
- create(context) {
33
+ create: (context) => {
34
34
  // The touchables plus whatever this project wraps them in
35
35
  const components = getComponents({
36
36
  context,
@@ -44,7 +44,7 @@ const noNestedFocusStops = createRule({
44
44
  hasTouchHandler(node));
45
45
  };
46
46
  return {
47
- JSXOpeningElement(node) {
47
+ JSXOpeningElement: (node) => {
48
48
  const componentName = getElementName(node);
49
49
  if (componentName === undefined ||
50
50
  !isDefinitelyGrouped(node) ||
@@ -29,13 +29,13 @@ const noPressInActivation = createRule({
29
29
  },
30
30
  ],
31
31
  },
32
- create(context) {
32
+ create: (context) => {
33
33
  const components = getComponents({
34
34
  context,
35
35
  defaultComponents: TOUCHABLES,
36
36
  });
37
37
  return {
38
- JSXOpeningElement(node) {
38
+ JSXOpeningElement: (node) => {
39
39
  const componentName = getElementName(node);
40
40
  if (componentName === undefined) {
41
41
  return;
@@ -38,16 +38,18 @@ const noUnnamedInteractive = createRule({
38
38
  },
39
39
  ],
40
40
  },
41
- create(context) {
41
+ create: (context) => {
42
42
  const components = getComponents({ context });
43
43
  return {
44
- JSXOpeningElement(node) {
44
+ JSXOpeningElement: (node) => {
45
45
  const componentName = getElementName(node);
46
46
  if (componentName === undefined) {
47
47
  return;
48
48
  }
49
- // accessibility-label owns the components it knows by name, so a
50
- // control does not collect a finding from both rules
49
+ /**
50
+ * accessibility-label owns the components it knows by name, so a
51
+ * control does not collect a finding from both rules
52
+ */
51
53
  if (ALREADY_COVERED.has(componentName) &&
52
54
  !components.includes(componentName)) {
53
55
  return;
@@ -29,17 +29,19 @@ const requireInvertColorsOptOut = createRule({
29
29
  },
30
30
  ],
31
31
  },
32
- create(context) {
33
- // Matched on the element name, so an image from expo-image or a wrapper
34
- // named through additionalComponents is checked the same way. Deliberately
35
- // not gated on the import statement: that reads the source text and misses
36
- // a codebase whose quote style differs.
32
+ create: (context) => {
33
+ /**
34
+ * Matched on the element name, so an image from expo-image or a wrapper
35
+ * named through additionalComponents is checked the same way. Deliberately
36
+ * not gated on the import statement: that reads the source text and misses
37
+ * a codebase whose quote style differs.
38
+ */
37
39
  const components = getComponents({
38
40
  context,
39
41
  defaultComponents: IMAGES,
40
42
  });
41
43
  return {
42
- JSXOpeningElement(node) {
44
+ JSXOpeningElement: (node) => {
43
45
  const componentName = getElementName(node);
44
46
  if (componentName === undefined) {
45
47
  return;
@@ -27,13 +27,15 @@ const requireModalA11yOnSheets = createRule({
27
27
  },
28
28
  ],
29
29
  },
30
- create(context) {
31
- // No default list: a sheet is whatever this project calls one, and
32
- // hardcoding one library's component names would fire on a codebase that
33
- // happens to reuse them. Configure through additionalComponents.
30
+ create: (context) => {
31
+ /**
32
+ * No default list: a sheet is whatever this project calls one, and
33
+ * hardcoding one library's component names would fire on a codebase that
34
+ * happens to reuse them. Configure through additionalComponents.
35
+ */
34
36
  const components = getComponents({ context });
35
37
  return {
36
- JSXOpeningElement(node) {
38
+ JSXOpeningElement: (node) => {
37
39
  const componentName = getElementName(node);
38
40
  if (componentName === undefined) {
39
41
  return;