@docusaurus/theme-classic 3.0.0-alpha.0 → 3.0.0-beta.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 (40) hide show
  1. package/lib/getSwizzleConfig.js +15 -8
  2. package/lib/options.js +5 -2
  3. package/lib/theme/Admonition/Icon/{Caution.d.ts → Warning.d.ts} +1 -1
  4. package/lib/theme/Admonition/Type/Caution.js +4 -2
  5. package/lib/theme/Admonition/Type/Warning.d.ts +9 -0
  6. package/lib/theme/Admonition/Type/Warning.js +32 -0
  7. package/lib/theme/Admonition/Types.js +4 -4
  8. package/lib/theme/BlogLayout/index.js +1 -1
  9. package/lib/theme/BlogPostItem/Container/index.js +12 -3
  10. package/lib/theme/BlogPostItem/Header/Author/index.js +6 -1
  11. package/lib/theme/CodeBlock/Content/String.js +9 -2
  12. package/lib/theme/CodeBlock/CopyButton/index.js +0 -1
  13. package/lib/theme/DocItem/index.js +1 -1
  14. package/lib/theme/DocSidebar/Desktop/index.d.ts +1 -1
  15. package/lib/theme/DocSidebar/Mobile/index.d.ts +1 -1
  16. package/lib/theme/DocSidebarItem/Category/index.js +21 -10
  17. package/lib/theme/MDXComponents/Ul/index.js +4 -0
  18. package/lib/theme/MDXComponents/index.js +1 -0
  19. package/lib/theme/MDXContent/index.js +0 -1
  20. package/lib/theme/SiteMetadata/index.js +30 -3
  21. package/package.json +20 -20
  22. package/src/getSwizzleConfig.ts +16 -8
  23. package/src/options.ts +6 -2
  24. package/src/theme/Admonition/Icon/{Caution.tsx → Warning.tsx} +1 -1
  25. package/src/theme/Admonition/Type/Caution.tsx +4 -2
  26. package/src/theme/Admonition/Type/Warning.tsx +37 -0
  27. package/src/theme/Admonition/Types.tsx +4 -4
  28. package/src/theme/BlogLayout/index.tsx +1 -1
  29. package/src/theme/BlogPostItem/Container/index.tsx +12 -3
  30. package/src/theme/BlogPostItem/Header/Author/index.tsx +6 -1
  31. package/src/theme/CodeBlock/Content/String.tsx +11 -2
  32. package/src/theme/CodeBlock/CopyButton/index.tsx +0 -1
  33. package/src/theme/DocItem/index.tsx +1 -1
  34. package/src/theme/DocSidebarItem/Category/index.tsx +22 -9
  35. package/src/theme/MDXComponents/Ul/index.tsx +5 -1
  36. package/src/theme/MDXComponents/index.tsx +8 -7
  37. package/src/theme/MDXContent/index.tsx +0 -1
  38. package/src/theme/SiteMetadata/index.tsx +36 -3
  39. package/src/theme-classic.d.ts +18 -3
  40. /package/lib/theme/Admonition/Icon/{Caution.js → Warning.js} +0 -0
@@ -17,13 +17,6 @@ function getSwizzleConfig() {
17
17
  },
18
18
  description: 'The folder containing all admonition icons',
19
19
  },
