@cparra/apexdocs 2.25.0-alpha.0 → 2.25.0-alpha.1
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/__mocks__/chalk.js +12 -0
- package/__mocks__/log-update.js +6 -0
- package/eslint.config.mjs +10 -0
- package/examples/plain-markdown/docs/Miscellaneous/ns.BaseClass.md +16 -0
- package/examples/plain-markdown/docs/Miscellaneous/ns.ParentInterface.md +15 -0
- package/examples/plain-markdown/docs/Miscellaneous/ns.ReferencedEnum.md +8 -0
- package/examples/plain-markdown/docs/Miscellaneous/ns.SampleException.md +7 -0
- package/examples/plain-markdown/docs/Miscellaneous/ns.SampleInterface.md +115 -0
- package/examples/plain-markdown/docs/Sample-Enums/ns.SampleEnum.md +36 -0
- package/examples/plain-markdown/docs/SampleGroup/ns.SampleClass.md +173 -0
- package/examples/plain-markdown/docs/index.md +36 -0
- package/examples/plain-markdown/force-app/classes/SampleClass.cls +37 -0
- package/examples/plain-markdown/package.json +2 -6
- package/jest.config.js +4 -0
- package/jest.d.ts +7 -0
- package/lib/__spec__/core/expect-extensions.d.ts +3 -0
- package/lib/__spec__/core/expect-extensions.js +54 -0
- package/lib/__spec__/core/expect-extensions.js.map +1 -0
- package/lib/__spec__/core/generating-class-docs.spec.d.ts +1 -0
- package/lib/__spec__/core/generating-class-docs.spec.js +427 -0
- package/lib/__spec__/core/generating-class-docs.spec.js.map +1 -0
- package/lib/__spec__/core/generating-enum-docs.spec.d.ts +1 -0
- package/lib/__spec__/core/generating-enum-docs.spec.js +303 -0
- package/lib/__spec__/core/generating-enum-docs.spec.js.map +1 -0
- package/lib/__spec__/core/generating-interface-docs.spec.d.ts +1 -0
- package/lib/__spec__/core/generating-interface-docs.spec.js +361 -0
- package/lib/__spec__/core/generating-interface-docs.spec.js.map +1 -0
- package/lib/__spec__/core/generating-reference-guide.spec.d.ts +1 -0
- package/lib/__spec__/core/generating-reference-guide.spec.js +161 -0
- package/lib/__spec__/core/generating-reference-guide.spec.js.map +1 -0
- package/lib/adapters/apex-types.d.ts +7 -5
- package/lib/adapters/apex-types.js +99 -21
- package/lib/adapters/apex-types.js.map +1 -1
- package/lib/adapters/documentables.d.ts +4 -3
- package/lib/adapters/documentables.js +23 -8
- package/lib/adapters/documentables.js.map +1 -1
- package/lib/adapters/fields-and-properties.d.ts +4 -3
- package/lib/adapters/fields-and-properties.js +26 -4
- package/lib/adapters/fields-and-properties.js.map +1 -1
- package/lib/adapters/methods-and-constructors.d.ts +4 -3
- package/lib/adapters/methods-and-constructors.js +52 -9
- package/lib/adapters/methods-and-constructors.js.map +1 -1
- package/lib/adapters/references.d.ts +1 -1
- package/lib/adapters/references.js +3 -3
- package/lib/adapters/references.js.map +1 -1
- package/lib/adapters/type-utils.d.ts +1 -1
- package/lib/adapters/type-utils.js +1 -2
- package/lib/adapters/type-utils.js.map +1 -1
- package/lib/application/Apexdocs.js.map +1 -1
- package/lib/cli/generate.js +7 -7
- package/lib/cli/generate.js.map +1 -1
- package/lib/core/generate-docs.d.ts +23 -0
- package/lib/core/generate-docs.js +241 -0
- package/lib/core/generate-docs.js.map +1 -0
- package/lib/core/template.d.ts +10 -0
- package/lib/core/template.js +92 -0
- package/lib/core/template.js.map +1 -0
- package/lib/core/templates/reference-guide.d.ts +1 -0
- package/lib/core/templates/reference-guide.js +18 -0
- package/lib/core/templates/reference-guide.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +14 -3
- package/lib/index.js.map +1 -1
- package/lib/model/manifest.js +8 -2
- package/lib/model/manifest.js.map +1 -1
- package/lib/model/markdown-file.d.ts +2 -2
- package/lib/model/markdown-file.js +5 -4
- package/lib/model/markdown-file.js.map +1 -1
- package/lib/model/markdown-generation-util/doc-comment-annotation-util.js +3 -4
- package/lib/model/markdown-generation-util/doc-comment-annotation-util.js.map +1 -1
- package/lib/model/markdown-generation-util/field-declaration-util.js +1 -2
- package/lib/model/markdown-generation-util/field-declaration-util.js.map +1 -1
- package/lib/model/markdown-generation-util/method-declaration-util.js +2 -3
- package/lib/model/markdown-generation-util/method-declaration-util.js.map +1 -1
- package/lib/model/markdown-generation-util/type-declaration-util.js +1 -2
- package/lib/model/markdown-generation-util/type-declaration-util.js.map +1 -1
- package/lib/model/markdown-home-file.js.map +1 -1
- package/lib/model/markdown-type-file.js.map +1 -1
- package/lib/model/openapi/open-api.js.map +1 -1
- package/lib/model/outputFile.d.ts +1 -1
- package/lib/model/outputFile.js +2 -9
- package/lib/model/outputFile.js.map +1 -1
- package/lib/model/types-repository.js.map +1 -1
- package/lib/service/apex-file-reader.js.map +1 -1
- package/lib/service/file-writer.js.map +1 -1
- package/lib/service/manifest-factory.js +1 -2
- package/lib/service/manifest-factory.js.map +1 -1
- package/lib/service/metadata-processor.js.map +1 -1
- package/lib/service/parser.js +1 -1
- package/lib/service/parser.js.map +1 -1
- package/lib/service/state.js.map +1 -1
- package/lib/service/walkers/class-walker.js.map +1 -1
- package/lib/service/walkers/interface-walker.js.map +1 -1
- package/lib/service/walkers/walker-factory.js.map +1 -1
- package/lib/service/walkers/walker.js.map +1 -1
- package/lib/settings.d.ts +0 -6
- package/lib/settings.js +0 -11
- package/lib/settings.js.map +1 -1
- package/lib/transpiler/factory.js.map +1 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.d.ts +1 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.js.map +1 -1
- package/lib/transpiler/markdown/jekyll/jekyll-docsProcessor.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/class-template.js +51 -10
- package/lib/transpiler/markdown/plain-markdown/class-template.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/constructors-partial-template.js +13 -16
- package/lib/transpiler/markdown/plain-markdown/constructors-partial-template.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/documentable-partial-template.js +11 -8
- package/lib/transpiler/markdown/plain-markdown/documentable-partial-template.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/enum-template.js +7 -6
- package/lib/transpiler/markdown/plain-markdown/enum-template.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/fieldsPartialTemplate.js +9 -6
- package/lib/transpiler/markdown/plain-markdown/fieldsPartialTemplate.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/grouped-members-partial-template.d.ts +1 -0
- package/lib/transpiler/markdown/plain-markdown/grouped-members-partial-template.js +10 -0
- package/lib/transpiler/markdown/plain-markdown/grouped-members-partial-template.js.map +1 -0
- package/lib/transpiler/markdown/plain-markdown/interface-template.js +4 -4
- package/lib/transpiler/markdown/plain-markdown/methods-partial-template.js +18 -20
- package/lib/transpiler/markdown/plain-markdown/methods-partial-template.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/plain-docsProcessor.d.ts +0 -4
- package/lib/transpiler/markdown/plain-markdown/plain-docsProcessor.js +6 -86
- package/lib/transpiler/markdown/plain-markdown/plain-docsProcessor.js.map +1 -1
- package/lib/transpiler/markdown/plain-markdown/type-doc-partial.d.ts +1 -0
- package/lib/transpiler/markdown/plain-markdown/type-doc-partial.js +31 -0
- package/lib/transpiler/markdown/plain-markdown/type-doc-partial.js.map +1 -0
- package/lib/transpiler/openapi/open-api-docs-processor.js.map +1 -1
- package/lib/transpiler/openapi/parsers/Builder.js.map +1 -1
- package/lib/transpiler/openapi/parsers/MethodParser.js.map +1 -1
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js +3 -2
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js.map +1 -1
- package/lib/transpiler/openapi/parsers/ResponsesBuilder.js.map +1 -1
- package/lib/transpiler/transpiler.js.map +1 -1
- package/lib/util/error-logger.js.map +1 -1
- package/lib/util/logger.js.map +1 -1
- package/lib/util/string-utils.js +2 -2
- package/lib/util/string-utils.js.map +1 -1
- package/package.json +19 -19
- package/src/__spec__/core/expect-extensions.ts +32 -0
- package/src/__spec__/core/generating-class-docs.spec.ts +511 -0
- package/src/__spec__/core/generating-enum-docs.spec.ts +355 -0
- package/src/__spec__/core/generating-interface-docs.spec.ts +431 -0
- package/src/__spec__/core/generating-reference-guide.spec.ts +163 -0
- package/src/adapters/__tests__/interface-adapter.spec.ts +15 -11
- package/src/adapters/__tests__/references.spec.ts +1 -1
- package/src/adapters/apex-types.ts +196 -39
- package/src/adapters/documentables.ts +44 -9
- package/src/adapters/fields-and-properties.ts +31 -7
- package/src/adapters/methods-and-constructors.ts +57 -18
- package/src/adapters/references.ts +1 -1
- package/src/adapters/type-utils.ts +1 -1
- package/src/cli/generate.ts +96 -96
- package/src/core/generate-docs.ts +357 -0
- package/src/core/renderable/types.d.ts +131 -0
- package/src/core/template.ts +108 -0
- package/src/core/templates/reference-guide.ts +14 -0
- package/src/index.ts +3 -1
- package/src/model/manifest.ts +12 -2
- package/src/model/markdown-file.ts +5 -4
- package/src/model/markdown-generation-util/doc-comment-annotation-util.ts +1 -1
- package/src/model/markdown-generation-util/method-declaration-util.ts +1 -1
- package/src/model/outputFile.ts +2 -11
- package/src/service/parser.ts +1 -1
- package/src/settings.ts +0 -15
- package/src/transpiler/markdown/class-file-generatorHelper.ts +1 -1
- package/src/transpiler/markdown/plain-markdown/class-template.ts +51 -10
- package/src/transpiler/markdown/plain-markdown/constructors-partial-template.ts +13 -16
- package/src/transpiler/markdown/plain-markdown/documentable-partial-template.ts +11 -8
- package/src/transpiler/markdown/plain-markdown/enum-template.ts +7 -6
- package/src/transpiler/markdown/plain-markdown/fieldsPartialTemplate.ts +9 -6
- package/src/transpiler/markdown/plain-markdown/grouped-members-partial-template.ts +6 -0
- package/src/transpiler/markdown/plain-markdown/interface-template.ts +4 -4
- package/src/transpiler/markdown/plain-markdown/methods-partial-template.ts +18 -20
- package/src/transpiler/markdown/plain-markdown/plain-docsProcessor.ts +8 -100
- package/src/transpiler/markdown/plain-markdown/type-doc-partial.ts +27 -0
- package/src/transpiler/openapi/parsers/ReferenceBuilder.ts +3 -2
- package/tsconfig.json +1 -1
- package/.eslintrc.js +0 -12
- package/examples/plain-markdown/README.md +0 -301
- package/lib/templating/compile.d.ts +0 -7
- package/lib/templating/compile.js +0 -98
- package/lib/templating/compile.js.map +0 -1
- package/lib/templating/helpers.d.ts +0 -2
- package/lib/templating/helpers.js +0 -18
- package/lib/templating/helpers.js.map +0 -1
- package/lib/transpiler/markdown/plain-markdown/type-level-apex-doc-partial-template.d.ts +0 -1
- package/lib/transpiler/markdown/plain-markdown/type-level-apex-doc-partial-template.js +0 -31
- package/lib/transpiler/markdown/plain-markdown/type-level-apex-doc-partial-template.js.map +0 -1
- package/src/templating/__tests__/compile.spec.ts +0 -741
- package/src/templating/compile.ts +0 -187
- package/src/templating/helpers.ts +0 -14
- package/src/templating/types.d.ts +0 -104
- package/src/transpiler/markdown/plain-markdown/type-level-apex-doc-partial-template.ts +0 -27
package/src/cli/generate.ts
CHANGED
|
@@ -9,99 +9,102 @@ import { cosmiconfig } from 'cosmiconfig';
|
|
|
9
9
|
const result = cosmiconfig('apexdocs').search();
|
|
10
10
|
result.then((config) => {
|
|
11
11
|
yargs.config(config?.config);
|
|
12
|
-
let argv = yargs
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
'
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
12
|
+
let argv = yargs
|
|
13
|
+
.options({
|
|
14
|
+
sourceDir: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
alias: 's',
|
|
17
|
+
demandOption: true,
|
|
18
|
+
describe: 'The directory location which contains your apex .cls classes.',
|
|
19
|
+
},
|
|
20
|
+
targetDir: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
alias: 't',
|
|
23
|
+
default: './docs/',
|
|
24
|
+
describe: 'The directory location where documentation will be generated to.',
|
|
25
|
+
},
|
|
26
|
+
recursive: {
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
alias: 'r',
|
|
29
|
+
default: true,
|
|
30
|
+
describe: 'Whether .cls classes will be searched for recursively in the directory provided.',
|
|
31
|
+
},
|
|
32
|
+
scope: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
array: true,
|
|
35
|
+
alias: 'p',
|
|
36
|
+
default: ['global'],
|
|
37
|
+
describe:
|
|
38
|
+
'A list of scopes to document. Values should be separated by a space, e.g --scope global public namespaceaccessible. ' +
|
|
39
|
+
'Annotations are supported and should be passed lowercased and without the @ symbol, e.g. namespaceaccessible auraenabled. ' +
|
|
40
|
+
'Note that this setting is ignored if generating an OpenApi REST specification since that looks for classes annotated with @RestResource.',
|
|
41
|
+
},
|
|
42
|
+
targetGenerator: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
alias: 'g',
|
|
45
|
+
default: 'jekyll',
|
|
46
|
+
choices: ['jekyll', 'docsify', 'plain-markdown', 'openapi'],
|
|
47
|
+
describe:
|
|
48
|
+
'Define the static file generator for which the documents will be created. ' +
|
|
49
|
+
'Currently supports jekyll, docsify, plain markdown, and OpenAPI v3.1.0.',
|
|
50
|
+
},
|
|
51
|
+
indexOnly: {
|
|
52
|
+
type: 'boolean',
|
|
53
|
+
default: false,
|
|
54
|
+
describe: 'Defines whether only the index file should be generated.',
|
|
55
|
+
},
|
|
56
|
+
defaultGroupName: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
default: 'Miscellaneous',
|
|
59
|
+
describe: 'Defines the @group name to be used when a file does not specify it.',
|
|
60
|
+
},
|
|
61
|
+
sanitizeHtml: {
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
default: true,
|
|
64
|
+
describe:
|
|
65
|
+
'When on, any special character within your ApexDocs is converted into its HTML code representation. ' +
|
|
66
|
+
'This is specially useful when generic objects are described within the docs, e.g. "List< Foo>", "Map<Foo, Bar>" ' +
|
|
67
|
+
'because otherwise the content within < and > would be treated as HTML tags and not shown in the output. ' +
|
|
68
|
+
'Content in @example blocks are never sanitized.',
|
|
69
|
+
},
|
|
70
|
+
openApiTitle: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
default: 'Apex REST Api',
|
|
73
|
+
describe: 'If using "openapi" as the target generator, this allows you to specify the OpenApi title value.',
|
|
74
|
+
},
|
|
75
|
+
title: {
|
|
76
|
+
type: 'string',
|
|
77
|
+
describe: "If this allows you to specify the title of the generated documentation's home file.",
|
|
78
|
+
default: 'Classes',
|
|
79
|
+
},
|
|
80
|
+
namespace: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
describe:
|
|
83
|
+
'The package namespace, if any. If this value is provided the namespace will be added as a prefix to all of the parsed files. ' +
|
|
84
|
+
"If generating an OpenApi definition, it will be added to the file's Server Url.",
|
|
85
|
+
},
|
|
86
|
+
openApiFileName: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
describe: 'If using "openapi" as the target generator, this allows you to specify the name of the output file.',
|
|
89
|
+
default: 'openapi',
|
|
90
|
+
},
|
|
91
|
+
sortMembersAlphabetically: {
|
|
92
|
+
type: 'boolean',
|
|
93
|
+
describe: 'Whether to sort members alphabetically.',
|
|
94
|
+
default: false,
|
|
95
|
+
},
|
|
96
|
+
includeMetadata: {
|
|
97
|
+
type: 'boolean',
|
|
98
|
+
describe: "Whether to include the file's meta.xml information: Whether it is active and and the API version",
|
|
99
|
+
default: false,
|
|
100
|
+
},
|
|
101
|
+
documentationRootDir: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
describe:
|
|
104
|
+
'Allows you to specify the root documentation directory where the files are being generated. This can be helpful when embedding the generated docs into an existing site so that the links are generated correctly.',
|
|
105
|
+
},
|
|
106
|
+
})
|
|
107
|
+
.parseSync();
|
|
105
108
|
|
|
106
109
|
if (config) {
|
|
107
110
|
argv = { ...config.config, ...argv };
|
|
@@ -126,9 +129,6 @@ result.then((config) => {
|
|
|
126
129
|
onAfterProcess: config?.config?.onAfterProcess,
|
|
127
130
|
onBeforeFileWrite: config?.config?.onBeforeFileWrite,
|
|
128
131
|
frontMatterHeader: config?.config?.frontMatterHeader,
|
|
129
|
-
singleFile: config?.config?.singleFile,
|
|
130
|
-
fileName: config?.config?.fileName,
|
|
131
|
-
templateFilePath: config?.config?.templateFilePath,
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
try {
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { ClassMirror, InterfaceMirror, reflect as mirrorReflection, Type } from '@cparra/apex-reflection';
|
|
2
|
+
import { typeToRenderableType } from '../adapters/apex-types';
|
|
3
|
+
import { Renderable, RenderableContent, RenderableEnum, StringOrLink } from './renderable/types';
|
|
4
|
+
import { classMarkdownTemplate } from '../transpiler/markdown/plain-markdown/class-template';
|
|
5
|
+
import { enumMarkdownTemplate } from '../transpiler/markdown/plain-markdown/enum-template';
|
|
6
|
+
import { interfaceMarkdownTemplate } from '../transpiler/markdown/plain-markdown/interface-template';
|
|
7
|
+
import * as E from 'fp-ts/Either';
|
|
8
|
+
import { flow, pipe } from 'fp-ts/function';
|
|
9
|
+
import { CompilationRequest, Template } from './template';
|
|
10
|
+
import Manifest from '../model/manifest';
|
|
11
|
+
import { referenceGuideTemplate } from './templates/reference-guide';
|
|
12
|
+
import { adaptDescribable } from '../adapters/documentables';
|
|
13
|
+
|
|
14
|
+
export const documentType = flow(typeToRenderableType, resolveApexTypeTemplate, compile);
|
|
15
|
+
|
|
16
|
+
export type DocumentationBundle = {
|
|
17
|
+
format: 'markdown';
|
|
18
|
+
referenceGuide: string; // Output file with links to all other files (e.g. index/table of contents)
|
|
19
|
+
docs: DocOutput[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type DocumentationConfig = {
|
|
23
|
+
scope: string[];
|
|
24
|
+
outputDir: string;
|
|
25
|
+
namespace?: string;
|
|
26
|
+
sortMembersAlphabetically?: boolean;
|
|
27
|
+
defaultGroupName: string;
|
|
28
|
+
referenceGuideTemplate: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type DocOutput = {
|
|
32
|
+
docContents: string;
|
|
33
|
+
typeName: string;
|
|
34
|
+
type: 'class' | 'interface' | 'enum';
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const configDefaults: DocumentationConfig = {
|
|
38
|
+
scope: ['public'],
|
|
39
|
+
outputDir: 'docs',
|
|
40
|
+
defaultGroupName: 'Miscellaneous',
|
|
41
|
+
referenceGuideTemplate: referenceGuideTemplate,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export function generateDocs(
|
|
45
|
+
input: string[],
|
|
46
|
+
config?: Partial<DocumentationConfig>,
|
|
47
|
+
): E.Either<string[], DocumentationBundle> {
|
|
48
|
+
const configWithDefaults = { ...configDefaults, ...config };
|
|
49
|
+
return pipe(
|
|
50
|
+
input,
|
|
51
|
+
(input) => input.map(reflectSourceBody),
|
|
52
|
+
checkForReflectionErrors,
|
|
53
|
+
E.map((types) => types.map((type) => addInheritedMembers(type, types))),
|
|
54
|
+
E.map((types) => filterTypesOutOfScope(types, configWithDefaults.scope)),
|
|
55
|
+
E.map((types) => typesToRenderableBundle(types, configWithDefaults)),
|
|
56
|
+
E.map(({ references, renderables }) => ({
|
|
57
|
+
referenceGuide: pipe(referencesToReferenceGuide(references, configWithDefaults.referenceGuideTemplate)),
|
|
58
|
+
docs: renderables.map(renderableToOutputDoc),
|
|
59
|
+
})),
|
|
60
|
+
E.map(({ referenceGuide, docs }) => ({ format: 'markdown', referenceGuide: referenceGuide, docs })),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type ReferenceGuideReference = {
|
|
65
|
+
title: StringOrLink;
|
|
66
|
+
description: RenderableContent[] | undefined;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type RenderableBundle = {
|
|
70
|
+
// References are grouped by their defined @group annotation
|
|
71
|
+
references: {
|
|
72
|
+
[key: string]: ReferenceGuideReference[];
|
|
73
|
+
};
|
|
74
|
+
renderables: Renderable[];
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
function typesToRenderableBundle(types: Type[], config: DocumentationConfig) {
|
|
78
|
+
return types.reduce<RenderableBundle>(
|
|
79
|
+
(acc, type) => {
|
|
80
|
+
const renderable = typeToRenderableType(
|
|
81
|
+
type,
|
|
82
|
+
(referenceName) => {
|
|
83
|
+
return linkFromTypeNameGenerator(type, types, referenceName, config);
|
|
84
|
+
},
|
|
85
|
+
config.namespace,
|
|
86
|
+
);
|
|
87
|
+
acc.renderables.push(renderable);
|
|
88
|
+
|
|
89
|
+
const descriptionLines = type.docComment?.descriptionLines;
|
|
90
|
+
const reference = {
|
|
91
|
+
title: getLinkFromRoot(config, type),
|
|
92
|
+
description: adaptDescribable(descriptionLines, (referenceName) => {
|
|
93
|
+
const type = findType(types, referenceName);
|
|
94
|
+
return type ? getLinkFromRoot(config, type) : referenceName;
|
|
95
|
+
}).description,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const group = getTypeGroup(type, config);
|
|
99
|
+
if (!acc.references[group]) {
|
|
100
|
+
acc.references[group] = [];
|
|
101
|
+
}
|
|
102
|
+
acc.references[group].push(reference);
|
|
103
|
+
|
|
104
|
+
return acc;
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
references: {},
|
|
108
|
+
renderables: [],
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function renderableToOutputDoc(renderable: Renderable): DocOutput {
|
|
114
|
+
function buildDocOutput(renderable: Renderable, docContents: string): DocOutput {
|
|
115
|
+
return {
|
|
116
|
+
docContents,
|
|
117
|
+
typeName: renderable.name,
|
|
118
|
+
type: renderable.type,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return pipe(renderable, resolveApexTypeTemplate, compile, (docContents) => buildDocOutput(renderable, docContents));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function referencesToReferenceGuide(
|
|
126
|
+
references: { [key: string]: ReferenceGuideReference[] },
|
|
127
|
+
template: string,
|
|
128
|
+
): string {
|
|
129
|
+
function alphabetizeReferences(references: { [key: string]: ReferenceGuideReference[] }): {
|
|
130
|
+
[key: string]: ReferenceGuideReference[];
|
|
131
|
+
} {
|
|
132
|
+
return Object.keys(references)
|
|
133
|
+
.sort((a, b) => a.localeCompare(b))
|
|
134
|
+
.reduce<{ [key: string]: ReferenceGuideReference[] }>((acc, key) => {
|
|
135
|
+
acc[key] = references[key].sort((a, b) => a.title.toString().localeCompare(b.title.toString()));
|
|
136
|
+
return acc;
|
|
137
|
+
}, {});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return pipe(references, alphabetizeReferences, (references) =>
|
|
141
|
+
compile({
|
|
142
|
+
template: template,
|
|
143
|
+
source: references,
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function filterTypesOutOfScope(types: Type[], scope: string[]): Type[] {
|
|
149
|
+
return new Manifest(types).filteredByAccessModifierAndAnnotations(scope);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function checkForReflectionErrors(reflectionResult: E.Either<string, Type>[]) {
|
|
153
|
+
function reduceReflectionResultIntoSingleEither(results: E.Either<string, Type>[]): {
|
|
154
|
+
errors: string[];
|
|
155
|
+
types: Type[];
|
|
156
|
+
} {
|
|
157
|
+
return results.reduce<{ errors: string[]; types: Type[] }>(
|
|
158
|
+
(acc, result) => {
|
|
159
|
+
E.isLeft(result) ? acc.errors.push(result.left) : acc.types.push(result.right);
|
|
160
|
+
return acc;
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
errors: [],
|
|
164
|
+
types: [],
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return pipe(reflectionResult, reduceReflectionResultIntoSingleEither, ({ errors, types }) =>
|
|
170
|
+
errors.length ? E.left(errors) : E.right(types),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function reflectSourceBody(input: string): E.Either<string, Type> {
|
|
175
|
+
const result = mirrorReflection(input);
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
177
|
+
return result.error ? E.left(result.error.message) : E.right(result.typeMirror!);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function resolveApexTypeTemplate(renderable: Renderable): CompilationRequest {
|
|
181
|
+
function getTemplate(renderable: Renderable): string {
|
|
182
|
+
switch (renderable.type) {
|
|
183
|
+
case 'enum':
|
|
184
|
+
return enumMarkdownTemplate;
|
|
185
|
+
case 'interface':
|
|
186
|
+
return interfaceMarkdownTemplate;
|
|
187
|
+
case 'class':
|
|
188
|
+
return classMarkdownTemplate;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
template: getTemplate(renderable),
|
|
194
|
+
source: renderable as RenderableEnum,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function compile(request: CompilationRequest): string {
|
|
199
|
+
return Template.getInstance().compile(request);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function findType(repository: Type[], referenceName: string) {
|
|
203
|
+
return repository.find((currentType: Type) => currentType.name.toLowerCase() === referenceName.toLowerCase());
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function addInheritedMembers<T extends Type>(current: T, repository: Type[]): T {
|
|
207
|
+
if (current.type_name === 'enum') {
|
|
208
|
+
return current;
|
|
209
|
+
} else if (current.type_name === 'interface') {
|
|
210
|
+
return addInheritedInterfaceMethods(current as InterfaceMirror, repository) as T;
|
|
211
|
+
} else {
|
|
212
|
+
return addInheritedClassMembers(current as ClassMirror, repository) as T;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getParents<T extends Type>(
|
|
217
|
+
extendedNamesExtractor: (current: T) => string[],
|
|
218
|
+
current: T,
|
|
219
|
+
repository: Type[],
|
|
220
|
+
): T[] {
|
|
221
|
+
return pipe(
|
|
222
|
+
extendedNamesExtractor(current),
|
|
223
|
+
(interfaces: string[]) => interfaces.map((interfaceName) => repository.find((type) => type.name === interfaceName)),
|
|
224
|
+
(interfaces = []) => interfaces.filter((type) => type !== undefined) as T[],
|
|
225
|
+
(interfaces) =>
|
|
226
|
+
interfaces.reduce<T[]>(
|
|
227
|
+
(acc, current) => [...acc, ...getParents(extendedNamesExtractor, current, repository)],
|
|
228
|
+
interfaces,
|
|
229
|
+
),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function addInheritedInterfaceMethods(interfaceMirror: InterfaceMirror, repository: Type[]): InterfaceMirror {
|
|
234
|
+
function methodAlreadyExists(memberName: string, members: { name: string }[]) {
|
|
235
|
+
return members.some((member) => member.name.toLowerCase() === memberName.toLowerCase());
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function parentExtractor(interfaceMirror: InterfaceMirror): string[] {
|
|
239
|
+
return interfaceMirror.extended_interfaces;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const parents = getParents(parentExtractor, interfaceMirror, repository);
|
|
243
|
+
return {
|
|
244
|
+
...interfaceMirror,
|
|
245
|
+
methods: parents.reduce(
|
|
246
|
+
(acc, currentValue) => [
|
|
247
|
+
...acc,
|
|
248
|
+
...currentValue.methods
|
|
249
|
+
.filter((method) => !methodAlreadyExists(method.name, acc))
|
|
250
|
+
.map((method) => ({
|
|
251
|
+
...method,
|
|
252
|
+
inherited: true,
|
|
253
|
+
})),
|
|
254
|
+
],
|
|
255
|
+
interfaceMirror.methods,
|
|
256
|
+
),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function addInheritedClassMembers(classMirror: ClassMirror, repository: Type[]): ClassMirror {
|
|
261
|
+
function memberAlreadyExists(memberName: string, members: { name: string }[]) {
|
|
262
|
+
return members.some((member) => member.name.toLowerCase() === memberName.toLowerCase());
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function parentExtractor(classMirror: ClassMirror): string[] {
|
|
266
|
+
return classMirror.extended_class ? [classMirror.extended_class] : [];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function filterMember<T extends { name: string; access_modifier: string }>(members: T[], existing: T[]): T[] {
|
|
270
|
+
return members
|
|
271
|
+
.filter((member) => member.access_modifier.toLowerCase() !== 'private')
|
|
272
|
+
.filter((member) => !memberAlreadyExists(member.name, existing))
|
|
273
|
+
.map((member) => ({
|
|
274
|
+
...member,
|
|
275
|
+
inherited: true,
|
|
276
|
+
}));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const parents = getParents(parentExtractor, classMirror, repository);
|
|
280
|
+
return {
|
|
281
|
+
...classMirror,
|
|
282
|
+
fields: parents.reduce(
|
|
283
|
+
(acc, currentValue) => [...acc, ...filterMember(currentValue.fields, acc)],
|
|
284
|
+
classMirror.fields,
|
|
285
|
+
),
|
|
286
|
+
properties: parents.reduce(
|
|
287
|
+
(acc, currentValue) => [...acc, ...filterMember(currentValue.properties, acc)],
|
|
288
|
+
classMirror.properties,
|
|
289
|
+
),
|
|
290
|
+
methods: parents.reduce(
|
|
291
|
+
(acc, currentValue) => [...acc, ...filterMember(currentValue.methods, acc)],
|
|
292
|
+
classMirror.methods,
|
|
293
|
+
),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function linkFromTypeNameGenerator(
|
|
298
|
+
typeBeingDocumented: Type,
|
|
299
|
+
repository: Type[],
|
|
300
|
+
referenceName: string,
|
|
301
|
+
config: DocumentationConfig,
|
|
302
|
+
): StringOrLink {
|
|
303
|
+
const type = findType(repository, referenceName);
|
|
304
|
+
if (!type) {
|
|
305
|
+
// If the type is not found, we return the type name as a string.
|
|
306
|
+
return referenceName;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const [fullClassName, fileLink] = getFileLinkTuple(typeBeingDocumented, type, config);
|
|
310
|
+
return {
|
|
311
|
+
title: fullClassName,
|
|
312
|
+
url: fileLink,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function getFileLinkTuple(
|
|
317
|
+
typeBeingDocumented: Type,
|
|
318
|
+
referencedType: Type,
|
|
319
|
+
config: DocumentationConfig,
|
|
320
|
+
): [string, string] {
|
|
321
|
+
const namespacePrefix = config.namespace ? `${config.namespace}.` : '';
|
|
322
|
+
const directoryRoot = `${getDirectoryRoot(typeBeingDocumented, referencedType, config)}`;
|
|
323
|
+
// TODO: Instead of adding a "." to the name when there is a namespace, maybe we want to create a folder for everything
|
|
324
|
+
// within that namespace and put the files in there.
|
|
325
|
+
const fullClassName = `${namespacePrefix}${referencedType.name}`;
|
|
326
|
+
return [fullClassName, `${directoryRoot}${fullClassName}.md`];
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function getLinkFromRoot(config: DocumentationConfig, type?: Type): StringOrLink {
|
|
330
|
+
if (!type) {
|
|
331
|
+
return '';
|
|
332
|
+
}
|
|
333
|
+
const namespacePrefix = config.namespace ? `${config.namespace}./` : '';
|
|
334
|
+
return {
|
|
335
|
+
title: `${namespacePrefix}${type.name}`,
|
|
336
|
+
url: `./${namespacePrefix}${getSanitizedGroup(type, config)}/${type.name}.md`,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function getDirectoryRoot(typeBeingDocumented: Type, referencedType: Type, config: DocumentationConfig) {
|
|
341
|
+
if (getTypeGroup(typeBeingDocumented, config) === getTypeGroup(referencedType, config)) {
|
|
342
|
+
// If the types the same groups then we simply link directly to that file
|
|
343
|
+
return './';
|
|
344
|
+
} else {
|
|
345
|
+
// If the types have different groups, then we have to go up a directory
|
|
346
|
+
return `../${getSanitizedGroup(referencedType, config)}/`;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function getTypeGroup(type: Type, config: DocumentationConfig): string {
|
|
351
|
+
const groupAnnotation = type.docComment?.annotations.find((annotation) => annotation.name.toLowerCase() === 'group');
|
|
352
|
+
return groupAnnotation?.body ?? config.defaultGroupName;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function getSanitizedGroup(classModel: Type, config: DocumentationConfig) {
|
|
356
|
+
return getTypeGroup(classModel, config).replace(/ /g, '-').replace('.', '');
|
|
357
|
+
}
|