mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-04 11:52:39 +02:00
refactor(v2): Convert docusaurus-core to TypeScript (#2578)
* refactor(v2): Convert docusaurus-core to TypeScript * Update types.d.ts Co-authored-by: Yangshun Tay <tay.yang.shun@gmail.com>
This commit is contained in:
parent
f6267dc52c
commit
5f487f3b02
30 changed files with 128 additions and 22 deletions
1
packages/docusaurus-types/src/index.d.ts
vendored
1
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -45,6 +45,7 @@ export interface DocusaurusConfig {
|
|||
|
||||
export interface DocusaurusContext {
|
||||
siteConfig?: DocusaurusConfig;
|
||||
isClient?: boolean;
|
||||
}
|
||||
|
||||
export interface Preset {
|
||||
|
|
|
@ -15,6 +15,6 @@ const srcDir = path.resolve(__dirname, 'src');
|
|||
const libDir = path.resolve(__dirname, 'lib');
|
||||
fs.copySync(srcDir, libDir, {
|
||||
filter(filepath) {
|
||||
return !/__tests__/.test(filepath) && !/\.ts$/.test(filepath);
|
||||
return !/__tests__/.test(filepath) && !/\.tsx?$/.test(filepath);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"docusaurus": "bin/docusaurus.js"
|
||||
},
|
||||
"scripts": {
|
||||
"tsc": "tsc && node copyUntypedFiles.js"
|
||||
"tsc": "tsc && tsc -p tsconfig.client.json && node copyUntypedFiles.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/facebook/docusaurus/issues"
|
||||
|
|
|
@ -9,8 +9,8 @@ import React, {useEffect, useState} from 'react';
|
|||
|
||||
import routes from '@generated/routes';
|
||||
import siteConfig from '@generated/docusaurus.config';
|
||||
import renderRoutes from '@docusaurus/renderRoutes';
|
||||
import DocusaurusContext from '@docusaurus/context';
|
||||
import renderRoutes from './exports/renderRoutes';
|
||||
import DocusaurusContext from './exports/context';
|
||||
import PendingNavigation from './PendingNavigation';
|
||||
|
||||
import './client-lifecycles-dispatcher';
|
|
@ -17,8 +17,20 @@ import 'nprogress/nprogress.css';
|
|||
|
||||
nprogress.configure({showSpinner: false});
|
||||
|
||||
class PendingNavigation extends React.Component {
|
||||
constructor(props) {
|
||||
interface Props {
|
||||
routes: any[];
|
||||
delay: number;
|
||||
location: any;
|
||||
}
|
||||
interface State {
|
||||
nextRouteHasLoaded: boolean;
|
||||
}
|
||||
|
||||
class PendingNavigation extends React.Component<Props, State> {
|
||||
previousLocation: any;
|
||||
progressBarTimeout: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// previousLocation doesn't affect rendering, hence not stored in state.
|
|
@ -16,7 +16,12 @@ function dispatchLifecycleAction(lifecycleAction, ...args) {
|
|||
});
|
||||
}
|
||||
|
||||
function createLifecyclesDispatcher() {
|
||||
interface Dispatchers {
|
||||
onRouteUpdate: Function;
|
||||
onRouteUpdateDelayed: Function;
|
||||
}
|
||||
|
||||
function createLifecyclesDispatcher(): Dispatchers {
|
||||
// TODO: Not sure whether it's better to declare an explicit object
|
||||
// with all the lifecycles. It's better for typing but quite verbose.
|
||||
// On the other hand, there's some runtime cost generating this object
|
||||
|
@ -30,7 +35,7 @@ function createLifecyclesDispatcher() {
|
|||
return lifecycles;
|
||||
},
|
||||
{},
|
||||
);
|
||||
) as Dispatchers;
|
||||
}
|
||||
|
||||
export default createLifecyclesDispatcher();
|
|
@ -10,11 +10,17 @@ import {hydrate, render} from 'react-dom';
|
|||
import {BrowserRouter} from 'react-router-dom';
|
||||
|
||||
import routes from '@generated/routes';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import ExecutionEnvironment from './exports/ExecutionEnvironment';
|
||||
import App from './App';
|
||||
import preload from './preload';
|
||||
import docusaurus from './docusaurus';
|
||||
|
||||
declare global {
|
||||
interface NodeModule {
|
||||
hot?: any;
|
||||
}
|
||||
}
|
||||
|
||||
// Client-side render (e.g: running in browser) to become single-page application (SPA).
|
||||
if (ExecutionEnvironment.canUseDOM) {
|
||||
window.docusaurus = docusaurus;
|
|
@ -14,6 +14,13 @@ import flat from './flat';
|
|||
const fetched = {};
|
||||
const loaded = {};
|
||||
|
||||
declare global {
|
||||
const __webpack_require__: any;
|
||||
interface Navigator {
|
||||
connection: any;
|
||||
}
|
||||
}
|
||||
|
||||
const isSlowConnection = () => {
|
||||
// If user is on slow or constrained connection.
|
||||
if (`connection` in navigator) {
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import ExecutionEnvironment from './ExecutionEnvironment';
|
||||
|
||||
function BrowserOnly({children}) {
|
||||
return (
|
|
@ -12,7 +12,7 @@ import routesChunkNames from '@generated/routesChunkNames';
|
|||
import registry from '@generated/registry';
|
||||
import flat from '../flat';
|
||||
|
||||
function ComponentCreator(path) {
|
||||
function ComponentCreator(path: string) {
|
||||
// 404 page
|
||||
if (path === '*') {
|
||||
return Loadable({
|
||||
|
@ -22,8 +22,8 @@ function ComponentCreator(path) {
|
|||
}
|
||||
|
||||
const chunkNames = routesChunkNames[path];
|
||||
const optsModules = [];
|
||||
const optsWebpack = [];
|
||||
const optsModules: string[] = [];
|
||||
const optsWebpack: string[] = [];
|
||||
const optsLoader = {};
|
||||
|
||||
/* Prepare opts data that react-loadable needs
|
|
@ -15,6 +15,7 @@ const ExecutionEnvironment = {
|
|||
canUseDOM,
|
||||
|
||||
canUseEventListeners:
|
||||
// @ts-ignore
|
||||
canUseDOM && !!(window.addEventListener || window.attachEvent),
|
||||
|
||||
canUseIntersectionObserver: canUseDOM && 'IntersectionObserver' in window,
|
||||
|
@ -22,4 +23,4 @@ const ExecutionEnvironment = {
|
|||
canUseViewport: canUseDOM && !!window.screen,
|
||||
};
|
||||
|
||||
module.exports = ExecutionEnvironment;
|
||||
export default ExecutionEnvironment;
|
|
@ -6,11 +6,24 @@
|
|||
*/
|
||||
|
||||
import React, {useEffect, useRef} from 'react';
|
||||
import {NavLink, Link as RRLink} from 'react-router-dom';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
|
||||
function Link({isNavLink, ...props}) {
|
||||
import {NavLink, Link as RRLink} from 'react-router-dom';
|
||||
import isInternalUrl from './isInternalUrl';
|
||||
import ExecutionEnvironment from './ExecutionEnvironment';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
docusaurus: any;
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
readonly isNavLink?: boolean;
|
||||
readonly to?: string;
|
||||
readonly href: string
|
||||
}
|
||||
|
||||
function Link({isNavLink, ...props}: Props) {
|
||||
const {to, href} = props;
|
||||
const targetLink = to || href;
|
||||
const isInternal = isInternalUrl(targetLink);
|
|
@ -6,5 +6,6 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {DocusaurusContext} from '@docusaurus/types';
|
||||
|
||||
export default React.createContext({});
|
||||
export default React.createContext<DocusaurusContext>({});
|
|
@ -5,6 +5,6 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export default function isInternalUrl(url) {
|
||||
export default function isInternalUrl(url: string): boolean {
|
||||
return /^(https?:|\/\/|mailto:|tel:)/.test(url) === false;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import useDocusaurusContext from './useDocusaurusContext';
|
||||
|
||||
export default function useBaseUrl(url) {
|
||||
export default function useBaseUrl(url: string): string {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const {baseUrl = '/'} = siteConfig || {};
|
||||
|
|
@ -9,7 +9,7 @@ function flat(target) {
|
|||
const delimiter = '.';
|
||||
const output = {};
|
||||
|
||||
function step(object, prev) {
|
||||
function step(object, prev?: string) {
|
||||
Object.keys(object).forEach((key) => {
|
||||
const value = object[key];
|
||||
const type = typeof value;
|
|
@ -18,7 +18,9 @@ import path from 'path';
|
|||
import fs from 'fs-extra';
|
||||
import routes from '@generated/routes';
|
||||
import packageJson from '../../package.json';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import preload from './preload';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import App from './App';
|
||||
import ssrTemplate from './templates/ssr.html.template';
|
||||
|
||||
|
|
43
packages/docusaurus/src/client/types.d.ts
vendored
Normal file
43
packages/docusaurus/src/client/types.d.ts
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare module '@generated/client-modules' {
|
||||
const clientModules: readonly any[];
|
||||
export default clientModules;
|
||||
}
|
||||
|
||||
declare module '@generated/docusaurus.config' {
|
||||
const config: any;
|
||||
export default config;
|
||||
}
|
||||
|
||||
declare module '@generated/registry' {
|
||||
const registry: {
|
||||
readonly [key: string]: [() => Promise<any>, string, string];
|
||||
};
|
||||
export default registry;
|
||||
}
|
||||
|
||||
declare module '@generated/routes' {
|
||||
type Route = {
|
||||
readonly path: string;
|
||||
readonly component: any;
|
||||
readonly exact?: boolean;
|
||||
};
|
||||
const routes: Route[];
|
||||
export default routes;
|
||||
}
|
||||
|
||||
declare module '@generated/routesChunkNames' {
|
||||
const routesChunkNames: any;
|
||||
export default routesChunkNames;
|
||||
}
|
||||
|
||||
declare module '@theme/*' {
|
||||
const component: any;
|
||||
export default component;
|
||||
}
|
13
packages/docusaurus/tsconfig.client.json
Normal file
13
packages/docusaurus/tsconfig.client.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"lib": ["DOM"],
|
||||
"module": "esnext",
|
||||
"tsBuildInfoFile": "./lib/client/.tsbuildinfo",
|
||||
"outDir": "lib/client",
|
||||
"noImplicitAny": false,
|
||||
"jsx": "react",
|
||||
},
|
||||
"include": ["src/client"]
|
||||
}
|
|
@ -2,10 +2,12 @@
|
|||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"lib": ["DOM"],
|
||||
"tsBuildInfoFile": "./lib/.tsbuildinfo",
|
||||
"rootDir": "src",
|
||||
"outDir": "lib",
|
||||
"noImplicitAny": false,
|
||||
"jsx": "react",
|
||||
},
|
||||
"exclude": ["node_modules", "**/__tests__/**/*", "**/lib/**/*", "src/client"]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue