Skip to content

Commit

Permalink
feat(v2): Support swizzling TypeScript components (#2671)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
SamChou19815 authored Jun 25, 2020
1 parent 20930dc commit 5ccd24c
Show file tree
Hide file tree
Showing 59 changed files with 345 additions and 108 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -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 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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/
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
7 changes: 3 additions & 4 deletions packages/docusaurus-module-type-aliases/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/*';

Expand Down
10 changes: 10 additions & 0 deletions packages/docusaurus-theme-classic/babel.config.js
Original file line number Diff line number Diff line change
@@ -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}]],
};
8 changes: 8 additions & 0 deletions packages/docusaurus-theme-classic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions packages/docusaurus-theme-classic/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const MONTHS = [
'December',
];

function BlogPostItem(props) {
function BlogPostItem(props): JSX.Element {
const {
children,
frontMatter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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] || [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}},
Expand All @@ -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, '');
}
Expand Down Expand Up @@ -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},`;
Expand Down Expand Up @@ -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}) => (
<>
Expand All @@ -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,
})}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -30,7 +30,7 @@ const Heading = (Tag) =>
<Tag {...props}>
<a
aria-hidden="true"
tabIndex="-1"
tabIndex={-1}
className={clsx('anchor', {
[styles.enhancedAnchor]: !hideOnScroll,
})}
Expand All @@ -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">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 5ccd24c

Please sign in to comment.