@macrulez/devtoolz 0.1.0 → 0.2.1

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 (135) hide show
  1. package/README.md +197 -2
  2. package/dist/cli.js +314 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/circular-imports/core.d.ts +15 -0
  5. package/dist/commands/circular-imports/core.js +95 -0
  6. package/dist/commands/circular-imports/core.js.map +1 -0
  7. package/dist/commands/circular-imports/report.d.ts +3 -0
  8. package/dist/commands/circular-imports/report.js +41 -0
  9. package/dist/commands/circular-imports/report.js.map +1 -0
  10. package/dist/commands/circular-imports/run.d.ts +19 -0
  11. package/dist/commands/circular-imports/run.js +29 -0
  12. package/dist/commands/circular-imports/run.js.map +1 -0
  13. package/dist/commands/dead-exports/core.d.ts +1 -1
  14. package/dist/commands/dead-exports/core.js +2 -2
  15. package/dist/commands/dead-exports/core.js.map +1 -1
  16. package/dist/commands/dead-exports/entry.d.ts +0 -1
  17. package/dist/commands/dead-exports/entry.js +1 -14
  18. package/dist/commands/dead-exports/entry.js.map +1 -1
  19. package/dist/commands/dead-exports/run.js +3 -2
  20. package/dist/commands/dead-exports/run.js.map +1 -1
  21. package/dist/commands/empty-catch/core.d.ts +8 -0
  22. package/dist/commands/empty-catch/core.js +61 -0
  23. package/dist/commands/empty-catch/core.js.map +1 -0
  24. package/dist/commands/empty-catch/report.d.ts +3 -0
  25. package/dist/commands/empty-catch/report.js +27 -0
  26. package/dist/commands/empty-catch/report.js.map +1 -0
  27. package/dist/commands/empty-catch/run.d.ts +17 -0
  28. package/dist/commands/empty-catch/run.js +34 -0
  29. package/dist/commands/empty-catch/run.js.map +1 -0
  30. package/dist/commands/empty-catch/vue.d.ts +2 -0
  31. package/dist/commands/empty-catch/vue.js +16 -0
  32. package/dist/commands/empty-catch/vue.js.map +1 -0
  33. package/dist/commands/full-check/report.d.ts +3 -0
  34. package/dist/commands/full-check/report.js +61 -0
  35. package/dist/commands/full-check/report.js.map +1 -0
  36. package/dist/commands/full-check/run.d.ts +32 -0
  37. package/dist/commands/full-check/run.js +251 -0
  38. package/dist/commands/full-check/run.js.map +1 -0
  39. package/dist/commands/orphan-tests/core.d.ts +9 -0
  40. package/dist/commands/orphan-tests/core.js +42 -0
  41. package/dist/commands/orphan-tests/core.js.map +1 -0
  42. package/dist/commands/orphan-tests/report.d.ts +3 -0
  43. package/dist/commands/orphan-tests/report.js +30 -0
  44. package/dist/commands/orphan-tests/report.js.map +1 -0
  45. package/dist/commands/orphan-tests/run.d.ts +25 -0
  46. package/dist/commands/orphan-tests/run.js +55 -0
  47. package/dist/commands/orphan-tests/run.js.map +1 -0
  48. package/dist/commands/readme-check/run.js +8 -3
  49. package/dist/commands/readme-check/run.js.map +1 -1
  50. package/dist/commands/scripts-check/core.d.ts +18 -0
  51. package/dist/commands/scripts-check/core.js +121 -0
  52. package/dist/commands/scripts-check/core.js.map +1 -0
  53. package/dist/commands/scripts-check/report.d.ts +3 -0
  54. package/dist/commands/scripts-check/report.js +34 -0
  55. package/dist/commands/scripts-check/report.js.map +1 -0
  56. package/dist/commands/scripts-check/run.d.ts +15 -0
  57. package/dist/commands/scripts-check/run.js +81 -0
  58. package/dist/commands/scripts-check/run.js.map +1 -0
  59. package/dist/commands/stale-ts-ignore/check.d.ts +23 -0
  60. package/dist/commands/stale-ts-ignore/check.js +104 -0
  61. package/dist/commands/stale-ts-ignore/check.js.map +1 -0
  62. package/dist/commands/stale-ts-ignore/core.d.ts +11 -0
  63. package/dist/commands/stale-ts-ignore/core.js +42 -0
  64. package/dist/commands/stale-ts-ignore/core.js.map +1 -0
  65. package/dist/commands/stale-ts-ignore/report.d.ts +3 -0
  66. package/dist/commands/stale-ts-ignore/report.js +30 -0
  67. package/dist/commands/stale-ts-ignore/report.js.map +1 -0
  68. package/dist/commands/stale-ts-ignore/run.d.ts +23 -0
  69. package/dist/commands/stale-ts-ignore/run.js +101 -0
  70. package/dist/commands/stale-ts-ignore/run.js.map +1 -0
  71. package/dist/commands/stale-ts-ignore/vue.d.ts +9 -0
  72. package/dist/commands/stale-ts-ignore/vue.js +16 -0
  73. package/dist/commands/stale-ts-ignore/vue.js.map +1 -0
  74. package/dist/commands/strip-comments/core.js +2 -56
  75. package/dist/commands/strip-comments/core.js.map +1 -1
  76. package/dist/commands/todo-report/core.d.ts +16 -0
  77. package/dist/commands/todo-report/core.js +112 -0
  78. package/dist/commands/todo-report/core.js.map +1 -0
  79. package/dist/commands/todo-report/report.d.ts +3 -0
  80. package/dist/commands/todo-report/report.js +31 -0
  81. package/dist/commands/todo-report/report.js.map +1 -0
  82. package/dist/commands/todo-report/run.d.ts +22 -0
  83. package/dist/commands/todo-report/run.js +41 -0
  84. package/dist/commands/todo-report/run.js.map +1 -0
  85. package/dist/commands/todo-report/vue.d.ts +2 -0
  86. package/dist/commands/todo-report/vue.js +71 -0
  87. package/dist/commands/todo-report/vue.js.map +1 -0
  88. package/dist/commands/unused-deps/config-files.d.ts +9 -0
  89. package/dist/commands/unused-deps/config-files.js +64 -0
  90. package/dist/commands/unused-deps/config-files.js.map +1 -0
  91. package/dist/commands/unused-deps/core.d.ts +25 -0
  92. package/dist/commands/unused-deps/core.js +121 -0
  93. package/dist/commands/unused-deps/core.js.map +1 -0
  94. package/dist/commands/unused-deps/disk-resolve.d.ts +11 -0
  95. package/dist/commands/unused-deps/disk-resolve.js +40 -0
  96. package/dist/commands/unused-deps/disk-resolve.js.map +1 -0
  97. package/dist/commands/unused-deps/package-name.d.ts +8 -0
  98. package/dist/commands/unused-deps/package-name.js +20 -0
  99. package/dist/commands/unused-deps/package-name.js.map +1 -0
  100. package/dist/commands/unused-deps/report.d.ts +3 -0
  101. package/dist/commands/unused-deps/report.js +32 -0
  102. package/dist/commands/unused-deps/report.js.map +1 -0
  103. package/dist/commands/unused-deps/run.d.ts +18 -0
  104. package/dist/commands/unused-deps/run.js +68 -0
  105. package/dist/commands/unused-deps/run.js.map +1 -0
  106. package/dist/index.d.ts +54 -5
  107. package/dist/index.js +35 -3
  108. package/dist/index.js.map +1 -1
  109. package/dist/utils/escape-regexp.d.ts +1 -0
  110. package/dist/utils/escape-regexp.js +4 -0
  111. package/dist/utils/escape-regexp.js.map +1 -0
  112. package/dist/utils/find-comments.d.ts +10 -0
  113. package/dist/utils/find-comments.js +62 -0
  114. package/dist/utils/find-comments.js.map +1 -0
  115. package/dist/utils/find-package-dir.d.ts +2 -0
  116. package/dist/utils/find-package-dir.js +15 -0
  117. package/dist/utils/find-package-dir.js.map +1 -0
  118. package/dist/utils/line-of.d.ts +2 -0
  119. package/dist/utils/line-of.js +12 -0
  120. package/dist/utils/line-of.js.map +1 -0
  121. package/dist/utils/load-tsconfig.d.ts +20 -0
  122. package/dist/utils/load-tsconfig.js +33 -0
  123. package/dist/utils/load-tsconfig.js.map +1 -0
  124. package/dist/utils/parse-module.d.ts +32 -0
  125. package/dist/utils/parse-module.js +178 -0
  126. package/dist/utils/parse-module.js.map +1 -0
  127. package/dist/utils/resolve-specifier.d.ts +15 -0
  128. package/dist/utils/resolve-specifier.js +63 -0
  129. package/dist/utils/resolve-specifier.js.map +1 -0
  130. package/dist/utils/walk.js +20 -1
  131. package/dist/utils/walk.js.map +1 -1
  132. package/dist/utils/workspace.d.ts +14 -0
  133. package/dist/utils/workspace.js +101 -0
  134. package/dist/utils/workspace.js.map +1 -0
  135. package/package.json +1 -1
