UNPKG

2.76 kBPlain TextView Raw
1import dataUrls from "data-urls";
2import fs from "fs";
3import urlMod from "url";
4import whatwgEncoding from "whatwg-encoding";
5import { NullableSourceText } from "./source-map/source-store";
6
7/**
8 * Returns the `string` corresponding to the provided URL record.
9 */
10export type GetText = (url: Readonly<urlMod.URL>) => Promise<string>;
11
12/**
13 * Synchronous variant of `GetText`.
14 */
15export type GetTextSync = (url: Readonly<urlMod.URL>) => string;
16
17// TODO: Find out why TSLint complains about whitespace
18// tslint:disable:whitespace
19/**
20 * Returns the string corresponding to the provided `url`.
21 *
22 * @param url URL for the text content.
23 */
24export 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// tslint:enable
35
36/**
37 * Synchronous variant of `getText`.
38 */
39export 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
50export 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 // Not sure what the default should be...
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
69export async function getTextByFileUrl(url: Readonly<urlMod.URL>): Promise<string> {
70 return fs.promises.readFile(url, {encoding: "UTF-8"}) as Promise<string>;
71}
72
73export function getTextByFileUrlSync(url: Readonly<urlMod.URL>): string {
74 return fs.readFileSync(url, {encoding: "UTF-8"});
75}
76
77export 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}