Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 30 additions & 148 deletions .agents/skills/jsdoc/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,71 +1,34 @@
---
name: jsdoc
description: Full JSDoc format guide for TypeScript, covering @example formats (short, multi-line, multi-variant), tag usage (@default, @deprecated, what to avoid), documentation patterns for properties/enums/functions, and tag order.
description: Full JSDoc format guide for TypeScript, covering @example formats, tag usage (@default, @deprecated, what to avoid), documentation patterns, and tag order.
---

# JSDoc

The detailed JSDoc format guide with examples for every case. The essentials live in the
`jsdoc` rule. Reach here when you need the full reference.

## `@example` format

### Short one-liner: label on the `@example` line, code as inline backtick on the next line

```typescript
/**
* @example Required parameter
* `name: Type`
*
* @example Optional parameter
* `name?: Type`
*/
```

### Multi-line: fenced code block immediately after `@example`

````typescript
/**
* @example
* ```ts
* const result = buildParams(node, {
* paramsType: 'inline',
* })
* ```
*/
````

### Multiple variants: use multiple `@example` blocks

```typescript
/**
* @example Object mode
* `{ id, data, params }: { id: string; data: Data; params?: QueryParams }`
*
* @example Inline mode
* `id: string, data: Data, params?: QueryParams`
*/
```

### Rules

| Rule | Correct | Incorrect |
| ----------------------- | ----------------------------------- | -------------------------------------------- |
| Label + inline code | `@example Required\n\`name: Type\`` | `@example \`name: Type\`` (code on tag line) |
| Multi-line code | Fenced ` ```ts ``` ` block | Bare code lines without a fence |
| Short examples | Inline backtick | Triple-backtick fence (too heavy) |
| One concern per example | Separate `@example` blocks | One example covering all cases |
The detailed JSDoc format guide. The essentials live in the `jsdoc` rule; reach here for the
full reference, including every `@example` format and documentation pattern in
[references/examples.md](references/examples.md).

## `@example` format, in brief

- Short value: label on the `@example` line, code as inline backtick on the next line.
- Multi-line code: a fenced ` ```ts ``` ` block immediately after `@example`, never bare lines.
- Multiple variants: separate `@example` blocks, one concern each, never one example for every
case.

See [references/examples.md](references/examples.md) for a worked example of each, plus the
property, enum, nested-property, and function documentation patterns.

## Tags

### Use frequently

| Tag | Purpose | Notes |
| ------------- | ------------------ | ------------------------------------------------------ |
| Tag | Purpose | Notes |
| ------------- | ------------------ | ----------------------------------------------------------- |
| `@default` | Default value | Only when the default is non-obvious (omit for `undefined`) |
| `@example` | Usage example | Prefer for complex or multi-variant APIs |
| `@note` | Important caveat | Version info, breaking changes |
| `@deprecated` | Mark as deprecated | Include a migration path |
| `@example` | Usage example | Prefer for complex or multi-variant APIs |
| `@note` | Important caveat | Version info, breaking changes |
| `@deprecated` | Mark as deprecated | Include a migration path |

### Use sparingly

Expand All @@ -77,106 +40,25 @@ The detailed JSDoc format guide with examples for every case. The essentials liv

### Avoid (TypeScript already provides these)

- `@param`: use TypeScript parameter types
- `@returns`: use the TypeScript return type
- `@type`: use a TypeScript type annotation
- `@typedef`: use `type` or `interface`
- `@default undefined`: optional (`?`) already implies this

## Documentation patterns

### Simple property: always multi-line

```typescript
/**
* Output directory for generated files.
*/
outDir?: string
```

Never use single-line `/** description */`. Always expand to multi-line.

### Property with a non-obvious default

```typescript
/**
* Maximum number of concurrent callbacks during traversal.
* Higher values overlap I/O-bound work, lower values save memory.
*
* @default 30
*/
concurrency?: number
```

Do not add `@default false` or `@default undefined` when the TypeScript type already makes the
default obvious.

### Enum or union with options

```typescript
/**
* How path parameters are emitted in the function signature.
* - `'object'` groups them as a single destructured parameter
* - `'inline'` spreads them as individual parameters
* - `'inlineSpread'` emits a single rest parameter
*/
pathParamsType: 'object' | 'inline' | 'inlineSpread'
```

### Nested properties: every field gets its own multi-line JSDoc

```typescript
names?: {
/**
* Name for the request body parameter.
* @default 'data'
*/
data?: string
/**
* Name for the query parameters group parameter.
* @default 'params'
*/
params?: string
}
```

### Function documentation

