Skip to content

Commit

Permalink
feat(core): always assign header ids to linkable symbols within table…
Browse files Browse the repository at this point in the history
… rows
  • Loading branch information
tgreyuk committed Dec 27, 2024
1 parent 5fd0f09 commit 640b9ca
Show file tree
Hide file tree
Showing 20 changed files with 156 additions and 172 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-pigs-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'typedoc-plugin-markdown': minor
---

- Always assign header ids to linkable symbols within table rows.
2 changes: 1 addition & 1 deletion docs/pages/docs/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ Options that are used for general configuration and utility purposes.
| [`publicPath`](./options/utility-options.mdx#--publicpath) | Specify the base path for all urls. |
| [`anchorPrefix`](./options/utility-options.mdx#--anchorprefix) | Custom anchor prefix when anchoring to in-page symbols. |
| [`useHTMLEncodedBrackets`](./options/utility-options.mdx#--usehtmlencodedbrackets) | Use HTML encoded entities for angle brackets. |
| [`useHTMLAnchors`](./options/utility-options.mdx#--usehtmlanchors) | Add HTML named anchors to headings and table rows. |
| [`useHTMLAnchors`](./options/utility-options.mdx#--usehtmlanchors) | Add HTML anchors to page headings. |
| [`preserveAnchorCasing`](./options/utility-options.mdx#--preserveanchorcasing) | Preserve anchor casing when generating link to symbols. |
| [`pageTitleTemplates`](./options/utility-options.mdx#--pagetitletemplates) | Change specific text placeholders in the template. |
9 changes: 5 additions & 4 deletions docs/pages/docs/options/utility-options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,15 @@ However, using HTML entities (`<` and `>`) might be preferable to avoid an

## --useHTMLAnchors

<Callout emoji="💡">Add HTML named anchors to headings and table rows.</Callout>
<Callout emoji="💡">Add HTML anchors to page headings.</Callout>

> Accepts a boolean value. Defaults to `false`.
This option should be used if there are issues when anchoring to symbols within a page.
By default markdown parsers normally assign header IDs to headings automatically.
This is required when cross linking to symbols within a page.
This option should be used when parsers that do not automatically assign header IDs.

- For Markdown parsers that do not automatically assign header ids.
- When cross referencing symbols that are referenced in a table row.
Note that HTML anchors will be added to linkable symbols listed in table rows as there is no alternative way to anchor to these items.

```json filename="typedoc.json"
{
Expand Down
9 changes: 5 additions & 4 deletions packages/typedoc-plugin-markdown/src/options/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,15 +649,16 @@ export const useHTMLEncodedBrackets: Partial<DeclarationOption> = {
};

/**
* This option should be used if there are issues when anchoring to symbols within a page.
* By default markdown parsers normally assign header IDs to headings automatically.
* This is required when cross linking to symbols within a page.
* This option should be used when parsers that do not automatically assign header IDs.
*
* - For Markdown parsers that do not automatically assign header ids.
* - When cross referencing symbols that are referenced in a table row.
* Note that HTML anchors will be added to linkable symbols listed in table rows as there is no alternative way to anchor to these items.
*
* @category Utility
*/
export const useHTMLAnchors: Partial<DeclarationOption> = {
help: 'Add HTML named anchors to headings and table rows.',
help: 'Add HTML anchors to page headings.',
type: ParameterType.Boolean,
defaultValue: false,
};
Expand Down
81 changes: 25 additions & 56 deletions packages/typedoc-plugin-markdown/src/theme/base/url-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,28 +514,34 @@ export class UrlBuilder {
);
}

private applyAnchorUrl(
reflection: DeclarationReflection,
containerUrl: string,
) {
private applyAnchorUrl(reflection: Reflection, containerUrl: string) {
const anchorPrefix = this.options.getValue('anchorPrefix');
const anchorId = this.getAnchorId(reflection);

if (anchorId) {
if (!this.anchors[containerUrl]) {
this.anchors[containerUrl] = [];
}

this.anchors[containerUrl].push(anchorId);
if (!this.anchors[containerUrl]) {
this.anchors[containerUrl] = [];
}

if (anchorId) {
const count = this.anchors[containerUrl]?.filter(
(id) => id === anchorId,
)?.length;

const anchorParts = [anchorId];
let anchorParts: string[] = [];

if (count > 1) {
anchorParts.push(`-${count - 1}`);
if (
reflection.parent?.parent?.kind === ReflectionKind.Property &&
reflection.kind === ReflectionKind.Property
) {
const anchorMatch = containerUrl.match(/#(.*)$/);
const anchor = anchorMatch ? anchorMatch[1] : '';
anchorParts = [anchor];
} else {
this.anchors[containerUrl].push(anchorId);
anchorParts = [anchorId];
if (count > 0) {
anchorParts.push(`-${count}`);
}
}

if (anchorPrefix) {
Expand All @@ -558,7 +564,7 @@ export class UrlBuilder {
}
}

private getAnchorId(reflection: DeclarationReflection) {
private getAnchorId(reflection: Reflection) {
const preserveAnchorCasing = this.options.getValue('preserveAnchorCasing');

const anchorName = this.getAnchorName(reflection);
Expand All @@ -570,55 +576,18 @@ export class UrlBuilder {
return null;
}

private getAnchorName(reflection: DeclarationReflection) {
private getAnchorName(reflection: Reflection) {
if ([ReflectionKind.TypeParameter].includes(reflection.kind)) {
return null;
}
const htmlTableAnchors = this.options.getValue('useHTMLAnchors');

if (!htmlTableAnchors) {
if (
(reflection.kind === ReflectionKind.Property &&
this.options
.getValue('propertiesFormat')
.toLowerCase()
.includes('table')) ||
(reflection.kind === ReflectionKind.Property &&
reflection.parent?.kind === ReflectionKind.TypeLiteral &&
this.options
.getValue('typeDeclarationFormat')
.toLowerCase()
.includes('table')) ||
(reflection.kind === ReflectionKind.Property &&
reflection.parent?.kind === ReflectionKind.Class &&
this.options
.getValue('classPropertiesFormat')
.toLowerCase()
.includes('table')) ||
(reflection.kind === ReflectionKind.Property &&
reflection.parent?.kind === ReflectionKind.Interface &&
this.options
.getValue('interfacePropertiesFormat')
.toLowerCase()
.includes('table')) ||
(reflection.kind === ReflectionKind.EnumMember &&
this.options
.getValue('enumMembersFormat')
.toLowerCase()
.includes('table'))
) {
return null;
}
}
if (reflection.kind === ReflectionKind.Constructor) {
return 'Constructors';
}
const anchorParts = [reflection.name];
if (reflection.typeParameters?.length) {
const anchorParts = [reflection.name.replace(/[\\[\]]/g, '')];
const typeParams = (reflection as DeclarationReflection)?.typeParameters;
if (typeParams?.length) {
anchorParts.push(
reflection.typeParameters
.map((typeParameter) => typeParameter.name)
.join('-'),
typeParams?.map((typeParameter) => typeParameter.name).join('-'),
);
}
return anchorParts.join('');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function enumMembersTable(
const row: string[] = [];
const nameColumn: string[] = [];

if (this.options.getValue('useHTMLAnchors') && property.anchor) {
if (property.anchor) {
nameColumn.push(`<a id="${property.anchor}"></a>`);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function propertiesTable(

const nameColumn: string[] = [];

if (this.options.getValue('useHTMLAnchors') && property.anchor) {
if (property.anchor) {
nameColumn.push(`<a id="${property.anchor}"></a>`);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function typeDeclarationTable(

const nameColumn: string[] = [];

if (this.options.getValue('useHTMLAnchors') && declaration.anchor) {
if (declaration.anchor) {
nameColumn.push(`<a id="${declaration.anchor}"></a>`);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/typedoc-plugin-markdown/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export interface PluginOptions {
useCodeBlocks: boolean;

/**
* Add HTML named anchors to headings and table rows.
* Add HTML anchors to page headings.
*/
useHTMLAnchors: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
* - {@link SameName.prop}
* - {@link TypeWithGenerics}
* - {@link TypeDeclarationType}
* - {@link TypeDeclarationType#declaration1 | Links to declaration1}
* - {@link TypeDeclarationType#declaration1}
* - {@link TypeDeclarationType2#declaration1}
*
* External links:
*
Expand Down Expand Up @@ -251,16 +252,21 @@ export interface InterfacePropertiesTable extends BaseInterfaceProperties {

export type TypeDeclarationType = {
/**
* The subroutine recursively parsed the hexadecimal data.
* to generate the binary output for input validation.
* Comments for declaration1
*/
declaration1: boolean;
/**
* The subroutine recursively parsed the hexadecimal data.
* to generate the binary output for input validation.
* Comments for declaration2
*/
declaration2: boolean;
declaration4: 100;
declaration3: 100;
};

export type TypeDeclarationType2 = {
/**
* Comments for declaration1
*/
declaration1: boolean;
};

export const TypeDeclarationConst = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ exports[`Comments should compile @links with anchors: (Output File Strategy "mod
- [SameName.prop](README.md#prop-2)
- [TypeWithGenerics](README.md#typewithgenericsc-d)
- [TypeDeclarationType](README.md#typedeclarationtype)
- [Links to declaration1](README.md#declaration1)
"
- [TypeDeclarationType#declaration1](README.md#declaration1)
- [TypeDeclarationType2#declaration1](README.md#declaration1-1)"
`;

exports[`Comments should compile comments for module: (Output File Strategy "members") (Option Group "1") 1`] = `
Expand All @@ -30,7 +30,8 @@ Links using \`{@link}\` inline tags.
- [SameName.prop](interfaces/SameName.md#prop)
- [TypeWithGenerics](type-aliases/TypeWithGenerics.md)
- [TypeDeclarationType](type-aliases/TypeDeclarationType.md)
- [Links to declaration1](type-aliases/TypeDeclarationType.md#declaration1)
- [TypeDeclarationType#declaration1](type-aliases/TypeDeclarationType.md#declaration1)
- [TypeDeclarationType2#declaration1](type-aliases/TypeDeclarationType2.md#declaration1)
External links:
Expand Down Expand Up @@ -104,6 +105,7 @@ Some <p> html </p> inside codeblock
## Type Aliases
- [TypeDeclarationType](type-aliases/TypeDeclarationType.md)
- [TypeDeclarationType2](type-aliases/TypeDeclarationType2.md)
- [typeWithBlockTags](type-aliases/typeWithBlockTags.md)
- [TypeWithGenerics](type-aliases/TypeWithGenerics.md)
Expand Down Expand Up @@ -512,9 +514,9 @@ exports[`Comments should get tables for type declarations: (Output File Strategy
| Name | Type | Description | Defined in |
| ------ | ------ | ------ | ------ |
| <a id="declaration1"></a> \`declaration1\` | \`boolean\` | The subroutine recursively parsed the hexadecimal data. to generate the binary output for input validation. | [index.ts:1](http://source-url) |
| <a id="declaration2"></a> \`declaration2\` | \`boolean\` | The subroutine recursively parsed the hexadecimal data. to generate the binary output for input validation. | [index.ts:1](http://source-url) |
| <a id="declaration4"></a> \`declaration4\` | \`100\` | - | [index.ts:1](http://source-url) |
| <a id="declaration1"></a> \`declaration1\` | \`boolean\` | Comments for declaration1 | [index.ts:1](http://source-url) |
| <a id="declaration2"></a> \`declaration2\` | \`boolean\` | Comments for declaration2 | [index.ts:1](http://source-url) |
| <a id="declaration3"></a> \`declaration3\` | \`100\` | - | [index.ts:1](http://source-url) |
"
`;
Expand All @@ -537,7 +539,7 @@ exports[`Comments should get tables for type declarations: (Output File Strategy
exports[`Comments should get tables for type declarations: (Output File Strategy "members") (Option Group "2") 1`] = `
"# Type Alias: TypeDeclarationType
> **TypeDeclarationType**: \\{ \`declaration1\`: \`boolean\`; \`declaration2\`: \`boolean\`; \`declaration4\`: \`100\`; \\}
> **TypeDeclarationType**: \\{ \`declaration1\`: \`boolean\`; \`declaration2\`: \`boolean\`; \`declaration3\`: \`100\`; \\}
**Defined in**: [index.ts:1](http://source-url)
Expand Down Expand Up @@ -565,8 +567,7 @@ exports[`Comments should get tables for type declarations: (Output File Strategy
</td>
<td>
The subroutine recursively parsed the hexadecimal data.
to generate the binary output for input validation.
Comments for declaration1
</td>
</tr>
Expand All @@ -583,15 +584,14 @@ to generate the binary output for input validation.
</td>
<td>
The subroutine recursively parsed the hexadecimal data.
to generate the binary output for input validation.
Comments for declaration2
</td>
</tr>
<tr>
<td>
<a id="declaration4"></a> \`declaration4\`
<a id="declaration3"></a> \`declaration3\`
</td>
<td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,18 @@ Comments for BasicInterface
| Property | Type | Description |
| :------ | :------ | :------ |
| ~~\`deprecatedProp\`~~ | \`string\` | **Deprecated** This prop is deprecated **See** Comments for some tag |
| \`functionProp\` | (\`s\`: \`string\`) => \`boolean\` | Comments for functionProper |
| \`optionalProp?\` | \`string\` | Comments for optional prop |
| \`prop\` | \`string\` | Comments for prop |
| \`propReturningObjectDeclaration\` | \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\} | Comments for propReturningObjectDeclaration |
| <a id="deprecatedprop"></a> ~~\`deprecatedProp\`~~ | \`string\` | **Deprecated** This prop is deprecated **See** Comments for some tag |
| <a id="functionprop"></a> \`functionProp\` | (\`s\`: \`string\`) => \`boolean\` | Comments for functionProper |
| <a id="optionalprop"></a> \`optionalProp?\` | \`string\` | Comments for optional prop |
| <a id="prop"></a> \`prop\` | \`string\` | Comments for prop |
| <a id="propreturningobjectdeclaration"></a> \`propReturningObjectDeclaration\` | \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\} | Comments for propReturningObjectDeclaration |
| \`propReturningObjectDeclaration.a\` | \`boolean\` | - |
| \`propReturningObjectDeclaration.b\` | \`string\` | - |
| \`propReturningObjectDeclarations\` | \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\} & \\{ \`c\`: \`boolean\`; \`d\`: \`string\`; \\} | Comments for propReturningObjectDeclarations |
| \`propReturningSignatureDeclaration?\` | () => \`string\` \\| \`number\` \\| \`boolean\` | Comments for propReturningSignatureDeclaration |
| \`propReturningSignatureDeclarations\` | () => \`any\` & (\`paramsA\`: \`true\` \\| \`any\`[], \`paramsB\`?: \`any\`) => \`any\` & (\`paramsC\`: \`any\`) => \`any\` | Comments for propReturningSignatureDeclarations |
| \`propWithFunction\` | (\`options\`: \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\}) => \`boolean\` | Comments for propWithFunction |
| \`propWithProps\` | \\{ \`callbacks\`: \`Partial\`\\<[\`CallbacksOptions\`](../classes/CallbacksOptions.md)\\>; \`nestedPropA\`: \`string\`; \`nestedPropB\`: \`boolean\`; \`nestedPropC\`: \\{ \`nestedPropCA\`: \`string\`; \\}; \`nestedPropD\`: () => \`boolean\`; \\} | Comments for propWithProps |
| <a id="propreturningobjectdeclarations"></a> \`propReturningObjectDeclarations\` | \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\} & \\{ \`c\`: \`boolean\`; \`d\`: \`string\`; \\} | Comments for propReturningObjectDeclarations |
| <a id="propreturningsignaturedeclaration"></a> \`propReturningSignatureDeclaration?\` | () => \`string\` \\| \`number\` \\| \`boolean\` | Comments for propReturningSignatureDeclaration |
| <a id="propreturningsignaturedeclarations"></a> \`propReturningSignatureDeclarations\` | () => \`any\` & (\`paramsA\`: \`true\` \\| \`any\`[], \`paramsB\`?: \`any\`) => \`any\` & (\`paramsC\`: \`any\`) => \`any\` | Comments for propReturningSignatureDeclarations |
| <a id="propwithfunction"></a> \`propWithFunction\` | (\`options\`: \\{ \`a\`: \`boolean\`; \`b\`: \`string\`; \\}) => \`boolean\` | Comments for propWithFunction |
| <a id="propwithprops"></a> \`propWithProps\` | \\{ \`callbacks\`: \`Partial\`\\<[\`CallbacksOptions\`](../classes/CallbacksOptions.md)\\>; \`nestedPropA\`: \`string\`; \`nestedPropB\`: \`boolean\`; \`nestedPropC\`: \\{ \`nestedPropCA\`: \`string\`; \\}; \`nestedPropD\`: () => \`boolean\`; \\} | Comments for propWithProps |
| \`propWithProps.callbacks?\` | \`Partial\`\\<[\`CallbacksOptions\`](../classes/CallbacksOptions.md)\\> | Comments for callbacks |
| \`propWithProps.nestedPropA\` | \`string\` | Comments for nestedPropA |
| \`propWithProps.nestedPropB\` | \`boolean\` | Comments for nestedPropB |
Expand Down
Loading

0 comments on commit 640b9ca

Please sign in to comment.