@docusaurus/theme-classic 0.0.0-4735 → 0.0.0-4738

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 (65) hide show
  1. package/lib/theme-classic.d.ts +63 -33
  2. package/lib-next/theme/BlogArchivePage/index.js +13 -9
  3. package/lib-next/theme/BlogListPage/index.js +34 -13
  4. package/lib-next/theme/BlogPostPage/index.js +56 -45
  5. package/lib-next/theme/BlogTagsListPage/index.js +16 -12
  6. package/lib-next/theme/BlogTagsPostsPage/index.js +40 -33
  7. package/lib-next/theme/DocCategoryGeneratedIndexPage/index.js +27 -6
  8. package/lib-next/theme/DocItem/index.js +78 -63
  9. package/lib-next/theme/DocPage/index.js +85 -77
  10. package/lib-next/theme/DocPage/styles.module.css +0 -4
  11. package/lib-next/theme/DocSidebar/Mobile/index.js +24 -20
  12. package/lib-next/theme/DocTagDocListPage/index.js +38 -31
  13. package/lib-next/theme/DocTagsListPage/index.js +21 -16
  14. package/lib-next/theme/Layout/index.js +15 -10
  15. package/lib-next/theme/LayoutProviders/index.js +4 -6
  16. package/lib-next/theme/MDXPage/index.js +32 -26
  17. package/lib-next/theme/Navbar/ColorModeToggle/index.js +25 -0
  18. package/lib-next/theme/Navbar/Content/index.js +70 -0
  19. package/lib-next/theme/Navbar/Content/styles.module.css +15 -0
  20. package/lib-next/theme/Navbar/Layout/index.js +54 -0
  21. package/{src/theme/Navbar → lib-next/theme/Navbar/Layout}/styles.module.css +0 -13
  22. package/lib-next/theme/Navbar/Logo/index.js +17 -0
  23. package/lib-next/theme/Navbar/MobileSidebar/Header/index.js +33 -0
  24. package/lib-next/theme/Navbar/MobileSidebar/Layout/index.js +28 -0
  25. package/lib-next/theme/Navbar/MobileSidebar/PrimaryMenu/index.js +33 -0
  26. package/lib-next/theme/Navbar/MobileSidebar/SecondaryMenu/index.js +36 -0
  27. package/lib-next/theme/Navbar/MobileSidebar/Toggle/index.js +23 -0
  28. package/lib-next/theme/Navbar/MobileSidebar/index.js +31 -0
  29. package/lib-next/theme/Navbar/index.js +6 -273
  30. package/lib-next/theme/NotFound.js +38 -33
  31. package/lib-next/theme/{LayoutHead → SiteMetadata}/index.js +11 -26
  32. package/package.json +13 -13
  33. package/src/theme/BlogArchivePage/index.tsx +13 -9
  34. package/src/theme/BlogListPage/index.tsx +32 -13
  35. package/src/theme/BlogPostPage/index.tsx +55 -48
  36. package/src/theme/BlogTagsListPage/index.tsx +16 -12
  37. package/src/theme/BlogTagsPostsPage/index.tsx +39 -32
  38. package/src/theme/DocCategoryGeneratedIndexPage/index.tsx +31 -4
  39. package/src/theme/DocItem/index.tsx +65 -52
  40. package/src/theme/DocPage/index.tsx +85 -77
  41. package/src/theme/DocPage/styles.module.css +0 -4
  42. package/src/theme/DocSidebar/Mobile/index.tsx +26 -23
  43. package/src/theme/DocTagDocListPage/index.tsx +38 -30
  44. package/src/theme/DocTagsListPage/index.tsx +21 -16
  45. package/src/theme/Layout/index.tsx +15 -10
  46. package/src/theme/LayoutProviders/index.tsx +4 -6
  47. package/src/theme/MDXPage/index.tsx +32 -26
  48. package/src/theme/Navbar/ColorModeToggle/index.tsx +30 -0
  49. package/src/theme/Navbar/Content/index.tsx +81 -0
  50. package/src/theme/Navbar/Content/styles.module.css +15 -0
  51. package/src/theme/Navbar/Layout/index.tsx +57 -0
  52. package/{lib-next/theme/Navbar → src/theme/Navbar/Layout}/styles.module.css +0 -13
  53. package/src/theme/Navbar/Logo/index.tsx +19 -0
  54. package/src/theme/Navbar/MobileSidebar/Header/index.tsx +34 -0
  55. package/src/theme/Navbar/MobileSidebar/Layout/index.tsx +31 -0
  56. package/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx +38 -0
  57. package/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.tsx +38 -0
  58. package/src/theme/Navbar/MobileSidebar/Toggle/index.tsx +25 -0
  59. package/src/theme/Navbar/MobileSidebar/index.tsx +33 -0
  60. package/src/theme/Navbar/index.tsx +6 -292
  61. package/src/theme/NotFound.tsx +38 -33
  62. package/src/theme/{LayoutHead → SiteMetadata}/index.tsx +11 -25
  63. package/src/theme-classic.d.ts +63 -33
  64. package/lib-next/theme/Seo/index.js +0 -40
  65. package/src/theme/Seo/index.tsx +0 -49
