@cparra/apexdocs 3.0.0-rc.0 → 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/README.md +50 -571
- package/dist/cli/generate.js +73 -3094
- 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 +35 -3
- 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/SampleClass.cls +72 -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-jsconfig/README.md +9 -0
- package/examples/markdown-jsconfig/apexdocs.config.mjs +1 -0
- package/examples/markdown-jsconfig/docs/index.md +1 -1
- 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 +2 -0
- package/examples/vitepress/force-app/main/default/classes/{SampleClass.cls → feature-a/SampleClass.cls} +1 -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 +2 -2
- 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 +14 -9
- 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 +14 -257
- package/src/core/markdown/__test__/generating-docs.spec.ts +271 -4
- package/src/core/markdown/__test__/generating-enum-docs.spec.ts +4 -264
- package/src/core/markdown/__test__/generating-interface-docs.spec.ts +4 -232
- 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 +2 -18
- 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 +4 -2
- package/src/defaults.ts +15 -3
- package/src/index.ts +65 -4
- 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/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
|
@@ -6,251 +6,6 @@ describe('When generating documentation for a class', () => {
|
|
|
6
6
|
extendExpect();
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
describe('documentation content', () => {
|
|
10
|
-
describe('type level information', () => {
|
|
11
|
-
it('generates a heading with the class name', async () => {
|
|
12
|
-
const input = 'public class MyClass {}';
|
|
13
|
-
|
|
14
|
-
const output = `# MyClass Class`;
|
|
15
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
16
|
-
expect(result).documentationBundleHasLength(1);
|
|
17
|
-
assertEither(result, (data) => expect(data).firstDocContains(output));
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('displays type level annotations', async () => {
|
|
21
|
-
const input = `
|
|
22
|
-
@NamespaceAccessible
|
|
23
|
-
public class MyClass {
|
|
24
|
-
@Deprecated
|
|
25
|
-
public void myMethod() {}
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
30
|
-
expect(result).documentationBundleHasLength(1);
|
|
31
|
-
assertEither(result, (data) => expect(data).firstDocContains('NAMESPACEACCESSIBLE'));
|
|
32
|
-
assertEither(result, (data) => expect(data).firstDocContains('DEPRECATED'));
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('displays metadata as annotations', async () => {
|
|
36
|
-
const input = 'public class MyClass {}';
|
|
37
|
-
const metadata = `
|
|
38
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
39
|
-
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
40
|
-
<apiVersion>59.0</apiVersion>
|
|
41
|
-
<status>Active</status>
|
|
42
|
-
</ApexClass>
|
|
43
|
-
`;
|
|
44
|
-
|
|
45
|
-
const result = await generateDocs([apexBundleFromRawString(input, metadata)])();
|
|
46
|
-
|
|
47
|
-
expect(result).documentationBundleHasLength(1);
|
|
48
|
-
assertEither(result, (data) => expect(data).firstDocContains('APIVERSION'));
|
|
49
|
-
assertEither(result, (data) => expect(data).firstDocContains('STATUS'));
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('displays the description', async () => {
|
|
53
|
-
const input = `
|
|
54
|
-
/**
|
|
55
|
-
* This is a description
|
|
56
|
-
*/
|
|
57
|
-
public class MyClass {}
|
|
58
|
-
`;
|
|
59
|
-
|
|
60
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
61
|
-
expect(result).documentationBundleHasLength(1);
|
|
62
|
-
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('display custom documentation tags', async () => {
|
|
66
|
-
const input = `
|
|
67
|
-
/**
|
|
68
|
-
* @custom-tag My Value
|
|
69
|
-
*/
|
|
70
|
-
public class MyClass {}
|
|
71
|
-
`;
|
|
72
|
-
|
|
73
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
74
|
-
expect(result).documentationBundleHasLength(1);
|
|
75
|
-
assertEither(result, (data) => expect(data).firstDocContains('Custom Tag'));
|
|
76
|
-
assertEither(result, (data) => expect(data).firstDocContains('My Value'));
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('displays the group', async () => {
|
|
80
|
-
const input = `
|
|
81
|
-
/**
|
|
82
|
-
* @group MyGroup
|
|
83
|
-
*/
|
|
84
|
-
public class MyClass {}`;
|
|
85
|
-
|
|
86
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
87
|
-
expect(result).documentationBundleHasLength(1);
|
|
88
|
-
assertEither(result, (data) => expect(data).firstDocContains('Group'));
|
|
89
|
-
assertEither(result, (data) => expect(data).firstDocContains('MyGroup'));
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('displays the author', async () => {
|
|
93
|
-
const input = `
|
|
94
|
-
/**
|
|
95
|
-
* @author John Doe
|
|
96
|
-
*/
|
|
97
|
-
public class MyClass {}`;
|
|
98
|
-
|
|
99
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
100
|
-
expect(result).documentationBundleHasLength(1);
|
|
101
|
-
assertEither(result, (data) => expect(data).firstDocContains('Author'));
|
|
102
|
-
assertEither(result, (data) => expect(data).firstDocContains('John Doe'));
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('displays the date', async () => {
|
|
106
|
-
const input = `
|
|
107
|
-
/**
|
|
108
|
-
* @date 2021-01-01
|
|
109
|
-
*/
|
|
110
|
-
public class MyClass {}`;
|
|
111
|
-
|
|
112
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
113
|
-
expect(result).documentationBundleHasLength(1);
|
|
114
|
-
assertEither(result, (data) => expect(data).firstDocContains('Date'));
|
|
115
|
-
assertEither(result, (data) => expect(data).firstDocContains('2021-01-01'));
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('displays descriptions', async () => {
|
|
119
|
-
const input = `
|
|
120
|
-
/**
|
|
121
|
-
* @description This is a description
|
|
122
|
-
*/
|
|
123
|
-
public class MyClass {}`;
|
|
124
|
-
|
|
125
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
126
|
-
expect(result).documentationBundleHasLength(1);
|
|
127
|
-
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('displays descriptions with links', async () => {
|
|
131
|
-
const input1 = `
|
|
132
|
-
/**
|
|
133
|
-
* @description This is a description with a {@link ClassRef} reference
|
|
134
|
-
*/
|
|
135
|
-
public enum MyClass {}
|
|
136
|
-
`;
|
|
137
|
-
|
|
138
|
-
const input2 = 'public class ClassRef {}';
|
|
139
|
-
|
|
140
|
-
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
141
|
-
expect(result).documentationBundleHasLength(2);
|
|
142
|
-
assertEither(result, (data) =>
|
|
143
|
-
expect(data).firstDocContains('This is a description with a [ClassRef](ClassRef.md) reference'),
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('displays descriptions with emails', async () => {
|
|
148
|
-
const input = `
|
|
149
|
-
/**
|
|
150
|
-
* @description This is a description with an {@email test@testerson.com} email
|
|
151
|
-
*/
|
|
152
|
-
public class MyClass {}
|
|
153
|
-
`;
|
|
154
|
-
|
|
155
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
156
|
-
expect(result).documentationBundleHasLength(1);
|
|
157
|
-
assertEither(result, (data) =>
|
|
158
|
-
expect(data).firstDocContains(
|
|
159
|
-
'This is a description with an [test@testerson.com](mailto:test@testerson.com) email',
|
|
160
|
-
),
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('displays sees with accurately resolved links', async () => {
|
|
165
|
-
const input1 = `
|
|
166
|
-
/**
|
|
167
|
-
* @see ClassRef
|
|
168
|
-
*/
|
|
169
|
-
public class MyClass {}
|
|
170
|
-
`;
|
|
171
|
-
|
|
172
|
-
const input2 = 'public class ClassRef {}';
|
|
173
|
-
|
|
174
|
-
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
175
|
-
expect(result).documentationBundleHasLength(2);
|
|
176
|
-
assertEither(result, (data) => expect(data).firstDocContains('See'));
|
|
177
|
-
assertEither(result, (data) => expect(data).firstDocContains('[ClassRef](ClassRef.md)'));
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('displays sees without links when the reference is not found', async () => {
|
|
181
|
-
const input = `
|
|
182
|
-
/**
|
|
183
|
-
* @see ClassRef
|
|
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('See'));
|
|
191
|
-
assertEither(result, (data) => expect(data).firstDocContains('ClassRef'));
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('displays the namespace if present in the config', async () => {
|
|
195
|
-
const input = 'public class MyClass {}';
|
|
196
|
-
|
|
197
|
-
const result = await generateDocs([apexBundleFromRawString(input)], { namespace: 'MyNamespace' })();
|
|
198
|
-
expect(result).documentationBundleHasLength(1);
|
|
199
|
-
assertEither(result, (data) => expect(data).firstDocContains('## Namespace'));
|
|
200
|
-
assertEither(result, (data) => expect(data).firstDocContains('MyNamespace'));
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('does not display the namespace if not present in the config', async () => {
|
|
204
|
-
const input = 'public class MyClass {}';
|
|
205
|
-
|
|
206
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
207
|
-
expect(result).documentationBundleHasLength(1);
|
|
208
|
-
assertEither(result, (data) => expect(data).firstDocContainsNot('## Namespace'));
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('displays a mermaid diagram', async () => {
|
|
212
|
-
const input = `
|
|
213
|
-
/**
|
|
214
|
-
* @mermaid
|
|
215
|
-
* \`\`\`mermaid
|
|
216
|
-
* graph TD
|
|
217
|
-
* A[Square Rect] -- Link text --> B((Circle))
|
|
218
|
-
* A --> C(Round Rect)
|
|
219
|
-
* B --> D{Rhombus}
|
|
220
|
-
* C --> D
|
|
221
|
-
* \`\`\`
|
|
222
|
-
*/
|
|
223
|
-
public class MyClass {}
|
|
224
|
-
`;
|
|
225
|
-
|
|
226
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
227
|
-
expect(result).documentationBundleHasLength(1);
|
|
228
|
-
assertEither(result, (data) => expect(data).firstDocContains('```mermaid'));
|
|
229
|
-
assertEither(result, (data) => expect(data).firstDocContains('graph TD'));
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('displays an example code block', async () => {
|
|
233
|
-
const input = `
|
|
234
|
-
/**
|
|
235
|
-
* @example
|
|
236
|
-
* \`\`\`apex
|
|
237
|
-
* public class MyClass {
|
|
238
|
-
* public void myMethod() {
|
|
239
|
-
* System.debug('Hello, World!');
|
|
240
|
-
* }
|
|
241
|
-
* }
|
|
242
|
-
* \`\`\`
|
|
243
|
-
*/
|
|
244
|
-
public class MyClass {}`;
|
|
245
|
-
|
|
246
|
-
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
247
|
-
expect(result).documentationBundleHasLength(1);
|
|
248
|
-
assertEither(result, (data) => expect(data).firstDocContains('```apex'));
|
|
249
|
-
assertEither(result, (data) => expect(data).firstDocContains('public class MyClass'));
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
9
|
describe('member information', () => {
|
|
255
10
|
it('displays the Method heading', async () => {
|
|
256
11
|
const input = `
|
|
@@ -272,7 +27,7 @@ describe('When generating documentation for a class', () => {
|
|
|
272
27
|
}
|
|
273
28
|
`;
|
|
274
29
|
|
|
275
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
30
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
276
31
|
expect(result).documentationBundleHasLength(1);
|
|
277
32
|
assertEither(result, (data) => {
|
|
278
33
|
const aMethodIndex = data.docs[0].content.indexOf('aMethod');
|
|
@@ -289,7 +44,7 @@ describe('When generating documentation for a class', () => {
|
|
|
289
44
|
}
|
|
290
45
|
`;
|
|
291
46
|
|
|
292
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
47
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
293
48
|
expect(result).documentationBundleHasLength(1);
|
|
294
49
|
assertEither(result, (data) => {
|
|
295
50
|
const aMethodIndex = data.docs[0].content.indexOf('aMethod');
|
|
@@ -318,7 +73,7 @@ describe('When generating documentation for a class', () => {
|
|
|
318
73
|
}
|
|
319
74
|
`;
|
|
320
75
|
|
|
321
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
76
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
322
77
|
expect(result).documentationBundleHasLength(1);
|
|
323
78
|
assertEither(result, (data) => {
|
|
324
79
|
const aPropertyIndex = data.docs[0].content.indexOf('aProperty');
|
|
@@ -335,7 +90,7 @@ describe('When generating documentation for a class', () => {
|
|
|
335
90
|
}
|
|
336
91
|
`;
|
|
337
92
|
|
|
338
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
93
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
339
94
|
expect(result).documentationBundleHasLength(1);
|
|
340
95
|
assertEither(result, (data) => {
|
|
341
96
|
const aPropertyIndex = data.docs[0].content.indexOf('aProperty');
|
|
@@ -364,7 +119,7 @@ describe('When generating documentation for a class', () => {
|
|
|
364
119
|
}
|
|
365
120
|
`;
|
|
366
121
|
|
|
367
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
122
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
368
123
|
expect(result).documentationBundleHasLength(1);
|
|
369
124
|
assertEither(result, (data) => {
|
|
370
125
|
const aFieldIndex = data.docs[0].content.indexOf('aField');
|
|
@@ -381,7 +136,7 @@ describe('When generating documentation for a class', () => {
|
|
|
381
136
|
}
|
|
382
137
|
`;
|
|
383
138
|
|
|
384
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
139
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
385
140
|
expect(result).documentationBundleHasLength(1);
|
|
386
141
|
assertEither(result, (data) => {
|
|
387
142
|
const aFieldIndex = data.docs[0].content.indexOf('aField');
|
|
@@ -422,7 +177,7 @@ describe('When generating documentation for a class', () => {
|
|
|
422
177
|
}
|
|
423
178
|
`;
|
|
424
179
|
|
|
425
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
180
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
426
181
|
expect(result).documentationBundleHasLength(1);
|
|
427
182
|
assertEither(result, (data) => {
|
|
428
183
|
const aInnerClassIndex = data.docs[0].content.indexOf('AInnerClass');
|
|
@@ -439,7 +194,7 @@ describe('When generating documentation for a class', () => {
|
|
|
439
194
|
}
|
|
440
195
|
`;
|
|
441
196
|
|
|
442
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
197
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
443
198
|
expect(result).documentationBundleHasLength(1);
|
|
444
199
|
assertEither(result, (data) => {
|
|
445
200
|
const aInnerClassIndex = data.docs[0].content.indexOf('AInnerClass');
|
|
@@ -468,7 +223,7 @@ describe('When generating documentation for a class', () => {
|
|
|
468
223
|
}
|
|
469
224
|
`;
|
|
470
225
|
|
|
471
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
226
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
472
227
|
expect(result).documentationBundleHasLength(1);
|
|
473
228
|
assertEither(result, (data) => {
|
|
474
229
|
const aInnerInterfaceIndex = data.docs[0].content.indexOf('AInnerInterface');
|
|
@@ -485,7 +240,7 @@ describe('When generating documentation for a class', () => {
|
|
|
485
240
|
}
|
|
486
241
|
`;
|
|
487
242
|
|
|
488
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
243
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
489
244
|
expect(result).documentationBundleHasLength(1);
|
|
490
245
|
assertEither(result, (data) => {
|
|
491
246
|
const aInnerInterfaceIndex = data.docs[0].content.indexOf('AInnerInterface');
|
|
@@ -514,7 +269,7 @@ describe('When generating documentation for a class', () => {
|
|
|
514
269
|
}
|
|
515
270
|
`;
|
|
516
271
|
|
|
517
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
272
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: true })();
|
|
518
273
|
expect(result).documentationBundleHasLength(1);
|
|
519
274
|
assertEither(result, (data) => {
|
|
520
275
|
const aInnerEnumIndex = data.docs[0].content.indexOf('AInnerEnum');
|
|
@@ -531,7 +286,7 @@ describe('When generating documentation for a class', () => {
|
|
|
531
286
|
}
|
|
532
287
|
`;
|
|
533
288
|
|
|
534
|
-
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
289
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { sortAlphabetically: false })();
|
|
535
290
|
expect(result).documentationBundleHasLength(1);
|
|
536
291
|
assertEither(result, (data) => {
|
|
537
292
|
const aInnerEnumIndex = data.docs[0].content.indexOf('AInnerEnum');
|
|
@@ -603,3 +358,5 @@ describe('When generating documentation for a class', () => {
|
|
|
603
358
|
});
|
|
604
359
|
});
|
|
605
360
|
});
|
|
361
|
+
|
|
362
|
+
// TODO: Skips tags at the member level
|
|
@@ -84,10 +84,8 @@ describe('When generating documentation', () => {
|
|
|
84
84
|
assertEither(result, (data) => expect(aSingleDoc(data).source.type).toBe(expected));
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
|
-
});
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
it('does not return files out of scope', async () => {
|
|
88
|
+
it('do not return files out of scope', async () => {
|
|
91
89
|
const input1 = 'global class MyClass {}';
|
|
92
90
|
const input2 = 'public class AnotherClass {}';
|
|
93
91
|
|
|
@@ -97,7 +95,7 @@ describe('When generating documentation', () => {
|
|
|
97
95
|
expect(result).documentationBundleHasLength(1);
|
|
98
96
|
});
|
|
99
97
|
|
|
100
|
-
it('
|
|
98
|
+
it('do not return files that have an @ignore in the docs', async () => {
|
|
101
99
|
const input = `
|
|
102
100
|
/**
|
|
103
101
|
* @ignore
|
|
@@ -108,4 +106,273 @@ describe('When generating documentation', () => {
|
|
|
108
106
|
expect(result).documentationBundleHasLength(0);
|
|
109
107
|
});
|
|
110
108
|
});
|
|
109
|
+
|
|
110
|
+
describe('the documentation content', () => {
|
|
111
|
+
it('includes a heading with the type name', async () => {
|
|
112
|
+
const properties: [string, string][] = [
|
|
113
|
+
['public class MyClass {}', 'MyClass Class'],
|
|
114
|
+
['public enum MyEnum {}', 'MyEnum Enum'],
|
|
115
|
+
['public interface MyInterface {}', 'MyInterface Interface'],
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
for (const [input, expected] of properties) {
|
|
119
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
120
|
+
|
|
121
|
+
expect(result).documentationBundleHasLength(1);
|
|
122
|
+
assertEither(result, (data) => expect(data).firstDocContains(expected));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('displays type level annotations', async () => {
|
|
127
|
+
const input = `
|
|
128
|
+
@NamespaceAccessible
|
|
129
|
+
public class MyClass {
|
|
130
|
+
@Deprecated
|
|
131
|
+
public void myMethod() {}
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
136
|
+
|
|
137
|
+
expect(result).documentationBundleHasLength(1);
|
|
138
|
+
assertEither(result, (data) => expect(data).firstDocContains('NAMESPACEACCESSIBLE'));
|
|
139
|
+
assertEither(result, (data) => expect(data).firstDocContains('DEPRECATED'));
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('displays metadata as annotations', async () => {
|
|
143
|
+
const input = 'public class MyClass {}';
|
|
144
|
+
const metadata = `
|
|
145
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
146
|
+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
147
|
+
<apiVersion>59.0</apiVersion>
|
|
148
|
+
<status>Active</status>
|
|
149
|
+
</ApexClass>
|
|
150
|
+
`;
|
|
151
|
+
|
|
152
|
+
const result = await generateDocs([apexBundleFromRawString(input, metadata)])();
|
|
153
|
+
|
|
154
|
+
expect(result).documentationBundleHasLength(1);
|
|
155
|
+
assertEither(result, (data) => expect(data).firstDocContains('APIVERSION'));
|
|
156
|
+
assertEither(result, (data) => expect(data).firstDocContains('STATUS'));
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('displays the description when no @description tag is used', async () => {
|
|
160
|
+
const input = `
|
|
161
|
+
/**
|
|
162
|
+
* This is a description
|
|
163
|
+
*/
|
|
164
|
+
public class MyClass {}
|
|
165
|
+
`;
|
|
166
|
+
|
|
167
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
168
|
+
|
|
169
|
+
expect(result).documentationBundleHasLength(1);
|
|
170
|
+
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('displays the description when a @description tag is used', async () => {
|
|
174
|
+
const input = `
|
|
175
|
+
/**
|
|
176
|
+
* @description This is a description
|
|
177
|
+
*/
|
|
178
|
+
public class MyClass {}`;
|
|
179
|
+
|
|
180
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
181
|
+
expect(result).documentationBundleHasLength(1);
|
|
182
|
+
assertEither(result, (data) => expect(data).firstDocContains('This is a description'));
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('display custom documentation tags', async () => {
|
|
186
|
+
const input = `
|
|
187
|
+
/**
|
|
188
|
+
* @custom-tag My Value
|
|
189
|
+
*/
|
|
190
|
+
public class MyClass {}
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
194
|
+
expect(result).documentationBundleHasLength(1);
|
|
195
|
+
assertEither(result, (data) => expect(data).firstDocContains('Custom Tag'));
|
|
196
|
+
assertEither(result, (data) => expect(data).firstDocContains('My Value'));
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('displays the group', async () => {
|
|
200
|
+
const input = `
|
|
201
|
+
/**
|
|
202
|
+
* @group MyGroup
|
|
203
|
+
*/
|
|
204
|
+
public class MyClass {}`;
|
|
205
|
+
|
|
206
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
207
|
+
expect(result).documentationBundleHasLength(1);
|
|
208
|
+
assertEither(result, (data) => expect(data).firstDocContains('Group'));
|
|
209
|
+
assertEither(result, (data) => expect(data).firstDocContains('MyGroup'));
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('displays the author', async () => {
|
|
213
|
+
const input = `
|
|
214
|
+
/**
|
|
215
|
+
* @author John Doe
|
|
216
|
+
*/
|
|
217
|
+
public class MyClass {}`;
|
|
218
|
+
|
|
219
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
220
|
+
expect(result).documentationBundleHasLength(1);
|
|
221
|
+
assertEither(result, (data) => expect(data).firstDocContains('Author'));
|
|
222
|
+
assertEither(result, (data) => expect(data).firstDocContains('John Doe'));
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('displays the date', async () => {
|
|
226
|
+
const input = `
|
|
227
|
+
/**
|
|
228
|
+
* @date 2021-01-01
|
|
229
|
+
*/
|
|
230
|
+
public class MyClass {}`;
|
|
231
|
+
|
|
232
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
233
|
+
expect(result).documentationBundleHasLength(1);
|
|
234
|
+
assertEither(result, (data) => expect(data).firstDocContains('Date'));
|
|
235
|
+
assertEither(result, (data) => expect(data).firstDocContains('2021-01-01'));
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('displays descriptions with links', async () => {
|
|
239
|
+
const input1 = `
|
|
240
|
+
/**
|
|
241
|
+
* @description This is a description with a {@link ClassRef} reference
|
|
242
|
+
*/
|
|
243
|
+
public enum MyClass {}
|
|
244
|
+
`;
|
|
245
|
+
|
|
246
|
+
const input2 = 'public class ClassRef {}';
|
|
247
|
+
|
|
248
|
+
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
249
|
+
expect(result).documentationBundleHasLength(2);
|
|
250
|
+
assertEither(result, (data) =>
|
|
251
|
+
expect(data).firstDocContains('This is a description with a [ClassRef](ClassRef.md) reference'),
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('displays descriptions with emails', async () => {
|
|
256
|
+
const input = `
|
|
257
|
+
/**
|
|
258
|
+
* @description This is a description with an {@email test@testerson.com} email
|
|
259
|
+
*/
|
|
260
|
+
public class MyClass {}
|
|
261
|
+
`;
|
|
262
|
+
|
|
263
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
264
|
+
expect(result).documentationBundleHasLength(1);
|
|
265
|
+
assertEither(result, (data) =>
|
|
266
|
+
expect(data).firstDocContains(
|
|
267
|
+
'This is a description with an [test@testerson.com](mailto:test@testerson.com) email',
|
|
268
|
+
),
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('displays @sees with accurately resolved links', async () => {
|
|
273
|
+
const input1 = `
|
|
274
|
+
/**
|
|
275
|
+
* @see ClassRef
|
|
276
|
+
*/
|
|
277
|
+
public class MyClass {}
|
|
278
|
+
`;
|
|
279
|
+
|
|
280
|
+
const input2 = 'public class ClassRef {}';
|
|
281
|
+
|
|
282
|
+
const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)])();
|
|
283
|
+
expect(result).documentationBundleHasLength(2);
|
|
284
|
+
assertEither(result, (data) => expect(data).firstDocContains('See'));
|
|
285
|
+
assertEither(result, (data) => expect(data).firstDocContains('[ClassRef](ClassRef.md)'));
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('displays @sees without links when the reference is not found', async () => {
|
|
289
|
+
const input = `
|
|
290
|
+
/**
|
|
291
|
+
* @see ClassRef
|
|
292
|
+
*/
|
|
293
|
+
public class MyClass {}
|
|
294
|
+
`;
|
|
295
|
+
|
|
296
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
297
|
+
|
|
298
|
+
expect(result).documentationBundleHasLength(1);
|
|
299
|
+
assertEither(result, (data) => expect(data).firstDocContains('See'));
|
|
300
|
+
assertEither(result, (data) => expect(data).firstDocContains('ClassRef'));
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('displays the namespace if present in the config', async () => {
|
|
304
|
+
const input = 'public class MyClass {}';
|
|
305
|
+
|
|
306
|
+
const result = await generateDocs([apexBundleFromRawString(input)], { namespace: 'MyNamespace' })();
|
|
307
|
+
expect(result).documentationBundleHasLength(1);
|
|
308
|
+
assertEither(result, (data) => expect(data).firstDocContains('## Namespace'));
|
|
309
|
+
assertEither(result, (data) => expect(data).firstDocContains('MyNamespace'));
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('does not display the namespace if not present in the config', async () => {
|
|
313
|
+
const input = 'public class MyClass {}';
|
|
314
|
+
|
|
315
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
316
|
+
expect(result).documentationBundleHasLength(1);
|
|
317
|
+
assertEither(result, (data) => expect(data).firstDocContainsNot('## Namespace'));
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('displays a mermaid diagram', async () => {
|
|
321
|
+
const input = `
|
|
322
|
+
/**
|
|
323
|
+
* @mermaid
|
|
324
|
+
* \`\`\`mermaid
|
|
325
|
+
* graph TD
|
|
326
|
+
* A[Square Rect] -- Link text --> B((Circle))
|
|
327
|
+
* A --> C(Round Rect)
|
|
328
|
+
* B --> D{Rhombus}
|
|
329
|
+
* C --> D
|
|
330
|
+
* \`\`\`
|
|
331
|
+
*/
|
|
332
|
+
public class MyClass {}
|
|
333
|
+
`;
|
|
334
|
+
|
|
335
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
336
|
+
expect(result).documentationBundleHasLength(1);
|
|
337
|
+
assertEither(result, (data) => expect(data).firstDocContains('```mermaid'));
|
|
338
|
+
assertEither(result, (data) => expect(data).firstDocContains('graph TD'));
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('displays an example code block', async () => {
|
|
342
|
+
const input = `
|
|
343
|
+
/**
|
|
344
|
+
* @example
|
|
345
|
+
* \`\`\`apex
|
|
346
|
+
* public class MyClass {
|
|
347
|
+
* public void myMethod() {
|
|
348
|
+
* System.debug('Hello, World!');
|
|
349
|
+
* }
|
|
350
|
+
* }
|
|
351
|
+
* \`\`\`
|
|
352
|
+
*/
|
|
353
|
+
public class MyClass {}`;
|
|
354
|
+
|
|
355
|
+
const result = await generateDocs([apexBundleFromRawString(input)])();
|
|
356
|
+
|
|
357
|
+
expect(result).documentationBundleHasLength(1);
|
|
358
|
+
assertEither(result, (data) => expect(data).firstDocContains('```apex'));
|
|
359
|
+
assertEither(result, (data) => expect(data).firstDocContains('public class MyClass'));
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('does not display tags marked as excluded', async () => {
|
|
363
|
+
const input = `
|
|
364
|
+
/**
|
|
365
|
+
* @see ClassRef
|
|
366
|
+
*/
|
|
367
|
+
public class MyClass {}
|
|
368
|
+
`;
|
|
369
|
+
|
|
370
|
+
const result = await generateDocs([apexBundleFromRawString(input)], {
|
|
371
|
+
excludeTags: ['see'],
|
|
372
|
+
})();
|
|
373
|
+
|
|
374
|
+
expect(result).documentationBundleHasLength(1);
|
|
375
|
+
assertEither(result, (data) => expect(data).firstDocContainsNot('See'));
|
|
376
|
+
});
|
|
377
|
+
});
|
|
111
378
|
});
|