yufan.me/plugins/images.ts

60 lines
2.0 KiB
TypeScript
Raw Normal View History

2024-06-14 02:11:26 +08:00
import type { Literal, Node, Parent } from 'unist';
2024-06-21 04:17:36 +08:00
import { selectAll } from 'unist-util-select';
import options from '../options';
2024-06-14 02:11:26 +08:00
import { imageMetadata } from '../src/helpers/images';
2024-06-21 04:17:36 +08:00
import { urlJoin } from '../src/helpers/tools';
2024-06-14 02:11:26 +08:00
2024-06-21 04:17:36 +08:00
type ImageNode = Parent & {
2024-06-14 02:11:26 +08:00
url: string;
alt: string;
name: string;
width?: number;
height?: number;
attributes: (Literal & { name: string })[];
};
export const astroImage = () => {
return async (tree: Node) => {
2024-06-21 04:17:36 +08:00
// Find all the image node.
const imageNodes = selectAll('image', tree)
.map((node) => node as ImageNode)
.filter((imageNode) => !imageNode.url.startsWith('http'))
.map(transformAstroImage);
2024-06-14 02:11:26 +08:00
2024-06-21 04:17:36 +08:00
// Process image with blur metadata.
await Promise.all(imageNodes);
2024-06-14 02:11:26 +08:00
return tree;
};
};
const transformAstroImage = async (imageNode: ImageNode) => {
imageNode.type = 'mdxJsxFlowElement';
imageNode.name = 'Image';
2024-06-21 04:17:36 +08:00
try {
const metadata = await imageMetadata(imageNode.url);
if (metadata == null) {
throw new Error(`Failed to get image metadata: ${imageNode.url}`);
}
imageNode.attributes = [
{ type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt },
{ type: 'mdxJsxAttribute', name: 'src', value: metadata.src },
{ type: 'mdxJsxAttribute', name: 'width', value: imageNode.width ?? metadata.width },
{ type: 'mdxJsxAttribute', name: 'height', value: imageNode.height ?? metadata.height },
{ type: 'mdxJsxAttribute', name: 'blurDataURL', value: metadata.blurDataURL },
{ type: 'mdxJsxAttribute', name: 'blurWidth', value: metadata.blurWidth },
{ type: 'mdxJsxAttribute', name: 'blurHeight', value: metadata.blurHeight },
];
} catch (error) {
imageNode.attributes = [
{ type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt },
{
type: 'mdxJsxAttribute',
name: 'src',
value: imageNode.url.startsWith('/') ? urlJoin(options.assetsPrefix(), imageNode.url) : imageNode.url,
},
];
}
2024-06-14 02:11:26 +08:00
};