@@ -4,280 +4,13 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React, {useCallback, useState, useEffect} from 'react';
8
- import clsx from 'clsx';
9
- import Translate from '@docusaurus/Translate';
10
- import SearchBar from '@theme/SearchBar';
11
- import ColorModeToggle from '@theme/ColorModeToggle';
12
- import {
13
- useThemeConfig,
14
- useMobileSecondaryMenuRenderer,
15
- usePrevious,
16
- useHistoryPopHandler,
17
- useHideableNavbar,
18
- useLockBodyScroll,
19
- useWindowSize,
20
- useColorMode,
21
- } from '@docusaurus/theme-common';
22
- import {useActivePlugin} from '@docusaurus/plugin-content-docs/client';
23
- import NavbarItem from '@theme/NavbarItem';
24
- import Logo from '@theme/Logo';
25
- import IconMenu from '@theme/IconMenu';
26
- import IconClose from '@theme/IconClose';
27
- import styles from './styles.module.css'; // retrocompatible with v1
28
-
29
- const DefaultNavItemPosition = 'right';
30
-
31
- function useNavbarItems() {
32
- // TODO temporary casting until ThemeConfig type is improved
33
- return useThemeConfig().navbar.items;
34
- } // If split links by left/right
35
- // if position is unspecified, fallback to right (as v1)
36
-
37
- function splitNavItemsByPosition(items) {
38
- const leftItems = items.filter(
39
- (item) => (item.position ?? DefaultNavItemPosition) === 'left',
40
- );
41
- const rightItems = items.filter(
42
- (item) => (item.position ?? DefaultNavItemPosition) === 'right',
43
- );
44
- return {
45
- leftItems,
46
- rightItems,
47
- };
48
- }
49
-
50
- function useMobileSidebar() {
51
- const windowSize = useWindowSize(); // Mobile sidebar not visible on hydration: can avoid SSR rendering
52
-
53
- const shouldRender = windowSize === 'mobile'; // || windowSize === 'ssr';
54
-
55
- const [shown, setShown] = useState(false); // Close mobile sidebar on navigation pop
56
- // Most likely firing when using the Android back button (but not only)
57
-
58
- useHistoryPopHandler(() => {
59
- if (shown) {
60
- setShown(false); // Should we prevent the navigation here?
61
- // See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846
62
-
63
- return false; // prevent pop navigation
64
- }
65
-
66
- return undefined;
67
- });
68
- const toggle = useCallback(() => {
69
- setShown((s) => !s);
70
- }, []);
71
- useEffect(() => {
72
- if (windowSize === 'desktop') {
73
- setShown(false);
74
- }
75
- }, [windowSize]);
76
- return {
77
- shouldRender,
78
- toggle,
79
- shown,
80
- };
81
- }
82
-
83
- function useColorModeToggle() {
84
- const {
85
- colorMode: {disableSwitch},
86
- } = useThemeConfig();
87
- const {colorMode, setColorMode} = useColorMode();
88
- return {
89
- value: colorMode,
90
- onChange: setColorMode,
91
- disabled: disableSwitch,
92
- };
93
- }
94
-
95
- function useSecondaryMenu({sidebarShown, toggleSidebar}) {
96
- const content = useMobileSecondaryMenuRenderer()?.({
97
- toggleSidebar,
98
- });
99
- const previousContent = usePrevious(content);
100
- const [shown, setShown] = useState(
101
- () =>
102
- // /!\ content is set with useEffect,
103
- // so it's not available on mount anyway
104
- // "return !!content" => always returns false
105
- false,
106
- ); // When content is become available for the first time (set in useEffect)
107
- // we set this content to be shown!
108
-
109
- useEffect(() => {
110
- const contentBecameAvailable = content && !previousContent;
111
-
112
- if (contentBecameAvailable) {
113
- setShown(true);
114
- }
115
- }, [content, previousContent]);
116
- const hasContent = !!content; // On sidebar close, secondary menu is set to be shown on next re-opening
117
- // (if any secondary menu content available)
118
-
119
- useEffect(() => {
120
- if (!hasContent) {
121
- setShown(false);
122
- return;
123
- }
124
-
125
- if (!sidebarShown) {
126
- setShown(true);
127
- }
128
- }, [sidebarShown, hasContent]);
129
- const hide = useCallback(() => {
130
- setShown(false);
131
- }, []);
132
- return {
133
- shown,
134
- hide,
135
- content,
136
- };
137
- }
138
-
139
- function NavbarMobileSidebar({sidebarShown, toggleSidebar}) {
140
- useLockBodyScroll(sidebarShown);
141
- const items = useNavbarItems();
142
- const colorModeToggle = useColorModeToggle();
143
- const secondaryMenu = useSecondaryMenu({
144
- sidebarShown,
145
- toggleSidebar,
146
- });
147
- return (
148
- <div className="navbar-sidebar">
149
- <div className="navbar-sidebar__brand">
150
- <Logo
151
- className="navbar__brand"
152
- imageClassName="navbar__logo"
153
- titleClassName="navbar__title"
154
- />
155
- {!colorModeToggle.disabled && (
156
- <ColorModeToggle
157
- className={styles.navbarSidebarToggle}
158
- value={colorModeToggle.value}
159
- onChange={colorModeToggle.onChange}
160
- />
161
- )}
162
- <button
163
- type="button"
164
- className="clean-btn navbar-sidebar__close"
165
- onClick={toggleSidebar}>
166
- <IconClose
167
- color="var(--ifm-color-emphasis-600)"
168
- className={styles.navbarSidebarCloseSvg}
169
- />
170
- </button>
171
- </div>
172
-
173
- <div
174
- className={clsx('navbar-sidebar__items', {
175
- 'navbar-sidebar__items--show-secondary': secondaryMenu.shown,
176
- })}>
177
- <div className="navbar-sidebar__item menu">
178
- <ul className="menu__list">
179
- {items.map((item, i) => (
180
- <NavbarItem mobile {...item} onClick={toggleSidebar} key={i} />
181
- ))}
182
- </ul>
183
- </div>
184
-
185
- <div className="navbar-sidebar__item menu">
186
- {items.length > 0 && (
187
- <button
188
- type="button"
189
- className="clean-btn navbar-sidebar__back"
190
- onClick={secondaryMenu.hide}>
191
- <Translate
192
- id="theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel"
193
- description="The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)">
194
- ← Back to main menu
195
- </Translate>
196
- </button>
197
- )}
198
- {secondaryMenu.content}
199
- </div>
200
- </div>
201
- </div>
202
- );
203
- }
204
-
7
+ import React from 'react';
8
+ import NavbarLayout from '@theme/Navbar/Layout';
9
+ import NavbarContent from '@theme/Navbar/Content';
205
10
  export default function Navbar() {
206
- const {
207
- navbar: {hideOnScroll, style},
208
- } = useThemeConfig();
209
- const mobileSidebar = useMobileSidebar();
210
- const colorModeToggle = useColorModeToggle();
211
- const activeDocPlugin = useActivePlugin();
212
- const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
213
- const items = useNavbarItems();
214
- const hasSearchNavbarItem = items.some((item) => item.type === 'search');
215
- const {leftItems, rightItems} = splitNavItemsByPosition(items);
216
11
  return (
217
- <nav
218
- ref={navbarRef}
219
- className={clsx(
220
- 'navbar',
221
- 'navbar--fixed-top',
222
- hideOnScroll && [
223
- styles.navbarHideable,
224
- !isNavbarVisible && styles.navbarHidden,
225
- ],
226
- {
227
- 'navbar--dark': style === 'dark',
228
- 'navbar--primary': style === 'primary',
229
- 'navbar-sidebar--show': mobileSidebar.shown,
230
- },
231
- )}>
232
- <div className="navbar__inner">
233
- <div className="navbar__items">
234
- {(items?.length > 0 || activeDocPlugin) && (
235
- <button
236
- aria-label="Navigation bar toggle"
237
- className="navbar__toggle clean-btn"
238
- type="button"
239
- tabIndex={0}
240
- onClick={mobileSidebar.toggle}
241
- onKeyDown={mobileSidebar.toggle}>
242
- <IconMenu />
243
- </button>
244
- )}
245
- <Logo
246
- className="navbar__brand"
247
- imageClassName="navbar__logo"
248
- titleClassName="navbar__title"
249
- />
250
- {leftItems.map((item, i) => (
251
- <NavbarItem {...item} key={i} />
252
- ))}
253
- </div>
254
- <div className="navbar__items navbar__items--right">
255
- {rightItems.map((item, i) => (
256
- <NavbarItem {...item} key={i} />
257
- ))}
258
- {!colorModeToggle.disabled && (
259
- <ColorModeToggle
260
- className={styles.toggle}
261
- value={colorModeToggle.value}
262
- onChange={colorModeToggle.onChange}
263
- />
264
- )}
265
- {!hasSearchNavbarItem && <SearchBar />}
266
- </div>
267
- </div>
268
-
269
- <div
270
- role="presentation"
271
- className="navbar-sidebar__backdrop"
272
- onClick={mobileSidebar.toggle}
273
- />
274
-
275
- {mobileSidebar.shouldRender && (
276
- <NavbarMobileSidebar
277
- sidebarShown={mobileSidebar.shown}
278
- toggleSidebar={mobileSidebar.toggle}
279
- />
280
- )}
281
- </nav>
12
+ <NavbarLayout>
13
+ <NavbarContent />
14
+ </NavbarLayout>
282
15
  );
283
16
  }
