diff --git a/src/index.ts b/src/index.ts index 32bbdb7..4e8c746 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,60 +1,22 @@ import path from 'node:path' import type { LoadContext, Plugin, OptionValidationContext } from '@docusaurus/types' -import type { ComponentProps } from 'react' -import { - DEFAULT_LOADER_OPTIONS, - type OutputDataForFormat, - type SupportedOutputMimeTypes, - type SupportedOutputTypes, -} from './loader.js' +import { DEFAULT_LOADER_OPTIONS, type LoaderOptions } from './loader.js' // import { Compilation, Compiler, NormalModule, type LoaderContext } from 'webpack' // import { fileURLToPath } from 'node:url' -export type Preset = { - sizes?: number | number[] - formats?: SupportedOutputTypes | SupportedOutputTypes[] - lqip?: boolean -} - -export type LoaderOptions = { - /** - * File name template for output files - */ - fileNameTemplate: string - /** - * Image loader presets - */ - presets: Record - /** - * Low quality image placeholder format - */ - lqipFormat: SupportedOutputTypes - /** - * Disable in dev mode for faster compile time - */ - disableInDev: boolean -} +export type { NativeIdealImageProps } from './theme/NativeIdealImage.js' +export type { + LoaderOutput, + DEFAULT_LOADER_OPTIONS, + SrcSetData, + SupportedOutputMimeTypes, + SupportedOutputTypes, + OutputDataForFormat, + LoaderOptions, + Preset, +} from './loader.js' export type NativeIdealImageOptions = Partial -export type LoaderOutput = { - formats: OutputDataForFormat[] - // src: { - // fileName: string - // width: number - // height: number - // } - lqip?: string -} - -export type NativeIdealImageProps = Omit, 'ref'> & { - readonly img: { default: string | LoaderOutput } | string | LoaderOutput - /** - * Swap (fade in) the actual image after it's fully loaded, - * requires JavaScript to work, so this might cause the image to load a bit slower - * */ - swapOnLoad?: boolean -} - export default function pluginNativeIdealImage( context: LoadContext, options: NativeIdealImageOptions diff --git a/src/loader.ts b/src/loader.ts index 5c1fc39..32f0416 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -1,8 +1,7 @@ import type { LoaderContext } from 'webpack' import { readFile } from 'node:fs/promises' -import sharp from 'sharp' import loaderUtils from 'loader-utils' -import { type LoaderOutput, type LoaderOptions } from './index.js' +import sharp from 'sharp' const MIMES = { jpeg: 'image/jpeg', @@ -24,6 +23,41 @@ export type OutputDataForFormat = { srcSet: SrcSetData[] } +export type Preset = { + sizes?: number | number[] + formats?: SupportedOutputTypes | SupportedOutputTypes[] + lqip?: boolean +} + +export type LoaderOptions = { + /** + * File name template for output files + */ + fileNameTemplate: string + /** + * Image loader presets + */ + presets: Record + /** + * Low quality image placeholder format + */ + lqipFormat: SupportedOutputTypes + /** + * Disable in dev mode for faster compile time + */ + disableInDev: boolean +} + +export type LoaderOutput = { + formats: OutputDataForFormat[] + // src: { + // fileName: string + // width: number + // height: number + // } + lqip?: string +} + export const DEFAULT_LOADER_OPTIONS = { fileNameTemplate: 'assets/native-ideal-image/[name]-[hash:hex:5]-[width].[format]', lqipFormat: 'webp', diff --git a/src/theme/NativeIdealImage.tsx b/src/theme/NativeIdealImage.tsx index d57ee70..7d9b5f0 100644 --- a/src/theme/NativeIdealImage.tsx +++ b/src/theme/NativeIdealImage.tsx @@ -1,9 +1,19 @@ -import React, { useEffect, useRef, useState } from 'react' +import React, { useEffect, useRef, useState, type ComponentProps } from 'react' import clsx from 'clsx' -import type { NativeIdealImageProps } from '../index.js' +import type { LoaderOutput } from '../index.js' +import type { SrcSetData } from '../loader.js' import './NativeIdealImage.css' +export type NativeIdealImageProps = Omit, 'ref'> & { + readonly img: { default: string | LoaderOutput } | string | LoaderOutput + /** + * Swap (fade in) the actual image after it's fully loaded, + * requires JavaScript to work, so this might cause the image to load a bit slower + * */ + swapOnLoad?: boolean +} + // This is kinda messy handling all those posibilities at a single place >.< export default function NativeIdealImage(props: NativeIdealImageProps): JSX.Element { const { img, swapOnLoad, src, srcSet, width, height, sizes, loading, ...propsRest } = props @@ -47,25 +57,15 @@ export default function NativeIdealImage(props: NativeIdealImageProps): JSX.Elem onLoad={() => setLoaded(true)} > {sources?.map((format) => ( - `${encodeURI(image.path)} ${image.width}w`).join(',') - } - type={format.mime} - key={format.mime} - /> + ))} `${encodeURI(image.path)} ${image.width}w`) - .join(',') + ? getSource(lastFormat!.srcSet) : undefined : undefined } @@ -80,3 +80,10 @@ export default function NativeIdealImage(props: NativeIdealImageProps): JSX.Elem ) } + +function getSource(srcSet: SrcSetData[]) { + if (srcSet.length === 1) { + return encodeURI(srcSet[0]!.path) + } + return srcSet.map((image) => `${encodeURI(image.path)} ${image.width}w`).join(',') +}