Only add JSDoc when it adds value beyond the signature:

```typescript
// No JSDoc needed: the signature is self-explanatory
function camelCase(str: string): string { ... }

// JSDoc adds value: it explains behavior and non-obvious edge cases
/**
* Returns `true` when the schema resolves to a plain string output.
*
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
* - `date` and `time` are plain strings when their `representation` is `'string'`.
*/
function isStringType(node: SchemaNode): boolean { ... }
```
`@param`, `@returns`, `@type`, and `@typedef` duplicate the TypeScript signature; use the type,
return type, or a `type`/`interface` instead. Skip `@default undefined` too, since an optional
(`?`) property already implies it.

## Guidelines

Do:

- Document what the property does, not its TypeScript type
- Give every exported type, property, and function a JSDoc comment
- Always use multi-line JSDoc blocks
- Use concrete, full-sentence descriptions
- Include `@default` only when the default is non-obvious
- Use multiple `@example` blocks for different variants
- Keep `@example` labels short and descriptive
- Document what the property does, not its TypeScript type.
- Give every exported type, property, and function a JSDoc comment, always multi-line, with
concrete, full-sentence descriptions.
- Include `@default` only when the default is non-obvious.
- Use multiple `@example` blocks for different variants, with short, descriptive labels.

Do not:

- Write single-line `/** description */`
- Write `@default undefined`
- Put code directly on the `@example` line
- Use `@param` or `@returns` tags
- Over-document trivial, self-explanatory properties
- Write single-line `/** description */` or `@default undefined`.
- Put code directly on the `@example` line, or use `@param`/`@returns`.
- Over-document trivial, self-explanatory properties.

## Tag order

Expand Down
127 changes: 127 additions & 0 deletions .agents/skills/jsdoc/references/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# JSDoc examples and patterns

Full examples for the `@example` formats and the documentation patterns the `jsdoc` skill
summarizes.

## `@example` format

### Short one-liner: label on the `@example` line, code as inline backtick on the next line

```typescript
/**
* @example Required parameter
* `name: Type`
*
* @example Optional parameter
* `name?: Type`
*/
```

### Multi-line: fenced code block immediately after `@example`

````typescript
/**
* @example
* ```ts
* const result = buildParams(node, {
* paramsType: 'inline',
* })
* ```
*/
````

### Multiple variants: use multiple `@example` blocks

```typescript
/**
* @example Object mode
* `{ id, data, params }: { id: string; data: Data; params?: QueryParams }`
*
* @example Inline mode
* `id: string, data: Data, params?: QueryParams`
*/
```

### Rules

| Rule | Correct | Incorrect |
| ----------------------- | ----------------------------------- | -------------------------------------------- |
| Label + inline code | `@example Required\n\`name: Type\`` | `@example \`name: Type\`` (code on tag line) |
| Multi-line code | Fenced ` ```ts ``` ` block | Bare code lines without a fence |
| Short examples | Inline backtick | Triple-backtick fence (too heavy) |
| One concern per example | Separate `@example` blocks | One example covering all cases |

## Documentation patterns

### Simple property: always multi-line

```typescript
/**
* Output directory for generated files.
*/
outDir?: string
```

Never use single-line `/** description */`. Always expand to multi-line.

### Property with a non-obvious default

```typescript
/**
* Maximum number of concurrent callbacks during traversal.
* Higher values overlap I/O-bound work, lower values save memory.
*
* @default 30
*/
concurrency?: number
```

Do not add `@default false` or `@default undefined` when the TypeScript type already makes the
default obvious.

### Enum or union with options

```typescript
/**
* How path parameters are emitted in the function signature.
* - `'object'` groups them as a single destructured parameter
* - `'inline'` spreads them as individual parameters
* - `'inlineSpread'` emits a single rest parameter
*/
pathParamsType: 'object' | 'inline' | 'inlineSpread'
```

### Nested properties: every field gets its own multi-line JSDoc

```typescript
names?: {
/**
* Name for the request body parameter.
* @default 'data'
*/
data?: string
/**
* Name for the query parameters group parameter.
* @default 'params'
*/
params?: string
}
```

### Function documentation

Only add JSDoc when it adds value beyond the signature:

```typescript
// No JSDoc needed: the signature is self-explanatory
function camelCase(str: string): string { ... }

// JSDoc adds value: it explains behavior and non-obvious edge cases
/**
* Returns `true` when the schema resolves to a plain string output.
*
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
* - `date` and `time` are plain strings when their `representation` is `'string'`.
*/
function isStringType(node: SchemaNode): boolean { ... }
```
Loading
Loading