qualm-a11y 1.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 (67) hide show
  1. package/README.md +201 -0
  2. package/RESEARCH.md +139 -0
  3. package/dist/analyser.d.ts +3 -0
  4. package/dist/analyser.d.ts.map +1 -0
  5. package/dist/analyser.js +77 -0
  6. package/dist/analyser.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +128 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/diff.d.ts +3 -0
  12. package/dist/diff.d.ts.map +1 -0
  13. package/dist/diff.js +60 -0
  14. package/dist/diff.js.map +1 -0
  15. package/dist/parser.d.ts +3 -0
  16. package/dist/parser.d.ts.map +1 -0
  17. package/dist/parser.js +22 -0
  18. package/dist/parser.js.map +1 -0
  19. package/dist/reporters/json.d.ts +4 -0
  20. package/dist/reporters/json.d.ts.map +1 -0
  21. package/dist/reporters/json.js +20 -0
  22. package/dist/reporters/json.js.map +1 -0
  23. package/dist/reporters/sarif.d.ts +3 -0
  24. package/dist/reporters/sarif.d.ts.map +1 -0
  25. package/dist/reporters/sarif.js +40 -0
  26. package/dist/reporters/sarif.js.map +1 -0
  27. package/dist/reporters/terminal.d.ts +5 -0
  28. package/dist/reporters/terminal.d.ts.map +1 -0
  29. package/dist/reporters/terminal.js +83 -0
  30. package/dist/reporters/terminal.js.map +1 -0
  31. package/dist/rules/aria-correctness.d.ts +3 -0
  32. package/dist/rules/aria-correctness.d.ts.map +1 -0
  33. package/dist/rules/aria-correctness.js +52 -0
  34. package/dist/rules/aria-correctness.js.map +1 -0
  35. package/dist/rules/complexity.d.ts +4 -0
  36. package/dist/rules/complexity.d.ts.map +1 -0
  37. package/dist/rules/complexity.js +86 -0
  38. package/dist/rules/complexity.js.map +1 -0
  39. package/dist/rules/document-structure.d.ts +3 -0
  40. package/dist/rules/document-structure.d.ts.map +1 -0
  41. package/dist/rules/document-structure.js +51 -0
  42. package/dist/rules/document-structure.js.map +1 -0
  43. package/dist/rules/form-semantics.d.ts +3 -0
  44. package/dist/rules/form-semantics.d.ts.map +1 -0
  45. package/dist/rules/form-semantics.js +105 -0
  46. package/dist/rules/form-semantics.js.map +1 -0
  47. package/dist/rules/heading-hierarchy.d.ts +3 -0
  48. package/dist/rules/heading-hierarchy.d.ts.map +1 -0
  49. package/dist/rules/heading-hierarchy.js +37 -0
  50. package/dist/rules/heading-hierarchy.js.map +1 -0
  51. package/dist/rules/index.d.ts +4 -0
  52. package/dist/rules/index.d.ts.map +1 -0
  53. package/dist/rules/index.js +20 -0
  54. package/dist/rules/index.js.map +1 -0
  55. package/dist/rules/interactive-semantics.d.ts +3 -0
  56. package/dist/rules/interactive-semantics.d.ts.map +1 -0
  57. package/dist/rules/interactive-semantics.js +65 -0
  58. package/dist/rules/interactive-semantics.js.map +1 -0
  59. package/dist/rules/landmark-structure.d.ts +3 -0
  60. package/dist/rules/landmark-structure.d.ts.map +1 -0
  61. package/dist/rules/landmark-structure.js +60 -0
  62. package/dist/rules/landmark-structure.js.map +1 -0
  63. package/dist/types.d.ts +73 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +37 -0
  66. package/dist/types.js.map +1 -0
  67. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,OAAO,CAmB/E"}
