@docusaurus/theme-classic 2.0.0-beta.17 → 2.0.0-beta.18
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.
- package/lib/getSwizzleConfig.js +113 -2
- package/lib/index.js +7 -12
- package/lib/theme-classic.d.ts +286 -60
- package/lib/translations.js +12 -2
- package/lib/validateThemeConfig.js +1 -1
- package/lib-next/theme/BackToTopButton/index.js +1 -3
- package/lib-next/theme/BlogArchivePage/index.js +14 -10
- package/lib-next/theme/BlogListPage/index.js +34 -13
- package/lib-next/theme/BlogPostItem/index.js +6 -6
- package/lib-next/theme/BlogPostPage/index.js +56 -45
- package/lib-next/theme/BlogTagsListPage/index.js +16 -12
- package/lib-next/theme/BlogTagsPostsPage/index.js +40 -33
- package/lib-next/theme/CodeBlock/CopyButton/index.js +60 -0
- package/lib-next/theme/CodeBlock/CopyButton/styles.module.css +66 -0
- package/lib-next/theme/CodeBlock/index.js +4 -36
- package/lib-next/theme/CodeBlock/styles.module.css +2 -22
- package/lib-next/theme/ColorModeToggle/index.js +36 -57
- package/lib-next/theme/ColorModeToggle/styles.module.css +8 -24
- package/lib-next/theme/DocBreadcrumbs/index.js +28 -11
- package/lib-next/theme/DocBreadcrumbs/styles.module.css +2 -17
- package/lib-next/theme/DocCard/index.js +17 -15
- package/lib-next/theme/DocCard/styles.module.css +8 -17
- package/lib-next/theme/DocCardList/index.js +15 -3
- package/lib-next/theme/DocCategoryGeneratedIndexPage/index.js +27 -6
- package/lib-next/theme/DocItem/index.js +84 -66
- package/lib-next/theme/DocPage/index.js +88 -89
- package/lib-next/theme/DocPage/styles.module.css +0 -4
- package/lib-next/theme/DocSidebar/Desktop/CollapseButton/index.js +34 -0
- package/lib-next/theme/DocSidebar/Desktop/CollapseButton/styles.module.css +44 -0
- package/lib-next/theme/DocSidebar/Desktop/Content/index.js +46 -0
- package/lib-next/theme/DocSidebar/Desktop/Content/styles.module.css +17 -0
- package/lib-next/theme/DocSidebar/Desktop/index.js +34 -0
- package/lib-next/theme/DocSidebar/Desktop/styles.module.css +50 -0
- package/lib-next/theme/DocSidebar/Mobile/index.js +49 -0
- package/lib-next/theme/DocSidebar/index.js +6 -113
- package/lib-next/theme/DocSidebarItem/index.js +14 -13
- package/lib-next/theme/DocSidebarItem/styles.module.css +4 -0
- package/lib-next/theme/DocTagDocListPage/index.js +38 -31
- package/lib-next/theme/DocTagsListPage/index.js +21 -16
- package/lib-next/theme/Footer/Copyright/index.js +18 -0
- package/lib-next/theme/Footer/Layout/index.js +26 -0
- package/lib-next/theme/Footer/LinkItem/index.js +33 -0
- package/lib-next/theme/Footer/Links/MultiColumn/index.js +47 -0
- package/lib-next/theme/Footer/Links/Simple/index.js +41 -0
- package/lib-next/theme/Footer/Links/index.js +17 -0
- package/lib-next/theme/Footer/Logo/index.js +38 -0
- package/lib-next/theme/Footer/{styles.module.css → Logo/styles.module.css} +0 -0
- package/lib-next/theme/Footer/index.js +11 -163
- package/lib-next/theme/Heading/index.js +6 -4
- package/lib-next/theme/IconExternalLink/styles.module.css +0 -2
- package/lib-next/theme/Layout/index.js +15 -10
- package/lib-next/theme/LayoutProviders/index.js +5 -4
- package/lib-next/theme/MDXComponents/A.js +11 -0
- package/lib-next/theme/MDXComponents/Code.js +28 -0
- package/lib-next/theme/MDXComponents/Details.js +20 -0
- package/lib-next/theme/MDXComponents/Head.js +26 -0
- package/lib-next/theme/MDXComponents/Heading.js +11 -0
- package/lib-next/theme/MDXComponents/Img.js +24 -0
- package/lib-next/theme/MDXComponents/Img.module.css +10 -0
- package/lib-next/theme/MDXComponents/Pre.js +18 -0
- package/lib-next/theme/MDXComponents/Ul.js +23 -0
- package/{src/theme/MDXComponents/styles.css → lib-next/theme/MDXComponents/Ul.module.css} +1 -5
- package/lib-next/theme/MDXComponents/index.js +22 -71
- package/lib-next/theme/MDXContent/index.js +12 -0
- package/lib-next/theme/MDXPage/index.js +33 -28
- package/lib-next/theme/Navbar/ColorModeToggle/index.js +25 -0
- package/lib-next/theme/Navbar/Content/index.js +70 -0
- package/lib-next/theme/Navbar/Content/styles.module.css +15 -0
- package/lib-next/theme/Navbar/Layout/index.js +54 -0
- package/{src/theme/Navbar → lib-next/theme/Navbar/Layout}/styles.module.css +0 -13
- package/lib-next/theme/Navbar/Logo/index.js +17 -0
- package/lib-next/theme/Navbar/MobileSidebar/Header/index.js +33 -0
- package/lib-next/theme/Navbar/MobileSidebar/Layout/index.js +28 -0
- package/lib-next/theme/Navbar/MobileSidebar/PrimaryMenu/index.js +33 -0
- package/lib-next/theme/Navbar/MobileSidebar/SecondaryMenu/index.js +36 -0
- package/lib-next/theme/Navbar/MobileSidebar/Toggle/index.js +23 -0
- package/lib-next/theme/Navbar/MobileSidebar/index.js +31 -0
- package/lib-next/theme/Navbar/index.js +6 -271
- package/lib-next/theme/NavbarItem/DefaultNavbarItem.js +2 -6
- package/lib-next/theme/NavbarItem/DropdownNavbarItem.js +10 -2
- package/lib-next/theme/NavbarItem/NavbarNavLink.js +8 -12
- package/lib-next/theme/NotFound.js +38 -33
- package/lib-next/theme/{LayoutHead → SiteMetadata}/index.js +11 -26
- package/lib-next/theme/TOCCollapsible/index.js +1 -3
- package/lib-next/theme/Tabs/__tests__/index.test.js +5 -5
- package/lib-next/theme/Tabs/index.js +2 -2
- package/lib-next/theme/Tag/index.js +4 -4
- package/lib-next/theme/ThemedImage/index.js +3 -3
- package/package.json +17 -17
- package/src/getSwizzleConfig.ts +122 -1
- package/src/index.ts +10 -12
- package/src/theme/BackToTopButton/index.tsx +1 -3
- package/src/theme/BlogArchivePage/index.tsx +18 -17
- package/src/theme/BlogLayout/index.tsx +1 -1
- package/src/theme/BlogListPage/index.tsx +32 -13
- package/src/theme/BlogPostItem/index.tsx +6 -6
- package/src/theme/BlogPostPage/index.tsx +55 -48
- package/src/theme/BlogTagsListPage/index.tsx +16 -12
- package/src/theme/BlogTagsPostsPage/index.tsx +39 -32
- package/src/theme/CodeBlock/CopyButton/index.tsx +66 -0
- package/src/theme/CodeBlock/CopyButton/styles.module.css +66 -0
- package/src/theme/CodeBlock/index.tsx +6 -38
- package/src/theme/CodeBlock/styles.module.css +2 -22
- package/src/theme/ColorModeToggle/index.tsx +36 -61
- package/src/theme/ColorModeToggle/styles.module.css +8 -24
- package/src/theme/DocBreadcrumbs/index.tsx +29 -10
- package/src/theme/DocBreadcrumbs/styles.module.css +2 -17
- package/src/theme/DocCard/index.tsx +24 -17
- package/src/theme/DocCard/styles.module.css +8 -17
- package/src/theme/DocCardList/index.tsx +14 -3
- package/src/theme/DocCategoryGeneratedIndexPage/index.tsx +31 -4
- package/src/theme/DocItem/index.tsx +71 -55
- package/src/theme/DocPage/index.tsx +89 -90
- package/src/theme/DocPage/styles.module.css +0 -4
- package/src/theme/DocSidebar/Desktop/CollapseButton/index.tsx +38 -0
- package/src/theme/DocSidebar/Desktop/CollapseButton/styles.module.css +44 -0
- package/src/theme/DocSidebar/Desktop/Content/index.tsx +55 -0
- package/src/theme/DocSidebar/Desktop/Content/styles.module.css +17 -0
- package/src/theme/DocSidebar/Desktop/index.tsx +38 -0
- package/src/theme/DocSidebar/Desktop/styles.module.css +50 -0
- package/src/theme/DocSidebar/Mobile/index.tsx +54 -0
- package/src/theme/DocSidebar/index.tsx +6 -121
- package/src/theme/DocSidebarItem/index.tsx +15 -16
- package/src/theme/DocSidebarItem/styles.module.css +4 -0
- package/src/theme/DocTagDocListPage/index.tsx +38 -30
- package/src/theme/DocTagsListPage/index.tsx +21 -16
- package/src/theme/DocVersionBanner/index.tsx +3 -4
- package/src/theme/Footer/Copyright/index.tsx +20 -0
- package/src/theme/Footer/Layout/index.tsx +34 -0
- package/src/theme/Footer/LinkItem/index.tsx +36 -0
- package/src/theme/Footer/Links/MultiColumn/index.tsx +51 -0
- package/src/theme/Footer/Links/Simple/index.tsx +42 -0
- package/src/theme/Footer/Links/index.tsx +21 -0
- package/src/theme/Footer/Logo/index.tsx +41 -0
- package/src/theme/Footer/{styles.module.css → Logo/styles.module.css} +0 -0
- package/src/theme/Footer/index.tsx +12 -186
- package/src/theme/Heading/index.tsx +6 -4
- package/src/theme/IconExternalLink/styles.module.css +0 -2
- package/src/theme/Layout/index.tsx +15 -10
- package/src/theme/LayoutProviders/index.tsx +5 -4
- package/src/theme/MDXComponents/A.tsx +14 -0
- package/src/theme/MDXComponents/Code.tsx +37 -0
- package/src/theme/MDXComponents/Details.tsx +26 -0
- package/src/theme/MDXComponents/Head.tsx +29 -0
- package/src/theme/MDXComponents/Heading.tsx +14 -0
- package/src/theme/MDXComponents/Img.module.css +10 -0
- package/src/theme/MDXComponents/Img.tsx +26 -0
- package/src/theme/MDXComponents/Pre.tsx +22 -0
- package/{lib-next/theme/MDXComponents/styles.css → src/theme/MDXComponents/Ul.module.css} +1 -5
- package/src/theme/MDXComponents/Ul.tsx +28 -0
- package/src/theme/MDXComponents/index.tsx +23 -80
- package/src/theme/MDXContent/index.tsx +15 -0
- package/src/theme/MDXPage/index.tsx +33 -28
- package/src/theme/Navbar/ColorModeToggle/index.tsx +30 -0
- package/src/theme/Navbar/Content/index.tsx +81 -0
- package/src/theme/Navbar/Content/styles.module.css +15 -0
- package/src/theme/Navbar/Layout/index.tsx +57 -0
- package/{lib-next/theme/Navbar → src/theme/Navbar/Layout}/styles.module.css +0 -13
- package/src/theme/Navbar/Logo/index.tsx +19 -0
- package/src/theme/Navbar/MobileSidebar/Header/index.tsx +34 -0
- package/src/theme/Navbar/MobileSidebar/Layout/index.tsx +31 -0
- package/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx +38 -0
- package/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.tsx +38 -0
- package/src/theme/Navbar/MobileSidebar/Toggle/index.tsx +25 -0
- package/src/theme/Navbar/MobileSidebar/index.tsx +33 -0
- package/src/theme/Navbar/index.tsx +6 -286
- package/src/theme/NavbarItem/DefaultNavbarItem.tsx +2 -2
- package/src/theme/NavbarItem/DropdownNavbarItem.tsx +11 -2
- package/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +1 -1
- package/src/theme/NavbarItem/NavbarNavLink.tsx +3 -7
- package/src/theme/NavbarItem/index.tsx +3 -4
- package/src/theme/NotFound.tsx +38 -33
- package/src/theme/{LayoutHead → SiteMetadata}/index.tsx +11 -25
- package/src/theme/TOCCollapsible/index.tsx +1 -3
- package/src/theme/Tabs/index.tsx +5 -6
- package/src/theme/Tag/index.tsx +4 -4
- package/src/theme/ThemedImage/index.tsx +4 -3
- package/src/theme-classic.d.ts +286 -60
- package/src/translations.ts +12 -6
- package/src/validateThemeConfig.ts +6 -6
- package/lib-next/theme/DocSidebar/styles.module.css +0 -107
- package/lib-next/theme/Seo/index.js +0 -40
- package/src/theme/DocSidebar/styles.module.css +0 -107
- package/src/theme/Seo/index.tsx +0 -49
|
@@ -257,7 +257,7 @@ const ThemeConfigSchema = _utilsValidation.Joi.object({
|
|
|
257
257
|
style: _utilsValidation.Joi.string().equal('dark', 'light').default('light'),
|
|
258
258
|
logo: _utilsValidation.Joi.object({
|
|
259
259
|
alt: _utilsValidation.Joi.string().allow(''),
|
|
260
|
-
src: _utilsValidation.Joi.string(),
|
|
260
|
+
src: _utilsValidation.Joi.string().required(),
|
|
261
261
|
srcDark: _utilsValidation.Joi.string(),
|
|
262
262
|
// TODO infer this from reading the image
|
|
263
263
|
width: _utilsValidation.Joi.alternatives().try(_utilsValidation.Joi.string(), _utilsValidation.Joi.number()),
|
|
@@ -120,9 +120,7 @@ export default function BackToTopButton() {
|
|
|
120
120
|
'clean-btn',
|
|
121
121
|
ThemeClassNames.common.backToTopButton,
|
|
122
122
|
styles.backToTopButton,
|
|
123
|
-
|
|
124
|
-
[styles.backToTopButtonShow]: show,
|
|
125
|
-
},
|
|
123
|
+
show && styles.backToTopButtonShow,
|
|
126
124
|
)}
|
|
127
125
|
type="button"
|
|
128
126
|
onClick={() => smoothScrollTop()}
|
|
@@ -8,6 +8,7 @@ import React from 'react';
|
|
|
8
8
|
import Layout from '@theme/Layout';
|
|
9
9
|
import Link from '@docusaurus/Link';
|
|
10
10
|
import {translate} from '@docusaurus/Translate';
|
|
11
|
+
import {PageMetadata} from '@docusaurus/theme-common';
|
|
11
12
|
|
|
12
13
|
function Year({year, posts}) {
|
|
13
14
|
return (
|
|
@@ -45,7 +46,7 @@ function YearsSection({years}) {
|
|
|
45
46
|
function listPostsByYears(blogPosts) {
|
|
46
47
|
const postsByYear = blogPosts.reduceRight((posts, post) => {
|
|
47
48
|
const year = post.metadata.date.split('-')[0];
|
|
48
|
-
const yearPosts = posts.get(year)
|
|
49
|
+
const yearPosts = posts.get(year) ?? [];
|
|
49
50
|
return posts.set(year, [post, ...yearPosts]);
|
|
50
51
|
}, new Map());
|
|
51
52
|
return Array.from(postsByYear, ([year, posts]) => ({
|
|
@@ -67,14 +68,17 @@ export default function BlogArchive({archive}) {
|
|
|
67
68
|
});
|
|
68
69
|
const years = listPostsByYears(archive.blogPosts);
|
|
69
70
|
return (
|
|
70
|
-
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
<>
|
|
72
|
+
<PageMetadata title={title} description={description} />
|
|
73
|
+
<Layout>
|
|
74
|
+
<header className="hero hero--primary">
|
|
75
|
+
<div className="container">
|
|
76
|
+
<h1 className="hero__title">{title}</h1>
|
|
77
|
+
<p className="hero__subtitle">{description}</p>
|
|
78
|
+
</div>
|
|
79
|
+
</header>
|
|
80
|
+
<main>{years.length > 0 && <YearsSection years={years} />}</main>
|
|
81
|
+
</Layout>
|
|
82
|
+
</>
|
|
79
83
|
);
|
|
80
84
|
}
|
|
@@ -9,9 +9,16 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
|
9
9
|
import BlogLayout from '@theme/BlogLayout';
|
|
10
10
|
import BlogPostItem from '@theme/BlogPostItem';
|
|
11
11
|
import BlogListPaginator from '@theme/BlogListPaginator';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import {
|
|
13
|
+
PageMetadata,
|
|
14
|
+
HtmlClassNameProvider,
|
|
15
|
+
ThemeClassNames,
|
|
16
|
+
} from '@docusaurus/theme-common';
|
|
17
|
+
import SearchMetadata from '@theme/SearchMetadata';
|
|
18
|
+
import clsx from 'clsx';
|
|
19
|
+
|
|
20
|
+
function BlogListPageMetadata(props) {
|
|
21
|
+
const {metadata} = props;
|
|
15
22
|
const {
|
|
16
23
|
siteConfig: {title: siteTitle},
|
|
17
24
|
} = useDocusaurusContext();
|
|
@@ -19,16 +26,17 @@ export default function BlogListPage(props) {
|
|
|
19
26
|
const isBlogOnlyMode = permalink === '/';
|
|
20
27
|
const title = isBlogOnlyMode ? siteTitle : blogTitle;
|
|
21
28
|
return (
|
|
22
|
-
|
|
23
|
-
title={title}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
<>
|
|
30
|
+
<PageMetadata title={title} description={blogDescription} />
|
|
31
|
+
<SearchMetadata tag="blog_posts_list" />
|
|
32
|
+
</>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function BlogListPageContent(props) {
|
|
37
|
+
const {metadata, items, sidebar} = props;
|
|
38
|
+
return (
|
|
39
|
+
<BlogLayout sidebar={sidebar}>
|
|
32
40
|
{items.map(({content: BlogPostContent}) => (
|
|
33
41
|
<BlogPostItem
|
|
34
42
|
key={BlogPostContent.metadata.permalink}
|
|
@@ -43,3 +51,16 @@ export default function BlogListPage(props) {
|
|
|
43
51
|
</BlogLayout>
|
|
44
52
|
);
|
|
45
53
|
}
|
|
54
|
+
|
|
55
|
+
export default function BlogListPage(props) {
|
|
56
|
+
return (
|
|
57
|
+
<HtmlClassNameProvider
|
|
58
|
+
className={clsx(
|
|
59
|
+
ThemeClassNames.wrapper.blogPages,
|
|
60
|
+
ThemeClassNames.page.blogListPage,
|
|
61
|
+
)}>
|
|
62
|
+
<BlogListPageMetadata {...props} />
|
|
63
|
+
<BlogListPageContent {...props} />
|
|
64
|
+
</HtmlClassNameProvider>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import clsx from 'clsx';
|
|
9
|
-
import {MDXProvider} from '@mdx-js/react';
|
|
10
9
|
import Translate, {translate} from '@docusaurus/Translate';
|
|
11
10
|
import Link from '@docusaurus/Link';
|
|
12
11
|
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
13
12
|
import {usePluralForm} from '@docusaurus/theme-common';
|
|
14
13
|
import {blogPostContainerID} from '@docusaurus/utils-common';
|
|
15
|
-
import
|
|
14
|
+
import MDXContent from '@theme/MDXContent';
|
|
16
15
|
import EditThisPage from '@theme/EditThisPage';
|
|
17
16
|
import styles from './styles.module.css';
|
|
18
17
|
import TagsListInline from '@theme/TagsListInline';
|
|
@@ -108,14 +107,15 @@ export default function BlogPostItem(props) {
|
|
|
108
107
|
id={isBlogPostPage ? blogPostContainerID : undefined}
|
|
109
108
|
className="markdown"
|
|
110
109
|
itemProp="articleBody">
|
|
111
|
-
<
|
|
110
|
+
<MDXContent>{children}</MDXContent>
|
|
112
111
|
</div>
|
|
113
112
|
|
|
114
113
|
{(tagsExists || truncated) && (
|
|
115
114
|
<footer
|
|
116
|
-
className={clsx(
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
className={clsx(
|
|
116
|
+
'row docusaurus-mt-lg',
|
|
117
|
+
isBlogPostPage && styles.blogPostDetailsFull,
|
|
118
|
+
)}>
|
|
119
119
|
{tagsExists && (
|
|
120
120
|
<div
|
|
121
121
|
className={clsx('col', {
|
|
@@ -5,36 +5,62 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import Seo from '@theme/Seo';
|
|
9
8
|
import BlogLayout from '@theme/BlogLayout';
|
|
10
9
|
import BlogPostItem from '@theme/BlogPostItem';
|
|
11
10
|
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
|
12
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
PageMetadata,
|
|
13
|
+
HtmlClassNameProvider,
|
|
14
|
+
ThemeClassNames,
|
|
15
|
+
} from '@docusaurus/theme-common';
|
|
13
16
|
import TOC from '@theme/TOC';
|
|
14
|
-
|
|
17
|
+
import clsx from 'clsx';
|
|
18
|
+
|
|
19
|
+
function BlogPostPageMetadata(props) {
|
|
20
|
+
const {content: BlogPostContents} = props;
|
|
21
|
+
const {assets, metadata} = BlogPostContents;
|
|
22
|
+
const {title, description, date, tags, authors, frontMatter} = metadata;
|
|
23
|
+
const {keywords} = frontMatter;
|
|
24
|
+
const image = assets.image ?? frontMatter.image;
|
|
25
|
+
return (
|
|
26
|
+
<PageMetadata
|
|
27
|
+
title={title}
|
|
28
|
+
description={description}
|
|
29
|
+
keywords={keywords}
|
|
30
|
+
image={image}>
|
|
31
|
+
<meta property="og:type" content="article" />
|
|
32
|
+
<meta property="article:published_time" content={date} />
|
|
33
|
+
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
|
|
34
|
+
{authors.some((author) => author.url) && (
|
|
35
|
+
<meta
|
|
36
|
+
property="article:author"
|
|
37
|
+
content={authors
|
|
38
|
+
.map((author) => author.url)
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join(',')}
|
|
41
|
+
/>
|
|
42
|
+
)}
|
|
43
|
+
{tags.length > 0 && (
|
|
44
|
+
<meta
|
|
45
|
+
property="article:tag"
|
|
46
|
+
content={tags.map((tag) => tag.label).join(',')}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
</PageMetadata>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function BlogPostPageContent(props) {
|
|
15
54
|
const {content: BlogPostContents, sidebar} = props;
|
|
16
55
|
const {assets, metadata} = BlogPostContents;
|
|
17
|
-
const {
|
|
18
|
-
title,
|
|
19
|
-
description,
|
|
20
|
-
nextItem,
|
|
21
|
-
prevItem,
|
|
22
|
-
date,
|
|
23
|
-
tags,
|
|
24
|
-
authors,
|
|
25
|
-
frontMatter,
|
|
26
|
-
} = metadata;
|
|
56
|
+
const {nextItem, prevItem, frontMatter} = metadata;
|
|
27
57
|
const {
|
|
28
58
|
hide_table_of_contents: hideTableOfContents,
|
|
29
|
-
keywords,
|
|
30
59
|
toc_min_heading_level: tocMinHeadingLevel,
|
|
31
60
|
toc_max_heading_level: tocMaxHeadingLevel,
|
|
32
61
|
} = frontMatter;
|
|
33
|
-
const image = assets.image ?? frontMatter.image;
|
|
34
62
|
return (
|
|
35
63
|
<BlogLayout
|
|
36
|
-
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
|
37
|
-
pageClassName={ThemeClassNames.page.blogPostPage}
|
|
38
64
|
sidebar={sidebar}
|
|
39
65
|
toc={
|
|
40
66
|
!hideTableOfContents &&
|
|
@@ -47,34 +73,6 @@ export default function BlogPostPage(props) {
|
|
|
47
73
|
/>
|
|
48
74
|
) : undefined
|
|
49
75
|
}>
|
|
50
|
-
<Seo // TODO refactor needed: it's a bit annoying but Seo MUST be inside
|
|
51
|
-
// BlogLayout, otherwise default image (set by BlogLayout) would shadow
|
|
52
|
-
// the custom blog post image
|
|
53
|
-
title={title}
|
|
54
|
-
description={description}
|
|
55
|
-
keywords={keywords}
|
|
56
|
-
image={image}>
|
|
57
|
-
<meta property="og:type" content="article" />
|
|
58
|
-
<meta property="article:published_time" content={date} />
|
|
59
|
-
|
|
60
|
-
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
|
|
61
|
-
{authors.some((author) => author.url) && (
|
|
62
|
-
<meta
|
|
63
|
-
property="article:author"
|
|
64
|
-
content={authors
|
|
65
|
-
.map((author) => author.url)
|
|
66
|
-
.filter(Boolean)
|
|
67
|
-
.join(',')}
|
|
68
|
-
/>
|
|
69
|
-
)}
|
|
70
|
-
{tags.length > 0 && (
|
|
71
|
-
<meta
|
|
72
|
-
property="article:tag"
|
|
73
|
-
content={tags.map((tag) => tag.label).join(',')}
|
|
74
|
-
/>
|
|
75
|
-
)}
|
|
76
|
-
</Seo>
|
|
77
|
-
|
|
78
76
|
<BlogPostItem
|
|
79
77
|
frontMatter={frontMatter}
|
|
80
78
|
assets={assets}
|
|
@@ -89,3 +87,16 @@ export default function BlogPostPage(props) {
|
|
|
89
87
|
</BlogLayout>
|
|
90
88
|
);
|
|
91
89
|
}
|
|
90
|
+
|
|
91
|
+
export default function BlogPostPage(props) {
|
|
92
|
+
return (
|
|
93
|
+
<HtmlClassNameProvider
|
|
94
|
+
className={clsx(
|
|
95
|
+
ThemeClassNames.wrapper.blogPages,
|
|
96
|
+
ThemeClassNames.page.blogPostPage,
|
|
97
|
+
)}>
|
|
98
|
+
<BlogPostPageMetadata {...props} />
|
|
99
|
+
<BlogPostPageContent {...props} />
|
|
100
|
+
</HtmlClassNameProvider>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
@@ -8,24 +8,28 @@ import React from 'react';
|
|
|
8
8
|
import BlogLayout from '@theme/BlogLayout';
|
|
9
9
|
import TagsListByLetter from '@theme/TagsListByLetter';
|
|
10
10
|
import {
|
|
11
|
+
PageMetadata,
|
|
12
|
+
HtmlClassNameProvider,
|
|
11
13
|
ThemeClassNames,
|
|
12
14
|
translateTagsPageTitle,
|
|
13
15
|
} from '@docusaurus/theme-common';
|
|
16
|
+
import SearchMetadata from '../SearchMetadata';
|
|
17
|
+
import clsx from 'clsx';
|
|
14
18
|
export default function BlogTagsListPage(props) {
|
|
15
19
|
const {tags, sidebar} = props;
|
|
16
20
|
const title = translateTagsPageTitle();
|
|
17
21
|
return (
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
</
|
|
22
|
+
<HtmlClassNameProvider
|
|
23
|
+
className={clsx(
|
|
24
|
+
ThemeClassNames.wrapper.blogPages,
|
|
25
|
+
ThemeClassNames.page.blogTagsListPage,
|
|
26
|
+
)}>
|
|
27
|
+
<PageMetadata title={title} />
|
|
28
|
+
<SearchMetadata tag="blog_tags_list" />
|
|
29
|
+
<BlogLayout sidebar={sidebar}>
|
|
30
|
+
<h1>{title}</h1>
|
|
31
|
+
<TagsListByLetter tags={Object.values(tags)} />
|
|
32
|
+
</BlogLayout>
|
|
33
|
+
</HtmlClassNameProvider>
|
|
30
34
|
);
|
|
31
35
|
}
|
|
@@ -9,8 +9,15 @@ import Link from '@docusaurus/Link';
|
|
|
9
9
|
import BlogLayout from '@theme/BlogLayout';
|
|
10
10
|
import BlogPostItem from '@theme/BlogPostItem';
|
|
11
11
|
import Translate, {translate} from '@docusaurus/Translate';
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
PageMetadata,
|
|
14
|
+
HtmlClassNameProvider,
|
|
15
|
+
ThemeClassNames,
|
|
16
|
+
usePluralForm,
|
|
17
|
+
} from '@docusaurus/theme-common';
|
|
18
|
+
import BlogListPaginator from '@theme/BlogListPaginator';
|
|
19
|
+
import SearchMetadata from '@theme/SearchMetadata';
|
|
20
|
+
import clsx from 'clsx'; // Very simple pluralization: probably good enough for now
|
|
14
21
|
|
|
15
22
|
function useBlogPostsPlural() {
|
|
16
23
|
const {selectMessage} = usePluralForm();
|
|
@@ -47,38 +54,38 @@ export default function BlogTagsPostsPage(props) {
|
|
|
47
54
|
},
|
|
48
55
|
);
|
|
49
56
|
return (
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<h1>{title}</h1>
|
|
57
|
+
<HtmlClassNameProvider
|
|
58
|
+
className={clsx(
|
|
59
|
+
ThemeClassNames.wrapper.blogPages,
|
|
60
|
+
ThemeClassNames.page.blogTagPostListPage,
|
|
61
|
+
)}>
|
|
62
|
+
<PageMetadata title={title} />
|
|
63
|
+
<SearchMetadata tag="blog_tags_posts" />
|
|
64
|
+
<BlogLayout sidebar={sidebar}>
|
|
65
|
+
<header className="margin-bottom--xl">
|
|
66
|
+
<h1>{title}</h1>
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
<Link href={allTagsPath}>
|
|
69
|
+
<Translate
|
|
70
|
+
id="theme.tags.tagsPageLink"
|
|
71
|
+
description="The label of the link targeting the tag list page">
|
|
72
|
+
View All Tags
|
|
73
|
+
</Translate>
|
|
74
|
+
</Link>
|
|
75
|
+
</header>
|
|
70
76
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
{items.map(({content: BlogPostContent}) => (
|
|
78
|
+
<BlogPostItem
|
|
79
|
+
key={BlogPostContent.metadata.permalink}
|
|
80
|
+
frontMatter={BlogPostContent.frontMatter}
|
|
81
|
+
assets={BlogPostContent.assets}
|
|
82
|
+
metadata={BlogPostContent.metadata}
|
|
83
|
+
truncated>
|
|
84
|
+
<BlogPostContent />
|
|
85
|
+
</BlogPostItem>
|
|
86
|
+
))}
|
|
87
|
+
<BlogListPaginator metadata={listMetadata} />
|
|
88
|
+
</BlogLayout>
|
|
89
|
+
</HtmlClassNameProvider>
|
|
83
90
|
);
|
|
84
91
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
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, {useCallback, useState, useRef, useEffect} from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import copy from 'copy-text-to-clipboard';
|
|
10
|
+
import {translate} from '@docusaurus/Translate';
|
|
11
|
+
import styles from './styles.module.css';
|
|
12
|
+
export default function CopyButton({code}) {
|
|
13
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
14
|
+
const copyTimeout = useRef(undefined);
|
|
15
|
+
const handleCopyCode = useCallback(() => {
|
|
16
|
+
copy(code);
|
|
17
|
+
setIsCopied(true);
|
|
18
|
+
copyTimeout.current = window.setTimeout(() => {
|
|
19
|
+
setIsCopied(false);
|
|
20
|
+
}, 1000);
|
|
21
|
+
}, [code]);
|
|
22
|
+
useEffect(() => () => window.clearTimeout(copyTimeout.current), []);
|
|
23
|
+
return (
|
|
24
|
+
<button
|
|
25
|
+
type="button"
|
|
26
|
+
aria-label={
|
|
27
|
+
isCopied
|
|
28
|
+
? translate({
|
|
29
|
+
id: 'theme.CodeBlock.copied',
|
|
30
|
+
message: 'Copied',
|
|
31
|
+
description: 'The copied button label on code blocks',
|
|
32
|
+
})
|
|
33
|
+
: translate({
|
|
34
|
+
id: 'theme.CodeBlock.copyButtonAriaLabel',
|
|
35
|
+
message: 'Copy code to clipboard',
|
|
36
|
+
description: 'The ARIA label for copy code blocks button',
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
title={translate({
|
|
40
|
+
id: 'theme.CodeBlock.copy',
|
|
41
|
+
message: 'Copy',
|
|
42
|
+
description: 'The copy button label on code blocks',
|
|
43
|
+
})}
|
|
44
|
+
className={clsx(
|
|
45
|
+
styles.copyButton,
|
|
46
|
+
'clean-btn',
|
|
47
|
+
isCopied && styles.copyButtonCopied,
|
|
48
|
+
)}
|
|
49
|
+
onClick={handleCopyCode}>
|
|
50
|
+
<span className={styles.copyButtonIcons} aria-hidden="true">
|
|
51
|
+
<svg className={styles.copyButtonIcon} viewBox="0 0 24 24">
|
|
52
|
+
<path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z" />
|
|
53
|
+
</svg>
|
|
54
|
+
<svg className={styles.copyButtonSuccessIcon} viewBox="0 0 24 24">
|
|
55
|
+
<path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" />
|
|
56
|
+
</svg>
|
|
57
|
+
</span>
|
|
58
|
+
</button>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
.copyButton {
|
|
9
|
+
display: flex;
|
|
10
|
+
background: inherit;
|
|
11
|
+
border: 1px solid var(--ifm-color-emphasis-300);
|
|
12
|
+
border-radius: var(--ifm-global-radius);
|
|
13
|
+
padding: 0.4rem;
|
|
14
|
+
position: absolute;
|
|
15
|
+
right: calc(var(--ifm-pre-padding) / 2);
|
|
16
|
+
top: calc(var(--ifm-pre-padding) / 2);
|
|
17
|
+
transition: opacity 200ms ease-in-out;
|
|
18
|
+
opacity: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.copyButton:focus-visible,
|
|
22
|
+
.copyButton:hover,
|
|
23
|
+
:global(.theme-code-block:hover) .copyButtonCopied {
|
|
24
|
+
opacity: 1 !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:global(.theme-code-block:hover) .copyButton:not(.copyButtonCopied) {
|
|
28
|
+
opacity: 0.4;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.copyButtonIcons {
|
|
32
|
+
position: relative;
|
|
33
|
+
width: 1.125rem;
|
|
34
|
+
height: 1.125rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.copyButtonIcon,
|
|
38
|
+
.copyButtonSuccessIcon {
|
|
39
|
+
position: absolute;
|
|
40
|
+
top: 0;
|
|
41
|
+
left: 0;
|
|
42
|
+
fill: currentColor;
|
|
43
|
+
opacity: inherit;
|
|
44
|
+
width: inherit;
|
|
45
|
+
height: inherit;
|
|
46
|
+
transition: all 0.15s ease;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.copyButtonSuccessIcon {
|
|
50
|
+
top: 50%;
|
|
51
|
+
left: 50%;
|
|
52
|
+
transform: translate(-50%, -50%) scale(0.33);
|
|
53
|
+
opacity: 0;
|
|
54
|
+
color: #00d600;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.copyButtonCopied .copyButtonIcon {
|
|
58
|
+
transform: scale(0.33);
|
|
59
|
+
opacity: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.copyButtonCopied .copyButtonSuccessIcon {
|
|
63
|
+
transform: translate(-50%, -50%) scale(1);
|
|
64
|
+
opacity: 1;
|
|
65
|
+
transition-delay: 0.075s;
|
|
66
|
+
}
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
import React, {isValidElement, useEffect, useState} from 'react';
|
|
8
8
|
import clsx from 'clsx';
|
|
9
9
|
import Highlight, {defaultProps} from 'prism-react-renderer';
|
|
10
|
-
import copy from 'copy-text-to-clipboard';
|
|
11
|
-
import Translate, {translate} from '@docusaurus/Translate';
|
|
12
10
|
import {
|
|
13
11
|
useThemeConfig,
|
|
14
12
|
parseCodeBlockTitle,
|
|
@@ -17,6 +15,7 @@ import {
|
|
|
17
15
|
ThemeClassNames,
|
|
18
16
|
usePrismTheme,
|
|
19
17
|
} from '@docusaurus/theme-common';
|
|
18
|
+
import CopyButton from '@theme/CodeBlock/CopyButton';
|
|
20
19
|
import styles from './styles.module.css';
|
|
21
20
|
export default function CodeBlock({
|
|
22
21
|
children,
|
|
@@ -26,7 +25,6 @@ export default function CodeBlock({
|
|
|
26
25
|
language: languageProp,
|
|
27
26
|
}) {
|
|
28
27
|
const {prism} = useThemeConfig();
|
|
29
|
-
const [showCopied, setShowCopied] = useState(false);
|
|
30
28
|
const [mounted, setMounted] = useState(false); // The Prism theme on SSR is always the default theme but the site theme
|
|
31
29
|
// can be in a different mode. React hydration doesn't update DOM styles
|
|
32
30
|
// that come from SSR. Hence force a re-render after mounting to apply the
|
|
@@ -78,13 +76,6 @@ export default function CodeBlock({
|
|
|
78
76
|
const language =
|
|
79
77
|
languageProp ?? parseLanguage(blockClassName) ?? prism.defaultLanguage;
|
|
80
78
|
const {highlightLines, code} = parseLines(content, metastring, language);
|
|
81
|
-
|
|
82
|
-
const handleCopyCode = () => {
|
|
83
|
-
copy(code);
|
|
84
|
-
setShowCopied(true);
|
|
85
|
-
setTimeout(() => setShowCopied(false), 2000);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
79
|
return (
|
|
89
80
|
<Highlight
|
|
90
81
|
{...defaultProps}
|
|
@@ -108,12 +99,11 @@ export default function CodeBlock({
|
|
|
108
99
|
{codeBlockTitle}
|
|
109
100
|
</div>
|
|
110
101
|
)}
|
|
111
|
-
<div className={
|
|
102
|
+
<div className={styles.codeBlockContent} style={style}>
|
|
112
103
|
<pre
|
|
113
104
|
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
|
114
105
|
tabIndex={0}
|
|
115
|
-
className={clsx(className, styles.codeBlock, 'thin-scrollbar')}
|
|
116
|
-
style={style}>
|
|
106
|
+
className={clsx(className, styles.codeBlock, 'thin-scrollbar')}>
|
|
117
107
|
<code className={styles.codeBlockLines}>
|
|
118
108
|
{tokens.map((line, i) => {
|
|
119
109
|
if (line.length === 1 && line[0].content === '\n') {
|
|
@@ -147,29 +137,7 @@ export default function CodeBlock({
|
|
|
147
137
|
</code>
|
|
148
138
|
</pre>
|
|
149
139
|
|
|
150
|
-
<
|
|
151
|
-
type="button"
|
|
152
|
-
aria-label={translate({
|
|
153
|
-
id: 'theme.CodeBlock.copyButtonAriaLabel',
|
|
154
|
-
message: 'Copy code to clipboard',
|
|
155
|
-
description: 'The ARIA label for copy code blocks button',
|
|
156
|
-
})}
|
|
157
|
-
className={clsx(styles.copyButton, 'clean-btn')}
|
|
158
|
-
onClick={handleCopyCode}>
|
|
159
|
-
{showCopied ? (
|
|
160
|
-
<Translate
|
|
161
|
-
id="theme.CodeBlock.copied"
|
|
162
|
-
description="The copied button label on code blocks">
|
|
163
|
-
Copied
|
|
164
|
-
</Translate>
|
|
165
|
-
) : (
|
|
166
|
-
<Translate
|
|
167
|
-
id="theme.CodeBlock.copy"
|
|
168
|
-
description="The copy button label on code blocks">
|
|
169
|
-
Copy
|
|
170
|
-
</Translate>
|
|
171
|
-
)}
|
|
172
|
-
</button>
|
|
140
|
+
<CopyButton code={code} />
|
|
173
141
|
</div>
|
|
174
142
|
</div>
|
|
175
143
|
)}
|