@huaqiu/dsh-ui-theme-huaqiu 0.3.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/cordis.patch.yml +8 -0
- package/lib/client.js +278 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.mts +6 -0
- package/lib/index.mjs +6 -0
- package/package.json +64 -0
- package/src/client/HuaqiuBrand.tsx +15 -0
- package/src/client/index.ts +62 -0
- package/src/client/legacyHeroBranding.ts +64 -0
- package/src/client/locales.ts +13 -0
- package/src/css-modules.d.ts +4 -0
- package/src/index.ts +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 深圳华秋智联股份有限公司
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @huaqiu/dsh-ui-theme-huaqiu
|
|
2
|
+
|
|
3
|
+
An installable Web profile Bundle that applies the HuaQiu red palette, HQ marks, the HuaQiu sidebar name, and the blank-session slogan without modifying DSH host source.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```powershell
|
|
8
|
+
dsh plugin --profile web add file:C:/Downloads/huaqiu-dsh-ui-theme-huaqiu-<version>.tgz
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Restart the Web profile after installing. Remove it with:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
dsh plugin --profile web remove @huaqiu/dsh-ui-theme-huaqiu
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Implementation
|
|
18
|
+
|
|
19
|
+
The Bundle disables the built-in `ui-brand-official` row and adds this package as the final Web presentation layer. It overrides theme tokens through `ctx.theme`, fills the existing sidebar and blank-session mark slots independently, and uses a reversible `MutationObserver` to replace the shipped blank-session headline and hide its adjacent preview badge after React renders.
|
|
20
|
+
|
|
21
|
+
The title adapter recognizes the shipped Chinese and English headline plus preview-badge pair. If an upstream UI changes that markup, the package retains its palette and HQ marks but leaves the unrelated page text unchanged.
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@huaqiu/dsh-ui-theme-huaqiu",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react = require("react");
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
//#region src/client/HuaqiuBrand.tsx
|
|
10
|
+
/** Render the supplied HQ mark at an owner-requested size. */
|
|
11
|
+
function HuaqiuBrandMark({ size, className }) {
|
|
12
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
className,
|
|
15
|
+
height: size,
|
|
16
|
+
style: {
|
|
17
|
+
display: "block",
|
|
18
|
+
flex: "none"
|
|
19
|
+
},
|
|
20
|
+
viewBox: "0 0 974.25 974.25",
|
|
21
|
+
width: size,
|
|
22
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
25
|
+
d: "M865.67,758.67a107,107,0,1,0,107,107A107,107,0,0,0,865.67,758.67Z",
|
|
26
|
+
fill: "#c7000b",
|
|
27
|
+
fillRule: "evenodd"
|
|
28
|
+
}),
|
|
29
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
30
|
+
d: "M744.11,0h-514C103.56,0,0,103.56,0,230.14v514C0,870.69,103.56,974.25,230.14,974.25h514c3.34,0,6.66-.06,10-.21a155.66,155.66,0,0,1-40-143.56H230.14a86.63,86.63,0,0,1-86.37-86.37v-514a86.63,86.63,0,0,1,86.37-86.37h514a86.61,86.61,0,0,1,86.37,86.37V714.06a156.93,156.93,0,0,1,35.19-4A155.1,155.1,0,0,1,974,754c.15-3.28.21-6.6.21-9.92v-514C974.25,103.56,870.69,0,744.11,0Z",
|
|
31
|
+
fill: "#c7000b",
|
|
32
|
+
fillRule: "evenodd"
|
|
33
|
+
}),
|
|
34
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
|
|
35
|
+
fill: "#c7000b",
|
|
36
|
+
fillRule: "evenodd",
|
|
37
|
+
points: "735.67 735.65 735.67 238.59 591.9 238.59 591.9 415.24 382.39 415.24 382.39 238.59 238.62 238.59 238.62 735.65 382.39 735.65 382.39 559.01 591.9 559.01 591.9 735.65 735.67 735.65"
|
|
38
|
+
})
|
|
39
|
+
]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** Render the HuaQiu wordmark beside the sidebar mark. */
|
|
43
|
+
function HuaqiuBrandName({ label }) {
|
|
44
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
45
|
+
style: {
|
|
46
|
+
color: "var(--dsw-alias-label-primary)",
|
|
47
|
+
fontSize: "16px",
|
|
48
|
+
fontWeight: 600,
|
|
49
|
+
letterSpacing: "0.02em"
|
|
50
|
+
},
|
|
51
|
+
children: label
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/client/legacyHeroBranding.ts
|
|
56
|
+
/** DOM-level replacement for the shipped blank-session headline and preview badge. */
|
|
57
|
+
const HERO_HEADLINES = /* @__PURE__ */ new Set(["探索未至之境", "Into the Unknown"]);
|
|
58
|
+
const PREVIEW_BADGES = /* @__PURE__ */ new Set(["预览版", "Preview"]);
|
|
59
|
+
const TITLE_ATTRIBUTE = "data-huaqiu-hero-title";
|
|
60
|
+
const TITLE_ORIGINAL_ATTRIBUTE = "data-huaqiu-hero-title-original";
|
|
61
|
+
const BADGE_ATTRIBUTE = "data-huaqiu-hero-badge";
|
|
62
|
+
const BADGE_DISPLAY_ATTRIBUTE = "data-huaqiu-hero-badge-display";
|
|
63
|
+
function leafText(node) {
|
|
64
|
+
return node.childElementCount === 0 ? node.textContent?.trim() : void 0;
|
|
65
|
+
}
|
|
66
|
+
function replaceHeroTitle(title, slogan) {
|
|
67
|
+
const parent = title.parentElement;
|
|
68
|
+
if (parent === null) return;
|
|
69
|
+
const badge = [...parent.querySelectorAll("span")].find((node) => PREVIEW_BADGES.has(leafText(node) ?? ""));
|
|
70
|
+
if (badge === void 0) return;
|
|
71
|
+
if (!title.hasAttribute(TITLE_ATTRIBUTE)) {
|
|
72
|
+
title.setAttribute(TITLE_ORIGINAL_ATTRIBUTE, title.textContent ?? "");
|
|
73
|
+
title.setAttribute(TITLE_ATTRIBUTE, "");
|
|
74
|
+
}
|
|
75
|
+
if (title.textContent !== slogan) title.textContent = slogan;
|
|
76
|
+
if (!badge.hasAttribute(BADGE_ATTRIBUTE)) {
|
|
77
|
+
badge.setAttribute(BADGE_DISPLAY_ATTRIBUTE, badge.style.display);
|
|
78
|
+
badge.setAttribute(BADGE_ATTRIBUTE, "");
|
|
79
|
+
}
|
|
80
|
+
if (badge.style.display !== "none") badge.style.display = "none";
|
|
81
|
+
}
|
|
82
|
+
function applyHeroBranding(slogan) {
|
|
83
|
+
for (const title of document.querySelectorAll("span")) {
|
|
84
|
+
const text = leafText(title);
|
|
85
|
+
if (HERO_HEADLINES.has(text ?? "") || title.hasAttribute(TITLE_ATTRIBUTE)) replaceHeroTitle(title, slogan);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function restoreHeroBranding() {
|
|
89
|
+
for (const title of document.querySelectorAll(`span[${TITLE_ATTRIBUTE}]`)) {
|
|
90
|
+
title.textContent = title.getAttribute(TITLE_ORIGINAL_ATTRIBUTE) ?? "";
|
|
91
|
+
title.removeAttribute(TITLE_ATTRIBUTE);
|
|
92
|
+
title.removeAttribute(TITLE_ORIGINAL_ATTRIBUTE);
|
|
93
|
+
}
|
|
94
|
+
for (const badge of document.querySelectorAll(`span[${BADGE_ATTRIBUTE}]`)) {
|
|
95
|
+
badge.style.display = badge.getAttribute(BADGE_DISPLAY_ATTRIBUTE) ?? "";
|
|
96
|
+
badge.removeAttribute(BADGE_ATTRIBUTE);
|
|
97
|
+
badge.removeAttribute(BADGE_DISPLAY_ATTRIBUTE);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Brand the stock blank-session hero without a host-source modification.
|
|
102
|
+
* @param slogan localized HuaQiu slogan for the active browser locale.
|
|
103
|
+
* @returns disposer restoring modified DOM nodes when the plugin unloads.
|
|
104
|
+
*/
|
|
105
|
+
function installLegacyHeroBranding(slogan) {
|
|
106
|
+
applyHeroBranding(slogan());
|
|
107
|
+
const observer = new MutationObserver(() => {
|
|
108
|
+
applyHeroBranding(slogan());
|
|
109
|
+
});
|
|
110
|
+
observer.observe(document.documentElement, {
|
|
111
|
+
childList: true,
|
|
112
|
+
characterData: true,
|
|
113
|
+
subtree: true
|
|
114
|
+
});
|
|
115
|
+
return () => {
|
|
116
|
+
observer.disconnect();
|
|
117
|
+
restoreHeroBranding();
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/client/locales.ts
|
|
122
|
+
/** HuaQiu brand dictionaries. */
|
|
123
|
+
const zh = {
|
|
124
|
+
name: "华秋",
|
|
125
|
+
slogan: "电子设计智能体平台"
|
|
126
|
+
};
|
|
127
|
+
const en = {
|
|
128
|
+
name: "HuaQiu",
|
|
129
|
+
slogan: "Electronic Design Agent Platform"
|
|
130
|
+
};
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/client/index.ts
|
|
133
|
+
const inject = [
|
|
134
|
+
"theme",
|
|
135
|
+
"slots",
|
|
136
|
+
"locale"
|
|
137
|
+
];
|
|
138
|
+
const HUAQIU_BRAND_NS = "brand.huaqiu";
|
|
139
|
+
const HUAQIU_TOKENS = {
|
|
140
|
+
"--dsw-alias-brand-primary": {
|
|
141
|
+
light: "#C7000B",
|
|
142
|
+
dark: "#FF6B74"
|
|
143
|
+
},
|
|
144
|
+
"--dsw-alias-brand-primary-invert": {
|
|
145
|
+
light: "#FFFFFF",
|
|
146
|
+
dark: "#210002"
|
|
147
|
+
},
|
|
148
|
+
"--dsw-alias-brand-primary-new-colorprimary-new-color": {
|
|
149
|
+
light: "#C7000B",
|
|
150
|
+
dark: "#FF6B74"
|
|
151
|
+
},
|
|
152
|
+
"--dsw-alias-brand-text": {
|
|
153
|
+
light: "#C7000B",
|
|
154
|
+
dark: "#FF6B74"
|
|
155
|
+
},
|
|
156
|
+
"--dsw-alias-button-info-fill": {
|
|
157
|
+
light: "#C7000B",
|
|
158
|
+
dark: "#FF6B74"
|
|
159
|
+
},
|
|
160
|
+
"--dsw-alias-button-info-hover": {
|
|
161
|
+
light: "#E53935",
|
|
162
|
+
dark: "#FF8A92"
|
|
163
|
+
},
|
|
164
|
+
"--dsw-alias-button-primary-dimmed": {
|
|
165
|
+
light: "#FFCDD2",
|
|
166
|
+
dark: "#5C1118"
|
|
167
|
+
},
|
|
168
|
+
"--dsw-alias-button-primary-fill": {
|
|
169
|
+
light: "#C7000B",
|
|
170
|
+
dark: "#FF6B74"
|
|
171
|
+
},
|
|
172
|
+
"--dsw-alias-button-primary-hover": {
|
|
173
|
+
light: "#E53935",
|
|
174
|
+
dark: "#FF8A92"
|
|
175
|
+
},
|
|
176
|
+
"--dsw-alias-interactive-bg-hover-accent": {
|
|
177
|
+
light: "rgb(199 0 11 / 12%)",
|
|
178
|
+
dark: "rgb(255 107 116 / 22%)"
|
|
179
|
+
},
|
|
180
|
+
"--dsw-alias-link": {
|
|
181
|
+
light: "#C7000B",
|
|
182
|
+
dark: "#FF8A92"
|
|
183
|
+
},
|
|
184
|
+
"--dsw-alias-state-business-primary": {
|
|
185
|
+
light: "#C7000B",
|
|
186
|
+
dark: "#FF6B74"
|
|
187
|
+
},
|
|
188
|
+
"--dsw-alias-state-business-tertiary": {
|
|
189
|
+
light: "#FFCDD2",
|
|
190
|
+
dark: "#5C1118"
|
|
191
|
+
},
|
|
192
|
+
"--dsw-specific-bubble": {
|
|
193
|
+
light: "#FFF5F5",
|
|
194
|
+
dark: "#351116"
|
|
195
|
+
},
|
|
196
|
+
"--dsw-specific-bubble-highlight": {
|
|
197
|
+
light: "#FFCDD2",
|
|
198
|
+
dark: "#5C1118"
|
|
199
|
+
},
|
|
200
|
+
"--dsw-specific-sidebar-fill": {
|
|
201
|
+
light: "#FAFAFA",
|
|
202
|
+
dark: "#211316"
|
|
203
|
+
},
|
|
204
|
+
"--dsw-specific-sidebar-nav-item-active-accent": {
|
|
205
|
+
light: "#FFCDD2",
|
|
206
|
+
dark: "#5C1118"
|
|
207
|
+
},
|
|
208
|
+
"--dsw-static-deepseek-50": {
|
|
209
|
+
light: "#FFF5F5",
|
|
210
|
+
dark: "#351116"
|
|
211
|
+
},
|
|
212
|
+
"--dsw-static-deepseek-100": {
|
|
213
|
+
light: "#FFEBEE",
|
|
214
|
+
dark: "#5C1118"
|
|
215
|
+
},
|
|
216
|
+
"--dsw-static-deepseek-200": {
|
|
217
|
+
light: "#FFCDD2",
|
|
218
|
+
dark: "#7A1E28"
|
|
219
|
+
},
|
|
220
|
+
"--dsw-static-deepseek-300": {
|
|
221
|
+
light: "#EF9A9A",
|
|
222
|
+
dark: "#A52B37"
|
|
223
|
+
},
|
|
224
|
+
"--dsw-static-deepseek-400": {
|
|
225
|
+
light: "#E53935",
|
|
226
|
+
dark: "#FF8A92"
|
|
227
|
+
},
|
|
228
|
+
"--dsw-static-deepseek-450": {
|
|
229
|
+
light: "#D32F2F",
|
|
230
|
+
dark: "#FF6B74"
|
|
231
|
+
},
|
|
232
|
+
"--dsw-static-deepseek-500": {
|
|
233
|
+
light: "#C7000B",
|
|
234
|
+
dark: "#FF6B74"
|
|
235
|
+
},
|
|
236
|
+
"--dsw-static-deepseek-600": {
|
|
237
|
+
light: "#C62828",
|
|
238
|
+
dark: "#FF555F"
|
|
239
|
+
},
|
|
240
|
+
"--dsw-static-deepseek-700-delete": {
|
|
241
|
+
light: "#B71C1C",
|
|
242
|
+
dark: "#FF3F4B"
|
|
243
|
+
},
|
|
244
|
+
"--dsw-static-deepseek-800": {
|
|
245
|
+
light: "#8E111A",
|
|
246
|
+
dark: "#FFCDD2"
|
|
247
|
+
},
|
|
248
|
+
"--dsw-static-deepseek-900": {
|
|
249
|
+
light: "#5F0007",
|
|
250
|
+
dark: "#FFE7E9"
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
/** Install HuaQiu colors and brand occupants without altering the host source. */
|
|
254
|
+
function apply(ctx) {
|
|
255
|
+
ctx.effect(() => ctx.theme.overrideTokens("@huaqiu/dsh-ui-theme-huaqiu", HUAQIU_TOKENS), "huaqiu theme: token override");
|
|
256
|
+
ctx.effect(() => ctx.locale.register(HUAQIU_BRAND_NS, {
|
|
257
|
+
zh,
|
|
258
|
+
en
|
|
259
|
+
}), "huaqiu theme: brand dictionaries");
|
|
260
|
+
const t = ctx.locale.bind(HUAQIU_BRAND_NS);
|
|
261
|
+
ctx.slots.inject("sidebar.brand.mark", () => ctx.slots.register({ name: "sidebar.brand.mark" }, ({ size }) => (0, react.createElement)(HuaqiuBrandMark, { size })));
|
|
262
|
+
ctx.slots.inject("sidebar.brand.name", () => ctx.slots.register({ name: "sidebar.brand.name" }, () => (0, react.createElement)(HuaqiuBrandName, { label: t("name") })));
|
|
263
|
+
ctx.slots.inject("conversation.hero.brand.mark", () => ctx.slots.register({ name: "conversation.hero.brand.mark" }, ({ size, className }) => (0, react.createElement)(HuaqiuBrandMark, {
|
|
264
|
+
className,
|
|
265
|
+
size
|
|
266
|
+
})));
|
|
267
|
+
ctx.effect(() => installLegacyHeroBranding(() => t("slogan")), "huaqiu theme: legacy hero branding");
|
|
268
|
+
}
|
|
269
|
+
//#endregion
|
|
270
|
+
exports.HUAQIU_BRAND_NS = HUAQIU_BRAND_NS;
|
|
271
|
+
exports.HUAQIU_TOKENS = HUAQIU_TOKENS;
|
|
272
|
+
exports.apply = apply;
|
|
273
|
+
exports.inject = inject;
|
|
274
|
+
return module.exports;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["createElement"],"sources":["../src/client/HuaqiuBrand.tsx","../src/client/legacyHeroBranding.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/** Render the supplied HQ mark at an owner-requested size. */\nexport function HuaqiuBrandMark({ size, className }: { size: number; className?: string }) {\n return (\n <svg aria-hidden=\"true\" className={className} height={size} style={{ display: 'block', flex: 'none' }} viewBox=\"0 0 974.25 974.25\" width={size} xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M865.67,758.67a107,107,0,1,0,107,107A107,107,0,0,0,865.67,758.67Z\" fill=\"#c7000b\" fillRule=\"evenodd\" />\n <path d=\"M744.11,0h-514C103.56,0,0,103.56,0,230.14v514C0,870.69,103.56,974.25,230.14,974.25h514c3.34,0,6.66-.06,10-.21a155.66,155.66,0,0,1-40-143.56H230.14a86.63,86.63,0,0,1-86.37-86.37v-514a86.63,86.63,0,0,1,86.37-86.37h514a86.61,86.61,0,0,1,86.37,86.37V714.06a156.93,156.93,0,0,1,35.19-4A155.1,155.1,0,0,1,974,754c.15-3.28.21-6.6.21-9.92v-514C974.25,103.56,870.69,0,744.11,0Z\" fill=\"#c7000b\" fillRule=\"evenodd\" />\n <polygon fill=\"#c7000b\" fillRule=\"evenodd\" points=\"735.67 735.65 735.67 238.59 591.9 238.59 591.9 415.24 382.39 415.24 382.39 238.59 238.62 238.59 238.62 735.65 382.39 735.65 382.39 559.01 591.9 559.01 591.9 735.65 735.67 735.65\" />\n </svg>\n )\n}\n\n/** Render the HuaQiu wordmark beside the sidebar mark. */\nexport function HuaqiuBrandName({ label }: { label: string }) {\n return <span style={{ color: 'var(--dsw-alias-label-primary)', fontSize: '16px', fontWeight: 600, letterSpacing: '0.02em' }}>{label}</span>\n}\n","/** DOM-level replacement for the shipped blank-session headline and preview badge. */\n\nconst HERO_HEADLINES = new Set(['探索未至之境', 'Into the Unknown'])\nconst PREVIEW_BADGES = new Set(['预览版', 'Preview'])\nconst TITLE_ATTRIBUTE = 'data-huaqiu-hero-title'\nconst TITLE_ORIGINAL_ATTRIBUTE = 'data-huaqiu-hero-title-original'\nconst BADGE_ATTRIBUTE = 'data-huaqiu-hero-badge'\nconst BADGE_DISPLAY_ATTRIBUTE = 'data-huaqiu-hero-badge-display'\n\nfunction leafText(node: HTMLSpanElement): string | undefined {\n return node.childElementCount === 0 ? node.textContent?.trim() : undefined\n}\n\nfunction replaceHeroTitle(title: HTMLSpanElement, slogan: string): void {\n const parent = title.parentElement\n if (parent === null) return\n const badge = [...parent.querySelectorAll('span')].find(node => PREVIEW_BADGES.has(leafText(node) ?? ''))\n if (badge === undefined) return\n if (!title.hasAttribute(TITLE_ATTRIBUTE)) {\n title.setAttribute(TITLE_ORIGINAL_ATTRIBUTE, title.textContent ?? '')\n title.setAttribute(TITLE_ATTRIBUTE, '')\n }\n if (title.textContent !== slogan) title.textContent = slogan\n if (!badge.hasAttribute(BADGE_ATTRIBUTE)) {\n badge.setAttribute(BADGE_DISPLAY_ATTRIBUTE, badge.style.display)\n badge.setAttribute(BADGE_ATTRIBUTE, '')\n }\n if (badge.style.display !== 'none') badge.style.display = 'none'\n}\n\nfunction applyHeroBranding(slogan: string): void {\n for (const title of document.querySelectorAll<HTMLSpanElement>('span')) {\n const text = leafText(title)\n if (HERO_HEADLINES.has(text ?? '') || title.hasAttribute(TITLE_ATTRIBUTE)) replaceHeroTitle(title, slogan)\n }\n}\n\nfunction restoreHeroBranding(): void {\n for (const title of document.querySelectorAll<HTMLSpanElement>(`span[${TITLE_ATTRIBUTE}]`)) {\n title.textContent = title.getAttribute(TITLE_ORIGINAL_ATTRIBUTE) ?? ''\n title.removeAttribute(TITLE_ATTRIBUTE)\n title.removeAttribute(TITLE_ORIGINAL_ATTRIBUTE)\n }\n for (const badge of document.querySelectorAll<HTMLSpanElement>(`span[${BADGE_ATTRIBUTE}]`)) {\n badge.style.display = badge.getAttribute(BADGE_DISPLAY_ATTRIBUTE) ?? ''\n badge.removeAttribute(BADGE_ATTRIBUTE)\n badge.removeAttribute(BADGE_DISPLAY_ATTRIBUTE)\n }\n}\n\n/**\n * Brand the stock blank-session hero without a host-source modification.\n * @param slogan localized HuaQiu slogan for the active browser locale.\n * @returns disposer restoring modified DOM nodes when the plugin unloads.\n */\nexport function installLegacyHeroBranding(slogan: () => string): () => void {\n applyHeroBranding(slogan())\n const observer = new MutationObserver(() => { applyHeroBranding(slogan()) })\n observer.observe(document.documentElement, { childList: true, characterData: true, subtree: true })\n return () => {\n observer.disconnect()\n restoreHeroBranding()\n }\n}\n","/** HuaQiu brand dictionaries. */\n\nexport const zh = {\n name: '华秋',\n slogan: '电子设计智能体平台',\n} as const\n\nexport type HuaqiuBrandKey = keyof typeof zh\n\nexport const en: Record<HuaqiuBrandKey, string> = {\n name: 'HuaQiu',\n slogan: 'Electronic Design Agent Platform',\n}\n","/** HuaQiu color tokens and HQ brand occupants for a DSH Web client. */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type { ThemeTokenOverrides } from '@deepseek-ai/dsh-client-ui-theme/client'\nimport { createElement } from 'react'\nimport { HuaqiuBrandMark, HuaqiuBrandName } from './HuaqiuBrand'\nimport { installLegacyHeroBranding } from './legacyHeroBranding'\nimport { en, zh, type HuaqiuBrandKey } from './locales'\n\nexport const inject = ['theme', 'slots', 'locale']\nexport const HUAQIU_BRAND_NS = 'brand.huaqiu'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'brand.huaqiu': HuaqiuBrandKey\n }\n}\n\nexport const HUAQIU_TOKENS: ThemeTokenOverrides = {\n '--dsw-alias-brand-primary': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-brand-primary-invert': { light: '#FFFFFF', dark: '#210002' },\n '--dsw-alias-brand-primary-new-colorprimary-new-color': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-brand-text': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-button-info-fill': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-button-info-hover': { light: '#E53935', dark: '#FF8A92' },\n '--dsw-alias-button-primary-dimmed': { light: '#FFCDD2', dark: '#5C1118' },\n '--dsw-alias-button-primary-fill': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-button-primary-hover': { light: '#E53935', dark: '#FF8A92' },\n '--dsw-alias-interactive-bg-hover-accent': { light: 'rgb(199 0 11 / 12%)', dark: 'rgb(255 107 116 / 22%)' },\n '--dsw-alias-link': { light: '#C7000B', dark: '#FF8A92' },\n '--dsw-alias-state-business-primary': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-alias-state-business-tertiary': { light: '#FFCDD2', dark: '#5C1118' },\n '--dsw-specific-bubble': { light: '#FFF5F5', dark: '#351116' },\n '--dsw-specific-bubble-highlight': { light: '#FFCDD2', dark: '#5C1118' },\n '--dsw-specific-sidebar-fill': { light: '#FAFAFA', dark: '#211316' },\n '--dsw-specific-sidebar-nav-item-active-accent': { light: '#FFCDD2', dark: '#5C1118' },\n '--dsw-static-deepseek-50': { light: '#FFF5F5', dark: '#351116' },\n '--dsw-static-deepseek-100': { light: '#FFEBEE', dark: '#5C1118' },\n '--dsw-static-deepseek-200': { light: '#FFCDD2', dark: '#7A1E28' },\n '--dsw-static-deepseek-300': { light: '#EF9A9A', dark: '#A52B37' },\n '--dsw-static-deepseek-400': { light: '#E53935', dark: '#FF8A92' },\n '--dsw-static-deepseek-450': { light: '#D32F2F', dark: '#FF6B74' },\n '--dsw-static-deepseek-500': { light: '#C7000B', dark: '#FF6B74' },\n '--dsw-static-deepseek-600': { light: '#C62828', dark: '#FF555F' },\n '--dsw-static-deepseek-700-delete': { light: '#B71C1C', dark: '#FF3F4B' },\n '--dsw-static-deepseek-800': { light: '#8E111A', dark: '#FFCDD2' },\n '--dsw-static-deepseek-900': { light: '#5F0007', dark: '#FFE7E9' },\n}\n\n/** Install HuaQiu colors and brand occupants without altering the host source. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.theme.overrideTokens('@huaqiu/dsh-ui-theme-huaqiu', HUAQIU_TOKENS), 'huaqiu theme: token override')\n ctx.effect(() => ctx.locale.register(HUAQIU_BRAND_NS, { zh, en }), 'huaqiu theme: brand dictionaries')\n const t = ctx.locale.bind(HUAQIU_BRAND_NS)\n ctx.slots.inject('sidebar.brand.mark', () => ctx.slots.register({ name: 'sidebar.brand.mark' }, ({ size }) => createElement(HuaqiuBrandMark, { size })))\n ctx.slots.inject('sidebar.brand.name', () => ctx.slots.register({ name: 'sidebar.brand.name' }, () => createElement(HuaqiuBrandName, { label: t('name') })))\n ctx.slots.inject('conversation.hero.brand.mark', () => ctx.slots.register({ name: 'conversation.hero.brand.mark' }, ({ size, className }) => createElement(HuaqiuBrandMark, { className, size })))\n ctx.effect(() => installLegacyHeroBranding(() => t('slogan')), 'huaqiu theme: legacy hero branding')\n}\n"],"mappings":"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"}
|
package/lib/index.d.mts
ADDED
package/lib/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@huaqiu/dsh-ui-theme-huaqiu",
|
|
3
|
+
"version": "0.3.24",
|
|
4
|
+
"description": "HuaQiu Web theme and HQ brand plugin for DeepSeek Harness",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.mjs",
|
|
7
|
+
"types": "./lib/index.d.mts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.mts",
|
|
11
|
+
"default": "./lib/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"default": "./lib/client.js"
|
|
15
|
+
},
|
|
16
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"dsh": {
|
|
20
|
+
"bundle": {
|
|
21
|
+
"patch": "./cordis.patch.yml"
|
|
22
|
+
},
|
|
23
|
+
"client": {
|
|
24
|
+
"platform": "web",
|
|
25
|
+
"inject": [
|
|
26
|
+
"@deepseek-ai/dsh-client-locale",
|
|
27
|
+
"@deepseek-ai/dsh-client-ui-theme",
|
|
28
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
29
|
+
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
30
|
+
"@deepseek-ai/dsh-client-ui-conversation"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"lib",
|
|
39
|
+
"src",
|
|
40
|
+
"cordis.patch.yml",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
48
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "^0.1.5-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-theme": "^0.1.5-rc.2",
|
|
54
|
+
"@testing-library/react": "^16.3.2",
|
|
55
|
+
"@types/react": "~18.3.1",
|
|
56
|
+
"react": "^18.3.1",
|
|
57
|
+
"react-dom": "^18.3.1"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"typecheck": "tsc --noEmit",
|
|
61
|
+
"build": "tsdown",
|
|
62
|
+
"test": "vitest run"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Render the supplied HQ mark at an owner-requested size. */
|
|
2
|
+
export function HuaqiuBrandMark({ size, className }: { size: number; className?: string }) {
|
|
3
|
+
return (
|
|
4
|
+
<svg aria-hidden="true" className={className} height={size} style={{ display: 'block', flex: 'none' }} viewBox="0 0 974.25 974.25" width={size} xmlns="http://www.w3.org/2000/svg">
|
|
5
|
+
<path d="M865.67,758.67a107,107,0,1,0,107,107A107,107,0,0,0,865.67,758.67Z" fill="#c7000b" fillRule="evenodd" />
|
|
6
|
+
<path d="M744.11,0h-514C103.56,0,0,103.56,0,230.14v514C0,870.69,103.56,974.25,230.14,974.25h514c3.34,0,6.66-.06,10-.21a155.66,155.66,0,0,1-40-143.56H230.14a86.63,86.63,0,0,1-86.37-86.37v-514a86.63,86.63,0,0,1,86.37-86.37h514a86.61,86.61,0,0,1,86.37,86.37V714.06a156.93,156.93,0,0,1,35.19-4A155.1,155.1,0,0,1,974,754c.15-3.28.21-6.6.21-9.92v-514C974.25,103.56,870.69,0,744.11,0Z" fill="#c7000b" fillRule="evenodd" />
|
|
7
|
+
<polygon fill="#c7000b" fillRule="evenodd" points="735.67 735.65 735.67 238.59 591.9 238.59 591.9 415.24 382.39 415.24 382.39 238.59 238.62 238.59 238.62 735.65 382.39 735.65 382.39 559.01 591.9 559.01 591.9 735.65 735.67 735.65" />
|
|
8
|
+
</svg>
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Render the HuaQiu wordmark beside the sidebar mark. */
|
|
13
|
+
export function HuaqiuBrandName({ label }: { label: string }) {
|
|
14
|
+
return <span style={{ color: 'var(--dsw-alias-label-primary)', fontSize: '16px', fontWeight: 600, letterSpacing: '0.02em' }}>{label}</span>
|
|
15
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** HuaQiu color tokens and HQ brand occupants for a DSH Web client. */
|
|
2
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis'
|
|
3
|
+
import type {} from '@deepseek-ai/dsh-client-locale/client'
|
|
4
|
+
import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
|
|
5
|
+
import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
|
|
6
|
+
import type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'
|
|
7
|
+
import type { ThemeTokenOverrides } from '@deepseek-ai/dsh-client-ui-theme/client'
|
|
8
|
+
import { createElement } from 'react'
|
|
9
|
+
import { HuaqiuBrandMark, HuaqiuBrandName } from './HuaqiuBrand'
|
|
10
|
+
import { installLegacyHeroBranding } from './legacyHeroBranding'
|
|
11
|
+
import { en, zh, type HuaqiuBrandKey } from './locales'
|
|
12
|
+
|
|
13
|
+
export const inject = ['theme', 'slots', 'locale']
|
|
14
|
+
export const HUAQIU_BRAND_NS = 'brand.huaqiu'
|
|
15
|
+
|
|
16
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
17
|
+
interface LocaleNamespaceMap {
|
|
18
|
+
'brand.huaqiu': HuaqiuBrandKey
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const HUAQIU_TOKENS: ThemeTokenOverrides = {
|
|
23
|
+
'--dsw-alias-brand-primary': { light: '#C7000B', dark: '#FF6B74' },
|
|
24
|
+
'--dsw-alias-brand-primary-invert': { light: '#FFFFFF', dark: '#210002' },
|
|
25
|
+
'--dsw-alias-brand-primary-new-colorprimary-new-color': { light: '#C7000B', dark: '#FF6B74' },
|
|
26
|
+
'--dsw-alias-brand-text': { light: '#C7000B', dark: '#FF6B74' },
|
|
27
|
+
'--dsw-alias-button-info-fill': { light: '#C7000B', dark: '#FF6B74' },
|
|
28
|
+
'--dsw-alias-button-info-hover': { light: '#E53935', dark: '#FF8A92' },
|
|
29
|
+
'--dsw-alias-button-primary-dimmed': { light: '#FFCDD2', dark: '#5C1118' },
|
|
30
|
+
'--dsw-alias-button-primary-fill': { light: '#C7000B', dark: '#FF6B74' },
|
|
31
|
+
'--dsw-alias-button-primary-hover': { light: '#E53935', dark: '#FF8A92' },
|
|
32
|
+
'--dsw-alias-interactive-bg-hover-accent': { light: 'rgb(199 0 11 / 12%)', dark: 'rgb(255 107 116 / 22%)' },
|
|
33
|
+
'--dsw-alias-link': { light: '#C7000B', dark: '#FF8A92' },
|
|
34
|
+
'--dsw-alias-state-business-primary': { light: '#C7000B', dark: '#FF6B74' },
|
|
35
|
+
'--dsw-alias-state-business-tertiary': { light: '#FFCDD2', dark: '#5C1118' },
|
|
36
|
+
'--dsw-specific-bubble': { light: '#FFF5F5', dark: '#351116' },
|
|
37
|
+
'--dsw-specific-bubble-highlight': { light: '#FFCDD2', dark: '#5C1118' },
|
|
38
|
+
'--dsw-specific-sidebar-fill': { light: '#FAFAFA', dark: '#211316' },
|
|
39
|
+
'--dsw-specific-sidebar-nav-item-active-accent': { light: '#FFCDD2', dark: '#5C1118' },
|
|
40
|
+
'--dsw-static-deepseek-50': { light: '#FFF5F5', dark: '#351116' },
|
|
41
|
+
'--dsw-static-deepseek-100': { light: '#FFEBEE', dark: '#5C1118' },
|
|
42
|
+
'--dsw-static-deepseek-200': { light: '#FFCDD2', dark: '#7A1E28' },
|
|
43
|
+
'--dsw-static-deepseek-300': { light: '#EF9A9A', dark: '#A52B37' },
|
|
44
|
+
'--dsw-static-deepseek-400': { light: '#E53935', dark: '#FF8A92' },
|
|
45
|
+
'--dsw-static-deepseek-450': { light: '#D32F2F', dark: '#FF6B74' },
|
|
46
|
+
'--dsw-static-deepseek-500': { light: '#C7000B', dark: '#FF6B74' },
|
|
47
|
+
'--dsw-static-deepseek-600': { light: '#C62828', dark: '#FF555F' },
|
|
48
|
+
'--dsw-static-deepseek-700-delete': { light: '#B71C1C', dark: '#FF3F4B' },
|
|
49
|
+
'--dsw-static-deepseek-800': { light: '#8E111A', dark: '#FFCDD2' },
|
|
50
|
+
'--dsw-static-deepseek-900': { light: '#5F0007', dark: '#FFE7E9' },
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Install HuaQiu colors and brand occupants without altering the host source. */
|
|
54
|
+
export function apply(ctx: ClientContext): void {
|
|
55
|
+
ctx.effect(() => ctx.theme.overrideTokens('@huaqiu/dsh-ui-theme-huaqiu', HUAQIU_TOKENS), 'huaqiu theme: token override')
|
|
56
|
+
ctx.effect(() => ctx.locale.register(HUAQIU_BRAND_NS, { zh, en }), 'huaqiu theme: brand dictionaries')
|
|
57
|
+
const t = ctx.locale.bind(HUAQIU_BRAND_NS)
|
|
58
|
+
ctx.slots.inject('sidebar.brand.mark', () => ctx.slots.register({ name: 'sidebar.brand.mark' }, ({ size }) => createElement(HuaqiuBrandMark, { size })))
|
|
59
|
+
ctx.slots.inject('sidebar.brand.name', () => ctx.slots.register({ name: 'sidebar.brand.name' }, () => createElement(HuaqiuBrandName, { label: t('name') })))
|
|
60
|
+
ctx.slots.inject('conversation.hero.brand.mark', () => ctx.slots.register({ name: 'conversation.hero.brand.mark' }, ({ size, className }) => createElement(HuaqiuBrandMark, { className, size })))
|
|
61
|
+
ctx.effect(() => installLegacyHeroBranding(() => t('slogan')), 'huaqiu theme: legacy hero branding')
|
|
62
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** DOM-level replacement for the shipped blank-session headline and preview badge. */
|
|
2
|
+
|
|
3
|
+
const HERO_HEADLINES = new Set(['探索未至之境', 'Into the Unknown'])
|
|
4
|
+
const PREVIEW_BADGES = new Set(['预览版', 'Preview'])
|
|
5
|
+
const TITLE_ATTRIBUTE = 'data-huaqiu-hero-title'
|
|
6
|
+
const TITLE_ORIGINAL_ATTRIBUTE = 'data-huaqiu-hero-title-original'
|
|
7
|
+
const BADGE_ATTRIBUTE = 'data-huaqiu-hero-badge'
|
|
8
|
+
const BADGE_DISPLAY_ATTRIBUTE = 'data-huaqiu-hero-badge-display'
|
|
9
|
+
|
|
10
|
+
function leafText(node: HTMLSpanElement): string | undefined {
|
|
11
|
+
return node.childElementCount === 0 ? node.textContent?.trim() : undefined
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function replaceHeroTitle(title: HTMLSpanElement, slogan: string): void {
|
|
15
|
+
const parent = title.parentElement
|
|
16
|
+
if (parent === null) return
|
|
17
|
+
const badge = [...parent.querySelectorAll('span')].find(node => PREVIEW_BADGES.has(leafText(node) ?? ''))
|
|
18
|
+
if (badge === undefined) return
|
|
19
|
+
if (!title.hasAttribute(TITLE_ATTRIBUTE)) {
|
|
20
|
+
title.setAttribute(TITLE_ORIGINAL_ATTRIBUTE, title.textContent ?? '')
|
|
21
|
+
title.setAttribute(TITLE_ATTRIBUTE, '')
|
|
22
|
+
}
|
|
23
|
+
if (title.textContent !== slogan) title.textContent = slogan
|
|
24
|
+
if (!badge.hasAttribute(BADGE_ATTRIBUTE)) {
|
|
25
|
+
badge.setAttribute(BADGE_DISPLAY_ATTRIBUTE, badge.style.display)
|
|
26
|
+
badge.setAttribute(BADGE_ATTRIBUTE, '')
|
|
27
|
+
}
|
|
28
|
+
if (badge.style.display !== 'none') badge.style.display = 'none'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function applyHeroBranding(slogan: string): void {
|
|
32
|
+
for (const title of document.querySelectorAll<HTMLSpanElement>('span')) {
|
|
33
|
+
const text = leafText(title)
|
|
34
|
+
if (HERO_HEADLINES.has(text ?? '') || title.hasAttribute(TITLE_ATTRIBUTE)) replaceHeroTitle(title, slogan)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function restoreHeroBranding(): void {
|
|
39
|
+
for (const title of document.querySelectorAll<HTMLSpanElement>(`span[${TITLE_ATTRIBUTE}]`)) {
|
|
40
|
+
title.textContent = title.getAttribute(TITLE_ORIGINAL_ATTRIBUTE) ?? ''
|
|
41
|
+
title.removeAttribute(TITLE_ATTRIBUTE)
|
|
42
|
+
title.removeAttribute(TITLE_ORIGINAL_ATTRIBUTE)
|
|
43
|
+
}
|
|
44
|
+
for (const badge of document.querySelectorAll<HTMLSpanElement>(`span[${BADGE_ATTRIBUTE}]`)) {
|
|
45
|
+
badge.style.display = badge.getAttribute(BADGE_DISPLAY_ATTRIBUTE) ?? ''
|
|
46
|
+
badge.removeAttribute(BADGE_ATTRIBUTE)
|
|
47
|
+
badge.removeAttribute(BADGE_DISPLAY_ATTRIBUTE)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Brand the stock blank-session hero without a host-source modification.
|
|
53
|
+
* @param slogan localized HuaQiu slogan for the active browser locale.
|
|
54
|
+
* @returns disposer restoring modified DOM nodes when the plugin unloads.
|
|
55
|
+
*/
|
|
56
|
+
export function installLegacyHeroBranding(slogan: () => string): () => void {
|
|
57
|
+
applyHeroBranding(slogan())
|
|
58
|
+
const observer = new MutationObserver(() => { applyHeroBranding(slogan()) })
|
|
59
|
+
observer.observe(document.documentElement, { childList: true, characterData: true, subtree: true })
|
|
60
|
+
return () => {
|
|
61
|
+
observer.disconnect()
|
|
62
|
+
restoreHeroBranding()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** HuaQiu brand dictionaries. */
|
|
2
|
+
|
|
3
|
+
export const zh = {
|
|
4
|
+
name: '华秋',
|
|
5
|
+
slogan: '电子设计智能体平台',
|
|
6
|
+
} as const
|
|
7
|
+
|
|
8
|
+
export type HuaqiuBrandKey = keyof typeof zh
|
|
9
|
+
|
|
10
|
+
export const en: Record<HuaqiuBrandKey, string> = {
|
|
11
|
+
name: 'HuaQiu',
|
|
12
|
+
slogan: 'Electronic Design Agent Platform',
|
|
13
|
+
}
|
package/src/index.ts
ADDED