Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(plugin-ideal-image): migrate package to TS #5940

Merged
merged 2 commits into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},
});
7 changes: 5 additions & 2 deletions packages/docusaurus-plugin-ideal-image/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
"main": "lib/index.js",
"types": "src/plugin-ideal-image.d.ts",
"scripts": {
"build": "tsc && node copyUntypedFiles.js",
"watch": "node copyUntypedFiles.js && tsc --watch"
"build": "yarn build:server && yarn build:browser && yarn build:copy && yarn build:prettier",
"build:server": "tsc --project tsconfig.server.json",
"build:browser": "tsc --project tsconfig.browser.json",
"build:copy": "node copyUntypedFiles.js",
"build:prettier": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
},
"publishConfig": {
"access": "public"
Expand Down
95 changes: 94 additions & 1 deletion packages/docusaurus-plugin-ideal-image/src/deps.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,97 @@
* LICENSE file in the root directory of this source tree.
*/

declare module '@endiliey/react-ideal-image';
/**
* @see https://github.com/endiliey/react-ideal-image/blob/master/index.d.ts
*/
declare module '@endiliey/react-ideal-image' {
export type LoadingState = 'initial' | 'loading' | 'loaded' | 'error';

export type IconKey =
| 'load'
| 'loading'
| 'loaded'
| 'error'
| 'noicon'
| 'offline';

export interface SrcType {
width: number;
src?: string;
size?: number;
format?: 'webp' | 'jpeg' | 'png' | 'gif';
}

type ThemeKey = 'placeholder' | 'img' | 'icon' | 'noscript';

export interface ImageProps {
/**
* This function decides what icon to show based on the current state of the component.
*/
getIcon?: (state: LoadingState) => IconKey;
/**
* This function decides what message to show based on the icon (returned from getIcon prop) and
* the current state of the component.
*/
getMessage?: (icon: IconKey, state: LoadingState) => string;
/**
* This function is called as soon as the component enters the viewport and is used to generate urls
* based on width and format if props.srcSet doesn't provide src field.
*/
getUrl?: (srcType: SrcType) => string;
/**
* The Height of the image in px.
*/
height: number;
/**
* This provides a map of the icons. By default, the component uses icons from material design,
* implemented as React components with the SVG element. You can customize icons
*/
icons: Partial<Record<IconKey, ComponentType>>;
/**
* This prop takes one of the 2 options, xhr and image.
* Read more about it:
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#cancel-download
*/
loader?: 'xhr' | 'image';
/**
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#lqip
*/
placeholder: {color: string} | {lqip: string};
/**
* This function decides if image should be downloaded automatically. The default function
* returns false for a 2g network, for a 3g network it decides based on props.threshold
* and for a 4g network it returns true by default.
*/
shouldAutoDownload?: (options: {
connection?: 'slow-2g' | '2g' | '3g' | '4g';
size?: number;
threshold?: number;
possiblySlowNetwork?: boolean;
}) => boolean;
/**
* This provides an array of sources of different format and size of the image.
* Read more about it:
* https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md#srcset
*/
srcSet: SrcType[];
/**
* This provides a theme to the component. By default, the component uses inline styles,
* but it is also possible to use CSS modules and override all styles.
*/
theme?: Partial<Record<ThemeKey, string | CSSProperties>>;
/**
* Tells how much to wait in milliseconds until consider the download to be slow.
*/
threshold?: number;
/**
* Width of the image in px.
*/
width: number;
}

type IdealImageComponent = ComponentClass<ImageProps>;

declare const IdealImage: IdealImageComponent;
export default IdealImage;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,23 @@ declare module '@docusaurus/plugin-ideal-image' {
declare module '@theme/IdealImage' {
import type {ComponentProps} from 'react';

export interface Props extends ComponentProps<'img'> {
img: any;
}
export type SrcType = {
width: number;
path?: string;
size?: number;
format?: 'webp' | 'jpeg' | 'png' | 'gif';
};

export type SrcImage = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering we don't even document those props anywhere, I'd suggest constraining the API to only what we document and not what is actually possible to pass.

Keeping a small API surface is likely to make it easier later to refactor/improve this image component

Copy link
Contributor Author

@armano2 armano2 Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure what do you think we should expose in here, i actually limited it already to only what is supported by plugin

theoretically user can provide anything what is present in
https://github.com/endiliey/react-ideal-image/blob/de4e8f0388ac3645d3f32355c79c3b6a7cc61ff3/index.d.ts#L22-L88

unless you want me to roll-it back to img: any; i don't see what i should do here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, I think you are right, let's move on

the thing is, this plugin's prop is not really supposed to be crafted manually but should rather be obtained by an import/require + image loader so 🤷‍♂️ not sure how to enforce that

height?: number;
width?: number;
preSrc: string;
src: string;
images: SrcType[];
};

export type Props = ComponentProps<'img'> & {
img: {default: string} | {src: SrcImage; preSrc: string} | string;
};
export default function IdealImage(props: Props): JSX.Element;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
*/

import React from 'react';
import IdealImage from '@endiliey/react-ideal-image';
import ReactIdealImage from '@endiliey/react-ideal-image';

function Image(props) {
import type {Props} from '@theme/IdealImage';

function IdealImage(props: Props): JSX.Element {
const {alt, className, img} = props;

// In dev env just use regular img with original file
if (typeof img === 'string' || typeof img.default === 'string') {
if (typeof img === 'string' || 'default' in img) {
return (
<img
src={img?.default ?? img}
src={typeof img === 'string' ? img : img.default}
className={className}
alt={alt}
{...props}
Expand All @@ -24,7 +26,7 @@ function Image(props) {
}

return (
<IdealImage
<ReactIdealImage
{...props}
alt={alt}
className={className}
Expand All @@ -40,4 +42,4 @@ function Image(props) {
);
}

export default Image;
export default IdealImage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext",
"jsx": "react-native"
},
"include": ["src/theme/", "src/*.d.ts"]
}
4 changes: 2 additions & 2 deletions packages/docusaurus-plugin-ideal-image/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"lib": ["DOM", "ES2019"],
"rootDir": "src",
"baseUrl": "src",
"outDir": "lib"
}
}
4 changes: 4 additions & 0 deletions packages/docusaurus-plugin-ideal-image/tsconfig.server.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["src/*.ts"]
}