Support absolute paths when bundling HTML (#16149)

This commit is contained in:
Jarred Sumner
2025-01-03 17:54:07 -08:00
committed by GitHub
parent 78498b4244
commit fd9d9242d8
2 changed files with 66 additions and 2 deletions

View File

@@ -28,12 +28,20 @@ pub fn deinit(this: *HTMLScanner) void {
this.import_records.deinitWithAllocator(this.allocator);
}
fn createImportRecord(this: *HTMLScanner, path: []const u8, kind: ImportKind) !void {
fn createImportRecord(this: *HTMLScanner, input_path: []const u8, kind: ImportKind) !void {
// In HTML, sometimes people do /src/index.js
// In that case, we don't want to use the absolute filesystem path, we want to use the path relative to the project root
const path_to_use = if (input_path.len > 1 and input_path[0] == '/')
bun.path.joinAbsString(bun.fs.FileSystem.instance.top_level_dir, &[_][]const u8{input_path[1..]}, .auto)
else
input_path;
const record = ImportRecord{
.path = fs.Path.init(try this.allocator.dupe(u8, path)),
.path = fs.Path.init(try this.allocator.dupeZ(u8, path_to_use)),
.kind = kind,
.range = logger.Range.None,
};
try this.import_records.push(this.allocator, record);
}

View File

@@ -721,4 +721,60 @@ body {
expect(cssBundle).toContain("box-sizing: border-box");
},
});
// Test absolute paths in HTML
itBundled("html/absolute-paths", {
outdir: "out/",
files: {
"/index.html": `
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/styles/main.css">
<script src="/scripts/app.js"></script>
</head>
<body>
<h1>Absolute Paths</h1>
<img src="/images/logo.png">
</body>
</html>`,
"/styles/main.css": "body { margin: 0; }",
"/scripts/app.js": "console.log('App loaded')",
"/images/logo.png": "fake image content",
},
experimentalHtml: true,
experimentalCss: true,
entryPoints: ["/index.html"],
onAfterBundle(api) {
// Check that absolute paths are handled correctly
const htmlBundle = api.readFile("out/index.html");
// CSS should be bundled and hashed
api.expectFile("out/index.html").not.toContain("/styles/main.css");
api.expectFile("out/index.html").toMatch(/href=".*\.css"/);
// JS should be bundled and hashed
api.expectFile("out/index.html").not.toContain("/scripts/app.js");
api.expectFile("out/index.html").toMatch(/src=".*\.js"/);
// Image should be hashed
api.expectFile("out/index.html").not.toContain("/images/logo.png");
api.expectFile("out/index.html").toMatch(/src=".*\.png"/);
// Get the bundled files and verify their contents
const cssMatch = htmlBundle.match(/href="(.*\.css)"/);
const jsMatch = htmlBundle.match(/src="(.*\.js)"/);
const imgMatch = htmlBundle.match(/src="(.*\.png)"/);
expect(cssMatch).not.toBeNull();
expect(jsMatch).not.toBeNull();
expect(imgMatch).not.toBeNull();
const cssBundle = api.readFile("out/" + cssMatch![1]);
const jsBundle = api.readFile("out/" + jsMatch![1]);
expect(cssBundle).toContain("margin: 0");
expect(jsBundle).toContain("App loaded");
},
});
});