zemdomu 1.3.14 → 1.3.16

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 (40) hide show
  1. package/README.md +20 -4
  2. package/out/cli.js +22 -1
  3. package/out/component-analyzer.d.ts +22 -0
  4. package/out/component-analyzer.js +429 -74
  5. package/out/index.d.ts +2 -1
  6. package/out/index.js +5 -1
  7. package/out/project-linter.d.ts +2 -0
  8. package/out/project-linter.js +38 -0
  9. package/out/rules/enforceListNesting.js +6 -44
  10. package/out/rules/requireAltText.js +20 -16
  11. package/out/rules/requireHrefOnAnchors.js +16 -5
  12. package/out/rules/requireLinkText.js +41 -16
  13. package/out/rules/requireNavLinks.js +8 -2
  14. package/out/rules/singleH1.js +85 -6
  15. package/out/rules/utils.d.ts +9 -0
  16. package/out/rules/utils.js +181 -0
  17. package/out/src/cli.js +22 -1
  18. package/out/src/component-analyzer.js +429 -74
  19. package/out/src/index.js +5 -1
  20. package/out/src/project-linter.js +38 -0
  21. package/out/src/rules/enforceListNesting.js +6 -44
  22. package/out/src/rules/requireAltText.js +20 -16
  23. package/out/src/rules/requireHrefOnAnchors.js +16 -5
  24. package/out/src/rules/requireLinkText.js +41 -16
  25. package/out/src/rules/requireNavLinks.js +8 -2
  26. package/out/src/rules/singleH1.js +85 -6
  27. package/out/src/rules/utils.js +181 -0
  28. package/out/tests/cli-custom-rule.test.js +19 -0
  29. package/out/tests/cli-performance.test.js +35 -0
  30. package/out/tests/cross-list-nesting.test.js +34 -0
  31. package/out/tests/cross-section-heading.test.js +32 -0
  32. package/out/tests/exports-helpers.test.js +45 -0
  33. package/out/tests/img-alt-dynamic.test.js +39 -0
  34. package/out/tests/link-href-text.test.js +52 -0
  35. package/out/tests/list-nesting-dynamic.test.js +27 -0
  36. package/out/tests/nav-links-components.test.js +27 -0
  37. package/out/tests/parse-error-multifile.test.js +29 -0
  38. package/out/tests/single-h1-returns.test.js +74 -0
  39. package/out/tests/vue-support.test.js +59 -0
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -109,8 +109,13 @@ npx zemdomu "src/**/*.html,src/**/*.jsx"
109
109
  ```
110
110
 
111
111
  Use `--custom` (or `-c`) to provide a path to a JavaScript or TypeScript module
112
- exporting a custom rule or array of rules. Use `--cross` to enable cross
113
- component analysis.
112
+ exporting a custom rule or array of rules. For safety, the CLI only accepts
113
+ files inside a `./custom-rules` directory (relative to your current working
114
+ directory). You can repeat `--custom` to load multiple rule files. Use `--cross`
115
+ to enable cross component analysis.
116
+
117
+ Use `--perf` to emit a JSON timing report to stdout, and `--perf-slowest` to
118
+ also print the slowest file and phase.
114
119
 
115
120
  ### Cross-component analysis
116
121
 
@@ -186,7 +191,11 @@ import {
186
191
  visitHtml,
187
192
  getAttr,
188
193
  getJsxAttr,
194
+ getJsxAttribute,
195
+ getJsxAttributeState,
196
+ getJsxExpressionState,
189
197
  getTag,
198
+ isJsxExpressionPossiblyEmpty,
190
199
  ElementNode,
191
200
  HtmlVisitor,
192
201
  } from "zemdomu";
@@ -195,14 +204,21 @@ import {
195
204
  `parseHtml` returns the root `ElementNode`. The `visitHtml` function performs a
196
205
  simple depth-first traversal using an `HtmlVisitor` with optional `enter` and
197
206
  `exit` callbacks. Utility functions like `getAttr` and `getJsxAttr` help reading
198
- attributes, while `getTag` resolves JSX element names.
207
+ attributes. JSX helpers like `getJsxAttribute`, `getJsxAttributeState`, and
208
+ `getJsxExpressionState` help interpret JSX attributes and expressions, while
209
+ `getTag` resolves JSX element names.
199
210
 
200
211
  Or via the CLI:
201
212
 
202
213
  ```bash
