@ng-prism/plugin-jsdoc 22.5.0 → 22.7.0-beta.0
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/README.md +18 -15
- package/dist/api-page/api-page.helpers.d.ts +79 -0
- package/dist/api-page/api-page.helpers.d.ts.map +1 -0
- package/dist/api-page/api-page.helpers.js +133 -0
- package/dist/api-page/api-page.model.d.ts +62 -0
- package/dist/api-page/api-page.model.d.ts.map +1 -0
- package/dist/api-page/api-page.model.js +122 -0
- package/dist/api-page/component-usage.d.ts +14 -0
- package/dist/api-page/component-usage.d.ts.map +1 -0
- package/dist/api-page/component-usage.js +120 -0
- package/dist/api-page/doc-links.d.ts +15 -0
- package/dist/api-page/doc-links.d.ts.map +1 -0
- package/dist/api-page/doc-links.js +45 -0
- package/dist/api-page/jsdoc-api-page.component.d.ts +98 -0
- package/dist/api-page/jsdoc-api-page.component.d.ts.map +1 -0
- package/dist/api-page/jsdoc-api-page.component.js +1458 -0
- package/dist/api-page/pipe-usage.d.ts +13 -0
- package/dist/api-page/pipe-usage.d.ts.map +1 -0
- package/dist/api-page/pipe-usage.js +35 -0
- package/dist/api-page/service-usage.d.ts +31 -0
- package/dist/api-page/service-usage.d.ts.map +1 -0
- package/dist/api-page/service-usage.js +66 -0
- package/dist/jsdoc-extractor.d.ts.map +1 -1
- package/dist/jsdoc-extractor.js +17 -10
- package/dist/jsdoc-panel.component.d.ts +8 -25
- package/dist/jsdoc-panel.component.d.ts.map +1 -1
- package/dist/jsdoc-panel.component.js +34 -474
- package/dist/jsdoc-plugin.browser.js +2 -2
- package/dist/jsdoc-plugin.d.ts.map +1 -1
- package/dist/jsdoc-plugin.js +4 -1
- package/dist/service-page/api-page.model.d.ts +35 -0
- package/dist/service-page/api-page.model.d.ts.map +1 -0
- package/dist/service-page/api-page.model.js +54 -0
- package/dist/service-page/jsdoc-service-page.component.d.ts +82 -0
- package/dist/service-page/jsdoc-service-page.component.d.ts.map +1 -0
- package/dist/service-page/jsdoc-service-page.component.js +1178 -0
- package/dist/service-page/pipe-usage.d.ts +13 -0
- package/dist/service-page/pipe-usage.d.ts.map +1 -0
- package/dist/service-page/pipe-usage.js +35 -0
- package/dist/service-page/service-page.model.d.ts +78 -0
- package/dist/service-page/service-page.model.d.ts.map +1 -0
- package/dist/service-page/service-page.model.js +130 -0
- package/dist/service-page/service-usage.d.ts +28 -0
- package/dist/service-page/service-usage.d.ts.map +1 -0
- package/dist/service-page/service-usage.js +61 -0
- package/package.json +3 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ScannedPipe } from '@ng-prism/core/plugin';
|
|
2
|
+
/**
|
|
3
|
+
* The snippet that shows how to use a pipe: the imports, the `providers`
|
|
4
|
+
* entries its setup asks for, the component's `imports` entry and a template
|
|
5
|
+
* line. Imports and setup are written as for a service.
|
|
6
|
+
*
|
|
7
|
+
* Like the service snippet it is generated and says nothing about values: the
|
|
8
|
+
* template line names the piped value `value` and each argument by its
|
|
9
|
+
* parameter name. It shows the first signature that is not `@deprecated`, the
|
|
10
|
+
* way a new template should call the pipe, or the first one when all are.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generatePipeUsage(pipe: ScannedPipe): string;
|
|
13
|
+
//# sourceMappingURL=pipe-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipe-usage.d.ts","sourceRoot":"","sources":["../../src/service-page/pipe-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpE;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAU3D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { importLines, joinUsageBlocks, setupBlock } from './service-usage.js';
|
|
2
|
+
/**
|
|
3
|
+
* The snippet that shows how to use a pipe: the imports, the `providers`
|
|
4
|
+
* entries its setup asks for, the component's `imports` entry and a template
|
|
5
|
+
* line. Imports and setup are written as for a service.
|
|
6
|
+
*
|
|
7
|
+
* Like the service snippet it is generated and says nothing about values: the
|
|
8
|
+
* template line names the piped value `value` and each argument by its
|
|
9
|
+
* parameter name. It shows the first signature that is not `@deprecated`, the
|
|
10
|
+
* way a new template should call the pipe, or the first one when all are.
|
|
11
|
+
*/
|
|
12
|
+
export function generatePipeUsage(pipe) {
|
|
13
|
+
const { className, pipeName, api } = pipe;
|
|
14
|
+
const signature = api.transform.find((method) => !method.tags.deprecated) ?? api.transform[0];
|
|
15
|
+
return joinUsageBlocks([
|
|
16
|
+
importLines(pipe),
|
|
17
|
+
setupBlock(api.setup),
|
|
18
|
+
['// in the component that uses it', `@Component({ imports: [${className}], … })`],
|
|
19
|
+
['// in its template', `{{ value | ${pipeName}${pipeArguments(signature)} }}`]
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The arguments of the template line, from a signature's parameters after the
|
|
24
|
+
* piped value: `: pattern` for each one the call has to pass. Pipe arguments
|
|
25
|
+
* are positional, so what can be left out is the optional and rest parameters
|
|
26
|
+
* at the end; one with a default that a required parameter follows stays in.
|
|
27
|
+
*/
|
|
28
|
+
function pipeArguments(signature) {
|
|
29
|
+
const params = signature?.params.slice(1) ?? [];
|
|
30
|
+
const lastRequired = params.map((param) => !param.optional && !param.rest).lastIndexOf(true);
|
|
31
|
+
return params
|
|
32
|
+
.slice(0, lastRequired + 1)
|
|
33
|
+
.map((param) => `: ${param.name}`)
|
|
34
|
+
.join('');
|
|
35
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ApiParam, ApiSetupEntry, ApiTypeRef } from '@ng-prism/core/plugin';
|
|
2
|
+
import type { ApiPageModel } from './api-page.model.js';
|
|
3
|
+
/** One entry of the API page's "On this page" list. `id` names the section, `level` 2 is a type below "Types". */
|
|
4
|
+
export interface TocEntry {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
level: 1 | 2;
|
|
8
|
+
}
|
|
9
|
+
/** A piece of a type as written; `link` is the TOC id of the documented type the piece names. */
|
|
10
|
+
export interface TypeSegment {
|
|
11
|
+
text: string;
|
|
12
|
+
link?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The TOC id of a documented type's card. */
|
|
15
|
+
export declare function typeAnchor(typeId: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* The sections of an API page in the order the page shows them. Usage is
|
|
18
|
+
* always there, being generated; any other section only when it has content.
|
|
19
|
+
* A service has properties and methods, a pipe its transform signatures.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildApiPageToc(page: ApiPageModel): TocEntry[];
|
|
22
|
+
/** Where the page is scrolled to, and where each anchor of the "On this page" list sits on it. */
|
|
23
|
+
export interface ScrollSpyState {
|
|
24
|
+
/** The TOC id of each anchor in page order, with its offset from the top of the scrolled content. */
|
|
25
|
+
anchors: readonly {
|
|
26
|
+
id: string;
|
|
27
|
+
top: number;
|
|
28
|
+
}[];
|
|
29
|
+
scrollTop: number;
|
|
30
|
+
clientHeight: number;
|
|
31
|
+
scrollHeight: number;
|
|
32
|
+
/** The entry a jump is heading for, for as long as the jump lasts. */
|
|
33
|
+
jumpTarget: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The entry the "On this page" list marks. During a jump, the one the reader
|
|
37
|
+
* jumped to, whatever the jump scrolls past. Otherwise the last section whose
|
|
38
|
+
* heading has come up to a line a quarter down the view, except at the bottom
|
|
39
|
+
* of the page: the sections there can never come up to the line, so the last
|
|
40
|
+
* one in view is active.
|
|
41
|
+
*/
|
|
42
|
+
export declare function activeTocId({ anchors, scrollTop, clientHeight, scrollHeight, jumpTarget }: ScrollSpyState): string;
|
|
43
|
+
/**
|
|
44
|
+
* Cut a type as written into plain text and the names of documented types, so
|
|
45
|
+
* the page can turn those names into links to their cards.
|
|
46
|
+
*
|
|
47
|
+
* `ref.links` holds type ids, and an id is the type's name, or
|
|
48
|
+
* `${name}@${importPath}` when two reachable types share a name. An identifier
|
|
49
|
+
* in the text is matched against the name part of each id, the id that is the
|
|
50
|
+
* name itself first. Known limitation: a type imported under another name
|
|
51
|
+
* (`import { Item as OtherItem }`) appears in the text by its local name, which
|
|
52
|
+
* no id carries, so it stays unlinked.
|
|
53
|
+
*/
|
|
54
|
+
export declare function typeSegments(ref: ApiTypeRef): TypeSegment[];
|
|
55
|
+
/** A parameter as a signature writes it, `config?: ToastConfig` or `...features: Feature[]`, with its type linked. */
|
|
56
|
+
export declare function paramSegments(param: ApiParam): TypeSegment[];
|
|
57
|
+
/**
|
|
58
|
+
* A parameter as its declaration writes it, default included:
|
|
59
|
+
* `config: ToastConfig = {}`. A default makes the parameter optional, so it
|
|
60
|
+
* goes without the `?`; one without a default reads as in a signature.
|
|
61
|
+
*/
|
|
62
|
+
export declare function declaredParamSegments(param: ApiParam): TypeSegment[];
|
|
63
|
+
/** Whether a parameter list says more than its signature: a `@param` text or a default. */
|
|
64
|
+
export declare function documentsParams(params: readonly ApiParam[] | undefined): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* What follows a setup entry's name on its signature line: the parameters and
|
|
67
|
+
* the return type of a function, the type of a token.
|
|
68
|
+
*/
|
|
69
|
+
export declare function setupSignature(entry: ApiSetupEntry): TypeSegment[];
|
|
70
|
+
/**
|
|
71
|
+
* Split a type's `reachedFrom` (`parameter of show()`, `via options.action`)
|
|
72
|
+
* into its words and the code they end in, so the page can set the code apart.
|
|
73
|
+
*/
|
|
74
|
+
export declare function splitReachedFrom(reachedFrom: string): {
|
|
75
|
+
text: string;
|
|
76
|
+
code?: string;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=service-page.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-page.model.d.ts","sourceRoot":"","sources":["../../src/service-page/service-page.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,kHAAkH;AAClH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;CAChB;AAED,iGAAiG;AACjG,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,EAAE,CAc9D;AAKD,kGAAkG;AAClG,MAAM,WAAW,cAAc;IAC3B,qGAAqG;IACrG,OAAO,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,cAAc,GAAG,MAAM,CAYlH;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,EAAE,CAsB3D;AAED,sHAAsH;AACtH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,EAAE,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,EAAE,CAGpE;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,GAAG,OAAO,CAEhF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,WAAW,EAAE,CAMlE;AAiBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAKrF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/** The TOC id of a documented type's card. */
|
|
2
|
+
export function typeAnchor(typeId) {
|
|
3
|
+
return `type-${typeId}`;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The sections of an API page in the order the page shows them. Usage is
|
|
7
|
+
* always there, being generated; any other section only when it has content.
|
|
8
|
+
* A service has properties and methods, a pipe its transform signatures.
|
|
9
|
+
*/
|
|
10
|
+
export function buildApiPageToc(page) {
|
|
11
|
+
const sections = [
|
|
12
|
+
['usage', 'Usage', true],
|
|
13
|
+
['setup', 'Setup', page.setup.length > 0],
|
|
14
|
+
['examples', 'Examples', page.examples.length > 0],
|
|
15
|
+
['properties', 'Properties', !!page.properties?.length],
|
|
16
|
+
['methods', 'Methods', !!page.methods?.length],
|
|
17
|
+
['transform', 'Transform', !!page.transform?.length],
|
|
18
|
+
['types', 'Types', page.types.length > 0]
|
|
19
|
+
];
|
|
20
|
+
const toc = sections.filter(([, , present]) => present).map(([id, label]) => ({ id, label, level: 1 }));
|
|
21
|
+
for (const type of page.types)
|
|
22
|
+
toc.push({ id: typeAnchor(type.id), label: type.name, level: 2 });
|
|
23
|
+
return toc;
|
|
24
|
+
}
|
|
25
|
+
/** How far down the view, as a share of its height, a section's heading has to come to make the section active. */
|
|
26
|
+
const ACTIVATION_LINE = 0.25;
|
|
27
|
+
/**
|
|
28
|
+
* The entry the "On this page" list marks. During a jump, the one the reader
|
|
29
|
+
* jumped to, whatever the jump scrolls past. Otherwise the last section whose
|
|
30
|
+
* heading has come up to a line a quarter down the view, except at the bottom
|
|
31
|
+
* of the page: the sections there can never come up to the line, so the last
|
|
32
|
+
* one in view is active.
|
|
33
|
+
*/
|
|
34
|
+
export function activeTocId({ anchors, scrollTop, clientHeight, scrollHeight, jumpTarget }) {
|
|
35
|
+
if (jumpTarget)
|
|
36
|
+
return jumpTarget;
|
|
37
|
+
if (scrollTop + clientHeight >= scrollHeight - 1) {
|
|
38
|
+
const inView = anchors.filter((anchor) => anchor.top >= scrollTop && anchor.top < scrollTop + clientHeight).at(-1);
|
|
39
|
+
if (inView)
|
|
40
|
+
return inView.id;
|
|
41
|
+
}
|
|
42
|
+
const line = scrollTop + clientHeight * ACTIVATION_LINE;
|
|
43
|
+
return (anchors.filter((anchor) => anchor.top <= line).at(-1) ?? anchors[0])?.id ?? 'usage';
|
|
44
|
+
}
|
|
45
|
+
const IDENTIFIER = /[A-Za-z_$][\w$]*/g;
|
|
46
|
+
/**
|
|
47
|
+
* Cut a type as written into plain text and the names of documented types, so
|
|
48
|
+
* the page can turn those names into links to their cards.
|
|
49
|
+
*
|
|
50
|
+
* `ref.links` holds type ids, and an id is the type's name, or
|
|
51
|
+
* `${name}@${importPath}` when two reachable types share a name. An identifier
|
|
52
|
+
* in the text is matched against the name part of each id, the id that is the
|
|
53
|
+
* name itself first. Known limitation: a type imported under another name
|
|
54
|
+
* (`import { Item as OtherItem }`) appears in the text by its local name, which
|
|
55
|
+
* no id carries, so it stays unlinked.
|
|
56
|
+
*/
|
|
57
|
+
export function typeSegments(ref) {
|
|
58
|
+
const links = ref.links ?? [];
|
|
59
|
+
const segments = [];
|
|
60
|
+
let plain = '';
|
|
61
|
+
let last = 0;
|
|
62
|
+
for (const match of ref.text.matchAll(IDENTIFIER)) {
|
|
63
|
+
const name = match[0];
|
|
64
|
+
const id = links.find((candidate) => candidate === name) ?? links.find((candidate) => candidate.split('@')[0] === name);
|
|
65
|
+
if (!id)
|
|
66
|
+
continue;
|
|
67
|
+
plain += ref.text.slice(last, match.index);
|
|
68
|
+
if (plain)
|
|
69
|
+
segments.push({ text: plain });
|
|
70
|
+
segments.push({ text: name, link: typeAnchor(id) });
|
|
71
|
+
plain = '';
|
|
72
|
+
last = match.index + name.length;
|
|
73
|
+
}
|
|
74
|
+
plain += ref.text.slice(last);
|
|
75
|
+
if (plain || !segments.length)
|
|
76
|
+
segments.push({ text: plain });
|
|
77
|
+
return segments;
|
|
78
|
+
}
|
|
79
|
+
/** A parameter as a signature writes it, `config?: ToastConfig` or `...features: Feature[]`, with its type linked. */
|
|
80
|
+
export function paramSegments(param) {
|
|
81
|
+
return joinSegments(`${param.rest ? '...' : ''}${param.name}${param.optional ? '?' : ''}: `, typeSegments(param.type));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A parameter as its declaration writes it, default included:
|
|
85
|
+
* `config: ToastConfig = {}`. A default makes the parameter optional, so it
|
|
86
|
+
* goes without the `?`; one without a default reads as in a signature.
|
|
87
|
+
*/
|
|
88
|
+
export function declaredParamSegments(param) {
|
|
89
|
+
if (param.defaultValue === undefined)
|
|
90
|
+
return paramSegments(param);
|
|
91
|
+
return joinSegments(`${param.rest ? '...' : ''}${param.name}: `, typeSegments(param.type), ` = ${param.defaultValue}`);
|
|
92
|
+
}
|
|
93
|
+
/** Whether a parameter list says more than its signature: a `@param` text or a default. */
|
|
94
|
+
export function documentsParams(params) {
|
|
95
|
+
return !!params?.some((param) => param.description || param.defaultValue !== undefined);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* What follows a setup entry's name on its signature line: the parameters and
|
|
99
|
+
* the return type of a function, the type of a token.
|
|
100
|
+
*/
|
|
101
|
+
export function setupSignature(entry) {
|
|
102
|
+
if (entry.kind === 'token')
|
|
103
|
+
return entry.tokenType ? joinSegments(': ', typeSegments(entry.tokenType)) : [];
|
|
104
|
+
const params = (entry.params ?? []).flatMap((param, index) => (index ? [', ', paramSegments(param)] : [paramSegments(param)]));
|
|
105
|
+
return joinSegments('(', ...params, ')', ...(entry.returnType ? [': ', typeSegments(entry.returnType)] : []));
|
|
106
|
+
}
|
|
107
|
+
/** Concatenate text and segments, merging neighbouring plain text into one segment. */
|
|
108
|
+
function joinSegments(...parts) {
|
|
109
|
+
const joined = [];
|
|
110
|
+
for (const segment of parts.flatMap((part) => (typeof part === 'string' ? [{ text: part }] : part))) {
|
|
111
|
+
const previous = joined.at(-1);
|
|
112
|
+
if (!segment.text)
|
|
113
|
+
continue;
|
|
114
|
+
if (previous && !previous.link && !segment.link)
|
|
115
|
+
previous.text += segment.text;
|
|
116
|
+
else
|
|
117
|
+
joined.push({ ...segment });
|
|
118
|
+
}
|
|
119
|
+
return joined;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Split a type's `reachedFrom` (`parameter of show()`, `via options.action`)
|
|
123
|
+
* into its words and the code they end in, so the page can set the code apart.
|
|
124
|
+
*/
|
|
125
|
+
export function splitReachedFrom(reachedFrom) {
|
|
126
|
+
const space = reachedFrom.lastIndexOf(' ');
|
|
127
|
+
if (space < 0)
|
|
128
|
+
return { text: reachedFrom };
|
|
129
|
+
return { text: reachedFrom.slice(0, space + 1), code: reachedFrom.slice(space + 1) };
|
|
130
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ApiSetupEntry, ScannedService } from '@ng-prism/core/plugin';
|
|
2
|
+
/** What the import lines read: a scanned service or pipe. */
|
|
3
|
+
export interface UsageSubject {
|
|
4
|
+
className: string;
|
|
5
|
+
importPath?: string;
|
|
6
|
+
api: {
|
|
7
|
+
setup: ApiSetupEntry[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The snippet that shows how to bring a service into an application: the
|
|
12
|
+
* imports, the `providers` entries its setup asks for, and the `inject()` call.
|
|
13
|
+
*
|
|
14
|
+
* It is generated from the scanned API, not taken from the author, so it says
|
|
15
|
+
* nothing about values: a setup function's arguments and a token's value are
|
|
16
|
+
* left as `…` for the reader to fill in.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateServiceUsage(service: ScannedService): string;
|
|
19
|
+
/**
|
|
20
|
+
* One line per entry point, the subject's first, each naming the subject
|
|
21
|
+
* before its setup entries. Shared with the pipe snippet.
|
|
22
|
+
*/
|
|
23
|
+
export declare function importLines({ className, importPath, api }: UsageSubject): string[];
|
|
24
|
+
/** The `app.config.ts` block with one `providers` entry per setup entry, or nothing without setup. Shared with the pipe snippet. */
|
|
25
|
+
export declare function setupBlock(setup: ApiSetupEntry[]): string[];
|
|
26
|
+
/** The blocks of a snippet, each a list of lines, with a blank line between them; an empty block is left out. */
|
|
27
|
+
export declare function joinUsageBlocks(blocks: string[][]): string;
|
|
28
|
+
//# sourceMappingURL=service-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-usage.d.ts","sourceRoot":"","sources":["../../src/service-page/service-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE3E,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE;QAAE,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAmBpE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,YAAY,GAAG,MAAM,EAAE,CASlF;AAED,oIAAoI;AACpI,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CAG3D;AAED,iHAAiH;AACjH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAK1D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The snippet that shows how to bring a service into an application: the
|
|
3
|
+
* imports, the `providers` entries its setup asks for, and the `inject()` call.
|
|
4
|
+
*
|
|
5
|
+
* It is generated from the scanned API, not taken from the author, so it says
|
|
6
|
+
* nothing about values: a setup function's arguments and a token's value are
|
|
7
|
+
* left as `…` for the reader to fill in.
|
|
8
|
+
*/
|
|
9
|
+
export function generateServiceUsage(service) {
|
|
10
|
+
const { className, provision, api } = service;
|
|
11
|
+
const variable = className.charAt(0).toLowerCase() + className.slice(1);
|
|
12
|
+
const blocks = [importLines(service), setupBlock(api.setup)];
|
|
13
|
+
// A setup function of a service provided by hand normally provides it; a token never does.
|
|
14
|
+
if (provision === 'manual' && !api.setup.some((entry) => entry.kind === 'function')) {
|
|
15
|
+
blocks.push([
|
|
16
|
+
'// the component that uses it',
|
|
17
|
+
`@Component({ …, providers: [${className}] })`,
|
|
18
|
+
'export class MyComponent {',
|
|
19
|
+
` private readonly ${variable} = inject(${className});`,
|
|
20
|
+
'}'
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
blocks.push(['// in a component or service', `private readonly ${variable} = inject(${className});`]);
|
|
25
|
+
}
|
|
26
|
+
return joinUsageBlocks(blocks);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* One line per entry point, the subject's first, each naming the subject
|
|
30
|
+
* before its setup entries. Shared with the pipe snippet.
|
|
31
|
+
*/
|
|
32
|
+
export function importLines({ className, importPath, api }) {
|
|
33
|
+
const groups = new Map();
|
|
34
|
+
const add = (path, name) => groups.set(path, [...(groups.get(path) ?? []), name]);
|
|
35
|
+
// A class the scanner could not place has no import path; there is nothing true to write for it.
|
|
36
|
+
if (importPath)
|
|
37
|
+
add(importPath, className);
|
|
38
|
+
for (const entry of api.setup)
|
|
39
|
+
add(entry.importPath, entry.name);
|
|
40
|
+
return [...groups].map(([path, names]) => `import { ${names.join(', ')} } from '${path}';`);
|
|
41
|
+
}
|
|
42
|
+
/** The `app.config.ts` block with one `providers` entry per setup entry, or nothing without setup. Shared with the pipe snippet. */
|
|
43
|
+
export function setupBlock(setup) {
|
|
44
|
+
if (!setup.length)
|
|
45
|
+
return [];
|
|
46
|
+
return ['// app.config.ts', `providers: [${setup.map(providerEntry).join(', ')}]`];
|
|
47
|
+
}
|
|
48
|
+
/** The blocks of a snippet, each a list of lines, with a blank line between them; an empty block is left out. */
|
|
49
|
+
export function joinUsageBlocks(blocks) {
|
|
50
|
+
return blocks
|
|
51
|
+
.filter((lines) => lines.length)
|
|
52
|
+
.map((lines) => lines.join('\n'))
|
|
53
|
+
.join('\n\n');
|
|
54
|
+
}
|
|
55
|
+
function providerEntry(entry) {
|
|
56
|
+
if (entry.kind === 'token')
|
|
57
|
+
return `{ provide: ${entry.name}, useValue: … }`;
|
|
58
|
+
// A rest parameter can be left out as well as an optional one.
|
|
59
|
+
const callableBare = (entry.params ?? []).every((param) => param.optional || param.rest);
|
|
60
|
+
return `${entry.name}(${callableBare ? '' : '…'})`;
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-prism/plugin-jsdoc",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.7.0-beta.0",
|
|
4
4
|
"description": "JSDoc API documentation panel for ng-prism.",
|
|
5
5
|
"ng-add": {
|
|
6
6
|
"save": "devDependencies"
|
|
@@ -35,8 +35,9 @@
|
|
|
35
35
|
"!**/*.tsbuildinfo"
|
|
36
36
|
],
|
|
37
37
|
"peerDependencies": {
|
|
38
|
+
"@angular/common": ">=20.0.0",
|
|
38
39
|
"@angular/core": ">=20.0.0",
|
|
39
|
-
"@ng-prism/core": "^22.
|
|
40
|
+
"@ng-prism/core": "^22.7.0-0",
|
|
40
41
|
"highlight.js": ">=11.0.0",
|
|
41
42
|
"ngx-highlightjs": ">=14.0.0",
|
|
42
43
|
"typescript": ">=5.5.0",
|