Skip to content

Commit 3511c54

Browse files
committed
feat(PluginsConfig): add pluginConfigs to the parsed data
Parses any `interface PluginsConfig {}` found within `declare module '@capacitor/cli'` and adds the data to the data returned from the `parse()` API. This can be used to auto-generate docs for plugin configs.
1 parent 81104d0 commit 3511c54

File tree

4 files changed

+123
-2
lines changed

4 files changed

+123
-2
lines changed

src/parse.ts

+62-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
DocsMethodParam,
1010
DocsJsDoc,
1111
DocsInterfaceProperty,
12+
DocsConfigInterface,
1213
DocsTypeAlias,
1314
DocsTypeAliasReference,
1415
} from './types';
@@ -30,9 +31,17 @@ export function parse(opts: DocsParseOptions) {
3031
const interfaces: DocsInterface[] = [];
3132
const enums: DocsEnum[] = [];
3233
const typeAliases: DocsTypeAlias[] = [];
34+
const pluginConfigs: DocsInterface[] = [];
3335

3436
tsSourceFiles.forEach(tsSourceFile => {
35-
parseSourceFile(tsSourceFile, typeChecker, interfaces, typeAliases, enums);
37+
parseSourceFile(
38+
tsSourceFile,
39+
typeChecker,
40+
interfaces,
41+
typeAliases,
42+
enums,
43+
pluginConfigs,
44+
);
3645
});
3746

3847
return (api: string) => {
@@ -43,6 +52,7 @@ export function parse(opts: DocsParseOptions) {
4352
interfaces: [],
4453
enums: [],
4554
typeAliases: [],
55+
pluginConfigs,
4656
};
4757

4858
if (apiInterface) {
@@ -108,11 +118,13 @@ function parseSourceFile(
108118
interfaces: DocsInterface[],
109119
typeAliases: DocsTypeAlias[],
110120
enums: DocsEnum[],
121+
pluginConfigs: DocsInterface[],
111122
) {
112123
const statements = tsSourceFile.statements;
113124
const interfaceDeclarations = statements.filter(ts.isInterfaceDeclaration);
114125
const typeAliasDeclarations = statements.filter(ts.isTypeAliasDeclaration);
115126
const enumDeclarations = statements.filter(ts.isEnumDeclaration);
127+
const moduleDeclarations = statements.filter(ts.isModuleDeclaration);
116128

117129
interfaceDeclarations.forEach(interfaceDeclaration => {
118130
interfaces.push(getInterface(typeChecker, interfaceDeclaration));
@@ -125,6 +137,12 @@ function parseSourceFile(
125137
typeAliasDeclarations.forEach(typeAliasDeclaration => {
126138
typeAliases.push(getTypeAlias(typeChecker, typeAliasDeclaration));
127139
});
140+
141+
moduleDeclarations
142+
.filter(m => m?.name?.text === '@capacitor/cli')
143+
.forEach(moduleDeclaration => {
144+
getPluginsConfig(typeChecker, moduleDeclaration, pluginConfigs);
145+
});
128146
}
129147

130148
function getInterface(
@@ -338,6 +356,49 @@ function getInterfaceProperty(
338356
return p;
339357
}
340358

359+
function getPluginsConfig(
360+
typeChecker: ts.TypeChecker,
361+
moduleDeclaration: ts.ModuleDeclaration,
362+
pluginConfigs: DocsConfigInterface[],
363+
) {
364+
const body = moduleDeclaration.body as ts.ModuleBlock;
365+
if (!Array.isArray(body.statements)) {
366+
return;
367+
}
368+
369+
const pluginConfigInterfaces = body.statements.filter(
370+
(s: ts.InterfaceDeclaration) =>
371+
s?.name?.text === 'PluginsConfig' &&
372+
Array.isArray(s?.members) &&
373+
s.members.length > 0,
374+
) as ts.InterfaceDeclaration[];
375+
376+
pluginConfigInterfaces.forEach(pluginConfigInterface => {
377+
pluginConfigInterface.members
378+
.filter(ts.isPropertySignature)
379+
.filter(p => p?.type && (p?.type as ts.TypeLiteralNode).members)
380+
.forEach(properytSignature => {
381+
const typeLiteral = properytSignature.type as ts.TypeLiteralNode;
382+
383+
const nm = properytSignature.name.getText();
384+
const i: DocsConfigInterface = {
385+
name: nm,
386+
slug: slugify(nm),
387+
properties: typeLiteral.members
388+
.filter(ts.isPropertySignature)
389+
.map(propertySignature => {
390+
return getInterfaceProperty(typeChecker, propertySignature);
391+
})
392+
.filter(p => p != null) as DocsInterfaceProperty[],
393+
};
394+
395+
if (i.properties.length > 0) {
396+
pluginConfigs.push(i);
397+
}
398+
});
399+
});
400+
}
401+
341402
function typeToString(
342403
checker: ts.TypeChecker,
343404
type: ts.Type,

src/test/fixtures/definitions.ts

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
/// <reference types="@capacitor/cli" />
2+
3+
declare module '@capacitor/cli' {
4+
export interface PluginsConfig {
5+
Haptics?: {
6+
/**
7+
* Configure the style.
8+
*
9+
* @since 1.0.0
10+
* @default native
11+
*/
12+
style?: 'none' | 'native';
13+
14+
/**
15+
* Configure the duration.
16+
*
17+
* @since 1.2.3
18+
*/
19+
duration?: number;
20+
};
21+
}
22+
}
23+
124
/**
225
* ## Docs from JSDoc comments!
326
*

src/test/parse.spec.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ describe('parse', () => {
66
tsconfigPath: path.join(__dirname, 'fixtures', 'tsconfig.json'),
77
});
88

9-
const { api, interfaces, enums, typeAliases } = apiFinder('HapticsPlugin');
9+
const { api, interfaces, enums, typeAliases, pluginConfigs } = apiFinder(
10+
'HapticsPlugin',
11+
);
1012

1113
it('api', () => {
1214
expect(api.name).toBe(`HapticsPlugin`);
@@ -139,4 +141,32 @@ describe('parse', () => {
139141
expect(t1.slug).toBe(`repeatschedule`);
140142
expect(t1.types).toHaveLength(4);
141143
});
144+
145+
it('Plugins Config', () => {
146+
expect(pluginConfigs).toHaveLength(1);
147+
const p = pluginConfigs.find(i => i.name === `Haptics`);
148+
149+
expect(p.slug).toBe(`haptics`);
150+
expect(p.properties).toHaveLength(2);
151+
152+
const p0 = p.properties[0];
153+
expect(p0.name).toBe(`style`);
154+
expect(p0.docs).toBe(`Configure the style.`);
155+
expect(p0.type).toBe(`'none' | 'native' | undefined`);
156+
expect(p0.complexTypes).toHaveLength(0);
157+
expect(p0.tags).toHaveLength(2);
158+
expect(p0.tags[0].name).toBe(`since`);
159+
expect(p0.tags[0].text).toBe(`1.0.0`);
160+
expect(p0.tags[1].name).toBe(`default`);
161+
expect(p0.tags[1].text).toBe(`native`);
162+
163+
const p1 = p.properties[1];
164+
expect(p1.name).toBe(`duration`);
165+
expect(p1.docs).toBe(`Configure the duration.`);
166+
expect(p1.type).toBe(`number | undefined`);
167+
expect(p1.complexTypes).toHaveLength(0);
168+
expect(p1.tags).toHaveLength(1);
169+
expect(p1.tags[0].name).toBe(`since`);
170+
expect(p1.tags[0].text).toBe(`1.2.3`);
171+
});
142172
});

src/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ export interface DocsData {
33
interfaces: DocsInterface[];
44
typeAliases: DocsTypeAlias[];
55
enums: DocsEnum[];
6+
pluginConfigs: DocsConfigInterface[];
7+
}
8+
9+
export interface DocsConfigInterface {
10+
name: string;
11+
slug: string;
12+
properties: DocsInterfaceProperty[];
613
}
714

815
export interface DocsInterface {

0 commit comments

Comments
 (0)