2022-07-01 20:06:01 +00:00
|
|
|
import type { AstroConfig } from 'astro';
|
2022-07-25 21:16:11 +00:00
|
|
|
import { pathToFileURL } from 'node:url';
|
2022-07-01 15:47:48 +00:00
|
|
|
import type { PluginContext } from 'rollup';
|
2022-07-01 20:06:01 +00:00
|
|
|
import slash from 'slash';
|
2022-07-01 15:47:48 +00:00
|
|
|
import type { Plugin, ResolvedConfig } from 'vite';
|
2022-07-22 23:01:56 +00:00
|
|
|
import type { IntegrationOptions } from './types.js';
|
2022-07-22 23:04:01 +00:00
|
|
|
import { metadata } from './utils/metadata.js';
|
2022-07-01 15:47:48 +00:00
|
|
|
|
|
|
|
export function createPlugin(config: AstroConfig, options: Required<IntegrationOptions>): Plugin {
|
2022-07-01 17:43:26 +00:00
|
|
|
const filter = (id: string) =>
|
|
|
|
/^(?!\/_image?).*.(heic|heif|avif|jpeg|jpg|png|tiff|webp|gif)$/.test(id);
|
2022-07-01 15:47:48 +00:00
|
|
|
|
|
|
|
const virtualModuleId = 'virtual:image-loader';
|
|
|
|
|
|
|
|
let resolvedConfig: ResolvedConfig;
|
|
|
|
let loaderModuleId: string;
|
|
|
|
|
|
|
|
async function resolveLoader(context: PluginContext) {
|
|
|
|
if (!loaderModuleId) {
|
|
|
|
const module = await context.resolve(options.serviceEntryPoint);
|
|
|
|
if (!module) {
|
|
|
|
throw new Error(`"${options.serviceEntryPoint}" could not be found`);
|
|
|
|
}
|
|
|
|
loaderModuleId = module.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
return loaderModuleId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
name: '@astrojs/image',
|
|
|
|
enforce: 'pre',
|
2022-07-07 21:06:44 +00:00
|
|
|
configResolved(viteConfig) {
|
|
|
|
resolvedConfig = viteConfig;
|
2022-07-01 15:47:48 +00:00
|
|
|
},
|
|
|
|
async resolveId(id) {
|
|
|
|
// The virtual model redirects imports to the ImageService being used
|
|
|
|
// This ensures the module is available in `astro dev` and is included
|
|
|
|
// in the SSR server bundle.
|
|
|
|
if (id === virtualModuleId) {
|
|
|
|
return await resolveLoader(this);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async load(id) {
|
|
|
|
// only claim image ESM imports
|
2022-07-01 17:43:26 +00:00
|
|
|
if (!filter(id)) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-07-01 15:47:48 +00:00
|
|
|
|
|
|
|
const meta = await metadata(id);
|
2022-07-01 17:43:26 +00:00
|
|
|
|
2022-07-01 15:47:48 +00:00
|
|
|
const fileUrl = pathToFileURL(id);
|
|
|
|
const src = resolvedConfig.isProduction
|
|
|
|
? fileUrl.pathname.replace(config.srcDir.pathname, '/')
|
|
|
|
: id;
|
|
|
|
|
|
|
|
const output = {
|
|
|
|
...meta,
|
|
|
|
src: slash(src), // Windows compat
|
|
|
|
};
|
|
|
|
|
|
|
|
return `export default ${JSON.stringify(output)}`;
|
2022-07-22 23:04:01 +00:00
|
|
|
},
|
2022-07-01 15:47:48 +00:00
|
|
|
};
|
|
|
|
}
|