Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ apexdocs-generate

The CLI supports the following parameters:

| Parameter | Alias | Description | Default | Required |
| ----------------- | ----- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- |
| --sourceDir | -s | The directory location which contains your apex .cls classes. | N/A | Yes |
| --targetDir | -t | The directory location where documentation will be generated to. | `docs` | No |
| --recursive | -r | Whether .cls classes will be searched for recursively in the directory provided. | `true` | No |
| --scope | -p | A list of scopes to document. Values should be separated by a space, e.g --scope public private | `global namespaceaccessible public` | No |
| --targetGenerator | -g | Define the static file generator for which the documents will be created. Currently supports jekyll and docsify. | `jekyll` | No |
| --configPath | -c | The path to the JSON configuration file that defines the structure of the documents to docGenerator. | N/A | No |
| --group | -o | Define whether the generated files should be grouped by the @group tag on the top level classes. | `true` | No |
| Parameter | Alias | Description | Default | Required |
| ----------------- | ----- |--------------------------------------------------------------------------------------------------------------------------| ----------------------------------- | -------- |
| --sourceDir | -s | The directory location which contains your apex .cls classes. | N/A | Yes |
| --targetDir | -t | The directory location where documentation will be generated to. | `docs` | No |
| --recursive | -r | Whether .cls classes will be searched for recursively in the directory provided. | `true` | No |
| --scope | -p | A list of scopes to document. Values should be separated by a space, e.g --scope public private | `global namespaceaccessible public` | No |
| --targetGenerator | -g | Define the static file generator for which the documents will be created. Currently supports jekyll and docsify. | `jekyll` | No |
| --configPath | -c | (Only versions 1.X) The path to the JSON configuration file that defines the structure of the documents to docGenerator. | N/A | No |
| --group | -o | (Only versions 1.X) Define whether the generated files should be grouped by the @group tag on the top level classes. | `true` | No |

#### Configuration File

