jsdoczoom 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.
- package/dist/barrel.js +37 -36
- package/dist/cli.js +248 -163
- package/dist/drilldown.js +173 -163
- package/dist/errors.js +14 -14
- package/dist/eslint-engine.js +214 -96
- package/dist/eslint-plugin.js +316 -159
- package/dist/file-discovery.js +44 -42
- package/dist/index.js +1 -1
- package/dist/jsdoc-parser.js +157 -157
- package/dist/lint.js +44 -29
- package/dist/selector.js +24 -21
- package/dist/skill-text.js +488 -7
- package/dist/type-declarations.js +83 -69
- package/dist/types.js +6 -6
- package/dist/validate.js +84 -69
- package/package.json +7 -1
- package/types/barrel.d.ts +4 -1
- package/types/drilldown.d.ts +12 -2
- package/types/errors.d.ts +8 -8
- package/types/eslint-engine.d.ts +23 -11
- package/types/eslint-plugin.d.ts +6 -5
- package/types/file-discovery.d.ts +5 -1
- package/types/index.d.ts +18 -1
- package/types/lint.d.ts +11 -2
- package/types/skill-text.d.ts +4 -1
- package/types/types.d.ts +59 -43
- package/types/validate.d.ts +11 -2
package/dist/skill-text.js
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
/** Markdown guidance text for each validation status category */
|
|
11
11
|
export const GUIDANCE = {
|
|
12
|
-
|
|
12
|
+
syntax_error: `### Syntax error
|
|
13
13
|
|
|
14
14
|
The file has TypeScript parse errors that prevent analysis. Fix syntax errors first — no JSDoc validation can run until the file parses cleanly.`,
|
|
15
|
-
|
|
15
|
+
missing_jsdoc: `### Missing file-level JSDoc
|
|
16
16
|
|
|
17
17
|
Add a \`/** ... */\` block before the first code statement (after imports). This block is what jsdoczoom reads for orientation and validation.
|
|
18
18
|
|
|
@@ -27,7 +27,7 @@ import { resolve } from "node:path";
|
|
|
27
27
|
|
|
28
28
|
export function example() { ... }
|
|
29
29
|
\`\`\``,
|
|
30
|
-
|
|
30
|
+
missing_summary: `### The @summary tag
|
|
31
31
|
|
|
32
32
|
The \`@summary\` tag provides a one-line overview — the first thing someone sees when scanning with jsdoczoom at the shallowest depth.
|
|
33
33
|
|
|
@@ -48,17 +48,35 @@ The \`@summary\` tag provides a one-line overview — the first thing someone se
|
|
|
48
48
|
- \`@summary This file contains utility functions\` — says what it *contains*, not what it *does*
|
|
49
49
|
- \`@summary Helpers\` — too vague, no domain context
|
|
50
50
|
- \`@summary The main module\` — no information about purpose or scope`,
|
|
51
|
-
|
|
51
|
+
multiple_summary: `### Multiple @summary tags
|
|
52
52
|
|
|
53
53
|
Each file must have exactly one \`@summary\` tag. Remove the extra \`@summary\` tags and keep a single one-line overview.`,
|
|
54
|
-
|
|
54
|
+
missing_barrel: `### Missing barrel file
|
|
55
55
|
|
|
56
56
|
Directories with more than 3 TypeScript files should have an \`index.ts\` barrel file. The barrel provides a module-level \`@summary\` and description that helps agents understand what the directory contains before drilling into individual files.
|
|
57
57
|
|
|
58
58
|
Create an \`index.ts\` that re-exports the directory's public API and add a file-level JSDoc block describing the module's capabilities.`,
|
|
59
|
-
|
|
59
|
+
missing_description: `### The description paragraph
|
|
60
60
|
|
|
61
|
-
The description is prose that
|
|
61
|
+
The description is prose that **must appear before the first \`@\` tag** in the file-level JSDoc block. Text placed after tags is not recognized as description content.
|
|
62
|
+
|
|
63
|
+
**Correct ordering:**
|
|
64
|
+
\`\`\`typescript
|
|
65
|
+
/**
|
|
66
|
+
* Description paragraph goes here, before any tags.
|
|
67
|
+
*
|
|
68
|
+
* @summary One-line overview
|
|
69
|
+
*/
|
|
70
|
+
\`\`\`
|
|
71
|
+
|
|
72
|
+
**Incorrect ordering (description will not be detected):**
|
|
73
|
+
\`\`\`typescript
|
|
74
|
+
/**
|
|
75
|
+
* @summary One-line overview
|
|
76
|
+
*
|
|
77
|
+
* Description paragraph after the tag — this will NOT be recognized.
|
|
78
|
+
*/
|
|
79
|
+
\`\`\`
|
|
62
80
|
|
|
63
81
|
**Good descriptions:**
|
|
64
82
|
- Explain *why* this file exists and what problem it solves
|
|
@@ -241,4 +259,467 @@ import { globSync } from "glob";
|
|
|
241
259
|
export function discoverFiles(...) { ... }
|
|
242
260
|
\`\`\`
|
|
243
261
|
|
|
262
|
+
### Common lint rules and examples
|
|
263
|
+
|
|
264
|
+
These rules are enforced in lint mode (\`-l\`). Understanding what passes and fails reduces trial-and-rerun cycles.
|
|
265
|
+
|
|
266
|
+
#### \`jsdoc/informative-docs\` — descriptions must add meaning
|
|
267
|
+
|
|
268
|
+
This rule rejects descriptions that merely restate the parameter name, type, or containing symbol name. Descriptions must provide behavioral context.
|
|
269
|
+
|
|
270
|
+
**Fails:**
|
|
271
|
+
- \`@param id - The id\`
|
|
272
|
+
- \`@param options - The options object\`
|
|
273
|
+
- \`@returns The result\`
|
|
274
|
+
- \`@param name - The name string\`
|
|
275
|
+
|
|
276
|
+
**Passes:**
|
|
277
|
+
- \`@param id - Unique identifier used for cache lookup and deduplication\`
|
|
278
|
+
- \`@param options - Controls retry behavior, timeout, and error handling strategy\`
|
|
279
|
+
- \`@returns Parsed configuration with defaults applied for missing fields\`
|
|
280
|
+
- \`@param name - Display name shown in the navigation sidebar\`
|
|
281
|
+
|
|
282
|
+
**Rule of thumb:** If removing the parameter name from the description leaves no useful information, the description is not informative enough.
|
|
283
|
+
|
|
284
|
+
#### \`jsdoc/check-tag-names\` — allowed tags only
|
|
285
|
+
|
|
286
|
+
The lint configuration rejects non-standard JSDoc tags. Common tags to **avoid in JSDoc blocks**:
|
|
287
|
+
- \`@remarks\` — move content to the description paragraph (prose before tags)
|
|
288
|
+
- \`@packageDocumentation\` — use \`@module\` instead
|
|
289
|
+
- \`@concept\`, \`@constraint\` — move content to the description paragraph
|
|
290
|
+
|
|
291
|
+
Framework directives that look like tags (e.g., \`@vitest-environment\`) should use plain comments instead:
|
|
292
|
+
\`\`\`typescript
|
|
293
|
+
// @vitest-environment node ← correct (plain comment)
|
|
294
|
+
/** @vitest-environment node */ ← incorrect (treated as JSDoc tag)
|
|
295
|
+
\`\`\`
|
|
296
|
+
|
|
297
|
+
#### \`jsdoc/require-throws\` — document throw conditions
|
|
298
|
+
|
|
299
|
+
Include \`@throws\` for any function that can throw, including catch-and-rethrow patterns:
|
|
300
|
+
\`\`\`typescript
|
|
301
|
+
/**
|
|
302
|
+
* @param path - File path to read
|
|
303
|
+
* @returns Parsed configuration object
|
|
304
|
+
* @throws {ConfigError} When the file is missing or contains invalid YAML
|
|
305
|
+
*/
|
|
306
|
+
\`\`\`
|
|
307
|
+
|
|
308
|
+
If a function catches errors and rethrows them (wrapped or unwrapped), it still needs \`@throws\`.
|
|
309
|
+
|
|
310
|
+
### Nested object parameters
|
|
311
|
+
|
|
312
|
+
When a function accepts an inline object parameter, document each property with a nested \`@param\` tag:
|
|
313
|
+
|
|
314
|
+
\`\`\`typescript
|
|
315
|
+
/**
|
|
316
|
+
* Create a new user account.
|
|
317
|
+
*
|
|
318
|
+
* @param data - Account creation payload
|
|
319
|
+
* @param data.email - Email address used for login and notifications
|
|
320
|
+
* @param data.displayName - Public-facing name shown in the UI
|
|
321
|
+
* @param data.role - Initial permission level assigned to the account
|
|
322
|
+
* @returns The created user record with generated ID
|
|
323
|
+
*/
|
|
324
|
+
function createUser(data: { email: string; displayName: string; role: Role }): User {
|
|
325
|
+
\`\`\`
|
|
326
|
+
|
|
327
|
+
For React component props, use \`props\` (or \`root0\` if destructured) as the root:
|
|
328
|
+
|
|
329
|
+
\`\`\`typescript
|
|
330
|
+
/**
|
|
331
|
+
* @param props - Component properties
|
|
332
|
+
* @param props.title - Page heading displayed at the top
|
|
333
|
+
* @param props.onSubmit - Callback invoked when the form is submitted
|
|
334
|
+
*/
|
|
335
|
+
function MyComponent(props: { title: string; onSubmit: () => void }) {
|
|
336
|
+
\`\`\`
|
|
337
|
+
|
|
338
|
+
### Overload documentation
|
|
339
|
+
|
|
340
|
+
When a function has TypeScript overload signatures, document **both** the overload declarations and the implementation signature:
|
|
341
|
+
|
|
342
|
+
\`\`\`typescript
|
|
343
|
+
/**
|
|
344
|
+
* Parse a value from a string representation.
|
|
345
|
+
*
|
|
346
|
+
* @param input - Raw string to parse
|
|
347
|
+
* @returns Parsed numeric value
|
|
348
|
+
*/
|
|
349
|
+
function parse(input: string): number;
|
|
350
|
+
/**
|
|
351
|
+
* Parse a value from a buffer.
|
|
352
|
+
*
|
|
353
|
+
* @param input - Binary buffer to parse
|
|
354
|
+
* @returns Parsed numeric value
|
|
355
|
+
*/
|
|
356
|
+
function parse(input: Buffer): number;
|
|
357
|
+
/**
|
|
358
|
+
* Parse a value from string or buffer input. String inputs are decoded
|
|
359
|
+
* as UTF-8 before numeric parsing.
|
|
360
|
+
*
|
|
361
|
+
* @param input - String or buffer to parse
|
|
362
|
+
* @returns Parsed numeric value
|
|
363
|
+
* @throws {ParseError} When the input cannot be interpreted as a number
|
|
364
|
+
*/
|
|
365
|
+
function parse(input: string | Buffer): number {
|
|
366
|
+
// implementation
|
|
367
|
+
}
|
|
368
|
+
\`\`\`
|
|
369
|
+
|
|
244
370
|
`;
|
|
371
|
+
/** Explanation text for each lint rule, used by --explain-rule */
|
|
372
|
+
export const RULE_EXPLANATIONS = {
|
|
373
|
+
"jsdoc/require-jsdoc": `## jsdoc/require-jsdoc
|
|
374
|
+
|
|
375
|
+
Requires JSDoc blocks on all public (exported) declarations: functions, classes, methods, and named exports.
|
|
376
|
+
|
|
377
|
+
**Triggers on:**
|
|
378
|
+
\`\`\`typescript
|
|
379
|
+
export function process(data: Data): Result { ... } // missing JSDoc
|
|
380
|
+
\`\`\`
|
|
381
|
+
|
|
382
|
+
**Passes with:**
|
|
383
|
+
\`\`\`typescript
|
|
384
|
+
/**
|
|
385
|
+
* Transform raw data into a normalized result.
|
|
386
|
+
*
|
|
387
|
+
* @param data - Input payload to process
|
|
388
|
+
* @returns Normalized result with defaults applied
|
|
389
|
+
*/
|
|
390
|
+
export function process(data: Data): Result { ... }
|
|
391
|
+
\`\`\`
|
|
392
|
+
|
|
393
|
+
Non-exported (private/internal) declarations do not require JSDoc.
|
|
394
|
+
`,
|
|
395
|
+
"jsdoc/require-param": `## jsdoc/require-param
|
|
396
|
+
|
|
397
|
+
Requires an \`@param\` tag for every parameter of a documented function.
|
|
398
|
+
|
|
399
|
+
**Triggers on:**
|
|
400
|
+
\`\`\`typescript
|
|
401
|
+
/**
|
|
402
|
+
* Load a configuration file.
|
|
403
|
+
*/
|
|
404
|
+
function loadConfig(path: string, strict: boolean): Config { ... }
|
|
405
|
+
// Missing @param path and @param strict
|
|
406
|
+
\`\`\`
|
|
407
|
+
|
|
408
|
+
**Passes with:**
|
|
409
|
+
\`\`\`typescript
|
|
410
|
+
/**
|
|
411
|
+
* Load a configuration file.
|
|
412
|
+
*
|
|
413
|
+
* @param path - Absolute path to the YAML config file
|
|
414
|
+
* @param strict - When true, unknown keys cause a validation error
|
|
415
|
+
*/
|
|
416
|
+
function loadConfig(path: string, strict: boolean): Config { ... }
|
|
417
|
+
\`\`\`
|
|
418
|
+
|
|
419
|
+
For inline object parameters, nested properties also require tags:
|
|
420
|
+
\`\`\`typescript
|
|
421
|
+
/**
|
|
422
|
+
* @param options - Request options
|
|
423
|
+
* @param options.timeout - Max wait time in milliseconds
|
|
424
|
+
* @param options.retries - Number of retry attempts on failure
|
|
425
|
+
*/
|
|
426
|
+
\`\`\`
|
|
427
|
+
`,
|
|
428
|
+
"jsdoc/require-param-description": `## jsdoc/require-param-description
|
|
429
|
+
|
|
430
|
+
Requires every \`@param\` tag to include a description, not just the parameter name.
|
|
431
|
+
|
|
432
|
+
**Triggers on:**
|
|
433
|
+
\`\`\`typescript
|
|
434
|
+
/** @param path */
|
|
435
|
+
\`\`\`
|
|
436
|
+
|
|
437
|
+
**Passes with:**
|
|
438
|
+
\`\`\`typescript
|
|
439
|
+
/** @param path - Absolute filesystem path to the input file */
|
|
440
|
+
\`\`\`
|
|
441
|
+
`,
|
|
442
|
+
"jsdoc/require-returns": `## jsdoc/require-returns
|
|
443
|
+
|
|
444
|
+
Requires an \`@returns\` tag for functions that return a value (non-void).
|
|
445
|
+
|
|
446
|
+
**Triggers on:**
|
|
447
|
+
\`\`\`typescript
|
|
448
|
+
/**
|
|
449
|
+
* Parse the input string.
|
|
450
|
+
*
|
|
451
|
+
* @param input - Raw input text
|
|
452
|
+
*/
|
|
453
|
+
function parse(input: string): ParsedResult { ... }
|
|
454
|
+
// Missing @returns
|
|
455
|
+
\`\`\`
|
|
456
|
+
|
|
457
|
+
**Passes with:**
|
|
458
|
+
\`\`\`typescript
|
|
459
|
+
/**
|
|
460
|
+
* Parse the input string.
|
|
461
|
+
*
|
|
462
|
+
* @param input - Raw input text
|
|
463
|
+
* @returns Parsed result with extracted tokens and metadata
|
|
464
|
+
*/
|
|
465
|
+
function parse(input: string): ParsedResult { ... }
|
|
466
|
+
\`\`\`
|
|
467
|
+
`,
|
|
468
|
+
"jsdoc/require-returns-description": `## jsdoc/require-returns-description
|
|
469
|
+
|
|
470
|
+
Requires every \`@returns\` tag to include a description.
|
|
471
|
+
|
|
472
|
+
**Triggers on:**
|
|
473
|
+
\`\`\`typescript
|
|
474
|
+
/** @returns */
|
|
475
|
+
\`\`\`
|
|
476
|
+
|
|
477
|
+
**Passes with:**
|
|
478
|
+
\`\`\`typescript
|
|
479
|
+
/** @returns The normalized configuration with defaults applied */
|
|
480
|
+
\`\`\`
|
|
481
|
+
`,
|
|
482
|
+
"jsdoc/require-throws": `## jsdoc/require-throws
|
|
483
|
+
|
|
484
|
+
Requires \`@throws\` tags for functions that contain throw statements.
|
|
485
|
+
|
|
486
|
+
**Triggers on:**
|
|
487
|
+
\`\`\`typescript
|
|
488
|
+
/**
|
|
489
|
+
* Read a config file.
|
|
490
|
+
*
|
|
491
|
+
* @param path - File path
|
|
492
|
+
* @returns Parsed config
|
|
493
|
+
*/
|
|
494
|
+
function readConfig(path: string): Config {
|
|
495
|
+
if (!existsSync(path)) throw new Error("not found");
|
|
496
|
+
// ...
|
|
497
|
+
}
|
|
498
|
+
// Missing @throws
|
|
499
|
+
\`\`\`
|
|
500
|
+
|
|
501
|
+
**Passes with:**
|
|
502
|
+
\`\`\`typescript
|
|
503
|
+
/**
|
|
504
|
+
* Read a config file.
|
|
505
|
+
*
|
|
506
|
+
* @param path - File path
|
|
507
|
+
* @returns Parsed config
|
|
508
|
+
* @throws {Error} When the file does not exist or contains invalid syntax
|
|
509
|
+
*/
|
|
510
|
+
\`\`\`
|
|
511
|
+
|
|
512
|
+
Functions that catch and rethrow errors also need \`@throws\`.
|
|
513
|
+
`,
|
|
514
|
+
"jsdoc/check-param-names": `## jsdoc/check-param-names
|
|
515
|
+
|
|
516
|
+
Ensures \`@param\` tag names match actual parameter names and are in the correct order.
|
|
517
|
+
|
|
518
|
+
**Triggers on:**
|
|
519
|
+
\`\`\`typescript
|
|
520
|
+
/**
|
|
521
|
+
* @param name - User name
|
|
522
|
+
* @param id - User ID
|
|
523
|
+
*/
|
|
524
|
+
function getUser(id: string, name: string) { ... }
|
|
525
|
+
// Parameters are in the wrong order
|
|
526
|
+
\`\`\`
|
|
527
|
+
|
|
528
|
+
**Passes with:**
|
|
529
|
+
\`\`\`typescript
|
|
530
|
+
/**
|
|
531
|
+
* @param id - User ID
|
|
532
|
+
* @param name - User name
|
|
533
|
+
*/
|
|
534
|
+
function getUser(id: string, name: string) { ... }
|
|
535
|
+
\`\`\`
|
|
536
|
+
`,
|
|
537
|
+
"jsdoc/check-tag-names": `## jsdoc/check-tag-names
|
|
538
|
+
|
|
539
|
+
Rejects non-standard or unsupported JSDoc tags. Only standard JSDoc tags are allowed.
|
|
540
|
+
|
|
541
|
+
**Common invalid tags and fixes:**
|
|
542
|
+
- \`@remarks\` — move content to the description paragraph (prose before tags)
|
|
543
|
+
- \`@packageDocumentation\` — use \`@module\` instead
|
|
544
|
+
- \`@concept\`, \`@constraint\` — move content to the description paragraph
|
|
545
|
+
- \`@vitest-environment\` — use a plain comment: \`// @vitest-environment node\`
|
|
546
|
+
|
|
547
|
+
**Triggers on:**
|
|
548
|
+
\`\`\`typescript
|
|
549
|
+
/** @remarks This is important context. */
|
|
550
|
+
\`\`\`
|
|
551
|
+
|
|
552
|
+
**Passes with:**
|
|
553
|
+
\`\`\`typescript
|
|
554
|
+
/**
|
|
555
|
+
* This is important context.
|
|
556
|
+
*
|
|
557
|
+
* @summary Overview line
|
|
558
|
+
*/
|
|
559
|
+
\`\`\`
|
|
560
|
+
`,
|
|
561
|
+
"jsdoc/no-types": `## jsdoc/no-types
|
|
562
|
+
|
|
563
|
+
Disallows type annotations in JSDoc tags. In TypeScript, types come from the type system.
|
|
564
|
+
|
|
565
|
+
**Triggers on:**
|
|
566
|
+
\`\`\`typescript
|
|
567
|
+
/** @param {string} name - The user name */
|
|
568
|
+
\`\`\`
|
|
569
|
+
|
|
570
|
+
**Passes with:**
|
|
571
|
+
\`\`\`typescript
|
|
572
|
+
/** @param name - The user name */
|
|
573
|
+
\`\`\`
|
|
574
|
+
`,
|
|
575
|
+
"jsdoc/informative-docs": `## jsdoc/informative-docs
|
|
576
|
+
|
|
577
|
+
Rejects JSDoc descriptions that merely restate the symbol name, type, or parameter name without adding meaning.
|
|
578
|
+
|
|
579
|
+
**Triggers on (not informative):**
|
|
580
|
+
- \`@param id - The id\`
|
|
581
|
+
- \`@param options - The options object\`
|
|
582
|
+
- \`@returns The result\`
|
|
583
|
+
- \`@param name - The name string\`
|
|
584
|
+
- \`@param data - Data to process\`
|
|
585
|
+
|
|
586
|
+
**Passes with (adds behavioral context):**
|
|
587
|
+
- \`@param id - Unique identifier used for cache lookup and deduplication\`
|
|
588
|
+
- \`@param options - Controls retry behavior, timeout, and error handling strategy\`
|
|
589
|
+
- \`@returns Parsed configuration with defaults applied for missing fields\`
|
|
590
|
+
- \`@param name - Display name shown in the navigation sidebar\`
|
|
591
|
+
- \`@param data - Raw sensor payload including timestamp and device metadata\`
|
|
592
|
+
|
|
593
|
+
**Rule of thumb:** If removing the parameter name from the description leaves no useful information, the description is not informative enough.
|
|
594
|
+
`,
|
|
595
|
+
"jsdoc/no-blank-blocks": `## jsdoc/no-blank-blocks
|
|
596
|
+
|
|
597
|
+
Disallows empty JSDoc blocks with no content.
|
|
598
|
+
|
|
599
|
+
**Triggers on:**
|
|
600
|
+
\`\`\`typescript
|
|
601
|
+
/** */
|
|
602
|
+
function doSomething() { ... }
|
|
603
|
+
\`\`\`
|
|
604
|
+
|
|
605
|
+
**Passes with:**
|
|
606
|
+
\`\`\`typescript
|
|
607
|
+
/**
|
|
608
|
+
* Execute the primary processing pipeline.
|
|
609
|
+
*/
|
|
610
|
+
function doSomething() { ... }
|
|
611
|
+
\`\`\`
|
|
612
|
+
`,
|
|
613
|
+
"jsdoc/require-description": `## jsdoc/require-description
|
|
614
|
+
|
|
615
|
+
Requires a text description in every JSDoc block (not just tags).
|
|
616
|
+
|
|
617
|
+
**Triggers on:**
|
|
618
|
+
\`\`\`typescript
|
|
619
|
+
/**
|
|
620
|
+
* @param path - File path
|
|
621
|
+
* @returns Config object
|
|
622
|
+
*/
|
|
623
|
+
function loadConfig(path: string): Config { ... }
|
|
624
|
+
// Has tags but no description text
|
|
625
|
+
\`\`\`
|
|
626
|
+
|
|
627
|
+
**Passes with:**
|
|
628
|
+
\`\`\`typescript
|
|
629
|
+
/**
|
|
630
|
+
* Load and parse a YAML configuration file with schema validation.
|
|
631
|
+
*
|
|
632
|
+
* @param path - File path
|
|
633
|
+
* @returns Config object
|
|
634
|
+
*/
|
|
635
|
+
function loadConfig(path: string): Config { ... }
|
|
636
|
+
\`\`\`
|
|
637
|
+
`,
|
|
638
|
+
"jsdoczoom/require-file-jsdoc": `## jsdoczoom/require-file-jsdoc
|
|
639
|
+
|
|
640
|
+
Requires a file-level JSDoc block (\`/** ... */\`) before the first code statement.
|
|
641
|
+
|
|
642
|
+
**Triggers on:** Files with no JSDoc block before the first export, const, function, class, etc.
|
|
643
|
+
|
|
644
|
+
**Passes with:**
|
|
645
|
+
\`\`\`typescript
|
|
646
|
+
import { resolve } from "node:path";
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Description of what this file does.
|
|
650
|
+
*
|
|
651
|
+
* @summary One-line overview
|
|
652
|
+
*/
|
|
653
|
+
|
|
654
|
+
export function example() { ... }
|
|
655
|
+
\`\`\`
|
|
656
|
+
`,
|
|
657
|
+
"jsdoczoom/require-file-summary": `## jsdoczoom/require-file-summary
|
|
658
|
+
|
|
659
|
+
Requires exactly one \`@summary\` tag (exact lowercase) in the file-level JSDoc block.
|
|
660
|
+
|
|
661
|
+
**Important:** Only exact lowercase \`@summary\` is recognized. \`@Summary\`, \`@SUMMARY\`, and other case variants are ignored.
|
|
662
|
+
|
|
663
|
+
**Triggers on:**
|
|
664
|
+
- Files with no \`@summary\` tag in the file-level block
|
|
665
|
+
- Files with multiple \`@summary\` tags
|
|
666
|
+
|
|
667
|
+
**Passes with:**
|
|
668
|
+
\`\`\`typescript
|
|
669
|
+
/**
|
|
670
|
+
* Description of the module.
|
|
671
|
+
*
|
|
672
|
+
* @summary Concise one-line overview of what this file does
|
|
673
|
+
*/
|
|
674
|
+
\`\`\`
|
|
675
|
+
`,
|
|
676
|
+
"jsdoczoom/require-file-description": `## jsdoczoom/require-file-description
|
|
677
|
+
|
|
678
|
+
Requires description content in the file-level JSDoc block. The description must appear as free-text before \`@\` tags, or use a description-synonym tag (\`@desc\`, \`@description\`, \`@file\`, \`@fileoverview\`).
|
|
679
|
+
|
|
680
|
+
**Triggers on:**
|
|
681
|
+
\`\`\`typescript
|
|
682
|
+
/** @summary Summary only */
|
|
683
|
+
export const x = 1;
|
|
684
|
+
// No description text before the tag
|
|
685
|
+
\`\`\`
|
|
686
|
+
|
|
687
|
+
**Passes with:**
|
|
688
|
+
\`\`\`typescript
|
|
689
|
+
/**
|
|
690
|
+
* This module handles user authentication and session management.
|
|
691
|
+
*
|
|
692
|
+
* @summary Auth module
|
|
693
|
+
*/
|
|
694
|
+
\`\`\`
|
|
695
|
+
|
|
696
|
+
**Important:** Description text must appear **before** the first \`@\` tag. Text after tags is not recognized as description.
|
|
697
|
+
`,
|
|
698
|
+
"jsdoczoom/require-file-ordering": `## jsdoczoom/require-file-ordering
|
|
699
|
+
|
|
700
|
+
Warns when the file-level JSDoc block has structural issues:
|
|
701
|
+
1. Multiple file-level JSDoc blocks before the first code statement
|
|
702
|
+
2. Description text appearing after \`@\` tags instead of before them
|
|
703
|
+
|
|
704
|
+
**Correct ordering:**
|
|
705
|
+
\`\`\`typescript
|
|
706
|
+
/**
|
|
707
|
+
* Description paragraph first.
|
|
708
|
+
*
|
|
709
|
+
* More description if needed.
|
|
710
|
+
*
|
|
711
|
+
* @summary Overview line
|
|
712
|
+
* @module my-module
|
|
713
|
+
*/
|
|
714
|
+
\`\`\`
|
|
715
|
+
|
|
716
|
+
**Incorrect (description after tags):**
|
|
717
|
+
\`\`\`typescript
|
|
718
|
+
/**
|
|
719
|
+
* @summary Overview line
|
|
720
|
+
*
|
|
721
|
+
* Description paragraph after tags — will trigger a warning.
|
|
722
|
+
*/
|
|
723
|
+
\`\`\`
|
|
724
|
+
`,
|
|
725
|
+
};
|
|
@@ -29,73 +29,87 @@ import { JsdocError } from "./errors.js";
|
|
|
29
29
|
* @throws {JsdocError} If the file cannot be read or parsed
|
|
30
30
|
*/
|
|
31
31
|
export function generateTypeDeclarations(filePath) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
32
|
+
let sourceText;
|
|
33
|
+
try {
|
|
34
|
+
sourceText = readFileSync(filePath, "utf-8");
|
|
35
|
+
} catch (_error) {
|
|
36
|
+
throw new JsdocError("FILE_NOT_FOUND", `Failed to read file: ${filePath}`);
|
|
37
|
+
}
|
|
38
|
+
// Create compiler options matching the project setup
|
|
39
|
+
const compilerOptions = {
|
|
40
|
+
declaration: true,
|
|
41
|
+
emitDeclarationOnly: true,
|
|
42
|
+
target: ts.ScriptTarget.Latest,
|
|
43
|
+
module: ts.ModuleKind.NodeNext,
|
|
44
|
+
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
45
|
+
skipLibCheck: true,
|
|
46
|
+
removeComments: false, // Preserve JSDoc comments
|
|
47
|
+
};
|
|
48
|
+
// Create a custom compiler host that provides our file
|
|
49
|
+
const host = ts.createCompilerHost(compilerOptions);
|
|
50
|
+
const originalGetSourceFile = host.getSourceFile;
|
|
51
|
+
host.getSourceFile = (
|
|
52
|
+
fileName,
|
|
53
|
+
languageVersion,
|
|
54
|
+
onError,
|
|
55
|
+
shouldCreateNewSourceFile,
|
|
56
|
+
) => {
|
|
57
|
+
if (fileName === filePath) {
|
|
58
|
+
return ts.createSourceFile(fileName, sourceText, languageVersion, true);
|
|
59
|
+
}
|
|
60
|
+
return originalGetSourceFile.call(
|
|
61
|
+
host,
|
|
62
|
+
fileName,
|
|
63
|
+
languageVersion,
|
|
64
|
+
onError,
|
|
65
|
+
shouldCreateNewSourceFile,
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
// Capture emitted output
|
|
69
|
+
let declarationOutput = "";
|
|
70
|
+
host.writeFile = (fileName, data) => {
|
|
71
|
+
if (fileName.endsWith(".d.ts")) {
|
|
72
|
+
declarationOutput = data;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
// Create program and emit declarations
|
|
76
|
+
const program = ts.createProgram([filePath], compilerOptions, host);
|
|
77
|
+
const sourceFile = program.getSourceFile(filePath);
|
|
78
|
+
if (!sourceFile) {
|
|
79
|
+
throw new JsdocError("PARSE_ERROR", `Failed to parse file: ${filePath}`);
|
|
80
|
+
}
|
|
81
|
+
const emitResult = program.emit(sourceFile, undefined, undefined, true);
|
|
82
|
+
// Check for emit errors
|
|
83
|
+
const diagnostics = ts
|
|
84
|
+
.getPreEmitDiagnostics(program)
|
|
85
|
+
.concat(emitResult.diagnostics);
|
|
86
|
+
if (diagnostics.length > 0) {
|
|
87
|
+
const errors = diagnostics
|
|
88
|
+
.map((diagnostic) => {
|
|
89
|
+
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
90
|
+
const { line, character } =
|
|
91
|
+
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
92
|
+
const message = ts.flattenDiagnosticMessageText(
|
|
93
|
+
diagnostic.messageText,
|
|
94
|
+
"\n",
|
|
95
|
+
);
|
|
96
|
+
return `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
|
|
97
|
+
}
|
|
98
|
+
return ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
99
|
+
})
|
|
100
|
+
.join("\n");
|
|
101
|
+
throw new JsdocError("PARSE_ERROR", `TypeScript errors:\n${errors}`);
|
|
102
|
+
}
|
|
103
|
+
if (!declarationOutput) {
|
|
104
|
+
// If no output was generated, the file may have no exports
|
|
105
|
+
// Return empty string in this case
|
|
106
|
+
return "";
|
|
107
|
+
}
|
|
108
|
+
// Clean up the output
|
|
109
|
+
let cleaned = declarationOutput;
|
|
110
|
+
// Remove empty export statement if present and no other exports
|
|
111
|
+
if (cleaned.trim() === "export {};") {
|
|
112
|
+
cleaned = "";
|
|
113
|
+
}
|
|
114
|
+
return cleaned;
|
|
101
115
|
}
|