@@ -7,41 +7,46 @@
7
7
  import React from 'react';
8
8
  import Layout from '@theme/Layout';
9
9
  import Translate, {translate} from '@docusaurus/Translate';
10
+ import {PageMetadata} from '@docusaurus/theme-common';
10
11
  export default function NotFound() {
11
12
  return (
12
- <Layout
13
- title={translate({
14
- id: 'theme.NotFound.title',
15
- message: 'Page Not Found',
16
- })}>
17
- <main className="container margin-vert--xl">
18
- <div className="row">
19
- <div className="col col--6 col--offset-3">
20
- <h1 className="hero__title">
21
- <Translate
22
- id="theme.NotFound.title"
23
- description="The title of the 404 page">
24
- Page Not Found
25
- </Translate>
26
- </h1>
27
- <p>
28
- <Translate
29
- id="theme.NotFound.p1"
30
- description="The first paragraph of the 404 page">
31
- We could not find what you were looking for.
32
- </Translate>
33
- </p>
34
- <p>
35
- <Translate
36
- id="theme.NotFound.p2"
37
- description="The 2nd paragraph of the 404 page">
38
- Please contact the owner of the site that linked you to the
39
- original URL and let them know their link is broken.
40
- </Translate>
41
- </p>
13
+ <>
14
+ <PageMetadata
15
+ title={translate({
16
+ id: 'theme.NotFound.title',
17
+ message: 'Page Not Found',
18
+ })}
19
+ />
20
+ <Layout>
21
+ <main className="container margin-vert--xl">
22
+ <div className="row">
23
+ <div className="col col--6 col--offset-3">
24
+ <h1 className="hero__title">
25
+ <Translate
26
+ id="theme.NotFound.title"
27
+ description="The title of the 404 page">
28
+ Page Not Found
29
+ </Translate>
30
+ </h1>
31
+ <p>
32
+ <Translate
33
+ id="theme.NotFound.p1"
34
+ description="The first paragraph of the 404 page">
35
+ We could not find what you were looking for.
36
+ </Translate>
37
+ </p>
38
+ <p>
39
+ <Translate
40
+ id="theme.NotFound.p2"
41
+ description="The 2nd paragraph of the 404 page">
42
+ Please contact the owner of the site that linked you to the
43
+ original URL and let them know their link is broken.
44
+ </Translate>
45
+ </p>
46
+ </div>
42
47
  </div>
43
- </div>
44
- </main>
45
- </Layout>
48
+ </main>
49
+ </Layout>
50
+ </>
46
51
  );
47
52
  }