20
- 'Admonition/Icon/Caution': {
21
- actions: {
22
- eject: 'safe',
23
- wrap: 'safe',
24
- },
25
- description: 'The admonition caution icon',
26
- },
27
20
  'Admonition/Icon/Danger': {
28
21
  actions: {
29
22
  eject: 'safe',
@@ -52,6 +45,13 @@ function getSwizzleConfig() {
52
45
  },
53
46
  description: 'The admonition tip icon',
54
47
  },
48
+ 'Admonition/Icon/Warning': {
49
+ actions: {
50
+ eject: 'safe',
51
+ wrap: 'safe',
52
+ },
53
+ description: 'The admonition warning icon',
54
+ },
55
55
  'Admonition/Layout': {
56
56
  actions: {
57
57
  eject: 'safe',
@@ -101,6 +101,13 @@ function getSwizzleConfig() {
101
101
  },
102
102
  description: 'The component responsible for rendering a :::tip admonition type',
103
103
  },
104
+ 'Admonition/Type/Warning': {
105
+ actions: {
106
+ eject: 'safe',
107
+ wrap: 'safe',
108
+ },
109
+ description: 'The component responsible for rendering a :::warning admonition type',
110
+ },
104
111
  'Admonition/Types': {
105
112
  actions: {
106
113
  eject: 'safe',
@@ -166,7 +173,7 @@ function getSwizzleConfig() {
166
173
  eject: 'safe',
167
174
  wrap: 'safe',
168
175
  },
169
- description: "The footer component of you site's layout",
176
+ description: "The footer component of your site's layout",
170
177
  },
171
178
  'Footer/Copyright': {
172
179
  actions: {
package/lib/options.js CHANGED
@@ -277,6 +277,9 @@ const LogoSchema = utils_validation_1.Joi.object({
277
277
  style: utils_validation_1.Joi.object(),
278
278
  className: utils_validation_1.Joi.string(),
279
279
  });
280
+ // Normalize prism language to lowercase
281
+ // See https://github.com/facebook/docusaurus/issues/9012
282
+ const PrismLanguage = utils_validation_1.Joi.string().custom((val) => val.toLowerCase());
280
283
  exports.ThemeConfigSchema = utils_validation_1.Joi.object({
281
284
  // TODO temporary (@alpha-58)
282
285
  // @ts-expect-error: forbidden
@@ -341,9 +344,9 @@ exports.ThemeConfigSchema = utils_validation_1.Joi.object({
341
344
  plain: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
342
345
  styles: utils_validation_1.Joi.alternatives().try(utils_validation_1.Joi.array(), utils_validation_1.Joi.object()).required(),
343
346
  }),
344
- defaultLanguage: utils_validation_1.Joi.string(),
347
+ defaultLanguage: PrismLanguage,
345
348
  additionalLanguages: utils_validation_1.Joi.array()
346
- .items(utils_validation_1.Joi.string())
349
+ .items(PrismLanguage)
347
350
  .default(exports.DEFAULT_CONFIG.prism.additionalLanguages),
348
351
  magicComments: utils_validation_1.Joi.array()
349
352
  .items(utils_validation_1.Joi.object({
@@ -5,5 +5,5 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  /// <reference types="react" />
8
- import type { Props } from '@theme/Admonition/Icon/Caution';
8
+ import type { Props } from '@theme/Admonition/Icon/Warning';
9
9
  export default function AdmonitionIconCaution(props: Props): JSX.Element;
@@ -8,10 +8,10 @@ import React from 'react';
8
8
  import clsx from 'clsx';
9
9
  import Translate from '@docusaurus/Translate';
10
10
  import AdmonitionLayout from '@theme/Admonition/Layout';
11
- import IconCaution from '@theme/Admonition/Icon/Caution';
11
+ import IconWarning from '@theme/Admonition/Icon/Warning';
12
12
  const infimaClassName = 'alert alert--warning';
13
13
  const defaultProps = {
14
- icon: <IconCaution />,
14
+ icon: <IconWarning />,
15
15
  title: (
16
16
  <Translate
17
17
  id="theme.admonition.caution"
@@ -20,6 +20,8 @@ const defaultProps = {
20
20
  </Translate>
21
21
  ),
22
22
  };
23
+ // TODO remove before v4: Caution replaced by Warning
24
+ // see https://github.com/facebook/docusaurus/issues/7558
23
25
  export default function AdmonitionTypeCaution(props) {
24
26
  return (
25
27
  <AdmonitionLayout
@@ -0,0 +1,9 @@
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
+ /// <reference types="react" />
8
+ import type { Props } from '@theme/Admonition/Type/Warning';
9
+ export default function AdmonitionTypeWarning(props: Props): JSX.Element;
@@ -0,0 +1,32 @@
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
+ import React from 'react';
8
+ import clsx from 'clsx';
9
+ import Translate from '@docusaurus/Translate';
10
+ import AdmonitionLayout from '@theme/Admonition/Layout';
11
+ import IconWarning from '@theme/Admonition/Icon/Warning';
12
+ const infimaClassName = 'alert alert--warning';
13
+ const defaultProps = {
14
+ icon: <IconWarning />,
15
+ title: (
16
+ <Translate
17
+ id="theme.admonition.warning"
18
+ description="The default label used for the Warning admonition (:::warning)">
19
+ warning
20
+ </Translate>
21
+ ),
22
+ };
23
+ export default function AdmonitionTypeWarning(props) {
24
+ return (
25
+ <AdmonitionLayout
26
+ {...defaultProps}
27
+ {...props}
28
+ className={clsx(infimaClassName, props.className)}>
29
+ {props.children}
30
+ </AdmonitionLayout>
31
+ );
32
+ }
@@ -8,13 +8,14 @@ import React from 'react';
8
8
  import AdmonitionTypeNote from '@theme/Admonition/Type/Note';
9
9
  import AdmonitionTypeTip from '@theme/Admonition/Type/Tip';
10
10
  import AdmonitionTypeInfo from '@theme/Admonition/Type/Info';
11
- import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
11
+ import AdmonitionTypeWarning from '@theme/Admonition/Type/Warning';
12
12
  import AdmonitionTypeDanger from '@theme/Admonition/Type/Danger';
13
+ import AdmonitionTypeCaution from '@theme/Admonition/Type/Caution';
13
14
  const admonitionTypes = {
14
15
  note: AdmonitionTypeNote,
15
16
  tip: AdmonitionTypeTip,
16
17
  info: AdmonitionTypeInfo,
17
- caution: AdmonitionTypeCaution,
18
+ warning: AdmonitionTypeWarning,
18
19
  danger: AdmonitionTypeDanger,
19
20
  };
20
21
  // Undocumented legacy admonition type aliases
@@ -24,8 +25,7 @@ const admonitionAliases = {
24
25
  secondary: (props) => <AdmonitionTypeNote title="secondary" {...props} />,
25
26
  important: (props) => <AdmonitionTypeInfo title="important" {...props} />,
26
27
  success: (props) => <AdmonitionTypeTip title="success" {...props} />,
27
- // TODO bad legacy mapping, warning is usually yellow, not red...
28
- warning: (props) => <AdmonitionTypeDanger title="warning" {...props} />,
28
+ caution: AdmonitionTypeCaution,
29
29
  };
30
30
  export default {
31
31
  ...admonitionTypes,
@@ -22,7 +22,7 @@ export default function BlogLayout(props) {
22
22
  'col--9 col--offset-1': !hasSidebar,
23
23
  })}
24
24
  itemScope
25
- itemType="http://schema.org/Blog">
25
+ itemType="https://schema.org/Blog">
26
26
  {children}
27
27
  </main>
28
28
  {toc && <div className="col col--2">{toc}</div>}
@@ -8,17 +8,26 @@ import React from 'react';
8
8
  import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
9
9
  import {useBlogPost} from '@docusaurus/theme-common/internal';
10
10
  export default function BlogPostItemContainer({children, className}) {
11
- const {frontMatter, assets} = useBlogPost();
11
+ const {
12
+ frontMatter,
13
+ assets,
14
+ metadata: {description},
15
+ } = useBlogPost();
12
16
  const {withBaseUrl} = useBaseUrlUtils();
13
17
  const image = assets.image ?? frontMatter.image;
18
+ const keywords = frontMatter.keywords ?? [];
14
19
  return (
15
20
  <article
16
21
  className={className}
17
22
  itemProp="blogPost"
18
23
  itemScope
19
- itemType="http://schema.org/BlogPosting">
24
+ itemType="https://schema.org/BlogPosting">
25
+ {description && <meta itemProp="description" content={description} />}
20
26
  {image && (
21
- <meta itemProp="image" content={withBaseUrl(image, {absolute: true})} />
27
+ <link itemProp="image" href={withBaseUrl(image, {absolute: true})} />
28
+ )}
29
+ {keywords.length > 0 && (
30
+ <meta itemProp="keywords" content={keywords.join(',')} />
22
31
  )}
23
32
  {children}
24
33
  </article>
@@ -20,7 +20,12 @@ export default function BlogPostItemHeaderAuthor({author, className}) {
20
20
  <div className={clsx('avatar margin-bottom--sm', className)}>
21
21
  {imageURL && (
22
22
  <MaybeLink href={link} className="avatar__photo-link">
23
- <img className="avatar__photo" src={imageURL} alt={name} />
23
+ <img
24
+ className="avatar__photo"
25
+ src={imageURL}
26
+ alt={name}
27
+ itemProp="image"
28
+ />
24
29
  </MaybeLink>
25
30
  )}
26
31
 
@@ -20,6 +20,12 @@ import CopyButton from '@theme/CodeBlock/CopyButton';
20
20
  import WordWrapButton from '@theme/CodeBlock/WordWrapButton';
21
21
  import Container from '@theme/CodeBlock/Container';
22
22
  import styles from './styles.module.css';
23
+ // Prism languages are always lowercase
24
+ // We want to fail-safe and allow both "php" and "PHP"
25
+ // See https://github.com/facebook/docusaurus/issues/9012
26
+ function normalizeLanguage(language) {
27
+ return language?.toLowerCase();
28
+ }
23
29
  export default function CodeBlockString({
24
30
  children,
25
31
  className: blockClassName = '',
@@ -31,8 +37,9 @@ export default function CodeBlockString({
31
37
  const {
32
38
  prism: {defaultLanguage, magicComments},
33
39
  } = useThemeConfig();
34
- const language =
35
- languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage;
40
+ const language = normalizeLanguage(
41
+ languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage,
42
+ );
36
43
  const prismTheme = usePrismTheme();
37
44
  const wordWrap = useCodeWordWrap();
38
45
  // We still parse the metastring in case we want to support more syntax in the
@@ -6,7 +6,6 @@
6
6
  */
7
7
  import React, {useCallback, useState, useRef, useEffect} from 'react';
8
8
  import clsx from 'clsx';
9
- // @ts-expect-error: TODO, we need to make theme-classic have type: module
10
9
  import copy from 'copy-text-to-clipboard';
11
10
  import {translate} from '@docusaurus/Translate';
12
11
  import IconCopy from '@theme/Icon/Copy';
@@ -10,7 +10,7 @@ import {DocProvider} from '@docusaurus/theme-common/internal';
10
10
  import DocItemMetadata from '@theme/DocItem/Metadata';
11
11
  import DocItemLayout from '@theme/DocItem/Layout';
12
12
  export default function DocItem(props) {
13
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
13
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
14
14
  const MDXComponent = props.content;
15
15
  return (
16
16
  <DocProvider content={props.content}>
@@ -6,6 +6,6 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import type { Props } from '@theme/DocSidebar/Desktop';
9
- declare function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props): JSX.Element;
9
+ declare function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props): React.JSX.Element;
10
10
  declare const _default: React.MemoExoticComponent<typeof DocSidebarDesktop>;
11
11
  export default _default;
@@ -6,6 +6,6 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import type { Props } from '@theme/DocSidebar/Mobile';
9
- declare function DocSidebarMobile(props: Props): JSX.Element;
9
+ declare function DocSidebarMobile(props: Props): React.JSX.Element;
10
10
  declare const _default: React.MemoExoticComponent<typeof DocSidebarMobile>;
11
11
  export default _default;
@@ -56,18 +56,28 @@ function useCategoryHrefWithSSRFallback(item) {
56
56
  return findFirstSidebarItemLink(item);
57
57
  }, [item, isBrowser]);
58
58
  }
59
- function CollapseButton({categoryLabel, onClick}) {
59
+ function CollapseButton({collapsed, categoryLabel, onClick}) {
60
60
  return (
61
61
  <button
62
- aria-label={translate(
63
- {
64
- id: 'theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel',
65
- message: "Toggle the collapsible sidebar category '{label}'",
66
- description:
67
- 'The ARIA label to toggle the collapsible sidebar category',
68
- },
69
- {label: categoryLabel},
70
- )}
62
+ aria-label={
63
+ collapsed
64
+ ? translate(
65
+ {
66
+ id: 'theme.DocSidebarItem.expandCategoryAriaLabel',
67
+ message: "Expand sidebar category '{label}'",
68
+ description: 'The ARIA label to expand the sidebar category',
69
+ },
70
+ {label: categoryLabel},
71
+ )
72
+ : translate(
73
+ {
74
+ id: 'theme.DocSidebarItem.collapseCategoryAriaLabel',
75
+ message: "Collapse sidebar category '{label}'",
76
+ description: 'The ARIA label to collapse the sidebar category',
77
+ },
78
+ {label: categoryLabel},
79
+ )
80
+ }
71
81
  type="button"
72
82
  className="clean-btn menu__caret"
73
83
  onClick={onClick}
@@ -162,6 +172,7 @@ export default function DocSidebarItemCategory({
162
172
  </Link>
163
173
  {href && collapsible && (
164
174
  <CollapseButton
175
+ collapsed={collapsed}
165
176
  categoryLabel={label}
166
177
  onClick={(e) => {
167
178
  e.preventDefault();
@@ -8,6 +8,10 @@ import React from 'react';
8
8
  import clsx from 'clsx';
9
9
  import styles from './styles.module.css';
10
10
  function transformUlClassName(className) {
11
+ // Fix https://github.com/facebook/docusaurus/issues/9098
12
+ if (typeof className === 'undefined') {
13
+ return undefined;
14
+ }
11
15
  return clsx(
12
16
  className,
13
17
  // This class is set globally by GitHub/MDX. We keep the global class, and
@@ -17,6 +17,7 @@ import Admonition from '@theme/Admonition';
17
17
  import Mermaid from '@theme/Mermaid';
18
18
  const MDXComponents = {
19
19
  Head,
20
+ details: MDXDetails,
20
21
  Details: MDXDetails,
21
22
  code: MDXCode,
22
23
  a: MDXA,
@@ -5,7 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
- // @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
9
8
  import {MDXProvider} from '@mdx-js/react';
10
9
  import MDXComponents from '@theme/MDXComponents';
11
10
  export default function MDXContent({children}) {
@@ -15,6 +15,7 @@ import {
15
15
  keyboardFocusedClassName,
16
16
  } from '@docusaurus/theme-common/internal';
17
17
  import {useLocation} from '@docusaurus/router';
18
+ import {applyTrailingSlash} from '@docusaurus/utils-common';
18
19
  import SearchMetadata from '@theme/SearchMetadata';
19
20
  // TODO move to SiteMetadataDefaults or theme-common ?
20
21
  // Useful for i18n/SEO
@@ -22,9 +23,15 @@ import SearchMetadata from '@theme/SearchMetadata';
22
23
  // See https://github.com/facebook/docusaurus/issues/3317
23
24
  function AlternateLangHeaders() {
24
25
  const {
25
- i18n: {defaultLocale, localeConfigs},
26
+ i18n: {currentLocale, defaultLocale, localeConfigs},
26
27
  } = useDocusaurusContext();
27
28
  const alternatePageUtils = useAlternatePageUtils();
29
+ const currentHtmlLang = localeConfigs[currentLocale].htmlLang;
30
+ // HTML lang is a BCP 47 tag, but the Open Graph protocol requires
31
+ // using underscores instead of dashes.
32
+ // See https://ogp.me/#optional
33
+ // See https://en.wikipedia.org/wiki/IETF_language_tag)
34
+ const bcp47ToOpenGraphLocale = (code) => code.replace('-', '_');
28
35
  // Note: it is fine to use both "x-default" and "en" to target the same url
29
36
  // See https://www.searchviu.com/en/multiple-hreflang-tags-one-url/
30
37
  return (
@@ -48,16 +55,36 @@ function AlternateLangHeaders() {
48
55
  })}
49
56
  hrefLang="x-default"
50
57
  />
58
+
59
+ <meta
60
+ property="og:locale"
61
+ content={bcp47ToOpenGraphLocale(currentHtmlLang)}
62
+ />
63
+ {Object.values(localeConfigs)
64
+ .filter((config) => currentHtmlLang !== config.htmlLang)
65
+ .map((config) => (
66
+ <meta
67
+ key={`meta-og-${config.htmlLang}`}
68
+ property="og:locale:alternate"
69
+ content={bcp47ToOpenGraphLocale(config.htmlLang)}
70
+ />
71
+ ))}
51
72
  </Head>
52
73
  );
53
74
  }
54
75
  // Default canonical url inferred from current page location pathname
55
76
  function useDefaultCanonicalUrl() {
56
77
  const {
57
- siteConfig: {url: siteUrl},
78
+ siteConfig: {url: siteUrl, baseUrl, trailingSlash},
58
79
  } = useDocusaurusContext();
80
+ // TODO using useLocation().pathname is not a super idea
81
+ // See https://github.com/facebook/docusaurus/issues/9170
59
82
  const {pathname} = useLocation();
60
- return siteUrl + useBaseUrl(pathname);
83
+ const canonicalPathname = applyTrailingSlash(useBaseUrl(pathname), {
84
+ trailingSlash,
85
+ baseUrl,
86
+ });
87
+ return siteUrl + canonicalPathname;
61
88
  }
62
89
  // TODO move to SiteMetadataDefaults or theme-common ?
63
90
  function CanonicalUrlHeaders({permalink}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-classic",
3
- "version": "3.0.0-alpha.0",
3
+ "version": "3.0.0-beta.0",
4
4
  "description": "Classic theme for Docusaurus",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/theme-classic.d.ts",
@@ -20,38 +20,38 @@
20
20
  "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
21
21
  },
22
22
  "dependencies": {
23
- "@docusaurus/core": "3.0.0-alpha.0",
24
- "@docusaurus/mdx-loader": "3.0.0-alpha.0",
25
- "@docusaurus/module-type-aliases": "3.0.0-alpha.0",
26
- "@docusaurus/plugin-content-blog": "3.0.0-alpha.0",
27
- "@docusaurus/plugin-content-docs": "3.0.0-alpha.0",
28
- "@docusaurus/plugin-content-pages": "3.0.0-alpha.0",
29
- "@docusaurus/theme-common": "3.0.0-alpha.0",
30
- "@docusaurus/theme-translations": "3.0.0-alpha.0",
31
- "@docusaurus/types": "3.0.0-alpha.0",
32
- "@docusaurus/utils": "3.0.0-alpha.0",
33
- "@docusaurus/utils-common": "3.0.0-alpha.0",
34
- "@docusaurus/utils-validation": "3.0.0-alpha.0",
23
+ "@docusaurus/core": "3.0.0-beta.0",
24
+ "@docusaurus/mdx-loader": "3.0.0-beta.0",
25
+ "@docusaurus/module-type-aliases": "3.0.0-beta.0",
26
+ "@docusaurus/plugin-content-blog": "3.0.0-beta.0",
27
+ "@docusaurus/plugin-content-docs": "3.0.0-beta.0",
28
+ "@docusaurus/plugin-content-pages": "3.0.0-beta.0",
29
+ "@docusaurus/theme-common": "3.0.0-beta.0",
30
+ "@docusaurus/theme-translations": "3.0.0-beta.0",
31
+ "@docusaurus/types": "3.0.0-beta.0",
32
+ "@docusaurus/utils": "3.0.0-beta.0",
33
+ "@docusaurus/utils-common": "3.0.0-beta.0",
34
+ "@docusaurus/utils-validation": "3.0.0-beta.0",
35
35
  "@mdx-js/react": "^2.1.5",
36
36
  "clsx": "^1.2.1",
37
- "copy-text-to-clipboard": "^3.0.1",
37
+ "copy-text-to-clipboard": "^3.2.0",
38
38
  "infima": "0.2.0-alpha.43",
39
39
  "lodash": "^4.17.21",
40
40
  "nprogress": "^0.2.0",
41
- "postcss": "^8.4.21",
41
+ "postcss": "^8.4.26",
42
42
  "prism-react-renderer": "^1.3.5",
43
43
  "prismjs": "^1.29.0",
44
44
  "react-router-dom": "^5.3.4",
45
- "rtlcss": "^4.0.0",
46
- "tslib": "^2.5.0",
45
+ "rtlcss": "^4.1.0",
46
+ "tslib": "^2.6.0",
47
47
  "utility-types": "^3.10.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/mdx-js__react": "^1.5.5",
51
51
  "@types/nprogress": "^0.2.0",
52
52
  "@types/prismjs": "^1.26.0",
53
- "@types/rtlcss": "^3.5.0",
54
- "fs-extra": "^11.1.0",
53
+ "@types/rtlcss": "^3.5.1",
54
+ "fs-extra": "^11.1.1",
55
55
  "react-test-renderer": "^18.0.0",
56
56
  "utility-types": "^3.10.0"
57
57
  },
@@ -62,5 +62,5 @@
62
62
  "engines": {
63
63
  "node": ">=16.14"
64
64
  },
65
- "gitHead": "7327f7ff880ed97ad7855744e59c9c55d467a950"
65
+ "gitHead": "27a1e90d9fff88af90ecad35bea16d4d7230482a"
66
66
  }
@@ -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
@@ -313,6 +313,10 @@ const LogoSchema = Joi.object({
313
313
  className: Joi.string(),
314
314
  });
315
315
 
316
+ // Normalize prism language to lowercase
317
+ // See https://github.com/facebook/docusaurus/issues/9012
318
+ const PrismLanguage = Joi.string().custom((val) => val.toLowerCase());
319
+
316
320
  export const ThemeConfigSchema = Joi.object<ThemeConfig>({
317
321
  // TODO temporary (@alpha-58)
318
322
  // @ts-expect-error: forbidden
@@ -385,9 +389,9 @@ export const ThemeConfigSchema = Joi.object<ThemeConfig>({
385
389
  plain: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
386
390
  styles: Joi.alternatives().try(Joi.array(), Joi.object()).required(),
387
391
  }),
388
- defaultLanguage: Joi.string(),
392
+ defaultLanguage: PrismLanguage,
389
393
  additionalLanguages: Joi.array()
390
- .items(Joi.string())
394
+ .items(PrismLanguage)
391
395
  .default(DEFAULT_CONFIG.prism.additionalLanguages),
392
396
  magicComments: Joi.array()
393
397
  .items(
@@ -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
 
@@ -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
 
@@ -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';
@@ -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 ?
@@ -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' {
@@ -891,8 +900,14 @@ declare module '@theme/MDXComponents' {
891
900
  import type Mermaid from '@theme/Mermaid';
892
901
  import type Head from '@docusaurus/Head';
893
902
 
894
- export type MDXComponentsObject = {
903
+ import type {MDXProvider} from '@mdx-js/react';
904
+
905
+ type MDXComponentsBase = ComponentProps<typeof MDXProvider>['components'];
906
+
907
+ export type MDXComponentsObject = MDXComponentsBase & {
895
908
  readonly Head: typeof Head;
909
+ readonly details: typeof MDXDetails;
910
+
896
911
  readonly Details: typeof MDXDetails;
897
912
  readonly code: typeof MDXCode;
898
913
  readonly a: typeof MDXA;