Skip to content

Commit ac1df88

Browse files
authored
refactor(plugin-ideal-image): migrate package to TS (#5940)
1 parent 3bf59a6 commit ac1df88

7 files changed

Lines changed: 139 additions & 14 deletions

File tree

packages/docusaurus-plugin-ideal-image/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
"main": "lib/index.js",
66
"types": "src/plugin-ideal-image.d.ts",
77
"scripts": {
8-
"build": "tsc && node copyUntypedFiles.js",
9-
"watch": "node copyUntypedFiles.js && tsc --watch"
8+
"build": "yarn build:server && yarn build:browser && yarn build:copy && yarn build:prettier",
9+
"build:server": "tsc --project tsconfig.server.json",
10+
"build:browser": "tsc --project tsconfig.browser.json",
11+
"build:copy": "node copyUntypedFiles.js",
12+
"build:prettier": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
1013
},
1114
"publishConfig": {
1215
"access": "public"

packages/docusaurus-plugin-ideal-image/src/deps.d.ts

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,97 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
declare module '@endiliey/react-ideal-image';
8+
/**
9+
* @see https://github.com/endiliey/react-ideal-image/blob/master/index.d.ts
10+
*/
11+
declare module '@endiliey/react-ideal-image' {
12+
export type LoadingState = 'initial' | 'loading' | 'loaded' | 'error';
13+
14+
export type IconKey =
15+
| 'load'
16+
| 'loading'
17+
| 'loaded'
18+
| 'error'
19+
| 'noicon'
20+
| 'offline';
21+
22+
export interface SrcType {
23+
width: number;
24+
src?: string;
25+
size?: number;
26+
format?: 'webp' | 'jpeg' | 'png' | 'gif';
27+
}
28+
29+
type ThemeKey = 'placeholder' | 'img' | 'icon' | 'noscript';
30+
31+
export interface ImageProps {
32+
/**
33+
* This function decides what icon to show based on the current state of the component.
34+
*/
35+
getIcon?: (state: LoadingState) => IconKey;
36+
/**
37+
* This function decides what message to show based on the icon (returned from getIcon prop) and
38+
* the current state of the component.
39+
*/
40+
getMessage?: (icon: IconKey, state: LoadingState) => string;
41+
/**
42+
* This function is called as soon as the component enters the viewport and is used to generate urls
43+
* based on width and format if props.srcSet doesn't provide src field.
44+
*/
45+
getUrl?: (srcType: SrcType) => string;
46+
/**
47+
* The Height of the image in px.
48+
*/
49+
height: number;
50+
/**
51+
* This provides a map of the icons. By default, the component uses icons from material design,
52+
* implemented as React components with the SVG element. You can customize icons
53+
*/
54+
icons: Partial<Record<IconKey, ComponentType>>;
55+
/**
56+
* This prop takes one of the 2 options, xhr and image.
57+
* Read more about it:
58+
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#cancel-download
59+
*/
60+
loader?: 'xhr' | 'image';
61+
/**
62+
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#lqip
63+
*/
64+
placeholder: {color: string} | {lqip: string};
65+
/**
66+
* This function decides if image should be downloaded automatically. The default function
67+
* returns false for a 2g network, for a 3g network it decides based on props.threshold
68+
* and for a 4g network it returns true by default.
69+
*/
70+
shouldAutoDownload?: (options: {
71+
connection?: 'slow-2g' | '2g' | '3g' | '4g';
72+
size?: number;
73+
threshold?: number;
74+
possiblySlowNetwork?: boolean;
75+
}) => boolean;
76+
/**
77+
* This provides an array of sources of different format and size of the image.
78+
* Read more about it:
79+
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#srcset
80+
*/
81+
srcSet: SrcType[];
82+
/**
83+
* This provides a theme to the component. By default, the component uses inline styles,
84+
* but it is also possible to use CSS modules and override all styles.
85+
*/
86+
theme?: Partial<Record<ThemeKey, string | CSSProperties>>;
87+
/**
88+
* Tells how much to wait in milliseconds until consider the download to be slow.
89+
*/
90+
threshold?: number;
91+
/**
92+
* Width of the image in px.
93+
*/
94+
width: number;
95+
}
96+
97+
type IdealImageComponent = ComponentClass<ImageProps>;
98+
99+
declare const IdealImage: IdealImageComponent;
100+
export default IdealImage;
101+
}

packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,23 @@ declare module '@docusaurus/plugin-ideal-image' {
4141
declare module '@theme/IdealImage' {
4242
import type {ComponentProps} from 'react';
4343

44-
export interface Props extends ComponentProps<'img'> {
45-
img: any;
46-
}
44+
export type SrcType = {
45+
width: number;
46+
path?: string;
47+
size?: number;
48+
format?: 'webp' | 'jpeg' | 'png' | 'gif';
49+
};
50+
51+
export type SrcImage = {
52+
height?: number;
53+
width?: number;
54+
preSrc: string;
55+
src: string;
56+
images: SrcType[];
57+
};
58+
59+
export type Props = ComponentProps<'img'> & {
60+
img: {default: string} | {src: SrcImage; preSrc: string} | string;
61+
};
4762
export default function IdealImage(props: Props): JSX.Element;
4863
}

packages/docusaurus-plugin-ideal-image/src/theme/IdealImage.js renamed to packages/docusaurus-plugin-ideal-image/src/theme/IdealImage/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
*/
77

88
import React from 'react';
9-
import IdealImage from '@endiliey/react-ideal-image';
9+
import ReactIdealImage from '@endiliey/react-ideal-image';
1010

11-
function Image(props) {
11+
import type {Props} from '@theme/IdealImage';
12+
13+
function IdealImage(props: Props): JSX.Element {
1214
const {alt, className, img} = props;
1315

1416
// In dev env just use regular img with original file
15-
if (typeof img === 'string' || typeof img.default === 'string') {
17+
if (typeof img === 'string' || 'default' in img) {
1618
return (
1719
<img
18-
src={img?.default ?? img}
20+
src={typeof img === 'string' ? img : img.default}
1921
className={className}
2022
alt={alt}
2123
{...props}
@@ -24,7 +26,7 @@ function Image(props) {
2426
}
2527

2628
return (
27-
<IdealImage
29+
<ReactIdealImage
2830
{...props}
2931
alt={alt}
3032
className={className}
@@ -40,4 +42,4 @@ function Image(props) {
4042
);
4143
}
4244

43-
export default Image;
45+
export default IdealImage;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"module": "esnext",
5+
"jsx": "react-native"
6+
},
7+
"include": ["src/theme/", "src/*.d.ts"]
8+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
4-
"incremental": true,
5-
"tsBuildInfoFile": "./lib/.tsbuildinfo",
4+
"lib": ["DOM", "ES2019"],
65
"rootDir": "src",
6+
"baseUrl": "src",
77
"outDir": "lib"
88
}
99
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": ["src/*.ts"]
4+
}

0 commit comments

Comments
 (0)