mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-04 20:57:17 +02:00
refactor(v2): correct client types and type aliases (#4451)
This commit is contained in:
parent
291a72fbae
commit
15107ee099
12 changed files with 128 additions and 97 deletions
|
@ -132,6 +132,12 @@ module.exports = {
|
|||
'header/header': OFF,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.d.ts'],
|
||||
rules: {
|
||||
'import/no-duplicates': OFF,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-helmet": "*",
|
||||
"@types/react-router-dom": "*"
|
||||
"@types/react-loadable": "*",
|
||||
"@types/react-router-dom": "*",
|
||||
"@types/react-router-config": "*"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
|
@ -69,16 +69,30 @@ declare module '@theme-original/*';
|
|||
declare module '@docusaurus/*';
|
||||
|
||||
declare module '@docusaurus/Head' {
|
||||
const helmet: typeof import('react-helmet').Helmet;
|
||||
export default helmet;
|
||||
import type {HelmetProps} from 'react-helmet';
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
export type HeadProps = HelmetProps & {children: ReactNode};
|
||||
|
||||
const Head: (props: HeadProps) => JSX.Element;
|
||||
export default Head;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/Link' {
|
||||
import type {ReactNode} from 'react';
|
||||
|
||||
type RRLinkProps = Partial<import('react-router-dom').LinkProps>;
|
||||
type LinkProps = RRLinkProps & {
|
||||
to?: string;
|
||||
activeClassName?: string;
|
||||
isNavLink?: boolean;
|
||||
export type LinkProps = RRLinkProps & {
|
||||
readonly isNavLink?: boolean;
|
||||
readonly to?: string;
|
||||
readonly href?: string;
|
||||
readonly activeClassName?: string;
|
||||
readonly children?: ReactNode;
|
||||
readonly isActive?: (match: any, location: any) => boolean;
|
||||
readonly autoAddBaseUrl?: boolean;
|
||||
|
||||
// escape hatch in case broken links check is annoying for a specific link
|
||||
readonly 'data-noBrokenLinkCheck'?: boolean;
|
||||
};
|
||||
const Link: (props: LinkProps) => JSX.Element;
|
||||
export default Link;
|
||||
|
@ -125,31 +139,33 @@ declare module '@docusaurus/Translate' {
|
|||
InterpolateValues,
|
||||
} from '@docusaurus/Interpolate';
|
||||
|
||||
type TranslateProps<Str extends string> = InterpolateProps<Str> & {
|
||||
export type TranslateParam<Str extends string> = Partial<
|
||||
InterpolateProps<Str>
|
||||
> & {
|
||||
message: Str;
|
||||
id?: string;
|
||||
description?: string;
|
||||
values?: InterpolateValues<Str, string | number>;
|
||||
};
|
||||
|
||||
export function translate<Str extends string>(
|
||||
param: TranslateParam<Str>,
|
||||
values?: InterpolateValues<Str, string | number>,
|
||||
): string;
|
||||
|
||||
export type TranslateProps<Str extends string> = InterpolateProps<Str> & {
|
||||
id?: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export default function Translate<Str extends string>(
|
||||
props: TranslateProps<Str>,
|
||||
): JSX.Element;
|
||||
|
||||
export function translate<Str extends string>(
|
||||
param: {
|
||||
message: Str;
|
||||
id?: string;
|
||||
description?: string;
|
||||
},
|
||||
values?: InterpolateValues<Str, string | number>,
|
||||
): string;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/router' {
|
||||
export const Redirect: (props: {to: string}) => import('react').Component;
|
||||
export function matchPath(
|
||||
pathname: string,
|
||||
opts: {path?: string; exact?: boolean; strict?: boolean},
|
||||
): boolean;
|
||||
export function useLocation(): Location;
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
export * from 'react-router-dom';
|
||||
}
|
||||
|
||||
declare module '@docusaurus/useDocusaurusContext' {
|
||||
|
@ -157,9 +173,20 @@ declare module '@docusaurus/useDocusaurusContext' {
|
|||
}
|
||||
|
||||
declare module '@docusaurus/useBaseUrl' {
|
||||
export type BaseUrlOptions = {
|
||||
forcePrependBaseUrl?: boolean;
|
||||
absolute?: boolean;
|
||||
};
|
||||
|
||||
export type BaseUrlUtils = {
|
||||
withBaseUrl: (url: string, options?: BaseUrlOptions) => string;
|
||||
};
|
||||
|
||||
export function useBaseUrlUtils(): BaseUrlUtils;
|
||||
|
||||
export default function useBaseUrl(
|
||||
relativePath: string | undefined,
|
||||
opts?: {absolute?: true; forcePrependBaseUrl?: true},
|
||||
opts?: BaseUrlOptions,
|
||||
): string;
|
||||
}
|
||||
|
||||
|
@ -173,6 +200,16 @@ declare module '@docusaurus/ExecutionEnvironment' {
|
|||
export default ExecutionEnvironment;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/ComponentCreator' {
|
||||
import type Loadable from 'react-loadable';
|
||||
|
||||
function ComponentCreator(
|
||||
path: string,
|
||||
hash: string,
|
||||
): ReturnType<typeof Loadable>;
|
||||
export default ComponentCreator;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/BrowserOnly' {
|
||||
export type Props = {
|
||||
children?: () => JSX.Element;
|
||||
|
@ -187,6 +224,31 @@ declare module '@docusaurus/isInternalUrl' {
|
|||
export default function isInternalUrl(url?: string): boolean;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/Noop' {
|
||||
export default function (): null;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/renderRoutes' {
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import {renderRoutes} from 'react-router-config';
|
||||
|
||||
export default renderRoutes;
|
||||
}
|
||||
|
||||
declare module '@docusaurus/useGlobalData' {
|
||||
export function useAllPluginInstancesData<T = unknown>(
|
||||
pluginName: string,
|
||||
): Record<string, T>;
|
||||
|
||||
export function usePluginData<T = unknown>(
|
||||
pluginName: string,
|
||||
pluginId?: string,
|
||||
): T;
|
||||
|
||||
function useGlobalData(): Record<string, any>;
|
||||
export default useGlobalData;
|
||||
}
|
||||
|
||||
declare module '*.module.css' {
|
||||
const classes: {readonly [key: string]: string};
|
||||
export default classes;
|
||||
|
|
|
@ -100,7 +100,7 @@ declare module '@theme/DocPage' {
|
|||
readonly route: {
|
||||
readonly path: string;
|
||||
readonly component: () => JSX.Element;
|
||||
readonly routes: readonly DocumentRoute[];
|
||||
readonly routes: DocumentRoute[];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -259,7 +259,9 @@ declare module '@theme/Layout' {
|
|||
}
|
||||
|
||||
declare module '@theme/LayoutHead' {
|
||||
import type {Props} from '@theme/Layout';
|
||||
import type {Props as LayoutProps} from '@theme/Layout';
|
||||
|
||||
export type Props = Omit<LayoutProps, 'children'>;
|
||||
|
||||
const LayoutHead: (props: Props) => JSX.Element;
|
||||
export default LayoutHead;
|
||||
|
|
|
@ -12,6 +12,8 @@ import routesChunkNames from '@generated/routesChunkNames';
|
|||
import registry from '@generated/registry';
|
||||
import flat from '../flat';
|
||||
|
||||
type OptsLoader = Record<string, typeof registry[keyof typeof registry][0]>;
|
||||
|
||||
function ComponentCreator(
|
||||
path: string,
|
||||
hash: string,
|
||||
|
@ -28,7 +30,7 @@ function ComponentCreator(
|
|||
const chunkNames = routesChunkNames[chunkNamesKey];
|
||||
const optsModules: string[] = [];
|
||||
const optsWebpack: string[] = [];
|
||||
const optsLoader = {};
|
||||
const optsLoader: OptsLoader = {};
|
||||
|
||||
/* Prepare opts data that react-loadable needs
|
||||
https://github.com/jamiebuilds/react-loadable#declaring-which-modules-are-being-loaded
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {ReactNode} from 'react';
|
||||
import {Helmet, HelmetProps} from 'react-helmet';
|
||||
|
||||
type HeadProps = HelmetProps & {children: ReactNode};
|
||||
import React from 'react';
|
||||
import {Helmet} from 'react-helmet';
|
||||
import type {HeadProps} from '@docusaurus/Head';
|
||||
|
||||
function Head(props: HeadProps): JSX.Element {
|
||||
return <Helmet {...props} />;
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
*/
|
||||
|
||||
import React, {ReactNode} from 'react';
|
||||
import type {
|
||||
InterpolateProps,
|
||||
InterpolateValues,
|
||||
ExtractInterpolatePlaceholders,
|
||||
} from '@docusaurus/Interpolate';
|
||||
|
||||
/*
|
||||
Minimal implementation of a React interpolate component.
|
||||
|
@ -16,16 +21,6 @@ More details here: https://github.com/facebook/docusaurus/pull/4295
|
|||
const ValueRegexp = /{\w+}/g;
|
||||
const ValueFoundMarker = '{}'; // does not care much
|
||||
|
||||
// TODO use TS template literal feature to make values typesafe!
|
||||
// (requires upgrading TS first)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type ExtractInterpolatePlaceholders<Str extends string> = string;
|
||||
|
||||
type InterpolateValues<Str extends string, Value extends ReactNode> = Record<
|
||||
ExtractInterpolatePlaceholders<Str>,
|
||||
Value
|
||||
>;
|
||||
|
||||
// TS function overload: if all the values are plain strings, then interpolate returns a simple string
|
||||
export function interpolate<Str extends string>(
|
||||
text: Str,
|
||||
|
@ -93,11 +88,6 @@ export function interpolate<Str extends string, Value extends ReactNode>(
|
|||
}
|
||||
}
|
||||
|
||||
export type InterpolateProps<Str extends string> = {
|
||||
children: Str;
|
||||
values?: InterpolateValues<Str, ReactNode>;
|
||||
};
|
||||
|
||||
export default function Interpolate<Str extends string>({
|
||||
children,
|
||||
values,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {ReactNode, useEffect, useRef} from 'react';
|
||||
import React, {useEffect, useRef} from 'react';
|
||||
|
||||
import {NavLink, Link as RRLink} from 'react-router-dom';
|
||||
import isInternalUrl from './isInternalUrl';
|
||||
|
@ -13,28 +13,15 @@ import ExecutionEnvironment from './ExecutionEnvironment';
|
|||
import {useLinksCollector} from '../LinksCollector';
|
||||
import {useBaseUrlUtils} from './useBaseUrl';
|
||||
|
||||
import type {LinkProps} from '@docusaurus/Link';
|
||||
import type docusaurus from '../docusaurus';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
docusaurus: {
|
||||
prefetch: (routePath: string) => boolean;
|
||||
preload: (routePath: string) => boolean;
|
||||
};
|
||||
docusaurus: typeof docusaurus;
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
readonly isNavLink?: boolean;
|
||||
readonly to?: string;
|
||||
readonly href?: string;
|
||||
readonly activeClassName?: string;
|
||||
readonly children?: ReactNode;
|
||||
readonly isActive?: () => boolean;
|
||||
readonly autoAddBaseUrl?: boolean;
|
||||
|
||||
// escape hatch in case broken links check is annoying for a specific link
|
||||
readonly 'data-noBrokenLinkCheck'?: boolean;
|
||||
}
|
||||
|
||||
// TODO all this wouldn't be necessary if we used ReactRouter basename feature
|
||||
// We don't automatically add base urls to all links,
|
||||
// only the "safe" ones, starting with / (like /docs/introduction)
|
||||
|
@ -51,7 +38,7 @@ function Link({
|
|||
'data-noBrokenLinkCheck': noBrokenLinkCheck,
|
||||
autoAddBaseUrl = true,
|
||||
...props
|
||||
}: Props): JSX.Element {
|
||||
}: LinkProps): JSX.Element {
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const linksCollector = useLinksCollector();
|
||||
|
||||
|
@ -92,8 +79,8 @@ function Link({
|
|||
|
||||
const IOSupported = ExecutionEnvironment.canUseIntersectionObserver;
|
||||
|
||||
let io;
|
||||
const handleIntersection = (el, cb) => {
|
||||
let io: IntersectionObserver;
|
||||
const handleIntersection = (el: HTMLAnchorElement, cb: () => void) => {
|
||||
io = new window.IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (el === entry.target) {
|
||||
|
@ -112,7 +99,7 @@ function Link({
|
|||
io.observe(el);
|
||||
};
|
||||
|
||||
const handleRef = (ref) => {
|
||||
const handleRef = (ref: HTMLAnchorElement | null) => {
|
||||
if (IOSupported && ref && isInternal) {
|
||||
// If IO supported and element reference found, setup Observer functionality.
|
||||
handleIntersection(ref, () => {
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
import React from 'react';
|
||||
import Interpolate, {
|
||||
interpolate,
|
||||
InterpolateProps,
|
||||
InterpolateValues,
|
||||
} from '@docusaurus/Interpolate';
|
||||
import type {TranslateParam, TranslateProps} from '@docusaurus/Translate';
|
||||
|
||||
// Can't read it from context, due to exposing imperative API
|
||||
import codeTranslations from '@generated/codeTranslations';
|
||||
|
@ -25,12 +25,6 @@ function getLocalizedMessage({
|
|||
return codeTranslations[id ?? message] ?? message;
|
||||
}
|
||||
|
||||
export type TranslateParam<Str extends string> = {
|
||||
message: Str;
|
||||
id?: string;
|
||||
description?: string;
|
||||
values?: InterpolateValues<Str, string | number>;
|
||||
};
|
||||
// Imperative translation API is useful for some edge-cases:
|
||||
// - translating page titles (meta)
|
||||
// - translating string props (input placeholders, image alt, aria labels...)
|
||||
|
@ -42,11 +36,6 @@ export function translate<Str extends string>(
|
|||
return interpolate(localizedMessage, values);
|
||||
}
|
||||
|
||||
export type TranslateProps<Str extends string> = InterpolateProps<Str> & {
|
||||
id?: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
// Maybe we'll want to improve this component with additional features
|
||||
// Like toggling a translation mode that adds a little translation button near the text?
|
||||
export default function Translate<Str extends string>({
|
||||
|
|
|
@ -7,11 +7,7 @@
|
|||
|
||||
import useDocusaurusContext from './useDocusaurusContext';
|
||||
import {hasProtocol} from './isInternalUrl';
|
||||
|
||||
type BaseUrlOptions = Partial<{
|
||||
forcePrependBaseUrl: boolean;
|
||||
absolute: boolean;
|
||||
}>;
|
||||
import type {BaseUrlOptions, BaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
|
||||
function addBaseUrl(
|
||||
siteUrl: string | undefined,
|
||||
|
@ -45,10 +41,6 @@ function addBaseUrl(
|
|||
return absolute ? siteUrl + basePath : basePath;
|
||||
}
|
||||
|
||||
export type BaseUrlUtils = {
|
||||
withBaseUrl: (url: string, options?: BaseUrlOptions) => string;
|
||||
};
|
||||
|
||||
export function useBaseUrlUtils(): BaseUrlUtils {
|
||||
const {
|
||||
siteConfig: {baseUrl = '/', url: siteUrl} = {},
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -3629,18 +3629,18 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-loadable@^5.5.3":
|
||||
version "5.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-loadable/-/react-loadable-5.5.3.tgz#65d50a6f9f7ff62513010bd6a460ed60ba58ca7d"
|
||||
integrity sha512-BRzQhbMo5CjfxFU2tmmBNh16QqKUwNiaX0vflCwIVPVG8g/pCOyJ3rOdSPo4m+TPS7C9q/TupaqYXXTMtFoyng==
|
||||
"@types/react-loadable@*", "@types/react-loadable@^5.5.3":
|
||||
version "5.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-loadable/-/react-loadable-5.5.4.tgz#9bfb31e1299e9a3b23ea6cae437fa8813afde544"
|
||||
integrity sha512-otKcjNCfVUzdBMdwOqFITTmBruIXw6GeoZitTBvJ6BMrif8Utu2JLy42GWukNnYI7ewJdncUCooz5Y/1dBz4+w==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
"@types/webpack" "*"
|
||||
|
||||
"@types/react-router-config@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.1.tgz#54da8418190ee47484dee279975e2b8038fb8b5d"
|
||||
integrity sha512-D4srFL4XP21GjWWnM7mL8j+Nrrw13pc2TYr57WTHJxU9YTxnrXL7p1iqGtwecgwhyeXJSm4WrGwq0SOgSALVbA==
|
||||
"@types/react-router-config@*", "@types/react-router-config@^5.0.1":
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.2.tgz#4d3b52e71ed363a1976a12321e67b09a99ad6d10"
|
||||
integrity sha512-WOSetDV3YPxbkVJAdv/bqExJjmcdCi/vpCJh3NfQOy1X15vHMSiMioXIcGekXDJJYhqGUMDo9e337mh508foAA==
|
||||
dependencies:
|
||||
"@types/history" "*"
|
||||
"@types/react" "*"
|
||||
|
|
Loading…
Add table
Reference in a new issue