2022-07-27 10:39:05 -05:00
|
|
|
import type { AstroConfig, AstroIntegration } from 'astro';
|
2022-08-30 16:09:44 -05:00
|
|
|
import { createPlugin } from './vite-plugin-astro-image.js';
|
2022-07-27 10:39:05 -05:00
|
|
|
import { ssgBuild } from './build/ssg.js';
|
2022-08-30 16:09:44 -05:00
|
|
|
import type { ImageService, TransformOptions } from './loaders/index.js';
|
2022-08-22 14:13:19 -05:00
|
|
|
import type { LoggerLevel } from './utils/logger.js';
|
2022-08-30 16:09:44 -05:00
|
|
|
import { joinPaths, prependForwardSlash, propsToFilename } from './utils/paths.js';
|
2022-07-01 10:47:48 -05:00
|
|
|
|
2022-07-27 10:39:05 -05:00
|
|
|
export { getImage } from './lib/get-image.js';
|
|
|
|
export { getPicture } from './lib/get-picture.js';
|
2022-08-30 16:09:44 -05:00
|
|
|
|
|
|
|
const PKG_NAME = '@astrojs/image';
|
|
|
|
const ROUTE_PATTERN = '/_image';
|
2022-07-27 10:39:05 -05:00
|
|
|
|
|
|
|
interface ImageIntegration {
|
|
|
|
loader?: ImageService;
|
2022-08-30 16:09:44 -05:00
|
|
|
addStaticImage?: (transform: TransformOptions) => string;
|
2022-07-27 10:39:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2022-08-22 14:13:19 -05:00
|
|
|
logLevel?: LoggerLevel;
|
2022-07-27 10:39:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export default function integration(options: IntegrationOptions = {}): AstroIntegration {
|
|
|
|
const resolvedOptions = {
|
|
|
|
serviceEntryPoint: '@astrojs/image/sharp',
|
2022-08-22 14:13:19 -05:00
|
|
|
logLevel: 'info' as LoggerLevel,
|
2022-07-27 10:39:05 -05:00
|
|
|
...options,
|
|
|
|
};
|
|
|
|
|
2022-08-30 16:09:44 -05:00
|
|
|
let _config: AstroConfig;
|
|
|
|
|
2022-07-27 10:39:05 -05:00
|
|
|
// During SSG builds, this is used to track all transformed images required.
|
|
|
|
const staticImages = new Map<string, Map<string, TransformOptions>>();
|
|
|
|
|
|
|
|
function getViteConfiguration() {
|
|
|
|
return {
|
|
|
|
plugins: [createPlugin(_config, resolvedOptions)],
|
|
|
|
optimizeDeps: {
|
|
|
|
include: ['image-size', 'sharp'],
|
|
|
|
},
|
|
|
|
ssr: {
|
|
|
|
noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
name: PKG_NAME,
|
|
|
|
hooks: {
|
2022-08-30 16:09:44 -05:00
|
|
|
'astro:config:setup': ({ command, config, updateConfig, injectRoute }) => {
|
2022-07-27 10:39:05 -05:00
|
|
|
_config = config;
|
|
|
|
|
|
|
|
updateConfig({ vite: getViteConfiguration() });
|
|
|
|
|
2022-08-30 16:09:44 -05:00
|
|
|
if (command === 'dev' || config.output === 'server') {
|
2022-07-27 10:39:05 -05:00
|
|
|
injectRoute({
|
|
|
|
pattern: ROUTE_PATTERN,
|
2022-08-30 16:09:44 -05:00
|
|
|
entryPoint: '@astrojs/image/endpoint',
|
2022-07-27 10:39:05 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'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>();
|
|
|
|
|
2022-08-30 16:09:44 -05:00
|
|
|
const filename = propsToFilename(transform);
|
2022-07-27 10:39:05 -05:00
|
|
|
|
2022-08-30 16:09:44 -05:00
|
|
|
srcTranforms.set(filename, transform);
|
2022-07-27 10:39:05 -05:00
|
|
|
staticImages.set(transform.src, srcTranforms);
|
2022-08-30 16:09:44 -05:00
|
|
|
|
|
|
|
// Prepend the Astro config's base path, if it was used.
|
|
|
|
// Doing this here makes sure that base is ignored when building
|
|
|
|
// staticImages to /dist, but the rendered HTML will include the
|
|
|
|
// base prefix for `src`.
|
|
|
|
return prependForwardSlash(joinPaths(_config.base, filename));
|
2022-07-27 10:39:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helpers for building static images should only be available for SSG
|
|
|
|
globalThis.astroImage =
|
2022-08-30 16:09:44 -05:00
|
|
|
_config.output === 'static'
|
2022-07-27 10:39:05 -05:00
|
|
|
? {
|
|
|
|
addStaticImage,
|
|
|
|
}
|
|
|
|
: {};
|
|
|
|
},
|
|
|
|
'astro:build:done': async ({ dir }) => {
|
2022-08-30 16:09:44 -05:00
|
|
|
if (_config.output === 'static') {
|
2022-07-27 10:39:05 -05:00
|
|
|
// for SSG builds, build all requested image transforms to dist
|
|
|
|
const loader = globalThis?.astroImage?.loader;
|
|
|
|
|
|
|
|
if (loader && 'transform' in loader && staticImages.size > 0) {
|
2022-08-22 14:15:35 -05:00
|
|
|
await ssgBuild({
|
|
|
|
loader,
|
|
|
|
staticImages,
|
2022-08-30 16:09:44 -05:00
|
|
|
config: _config,
|
2022-08-22 14:15:35 -05:00
|
|
|
outDir: dir,
|
|
|
|
logLevel: resolvedOptions.logLevel,
|
|
|
|
});
|
2022-07-27 10:39:05 -05:00
|
|
|
}
|
|
|
|
}
|
2022-08-30 16:09:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-27 10:39:05 -05:00
|
|
|
}
|