import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { mergeWidgetCode, parseMixedWidgetCode, scopeWidgetCss } from "./widgetCode.ts"; describe("parseMixedWidgetCode", () => { it("拆分混写的 style/script 段", () => { const r = parseMixedWidgetCode( `
hi
\n\n` ); assert.equal(r.html, `
hi
`); assert.equal(r.css, `.a { color: red; }`); assert.equal(r.js, `console.log(1);`); }); it("多段 style/script 按序拼接", () => { const r = parseMixedWidgetCode(`

x

`); assert.equal(r.css, ".a{}\n\n.b{}"); assert.equal(r.js, "a();\n\nb();"); assert.equal(r.html, "

x

"); }); it("纯 HTML 不误伤", () => { const r = parseMixedWidgetCode(`

hello

`); assert.deepEqual(r, { html: "

hello

", css: "", js: "" }); }); it("外链与非 JS type 的 script 留在 html", () => { const code = ``; const r = parseMixedWidgetCode(code); assert.equal(r.js, "z();"); assert.equal( r.html, `` ); }); }); describe("mergeWidgetCode", () => { it("合并后再解析可还原三字段", () => { const parts = { html: "go", css: "b { font-size: 18px; }", js: "x();" }; assert.deepEqual(parseMixedWidgetCode(mergeWidgetCode(parts)), parts); }); it("空段不产生标签", () => { assert.equal(mergeWidgetCode({ html: "hi", css: "", js: "" }), "hi"); }); }); describe("scopeWidgetCss", () => { const p = ".j13-widget-7"; it("普通规则加前缀", () => { assert.equal(scopeWidgetCss(".a { color: red; }", 7), `${p} .a { color: red; }`); }); it("选择器列表逐个前缀,括号内逗号不分割", () => { assert.equal( scopeWidgetCss(".a, .b {}", 7), `${p} .a, ${p} .b {}` ); assert.equal( scopeWidgetCss(':is(.a, .b) { color: red }', 7), `${p} :is(.a, .b) { color: red }` ); }); it("root/body 选择器替换为容器本身", () => { assert.equal(scopeWidgetCss(":root { --x: 1; }", 7), `${p} { --x: 1; }`); assert.equal(scopeWidgetCss("body { margin: 0 }", 7), `${p} { margin: 0 }`); assert.equal(scopeWidgetCss("body .card {}", 7), `${p} .card {}`); }); it("容器自身伪类紧贴前缀", () => { assert.equal(scopeWidgetCss(":hover { opacity: .8 }", 7), `${p}:hover { opacity: .8 }`); }); it("@media 内层前缀化,头部原样", () => { assert.equal( scopeWidgetCss("@media (min-width: 10px) { .a {} }", 7), `@media (min-width: 10px) { ${p} .a {} }` ); }); it("@keyframes 原样保留", () => { const css = "@keyframes spin { from { opacity: 0 } to { opacity: 1 } }"; assert.equal(scopeWidgetCss(css, 7), css); }); it("@import 语句原样保留", () => { assert.equal( scopeWidgetCss('@import url("a.css"); .a {}', 7), '@import url("a.css"); .j13-widget-7 .a {}' ); }); it("注释与字符串内的花括号不干扰配对", () => { assert.equal( scopeWidgetCss("/* { nope } */ .a::after { content: \"{\" }", 7), `/* { nope } */ ${p} .a::after { content: "{" }` ); }); });