@@ -9,15 +9,15 @@ import Head from '@docusaurus/Head';
9
9
  import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
10
10
  import useBaseUrl from '@docusaurus/useBaseUrl';
11
11
  import SearchMetadata from '@theme/SearchMetadata';
12
- import Seo from '@theme/Seo';
13
12
  import {
13
+ PageMetadata,
14
14
  DEFAULT_SEARCH_TAG,
15
- useTitleFormatter,
16
15
  useAlternatePageUtils,
17
16
  useThemeConfig,
18
17
  keyboardFocusedClassName,
19
18
  } from '@docusaurus/theme-common';
20
- import {useLocation} from '@docusaurus/router'; // Useful for SEO
19
+ import {useLocation} from '@docusaurus/router'; // TODO move to SiteMetadataDefaults or theme-common ?
20
+ // Useful for i18n/SEO
21
21
  // See https://developers.google.com/search/docs/advanced/crawling/localized-versions
22
22
  // See https://github.com/facebook/docusaurus/issues/3317
23
23
 
@@ -59,7 +59,7 @@ function useDefaultCanonicalUrl() {
59
59
  } = useDocusaurusContext();
60
60
  const {pathname} = useLocation();
61
61
  return siteUrl + useBaseUrl(pathname);
62
- }
62
+ } // TODO move to SiteMetadataDefaults or theme-common ?
63
63
 
