react-native-accessibility-scanner 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +501 -0
  3. package/dist/cli/index.d.ts +3 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +131 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/eslint/index.d.ts +59 -0
  8. package/dist/eslint/index.d.ts.map +1 -0
  9. package/dist/eslint/index.js +181 -0
  10. package/dist/eslint/index.js.map +1 -0
  11. package/dist/index.d.ts +12 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +36 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/reporters/console-reporter.d.ts +5 -0
  16. package/dist/reporters/console-reporter.d.ts.map +1 -0
  17. package/dist/reporters/console-reporter.js +67 -0
  18. package/dist/reporters/console-reporter.js.map +1 -0
  19. package/dist/reporters/json-reporter.d.ts +5 -0
  20. package/dist/reporters/json-reporter.d.ts.map +1 -0
  21. package/dist/reporters/json-reporter.js +13 -0
  22. package/dist/reporters/json-reporter.js.map +1 -0
  23. package/dist/reporters/markdown-reporter.d.ts +5 -0
  24. package/dist/reporters/markdown-reporter.d.ts.map +1 -0
  25. package/dist/reporters/markdown-reporter.js +66 -0
  26. package/dist/reporters/markdown-reporter.js.map +1 -0
  27. package/dist/rules/duplicate-labels.d.ts +25 -0
  28. package/dist/rules/duplicate-labels.d.ts.map +1 -0
  29. package/dist/rules/duplicate-labels.js +107 -0
  30. package/dist/rules/duplicate-labels.js.map +1 -0
  31. package/dist/rules/index.d.ts +13 -0
  32. package/dist/rules/index.d.ts.map +1 -0
  33. package/dist/rules/index.js +38 -0
  34. package/dist/rules/index.js.map +1 -0
  35. package/dist/rules/missing-hint.d.ts +14 -0
  36. package/dist/rules/missing-hint.d.ts.map +1 -0
  37. package/dist/rules/missing-hint.js +94 -0
  38. package/dist/rules/missing-hint.js.map +1 -0
  39. package/dist/rules/missing-label.d.ts +10 -0
  40. package/dist/rules/missing-label.d.ts.map +1 -0
  41. package/dist/rules/missing-label.js +75 -0
  42. package/dist/rules/missing-label.js.map +1 -0
  43. package/dist/rules/missing-role.d.ts +10 -0
  44. package/dist/rules/missing-role.d.ts.map +1 -0
  45. package/dist/rules/missing-role.js +82 -0
  46. package/dist/rules/missing-role.js.map +1 -0
  47. package/dist/rules/small-touch-target.d.ts +10 -0
  48. package/dist/rules/small-touch-target.d.ts.map +1 -0
  49. package/dist/rules/small-touch-target.js +90 -0
  50. package/dist/rules/small-touch-target.js.map +1 -0
  51. package/dist/rules/touchable-without-label.d.ts +17 -0
  52. package/dist/rules/touchable-without-label.d.ts.map +1 -0
  53. package/dist/rules/touchable-without-label.js +81 -0
  54. package/dist/rules/touchable-without-label.js.map +1 -0
  55. package/dist/scanner/config-loader.d.ts +3 -0
  56. package/dist/scanner/config-loader.d.ts.map +1 -0
  57. package/dist/scanner/config-loader.js +46 -0
  58. package/dist/scanner/config-loader.js.map +1 -0
  59. package/dist/scanner/file-scanner.d.ts +6 -0
  60. package/dist/scanner/file-scanner.d.ts.map +1 -0
  61. package/dist/scanner/file-scanner.js +82 -0
  62. package/dist/scanner/file-scanner.js.map +1 -0
  63. package/dist/scanner/index.d.ts +12 -0
  64. package/dist/scanner/index.d.ts.map +1 -0
  65. package/dist/scanner/index.js +64 -0
  66. package/dist/scanner/index.js.map +1 -0
  67. package/dist/scanner/scorer.d.ts +26 -0
  68. package/dist/scanner/scorer.d.ts.map +1 -0
  69. package/dist/scanner/scorer.js +65 -0
  70. package/dist/scanner/scorer.js.map +1 -0
  71. package/dist/types/index.d.ts +88 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/index.js +13 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/utils/ast.d.ts +24 -0
  76. package/dist/utils/ast.d.ts.map +1 -0
  77. package/dist/utils/ast.js +170 -0
  78. package/dist/utils/ast.js.map +1 -0
  79. package/package.json +67 -0
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CRITICAL_ACTION_KEYWORDS = exports.TOUCHABLE_COMPONENTS = exports.INTERACTIVE_COMPONENTS = void 0;
37
+ exports.getComponentName = getComponentName;
38
+ exports.getJSXAttributes = getJSXAttributes;
39
+ exports.findAttribute = findAttribute;
40
+ exports.hasNonEmptyAttribute = hasNonEmptyAttribute;
41
+ exports.getStringAttributeValue = getStringAttributeValue;
42
+ exports.hasTextChild = hasTextChild;
43
+ exports.extractStyleDimension = extractStyleDimension;
44
+ exports.getSnippet = getSnippet;
45
+ const t = __importStar(require("@babel/types"));
46
+ /** Interactive RN component names that must have accessibility props */
47
+ exports.INTERACTIVE_COMPONENTS = new Set([
48
+ "TouchableOpacity",
49
+ "TouchableHighlight",
50
+ "TouchableNativeFeedback",
51
+ "TouchableWithoutFeedback",
52
+ "Pressable",
53
+ "Button",
54
+ ]);
55
+ /** Components where touch-target rules apply */
56
+ exports.TOUCHABLE_COMPONENTS = new Set([
57
+ "TouchableOpacity",
58
+ "TouchableHighlight",
59
+ "TouchableNativeFeedback",
60
+ "TouchableWithoutFeedback",
61
+ "Pressable",
62
+ ]);
63
+ /** Critical action keywords that should have accessibilityHint */
64
+ exports.CRITICAL_ACTION_KEYWORDS = [
65
+ "delete",
66
+ "remove",
67
+ "purchase",
68
+ "checkout",
69
+ "submit",
70
+ "payment",
71
+ "pay",
72
+ "buy",
73
+ "confirm",
74
+ "cancel",
75
+ ];
76
+ // ─── JSX Helpers ──────────────────────────────────────────────────────────────
77
+ /** Get the component name from a JSXOpeningElement */
78
+ function getComponentName(node) {
79
+ const { name } = node;
80
+ if (t.isJSXIdentifier(name))
81
+ return name.name;
82
+ if (t.isJSXMemberExpression(name)) {
83
+ return `${name.object.name}.${name.property.name}`;
84
+ }
85
+ return null;
86
+ }
87
+ /** Return all JSX attributes from an opening element */
88
+ function getJSXAttributes(node) {
89
+ return node.attributes.filter((a) => t.isJSXAttribute(a));
90
+ }
91
+ /** Find a specific named attribute, or return undefined */
92
+ function findAttribute(node, attrName) {
93
+ return getJSXAttributes(node).find((a) => t.isJSXIdentifier(a.name) && a.name.name === attrName);
94
+ }
95
+ /** Check if an attribute is present AND has a non-empty value */
96
+ function hasNonEmptyAttribute(node, attrName) {
97
+ const attr = findAttribute(node, attrName);
98
+ if (!attr)
99
+ return false;
100
+ const val = attr.value;
101
+ if (!val)
102
+ return true; // bare prop = true (e.g. accessible)
103
+ if (t.isStringLiteral(val))
104
+ return val.value.trim().length > 0;
105
+ if (t.isJSXExpressionContainer(val)) {
106
+ const expr = val.expression;
107
+ if (t.isStringLiteral(expr))
108
+ return expr.value.trim().length > 0;
109
+ if (t.isTemplateLiteral(expr)) {
110
+ return expr.quasis.some((q) => q.value.raw.trim().length > 0) ||
111
+ expr.expressions.length > 0;
112
+ }
113
+ // Dynamic expression — assume it's populated
114
+ return !t.isNullLiteral(expr);
115
+ }
116
+ return false;
117
+ }
118
+ /** Get the string value of an attribute, or null if dynamic/missing */
119
+ function getStringAttributeValue(node, attrName) {
120
+ const attr = findAttribute(node, attrName);
121
+ if (!attr || !attr.value)
122
+ return null;
123
+ if (t.isStringLiteral(attr.value))
124
+ return attr.value.value;
125
+ if (t.isJSXExpressionContainer(attr.value) &&
126
+ t.isStringLiteral(attr.value.expression)) {
127
+ return attr.value.expression.value;
128
+ }
129
+ return null;
130
+ }
131
+ /** Check if a JSXElement has any direct Text children */
132
+ function hasTextChild(node) {
133
+ return node.children.some((child) => {
134
+ if (t.isJSXText(child))
135
+ return child.value.trim().length > 0;
136
+ if (t.isJSXElement(child)) {
137
+ const name = getComponentName(child.openingElement);
138
+ return name === "Text";
139
+ }
140
+ return false;
141
+ });
142
+ }
143
+ /** Extract a style value (width/height) from a style prop — best-effort static analysis */
144
+ function extractStyleDimension(node, dimension) {
145
+ const styleAttr = findAttribute(node, "style");
146
+ if (!styleAttr || !styleAttr.value)
147
+ return null;
148
+ const extractFromObject = (obj) => {
149
+ const prop = obj.properties.find((p) => t.isObjectProperty(p) &&
150
+ ((t.isIdentifier(p.key) && p.key.name === dimension) ||
151
+ (t.isStringLiteral(p.key) && p.key.value === dimension)));
152
+ if (!prop)
153
+ return null;
154
+ if (t.isNumericLiteral(prop.value))
155
+ return prop.value.value;
156
+ return null;
157
+ };
158
+ // style={{ width: 30, height: 30 }}
159
+ if (t.isJSXExpressionContainer(styleAttr.value) &&
160
+ t.isObjectExpression(styleAttr.value.expression)) {
161
+ return extractFromObject(styleAttr.value.expression);
162
+ }
163
+ return null;
164
+ }
165
+ /** Get a short code snippet for an issue (the line of source) */
166
+ function getSnippet(source, line) {
167
+ const lines = source.split("\n");
168
+ return (lines[line - 1] || "").trim();
169
+ }
170
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/utils/ast.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "react-native-accessibility-scanner",
3
+ "version": "0.1.0",
4
+ "description": "Accessibility auditing for React Native apps — CLI, ESLint plugin, GitHub Action, and programmatic API.",
5
+ "keywords": [
6
+ "react-native",
7
+ "accessibility",
8
+ "a11y",
9
+ "eslint",
10
+ "scanner",
11
+ "linting",
12
+ "audit"
13
+ ],
14
+ "author": "Your Name",
15
+ "license": "MIT",
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "bin": {
19
+ "react-native-accessibility-scan": "dist/cli/index.js"
20
+ },
21
+ "exports": {
22
+ ".": "./dist/index.js",
23
+ "./eslint": "./dist/eslint/index.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "test:coverage": "vitest run --coverage",
36
+ "lint": "eslint src --ext .ts",
37
+ "prepublishOnly": "npm run build && npm test"
38
+ },
39
+ "dependencies": {
40
+ "@babel/parser": "^7.23.0",
41
+ "@babel/traverse": "^7.23.0",
42
+ "@babel/types": "^7.23.0",
43
+ "chalk": "^4.1.2",
44
+ "commander": "^11.1.0",
45
+ "cosmiconfig": "^9.0.0",
46
+ "glob": "^10.3.10"
47
+ },
48
+ "devDependencies": {
49
+ "@types/babel__traverse": "^7.20.5",
50
+ "@types/eslint": "^9.6.1",
51
+ "@types/node": "^20.10.0",
52
+ "@vitest/coverage-v8": "^1.0.0",
53
+ "typescript": "^5.3.0",
54
+ "vitest": "^1.0.0"
55
+ },
56
+ "engines": {
57
+ "node": ">=16.0.0"
58
+ },
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "https://github.com/YOUR_USERNAME/react-native-accessibility-scanner"
62
+ },
63
+ "bugs": {
64
+ "url": "https://github.com/YOUR_USERNAME/react-native-accessibility-scanner/issues"
65
+ },
66
+ "homepage": "https://github.com/YOUR_USERNAME/react-native-accessibility-scanner#readme"
67
+ }