Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add new site config option siteConfig.markdown.anchors.maintainCase #10064

Merged
merged 9 commits into from
Apr 25, 2024
12 changes: 4 additions & 8 deletions packages/docusaurus-mdx-loader/src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ type SimpleProcessor = {
}) => Promise<SimpleProcessorResult>;
};

async function getDefaultRemarkPlugins(): Promise<MDXPlugin[]> {
const {default: emoji} = await import('remark-emoji');
return [headings, emoji, toc];
}

export type MDXPlugin = Pluggable;

export type MDXOptions = {
Expand Down Expand Up @@ -86,8 +81,7 @@ async function createProcessorFactory() {
const {default: comment} = await import('@slorber/remark-comment');
const {default: directive} = await import('remark-directive');
const {VFile} = await import('vfile');

const defaultRemarkPlugins = await getDefaultRemarkPlugins();
const {default: emoji} = await import('remark-emoji');

// /!\ this method is synchronous on purpose
// Using async code here can create cache entry race conditions!
Expand All @@ -104,7 +98,9 @@ async function createProcessorFactory() {
directive,
[contentTitle, {removeContentTitle: options.removeContentTitle}],
...getAdmonitionsPlugins(options.admonitions ?? false),
...defaultRemarkPlugins,
[headings, options.markdownConfig.anchors],
emoji,
toc,
details,
head,
...(options.markdownConfig.mermaid ? [mermaid] : []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,19 @@ import {removePosition} from 'unist-util-remove-position';
import {toString} from 'mdast-util-to-string';
import {visit} from 'unist-util-visit';
import slug from '../index';
import type {PluginOptions} from '../index';
import type {Plugin} from 'unified';
import type {Parent} from 'unist';

async function process(doc: string, plugins: Plugin[] = []) {
async function process(
doc: string,
plugins: Plugin[] = [],
options: PluginOptions = {maintainCase: false},
) {
const {remark} = await import('remark');
const processor = await remark().use({plugins: [...plugins, slug]});
const processor = await remark().use({
plugins: [...plugins, [slug, options]],
});
const result = await processor.run(processor.parse(doc));
removePosition(result, {force: true});
return result;
Expand Down Expand Up @@ -312,4 +319,20 @@ describe('headings remark plugin', () => {
},
]);
});

it('preserve anchors case then "maintainCase" option is set', async () => {
const result = await process('# Normal\n', [], {maintainCase: true});
const expected = u('root', [
u(
'heading',
{
depth: 1,
data: {hProperties: {id: 'Normal'}, id: 'Normal'},
},
[u('text', 'Normal')],
),
]);

expect(result).toEqual(expected);
});
});
10 changes: 8 additions & 2 deletions packages/docusaurus-mdx-loader/src/remark/headings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ import {parseMarkdownHeadingId, createSlugger} from '@docusaurus/utils';
import type {Transformer} from 'unified';
import type {Heading, Text} from 'mdast';

export default function plugin(): Transformer {
export interface PluginOptions {
maintainCase: boolean;
}

export default function plugin(
{maintainCase}: PluginOptions = {maintainCase: false},
): Transformer {
return async (root) => {
const {toString} = await import('mdast-util-to-string');
const {visit} = await import('unist-util-visit');
Expand All @@ -38,7 +44,7 @@ export default function plugin(): Transformer {
// Support explicit heading IDs
const parsedHeading = parseMarkdownHeadingId(heading);

id = parsedHeading.id ?? slugs.slug(heading);
id = parsedHeading.id ?? slugs.slug(heading, {maintainCase});

if (parsedHeading.id) {
// When there's an id, it is always in the last child node
Expand Down
7 changes: 7 additions & 0 deletions packages/docusaurus-types/src/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ export type MarkdownConfig = {
* See also https://github.com/remarkjs/remark-rehype#options
*/
remarkRehypeOptions: RemarkRehypeOptions;

anchors?: {
/**
* Ability to preserve the case of the heading anchor links.
*/
maintainCase: boolean;
};
};

/**
Expand Down
6 changes: 6 additions & 0 deletions website/docs/api/docusaurus.config.js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,9 @@ type MarkdownConfig = {
parseFrontMatter?: ParseFrontMatter;
mdx1Compat: MDX1CompatOptions;
remarkRehypeOptions: object; // see https://github.com/remarkjs/remark-rehype#options
anchors?: {
maintainCase: boolean;
};
};
```

Expand All @@ -469,6 +472,9 @@ export default {
admonitions: true,
headingIds: true,
},
anchors: {
maintainCase: true,
},
},
};
```
Expand Down
Loading