summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src/rehype-images.ts
blob: f94960ba0b74f2cfa74daf73a38dd4ba02ec2950 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import sizeOf from 'image-size';
import { join as pathJoin } from 'node:path';
import { fileURLToPath } from 'node:url';
import { visit } from 'unist-util-visit';
import { pathToFileURL } from 'url';
import type { MarkdownVFile } from './types.js';

export function rehypeImages(imageService: any, assetsDir: URL | undefined) {
	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));
						}

						const fileData = sizeOf(fileURLToPath(fileURL));
						fileURL.searchParams.append('origWidth', fileData.width!.toString());
						fileURL.searchParams.append('origHeight', fileData.height!.toString());
						fileURL.searchParams.append('origFormat', fileData.type!.toString());

						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 === '/';
}