@@ -0,0 +1,101 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join, relative, resolve } from 'node:path';
3
+ import ts from 'typescript';
4
+ import { loadTsconfig } from '../../utils/load-tsconfig.js';
5
+ import { walk } from '../../utils/walk.js';
6
+ import { findTsIgnoreDirectives, blankDirectives } from './core.js';
7
+ import { extractVueScript, findVueTsIgnoreDirectives } from './vue.js';
8
+ import { runProjectTypecheck, checkIsolatedFile, normalize } from './check.js';
9
+ function scriptKindFor(file) {
10
+ if (file.endsWith('.tsx'))
11
+ return ts.ScriptKind.TSX;
12
+ if (file.endsWith('.jsx'))
13
+ return ts.ScriptKind.JSX;
14
+ if (file.endsWith('.js') || file.endsWith('.mjs') || file.endsWith('.cjs'))
15
+ return ts.ScriptKind.JS;
16
+ return ts.ScriptKind.TS;
17
+ }
18
+ export function runStaleTsIgnore(options) {
19
+ const packageDir = resolve(options.dir);
20
+ const loaded = loadTsconfig(packageDir, options.tsconfig);
21
+ if ('error' in loaded) {
22
+ return { directivesChecked: 0, findings: [], error: loaded.error, exitCode: 1 };
23
+ }
24
+ const tsFiles = new Map();
25
+ for (const fileName of loaded.fileNames) {
26
+ let text;
27
+ try {
28
+ text = readFileSync(fileName, 'utf8');
29
+ }
30
+ catch {
31
+ continue;
32
+ }
33
+ const sf = ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, scriptKindFor(fileName));
34
+ const directives = findTsIgnoreDirectives(text, sf);
35
+ if (directives.length > 0)
36
+ tsFiles.set(normalize(fileName), { text, directives });
37
+ }
38
+ const vueFiles = new Map();
39
+ for (const absFile of walk(['.'], {
40
+ cwd: packageDir,
41
+ extensions: ['.vue'],
42
+ ignoreGlobs: options.ignoreGlobs ?? [],
43
+ ...(options.respectGitignore !== undefined
44
+ ? { respectGitignore: options.respectGitignore }
45
+ : {}),
46
+ })) {
47
+ const text = readFileSync(absFile, 'utf8');
48
+ const script = extractVueScript(text);
49
+ if (!script)
50
+ continue;
51
+ const directives = findVueTsIgnoreDirectives(script.body);
52
+ if (directives.length > 0) {
53
+ vueFiles.set(absFile, { body: script.body, lineOffset: script.lineOffset, directives });
54
+ }
55
+ }
56
+ const directivesChecked = [...tsFiles.values()].reduce((n, f) => n + f.directives.length, 0) +
57
+ [...vueFiles.values()].reduce((n, f) => n + f.directives.length, 0);
58
+ if (directivesChecked === 0) {
59
+ return { directivesChecked: 0, findings: [], error: null, exitCode: 0 };
60
+ }
61
+ options.onProgress?.('Running a project-wide typecheck, twice — this can take a while on a large project…');
62
+ const findings = [];
63
+ if (tsFiles.size > 0) {
64
+ const before = runProjectTypecheck(loaded.fileNames, loaded.options);
65
+ const overrides = new Map();
66
+ for (const [key, { text, directives }] of tsFiles) {
67
+ overrides.set(key, blankDirectives(text, directives));
68
+ }
69
+ const after = runProjectTypecheck(loaded.fileNames, loaded.options, overrides);
70
+ for (const [key, { directives }] of tsFiles) {
71
+ for (const d of directives) {
72
+ const wasAlreadyThere = before.get(key)?.has(d.targetLine) ?? false;
73
+ const appearedAfterBlanking = after.get(key)?.has(d.targetLine) ?? false;
74
+ if (appearedAfterBlanking && !wasAlreadyThere)
75
+ continue;
76
+ findings.push({ file: relative(packageDir, key).split('\\').join('/'), line: d.line });
77
+ }
78
+ }
79
+ }
80
+ for (const [absFile, { body, lineOffset, directives }] of vueFiles) {
81
+ const virtualFileName = normalize(join(dirname(absFile), '__devtoolz_stale_ts_ignore__.ts'));
82
+ const before = checkIsolatedFile(virtualFileName, body, loaded.options);
83
+ const after = checkIsolatedFile(virtualFileName, blankDirectives(body, directives), loaded.options);
84
+ for (const d of directives) {
85
+ if (after.has(d.targetLine) && !before.has(d.targetLine))
86
+ continue;
87
+ findings.push({
88
+ file: relative(packageDir, absFile).split('\\').join('/'),
89
+ line: d.line + lineOffset,
90
+ });
91
+ }
92
+ }
93
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
94
+ return {
95
+ directivesChecked,
96
+ findings,
97
+ error: null,
98
+ exitCode: findings.length > 0 ? 1 : 0,
99
+ };
100
+ }
101
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/stale-ts-ignore/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type TsIgnoreDirective } from './core.js';
2
+ export interface VueScript {
3
+ /** the <script> block's own text, starting right after the opening tag */
4
+ body: string;
5
+ /** how many lines come before the block in the real .vue file */
6
+ lineOffset: number;
7
+ }
8
+ export declare function extractVueScript(text: string): VueScript | null;
9
+ export declare function findVueTsIgnoreDirectives(body: string): TsIgnoreDirective[];
@@ -0,0 +1,16 @@
1
+ import ts from 'typescript';
2
+ import { findTsIgnoreDirectives } from './core.js';
3
+ const SCRIPT_RE = /(<script[^>]*>)([\s\S]*?)(<\/script>)/;
4
+ export function extractVueScript(text) {
5
+ const match = text.match(SCRIPT_RE);
6
+ if (!match)
7
+ return null;
8
+ const [, , body] = match;
9
+ const lineOffset = (text.slice(0, match.index).match(/\n/g) ?? []).length;
10
+ return { body, lineOffset };
11
+ }
12
+ export function findVueTsIgnoreDirectives(body) {
13
+ const sf = ts.createSourceFile('f.ts', body, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
14
+ return findTsIgnoreDirectives(body, sf);
15
+ }
16
+ //# sourceMappingURL=vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.js","sourceRoot":"","sources":["../../../src/commands/stale-ts-ignore/vue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EAAE,sBAAsB,EAA0B,MAAM,WAAW,CAAA;AAE1E,MAAM,SAAS,GAAG,uCAAuC,CAAA;AASzD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,CAAC,EAAE,AAAD,EAAG,IAAI,CAAC,GAAG,KAAyC,CAAA;IAC5D,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;IACzE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;AAC7B,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,MAAM,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAC5F,OAAO,sBAAsB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AACzC,CAAC"}
@@ -15,59 +15,7 @@
15
15
  // everything outside a comment is byte-identical to the input.
16
16
  import ts from 'typescript';
17
17
  import { applyDeletions, collapseBlankLineRuns } from './apply-deletions.js';
18
- const LITERAL_KINDS = new Set([
19
- ts.SyntaxKind.StringLiteral,
20
- ts.SyntaxKind.NoSubstitutionTemplateLiteral,
21
- ts.SyntaxKind.TemplateHead,
22
- ts.SyntaxKind.TemplateMiddle,
23
- ts.SyntaxKind.TemplateTail,
24
- ts.SyntaxKind.RegularExpressionLiteral,
25
- ts.SyntaxKind.JsxText,
26
- ]);
27
- function findLiteralRanges(sf) {
28
- const ranges = [];
29
- function visit(node) {
30
- if (LITERAL_KINDS.has(node.kind)) {
31
- ranges.push([node.getStart(sf), node.getEnd()]);
32
- }
33
- ts.forEachChild(node, visit);
34
- }
35
- visit(sf);
36
- return ranges;
37
- }
38
- function maskLiterals(text, ranges) {
39
- // `ts.SourceFile` positions are UTF-16 CODE UNIT offsets (same as
40
- // `string.length`/`charAt`) — `[...text]`/`Array.from(text)` iterate by
41
- // CODE POINT instead, collapsing any surrogate pair (an emoji, or any
42
- // character outside the BMP) into a single array element. The moment a
43
- // literal masked earlier in the file contains one, every position after
44
- // it drifts by one (or more) index, and later deletions land on the
45
- // wrong bytes entirely. `split('')` is UTF-16-code-unit based — it
46
- // splits a surrogate pair into its two halves instead of merging them,
47
- // which is exactly what keeps this array's indices aligned with the
48
- // parser's.
49
- const chars = text.split('');
50
- for (const [s, e] of ranges) {
51
- for (let i = s; i < e; i++) {
52
- if (chars[i] !== '\n')
53
- chars[i] = 'x';
54
- }
55
- }
56
- return chars.join('');
57
- }
58
- function findCommentRanges(maskedText) {
59
- const ranges = [];
60
- const scanner = ts.createScanner(ts.ScriptTarget.Latest, false, ts.LanguageVariant.Standard, maskedText);
61
- let tok = scanner.scan();
62
- while (tok !== ts.SyntaxKind.EndOfFileToken) {
63
- if (tok === ts.SyntaxKind.SingleLineCommentTrivia ||
64
- tok === ts.SyntaxKind.MultiLineCommentTrivia) {
65
- ranges.push([scanner.getTokenStart(), scanner.getTokenEnd()]);
66
- }
67
- tok = scanner.scan();
68
- }
69
- return ranges;
70
- }
18
+ import { findCommentRanges } from '../../utils/find-comments.js';
71
19
  // Every `/** ... */` immediately leading an `export`-modified declaration
72
20
  // — these are what `keepJsdoc` protects from deletion. Only JSDoc-style
73
21
  // (`/**`, not a plain `/*`) counts, matching the convention IDEs actually
@@ -94,9 +42,7 @@ function findExportedJsdocRanges(sf, text) {
94
42
  export function stripComments(text, options = {}) {
95
43
  const scriptKind = options.scriptKind ?? ts.ScriptKind.TS;
96
44
  const sf = ts.createSourceFile('f.ts', text, ts.ScriptTarget.Latest, true, scriptKind);
97
- const literalRanges = findLiteralRanges(sf);
98
- const masked = maskLiterals(text, literalRanges);
99
- let comments = findCommentRanges(masked);
45
+ let comments = findCommentRanges(text, sf);
100
46
  if (comments.length === 0)
101
47
  return { text, changed: false, count: 0 };
102
48
  if (options.keepJsdoc) {
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/strip-comments/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/strip-comments/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface TodoFinding {
2
+ line: number;
3
+ column: number;
4
+ tag: string;
5
+ text: string;
6
+ }
7
+ export declare const DEFAULT_TAGS: string[];
8
+ export declare function buildTagMatcher(tags: string[]): {
9
+ pattern: RegExp;
10
+ canonical: Map<string, string>;
11
+ };
12
+ export declare function collectNoteText(rawLines: string[], startIndex: number, clean: (line: string) => string, pattern: RegExp): {
13
+ text: string;
14
+ consumedThrough: number;
15
+ };
16
+ export declare function analyzeTodoReport(text: string, file: string, tags?: string[]): TodoFinding[];
@@ -0,0 +1,112 @@
1
+ import ts from 'typescript';
2
+ import { findCommentRanges } from '../../utils/find-comments.js';
3
+ import { escapeRegExp } from '../../utils/escape-regexp.js';
4
+ export const DEFAULT_TAGS = ['TODO', 'FIXME', 'HACK'];
5
+ function scriptKindFor(file) {
6
+ return file.endsWith('.tsx')
7
+ ? ts.ScriptKind.TSX
8
+ : file.endsWith('.jsx')
9
+ ? ts.ScriptKind.JSX
10
+ : ts.ScriptKind.TS;
11
+ }
12
+ // Matches a configured tag as its own word anywhere in a comment line
13
+ // (`// see TODO above` counts, same as most editors' TODO highlighters) —
14
+ // case-insensitively, but the reported `tag` is always the CONFIGURED
15
+ // spelling/casing, not whatever casing happened to appear in the source.
16
+ export function buildTagMatcher(tags) {
17
+ const canonical = new Map();
18
+ for (const tag of tags)
19
+ canonical.set(tag.toLowerCase(), tag);
20
+ const alternation = tags.map(escapeRegExp).join('|');
21
+ return { pattern: new RegExp(`\\b(?:${alternation})\\b`, 'i'), canonical };
22
+ }
23
+ // Strips the comment syntax itself (`//`, `/*`, trailing `*/`, a leading
24
+ // `*` on a block comment's continuation lines) off one line of a comment,
25
+ // so the reported text is just what a human wrote.
26
+ function cleanCommentLine(line) {
27
+ return line
28
+ .replace(/\*\/\s*$/, '')
29
+ .replace(/^\s*\/\*+/, '')
30
+ .replace(/^\s*\/\/+/, '')
31
+ .replace(/^\s*\*/, '')
32
+ .trim();
33
+ }
34
+ // A note is often wrapped across several lines — a run of `//` comments,
35
+ // or one line of a `/* */` block — and only the FIRST line contains the
36
+ // tag. Reporting just that line cuts the sentence off mid-thought (found
37
+ // via real dogfooding against npm-center's own data files: a genuine
38
+ // wrapped TODO came back truncated at "see design.md ..." with no
39
+ // continuation). This keeps absorbing subsequent lines of the same
40
+ // comment as long as they're non-empty and don't themselves start a NEW
41
+ // tagged note, joining them into one readable line.
42
+ export function collectNoteText(rawLines, startIndex, clean, pattern) {
43
+ const parts = [clean(rawLines[startIndex])];
44
+ let j = startIndex + 1;
45
+ while (j < rawLines.length) {
46
+ const line = rawLines[j];
47
+ const cleaned = clean(line);
48
+ if (!cleaned || pattern.test(line))
49
+ break;
50
+ parts.push(cleaned);
51
+ j++;
52
+ }
53
+ return { text: parts.join(' '), consumedThrough: j };
54
+ }
55
+ // `findCommentRanges` gives each `//` line its own separate range (that's
56
+ // how the TS scanner tokenizes them) — merges adjacent ones (nothing but
57
+ // indentation and a single newline between them) into one logical block,
58
+ // the same unit a `/* */` comment already is, so a wrapped `//` note can
59
+ // be collected the same way.
60
+ function mergeAdjacentLineComments(text, ranges) {
61
+ const merged = [];
62
+ for (const range of ranges) {
63
+ const [s, e] = range;
64
+ const last = merged[merged.length - 1];
65
+ const isLineComment = text[s] === '/' && text[s + 1] === '/';
66
+ const lastIsLineComment = last && text[last[0]] === '/' && text[last[0] + 1] === '/';
67
+ if (last &&
68
+ isLineComment &&
69
+ lastIsLineComment &&
70
+ /^[ \t]*\n[ \t]*$/.test(text.slice(last[1], s))) {
71
+ last[1] = e;
72
+ }
73
+ else {
74
+ merged.push([s, e]);
75
+ }
76
+ }
77
+ return merged;
78
+ }
79
+ export function analyzeTodoReport(text, file, tags = DEFAULT_TAGS) {
80
+ const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, scriptKindFor(file));
81
+ const { pattern, canonical } = buildTagMatcher(tags);
82
+ const findings = [];
83
+ const ranges = mergeAdjacentLineComments(text, findCommentRanges(text, sf));
84
+ for (const [start, end] of ranges) {
85
+ const commentText = text.slice(start, end);
86
+ const rawLines = commentText.split('\n');
87
+ let lineStart = start;
88
+ let i = 0;
89
+ while (i < rawLines.length) {
90
+ const rawLine = rawLines[i];
91
+ const match = pattern.exec(rawLine);
92
+ if (match) {
93
+ const pos = sf.getLineAndCharacterOfPosition(lineStart + match.index);
94
+ const { text: noteText, consumedThrough } = collectNoteText(rawLines, i, cleanCommentLine, pattern);
95
+ findings.push({
96
+ line: pos.line + 1,
97
+ column: pos.character + 1,
98
+ tag: canonical.get(match[0].toLowerCase()) ?? match[0],
99
+ text: noteText,
100
+ });
101
+ for (let k = i; k < consumedThrough; k++)
102
+ lineStart += rawLines[k].length + 1;
103
+ i = consumedThrough;
104
+ continue;
105
+ }
106
+ lineStart += rawLine.length + 1;
107
+ i++;
108
+ }
109
+ }
110
+ return findings;
111
+ }
112
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/todo-report/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type VibesOptions } from '../../format/vibes.js';
2
+ import type { TodoReportReport } from './run.js';
3
+ export declare function renderTodoReportReport(report: TodoReportReport, options?: VibesOptions): string;
@@ -0,0 +1,31 @@
1
+ import { banner, cleanCelebration } from '../../format/vibes.js';
2
+ import { formatFindingsRows } from '../../format/findings-list.js';
3
+ export function renderTodoReportReport(report, options = {}) {
4
+ const isClean = report.findings.length === 0;
5
+ if (options.quiet && isClean)
6
+ return '';
7
+ const lines = [];
8
+ if (!options.quiet && !options.plain)
9
+ lines.push(banner(), '');
10
+ lines.push(`Scanned ${report.filesScanned} file${report.filesScanned === 1 ? '' : 's'}.`, '');
11
+ if (isClean) {
12
+ lines.push(cleanCelebration(options));
13
+ return lines.join('\n');
14
+ }
15
+ const tagSummary = Object.entries(report.countsByTag)
16
+ .map(([tag, count]) => `${tag}: ${count}`)
17
+ .join(', ');
18
+ lines.push(`${report.findings.length} comment${report.findings.length === 1 ? '' : 's'} found (${tagSummary}):`);
19
+ lines.push(...formatFindingsRows(report.findings.map((f) => ({
20
+ location: `${f.file}:${f.line}:${f.column}`,
21
+ name: f.tag,
22
+ tag: f.text,
23
+ })), options));
24
+ if (report.max > 0) {
25
+ lines.push('', report.exitCode === 0
26
+ ? `Within the configured limit (--max ${report.max}).`
27
+ : `Over the configured limit (--max ${report.max}).`);
28
+ }
29
+ return lines.join('\n');
30
+ }
31
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/todo-report/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAGlE,MAAM,UAAU,sBAAsB,CACpC,MAAwB,EACxB,UAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;IAC5C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IAE9D,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,YAAY,QAAQ,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,CAAC,CAAA;IAE7F,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;SAClD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;SACzC,IAAI,CAAC,IAAI,CAAC,CAAA;IACb,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,UAAU,IAAI,CACrG,CAAA;IACD,KAAK,CAAC,IAAI,CACR,GAAG,kBAAkB,CACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE;QAC3C,IAAI,EAAE,CAAC,CAAC,GAAG;QACX,GAAG,EAAE,CAAC,CAAC,IAAI;KACZ,CAAC,CAAC,EACH,OAAO,CACR,CACF,CAAA;IAED,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CACR,EAAE,EACF,MAAM,CAAC,QAAQ,KAAK,CAAC;YACnB,CAAC,CAAC,sCAAsC,MAAM,CAAC,GAAG,IAAI;YACtD,CAAC,CAAC,oCAAoC,MAAM,CAAC,GAAG,IAAI,CACvD,CAAA;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type TodoFinding } from './core.js';
2
+ export interface TodoReportRunOptions {
3
+ paths: string[];
4
+ cwd: string;
5
+ extensions?: string[];
6
+ ignoreGlobs?: string[];
7
+ respectGitignore?: boolean;
8
+ tags?: string[];
9
+ /** don't fail (exit 1) unless findings exceed this count — a ratchet for projects living with existing debt */
10
+ max?: number;
11
+ }
12
+ export interface TodoFileFinding extends TodoFinding {
13
+ file: string;
14
+ }
15
+ export interface TodoReportReport {
16
+ filesScanned: number;
17
+ findings: TodoFileFinding[];
18
+ countsByTag: Record<string, number>;
19
+ max: number;
20
+ exitCode: number;
21
+ }
22
+ export declare function runTodoReport(options: TodoReportRunOptions): TodoReportReport;
@@ -0,0 +1,41 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { relative } from 'node:path';
3
+ import { walk } from '../../utils/walk.js';
4
+ import { analyzeTodoReport, DEFAULT_TAGS } from './core.js';
5
+ import { analyzeTodoReportVue } from './vue.js';
6
+ const DEFAULT_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs', '.vue'];
7
+ export function runTodoReport(options) {
8
+ const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
9
+ const tags = options.tags ?? DEFAULT_TAGS;
10
+ const max = options.max ?? 0;
11
+ const files = walk(options.paths, {
12
+ cwd: options.cwd,
13
+ extensions,
14
+ ignoreGlobs: options.ignoreGlobs ?? [],
15
+ ...(options.respectGitignore !== undefined
16
+ ? { respectGitignore: options.respectGitignore }
17
+ : {}),
18
+ });
19
+ const findings = [];
20
+ for (const file of files) {
21
+ const text = readFileSync(file, 'utf8');
22
+ const fileFindings = file.endsWith('.vue')
23
+ ? analyzeTodoReportVue(text, file, tags)
24
+ : analyzeTodoReport(text, file, tags);
25
+ const relFile = relative(options.cwd, file).split('\\').join('/');
26
+ for (const f of fileFindings)
27
+ findings.push({ ...f, file: relFile });
28
+ }
29
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
30
+ const countsByTag = {};
31
+ for (const f of findings)
32
+ countsByTag[f.tag] = (countsByTag[f.tag] ?? 0) + 1;
33
+ return {
34
+ filesScanned: files.length,
35
+ findings,
36
+ countsByTag,
37
+ max,
38
+ exitCode: findings.length > max ? 1 : 0,
39
+ };
40
+ }
41
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/todo-report/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAoB,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAE/C,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAyBjF,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAA;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,CAAA;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;QAChC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;QACtC,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS;YACxC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE;YAChD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACxC,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACxC,CAAC,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjE,KAAK,MAAM,CAAC,IAAI,YAAY;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;IACtE,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;IAExE,MAAM,WAAW,GAA2B,EAAE,CAAA;IAC9C,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IAE5E,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,MAAM;QAC1B,QAAQ;QACR,WAAW;QACX,GAAG;QACH,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACxC,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type TodoFinding } from './core.js';
2
+ export declare function analyzeTodoReportVue(text: string, file: string, tags?: string[]): TodoFinding[];
@@ -0,0 +1,71 @@
1
+ // `.vue` handling, same split as strip-comments/vue.ts: the `<script>`
2
+ // block goes through the real TS-parser path (core.ts), and the
3
+ // `<template>` block's `<!-- -->` comments are matched by regex — no full
4
+ // SFC template parser here, so a `<!-- -->`-looking sequence inside a
5
+ // bound attribute string would be misread as a real comment. Same known,
6
+ // documented limitation as strip-comments.
7
+ import { analyzeTodoReport, buildTagMatcher, collectNoteText, DEFAULT_TAGS, } from './core.js';
8
+ const SCRIPT_RE = /(<script[^>]*>)([\s\S]*?)(<\/script>)/;
9
+ const TEMPLATE_RE = /(<template[^>]*>)([\s\S]*?)(<\/template>)/;
10
+ const TEMPLATE_COMMENT_RE = /<!--[\s\S]*?-->/g;
11
+ function lineAt(text, index) {
12
+ return (text.slice(0, index).match(/\n/g) ?? []).length;
13
+ }
14
+ function cleanTemplateLine(line) {
15
+ return line
16
+ .replace(/^\s*<!--/, '')
17
+ .replace(/-->\s*$/, '')
18
+ .trim();
19
+ }
20
+ function findTemplateTodos(body, tags) {
21
+ const findings = [];
22
+ const { pattern, canonical } = buildTagMatcher(tags);
23
+ for (const match of body.matchAll(TEMPLATE_COMMENT_RE)) {
24
+ const start = match.index;
25
+ const rawLines = match[0].split('\n');
26
+ let lineStart = start;
27
+ let i = 0;
28
+ while (i < rawLines.length) {
29
+ const rawLine = rawLines[i];
30
+ const m = pattern.exec(rawLine);
31
+ if (m) {
32
+ const { text: noteText, consumedThrough } = collectNoteText(rawLines, i, cleanTemplateLine, pattern);
33
+ findings.push({
34
+ line: lineAt(body, lineStart + m.index) + 1,
35
+ column: lineStart + m.index - body.lastIndexOf('\n', lineStart + m.index),
36
+ tag: canonical.get(m[0].toLowerCase()) ?? m[0],
37
+ text: noteText,
38
+ });
39
+ for (let k = i; k < consumedThrough; k++)
40
+ lineStart += rawLines[k].length + 1;
41
+ i = consumedThrough;
42
+ continue;
43
+ }
44
+ lineStart += rawLine.length + 1;
45
+ i++;
46
+ }
47
+ }
48
+ return findings;
49
+ }
50
+ export function analyzeTodoReportVue(text, file, tags = DEFAULT_TAGS) {
51
+ const findings = [];
52
+ const scriptMatch = text.match(SCRIPT_RE);
53
+ if (scriptMatch) {
54
+ const [, , body] = scriptMatch;
55
+ const offset = lineAt(text, scriptMatch.index);
56
+ for (const f of analyzeTodoReport(body, file.replace(/\.vue$/, '.ts'), tags)) {
57
+ findings.push({ ...f, line: f.line + offset });
58
+ }
59
+ }
60
+ const templateMatch = text.match(TEMPLATE_RE);
61
+ if (templateMatch) {
62
+ const [, , body] = templateMatch;
63
+ const offset = lineAt(text, templateMatch.index);
64
+ for (const f of findTemplateTodos(body, tags)) {
65
+ findings.push({ ...f, line: f.line + offset });
66
+ }
67
+ }
68
+ findings.sort((a, b) => a.line - b.line || a.column - b.column);
69
+ return findings;
70
+ }
71
+ //# sourceMappingURL=vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.js","sourceRoot":"","sources":["../../../src/commands/todo-report/vue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function readConfigFilesText(packageDir: string): string;
2
+ /**
3
+ * Whether `name` appears as its own token anywhere in `text` — either
4
+ * quoted (`extends: 'stylelint-config-standard'`) or a bare identifier
5
+ * (`plugins: { autoprefixer: {} }`). Bounded on both sides so a
6
+ * different package that merely contains `name` as a substring
7
+ * (`autoprefixer-wrapper`, `@scope/autoprefixer`) doesn't count.
8
+ */
9
+ export declare function textReferencesPackage(text: string, name: string): boolean;