Original-Commit: d049f7014d49e93ab0e6aa8b7e715d5155b94dc0 fix(web): 首屏 favicon - 不再先闪内置品牌图标 index.html 静态声明 /logo.svg 作 icon,而 favicon 由 use-appearance-store 在解析出外观后写入 (link[rel~="icon"] + appearanceLogoURL)。自定义品牌部署于是会先闪一下内置 logo。 换成空占位 <link rel="icon" href="data:," />:外观系统照旧覆盖它,占位只是为了不让浏览器去 请求 /favicon.ico(那是一条 404)。代价是外观接口不可用时标签页没有图标,这是有意的取舍。 新增源码级守卫用例(上游原态 1 pass/1 fail,改后 2 pass)。
23 lines
1.1 KiB
TypeScript
23 lines
1.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
||
import { readFileSync } from "node:fs";
|
||
|
||
const readProjectFile = (relative: string) => readFileSync(new URL(`../${relative}`, import.meta.url), "utf8");
|
||
|
||
// 首屏必须品牌中性:静态的 /logo.svg 会让自定义品牌部署在标签页上先闪一下内置 logo,
|
||
// 而 favicon 本来就由 use-appearance-store 在解析出外观后写入。空 data URL 只是占位,
|
||
// 避免浏览器去请求 /favicon.ico(那是一条 404)。
|
||
describe("app icon bootstrap", () => {
|
||
const indexHtml = readProjectFile("index.html");
|
||
const appearanceStore = readProjectFile("src/stores/use-appearance-store.ts");
|
||
|
||
test("index.html declares a neutral placeholder icon instead of the built-in brand", () => {
|
||
expect(indexHtml).toContain('<link rel="icon" href="data:," />');
|
||
expect(indexHtml).not.toContain('<link rel="icon" href="/logo.svg"');
|
||
});
|
||
|
||
test("the appearance store remains the single writer of the favicon", () => {
|
||
expect(appearanceStore).toContain('link[rel~="icon"]');
|
||
expect(appearanceStore).toContain("favicon.href = appearanceLogoURL(");
|
||
});
|
||
});
|