mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-11 08:07:26 +02:00
fix(content-blog): make footnote reference DOM ID unique on post listing page (#7212)
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
parent
3b32a41f22
commit
71ba449a28
10 changed files with 197 additions and 1 deletions
|
@ -31,6 +31,7 @@
|
||||||
"reading-time": "^1.5.0",
|
"reading-time": "^1.5.0",
|
||||||
"remark-admonitions": "^1.2.1",
|
"remark-admonitions": "^1.2.1",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.3.1",
|
||||||
|
"unist-util-visit": "^2.0.3",
|
||||||
"utility-types": "^3.10.0",
|
"utility-types": "^3.10.0",
|
||||||
"webpack": "^5.72.0"
|
"webpack": "^5.72.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import admonitions from 'remark-admonitions';
|
import admonitions from 'remark-admonitions';
|
||||||
|
import footnoteIDFixer from './remark/footnoteIDFixer';
|
||||||
import {
|
import {
|
||||||
normalizeUrl,
|
normalizeUrl,
|
||||||
docuHash,
|
docuHash,
|
||||||
|
@ -435,7 +436,10 @@ export default async function pluginContentBlog(
|
||||||
options: {
|
options: {
|
||||||
remarkPlugins,
|
remarkPlugins,
|
||||||
rehypePlugins,
|
rehypePlugins,
|
||||||
beforeDefaultRemarkPlugins,
|
beforeDefaultRemarkPlugins: [
|
||||||
|
footnoteIDFixer,
|
||||||
|
...beforeDefaultRemarkPlugins,
|
||||||
|
],
|
||||||
beforeDefaultRehypePlugins,
|
beforeDefaultRehypePlugins,
|
||||||
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
||||||
path.resolve(siteDir, dir),
|
path.resolve(siteDir, dir),
|
||||||
|
|
9
packages/docusaurus-plugin-content-blog/src/remark/__tests__/__fixtures__/post.md
generated
Normal file
9
packages/docusaurus-plugin-content-blog/src/remark/__tests__/__fixtures__/post.md
generated
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
foo[^1]
|
||||||
|
|
||||||
|
bar[^2]
|
||||||
|
|
||||||
|
baz[^3]
|
||||||
|
|
||||||
|
[^1]: foo
|
||||||
|
[^2]: foo
|
||||||
|
[^3]: foo
|
9
packages/docusaurus-plugin-content-blog/src/remark/__tests__/__fixtures__/post2.md
generated
Normal file
9
packages/docusaurus-plugin-content-blog/src/remark/__tests__/__fixtures__/post2.md
generated
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
foo[^1]
|
||||||
|
|
||||||
|
bar[^2]
|
||||||
|
|
||||||
|
baz[^3]
|
||||||
|
|
||||||
|
[^1]: foo
|
||||||
|
[^2]: foo
|
||||||
|
[^3]: foo
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`footnoteIDFixer remark plugin appends a hash to each footnote def/ref 1`] = `
|
||||||
|
"/* @jsxRuntime classic */
|
||||||
|
/* @jsx mdx */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const layoutProps = {
|
||||||
|
|
||||||
|
};
|
||||||
|
const MDXLayout = "wrapper"
|
||||||
|
export default function MDXContent({
|
||||||
|
components,
|
||||||
|
...props
|
||||||
|
}) {
|
||||||
|
return <MDXLayout {...layoutProps} {...props} components={components} mdxType="MDXLayout">
|
||||||
|
<p>{\`foo\`}<sup parentName="p" {...{
|
||||||
|
"id": "fnref-1-[HASH]"
|
||||||
|
}}><a parentName="sup" {...{
|
||||||
|
"href": "#fn-1-[HASH]",
|
||||||
|
"className": "footnote-ref"
|
||||||
|
}}>{\`1\`}</a></sup></p>
|
||||||
|
<p>{\`bar\`}<sup parentName="p" {...{
|
||||||
|
"id": "fnref-2-[HASH]"
|
||||||
|
}}><a parentName="sup" {...{
|
||||||
|
"href": "#fn-2-[HASH]",
|
||||||
|
"className": "footnote-ref"
|
||||||
|
}}>{\`2\`}</a></sup></p>
|
||||||
|
<p>{\`baz\`}<sup parentName="p" {...{
|
||||||
|
"id": "fnref-3-[HASH]"
|
||||||
|
}}><a parentName="sup" {...{
|
||||||
|
"href": "#fn-3-[HASH]",
|
||||||
|
"className": "footnote-ref"
|
||||||
|
}}>{\`3\`}</a></sup></p>
|
||||||
|
<div {...{
|
||||||
|
"className": "footnotes"
|
||||||
|
}}>
|
||||||
|
<hr parentName="div"></hr>
|
||||||
|
<ol parentName="div">
|
||||||
|
<li parentName="ol" {...{
|
||||||
|
"id": "fn-1-[HASH]"
|
||||||
|
}}>{\`foo\`}<a parentName="li" {...{
|
||||||
|
"href": "#fnref-1-[HASH]",
|
||||||
|
"className": "footnote-backref"
|
||||||
|
}}>{\`↩\`}</a></li>
|
||||||
|
<li parentName="ol" {...{
|
||||||
|
"id": "fn-2-[HASH]"
|
||||||
|
}}>{\`foo\`}<a parentName="li" {...{
|
||||||
|
"href": "#fnref-2-[HASH]",
|
||||||
|
"className": "footnote-backref"
|
||||||
|
}}>{\`↩\`}</a></li>
|
||||||
|
<li parentName="ol" {...{
|
||||||
|
"id": "fn-3-[HASH]"
|
||||||
|
}}>{\`foo\`}<a parentName="li" {...{
|
||||||
|
"href": "#fnref-3-[HASH]",
|
||||||
|
"className": "footnote-backref"
|
||||||
|
}}>{\`↩\`}</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</MDXLayout>;
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
MDXContent.isMDXComponent = true;"
|
||||||
|
`;
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
import path from 'path';
|
||||||
|
import {simpleHash} from '@docusaurus/utils';
|
||||||
|
import mdx from '@mdx-js/mdx';
|
||||||
|
import footnoteIDFixer from '../footnoteIDFixer';
|
||||||
|
|
||||||
|
const processFixture = async (name: string) => {
|
||||||
|
const filepath = path.join(__dirname, `__fixtures__/${name}.md`);
|
||||||
|
const result = await mdx(await fs.readFile(filepath), {
|
||||||
|
filepath,
|
||||||
|
remarkPlugins: [footnoteIDFixer],
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('footnoteIDFixer remark plugin', () => {
|
||||||
|
it('appends a hash to each footnote def/ref', async () => {
|
||||||
|
const hash = simpleHash(path.join(__dirname, `__fixtures__/post.md`), 6);
|
||||||
|
expect(
|
||||||
|
(await processFixture('post')).replace(new RegExp(hash, 'g'), '[HASH]'),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('produces different hashes for different posts but same hash for the same path', async () => {
|
||||||
|
const file1 = await processFixture('post');
|
||||||
|
const file1again = await processFixture('post');
|
||||||
|
const file2 = await processFixture('post2');
|
||||||
|
expect(file1).toBe(file1again);
|
||||||
|
expect(file1).not.toBe(file2);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import visit from 'unist-util-visit';
|
||||||
|
import {simpleHash} from '@docusaurus/utils';
|
||||||
|
import type {Transformer} from 'unified';
|
||||||
|
import type {FootnoteReference, FootnoteDefinition} from 'mdast';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In the blog list view, each post will be compiled separately. However, they
|
||||||
|
* may use the same footnote IDs. This leads to duplicated DOM IDs and inability
|
||||||
|
* to navigate to footnote references. This plugin fixes it by appending a
|
||||||
|
* unique hash to each reference/definition.
|
||||||
|
*/
|
||||||
|
export default function plugin(): Transformer {
|
||||||
|
return (root, vfile) => {
|
||||||
|
const suffix = `-${simpleHash(vfile.path!, 6)}`;
|
||||||
|
visit(root, 'footnoteReference', (node: FootnoteReference) => {
|
||||||
|
node.identifier += suffix;
|
||||||
|
});
|
||||||
|
visit(root, 'footnoteDefinition', (node: FootnoteDefinition) => {
|
||||||
|
node.identifier += suffix;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
13
website/_dogfooding/_blog tests/2022-01-21-dup-footnote.md
Normal file
13
website/_dogfooding/_blog tests/2022-01-21-dup-footnote.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
title: Third post with footnote to test posts with same footnote reference.
|
||||||
|
---
|
||||||
|
|
||||||
|
foo[^1]
|
||||||
|
|
||||||
|
bar[^2]
|
||||||
|
|
||||||
|
baz[^3]
|
||||||
|
|
||||||
|
[^1]: foo
|
||||||
|
[^2]: bar
|
||||||
|
[^3]: baz
|
13
website/_dogfooding/_blog tests/2022-01-22-dup-footnote.md
Normal file
13
website/_dogfooding/_blog tests/2022-01-22-dup-footnote.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
title: Second post with footnote to test posts with same footnote reference.
|
||||||
|
---
|
||||||
|
|
||||||
|
foo[^1]
|
||||||
|
|
||||||
|
bar[^2]
|
||||||
|
|
||||||
|
baz[^3]
|
||||||
|
|
||||||
|
[^1]: foo
|
||||||
|
[^2]: bar
|
||||||
|
[^3]: baz
|
13
website/_dogfooding/_blog tests/2022-04-20-dup-footnote.md
Normal file
13
website/_dogfooding/_blog tests/2022-04-20-dup-footnote.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
title: First post with footnote to test posts with same footnote reference.
|
||||||
|
---
|
||||||
|
|
||||||
|
foo[^1]
|
||||||
|
|
||||||
|
bar[^2]
|
||||||
|
|
||||||
|
baz[^3]
|
||||||
|
|
||||||
|
[^1]: foo
|
||||||
|
[^2]: bar
|
||||||
|
[^3]: baz
|
Loading…
Add table
Add a link
Reference in a new issue