@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.
Files changed (125) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +246 -650
  3. package/dist/cli/generate.js +74 -3095
  4. package/dist/defaults-BcE8DTat.js +13 -0
  5. package/dist/defaults-D07y_bq4.js +40 -0
  6. package/dist/defaults-gPzwP66p.js +14 -0
  7. package/dist/index.d.ts +49 -19
  8. package/dist/index.js +90 -2
  9. package/dist/logger-BEbUIfqN.js +3282 -0
  10. package/dist/logger-BGuf1PnL.js +3281 -0
  11. package/dist/logger-CWBRF2za.js +3284 -0
  12. package/dist/logger-CdBmDEN1.js +3283 -0
  13. package/dist/logger-Ce4QqPFR.js +3278 -0
  14. package/dist/logger-CyEVYaAC.js +3284 -0
  15. package/dist/logger-D7a83ycP.js +3277 -0
  16. package/dist/logger-DGaHeBKk.js +3279 -0
  17. package/dist/logger-Dqhl_lO_.js +3278 -0
  18. package/dist/logger-aySSWi0G.js +3280 -0
  19. package/dist/logger-qLCcAtiy.js +3284 -0
  20. package/examples/README.md +5 -0
  21. package/examples/docsify/README.md +17 -0
  22. package/examples/docsify/apexdocs.config.ts +13 -0
  23. package/examples/docsify/classes/ASampleClass.cls +57 -0
  24. package/examples/docsify/classes/CodeControl.cls +19 -0
  25. package/examples/docsify/classes/SampleClass.cls +95 -0
  26. package/examples/docsify/classes/SampleInterface.cls +17 -0
  27. package/examples/docsify/classes/SomeDto.cls +122 -0
  28. package/examples/docsify/docs/.nojekyll +0 -0
  29. package/examples/docsify/docs/README.md +25 -0
  30. package/examples/docsify/docs/_config.yml +1 -0
  31. package/examples/docsify/docs/index.html +22 -0
  32. package/examples/docsify/docs/miscellaneous/ASampleClass.md +88 -0
  33. package/examples/docsify/docs/miscellaneous/CodeControl.md +107 -0
  34. package/examples/docsify/docs/miscellaneous/SomeDto.md +244 -0
  35. package/examples/docsify/docs/sample-classes/SampleClass.md +171 -0
  36. package/examples/docsify/docs/sample-interfaces/SampleInterface.md +36 -0
  37. package/examples/docsify/package-lock.json +2459 -0
  38. package/examples/docsify/package.json +14 -0
  39. package/examples/imported/.forceignore +12 -0
  40. package/examples/imported/README.md +6 -0
  41. package/examples/imported/config/project-scratch-def.json +5 -0
  42. package/examples/imported/docs/index.md +109 -0
  43. package/examples/imported/docs/miscellaneous/BaseClass.md +13 -0
  44. package/examples/imported/docs/miscellaneous/MultiInheritanceClass.md +69 -0
  45. package/examples/imported/docs/miscellaneous/ParentInterface.md +12 -0
  46. package/examples/imported/docs/miscellaneous/ReferencedEnum.md +5 -0
  47. package/examples/imported/docs/miscellaneous/SampleException.md +21 -0
  48. package/examples/imported/docs/miscellaneous/SampleInterface.md +113 -0
  49. package/examples/imported/docs/miscellaneous/Url.md +308 -0
  50. package/examples/imported/docs/sample-enums/SampleEnum.md +33 -0
  51. package/examples/imported/docs/samplegroup/SampleClass.md +167 -0
  52. package/examples/imported/force-app/classes/BaseClass.cls +3 -0
  53. package/examples/imported/force-app/classes/MultiInheritanceClass.cls +1 -0
  54. package/examples/imported/force-app/classes/ParentInterface.cls +3 -0
  55. package/examples/imported/force-app/classes/ReferencedEnum.cls +3 -0
  56. package/examples/imported/force-app/classes/SampleInterface.cls +50 -0
  57. package/examples/imported/force-app/classes/Url.cls +196 -0
  58. package/examples/imported/package-lock.json +665 -0
  59. package/examples/imported/package.json +6 -0
  60. package/examples/imported/scripts/process-docs.mjs +16 -0
  61. package/examples/imported/sfdx-project.json +12 -0
  62. package/examples/markdown/README.md +7 -0
  63. package/examples/markdown/docs/miscellaneous/Url.md +10 -8
  64. package/examples/markdown/force-app/classes/Url.cls +3 -1
  65. package/examples/markdown-jsconfig/.forceignore +12 -0
  66. package/examples/markdown-jsconfig/README.md +9 -0
  67. package/examples/markdown-jsconfig/apexdocs.config.mjs +22 -0
  68. package/examples/markdown-jsconfig/config/project-scratch-def.json +5 -0
  69. package/examples/markdown-jsconfig/docs/index.md +12 -0
  70. package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +315 -0
  71. package/examples/markdown-jsconfig/force-app/classes/Url.cls +196 -0
  72. package/examples/markdown-jsconfig/package-lock.json +665 -0
  73. package/examples/markdown-jsconfig/package.json +15 -0
  74. package/examples/markdown-jsconfig/sfdx-project.json +12 -0
  75. package/examples/open-api/README.md +5 -0
  76. package/examples/open-api/docs/openapi.json +2 -570
  77. package/examples/vitepress/README.md +25 -0
  78. package/examples/vitepress/apexdocs.config.ts +9 -2
  79. package/examples/vitepress/docs/index.md +11 -11
  80. package/examples/vitepress/docs/miscellaneous/BaseClass.md +1 -1
  81. package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +2 -2
  82. package/examples/vitepress/docs/miscellaneous/SampleException.md +1 -1
  83. package/examples/vitepress/docs/miscellaneous/SampleInterface.md +6 -6
  84. package/examples/vitepress/docs/miscellaneous/Url.md +3 -3
  85. package/examples/vitepress/docs/sample-enums/SampleEnum.md +3 -3
  86. package/examples/vitepress/docs/samplegroup/SampleClass.md +5 -5
  87. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleClass.cls +73 -0
  88. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleEnum.cls +30 -0
  89. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleException.cls +17 -0
  90. package/package.json +3 -3
  91. package/src/application/Apexdocs.ts +16 -19
  92. package/src/application/__tests__/apex-file-reader.spec.ts +108 -67
  93. package/src/application/apex-file-reader.ts +1 -0
  94. package/src/application/generators/openapi.ts +17 -13
  95. package/src/cli/args.ts +12 -3
  96. package/src/cli/commands/markdown.ts +15 -12
  97. package/src/cli/commands/openapi.ts +5 -5
  98. package/src/cli/generate.ts +20 -4
  99. package/src/core/markdown/__test__/generating-class-docs.spec.ts +15 -386
  100. package/src/core/markdown/__test__/generating-docs.spec.ts +378 -0
  101. package/src/core/markdown/__test__/generating-enum-docs.spec.ts +4 -328
  102. package/src/core/markdown/__test__/generating-interface-docs.spec.ts +4 -296
  103. package/src/core/markdown/__test__/generating-reference-guide.spec.ts +17 -1
  104. package/src/core/markdown/__test__/test-helpers.ts +3 -1
  105. package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +3 -1
  106. package/src/core/markdown/adapters/renderable-to-page-data.ts +6 -4
  107. package/src/core/markdown/generate-docs.ts +13 -15
  108. package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +290 -0
  109. package/src/core/markdown/reflection/__test__/helpers.ts +18 -0
  110. package/src/core/markdown/reflection/__test__/remove-excluded-tags.spec.ts +200 -0
  111. package/src/core/markdown/reflection/remove-excluded-tags.ts +168 -0
  112. package/src/core/markdown/reflection/{sort-members.ts → sort-types-and-members.ts} +7 -5
  113. package/src/core/markdown/templates/reference-guide.ts +2 -2
  114. package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +6 -3
  115. package/src/core/openapi/open-api-docs-processor.ts +3 -3
  116. package/src/core/openapi/parser.ts +5 -2
  117. package/src/core/shared/types.d.ts +18 -18
  118. package/src/defaults.ts +15 -3
  119. package/src/index.ts +88 -14
  120. package/src/util/error-logger.ts +36 -36
  121. package/src/util/logger.ts +18 -11
  122. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleClass.cls +0 -0
  123. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleEnum.cls +0 -0
  124. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleException.cls +0 -0
  125. /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<UserDefinedMarkdownConfig> {
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
- return { ...config?.config, ...cliArgs, targetGenerator: commandName as 'markdown' | 'openapi' };
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 { defaults } from '../../defaults';
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: defaults.targetDir,
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: defaults.scope,
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: defaults.defaultGroupName,
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
- sortMembersAlphabetically: {
35
+ sortAlphabetically: {
38
36
  type: 'boolean',
39
- describe: 'Whether to sort members alphabetically.',
40
- default: defaults.sortMembersAlphabetically,
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: defaults.includeMetadata,
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: defaults.linkingStrategy,
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 { defaults } from '../../defaults';
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: defaults.targetDir,
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: 'openapi',
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: 'Apex REST API',
28
+ default: openApiDefaults.title,
29
29
  describe: 'The title of the OpenApi file.',
30
30
  },
31
31
  apiVersion: {
32
32
  type: 'string',
33
- default: '1.0.0',
33
+ default: openApiDefaults.apiVersion,
34
34
  describe: 'The version of the OpenApi file.',
35
35
  },
36
36
  };
@@ -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 catchError(error: Error) {
7
- console.error(error);
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).catch(catchError))
13
- .catch(catchError);
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('Generates interface documentation', () => {
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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)], { sortMembersAlphabetically: true })();
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)], { sortMembersAlphabetically: false })();
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