2023-03-07 16:12:21 +01:00
|
|
|
import { join as pathJoin } from 'node:path';
|
|
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { visit } from 'unist-util-visit';
|
|
|
|
import { pathToFileURL } from 'url';
|
2023-03-16 15:10:46 +01:00
|
|
|
import type { ImageMetadata, MarkdownVFile } from './types.js';
|
2023-03-07 16:12:21 +01:00
|
|
|
|
2023-03-16 15:10:46 +01:00
|
|
|
export function rehypeImages(imageService: any, assetsDir: URL | undefined, getImageMetadata: any) {
|
2023-03-07 16:12:21 +01:00
|
|
|
return () =>
|
|
|
|
function (tree: any, file: MarkdownVFile) {
|
|
|
|
visit(tree, (node) => {
|
|
|
|
if (!assetsDir) return;
|
|
|
|
if (node.type !== 'element') return;
|
|
|
|
if (node.tagName !== 'img') return;
|
|
|
|
|
|
|
|
if (node.properties?.src) {
|
|
|
|
if (file.dirname) {
|
|
|
|
if (!isRelativePath(node.properties.src) && !isAliasedPath(node.properties.src)) return;
|
|
|
|
|
|
|
|
let fileURL: URL;
|
|
|
|
if (isAliasedPath(node.properties.src)) {
|
|
|
|
fileURL = new URL(stripAliasPath(node.properties.src), assetsDir);
|
|
|
|
} else {
|
|
|
|
fileURL = pathToFileURL(pathJoin(file.dirname, node.properties.src));
|
|
|
|
}
|
|
|
|
|
2023-03-16 15:10:46 +01:00
|
|
|
const fileData = getImageMetadata!(fileURLToPath(fileURL)) as ImageMetadata;
|
|
|
|
fileURL.searchParams.append('origWidth', fileData.width.toString());
|
|
|
|
fileURL.searchParams.append('origHeight', fileData.height.toString());
|
|
|
|
fileURL.searchParams.append('origFormat', fileData.type.toString());
|
2023-03-07 16:12:21 +01:00
|
|
|
|
|
|
|
let options = {
|
|
|
|
src: {
|
|
|
|
src: fileURL,
|
|
|
|
width: fileData.width,
|
|
|
|
height: fileData.height,
|
|
|
|
format: fileData.type,
|
|
|
|
},
|
|
|
|
alt: node.properties.alt,
|
|
|
|
};
|
|
|
|
|
|
|
|
const imageURL = imageService.getURL(options);
|
|
|
|
node.properties = Object.assign(node.properties, {
|
|
|
|
src: imageURL,
|
|
|
|
...(imageService.getHTMLAttributes !== undefined
|
|
|
|
? imageService.getHTMLAttributes(options)
|
|
|
|
: {}),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function isAliasedPath(path: string) {
|
|
|
|
return path.startsWith('~/assets');
|
|
|
|
}
|
|
|
|
|
|
|
|
function stripAliasPath(path: string) {
|
|
|
|
return path.replace('~/assets/', '');
|
|
|
|
}
|
|
|
|
|
|
|
|
function isRelativePath(path: string) {
|
|
|
|
return startsWithDotDotSlash(path) || startsWithDotSlash(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
function startsWithDotDotSlash(path: string) {
|
|
|
|
const c1 = path[0];
|
|
|
|
const c2 = path[1];
|
|
|
|
const c3 = path[2];
|
|
|
|
return c1 === '.' && c2 === '.' && c3 === '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
function startsWithDotSlash(path: string) {
|
|
|
|
const c1 = path[0];
|
|
|
|
const c2 = path[1];
|
|
|
|
return c1 === '.' && c2 === '/';
|
|
|
|
}
|