Skip to content

Commit

Permalink
feat: support for class properties (#47)
Browse files Browse the repository at this point in the history
* feat: support for class properties

* 🤖 Documentation auto-update

* feat: keep undefined if nothing visited

* 🤖 Documentation auto-update

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
peterpeterparker and github-actions[bot] authored Dec 16, 2024
1 parent 19c4f88 commit 6664dea
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 33 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Parameters:
- `params.inputFiles`: The list of files to scan and for which the documentation should be build.
- `params.options`: Optional compiler options to generate the docs

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/docs.ts#L402)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/docs.ts#L426)

### :gear: documentationToMarkdown

Expand All @@ -164,7 +164,7 @@ Parameters:
- `params.entries`: The entries of the documentation (functions, constants and classes).
- `params.options`: Optional configuration to render the Markdown content. See `types.ts` for details.

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/markdown.ts#L280)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/markdown.ts#L293)

### :gear: generateDocumentation

Expand Down
27 changes: 25 additions & 2 deletions src/lib/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
isInterfaceDeclaration,
isMethodDeclaration,
isModuleDeclaration,
isPropertyDeclaration,
isPropertySignature,
isTypeAliasDeclaration,
isVariableStatement
Expand Down Expand Up @@ -117,7 +118,10 @@ const isNodeExportedOrPublic = (node: Node): boolean => {
const flags = getCombinedModifierFlags(node as Declaration);

// Check for '#' methods or properties
if (isMethodDeclaration(node) && node.name.kind === SyntaxKind.PrivateIdentifier) {
if (
(isMethodDeclaration(node) || isPropertyDeclaration(node)) &&
node.name.kind === SyntaxKind.PrivateIdentifier
) {
return false;
}

Expand Down Expand Up @@ -255,9 +259,24 @@ const visit = ({

const visitChild = (node: Node) => {
const docEntries: DocEntry[] = visit({node, checker, types, ...rest});

// We do not need to repeat the file name for class members
// eslint-disable-next-line @typescript-eslint/no-unused-vars
classEntry.methods?.push(...docEntries.map(({fileName: _, ...rest}) => rest));
const omitFilename = ({fileName: _, ...rest}: DocEntry): Omit<DocEntry, 'fileName'> => rest;

classEntry.methods?.push(
...docEntries
.filter(({doc_type}) => doc_type === 'method' || doc_type === 'function')
.map(omitFilename)
);

const properties = docEntries
.filter(({doc_type}) => doc_type === 'property')
.map(omitFilename);

if (properties.length > 0) {
classEntry.properties = [...(classEntry?.properties ?? []), ...properties];
}
};

forEachChild(node, visitChild);
Expand Down Expand Up @@ -286,6 +305,10 @@ const visit = ({
((arrowFunc as ArrowFunction).parent as VariableDeclaration).name
);
addDocEntry({symbol, doc_type: 'function', node: arrowFunc});
} else if (isPropertyDeclaration(node)) {
// We test for the property after the arrow function because a public property of a class can be an arrow function.
const symbol = checker.getSymbolAtLocation(node.name);
addDocEntry({symbol, doc_type: 'property', node});
} else if (isVariableStatement(node)) {
const {
declarationList: {declarations, flags}
Expand Down
43 changes: 28 additions & 15 deletions src/lib/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const classesToMarkdown = ({
entry: DocEntry;
} & Required<Pick<MarkdownOptions, 'headingLevel'>> &
Omit<MarkdownOptions, 'headingLevel'>): string => {
const {name, url, documentation, methods, constructors} = entry;
const {name, url, documentation, methods, properties, constructors} = entry;

const markdown: string[] = [`${headingLevel}${emojiTitle({emoji, key: 'classes'})} ${name}\n`];

Expand Down Expand Up @@ -70,22 +70,35 @@ const classesToMarkdown = ({
markdown.push('\n');
}

if (!methods || methods.length === 0) {
return markdown.join('\n');
if ((methods?.length ?? 0) > 0) {
markdown.push(`${headingLevel}# Methods\n`);
markdown.push(`${tableOfContent({entries: methods ?? [], emoji})}\n`);

// Explicitly do not pass repo to generate the source code link afterwards for the all block
markdown.push(
`${toMarkdown({
entries: methods ?? [],
headingLevel: `${headingLevel}#`,
docType: 'Method',
emoji
})}`
);
}

markdown.push(`${headingLevel}# Methods\n`);
markdown.push(`${tableOfContent({entries: methods ?? [], emoji})}\n`);
if ((properties?.length ?? 0) > 0) {
markdown.push(`${headingLevel}# Properties\n`);
markdown.push(`${tableOfContent({entries: properties ?? [], emoji})}\n`);

// Explicitly do not pass repo to generate the source code link afterwards for the all block
markdown.push(
`${toMarkdown({
entries: methods ?? [],
headingLevel: `${headingLevel}#`,
docType: 'Method',
emoji
})}\n`
);
// Explicitly do not pass repo to generate the source code link afterwards for the all block
markdown.push(
`${toMarkdown({
entries: properties ?? [],
headingLevel: `${headingLevel}#`,
docType: 'Property',
emoji
})}`
);
}

return markdown.join('\n');
};
Expand Down Expand Up @@ -151,7 +164,7 @@ const toMarkdown = ({
}: {
entries: DocEntry[];
headingLevel: MarkdownHeadingLevel | '####';
docType: 'Constant' | 'Function' | 'Method' | 'Type' | 'Enum';
docType: 'Constant' | 'Function' | 'Method' | 'Property' | 'Type' | 'Enum';
} & Pick<MarkdownOptions, 'emoji'>): string => {
const jsDocsToParams = (jsDocs: JSDocTagInfo[]): Params[] => {
const params: JSDocTagInfo[] = jsDocs.filter(({name}: JSDocTagInfo) => name === 'param');
Expand Down
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {CompilerOptions, JSDocTagInfo} from 'typescript';

export type DocEntryType =
| 'property'
| 'function'
| 'method'
| 'class'
Expand Down
2 changes: 1 addition & 1 deletion src/test/markdown.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('markdown', () => {
expect(markdown).toEqual(expectedDoc);
});

it.each([35, 101, 129])('should generate a markdown link to line %s', (line) => {
it.each([35, 118, 146])('should generate a markdown link to line %s', (line) => {
const doc = buildDocumentation({
inputFiles: ['./src/test/mock.ts'],
options: {
Expand Down
9 changes: 9 additions & 0 deletions src/test/mock.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@
"doc_type": "method"
}
],
"properties": [
{
"name": "publicShouldBeDocumented",
"documentation": "The documentation of the public property.",
"type": "string",
"jsDocs": [],
"doc_type": "property"
}
],
"fileName": "src/test/mock.ts"
},
{
Expand Down
37 changes: 24 additions & 13 deletions src/test/mock.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function submit() {
```


[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L221)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L238)


## :wrench: Constants
Expand Down Expand Up @@ -155,12 +155,25 @@ Public method.
| ---------- | ---------- |
| `shouldBeDocumented` | `() => void` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L80)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L97)

### Properties

- [publicShouldBeDocumented](#gear-publicshouldbedocumented)

#### :gear: publicShouldBeDocumented

The documentation of the public property.

| Property | Type |
| ---------- | ---------- |
| `publicShouldBeDocumented` | `string` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L80)

## :factory: SnsLedgerCanister

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L101)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L118)

### Constructors

Expand All @@ -181,7 +194,7 @@ This create function is public as well.
| ---------- | ---------- |
| `create` | `(options: { canisterId?: string or undefined; }) => SnsLedgerCanister` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L116)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L133)

#### :gear: metadata

Expand All @@ -191,12 +204,11 @@ The token metadata (name, symbol, etc.).
| ---------- | ---------- |
| `metadata` | `(params: QueryParams) => Promise<SnsTokenMetadataResponse>` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L125)

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L142)

