MCPcopy Create free account
hub / github.com/backnotprop/plannotator / inlineHtmlLocalAssets

Function inlineHtmlLocalAssets

packages/shared/html-assets-node.ts:11–56  ·  view source on GitHub ↗
(html: string, htmlFilePath: string)

Source from the content-addressed store, hash-verified

9export const MAX_HTML_ASSET_BYTES = 50 * 1024 * 1024;
10
11export function inlineHtmlLocalAssets(html: string, htmlFilePath: string): string {
12 if (/^https?:\/\//i.test(htmlFilePath)) return html;
13
14 try {
15 const root = dirname(resolvePath(htmlFilePath));
16 const activeCss = new Set<string>();
17
18 const dataUrlFor = (assetPath: string): string | null => {
19 try {
20 const contentType = htmlAssetContentType(assetPath);
21 if (!contentType) return null;
22
23 const resolved = resolvePath(root, assetPath);
24 if (!isWithinDirectory(resolved, root)) return null;
25 if (!existsSync(resolved)) return null;
26
27 const stat = statSync(resolved);
28 if (!stat.isFile() || stat.size > MAX_HTML_ASSET_BYTES) return null;
29
30 let bytes = readFileSync(resolved);
31 if (contentType.startsWith("text/css") && !activeCss.has(assetPath)) {
32 activeCss.add(assetPath);
33 try {
34 const cssBase = pathPosix.dirname(assetPath);
35 const rewrittenCss = rewriteCssAssetReferences(
36 bytes.toString("utf-8"),
37 dataUrlFor,
38 cssBase === "." ? "" : cssBase,
39 );
40 bytes = Buffer.from(rewrittenCss, "utf-8");
41 } finally {
42 activeCss.delete(assetPath);
43 }
44 }
45
46 return `data:${contentType.replace(/;\s*/g, ";")};base64,${Buffer.from(bytes).toString("base64")}`;
47 } catch {
48 return null;
49 }
50 };
51
52 return rewriteHtmlAssetReferences(html, dataUrlFor);
53 } catch {
54 return html;
55 }
56}
57
58/**
59 * Single source of truth for "is this file inside this root?" containment used

Callers 4

inlineHtmlFunction · 0.90
index.tsFile · 0.90
inlineHtmlFunction · 0.85

Calls 2

dirnameFunction · 0.85

Tested by

no test coverage detected