@cparra/apexdocs 3.0.0-beta.1 → 3.0.0-rc.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 (34) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +442 -325
  3. package/dist/cli/generate.js +1 -1
  4. package/dist/index.d.ts +15 -17
  5. package/examples/markdown/docs/miscellaneous/Url.md +10 -8
  6. package/examples/markdown/force-app/classes/Url.cls +3 -1
  7. package/examples/markdown-jsconfig/.forceignore +12 -0
  8. package/examples/markdown-jsconfig/apexdocs.config.mjs +21 -0
  9. package/examples/markdown-jsconfig/config/project-scratch-def.json +5 -0
  10. package/examples/markdown-jsconfig/docs/index.md +12 -0
  11. package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +315 -0
  12. package/examples/markdown-jsconfig/force-app/classes/Url.cls +196 -0
  13. package/examples/markdown-jsconfig/package-lock.json +665 -0
  14. package/examples/markdown-jsconfig/package.json +15 -0
  15. package/examples/markdown-jsconfig/sfdx-project.json +12 -0
  16. package/examples/vitepress/apexdocs.config.ts +7 -2
  17. package/examples/vitepress/docs/index.md +11 -11
  18. package/examples/vitepress/docs/miscellaneous/BaseClass.md +1 -1
  19. package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +2 -2
  20. package/examples/vitepress/docs/miscellaneous/SampleException.md +1 -1
  21. package/examples/vitepress/docs/miscellaneous/SampleInterface.md +6 -6
  22. package/examples/vitepress/docs/miscellaneous/Url.md +3 -3
  23. package/examples/vitepress/docs/sample-enums/SampleEnum.md +3 -3
  24. package/examples/vitepress/docs/samplegroup/SampleClass.md +5 -5
  25. package/examples/vitepress/force-app/main/default/classes/SampleClass.cls +1 -1
  26. package/package.json +2 -2
  27. package/src/cli/commands/markdown.ts +1 -3
  28. package/src/core/markdown/__test__/generating-class-docs.spec.ts +1 -129
  29. package/src/core/markdown/__test__/generating-docs.spec.ts +111 -0
  30. package/src/core/markdown/__test__/generating-enum-docs.spec.ts +0 -64
  31. package/src/core/markdown/__test__/generating-interface-docs.spec.ts +0 -64
  32. package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +306 -0
  33. package/src/core/shared/types.d.ts +14 -16
  34. package/src/index.ts +23 -10
@@ -6,70 +6,6 @@ describe('Generates interface documentation', () => {
6
6
  extendExpect();
7
7
  });
8
8
 
