@cparra/apexdocs 2.25.0-alpha.8 → 2.25.0-alpha.9
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/cli/generate.js +153 -165
- package/dist/index.d.ts +51 -13
- package/examples/plain-markdown/docs/index.md +25 -33
- package/examples/plain-markdown/docs/{Miscellaneous/ns.BaseClass.md → miscellaneous/BaseClass.md} +1 -1
- package/examples/plain-markdown/docs/{Miscellaneous/ns.MultiInheritanceClass.md → miscellaneous/MultiInheritanceClass.md} +5 -6
- package/examples/plain-markdown/docs/{Miscellaneous/ns.SampleException.md → miscellaneous/SampleException.md} +3 -4
- package/examples/plain-markdown/docs/{Miscellaneous/ns.SampleInterface.md → miscellaneous/SampleInterface.md} +22 -29
- package/examples/plain-markdown/docs/{Miscellaneous/ns.Url.md → miscellaneous/Url.md} +32 -43
- package/examples/plain-markdown/docs/sample-enums/SampleEnum.md +36 -0
- package/examples/plain-markdown/docs/{SampleGroup/ns.SampleClass.md → samplegroup/SampleClass.md} +8 -11
- package/examples/vitepress/apexdocs.config.ts +1 -3
- package/examples/vitepress/docs/.vitepress/sidebar.json +18 -18
- package/examples/vitepress/docs/index.md +10 -10
- package/examples/vitepress/docs/{Miscellaneous/apexdocs.BaseClass.md → miscellaneous/BaseClass.md} +1 -1
- package/examples/vitepress/docs/{Miscellaneous/apexdocs.MultiInheritanceClass.md → miscellaneous/MultiInheritanceClass.md} +2 -2
- package/examples/vitepress/docs/{Miscellaneous/apexdocs.SampleException.md → miscellaneous/SampleException.md} +1 -1
- package/examples/vitepress/docs/{Miscellaneous/apexdocs.SampleInterface.md → miscellaneous/SampleInterface.md} +6 -6
- package/examples/vitepress/docs/{Miscellaneous/apexdocs.Url.md → miscellaneous/Url.md} +3 -3
- package/examples/vitepress/docs/{Sample-Enums/apexdocs.SampleEnum.md → sample-enums/SampleEnum.md} +3 -3
- package/examples/vitepress/docs/{SampleGroup/apexdocs.SampleClass.md → samplegroup/SampleClass.md} +4 -4
- package/package.json +1 -1
- package/src/application/apex-file-reader.ts +3 -3
- package/src/application/file-writer.ts +5 -9
- package/src/application/generators/markdown.ts +9 -4
- package/src/application/generators/openapi.ts +4 -4
- package/src/core/markdown/__test__/generating-class-docs.spec.ts +5 -3
- package/src/core/markdown/__test__/generating-enum-docs.spec.ts +3 -3
- package/src/core/markdown/__test__/generating-interface-docs.spec.ts +5 -3
- package/src/core/markdown/__test__/generating-reference-guide.spec.ts +3 -7
- package/src/core/markdown/__test__/test-helpers.ts +3 -3
- package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +40 -5
- package/src/core/markdown/adapters/apex-types.ts +3 -2
- package/src/core/markdown/adapters/reference-guide.ts +35 -0
- package/src/core/markdown/adapters/renderable-bundle.ts +43 -119
- package/src/core/markdown/adapters/renderable-to-page-data.ts +12 -15
- package/src/core/markdown/adapters/types.d.ts +4 -6
- package/src/core/markdown/generate-docs.ts +99 -42
- package/src/core/markdown/reflection/inheritance-chain-expanion.ts +1 -1
- package/src/core/markdown/reflection/reflect-source.ts +8 -4
- package/src/core/openapi/manifest-factory.ts +2 -2
- package/src/core/openapi/openapi-type-file.ts +1 -3
- package/src/core/openapi/parser.ts +4 -4
- package/src/core/shared/types.d.ts +52 -14
- package/src/index.ts +2 -1
- package/examples/plain-markdown/docs/Sample-Enums/ns.SampleEnum.md +0 -38
- /package/examples/plain-markdown/docs/{Miscellaneous/ns.ParentInterface.md → miscellaneous/ParentInterface.md} +0 -0
- /package/examples/plain-markdown/docs/{Miscellaneous/ns.ReferencedEnum.md → miscellaneous/ReferencedEnum.md} +0 -0
- /package/examples/vitepress/docs/{Miscellaneous/apexdocs.ParentInterface.md → miscellaneous/ParentInterface.md} +0 -0
- /package/examples/vitepress/docs/{Miscellaneous/apexdocs.ReferencedEnum.md → miscellaneous/ReferencedEnum.md} +0 -0
|
@@ -21,7 +21,14 @@ describe('Conversion from InterfaceMirror to InterfaceSource understandable by t
|
|
|
21
21
|
it('converts the name', () => {
|
|
22
22
|
const interfaceMirror = new InterfaceMirrorBuilder().withName('SampleInterface').build();
|
|
23
23
|
const interfaceSource = typeToRenderable(
|
|
24
|
-
{
|
|
24
|
+
{
|
|
25
|
+
source: {
|
|
26
|
+
filePath: '',
|
|
27
|
+
type: 'interface',
|
|
28
|
+
name: 'SampleInterface',
|
|
29
|
+
},
|
|
30
|
+
type: interfaceMirror,
|
|
31
|
+
},
|
|
25
32
|
linkGenerator,
|
|
26
33
|
defaultMarkdownGeneratorConfig,
|
|
27
34
|
);
|
|
@@ -32,7 +39,14 @@ describe('Conversion from InterfaceMirror to InterfaceSource understandable by t
|
|
|
32
39
|
it('converts the access modifier', () => {
|
|
33
40
|
const interfaceMirror = new InterfaceMirrorBuilder().build();
|
|
34
41
|
const interfaceSource = typeToRenderable(
|
|
35
|
-
{
|
|
42
|
+
{
|
|
43
|
+
source: {
|
|
44
|
+
filePath: '',
|
|
45
|
+
type: 'interface',
|
|
46
|
+
name: 'SampleInterface',
|
|
47
|
+
},
|
|
48
|
+
type: interfaceMirror,
|
|
49
|
+
},
|
|
36
50
|
linkGenerator,
|
|
37
51
|
defaultMarkdownGeneratorConfig,
|
|
38
52
|
);
|
|
@@ -45,7 +59,14 @@ describe('Conversion from InterfaceMirror to InterfaceSource understandable by t
|
|
|
45
59
|
.addAnnotation(new AnnotationBuilder().withName('MyAnnotation').build())
|
|
46
60
|
.build();
|
|
47
61
|
const interfaceSource = typeToRenderable(
|
|
48
|
-
{
|
|
62
|
+
{
|
|
63
|
+
source: {
|
|
64
|
+
filePath: '',
|
|
65
|
+
type: 'interface',
|
|
66
|
+
name: 'SampleInterface',
|
|
67
|
+
},
|
|
68
|
+
type: interfaceMirror,
|
|
69
|
+
},
|
|
49
70
|
linkGenerator,
|
|
50
71
|
defaultMarkdownGeneratorConfig,
|
|
51
72
|
);
|
|
@@ -67,7 +88,14 @@ describe('Conversion from InterfaceMirror to InterfaceSource understandable by t
|
|
|
67
88
|
.build();
|
|
68
89
|
|
|
69
90
|
const interfaceSource = typeToRenderable(
|
|
70
|
-
{
|
|
91
|
+
{
|
|
92
|
+
source: {
|
|
93
|
+
filePath: '',
|
|
94
|
+
type: 'interface',
|
|
95
|
+
name: 'SampleInterface',
|
|
96
|
+
},
|
|
97
|
+
type: interfaceMirror,
|
|
98
|
+
},
|
|
71
99
|
linkGenerator,
|
|
72
100
|
defaultMarkdownGeneratorConfig,
|
|
73
101
|
);
|
|
@@ -99,7 +127,14 @@ describe('Conversion from InterfaceMirror to InterfaceSource understandable by t
|
|
|
99
127
|
.build();
|
|
100
128
|
|
|
101
129
|
const interfaceSource = typeToRenderable(
|
|
102
|
-
{
|
|
130
|
+
{
|
|
131
|
+
source: {
|
|
132
|
+
filePath: '',
|
|
133
|
+
type: 'interface',
|
|
134
|
+
name: 'SampleInterface',
|
|
135
|
+
},
|
|
136
|
+
type: interfaceMirror,
|
|
137
|
+
},
|
|
103
138
|
linkGenerator,
|
|
104
139
|
defaultMarkdownGeneratorConfig,
|
|
105
140
|
);
|
|
@@ -15,6 +15,7 @@ import { adaptDescribable, adaptDocumentable } from './documentables';
|
|
|
15
15
|
import { adaptConstructor, adaptMethod } from './methods-and-constructors';
|
|
16
16
|
import { adaptFieldOrProperty } from './fields-and-properties';
|
|
17
17
|
import { MarkdownGeneratorConfig } from '../generate-docs';
|
|
18
|
+
import { SourceFileMetadata } from '../../shared/types';
|
|
18
19
|
|
|
19
20
|
type GetReturnRenderable<T extends Type> = T extends InterfaceMirror
|
|
20
21
|
? RenderableInterface
|
|
@@ -23,7 +24,7 @@ type GetReturnRenderable<T extends Type> = T extends InterfaceMirror
|
|
|
23
24
|
: RenderableEnum;
|
|
24
25
|
|
|
25
26
|
export function typeToRenderable<T extends Type>(
|
|
26
|
-
parsedFile: {
|
|
27
|
+
parsedFile: { source: SourceFileMetadata; type: T },
|
|
27
28
|
linkGenerator: GetRenderableContentByTypeName,
|
|
28
29
|
config: MarkdownGeneratorConfig,
|
|
29
30
|
): GetReturnRenderable<T> & { filePath: string; namespace?: string } {
|
|
@@ -41,7 +42,7 @@ export function typeToRenderable<T extends Type>(
|
|
|
41
42
|
|
|
42
43
|
return {
|
|
43
44
|
...(getRenderable() as GetReturnRenderable<T>),
|
|
44
|
-
filePath: parsedFile.filePath,
|
|
45
|
+
filePath: parsedFile.source.filePath,
|
|
45
46
|
namespace: config.namespace,
|
|
46
47
|
};
|
|
47
48
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MarkdownGeneratorConfig } from '../generate-docs';
|
|
2
|
+
import { DocPageReference, ParsedFile } from '../../shared/types';
|
|
3
|
+
import { Type } from '@cparra/apex-reflection';
|
|
4
|
+
|
|
5
|
+
export function parsedFilesToReferenceGuide(
|
|
6
|
+
config: MarkdownGeneratorConfig,
|
|
7
|
+
parsedFiles: ParsedFile[],
|
|
8
|
+
): Record<string, DocPageReference> {
|
|
9
|
+
return parsedFiles.reduce<Record<string, DocPageReference>>((acc, parsedFile) => {
|
|
10
|
+
acc[parsedFile.type.name] = parsedFileToDocPageReference(config, parsedFile);
|
|
11
|
+
return acc;
|
|
12
|
+
}, {});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function parsedFileToDocPageReference(config: MarkdownGeneratorConfig, parsedFile: ParsedFile): DocPageReference {
|
|
16
|
+
return {
|
|
17
|
+
source: parsedFile.source,
|
|
18
|
+
displayName: parsedFile.type.name,
|
|
19
|
+
pathFromRoot: `${slugify(getTypeGroup(parsedFile.type, config))}/${parsedFile.type.name}.md`,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getTypeGroup(type: Type, config: MarkdownGeneratorConfig): string {
|
|
24
|
+
const groupAnnotation = type.docComment?.annotations.find((annotation) => annotation.name.toLowerCase() === 'group');
|
|
25
|
+
return groupAnnotation?.body ?? config.defaultGroupName;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function slugify(text: string): string {
|
|
29
|
+
return text
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9\s-]/g, '') // Remove non-alphanumeric characters except spaces and hyphens
|
|
32
|
+
.trim()
|
|
33
|
+
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
|
34
|
+
.replace(/-+/g, '-'); // Replace multiple hyphens with a single hyphen
|
|
35
|
+
}
|
|
@@ -1,144 +1,68 @@
|
|
|
1
|
-
import { ParsedFile } from '../../shared/types';
|
|
2
|
-
import { Link, RenderableBundle, StringOrLink } from './types';
|
|
1
|
+
import { DocPageReference, ParsedFile } from '../../shared/types';
|
|
2
|
+
import { Link, ReferenceGuideReference, Renderable, RenderableBundle, StringOrLink } from './types';
|
|
3
3
|
import { typeToRenderable } from './apex-types';
|
|
4
4
|
import { adaptDescribable } from './documentables';
|
|
5
|
-
import { Type } from '@cparra/apex-reflection';
|
|
6
5
|
import { MarkdownGeneratorConfig } from '../generate-docs';
|
|
6
|
+
import { apply } from '#utils/fp';
|
|
7
|
+
import { Type } from '@cparra/apex-reflection';
|
|
7
8
|
|
|
8
9
|
export function parsedFilesToRenderableBundle(
|
|
9
10
|
config: MarkdownGeneratorConfig,
|
|
10
11
|
parsedFiles: ParsedFile[],
|
|
12
|
+
references: Record<string, DocPageReference>,
|
|
11
13
|
): RenderableBundle {
|
|
12
|
-
|
|
13
|
-
(acc, parsedFile) => {
|
|
14
|
-
const renderable = typeToRenderable(
|
|
15
|
-
parsedFile,
|
|
16
|
-
(referenceName) => {
|
|
17
|
-
return linkFromTypeNameGenerator(
|
|
18
|
-
parsedFile.type,
|
|
19
|
-
parsedFiles.map((file) => file.type),
|
|
20
|
-
referenceName,
|
|
21
|
-
config,
|
|
22
|
-
);
|
|
23
|
-
},
|
|
24
|
-
config,
|
|
25
|
-
);
|
|
26
|
-
acc.renderables.push(renderable);
|
|
14
|
+
const referenceFinder = apply(linkGenerator, references);
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
getPossibleLinkFromRoot(
|
|
35
|
-
config,
|
|
36
|
-
referenceName,
|
|
37
|
-
findType(
|
|
38
|
-
parsedFiles.map((file) => file.type),
|
|
39
|
-
referenceName,
|
|
40
|
-
),
|
|
41
|
-
),
|
|
42
|
-
).description,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const group = getTypeGroup(parsedFile.type, config);
|
|
46
|
-
if (!acc.references[group]) {
|
|
47
|
-
acc.references[group] = [];
|
|
48
|
-
}
|
|
49
|
-
acc.references[group].push(reference);
|
|
16
|
+
function toReferenceGuide(parsedFiles: ParsedFile[]): Record<string, ReferenceGuideReference[]> {
|
|
17
|
+
return parsedFiles.reduce<Record<string, ReferenceGuideReference[]>>(
|
|
18
|
+
addToReferenceGuide(referenceFinder, config, references),
|
|
19
|
+
{},
|
|
20
|
+
);
|
|
21
|
+
}
|
|
50
22
|
|
|
23
|
+
function toRenderables(parsedFiles: ParsedFile[]): Renderable[] {
|
|
24
|
+
return parsedFiles.reduce<Renderable[]>((acc, parsedFile) => {
|
|
25
|
+
const renderable = typeToRenderable(parsedFile, referenceFinder, config);
|
|
26
|
+
acc.push(renderable);
|
|
51
27
|
return acc;
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
references: {},
|
|
55
|
-
renderables: [],
|
|
56
|
-
},
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function linkFromTypeNameGenerator(
|
|
61
|
-
typeBeingDocumented: Type,
|
|
62
|
-
repository: Type[],
|
|
63
|
-
referenceName: string,
|
|
64
|
-
config: MarkdownGeneratorConfig,
|
|
65
|
-
): StringOrLink {
|
|
66
|
-
const type = findType(repository, referenceName);
|
|
67
|
-
if (!type) {
|
|
68
|
-
// If the type is not found, we return the type name as a string.
|
|
69
|
-
return referenceName;
|
|
28
|
+
}, []);
|
|
70
29
|
}
|
|
71
30
|
|
|
72
|
-
const [fullClassName, fileLink] = getFileLinkTuple(typeBeingDocumented, type, config);
|
|
73
31
|
return {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
url: fileLink,
|
|
32
|
+
referencesByGroup: toReferenceGuide(parsedFiles),
|
|
33
|
+
renderables: toRenderables(parsedFiles),
|
|
77
34
|
};
|
|
78
35
|
}
|
|
79
36
|
|
|
80
|
-
function
|
|
81
|
-
|
|
82
|
-
return fallback;
|
|
83
|
-
}
|
|
84
|
-
const namespacePrefix = config.namespace ? `${config.namespace}.` : '';
|
|
85
|
-
const title = `${namespacePrefix}${type.name}`;
|
|
86
|
-
return {
|
|
87
|
-
__type: 'link',
|
|
88
|
-
title: title,
|
|
89
|
-
url: `${getDirectoryFromRoot(config, type)}/${title}.md`,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function getDirectoryFromRoot(config: MarkdownGeneratorConfig, type?: Type): string {
|
|
94
|
-
if (!type) {
|
|
95
|
-
return '';
|
|
96
|
-
}
|
|
97
|
-
return `./${getSanitizedGroup(type, config)}`;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function findType(repository: Type[], referenceName: string) {
|
|
101
|
-
return repository.find((currentType: Type) => currentType.name.toLowerCase() === referenceName.toLowerCase());
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function getFileLinkTuple(
|
|
105
|
-
typeBeingDocumented: Type,
|
|
106
|
-
referencedType: Type,
|
|
37
|
+
function addToReferenceGuide(
|
|
38
|
+
findLinkFromHome: (referenceName: string) => string | Link,
|
|
107
39
|
config: MarkdownGeneratorConfig,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
40
|
+
references: Record<string, DocPageReference>,
|
|
41
|
+
) {
|
|
42
|
+
return (acc: Record<string, ReferenceGuideReference[]>, parsedFile: ParsedFile) => {
|
|
43
|
+
const group: string = getTypeGroup(parsedFile.type, config);
|
|
44
|
+
if (!acc[group]) {
|
|
45
|
+
acc[group] = [];
|
|
46
|
+
}
|
|
47
|
+
acc[group].push({
|
|
48
|
+
reference: references[parsedFile.type.name],
|
|
49
|
+
title: findLinkFromHome(parsedFile.type.name) as Link,
|
|
50
|
+
description: adaptDescribable(parsedFile.type.docComment?.descriptionLines, findLinkFromHome).description ?? null,
|
|
51
|
+
});
|
|
116
52
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// If the types the same groups then we simply link directly to that file
|
|
120
|
-
return './';
|
|
121
|
-
} else {
|
|
122
|
-
// If the types have different groups, then we have to go up a directory
|
|
123
|
-
return `../${getSanitizedGroup(referencedType, config)}/`;
|
|
124
|
-
}
|
|
53
|
+
return acc;
|
|
54
|
+
};
|
|
125
55
|
}
|
|
126
56
|
|
|
57
|
+
const linkGenerator = (references: Record<string, DocPageReference>, referenceName: string): StringOrLink => {
|
|
58
|
+
const reference: DocPageReference | undefined = references[referenceName];
|
|
59
|
+
return reference
|
|
60
|
+
? // Starting the path with a "/" will ensure the link will always be relative to the root of the site.
|
|
61
|
+
{ __type: 'link', title: reference.displayName, url: `/${reference.pathFromRoot}` }
|
|
62
|
+
: referenceName;
|
|
63
|
+
};
|
|
64
|
+
|
|
127
65
|
function getTypeGroup(type: Type, config: MarkdownGeneratorConfig): string {
|
|
128
66
|
const groupAnnotation = type.docComment?.annotations.find((annotation) => annotation.name.toLowerCase() === 'group');
|
|
129
67
|
return groupAnnotation?.body ?? config.defaultGroupName;
|
|
130
68
|
}
|
|
131
|
-
|
|
132
|
-
function getSanitizedGroup(classModel: Type, config: MarkdownGeneratorConfig) {
|
|
133
|
-
return getTypeGroup(classModel, config).replace(/ /g, '-').replace('.', '');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function getLinkFromRoot(config: MarkdownGeneratorConfig, type: Type): Link {
|
|
137
|
-
const namespacePrefix = config.namespace ? `${config.namespace}.` : '';
|
|
138
|
-
const title = `${namespacePrefix}${type.name}`;
|
|
139
|
-
return {
|
|
140
|
-
__type: 'link',
|
|
141
|
-
title: title,
|
|
142
|
-
url: `${getDirectoryFromRoot(config, type)}/${title}.md`,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
@@ -5,19 +5,20 @@ import { CompilationRequest, Template } from '../templates/template';
|
|
|
5
5
|
import { enumMarkdownTemplate } from '../templates/enum-template';
|
|
6
6
|
import { interfaceMarkdownTemplate } from '../templates/interface-template';
|
|
7
7
|
import { classMarkdownTemplate } from '../templates/class-template';
|
|
8
|
+
import { defaults } from '../../../defaults';
|
|
8
9
|
|
|
9
10
|
export const convertToDocumentationBundle = (
|
|
10
11
|
referenceGuideTemplate: string,
|
|
11
|
-
{
|
|
12
|
+
{ referencesByGroup, renderables }: RenderableBundle,
|
|
12
13
|
): DocumentationBundle => ({
|
|
13
14
|
referenceGuide: {
|
|
14
|
-
directory: '',
|
|
15
15
|
frontmatter: null,
|
|
16
|
-
content: referencesToReferenceGuideContent(
|
|
17
|
-
|
|
18
|
-
fileName: 'index',
|
|
16
|
+
content: referencesToReferenceGuideContent(referencesByGroup, referenceGuideTemplate),
|
|
17
|
+
filePath: 'index.md',
|
|
19
18
|
},
|
|
20
|
-
docs: renderables.map((renderable: Renderable) =>
|
|
19
|
+
docs: renderables.map((renderable: Renderable) =>
|
|
20
|
+
renderableToPageData(Object.values(referencesByGroup).flat(), renderable),
|
|
21
|
+
),
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
function referencesToReferenceGuideContent(
|
|
@@ -45,11 +46,9 @@ function referencesToReferenceGuideContent(
|
|
|
45
46
|
|
|
46
47
|
function renderableToPageData(referenceGuideReference: ReferenceGuideReference[], renderable: Renderable): DocPageData {
|
|
47
48
|
function buildDocOutput(renderable: Renderable, docContents: string): DocPageData {
|
|
48
|
-
const reference = referenceGuideReference.find(
|
|
49
|
-
(ref) => ref.
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const namespacePrefix = renderable.namespace ? `${renderable.namespace}.` : '';
|
|
49
|
+
const reference: ReferenceGuideReference = referenceGuideReference.find(
|
|
50
|
+
(ref) => ref.reference.source.name.toLowerCase() === renderable.name.toLowerCase(),
|
|
51
|
+
)!;
|
|
53
52
|
|
|
54
53
|
return {
|
|
55
54
|
source: {
|
|
@@ -57,12 +56,10 @@ function renderableToPageData(referenceGuideReference: ReferenceGuideReference[]
|
|
|
57
56
|
name: renderable.name,
|
|
58
57
|
type: renderable.type,
|
|
59
58
|
},
|
|
60
|
-
|
|
61
|
-
fileExtension: 'md',
|
|
62
|
-
directory: `${reference?.directory}`,
|
|
59
|
+
filePath: reference!.reference.pathFromRoot,
|
|
63
60
|
frontmatter: null,
|
|
64
61
|
content: docContents,
|
|
65
|
-
group: renderable.doc.group ??
|
|
62
|
+
group: renderable.doc.group ?? defaults.defaultGroupName,
|
|
66
63
|
};
|
|
67
64
|
}
|
|
68
65
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
MethodMirror,
|
|
8
8
|
PropertyMirror,
|
|
9
9
|
} from '@cparra/apex-reflection';
|
|
10
|
+
import { DocPageReference } from '../../shared/types';
|
|
10
11
|
|
|
11
12
|
export type Describable = string[] | undefined;
|
|
12
13
|
|
|
@@ -24,17 +25,14 @@ export type MethodMirrorWithInheritance = MethodMirror & InheritanceSupport;
|
|
|
24
25
|
// Renderable types
|
|
25
26
|
|
|
26
27
|
export type ReferenceGuideReference = {
|
|
27
|
-
|
|
28
|
-
directory: string;
|
|
28
|
+
reference: DocPageReference;
|
|
29
29
|
title: Link;
|
|
30
|
-
description: RenderableContent[] |
|
|
30
|
+
description: RenderableContent[] | null;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export type RenderableBundle = {
|
|
34
34
|
// References are grouped by their defined @group annotation
|
|
35
|
-
|
|
36
|
-
[key: string]: ReferenceGuideReference[];
|
|
37
|
-
};
|
|
35
|
+
referencesByGroup: Record<string, ReferenceGuideReference[]>;
|
|
38
36
|
renderables: Renderable[];
|
|
39
37
|
};
|
|
40
38
|
|
|
@@ -10,11 +10,14 @@ import {
|
|
|
10
10
|
Frontmatter,
|
|
11
11
|
PostHookDocumentationBundle,
|
|
12
12
|
ReferenceGuidePageData,
|
|
13
|
-
|
|
13
|
+
UnparsedSourceFile,
|
|
14
14
|
TransformDocPage,
|
|
15
15
|
TransformDocs,
|
|
16
16
|
TransformReferenceGuide,
|
|
17
17
|
UserDefinedMarkdownConfig,
|
|
18
|
+
DocPageReference,
|
|
19
|
+
TransformReference,
|
|
20
|
+
ParsedFile,
|
|
18
21
|
} from '../shared/types';
|
|
19
22
|
import { parsedFilesToRenderableBundle } from './adapters/renderable-bundle';
|
|
20
23
|
import { reflectSourceCode } from './reflection/reflect-source';
|
|
@@ -27,6 +30,7 @@ import { Template } from './templates/template';
|
|
|
27
30
|
import { hookableTemplate } from './templates/hookable';
|
|
28
31
|
import { sortMembers } from './reflection/sort-members';
|
|
29
32
|
import { isSkip } from '../shared/utils';
|
|
33
|
+
import { parsedFilesToReferenceGuide } from './adapters/reference-guide';
|
|
30
34
|
|
|
31
35
|
export type MarkdownGeneratorConfig = Pick<
|
|
32
36
|
UserDefinedMarkdownConfig,
|
|
@@ -37,6 +41,7 @@ export type MarkdownGeneratorConfig = Pick<
|
|
|
37
41
|
| 'transformReferenceGuide'
|
|
38
42
|
| 'transformDocs'
|
|
39
43
|
| 'transformDocPage'
|
|
44
|
+
| 'transformReference'
|
|
40
45
|
> & {
|
|
41
46
|
referenceGuideTemplate: string;
|
|
42
47
|
sortMembersAlphabetically: boolean;
|
|
@@ -48,8 +53,9 @@ export class HookError {
|
|
|
48
53
|
constructor(public error: unknown) {}
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
export function generateDocs(apexBundles:
|
|
56
|
+
export function generateDocs(apexBundles: UnparsedSourceFile[], config: MarkdownGeneratorConfig) {
|
|
52
57
|
const filterOutOfScope = apply(filterScope, config.scope);
|
|
58
|
+
const convertToReferences = apply(parsedFilesToReferenceGuide, config);
|
|
53
59
|
const convertToRenderableBundle = apply(parsedFilesToRenderableBundle, config);
|
|
54
60
|
const convertToDocumentationBundleForTemplate = apply(convertToDocumentationBundle, config.referenceGuideTemplate);
|
|
55
61
|
const sortTypeMembers = apply(sortMembers, config.sortMembersAlphabetically);
|
|
@@ -62,53 +68,45 @@ export function generateDocs(apexBundles: SourceFile[], config: MarkdownGenerato
|
|
|
62
68
|
E.map(addInheritedMembersToTypes),
|
|
63
69
|
E.map(addInheritanceChainToTypes),
|
|
64
70
|
E.map(sortTypeMembers),
|
|
65
|
-
E.
|
|
66
|
-
E.
|
|
71
|
+
E.bindTo('parsedFiles'),
|
|
72
|
+
E.bind('references', ({ parsedFiles }) => E.right(convertToReferences(parsedFiles))),
|
|
67
73
|
TE.fromEither,
|
|
68
|
-
TE.flatMap((
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
),
|
|
74
|
-
TE.map((bundle: PostHookDocumentationBundle) => ({
|
|
75
|
-
referenceGuide: isSkip(bundle.referenceGuide)
|
|
76
|
-
? bundle.referenceGuide
|
|
77
|
-
: {
|
|
78
|
-
...bundle.referenceGuide,
|
|
79
|
-
content: Template.getInstance().compile({
|
|
80
|
-
source: {
|
|
81
|
-
frontmatter: toFrontmatterString(bundle.referenceGuide.frontmatter),
|
|
82
|
-
content: bundle.referenceGuide.content,
|
|
83
|
-
},
|
|
84
|
-
template: hookableTemplate,
|
|
85
|
-
}),
|
|
86
|
-
},
|
|
87
|
-
docs: bundle.docs.map((doc) => ({
|
|
88
|
-
...doc,
|
|
89
|
-
content: Template.getInstance().compile({
|
|
90
|
-
source: {
|
|
91
|
-
frontmatter: toFrontmatterString(doc.frontmatter),
|
|
92
|
-
content: doc.content,
|
|
93
|
-
},
|
|
94
|
-
template: hookableTemplate,
|
|
95
|
-
}),
|
|
96
|
-
})),
|
|
97
|
-
})),
|
|
74
|
+
TE.flatMap(({ parsedFiles, references }) => transformReferenceHook(config)({ references, parsedFiles })),
|
|
75
|
+
TE.map(({ parsedFiles, references }) => convertToRenderableBundle(parsedFiles, references)),
|
|
76
|
+
TE.map(convertToDocumentationBundleForTemplate),
|
|
77
|
+
TE.flatMap(transformDocumentationBundleHook(config)),
|
|
78
|
+
TE.map(postHookCompile),
|
|
98
79
|
);
|
|
99
80
|
}
|
|
100
81
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
82
|
+
function transformReferenceHook(config: MarkdownGeneratorConfig) {
|
|
83
|
+
async function _execute(
|
|
84
|
+
references: Record<string, DocPageReference>,
|
|
85
|
+
parsedFiles: ParsedFile[],
|
|
86
|
+
transformReference?: TransformReference | undefined,
|
|
87
|
+
): Promise<{
|
|
88
|
+
references: Record<string, DocPageReference>;
|
|
89
|
+
parsedFiles: ParsedFile[];
|
|
90
|
+
}> {
|
|
91
|
+
return {
|
|
92
|
+
references: await execTransformReferenceHook(Object.values(references), transformReference),
|
|
93
|
+
parsedFiles,
|
|
94
|
+
};
|
|
104
95
|
}
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
return ({ references, parsedFiles }: { references: Record<string, DocPageReference>; parsedFiles: ParsedFile[] }) =>
|
|
98
|
+
TE.tryCatch(
|
|
99
|
+
() => _execute(references, parsedFiles, config.transformReference),
|
|
100
|
+
(error) => new HookError(error),
|
|
101
|
+
);
|
|
102
|
+
}
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
return
|
|
104
|
+
function transformDocumentationBundleHook(config: MarkdownGeneratorConfig) {
|
|
105
|
+
return (bundle: DocumentationBundle) =>
|
|
106
|
+
TE.tryCatch(
|
|
107
|
+
() => documentationBundleHook(bundle, config),
|
|
108
|
+
(error) => new HookError(error),
|
|
109
|
+
);
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
// Configurable hooks
|
|
@@ -116,6 +114,25 @@ function passThroughHook<T>(value: T): T {
|
|
|
116
114
|
return value;
|
|
117
115
|
}
|
|
118
116
|
|
|
117
|
+
const execTransformReferenceHook = async (
|
|
118
|
+
references: DocPageReference[],
|
|
119
|
+
hook: TransformReference = passThroughHook,
|
|
120
|
+
): Promise<Record<string, DocPageReference>> => {
|
|
121
|
+
const hooked = references.map<Promise<DocPageReference>>(async (reference) => {
|
|
122
|
+
const hookedResult = await hook(reference);
|
|
123
|
+
return {
|
|
124
|
+
...reference,
|
|
125
|
+
...hookedResult,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
const awaited = await Promise.all(hooked);
|
|
129
|
+
|
|
130
|
+
return awaited.reduce<Record<string, DocPageReference>>((acc, reference) => {
|
|
131
|
+
acc[reference.source.name] = reference;
|
|
132
|
+
return acc;
|
|
133
|
+
}, {});
|
|
134
|
+
};
|
|
135
|
+
|
|
119
136
|
const documentationBundleHook = async (
|
|
120
137
|
bundle: DocumentationBundle,
|
|
121
138
|
config: MarkdownGeneratorConfig,
|
|
@@ -156,3 +173,43 @@ const transformDocPage = async (doc: DocPageData, hook: TransformDocPage = passT
|
|
|
156
173
|
...(await hook(doc)),
|
|
157
174
|
};
|
|
158
175
|
};
|
|
176
|
+
|
|
177
|
+
function postHookCompile(bundle: PostHookDocumentationBundle) {
|
|
178
|
+
return {
|
|
179
|
+
referenceGuide: isSkip(bundle.referenceGuide)
|
|
180
|
+
? bundle.referenceGuide
|
|
181
|
+
: {
|
|
182
|
+
...bundle.referenceGuide,
|
|
183
|
+
content: Template.getInstance().compile({
|
|
184
|
+
source: {
|
|
185
|
+
frontmatter: toFrontmatterString(bundle.referenceGuide.frontmatter),
|
|
186
|
+
content: bundle.referenceGuide.content,
|
|
187
|
+
},
|
|
188
|
+
template: hookableTemplate,
|
|
189
|
+
}),
|
|
190
|
+
},
|
|
191
|
+
docs: bundle.docs.map((doc) => ({
|
|
192
|
+
...doc,
|
|
193
|
+
content: Template.getInstance().compile({
|
|
194
|
+
source: {
|
|
195
|
+
frontmatter: toFrontmatterString(doc.frontmatter),
|
|
196
|
+
content: doc.content,
|
|
197
|
+
},
|
|
198
|
+
template: hookableTemplate,
|
|
199
|
+
}),
|
|
200
|
+
})),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function toFrontmatterString(frontmatter: Frontmatter): string {
|
|
205
|
+
if (typeof frontmatter === 'string') {
|
|
206
|
+
return frontmatter;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!frontmatter) {
|
|
210
|
+
return '';
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const yamlString = yaml.dump(frontmatter);
|
|
214
|
+
return `---\n${yamlString}---\n`;
|
|
215
|
+
}
|
|
@@ -3,7 +3,7 @@ import { createInheritanceChain } from './inheritance-chain';
|
|
|
3
3
|
import { ParsedFile } from '../../shared/types';
|
|
4
4
|
import { parsedFilesToTypes } from '../utils';
|
|
5
5
|
|
|
6
|
-
export const addInheritanceChainToTypes = (parsedFiles: ParsedFile[]) =>
|
|
6
|
+
export const addInheritanceChainToTypes = (parsedFiles: ParsedFile[]): ParsedFile[] =>
|
|
7
7
|
parsedFiles.map((parsedFile) => ({
|
|
8
8
|
...parsedFile,
|
|
9
9
|
type: addInheritanceChain(parsedFile.type, parsedFilesToTypes(parsedFiles)),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ParsedFile,
|
|
1
|
+
import { ParsedFile, UnparsedSourceFile } from '../../shared/types';
|
|
2
2
|
import * as E from 'fp-ts/Either';
|
|
3
3
|
import { reflect as mirrorReflection, Type } from '@cparra/apex-reflection';
|
|
4
4
|
import { pipe } from 'fp-ts/function';
|
|
@@ -6,17 +6,21 @@ import * as O from 'fp-ts/Option';
|
|
|
6
6
|
import { parseApexMetadata } from '../../parse-apex-metadata';
|
|
7
7
|
import { ReflectionError } from './error-handling';
|
|
8
8
|
|
|
9
|
-
export function reflectSourceCode(apexBundles:
|
|
9
|
+
export function reflectSourceCode(apexBundles: UnparsedSourceFile[]) {
|
|
10
10
|
return apexBundles.map(reflectSourceBody);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function reflectSourceBody(apexBundle:
|
|
13
|
+
function reflectSourceBody(apexBundle: UnparsedSourceFile): E.Either<ReflectionError, ParsedFile> {
|
|
14
14
|
const { filePath, content: input, metadataContent: metadata } = apexBundle;
|
|
15
15
|
const result = mirrorReflection(input);
|
|
16
16
|
return result.error
|
|
17
17
|
? E.left(new ReflectionError(filePath, result.error.message))
|
|
18
18
|
: E.right({
|
|
19
|
-
|
|
19
|
+
source: {
|
|
20
|
+
filePath,
|
|
21
|
+
name: result.typeMirror!.name,
|
|
22
|
+
type: result.typeMirror!.type_name,
|
|
23
|
+
},
|
|
20
24
|
type: addFileMetadataToTypeAnnotation(result.typeMirror!, metadata),
|
|
21
25
|
});
|
|
22
26
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Manifest from '../manifest';
|
|
2
2
|
import { TypeParser } from './parser';
|
|
3
3
|
import { ReflectionResult } from '@cparra/apex-reflection';
|
|
4
|
-
import {
|
|
4
|
+
import { UnparsedSourceFile } from '../shared/types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Builds a new Manifest object, sourcing its types from the received TypeParser.
|
|
@@ -10,7 +10,7 @@ import { SourceFile } from '../shared/types';
|
|
|
10
10
|
*/
|
|
11
11
|
export function createManifest(
|
|
12
12
|
typeParser: TypeParser,
|
|
13
|
-
reflect: (apexBundle:
|
|
13
|
+
reflect: (apexBundle: UnparsedSourceFile) => ReflectionResult,
|
|
14
14
|
): Manifest {
|
|
15
15
|
return new Manifest(typeParser.parse(reflect));
|
|
16
16
|
}
|