diff --git a/.eslintignore b/.eslintignore index 03ed7e494d..6d9160dd1a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -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 diff --git a/.gitignore b/.gitignore index 83d670a967..e140fc696a 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/README.md b/README.md index 41606602b6..0fe27f2e33 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,20 @@ > **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 [![Runme](https://runme.io/static/button.svg)](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 [![Runme](https://runme.io/static/button.svg)](https://runme.io/run?app_id=0dd80306-47bb-4e80-95dc-dc95eb05d3fd) ## Introduction Docusaurus is a project for building, deploying, and maintaining open source project websites easily. -- **Simple to Start** +- **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. -- **Localizable** ->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/). +> 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. +- **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/). ## Installation diff --git a/packages/docusaurus-init/templates/bootstrap/src/pages/index.js b/packages/docusaurus-init/templates/bootstrap/src/pages/index.js index 27de9db3bc..730b092848 100644 --- a/packages/docusaurus-init/templates/bootstrap/src/pages/index.js +++ b/packages/docusaurus-init/templates/bootstrap/src/pages/index.js @@ -58,6 +58,7 @@ function Feature({imageUrl, title, description}) { function Home() { const context = useDocusaurusContext(); const {siteConfig = {}} = context; + return ( { return Math.ceil(readingTime); }; -function BlogPostItem(props) { +function BlogPostItem(props: Props): JSX.Element { const { children, frontMatter, @@ -61,7 +62,7 @@ function BlogPostItem(props) {
{author && (
- + {author}
diff --git a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.tsx similarity index 83% rename from packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.tsx index a4767e084d..f97320337e 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPage/index.tsx @@ -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 ( diff --git a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.js b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.tsx similarity index 89% rename from packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.tsx index bd30571b55..99e8538cd0 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/BlogPostPaginator/index.tsx @@ -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 ( diff --git a/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.tsx similarity index 90% rename from packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.tsx index 2d39a25a8e..cb8d5f5d02 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsListPage/index.tsx @@ -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 = () => ( <> diff --git a/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.tsx similarity index 93% rename from packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.tsx index 07a50ff6bc..bdee5eb174 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/BlogTagsPostsPage/index.tsx @@ -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; diff --git a/packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.js b/packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.tsx similarity index 94% rename from packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.tsx index 19c2c77d26..0873494ffb 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/CodeBlock/index.tsx @@ -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 ( diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.tsx similarity index 78% rename from packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.tsx index a23d48c9a4..c14b0a936f 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DebugLayout/index.tsx @@ -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 && ( )} - {version && } {keywords && keywords.length && ( )} @@ -69,6 +68,18 @@ function Layout(props) { {permalink && } + element here, + // as it allows react-helmet to override values set in previous + // 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) => ( + + ))} +
{children} diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.tsx similarity index 88% rename from packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.tsx index 4045234e91..e1d02f3bd5 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocItem/index.tsx @@ -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; } diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx similarity index 65% rename from packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx index d63a812e8d..54828fc32d 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx @@ -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 ( -
+
{sidebar && ( -
- +
+
)} -
+
{children}
@@ -38,7 +47,7 @@ function DocPageContent({currentDocRoute, versionMetadata, children}) { ); } -function DocPage(props) { +function DocPage(props: Props): JSX.Element { const { route: {routes: docRoutes}, versionMetadata, diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.tsx similarity index 90% rename from packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.tsx index 39e0e82901..df83a74b45 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocPaginator/index.tsx @@ -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 ( diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.tsx similarity index 60% rename from packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.tsx index bf07afb1ed..4075698bc6 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocSidebar/index.tsx @@ -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; +}; - switch (type) { - case 'category': - return ( - items.length > 0 && ( -
-

{label}

- {items.map((childItem) => ( - - ))} -
- ) - ); - - case 'link': - default: - return ( - - - {label} - - - ); +const DocSidebarItem = ({ + item, + onItemClick, +}: DocSidebarItemProps): JSX.Element => { + if (item.type === 'category') { + return item.items.length > 0 ? ( +
+

{item.label}

+ {item.items.map((childItem) => ( + + ))} +
+ ) : ( + <> + ); + } else if (item.type === 'link') { + return ( + + + {item.label} + + + ); + } 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); }} /> diff --git a/packages/docusaurus-theme-bootstrap/src/theme/Footer/index.js b/packages/docusaurus-theme-bootstrap/src/theme/Footer/index.tsx similarity index 100% rename from packages/docusaurus-theme-bootstrap/src/theme/Footer/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/Footer/index.tsx diff --git a/packages/docusaurus-theme-bootstrap/src/theme/Layout/index.tsx b/packages/docusaurus-theme-bootstrap/src/theme/Layout/index.tsx new file mode 100644 index 0000000000..0f96ef5b43 --- /dev/null +++ b/packages/docusaurus-theme-bootstrap/src/theme/Layout/index.tsx @@ -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 ( +
+ + {/* TODO: Do not assume that it is in english language */} + + + {metaTitle && {metaTitle}} + {metaTitle && } + {favicon && } + {description && } + {description && ( + + )} + {keywords && keywords.length && ( + + )} + {metaImage && } + {metaImage && } + {metaImage && ( + + )} + {permalink && } + + + element here, + // as it allows react-helmet to override values set in previous + // 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) => ( + + ))} + + +
+ {children} +
+ {!noFooter &&
} +
+ ); +} + +export default Layout; diff --git a/packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.js b/packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.tsx similarity index 91% rename from packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.tsx index d8ba7cd62e..08a45cf4eb 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/MDXComponents/index.tsx @@ -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}); }; diff --git a/packages/docusaurus-theme-bootstrap/src/theme/MDXPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/MDXPage/index.tsx similarity index 100% rename from packages/docusaurus-theme-bootstrap/src/theme/MDXPage/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/MDXPage/index.tsx diff --git a/packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.js b/packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.tsx similarity index 95% rename from packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.tsx index 6ebff920fa..e36ce9546b 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/Navbar/index.tsx @@ -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 ( @@ -65,7 +65,7 @@ function NavItem({ function Navbar() { const { siteConfig: { - themeConfig: {navbar: {title, links = []} = {}}, + themeConfig: {navbar: {title = '', items: links = []} = {}}, }, isClient, } = useDocusaurusContext(); diff --git a/packages/docusaurus-theme-bootstrap/src/theme/NotFound.js b/packages/docusaurus-theme-bootstrap/src/theme/NotFound.tsx similarity index 95% rename from packages/docusaurus-theme-bootstrap/src/theme/NotFound.js rename to packages/docusaurus-theme-bootstrap/src/theme/NotFound.tsx index 649986ac9c..b1329dca19 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/NotFound.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/NotFound.tsx @@ -8,7 +8,7 @@ import React from 'react'; import Layout from '@theme/Layout'; -function NotFound() { +function NotFound(): JSX.Element { return (
diff --git a/packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.js b/packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.tsx similarity index 76% rename from packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.tsx index 709748b85c..99559b36e6 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/TabItem/index.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; +import type {Props} from '@theme/TabItem'; -function TabItem(props) { +function TabItem(props: Props): JSX.Element { return
{props.children}
; } diff --git a/packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js b/packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.tsx similarity index 91% rename from packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js rename to packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.tsx index f8c9c0cce0..7b9fcc93d3 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/Tabs/index.tsx @@ -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) {
{ Children.toArray(children).filter( - (child) => child.props.value === selectedValue, + (child) => + (child as ReactElement<{value: string}>).props.value === + selectedValue, )[0] }
diff --git a/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.js b/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.ts similarity index 88% rename from packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.js rename to packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.ts index ca77ea84d1..8b2f494c65 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLockBodyScroll.ts @@ -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'; }; diff --git a/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.js b/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.ts similarity index 73% rename from packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.js rename to packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.ts index f7bc13cac0..886ab6109f 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/hooks/useLogo.ts @@ -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 { diff --git a/packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.js b/packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.ts similarity index 76% rename from packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.js rename to packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.ts index fb370e355a..341c8f5fd1 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/hooks/usePrismTheme.ts @@ -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; }; diff --git a/packages/docusaurus-theme-bootstrap/src/types.d.ts b/packages/docusaurus-theme-bootstrap/src/types.d.ts new file mode 100644 index 0000000000..b820dcb183 --- /dev/null +++ b/packages/docusaurus-theme-bootstrap/src/types.d.ts @@ -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 */ +/// +/// +/// +/// + +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; +} diff --git a/packages/docusaurus-theme-bootstrap/tsconfig.json b/packages/docusaurus-theme-bootstrap/tsconfig.json new file mode 100644 index 0000000000..a27160e601 --- /dev/null +++ b/packages/docusaurus-theme-bootstrap/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "lib": ["DOM"], + "module": "esnext", + "noEmit": true, + "noImplicitAny": false, + "jsx": "react", + "baseUrl": "src" + }, + "include": ["src/"] +}