-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transform.ts
81 lines (64 loc) · 1.9 KB
/
transform.ts
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
79
80
81
/*
* Copyright (C) 2024 Delusoire
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import type { MixinLoader } from "./module.ts";
// @deno-types="./util/fetch.ts"
import { fetchText } from "./util/fetch.js";
const MimeTypes = {
".js": "application/javascript",
".css": "text/css",
} as const;
export class SourceFile {
objectURL?: string;
transforms = new Array<(input: string) => string>();
static SOURCES = new Map<string, SourceFile>();
private constructor(private path: string) { }
static from(path: string) {
return SourceFile.SOURCES.get(path) ?? new SourceFile(path);
}
async getObjectURL() {
if (this.objectURL) return this.objectURL;
const trs = transforms.filter(([glob]) => glob.test(this.path));
if (!trs.length) {
return this.path;
}
const content = await fetchText(this.path);
const modifiedContent = trs.reduce(
(p, [, transform]) => transform(p, this.path),
content!,
);
const ext = this.path.slice(this.path.lastIndexOf("."));
// @ts-ignore
const type: string | undefined = MimeTypes[ext];
if (!type) {
return this.path;
}
const blob = new Blob([modifiedContent], { type });
this.objectURL = URL.createObjectURL(blob);
return this.objectURL;
}
}
export type Thunk<A> = (value: A) => void;
export type MixinProps = {
glob?: RegExp;
wait?: boolean;
};
export type Transformer = ReturnType<typeof createTransformer>;
export const createTransformer = (module: MixinLoader) =>
<A = void>(
transform: (emit: Thunk<A>) => (input: string, path: string) => string,
{ glob = /(?:)/, wait = true }: MixinProps,
) => {
const { promise, resolve } = Promise.withResolvers<A>();
transforms.push([glob, transform(resolve)]);
// @ts-ignore
promise.transform = transform;
if (wait) {
module.awaitedMixins.push(promise as Promise<void>);
}
return promise;
};
export const transforms = new Array<
[RegExp, (input: string, path: string) => string]
>();