1 | import dataUrls from "data-urls";
|
2 | import fs from "fs";
|
3 | import urlMod from "url";
|
4 | import whatwgEncoding from "whatwg-encoding";
|
5 | import { NullableSourceText } from "./source-map/source-store";
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | export type GetText = (url: Readonly<urlMod.URL>) => Promise<string>;
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | export type GetTextSync = (url: Readonly<urlMod.URL>) => string;
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | export async function getText(url: Readonly<urlMod.URL>): Promise<string> {
|
25 | switch (url.protocol) {
|
26 | case "data:":
|
27 | return getTextByDataUrl(url);
|
28 | case "file:":
|
29 | return getTextByFileUrl(url);
|
30 | default:
|
31 | throw new Error(`UnsupportedProtocol ${url.protocol} for: ${url}`);
|
32 | }
|
33 | }
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | export function getTextSync(url: Readonly<urlMod.URL>): string {
|
40 | switch (url.protocol) {
|
41 | case "data:":
|
42 | return getTextByDataUrl(url);
|
43 | case "file:":
|
44 | return getTextByFileUrlSync(url);
|
45 | default:
|
46 | throw new Error(`UnsupportedProtocol ${url.protocol} for: ${url}`);
|
47 | }
|
48 | }
|
49 |
|
50 | export function getTextByDataUrl(url: Readonly<urlMod.URL>): string {
|
51 | const parsed: dataUrls.DataURL | null = dataUrls(url.toString());
|
52 | if (parsed === null) {
|
53 | throw new Error(`CannotParseDataUrl: ${url}`);
|
54 | }
|
55 | const charset: string | undefined = parsed.mimeType.parameters.get("charset");
|
56 | let encodingName: string | null;
|
57 | if (charset !== undefined) {
|
58 | encodingName = whatwgEncoding.labelToName(charset);
|
59 | } else {
|
60 |
|
61 | encodingName = "UTF-8";
|
62 | }
|
63 | if (encodingName === null) {
|
64 | throw new Error(`Unable to resolve encoding for data URL: ${url}`);
|
65 | }
|
66 | return whatwgEncoding.decode(parsed.body, encodingName);
|
67 | }
|
68 |
|
69 | export async function getTextByFileUrl(url: Readonly<urlMod.URL>): Promise<string> {
|
70 | return fs.promises.readFile(url, {encoding: "UTF-8"}) as Promise<string>;
|
71 | }
|
72 |
|
73 | export function getTextByFileUrlSync(url: Readonly<urlMod.URL>): string {
|
74 | return fs.readFileSync(url, {encoding: "UTF-8"});
|
75 | }
|
76 |
|
77 | export function getTextSyncFromSourceStore(_sources: Iterable<[string, NullableSourceText]>): GetTextSync {
|
78 | const cache: Map<string, NullableSourceText> = new Map();
|
79 | return (url: Readonly<urlMod.URL>): string => {
|
80 | const cached: NullableSourceText | undefined = cache.get(url.toString());
|
81 | if (typeof cached === "string") {
|
82 | return cached;
|
83 | }
|
84 | const sourceText: string = getTextSync(url);
|
85 | cache.set(url.toString(), sourceText);
|
86 | return sourceText;
|
87 | };
|
88 | }
|