mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-02 19:57:25 +02:00
Merge branch 'main' of github.com:facebook/docusaurus into lex111/filter-sidebar
This commit is contained in:
commit
aa997da632
47 changed files with 979 additions and 836 deletions
|
@ -16,6 +16,6 @@ packages/stylelint-copyright/lib/
|
|||
copyUntypedFiles.mjs
|
||||
|
||||
packages/create-docusaurus/lib/*
|
||||
packages/create-docusaurus/templates/facebook/.eslintrc.js
|
||||
packages/create-docusaurus/templates/facebook
|
||||
|
||||
website/_dogfooding/_swizzle_theme_tests
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@babel/env',
|
||||
{
|
||||
targets: {
|
||||
node: 'current',
|
||||
},
|
||||
},
|
||||
],
|
||||
'@babel/react',
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
};
|
|
@ -30,7 +30,7 @@ export default {
|
|||
testPathIgnorePatterns: ignorePatterns,
|
||||
coveragePathIgnorePatterns: ignorePatterns,
|
||||
transform: {
|
||||
'^.+\\.[jt]sx?$': 'babel-jest',
|
||||
'^.+\\.[jt]sx?$': '@swc/jest',
|
||||
},
|
||||
errorOnDeprecated: true,
|
||||
moduleNameMapper: {
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
"@babel/core": "^7.17.7",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"@crowdin/cli": "^3.7.8",
|
||||
"@swc/core": "^1.2.158",
|
||||
"@swc/jest": "^0.2.20",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/jest": "^27.4.1",
|
||||
|
|
|
@ -92,8 +92,6 @@ declare module '@theme/Layout' {
|
|||
|
||||
export interface Props {
|
||||
readonly children?: ReactNode;
|
||||
readonly title?: string;
|
||||
readonly description?: string;
|
||||
}
|
||||
export default function Layout(props: Props): JSX.Element;
|
||||
}
|
||||
|
@ -117,6 +115,10 @@ declare module '@theme/Root' {
|
|||
export default function Root({children}: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/SiteMetadata' {
|
||||
export default function SiteMetadata(): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/constants' {
|
||||
export const DEFAULT_PLUGIN_ID: 'default';
|
||||
}
|
||||
|
|
|
@ -368,31 +368,17 @@ declare module '@theme/Layout' {
|
|||
|
||||
export interface Props {
|
||||
readonly children?: ReactNode;
|
||||
readonly title?: string;
|
||||
readonly noFooter?: boolean;
|
||||
readonly description?: string;
|
||||
readonly image?: string;
|
||||
readonly keywords?: string | string[];
|
||||
readonly permalink?: string;
|
||||
readonly wrapperClassName?: string;
|
||||
readonly pageClassName?: string;
|
||||
readonly searchMetadata?: {
|
||||
readonly version?: string;
|
||||
readonly tag?: string;
|
||||
};
|
||||
|
||||
// Not really layout-related, but kept for convenience/retro-compatibility
|
||||
readonly title?: string;
|
||||
readonly description?: string;
|
||||
}
|
||||
|
||||
export default function Layout(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/LayoutHead' {
|
||||
import type {Props as LayoutProps} from '@theme/Layout';
|
||||
|
||||
export interface Props extends Omit<LayoutProps, 'children'> {}
|
||||
|
||||
export default function LayoutHead(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/LayoutProviders' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
|
@ -484,7 +470,7 @@ declare module '@theme/Navbar/Content' {
|
|||
|
||||
declare module '@theme/Navbar/Layout' {
|
||||
export interface Props {
|
||||
children: React.ReactNode;
|
||||
readonly children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function NavbarLayout(props: Props): JSX.Element;
|
||||
|
@ -924,28 +910,6 @@ declare module '@theme/Tag' {
|
|||
export default function Tag(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/prism-include-languages' {
|
||||
import type * as PrismNamespace from 'prismjs';
|
||||
|
||||
export default function prismIncludeLanguages(
|
||||
PrismObject: typeof PrismNamespace,
|
||||
): void;
|
||||
}
|
||||
|
||||
declare module '@theme/Seo' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
export interface Props {
|
||||
readonly title?: string;
|
||||
readonly description?: string;
|
||||
readonly keywords?: readonly string[] | string;
|
||||
readonly image?: string;
|
||||
readonly children?: ReactNode;
|
||||
}
|
||||
|
||||
export default function Seo(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/TextHighlight' {
|
||||
export interface Props {
|
||||
readonly text?: string;
|
||||
|
@ -954,3 +918,11 @@ declare module '@theme/TextHighlight' {
|
|||
|
||||
export default function TextHighlight(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/prism-include-languages' {
|
||||
import type * as PrismNamespace from 'prismjs';
|
||||
|
||||
export default function prismIncludeLanguages(
|
||||
PrismObject: typeof PrismNamespace,
|
||||
): void;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import Layout from '@theme/Layout';
|
|||
import Link from '@docusaurus/Link';
|
||||
import type {ArchiveBlogPost, Props} from '@theme/BlogArchivePage';
|
||||
import {translate} from '@docusaurus/Translate';
|
||||
import {PageMetadata} from '@docusaurus/theme-common';
|
||||
|
||||
type YearProp = {
|
||||
year: string;
|
||||
|
@ -75,14 +76,17 @@ export default function BlogArchive({archive}: Props): JSX.Element {
|
|||
});
|
||||
const years = listPostsByYears(archive.blogPosts);
|
||||
return (
|
||||
<Layout title={title} description={description}>
|
||||
<header className="hero hero--primary">
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{title}</h1>
|
||||
<p className="hero__subtitle">{description}</p>
|
||||
</div>
|
||||
</header>
|
||||
<main>{years.length > 0 && <YearsSection years={years} />}</main>
|
||||
</Layout>
|
||||
<>
|
||||
<PageMetadata title={title} description={description} />
|
||||
<Layout>
|
||||
<header className="hero hero--primary">
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{title}</h1>
|
||||
<p className="hero__subtitle">{description}</p>
|
||||
</div>
|
||||
</header>
|
||||
<main>{years.length > 0 && <YearsSection years={years} />}</main>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -12,28 +12,34 @@ import BlogLayout from '@theme/BlogLayout';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
import type {Props} from '@theme/BlogListPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
} from '@docusaurus/theme-common';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export default function BlogListPage(props: Props): JSX.Element {
|
||||
const {metadata, items, sidebar} = props;
|
||||
function BlogListPageMetadata(props: Props): JSX.Element {
|
||||
const {metadata} = props;
|
||||
const {
|
||||
siteConfig: {title: siteTitle},
|
||||
} = useDocusaurusContext();
|
||||
const {blogDescription, blogTitle, permalink} = metadata;
|
||||
const isBlogOnlyMode = permalink === '/';
|
||||
const title = isBlogOnlyMode ? siteTitle : blogTitle;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
title={title}
|
||||
description={blogDescription}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'blog_posts_list',
|
||||
}}
|
||||
sidebar={sidebar}>
|
||||
<>
|
||||
<PageMetadata title={title} description={blogDescription} />
|
||||
<SearchMetadata tag="blog_posts_list" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function BlogListPageContent(props: Props): JSX.Element {
|
||||
const {metadata, items, sidebar} = props;
|
||||
return (
|
||||
<BlogLayout sidebar={sidebar}>
|
||||
{items.map(({content: BlogPostContent}) => (
|
||||
<BlogPostItem
|
||||
key={BlogPostContent.metadata.permalink}
|
||||
|
@ -48,3 +54,16 @@ export default function BlogListPage(props: Props): JSX.Element {
|
|||
</BlogLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default function BlogListPage(props: Props): JSX.Element {
|
||||
return (
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogListPage,
|
||||
)}>
|
||||
<BlogListPageMetadata {...props} />
|
||||
<BlogListPageContent {...props} />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,40 +6,63 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Seo from '@theme/Seo';
|
||||
import BlogLayout from '@theme/BlogLayout';
|
||||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
import type {Props} from '@theme/BlogPostPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
} from '@docusaurus/theme-common';
|
||||
import TOC from '@theme/TOC';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export default function BlogPostPage(props: Props): JSX.Element {
|
||||
function BlogPostPageMetadata(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents} = props;
|
||||
const {assets, metadata} = BlogPostContents;
|
||||
const {title, description, date, tags, authors, frontMatter} = metadata;
|
||||
const {keywords} = frontMatter;
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
return (
|
||||
<PageMetadata
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
|
||||
{authors.some((author) => author.url) && (
|
||||
<meta
|
||||
property="article:author"
|
||||
content={authors
|
||||
.map((author) => author.url)
|
||||
.filter(Boolean)
|
||||
.join(',')}
|
||||
/>
|
||||
)}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</PageMetadata>
|
||||
);
|
||||
}
|
||||
|
||||
function BlogPostPageContent(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents, sidebar} = props;
|
||||
const {assets, metadata} = BlogPostContents;
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
nextItem,
|
||||
prevItem,
|
||||
date,
|
||||
tags,
|
||||
authors,
|
||||
frontMatter,
|
||||
} = metadata;
|
||||
const {nextItem, prevItem, frontMatter} = metadata;
|
||||
const {
|
||||
hide_table_of_contents: hideTableOfContents,
|
||||
keywords,
|
||||
toc_min_heading_level: tocMinHeadingLevel,
|
||||
toc_max_heading_level: tocMaxHeadingLevel,
|
||||
} = frontMatter;
|
||||
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogPostPage}
|
||||
sidebar={sidebar}
|
||||
toc={
|
||||
!hideTableOfContents &&
|
||||
|
@ -52,35 +75,6 @@ export default function BlogPostPage(props: Props): JSX.Element {
|
|||
/>
|
||||
) : undefined
|
||||
}>
|
||||
<Seo
|
||||
// TODO refactor needed: it's a bit annoying but Seo MUST be inside
|
||||
// BlogLayout, otherwise default image (set by BlogLayout) would shadow
|
||||
// the custom blog post image
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
|
||||
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
|
||||
{authors.some((author) => author.url) && (
|
||||
<meta
|
||||
property="article:author"
|
||||
content={authors
|
||||
.map((author) => author.url)
|
||||
.filter(Boolean)
|
||||
.join(',')}
|
||||
/>
|
||||
)}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</Seo>
|
||||
|
||||
<BlogPostItem
|
||||
frontMatter={frontMatter}
|
||||
assets={assets}
|
||||
|
@ -95,3 +89,16 @@ export default function BlogPostPage(props: Props): JSX.Element {
|
|||
</BlogLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default function BlogPostPage(props: Props): JSX.Element {
|
||||
return (
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogPostPage,
|
||||
)}>
|
||||
<BlogPostPageMetadata {...props} />
|
||||
<BlogPostPageContent {...props} />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,25 +11,29 @@ import BlogLayout from '@theme/BlogLayout';
|
|||
import TagsListByLetter from '@theme/TagsListByLetter';
|
||||
import type {Props} from '@theme/BlogTagsListPage';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
translateTagsPageTitle,
|
||||
} from '@docusaurus/theme-common';
|
||||
import SearchMetadata from '../SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export default function BlogTagsListPage(props: Props): JSX.Element {
|
||||
const {tags, sidebar} = props;
|
||||
const title = translateTagsPageTitle();
|
||||
return (
|
||||
<BlogLayout
|
||||
title={title}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogTagsListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'blog_tags_list',
|
||||
}}
|
||||
sidebar={sidebar}>
|
||||
<h1>{title}</h1>
|
||||
<TagsListByLetter tags={Object.values(tags)} />
|
||||
</BlogLayout>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogTagsListPage,
|
||||
)}>
|
||||
<PageMetadata title={title} />
|
||||
<SearchMetadata tag="blog_tags_list" />
|
||||
<BlogLayout sidebar={sidebar}>
|
||||
<h1>{title}</h1>
|
||||
<TagsListByLetter tags={Object.values(tags)} />
|
||||
</BlogLayout>
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,15 @@ import BlogLayout from '@theme/BlogLayout';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import type {Props} from '@theme/BlogTagsPostsPage';
|
||||
import Translate, {translate} from '@docusaurus/Translate';
|
||||
import {ThemeClassNames, usePluralForm} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
usePluralForm,
|
||||
} from '@docusaurus/theme-common';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
// Very simple pluralization: probably good enough for now
|
||||
function useBlogPostsPlural() {
|
||||
|
@ -47,38 +54,38 @@ export default function BlogTagsPostsPage(props: Props): JSX.Element {
|
|||
);
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
title={title}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogTagPostListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'blog_tags_posts',
|
||||
}}
|
||||
sidebar={sidebar}>
|
||||
<header className="margin-bottom--xl">
|
||||
<h1>{title}</h1>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogTagPostListPage,
|
||||
)}>
|
||||
<PageMetadata title={title} />
|
||||
<SearchMetadata tag="blog_tags_posts" />
|
||||
<BlogLayout sidebar={sidebar}>
|
||||
<header className="margin-bottom--xl">
|
||||
<h1>{title}</h1>
|
||||
|
||||
<Link href={allTagsPath}>
|
||||
<Translate
|
||||
id="theme.tags.tagsPageLink"
|
||||
description="The label of the link targeting the tag list page">
|
||||
View All Tags
|
||||
</Translate>
|
||||
</Link>
|
||||
</header>
|
||||
<Link href={allTagsPath}>
|
||||
<Translate
|
||||
id="theme.tags.tagsPageLink"
|
||||
description="The label of the link targeting the tag list page">
|
||||
View All Tags
|
||||
</Translate>
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
{items.map(({content: BlogPostContent}) => (
|
||||
<BlogPostItem
|
||||
key={BlogPostContent.metadata.permalink}
|
||||
frontMatter={BlogPostContent.frontMatter}
|
||||
assets={BlogPostContent.assets}
|
||||
metadata={BlogPostContent.metadata}
|
||||
truncated>
|
||||
<BlogPostContent />
|
||||
</BlogPostItem>
|
||||
))}
|
||||
<BlogListPaginator metadata={listMetadata} />
|
||||
</BlogLayout>
|
||||
{items.map(({content: BlogPostContent}) => (
|
||||
<BlogPostItem
|
||||
key={BlogPostContent.metadata.permalink}
|
||||
frontMatter={BlogPostContent.frontMatter}
|
||||
assets={BlogPostContent.assets}
|
||||
metadata={BlogPostContent.metadata}
|
||||
truncated>
|
||||
<BlogPostContent />
|
||||
</BlogPostItem>
|
||||
))}
|
||||
<BlogListPaginator metadata={listMetadata} />
|
||||
</BlogLayout>
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
useCurrentSidebarCategory,
|
||||
} from '@docusaurus/theme-common';
|
||||
import type {Props} from '@theme/DocCategoryGeneratedIndexPage';
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
import DocPaginator from '@theme/DocPaginator';
|
||||
import Seo from '@theme/Seo';
|
||||
import DocVersionBanner from '@theme/DocVersionBanner';
|
||||
import DocVersionBadge from '@theme/DocVersionBadge';
|
||||
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
|
||||
|
@ -19,13 +21,27 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
|
|||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
export default function DocCategoryGeneratedIndexPage({
|
||||
function DocCategoryGeneratedIndexPageMetadata({
|
||||
categoryGeneratedIndex,
|
||||
}: Props): JSX.Element {
|
||||
return (
|
||||
<PageMetadata
|
||||
title={categoryGeneratedIndex.title}
|
||||
description={categoryGeneratedIndex.description}
|
||||
keywords={categoryGeneratedIndex.keywords}
|
||||
// TODO `require` this?
|
||||
image={useBaseUrl(categoryGeneratedIndex.image)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DocCategoryGeneratedIndexPageContent({
|
||||
categoryGeneratedIndex,
|
||||
}: Props): JSX.Element {
|
||||
const category = useCurrentSidebarCategory();
|
||||
return (
|
||||
<>
|
||||
<Seo
|
||||
<PageMetadata
|
||||
title={categoryGeneratedIndex.title}
|
||||
description={categoryGeneratedIndex.description}
|
||||
keywords={categoryGeneratedIndex.keywords}
|
||||
|
@ -57,3 +73,14 @@ export default function DocCategoryGeneratedIndexPage({
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DocCategoryGeneratedIndexPage(
|
||||
props: Props,
|
||||
): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<DocCategoryGeneratedIndexPageMetadata {...props} />
|
||||
<DocCategoryGeneratedIndexPageContent {...props} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import clsx from 'clsx';
|
|||
import DocPaginator from '@theme/DocPaginator';
|
||||
import DocVersionBanner from '@theme/DocVersionBanner';
|
||||
import DocVersionBadge from '@theme/DocVersionBadge';
|
||||
import Seo from '@theme/Seo';
|
||||
import type {Props} from '@theme/DocItem';
|
||||
import DocItemFooter from '@theme/DocItemFooter';
|
||||
import TOC from '@theme/TOC';
|
||||
|
@ -18,6 +17,7 @@ import TOCCollapsible from '@theme/TOCCollapsible';
|
|||
import Heading from '@theme/Heading';
|
||||
import styles from './styles.module.css';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
useWindowSize,
|
||||
|
@ -25,18 +25,26 @@ import {
|
|||
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
|
||||
import MDXContent from '@theme/MDXContent';
|
||||
|
||||
export default function DocItem(props: Props): JSX.Element {
|
||||
function DocItemMetadata(props: Props): JSX.Element {
|
||||
const {content: DocContent} = props;
|
||||
const {metadata, frontMatter, assets} = DocContent;
|
||||
const {keywords} = frontMatter;
|
||||
const {description, title} = metadata;
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
|
||||
return <PageMetadata {...{title, description, keywords, image}} />;
|
||||
}
|
||||
|
||||
function DocItemContent(props: Props): JSX.Element {
|
||||
const {content: DocContent} = props;
|
||||
const {metadata, frontMatter} = DocContent;
|
||||
const {
|
||||
keywords,
|
||||
hide_title: hideTitle,
|
||||
hide_table_of_contents: hideTableOfContents,
|
||||
toc_min_heading_level: tocMinHeadingLevel,
|
||||
toc_max_heading_level: tocMaxHeadingLevel,
|
||||
} = frontMatter;
|
||||
const {description, title} = metadata;
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
const {title} = metadata;
|
||||
|
||||
// We only add a title if:
|
||||
// - user asks to hide it with front matter
|
||||
|
@ -53,64 +61,69 @@ export default function DocItem(props: Props): JSX.Element {
|
|||
canRenderTOC && (windowSize === 'desktop' || windowSize === 'ssr');
|
||||
|
||||
return (
|
||||
<HtmlClassNameProvider className={`docs-doc-id-${metadata.unversionedId}`}>
|
||||
<Seo {...{title, description, keywords, image}} />
|
||||
<div className="row">
|
||||
<div className={clsx('col', !hideTableOfContents && styles.docItemCol)}>
|
||||
<DocVersionBanner />
|
||||
<div className={styles.docItemContainer}>
|
||||
<article>
|
||||
<DocBreadcrumbs />
|
||||
<DocVersionBadge />
|
||||
|
||||
<div className="row">
|
||||
<div className={clsx('col', !hideTableOfContents && styles.docItemCol)}>
|
||||
<DocVersionBanner />
|
||||
<div className={styles.docItemContainer}>
|
||||
<article>
|
||||
<DocBreadcrumbs />
|
||||
<DocVersionBadge />
|
||||
{canRenderTOC && (
|
||||
<TOCCollapsible
|
||||
toc={DocContent.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
className={clsx(
|
||||
ThemeClassNames.docs.docTocMobile,
|
||||
styles.tocMobile,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canRenderTOC && (
|
||||
<TOCCollapsible
|
||||
toc={DocContent.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
className={clsx(
|
||||
ThemeClassNames.docs.docTocMobile,
|
||||
styles.tocMobile,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
|
||||
{/*
|
||||
<div className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
|
||||
{/*
|
||||
Title can be declared inside md content or declared through
|
||||
front matter and added manually. To make both cases consistent,
|
||||
the added title is added under the same div.markdown block
|
||||
See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120
|
||||
*/}
|
||||
{shouldAddTitle && (
|
||||
<header>
|
||||
<Heading as="h1">{title}</Heading>
|
||||
</header>
|
||||
)}
|
||||
<MDXContent>
|
||||
<DocContent />
|
||||
</MDXContent>
|
||||
</div>
|
||||
{shouldAddTitle && (
|
||||
<header>
|
||||
<Heading as="h1">{title}</Heading>
|
||||
</header>
|
||||
)}
|
||||
<MDXContent>
|
||||
<DocContent />
|
||||
</MDXContent>
|
||||
</div>
|
||||
|
||||
<DocItemFooter {...props} />
|
||||
</article>
|
||||
<DocItemFooter {...props} />
|
||||
</article>
|
||||
|
||||
<DocPaginator previous={metadata.previous} next={metadata.next} />
|
||||
</div>
|
||||
<DocPaginator previous={metadata.previous} next={metadata.next} />
|
||||
</div>
|
||||
{renderTocDesktop && (
|
||||
<div className="col col--3">
|
||||
<TOC
|
||||
toc={DocContent.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
className={ThemeClassNames.docs.docTocDesktop}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{renderTocDesktop && (
|
||||
<div className="col col--3">
|
||||
<TOC
|
||||
toc={DocContent.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
className={ThemeClassNames.docs.docTocDesktop}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DocItem(props: Props): JSX.Element {
|
||||
const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
|
||||
return (
|
||||
<HtmlClassNameProvider className={docHtmlClassName}>
|
||||
<DocItemMetadata {...props} />
|
||||
<DocItemContent {...props} />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,15 +8,6 @@
|
|||
import React, {type ReactNode, useState, useCallback} from 'react';
|
||||
import renderRoutes from '@docusaurus/renderRoutes';
|
||||
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs';
|
||||
import {
|
||||
DocsFilterProvider,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
docVersionSearchTag,
|
||||
DocsSidebarProvider,
|
||||
useDocsSidebar,
|
||||
DocsVersionProvider,
|
||||
} from '@docusaurus/theme-common';
|
||||
import Layout from '@theme/Layout';
|
||||
import DocSidebar from '@theme/DocSidebar';
|
||||
import NotFound from '@theme/NotFound';
|
||||
|
@ -30,6 +21,17 @@ import {translate} from '@docusaurus/Translate';
|
|||
import clsx from 'clsx';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
import {
|
||||
DocsFilterProvider,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
docVersionSearchTag,
|
||||
DocsSidebarProvider,
|
||||
useDocsSidebar,
|
||||
DocsVersionProvider,
|
||||
} from '@docusaurus/theme-common';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
|
||||
type DocPageContentProps = {
|
||||
readonly currentDocRoute: DocumentRoute;
|
||||
readonly versionMetadata: PropVersionMetadata;
|
||||
|
@ -56,87 +58,89 @@ function DocPageContent({
|
|||
}, [hiddenSidebar]);
|
||||
|
||||
return (
|
||||
<Layout
|
||||
wrapperClassName={ThemeClassNames.wrapper.docsPages}
|
||||
pageClassName={ThemeClassNames.page.docsDocPage}
|
||||
searchMetadata={{
|
||||
version,
|
||||
tag: docVersionSearchTag(pluginId, version),
|
||||
}}>
|
||||
<div className={styles.docPage}>
|
||||
<BackToTopButton />
|
||||
<>
|
||||
<SearchMetadata
|
||||
version={version}
|
||||
tag={docVersionSearchTag(pluginId, version)}
|
||||
/>
|
||||
<Layout>
|
||||
<div className={styles.docPage}>
|
||||
<BackToTopButton />
|
||||
|
||||
{sidebar && (
|
||||
<aside
|
||||
{sidebar && (
|
||||
<aside
|
||||
className={clsx(
|
||||
ThemeClassNames.docs.docSidebarContainer,
|
||||
styles.docSidebarContainer,
|
||||
hiddenSidebarContainer && styles.docSidebarContainerHidden,
|
||||
)}
|
||||
onTransitionEnd={(e) => {
|
||||
if (
|
||||
!e.currentTarget.classList.contains(
|
||||
styles.docSidebarContainer!,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hiddenSidebarContainer) {
|
||||
setHiddenSidebar(true);
|
||||
}
|
||||
}}>
|
||||
<DocSidebar
|
||||
key={
|
||||
// Reset sidebar state on sidebar changes
|
||||
// See https://github.com/facebook/docusaurus/issues/3414
|
||||
sidebarName
|
||||
}
|
||||
sidebar={sidebar}
|
||||
path={currentDocRoute.path}
|
||||
onCollapse={toggleSidebar}
|
||||
isHidden={hiddenSidebar}
|
||||
/>
|
||||
|
||||
{hiddenSidebar && (
|
||||
<div
|
||||
className={styles.collapsedDocSidebar}
|
||||
title={translate({
|
||||
id: 'theme.docs.sidebar.expandButtonTitle',
|
||||
message: 'Expand sidebar',
|
||||
description:
|
||||
'The ARIA label and title attribute for expand button of doc sidebar',
|
||||
})}
|
||||
aria-label={translate({
|
||||
id: 'theme.docs.sidebar.expandButtonAriaLabel',
|
||||
message: 'Expand sidebar',
|
||||
description:
|
||||
'The ARIA label and title attribute for expand button of doc sidebar',
|
||||
})}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onKeyDown={toggleSidebar}
|
||||
onClick={toggleSidebar}>
|
||||
<IconArrow className={styles.expandSidebarButtonIcon} />
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
)}
|
||||
<main
|
||||
className={clsx(
|
||||
ThemeClassNames.docs.docSidebarContainer,
|
||||
styles.docSidebarContainer,
|
||||
hiddenSidebarContainer && styles.docSidebarContainerHidden,
|
||||
)}
|
||||
onTransitionEnd={(e) => {
|
||||
if (
|
||||
!e.currentTarget.classList.contains(styles.docSidebarContainer!)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hiddenSidebarContainer) {
|
||||
setHiddenSidebar(true);
|
||||
}
|
||||
}}>
|
||||
<DocSidebar
|
||||
key={
|
||||
// Reset sidebar state on sidebar changes
|
||||
// See https://github.com/facebook/docusaurus/issues/3414
|
||||
sidebarName
|
||||
}
|
||||
sidebar={sidebar}
|
||||
path={currentDocRoute.path}
|
||||
onCollapse={toggleSidebar}
|
||||
isHidden={hiddenSidebar}
|
||||
/>
|
||||
|
||||
{hiddenSidebar && (
|
||||
<div
|
||||
className={styles.collapsedDocSidebar}
|
||||
title={translate({
|
||||
id: 'theme.docs.sidebar.expandButtonTitle',
|
||||
message: 'Expand sidebar',
|
||||
description:
|
||||
'The ARIA label and title attribute for expand button of doc sidebar',
|
||||
})}
|
||||
aria-label={translate({
|
||||
id: 'theme.docs.sidebar.expandButtonAriaLabel',
|
||||
message: 'Expand sidebar',
|
||||
description:
|
||||
'The ARIA label and title attribute for expand button of doc sidebar',
|
||||
})}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onKeyDown={toggleSidebar}
|
||||
onClick={toggleSidebar}>
|
||||
<IconArrow className={styles.expandSidebarButtonIcon} />
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
)}
|
||||
<main
|
||||
className={clsx(
|
||||
styles.docMainContainer,
|
||||
(hiddenSidebarContainer || !sidebar) &&
|
||||
styles.docMainContainerEnhanced,
|
||||
)}>
|
||||
<div
|
||||
className={clsx(
|
||||
'container padding-top--md padding-bottom--lg',
|
||||
styles.docItemWrapper,
|
||||
hiddenSidebarContainer && styles.docItemWrapperEnhanced,
|
||||
styles.docMainContainer,
|
||||
(hiddenSidebarContainer || !sidebar) &&
|
||||
styles.docMainContainerEnhanced,
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</Layout>
|
||||
<div
|
||||
className={clsx(
|
||||
'container padding-top--md padding-bottom--lg',
|
||||
styles.docItemWrapper,
|
||||
hiddenSidebarContainer && styles.docItemWrapperEnhanced,
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -161,7 +165,12 @@ export default function DocPage(props: Props): JSX.Element {
|
|||
: null;
|
||||
|
||||
return (
|
||||
<HtmlClassNameProvider className={versionMetadata.className}>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.docsPages,
|
||||
ThemeClassNames.page.docsDocPage,
|
||||
versionMetadata.className,
|
||||
)}>
|
||||
<DocsVersionProvider version={versionMetadata}>
|
||||
<DocsSidebarProvider sidebar={sidebar ?? null}>
|
||||
<DocsFilterProvider>
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
--doc-sidebar-hidden-width: 30px;
|
||||
}
|
||||
|
||||
:global(.docs-wrapper) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.docPage,
|
||||
.docMainContainer {
|
||||
display: flex;
|
||||
|
|
|
@ -9,10 +9,17 @@ import React from 'react';
|
|||
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {ThemeClassNames, usePluralForm} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
usePluralForm,
|
||||
} from '@docusaurus/theme-common';
|
||||
import type {PropTagDocListDoc} from '@docusaurus/plugin-content-docs';
|
||||
import Translate, {translate} from '@docusaurus/Translate';
|
||||
import type {Props} from '@theme/DocTagDocListPage';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
// Very simple pluralization: probably good enough for now
|
||||
function useNDocsTaggedPlural() {
|
||||
|
@ -55,35 +62,36 @@ export default function DocTagDocListPage({tag}: Props): JSX.Element {
|
|||
);
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title={title}
|
||||
wrapperClassName={ThemeClassNames.wrapper.docsPages}
|
||||
pageClassName={ThemeClassNames.page.docsTagDocListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'doc_tag_doc_list',
|
||||
}}>
|
||||
<div className="container margin-vert--lg">
|
||||
<div className="row">
|
||||
<main className="col col--8 col--offset-2">
|
||||
<header className="margin-bottom--xl">
|
||||
<h1>{title}</h1>
|
||||
<Link href={tag.allTagsPath}>
|
||||
<Translate
|
||||
id="theme.tags.tagsPageLink"
|
||||
description="The label of the link targeting the tag list page">
|
||||
View All Tags
|
||||
</Translate>
|
||||
</Link>
|
||||
</header>
|
||||
<section className="margin-vert--lg">
|
||||
{tag.docs.map((doc) => (
|
||||
<DocItem key={doc.id} doc={doc} />
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.docsPages,
|
||||
ThemeClassNames.page.docsTagDocListPage,
|
||||
)}>
|
||||
<PageMetadata title={title} />
|
||||
<SearchMetadata tag="doc_tag_doc_list" />
|
||||
<Layout>
|
||||
<div className="container margin-vert--lg">
|
||||
<div className="row">
|
||||
<main className="col col--8 col--offset-2">
|
||||
<header className="margin-bottom--xl">
|
||||
<h1>{title}</h1>
|
||||
<Link href={tag.allTagsPath}>
|
||||
<Translate
|
||||
id="theme.tags.tagsPageLink"
|
||||
description="The label of the link targeting the tag list page">
|
||||
View All Tags
|
||||
</Translate>
|
||||
</Link>
|
||||
</header>
|
||||
<section className="margin-vert--lg">
|
||||
{tag.docs.map((doc) => (
|
||||
<DocItem key={doc.id} doc={doc} />
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,31 +9,36 @@ import React from 'react';
|
|||
|
||||
import Layout from '@theme/Layout';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
translateTagsPageTitle,
|
||||
} from '@docusaurus/theme-common';
|
||||
import TagsListByLetter from '@theme/TagsListByLetter';
|
||||
import type {Props} from '@theme/DocTagsListPage';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export default function DocTagsListPage({tags}: Props): JSX.Element {
|
||||
const title = translateTagsPageTitle();
|
||||
return (
|
||||
<Layout
|
||||
title={title}
|
||||
wrapperClassName={ThemeClassNames.wrapper.docsPages}
|
||||
pageClassName={ThemeClassNames.page.docsTagsListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'doc_tags_list',
|
||||
}}>
|
||||
<div className="container margin-vert--lg">
|
||||
<div className="row">
|
||||
<main className="col col--8 col--offset-2">
|
||||
<h1>{title}</h1>
|
||||
<TagsListByLetter tags={tags} />
|
||||
</main>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.docsPages,
|
||||
ThemeClassNames.page.docsTagsListPage,
|
||||
)}>
|
||||
<PageMetadata title={title} />
|
||||
<SearchMetadata tag="doc_tags_list" />
|
||||
<Layout>
|
||||
<div className="container margin-vert--lg">
|
||||
<div className="row">
|
||||
<main className="col col--8 col--offset-2">
|
||||
<h1>{title}</h1>
|
||||
<TagsListByLetter tags={tags} />
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,20 +13,30 @@ import AnnouncementBar from '@theme/AnnouncementBar';
|
|||
import Navbar from '@theme/Navbar';
|
||||
import Footer from '@theme/Footer';
|
||||
import LayoutProviders from '@theme/LayoutProviders';
|
||||
import LayoutHead from '@theme/LayoutHead';
|
||||
import type {Props} from '@theme/Layout';
|
||||
import {ThemeClassNames, useKeyboardNavigation} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
ThemeClassNames,
|
||||
useKeyboardNavigation,
|
||||
} from '@docusaurus/theme-common';
|
||||
import ErrorPageContent from '@theme/ErrorPageContent';
|
||||
import './styles.css';
|
||||
|
||||
export default function Layout(props: Props): JSX.Element {
|
||||
const {children, noFooter, wrapperClassName, pageClassName} = props;
|
||||
const {
|
||||
children,
|
||||
noFooter,
|
||||
wrapperClassName,
|
||||
// not really layout-related, but kept for convenience/retro-compatibility
|
||||
title,
|
||||
description,
|
||||
} = props;
|
||||
|
||||
useKeyboardNavigation();
|
||||
|
||||
return (
|
||||
<LayoutProviders>
|
||||
<LayoutHead {...props} />
|
||||
<PageMetadata title={title} description={description} />
|
||||
|
||||
<SkipToContent />
|
||||
|
||||
|
@ -34,12 +44,7 @@ export default function Layout(props: Props): JSX.Element {
|
|||
|
||||
<Navbar />
|
||||
|
||||
<div
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.main,
|
||||
wrapperClassName,
|
||||
pageClassName,
|
||||
)}>
|
||||
<div className={clsx(ThemeClassNames.wrapper.main, wrapperClassName)}>
|
||||
<ErrorBoundary fallback={ErrorPageContent}>{children}</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -11,43 +11,49 @@ import Layout from '@theme/Layout';
|
|||
import MDXContent from '@theme/MDXContent';
|
||||
import type {Props} from '@theme/MDXPage';
|
||||
import TOC from '@theme/TOC';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
} from '@docusaurus/theme-common';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
export default function MDXPage(props: Props): JSX.Element {
|
||||
const {content: MDXPageContent} = props;
|
||||
const {
|
||||
metadata: {title, description, permalink, frontMatter},
|
||||
metadata: {title, description, frontMatter},
|
||||
} = MDXPageContent;
|
||||
const {wrapperClassName, hide_table_of_contents: hideTableOfContents} =
|
||||
frontMatter;
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title={title}
|
||||
description={description}
|
||||
permalink={permalink}
|
||||
wrapperClassName={wrapperClassName ?? ThemeClassNames.wrapper.mdxPages}
|
||||
pageClassName={ThemeClassNames.page.mdxPage}>
|
||||
<main className="container container--fluid margin-vert--lg">
|
||||
<div className={clsx('row', styles.mdxPageWrapper)}>
|
||||
<div className={clsx('col', !hideTableOfContents && 'col--8')}>
|
||||
<MDXContent>
|
||||
<MDXPageContent />
|
||||
</MDXContent>
|
||||
</div>
|
||||
{!hideTableOfContents && MDXPageContent.toc && (
|
||||
<div className="col col--2">
|
||||
<TOC
|
||||
toc={MDXPageContent.toc}
|
||||
minHeadingLevel={frontMatter.toc_min_heading_level}
|
||||
maxHeadingLevel={frontMatter.toc_max_heading_level}
|
||||
/>
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
wrapperClassName ?? ThemeClassNames.wrapper.mdxPages,
|
||||
ThemeClassNames.page.mdxPage,
|
||||
)}>
|
||||
<PageMetadata title={title} description={description} />
|
||||
<Layout>
|
||||
<main className="container container--fluid margin-vert--lg">
|
||||
<div className={clsx('row', styles.mdxPageWrapper)}>
|
||||
<div className={clsx('col', !hideTableOfContents && 'col--8')}>
|
||||
<MDXContent>
|
||||
<MDXPageContent />
|
||||
</MDXContent>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
{!hideTableOfContents && MDXPageContent.toc && (
|
||||
<div className="col col--2">
|
||||
<TOC
|
||||
toc={MDXPageContent.toc}
|
||||
minHeadingLevel={frontMatter.toc_min_heading_level}
|
||||
maxHeadingLevel={frontMatter.toc_max_heading_level}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,42 +8,47 @@
|
|||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Translate, {translate} from '@docusaurus/Translate';
|
||||
import {PageMetadata} from '@docusaurus/theme-common';
|
||||
|
||||
export default function NotFound(): JSX.Element {
|
||||
return (
|
||||
<Layout
|
||||
title={translate({
|
||||
id: 'theme.NotFound.title',
|
||||
message: 'Page Not Found',
|
||||
})}>
|
||||
<main className="container margin-vert--xl">
|
||||
<div className="row">
|
||||
<div className="col col--6 col--offset-3">
|
||||
<h1 className="hero__title">
|
||||
<Translate
|
||||
id="theme.NotFound.title"
|
||||
description="The title of the 404 page">
|
||||
Page Not Found
|
||||
</Translate>
|
||||
</h1>
|
||||
<p>
|
||||
<Translate
|
||||
id="theme.NotFound.p1"
|
||||
description="The first paragraph of the 404 page">
|
||||
We could not find what you were looking for.
|
||||
</Translate>
|
||||
</p>
|
||||
<p>
|
||||
<Translate
|
||||
id="theme.NotFound.p2"
|
||||
description="The 2nd paragraph of the 404 page">
|
||||
Please contact the owner of the site that linked you to the
|
||||
original URL and let them know their link is broken.
|
||||
</Translate>
|
||||
</p>
|
||||
<>
|
||||
<PageMetadata
|
||||
title={translate({
|
||||
id: 'theme.NotFound.title',
|
||||
message: 'Page Not Found',
|
||||
})}
|
||||
/>
|
||||
<Layout>
|
||||
<main className="container margin-vert--xl">
|
||||
<div className="row">
|
||||
<div className="col col--6 col--offset-3">
|
||||
<h1 className="hero__title">
|
||||
<Translate
|
||||
id="theme.NotFound.title"
|
||||
description="The title of the 404 page">
|
||||
Page Not Found
|
||||
</Translate>
|
||||
</h1>
|
||||
<p>
|
||||
<Translate
|
||||
id="theme.NotFound.p1"
|
||||
description="The first paragraph of the 404 page">
|
||||
We could not find what you were looking for.
|
||||
</Translate>
|
||||
</p>
|
||||
<p>
|
||||
<Translate
|
||||
id="theme.NotFound.p2"
|
||||
description="The 2nd paragraph of the 404 page">
|
||||
Please contact the owner of the site that linked you to the
|
||||
original URL and let them know their link is broken.
|
||||
</Translate>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
</main>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import {useTitleFormatter} from '@docusaurus/theme-common';
|
||||
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
|
||||
import type {Props} from '@theme/Seo';
|
||||
|
||||
export default function Seo({
|
||||
title,
|
||||
description,
|
||||
keywords,
|
||||
image,
|
||||
children,
|
||||
}: Props): JSX.Element {
|
||||
const pageTitle = useTitleFormatter(title);
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const pageImage = image ? withBaseUrl(image, {absolute: true}) : undefined;
|
||||
|
||||
return (
|
||||
<Head>
|
||||
{title && <title>{pageTitle}</title>}
|
||||
{title && <meta property="og:title" content={pageTitle} />}
|
||||
|
||||
{description && <meta name="description" content={description} />}
|
||||
{description && <meta property="og:description" content={description} />}
|
||||
|
||||
{keywords && (
|
||||
<meta
|
||||
name="keywords"
|
||||
content={
|
||||
(Array.isArray(keywords) ? keywords.join(',') : keywords) as string
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{pageImage && <meta property="og:image" content={pageImage} />}
|
||||
{pageImage && <meta name="twitter:image" content={pageImage} />}
|
||||
|
||||
{children}
|
||||
</Head>
|
||||
);
|
||||
}
|
|
@ -9,19 +9,18 @@ import React from 'react';
|
|||
import Head from '@docusaurus/Head';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import type {Props} from '@theme/Layout';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import Seo from '@theme/Seo';
|
||||
import {
|
||||
PageMetadata,
|
||||
DEFAULT_SEARCH_TAG,
|
||||
useTitleFormatter,
|
||||
useAlternatePageUtils,
|
||||
useThemeConfig,
|
||||
keyboardFocusedClassName,
|
||||
} from '@docusaurus/theme-common';
|
||||
import {useLocation} from '@docusaurus/router';
|
||||
|
||||
// Useful for SEO
|
||||
// TODO move to SiteMetadataDefaults or theme-common ?
|
||||
// Useful for i18n/SEO
|
||||
// See https://developers.google.com/search/docs/advanced/crawling/localized-versions
|
||||
// See https://github.com/facebook/docusaurus/issues/3317
|
||||
function AlternateLangHeaders(): JSX.Element {
|
||||
|
@ -66,6 +65,7 @@ function useDefaultCanonicalUrl() {
|
|||
return siteUrl + useBaseUrl(pathname);
|
||||
}
|
||||
|
||||
// TODO move to SiteMetadataDefaults or theme-common ?
|
||||
function CanonicalUrlHeaders({permalink}: {permalink?: string}) {
|
||||
const {
|
||||
siteConfig: {url: siteUrl},
|
||||
|
@ -83,45 +83,31 @@ function CanonicalUrlHeaders({permalink}: {permalink?: string}) {
|
|||
);
|
||||
}
|
||||
|
||||
export default function LayoutHead(props: Props): JSX.Element {
|
||||
export default function SiteMetadata(): JSX.Element {
|
||||
const {
|
||||
siteConfig: {favicon},
|
||||
i18n: {currentLocale, localeConfigs},
|
||||
i18n: {currentLocale},
|
||||
} = useDocusaurusContext();
|
||||
|
||||
// TODO maybe move these 2 themeConfig to siteConfig?
|
||||
// These seems useful for other themes as well
|
||||
const {metadata, image: defaultImage} = useThemeConfig();
|
||||
const {title, description, image, keywords, searchMetadata} = props;
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
const pageTitle = useTitleFormatter(title);
|
||||
const {htmlLang, direction: htmlDir} = localeConfigs[currentLocale]!;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<html lang={htmlLang} dir={htmlDir} />
|
||||
{favicon && <link rel="icon" href={faviconUrl} />}
|
||||
<title>{pageTitle}</title>
|
||||
<meta property="og:title" content={pageTitle} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
{/* The keyboard focus class name need to be applied when SSR so links
|
||||
are outlined when JS is disabled */}
|
||||
<body className={keyboardFocusedClassName} />
|
||||
</Head>
|
||||
|
||||
{/* image can override the default image */}
|
||||
{defaultImage && <Seo image={defaultImage} />}
|
||||
{image && <Seo image={image} />}
|
||||
|
||||
<Seo description={description} keywords={keywords} />
|
||||
{defaultImage && <PageMetadata image={defaultImage} />}
|
||||
|
||||
<CanonicalUrlHeaders />
|
||||
|
||||
<AlternateLangHeaders />
|
||||
|
||||
<SearchMetadata
|
||||
tag={DEFAULT_SEARCH_TAG}
|
||||
locale={currentLocale}
|
||||
{...searchMetadata}
|
||||
/>
|
||||
<SearchMetadata tag={DEFAULT_SEARCH_TAG} locale={currentLocale} />
|
||||
|
||||
<Head
|
||||
// it's important to have an additional <Head> element here,
|
|
@ -15,10 +15,10 @@ function TextHighlight({text, highlight}: Props): JSX.Element {
|
|||
return <>{text}</>;
|
||||
}
|
||||
|
||||
const highlightedText = text.replace(
|
||||
const highlightedText = text?.replace(
|
||||
new RegExp(highlight, 'gi'),
|
||||
(match) => `<mark>${match}</mark>`,
|
||||
);
|
||||
) as string;
|
||||
|
||||
return (
|
||||
<span
|
||||
|
|
|
@ -129,9 +129,10 @@ export {isRegexpStringMatch} from './utils/regexpUtils';
|
|||
export {useHomePageRoute} from './utils/routesUtils';
|
||||
|
||||
export {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
PluginHtmlClassNameProvider,
|
||||
} from './utils/metadataUtilsTemp';
|
||||
} from './utils/metadataUtils';
|
||||
|
||||
export {
|
||||
useColorMode,
|
||||
|
|
|
@ -9,6 +9,53 @@ import React, {type ReactNode} from 'react';
|
|||
import Head from '@docusaurus/Head';
|
||||
import clsx from 'clsx';
|
||||
import useRouteContext from '@docusaurus/useRouteContext';
|
||||
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
import {useTitleFormatter} from './generalUtils';
|
||||
|
||||
interface PageMetadataProps {
|
||||
readonly title?: string;
|
||||
readonly description?: string;
|
||||
readonly keywords?: readonly string[] | string;
|
||||
readonly image?: string;
|
||||
readonly children?: ReactNode;
|
||||
}
|
||||
|
||||
// Helper component to manipulate page metadata and override site defaults
|
||||
export function PageMetadata({
|
||||
title,
|
||||
description,
|
||||
keywords,
|
||||
image,
|
||||
children,
|
||||
}: PageMetadataProps): JSX.Element {
|
||||
const pageTitle = useTitleFormatter(title);
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const pageImage = image ? withBaseUrl(image, {absolute: true}) : undefined;
|
||||
|
||||
return (
|
||||
<Head>
|
||||
{title && <title>{pageTitle}</title>}
|
||||
{title && <meta property="og:title" content={pageTitle} />}
|
||||
|
||||
{description && <meta name="description" content={description} />}
|
||||
{description && <meta property="og:description" content={description} />}
|
||||
|
||||
{keywords && (
|
||||
<meta
|
||||
name="keywords"
|
||||
content={
|
||||
(Array.isArray(keywords) ? keywords.join(',') : keywords) as string
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{pageImage && <meta property="og:image" content={pageImage} />}
|
||||
{pageImage && <meta name="twitter:image" content={pageImage} />}
|
||||
|
||||
{children}
|
||||
</Head>
|
||||
);
|
||||
}
|
||||
|
||||
const HtmlClassNameContext = React.createContext<string | undefined>(undefined);
|
||||
|
|
@ -47,7 +47,8 @@ export class ReactContextError extends Error {
|
|||
super();
|
||||
this.name = 'ReactContextError';
|
||||
this.message = `Hook ${
|
||||
this.stack?.split('\n')[1]?.match(/at (?<name>\w+)/)?.groups!.name
|
||||
this.stack?.split('\n')[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups!
|
||||
.name
|
||||
} is called outside the <${providerName}>. ${additionalInfo || ''}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import Head from '@docusaurus/Head';
|
|||
import Link from '@docusaurus/Link';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import {
|
||||
HtmlClassNameProvider,
|
||||
useTitleFormatter,
|
||||
usePluralForm,
|
||||
isRegexpStringMatch,
|
||||
|
@ -149,7 +150,7 @@ type ResultDispatcher =
|
|||
| {type: 'update'; value: ResultDispatcherState}
|
||||
| {type: 'advance'; value?: undefined};
|
||||
|
||||
export default function SearchPage(): JSX.Element {
|
||||
function SearchPageContent(): JSX.Element {
|
||||
const {
|
||||
siteConfig: {themeConfig},
|
||||
i18n: {currentLocale},
|
||||
|
@ -356,7 +357,7 @@ export default function SearchPage(): JSX.Element {
|
|||
}, [makeSearch, searchResultState.lastPage]);
|
||||
|
||||
return (
|
||||
<Layout wrapperClassName="search-page-wrapper">
|
||||
<Layout>
|
||||
<Head>
|
||||
<title>{useTitleFormatter(getTitle())}</title>
|
||||
{/*
|
||||
|
@ -516,3 +517,11 @@ export default function SearchPage(): JSX.Element {
|
|||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SearchPage(): JSX.Element {
|
||||
return (
|
||||
<HtmlClassNameProvider className="search-page-wrapper">
|
||||
<SearchPageContent />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ import {BrowserContextProvider} from './exports/browserContext';
|
|||
import {DocusaurusContextProvider} from './exports/docusaurusContext';
|
||||
import PendingNavigation from './PendingNavigation';
|
||||
import BaseUrlIssueBanner from './baseUrlIssueBanner/BaseUrlIssueBanner';
|
||||
import SiteMetadataDefaults from './SiteMetadataDefaults';
|
||||
import Root from '@theme/Root';
|
||||
import SiteMetadata from '@theme/SiteMetadata';
|
||||
|
||||
import './client-lifecycles-dispatcher';
|
||||
|
||||
|
@ -27,6 +29,8 @@ export default function App(): JSX.Element {
|
|||
<DocusaurusContextProvider>
|
||||
<BrowserContextProvider>
|
||||
<Root>
|
||||
<SiteMetadataDefaults />
|
||||
<SiteMetadata />
|
||||
<BaseUrlIssueBanner />
|
||||
<PendingNavigation routes={routes} delay={1000}>
|
||||
{renderRoutes(routes)}
|
||||
|
|
27
packages/docusaurus/src/client/SiteMetadataDefaults.tsx
Normal file
27
packages/docusaurus/src/client/SiteMetadataDefaults.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
export default function SiteMetadataDefaults(): JSX.Element {
|
||||
const {
|
||||
siteConfig: {favicon, tagline, title},
|
||||
i18n: {currentLocale, localeConfigs},
|
||||
} = useDocusaurusContext();
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
const {htmlLang, direction: htmlDir} = localeConfigs[currentLocale]!;
|
||||
|
||||
return (
|
||||
<Head defaultTitle={`${title}${tagline ? ` · ${tagline}` : ''}`}>
|
||||
<html lang={htmlLang} dir={htmlDir} />
|
||||
{favicon && <link rel="icon" href={faviconUrl} />}
|
||||
</Head>
|
||||
);
|
||||
}
|
|
@ -62,7 +62,8 @@ export default function ComponentCreator(
|
|||
if (chunkRegistry) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
optsLoader[key] = chunkRegistry[0];
|
||||
optsModules.push(chunkRegistry[1], chunkRegistry[2]);
|
||||
optsModules.push(chunkRegistry[1]);
|
||||
optsWebpack.push(chunkRegistry[2]);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -75,21 +76,25 @@ export default function ComponentCreator(
|
|||
// Clone the original object since we don't want to alter the original.
|
||||
const loadedModules = JSON.parse(JSON.stringify(chunkNames));
|
||||
Object.keys(loaded).forEach((key) => {
|
||||
const newComp = loaded[key].default;
|
||||
if (!newComp) {
|
||||
throw new Error(
|
||||
`The page component at ${path} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`,
|
||||
);
|
||||
}
|
||||
if (typeof newComp === 'object' || typeof newComp === 'function') {
|
||||
Object.keys(loaded[key])
|
||||
.filter((k) => k !== 'default')
|
||||
.forEach((nonDefaultKey) => {
|
||||
newComp[nonDefaultKey] = loaded[key][nonDefaultKey];
|
||||
});
|
||||
}
|
||||
let val = loadedModules;
|
||||
const keyPath = key.split('.');
|
||||
keyPath.slice(0, -1).forEach((k) => {
|
||||
val = val[k];
|
||||
});
|
||||
val[keyPath[keyPath.length - 1]!] = loaded[key].default;
|
||||
const nonDefaultKeys = Object.keys(loaded[key]).filter(
|
||||
(k) => k !== 'default',
|
||||
);
|
||||
if (nonDefaultKeys?.length) {
|
||||
nonDefaultKeys.forEach((nonDefaultKey) => {
|
||||
val[keyPath[keyPath.length - 1]!][nonDefaultKey] =
|
||||
loaded[key][nonDefaultKey];
|
||||
});
|
||||
}
|
||||
val[keyPath[keyPath.length - 1]!] = newComp;
|
||||
});
|
||||
|
||||
const Component = loadedModules.component;
|
||||
|
@ -103,7 +108,7 @@ export default function ComponentCreator(
|
|||
// Is there any way to put this RouteContextProvider upper in the tree?
|
||||
return (
|
||||
<RouteContextProvider value={routeContextModule}>
|
||||
<Component {...loadedModules} {...props} />;
|
||||
<Component {...loadedModules} {...props} />
|
||||
</RouteContextProvider>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -9,6 +9,7 @@ import React from 'react';
|
|||
import Layout from '@theme/Layout';
|
||||
import ErrorBoundary from '@docusaurus/ErrorBoundary';
|
||||
import type {Props} from '@theme/Error';
|
||||
import Head from '@docusaurus/Head';
|
||||
|
||||
function ErrorDisplay({error, tryAgain}: Props): JSX.Element {
|
||||
return (
|
||||
|
@ -40,7 +41,10 @@ export default function Error({error, tryAgain}: Props): JSX.Element {
|
|||
// Note: we display the original error here, not the error that we
|
||||
// captured in this extra error boundary
|
||||
fallback={() => <ErrorDisplay error={error} tryAgain={tryAgain} />}>
|
||||
<Layout title="Page Error">
|
||||
<Head>
|
||||
<title>Page Error</title>
|
||||
</Head>
|
||||
<Layout>
|
||||
<ErrorDisplay error={error} tryAgain={tryAgain} />
|
||||
</Layout>
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -6,31 +6,8 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import type {Props} from '@theme/Layout';
|
||||
|
||||
export default function Layout({
|
||||
children,
|
||||
title,
|
||||
description,
|
||||
}: Props): JSX.Element {
|
||||
const context = useDocusaurusContext();
|
||||
const {siteConfig} = context;
|
||||
const {favicon, tagline, title: defaultTitle} = siteConfig;
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
return (
|
||||
<>
|
||||
<Head defaultTitle={`${defaultTitle}${tagline ? ` · ${tagline}` : ''}`}>
|
||||
{title && <title>{`${title} · ${tagline}`}</title>}
|
||||
{favicon && <link rel="icon" href={faviconUrl} />}
|
||||
{description && <meta name="description" content={description} />}
|
||||
{description && (
|
||||
<meta property="og:description" content={description} />
|
||||
)}
|
||||
</Head>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
export default function Layout({children}: Props): JSX.Element {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
|
|
@ -7,20 +7,26 @@
|
|||
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Head from '@docusaurus/Head';
|
||||
|
||||
export default function NotFound(): JSX.Element {
|
||||
return (
|
||||
<Layout title="Page Not Found">
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '50vh',
|
||||
fontSize: '20px',
|
||||
}}>
|
||||
<h1>Oops, page not found </h1>
|
||||
</div>
|
||||
</Layout>
|
||||
<>
|
||||
<Head>
|
||||
<title>Page Not Found</title>
|
||||
</Head>
|
||||
<Layout>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '50vh',
|
||||
fontSize: '20px',
|
||||
}}>
|
||||
<h1>Oops, page not found </h1>
|
||||
</div>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {type ReactNode} from 'react';
|
||||
import React from 'react';
|
||||
import type {Props} from '@theme/Root';
|
||||
|
||||
// Wrapper at the very top of the app, that is applied constantly
|
||||
// and does not depend on current route (unlike the layout)
|
||||
|
@ -14,6 +15,6 @@ import React, {type ReactNode} from 'react';
|
|||
// and these providers won't reset state when we navigate
|
||||
//
|
||||
// See https://github.com/facebook/docusaurus/issues/3919
|
||||
export default function Root({children}: {children: ReactNode}): JSX.Element {
|
||||
export default function Root({children}: Props): JSX.Element {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// To be implemented by the theme with <Head>
|
||||
export default function SiteMetadata(): JSX.Element | null {
|
||||
return null;
|
||||
}
|
|
@ -33,6 +33,7 @@ exports[`base webpack config creates webpack aliases 1`] = `
|
|||
"@theme-original/PluginThemeComponentEnhanced": "secondPluginThemeFolder/PluginThemeComponentEnhanced.js",
|
||||
"@theme-original/PluginThemeComponentOverriddenByUser": "pluginThemeFolder/PluginThemeComponentOverriddenByUser.js",
|
||||
"@theme-original/Root": "../../../../client/theme-fallback/Root/index.tsx",
|
||||
"@theme-original/SiteMetadata": "../../../../client/theme-fallback/SiteMetadata/index.tsx",
|
||||
"@theme-original/subfolder/PluginThemeComponent2": "pluginThemeFolder/subfolder/PluginThemeComponent2.js",
|
||||
"@theme/Error": "../../../../client/theme-fallback/Error/index.tsx",
|
||||
"@theme/Layout": "../../../../client/theme-fallback/Layout/index.tsx",
|
||||
|
@ -42,6 +43,7 @@ exports[`base webpack config creates webpack aliases 1`] = `
|
|||
"@theme/PluginThemeComponentEnhanced": "src/theme/PluginThemeComponentEnhanced.js",
|
||||
"@theme/PluginThemeComponentOverriddenByUser": "src/theme/PluginThemeComponentOverriddenByUser.js",
|
||||
"@theme/Root": "../../../../client/theme-fallback/Root/index.tsx",
|
||||
"@theme/SiteMetadata": "../../../../client/theme-fallback/SiteMetadata/index.tsx",
|
||||
"@theme/UserThemeComponent1": "src/theme/UserThemeComponent1.js",
|
||||
"@theme/subfolder/PluginThemeComponent2": "pluginThemeFolder/subfolder/PluginThemeComponent2.js",
|
||||
"@theme/subfolder/UserThemeComponent2": "src/theme/subfolder/UserThemeComponent2.js",
|
||||
|
|
22
website/_dogfooding/dogfooding.css
Normal file
22
website/_dogfooding/dogfooding.css
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
html.plugin-docs.plugin-id-docs-tests .red > a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
html.plugin-docs.plugin-id-docs-tests .navbar {
|
||||
border-bottom: solid thin cyan;
|
||||
}
|
||||
|
||||
html.plugin-blog.plugin-id-blog-tests .navbar {
|
||||
border-bottom: solid thin lime;
|
||||
}
|
||||
|
||||
html.plugin-pages.plugin-id-pages-tests .navbar {
|
||||
border-bottom: solid thin yellow;
|
||||
}
|
|
@ -35,9 +35,9 @@ Create a file `/src/pages/helloReact.js`:
|
|||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
function Hello() {
|
||||
export default function Hello() {
|
||||
return (
|
||||
<Layout title="Hello">
|
||||
<Layout title="Hello" description="Hello React Page">
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
|
@ -53,8 +53,6 @@ function Hello() {
|
|||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default Hello;
|
||||
```
|
||||
|
||||
Once you save the file, the development server will automatically reload the changes. Now open `http://localhost:3000/helloReact` and you will see the new page you just created.
|
||||
|
|
|
@ -42,22 +42,6 @@ Similar to [global metadata](#global-metadata), Docusaurus also allows for the a
|
|||
Some content...
|
||||
```
|
||||
|
||||
```jsx title="my-react-page.jsx"
|
||||
import React from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
|
||||
export default function page() {
|
||||
return (
|
||||
<Layout title="Page" description="A React page demo">
|
||||
<Head>
|
||||
<meta property="og:image" content="image.png" />
|
||||
</Head>
|
||||
{/* ... */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Docusaurus automatically adds `description`, `title`, canonical URL links, and other useful metadata to each Markdown page. They are configurable through front matter:
|
||||
|
||||
```md
|
||||
|
@ -77,6 +61,31 @@ Prefer to use front matter for fields like `description` and `keywords`: Docusau
|
|||
|
||||
:::
|
||||
|
||||
For JSX pages, you can use the Docusaurus [`<Head>`](docusaurus-core.md#head) component.
|
||||
|
||||
```jsx title="my-react-page.jsx"
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Head from '@docusaurus/Head';
|
||||
|
||||
export default function page() {
|
||||
return (
|
||||
<Layout title="Page" description="A React page demo">
|
||||
<Head>
|
||||
<meta property="og:image" content="image.png" />
|
||||
</Head>
|
||||
{/* ... */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
For convenience, the default theme `<Layout>` component accept `title` and `description` as props.
|
||||
|
||||
:::
|
||||
|
||||
## Static HTML generation {#static-html-generation}
|
||||
|
||||
Docusaurus is a static site generator—HTML files are statically generated for every URL route, which helps search engines discover your content more easily.
|
||||
|
|
|
@ -94,10 +94,18 @@ const config = {
|
|||
},
|
||||
webpack: {
|
||||
jsLoader: (isServer) => ({
|
||||
loader: require.resolve('esbuild-loader'),
|
||||
loader: require.resolve('swc-loader'),
|
||||
options: {
|
||||
loader: 'tsx',
|
||||
target: isServer ? 'node12' : 'es2017',
|
||||
jsc: {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"tsx": true
|
||||
},
|
||||
target: 'es2017',
|
||||
},
|
||||
module: {
|
||||
type: isServer ? 'commonjs' : 'es6',
|
||||
}
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -320,7 +328,10 @@ const config = {
|
|||
remarkPlugins: [npm2yarn],
|
||||
},
|
||||
theme: {
|
||||
customCss: [require.resolve('./src/css/custom.css')],
|
||||
customCss: [
|
||||
require.resolve('./src/css/custom.css'),
|
||||
require.resolve('./_dogfooding/dogfooding.css'),
|
||||
],
|
||||
},
|
||||
gtag: !isDeployPreview
|
||||
? {
|
||||
|
|
|
@ -49,9 +49,9 @@
|
|||
"@docusaurus/utils": "2.0.0-beta.17",
|
||||
"@docusaurus/utils-common": "2.0.0-beta.17",
|
||||
"@popperjs/core": "^2.11.4",
|
||||
"@swc/core": "^1.2.158",
|
||||
"clsx": "^1.1.1",
|
||||
"color": "^4.2.1",
|
||||
"esbuild-loader": "2.18.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"netlify-plugin-cache": "^1.0.3",
|
||||
"raw-loader": "^4.0.2",
|
||||
|
@ -61,6 +61,7 @@
|
|||
"react-popper": "^2.2.5",
|
||||
"rehype-katex": "^6.0.2",
|
||||
"remark-math": "^3.0.1",
|
||||
"swc-loader": "^0.1.15",
|
||||
"unist-util-visit": "^2.0.2",
|
||||
"workbox-routing": "^6.5.1",
|
||||
"workbox-strategies": "^6.5.1"
|
||||
|
|
|
@ -166,10 +166,6 @@ div[class^='announcementBar_'] {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.red > a {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.screen-reader-only {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
|
|
BIN
website/src/data/showcase/SeaORM.png
Normal file
BIN
website/src/data/showcase/SeaORM.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -778,6 +778,15 @@ const Users: User[] = [
|
|||
source: null,
|
||||
tags: ['product'],
|
||||
},
|
||||
{
|
||||
title: 'SeaORM - 🐚 An async & dynamic ORM for Rust',
|
||||
description:
|
||||
'SeaORM is a relational ORM to help you build web services in Rust with the familiarity of dynamic languages.',
|
||||
preview: require('./showcase/SeaORM.png'),
|
||||
website: 'https://www.sea-ql.org/SeaORM/',
|
||||
source: 'https://github.com/SeaQL/seaql.github.io',
|
||||
tags: ['opensource', 'versioning'],
|
||||
},
|
||||
{
|
||||
title: 'Ionic',
|
||||
description:
|
||||
|
|
|
@ -9,27 +9,35 @@ import React from 'react';
|
|||
import BlogLayout from '@theme/BlogLayout';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
import type {Props} from '@theme/BlogListPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
} from '@docusaurus/theme-common';
|
||||
import Link from '@docusaurus/Link';
|
||||
import ChangelogItem from '@theme/ChangelogItem';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import SearchMetadata from '@theme/SearchMetadata';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export default function ChangelogList(props: Props): JSX.Element {
|
||||
function ChangelogListMetadata(props: Props): JSX.Element {
|
||||
const {metadata} = props;
|
||||
const {blogTitle, blogDescription} = metadata;
|
||||
return (
|
||||
<>
|
||||
<PageMetadata title={blogTitle} description={blogDescription} />
|
||||
<SearchMetadata tag="blog_posts_list" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ChangelogListContent(props: Props): JSX.Element {
|
||||
const {metadata, items, sidebar} = props;
|
||||
const {blogDescription, blogTitle} = metadata;
|
||||
const {blogTitle} = metadata;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
title={blogTitle}
|
||||
description={blogDescription}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'blog_posts_list',
|
||||
}}
|
||||
sidebar={sidebar}>
|
||||
<BlogLayout sidebar={sidebar}>
|
||||
<header className="margin-bottom--lg">
|
||||
<h1 style={{fontSize: '3rem'}}>{blogTitle}</h1>
|
||||
<p>
|
||||
|
@ -88,3 +96,16 @@ export default function ChangelogList(props: Props): JSX.Element {
|
|||
</BlogLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ChangelogList(props: Props): JSX.Element {
|
||||
return (
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogListPage,
|
||||
)}>
|
||||
<ChangelogListMetadata {...props} />
|
||||
<ChangelogListContent {...props} />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,96 +6,116 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Seo from '@theme/Seo';
|
||||
import BlogLayout from '@theme/BlogLayout';
|
||||
import ChangelogItem from '@theme/ChangelogItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
import type {Props} from '@theme/BlogPostPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import {
|
||||
PageMetadata,
|
||||
HtmlClassNameProvider,
|
||||
ThemeClassNames,
|
||||
} from '@docusaurus/theme-common';
|
||||
import TOC from '@theme/TOC';
|
||||
import Link from '@docusaurus/Link';
|
||||
import clsx from 'clsx';
|
||||
|
||||
// This page doesn't change anything. It's just swapping BlogPostItem with our
|
||||
// own ChangelogItem. We don't want to apply the swizzled item to the actual
|
||||
// blog.
|
||||
export default function BlogPostPage(props: Props): JSX.Element {
|
||||
function ChangelogPageMetadata(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents} = props;
|
||||
const {assets, metadata} = BlogPostContents;
|
||||
const {title, description, date, tags, authors, frontMatter} = metadata;
|
||||
const {keywords} = frontMatter;
|
||||
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
return (
|
||||
<PageMetadata
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
|
||||
{authors.some((author) => author.url) && (
|
||||
<meta
|
||||
property="article:author"
|
||||
content={authors
|
||||
.map((author) => author.url)
|
||||
.filter(Boolean)
|
||||
.join(',')}
|
||||
/>
|
||||
)}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</PageMetadata>
|
||||
);
|
||||
}
|
||||
|
||||
function ChangelogPageContent(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents, sidebar} = props;
|
||||
const {assets, metadata} = BlogPostContents;
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
nextItem,
|
||||
prevItem,
|
||||
date,
|
||||
tags,
|
||||
authors,
|
||||
frontMatter,
|
||||
// @ts-expect-error: we injected this
|
||||
listPageLink,
|
||||
} = metadata;
|
||||
const {
|
||||
hide_table_of_contents: hideTableOfContents,
|
||||
keywords,
|
||||
toc_min_heading_level: tocMinHeadingLevel,
|
||||
toc_max_heading_level: tocMaxHeadingLevel,
|
||||
} = frontMatter;
|
||||
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogPostPage}
|
||||
sidebar={sidebar}
|
||||
toc={
|
||||
!hideTableOfContents &&
|
||||
BlogPostContents.toc &&
|
||||
BlogPostContents.toc.length > 0 ? (
|
||||
<TOC
|
||||
toc={BlogPostContents.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
/>
|
||||
) : undefined
|
||||
}>
|
||||
<Seo
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
<>
|
||||
<PageMetadata />
|
||||
<BlogLayout
|
||||
sidebar={sidebar}
|
||||
toc={
|
||||
!hideTableOfContents &&
|
||||
BlogPostContents.toc &&
|
||||
BlogPostContents.toc.length > 0 ? (
|
||||
<TOC
|
||||
toc={BlogPostContents.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
/>
|
||||
) : undefined
|
||||
}>
|
||||
<Link to={listPageLink}>← Back to index page</Link>
|
||||
|
||||
{authors.some((author) => author.url) && (
|
||||
<meta
|
||||
property="article:author"
|
||||
content={authors
|
||||
.map((author) => author.url)
|
||||
.filter(Boolean)
|
||||
.join(',')}
|
||||
/>
|
||||
<ChangelogItem
|
||||
frontMatter={frontMatter}
|
||||
assets={assets}
|
||||
metadata={metadata}
|
||||
isBlogPostPage>
|
||||
<BlogPostContents />
|
||||
</ChangelogItem>
|
||||
|
||||
{(nextItem || prevItem) && (
|
||||
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||
)}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</Seo>
|
||||
|
||||
<Link to={listPageLink}>← Back to index page</Link>
|
||||
|
||||
<ChangelogItem
|
||||
frontMatter={frontMatter}
|
||||
assets={assets}
|
||||
metadata={metadata}
|
||||
isBlogPostPage>
|
||||
<BlogPostContents />
|
||||
</ChangelogItem>
|
||||
|
||||
{(nextItem || prevItem) && (
|
||||
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||
)}
|
||||
</BlogLayout>
|
||||
</BlogLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// This page doesn't change anything. It's just swapping BlogPostItem with our
|
||||
// own ChangelogItem. We don't want to apply the swizzled item to the actual
|
||||
// blog.
|
||||
export default function ChangelogPage(props: Props): JSX.Element {
|
||||
return (
|
||||
<HtmlClassNameProvider
|
||||
className={clsx(
|
||||
ThemeClassNames.wrapper.blogPages,
|
||||
ThemeClassNames.page.blogPostPage,
|
||||
)}>
|
||||
<ChangelogPageMetadata {...props} />
|
||||
<ChangelogPageContent {...props} />
|
||||
</HtmlClassNameProvider>
|
||||
);
|
||||
}
|
||||
|
|
258
yarn.lock
258
yarn.lock
|
@ -1751,6 +1751,13 @@
|
|||
slash "^3.0.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"@jest/create-cache-key-function@^27.4.2":
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz#7448fae15602ea95c828f5eceed35c202a820b31"
|
||||
integrity sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==
|
||||
dependencies:
|
||||
"@jest/types" "^27.5.1"
|
||||
|
||||
"@jest/environment@^27.5.1":
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
|
||||
|
@ -3579,6 +3586,97 @@
|
|||
"@svgr/plugin-jsx" "^6.2.1"
|
||||
"@svgr/plugin-svgo" "^6.2.0"
|
||||
|
||||
"@swc/core-android-arm-eabi@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.158.tgz#c850b614854da8e58e27cf51390bee656f093cc7"
|
||||
integrity sha512-8RHlMo9+N8V5EE/2VOCF9H9DU3s3rj6SIRpTnQbIaJlZNwqCHp+q8xQGfKEFTrY2GShhFa/vN+w279gl2NXA+g==
|
||||
|
||||
"@swc/core-android-arm64@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.158.tgz#62764c3f509df24c6f504827d2cb7adad8a2f634"
|
||||
integrity sha512-lfSUGzIjIvyj9sMtvnL6VPuC0XryfVCs3Fsvzbk4H0bi3nSDYFmVbpBvXZFhd60lcw1bcOFepBfi70LFmnhHTQ==
|
||||
|
||||
"@swc/core-darwin-arm64@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.158.tgz#64ef42f32b06c64c61d2648a5bbca8766338197c"
|
||||
integrity sha512-vrdITsJjbx7lVN43Aq//gT+NRSdxS1+KxC6EiOct3qLcQA+P7w1nehZnlR+4qRLCgbBmQZQeeNnInaKpm9G7+g==
|
||||
|
||||
"@swc/core-darwin-x64@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.158.tgz#0ca64b3d244771e4d99a1555c4e9052dbe63d00f"
|
||||
integrity sha512-+SIZgX01YEbTTClVdbc4aNR4dDsIVP+JiXxH1Zq5JYSsGxXzunRBMYcmTxnxRK2RHY1wOsLMD8AT5lZqQK6jsg==
|
||||
|
||||
"@swc/core-freebsd-x64@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.158.tgz#f0609f2f4c9d5bde24f6ab4b061ee42fbaec85f5"
|
||||
integrity sha512-a+dF5T+Wi95E5IrMlHdGVETUgFkeL2roFT7cfjfWokR8UudD40kYkr8dxOBFizeIvgoeQdQ0hnJJl1dASL/ydA==
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.158.tgz#c166c42e6c07b1f1c273b4034d40ce486a23ef00"
|
||||
integrity sha512-+B/WYr8RRe6YcCUAfD8r/p2rGrxEEDud2MXxbAS3OMYuSYrFzfOxqKzCd6rQ7/OTXpTpapg0yctvhzOyArtAZw==
|
||||
|
||||
"@swc/core-linux-arm64-gnu@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.158.tgz#597577dda702400f5f5d4cf49b32bb3fa6017835"
|
||||
integrity sha512-QNTs6g9VYMF4UxRnSCMe7TRAPgCdsaUbHeWhaRtRE2nfKN4fd0YYPOzODEi7P3mvLW5p75FlHtRWokaME/J1HA==
|
||||
|
||||
"@swc/core-linux-arm64-musl@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.158.tgz#fb8e9aadace980eaa408596edb78090b20f4d982"
|
||||
integrity sha512-dylgrtZQJIZ6JfRDL87sPdXlOew/hl5VQaIjjhN6hu+tuRmAHzyN50DJIioErMxqFFaxnqJCxMZUFX0AlPwEKg==
|
||||
|
||||
"@swc/core-linux-x64-gnu@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.158.tgz#190113e5afa441e20db60d67ea1926ed1f9e1ae6"
|
||||
integrity sha512-f+l13OggHhdlk3va4tol7KxHm3kt1QPusLZJpVh00OENqXV6Wuv3Xh1BMgv5XMy6oXfOUdrXcPi3GWWi8079XA==
|
||||
|
||||
"@swc/core-linux-x64-musl@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.158.tgz#72894115ea3af335be0ec530c00aea88ce4fa298"
|
||||
integrity sha512-+TuNuzCBkDfoZKaaeqUrDdEANc3iVS8TYQgutHokSu6FCcNd9OGCm81SXknmYuDMtqYGs1LwVNMwCV7YOWEsiA==
|
||||
|
||||
"@swc/core-win32-arm64-msvc@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.158.tgz#5569523a0b2758d62e65319433e2228ace4cc64e"
|
||||
integrity sha512-GXfOgEgqWdrol6dpseLXQL9RkRy6TSBMULtwpxwH5uf1jwAAZaMBsd+JemvhW0OjbIX0P9M19hdvQYtxuYxvrg==
|
||||
|
||||
"@swc/core-win32-ia32-msvc@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.158.tgz#18f0b6cb1b6343a127b9da24904b3d1b1283db82"
|
||||
integrity sha512-Z/KIIgJrI2lXm+S/vRmYLcanOTvvxWq929ggjgY93m3zWrHjsWGVFoelbn2xLRUOtI/u0qna6DovLHhC4KcuBw==
|
||||
|
||||
"@swc/core-win32-x64-msvc@1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.158.tgz#1f52b172617f62892afab6bfa8d624e99fa26964"
|
||||
integrity sha512-h0jGYJmcNFhOinLT9vNE95DZfGtxROv9eDD+b5vMz03rvli5EUEUSkQ2MPDMuezHmL/P+cpKfVc/WGWWWXpfuQ==
|
||||
|
||||
"@swc/core@^1.2.158":
|
||||
version "1.2.158"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.158.tgz#aba1421d16fc9cdda8e09872776957dcdae70917"
|
||||
integrity sha512-EBTuqLC2CRd4HN2CSbe+z0QoYdMCGZV2GqUvco0s2pqcNSssrWAZj6xozcJOQ5VeUsYRVdKro2muMAWdNe7qug==
|
||||
optionalDependencies:
|
||||
"@swc/core-android-arm-eabi" "1.2.158"
|
||||
"@swc/core-android-arm64" "1.2.158"
|
||||
"@swc/core-darwin-arm64" "1.2.158"
|
||||
"@swc/core-darwin-x64" "1.2.158"
|
||||
"@swc/core-freebsd-x64" "1.2.158"
|
||||
"@swc/core-linux-arm-gnueabihf" "1.2.158"
|
||||
"@swc/core-linux-arm64-gnu" "1.2.158"
|
||||
"@swc/core-linux-arm64-musl" "1.2.158"
|
||||
"@swc/core-linux-x64-gnu" "1.2.158"
|
||||
"@swc/core-linux-x64-musl" "1.2.158"
|
||||
"@swc/core-win32-arm64-msvc" "1.2.158"
|
||||
"@swc/core-win32-ia32-msvc" "1.2.158"
|
||||
"@swc/core-win32-x64-msvc" "1.2.158"
|
||||
|
||||
"@swc/jest@^0.2.20":
|
||||
version "0.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.20.tgz#2bddb4348fb730296b86cdcd96748be131b11395"
|
||||
integrity sha512-5qSUBYY1wyIMn7p0Vl9qqV4hMI69oJwZCIPUpBsTFWN2wlwn6RDugzdgCn+bLXVYh+Cxi8bJcZ1uumDgsoL+FA==
|
||||
dependencies:
|
||||
"@jest/create-cache-key-function" "^27.4.2"
|
||||
|
||||
"@szmarczak/http-timer@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
|
||||
|
@ -8160,144 +8258,6 @@ es6-promisify@^6.0.0:
|
|||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.1.tgz#46837651b7b06bf6fff893d03f29393668d01621"
|
||||
integrity sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==
|
||||
|
||||
esbuild-android-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.27.tgz#b868bbd9955a92309c69df628d8dd1945478b45c"
|
||||
integrity sha512-LuEd4uPuj/16Y8j6kqy3Z2E9vNY9logfq8Tq+oTE2PZVuNs3M1kj5Qd4O95ee66yDGb3isaOCV7sOLDwtMfGaQ==
|
||||
|
||||
esbuild-android-arm64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.27.tgz#e7d6430555e8e9c505fd87266bbc709f25f1825c"
|
||||
integrity sha512-E8Ktwwa6vX8q7QeJmg8yepBYXaee50OdQS3BFtEHKrzbV45H4foMOeEE7uqdjGQZFBap5VAqo7pvjlyA92wznQ==
|
||||
|
||||
esbuild-darwin-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.27.tgz#4dc7484127564e89b4445c0a560a3cb50b3d68e1"
|
||||
integrity sha512-czw/kXl/1ZdenPWfw9jDc5iuIYxqUxgQ/Q+hRd4/3udyGGVI31r29LCViN2bAJgGvQkqyLGVcG03PJPEXQ5i2g==
|
||||
|
||||
esbuild-darwin-arm64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.27.tgz#469e59c665f84a8ed323166624c5e7b9b2d22ac1"
|
||||
integrity sha512-BEsv2U2U4o672oV8+xpXNxN9bgqRCtddQC6WBh4YhXKDcSZcdNh7+6nS+DM2vu7qWIWNA4JbRG24LUUYXysimQ==
|
||||
|
||||
esbuild-freebsd-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.27.tgz#895df03bf5f87094a56c9a5815bf92e591903d70"
|
||||
integrity sha512-7FeiFPGBo+ga+kOkDxtPmdPZdayrSzsV9pmfHxcyLKxu+3oTcajeZlOO1y9HW+t5aFZPiv7czOHM4KNd0tNwCA==
|
||||
|
||||
esbuild-freebsd-arm64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.27.tgz#0b72a41a6b8655e9a8c5608f2ec1afdcf6958441"
|
||||
integrity sha512-8CK3++foRZJluOWXpllG5zwAVlxtv36NpHfsbWS7TYlD8S+QruXltKlXToc/5ZNzBK++l6rvRKELu/puCLc7jA==
|
||||
|
||||
esbuild-linux-32@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.27.tgz#43b8ba3803b0bbe7f051869c6a8bf6de1e95de28"
|
||||
integrity sha512-qhNYIcT+EsYSBClZ5QhLzFzV5iVsP1YsITqblSaztr3+ZJUI+GoK8aXHyzKd7/CKKuK93cxEMJPpfi1dfsOfdw==
|
||||
|
||||
esbuild-linux-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.27.tgz#dc8072097327ecfadba1735562824ce8c05dd0bd"
|
||||
integrity sha512-ESjck9+EsHoTaKWlFKJpPZRN26uiav5gkI16RuI8WBxUdLrrAlYuYSndxxKgEn1csd968BX/8yQZATYf/9+/qg==
|
||||
|
||||
esbuild-linux-arm64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.27.tgz#c52b58cbe948426b1559910f521b0a3f396f10b8"
|
||||
integrity sha512-no6Mi17eV2tHlJnqBHRLekpZ2/VYx+NfGxKcBE/2xOMYwctsanCaXxw4zapvNrGE9X38vefVXLz6YCF8b1EHiQ==
|
||||
|
||||
esbuild-linux-arm@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.27.tgz#df869dbd67d4ee3a04b3c7273b6bd2b233e78a18"
|
||||
integrity sha512-JnnmgUBdqLQO9hoNZQqNHFWlNpSX82vzB3rYuCJMhtkuaWQEmQz6Lec1UIxJdC38ifEghNTBsF9bbe8dFilnCw==
|
||||
|
||||
esbuild-linux-mips64le@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.27.tgz#a2b646d9df368b01aa970a7b8968be6dd6b01d19"
|
||||
integrity sha512-NolWP2uOvIJpbwpsDbwfeExZOY1bZNlWE/kVfkzLMsSgqeVcl5YMen/cedRe9mKnpfLli+i0uSp7N+fkKNU27A==
|
||||
|
||||
esbuild-linux-ppc64le@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.27.tgz#9a21af766a0292578a3009c7408b8509cac7cefd"
|
||||
integrity sha512-/7dTjDvXMdRKmsSxKXeWyonuGgblnYDn0MI1xDC7J1VQXny8k1qgNp6VmrlsawwnsymSUUiThhkJsI+rx0taNA==
|
||||
|
||||
esbuild-linux-riscv64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.27.tgz#344a27f91568056a5903ad5841b447e00e78d740"
|
||||
integrity sha512-D+aFiUzOJG13RhrSmZgrcFaF4UUHpqj7XSKrIiCXIj1dkIkFqdrmqMSOtSs78dOtObWiOrFCDDzB24UyeEiNGg==
|
||||
|
||||
esbuild-linux-s390x@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.27.tgz#73a7309bd648a07ef58f069658f989a5096130db"
|
||||
integrity sha512-CD/D4tj0U4UQjELkdNlZhQ8nDHU5rBn6NGp47Hiz0Y7/akAY5i0oGadhEIg0WCY/HYVXFb3CsSPPwaKcTOW3bg==
|
||||
|
||||
esbuild-loader@2.18.0:
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.18.0.tgz#7b9548578ab954574fd94655693d22aa5ec74120"
|
||||
integrity sha512-AKqxM3bI+gvGPV8o6NAhR+cBxVO8+dh+O0OXBHIXXwuSGumckbPWHzZ17subjBGI2YEGyJ1STH7Haj8aCrwL/w==
|
||||
dependencies:
|
||||
esbuild "^0.14.6"
|
||||
joycon "^3.0.1"
|
||||
json5 "^2.2.0"
|
||||
loader-utils "^2.0.0"
|
||||
tapable "^2.2.0"
|
||||
webpack-sources "^2.2.0"
|
||||
|
||||
esbuild-netbsd-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.27.tgz#482a587cdbd18a6c264a05136596927deb46c30a"
|
||||
integrity sha512-h3mAld69SrO1VoaMpYl3a5FNdGRE/Nqc+E8VtHOag4tyBwhCQXxtvDDOAKOUQexBGca0IuR6UayQ4ntSX5ij1Q==
|
||||
|
||||
esbuild-openbsd-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.27.tgz#e99f8cdc63f1628747b63edd124d53cf7796468d"
|
||||
integrity sha512-xwSje6qIZaDHXWoPpIgvL+7fC6WeubHHv18tusLYMwL+Z6bEa4Pbfs5IWDtQdHkArtfxEkIZz77944z8MgDxGw==
|
||||
|
||||
esbuild-sunos-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.27.tgz#8611d825bcb8239c78d57452e83253a71942f45c"
|
||||
integrity sha512-/nBVpWIDjYiyMhuqIqbXXsxBc58cBVH9uztAOIfWShStxq9BNBik92oPQPJ57nzWXRNKQUEFWr4Q98utDWz7jg==
|
||||
|
||||
esbuild-windows-32@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.27.tgz#c06374206d4d92dd31d4fda299b09f51a35e82f6"
|
||||
integrity sha512-Q9/zEjhZJ4trtWhFWIZvS/7RUzzi8rvkoaS9oiizkHTTKd8UxFwn/Mm2OywsAfYymgUYm8+y2b+BKTNEFxUekw==
|
||||
|
||||
esbuild-windows-64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.27.tgz#756631c1d301dfc0d1a887deed2459ce4079582f"
|
||||
integrity sha512-b3y3vTSl5aEhWHK66ngtiS/c6byLf6y/ZBvODH1YkBM+MGtVL6jN38FdHUsZasCz9gFwYs/lJMVY9u7GL6wfYg==
|
||||
|
||||
esbuild-windows-arm64@0.14.27:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.27.tgz#ad7e187193dcd18768b16065a950f4441d7173f4"
|
||||
integrity sha512-I/reTxr6TFMcR5qbIkwRGvldMIaiBu2+MP0LlD7sOlNXrfqIl9uNjsuxFPGEG4IRomjfQ5q8WT+xlF/ySVkqKg==
|
||||
|
||||
esbuild@^0.14.6:
|
||||
version "0.14.27"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.27.tgz#41fe0f1b6b68b9f77cac025009bc54bb96e616f1"
|
||||
integrity sha512-MZQt5SywZS3hA9fXnMhR22dv0oPGh6QtjJRIYbgL1AeqAoQZE+Qn5ppGYQAoHv/vq827flj4tIJ79Mrdiwk46Q==
|
||||
optionalDependencies:
|
||||
esbuild-android-64 "0.14.27"
|
||||
esbuild-android-arm64 "0.14.27"
|
||||
esbuild-darwin-64 "0.14.27"
|
||||
esbuild-darwin-arm64 "0.14.27"
|
||||
esbuild-freebsd-64 "0.14.27"
|
||||
esbuild-freebsd-arm64 "0.14.27"
|
||||
esbuild-linux-32 "0.14.27"
|
||||
esbuild-linux-64 "0.14.27"
|
||||
esbuild-linux-arm "0.14.27"
|
||||
esbuild-linux-arm64 "0.14.27"
|
||||
esbuild-linux-mips64le "0.14.27"
|
||||
esbuild-linux-ppc64le "0.14.27"
|
||||
esbuild-linux-riscv64 "0.14.27"
|
||||
esbuild-linux-s390x "0.14.27"
|
||||
esbuild-netbsd-64 "0.14.27"
|
||||
esbuild-openbsd-64 "0.14.27"
|
||||
esbuild-sunos-64 "0.14.27"
|
||||
esbuild-windows-32 "0.14.27"
|
||||
esbuild-windows-64 "0.14.27"
|
||||
esbuild-windows-arm64 "0.14.27"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
|
@ -11825,11 +11785,6 @@ joi@^17.6.0:
|
|||
"@sideway/formula" "^3.0.0"
|
||||
"@sideway/pinpoint" "^2.0.0"
|
||||
|
||||
joycon@^3.0.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
|
||||
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
|
||||
|
||||
jpeg-js@0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.2.tgz#8b345b1ae4abde64c2da2fe67ea216a114ac279d"
|
||||
|
@ -17352,7 +17307,7 @@ sort-keys@^4.0.0:
|
|||
dependencies:
|
||||
is-plain-obj "^2.0.0"
|
||||
|
||||
source-list-map@^2.0.0, source-list-map@^2.0.1:
|
||||
source-list-map@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
@ -18040,6 +17995,13 @@ svgo@^2.5.0, svgo@^2.7.0:
|
|||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
swc-loader@^0.1.15:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.1.15.tgz#cb9c630ccfbb46dabc5aebc5560cced658e32992"
|
||||
integrity sha512-cn1WPIeQJvXM4bbo3OwdEIapsQ4uUGOfyFj0h2+2+brT0k76DCGnZXDE2KmcqTd2JSQ+b61z2NPMib7eEwMYYw==
|
||||
dependencies:
|
||||
loader-utils "^2.0.0"
|
||||
|
||||
symbol-observable@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
|
@ -19490,14 +19452,6 @@ webpack-sources@^1.4.3:
|
|||
source-list-map "^2.0.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
webpack-sources@^2.2.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
|
||||
integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
|
||||
dependencies:
|
||||
source-list-map "^2.0.1"
|
||||
source-map "^0.6.1"
|
||||
|
||||
webpack-sources@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
|
||||
|
|
Loading…
Add table
Reference in a new issue