Skip to content

Commit d1f81d1

Browse files
authored
Support import with { type: 'css' } (#1193)
1 parent 0358f14 commit d1f81d1

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

server/build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
679679

680680
if len(args.With) > 0 && args.With["type"] == "css" {
681681
return esbuild.OnResolveResult{
682-
Path: "/" + ctx.esmPath.Name() + utils.NormalizePathname(modulePath),
682+
Path: "/" + ctx.esmPath.Name() + utils.NormalizePathname(modulePath) + "?module",
683683
External: true,
684684
SideEffects: esbuild.SideEffectsFalse,
685685
}, nil

server/router.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,11 +1029,39 @@ func esmRouter(db Database, esmStorage storage.Storage, logger *log.Logger) rex.
10291029
} else {
10301030
// return wasm file as an es6 module when `?module` query is present (requires `top-level-await` support)
10311031
if pathKind == RawFile && strings.HasSuffix(esm.SubPath, ".wasm") && query.Has("module") {
1032-
buf := &bytes.Buffer{}
10331032
wasmUrl := origin + pathname
1034-
fmt.Fprintf(buf, "/* esm.sh - wasm module */\n")
1035-
fmt.Fprintf(buf, "const data = await fetch(%s).then(r => r.arrayBuffer());\nexport default new WebAssembly.Module(data);", strings.TrimSpace(string(utils.MustEncodeJSON(wasmUrl))))
1033+
buf := bytes.NewBufferString("/* esm.sh - wasm module */\n")
1034+
buf.WriteString("const data = await fetch(")
1035+
buf.WriteString(strings.TrimSpace(string(utils.MustEncodeJSON(wasmUrl))))
1036+
buf.WriteString(").then(r => r.arrayBuffer());\n")
1037+
buf.WriteString("export default new WebAssembly.Module(data);")
10361038
ctx.SetHeader("Content-Type", ctJavaScript)
1039+
ctx.SetHeader("Content-Length", fmt.Sprintf("%d", buf.Len()))
1040+
ctx.SetHeader("Cache-Control", ccImmutable)
1041+
return buf
1042+
}
1043+
1044+
// return css file as a `CSSStyleSheet` object when `?module` query is present
1045+
if pathKind == RawFile && strings.HasSuffix(esm.SubPath, ".css") && query.Has("module") {
1046+
filename := path.Join(npmrc.StoreDir(), esm.Name(), "node_modules", esm.PkgName, esm.SubPath)
1047+
css, err := os.ReadFile(filename)
1048+
if err != nil {
1049+
return rex.Status(500, err.Error())
1050+
}
1051+
buf := bytes.NewBufferString("/* esm.sh - css module */\n")
1052+
buf.WriteString("const stylesheet = new CSSStyleSheet();\n")
1053+
if bytes.ContainsRune(css, '`') {
1054+
buf.WriteString("stylesheet.replaceSync(`")
1055+
buf.WriteString(strings.TrimSpace(string(utils.MustEncodeJSON(string(css)))))
1056+
buf.WriteString(");\n")
1057+
} else {
1058+
buf.WriteString("stylesheet.replaceSync(`")
1059+
buf.Write(css)
1060+
buf.WriteString("`);\n")
1061+
}
1062+
buf.WriteString("export default stylesheet;\n")
1063+
ctx.SetHeader("Content-Type", ctJavaScript)
1064+
ctx.SetHeader("Content-Length", fmt.Sprintf("%d", buf.Len()))
10371065
ctx.SetHeader("Cache-Control", ccImmutable)
10381066
return buf
10391067
}

test/issue-1191/test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { assert, assertEquals } from "jsr:@std/assert";
2+
3+
// related issue: https://github.com/esm-dev/esm.sh/issues/1191
4+
Deno.test(
5+
"import with { type: 'css' }",
6+
async () => {
7+
const res = await fetch("http://localhost:8080/[email protected]/es2022/menu/menu.mjs");
8+
const text = await res.text();
9+
assert(res.ok);
10+
assertEquals(res.headers.get("content-type"), "application/javascript; charset=utf-8");
11+
assertEquals(res.headers.get("cache-control"), "public, max-age=31536000, immutable");
12+
assert(text.includes(`import("/[email protected]/style.css?module")`));
13+
},
14+
);
15+
16+
Deno.test(
17+
"css?module",
18+
async () => {
19+
const res = await fetch("http://localhost:8080/[email protected]/style.css?module");
20+
const text = await res.text();
21+
assert(res.ok);
22+
assertEquals(res.headers.get("content-type"), "application/javascript; charset=utf-8");
23+
assertEquals(res.headers.get("cache-control"), "public, max-age=31536000, immutable");
24+
assert(text.includes("const stylesheet = new CSSStyleSheet();"));
25+
assert(text.includes("stylesheet.replaceSync(`"));
26+
assert(text.includes("`);\nexport default stylesheet;"));
27+
},
28+
);

0 commit comments

Comments
 (0)