diff options
author | 2022-07-27 15:39:05 +0000 | |
---|---|---|
committer | 2022-07-27 15:39:05 +0000 | |
commit | a397b981f5f46dee85e6e00aa39633d018d4b9a2 (patch) | |
tree | 8622069c50ed93364d01d62f2aa9ac664429ed14 /packages/integrations/image/src | |
parent | 55c8aced44a60a664f28de9dabf03ca51897599e (diff) | |
download | astro-a397b981f5f46dee85e6e00aa39633d018d4b9a2.tar.gz astro-a397b981f5f46dee85e6e00aa39633d018d4b9a2.tar.zst astro-a397b981f5f46dee85e6e00aa39633d018d4b9a2.zip |
Fixes type definitions `@astrojs/image` and adds more documentation to the README (#4045)
* WIP: moving to a static .d.ts types file
* fixing named exports for getImage and getPicture
* removing the exports.astro map for now
* WIP: adding readme docs for component attributes
* Adding docs for getImage and getPicture
* leaning fully on TSC to build .d.ts files
* finally found the solution for proper ESM import types
* adding a note to the README for tsconfig updates
* chore: add changesets
* typo
* docs: removing the "Images in Markdown" example
* removing the need for publishing src to NPM
* fix: make type re-export explicit
* updating image module defs to match InputFormat
* using astro syntax highlighting for README code blocks
* nit: missing backtick in README
* make sure Astro component directives aren't recommended twice
Diffstat (limited to 'packages/integrations/image/src')
-rw-r--r-- | packages/integrations/image/src/build/ssg.ts | 2 | ||||
-rw-r--r-- | packages/integrations/image/src/index.ts | 119 | ||||
-rw-r--r-- | packages/integrations/image/src/integration.ts | 93 | ||||
-rw-r--r-- | packages/integrations/image/src/lib/get-image.ts | 8 | ||||
-rw-r--r-- | packages/integrations/image/src/lib/get-picture.ts | 6 | ||||
-rw-r--r-- | packages/integrations/image/src/loaders/index.ts (renamed from packages/integrations/image/src/types.ts) | 44 | ||||
-rw-r--r-- | packages/integrations/image/src/loaders/sharp.ts | 2 | ||||
-rw-r--r-- | packages/integrations/image/src/utils/images.ts | 2 | ||||
-rw-r--r-- | packages/integrations/image/src/utils/metadata.ts | 3 | ||||
-rw-r--r-- | packages/integrations/image/src/utils/paths.ts | 2 | ||||
-rw-r--r-- | packages/integrations/image/src/vite-plugin-astro-image.ts | 10 |
11 files changed, 141 insertions, 150 deletions
diff --git a/packages/integrations/image/src/build/ssg.ts b/packages/integrations/image/src/build/ssg.ts index 78510889c..496905f92 100644 --- a/packages/integrations/image/src/build/ssg.ts +++ b/packages/integrations/image/src/build/ssg.ts @@ -2,7 +2,7 @@ import fs from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { OUTPUT_DIR } from '../constants.js'; -import type { SSRImageService, TransformOptions } from '../types.js'; +import type { SSRImageService, TransformOptions } from '../loaders/index.js'; import { isRemoteImage, loadLocalImage, loadRemoteImage } from '../utils/images.js'; import { ensureDir } from '../utils/paths.js'; diff --git a/packages/integrations/image/src/index.ts b/packages/integrations/image/src/index.ts index 81ef8c6b9..234b1646d 100644 --- a/packages/integrations/image/src/index.ts +++ b/packages/integrations/image/src/index.ts @@ -1,5 +1,116 @@ -import integration from './integration.js'; -export * from './lib/get-image.js'; -export * from './lib/get-picture.js'; +import type { AstroConfig, AstroIntegration } from 'astro'; +import { ssgBuild } from './build/ssg.js'; +import { ssrBuild } from './build/ssr.js'; +import { PKG_NAME, ROUTE_PATTERN } from './constants.js'; +import { ImageService, TransformOptions } from './loaders/index.js'; +import { filenameFormat, propsToFilename } from './utils/paths.js'; +import { createPlugin } from './vite-plugin-astro-image.js'; -export default integration; +export { getImage } from './lib/get-image.js'; +export { getPicture } from './lib/get-picture.js'; +export * from './loaders/index.js'; +export type { ImageMetadata} from './vite-plugin-astro-image.js'; + +interface ImageIntegration { + loader?: ImageService; + addStaticImage?: (transform: TransformOptions) => void; + filenameFormat?: (transform: TransformOptions, searchParams: URLSearchParams) => string; +} + +declare global { + // eslint-disable-next-line no-var + var astroImage: ImageIntegration | undefined; +} + +export interface IntegrationOptions { + /** + * Entry point for the @type {HostedImageService} or @type {LocalImageService} to be used. + */ + serviceEntryPoint?: string; +} + +export default function integration(options: IntegrationOptions = {}): AstroIntegration { + const resolvedOptions = { + serviceEntryPoint: '@astrojs/image/sharp', + ...options, + }; + + // During SSG builds, this is used to track all transformed images required. + const staticImages = new Map<string, Map<string, TransformOptions>>(); + + let _config: AstroConfig; + let output: 'server' | 'static'; + + function getViteConfiguration() { + return { + plugins: [createPlugin(_config, resolvedOptions)], + optimizeDeps: { + include: ['image-size', 'sharp'], + }, + ssr: { + noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint], + }, + }; + } + + return { + name: PKG_NAME, + hooks: { + 'astro:config:setup': ({ command, config, injectRoute, updateConfig }) => { + _config = config; + + // Always treat `astro dev` as SSR mode, even without an adapter + output = command === 'dev' ? 'server' : config.output; + + updateConfig({ vite: getViteConfiguration() }); + + if (output === 'server') { + injectRoute({ + pattern: ROUTE_PATTERN, + entryPoint: + command === 'dev' ? '@astrojs/image/endpoints/dev' : '@astrojs/image/endpoints/prod', + }); + } + }, + 'astro:server:setup': async () => { + globalThis.astroImage = {}; + }, + 'astro:build:setup': () => { + // Used to cache all images rendered to HTML + // Added to globalThis to share the same map in Node and Vite + function addStaticImage(transform: TransformOptions) { + const srcTranforms = staticImages.has(transform.src) + ? staticImages.get(transform.src)! + : new Map<string, TransformOptions>(); + + srcTranforms.set(propsToFilename(transform), transform); + + staticImages.set(transform.src, srcTranforms); + } + + // Helpers for building static images should only be available for SSG + globalThis.astroImage = + output === 'static' + ? { + addStaticImage, + filenameFormat, + } + : {}; + }, + 'astro:build:done': async ({ dir }) => { + if (output === 'server') { + // for SSR builds, copy all image files from src to dist + // to make sure they are available for use in production + await ssrBuild({ srcDir: _config.srcDir, outDir: dir }); + } else { + // for SSG builds, build all requested image transforms to dist + const loader = globalThis?.astroImage?.loader; + + if (loader && 'transform' in loader && staticImages.size > 0) { + await ssgBuild({ loader, staticImages, srcDir: _config.srcDir, outDir: dir }); + } + } + }, + }, + }; +} diff --git a/packages/integrations/image/src/integration.ts b/packages/integrations/image/src/integration.ts deleted file mode 100644 index 725276d03..000000000 --- a/packages/integrations/image/src/integration.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { AstroConfig, AstroIntegration } from 'astro'; -import { ssgBuild } from './build/ssg.js'; -import { ssrBuild } from './build/ssr.js'; -import { PKG_NAME, ROUTE_PATTERN } from './constants.js'; -import { IntegrationOptions, TransformOptions } from './types.js'; -import { filenameFormat, propsToFilename } from './utils/paths.js'; -import { createPlugin } from './vite-plugin-astro-image.js'; - -export default function integration(options: IntegrationOptions = {}): AstroIntegration { - const resolvedOptions = { - serviceEntryPoint: '@astrojs/image/sharp', - ...options, - }; - - // During SSG builds, this is used to track all transformed images required. - const staticImages = new Map<string, Map<string, TransformOptions>>(); - - let _config: AstroConfig; - let output: 'server' | 'static'; - - function getViteConfiguration() { - return { - plugins: [createPlugin(_config, resolvedOptions)], - optimizeDeps: { - include: ['image-size', 'sharp'], - }, - ssr: { - noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint], - }, - }; - } - - return { - name: PKG_NAME, - hooks: { - 'astro:config:setup': ({ command, config, injectRoute, updateConfig }) => { - _config = config; - - // Always treat `astro dev` as SSR mode, even without an adapter - output = command === 'dev' ? 'server' : config.output; - - updateConfig({ vite: getViteConfiguration() }); - - if (output === 'server') { - injectRoute({ - pattern: ROUTE_PATTERN, - entryPoint: - command === 'dev' ? '@astrojs/image/endpoints/dev' : '@astrojs/image/endpoints/prod', - }); - } - }, - 'astro:server:setup': async () => { - globalThis.astroImage = {}; - }, - 'astro:build:setup': () => { - // Used to cache all images rendered to HTML - // Added to globalThis to share the same map in Node and Vite - function addStaticImage(transform: TransformOptions) { - const srcTranforms = staticImages.has(transform.src) - ? staticImages.get(transform.src)! - : new Map<string, TransformOptions>(); - - srcTranforms.set(propsToFilename(transform), transform); - - staticImages.set(transform.src, srcTranforms); - } - - // Helpers for building static images should only be available for SSG - globalThis.astroImage = - output === 'static' - ? { - addStaticImage, - filenameFormat, - } - : {}; - }, - 'astro:build:done': async ({ dir }) => { - if (output === 'server') { - // for SSR builds, copy all image files from src to dist - // to make sure they are available for use in production - await ssrBuild({ srcDir: _config.srcDir, outDir: dir }); - } else { - // for SSG builds, build all requested image transforms to dist - const loader = globalThis?.astroImage?.loader; - - if (loader && 'transform' in loader && staticImages.size > 0) { - await ssgBuild({ loader, staticImages, srcDir: _config.srcDir, outDir: dir }); - } - } - }, - }, - }; -} diff --git a/packages/integrations/image/src/lib/get-image.ts b/packages/integrations/image/src/lib/get-image.ts index e0f57e873..0a28ff3ac 100644 --- a/packages/integrations/image/src/lib/get-image.ts +++ b/packages/integrations/image/src/lib/get-image.ts @@ -1,15 +1,15 @@ +/// <reference types="astro/astro-jsx" /> import slash from 'slash'; import { ROUTE_PATTERN } from '../constants.js'; import sharp from '../loaders/sharp.js'; import { - ImageAttributes, - ImageMetadata, ImageService, isSSRService, OutputFormat, TransformOptions, -} from '../types.js'; +} from '../loaders/index.js'; import { isRemoteImage, parseAspectRatio } from '../utils/images.js'; +import { ImageMetadata } from '../vite-plugin-astro-image.js'; export interface GetImageTransform extends Omit<TransformOptions, 'src'> { src: string | ImageMetadata | Promise<{ default: ImageMetadata }>; @@ -101,7 +101,7 @@ async function resolveTransform(input: GetImageTransform): Promise<TransformOpti * @param transform @type {TransformOptions} The transformations requested for the optimized image. * @returns @type {ImageAttributes} The HTML attributes to be included on the built `<img />` element. */ -export async function getImage(transform: GetImageTransform): Promise<ImageAttributes> { +export async function getImage(transform: GetImageTransform): Promise<astroHTML.JSX.ImgHTMLAttributes> { if (!transform.src) { throw new Error('[@astrojs/image] `src` is required'); } diff --git a/packages/integrations/image/src/lib/get-picture.ts b/packages/integrations/image/src/lib/get-picture.ts index 82bf9f7c5..0b9521853 100644 --- a/packages/integrations/image/src/lib/get-picture.ts +++ b/packages/integrations/image/src/lib/get-picture.ts @@ -1,7 +1,9 @@ +/// <reference types="astro/astro-jsx" /> import { lookup } from 'mrmime'; import { extname } from 'node:path'; -import { ImageAttributes, ImageMetadata, OutputFormat, TransformOptions } from '../types.js'; +import { OutputFormat, TransformOptions } from '../loaders/index.js'; import { parseAspectRatio } from '../utils/images.js'; +import { ImageMetadata } from '../vite-plugin-astro-image.js'; import { getImage } from './get-image.js'; export interface GetPictureParams { @@ -12,7 +14,7 @@ export interface GetPictureParams { } export interface GetPictureResult { - image: ImageAttributes; + image: astroHTML.JSX.HTMLAttributes; sources: { type: string; srcset: string }[]; } diff --git a/packages/integrations/image/src/types.ts b/packages/integrations/image/src/loaders/index.ts index f7e0c0e5f..7681f25d4 100644 --- a/packages/integrations/image/src/types.ts +++ b/packages/integrations/image/src/loaders/index.ts @@ -1,17 +1,4 @@ /// <reference types="astro/astro-jsx" /> -export * from './index.js'; - -interface ImageIntegration { - loader?: ImageService; - addStaticImage?: (transform: TransformOptions) => void; - filenameFormat?: (transform: TransformOptions, searchParams: URLSearchParams) => string; -} - -declare global { - // eslint-disable-next-line no-var - var astroImage: ImageIntegration | undefined; -} - export type InputFormat = | 'heic' | 'heif' @@ -26,21 +13,6 @@ export type InputFormat = export type OutputFormat = 'avif' | 'jpeg' | 'png' | 'webp'; /** - * Converts a set of image transforms to the filename to use when building for static. - * - * This is only used for static production builds and ignored when an SSR adapter is used, - * or in `astro dev` for static builds. - */ -export type FilenameFormatter = (transform: TransformOptions) => string; - -export interface IntegrationOptions { - /** - * Entry point for the @type {HostedImageService} or @type {LocalImageService} to be used. - */ - serviceEntryPoint?: string; -} - -/** * Defines the original image and transforms that need to be applied to it. */ export interface TransformOptions { @@ -83,22 +55,19 @@ export interface TransformOptions { aspectRatio?: number | `${number}:${number}`; } -export type ImageAttributes = astroHTML.JSX.ImgHTMLAttributes; -export type PictureAttributes = astroHTML.JSX.HTMLAttributes; - export interface HostedImageService<T extends TransformOptions = TransformOptions> { /** * Gets the HTML attributes needed for the server rendered `<img />` element. */ - getImageAttributes(transform: T): Promise<ImageAttributes>; + getImageAttributes(transform: T): Promise<astroHTML.JSX.ImgHTMLAttributes>; } export interface SSRImageService<T extends TransformOptions = TransformOptions> extends HostedImageService<T> { /** - * Gets tthe HTML attributes needed for the server rendered `<img />` element. + * Gets the HTML attributes needed for the server rendered `<img />` element. */ - getImageAttributes(transform: T): Promise<Exclude<ImageAttributes, 'src'>>; + getImageAttributes(transform: T): Promise<Exclude<astroHTML.JSX.ImgHTMLAttributes, 'src'>>; /** * Serializes image transformation properties to URLSearchParams, used to build * the final `src` that points to the self-hosted SSR endpoint. @@ -134,10 +103,3 @@ export function isHostedService(service: ImageService): service is ImageService export function isSSRService(service: ImageService): service is SSRImageService { return 'transform' in service; } - -export interface ImageMetadata { - src: string; - width: number; - height: number; - format: InputFormat; -} diff --git a/packages/integrations/image/src/loaders/sharp.ts b/packages/integrations/image/src/loaders/sharp.ts index b4c5e18fd..f76a16d39 100644 --- a/packages/integrations/image/src/loaders/sharp.ts +++ b/packages/integrations/image/src/loaders/sharp.ts @@ -1,5 +1,5 @@ import sharp from 'sharp'; -import type { OutputFormat, SSRImageService, TransformOptions } from '../types.js'; +import type { OutputFormat, SSRImageService, TransformOptions } from './index.js'; import { isAspectRatioString, isOutputFormat } from '../utils/images.js'; class SharpService implements SSRImageService { diff --git a/packages/integrations/image/src/utils/images.ts b/packages/integrations/image/src/utils/images.ts index d36c64fc0..f3c519657 100644 --- a/packages/integrations/image/src/utils/images.ts +++ b/packages/integrations/image/src/utils/images.ts @@ -1,5 +1,5 @@ import fs from 'node:fs/promises'; -import type { OutputFormat, TransformOptions } from '../types.js'; +import type { OutputFormat, TransformOptions } from '../loaders/index.js'; export function isOutputFormat(value: string): value is OutputFormat { return ['avif', 'jpeg', 'png', 'webp'].includes(value); diff --git a/packages/integrations/image/src/utils/metadata.ts b/packages/integrations/image/src/utils/metadata.ts index fa60281b6..349a37535 100644 --- a/packages/integrations/image/src/utils/metadata.ts +++ b/packages/integrations/image/src/utils/metadata.ts @@ -1,6 +1,7 @@ import sizeOf from 'image-size'; import fs from 'node:fs/promises'; -import { ImageMetadata, InputFormat } from '../types.js'; +import { InputFormat } from '../loaders/index.js'; +import { ImageMetadata } from '../vite-plugin-astro-image.js'; export async function metadata(src: string): Promise<ImageMetadata | undefined> { const file = await fs.readFile(src); diff --git a/packages/integrations/image/src/utils/paths.ts b/packages/integrations/image/src/utils/paths.ts index a958d4911..6258d392d 100644 --- a/packages/integrations/image/src/utils/paths.ts +++ b/packages/integrations/image/src/utils/paths.ts @@ -1,7 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { OUTPUT_DIR } from '../constants.js'; -import type { TransformOptions } from '../types.js'; +import type { TransformOptions } from '../loaders/index.js'; import { isRemoteImage } from './images.js'; import { shorthash } from './shorthash.js'; diff --git a/packages/integrations/image/src/vite-plugin-astro-image.ts b/packages/integrations/image/src/vite-plugin-astro-image.ts index 81593c142..aefc910bb 100644 --- a/packages/integrations/image/src/vite-plugin-astro-image.ts +++ b/packages/integrations/image/src/vite-plugin-astro-image.ts @@ -3,9 +3,17 @@ import { pathToFileURL } from 'node:url'; import type { PluginContext } from 'rollup'; import slash from 'slash'; import type { Plugin, ResolvedConfig } from 'vite'; -import type { IntegrationOptions } from './types.js'; +import type { IntegrationOptions } from './index.js'; +import type { InputFormat } from './loaders/index.js'; import { metadata } from './utils/metadata.js'; +export interface ImageMetadata { + src: string; + width: number; + height: number; + format: InputFormat; +} + export function createPlugin(config: AstroConfig, options: Required<IntegrationOptions>): Plugin { const filter = (id: string) => /^(?!\/_image?).*.(heic|heif|avif|jpeg|jpg|png|tiff|webp|gif)$/.test(id); |