203
- npx zemdomu file.html --custom my-rule.js
214
+ mkdir -p custom-rules
215
+ cp my-rule.js custom-rules/my-rule.js
216
+ npx zemdomu file.html --custom custom-rules/my-rule.js
217
+ npx zemdomu "src/**/*.{html,jsx,tsx,vue}" --perf --perf-slowest
204
218
  ```
205
219
 
220
+ There is a sample rule in `custom-rules/example-rule.js` you can copy and edit.
221
+
206
222
  ## Local development (monorepo)
207
223
 
208
224
  From the core package:
package/out/cli.js CHANGED
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const glob_1 = require("glob");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const project_linter_1 = require("./project-linter");
10
+ const performance_diagnostics_1 = require("./performance-diagnostics");
10
11
  const rule_codes_1 = require("./rule-codes");
11
12
  function parsePatterns(inputs) {
12
13
  const result = [];
@@ -26,6 +27,8 @@ async function run() {
26
27
  const customRules = [];
27
28
  let cross = false;
28
29
  let depth;
30
+ let perfEnabled = false;
31
+ let perfSlowest = false;
29
32
  for (let i = 0; i < args.length; i++) {
30
33
  const arg = args[i];
31
34
  if (arg === '--custom' || arg === '-c') {
@@ -48,6 +51,13 @@ async function run() {
48
51
  else if (arg === '--cross') {
49
52
  cross = true;
50
53
  }
54
+ else if (arg === '--perf') {
55
+ perfEnabled = true;
56
+ }
57
+ else if (arg === '--perf-slowest') {
58
+ perfEnabled = true;
59
+ perfSlowest = true;
60
+ }
51
61
  else if (arg === '--cross-depth') {
52
62
  const val = args[++i];
53
63
  if (!val)
@@ -71,7 +81,13 @@ async function run() {
71
81
  for (const m of matches)
72
82
  files.add(m);
73
83
  }
74
- const linter = new project_linter_1.ProjectLinter({ customRules, crossComponentAnalysis: cross, crossComponentDepth: depth });
84
+ const perf = perfEnabled ? new performance_diagnostics_1.PerformanceDiagnostics() : undefined;
85
+ const linter = new project_linter_1.ProjectLinter({
86
+ customRules,
87
+ crossComponentAnalysis: cross,
88
+ crossComponentDepth: depth,
89
+ perf,
90
+ });
75
91
  const results = await linter.lintFiles(Array.from(files));
76
92
  let hasIssues = false;
77
93
  for (const [file, issues] of results.entries()) {
@@ -81,6 +97,11 @@ async function run() {
81
97
  hasIssues = true;
82
98
  }
83
99
  }
100
+ if (perfEnabled && perf) {
101
+ process.stdout.write(perf.getAsJSON() + '\n');
102
+ if (perfSlowest)
103
+ perf.logSlowest();
104
+ }
84
105
  if (hasIssues)
85
106
  process.exit(1);
86
107
  }
@@ -13,6 +13,9 @@ interface ComponentReference {
13
13
  usageLocations: Array<{
14
14
  line: number;
15
15
  column: number;
16
+ inListDirect?: boolean;
17
+ inSection?: boolean;
18
+ renderGroup?: string;
16
19
  }>;
17
20
  }
18
21
  interface HeadingInfo {
@@ -34,6 +37,19 @@ interface NavInfo {
34
37
  hasLocalLink: boolean;
35
38
  childComponents: ComponentReference[];
36
39
  }
40
+ interface SectionInfo {
41
+ filePath: string;
42
+ line: number;
43
+ column: number;
44
+ hasLocalHeading: boolean;
45
+ childComponents: ComponentReference[];
46
+ }
47
+ interface ListItemInfo {
48
+ filePath: string;
49
+ line: number;
50
+ column: number;
51
+ nesting: 'root' | 'inList' | 'inOther';
52
+ }
37
53
  interface ComponentDefinition {
38
54
  name: string;
39
55
  filePath: string;
@@ -43,6 +59,9 @@ interface ComponentDefinition {
43
59
  ids: IdInfo[];
44
60
  navs: NavInfo[];
45
61
  hasLocalAnchor: boolean;
62
+ sections: SectionInfo[];
63
+ hasHeadingOutsideSection: boolean;
64
+ listItems: ListItemInfo[];
46
65
  }
47
66
  export declare class ComponentAnalyzer {
48
67
  private componentRegistry;
@@ -80,9 +99,12 @@ export declare class ComponentAnalyzer {
80
99
  private findCrossComponentDuplicateIds;
81
100
  private collectIds;
82
101
  private findCrossComponentNavLinks;
102
+ private findCrossComponentListNestingIssues;
83
103
  private checkNavs;
84
104
  private navHasLink;
85
105
  private componentHasAnchor;
106
+ getListNestingSuppressions(): Map<string, Set<string>>;
107
+ getSectionHeadingSuppressions(): Map<string, Set<string>>;
86
108
  private findEntryPoints;
87
109
  private findComponentsWithRule;
88
110
  }