Expand Down Expand Up @@ -314,6 +314,34 @@ The following tags are supported on the method level:
public static Object call(String action) {
```

### Grouping Declarations Within A Class

A class might have members that should be grouped together. For example, you can have a class for constants with
groups of constants that should be grouped together because they share a common behavior (e.g. different groups
of constants representing the possible values for different picklists.)

You can group things together within a class by using the following syntax:
```apex
// @start-group Group Name or Description
public static final String CONSTANT_FOO = 'Foo';
public static final String CONSTANT_BAR = 'Bar';
// @end-group
```

Groups of members are displayed together under their own subsection after its name or description.

Some notes about grouping:
* This is only supported on classes, NOT enums and interfaces
* Supports
* Properties
* Fields (variables and constants)
* Constructors
* Methods
* BUT only members of the same type are grouped together. For example,
if you have a group that contains properties and methods the properties will be grouped together under Properties -> Group Name, and the methods will be grouped together under Methods -> Group Name
* Does not support inner types (inner classes, interfaces, and enums)
* It is necessary to use `// @end-group` whenever a group has been started, otherwise a parsing error will be raised for that file.

### Inline linking

Apexdocs allows you to reference other classes from anywhere in your docs, and automatically creates a link to that
Expand Down
31 changes: 19 additions & 12 deletions docs/Sample-Classes/SampleClass.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ This is a class description. This class relates to [SampleInterface](/Sample-Int
**See** [SampleInterface](/Sample-Interfaces/SampleInterface.md)

## Constructors
### `SampleClass()`
### My Super Group
##### `SampleClass()`

`NAMESPACEACCESSIBLE`

Constructs a SampleClass without any arguments. This relates to [SampleInterface](/Sample-Interfaces/SampleInterface.md)

#### Throws
###### Throws
|Exception|Description|
|---|---|
|`ExcName`|some exception|
Expand All @@ -33,41 +34,45 @@ Constructs a SampleClass without any arguments. This relates to [SampleInterface

**See** [SampleInterface](/Sample-Interfaces/SampleInterface.md)

#### Example
###### Example
```apex
// Example
SampleClass sampleInstance = new SampleClass();
```

### `SampleClass(String argument)`
---
### Other
##### `SampleClass(String argument)`

Constructs a SampleClass with an argument.

#### Parameters
###### Parameters
|Param|Description|
|---|---|
|`argument`|Argument definition|
---
## Fields
### Common Constants

### `A_CONSTANT` → `String`

This is a constant.

### `someVariable` → `String`
* `ANOTHER_CONSTANT` → `String`
* `A_CONSTANT` → `String` [`NAMESPACEACCESSIBLE` ] - This is a constant.
---
### Other variables

* `someVariable` → `String`
---
## Properties

### `AnotherProp` → `Decimal`

`AURAENABLED`
`AURAENABLED`

This is a Decimal property.

### `MyProp` → `String`

`AURAENABLED`
`AURAENABLED`
`DEPRECATED`

This is a String property.

Expand Down Expand Up @@ -122,6 +127,7 @@ Inner class belonging to SampleClass.

##### `InnerProp` → `String`


Description of the inner property.

---
Expand All @@ -140,6 +146,7 @@ Inner class belonging to SampleClass.

##### `InnerProp` → `String`


Description of the inner property.

---
Expand Down
10 changes: 10 additions & 0 deletions examples/force-app/main/default/classes/SampleClass.cls
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ public with sharing class SampleClass {
C
}

// @start-group Common Constants
/**
* @description This is a constant.
*/
@NamespaceAccessible
public static final String A_CONSTANT = 'My Constant Value';
public static final String ANOTHER_CONSTANT = 'My Constant Value';
// @end-group

// @start-group Other variables
public String someVariable = 'test';
// @end-group

// @start-group My Super Group
/**
* @description Constructs a SampleClass without any arguments. This relates to {@link SampleInterface}
* @throws ExcName some exception
Expand All @@ -38,6 +46,7 @@ public with sharing class SampleClass {
public SampleClass() {
System.debug('Constructor');
}
// @end-group

/**
* @description Constructs a SampleClass with an argument.
Expand Down Expand Up @@ -73,6 +82,7 @@ public with sharing class SampleClass {
* @description This is a String property.
*/
@AuraEnabled
@Deprecated
public String MyProp { get; set; }

/**
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cparra/apexdocs",
"version": "2.0.2",
"version": "2.1.0",
"description": "Library with CLI capabilities to generate documentation for Salesforce Apex classes.",
"keywords": [
"apex",
Expand Down Expand Up @@ -63,7 +63,7 @@
]
},
"dependencies": {
"@cparra/apex-reflection": "^1.0.0",
"@cparra/apex-reflection": "^1.1.1",
"chalk": "^4.1.2",
"html-entities": "^2.3.2",
"yargs": "^16.0.3"
Expand Down
4 changes: 4 additions & 0 deletions src/model/markdown-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export class MarkdownFile extends File {
});
}

addListItem(text: string) {
this._contents += `* ${text}`;
}

protected static replaceInlineLinks(text: string) {
// Parsing text to extract possible linking classes.
const possibleLinks = text.match(/<<.*?>>/g);
Expand Down
44 changes: 33 additions & 11 deletions src/model/markdown-generation-util/field-declaration-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { MarkdownFile } from '../markdown-file';
import { FieldMirror, PropertyMirror } from '@cparra/apex-reflection';

export function declareField(
title: string,
markdownFile: MarkdownFile,
fields: FieldMirror[] | PropertyMirror[],
startingHeadingLevel: number,
grouped = false,
) {
markdownFile.addTitle(title, startingHeadingLevel + 1);
markdownFile.addBlankLine();
fields
.sort((propA, propB) => {
Expand All @@ -16,27 +15,50 @@ export function declareField(
return 0;
})
.forEach((propertyModel) => {
addFieldSection(markdownFile, propertyModel, startingHeadingLevel);
addFieldSection(markdownFile, propertyModel, startingHeadingLevel, grouped);
});

markdownFile.addHorizontalRule();
}

function addFieldSection(
markdownFile: MarkdownFile,
propertyModel: FieldMirror | PropertyMirror,
mirrorModel: FieldMirror | PropertyMirror,
startingHeadingLevel: number,
grouped: boolean,
) {
markdownFile.addTitle(`\`${propertyModel.name}\` → \`${propertyModel.type}\``, startingHeadingLevel + 2);
if (!grouped) {
markdownFile.addTitle(`\`${mirrorModel.name}\` → \`${mirrorModel.type}\``, startingHeadingLevel + 2);
markdownFile.addBlankLine();

mirrorModel.annotations.forEach((annotation) => {
markdownFile.addText(`\`${annotation.type.toUpperCase()}\` `);
});

propertyModel.annotations.forEach((annotation) => {
if (mirrorModel.docComment?.description) {
markdownFile.addBlankLine();
markdownFile.addText(mirrorModel.docComment.description);
}
markdownFile.addBlankLine();
markdownFile.addText(`\`${annotation.type.toUpperCase()}\``);
});
} else {
let annotations = '';
const hasAnnotations = !!mirrorModel.annotations.length;
if (hasAnnotations) {
annotations += ' [';
}
mirrorModel.annotations.forEach((annotation) => {
annotations += `\`${annotation.type.toUpperCase()}\` `;
});
if (hasAnnotations) {
annotations += ']';
}

if (propertyModel.docComment?.description) {
// If grouped we want to display these as a list
let description = '';
if (mirrorModel.docComment?.description) {
description = ` - ${mirrorModel.docComment?.description}`;
}
markdownFile.addListItem(`\`${mirrorModel.name}\` → \`${mirrorModel.type}\`${annotations} ${description}`);
markdownFile.addBlankLine();
markdownFile.addText(propertyModel.docComment.description);
}
markdownFile.addBlankLine();
}
2 changes: 0 additions & 2 deletions src/model/markdown-generation-util/method-declaration-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { ParameterMirror } from '@cparra/apex-reflection/index';
import { addCustomDocCommentAnnotations } from './doc-comment-annotation-util';

export function declareMethod(
title: string,
markdownFile: MarkdownFile,
methods: ConstructorMirror[] | MethodMirror[],
startingHeadingLevel: number,
className = '',
): void {
markdownFile.addTitle(title, startingHeadingLevel + 1);
methods.forEach((currentMethod) => {
const signatureName = isMethod(currentMethod) ? (currentMethod as MethodMirror).name : className;
markdownFile.addTitle(`\`${buildSignature(signatureName, currentMethod)}\``, startingHeadingLevel + 2);
Expand Down
4 changes: 1 addition & 3 deletions src/model/markdown-generation-util/type-declaration-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { MarkdownFile } from '../markdown-file';
import { addCustomDocCommentAnnotations } from './doc-comment-annotation-util';
import { Annotation, Type } from '@cparra/apex-reflection';

export function declareType(markdownFile: MarkdownFile, typeMirror: Type, startingHeadingLevel: number): void {
markdownFile.addTitle(typeMirror.name, startingHeadingLevel);

export function declareType(markdownFile: MarkdownFile, typeMirror: Type): void {
typeMirror.annotations.forEach((currentAnnotation: Annotation) => {
markdownFile.addBlankLine();
markdownFile.addText(`\`${currentAnnotation.type.toUpperCase()}\``);
Expand Down
Loading