## :factory: default

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L129)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L146)

### Methods

Expand All @@ -210,8 +222,7 @@ Description
| ---------- | ---------- |
| `bar` | `() => void` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L133)

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L150)

## :nut_and_bolt: Enum

Expand Down Expand Up @@ -281,7 +292,7 @@ A type yolo
| ---------- | ---------- |
| `yolo` | `'string'` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L158)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L175)

### :gear: Abc

Expand All @@ -291,21 +302,21 @@ A type yolo
| ---------- | ---------- |
| `Abc` | `Foo and {hello: string}` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L163)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L180)

### :gear: StorageConfigSourceGlob

| Type | Type |
| ---------- | ---------- |
| `StorageConfigSourceGlob` | |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L234)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L251)

### :gear: SatelliteConfig

| Type | Type |
| ---------- | ---------- |
| `SatelliteConfig` | `Either<SatelliteId, SatelliteIds> and CliConfig and SatelliteConfigOptions` |

[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L260)
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L277)

17 changes: 17 additions & 0 deletions src/test/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,23 @@ export class LedgerCanister {
return {icp: 1n};
};

/**
* The documentation of the public property.
*/
publicShouldBeDocumented = 'hello';

/**
* Private property.
* @private
*/
private privateShouldNoBeDocumented = 'hello';

/**
* Private property with a # identifier.
* @private
*/
#privateShouldNoBeDocumentedNeither = 'hello';

/**
* Public method.
*/
Expand Down

0 comments on commit 6664dea

Please sign in to comment.