package/dist/parser.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTSX = parseTSX;
4
+ const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
+ const types_1 = require("./types");
6
+ function parseTSX(sourceCode, filePath) {
7
+ try {
8
+ return (0, typescript_estree_1.parse)(sourceCode, {
9
+ jsx: true,
10
+ loc: true,
11
+ range: true,
12
+ tokens: false,
13
+ comment: false,
14
+ errorOnUnknownASTType: false,
15
+ filePath,
16
+ });
17
+ }
18
+ catch (err) {
19
+ throw new types_1.QualmParserError(`Failed to parse ${filePath}: ${err.message}`, err.lineNumber ?? 0, err.column ?? 0, filePath);
20
+ }
21
+ }
22
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":";;AAIA,4BAmBC;AAvBD,4EAA6D;AAE7D,mCAA2C;AAE3C,SAAgB,QAAQ,CAAC,UAAkB,EAAE,QAAgB;IAC3D,IAAI,CAAC;QACH,OAAO,IAAA,yBAAK,EAAC,UAAU,EAAE;YACvB,GAAG,EAAE,IAAI;YACT,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,KAAK;YACd,qBAAqB,EAAE,KAAK;YAC5B,QAAQ;SACT,CAAqB,CAAC;IACzB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,wBAAgB,CACxB,mBAAmB,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,EAC7C,GAAG,CAAC,UAAU,IAAI,CAAC,EACnB,GAAG,CAAC,MAAM,IAAI,CAAC,EACf,QAAQ,CACT,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { FileAnalysisResult, DiffResult } from '../types';
2
+ export declare function renderJSON(results: FileAnalysisResult[]): string;
3
+ export declare function renderDiffJSON(diff: DiffResult): string;
4
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/reporters/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,wBAAgB,UAAU,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAWhE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderJSON = renderJSON;
4
+ exports.renderDiffJSON = renderDiffJSON;
5
+ function renderJSON(results) {
6
+ return JSON.stringify({
7
+ summary: {
8
+ scannedFiles: results.length,
9
+ totalViolations: results.reduce((a, r) => a + r.violations.length, 0),
10
+ globalSemanticScore: results.length > 0
11
+ ? results.reduce((a, r) => a + r.semanticScore, 0) / results.length
12
+ : 1.0
13
+ },
14
+ results
15
+ }, null, 2);
16
+ }
17
+ function renderDiffJSON(diff) {
18
+ return JSON.stringify(diff, null, 2);
19
+ }
20
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/reporters/json.ts"],"names":[],"mappings":";;AAEA,gCAWC;AAED,wCAEC;AAfD,SAAgB,UAAU,CAAC,OAA6B;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,OAAO,EAAE;YACP,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;YACrE,mBAAmB,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;gBACrC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM;gBACnE,CAAC,CAAC,GAAG;SACR;QACD,OAAO;KACR,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACd,CAAC;AAED,SAAgB,cAAc,CAAC,IAAgB;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { FileAnalysisResult } from '../types';
2
+ export declare function renderSARIF(results: FileAnalysisResult[]): string;
3
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/reporters/sarif.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAG9C,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAqCjE"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderSARIF = renderSARIF;
4
+ const index_1 = require("../rules/index");
5
+ function renderSARIF(results) {
6
+ const sarif = {
7
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
8
+ version: '2.1.0',
9
+ runs: [{
10
+ tool: {
11
+ driver: {
12
+ name: 'qualm',
13
+ version: '1.0.0',
14
+ informationUri: 'https://doi.org/10.5281/zenodo.20482307',
15
+ rules: index_1.activeRules.map(r => ({
16
+ id: r.id,
17
+ shortDescription: { text: r.meta.description },
18
+ helpUri: r.meta.docsUrl ?? 'https://doi.org/10.5281/zenodo.20482307'
19
+ }))
20
+ }
21
+ },
22
+ results: results.flatMap(result => result.violations.map(v => ({
23
+ ruleId: v.ruleId,
24
+ level: v.severity === 'error' ? 'error' : v.severity === 'warning' ? 'warning' : 'note',
25
+ message: { text: v.message },
26
+ locations: [{
27
+ physicalLocation: {
28
+ artifactLocation: { uri: result.filePath },
29
+ region: {
30
+ startLine: v.location.line,
31
+ startColumn: v.location.column + 1
32
+ }
33
+ }
34
+ }]
35
+ })))
36
+ }]
37
+ };
38
+ return JSON.stringify(sarif, null, 2);
39
+ }
40
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/reporters/sarif.ts"],"names":[],"mappings":";;AAGA,kCAqCC;AAvCD,0CAA6C;AAE7C,SAAgB,WAAW,CAAC,OAA6B;IACvD,MAAM,KAAK,GAAG;QACZ,OAAO,EAAE,gGAAgG;QACzG,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,CAAC;gBACL,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,OAAO;wBAChB,cAAc,EAAE,yCAAyC;wBACzD,KAAK,EAAE,mBAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;4BAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;4BACR,gBAAgB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE;4BAC9C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,yCAAyC;yBACrE,CAAC,CAAC;qBACJ;iBACF;gBACD,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAChC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,KAAK,EAAE,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;oBACvF,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;oBAC5B,SAAS,EAAE,CAAC;4BACV,gBAAgB,EAAE;gCAChB,gBAAgB,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE;gCAC1C,MAAM,EAAE;oCACN,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;oCAC1B,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;iCACnC;6BACF;yBACF,CAAC;iBACH,CAAC,CAAC,CACJ;aACF,CAAC;KACH,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { FileAnalysisResult, DiffResult } from '../types';
2
+ export declare function renderTerminal(results: FileAnalysisResult[]): void;
3
+ export declare function renderDiffTerminal(diff: DiffResult): void;
4
+ export declare function renderResearchMode(results: FileAnalysisResult[]): void;
5
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/reporters/terminal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA8C,MAAM,UAAU,CAAC;AAEtG,wBAAgB,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,CA+BlE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAqBzD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAiCtE"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.renderTerminal = renderTerminal;
7
+ exports.renderDiffTerminal = renderDiffTerminal;
8
+ exports.renderResearchMode = renderResearchMode;
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const types_1 = require("../types");
11
+ function renderTerminal(results) {
12
+ const totalViolations = results.reduce((a, r) => a + r.violations.length, 0);
13
+ const avgScore = results.length > 0
14
+ ? results.reduce((a, r) => a + r.semanticScore, 0) / results.length
15
+ : 1.0;
16
+ console.log(chalk_1.default.bold.cyan('\n qualm — Static Quality Analysis\n'));
17
+ console.log(`Scanned ${chalk_1.default.bold(String(results.length))} file(s) · ${chalk_1.default.bold(String(totalViolations))} violation(s) found\n`);
18
+ for (const result of results) {
19
+ if (result.violations.length === 0) {
20
+ console.log(chalk_1.default.green(`✓ ${result.filePath}`));
21
+ continue;
22
+ }
23
+ console.log(chalk_1.default.bold.white(`\n${result.filePath}`));
24
+ for (const v of result.violations) {
25
+ const icon = v.severity === 'error' ? chalk_1.default.red('✗') : chalk_1.default.yellow('⚠');
26
+ const loc = chalk_1.default.dim(`[${v.location.line}:${v.location.column}]`);
27
+ const cat = chalk_1.default.dim(`[${v.category}]`);
28
+ const sev = v.severity === 'error' ? chalk_1.default.red(v.severity) : chalk_1.default.yellow(v.severity);
29
+ console.log(` ${icon} ${loc} ${cat} ${sev}: ${v.message}`);
30
+ console.log(` ${chalk_1.default.cyan('→')} ${v.fixSuggestion}`);
31
+ if (v.snippet)
32
+ console.log(` ${chalk_1.default.dim(v.snippet.trim().slice(0, 120))}`);
33
+ }
34
+ }
35
+ console.log(chalk_1.default.bold('\n📊 Summary — Sharma (2026) Taxonomy'));
36
+ console.log('─'.repeat(60));
37
+ console.log(`Mean Semantic Score : ${chalk_1.default.bold(avgScore.toFixed(4))} ${chalk_1.default.dim('(paper baseline: treated-pre=0.989, treated-post=0.983)')}`);
38
+ }
39
+ function renderDiffTerminal(diff) {
40
+ const icon = diff.regressionDetected
41
+ ? chalk_1.default.red('REGRESSION DETECTED')
42
+ : chalk_1.default.green('✓ No regression');
43
+ console.log(`\n${icon} · ${diff.filePath}`);
44
+ console.log(` Semantic Score: ${diff.before?.semanticScore.toFixed(4) ?? 'N/A'} → ${diff.after.semanticScore.toFixed(4)} (Δ ${diff.deltaSemanticScore.toFixed(4)})`);
45
+ console.log(` Violations: ${diff.before?.violationsCount ?? 0} → ${diff.after.violationsCount}`);
46
+ if (diff.addedViolations.length > 0) {
47
+ console.log(chalk_1.default.red(`\n Added violations (${diff.addedViolations.length}):`));
48
+ for (const v of diff.addedViolations) {
49
+ console.log(` + [${v.category}] ${v.message}`);
50
+ }
51
+ }
52
+ if (diff.removedViolations.length > 0) {
53
+ console.log(chalk_1.default.green(`\n Removed violations (${diff.removedViolations.length}):`));
54
+ for (const v of diff.removedViolations) {
55
+ console.log(` - [${v.category}] ${v.message}`);
56
+ }
57
+ }
58
+ }
59
+ function renderResearchMode(results) {
60
+ console.log(chalk_1.default.bold.cyan('\nqualm Research Mode — Sharma (2026) Taxonomy\n'));
61
+ console.log('─'.repeat(80));
62
+ console.log(`${'Category'.padEnd(28)} | ${'Violations'.padEnd(12)} | ${'β (paper)'.padEnd(12)} | Weighted Score`);
63
+ console.log('─'.repeat(80));
64
+ const allViolations = results.flatMap(r => r.violations);
65
+ const totalBeta = Object.values(types_1.PAPER_BETA_COEFFICIENTS).reduce((a, b) => a + b, 0);
66
+ let compositeScore = 0;
67
+ for (const [category, beta] of Object.entries(types_1.PAPER_BETA_COEFFICIENTS)) {
68
+ const count = allViolations.filter(v => v.category === category).length;
69
+ const weight = beta / totalBeta;
70
+ const weighted = weight * count * 0.05;
71
+ compositeScore += weighted;
72
+ const betaStr = (beta >= 0 ? '+' : '') + beta.toFixed(3);
73
+ console.log(`${category.padEnd(28)} | ${String(count).padEnd(12)} | ${betaStr.padEnd(12)} | ${weighted.toFixed(4)}`);
74
+ }
75
+ console.log('─'.repeat(80));
76
+ const avgBaseline = results.length > 0
77
+ ? results.reduce((a, r) => a + r.semanticScore, 0) / results.length
78
+ : 1.0;
79
+ console.log(`${'Composite Regression Score'.padEnd(28)} | ${compositeScore.toFixed(4).padEnd(12)} | ${'Baseline'.padEnd(12)} | ${avgBaseline.toFixed(4)}`);
80
+ console.log('─'.repeat(80));
81
+ console.log(chalk_1.default.dim('Paper baseline (Table A1): treated-pre AST score = 0.989, treated-post = 0.983'));
82
+ }
83
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/reporters/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Rule } from '../types';
2
+ export declare const ariaCorrectnessRule: Rule;
3
+ //# sourceMappingURL=aria-correctness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aria-correctness.d.ts","sourceRoot":"","sources":["../../src/rules/aria-correctness.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAWhC,eAAO,MAAM,mBAAmB,EAAE,IA4CjC,CAAC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ariaCorrectnessRule = void 0;
4
+ const BOOLEAN_ARIA_ATTRS = new Set([
5
+ 'aria-expanded', 'aria-hidden', 'aria-checked', 'aria-selected',
6
+ 'aria-pressed', 'aria-disabled', 'aria-invalid', 'aria-required',
7
+ 'aria-multiselectable', 'aria-readonly', 'aria-busy', 'aria-modal',
8
+ 'aria-atomic', 'aria-grabbed'
9
+ ]);
10
+ const VALID_BOOLEAN_VALUES = new Set(['true', 'false']);
11
+ exports.ariaCorrectnessRule = {
12
+ id: 'aria-correctness',
13
+ category: 'aria_correctness',
14
+ severity: 'error',
15
+ meta: {
16
+ description: 'Enforce valid ARIA attribute values per WAI-ARIA specification'
17
+ },
18
+ create(context) {
19
+ return {
20
+ JSXAttribute(node) {
21
+ const attrName = node.name.type === 'JSXIdentifier' ? node.name.name : null;
22
+ if (!attrName || !attrName.startsWith('aria-'))
23
+ return;
24
+ if (!BOOLEAN_ARIA_ATTRS.has(attrName))
25
+ return;
26
+ // Bare boolean attribute (e.g. aria-disabled with no value) is invalid —
27
+ // WAI-ARIA requires an explicit "true" or "false" string.
28
+ if (!node.value) {
29
+ context.report({
30
+ message: `${attrName} used as a bare boolean attribute. WAI-ARIA requires an explicit string value: "true" or "false".`,
31
+ fixSuggestion: `Change to ${attrName}="true" to make the intent explicit and ensure assistive technology reads it correctly.`,
32
+ location: context.getLoc(node),
33
+ snippet: context.getSourceCode(node)
34
+ });
35
+ return;
36
+ }
37
+ if (node.value.type === 'Literal' &&
38
+ typeof node.value.value === 'string') {
39
+ if (!VALID_BOOLEAN_VALUES.has(node.value.value)) {
40
+ context.report({
41
+ message: `Invalid value "${node.value.value}" for ${attrName}. Boolean ARIA attributes only accept "true" or "false".`,
42
+ fixSuggestion: `Change to ${attrName}="true" or ${attrName}="false", or use a dynamic expression like ${attrName}={isOpen ? "true" : "false"}.`,
43
+ location: context.getLoc(node),
44
+ snippet: context.getSourceCode(node)
45
+ });
46
+ }
47
+ }
48
+ }
49
+ };
50
+ }
51
+ };
52
+ //# sourceMappingURL=aria-correctness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aria-correctness.js","sourceRoot":"","sources":["../../src/rules/aria-correctness.ts"],"names":[],"mappings":";;;AAGA,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe;IAC/D,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe;IAChE,sBAAsB,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY;IAClE,aAAa,EAAE,cAAc;CAC9B,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3C,QAAA,mBAAmB,GAAS;IACvC,EAAE,EAAE,kBAAkB;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE;QACJ,WAAW,EAAE,gEAAgE;KAC9E;IACD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,YAAY,CAAC,IAA2B;gBACtC,MAAM,QAAQ,GACZ,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7D,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;oBAAE,OAAO;gBAEvD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,OAAO;gBAE9C,yEAAyE;gBACzE,0DAA0D;gBAC1D,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAChB,OAAO,CAAC,MAAM,CAAC;wBACb,OAAO,EAAE,GAAG,QAAQ,mGAAmG;wBACvH,aAAa,EAAE,aAAa,QAAQ,yFAAyF;wBAC7H,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;wBAC9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;qBACrC,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,IACE,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;oBAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EACpC,CAAC;oBACD,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;wBAChD,OAAO,CAAC,MAAM,CAAC;4BACb,OAAO,EAAE,kBAAkB,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,QAAQ,0DAA0D;4BACtH,aAAa,EAAE,aAAa,QAAQ,cAAc,QAAQ,8CAA8C,QAAQ,+BAA+B;4BAC/I,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;4BAC9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;yBACrC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { TSESTree } from '@typescript-eslint/utils';
2
+ import { ComplexityMetrics } from '../types';
3
+ export declare function calculateComplexityMetrics(ast: TSESTree.Program, sourceCode: string): ComplexityMetrics;
4
+ //# sourceMappingURL=complexity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.d.ts","sourceRoot":"","sources":["../../src/rules/complexity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAmC7C,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,QAAQ,CAAC,OAAO,EACrB,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAwDnB"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateComplexityMetrics = calculateComplexityMetrics;
4
+ const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
+ const CYCLOMATIC_NODES = new Set([
6
+ 'IfStatement', 'ConditionalExpression', 'SwitchCase',
7
+ 'ForStatement', 'ForInStatement', 'ForOfStatement',
8
+ 'WhileStatement', 'DoWhileStatement', 'LogicalExpression',
9
+ 'CatchClause'
10
+ ]);
11
+ // Recursively compute max JSX nesting depth
12
+ function jsxDepth(node) {
13
+ if (node.type === 'JSXElement') {
14
+ const childDepths = node.children.map(c => jsxDepth(c));
15
+ return 1 + (childDepths.length > 0 ? Math.max(...childDepths) : 0);
16
+ }
17
+ let max = 0;
18
+ for (const key of Object.keys(node)) {
19
+ const child = node[key];
20
+ if (child && typeof child === 'object') {
21
+ if (Array.isArray(child)) {
22
+ for (const item of child) {
23
+ if (item && typeof item === 'object' && 'type' in item) {
24
+ const d = jsxDepth(item);
25
+ if (d > max)
26
+ max = d;
27
+ }
28
+ }
29
+ }
30
+ else if ('type' in child) {
31
+ const d = jsxDepth(child);
32
+ if (d > max)
33
+ max = d;
34
+ }
35
+ }
36
+ }
37
+ return max;
38
+ }
39
+ function calculateComplexityMetrics(ast, sourceCode) {
40
+ let cyclomaticComplexity = 1;
41
+ let cognitiveComplexity = 0;
42
+ let nestingDepth = 0;
43
+ let nodeCount = 0;
44
+ let propsCount = 0;
45
+ // Track nesting via parent stack — simpleTraverse is enter-only, so we
46
+ // increment nesting when entering control flow nodes and use node.range
47
+ // to determine when we've "exited" them.
48
+ // Simpler: count nesting depth by tracking enter-only and resetting on
49
+ // function/component boundaries.
50
+ const nestingStack = [];
51
+ (0, typescript_estree_1.simpleTraverse)(ast, {
52
+ enter(node) {
53
+ nodeCount++;
54
+ if (CYCLOMATIC_NODES.has(node.type)) {
55
+ cyclomaticComplexity++;
56
+ }
57
+ // Cognitive complexity: add (1 + current nesting level) for control flow
58
+ if (node.type === 'IfStatement' ||
59
+ node.type === 'ForStatement' ||
60
+ node.type === 'WhileStatement' ||
61
+ node.type === 'ForOfStatement' ||
62
+ node.type === 'ForInStatement' ||
63
+ node.type === 'DoWhileStatement') {
64
+ cognitiveComplexity += 1 + nestingStack.length;
65
+ nestingStack.push(node.type);
66
+ }
67
+ if (node.type === 'JSXAttribute') {
68
+ propsCount++;
69
+ }
70
+ }
71
+ });
72
+ const linesOfCode = sourceCode.split('\n').length;
73
+ // Compute max JSX nesting depth via recursive walk
74
+ const maxJsxNestingDepth = jsxDepth(ast);
75
+ const propDrillingDepth = Math.max(0, maxJsxNestingDepth - 3);
76
+ return {
77
+ cyclomaticComplexity,
78
+ cognitiveComplexity,
79
+ maxJsxNestingDepth,
80
+ linesOfCode,
81
+ nodeCount,
82
+ propsCount,
83
+ propDrillingDepth
84
+ };
85
+ }
86
+ //# sourceMappingURL=complexity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../src/rules/complexity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Rule } from '../types';
2
+ export declare const documentStructureRule: Rule;
3
+ //# sourceMappingURL=document-structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-structure.d.ts","sourceRoot":"","sources":["../../src/rules/document-structure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAOhC,eAAO,MAAM,qBAAqB,EAAE,IA4CnC,CAAC"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.documentStructureRule = void 0;
4
+ const INTERACTIVE_EVENT_HANDLERS = new Set([
5
+ 'onClick', 'onKeyDown', 'onKeyUp', 'onKeyPress',
6
+ 'onFocus', 'onBlur', 'onMouseDown', 'onMouseUp'
7
+ ]);
8
+ exports.documentStructureRule = {
9
+ id: 'document-structure',
10
+ category: 'document_structure',
11
+ severity: 'error',
12
+ meta: {
13
+ description: 'Enforce semantic HTML elements over generic containers with interactive handlers',
14
+ docsUrl: 'https://doi.org/10.5281/zenodo.20482307'
15
+ },
16
+ create(context) {
17
+ return {
18
+ JSXOpeningElement(node) {
19
+ const elementName = node.name.type === 'JSXIdentifier' ? node.name.name : null;
20
+ if (!elementName)
21
+ return;
22
+ if (elementName !== 'div' && elementName !== 'span')
23
+ return;
24
+ const attrs = node.attributes;
25
+ const hasInteractiveHandler = attrs.some(attr => {
26
+ if (attr.type !== 'JSXAttribute')
27
+ return false;
28
+ const name = attr.name.type === 'JSXIdentifier' ? attr.name.name : null;
29
+ return name !== null && INTERACTIVE_EVENT_HANDLERS.has(name);
30
+ });
31
+ if (!hasInteractiveHandler)
32
+ return;
33
+ const hasRoleAttr = attrs.some(attr => {
34
+ if (attr.type !== 'JSXAttribute')
35
+ return false;
36
+ const name = attr.name.type === 'JSXIdentifier' ? attr.name.name : null;
37
+ return name === 'role';
38
+ });
39
+ if (hasRoleAttr)
40
+ return;
41
+ context.report({
42
+ message: `Generic <${elementName}> element has interactive event handler without semantic element or explicit role. This is the dominant AI-generated code quality failure mode identified in Sharma (2026).`,
43
+ fixSuggestion: `Replace <${elementName}> with a semantic element like <button> for click handlers, or add role="button" with tabIndex={0} as a minimum. Prefer semantic HTML over role overrides.`,
44
+ location: context.getLoc(node),
45
+ snippet: context.getSourceCode(node)
46
+ });
47
+ }
48
+ };
49
+ }
50
+ };
51
+ //# sourceMappingURL=document-structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-structure.js","sourceRoot":"","sources":["../../src/rules/document-structure.ts"],"names":[],"mappings":";;;AAGA,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IACzC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY;IAC/C,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW;CAChD,CAAC,CAAC;AAEU,QAAA,qBAAqB,GAAS;IACzC,EAAE,EAAE,oBAAoB;IACxB,QAAQ,EAAE,oBAAoB;IAC9B,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE;QACJ,WAAW,EAAE,kFAAkF;QAC/F,OAAO,EAAE,yCAAyC;KACnD;IACD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,MAAM,WAAW,GACf,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAE7D,IAAI,CAAC,WAAW;oBAAE,OAAO;gBACzB,IAAI,WAAW,KAAK,KAAK,IAAI,WAAW,KAAK,MAAM;oBAAE,OAAO;gBAE5D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;gBAE9B,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;wBAAE,OAAO,KAAK,CAAC;oBAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;oBACxE,OAAO,IAAI,KAAK,IAAI,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC/D,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,qBAAqB;oBAAE,OAAO;gBAEnC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACpC,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;wBAAE,OAAO,KAAK,CAAC;oBAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;oBACxE,OAAO,IAAI,KAAK,MAAM,CAAC;gBACzB,CAAC,CAAC,CAAC;gBAEH,IAAI,WAAW;oBAAE,OAAO;gBAExB,OAAO,CAAC,MAAM,CAAC;oBACb,OAAO,EAAE,YAAY,WAAW,6KAA6K;oBAC7M,aAAa,EAAE,YAAY,WAAW,4JAA4J;oBAClM,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;oBAC9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;iBACrC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Rule } from '../types';
2
+ export declare const formSemanticsRule: Rule;
3
+ //# sourceMappingURL=form-semantics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-semantics.d.ts","sourceRoot":"","sources":["../../src/rules/form-semantics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAoBhC,eAAO,MAAM,iBAAiB,EAAE,IA8F/B,CAAC"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formSemanticsRule = void 0;
4
+ const FORM_CONTROLS = new Set(['input', 'select', 'textarea']);
5
+ // Walk up the parent chain to detect implicit label wrapping.
6
+ // simpleTraverse doesn't set parent pointers, so we track the JSXElement
7
+ // ancestor stack ourselves via JSXElement enter/exit using a set of range starts.
8
+ function isInsideLabelElement(node, labelRanges) {
9
+ // We stored range[0] of every open <label> JSXElement that is currently open
10
+ // on the stack. If any open label's range contains this node's range, it's wrapped.
11
+ // Since simpleTraverse is single-pass enter-only in our analyser context, we
12
+ // instead record all label JSXElement ranges and check containment by range.
13
+ for (const labelStart of labelRanges) {
14
+ if (node.range && node.range[0] > labelStart) {
15
+ return true;
16
+ }
17
+ }
18
+ return false;
19
+ }
20
+ exports.formSemanticsRule = {
21
+ id: 'form-semantics',
22
+ category: 'form_semantics',
23
+ severity: 'error',
24
+ meta: {
25
+ description: 'Ensure form controls have associated label elements'
26
+ },
27
+ create(context) {
28
+ const labelHtmlFors = new Set();
29
+ const inputsWithIds = [];
30
+ // Track range[0] of every <label> JSXElement opening tag seen in the file.
31
+ // Used to detect implicit label wrapping (input inside <label>...</label>).
32
+ const labelElementRanges = [];
33
+ return {
34
+ JSXElement(node) {
35
+ const openingName = node.openingElement.name.type === 'JSXIdentifier'
36
+ ? node.openingElement.name.name : null;
37
+ if (openingName === 'label' && node.range) {
38
+ labelElementRanges.push({ start: node.range[0], end: node.range[1] });
39
+ }
40
+ },
41
+ JSXAttribute(node) {
42
+ const attrName = node.name.type === 'JSXIdentifier' ? node.name.name : null;
43
+ if (attrName !== 'htmlFor')
44
+ return;
45
+ if (node.value?.type === 'Literal' &&
46
+ typeof node.value.value === 'string') {
47
+ labelHtmlFors.add(node.value.value);
48
+ }
49
+ },
50
+ JSXOpeningElement(node) {
51
+ const name = node.name.type === 'JSXIdentifier' ? node.name.name : null;
52
+ if (!name || !FORM_CONTROLS.has(name))
53
+ return;
54
+ const hasAriaLabel = node.attributes.some(attr => {
55
+ if (attr.type !== 'JSXAttribute')
56
+ return false;
57
+ const n = attr.name.type === 'JSXIdentifier' ? attr.name.name : null;
58
+ return n === 'aria-label' || n === 'aria-labelledby';
59
+ });
60
+ if (hasAriaLabel)
61
+ return;
62
+ // Implicit label: input is wrapped inside a <label> element
63
+ const isImplicitlyLabelled = node.range
64
+ ? labelElementRanges.some(l => node.range[0] > l.start && node.range[0] < l.end)
65
+ : false;
66
+ if (isImplicitlyLabelled)
67
+ return;
68
+ const idAttr = node.attributes.find(attr => {
69
+ if (attr.type !== 'JSXAttribute')
70
+ return false;
71
+ return attr.name.type === 'JSXIdentifier' && attr.name.name === 'id';
72
+ });
73
+ const idValue = idAttr?.value?.type === 'Literal' &&
74
+ typeof idAttr.value.value === 'string'
75
+ ? idAttr.value.value
76
+ : null;
77
+ if (idValue) {
78
+ inputsWithIds.push({ id: idValue, node });
79
+ }
80
+ else {
81
+ context.report({
82
+ message: `<${name}> has no associated label. Add a <label htmlFor="..."> or aria-label attribute.`,
83
+ fixSuggestion: `Add an id to the <${name}> and a matching <label htmlFor="id"> element, or use aria-label="Description".`,
84
+ location: context.getLoc(node),
85
+ snippet: context.getSourceCode(node)
86
+ });
87
+ }
88
+ },
89
+ 'Program:exit'() {
90
+ for (const { id, node } of inputsWithIds) {
91
+ if (!labelHtmlFors.has(id)) {
92
+ const name = node.name.type === 'JSXIdentifier' ? node.name.name : 'input';
93
+ context.report({
94
+ message: `<${name} id="${id}"> has no associated <label htmlFor="${id}">. Form controls must be programmatically associated with labels.`,
95
+ fixSuggestion: `Add <label htmlFor="${id}">Label text</label> before or after the form control.`,
96
+ location: context.getLoc(node),
97
+ snippet: context.getSourceCode(node)
98
+ });
99
+ }
100
+ }
101
+ }
102
+ };
103
+ }
104
+ };
105
+ //# sourceMappingURL=form-semantics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-semantics.js","sourceRoot":"","sources":["../../src/rules/form-semantics.ts"],"names":[],"mappings":";;;AAGA,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/D,8DAA8D;AAC9D,yEAAyE;AACzE,kFAAkF;AAClF,SAAS,oBAAoB,CAAC,IAAgC,EAAE,WAAwB;IACtF,6EAA6E;IAC7E,oFAAoF;IACpF,6EAA6E;IAC7E,6EAA6E;IAC7E,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAEY,QAAA,iBAAiB,GAAS;IACrC,EAAE,EAAE,gBAAgB;IACpB,QAAQ,EAAE,gBAAgB;IAC1B,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE;QACJ,WAAW,EAAE,qDAAqD;KACnE;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,MAAM,aAAa,GAAuD,EAAE,CAAC;QAC7E,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,kBAAkB,GAAqC,EAAE,CAAC;QAEhE,OAAO;YACL,UAAU,CAAC,IAAyB;gBAClC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oBACnE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzC,IAAI,WAAW,KAAK,OAAO,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC1C,kBAAkB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAA2B;gBACtC,MAAM,QAAQ,GACZ,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7D,IAAI,QAAQ,KAAK,SAAS;oBAAE,OAAO;gBAEnC,IACE,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS;oBAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EACpC,CAAC;oBACD,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;YAED,iBAAiB,CAAC,IAAgC;gBAChD,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7D,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAE9C,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;wBAAE,OAAO,KAAK,CAAC;oBAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;oBACrE,OAAO,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,iBAAiB,CAAC;gBACvD,CAAC,CAAC,CAAC;gBAEH,IAAI,YAAY;oBAAE,OAAO;gBAEzB,4DAA4D;gBAC5D,MAAM,oBAAoB,GAAG,IAAI,CAAC,KAAK;oBACrC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;oBAClF,CAAC,CAAC,KAAK,CAAC;gBACV,IAAI,oBAAoB;oBAAE,OAAO;gBAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACzC,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;wBAAE,OAAO,KAAK,CAAC;oBAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;gBACvE,CAAC,CAAsC,CAAC;gBAExC,MAAM,OAAO,GACX,MAAM,EAAE,KAAK,EAAE,IAAI,KAAK,SAAS;oBACjC,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ;oBACpC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK;oBACpB,CAAC,CAAC,IAAI,CAAC;gBAEX,IAAI,OAAO,EAAE,CAAC;oBACZ,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5C,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC;wBACb,OAAO,EAAE,IAAI,IAAI,iFAAiF;wBAClG,aAAa,EAAE,qBAAqB,IAAI,iFAAiF;wBACzH,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;wBAC9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;qBACrC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,cAAc;gBACZ,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;oBACzC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;wBAC3B,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;wBAChE,OAAO,CAAC,MAAM,CAAC;4BACb,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,wCAAwC,EAAE,oEAAoE;4BACzI,aAAa,EAAE,uBAAuB,EAAE,wDAAwD;4BAChG,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;4BAC9B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;yBACrC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Rule } from '../types';
2
+ export declare const headingHierarchyRule: Rule;
3
+ //# sourceMappingURL=heading-hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heading-hierarchy.d.ts","sourceRoot":"","sources":["../../src/rules/heading-hierarchy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAIhC,eAAO,MAAM,oBAAoB,EAAE,IAkClC,CAAC"}