mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +02:00
feat(v2): migrate bootstrap components to ts (#3496)
* feat(v2): Migrate bootstrap theme to typescript * chore(v2): Add eslint rule to avoid delete import of modules * chore(v2): Add lib to gitignore * chore(v2): Add prettier script * chore(v2): change hooks to ts * fix(v2): Fix Navbar and Layout problems * fix(v2): scroll * fix(v2): navbar metadata * refactor(v2): improve css styles * chore(v2): Restore debug layout * feat(v2): Remove console.log Co-authored-by: fanny <fanny.vieira@ccc.ufcg.edu.br>
This commit is contained in:
parent
1c251bca2e
commit
f343450e85
33 changed files with 417 additions and 99 deletions
|
@ -24,6 +24,7 @@ packages/docusaurus-plugin-sitemap/lib/
|
|||
packages/docusaurus-plugin-ideal-image/lib/
|
||||
packages/docusaurus-plugin-ideal-image/copyUntypedFiles.js
|
||||
packages/docusaurus-theme-classic/lib/
|
||||
packages/docusaurus-theme-bootstrap/lib/
|
||||
packages/docusaurus-migrate/lib/
|
||||
|
||||
packages/docusaurus-1.x/.eslintrc.js
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -28,6 +28,7 @@ packages/docusaurus-plugin-debug/lib/
|
|||
packages/docusaurus-plugin-sitemap/lib/
|
||||
packages/docusaurus-plugin-ideal-image/lib/
|
||||
packages/docusaurus-theme-classic/lib/
|
||||
packages/docusaurus-theme-bootstrap/lib/
|
||||
packages/docusaurus-migrate/lib/
|
||||
|
||||
website/netlifyDeployPreview
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
> **We are working hard on Docusaurus v2. If you are new to Docusaurus, try using the new version instead of v1. See the [Docusaurus v2 website](https://v2.docusaurus.io/) for more details.**
|
||||
>
|
||||
> You can see the clean live demo with classic theme by clicking this badge [](https://runme.io/run?app_id=0dd80306-47bb-4e80-95dc-dc95eb05d3fd)
|
||||
> You can see the clean live demo with classic theme by clicking this badge [](https://runme.io/run?app_id=0dd80306-47bb-4e80-95dc-dc95eb05d3fd)
|
||||
|
||||
## Introduction
|
||||
|
||||
|
@ -28,11 +28,12 @@ Docusaurus is a project for building, deploying, and maintaining open source pro
|
|||
|
||||
- **Simple to Start**
|
||||
|
||||
>Docusaurus is built in a way so that it can [get running](https://docusaurus.io/docs/en/installation/) in as little time as possible. We've built Docusaurus to handle the website build process so you can focus on your project.
|
||||
> Docusaurus is built in a way so that it can [get running](https://docusaurus.io/docs/en/installation/) in as little time as possible. We've built Docusaurus to handle the website build process so you can focus on your project.
|
||||
|
||||
- **Localizable**
|
||||
>Docusaurus ships with [localization support](https://docusaurus.io/docs/en/translation/) via CrowdIn. Empower and grow your international community by translating your documentation.
|
||||
> Docusaurus ships with [localization support](https://docusaurus.io/docs/en/translation/) via CrowdIn. Empower and grow your international community by translating your documentation.
|
||||
- **Customizable**
|
||||
>While Docusaurus ships with the key pages and sections you need to get started, including a home page, a docs section, a [blog](https://docusaurus.io/docs/en/adding-blog/), and additional support pages, it is also [customizable](https://docusaurus.io/docs/en/custom-pages/) as well to ensure you have a site that is [uniquely yours](https://docusaurus.io/docs/en/api-pages/).
|
||||
> While Docusaurus ships with the key pages and sections you need to get started, including a home page, a docs section, a [blog](https://docusaurus.io/docs/en/adding-blog/), and additional support pages, it is also [customizable](https://docusaurus.io/docs/en/custom-pages/) as well to ensure you have a site that is [uniquely yours](https://docusaurus.io/docs/en/api-pages/).
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ function Feature({imageUrl, title, description}) {
|
|||
function Home() {
|
||||
const context = useDocusaurusContext();
|
||||
const {siteConfig = {}} = context;
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
|
|
10
packages/docusaurus-theme-bootstrap/babel.config.js
Normal file
10
packages/docusaurus-theme-bootstrap/babel.config.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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/preset-typescript', {isTSX: true, allExtensions: true}]],
|
||||
};
|
|
@ -3,12 +3,17 @@
|
|||
"version": "2.0.0-alpha.64",
|
||||
"description": "Bootstrap theme for docusaurus",
|
||||
"main": "src/index.js",
|
||||
"types": "src/types.d.ts",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.0.0-alpha.64",
|
||||
"@docusaurus/types": "2.0.0-alpha.64",
|
||||
"@docusaurus/plugin-content-blog": "2.0.0-alpha.64",
|
||||
"@docusaurus/plugin-content-docs": "2.0.0-alpha.64",
|
||||
"@docusaurus/plugin-content-pages": "2.0.0-alpha.64",
|
||||
"@mdx-js/react": "^1.5.8",
|
||||
"bootstrap": "^4.4.1",
|
||||
"classnames": "^2.2.6",
|
||||
|
@ -16,6 +21,15 @@
|
|||
"prism-react-renderer": "^1.1.0",
|
||||
"reactstrap": "^8.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "2.0.0-alpha.64"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit && yarn babel && yarn prettier",
|
||||
"watch": "yarn babel --watch",
|
||||
"babel": "babel src -d lib --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
|
||||
"prettier": "prettier --config ../../.prettierrc --write \"**/*.{js,ts}\""
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4",
|
||||
"react-dom": "^16.8.4"
|
||||
|
|
|
@ -11,6 +11,9 @@ module.exports = function () {
|
|||
return {
|
||||
name: 'docusaurus-theme-bootstrap',
|
||||
getThemePath() {
|
||||
return path.resolve(__dirname, '..', 'lib', 'theme');
|
||||
},
|
||||
getTypeScriptThemePath() {
|
||||
return path.resolve(__dirname, './theme');
|
||||
},
|
||||
getClientModules() {
|
||||
|
|
|
@ -10,8 +10,9 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|||
import BlogPostCard from '@theme/BlogPostItem';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
import Layout from '@theme/Layout';
|
||||
import type {Props} from '@theme/BlogListPage';
|
||||
|
||||
function BlogListPage(props) {
|
||||
function BlogListPage(props: Props): JSX.Element {
|
||||
const {items, metadata} = props;
|
||||
const {
|
||||
siteConfig: {title: siteTitle},
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogListPaginator';
|
||||
|
||||
function BlogListPaginator(props) {
|
||||
function BlogListPaginator(props: Props): JSX.Element {
|
||||
const {previousPage, nextPage} = props.metadata;
|
||||
|
||||
return (
|
|
@ -9,6 +9,7 @@ import React from 'react';
|
|||
import {MDXProvider} from '@mdx-js/react';
|
||||
import MDXComponents from '@theme/MDXComponents';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogPostItem';
|
||||
|
||||
const MONTHS = [
|
||||
'January',
|
||||
|
@ -29,7 +30,7 @@ const getReadingTime = (readingTime) => {
|
|||
return Math.ceil(readingTime);
|
||||
};
|
||||
|
||||
function BlogPostItem(props) {
|
||||
function BlogPostItem(props: Props): JSX.Element {
|
||||
const {
|
||||
children,
|
||||
frontMatter,
|
||||
|
@ -61,7 +62,7 @@ function BlogPostItem(props) {
|
|||
<div className="col">
|
||||
{author && (
|
||||
<h5>
|
||||
<a href={authorURL} alt={author}>
|
||||
<a href={authorURL} rel={author}>
|
||||
{author}
|
||||
</a>
|
||||
</h5>
|
|
@ -9,11 +9,12 @@ import React from 'react';
|
|||
import Layout from '@theme/Layout';
|
||||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
import type {Props} from '@theme/BlogPostPage';
|
||||
|
||||
function BlogPostPage(props) {
|
||||
function BlogPostPage(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents} = props;
|
||||
const {title, description, frontMatter, metadata} = BlogPostContents;
|
||||
const {nextItem, prevItem} = metadata;
|
||||
const {frontMatter, metadata} = BlogPostContents;
|
||||
const {title, description, nextItem, prevItem} = metadata;
|
||||
|
||||
return (
|
||||
<Layout title={title} description={description}>
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogPostPaginator';
|
||||
|
||||
function BlogPostPaginator(props) {
|
||||
function BlogPostPaginator(props: Props): JSX.Element {
|
||||
const {nextItem, prevItem} = props;
|
||||
|
||||
return (
|
|
@ -8,8 +8,9 @@
|
|||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogTagsListPage';
|
||||
|
||||
function BlogTagsListPage(props) {
|
||||
function BlogTagsListPage(props: Props): JSX.Element {
|
||||
const {tags} = props;
|
||||
const renderAllTags = () => (
|
||||
<>
|
|
@ -9,12 +9,13 @@ import React from 'react';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogTagsPostsPage';
|
||||
|
||||
function pluralize(count, word) {
|
||||
return count > 1 ? `${word}s` : word;
|
||||
}
|
||||
|
||||
function BlogTagsPostPage(props) {
|
||||
function BlogTagsPostPage(props: Props): JSX.Element {
|
||||
const {metadata, items} = props;
|
||||
const {allTagsPath, name, count} = metadata;
|
||||
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import Highlight, {defaultProps} from 'prism-react-renderer';
|
||||
import theme from 'prism-react-renderer/themes/nightOwl';
|
||||
|
||||
export default ({children, className}) => {
|
||||
export default ({children, className}): JSX.Element => {
|
||||
const language = className && className.replace(/language-/, '');
|
||||
|
||||
return (
|
|
@ -14,13 +14,14 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
|
|||
|
||||
import Navbar from '@theme/Navbar';
|
||||
import Footer from '@theme/Footer';
|
||||
import type {Props} from '@theme/Layout';
|
||||
|
||||
function Layout(props) {
|
||||
function Layout(props: Props): JSX.Element {
|
||||
const {siteConfig = {}} = useDocusaurusContext();
|
||||
const {
|
||||
favicon,
|
||||
title: siteTitle,
|
||||
themeConfig: {image: defaultImage},
|
||||
themeConfig: {image: defaultImage, metadatas},
|
||||
url: siteUrl,
|
||||
titleDelimiter,
|
||||
} = siteConfig;
|
||||
|
@ -32,7 +33,6 @@ function Layout(props) {
|
|||
image,
|
||||
keywords,
|
||||
permalink,
|
||||
version,
|
||||
} = props;
|
||||
const metaTitle = title
|
||||
? `${title} ${titleDelimiter} ${siteTitle}`
|
||||
|
@ -57,7 +57,6 @@ function Layout(props) {
|
|||
{description && (
|
||||
<meta property="og:description" content={description} />
|
||||
)}
|
||||
{version && <meta name="docsearch:version" content={version} />}
|
||||
{keywords && keywords.length && (
|
||||
<meta name="keywords" content={keywords.join(',')} />
|
||||
)}
|
||||
|
@ -69,6 +68,18 @@ function Layout(props) {
|
|||
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</Head>
|
||||
<Head
|
||||
// it's important to have an additional <Head> element here,
|
||||
// as it allows react-helmet to override values set in previous <Head>
|
||||
// ie we can override default metadatas such as "twitter:card"
|
||||
// In same Head, the same meta would appear twice instead of overriding
|
||||
// See react-helmet doc
|
||||
>
|
||||
{metadatas?.length > 0 &&
|
||||
metadatas.map((metadata, i) => (
|
||||
<meta key={`metadata_${i}`} {...metadata} />
|
||||
))}
|
||||
</Head>
|
||||
<Navbar />
|
||||
<div className="container-fluid px-0 d-inline-flex flex-row">
|
||||
{children}
|
|
@ -11,10 +11,11 @@ import Head from '@docusaurus/Head';
|
|||
import DocPaginator from '@theme/DocPaginator';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import {Props} from '@theme/DocItem';
|
||||
|
||||
function DocItem(props) {
|
||||
function DocItem(props: Props): JSX.Element {
|
||||
const {siteConfig = {}} = useDocusaurusContext();
|
||||
const {url: siteUrl, title: siteTitle, titleDelimiter} = siteConfig;
|
||||
const {url: siteUrl, title: siteTitle, titleDelimiter = ' | '} = siteConfig;
|
||||
const {content: DocContent} = props;
|
||||
const {metadata} = DocContent;
|
||||
const {description, title, permalink} = metadata;
|
||||
|
@ -25,7 +26,8 @@ function DocItem(props) {
|
|||
const metaTitle = title
|
||||
? `${title} ${titleDelimiter} ${siteTitle}`
|
||||
: siteTitle;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
let metaImageUrl: string | undefined = siteUrl + useBaseUrl(metaImage);
|
||||
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
import renderRoutes from '@docusaurus/renderRoutes';
|
||||
import NotFound from '@theme/NotFound';
|
||||
import DocSidebar from '@theme/DocSidebar';
|
||||
|
@ -13,24 +13,33 @@ import MDXComponents from '@theme/MDXComponents';
|
|||
import Layout from '@theme/Layout';
|
||||
import {MDXProvider} from '@mdx-js/react';
|
||||
import {matchPath} from '@docusaurus/router';
|
||||
import type {Props} from '@theme/DocPage';
|
||||
import type {DocumentRoute} from '@theme/DocItem';
|
||||
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types';
|
||||
|
||||
function DocPageContent({currentDocRoute, versionMetadata, children}) {
|
||||
type DocPageContentProps = {
|
||||
readonly currentDocRoute: DocumentRoute;
|
||||
readonly versionMetadata: PropVersionMetadata;
|
||||
readonly children: ReactNode;
|
||||
};
|
||||
|
||||
function DocPageContent({
|
||||
currentDocRoute,
|
||||
versionMetadata,
|
||||
children,
|
||||
}: DocPageContentProps): JSX.Element {
|
||||
const {permalinkToSidebar, docsSidebars} = versionMetadata;
|
||||
const sidebarName = permalinkToSidebar[currentDocRoute.path];
|
||||
const sidebar = docsSidebars[sidebarName];
|
||||
return (
|
||||
<Layout title="Doc page" description="My Doc page">
|
||||
<div className="d-flex vh-100 overflow-hidden">
|
||||
<div className="d-flex vh-100">
|
||||
{sidebar && (
|
||||
<div className="vh-100" role="complementary">
|
||||
<DocSidebar
|
||||
key={sidebarName}
|
||||
path={currentDocRoute.path}
|
||||
sidebar={sidebar}
|
||||
/>
|
||||
<div role="complementary">
|
||||
<DocSidebar key={sidebarName} sidebar={sidebar} />
|
||||
</div>
|
||||
)}
|
||||
<main className="vh-100 w-100 d-flex flex-column align-items-center overflow-auto p-5">
|
||||
<main className="w-100 align-items-center overflow-auto p-5">
|
||||
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
|
||||
</main>
|
||||
</div>
|
||||
|
@ -38,7 +47,7 @@ function DocPageContent({currentDocRoute, versionMetadata, children}) {
|
|||
);
|
||||
}
|
||||
|
||||
function DocPage(props) {
|
||||
function DocPage(props: Props): JSX.Element {
|
||||
const {
|
||||
route: {routes: docRoutes},
|
||||
versionMetadata,
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {Props} from '@theme/DocPaginator';
|
||||
|
||||
function DocPaginator(props) {
|
||||
function DocPaginator(props: Props): JSX.Element {
|
||||
const {previous, next} = props.metadata;
|
||||
|
||||
return (
|
|
@ -11,57 +11,63 @@ import isInternalUrl from '@docusaurus/isInternalUrl';
|
|||
import {NavItem, Nav, Button} from 'reactstrap';
|
||||
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
|
||||
import classNames from 'classnames';
|
||||
import {Props} from '@theme/DocSidebar';
|
||||
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs-types';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const DocSidebarItem = ({item, onItemClick, ...props}) => {
|
||||
const {items, href, label, type} = item;
|
||||
type DocSidebarItemProps = {
|
||||
item: PropSidebarItem;
|
||||
onItemClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case 'category':
|
||||
return (
|
||||
items.length > 0 && (
|
||||
<div>
|
||||
<h4 className="ml-2">{label}</h4>
|
||||
{items.map((childItem) => (
|
||||
<DocSidebarItem
|
||||
key={childItem.label}
|
||||
item={childItem}
|
||||
onItemClick={onItemClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
case 'link':
|
||||
default:
|
||||
return (
|
||||
<NavItem>
|
||||
<Link
|
||||
key={label}
|
||||
className="sidebar-item m-4 text-white"
|
||||
to={href}
|
||||
{...(isInternalUrl(href)
|
||||
? {
|
||||
isNavLink: true,
|
||||
activeClassName: 'active',
|
||||
exact: true,
|
||||
onClick: onItemClick,
|
||||
}
|
||||
: {
|
||||
target: '_blank',
|
||||
rel: 'noreferrer noopener',
|
||||
})}
|
||||
{...props}>
|
||||
{label}
|
||||
</Link>
|
||||
</NavItem>
|
||||
);
|
||||
const DocSidebarItem = ({
|
||||
item,
|
||||
onItemClick,
|
||||
}: DocSidebarItemProps): JSX.Element => {
|
||||
if (item.type === 'category') {
|
||||
return item.items.length > 0 ? (
|
||||
<div>
|
||||
<h4 className="ml-2">{item.label}</h4>
|
||||
{item.items.map((childItem) => (
|
||||
<DocSidebarItem
|
||||
key={childItem.label}
|
||||
item={childItem}
|
||||
onItemClick={onItemClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
} else if (item.type === 'link') {
|
||||
return (
|
||||
<NavItem>
|
||||
<Link
|
||||
key={item.label}
|
||||
className="sidebar-item m-4 text-white"
|
||||
to={item.href}
|
||||
{...(isInternalUrl(item.href)
|
||||
? {
|
||||
isNavLink: true,
|
||||
activeClassName: 'active',
|
||||
exact: true,
|
||||
onClick: onItemClick,
|
||||
}
|
||||
: {
|
||||
target: '_blank',
|
||||
rel: 'noreferrer noopener',
|
||||
})}>
|
||||
{item.label}
|
||||
</Link>
|
||||
</NavItem>
|
||||
);
|
||||
} else {
|
||||
return <></>;
|
||||
}
|
||||
};
|
||||
|
||||
const DocSidebar = ({sidebar, path}) => {
|
||||
const DocSidebar = ({sidebar}: Props): JSX.Element => {
|
||||
const [sidebarShown, setSidebarShown] = useState(false);
|
||||
const handleSidebarToggle = useCallback(() => {
|
||||
setSidebarShown(!sidebarShown);
|
||||
|
@ -106,7 +112,7 @@ const DocSidebar = ({sidebar, path}) => {
|
|||
key={item.label}
|
||||
item={item}
|
||||
onItemClick={(e) => {
|
||||
e.target.blur();
|
||||
e.currentTarget.blur();
|
||||
setSidebarShown(false);
|
||||
}}
|
||||
/>
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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 isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
import Navbar from '@theme/Navbar';
|
||||
import Footer from '@theme/Footer';
|
||||
import type {Props} from '@theme/Layout';
|
||||
|
||||
function Layout(props: Props): JSX.Element {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {
|
||||
favicon,
|
||||
title: siteTitle,
|
||||
themeConfig: {image: defaultImage, metadatas},
|
||||
url: siteUrl,
|
||||
} = siteConfig;
|
||||
const {
|
||||
children,
|
||||
title,
|
||||
noFooter,
|
||||
description,
|
||||
image,
|
||||
keywords,
|
||||
permalink,
|
||||
} = props;
|
||||
const metaTitle = title ? `${title} | ${siteTitle}` : siteTitle;
|
||||
|
||||
const metaImage = image || defaultImage;
|
||||
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
|
||||
if (!isInternalUrl(metaImage)) {
|
||||
metaImageUrl = metaImage;
|
||||
}
|
||||
const faviconUrl = useBaseUrl(favicon);
|
||||
|
||||
return (
|
||||
<div className="container-fluid vh-100 vw-100 row m-0 p-0">
|
||||
<Head>
|
||||
{/* TODO: Do not assume that it is in english language */}
|
||||
<html lang="en" />
|
||||
|
||||
{metaTitle && <title>{metaTitle}</title>}
|
||||
{metaTitle && <meta property="og:title" content={metaTitle} />}
|
||||
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
|
||||
{description && <meta name="description" content={description} />}
|
||||
{description && (
|
||||
<meta property="og:description" content={description} />
|
||||
)}
|
||||
{keywords && keywords.length && (
|
||||
<meta name="keywords" content={keywords.join(',')} />
|
||||
)}
|
||||
{metaImage && <meta property="og:image" content={metaImageUrl} />}
|
||||
{metaImage && <meta property="twitter:image" content={metaImageUrl} />}
|
||||
{metaImage && (
|
||||
<meta name="twitter:image:alt" content={`Image for ${metaTitle}`} />
|
||||
)}
|
||||
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</Head>
|
||||
<Head
|
||||
// it's important to have an additional <Head> element here,
|
||||
// as it allows react-helmet to override values set in previous <Head>
|
||||
// ie we can override default metadatas such as "twitter:card"
|
||||
// In same Head, the same meta would appear twice instead of overriding
|
||||
// See react-helmet doc
|
||||
>
|
||||
{metadatas?.length > 0 &&
|
||||
metadatas.map((metadata, i) => (
|
||||
<meta key={`metadata_${i}`} {...metadata} />
|
||||
))}
|
||||
</Head>
|
||||
<Navbar />
|
||||
<div className="container-fluid px-0 d-inline-flex flex-row">
|
||||
{children}
|
||||
</div>
|
||||
{!noFooter && <Footer />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Layout;
|
|
@ -5,11 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import {Table} from 'reactstrap';
|
||||
|
||||
const Heading = (tag) => {
|
||||
const Heading = (tag: string): ReactNode => {
|
||||
return function (props) {
|
||||
return React.createElement(tag, {className: `${tag} my-3`, ...props});
|
||||
};
|
|
@ -30,7 +30,7 @@ function NavItem({
|
|||
}) {
|
||||
const toUrl = useBaseUrl(to);
|
||||
const activeBaseUrl = useBaseUrl(activeBasePath);
|
||||
const normalizedHref = useBaseUrl(href, true);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
||||
return (
|
||||
<NavItemBase>
|
||||
|
@ -65,7 +65,7 @@ function NavItem({
|
|||
function Navbar() {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {navbar: {title, links = []} = {}},
|
||||
themeConfig: {navbar: {title = '', items: links = []} = {}},
|
||||
},
|
||||
isClient,
|
||||
} = useDocusaurusContext();
|
|
@ -8,7 +8,7 @@
|
|||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
function NotFound() {
|
||||
function NotFound(): JSX.Element {
|
||||
return (
|
||||
<Layout title="Page Not Found">
|
||||
<div className="container my-xl-3">
|
|
@ -6,8 +6,9 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import type {Props} from '@theme/TabItem';
|
||||
|
||||
function TabItem(props) {
|
||||
function TabItem(props: Props): JSX.Element {
|
||||
return <div>{props.children}</div>;
|
||||
}
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useState, Children, useEffect} from 'react';
|
||||
import React, {useState, ReactElement, Children, useEffect} from 'react';
|
||||
import type {Props} from '@theme/Tabs';
|
||||
|
||||
import clsx from 'clsx';
|
||||
|
||||
|
@ -29,7 +30,7 @@ function useUserPreferencesContext() {
|
|||
};
|
||||
}
|
||||
|
||||
function Tabs(props) {
|
||||
function Tabs(props: Props): JSX.Element {
|
||||
const {block, children, defaultValue, values, groupId} = props;
|
||||
|
||||
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
|
||||
|
@ -55,7 +56,7 @@ function Tabs(props) {
|
|||
}
|
||||
};
|
||||
|
||||
const tabRefs = [];
|
||||
const tabRefs: (HTMLLIElement | null)[] = [];
|
||||
|
||||
const focusNextTab = (tabs, target) => {
|
||||
const next = tabs.indexOf(target) + 1;
|
||||
|
@ -143,7 +144,9 @@ function Tabs(props) {
|
|||
<div role="tabpanel" className="margin-vert--md">
|
||||
{
|
||||
Children.toArray(children).filter(
|
||||
(child) => child.props.value === selectedValue,
|
||||
(child) =>
|
||||
(child as ReactElement<{value: string}>).props.value ===
|
||||
selectedValue,
|
||||
)[0]
|
||||
}
|
||||
</div>
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
import {useEffect} from 'react';
|
||||
|
||||
function useLockBodyScroll(lock = true) {
|
||||
function useLockBodyScroll(lock: boolean = true): void {
|
||||
useEffect(() => {
|
||||
document.body.style.overflow = lock ? 'hidden' : 'visible';
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = 'visible';
|
||||
};
|
|
@ -8,13 +8,14 @@
|
|||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import type {LogoLinkProps, useLogoReturns} from '@theme/hooks/useLogo';
|
||||
|
||||
const useLogo = () => {
|
||||
const useLogo = (): useLogoReturns => {
|
||||
const {
|
||||
siteConfig: {baseUrl, themeConfig: {navbar: {logo = {}} = {}}} = {},
|
||||
siteConfig: {themeConfig: {navbar: {logo = {}} = {}} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
const logoLink = logo.href || baseUrl;
|
||||
let logoLinkProps = {};
|
||||
const logoLink = useBaseUrl(logo.href || '/');
|
||||
let logoLinkProps: LogoLinkProps = {};
|
||||
|
||||
if (logo.target) {
|
||||
logoLinkProps = {target: logo.target};
|
||||
|
@ -24,7 +25,6 @@ const useLogo = () => {
|
|||
target: '_blank',
|
||||
};
|
||||
}
|
||||
|
||||
const logoImageUrl = useBaseUrl(logo.src);
|
||||
|
||||
return {
|
|
@ -6,8 +6,9 @@
|
|||
*/
|
||||
|
||||
import defaultTheme from 'prism-react-renderer/themes/palenight';
|
||||
import type {PrismTheme} from 'prism-react-renderer';
|
||||
|
||||
const usePrismTheme = () => {
|
||||
const usePrismTheme = (): PrismTheme => {
|
||||
return defaultTheme;
|
||||
};
|
||||
|
143
packages/docusaurus-theme-bootstrap/src/types.d.ts
vendored
Normal file
143
packages/docusaurus-theme-bootstrap/src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-duplicates */
|
||||
/* eslint-disable spaced-comment */
|
||||
/// <reference types="@docusaurus/module-type-aliases" />
|
||||
/// <reference types="@docusaurus/plugin-content-blog" />
|
||||
/// <reference types="@docusaurus/plugin-content-docs" />
|
||||
/// <reference types="@docusaurus/plugin-content-pages" />
|
||||
|
||||
declare module '@theme/BlogListPaginator' {
|
||||
import type {Metadata} from '@theme/BlogListPage';
|
||||
|
||||
export type Props = {readonly metadata: Metadata};
|
||||
|
||||
const BlogListPaginator: (props: Props) => JSX.Element;
|
||||
export default BlogListPaginator;
|
||||
}
|
||||
|
||||
declare module '@theme/BlogPostItem' {
|
||||
import type {FrontMatter, Metadata} from '@theme/BlogPostPage';
|
||||
|
||||
export type Props = {
|
||||
readonly frontMatter: FrontMatter;
|
||||
readonly metadata: Metadata;
|
||||
readonly truncated?: string | boolean;
|
||||
readonly isBlogPostPage?: boolean;
|
||||
readonly children: JSX.Element;
|
||||
};
|
||||
|
||||
const BlogPostItem: (props: Props) => JSX.Element;
|
||||
export default BlogPostItem;
|
||||
}
|
||||
|
||||
declare module '@theme/BlogPostPaginator' {
|
||||
type Item = {readonly title: string; readonly permalink: string};
|
||||
|
||||
export type Props = {readonly nextItem?: Item; readonly prevItem?: Item};
|
||||
|
||||
const BlogPostPaginator: (props: Props) => JSX.Element;
|
||||
export default BlogPostPaginator;
|
||||
}
|
||||
|
||||
declare module '@theme/CodeBlock' {
|
||||
export type Props = {
|
||||
readonly children: string;
|
||||
readonly className: string;
|
||||
};
|
||||
|
||||
const CodeBlock: (props: Props) => JSX.Element;
|
||||
export default CodeBlock;
|
||||
}
|
||||
|
||||
declare module '@theme/DocPaginator' {
|
||||
type PageInfo = {readonly permalink: string; readonly title: string};
|
||||
|
||||
export type Props = {
|
||||
readonly metadata: {readonly previous?: PageInfo; readonly next?: PageInfo};
|
||||
};
|
||||
|
||||
const DocPaginator: (props: Props) => JSX.Element;
|
||||
export default DocPaginator;
|
||||
}
|
||||
|
||||
declare module '@theme/DocSidebar' {
|
||||
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs-types';
|
||||
|
||||
export type Props = {
|
||||
readonly sidebar: readonly PropSidebarItem[];
|
||||
};
|
||||
|
||||
const DocSidebar: (props: Props) => JSX.Element;
|
||||
export default DocSidebar;
|
||||
}
|
||||
|
||||
declare module '@theme/Tabs' {
|
||||
import type {ReactElement, ReactNode} from 'react';
|
||||
|
||||
export type Props = {
|
||||
readonly block?: boolean;
|
||||
readonly children: readonly ReactElement<{value: string}>[];
|
||||
readonly defaultValue?: string;
|
||||
readonly values: readonly {value: string; label: string}[];
|
||||
readonly groupId?: string;
|
||||
};
|
||||
|
||||
const Tabs: () => JSX.Element;
|
||||
export default Tabs;
|
||||
}
|
||||
|
||||
declare module '@theme/Footer' {
|
||||
const Footer: () => JSX.Element | null;
|
||||
export default Footer;
|
||||
}
|
||||
|
||||
declare module '@theme/Navbar' {
|
||||
const Navbar: () => JSX.Element;
|
||||
export default Navbar;
|
||||
}
|
||||
|
||||
declare module '@theme/TabItem' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
export type Props = {readonly children: ReactNode};
|
||||
|
||||
const TabItem: (props: Props) => JSX.Element;
|
||||
export default TabItem;
|
||||
}
|
||||
|
||||
declare module '@theme/hooks/useLogo' {
|
||||
export type LogoLinkProps = {target?: string; rel?: string};
|
||||
|
||||
export type useLogoReturns = {
|
||||
readonly logoLink: string;
|
||||
readonly logoLinkProps: LogoLinkProps;
|
||||
readonly logoImageUrl: string;
|
||||
readonly logoAlt: string;
|
||||
};
|
||||
|
||||
const useLogo: () => useLogoReturns;
|
||||
export default useLogo;
|
||||
}
|
||||
|
||||
declare module '@theme/Layout' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
export type Props = {
|
||||
children: ReactNode;
|
||||
title?: string;
|
||||
noFooter?: boolean;
|
||||
description?: string;
|
||||
image?: string;
|
||||
keywords?: string[];
|
||||
permalink?: string;
|
||||
};
|
||||
|
||||
const Layout: (props: Props) => JSX.Element;
|
||||
export default Layout;
|
||||
}
|
12
packages/docusaurus-theme-bootstrap/tsconfig.json
Normal file
12
packages/docusaurus-theme-bootstrap/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM"],
|
||||
"module": "esnext",
|
||||
"noEmit": true,
|
||||
"noImplicitAny": false,
|
||||
"jsx": "react",
|
||||
"baseUrl": "src"
|
||||
},
|
||||
"include": ["src/"]
|
||||
}
|
Loading…
Add table
Reference in a new issue