@docusaurus/theme-classic 3.0.0-alpha.0 → 3.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/lib/getSwizzleConfig.js +15 -8
  2. package/lib/options.js +8 -5
  3. package/lib/prism-include-languages.js +1 -1
  4. package/lib/theme/Admonition/Icon/{Caution.d.ts → Warning.d.ts} +1 -1
  5. package/lib/theme/Admonition/Type/Caution.js +4 -2
  6. package/{src/deps.d.ts → lib/theme/Admonition/Type/Warning.d.ts} +3 -7
  7. package/lib/theme/Admonition/Type/Warning.js +32 -0
  8. package/lib/theme/Admonition/Types.js +4 -4
  9. package/lib/theme/BlogLayout/index.js +1 -1
  10. package/lib/theme/BlogPostItem/Container/index.js +12 -3
  11. package/lib/theme/BlogPostItem/Header/Author/index.js +6 -1
  12. package/lib/theme/CodeBlock/Content/String.js +14 -10
  13. package/lib/theme/CodeBlock/CopyButton/index.js +0 -1
  14. package/lib/theme/DocItem/index.js +1 -1
  15. package/lib/theme/DocSidebar/Desktop/index.d.ts +1 -1
  16. package/lib/theme/DocSidebar/Mobile/index.d.ts +1 -1
  17. package/lib/theme/DocSidebarItem/Category/index.js +21 -10
  18. package/lib/theme/MDXComponents/Ul/index.js +4 -0
  19. package/lib/theme/MDXComponents/index.js +1 -0
  20. package/lib/theme/MDXContent/index.js +0 -1
  21. package/lib/theme/Navbar/Search/index.js +5 -1
  22. package/lib/theme/Navbar/Search/styles.module.css +10 -2
  23. package/lib/theme/SiteMetadata/index.js +30 -3
  24. package/lib/theme/prism-include-languages.js +4 -0
  25. package/package.json +22 -22
  26. package/src/getSwizzleConfig.ts +16 -8
  27. package/src/options.ts +8 -3
  28. package/src/prism-include-languages.ts +1 -1
  29. package/src/theme/Admonition/Icon/{Caution.tsx → Warning.tsx} +1 -1
  30. package/src/theme/Admonition/Type/Caution.tsx +4 -2
  31. package/src/theme/Admonition/Type/Warning.tsx +37 -0
  32. package/src/theme/Admonition/Types.tsx +4 -4
  33. package/src/theme/BlogLayout/index.tsx +1 -1
  34. package/src/theme/BlogPostItem/Container/index.tsx +12 -3
  35. package/src/theme/BlogPostItem/Header/Author/index.tsx +6 -1
  36. package/src/theme/CodeBlock/Content/String.tsx +15 -6
  37. package/src/theme/CodeBlock/CopyButton/index.tsx +0 -1
  38. package/src/theme/DocItem/index.tsx +1 -1
  39. package/src/theme/DocSidebarItem/Category/index.tsx +22 -9
  40. package/src/theme/MDXComponents/Ul/index.tsx +5 -1
  41. package/src/theme/MDXComponents/index.tsx +8 -7
  42. package/src/theme/MDXContent/index.tsx +0 -1
  43. package/src/theme/Navbar/Search/index.tsx +5 -1
  44. package/src/theme/Navbar/Search/styles.module.css +10 -2
  45. package/src/theme/SiteMetadata/index.tsx +36 -3
  46. package/src/theme/prism-include-languages.ts +4 -0
  47. package/src/theme-classic.d.ts +27 -15
  48. /package/lib/theme/Admonition/Icon/{Caution.js → Warning.js} +0 -0
@@ -19,13 +19,6 @@ export default function getSwizzleConfig(): SwizzleConfig {
19
19
  },
20
20
  description: 'The folder containing all admonition icons',
21
21
  },