64
64
  function CanonicalUrlHeaders({permalink}) {
65
65
  const {
@@ -77,44 +77,29 @@ function CanonicalUrlHeaders({permalink}) {
77
77
  );
78
78
  }
79
79
 
80
- export default function LayoutHead(props) {
80
+ export default function SiteMetadata() {
81
81
  const {
82
- siteConfig: {favicon},
83
- i18n: {currentLocale, localeConfigs},
84
- } = useDocusaurusContext();
82
+ i18n: {currentLocale},
83
+ } = useDocusaurusContext(); // TODO maybe move these 2 themeConfig to siteConfig?
84
+ // These seems useful for other themes as well
85
+
85
86
  const {metadata, image: defaultImage} = useThemeConfig();
86
- const {title, description, image, keywords, searchMetadata} = props;
87
- const faviconUrl = useBaseUrl(favicon);
88
- const pageTitle = useTitleFormatter(title);
89
- const {htmlLang, direction: htmlDir} = localeConfigs[currentLocale];
90
87
  return (
91
88
  <>
92
89
  <Head>
93
- <html lang={htmlLang} dir={htmlDir} />
94
- {favicon && <link rel="icon" href={faviconUrl} />}
95
- <title>{pageTitle}</title>
96
- <meta property="og:title" content={pageTitle} />
97
90
  <meta name="twitter:card" content="summary_large_image" />
98
91
  {/* The keyboard focus class name need to be applied when SSR so links
99
92
  are outlined when JS is disabled */}
100
93
  <body className={keyboardFocusedClassName} />
101
94
  </Head>
102
95
 
103
- {/* image can override the default image */}
104
- {defaultImage && <Seo image={defaultImage} />}
105
- {image && <Seo image={image} />}
106
-
107
- <Seo description={description} keywords={keywords} />
96
+ {defaultImage && <PageMetadata image={defaultImage} />}
108
97
 
109
98
  <CanonicalUrlHeaders />
110
99
 
111
100
  <AlternateLangHeaders />
112
101
 
113
- <SearchMetadata
114
- tag={DEFAULT_SEARCH_TAG}
115
- locale={currentLocale}
116
- {...searchMetadata}
117
- />
102
+ <SearchMetadata tag={DEFAULT_SEARCH_TAG} locale={currentLocale} />
118
103
 
119
104
  <Head // it's important to have an additional <Head> element here,
120
105
  // as it allows react-helmet to override values set in previous <Head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-classic",
3
- "version": "0.0.0-4735",
3
+ "version": "0.0.0-4738",
4
4
  "description": "Classic theme for Docusaurus",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/theme-classic.d.ts",
@@ -21,15 +21,15 @@
21
21
  "format:lib-next": "prettier --config ../../.prettierrc --write \"lib-next/**/*.{js,ts,jsx,tsc}\""
22
22
  },
23
23
  "dependencies": {
24
- "@docusaurus/core": "0.0.0-4735",
25
- "@docusaurus/plugin-content-blog": "0.0.0-4735",
26
- "@docusaurus/plugin-content-docs": "0.0.0-4735",
27
- "@docusaurus/plugin-content-pages": "0.0.0-4735",
28
- "@docusaurus/theme-common": "0.0.0-4735",
29
- "@docusaurus/theme-translations": "0.0.0-4735",
30
- "@docusaurus/utils": "0.0.0-4735",
31
- "@docusaurus/utils-common": "0.0.0-4735",
32
- "@docusaurus/utils-validation": "0.0.0-4735",
24
+ "@docusaurus/core": "0.0.0-4738",
25
+ "@docusaurus/plugin-content-blog": "0.0.0-4738",
26
+ "@docusaurus/plugin-content-docs": "0.0.0-4738",
27
+ "@docusaurus/plugin-content-pages": "0.0.0-4738",
28
+ "@docusaurus/theme-common": "0.0.0-4738",
29
+ "@docusaurus/theme-translations": "0.0.0-4738",
30
+ "@docusaurus/utils": "0.0.0-4738",
31
+ "@docusaurus/utils-common": "0.0.0-4738",
32
+ "@docusaurus/utils-validation": "0.0.0-4738",
33
33
  "@mdx-js/react": "^1.6.22",
34
34
  "clsx": "^1.1.1",
35
35
  "copy-text-to-clipboard": "^3.0.1",
@@ -42,8 +42,8 @@
42
42
  "rtlcss": "^3.5.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@docusaurus/module-type-aliases": "0.0.0-4735",
46
- "@docusaurus/types": "0.0.0-4735",
45
+ "@docusaurus/module-type-aliases": "0.0.0-4738",
46
+ "@docusaurus/types": "0.0.0-4738",
47
47
  "@types/mdx-js__react": "^1.5.5",
48
48
  "@types/prismjs": "^1.26.0",
49
49
  "@types/rtlcss": "^3.1.2",
@@ -59,5 +59,5 @@
59
59
  "engines": {
60
60
  "node": ">=14"
61
61
  },
62
- "gitHead": "0f869a8574293be34dcba878680b8adb519887dd"
62
+ "gitHead": "a9c78632ceba2532982c6b12e97de11b055e6c45"
63
63
  }
@@ -10,6 +10,7 @@ import Layout from '@theme/Layout';
10
10
  import Link from '@docusaurus/Link';
11
11
  import type {ArchiveBlogPost, Props} from '@theme/BlogArchivePage';
12
12
  import {translate} from '@docusaurus/Translate';
13
+ import {PageMetadata} from '@docusaurus/theme-common';
13
14
 
14
15
  type YearProp = {
15
16
  year: string;
@@ -75,14 +76,17 @@ export default function BlogArchive({archive}: Props): JSX.Element {
75
76
  });
76
77
  const years = listPostsByYears(archive.blogPosts);
77
78
  return (
78
- <Layout title={title} description={description}>
79
- <header className="hero hero--primary">
80
- <div className="container">
81
- <h1 className="hero__title">{title}</h1>
82
- <p className="hero__subtitle">{description}</p>
83
- </div>
84
- </header>
85
- <main>{years.length > 0 && <YearsSection years={years} />}</main>
86
- </Layout>
79
+ <>
80
+ <PageMetadata title={title} description={description} />
81
+ <Layout>
82
+ <header className="hero hero--primary">
83
+ <div className="container">
84
+ <h1 className="hero__title">{title}</h1>
85
+ <p className="hero__subtitle">{description}</p>
86
+ </div>
87
+ </header>
88
+ <main>{years.length > 0 && <YearsSection years={years} />}</main>
89
+ </Layout>
90
+ </>
87
91
  );
88
92
  }
@@ -12,28 +12,34 @@ import BlogLayout from '@theme/BlogLayout';
12
12
  import BlogPostItem from '@theme/BlogPostItem';
13
13
  import BlogListPaginator from '@theme/BlogListPaginator';
14
14
  import type {Props} from '@theme/BlogListPage';
15
- import {ThemeClassNames} from '@docusaurus/theme-common';
15
+ import {
16
+ PageMetadata,
17
+ HtmlClassNameProvider,
18
+ ThemeClassNames,
19
+ } from '@docusaurus/theme-common';
20
+ import SearchMetadata from '@theme/SearchMetadata';
21
+ import clsx from 'clsx';
16
22
 
17
- export default function BlogListPage(props: Props): JSX.Element {
18
- const {metadata, items, sidebar} = props;
23
+ function BlogListPageMetadata(props: Props): JSX.Element {
24
+ const {metadata} = props;
19
25
  const {
20
26
  siteConfig: {title: siteTitle},
21
27
  } = useDocusaurusContext();
22
28
  const {blogDescription, blogTitle, permalink} = metadata;
23
29
  const isBlogOnlyMode = permalink === '/';
24
30
  const title = isBlogOnlyMode ? siteTitle : blogTitle;
31
+ return (
32
+ <>
33
+ <PageMetadata title={title} description={blogDescription} />
34
+ <SearchMetadata tag="blog_posts_list" />
35
+ </>
36
+ );
37
+ }
25
38
 
39
+ function BlogListPageContent(props: Props): JSX.Element {
40
+ const {metadata, items, sidebar} = props;
26
41
  return (
27
- <BlogLayout
28
- title={title}
29
- description={blogDescription}
30
- wrapperClassName={ThemeClassNames.wrapper.blogPages}
31
- pageClassName={ThemeClassNames.page.blogListPage}
32
- searchMetadata={{
33
- // assign unique search tag to exclude this page from search results!
34
- tag: 'blog_posts_list',
35
- }}
36
- sidebar={sidebar}>
42
+ <BlogLayout sidebar={sidebar}>
37
43
  {items.map(({content: BlogPostContent}) => (
38
44
  <BlogPostItem
39
45
  key={BlogPostContent.metadata.permalink}
@@ -48,3 +54,16 @@ export default function BlogListPage(props: Props): JSX.Element {
48
54
  </BlogLayout>
49
55
  );
50
56
  }
57
+
58
+ export default function BlogListPage(props: Props): JSX.Element {
59
+ return (
60
+ <HtmlClassNameProvider
61
+ className={clsx(
62
+ ThemeClassNames.wrapper.blogPages,
63
+ ThemeClassNames.page.blogListPage,
64
+ )}>
65
+ <BlogListPageMetadata {...props} />
66
+ <BlogListPageContent {...props} />
67
+ </HtmlClassNameProvider>
68
+ );
69
+ }