Refactor of asset bundles
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { assertEquals } from "../../test_deps.ts";
|
||||
import { base64Decode } from "./base64.ts";
|
||||
import { base64Encode } from "./base64.ts";
|
||||
|
||||
Deno.test("Base 64 encoding", () => {
|
||||
const buf = new Uint8Array(3);
|
||||
buf[0] = 1;
|
||||
buf[1] = 2;
|
||||
buf[2] = 3;
|
||||
|
||||
assertEquals(buf, base64Decode(base64Encode(buf)));
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { buf } from "https://deno.land/x/sqlite3@0.6.1/src/util.ts";
|
||||
|
||||
export function base64Decode(s: string): Uint8Array {
|
||||
const binString = atob(s);
|
||||
const len = binString.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binString.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export function base64Encode(buffer: Uint8Array): string {
|
||||
let binary = "";
|
||||
const len = buffer.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(buffer[i]);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { globToRegExp, path, walk } from "../deps.ts";
|
||||
import { AssetBundle } from "./bundle.ts";
|
||||
|
||||
export async function bundleAssets(
|
||||
rootPath: string,
|
||||
patterns: string[],
|
||||
): Promise<AssetBundle> {
|
||||
const bundle = new AssetBundle();
|
||||
for await (
|
||||
const file of walk(rootPath, {
|
||||
match: patterns.map((pat) => globToRegExp(pat)),
|
||||
})
|
||||
) {
|
||||
const cleanPath = file.path.substring("".length);
|
||||
await bundle.writeFileSync(cleanPath, await Deno.readFile(file.path));
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
export async function bundleFolder(rootPath: string, bundlePath: string) {
|
||||
const bundle = new AssetBundle();
|
||||
await Deno.mkdir(path.dirname(bundlePath), { recursive: true });
|
||||
for await (
|
||||
const { path: filePath } of walk(rootPath, { includeDirs: false })
|
||||
) {
|
||||
console.log("Bundling", filePath);
|
||||
const cleanPath = filePath.substring(`${rootPath}/`.length);
|
||||
await bundle.writeFileSync(cleanPath, await Deno.readFile(filePath));
|
||||
}
|
||||
await Deno.writeTextFile(
|
||||
bundlePath,
|
||||
JSON.stringify(bundle.toJSON(), null, 2),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { AssetBundle } from "./bundle.ts";
|
||||
import { assertEquals } from "../../test_deps.ts";
|
||||
|
||||
Deno.test("Asset bundle", () => {
|
||||
const assetBundle = new AssetBundle();
|
||||
assetBundle.writeTextFileSync("test.txt", "Sup yo");
|
||||
assertEquals("text/plain", assetBundle.getMimeType("test.txt"));
|
||||
assertEquals("Sup yo", assetBundle.readTextFileSync("test.txt"));
|
||||
const buf = new Uint8Array(3);
|
||||
buf[0] = 1;
|
||||
buf[1] = 2;
|
||||
buf[2] = 3;
|
||||
assetBundle.writeFileSync("test.bin", buf);
|
||||
assertEquals("application/octet-stream", assetBundle.getMimeType("test.bin"));
|
||||
assertEquals(buf, assetBundle.readFileSync("test.bin"));
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { base64Decode, base64Encode } from "./base64.ts";
|
||||
import { mime } from "../deps.ts";
|
||||
|
||||
export type AssetJson = Record<string, string>;
|
||||
|
||||
export class AssetBundle {
|
||||
readonly bundle: AssetJson;
|
||||
|
||||
constructor(bundle: AssetJson = {}) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
has(path: string): boolean {
|
||||
return path in this.bundle;
|
||||
}
|
||||
|
||||
listFiles(): string[] {
|
||||
return Object.keys(this.bundle);
|
||||
}
|
||||
|
||||
readFileSync(
|
||||
path: string,
|
||||
): Uint8Array {
|
||||
const content = this.bundle[path];
|
||||
if (!content) {
|
||||
throw new Error(`No such file ${path}`);
|
||||
}
|
||||
const data = content.split(",", 2)[1];
|
||||
return base64Decode(data);
|
||||
}
|
||||
|
||||
readFileAsDataUrl(path: string): string {
|
||||
const content = this.bundle[path];
|
||||
if (!content) {
|
||||
throw new Error(`No such file ${path}`);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
readTextFileSync(
|
||||
path: string,
|
||||
): string {
|
||||
return new TextDecoder().decode(this.readFileSync(path));
|
||||
}
|
||||
|
||||
getMimeType(
|
||||
path: string,
|
||||
): string {
|
||||
const content = this.bundle[path];
|
||||
if (!content) {
|
||||
throw new Error(`No such file ${path}`);
|
||||
}
|
||||
return content.split(";")[0].split(":")[1];
|
||||
}
|
||||
|
||||
writeFileSync(path: string, data: Uint8Array) {
|
||||
const encoded = base64Encode(data);
|
||||
const mimeType = mime.getType(path);
|
||||
this.bundle[path] = `data:${mimeType};base64,${encoded}`;
|
||||
}
|
||||
|
||||
writeTextFileSync(path: string, s: string) {
|
||||
this.writeFileSync(path, new TextEncoder().encode(s));
|
||||
}
|
||||
|
||||
toJSON(): AssetJson {
|
||||
return this.bundle;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user