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
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Dependency Review
uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # 4.7.3
uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # 4.8.0
18 changes: 5 additions & 13 deletions packages/docusaurus-theme-classic/src/theme/Heading/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import {translate} from '@docusaurus/Translate';
import {useThemeConfig} from '@docusaurus/theme-common';
import {useAnchorTargetClassName} from '@docusaurus/theme-common';
import Link from '@docusaurus/Link';
import useBrokenLinks from '@docusaurus/useBrokenLinks';
import type {Props} from '@theme/Heading';

import styles from './styles.module.css';
import './styles.module.css';

export default function Heading({as: As, id, ...props}: Props): ReactNode {
const brokenLinks = useBrokenLinks();
const {
navbar: {hideOnScroll},
} = useThemeConfig();
const anchorTargetClassName = useAnchorTargetClassName(id);

// H1 headings do not need an id because they don't appear in the TOC.
if (As === 'h1' || !id) {
return <As {...props} id={undefined} />;
Expand All @@ -41,13 +39,7 @@ export default function Heading({as: As, id, ...props}: Props): ReactNode {
return (
<As
{...props}
className={clsx(
'anchor',
hideOnScroll
? styles.anchorWithHideOnScrollNavbar
: styles.anchorWithStickyNavbar,
props.className,
)}
className={clsx('anchor', anchorTargetClassName, props.className)}
id={id}>
{props.children}
<Link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/

/*
When the navbar is sticky, ensure that on anchor click,
the browser does not scroll that anchor behind the navbar
See https://x.com/JoshWComeau/status/1332015868725891076
*/
.anchorWithStickyNavbar {
scroll-margin-top: calc(var(--ifm-navbar-height) + 0.5rem);
}

.anchorWithHideOnScrollNavbar {
scroll-margin-top: 0.5rem;
}

:global(.hash-link) {
opacity: 0;
padding-left: 0.5rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,14 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import {useThemeConfig} from '@docusaurus/theme-common';
import {useAnchorTargetClassName} from '@docusaurus/theme-common';
import type {Props} from '@theme/MDXComponents/A';
import styles from './styles.module.css';

function isFootnoteRef(props: Props) {
return props['data-footnote-ref'] === true;
}
export default function MDXA(props: Props): ReactNode {
// MDX Footnotes have ids such as <a id="user-content-fn-1-953011" ...>
const anchorTargetClassName = useAnchorTargetClassName(props.id);

function FootnoteRefLink(props: Props) {
const {
navbar: {hideOnScroll},
} = useThemeConfig();
return (
<Link
{...props}
className={clsx(
hideOnScroll
? styles.footnoteRefHideOnScrollNavbar
: styles.footnoteRefStickyNavbar,

props.className,
)}
/>
<Link {...props} className={clsx(anchorTargetClassName, props.className)} />
);
}

export default function MDXA(props: Props): ReactNode {
if (isFootnoteRef(props)) {
return <FootnoteRefLink {...props} />;
}
return <Link {...props} />;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
*/

import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import useBrokenLinks from '@docusaurus/useBrokenLinks';
import {useAnchorTargetClassName} from '@docusaurus/theme-common';
import type {Props} from '@theme/MDXComponents/Li';

export default function MDXLi(props: Props): ReactNode | undefined {
// MDX Footnotes have ids such as <li id="user-content-fn-1-953011">
useBrokenLinks().collectAnchor(props.id);
const anchorTargetClassName = useAnchorTargetClassName(props.id);

return <li {...props} />;
return (
<li className={clsx(anchorTargetClassName, props.className)} {...props} />
);
}
2 changes: 2 additions & 0 deletions packages/docusaurus-theme-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ export {
useSearchLinkCreator,
} from './hooks/useSearchPage';

export {useAnchorTargetClassName} from './utils/anchorUtils';

export {isMultiColumnFooterLinks} from './utils/footerUtils';

export {isRegexpStringMatch} from './utils/regexpUtils';
Expand Down
14 changes: 14 additions & 0 deletions packages/docusaurus-theme-common/src/utils/anchorUtils.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* 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.
*/

.anchorTargetStickyNavbar {
scroll-margin-top: calc(var(--ifm-navbar-height) + 0.5rem);
}

.anchorTargetHideOnScrollNavbar {
scroll-margin-top: 0.5rem;
}
31 changes: 31 additions & 0 deletions packages/docusaurus-theme-common/src/utils/anchorUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* 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 {useThemeConfig} from './useThemeConfig';
import styles from './anchorUtils.module.css';

/**
* When the navbar is sticky, this ensures that when clicking a hash link,
* we do not navigate to an anchor that will appear below the navbar.
* This happens in particular for MDX headings and footnotes.
*
* See https://github.com/facebook/docusaurus/issues/11232
* See also headings case https://x.com/JoshWComeau/status/1332015868725891076
*/
export function useAnchorTargetClassName(
id: string | undefined,
): string | undefined {
const {
navbar: {hideOnScroll},
} = useThemeConfig();
if (typeof id === 'undefined') {
return undefined;
}
return hideOnScroll
? styles.anchorTargetHideOnScrollNavbar
: styles.anchorTargetStickyNavbar;
}
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,12 @@ describe('i18n', () => {
baseUrl: '/myBase/Url/',
});
});

it('accepts translate true', () => {
expect(normalizeLocaleConfig({translate: true})).toEqual({
translate: true,
});
});
});
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus/src/server/configValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ const LocaleConfigSchema = Joi.object<I18nLocaleConfig>({
direction: Joi.string().equal('ltr', 'rtl'),
calendar: Joi.string(),
path: Joi.string(),
translate: Joi.boolean(),
url: SiteUrlSchema,
baseUrl: BaseUrlSchema,
});
Expand Down
146 changes: 146 additions & 0 deletions website/_dogfooding/_docs tests/tests/footnotes.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Footnotes

Lorem ipsum dolor sit amet [^1] [^2]

Lorem ipsum dolor sit amet [^3]

Lorem ipsum dolor sit amet [^4]

Lorem ipsum dolor sit amet [^5]

Lorem ipsum dolor sit amet [^6]

Lorem ipsum dolor sit amet [^7]

Lorem ipsum dolor sit amet [^8]

Lorem ipsum dolor sit amet [^9]

Lorem ipsum dolor sit amet [^10]

Lorem ipsum dolor sit amet [^11]

Lorem ipsum dolor sit amet [^12]

Lorem ipsum dolor sit amet [^13]

Lorem ipsum dolor sit amet [^14]

Lorem ipsum dolor sit amet [^15]

Lorem ipsum dolor sit amet [^16]

Lorem ipsum dolor sit amet [^17]

Lorem ipsum dolor sit amet [^18]

Lorem ipsum dolor sit amet [^19]

Lorem ipsum dolor sit amet [^20]

Lorem ipsum dolor sit amet [^21] [^22]

Lorem ipsum dolor sit amet [^23]

Lorem ipsum dolor sit amet [^24]

Lorem ipsum dolor sit amet [^25]

Lorem ipsum dolor sit amet [^26]

Lorem ipsum dolor sit amet [^27]

Lorem ipsum dolor sit amet [^28]

Lorem ipsum dolor sit amet [^29]

Lorem ipsum dolor sit amet [^30]

Lorem ipsum dolor sit amet [^31]

Lorem ipsum dolor sit amet [^32]

Lorem ipsum dolor sit amet [^33]

Lorem ipsum dolor sit amet [^34]

Lorem ipsum dolor sit amet [^35]

Lorem ipsum dolor sit amet [^36]

Lorem ipsum dolor sit amet [^37]

Lorem ipsum dolor sit amet [^38]

Lorem ipsum dolor sit amet [^39]

Lorem ipsum dolor sit amet [^40]

Lorem ipsum dolor sit amet [^41]

Lorem ipsum dolor sit amet [^42]

Lorem ipsum dolor sit amet [^43]

Lorem ipsum dolor sit amet [^44]

Lorem ipsum dolor sit amet [^45]

Lorem ipsum dolor sit amet [^46]

Lorem ipsum dolor sit amet [^47]

Lorem ipsum dolor sit amet [^48]

Lorem ipsum dolor sit amet [^49] [^50]

[^1]: footnote 1
[^2]: footnote 2
[^3]: footnote 3
[^4]: footnote 4
[^5]: footnote 5
[^6]: footnote 6
[^7]: footnote 7
[^8]: footnote 8
[^9]: footnote 9
[^10]: footnote 10
[^11]: footnote 11
[^12]: footnote 12
[^13]: footnote 13
[^14]: footnote 14
[^15]: footnote 15
[^16]: footnote 16
[^17]: footnote 17
[^18]: footnote 18
[^19]: footnote 19
[^20]: footnote 20
[^21]: footnote 21
[^22]: footnote 22
[^23]: footnote 23
[^24]: footnote 24
[^25]: footnote 25
[^26]: footnote 26
[^27]: footnote 27
[^28]: footnote 28
[^29]: footnote 29
[^30]: footnote 30
[^31]: footnote 31
[^32]: footnote 32
[^33]: footnote 33
[^34]: footnote 34
[^35]: footnote 35
[^36]: footnote 36
[^37]: footnote 37
[^38]: footnote 38
[^39]: footnote 39
[^40]: footnote 40
[^41]: footnote 41
[^42]: footnote 42
[^43]: footnote 43
[^44]: footnote 44
[^45]: footnote 45
[^46]: footnote 46
[^47]: footnote 47
[^48]: footnote 48
[^49]: footnote 49
[^50]: footnote 50
Loading