22
- 'Admonition/Icon/Caution': {
23
- actions: {
24
- eject: 'safe',
25
- wrap: 'safe',
26
- },
27
- description: 'The admonition caution icon',
28
- },
29
22
  'Admonition/Icon/Danger': {
30
23
  actions: {
31
24
  eject: 'safe',
@@ -54,6 +47,13 @@ export default function getSwizzleConfig(): SwizzleConfig {
54
47
  },
55
48
  description: 'The admonition tip icon',
56
49
  },
50
+ 'Admonition/Icon/Warning': {
51
+ actions: {
52
+ eject: 'safe',
53
+ wrap: 'safe',
54
+ },
55
+ description: 'The admonition warning icon',
56
+ },
57
57
  'Admonition/Layout': {
58
58
  actions: {
59
59
  eject: 'safe',
@@ -110,6 +110,14 @@ export default function getSwizzleConfig(): SwizzleConfig {
110
110
  description:
111
111
  'The component responsible for rendering a :::tip admonition type',
112
112
  },
113
+ 'Admonition/Type/Warning': {
114
+ actions: {
115
+ eject: 'safe',
116
+ wrap: 'safe',
117
+ },
118
+ description:
119
+ 'The component responsible for rendering a :::warning admonition type',
120
+ },
113
121
  'Admonition/Types': {
114
122
  actions: {
115
123
  eject: 'safe',
@@ -182,7 +190,7 @@ export default function getSwizzleConfig(): SwizzleConfig {
182
190
  eject: 'safe',
183
191
  wrap: 'safe',
184
192
  },
185
- description: "The footer component of you site's layout",
193
+ description: "The footer component of your site's layout",
186
194
  },
187
195
  'Footer/Copyright': {
188
196
  actions: {
package/src/options.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import defaultPrismTheme from 'prism-react-renderer/themes/palenight';
8
+ import {themes} from 'prism-react-renderer';
9
9
  import {Joi, URISchema} from '@docusaurus/utils-validation';
10
10
  import type {Options, PluginOptions} from '@docusaurus/theme-classic';
11
11
  import type {ThemeConfig} from '@docusaurus/theme-common';
@@ -14,6 +14,7 @@ import type {
14
14
  OptionValidationContext,
15
15
  } from '@docusaurus/types';
16
16
 
17
+ const defaultPrismTheme = themes.palenight;
17
18
  const DEFAULT_DOCS_CONFIG: ThemeConfig['docs'] = {
18
19
  versionPersistence: 'localStorage',
19
20
  sidebar: {
@@ -313,6 +314,10 @@ const LogoSchema = Joi.object({
313
314
  className: Joi.string(),
314
315
  });
315
316
 
317
+ // Normalize prism language to lowercase
318
+ // See https://github.com/facebook/docusaurus/issues/9012
319
+ const PrismLanguage = Joi.string().custom((val) => val.toLowerCase());
320
+
316
321
  export const ThemeConfigSchema = Joi.object<ThemeConfig>({
317
322
  // TODO temporary (@alpha-58)
318
323
  // @ts-expect-error: forbidden
@@ -385,9 +390,9 @@ export const ThemeConfigSchema = Joi.object<ThemeConfig>({
385
390
  plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
386
391
  styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
387
392
  }),
388
- defaultLanguage: Joi.string(),
393
+ defaultLanguage: PrismLanguage,
389
394
  additionalLanguages: Joi.array()
390
- .items(Joi.string())
395
+ .items(PrismLanguage)
391
396
  .default(DEFAULT_CONFIG.prism.additionalLanguages),
392
397
  magicComments: Joi.array()
393
398
  .items(
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import Prism from 'prism-react-renderer/prism';
8
+ import {Prism} from 'prism-react-renderer';
9
9
  import prismIncludeLanguages from '@theme/prism-include-languages';
10
10
 
11
11
  prismIncludeLanguages(Prism);
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import React from 'react';
9
- import type {Props} from '@theme/Admonition/Icon/Caution';
9
+ import type {Props} from '@theme/Admonition/Icon/Warning';
10
10
 
11
11
  export default function AdmonitionIconCaution(props: Props): JSX.Element {
12
12
  return (
@@ -10,12 +10,12 @@ import clsx from 'clsx';
10
10
  import Translate from '@docusaurus/Translate';
11
11
  import type {Props} from '@theme/Admonition/Type/Caution';
12
12
  import AdmonitionLayout from '@theme/Admonition/Layout';
13
- import IconCaution from '@theme/Admonition/Icon/Caution';
13
+ import IconWarning from '@theme/Admonition/Icon/Warning';
14
14
 
15
15
  const infimaClassName = 'alert alert--warning';
16
16
 
17
17
  const defaultProps = {
18
- icon: <IconCaution />,
18
+ icon: <IconWarning />,
19
19
  title: (
20
20
  <Translate
21
21
  id="theme.admonition.caution"
@@ -25,6 +25,8 @@ const defaultProps = {
25
25
  ),
26
26
  };
27
27
 
28
+ // TODO remove before v4: Caution replaced by Warning
29
+ // see https://github.com/facebook/docusaurus/issues/7558
28
30
  export default function AdmonitionTypeCaution(props: Props): JSX.Element {
29
31
  return (
30
32
  <AdmonitionLayout
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import React from 'react';
9
+ import clsx from 'clsx';
10
+ import Translate from '@docusaurus/Translate';
11
+ import type {Props} from '@theme/Admonition/Type/Warning';
12
+ import AdmonitionLayout from '@theme/Admonition/Layout';
13
+ import IconWarning from '@theme/Admonition/Icon/Warning';
14
+
15
+ const infimaClassName = 'alert alert--warning';
16
+
17
+ const defaultProps = {
18
+ icon: <IconWarning />,
19
+ title: (
20
+ <Translate
21
+ id="theme.admonition.warning"
22
+ description="The default label used for the Warning admonition (:::warning)">
23
+ warning
24
+ </Translate>
25
+ ),
26
+ };
27
+
28
+ export default function AdmonitionTypeWarning(props: Props): JSX.Element {
29
+ return (
30
+ <AdmonitionLayout
31
+ {...defaultProps}
32
+ {...props}
33
+ className={clsx(infimaClassName, props.className)}>
34
+ {props.children}
35
+ </AdmonitionLayout>
36
+ );
37
+ }
@@ -9,15 +9,16 @@ import React from 'react';
9
9
  import AdmonitionTypeNote from '@theme/Admonition/Type/Note';
10
10
  import AdmonitionTypeTip from '@theme/Admonition/Type/Tip';
11
11
  import AdmonitionTypeInfo from '@theme/Admonition/Type/Info';
12
- import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
12
+ import AdmonitionTypeWarning from '@theme/Admonition/Type/Warning';
13
13
  import AdmonitionTypeDanger from '@theme/Admonition/Type/Danger';
14
+ import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
14
15
  import type AdmonitionTypes from '@theme/Admonition/Types';
15
16
 
16
17
  const admonitionTypes: typeof AdmonitionTypes = {
17
18
  note: AdmonitionTypeNote,
18
19
  tip: AdmonitionTypeTip,
19
20
  info: AdmonitionTypeInfo,
20
- caution: AdmonitionTypeCaution,
21
+ warning: AdmonitionTypeWarning,
21
22
  danger: AdmonitionTypeDanger,
22
23
  };
23
24
 
@@ -28,8 +29,7 @@ const admonitionAliases: typeof AdmonitionTypes = {
28
29
  secondary: (props) => <AdmonitionTypeNote title="secondary" {...props} />,
29
30
  important: (props) => <AdmonitionTypeInfo title="important" {...props} />,
30
31
  success: (props) => <AdmonitionTypeTip title="success" {...props} />,
31
- // TODO bad legacy mapping, warning is usually yellow, not red...
32
- warning: (props) => <AdmonitionTypeDanger title="warning" {...props} />,
32
+ caution: AdmonitionTypeCaution,
33
33
  };
34
34
 
35
35
  export default {
@@ -27,7 +27,7 @@ export default function BlogLayout(props: Props): JSX.Element {
27
27
  'col--9 col--offset-1': !hasSidebar,
28
28
  })}
29
29
  itemScope
30
- itemType="http://schema.org/Blog">
30
+ itemType="https://schema.org/Blog">
31
31
  {children}
32
32
  </main>
33
33
  {toc && <div className="col col--2">{toc}</div>}
@@ -14,17 +14,26 @@ export default function BlogPostItemContainer({
14
14
  children,
15
15
  className,
16
16
  }: Props): JSX.Element {
17
- const {frontMatter, assets} = useBlogPost();
17
+ const {
18
+ frontMatter,
19
+ assets,
20
+ metadata: {description},
21
+ } = useBlogPost();
18
22
  const {withBaseUrl} = useBaseUrlUtils();
19
23
  const image = assets.image ?? frontMatter.image;
24
+ const keywords = frontMatter.keywords ?? [];
20
25
  return (
21
26
  <article
22
27
  className={className}
23
28
  itemProp="blogPost"
24
29
  itemScope
25
- itemType="http://schema.org/BlogPosting">
30
+ itemType="https://schema.org/BlogPosting">
31
+ {description && <meta itemProp="description" content={description} />}
26
32
  {image && (
27
- <meta itemProp="image" content={withBaseUrl(image, {absolute: true})} />
33
+ <link itemProp="image" href={withBaseUrl(image, {absolute: true})} />
34
+ )}
35
+ {keywords.length > 0 && (
36
+ <meta itemProp="keywords" content={keywords.join(',')} />
28
37
  )}
29
38
  {children}
30
39
  </article>
@@ -28,7 +28,12 @@ export default function BlogPostItemHeaderAuthor({
28
28
  <div className={clsx('avatar margin-bottom--sm', className)}>
29
29
  {imageURL && (
30
30
  <MaybeLink href={link} className="avatar__photo-link">
31
- <img className="avatar__photo" src={imageURL} alt={name} />
31
+ <img
32
+ className="avatar__photo"
33
+ src={imageURL}
34
+ alt={name}
35
+ itemProp="image"
36
+ />
32
37
  </MaybeLink>
33
38
  )}
34
39
 
@@ -15,7 +15,7 @@ import {
15
15
  containsLineNumbers,
16
16
  useCodeWordWrap,
17
17
  } from '@docusaurus/theme-common/internal';
18
- import Highlight, {defaultProps, type Language} from 'prism-react-renderer';
18
+ import {Highlight, type Language} from 'prism-react-renderer';
19
19
  import Line from '@theme/CodeBlock/Line';
20
20
  import CopyButton from '@theme/CodeBlock/CopyButton';
21
21
  import WordWrapButton from '@theme/CodeBlock/WordWrapButton';
@@ -24,6 +24,13 @@ import type {Props} from '@theme/CodeBlock/Content/String';
24
24
 
25
25
  import styles from './styles.module.css';
26
26
 
27
+ // Prism languages are always lowercase
28
+ // We want to fail-safe and allow both "php" and "PHP"
29
+ // See https://github.com/facebook/docusaurus/issues/9012
30
+ function normalizeLanguage(language: string | undefined): string | undefined {
31
+ return language?.toLowerCase();
32
+ }
33
+
27
34
  export default function CodeBlockString({
28
35
  children,
29
36
  className: blockClassName = '',
@@ -35,8 +42,10 @@ export default function CodeBlockString({
35
42
  const {
36
43
  prism: {defaultLanguage, magicComments},
37
44
  } = useThemeConfig();
38
- const language =
39
- languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage;
45
+ const language = normalizeLanguage(
46
+ languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage,
47
+ );
48
+
40
49
  const prismTheme = usePrismTheme();
41
50
  const wordWrap = useCodeWordWrap();
42
51
 
@@ -65,16 +74,16 @@ export default function CodeBlockString({
65
74
  {title && <div className={styles.codeBlockTitle}>{title}</div>}
66
75
  <div className={styles.codeBlockContent}>
67
76
  <Highlight
68
- {...defaultProps}
69
77
  theme={prismTheme}
70
78
  code={code}
71
79
  language={(language ?? 'text') as Language}>
72
- {({className, tokens, getLineProps, getTokenProps}) => (
80
+ {({className, style, tokens, getLineProps, getTokenProps}) => (
73
81
  <pre
74
82
  /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
75
83
  tabIndex={0}
76
84
  ref={wordWrap.codeBlockRef}
77
- className={clsx(className, styles.codeBlock, 'thin-scrollbar')}>
85
+ className={clsx(className, styles.codeBlock, 'thin-scrollbar')}
86
+ style={style}>
78
87
  <code
79
88
  className={clsx(
80
89
  styles.codeBlockLines,
@@ -7,7 +7,6 @@
7
7
 
8
8
  import React, {useCallback, useState, useRef, useEffect} from 'react';
9
9
  import clsx from 'clsx';
10
- // @ts-expect-error: TODO, we need to make theme-classic have type: module
11
10
  import copy from 'copy-text-to-clipboard';
12
11
  import {translate} from '@docusaurus/Translate';
13
12
  import type {Props} from '@theme/CodeBlock/CopyButton';
@@ -13,7 +13,7 @@ import DocItemLayout from '@theme/DocItem/Layout';
13
13
  import type {Props} from '@theme/DocItem';
14
14
 
15
15
  export default function DocItem(props: Props): JSX.Element {
16
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
16
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
17
17
  const MDXComponent = props.content;
18
18
  return (
19
19
  <DocProvider content={props.content}>
@@ -72,23 +72,35 @@ function useCategoryHrefWithSSRFallback(
72
72
  }
73
73
 
74
74
  function CollapseButton({
75
+ collapsed,
75
76
  categoryLabel,
76
77
  onClick,
77
78
  }: {
79
+ collapsed: boolean;
78
80
  categoryLabel: string;
79
81
  onClick: ComponentProps<'button'>['onClick'];
80
82
  }) {
81
83
  return (
82
84
  <button
83
- aria-label={translate(
84
- {
85
- id: 'theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel',
86
- message: "Toggle the collapsible sidebar category '{label}'",
87
- description:
88
- 'The ARIA label to toggle the collapsible sidebar category',
89
- },
90
- {label: categoryLabel},
91
- )}
85
+ aria-label={
86
+ collapsed
87
+ ? translate(
88
+ {
89
+ id: 'theme.DocSidebarItem.expandCategoryAriaLabel',
90
+ message: "Expand sidebar category '{label}'",
91
+ description: 'The ARIA label to expand the sidebar category',
92
+ },
93
+ {label: categoryLabel},
94
+ )
95
+ : translate(
96
+ {
97
+ id: 'theme.DocSidebarItem.collapseCategoryAriaLabel',
98
+ message: "Collapse sidebar category '{label}'",
99
+ description: 'The ARIA label to collapse the sidebar category',
100
+ },
101
+ {label: categoryLabel},
102
+ )
103
+ }
92
104
  type="button"
93
105
  className="clean-btn menu__caret"
94
106
  onClick={onClick}
@@ -188,6 +200,7 @@ export default function DocSidebarItemCategory({
188
200
  </Link>
189
201
  {href && collapsible && (
190
202
  <CollapseButton
203
+ collapsed={collapsed}
191
204
  categoryLabel={label}
192
205
  onClick={(e) => {
193
206
  e.preventDefault();
@@ -11,7 +11,11 @@ import type {Props} from '@theme/MDXComponents/Ul';
11
11
 
12
12
  import styles from './styles.module.css';
13
13
 
14
- function transformUlClassName(className?: string): string {
14
+ function transformUlClassName(className?: string): string | undefined {
15
+ // Fix https://github.com/facebook/docusaurus/issues/9098
16
+ if (typeof className === 'undefined') {
17
+ return undefined;
18
+ }
15
19
  return clsx(
16
20
  className,
17
21
  // This class is set globally by GitHub/MDX. We keep the global class, and
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import React from 'react';
8
+ import React, {type ComponentProps} from 'react';
9
9
  import Head from '@docusaurus/Head';
10
10
  import MDXCode from '@theme/MDXComponents/Code';
11
11
  import MDXA from '@theme/MDXComponents/A';
@@ -21,18 +21,19 @@ import type {MDXComponentsObject} from '@theme/MDXComponents';
21
21
 
22
22
  const MDXComponents: MDXComponentsObject = {
23
23
  Head,
24
+ details: MDXDetails, // For MD mode support, see https://github.com/facebook/docusaurus/issues/9092#issuecomment-1602902274
24
25
  Details: MDXDetails,
25
26
  code: MDXCode,
26
27
  a: MDXA,
27
28
  pre: MDXPre,
28
29
  ul: MDXUl,
29
30
  img: MDXImg,
30
- h1: (props) => <MDXHeading as="h1" {...props} />,
31
- h2: (props) => <MDXHeading as="h2" {...props} />,
32
- h3: (props) => <MDXHeading as="h3" {...props} />,
33
- h4: (props) => <MDXHeading as="h4" {...props} />,
34
- h5: (props) => <MDXHeading as="h5" {...props} />,
35
- h6: (props) => <MDXHeading as="h6" {...props} />,
31
+ h1: (props: ComponentProps<'h1'>) => <MDXHeading as="h1" {...props} />,
32
+ h2: (props: ComponentProps<'h2'>) => <MDXHeading as="h2" {...props} />,
33
+ h3: (props: ComponentProps<'h3'>) => <MDXHeading as="h3" {...props} />,
34
+ h4: (props: ComponentProps<'h4'>) => <MDXHeading as="h4" {...props} />,
35
+ h5: (props: ComponentProps<'h5'>) => <MDXHeading as="h5" {...props} />,
36
+ h6: (props: ComponentProps<'h6'>) => <MDXHeading as="h6" {...props} />,
36
37
  admonition: Admonition,
37
38
  mermaid: Mermaid,
38
39
  };
@@ -6,7 +6,6 @@
6
6
  */
7
7
 
8
8
  import React from 'react';
9
- // @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
10
9
  import {MDXProvider} from '@mdx-js/react';
11
10
  import MDXComponents from '@theme/MDXComponents';
12
11
  import type {Props} from '@theme/MDXContent';
@@ -15,5 +15,9 @@ export default function NavbarSearch({
15
15
  children,
16
16
  className,
17
17
  }: Props): JSX.Element {
18
- return <div className={clsx(className, styles.searchBox)}>{children}</div>;
18
+ return (
19
+ <div className={clsx(className, styles.navbarSearchContainer)}>
20
+ {children}
21
+ </div>
22
+ );
19
23
  }
@@ -5,15 +5,23 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ /*
9
+ Workaround to avoid rendering empty search container
10
+ See https://github.com/facebook/docusaurus/pull/9385
11
+ */
12
+ .navbarSearchContainer:not(:has(> *)) {
13
+ display: none;
14
+ }
15
+
8
16
  @media (max-width: 996px) {
9
- .searchBox {
17
+ .navbarSearchContainer {
10
18
  position: absolute;
11
19
  right: var(--ifm-navbar-padding-horizontal);
12
20
  }
13
21
  }
14
22
 
15
23
  @media (min-width: 997px) {
16
- .searchBox {
24
+ .navbarSearchContainer {
17
25
  padding: var(--ifm-navbar-item-padding-vertical)
18
26
  var(--ifm-navbar-item-padding-horizontal);
19
27
  }
@@ -16,6 +16,7 @@ import {
16
16
  keyboardFocusedClassName,
17
17
  } from '@docusaurus/theme-common/internal';
18
18
  import {useLocation} from '@docusaurus/router';
19
+ import {applyTrailingSlash} from '@docusaurus/utils-common';
19
20
  import SearchMetadata from '@theme/SearchMetadata';
20
21
 
21
22
  // TODO move to SiteMetadataDefaults or theme-common ?
@@ -24,10 +25,19 @@ import SearchMetadata from '@theme/SearchMetadata';
24
25
  // See https://github.com/facebook/docusaurus/issues/3317
25
26
  function AlternateLangHeaders(): JSX.Element {
26
27
  const {
27
- i18n: {defaultLocale, localeConfigs},
28
+ i18n: {currentLocale, defaultLocale, localeConfigs},
28
29
  } = useDocusaurusContext();
29
30
  const alternatePageUtils = useAlternatePageUtils();
30
31
 
32
+ const currentHtmlLang = localeConfigs[currentLocale]!.htmlLang;
33
+
34
+ // HTML lang is a BCP 47 tag, but the Open Graph protocol requires
35
+ // using underscores instead of dashes.
36
+ // See https://ogp.me/#optional
37
+ // See https://en.wikipedia.org/wiki/IETF_language_tag)
38
+ const bcp47ToOpenGraphLocale = (code: string): string =>
39
+ code.replace('-', '_');
40
+
31
41
  // Note: it is fine to use both "x-default" and "en" to target the same url
32
42
  // See https://www.searchviu.com/en/multiple-hreflang-tags-one-url/
33
43
  return (
@@ -51,6 +61,20 @@ function AlternateLangHeaders(): JSX.Element {
51
61
  })}
52
62
  hrefLang="x-default"
53
63
  />
64
+
65
+ <meta
66
+ property="og:locale"
67
+ content={bcp47ToOpenGraphLocale(currentHtmlLang)}
68
+ />
69
+ {Object.values(localeConfigs)
70
+ .filter((config) => currentHtmlLang !== config.htmlLang)
71
+ .map((config) => (
72
+ <meta
73
+ key={`meta-og-${config.htmlLang}`}
74
+ property="og:locale:alternate"
75
+ content={bcp47ToOpenGraphLocale(config.htmlLang)}
76
+ />
77
+ ))}
54
78
  </Head>
55
79
  );
56
80
  }
@@ -58,10 +82,19 @@ function AlternateLangHeaders(): JSX.Element {
58
82
  // Default canonical url inferred from current page location pathname
59
83
  function useDefaultCanonicalUrl() {
60
84
  const {
61
- siteConfig: {url: siteUrl},
85
+ siteConfig: {url: siteUrl, baseUrl, trailingSlash},
62
86
  } = useDocusaurusContext();
87
+
88
+ // TODO using useLocation().pathname is not a super idea
89
+ // See https://github.com/facebook/docusaurus/issues/9170
63
90
  const {pathname} = useLocation();
64
- return siteUrl + useBaseUrl(pathname);
91
+
92
+ const canonicalPathname = applyTrailingSlash(useBaseUrl(pathname), {
93
+ trailingSlash,
94
+ baseUrl,
95
+ });
96
+
97
+ return siteUrl + canonicalPathname;
65
98
  }
66
99
 
67
100
  // TODO move to SiteMetadataDefaults or theme-common ?
@@ -26,6 +26,10 @@ export default function prismIncludeLanguages(
26
26
  globalThis.Prism = PrismObject;
27
27
 
28
28
  additionalLanguages.forEach((lang) => {
29
+ if (lang === 'php') {
30
+ // eslint-disable-next-line global-require
31
+ require('prismjs/components/prism-markup-templating.js');
32
+ }
29
33
  // eslint-disable-next-line global-require, import/no-dynamic-require
30
34
  require(`prismjs/components/prism-${lang}`);
31
35
  });
@@ -74,6 +74,8 @@ declare module '@theme/Admonition/Type/Tip' {
74
74
  export default function AdmonitionTypeTip(props: Props): JSX.Element;
75
75
  }
76
76
 
77
+ // TODO remove before v4: Caution replaced by Warning
78
+ // see https://github.com/facebook/docusaurus/issues/7558
77
79
  declare module '@theme/Admonition/Type/Caution' {
78
80
  import type {Props as AdmonitionProps} from '@theme/Admonition';
79
81
 
@@ -81,6 +83,13 @@ declare module '@theme/Admonition/Type/Caution' {
81
83
  export default function AdmonitionTypeCaution(props: Props): JSX.Element;
82
84
  }
83
85
 
86
+ declare module '@theme/Admonition/Type/Warning' {
87
+ import type {Props as AdmonitionProps} from '@theme/Admonition';
88
+
89
+ export interface Props extends AdmonitionProps {}
90
+ export default function AdmonitionTypeWarning(props: Props): JSX.Element;
91
+ }
92
+
84
93
  declare module '@theme/Admonition/Type/Danger' {
85
94
  import type {Props as AdmonitionProps} from '@theme/Admonition';
86
95
 
@@ -128,12 +137,12 @@ declare module '@theme/Admonition/Icon/Tip' {
128
137
  export default function AdmonitionIconTip(props: Props): JSX.Element;
129
138
  }
130
139
 
131
- declare module '@theme/Admonition/Icon/Caution' {
140
+ declare module '@theme/Admonition/Icon/Warning' {
132
141
  import type {ComponentProps} from 'react';
133
142
 
134
143
  export interface Props extends ComponentProps<'svg'> {}
135
144
 
136
- export default function AdmonitionIconCaution(props: Props): JSX.Element;
145
+ export default function AdmonitionIconWarning(props: Props): JSX.Element;
137
146
  }
138
147
 
139
148
  declare module '@theme/Admonition/Icon/Danger' {
@@ -391,23 +400,20 @@ declare module '@theme/CodeBlock/Content/String' {
391
400
  }
392
401
 
393
402
  declare module '@theme/CodeBlock/Line' {
394
- import type {ComponentProps} from 'react';
395
- import type Highlight from 'prism-react-renderer';
396
-
397
- // Lib does not make this easy
398
- type RenderProps = Parameters<
399
- ComponentProps<typeof Highlight>['children']
400
- >[0];
401
- type GetLineProps = RenderProps['getLineProps'];
402
- type GetTokenProps = RenderProps['getTokenProps'];
403
- type Token = RenderProps['tokens'][number][number];
403
+ import type {
404
+ LineInputProps,
405
+ LineOutputProps,
406
+ Token,
407
+ TokenInputProps,
408
+ TokenOutputProps,
409
+ } from 'prism-react-renderer';
404
410
 
405
411
  export interface Props {
406
412
  readonly line: Token[];
407
413
  readonly classNames: string[] | undefined;
408
414
  readonly showLineNumbers: boolean;
409
- readonly getLineProps: GetLineProps;
410
- readonly getTokenProps: GetTokenProps;
415
+ readonly getLineProps: (input: LineInputProps) => LineOutputProps;
416
+ readonly getTokenProps: (input: TokenInputProps) => TokenOutputProps;
411
417
  }
412
418
 
413
419
  export default function CodeBlockLine(props: Props): JSX.Element;
@@ -891,8 +897,14 @@ declare module '@theme/MDXComponents' {
891
897
  import type Mermaid from '@theme/Mermaid';
892
898
  import type Head from '@docusaurus/Head';
893
899
 
894
- export type MDXComponentsObject = {
900
+ import type {MDXProvider} from '@mdx-js/react';
901
+
902
+ type MDXComponentsBase = ComponentProps<typeof MDXProvider>['components'];
903
+
904
+ export type MDXComponentsObject = MDXComponentsBase & {
895
905
  readonly Head: typeof Head;
906
+ readonly details: typeof MDXDetails;
907
+
896
908
  readonly Details: typeof MDXDetails;
897
909
  readonly code: typeof MDXCode;
898
910
  readonly a: typeof MDXA;