@cparra/apexdocs 3.0.0-beta.1 → 3.0.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/LICENSE +1 -1
- package/README.md +246 -650
- package/dist/cli/generate.js +74 -3095
- package/dist/defaults-BcE8DTat.js +13 -0
- package/dist/defaults-D07y_bq4.js +40 -0
- package/dist/defaults-gPzwP66p.js +14 -0
- package/dist/index.d.ts +49 -19
- package/dist/index.js +90 -2
- package/dist/logger-BEbUIfqN.js +3282 -0
- package/dist/logger-BGuf1PnL.js +3281 -0
- package/dist/logger-CWBRF2za.js +3284 -0
- package/dist/logger-CdBmDEN1.js +3283 -0
- package/dist/logger-Ce4QqPFR.js +3278 -0
- package/dist/logger-CyEVYaAC.js +3284 -0
- package/dist/logger-D7a83ycP.js +3277 -0
- package/dist/logger-DGaHeBKk.js +3279 -0
- package/dist/logger-Dqhl_lO_.js +3278 -0
- package/dist/logger-aySSWi0G.js +3280 -0
- package/dist/logger-qLCcAtiy.js +3284 -0
- package/examples/README.md +5 -0
- package/examples/docsify/README.md +17 -0
- package/examples/docsify/apexdocs.config.ts +13 -0
- package/examples/docsify/classes/ASampleClass.cls +57 -0
- package/examples/docsify/classes/CodeControl.cls +19 -0
- package/examples/docsify/classes/SampleClass.cls +95 -0
- package/examples/docsify/classes/SampleInterface.cls +17 -0
- package/examples/docsify/classes/SomeDto.cls +122 -0
- package/examples/docsify/docs/.nojekyll +0 -0
- package/examples/docsify/docs/README.md +25 -0
- package/examples/docsify/docs/_config.yml +1 -0
- package/examples/docsify/docs/index.html +22 -0
- package/examples/docsify/docs/miscellaneous/ASampleClass.md +88 -0
- package/examples/docsify/docs/miscellaneous/CodeControl.md +107 -0
- package/examples/docsify/docs/miscellaneous/SomeDto.md +244 -0
- package/examples/docsify/docs/sample-classes/SampleClass.md +171 -0
- package/examples/docsify/docs/sample-interfaces/SampleInterface.md +36 -0
- package/examples/docsify/package-lock.json +2459 -0
- package/examples/docsify/package.json +14 -0
- package/examples/imported/.forceignore +12 -0
- package/examples/imported/README.md +6 -0
- package/examples/imported/config/project-scratch-def.json +5 -0
- package/examples/imported/docs/index.md +109 -0
- package/examples/imported/docs/miscellaneous/BaseClass.md +13 -0
- package/examples/imported/docs/miscellaneous/MultiInheritanceClass.md +69 -0
- package/examples/imported/docs/miscellaneous/ParentInterface.md +12 -0
- package/examples/imported/docs/miscellaneous/ReferencedEnum.md +5 -0
- package/examples/imported/docs/miscellaneous/SampleException.md +21 -0
- package/examples/imported/docs/miscellaneous/SampleInterface.md +113 -0
- package/examples/imported/docs/miscellaneous/Url.md +308 -0
- package/examples/imported/docs/sample-enums/SampleEnum.md +33 -0
- package/examples/imported/docs/samplegroup/SampleClass.md +167 -0
- package/examples/imported/force-app/classes/BaseClass.cls +3 -0
- package/examples/imported/force-app/classes/MultiInheritanceClass.cls +1 -0
- package/examples/imported/force-app/classes/ParentInterface.cls +3 -0
- package/examples/imported/force-app/classes/ReferencedEnum.cls +3 -0
- package/examples/imported/force-app/classes/SampleInterface.cls +50 -0
- package/examples/imported/force-app/classes/Url.cls +196 -0
- package/examples/imported/package-lock.json +665 -0
- package/examples/imported/package.json +6 -0
- package/examples/imported/scripts/process-docs.mjs +16 -0
- package/examples/imported/sfdx-project.json +12 -0
- package/examples/markdown/README.md +7 -0
- package/examples/markdown/docs/miscellaneous/Url.md +10 -8
- package/examples/markdown/force-app/classes/Url.cls +3 -1
- package/examples/markdown-jsconfig/.forceignore +12 -0
- package/examples/markdown-jsconfig/README.md +9 -0
- package/examples/markdown-jsconfig/apexdocs.config.mjs +22 -0
- package/examples/markdown-jsconfig/config/project-scratch-def.json +5 -0
- package/examples/markdown-jsconfig/docs/index.md +12 -0
- package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +315 -0
- package/examples/markdown-jsconfig/force-app/classes/Url.cls +196 -0
- package/examples/markdown-jsconfig/package-lock.json +665 -0
- package/examples/markdown-jsconfig/package.json +15 -0
- package/examples/markdown-jsconfig/sfdx-project.json +12 -0
- package/examples/open-api/README.md +5 -0
- package/examples/open-api/docs/openapi.json +2 -570
- package/examples/vitepress/README.md +25 -0
- package/examples/vitepress/apexdocs.config.ts +9 -2
- package/examples/vitepress/docs/index.md +11 -11
- package/examples/vitepress/docs/miscellaneous/BaseClass.md +1 -1
- package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +2 -2
- package/examples/vitepress/docs/miscellaneous/SampleException.md +1 -1
- package/examples/vitepress/docs/miscellaneous/SampleInterface.md +6 -6
- package/examples/vitepress/docs/miscellaneous/Url.md +3 -3
- package/examples/vitepress/docs/sample-enums/SampleEnum.md +3 -3
- package/examples/vitepress/docs/samplegroup/SampleClass.md +5 -5
- package/examples/vitepress/force-app/main/default/classes/feature-a/SampleClass.cls +73 -0
- package/examples/vitepress/force-app/main/default/classes/feature-a/SampleEnum.cls +30 -0
- package/examples/vitepress/force-app/main/default/classes/feature-a/SampleException.cls +17 -0
- package/package.json +3 -3
- package/src/application/Apexdocs.ts +16 -19
- package/src/application/__tests__/apex-file-reader.spec.ts +108 -67
- package/src/application/apex-file-reader.ts +1 -0
- package/src/application/generators/openapi.ts +17 -13
- package/src/cli/args.ts +12 -3
- package/src/cli/commands/markdown.ts +15 -12
- package/src/cli/commands/openapi.ts +5 -5
- package/src/cli/generate.ts +20 -4
- package/src/core/markdown/__test__/generating-class-docs.spec.ts +15 -386
- package/src/core/markdown/__test__/generating-docs.spec.ts +378 -0
- package/src/core/markdown/__test__/generating-enum-docs.spec.ts +4 -328
- package/src/core/markdown/__test__/generating-interface-docs.spec.ts +4 -296
- package/src/core/markdown/__test__/generating-reference-guide.spec.ts +17 -1
- package/src/core/markdown/__test__/test-helpers.ts +3 -1
- package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +3 -1
- package/src/core/markdown/adapters/renderable-to-page-data.ts +6 -4
- package/src/core/markdown/generate-docs.ts +13 -15
- package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +290 -0
- package/src/core/markdown/reflection/__test__/helpers.ts +18 -0
- package/src/core/markdown/reflection/__test__/remove-excluded-tags.spec.ts +200 -0
- package/src/core/markdown/reflection/remove-excluded-tags.ts +168 -0
- package/src/core/markdown/reflection/{sort-members.ts → sort-types-and-members.ts} +7 -5
- package/src/core/markdown/templates/reference-guide.ts +2 -2
- package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +6 -3
- package/src/core/openapi/open-api-docs-processor.ts +3 -3
- package/src/core/openapi/parser.ts +5 -2
- package/src/core/shared/types.d.ts +18 -18
- package/src/defaults.ts +15 -3
- package/src/index.ts +88 -14
- package/src/util/error-logger.ts +36 -36
- package/src/util/logger.ts +18 -11
- /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleClass.cls +0 -0
- /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleEnum.cls +0 -0
- /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleException.cls +0 -0
- /package/examples/vitepress/force-app/main/default/classes/{SampleInterface.cls → feature-a/SampleInterface.cls} +0 -0
package/src/cli/args.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { cosmiconfig, CosmiconfigResult } from 'cosmiconfig';
|
|
2
2
|
import * as yargs from 'yargs';
|
|
3
|
-
import { UserDefinedMarkdownConfig } from '../core/shared/types';
|
|
3
|
+
import { UserDefinedConfig, UserDefinedMarkdownConfig } from '../core/shared/types';
|
|
4
4
|
import { TypeScriptLoader } from 'cosmiconfig-typescript-loader';
|
|
5
5
|
import { markdownOptions } from './commands/markdown';
|
|
6
6
|
import { openApiOptions } from './commands/openapi';
|
|
7
7
|
|
|
8
|
+
const configOnlyDefaults: Partial<UserDefinedMarkdownConfig> = {
|
|
9
|
+
excludeTags: [],
|
|
10
|
+
};
|
|
11
|
+
|
|
8
12
|
/**
|
|
9
13
|
* Extracts configuration from a configuration file or the package.json
|
|
10
14
|
* through cosmiconfig.
|
|
@@ -37,10 +41,15 @@ function _extractYargs(config?: CosmiconfigResult) {
|
|
|
37
41
|
/**
|
|
38
42
|
* Combines the extracted configuration and arguments.
|
|
39
43
|
*/
|
|
40
|
-
export async function extractArgs(): Promise<
|
|
44
|
+
export async function extractArgs(): Promise<UserDefinedConfig> {
|
|
41
45
|
const config = await _extractConfig();
|
|
42
46
|
const cliArgs = _extractYargs(config);
|
|
43
47
|
const commandName = cliArgs._[0];
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
const mergedConfig = { ...config?.config, ...cliArgs, targetGenerator: commandName as 'markdown' | 'openapi' };
|
|
50
|
+
if (mergedConfig.targetGenerator === 'markdown') {
|
|
51
|
+
return { ...configOnlyDefaults, ...mergedConfig };
|
|
52
|
+
} else {
|
|
53
|
+
return mergedConfig;
|
|
54
|
+
}
|
|
46
55
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Options } from 'yargs';
|
|
2
|
-
import {
|
|
2
|
+
import { markdownDefaults } from '../../defaults';
|
|
3
3
|
|
|
4
4
|
export const markdownOptions: { [key: string]: Options } = {
|
|
5
5
|
sourceDir: {
|
|
@@ -11,43 +11,46 @@ export const markdownOptions: { [key: string]: Options } = {
|
|
|
11
11
|
targetDir: {
|
|
12
12
|
type: 'string',
|
|
13
13
|
alias: 't',
|
|
14
|
-
default:
|
|
14
|
+
default: markdownDefaults.targetDir,
|
|
15
15
|
describe: 'The directory location where documentation will be generated to.',
|
|
16
16
|
},
|
|
17
17
|
scope: {
|
|
18
18
|
type: 'string',
|
|
19
19
|
array: true,
|
|
20
20
|
alias: 'p',
|
|
21
|
-
default:
|
|
21
|
+
default: markdownDefaults.scope,
|
|
22
22
|
describe:
|
|
23
23
|
'A list of scopes to document. Values should be separated by a space, e.g --scope global public namespaceaccessible. ' +
|
|
24
24
|
'Annotations are supported and should be passed lowercased and without the @ symbol, e.g. namespaceaccessible auraenabled.',
|
|
25
25
|
},
|
|
26
26
|
defaultGroupName: {
|
|
27
27
|
type: 'string',
|
|
28
|
-
default:
|
|
28
|
+
default: markdownDefaults.defaultGroupName,
|
|
29
29
|
describe: 'Defines the @group name to be used when a file does not specify it.',
|
|
30
30
|
},
|
|
31
31
|
namespace: {
|
|
32
32
|
type: 'string',
|
|
33
|
-
describe:
|
|
34
|
-
'The package namespace, if any. If this value is provided the namespace will be added as a prefix to all of the parsed files. ' +
|
|
35
|
-
"If generating an OpenApi definition, it will be added to the file's Server Url.",
|
|
33
|
+
describe: 'The package namespace, if any. If provided, it will be added to the generated files.',
|
|
36
34
|
},
|
|
37
|
-
|
|
35
|
+
sortAlphabetically: {
|
|
38
36
|
type: 'boolean',
|
|
39
|
-
describe: 'Whether to sort members alphabetically.',
|
|
40
|
-
default:
|
|
37
|
+
describe: 'Whether to sort files and members alphabetically.',
|
|
38
|
+
default: markdownDefaults.sortAlphabetically,
|
|
41
39
|
},
|
|
42
40
|
includeMetadata: {
|
|
43
41
|
type: 'boolean',
|
|
44
42
|
describe: "Whether to include the file's meta.xml information: Whether it is active and and the API version",
|
|
45
|
-
default:
|
|
43
|
+
default: markdownDefaults.includeMetadata,
|
|
46
44
|
},
|
|
47
45
|
linkingStrategy: {
|
|
48
46
|
type: 'string',
|
|
49
47
|
describe: 'The strategy to use when linking to other documentation pages.',
|
|
50
48
|
choices: ['relative', 'no-link', 'none'],
|
|
51
|
-
default:
|
|
49
|
+
default: markdownDefaults.linkingStrategy,
|
|
50
|
+
},
|
|
51
|
+
referenceGuideTitle: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
describe: 'The title of the reference guide.',
|
|
54
|
+
default: markdownDefaults.referenceGuideTitle,
|
|
52
55
|
},
|
|
53
56
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Options } from 'yargs';
|
|
2
|
-
import {
|
|
2
|
+
import { markdownDefaults, openApiDefaults } from '../../defaults';
|
|
3
3
|
|
|
4
4
|
export const openApiOptions: { [key: string]: Options } = {
|
|
5
5
|
sourceDir: {
|
|
@@ -11,12 +11,12 @@ export const openApiOptions: { [key: string]: Options } = {
|
|
|
11
11
|
targetDir: {
|
|
12
12
|
type: 'string',
|
|
13
13
|
alias: 't',
|
|
14
|
-
default:
|
|
14
|
+
default: markdownDefaults.targetDir,
|
|
15
15
|
describe: 'The directory location where the OpenApi file will be generated.',
|
|
16
16
|
},
|
|
17
17
|
fileName: {
|
|
18
18
|
type: 'string',
|
|
19
|
-
default:
|
|
19
|
+
default: openApiDefaults.fileName,
|
|
20
20
|
describe: 'The name of the OpenApi file to be generated.',
|
|
21
21
|
},
|
|
22
22
|
namespace: {
|
|
@@ -25,12 +25,12 @@ export const openApiOptions: { [key: string]: Options } = {
|
|
|
25
25
|
},
|
|
26
26
|
title: {
|
|
27
27
|
type: 'string',
|
|
28
|
-
default:
|
|
28
|
+
default: openApiDefaults.title,
|
|
29
29
|
describe: 'The title of the OpenApi file.',
|
|
30
30
|
},
|
|
31
31
|
apiVersion: {
|
|
32
32
|
type: 'string',
|
|
33
|
-
default:
|
|
33
|
+
default: openApiDefaults.apiVersion,
|
|
34
34
|
describe: 'The version of the OpenApi file.',
|
|
35
35
|
},
|
|
36
36
|
};
|
package/src/cli/generate.ts
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Apexdocs } from '../application/Apexdocs';
|
|
3
3
|
import { extractArgs } from './args';
|
|
4
|
+
import { StdOutLogger } from '#utils/logger';
|
|
5
|
+
import * as E from 'fp-ts/Either';
|
|
6
|
+
|
|
7
|
+
const logger = new StdOutLogger();
|
|
4
8
|
|
|
5
9
|
function main() {
|
|
6
|
-
function
|
|
7
|
-
|
|
10
|
+
function parseResult(result: E.Either<unknown, string>) {
|
|
11
|
+
E.match(
|
|
12
|
+
(error) => {
|
|
13
|
+
logger.error(`❌ An error occurred while generating the documentation: ${error}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
},
|
|
16
|
+
(successMessage: string) => {
|
|
17
|
+
logger.logSingle(successMessage);
|
|
18
|
+
},
|
|
19
|
+
)(result);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function catchUnexpectedError(error: Error) {
|
|
23
|
+
logger.error(`❌ An unexpected error occurred: ${error.message}`);
|
|
8
24
|
process.exit(1);
|
|
9
25
|
}
|
|
10
26
|
|
|
11
27
|
extractArgs()
|
|
12
|
-
.then((config) => Apexdocs.generate(config).
|
|
13
|
-
.catch(
|
|
28
|
+
.then((config) => Apexdocs.generate(config, logger).then(parseResult))
|
|
29
|
+
.catch(catchUnexpectedError);
|
|
14
30
|
}
|
|
15
31
|
|
|
16
32
|
main();
|
|
@@ -1,384 +1,11 @@
|
|
|
1
1
|
import { assertEither, extendExpect } from './expect-extensions';
|
|
2
2
|
import { apexBundleFromRawString, generateDocs } from './test-helpers';
|
|
3
3
|
|
|
4
|
-
describe('
|
|
4
|
+
describe('When generating documentation for a class', () => {
|
|
5
5
|
beforeAll(() => {
|
|
6
6
|
extendExpect();
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
describe('documentation output', () => {
|
|
10
|
-
it('returns the name of the class', async () => {
|
|
11
|
-
const input = 'public class MyClass {}';
|
|
12
|
-
|
|
13
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
14
|
-
expect(result).documentationBundleHasLength(1);
|
|
15
|
-
assertEither(result, (data) => expect(data.docs[0].outputDocPath).toContain('MyClass'));
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('returns the type as class', async () => {
|
|
19
|
-
const input = 'public class MyClass {}';
|
|
20
|
-
|
|
21
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
22
|
-
expect(result).documentationBundleHasLength(1);
|
|
23
|
-
assertEither(result, (data) => expect(data.docs[0].source.type).toBe('class'));
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('does not return classes out of scope', async () => {
|
|
27
|
-
const input1 = `
|
|
28
|
-
global class MyClass {}
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const input2 = `
|
|
32
|
-
public class AnotherClass {}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
|
|
36
|
-
scope: ['global'],
|
|
37
|
-
})();
|
|
38
|
-
expect(result).documentationBundleHasLength(1);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('does not return classes that have an @ignore in the docs', async () => {
|
|
42
|
-
const input = `
|
|
43
|
-
/**
|
|
44
|
-
* @ignore
|
|
45
|
-
*/
|
|
46
|
-
public class MyClass {}`;
|
|
47
|
-
|
|
48
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
49
|
-
expect(result).documentationBundleHasLength(0);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('does not return class methods that have @ignore in the docs', async () => {
|
|
53
|
-
const input = `
|
|
54
|
-
public class MyClass {
|
|
55
|
-
/**
|
|
56
|
-
* @ignore
|
|
57
|
-
*/
|
|
58
|
-
public void myMethod() {}
|
|
59
|
-
}`;
|
|
60
|
-
|
|
61
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
62
|
-
expect(result).documentationBundleHasLength(1);
|
|
63
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myMethod'));
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('does not return class properties that have @ignore in the docs', async () => {
|
|
67
|
-
const input = `
|
|
68
|
-
public class MyClass {
|
|
69
|
-
/**
|
|
70
|
-
* @ignore
|
|
71
|
-
*/
|
|
72
|
-
public String myProperty { get; set; }
|
|
73
|
-
}`;
|
|
74
|
-
|
|
75
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
76
|
-
expect(result).documentationBundleHasLength(1);
|
|
77
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myProperty'));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('does not return class fields that have @ignore in the docs', async () => {
|
|
81
|
-
const input = `
|
|
82
|
-
public class MyClass {
|
|
83
|
-
/**
|
|
84
|
-
* @ignore
|
|
85
|
-
*/
|
|
86
|
-
public String myField;
|
|
87
|
-
}`;
|
|
88
|
-
|
|
89
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
90
|
-
expect(result).documentationBundleHasLength(1);
|
|
91
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myField'));
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('does not return class inner classes that have @ignore in the docs', async () => {
|
|
95
|
-
const input = `
|
|
96
|
-
public class MyClass {
|
|
97
|
-
/**
|
|
98
|
-
* @ignore
|
|
99
|
-
*/
|
|
100
|
-
public class InnerClass {}
|
|
101
|
-
}`;
|
|
102
|
-
|
|
103
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
104
|
-
expect(result).documentationBundleHasLength(1);
|
|
105
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerClass'));
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('does not return class inner interfaces that have @ignore in the docs', async () => {
|
|
109
|
-
const input = `
|
|
110
|
-
public class MyClass {
|
|
111
|
-
/**
|
|
112
|
-
* @ignore
|
|
113
|
-
*/
|
|
114
|
-
public interface InnerInterface {}
|
|
115
|
-
}`;
|
|
116
|
-
|
|
117
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
118
|
-
expect(result).documentationBundleHasLength(1);
|
|
119
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerInterface'));
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('does not return class inner enums that have @ignore in the docs', async () => {
|
|
123
|
-
const input = `
|
|
124
|
-
public class MyClass {
|
|
125
|
-
/**
|
|
126
|
-
* @ignore
|
|
127
|
-
*/
|
|
128
|
-
public enum InnerEnum {}
|
|
129
|
-
}`;
|
|
130
|
-
|
|
131
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
132
|
-
expect(result).documentationBundleHasLength(1);
|
|
133
|
-
assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerEnum'));
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe('documentation content', () => {
|
|
138
|
-
describe('type level information', () => {
|
|
139
|
-
it('generates a heading with the class name', async () => {
|
|
140
|
-
const input = 'public class MyClass {}';
|
|
141
|
-
|
|
142
|
-
const output = `# MyClass Class`;
|
|
143
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
144
|
-
expect(result).documentationBundleHasLength(1);
|
|
145
|
-
assertEither(result, (data) => expect(data).firstDocContains(output));
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('displays type level annotations', async () => {
|
|
149
|
-
const input = `
|
|
150
|
-
@NamespaceAccessible
|
|
151
|
-
public class MyClass {
|
|
152
|
-
@Deprecated
|
|
153
|
-
public void myMethod() {}
|
|
154
|
-
}
|
|
155
|
-
`;
|
|
156
|
-
|
|
157
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
158
|
-
expect(result).documentationBundleHasLength(1);
|
|
159
|
-
assertEither(result, (data) => expect(data).firstDocContains('NAMESPACEACCESSIBLE'));
|
|
160
|
-
assertEither(result, (data) => expect(data).firstDocContains('DEPRECATED'));
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('displays metadata as annotations', async () => {
|
|
164
|
-
const input = 'public class MyClass {}';
|
|
165
|
-
const metadata = `
|
|
166
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
167
|
-
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
168
|
-
<apiVersion>59.0</apiVersion>
|
|
169
|
-
<status>Active</status>
|
|
170
|
-
</ApexClass>
|
|
171
|
-
`;
|
|
172
|
-
|
|
173
|
-
const result = await generateDocs([apexBundleFromRawString(input, metadata)])();
|
|
174
|
-
|
|
175
|
-
expect(result).documentationBundleHasLength(1);
|
|
176
|
-
assertEither(result, (data) => expect(data).firstDocContains('APIVERSION'));
|
|
177
|
-
assertEither(result, (data) => expect(data).firstDocContains('STATUS'));
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('displays the description', async () => {
|
|
181
|
-
const input = `
|
|
182
|
-
/**
|
|
183
|
-
* This is a description
|
|
184
|
-
*/
|
|
185
|
-
public class MyClass {}
|
|
186
|
-
`;
|
|
187
|
-
|
|
188
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
189
|
-
expect(result).documentationBundleHasLength(1);
|
|
190
|
-
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('display custom documentation tags', async () => {
|
|
194
|
-
const input = `
|
|
195
|
-
/**
|
|
196
|
-
* @custom-tag My Value
|
|
197
|
-
*/
|
|
198
|
-
public class MyClass {}
|
|
199
|
-
`;
|
|
200
|
-
|
|
201
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
202
|
-
expect(result).documentationBundleHasLength(1);
|
|
203
|
-
assertEither(result, (data) => expect(data).firstDocContains('Custom Tag'));
|
|
204
|
-
assertEither(result, (data) => expect(data).firstDocContains('My Value'));
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('displays the group', async () => {
|
|
208
|
-
const input = `
|
|
209
|
-
/**
|
|
210
|
-
* @group MyGroup
|
|
211
|
-
*/
|
|
212
|
-
public class MyClass {}`;
|
|
213
|
-
|
|
214
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
215
|
-
expect(result).documentationBundleHasLength(1);
|
|
216
|
-
assertEither(result, (data) => expect(data).firstDocContains('Group'));
|
|
217
|
-
assertEither(result, (data) => expect(data).firstDocContains('MyGroup'));
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('displays the author', async () => {
|
|
221
|
-
const input = `
|
|
222
|
-
/**
|
|
223
|
-
* @author John Doe
|
|
224
|
-
*/
|
|
225
|
-
public class MyClass {}`;
|
|
226
|
-
|
|
227
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
228
|
-
expect(result).documentationBundleHasLength(1);
|
|
229
|
-
assertEither(result, (data) => expect(data).firstDocContains('Author'));
|
|
230
|
-
assertEither(result, (data) => expect(data).firstDocContains('John Doe'));
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('displays the date', async () => {
|
|
234
|
-
const input = `
|
|
235
|
-
/**
|
|
236
|
-
* @date 2021-01-01
|
|
237
|
-
*/
|
|
238
|
-
public class MyClass {}`;
|
|
239
|
-
|
|
240
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
241
|
-
expect(result).documentationBundleHasLength(1);
|
|
242
|
-
assertEither(result, (data) => expect(data).firstDocContains('Date'));
|
|
243
|
-
assertEither(result, (data) => expect(data).firstDocContains('2021-01-01'));
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('displays descriptions', async () => {
|
|
247
|
-
const input = `
|
|
248
|
-
/**
|
|
249
|
-
* @description This is a description
|
|
250
|
-
*/
|
|
251
|
-
public class MyClass {}`;
|
|
252
|
-
|
|
253
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
254
|
-
expect(result).documentationBundleHasLength(1);
|
|
255
|
-
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('displays descriptions with links', async () => {
|
|
259
|
-
const input1 = `
|
|
260
|
-
/**
|
|
261
|
-
* @description This is a description with a {@link ClassRef} reference
|
|
262
|
-
*/
|
|
263
|
-
public enum MyClass {}
|
|
264
|
-
`;
|
|
265
|
-
|
|
266
|
-
const input2 = 'public class ClassRef {}';
|
|
267
|
-
|
|
268
|
-
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
269
|
-
expect(result).documentationBundleHasLength(2);
|
|
270
|
-
assertEither(result, (data) =>
|
|
271
|
-
expect(data).firstDocContains('This is a description with a [ClassRef](ClassRef.md) reference'),
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('displays descriptions with emails', async () => {
|
|
276
|
-
const input = `
|
|
277
|
-
/**
|
|
278
|
-
* @description This is a description with an {@email test@testerson.com} email
|
|
279
|
-
*/
|
|
280
|
-
public class MyClass {}
|
|
281
|
-
`;
|
|
282
|
-
|
|
283
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
284
|
-
expect(result).documentationBundleHasLength(1);
|
|
285
|
-
assertEither(result, (data) =>
|
|
286
|
-
expect(data).firstDocContains(
|
|
287
|
-
'This is a description with an [test@testerson.com](mailto:test@testerson.com) email',
|
|
288
|
-
),
|
|
289
|
-
);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('displays sees with accurately resolved links', async () => {
|
|
293
|
-
const input1 = `
|
|
294
|
-
/**
|
|
295
|
-
* @see ClassRef
|
|
296
|
-
*/
|
|
297
|
-
public class MyClass {}
|
|
298
|
-
`;
|
|
299
|
-
|
|
300
|
-
const input2 = 'public class ClassRef {}';
|
|
301
|
-
|
|
302
|
-
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
303
|
-
expect(result).documentationBundleHasLength(2);
|
|
304
|
-
assertEither(result, (data) => expect(data).firstDocContains('See'));
|
|
305
|
-
assertEither(result, (data) => expect(data).firstDocContains('[ClassRef](ClassRef.md)'));
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it('displays sees without links when the reference is not found', async () => {
|
|
309
|
-
const input = `
|
|
310
|
-
/**
|
|
311
|
-
* @see ClassRef
|
|
312
|
-
*/
|
|
313
|
-
public class MyClass {}
|
|
314
|
-
`;
|
|
315
|
-
|
|
316
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
317
|
-
expect(result).documentationBundleHasLength(1);
|
|
318
|
-
assertEither(result, (data) => expect(data).firstDocContains('See'));
|
|
319
|
-
assertEither(result, (data) => expect(data).firstDocContains('ClassRef'));
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it('displays the namespace if present in the config', async () => {
|
|
323
|
-
const input = 'public class MyClass {}';
|
|
324
|
-
|
|
325
|
-
const result = await generateDocs([apexBundleFromRawString(input)], { namespace: 'MyNamespace' })();
|
|
326
|
-
expect(result).documentationBundleHasLength(1);
|
|
327
|
-
assertEither(result, (data) => expect(data).firstDocContains('## Namespace'));
|
|
328
|
-
assertEither(result, (data) => expect(data).firstDocContains('MyNamespace'));
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('does not display the namespace if not present in the config', async () => {
|
|
332
|
-
const input = 'public class MyClass {}';
|
|
333
|
-
|
|
334
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
335
|
-
expect(result).documentationBundleHasLength(1);
|
|
336
|
-
assertEither(result, (data) => expect(data).firstDocContainsNot('## Namespace'));
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it('displays a mermaid diagram', async () => {
|
|
340
|
-
const input = `
|
|
341
|
-
/**
|
|
342
|
-
* @mermaid
|
|
343
|
-
* \`\`\`mermaid
|
|
344
|
-
* graph TD
|
|
345
|
-
* A[Square Rect] -- Link text --> B((Circle))
|
|
346
|
-
* A --> C(Round Rect)
|
|
347
|
-
* B --> D{Rhombus}
|
|
348
|
-
* C --> D
|
|
349
|
-
* \`\`\`
|
|
350
|
-
*/
|
|
351
|
-
public class MyClass {}
|
|
352
|
-
`;
|
|
353
|
-
|
|
354
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
355
|
-
expect(result).documentationBundleHasLength(1);
|
|
356
|
-
assertEither(result, (data) => expect(data).firstDocContains('```mermaid'));
|
|
357
|
-
assertEither(result, (data) => expect(data).firstDocContains('graph TD'));
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
it('displays an example code block', async () => {
|
|
361
|
-
const input = `
|
|
362
|
-
/**
|
|
363
|
-
* @example
|
|
364
|
-
* \`\`\`apex
|
|
365
|
-
* public class MyClass {
|
|
366
|
-
* public void myMethod() {
|
|
367
|
-
* System.debug('Hello, World!');
|
|
368
|
-
* }
|
|
369
|
-
* }
|
|
370
|
-
* \`\`\`
|
|
371
|
-
*/
|
|
372
|
-
public class MyClass {}`;
|
|
373
|
-
|
|
374
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
375
|
-
expect(result).documentationBundleHasLength(1);
|
|
376
|
-
assertEither(result, (data) => expect(data).firstDocContains('```apex'));
|
|
377
|
-
assertEither(result, (data) => expect(data).firstDocContains('public class MyClass'));
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
|
|
382
9
|
describe('member information', () => {
|
|
383
10
|
it('displays the Method heading', async () => {
|
|
384
11
|
const input = `
|
|
@@ -400,7 +27,7 @@ describe('Generates interface documentation', () => {
|
|
|
400
27
|
}
|
|
401
28
|
`;
|
|
402
29
|
|
|
403
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
30
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
404
31
|
expect(result).documentationBundleHasLength(1);
|
|
405
32
|
assertEither(result, (data) => {
|
|
406
33
|
const aMethodIndex = data.docs[0].content.indexOf('aMethod');
|
|
@@ -417,7 +44,7 @@ describe('Generates interface documentation', () => {
|
|
|
417
44
|
}
|
|
418
45
|
`;
|
|
419
46
|
|
|
420
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
47
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
421
48
|
expect(result).documentationBundleHasLength(1);
|
|
422
49
|
assertEither(result, (data) => {
|
|
423
50
|
const aMethodIndex = data.docs[0].content.indexOf('aMethod');
|
|
@@ -446,7 +73,7 @@ describe('Generates interface documentation', () => {
|
|
|
446
73
|
}
|
|
447
74
|
`;
|
|
448
75
|
|
|
449
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
76
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
450
77
|
expect(result).documentationBundleHasLength(1);
|
|
451
78
|
assertEither(result, (data) => {
|
|
452
79
|
const aPropertyIndex = data.docs[0].content.indexOf('aProperty');
|
|
@@ -463,7 +90,7 @@ describe('Generates interface documentation', () => {
|
|
|
463
90
|
}
|
|
464
91
|
`;
|
|
465
92
|
|
|
466
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
93
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
467
94
|
expect(result).documentationBundleHasLength(1);
|
|
468
95
|
assertEither(result, (data) => {
|
|
469
96
|
const aPropertyIndex = data.docs[0].content.indexOf('aProperty');
|
|
@@ -492,7 +119,7 @@ describe('Generates interface documentation', () => {
|
|
|
492
119
|
}
|
|
493
120
|
`;
|
|
494
121
|
|
|
495
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
122
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
496
123
|
expect(result).documentationBundleHasLength(1);
|
|
497
124
|
assertEither(result, (data) => {
|
|
498
125
|
const aFieldIndex = data.docs[0].content.indexOf('aField');
|
|
@@ -509,7 +136,7 @@ describe('Generates interface documentation', () => {
|
|
|
509
136
|
}
|
|
510
137
|
`;
|
|
511
138
|
|
|
512
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
139
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
513
140
|
expect(result).documentationBundleHasLength(1);
|
|
514
141
|
assertEither(result, (data) => {
|
|
515
142
|
const aFieldIndex = data.docs[0].content.indexOf('aField');
|
|
@@ -550,7 +177,7 @@ describe('Generates interface documentation', () => {
|
|
|
550
177
|
}
|
|
551
178
|
`;
|
|
552
179
|
|
|
553
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
180
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
554
181
|
expect(result).documentationBundleHasLength(1);
|
|
555
182
|
assertEither(result, (data) => {
|
|
556
183
|
const aInnerClassIndex = data.docs[0].content.indexOf('AInnerClass');
|
|
@@ -567,7 +194,7 @@ describe('Generates interface documentation', () => {
|
|
|
567
194
|
}
|
|
568
195
|
`;
|
|
569
196
|
|
|
570
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
197
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
571
198
|
expect(result).documentationBundleHasLength(1);
|
|
572
199
|
assertEither(result, (data) => {
|
|
573
200
|
const aInnerClassIndex = data.docs[0].content.indexOf('AInnerClass');
|
|
@@ -596,7 +223,7 @@ describe('Generates interface documentation', () => {
|
|
|
596
223
|
}
|
|
597
224
|
`;
|
|
598
225
|
|
|
599
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
226
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
600
227
|
expect(result).documentationBundleHasLength(1);
|
|
601
228
|
assertEither(result, (data) => {
|
|
602
229
|
const aInnerInterfaceIndex = data.docs[0].content.indexOf('AInnerInterface');
|
|
@@ -613,7 +240,7 @@ describe('Generates interface documentation', () => {
|
|
|
613
240
|
}
|
|
614
241
|
`;
|
|
615
242
|
|
|
616
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
243
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
617
244
|
expect(result).documentationBundleHasLength(1);
|
|
618
245
|
assertEither(result, (data) => {
|
|
619
246
|
const aInnerInterfaceIndex = data.docs[0].content.indexOf('AInnerInterface');
|
|
@@ -642,7 +269,7 @@ describe('Generates interface documentation', () => {
|
|
|
642
269
|
}
|
|
643
270
|
`;
|
|
644
271
|
|
|
645
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
272
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
646
273
|
expect(result).documentationBundleHasLength(1);
|
|
647
274
|
assertEither(result, (data) => {
|
|
648
275
|
const aInnerEnumIndex = data.docs[0].content.indexOf('AInnerEnum');
|
|
@@ -659,7 +286,7 @@ describe('Generates interface documentation', () => {
|
|
|
659
286
|
}
|
|
660
287
|
`;
|
|
661
288
|
|
|
662
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
289
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
663
290
|
expect(result).documentationBundleHasLength(1);
|
|
664
291
|
assertEither(result, (data) => {
|
|
665
292
|
const aInnerEnumIndex = data.docs[0].content.indexOf('AInnerEnum');
|
|
@@ -731,3 +358,5 @@ describe('Generates interface documentation', () => {
|
|
|
731
358
|
});
|
|
732
359
|
});
|
|
733
360
|
});
|
|
361
|
+
|
|
362
|
+
// TODO: Skips tags at the member level
|