9
- describe('documentation output', () => {
10
- it('returns the name of the interface', async () => {
11
- const input = `
12
- public interface MyInterface {
13
- }
14
- `;
15
-
16
- const result = await generateDocs([apexBundleFromRawString(input)])();
17
- expect(result).documentationBundleHasLength(1);
18
- assertEither(result, (data) => expect(data.docs[0].source.name).toBe('MyInterface'));
19
- });
20
-
21
- it('returns the type as interface', async () => {
22
- const input = `
23
- public interface MyInterface {
24
- }
25
- `;
26
-
27
- const result = await generateDocs([apexBundleFromRawString(input)])();
28
- expect(result).documentationBundleHasLength(1);
29
- assertEither(result, (data) => expect(data.docs[0].source.type).toBe('interface'));
30
- });
31
-
32
- it('does not return interfaces out of scope', async () => {
33
- const input1 = `
34
- global interface MyInterface {}
35
- `;
36
-
37
- const input2 = `
38
- public interface AnotherInterface {}
39
- `;
40
-
41
- const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
42
- scope: ['global'],
43
- })();
44
- expect(result).documentationBundleHasLength(1);
45
- });
46
-
47
- it('does not return interfaces that have an @ignore in the docs', async () => {
48
- const input = `
49
- /**
50
- * @ignore
51
- */
52
- public interface MyInterface {}`;
53
-
54
- const result = await generateDocs([apexBundleFromRawString(input)])();
55
- expect(result).documentationBundleHasLength(0);
56
- });
57
-
58
- it('does not return interface methods that have @ignore in the docs', async () => {
59
- const input = `
60
- public interface MyInterface {
61
- /**
62
- * @ignore
63
- */
64
- void myMethod();
65
- }`;
66
-
67
- const result = await generateDocs([apexBundleFromRawString(input)])();
68
- expect(result).documentationBundleHasLength(1);
69
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myMethod'));
70
- });
71
- });
72
-
73
9
  describe('documentation content', () => {
74
10
  describe('type level information', () => {
75
11
  it('generates a heading with the interface name', async () => {
@@ -0,0 +1,306 @@
1
+ import { ParsedFile } from '../../../shared/types';
2
+ import { ClassMirror, EnumMirror, InterfaceMirror, reflect } from '@cparra/apex-reflection';
3
+ import { filterScope } from '../filter-scope';
4
+
5
+ function parsedFileFromRawString(raw: string): ParsedFile {
6
+ const { error, typeMirror } = reflect(raw);
7
+ if (error) {
8
+ throw new Error(error.message);
9
+ }
10
+
11
+ return {
12
+ source: {
13
+ filePath: 'test.cls',
14
+ name: typeMirror!.name,
15
+ type: typeMirror!.type_name,
16
+ },
17
+ type: typeMirror!,
18
+ };
19
+ }
20
+
21
+ describe('When filtering scope', () => {
22
+ it('filters out files with the @ignore annotation', () => {
23
+ const properties: [string, number][] = [
24
+ [
25
+ `
26
+ /**
27
+ * @ignore
28
+ */
29
+ global class MyClass {}
30
+ `,
31
+ 0,
32
+ ],
33
+ ['global class MyClass {}', 1],
34
+ ];
35
+
36
+ for (const [input, expected] of properties) {
37
+ const parsedFile = parsedFileFromRawString(input);
38
+
39
+ const result = filterScope(['global'], [parsedFile]);
40
+
41
+ expect(result).toHaveLength(expected);
42
+ }
43
+ });
44
+
45
+ describe('when scoping a class', () => {
46
+ it('filters out methods tagged with @ignore', () => {
47
+ const properties: [string, number][] = [
48
+ [
49
+ `
50
+ global class MyClass {
51
+ /**
52
+ * @ignore
53
+ */
54
+ global void myMethod() {}
55
+ }
56
+ `,
57
+ 0,
58
+ ],
59
+ [
60
+ `
61
+ global class MyClass {
62
+ global void myMethod() {}
63
+ }
64
+ `,
65
+ 1,
66
+ ],
67
+ ];
68
+
69
+ for (const [input, expected] of properties) {
70
+ const parsedFile = parsedFileFromRawString(input);
71
+
72
+ const result = filterScope(['global'], [parsedFile]);
73
+
74
+ expect((result[0].type as ClassMirror).methods).toHaveLength(expected);
75
+ }
76
+ });
77
+
78
+ it('filters out properties tagged with @ignore', () => {
79
+ const properties: [string, number][] = [
80
+ [
81
+ `
82
+ global class MyClass {
83
+ /**
84
+ * @ignore
85
+ */
86
+ global Integer myProperty { get; set; }
87
+ }
88
+ `,
89
+ 0,
90
+ ],
91
+ [
92
+ `
93
+ global class MyClass {
94
+ global Integer myProperty { get; set; }
95
+ }
96
+ `,
97
+ 1,
98
+ ],
99
+ ];
100
+
101
+ for (const [input, expected] of properties) {
102
+ const parsedFile = parsedFileFromRawString(input);
103
+
104
+ const result = filterScope(['global'], [parsedFile]);
105
+
106
+ expect((result[0].type as ClassMirror).properties).toHaveLength(expected);
107
+ }
108
+ });
109
+
110
+ it('filters out fields tagged with @ignore', () => {
111
+ const properties: [string, number][] = [
112
+ [
113
+ `
114
+ global class MyClass {
115
+ /**
116
+ * @ignore
117
+ */
118
+ global Integer myField;
119
+ }
120
+ `,
121
+ 0,
122
+ ],
123
+ [
124
+ `
125
+ global class MyClass {
126
+ global Integer myField;
127
+ }
128
+ `,
129
+ 1,
130
+ ],
131
+ ];
132
+
133
+ for (const [input, expected] of properties) {
134
+ const parsedFile = parsedFileFromRawString(input);
135
+
136
+ const result = filterScope(['global'], [parsedFile]);
137
+
138
+ expect((result[0].type as ClassMirror).fields).toHaveLength(expected);
139
+ }
140
+ });
141
+
142
+ it('filters out inner classes tagged with @ignore', () => {
143
+ const properties: [string, number][] = [
144
+ [
145
+ `
146
+ global class MyClass {
147
+ /**
148
+ * @ignore
149
+ */
150
+ global class InnerClass {}
151
+ }
152
+ `,
153
+ 0,
154
+ ],
155
+ [
156
+ `
157
+ global class MyClass {
158
+ global class InnerClass {}
159
+ }
160
+ `,
161
+ 1,
162
+ ],
163
+ ];
164
+
165
+ for (const [input, expected] of properties) {
166
+ const parsedFile = parsedFileFromRawString(input);
167
+
168
+ const result = filterScope(['global'], [parsedFile]);
169
+
170
+ expect((result[0].type as ClassMirror).classes).toHaveLength(expected);
171
+ }
172
+ });
173
+
174
+ it('filters out inner interfaces tagged with @ignore', () => {
175
+ const properties: [string, number][] = [
176
+ [
177
+ `
178
+ global class MyClass {
179
+ /**
180
+ * @ignore
181
+ */
182
+ global interface InnerInterface {}
183
+ }
184
+ `,
185
+ 0,
186
+ ],
187
+ [
188
+ `
189
+ global class MyClass {
190
+ global interface InnerInterface {}
191
+ }
192
+ `,
193
+ 1,
194
+ ],
195
+ ];
196
+
197
+ for (const [input, expected] of properties) {
198
+ const parsedFile = parsedFileFromRawString(input);
199
+
200
+ const result = filterScope(['global'], [parsedFile]);
201
+
202
+ expect((result[0].type as ClassMirror).interfaces).toHaveLength(expected);
203
+ }
204
+ });
205
+
206
+ it('filters out inner enums tagged with @ignore', () => {
207
+ const properties: [string, number][] = [
208
+ [
209
+ `
210
+ global class MyClass {
211
+ /**
212
+ * @ignore
213
+ */
214
+ global enum InnerEnum {}
215
+ }
216
+ `,
217
+ 0,
218
+ ],
219
+ [
220
+ `
221
+ global class MyClass {
222
+ global enum InnerEnum {}
223
+ }
224
+ `,
225
+ 1,
226
+ ],
227
+ ];
228
+
229
+ for (const [input, expected] of properties) {
230
+ const parsedFile = parsedFileFromRawString(input);
231
+
232
+ const result = filterScope(['global'], [parsedFile]);
233
+
234
+ expect((result[0].type as ClassMirror).enums).toHaveLength(expected);
235
+ }
236
+ });
237
+ });
238
+
239
+ describe('when scoping an interface', () => {
240
+ it('filters out methods tagged with @ignore', () => {
241
+ const properties: [string, number][] = [
242
+ [
243
+ `
244
+ global interface MyInterface {
245
+ /**
246
+ * @ignore
247
+ */
248
+ void myMethod();
249
+ }
250
+ `,
251
+ 0,
252
+ ],
253
+ [
254
+ `
255
+ global interface MyInterface {
256
+ void myMethod();
257
+ }
258
+ `,
259
+ 1,
260
+ ],
261
+ ];
262
+
263
+ for (const [input, expected] of properties) {
264
+ const parsedFile = parsedFileFromRawString(input);
265
+
266
+ const result = filterScope(['global'], [parsedFile]);
267
+
268
+ expect((result[0].type as InterfaceMirror).methods).toHaveLength(expected);
269
+ }
270
+ });
271
+ });
272
+
273
+ describe('when scoping an enum', () => {
274
+ it('never filters out enum values, even if tagged with @ignore', () => {
275
+ const properties: [string, number][] = [
276
+ [
277
+ `
278
+ global enum MyEnum {
279
+ /**
280
+ * @ignore
281
+ */
282
+ VALUE
283
+ }
284
+ `,
285
+ 1,
286
+ ],
287
+ [
288
+ `
289
+ global enum MyEnum {
290
+ VALUE
291
+ }
292
+ `,
293
+ 1,
294
+ ],
295
+ ];
296
+
297
+ for (const [input, expected] of properties) {
298
+ const parsedFile = parsedFileFromRawString(input);
299
+
300
+ const result = filterScope(['global'], [parsedFile]);
301
+
302
+ expect((result[0].type as EnumMirror).values).toHaveLength(expected);
303
+ }
304
+ });
305
+ });
306
+ });
@@ -1,17 +1,5 @@
1
1
  import { Type } from '@cparra/apex-reflection';
2
2
 
3
- export type Generator = 'markdown' | 'openapi';
4
-
5
- /**
6
- * The configurable hooks that can be used to modify the output of the generator.
7
- */
8
- export type ConfigurableHooks = {
9
- transformReferenceGuide: TransformReferenceGuide;
10
- transformDocs: TransformDocs;
11
- transformDocPage: TransformDocPage;
12
- transformReference: TransformReference;
13
- };
14
-
15
3
  type LinkingStrategy =
16
4
  // Links will be generated using relative paths.
17
5
  | 'relative'
@@ -24,8 +12,8 @@ type LinkingStrategy =
24
12
  | 'none';
25
13
 
26
14
  export type UserDefinedMarkdownConfig = {
27
- targetGenerator: 'markdown';
28
15
  sourceDir: string;
16
+ targetGenerator: 'markdown';
29
17
  targetDir: string;
30
18
  scope: string[];
31
19
  defaultGroupName: string;
@@ -115,11 +103,21 @@ export type PostHookDocumentationBundle = {
115
103
  docs: DocPageData[];
116
104
  };
117
105
 
118
- // Configurable Hooks
106
+ // CONFIGURABLE HOOKS
107
+
108
+ /**
109
+ * The configurable hooks that can be used to modify the output of the generator.
110
+ */
111
+ export type ConfigurableHooks = {
112
+ transformReferenceGuide: TransformReferenceGuide;
113
+ transformDocs: TransformDocs;
114
+ transformDocPage: TransformDocPage;
115
+ transformReference: TransformReference;
116
+ };
119
117
 
120
- type ConfigurableDocPageReference = Omit<DocPageReference, 'source'>;
118
+ export type ConfigurableDocPageReference = Omit<DocPageReference, 'source'>;
121
119
 
122
- type ConfigurableDocPageData = Omit<DocPageData, 'source' | 'outputDocPath'>;
120
+ export type ConfigurableDocPageData = Omit<DocPageData, 'source' | 'outputDocPath'>;
123
121
 
124
122
  /**
125
123
  * Allows changing where the files are written to.
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { SetOptional } from 'type-fest';
2
1
  import type {
3
2
  ConfigurableHooks,
4
3
  Skip,
@@ -6,18 +5,18 @@ import type {
6
5
  ReferenceGuidePageData,
7
6
  DocPageData,
8
7
  DocPageReference,
8
+ ConfigurableDocPageData,
9
+ TransformReferenceGuide,
10
+ TransformDocs,
11
+ TransformDocPage,
12
+ TransformReference,
13
+ ConfigurableDocPageReference,
9
14
  } from './core/shared/types';
10
15
  import { defaults } from './defaults';
11
16
 
12
- type ConfigurableMarkdownConfig = Omit<
13
- SetOptional<
14
- UserDefinedMarkdownConfig,
15
- 'targetDir' | 'scope' | 'defaultGroupName' | 'includeMetadata' | 'sortMembersAlphabetically' | 'linkingStrategy'
16
- >,
17
- 'targetGenerator'
18
- >;
17
+ type ConfigurableMarkdownConfig = Omit<Partial<UserDefinedMarkdownConfig>, 'targetGenerator'>;
19
18
 
20
- function defineMarkdownConfig(config: ConfigurableMarkdownConfig): UserDefinedMarkdownConfig {
19
+ function defineMarkdownConfig(config: ConfigurableMarkdownConfig): Partial<UserDefinedMarkdownConfig> {
21
20
  return {
22
21
  ...defaults,
23
22
  ...config,
@@ -33,4 +32,18 @@ function skip(): Skip {
33
32
 
34
33
  // Exports
35
34
 
36
- export { defineMarkdownConfig, skip, ConfigurableHooks, ReferenceGuidePageData, DocPageData, DocPageReference };
35
+ export {
36
+ defineMarkdownConfig,
37
+ skip,
38
+ TransformReferenceGuide,
39
+ TransformDocs,
40
+ TransformDocPage,
41
+ TransformReference,
42
+ ConfigurableHooks,
43
+ ReferenceGuidePageData,
44
+ DocPageData,
45
+ DocPageReference,
46
+ Skip,
47
+ ConfigurableDocPageData,
48
+ ConfigurableDocPageReference,
49
+ };