mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-24 22:46:57 +02:00
feat(v2): Support swizzling TypeScript components (#2671)
* feat(v2): Support swizzling TypeScript components * Add tsc --noEmit to tsc script in theme-classic Now everything can pass the type checker! (although still a lot of any) * Add tsconfig and types.d.ts to website Improve developer experience. As an example, I converted NotFound to tsx * Apply type annotation suggestions * Do not fallback to `getThemePath` if getTypeScriptThemePath is undefined * Fix tsc * Add module declaration for @theme-original/* * Move babel cli to root package.json
This commit is contained in:
parent
20930dc837
commit
5ccd24cc1f
59 changed files with 345 additions and 108 deletions
|
@ -22,6 +22,7 @@ packages/docusaurus-plugin-debug/lib/
|
|||
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-1.x/.eslintrc.js
|
||||
packages/docusaurus-init/templates/facebook/.eslintrc.js
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -26,3 +26,4 @@ packages/docusaurus-plugin-content-pages/lib/
|
|||
packages/docusaurus-plugin-debug/lib/
|
||||
packages/docusaurus-plugin-sitemap/lib/
|
||||
packages/docusaurus-plugin-ideal-image/lib/
|
||||
packages/docusaurus-theme-classic/lib/
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/cli": "^7.9.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
|
@ -52,6 +53,7 @@
|
|||
"@types/lodash.pick": "^4.4.6",
|
||||
"@types/lodash.pickby": "^4.6.6",
|
||||
"@types/node": "^13.11.0",
|
||||
"@types/prismjs": "^1.16.1",
|
||||
"@types/react": "^16.9.38",
|
||||
"@types/react-dev-utils": "^9.0.1",
|
||||
"@types/react-helmet": "^6.0.0",
|
||||
|
|
|
@ -37,10 +37,9 @@ declare module '@generated/routesChunkNames' {
|
|||
export default routesChunkNames;
|
||||
}
|
||||
|
||||
declare module '@theme/*' {
|
||||
const component: any;
|
||||
export default component;
|
||||
}
|
||||
declare module '@theme/*';
|
||||
|
||||
declare module '@theme-original/*';
|
||||
|
||||
declare module '@docusaurus/*';
|
||||
|
||||
|
|
10
packages/docusaurus-theme-classic/babel.config.js
Normal file
10
packages/docusaurus-theme-classic/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}]],
|
||||
};
|
|
@ -7,6 +7,11 @@
|
|||
"access": "public"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"tsc": "tsc --noEmit && yarn babel && yarn prettier",
|
||||
"babel": "babel src -d lib --extensions \".tsx,.ts\" --copy-files",
|
||||
"prettier": "prettier --config ../../.prettierrc --write \"**/*.{js,ts}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"@mdx-js/mdx": "^1.5.8",
|
||||
|
@ -21,6 +26,9 @@
|
|||
"react-router-dom": "^5.1.2",
|
||||
"react-toggle": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^2.0.0-alpha.58"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@docusaurus/core": "^2.0.0",
|
||||
"react": "^16.8.4",
|
||||
|
|
|
@ -61,6 +61,10 @@ module.exports = function (context, options) {
|
|||
name: 'docusaurus-theme-classic',
|
||||
|
||||
getThemePath() {
|
||||
return path.join(__dirname, '..', 'lib', 'theme');
|
||||
},
|
||||
|
||||
getTypeScriptThemePath() {
|
||||
return path.resolve(__dirname, './theme');
|
||||
},
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
|
|||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function AnnouncementBar() {
|
||||
function AnnouncementBar(): JSX.Element | null {
|
||||
const {
|
||||
siteConfig: {themeConfig: {announcementBar = {}}} = {},
|
||||
siteConfig: {themeConfig: {announcementBar = {}} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
const {content, backgroundColor, textColor} = announcementBar;
|
||||
const {
|
|
@ -12,7 +12,12 @@ import Layout from '@theme/Layout';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
|
||||
function BlogListPage(props) {
|
||||
type Props = {
|
||||
metadata: {permalink: string; title: string};
|
||||
items: {content}[];
|
||||
};
|
||||
|
||||
function BlogListPage(props: Props): JSX.Element {
|
||||
const {metadata, items} = props;
|
||||
const {
|
||||
siteConfig: {title: siteTitle},
|
|
@ -8,7 +8,7 @@
|
|||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
function BlogListPaginator(props) {
|
||||
function BlogListPaginator(props): JSX.Element {
|
||||
const {metadata} = props;
|
||||
const {previousPage, nextPage} = metadata;
|
||||
|
|
@ -31,7 +31,7 @@ const MONTHS = [
|
|||
'December',
|
||||
];
|
||||
|
||||
function BlogPostItem(props) {
|
||||
function BlogPostItem(props): JSX.Element {
|
||||
const {
|
||||
children,
|
||||
frontMatter,
|
|
@ -11,7 +11,7 @@ import Layout from '@theme/Layout';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
|
||||
function BlogPostPage(props) {
|
||||
function BlogPostPage(props): JSX.Element {
|
||||
const {content: BlogPostContents} = props;
|
||||
const {frontMatter, metadata} = BlogPostContents;
|
||||
const {title, description, nextItem, prevItem, editUrl} = metadata;
|
|
@ -8,7 +8,7 @@
|
|||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
function BlogPostPaginator(props) {
|
||||
function BlogPostPaginator(props): JSX.Element {
|
||||
const {nextItem, prevItem} = props;
|
||||
|
||||
return (
|
|
@ -10,15 +10,17 @@ import React from 'react';
|
|||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
function getCategoryOfTag(tag) {
|
||||
function getCategoryOfTag(tag: string) {
|
||||
// tag's category should be customizable
|
||||
return tag[0].toUpperCase();
|
||||
}
|
||||
|
||||
function BlogTagsListPage(props) {
|
||||
type Tag = {permalink: string; name: string; count: number};
|
||||
|
||||
function BlogTagsListPage(props: {tags: Record<string, Tag>}): JSX.Element {
|
||||
const {tags} = props;
|
||||
|
||||
const tagCategories = {};
|
||||
const tagCategories: {[category: string]: string[]} = {};
|
||||
Object.keys(tags).forEach((tag) => {
|
||||
const category = getCategoryOfTag(tag);
|
||||
tagCategories[category] = tagCategories[category] || [];
|
|
@ -11,11 +11,11 @@ import Layout from '@theme/Layout';
|
|||
import BlogPostItem from '@theme/BlogPostItem';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
function pluralize(count, word) {
|
||||
function pluralize(count: number, word: string) {
|
||||
return count > 1 ? `${word}s` : word;
|
||||
}
|
||||
|
||||
function BlogTagsPostPage(props) {
|
||||
function BlogTagsPostPage(props): JSX.Element {
|
||||
const {metadata, items} = props;
|
||||
const {allTagsPath, name: tagName, count} = metadata;
|
||||
|
|
@ -87,7 +87,15 @@ const highlightDirectiveRegex = (lang) => {
|
|||
};
|
||||
const codeBlockTitleRegex = /title=".*"/;
|
||||
|
||||
export default ({children, className: languageClassName, metastring}) => {
|
||||
export default ({
|
||||
children,
|
||||
className: languageClassName,
|
||||
metastring,
|
||||
}: {
|
||||
children: string;
|
||||
className: string;
|
||||
metastring: string;
|
||||
}): JSX.Element => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
||||
|
@ -108,21 +116,25 @@ export default ({children, className: languageClassName, metastring}) => {
|
|||
}, []);
|
||||
|
||||
const button = useRef(null);
|
||||
let highlightLines = [];
|
||||
let highlightLines: number[] = [];
|
||||
let codeBlockTitle = '';
|
||||
|
||||
const prismTheme = usePrismTheme();
|
||||
|
||||
if (metastring && highlightLinesRangeRegex.test(metastring)) {
|
||||
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1];
|
||||
// Tested above
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)![1];
|
||||
highlightLines = rangeParser
|
||||
.parse(highlightLinesRange)
|
||||
.filter((n) => n > 0);
|
||||
}
|
||||
|
||||
if (metastring && codeBlockTitleRegex.test(metastring)) {
|
||||
// Tested above
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
codeBlockTitle = metastring
|
||||
.match(codeBlockTitleRegex)[0]
|
||||
.match(codeBlockTitleRegex)![0]
|
||||
.split('title=')[1]
|
||||
.replace(/"+/g, '');
|
||||
}
|
||||
|
@ -151,7 +163,10 @@ export default ({children, className: languageClassName, metastring}) => {
|
|||
if (match !== null) {
|
||||
const directive = match
|
||||
.slice(1)
|
||||
.reduce((final, item) => final || item, undefined);
|
||||
.reduce(
|
||||
(final: string | undefined, item) => final || item,
|
||||
undefined,
|
||||
);
|
||||
switch (directive) {
|
||||
case 'highlight-next-line':
|
||||
range += `${lineNumber},`;
|
||||
|
@ -188,9 +203,10 @@ export default ({children, className: languageClassName, metastring}) => {
|
|||
return (
|
||||
<Highlight
|
||||
{...defaultProps}
|
||||
key={mounted}
|
||||
key={String(mounted)}
|
||||
theme={prismTheme}
|
||||
code={code}
|
||||
// @ts-expect-error: prism-react-renderer doesn't export Language type
|
||||
language={language}>
|
||||
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
||||
<>
|
||||
|
@ -211,7 +227,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
|||
{showCopied ? 'Copied' : 'Copy'}
|
||||
</button>
|
||||
<div
|
||||
tabIndex="0"
|
||||
tabIndex={0}
|
||||
className={clsx(className, styles.codeBlock, {
|
||||
[styles.codeBlockWithTitle]: codeBlockTitle,
|
||||
})}>
|
|
@ -33,7 +33,7 @@ function DocTOC({headings}) {
|
|||
}
|
||||
|
||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||
function Headings({headings, isChild}) {
|
||||
function Headings({headings, isChild}: {headings; isChild?: boolean}) {
|
||||
if (!headings.length) {
|
||||
return null;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ function Headings({headings, isChild}) {
|
|||
);
|
||||
}
|
||||
|
||||
function DocItem(props) {
|
||||
function DocItem(props): JSX.Element {
|
||||
const {siteConfig = {}} = useDocusaurusContext();
|
||||
const {url: siteUrl, title: siteTitle} = siteConfig;
|
||||
const {content: DocContent} = props;
|
|
@ -18,7 +18,7 @@ import {matchPath} from '@docusaurus/router';
|
|||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function DocPage(props) {
|
||||
function DocPage(props): JSX.Element {
|
||||
const {route: baseRoute, docsMetadata, location} = props;
|
||||
// case-sensitive route such as it is defined in the sidebar
|
||||
const currentRoute =
|
|
@ -8,7 +8,13 @@
|
|||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
function DocPaginator(props) {
|
||||
type PageInfo = {permalink: string; title: string};
|
||||
|
||||
type Props = {
|
||||
metadata: {previous: PageInfo; next: PageInfo};
|
||||
};
|
||||
|
||||
function DocPaginator(props: Props): JSX.Element {
|
||||
const {metadata} = props;
|
||||
|
||||
return (
|
|
@ -163,11 +163,11 @@ function DocSidebarItem(props) {
|
|||
}
|
||||
}
|
||||
|
||||
function DocSidebar(props) {
|
||||
function DocSidebar(props): JSX.Element | null {
|
||||
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {navbar: {title, hideOnScroll = false} = {}},
|
||||
themeConfig: {navbar: {title = '', hideOnScroll = false} = {}} = {},
|
||||
} = {},
|
||||
isClient,
|
||||
} = useDocusaurusContext();
|
|
@ -39,7 +39,7 @@ const FooterLogo = ({url, alt}) => (
|
|||
<img className="footer__logo" alt={alt} src={url} />
|
||||
);
|
||||
|
||||
function Footer() {
|
||||
function Footer(): JSX.Element | null {
|
||||
const context = useDocusaurusContext();
|
||||
const {siteConfig = {}} = context;
|
||||
const {themeConfig = {}} = siteConfig;
|
|
@ -7,14 +7,14 @@
|
|||
|
||||
/* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */
|
||||
|
||||
import React from 'react';
|
||||
import React, {ComponentType} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
import './styles.css';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const Heading = (Tag) =>
|
||||
const Heading = (Tag: ComponentType): ((props) => JSX.Element) =>
|
||||
function TargetComponent({id, ...props}) {
|
||||
const {
|
||||
siteConfig: {
|
||||
|
@ -30,7 +30,7 @@ const Heading = (Tag) =>
|
|||
<Tag {...props}>
|
||||
<a
|
||||
aria-hidden="true"
|
||||
tabIndex="-1"
|
||||
tabIndex={-1}
|
||||
className={clsx('anchor', {
|
||||
[styles.enhancedAnchor]: !hideOnScroll,
|
||||
})}
|
||||
|
@ -39,7 +39,7 @@ const Heading = (Tag) =>
|
|||
{props.children}
|
||||
<a
|
||||
aria-hidden="true"
|
||||
tabIndex="-1"
|
||||
tabIndex={-1}
|
||||
className="hash-link"
|
||||
href={`#${id}`}
|
||||
title="Direct link to heading">
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
import Head from '@docusaurus/Head';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
@ -18,7 +18,18 @@ import Footer from '@theme/Footer';
|
|||
|
||||
import './styles.css';
|
||||
|
||||
function Layout(props) {
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
title?: string;
|
||||
noFooter?: boolean;
|
||||
description?: string;
|
||||
image?: string;
|
||||
keywords?: string[];
|
||||
permalink?: string;
|
||||
version?: string;
|
||||
};
|
||||
|
||||
function Layout(props: Props): JSX.Element {
|
||||
const {siteConfig = {}} = useDocusaurusContext();
|
||||
const {
|
||||
favicon,
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ComponentProps} from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import Heading from '@theme/Heading';
|
||||
|
@ -13,7 +13,7 @@ import Heading from '@theme/Heading';
|
|||
import styles from './styles.module.css';
|
||||
|
||||
export default {
|
||||
code: (props) => {
|
||||
code: (props: ComponentProps<typeof CodeBlock>): JSX.Element => {
|
||||
const {children} = props;
|
||||
if (typeof children === 'string') {
|
||||
if (!children.includes('\n')) {
|
||||
|
@ -23,14 +23,16 @@ export default {
|
|||
}
|
||||
return children;
|
||||
},
|
||||
a: (props) => {
|
||||
if (/\.[^./]+$/.test(props.href)) {
|
||||
a: (props: ComponentProps<'a'>): JSX.Element => {
|
||||
if (/\.[^./]+$/.test(props.href || '')) {
|
||||
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
||||
return <a {...props} />;
|
||||
}
|
||||
return <Link {...props} />;
|
||||
},
|
||||
pre: (props) => <div className={styles.mdxCodeBlock} {...props} />,
|
||||
pre: (props: ComponentProps<'div'>): JSX.Element => (
|
||||
<div className={styles.mdxCodeBlock} {...props} />
|
||||
),
|
||||
h1: Heading('h1'),
|
||||
h2: Heading('h2'),
|
||||
h3: Heading('h3'),
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useCallback, useState, useEffect} from 'react';
|
||||
import React, {useCallback, useState, useEffect, ComponentProps} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
@ -33,7 +33,15 @@ function NavLink({
|
|||
activeClassName = 'navbar__link--active',
|
||||
prependBaseUrlToHref,
|
||||
...props
|
||||
}) {
|
||||
}: {
|
||||
activeBasePath?: string;
|
||||
activeBaseRegex?: string;
|
||||
to?: string;
|
||||
href?: string;
|
||||
label?: string;
|
||||
activeClassName?: string;
|
||||
prependBaseUrlToHref?: string;
|
||||
} & ComponentProps<'a'>) {
|
||||
const toUrl = useBaseUrl(to);
|
||||
const activeBaseUrl = useBaseUrl(activeBasePath);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
@ -96,7 +104,8 @@ function NavItem({
|
|||
onClick={(e) => e.preventDefault()}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.target.parentNode.classList.toggle('dropdown--show');
|
||||
((e.target as HTMLElement)
|
||||
.parentNode as HTMLElement).classList.toggle('dropdown--show');
|
||||
}
|
||||
}}>
|
||||
{props.label}
|
||||
|
@ -171,11 +180,11 @@ function splitLinks(links) {
|
|||
};
|
||||
}
|
||||
|
||||
function Navbar() {
|
||||
function Navbar(): JSX.Element {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {
|
||||
navbar: {title, links = [], hideOnScroll = false} = {},
|
||||
navbar: {title = '', links = [], hideOnScroll = false} = {},
|
||||
disableDarkMode = false,
|
||||
},
|
||||
},
|
|
@ -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 margin-vert--xl">
|
|
@ -5,9 +5,9 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
|
||||
function TabItem(props) {
|
||||
function TabItem(props: {readonly children: ReactNode}): JSX.Element {
|
||||
return <div>{props.children}</div>;
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useState, Children} from 'react';
|
||||
import React, {useState, Children, ReactElement} from 'react';
|
||||
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
|
||||
|
||||
import clsx from 'clsx';
|
||||
|
@ -17,7 +17,15 @@ const keys = {
|
|||
right: 39,
|
||||
};
|
||||
|
||||
function Tabs(props) {
|
||||
type Props = {
|
||||
block?: boolean;
|
||||
children: ReactElement<{value: string}>[];
|
||||
defaultValue?: string;
|
||||
values: {value: string; label: string}[];
|
||||
groupId?: string;
|
||||
};
|
||||
|
||||
function Tabs(props: Props): JSX.Element {
|
||||
const {block, children, defaultValue, values, groupId} = props;
|
||||
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
|
||||
const [selectedValue, setSelectedValue] = useState(defaultValue);
|
||||
|
@ -40,7 +48,7 @@ function Tabs(props) {
|
|||
}
|
||||
};
|
||||
|
||||
const tabRefs = [];
|
||||
const tabRefs: (HTMLLIElement | null)[] = [];
|
||||
|
||||
const focusNextTab = (tabs, target) => {
|
||||
const next = tabs.indexOf(target) + 1;
|
||||
|
@ -86,7 +94,7 @@ function Tabs(props) {
|
|||
{values.map(({value, label}) => (
|
||||
<li
|
||||
role="tab"
|
||||
tabIndex="0"
|
||||
tabIndex={0}
|
||||
aria-selected={selectedValue === value}
|
||||
className={clsx('tabs__item', styles.tabItem, {
|
||||
'tabs__item--active': selectedValue === value,
|
||||
|
@ -103,7 +111,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,6 +7,6 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
const ThemeContext = React.createContext();
|
||||
const ThemeContext = React.createContext(undefined);
|
||||
|
||||
export default ThemeContext;
|
|
@ -5,12 +5,12 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
|
||||
import useTheme from '@theme/hooks/useTheme';
|
||||
import ThemeContext from '@theme/ThemeContext';
|
||||
|
||||
function ThemeProvider(props) {
|
||||
function ThemeProvider(props: {readonly children: ReactNode}): JSX.Element {
|
||||
const {isDarkTheme, setLightTheme, setDarkTheme} = useTheme();
|
||||
|
||||
return (
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ComponentProps} from 'react';
|
||||
import Toggle from 'react-toggle';
|
||||
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
@ -16,7 +16,7 @@ import styles from './styles.module.css';
|
|||
const Moon = () => <span className={clsx(styles.toggle, styles.moon)} />;
|
||||
const Sun = () => <span className={clsx(styles.toggle, styles.sun)} />;
|
||||
|
||||
export default function (props) {
|
||||
export default function (props: ComponentProps<typeof Toggle>): JSX.Element {
|
||||
const {isClient} = useDocusaurusContext();
|
||||
return (
|
||||
<Toggle
|
|
@ -7,6 +7,6 @@
|
|||
|
||||
import {createContext} from 'react';
|
||||
|
||||
const UserPreferencesContext = createContext();
|
||||
const UserPreferencesContext = createContext(undefined);
|
||||
|
||||
export default UserPreferencesContext;
|
|
@ -5,13 +5,13 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {ReactNode} from 'react';
|
||||
|
||||
import useTabGroupChoice from '@theme/hooks/useTabGroupChoice';
|
||||
import useAnnouncementBar from '@theme/hooks/useAnnouncementBar';
|
||||
import UserPreferencesContext from '@theme/UserPreferencesContext';
|
||||
|
||||
function UserPreferencesProvider(props) {
|
||||
function UserPreferencesProvider(props: {children: ReactNode}): JSX.Element {
|
||||
const {tabGroupChoices, setTabGroupChoices} = useTabGroupChoice();
|
||||
const {isAnnouncementBarClosed, closeAnnouncementBar} = useAnnouncementBar();
|
||||
|
|
@ -11,13 +11,18 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|||
const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss';
|
||||
const STORAGE_ID_KEY = 'docusaurus.announcement.id';
|
||||
|
||||
const useAnnouncementBar = () => {
|
||||
const useAnnouncementBar = (): {
|
||||
isAnnouncementBarClosed: boolean;
|
||||
closeAnnouncementBar: () => void;
|
||||
} => {
|
||||
const {
|
||||
siteConfig: {themeConfig: {announcementBar: {id} = {}}} = {},
|
||||
siteConfig: {
|
||||
themeConfig: {announcementBar: {id = 'annoucement-bar'} = {}} = {},
|
||||
} = {},
|
||||
} = useDocusaurusContext();
|
||||
const [isClosed, setClosed] = useState(true);
|
||||
const handleClose = () => {
|
||||
localStorage.setItem(STORAGE_DISMISS_KEY, true);
|
||||
localStorage.setItem(STORAGE_DISMISS_KEY, 'true');
|
||||
setClosed(true);
|
||||
};
|
||||
|
||||
|
@ -32,7 +37,7 @@ const useAnnouncementBar = () => {
|
|||
localStorage.setItem(STORAGE_ID_KEY, id);
|
||||
|
||||
if (isNewAnnouncement) {
|
||||
localStorage.setItem(STORAGE_DISMISS_KEY, false);
|
||||
localStorage.setItem(STORAGE_DISMISS_KEY, 'false');
|
||||
}
|
||||
|
||||
if (
|
|
@ -10,7 +10,7 @@ import {useLocation} from '@docusaurus/router';
|
|||
import useLocationHash from '@theme/hooks/useLocationHash';
|
||||
import useScrollPosition from '@theme/hooks/useScrollPosition';
|
||||
|
||||
const useHideableNavbar = (hideOnScroll) => {
|
||||
const useHideableNavbar = (hideOnScroll: boolean) => {
|
||||
const [isNavbarVisible, setIsNavbarVisible] = useState(true);
|
||||
const [isFocusedAnchor, setIsFocusedAnchor] = useState(false);
|
||||
const [lastScrollTop, setLastScrollTop] = useState(0);
|
|
@ -5,9 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {useState, useEffect} from 'react';
|
||||
import {useState, useEffect, Dispatch, SetStateAction} from 'react';
|
||||
|
||||
function useLocationHash(initialHash) {
|
||||
function useLocationHash(
|
||||
initialHash: string,
|
||||
): [string, Dispatch<SetStateAction<string>>] {
|
||||
const [hash, setHash] = useState(initialHash);
|
||||
|
||||
useEffect(() => {
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import {useEffect} from 'react';
|
||||
|
||||
function useLockBodyScroll(lock = true) {
|
||||
function useLockBodyScroll(lock: boolean = true): void {
|
||||
useEffect(() => {
|
||||
document.body.style.overflow = lock ? 'hidden' : 'visible';
|
||||
|
|
@ -10,13 +10,20 @@ import useThemeContext from '@theme/hooks/useThemeContext';
|
|||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
|
||||
const useLogo = () => {
|
||||
type LogoLinkProps = {target?: string; rel?: string};
|
||||
|
||||
const useLogo = (): {
|
||||
logoLink: string;
|
||||
logoLinkProps: LogoLinkProps;
|
||||
logoImageUrl: string;
|
||||
logoAlt: string;
|
||||
} => {
|
||||
const {
|
||||
siteConfig: {themeConfig: {navbar: {logo = {}} = {}}} = {},
|
||||
siteConfig: {themeConfig: {navbar: {logo = {}} = {}} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
const {isDarkTheme} = useThemeContext();
|
||||
const logoLink = useBaseUrl(logo.href || '/');
|
||||
let logoLinkProps = {};
|
||||
let logoLinkProps: LogoLinkProps = {};
|
||||
|
||||
if (logo.target) {
|
||||
logoLinkProps = {target: logo.target};
|
|
@ -9,7 +9,7 @@ import defaultTheme from 'prism-react-renderer/themes/palenight';
|
|||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useThemeContext from '@theme/hooks/useThemeContext';
|
||||
|
||||
const usePrismTheme = () => {
|
||||
const usePrismTheme = (): typeof defaultTheme => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
|
@ -8,12 +8,17 @@
|
|||
import {useState, useEffect} from 'react';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
|
||||
const getScrollPosition = () => ({
|
||||
type ScrollPosition = {scrollX: number; scrollY: number};
|
||||
|
||||
const getScrollPosition = (): ScrollPosition => ({
|
||||
scrollX: ExecutionEnvironment.canUseDOM ? window.pageXOffset : 0,
|
||||
scrollY: ExecutionEnvironment.canUseDOM ? window.pageYOffset : 0,
|
||||
});
|
||||
|
||||
const useScrollPosition = (effect, deps = []) => {
|
||||
const useScrollPosition = (
|
||||
effect: (position: ScrollPosition) => void,
|
||||
deps = [],
|
||||
): ScrollPosition => {
|
||||
const [scrollPosition, setScrollPosition] = useState(getScrollPosition());
|
||||
|
||||
const handleScroll = () => {
|
||||
|
@ -31,6 +36,7 @@ const useScrollPosition = (effect, deps = []) => {
|
|||
|
||||
return () =>
|
||||
window.removeEventListener('scroll', handleScroll, {
|
||||
// @ts-expect-error: See https://github.com/microsoft/TypeScript/issues/32912
|
||||
passive: true,
|
||||
});
|
||||
}, deps);
|
|
@ -7,17 +7,23 @@
|
|||
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
function useTOCHighlight(linkClassName, linkActiveClassName, topOffset) {
|
||||
const [lastActiveLink, setLastActiveLink] = useState(undefined);
|
||||
function useTOCHighlight(
|
||||
linkClassName: string,
|
||||
linkActiveClassName: string,
|
||||
topOffset: number,
|
||||
): void {
|
||||
const [lastActiveLink, setLastActiveLink] = useState<HTMLAnchorElement>(
|
||||
undefined!,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
let headersAnchors = [];
|
||||
let links = [];
|
||||
let headersAnchors: HTMLCollectionOf<Element>;
|
||||
let links: HTMLCollectionOf<HTMLAnchorElement>;
|
||||
|
||||
function setActiveLink() {
|
||||
function getActiveHeaderAnchor() {
|
||||
let index = 0;
|
||||
let activeHeaderAnchor = null;
|
||||
let activeHeaderAnchor: Element | null = null;
|
||||
|
||||
headersAnchors = document.getElementsByClassName('anchor');
|
||||
while (index < headersAnchors.length && !activeHeaderAnchor) {
|
||||
|
@ -40,6 +46,7 @@ function useTOCHighlight(linkClassName, linkActiveClassName, topOffset) {
|
|||
let index = 0;
|
||||
let itemHighlighted = false;
|
||||
|
||||
// @ts-expect-error: Must be <a> tags.
|
||||
links = document.getElementsByClassName(linkClassName);
|
||||
while (index < links.length && !itemHighlighted) {
|
||||
const link = links[index];
|
|
@ -9,8 +9,13 @@ import {useState, useCallback, useEffect} from 'react';
|
|||
|
||||
const TAB_CHOICE_PREFIX = 'docusaurus.tab.';
|
||||
|
||||
const useTabGroupChoice = () => {
|
||||
const [tabGroupChoices, setChoices] = useState({});
|
||||
const useTabGroupChoice = (): {
|
||||
tabGroupChoices: {readonly [groupId: string]: string};
|
||||
setTabGroupChoices: (groupId: string, newChoice: string) => void;
|
||||
} => {
|
||||
const [tabGroupChoices, setChoices] = useState<{
|
||||
readonly [groupId: string]: string;
|
||||
}>({});
|
||||
const setChoiceSyncWithLocalStorage = useCallback((groupId, newChoice) => {
|
||||
try {
|
||||
localStorage.setItem(`${TAB_CHOICE_PREFIX}${groupId}`, newChoice);
|
||||
|
@ -23,7 +28,7 @@ const useTabGroupChoice = () => {
|
|||
try {
|
||||
const localStorageChoices = {};
|
||||
for (let i = 0; i < localStorage.length; i += 1) {
|
||||
const storageKey = localStorage.key(i);
|
||||
const storageKey = localStorage.key(i) as string;
|
||||
if (storageKey.startsWith(TAB_CHOICE_PREFIX)) {
|
||||
const groupId = storageKey.substring(TAB_CHOICE_PREFIX.length);
|
||||
localStorageChoices[groupId] = localStorage.getItem(storageKey);
|
||||
|
@ -37,7 +42,7 @@ const useTabGroupChoice = () => {
|
|||
|
||||
return {
|
||||
tabGroupChoices,
|
||||
setTabGroupChoices: (groupId, newChoice) => {
|
||||
setTabGroupChoices: (groupId: string, newChoice: string) => {
|
||||
setChoices((oldChoices) => ({...oldChoices, [groupId]: newChoice}));
|
||||
setChoiceSyncWithLocalStorage(groupId, newChoice);
|
||||
},
|
|
@ -14,9 +14,13 @@ const themes = {
|
|||
dark: 'dark',
|
||||
};
|
||||
|
||||
const useTheme = () => {
|
||||
const useTheme = (): {
|
||||
isDarkTheme: boolean;
|
||||
setLightTheme: () => void;
|
||||
setDarkTheme: () => void;
|
||||
} => {
|
||||
const {
|
||||
siteConfig: {themeConfig: {disableDarkMode}} = {},
|
||||
siteConfig: {themeConfig: {disableDarkMode = false} = {}} = {},
|
||||
} = useDocusaurusContext();
|
||||
const [theme, setTheme] = useState(
|
||||
typeof document !== 'undefined'
|
||||
|
@ -43,6 +47,7 @@ const useTheme = () => {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error: safe to set null as attribute
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}, [theme]);
|
||||
|
|
@ -9,8 +9,14 @@ import {useContext} from 'react';
|
|||
|
||||
import ThemeContext from '@theme/ThemeContext';
|
||||
|
||||
function useThemeContext() {
|
||||
const context = useContext(ThemeContext);
|
||||
type ThemeContextProps = {
|
||||
isDarkTheme: boolean;
|
||||
setLightTheme: () => void;
|
||||
setDarkTheme: () => void;
|
||||
};
|
||||
|
||||
function useThemeContext(): ThemeContextProps {
|
||||
const context = useContext<ThemeContextProps>(ThemeContext);
|
||||
if (context == null) {
|
||||
throw new Error(
|
||||
'`useThemeContext` is used outside of `Layout` Component. See https://v2.docusaurus.io/docs/theme-classic#usethemecontext.',
|
|
@ -9,8 +9,17 @@ import {useContext} from 'react';
|
|||
|
||||
import UserPreferencesContext from '@theme/UserPreferencesContext';
|
||||
|
||||
function useUserPreferencesContext() {
|
||||
const context = useContext(UserPreferencesContext);
|
||||
type UserPreferencesContextProps = {
|
||||
tabGroupChoices: {readonly [groupId: string]: string};
|
||||
setTabGroupChoices: (groupId: string, newChoice: string) => void;
|
||||
isAnnouncementBarClosed: boolean;
|
||||
closeAnnouncementBar: () => void;
|
||||
};
|
||||
|
||||
function useUserPreferencesContext(): UserPreferencesContextProps {
|
||||
const context = useContext<UserPreferencesContextProps>(
|
||||
UserPreferencesContext,
|
||||
);
|
||||
if (context == null) {
|
||||
throw new Error(
|
||||
'`useUserPreferencesContext` is used outside of `Layout` Component.',
|
|
@ -12,9 +12,11 @@ const desktopThresholdWidth = 996;
|
|||
const windowSizes = {
|
||||
desktop: 'desktop',
|
||||
mobile: 'mobile',
|
||||
};
|
||||
} as const;
|
||||
|
||||
function useWindowSize() {
|
||||
type WindowSize = keyof typeof windowSizes;
|
||||
|
||||
function useWindowSize(): WindowSize | undefined {
|
||||
const isClient = typeof window !== 'undefined';
|
||||
|
||||
function getSize() {
|
||||
|
@ -30,7 +32,7 @@ function useWindowSize() {
|
|||
|
||||
useEffect(() => {
|
||||
if (!isClient) {
|
||||
return false;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function handleResize() {
|
|
@ -7,16 +7,17 @@
|
|||
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import siteConfig from '@generated/docusaurus.config';
|
||||
import type * as PrismNamespace from 'prismjs';
|
||||
|
||||
const prismIncludeLanguages = (Prism) => {
|
||||
const prismIncludeLanguages = (PrismObject: typeof PrismNamespace): void => {
|
||||
if (ExecutionEnvironment.canUseDOM) {
|
||||
const {
|
||||
themeConfig: {prism: {additionalLanguages = []} = {}},
|
||||
} = siteConfig;
|
||||
|
||||
window.Prism = Prism;
|
||||
window.Prism = PrismObject;
|
||||
|
||||
additionalLanguages.forEach((lang) => {
|
||||
additionalLanguages.forEach((lang: string) => {
|
||||
require(`prismjs/components/prism-${lang}`); // eslint-disable-line
|
||||
});
|
||||
|
9
packages/docusaurus-theme-classic/src/types.d.ts
vendored
Normal file
9
packages/docusaurus-theme-classic/src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* 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-next-line spaced-comment
|
||||
/// <reference types="@docusaurus/module-type-aliases" />
|
12
packages/docusaurus-theme-classic/tsconfig.json
Normal file
12
packages/docusaurus-theme-classic/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/"]
|
||||
}
|
1
packages/docusaurus-types/src/index.d.ts
vendored
1
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -120,6 +120,7 @@ export interface Plugin<T, U = unknown> {
|
|||
utils: ConfigureWebpackUtils,
|
||||
): Configuration;
|
||||
getThemePath?(): string;
|
||||
getTypeScriptThemePath?(): string;
|
||||
getPathsToWatch?(): string[];
|
||||
getClientModules?(): string[];
|
||||
extendCli?(cli: Command): void;
|
||||
|
|
|
@ -60,7 +60,7 @@ export function objectWithKeySorted(obj: {[index: string]: any}) {
|
|||
}
|
||||
|
||||
const indexRE = /(^|.*\/)index\.(md|js|jsx|ts|tsx)$/i;
|
||||
const extRE = /\.(md|js|tsx)$/;
|
||||
const extRE = /\.(md|js|ts|tsx)$/;
|
||||
|
||||
/**
|
||||
* Convert filepath to url path.
|
||||
|
|
|
@ -60,8 +60,17 @@ cli
|
|||
cli
|
||||
.command('swizzle <themeName> [componentName] [siteDir]')
|
||||
.description('Copy the theme files into website folder for customization.')
|
||||
.action((themeName, componentName, siteDir = '.') => {
|
||||
wrapCommand(swizzle)(path.resolve(siteDir), themeName, componentName);
|
||||
.option(
|
||||
'--typescript',
|
||||
'Copy TypeScript theme files when possible (default: false)',
|
||||
)
|
||||
.action((themeName, componentName, siteDir = '.', {typescript}) => {
|
||||
wrapCommand(swizzle)(
|
||||
path.resolve(siteDir),
|
||||
themeName,
|
||||
componentName,
|
||||
typescript,
|
||||
);
|
||||
});
|
||||
|
||||
cli
|
||||
|
|
|
@ -18,13 +18,16 @@ export default async function swizzle(
|
|||
siteDir: string,
|
||||
themeName: string,
|
||||
componentName?: string,
|
||||
typescript?: boolean,
|
||||
): Promise<void> {
|
||||
const plugin = importFresh(themeName) as (
|
||||
context: LoadContext,
|
||||
) => Plugin<unknown>;
|
||||
const context = loadContext(siteDir);
|
||||
const pluginInstance = plugin(context);
|
||||
let fromPath = pluginInstance.getThemePath?.();
|
||||
let fromPath = typescript
|
||||
? pluginInstance.getTypeScriptThemePath?.()
|
||||
: pluginInstance.getThemePath?.();
|
||||
|
||||
if (fromPath) {
|
||||
let toPath = path.resolve(siteDir, THEME_PATH);
|
||||
|
@ -32,10 +35,16 @@ export default async function swizzle(
|
|||
fromPath = path.join(fromPath, componentName);
|
||||
toPath = path.join(toPath, componentName);
|
||||
|
||||
// Handle single JavaScript file only.
|
||||
// E.g: if <fromPath> does not exist, we try to swizzle <fromPath>.js instead
|
||||
if (!fs.existsSync(fromPath) && fs.existsSync(`${fromPath}.js`)) {
|
||||
[fromPath, toPath] = [`${fromPath}.js`, `${toPath}.js`];
|
||||
// Handle single TypeScript/JavaScript file only.
|
||||
// E.g: if <fromPath> does not exist, we try to swizzle <fromPath>.(ts|tsx|js) instead
|
||||
if (!fs.existsSync(fromPath)) {
|
||||
if (fs.existsSync(`${fromPath}.ts`)) {
|
||||
[fromPath, toPath] = [`${fromPath}.ts`, `${toPath}.ts`];
|
||||
} else if (fs.existsSync(`${fromPath}.tsx`)) {
|
||||
[fromPath, toPath] = [`${fromPath}.tsx`, `${toPath}.tsx`];
|
||||
} else if (fs.existsSync(`${fromPath}.js`)) {
|
||||
[fromPath, toPath] = [`${fromPath}.js`, `${toPath}.js`];
|
||||
}
|
||||
}
|
||||
}
|
||||
await fs.copy(fromPath, toPath);
|
||||
|
@ -48,5 +57,13 @@ export default async function swizzle(
|
|||
console.log(
|
||||
`\n${chalk.green('Success!')} Copied ${fromMsg} to ${toMsg}.\n`,
|
||||
);
|
||||
} else if (typescript) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`${themeName} does not provide TypeScript theme code via getTypeScriptThemePath().`,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
console.warn(chalk.yellow(`${themeName} does not provide any theme code.`));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"lib": ["es2017","es2019.array"],
|
||||
"lib": ["es2017","es2019.array", "DOM"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import Layout from '@theme/Layout';
|
||||
import Feedback from '../pages/feedback';
|
||||
|
||||
function NotFound({location}) {
|
||||
function NotFound({location}: {location: {pathname: string}}): JSX.Element {
|
||||
if (/^\/feedback/.test(location.pathname)) {
|
||||
return <Feedback />;
|
||||
}
|
9
website/src/types.d.ts
vendored
Normal file
9
website/src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* 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-next-line spaced-comment
|
||||
/// <reference types="@docusaurus/module-type-aliases" />
|
13
website/tsconfig.json
Normal file
13
website/tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM"],
|
||||
"module": "esnext",
|
||||
"noEmit": true,
|
||||
"noImplicitAny": false,
|
||||
"jsx": "react",
|
||||
"baseUrl": "src"
|
||||
},
|
||||
"include": ["src/"]
|
||||
}
|
28
yarn.lock
28
yarn.lock
|
@ -2,6 +2,22 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/cli@^7.9.0":
|
||||
version "7.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.10.3.tgz#4ea83bd997d2a41c78d07263ada3ec466fb3764b"
|
||||
integrity sha512-lWB3yH5/fWY8pi2Kj5/fA+17guJ9feSBw5DNjTju3/nRi9sXnl1JPh7aKQOSvdNbiDbkzzoGYtsr46M8dGmXDQ==
|
||||
dependencies:
|
||||
commander "^4.0.1"
|
||||
convert-source-map "^1.1.0"
|
||||
fs-readdir-recursive "^1.1.0"
|
||||
glob "^7.0.0"
|
||||
lodash "^4.17.13"
|
||||
make-dir "^2.1.0"
|
||||
slash "^2.0.0"
|
||||
source-map "^0.5.0"
|
||||
optionalDependencies:
|
||||
chokidar "^2.1.8"
|
||||
|
||||
"@babel/code-frame@7.5.5":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
|
||||
|
@ -3051,6 +3067,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
|
||||
integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==
|
||||
|
||||
"@types/prismjs@^1.16.1":
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.16.1.tgz#50b82947207847db6abcbcd14caa89e3b897c259"
|
||||
integrity sha512-RNgcK3FEc1GpeOkamGDq42EYkb6yZW5OWQwTS56NJIB8WL0QGISQglA7En7NUx9RGP8AC52DOe+squqbAckXlA==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
|
@ -5807,7 +5828,7 @@ conventional-recommended-bump@^5.0.0:
|
|||
meow "^4.0.0"
|
||||
q "^1.5.1"
|
||||
|
||||
convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
||||
|
@ -8301,6 +8322,11 @@ fs-minipass@^2.0.0:
|
|||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs-readdir-recursive@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27"
|
||||
integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==
|
||||
|
||||
fs-write-stream-atomic@^1.0.8:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue