dsh-claude-style 0.3.0 → 0.3.2

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.
Files changed (115) hide show
  1. package/CHANGELOG.md +56 -2
  2. package/LICENSE +9 -0
  3. package/README.en.md +4 -3
  4. package/README.md +4 -15
  5. package/docs/STYLE.md +22 -14
  6. package/docs/architecture.md +74 -0
  7. package/fonts/GoogleSansFlexPicker.woff2 +0 -0
  8. package/fonts/OFL-GoogleSansFlex.txt +93 -0
  9. package/lib/client.js +710 -1485
  10. package/lib/index.js +6 -23
  11. package/lib/model-descriptions.json +225 -209
  12. package/package.json +7 -2
  13. package/docs/REFACTOR.md +0 -294
  14. package/lib/icons/providers/ClaudeApi.png +0 -0
  15. package/lib/icons/providers/README.md +0 -13
  16. package/lib/icons/providers/TeamoRouter-icon-dark.png +0 -0
  17. package/lib/icons/providers/a6-icon.png +0 -0
  18. package/lib/icons/providers/aicodemirror.svg +0 -19
  19. package/lib/icons/providers/aicoding.svg +0 -20
  20. package/lib/icons/providers/aihubmix-color.svg +0 -1
  21. package/lib/icons/providers/algocode.svg +0 -51
  22. package/lib/icons/providers/alibaba.svg +0 -1
  23. package/lib/icons/providers/amuxapi-icon.svg +0 -13
  24. package/lib/icons/providers/anthropic.svg +0 -1
  25. package/lib/icons/providers/apikeyfun.png +0 -0
  26. package/lib/icons/providers/apinebula_icon.png +0 -0
  27. package/lib/icons/providers/atlascloud_icon.png +0 -0
  28. package/lib/icons/providers/aws.svg +0 -1
  29. package/lib/icons/providers/azure.svg +0 -1
  30. package/lib/icons/providers/baidu.svg +0 -1
  31. package/lib/icons/providers/bailian.svg +0 -1
  32. package/lib/icons/providers/bytedance.svg +0 -1
  33. package/lib/icons/providers/byteplus.png +0 -0
  34. package/lib/icons/providers/catcoder.svg +0 -1
  35. package/lib/icons/providers/ccsub.svg +0 -4
  36. package/lib/icons/providers/chatglm.svg +0 -1
  37. package/lib/icons/providers/cherryin.png +0 -0
  38. package/lib/icons/providers/claude.svg +0 -1
  39. package/lib/icons/providers/claudecn.png +0 -0
  40. package/lib/icons/providers/claw.svg +0 -22
  41. package/lib/icons/providers/cloudflare.svg +0 -1
  42. package/lib/icons/providers/code0.png +0 -0
  43. package/lib/icons/providers/cohere.svg +0 -1
  44. package/lib/icons/providers/copilot.svg +0 -1
  45. package/lib/icons/providers/crazyrouter.svg +0 -1
  46. package/lib/icons/providers/cubence.svg +0 -9
  47. package/lib/icons/providers/deepseek.svg +0 -1
  48. package/lib/icons/providers/doubao.svg +0 -1
  49. package/lib/icons/providers/eflowcode.png +0 -0
  50. package/lib/icons/providers/etok.png +0 -0
  51. package/lib/icons/providers/fenno-icon.webp +0 -0
  52. package/lib/icons/providers/gemini.svg +0 -1
  53. package/lib/icons/providers/gemma.svg +0 -1
  54. package/lib/icons/providers/github.svg +0 -1
  55. package/lib/icons/providers/githubcopilot.svg +0 -1
  56. package/lib/icons/providers/google.svg +0 -1
  57. package/lib/icons/providers/googlecloud.svg +0 -1
  58. package/lib/icons/providers/grok.svg +0 -1
  59. package/lib/icons/providers/hermes.png +0 -0
  60. package/lib/icons/providers/huawei.svg +0 -1
  61. package/lib/icons/providers/huggingface.svg +0 -1
  62. package/lib/icons/providers/hunyuan.svg +0 -1
  63. package/lib/icons/providers/huoshan.png +0 -0
  64. package/lib/icons/providers/kimi.svg +0 -1
  65. package/lib/icons/providers/lioncc.svg +0 -6
  66. package/lib/icons/providers/longcat-color.svg +0 -1
  67. package/lib/icons/providers/mcp.svg +0 -1
  68. package/lib/icons/providers/meta.svg +0 -1
  69. package/lib/icons/providers/micu.svg +0 -23
  70. package/lib/icons/providers/midjourney.svg +0 -1
  71. package/lib/icons/providers/minimax.svg +0 -1
  72. package/lib/icons/providers/mistral.svg +0 -1
  73. package/lib/icons/providers/modelscope-color.svg +0 -1
  74. package/lib/icons/providers/nekocode-icon.png +0 -0
  75. package/lib/icons/providers/newapi.svg +0 -1
  76. package/lib/icons/providers/notion.svg +0 -1
  77. package/lib/icons/providers/novita.svg +0 -11
  78. package/lib/icons/providers/nvidia.svg +0 -1
  79. package/lib/icons/providers/ollama.svg +0 -1
  80. package/lib/icons/providers/openai.svg +0 -1
  81. package/lib/icons/providers/opencode-logo-light.svg +0 -1
  82. package/lib/icons/providers/openrouter.svg +0 -1
  83. package/lib/icons/providers/packycode.svg +0 -1
  84. package/lib/icons/providers/palm.svg +0 -1
  85. package/lib/icons/providers/pateway.jpg +0 -0
  86. package/lib/icons/providers/perplexity.svg +0 -1
  87. package/lib/icons/providers/pipellm.png +0 -0
  88. package/lib/icons/providers/ppio.svg +0 -1
  89. package/lib/icons/providers/qianwenai.svg +0 -1
  90. package/lib/icons/providers/qiniu.png +0 -0
  91. package/lib/icons/providers/qwen.svg +0 -1
  92. package/lib/icons/providers/qwencloud.svg +0 -1
  93. package/lib/icons/providers/rc.svg +0 -1
  94. package/lib/icons/providers/relaxcode.png +0 -0
  95. package/lib/icons/providers/runapi.jpg +0 -0
  96. package/lib/icons/providers/shengsuanyun.svg +0 -4
  97. package/lib/icons/providers/siliconflow.svg +0 -1
  98. package/lib/icons/providers/sssaicode.svg +0 -73
  99. package/lib/icons/providers/stability.svg +0 -1
  100. package/lib/icons/providers/stepfun.svg +0 -10
  101. package/lib/icons/providers/subrouter.svg +0 -30
  102. package/lib/icons/providers/sudocode-us.png +0 -0
  103. package/lib/icons/providers/sudocode.png +0 -0
  104. package/lib/icons/providers/tencent.svg +0 -1
  105. package/lib/icons/providers/ucloud.svg +0 -1
  106. package/lib/icons/providers/unity2.png +0 -0
  107. package/lib/icons/providers/vercel.svg +0 -1
  108. package/lib/icons/providers/wenxin.svg +0 -1
  109. package/lib/icons/providers/xai.svg +0 -1
  110. package/lib/icons/providers/xiaomimimo.svg +0 -1
  111. package/lib/icons/providers/xycai-icon.png +0 -0
  112. package/lib/icons/providers/yi.svg +0 -1
  113. package/lib/icons/providers/zeroone.svg +0 -1
  114. package/lib/icons/providers/zetaapi-icon.png +0 -0
  115. package/lib/icons/providers/zhipu.svg +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## [0.3.2] - 2026-09-21
6
+
7
+ ### Added
8
+ - **会话统计弹层现在跟随「自动弹出弹层」设置**:账户、模型、权限三个弹层都检查了 `readPrefs().autoPopover`,只有会话统计那个漏了——`bindStatsHover` 无条件在 `mouseenter` 打开弹层,于是它无视开关、永远悬停即弹。现在与那三个对齐:关掉开关后悬停不再弹出,点击仍可打开宿主自己的统计对话框。
9
+ - **「更多模型」弹层再收紧**:列间距 6 → 4px、分组间距 6 → 4px、分组标题上边距 6 → 4px(上一轮已把行内边距 4 → 3px)。
10
+ - **锁定标不再回退到供应商,用不到的标一并删掉**:此前「没有规则认领的模型」会退回它所在 provider 的锁定标,于是 OpenCode 转售的 `LongCat-2.0` 戴上 OpenCode 自己的标——那不是缺一个标,而是给了一个错的标。现在没有规则命中就不画标(`modelBrand` 不再回退),`brands.providers` 随之清空,vendoring 的品牌集合只剩规则真正用到的那些:**43 → 25 个锁定标**,产物 **756 KB → 649 KB**(−107 KB)。
11
+ - **新增 `longcat` 品牌与 `mimo` → `xiaomimimo` 规则**:OpenCode 转售的 `MiMo V2.5 Pro` 此前解析不到(没有 `mimo` 规则,于是落到 provider),现在命中;LongCat 用 Lobe 的 `longcat` 图标。
12
+ - **OpenAI 的标在暖黑画布上不可见**:手工提供的 ChatGPT SVG 把颜色写在 `style="fill:#000000"` 里,而内联 style **优先于**呈现属性,所以 `fill="currentColor"` 的包装不生效——标是黑的,暖黑上等于没有。现在 vendoring 会清掉本地资产里带 fill 的内联 style,再补 `currentColor`。
13
+ - **「更多模型」弹层收紧、同供应商内按 id 升序**:行内边距 4px → 3px;每个 provider 的模型按 id 升序排(目录自己的顺序是 provider 返回的顺序,不可预期),排序在副本上做,不动宿主的快照。
14
+ - **锁定标的七处修正**:(1) **Meta 的锁定标向左漂移**——`compose_lockup` 的 viewBox 左右边界只取了字标簇,而图标画在字标左侧,于是它落到元素框外、压向前一列;现在边界取整件墨迹,只有大写带仍取自字标簇(viewBox 左边界 38.3 → 2.0)。(2) **混元标的一部分被染黑**——`recolour_illegible` 会把任何在象牙白上读不出的填充换成 `currentColor`,而混元图标里那块浅色高光并非主导色,因此被误伤;现在只换**按墨迹面积加权的主导色**(Kimi 的白 K 是主导 → 仍换 ✓,它的蓝点保留 ✓,混元的 `#ECECEE` 保留 ✓)。(3) **`hy-mt2-*` 三个混元模型解析不到品牌**——规则 `hy\d` 不匹配 `hy-mt2`,放宽为 `hy(\d|-?mt)`。(4) **新增 Gemma 品牌**(Lobe 有 `gemma` 图标):Gemma 是 Google 的开放模型线,此前落到 `google`,而 Google 没有锁定标、行里就是空的;现在有自己的 ✓。(5) **Gemini 标与字标之间空隙过大**——字标定位改用**图标墨迹**的右边缘;Lobe 的 24 单位盒子里留白很多(Gemini 星芒远窄于盒子),按盒子定位就多出一大截空隙。(6) **新增 Nano Banana 品牌**(Lobe 的 id 是 `nanobanana`,词覆写为 `Nano Banana` 才与目录名对得上)。(7) **Claude 行改用 Anthropic Serif 排其余文字**——那枚锁定标本身是衬线体,标签此前是无衬线,两截字形不同;`@font-face` 与宿主路由白名单本就存在,所以只加了一个字体 token 与一条 `[data-brand='claude']` 规则。
15
+ - **模型行改用厂商锁定标:图标与字标合成一件图形,随包的自建字标全部删掉**:起因是「引入自建字体」这条路——每接一个厂商的字标都要单独弄一枚资产、自己裁 viewBox 对齐大写带。Lobe 的 React 包有一个 `Combine` 变体(`<Qwen.Combine/>`),但**静态资产包里没有 `-combine` 文件**:它是运行时把「图标」和「文字变体」拼起来的,所以合成得自己做,而**规则不用自己发明**——每个图标 `es/<Icon>/style.js` 里的 `TEXT_MULTIPLE`(字标 ÷ 图标)与 `SPACE_MULTIPLE`(间距)就是 Lobe 自己发布的合成比例,`es/toc.js` 给品牌色与变体清单。产出 `src/assets/icons/combine/<厂商>.svg`:viewBox 高度归一化为「字标的大写带」(所以样式表一条 `height: 1cap` 管住全部 43 个),内部三组——亮色画布显彩色图标、暗色画布显单色图标(`currentColor`;Lobe 自己用品牌色染,但 `#000` 在暖黑上会消失)、字标两份共用。厂商自己的词也由 Lobe 的 `TITLE` 带出(`moonshot` 画的是 `MoonshotAI`、`zai` 是 `zai`,从品牌 id 推不出来)。渲染规则:名称里以该厂商词开头就替换掉那个词(连分隔符一起),名称里没有该词(Kimi 官方目录只叫 `K3`)就把锁定标领在开头;该行不再另起前置图标。
16
+ **顺带瘦身**:删掉 `assets/icons/lobe/`(41 个厂商标)、`assets/icons/wordmarks/`(3 个自建字标)、`fetch-lobe-icons.mjs`,以及 `PROVIDER_ICONS`(157 KB 的供应商图标 markup)与 `PROVIDER_ICON_URL_KEYS`——供应商行不再显示图标后,最大的一块正好变成死重量;`providerIconName()` 改为只吃 id 集合 `PROVIDER_ICON_KEYS`,元数据保留(品牌解析靠它)。产物 711 KB → 739 KB(锁定标本身 235 KB,净 +28 KB)。
17
+ - **Claude 行改画 Claude 自己的锁定标**:原先 `claude` 规则指向 `anthropic`,行里画的是「Anthropic」字标,而名称里那个词是「Claude」——字标必须和它替换的词对得上(Grok 行画 Grok 而不是 xAI,同一个道理)。`anthropic` 仍留作 `anthropic` 路由的兜底。
18
+ - **新增 `gemma` 与 `nano-?banana` 两条家族规则**:这两个品牌在 `brands.models` 里有锁定标,`families` 里却没有文案规则,于是模型行一路掉到档位规则上(Gemma 会显示成「轻量档…」这类通用话术)。现在两条各有官网口径的一行。
19
+ - **新增 Claude Fable 与 Mythos 两条家族规则**:Anthropic 的模型线现在是 Mythos / Fable / Opus / Sonnet / Haiku,而 `families` 里只有 opus / sonnet / haiku 三条,Fable 与 Mythos 会掉到兜底的「Anthropic Claude 模型。」。两条各用官网自己的定位句(Fable 用 anthropic.com/claude/fable 的 tagline,Mythos 用它的受众与访问限制)。
20
+
21
+ ### Changed
22
+ - **抽出 `model-brand.js`**:`model-picker.js` 已达 737/750 行,撞上仓库的体量停止线,所以先把「这一行/这个分组属于哪个厂商」整块(含共用的元素工厂 `modelEl` 与五个品牌函数)搬进新碎片,再落上面的字标功能。产物侧用行多重集比对证明这是纯搬移——旧 `lib/client.js` 8717 个非空行 vs 新 8729,差异只有新碎片的横幅与构建的碎片清单;`model-picker.js` 737 → 636 行。
23
+ - **厂商字标扫描改为预置数组,并补上分项计时探针**:`.debug/wordmark-cost.cjs` 量出每行标签构建里扫描词表约占 0.5µs(50 行一次渲染约 25ms),改为加载时构建成数组后整行成本从约 0.78µs 降到约 0.72µs。同一批量具还带出 `scripts/probe-timing.cjs`:在真实浏览器里分项计时——启动长任务与插件资源、模型目录就绪、选择器打开延迟、行构成、锁定标 markup 的 `innerHTML` 解析成本、JS 堆——把「哪一段慢」从推测变成测量。
24
+ - **模型简介全部按厂商官网口径重写**:19 条精确条目与 54 条家族规则的文案此前多为转述与推测,现逐条对着官网的发布页 / 模型文档页 / 价格页重写(DeepSeek、Anthropic、OpenAI、Google、Z.ai、Moonshot、阿里、阶跃、MiniMax、xAI、字节、百度、Mistral,以及 Meta、Inception、Cohere、微软、AWS、Perplexity、Motif、Apodex 等十余家),把可核对的事实写进文案——参数量与激活参数、上下文与输出上限、许可证、吞吐与单价。家族规则照旧不写最高级、不写版本相关数字:调研素材里带进来的「1M 上下文」这类数字已从家族文案剔除,否则会把同一家族的旧版一起误标。
25
+ - **文案改为「按线映射」,不再按版本钉死**:DeepSeek 的三条旧版精确条目(V4 Flash、V4 Flash Vision Exp、V4 Pro)与 V3.2 条目一并删除,改为按名字模式映射——所有 Flash 共用一句、所有 Pro 共用一句(官网小标题「性能比肩顶级闭源模型」)、其余共用一句(V4.1 发布标题「更强、更快、更普惠」)。理由是模型会迭代:给某个版本写的描述会被下一代继承,给「已退场版本」写的描述又会挂在当前版本上,而线级文案没有这个问题(已记入 `docs/architecture.md` D5)。
26
+ - **去掉我们自己加的档位前缀**:此前多条家族与档位文案以「旗舰档:」「主力档:」「轻量档:」「高能力档:」「中端档:」开头——那是我们的定位话术,不是模型自己的说法。现在要么用厂商自己的定位句,要么直接说它做什么。例:Claude Fable 线写官网 tagline「新一代智能,专为解决最艰深的知识工作和编程难题」,而不是「顶级档位:新一代智能,专为解决最艰深的知识工作和编程难题」。
27
+ - **描述不再重复模型名与产品线名**:行里已经写着模型名,文案再以「X 系列:」「X 档:」「模型名:」开头就是同一句话说两遍。共改 50 条——16 条精确条目 + 32 条家族规则 + 2 条档位规则。例:GLM 家族规则从「智谱的开源大模型系列:覆盖对话、编程与智能体,支持思考模式与函数调用。」改成「覆盖对话、编程与智能体,支持思考模式与函数调用。」;Kimi K3 从「全球首个开源 3T 级模型:2.8T 参数、1M 上下文、原生多模态。」改成官网模型页标题去掉模型名之后的那半句「面向编程与知识工作的 2.8T 开源模型。」;Mistral Large 3、文心 5.0、ERNIE 等条目的「…:」结构改为逗号并列,事实一个不丢。DeepSeek 的三条线级文案按指定保持不变(DeepSeek 官网没有 per-model 模型页,`/news/*` 的标题是动词句,形状对不上)。
28
+ - **只剩规格的条目补上用途**:删掉标签后有几条只剩参数与价格(`gpt-5.4` 一度只剩「105 万 token 上下文、原生电脑操作。」),读起来不知道它是干什么用的。这些条目按 Kimi 那种「面向…的…」形状,把官网模型卡的用途句并回句首,共 10 条:`gpt-5.4`、`gemini-3.8-flash`、`glm-5.3`、`glm-5.3-flash`、`glm-5.3-flashx`、`kimi-for-coding-highspeed`、`qwen3.8-max`、`step-5-preview`、`step-3.7-flash`、`gpt-oss`。官网 tagline 不如现有事实句的(Codex「The same powerful coding agent—now in ChatGPT」、Gemma、Nano Banana)没有替换。
29
+
30
+ ### Fixed
31
+ - **几处已经过时或张冠李戴的模型说法**:(1) DeepSeek V4 Flash 与 V4 Flash Vision Exp 已下线、V4 Pro 已公告退场(旧模型名现由 V4.1 Flash 提供服务并按 Flash 价计费),这三条不再逐版本描述,改由线级映射给出文案;(2) Grok 4.5 的「最强」在 4.6 发布后已不成立,改为它自身的事实并注明有更新版本;(3) 文心 5.0 的「预训练成本极低」实为 ERNIE 5.1 的说法,换成官网确有的 2.4 万亿参数 / 每 token 激活约 3% / 128K 上下文;(4) `kimi-for-coding` 的官方名是 Kimi K2.7 Code,文案改按官方命名。
32
+ - **插件加载即崩(皮肤全崩)**:上一版把 `WORDMARK_SVGS` 从产物里删了,却没删 `model-brand.js` 里读它的那个**加载期 IIFE** → `ReferenceError: WORDMARK_SVGS is not defined` → 客户端半边整个加载失败。构建的语法门禁抓不到这类「引用一个已不存在的全局」——语法完全合法,跑起来才抛。补了 `.debug/bundle-load-check.cjs`:用桩跑一遍产物工厂,正反两次对照都验过(把引用注回去即 `FAIL factory runs`)。
33
+ - **锁定标占位但不显示**:源文件把 `fill="currentColor"` 与 `fill-rule="evenodd"` 放在**根 `<svg>` 上**、内部路径靠继承,而 vendoring 只取了内部内容 → 属性丢失、形状无填充(彩色层因为 `fill` 写在每条路径上反而正常,于是现象是「彩色图标在、字标不在」)。现在把根的绘制属性重新包一层 `<g>`,并去掉会变成 hover 提示的 `<title>`。
34
+ - **一级弹层「当前模型」那行的供应商、以及两级都显示模型描述**:三处相关调整。(1) 那行原先显示 `供应商id/模型id`,上一版按「外显名而非 id」改成了只显示模型名,把供应商整个丢了——现在格式定为 `模型 (供应商)`,两侧都是外显名(模型取目录里的 name,供应商取 `group.name`,目录没给名字时退回 id)。**带字标的模型同样带供应商**:字标只说明厂商,没说明这个席位由哪个 provider 提供,所以 `[KiMi]K3 (opencode)` 才是完整信息;供应商放在模型之后而不是之前,因为字标正站在标签开头。(2) 「更多模型」是每个 provider 的完整目录,描述行在那里只是噪声,改为只在第一级显示。(3) 一级那行补上描述——它和官方列表里的行一样是「读」的行,描述正是把模型区分开的东西。
35
+ - **冷启动后模型选择器要等几秒才有内容**:宿主的模型目录是每个 Host generation 一次 RPC(`remote.session.modelCatalog()`),而它**只在宿主自己菜单的 `show()` 里发起**——本皮肤把宿主的模型席位藏了起来,那个菜单永远不会打开,于是整趟往返都压在第一次打开选择器上(冷启动时是数秒的「正在加载模型…」)。现在插件在会话一解析出来就 `load()` 预热(`warmModelCatalog()`,每次安装只发一次、失败交给 store 的错误面),把这趟等待挪进用户本来就在等的启动过程;触发器的模型名标签读的也是同一份目录,所以它一起提前出来了。目录的 load 是共享在途且宿主侧缓存的,因此选择器自己那次 `load()` 变成空操作,而不是第二个请求。
36
+ - **Grok 行显示的是 xAI 的标识**:`brands.models` 里的 `{ "match": "grok", "brand": "xai" }` 把模型行指到了公司标识上——xAI 是公司、Grok 是模型线,所以 Grok 行该显示 Grok 自己的标记(provider 分组标题仍显示 xAI 的,因为 provider 只从 `providers` 解析,与模型行互不影响)。标识本来就在仓库里:`src/assets/icons/providers/grok.svg`(cc-switch 供应商集,路径数据与 Lobe 的 `grok.svg` 完全一致,只是带着 `<title>`/`style`/em 宽高),而选择器优先用 cc-switch 图标、缺失才回退 Lobe,所以这一处不必重新抓图,改映射即可。规则补了一条 note 说明这个分工。
37
+ - **一级弹层里「当前模型」那行显示的是 `供应商id/模型id`**:当选中模型不在官方服务上时,一级弹层会在官方列表下面补一行显示当前席位——但它直接把 `group.id + '/' + model.id` 当标签写了出来,于是那一行是 `openrouter/anthropic-claude-4.5` 这种 id 串,而它上下每一行都是模型的外显名。现在这行与其他行同一套标签逻辑(`buildModelName`,含厂商字标),只在目录没给名字时才退回 id;同时补上了行的 `data-brand`,所以它和列表里对应的那一行穿同一件厂商标记与字体。变更签名(判断是否需要重绘)仍然只比对 id——那是每轮 pass 都要算的热路径,而目录的名字在一次会话内是稳定的。
38
+
39
+ ## [0.3.1] - 2026-09-21
40
+
41
+ ### Added
42
+ - **声明最低运行时与商店截图清单**:`package.json` 的 `dsh` 对象新增 `engines.dsh: ">=0.1.5-rc.2"`(README 标注的实测版本),dsh-market.com 的插件卡片、插件管理器的更新检查与 awesome-dsh-plugin 商店的 host-aware 过滤都会读取它,避免在不满足条件的宿主上被安装或被误判不兼容;仓库根新增 `screenshots.json` 指向 `docs/light.png` 与 `docs/dark.png`,供 dsh-market 等商店以 App Store 式截图展示——截图随仓库推送更新、商店夜间构建自动拾取,之后换图不必再提任何 PR。
43
+ - **模型选择器里 Gemini 行的名称改用 Google Sans Flex**:模型行自 0.2.7 起带厂商标识,但名称仍与其他行同一字体——「这是 Google 的模型」这个信号只给了一半,同一行里标识说厂商、字体说本主题。现在 Gemini 行的名称用上游 Google Sans Flex 的标准字重正体绘制,与标识构成同一个信号。字体由 `scripts/slim-google-sans.py`(手工工具,不进构建——它需要 Python 与 fontTools,而本仓库的 Node 构建必须保持零依赖)从 4.2 MB 的六轴可变字体得到:6 个轴全部钉在**字体自身的默认值**(wght 400 / slnt 0 / wdth 100 / GRAD 0 / ROND 0 / opsz 18,默认值读自 `fvar` 而非写死,上游改默认值时这里不会静默改变「标准」的含义),只保留拉丁字母、数字与标签用得到的标点(ASCII 可打印、不换行空格、间隔号、长/短破折号、弯引号、省略号),并且只保留 `kern` 特性——标签里不该发生连字替换。产物 9 KB,随 npm 包分发,采用 SIL OFL 1.1(`fonts/OFL-GoogleSansFlex.txt` 带上游版权声明与许可证全文)。家族名改为 `Google Sans Flex Picker`:上游没有声明 Reserved Font Name,子集沿用原名并不违规,但一个只含拉丁字符的同名字体会在页面上盖掉用户系统里安装的完整版。样式表的挂载点是行上的 `data-brand`(厂商标识 id):今天只有 Gemini 解析到字体,其他厂商的行保持界面字体,将来给别的厂商加字体是加一行 CSS 的事;字体栈把界面字体留在后面,子集覆盖不到的字符逐个回落而不是变豆腐块。
44
+
45
+ ### Changed
46
+ - **亮暗切换时输入框一带「先色后样」已修复**:皮肤为 hover/focus 调的 0.12s 边框/阴影过渡(composer 卡、输入域、附件轨、hero 托盘)在主题翻转时被重放——画布随 CSS 变量一帧重绘,输入框的边框与 halo 却慢半拍缓入,亮暗切换的瞬间输入区一带肉眼可见分两步换。现在翻转瞬间在 `<html>`/`<body>` 上挂一个只存活约 0.3s 的抑制属性(`html[data-dsh-theme-transitioning] body[data-dsh-claude-style][data-dsh-theme-transitioning] * { transition: none !important }`),并在同一微任务里强制刷一次样式后取消所有进行中的绘制类过渡(`getAnimations()` 里 `transitionProperty` 属于边框/阴影/颜色/背景的 `cancel()`)——属性当帧跳到终值,盖住抑制规则特异性够不着的几条高优先级规则(输入域 (0,6,1)、附件轨 (0,7,1))。窗口结束即恢复,日常 hover/focus 的 0.12s 手感不受影响;只取消主题会改的绘制属性,transform/opacity 过渡(悬停、菜单反馈)照常运行。
47
+ - **composer 形态判断从 CSS 结构感知的 `:has()` 改为 JS 写属性,降低流式输出期间的样式重算开销**:皮肤原先用约 60 处 `[class*="composerStack"]` 上的 hero/inline 分支(`[class*="composerStack"]:has([class*="heroWorkspaceRow"])` 及其 `:not()` 形式)在 CSS 里判断输入卡处于主屏 hero 形态还是会话内联形态。流式输出时每秒几十次 DOM 变更,每次都要重算这些昂贵的选择器,是渲染压力的主要来源。现在 `syncSegments()` 在每轮 pass 里把同一个 `data-composer-variant="hero|inline"` 属性镜像写到卡片所属的 `composerStack` 祖先上(写前比对旧值避免同值重复写触发无谓的样式失效,同轮去重避免多卡命中同一栈反复写),CSS 改为直接读属性:hero 分支读 `[class*="composerStack"][data-composer-variant="hero"]`,inline 分支读 `[class*="composerStack"]:not([data-composer-variant="hero"])`。属性缺席时按 inline 渲染——inline 是流式高频路径,首帧不闪;hero 屏无流式,属性在首个 pass 补上即可。交互驱动与低频的 `:has()`(`:hover`、`:focus-within`、弹窗、placeholder)按原样保留。
48
+ - **设置页 Claude Style 导航 Tab 图标替换为 Claude 标识**:设置弹窗内「Claude Style」Tab 默认由宿主回退为通用的齿轮图标(`IconSettingsOutline16`)。现通过 CSS 蒙版与调度器轻量属性标记,将其替换为黑色的 Claude 经典星芒图标(亮色模式下为纯正墨黑,暗色模式下随文字主色白亮),与左侧导航栏其他选项的视觉语汇保持一致。
49
+ - **亮色模式背景层级色调调优**:为解决浅色界面在纯白控件反衬下局部偏黄的问题,将亮色模式的背景层级收敛至更清爽中性的象牙白阶梯:一级层级(`--dsw-alias-bg-layer-1`)对齐主画布采用 `#FCFCFB`,二级层级(`--dsw-alias-bg-layer-2`)调整为 `#FBFBF9`,三级层级(`--dsw-alias-bg-layer-3`)调整为 `#F9F9F6`;设置弹窗面板亦对齐主画布底色(`#FCFCFB`),保持整体视觉明净统一。
50
+ - **去 AI 化与精简**:清理 `.debug/` 临时调试日志与历史规划文档;移除 `src/overrides/` 拆分残留的旧章节编号与重复注释;精简 README 冗余功能表格并修正更新日志中对内部开发路径的提及。
51
+
52
+ ### Fixed
53
+ - **新对话页只贴图不打字时 hint 发黑、位置跑到输入框外**:宿主只在「草稿为空**且**没有附件」时才渲染自己的 placeholder(`draft === "" && attachments.length === 0`),所以在新对话页贴一张图、不打字,它会把自己的 hint 摘掉,改由皮肤的兜底节点接手——可那个节点身上没有任何宿主类名,而皮肤原有的 hint 规则只覆盖对话里的单行输入框(`data-composer-variant="inline"`),于是它退回成普通块级元素:用卡片正文的墨色(看着发黑),并且排在输入框**下面**而不是里面。现在给 hero 变体的兜底节点补上宿主那套定位与墨色(`position: absolute` + 宿主自己的 `inset: 4px 8px auto 14px`,caption 灰、单行省略),hint 回到输入框首行。验证时把宿主 composer 的样式表与构建产物里的皮肤样式表拼成 mock,逐项对照兜底节点与宿主自带 placeholder 的计算样式(8 项检查,含「修复前不成立」的反证)。
54
+ - **inline 输入框聚焦时的底纹把输入框刷成了另一种颜色**:会话内单行输入框聚焦时,画布色的三层底纹(`box-shadow`)原本挂在 rail 上,而 rail 是 `z-index: 4`、输入框本体是 `z-index: 2`——底纹于是刷在输入框**上面**:盖住输入框自己的背景(两个盒子读起来不同色),也盖住草稿第一行。现在底纹移到卡片(`[data-composer-card]`)身上,与 hero 卡片同一位置,所有子元素共用一个底纹,谁也压不住谁;rail 那份去掉,亮暗两态的 rail 规则只保留描边色。
55
+ - **封号彩蛋语言选不动**:设置里选「中文」立刻弹回英文,且没有任何提示。根因是宿主半边(`lib/index.js`)只在 app 启动时被 import 一次,而它是后来才认识 `banLocale` 这个字段的——旧宿主半边的写入口不认这个键,把它丢掉之后按「没有可写字段」当成一次读取返回,客户端拿到原值就把刚做的选择覆盖回去了(浏览器半边每次刷新都是新的,宿主半边不是,两边版本就此错位)。现在 `banLocale` 与用户名走同一套浏览器本地兜底:宿主不认这个键时把选择存在本地(`localStorage`)并立刻按它渲染,页面刷新后仍在;等宿主半边重启、第一次读取时自动把待写入的值补写一次,宿主回显确认后本地兜底才清除——所以选择既不会丢,也不会和宿主长期打架。
56
+
3
57
  ## [0.3.0] - 2026-09-20
4
58
 
5
59
  ### Added
@@ -8,7 +62,7 @@
8
62
 
9
63
  ### Changed
10
64
  - **封号页的锁改为手绘描摹**:那页顶部的锁此前是 `rect` + `circle` 拼出来的标准图标,跟参考草图的手绘气质不搭。现在整把锁按参考图(89×92px)的墨迹中心线逐锚点描摹成三条三次贝塞尔路径——方框的每条「直」边都带一点自己的倾斜与漂移(顶边右低、底边微垂、左边下行时外移、右边绕过锁孔处外鼓再收回),四角用一小段斜线收口,锁梁里外两拱不同心、两条腿停在方框顶边上而不穿过它,锁孔的头部比正圆扁、腰身偏右、底座比头更宽。手绘感来自锚点本身,不是滤镜也不是随机抖动,所以缩放到任何尺寸都成立;锚点数值整体映射到图标集统一的 24 单位格(墨迹 15.3×20 单位居中),图标框 58px → 75px(墨迹 47.5px → 62.8px,约 +32%),描边 0.5 单位。选这两个数是量出来的:参考页里「锁的墨迹高 ÷ 标题墨迹高」是 3.08,改完是 2.70(此前 2.05);参考页的「线宽 ÷ 锁高」是 0.025,改完实测 0.0250(此前 0.075,粗了近三倍)。
11
- - **修掉 `banSvg` 的重复属性**:图标助手此前把 `stroke-width` 追加在 `<svg>` 已有的一条之后,形成重复属性——HTML 解析器只认第一条,于是覆盖静默失效,锁实际按图标集的 1.6 画(在 58px 框里近 3.9px),这正是它看起来「线条太粗」的原因。现在粗细是 `banSvg(body, strokeWidth)` 的形参,只发一条属性;`.debug` 里的校验脚本会数属性条数,防止再犯。
65
+ - **修掉 `banSvg` 的重复属性**:图标助手此前把 `stroke-width` 追加在 `<svg>` 已有的一条之后,形成重复属性——HTML 解析器只认第一条,于是覆盖静默失效,锁实际按图标集的 1.6 画(在 58px 框里近 3.9px),这正是它看起来「线条太粗」的原因。现在粗细是 `banSvg(body, strokeWidth)` 的形参,只发一条属性,杜绝属性覆盖失效。
12
66
  - **点击展开的账户弹层不再被鼠标移出关掉**:此前点账户按钮展开弹层后,指针一离开按钮(弹层挂在按钮下方,指针必须离开)就被 `mouseleave` 关掉,等于点开即关、弹层里的条目够不着;现在点击展开的弹层改为由「点击别处」或「移出整个底栏」关闭,悬停展开仍按原来的延迟关闭逻辑。
13
67
  - **账户弹层:账号名下的横线移出 hover 区**:弹层顶部原来是「整块(含横线)在 hover 时整体铺底」,指针扫过横线也会亮;现在横线是账号行的兄弟节点、归弹层所有(左右通栏到弹层内边距边缘),hover 底板只覆盖账号名那一行。
14
68
  - **封号页排版**:内容列由靠左改为水平居中;页头(左上角品牌标 + 右上角 Sign out 与窗口控制)整体下移 30px。
@@ -17,7 +71,7 @@
17
71
  ### Fixed
18
72
  - **回退引用块的链接材质**:0.2.7 把 Markdown 引用块(`blockquote`)改成了链接材质(蓝字 + 蓝色下划线 + 蓝色底纹/竖条),但引用是**容器**而不是链接,这套样式会连同块内的行内代码、文件引用一起染蓝,等于让链接材质泄露进引用块。现回退为原来的中性灰:文字 `#B0AEA5`(亮色 `#6E6A60`)、灰底 + 灰竖条,块内的链接、行内代码片、文件引用各自保持自己的材质,互不串色。`padding` 也不再需要 `!important` 钉死。
19
73
  - **文件引用(行内文件名)颜色与超链接不一致**:聊天里的 `` `CHANGELOG.md` `` 这类**文件引用**是宿主把行内代码里的文件路径解析成按钮(`.fileMention`)后的产物,但皮肤的通配行内代码规则(`code:not(pre code)`,特异性 (0,2,1))压过宿主自己的链接色类((0,1,0)),于是同一段话里文件引用是代码片的暖红、真正的超链接是链接蓝。现在文件引用的文字改用链接色(亮 `#184F95` / 暗 `#8AB4F8`)、字重 500,下划线沿用超链接那一套(静止态实线、链接色调 60%、1.5px、offset 2px;hover/focus 同样实线、换成不透明的链接色,**线宽与线位不变**),**代码片本身完全不动**——底纹、描边、圆角、内边距与普通行内代码逐项相同,只有文字颜色不同。hover 规则只改颜色:先前用 `text-decoration` 简写会把 `text-decoration-thickness` 重置为 `auto`,导致 hover 时下划线反而变细。普通行内代码仍是暖红代码片;宿主类名带哈希,故按仓库纪律取最长稳定片段 `[class*="_fileMention"]`。
20
- - **修复 Markdown 表格左侧空隙**:删除旧的全局 `table { width:100% }`、`table th` 背景与 `td/th { padding: 0.6em 0.85em !important }` 规则,避免覆盖宿主 `th:first-child { padding-left: 0 }` 和 `width: max-content`,表格过宽时不再出现左侧空白与外部边框错位。 同时对全部 `.tableScroll` 包装器强制 table margin/padding/border-spacing 归零,首/末单元格恢复 16px 内边距,并把表头背景与行线覆盖到 `thead th/td` 和每行首末单元格(th 或 td),使首列的留白看起来是表格内部区域而不是空隙。
74
+ - **修复 Markdown 表格左侧空隙**:删除旧的全局 `table { width:100% }`、`table th` 背景与 `td/th { padding: 0.6em 0.85em !important }` 规则,避免覆盖宿主 `th:first-child { padding-left: 0 }` 和 `width: max-content`,表格过宽时不再出现左侧空白与外部边框错位。 同时对全部 `.tableScroll` 包装器强制 table margin/padding/border-spacing 归零,首/末单元格恢复 16px 内边距,并把表头背景与行线覆盖到 `thead th/td` 和每行首末单元格(th 或 td),使首列的留白看起来是表格内部区域而不是空隙。 另外,窄表不再被宿主 `.tableFill` 拉满:`.tableScroll` 宽度限制到正文内容块 `--dsh-chat-content-width` 并居中,表格用 `min-width: 100%` 撑满内容块;宽表保持 `max-content` 并保留横向滚动。
21
75
 
22
76
  ## [0.2.7] - 2026-09-20
23
77
 
package/LICENSE CHANGED
@@ -39,3 +39,12 @@ owners.
39
39
  are JetBrains Mono, distributed under the SIL Open Font License
40
40
  (`fonts/OFL.txt`). They may be redistributed with this plugin.
41
41
 
42
+ - `fonts/GoogleSansFlexPicker.woff2` is a Latin-only subset of Google Sans Flex
43
+ (standard weight, upright), built by `scripts/slim-google-sans.py` and renamed
44
+ to `Google Sans Flex Picker`. Google Sans Flex is distributed under the SIL
45
+ Open Font License (`fonts/OFL-GoogleSansFlex.txt`, Copyright 2022 The Google
46
+ Sans Flex Project Authors); upstream declares no Reserved Font Name, and this
47
+ subset is renamed so it cannot shadow a full system-installed copy. It ships
48
+ with the npm package and may be redistributed with this plugin, under no other
49
+ licence.
50
+
package/README.en.md CHANGED
@@ -25,17 +25,18 @@
25
25
 
26
26
  ## Fonts
27
27
 
28
- > **Important: the JetBrains Mono code font ships with the plugin and is served to the browser as a webfont by the plugin host — no installation needed. The Anthropic Sans/Serif fonts are NOT shipped with the npm package**; they remain in the repository [`fonts/`](fonts/) for download. You can either install them on the system, or skip installation entirely: drop the two `.ttf` files into the plugin package's `fonts/` directory and the host serves them as webfonts the same way (identical files, identical result). Either way, refresh / restart web afterwards.
28
+ > **Important: the JetBrains Mono code font, plus the Google Sans Flex Picker face used only by Gemini rows in the model picker, ship with the plugin and are served to the browser as webfonts by the plugin host — no installation needed. The Anthropic Sans/Serif fonts are NOT shipped with the npm package**; they remain in the repository [`fonts/`](fonts/) for download. You can either install them on the system, or skip installation entirely: drop the two `.ttf` files into the plugin package's `fonts/` directory and the host serves them as webfonts the same way (identical files, identical result). Either way, refresh / restart web afterwards.
29
29
 
30
30
  | Font | Used for | File |
31
31
  |---|---|---|
32
32
  | Anthropic Sans Web Text | UI chrome | [`fonts/AnthropicSansWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/AnthropicSansWebText.ttf) |
33
33
  | Anthropic Serif Web Text | Conversation body / markdown | [`fonts/AnthropicSerifWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/AnthropicSerifWebText.ttf) |
34
34
  | JetBrains Mono Variable | Code / code blocks | [`fonts/JetBrainsMonoVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/JetBrainsMonoVariable.ttf), [`fonts/JetBrainsMonoItalicVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/JetBrainsMonoItalicVariable.ttf) |
35
+ | Google Sans Flex Picker | Model picker · Gemini row name | Shipped with the package: [`fonts/GoogleSansFlexPicker.woff2`](fonts/GoogleSansFlexPicker.woff2) |
35
36
 
36
37
  Enabling the Anthropic faces (pick one): ① install on the system — double-click the `.ttf` on Windows → *Install*, or import via *Font Book* on macOS; ② no-install — copy the `.ttf` files into the plugin package's `fonts/` directory (next to `JetBrainsMonoVariable.ttf`). Refresh the page afterwards.
37
38
 
38
- > JetBrains Mono is distributed under the [SIL Open Font License](fonts/OFL.txt). The Anthropic Sans/Serif typefaces are Anthropic's property, provided for personal use only and not covered by the MIT license above. See [LICENSE](LICENSE) for the font notice.
39
+ > JetBrains Mono is distributed under the [SIL Open Font License](fonts/OFL.txt). Google Sans Flex Picker is a renamed Latin-only subset of Google Sans Flex, distributed under the same [SIL Open Font License](fonts/OFL-GoogleSansFlex.txt). The Anthropic Sans/Serif typefaces are Anthropic's property, provided for personal use only and not covered by the MIT license above. See [LICENSE](LICENSE) for the font notice.
39
40
 
40
41
  ## Install
41
42
 
@@ -56,7 +57,7 @@ Only one theme should be active at a time. After installing, **restart `dsh web`
56
57
 
57
58
  1. **Theme** — applies the whole canvas automatically after install; no configuration needed. Light and dark follow the system color scheme.
58
59
  2. **Permission segments** — the composer gets a Read | Edit | Auto segmented control replacing the shipped access-mode menu: read-only, workspace write, and full access (Auto is switched through the shipped risk-confirmation dialog).
59
- 3. **Model picker** — the composer's model seat becomes a two-level Claude-style menu: the first level lists DeepSeek's official models, a divider, the reasoning-effort row and "More models", and the second opens beside it. Every model row carries the mark of the **vendor that made the model** (not the provider reselling it), and the "More models" group headers carry the provider's mark. The marks are [Lobe Icons](https://lobehub.com/icons) mono glyphs painted in the theme's own text colour, so they stay legible on both canvases no React dependency, and no full-colour logos.
60
+ 3. **Model picker** — the composer's model seat becomes a two-level Claude-style menu: the first level lists DeepSeek's official models, a divider, the reasoning-effort row and "More models", and the second opens beside it. Model descriptions appear on the first level only (including the row for the current selection, which reads `model (provider)` in display names); the "More models" level is every provider's full catalog and lists names alone. Every model row carries its **vendor's lockup** — the mark and the vendor's wordmark composed into one piece of art, drawn in place of the vendor's name inside the label (`[DeepSeek whale + wordmark] V4.1-Flash`); a name that never spells the vendor (Kimi's own catalog calls the model `K3`) leads with the lockup instead. The "More models" group headers carry the provider's name alone, no mark. The artwork is [Lobe Icons](https://lobehub.com/icons) (MIT), composed before the build into one `<svg>` per vendor (43 of them, no React dependency). The mark's size and the gap after it are **global constants**, not Lobe's per-icon `TEXT_MULTIPLE`/`SPACE_MULTIPLE` — those ratios are relative to each wordmark's own box, which made every vendor's mark a different size and every gap a different width; the brand colours and variant list come from `es/toc.js`. The colour artwork draws on the ivory canvas, with any fill that cannot be read there swapped to `currentColor` (Kimi's white K would vanish, its blue dot stays); the warm black canvas gets the mono layer in the theme's text colour. A few vendors override the lockup in `brands.lockups`: the two halves may come from different icons (Hunyuan's mark with Tencent's wordmark), the word it stands in for may be spelled differently (`Step` for `step-*`, also `MiMo` and `GLM`), and a wordmark may be cropped (GLM-V drops its `-V`, ChatGPT keeps only `GPT`); hand-provided artwork lives in `src/assets/icons/`, beside the generated `combine/` directory. A wordmark has to match the word it stands in for: Claude rows draw Claude's and Grok rows draw Grok's, not their parent companies' — and Claude's remaining text is set in Anthropic Serif, because that lockup is serif lettering. Hidden text keeps the full vendor name in the accessibility tree, so a screen reader still hears "Kimi K3" rather than "K3".
60
61
  4. **Brand switch** — Settings (`Ctrl+,`) → **Claude Style**: the sidebar brand flips between the Claude starburst + the official Claude wordmark and Anthropic (`A\` + ANTHROPIC wordmark); the hero mark follows the choice with the clay fill. The choice persists in the browser; `claude` is the default.
61
62
  5. **Account drawer** — the sidebar footer button opens a hover popover with quick access to Settings (`Ctrl+,`) and plugin management; the username row at its top is an easter egg: it opens Claude's own "Your account is on hold" page (a purely local reproduction that touches no real state — click any control on it, or press `Esc`, to leave; it deliberately stays put when the window loses focus, so you can switch away and read it). That page's language is its own setting (**Account-hold easter egg language**, Chinese/English, English by default).
62
63
  6. **Status polish** — thinking turns pick one of Claude Code's 185 spinner verbs per turn; the workspace loading state uses a Fluent-style circular indicator.
package/README.md CHANGED
@@ -26,17 +26,18 @@
26
26
 
27
27
  ## 字体
28
28
 
29
- > **重要:JetBrains Mono 代码字体随插件库分发,由插件宿主以 webfont 形式直接提供给浏览器,无需安装。Anthropic 字体(Sans/Serif)不随 npm 包分发,仅在仓库 [`fonts/`](fonts/) 供下载**——既可以直接安装到系统,也可以免安装:把两个 `.ttf` 放进插件包的 `fonts/` 目录,宿主会以同样的 webfont 方式提供它们(两种方式的字体文件完全一致,效果相同)。生效均需刷新 / 重启 web。
29
+ > **重要:JetBrains Mono 代码字体、以及模型选择器里 Gemini 行专用的 Google Sans Flex Picker,都随插件库分发,由插件宿主以 webfont 形式直接提供给浏览器,无需安装。Anthropic 字体(Sans/Serif)不随 npm 包分发,仅在仓库 [`fonts/`](fonts/) 供下载**——既可以直接安装到系统,也可以免安装:把两个 `.ttf` 放进插件包的 `fonts/` 目录,宿主会以同样的 webfont 方式提供它们(两种方式的字体文件完全一致,效果相同)。生效均需刷新 / 重启 web。
30
30
 
31
31
  | 字体 | 用途 | 文件 |
32
32
  |---|---|---|
33
33
  | Anthropic Sans Web Text | 界面 / UI | [`fonts/AnthropicSansWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/AnthropicSansWebText.ttf) |
34
34
  | Anthropic Serif Web Text | 对话正文 / Markdown | [`fonts/AnthropicSerifWebText.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/AnthropicSerifWebText.ttf) |
35
35
  | JetBrains Mono Variable | 代码 / 代码块 | [`fonts/JetBrainsMonoVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/JetBrainsMonoVariable.ttf)、[`fonts/JetBrainsMonoItalicVariable.ttf`](https://github.com/Nwflower/dsh-claude-style/raw/main/fonts/JetBrainsMonoItalicVariable.ttf) |
36
+ | Google Sans Flex Picker | 模型选择器 · Gemini 行名称 | 随包分发:[`fonts/GoogleSansFlexPicker.woff2`](fonts/GoogleSansFlexPicker.woff2) |
36
37
 
37
38
  Anthropic 字体启用(二选一):① 安装到系统——Windows 双击 `.ttf` → 「安装」,macOS 用「字体册」导入;② 免安装——把 `.ttf` 复制到插件包的 `fonts/` 目录(与 `JetBrainsMonoVariable.ttf` 同目录)。完成后刷新页面生效。
38
39
 
39
- > JetBrains Mono 以 [SIL Open Font License](fonts/OFL.txt) 分发;Anthropic Sans/Serif 字体版权归 Anthropic 所有,仅供个人使用,不适用 MIT 许可(详见 [LICENSE](LICENSE) 字体声明)。
40
+ > JetBrains Mono 以 [SIL Open Font License](fonts/OFL.txt) 分发;Google Sans Flex Picker 是 Google Sans Flex 的拉丁子集(已改名),同样以 [SIL Open Font License](fonts/OFL-GoogleSansFlex.txt) 分发;Anthropic Sans/Serif 字体版权归 Anthropic 所有,仅供个人使用,不适用 MIT 许可(详见 [LICENSE](LICENSE) 字体声明)。
40
41
 
41
42
  ## 安装
42
43
 
@@ -57,7 +58,7 @@ dsh plugin --profile web add Nwflower/dsh-claude-style # GitHub 源
57
58
 
58
59
  1. **主题** —— 安装即全局生效,无需配置;亮暗跟随系统颜色模式。
59
60
  2. **权限分段** —— 输入框以 Read | Edit | Auto 三段式控制器替换原生的访问模式菜单:只读、工作区写入与完全权限(Auto 经宿主的安全确认弹窗切换)。
60
- 3. **模型选择器** —— 输入框的模型席位换成 Claude 风格的两级弹层:一级列出 DeepSeek 官方模型、分隔线、推理等级与「更多模型」,二级在右侧展开。每个模型行显示**所属厂商**的标识(不是转售该模型的 provider),「更多模型」的分组标题显示 provider 的标识。标识取自 [Lobe Icons](https://lobehub.com/icons) 的单色字形,跟随主题文字色绘制,因此亮暗两套画布都清晰;不引入 React 组件依赖,也不使用彩色 logo。
61
+ 3. **模型选择器** —— 输入框的模型席位换成 Claude 风格的两级弹层:一级列出 DeepSeek 官方模型、分隔线、推理等级与「更多模型」,二级在右侧展开。模型描述只出现在第一级(含当前选中的那一行,格式为「模型 (供应商)」的外显名);二级「更多模型」是各 provider 的完整目录,只列名称。每个模型行显示**所属厂商的锁定标**——图标与厂商字标合成的一件图形,直接替换名称里的厂商名(`[DeepSeek 鲸鱼+字标] V4.1-Flash`);名称里没有厂商词的(Kimi 官方目录只叫 `K3`)则锁定标领在开头。「更多模型」的分组标题只显示 provider 名称,不带图标。图形取自 [Lobe Icons](https://lobehub.com/icons)(MIT),在构建前的 vendoring 阶段合成为 43 个厂商各一个 `<svg>`,不含 React 依赖。图标高度与间距是**全局常数**——不逐家采用 Lobe 的 `TEXT_MULTIPLE`/`SPACE_MULTIPLE`,那套比例是相对各家字标盒子的,会让图标大小与间距逐家漂移;品牌色与变体清单取自 `es/toc.js`。亮色画布用彩色原图,其中在象牙白上读不出来的填充换成 `currentColor`(Kimi 的白 K 会消失、而它的蓝点保留);暖黑画布换成单色、跟随主题文字色。少数厂商在 `brands.lockups` 里覆写:图标与字标可来自不同图标(混元的标 + Tencent 的字标)、匹配词可指定(`step-*` 用 `Step`,另有 `MiMo`、`GLM`)、字标可裁掉多余部分(GLM-V 截掉 `-V`、ChatGPT 只留 `GPT`);手工提供的资产放 `src/assets/icons/`(与生成的 `combine/` 同级)。字标要和它替换的词对得上:Claude 行画 Claude 的、Grok 行画 Grok 的,而不是各自母公司的;Claude 行的其余文字用 Anthropic Serif 排(那枚锁定标本身就是衬线体)。名称里另有视觉隐藏的厂商名,屏读听到的仍是「Kimi K3」而不是「K3」。
61
62
  4. **品牌切换** —— 设置(`Ctrl+,`)→ **Claude Style**:侧栏品牌在 Claude(官方星芒 + Claude 字标)与 Anthropic(`A\` + ANTHROPIC 字标)之间切换,新会话页标识随所选品牌保持陶烬橙星芒;选择保存在浏览器本地,默认 Claude。
62
63
  5. **账户抽屉** —— 侧栏底栏的账户按钮悬停展开弹层,一键打开设置(`Ctrl+,`)与管理插件;弹层顶部那条用户名横条是个彩蛋:点开会看到 Claude 官方的「账户已暂停」页(纯本地复刻,不碰任何真实状态,点页面上任意按钮或按 `Esc` 退出;切走窗口**不会**关,方便你切出去照着它看)。这页的语言在设置里单独选(**封号彩蛋语言**,中文/英文,默认英文)。
63
64
  6. **状态细节** —— 思考状态每轮从 Claude Code 的 185 个思考动词随机抽取一个稳定展示;工作区运行中状态使用 Fluent 风格的圆形加载动画。
@@ -79,18 +80,6 @@ dsh plugin --profile web remove dsh-claude-style # 卸载
79
80
 
80
81
  然后重启 `dsh web`;若曾在 `cordis.patch.yml` 手工添加过本主题的条目,一并删除。
81
82
 
82
- ## 功能一览
83
-
84
- | 能力 | 入口 | 说明 |
85
- | --- | --- | --- |
86
- | Claude 视觉 | 全局 | 象牙白/暖黑双画布、陶烬橙唯一强调色、衬线展示标题 + 无衬线界面 + 等宽代码三字体分工 |
87
- | 权限控制器 | 输入框浮层 / 新会话分段 | Read · Edit · Auto 三段切换会话权限,Auto 走宿主安全确认 |
88
- | 模型选择器 | 输入框模型席位 | 两级弹层(官方模型 / 推理等级 / 更多模型);模型行按厂商、分组标题按 provider 显示单色品牌标识 |
89
- | 品牌切换 | 设置 → Claude Style | Claude(星芒 + Claude 字标)与 Anthropic(`A\`)双标识,选择持久化 |
90
- | 状态动画 | 会话运行中 | 185 个思考动词随机展示;Windows 11 Fluent 风格圆形加载器 |
91
- | 账户抽屉 | 侧栏底栏 | 悬停展开弹层,直达设置与管理插件 |
92
- | 封号页彩蛋 | 账户弹层顶部的用户名横条 | 复刻 Claude「Your account is on hold」整页,点任意按钮或按 `Esc` 退出(切走窗口不关);语言由「封号彩蛋语言」设置决定(默认英文) |
93
-
94
83
  ## 文档
95
84
 
96
85
  | 文档 | 说明 |
package/docs/STYLE.md CHANGED
@@ -6,10 +6,10 @@ Design tokens for `dsh-claude-style`, recreating the Claude Code Desktop aesthet
6
6
 
7
7
  | Token | Value | Use |
8
8
  |---|---|---|
9
- | ivory light | `#FCFCFB` | light canvas |
10
- | sidebar light | `#FBFBF9` | light sidebar |
11
- | ivory | `#F0EEE6` | secondary surfaces |
12
- | ivory dark | `#E8E6DC` | hover / section bg |
9
+ | ivory light | `#FCFCFB` | light canvas / layer 1 |
10
+ | sidebar light | `#FBFBF9` | light sidebar / layer 2 |
11
+ | ivory neutral | `#F9F9F6` | layer 3 / section bg |
12
+ | ivory border | `#E8E6DC` | border l1 |
13
13
  | slate dark | `#141413` | text (light mode), canvas (dark mode) |
14
14
  | warm gray | `#B0AEA5` | metadata |
15
15
  | clay | `#D97757` | single accent — CTA / links |
@@ -26,6 +26,12 @@ Rules:
26
26
  - **Serif display** — headings / editorial statements (`--dsw-font-serif`).
27
27
  - **Sans UI** — chrome, body (`--dsw-font-family`).
28
28
  - **Mono** — code, technical labels (`--dsw-font-code`).
29
+ - **Vendor face** — one model name in the picker, where the row already wears the
30
+ vendor's mark (`--dsw-font-brand-gemini`: a Latin-only Google Sans Flex subset,
31
+ standard weight, SIL OFL 1.1). A vendor face is a *material*, not a new UI role:
32
+ it never replaces the sans stack, it sits in front of it, so text the subset does
33
+ not cover falls through instead of turning to tofu. Rebuilt with
34
+ `scripts/slim-google-sans.py`; licence in `fonts/OFL-GoogleSansFlex.txt`.
29
35
 
30
36
  ## Shapes
31
37
 
@@ -103,8 +109,8 @@ assembles the bundle:
103
109
  |---|---|
104
110
  | `src/constants.js` | constants, spinner verbs, shared token values (evaluated at build time to fill `%%TOKEN%%` placeholders) |
105
111
  | `src/assets/brand/*.svg` | brand marks, inlined as CSS `url()` data URIs at build time (the loader exposes no asset URLs) |
106
- | `src/assets/icons/lobe/*.svg` | model-vendor marks (Lobe Icons mono, MIT), inlined as a JS markup table at build time; bound to providers/models by `model-descriptions.json` → `brands` |
107
- | `src/assets/icons/providers/*` | cc-switch provider/vendor icon set (MIT); inline SVGs are bundled, raster/imported files are served by the host route |
112
+ | `src/assets/icons/combine/*.svg` | vendor lockups (Lobe Icons mark + wordmark composed into one SVG, MIT), inlined as JS markup tables at build time; bound to models by `model-descriptions.json` → `brands` |
113
+ | `src/assets/icons/*.svg` | hand-provided lockup artwork (e.g. ChatGPT), which the vendoring step prefers over anything fetched; `brands.lockups` may also point a brand's two halves at different Lobe icons or crop a wordmark |
108
114
  | `src/styles/tokens.css` | design tokens (dark base + ivory light) |
109
115
  | `src/styles/typography.css` | serif display / sans UI / mono code, editorial markdown |
110
116
  | `src/styles/chrome.css` | canvas, hairlines, clay accent, chrome details |
@@ -153,14 +159,16 @@ the catalog's own text; family rules are ordered and must stay anchored (the
153
159
  DeepSeek's copy).
154
160
 
155
161
  The same document carries the picker's **brand marks** under `brands`:
156
- `brands.providers` maps a provider route id to a vendored mark (the level-2
157
- group header), and `brands.models` is an ordered, anchored rule list matching a
158
- model id (the row's vendor the vendor that made the model, not the aggregator
159
- reselling it, with the provider's mark as the fallback). Both name ids vendored
160
- in `src/assets/icons/lobe/`, and the build fails on an id that is not there, so the
161
- binding cannot drift. The marks are the **mono** Lobe Icons glyphs
162
- (`fill="currentColor"`), stamped into the row as markup: the theme's own text
163
- colour paints them, which keeps them legible on both canvases and keeps the
162
+ `brands.providers` is deliberately empty a model no rule claims draws **no**
163
+ lockup rather than its provider's, because a reseller's own lockup on a model it did
164
+ not make reads as a wrong answer rather than a missing one. `brands.models` is an
165
+ ordered, anchored rule list matching a model id (the row's vendor the vendor that
166
+ made the model, not the aggregator reselling it). Both name ids with a vendored lockup in
167
+ `src/assets/icons/combine/` or a provider icon key, and the build fails on an id
168
+ that is not there, so the binding cannot drift. A lockup carries the vendor's mark
169
+ and its wordmark as one piece of art: the colour mark on the ivory canvas, the
170
+ mono one in `currentColor` on the warm black canvas (where a brand colour like
171
+ `#000` would vanish), so the label stays legible on both.
164
172
  palette to its single clay accent. Full-colour variants are deliberately not
165
173
  used — a third of the vendors ship no colour version (OpenAI, Anthropic, xAI,
166
174
  Moonshot, Z.ai, Vercel, Groq), and several brand colours are near-black on the
@@ -0,0 +1,74 @@
1
+ # 架构决策记录
2
+
3
+ 本文件记录本仓库**为什么**是现在这个样子:每条决策写背景、决定、代价,以及什么情况下允许重审。
4
+ 操作手册看 README,硬性规则看 AGENTS.md,视觉令牌看 docs/STYLE.md;本文件只管「权衡」。
5
+
6
+ 执行约束:
7
+
8
+ - 任何重构/拆分方案若与本文件已记录的决策冲突,必须先修改对应条目、说明旧决策为何失效,再动手。禁止静默推翻。
9
+ - 新决策追加在文末,编号递增,不删旧条目;被推翻的条目改为「已废弃 + 指向新决策」。
10
+
11
+ ---
12
+
13
+ ## D1. 零构建工具链,构建期逐字拼接
14
+
15
+ - **背景**:DSH Web 的模块加载器没有相对 require、没有资产 URL 机制,常规打包器(esbuild/rollup)产出的 chunk 拆分与资产引用无处安放。
16
+ - **决定**:`scripts/build.mjs` 把 `src/` 碎片按固定顺序逐字拼接成单个 `lib/client.js`;所有碎片共享一个工厂作用域,禁止 import/export,React 只能经加载器 `require('react')` 取得;资产(SVG/字体)构建期内联为 data URI 或走宿主路由。
17
+ - **代价**:碎片写法受限(ES5 风格、4 空格基础缩进、`%%TOKEN%%` 占位);没有 tree-shaking,bundle 体积靠自律控制。
18
+ - **重审条件**:DSH 加载器原生支持 ES module 相对导入与资产 URL 之时。
19
+
20
+ ## D2. 纯浏览器半边实现,不动宿主
21
+
22
+ - **背景**:主题是皮肤,不应 fork DSH;宿主升级要快跟随。
23
+ - **决定**:一切效果通过 CSS 覆盖与客户端 DOM override 实现;宿主半边(`lib/index.js`)只提供静态路由(模型文案 JSON、位图图标)。
24
+ - **代价**:依赖宿主带哈希的 CSS-module 类名,宿主改版可能击穿选择器——用 D3 的纪律和 probe 回归对冲。
25
+ - **重审条件**:DSH 官方开放主题 API / 插槽覆盖所 target 的区域时,逐步迁移过去。
26
+
27
+ ## D3. 宿主选择器纪律:最长稳定片段
28
+
29
+ - **背景**:宿主类名带哈希(`_54WpYG_imageItem`),短子串(`[class*="row"]`)极易误伤不相关组件,曾出过事故。
30
+ - **决定**:子串匹配只用最长稳定片段(`[class*="_row"]`);不得覆盖 `[class*="viewArea"]` 的活跃期布局契约;新增子串选择器必须检查误伤面。
31
+ - **代价**:选择器冗长;需要人肉维护「哪些片段稳定」的经验。
32
+ - **重审条件**:宿主提供稳定的 data-* 契约后全面迁移。
33
+
34
+ ## D4. composer 样式构建期门控(composer-gate)
35
+
36
+ - **背景**:composer 是性能与正确性最敏感的区域;皮肤规则若在未启用皮肤时泄漏到宿主 DOM 会造成事故。
37
+ - **决定**:composer 相关规则必须位于 `/* @composer-gate */` 标记之下,构建把 `[%%COMPOSER_ATTR%%]` 门控盖到标记以下每条规则,漏盖即构建失败。
38
+ - **代价**:写 composer 样式多一道心智负担;构建脚本要维护门控逻辑。
39
+ - **重审条件**:无(这是安全网,不是权衡)。
40
+
41
+ ## D5. 模型文案是数据,不进 bundle
42
+
43
+ - **背景**:模型目录日新月异,文案更新不应要求改 JS 发版。
44
+ - **决定**:`src/model-descriptions.json` 构建期校验后复制到 `lib/`,浏览器首次绘制选择器时经宿主路由 fetch;查找按 精确条目 → 家族规则 → 档位规则 → 目录自带文本 逐级降级;不写「最强/旗舰」等最高级(钉住版本的精确条目除外)。两条附加纪律:**文案是「线」的文案,不是「版本」的文案**——同一条产品线(如 DeepSeek 的 Flash / Pro)按名字模式映射到同一句,版本迭代与退场都不改这句话,因为过时版本会命中同一条规则,给某个版本写的描述最终会挂在别的版本上;**不写我们自己加的档位前缀**(「旗舰档:」「顶级档位:」),文案要么是厂商自己的定位句,要么直接说它做什么——前缀是我们的定位话术,会随产品线换代变成假话;**描述也不重复模型名**——行里已经写着模型名,文案再以「X 系列:」「X 档:」开头就是重复,只写后半句(Kimi K3 那条就是官网模型页标题去掉「Kimi K3:」之后的部分)。
45
+ - **代价**:首次绘制选择器有一次异步 fetch;文案体系有学习成本。
46
+ - **重审条件**:宿主模型目录 API 直接提供本地化文案时。
47
+
48
+ ## D6. 单一 scheduler 统一所有 override 的生命周期
49
+
50
+ - **背景**:多个 override 各自挂 observer/listener 会互相踩踏、泄漏、重复扫树。
51
+ - **决定**:`overrides/scheduler.js` 持有唯一的 MutationObserver(body 子树、attributes 过滤到 aria-label/aria-selected),用 requestAnimationFrame 合并为每帧一次 pass,统一驱动各 `ui.*.sync()`;teardown 统一清理。
52
+ - **代价**:每个 sync 必须有廉价的 early-out;新增 override 要接入同一调度器而不是自立门户。
53
+ - **已知代价与对策**:流式输出期间每帧一次全量 pass 是性能热点,见 D9。
54
+
55
+ ## D7. UI 行为优化内置在本插件,不拆独立插件(2026-09 定)
56
+
57
+ - **背景**:模型选择器、权限分段、账户抽屉等「UI 优化」与皮肤共享同一套宿主锚点(选择器纪律)、同一调度器(D6)、同一 popover 工具与 teardown。
58
+ - **决定**:行为层(`src/overrides/`)与皮肤层(`src/styles/`、tokens、品牌资产)在源码内保持分离,但发布为同一个包。不想要 Claude 皮肤的用户用设置里的品牌切换回到接近宿主的观感。
59
+ - **代价**:包名与主题绑定,「只用 UI 优化不要皮」的诉求没有独立入口。
60
+ - **重审条件**:出现第二个真实消费者(另一个主题包或宿主官方)需要复用 overrides 层时,把 overrides 抽成独立包,皮肤包依赖它。
61
+
62
+ ## D8. 多主题走「单仓库构建期分包」,不多合一、不抽运行时公共包(2026-09 定)
63
+
64
+ - **背景**:做 Codex / Kimi Code 等第二个主题时,多合一会让包名(claude)名不副实;分仓库会让共享机制(build.mjs、scheduler、popover-utils、选择器纪律)多处漂移;抽 npm 运行时公共包则违反 D1(加载器没有相对 require)。
65
+ - **决定**:第二个主题立项时,把本仓库改为单仓库多主题:共享碎片留仓库级 `src/`,主题私有碎片(tokens、品牌资产、copy、主题特有 overrides)收进 `themes/<name>/`,`build.mjs` 参数化 `--theme`,每个主题产出自包含单文件、各自发 npm 包。`dsh-claude-style` 包名不动。
66
+ - **触发条件(重要)**:仅当新主题有**行为分叉**(不同的 DOM override、不同的 composer 结构)才动手。若只是换色板与 logo,先用现有品牌切换机制(settings.js)在包内消化,不提前改造。
67
+ - **代价**:改造时 build.mjs 与目录布局有一次性手术;两个主题之后共享碎片的改动需要双主题回归。
68
+
69
+ ## D9. composer 的 :has() 分支改 JS 写属性(2026-09 定,性能方向)
70
+
71
+ - **背景**:皮肤在流式输出期间的渲染压力主要来自两处:D6 的每帧全量 pass,以及 CSS 中约 70 处对 DOM 结构敏感的 `:has()`(绝大多数是 `[class*="composerStack"]` 上的 hero/inline 分支)——每次 DOM 变更都触发昂贵的选择器重算。
72
+ - **决定**:把「结构感知」从 CSS 移到 JS:`permissions.js` 的 `syncSegments()` 在 scheduler 每轮 pass 里为 composerStack 祖先写 `data-composer-variant="hero|inline"` 属性(observer 的 attributeFilter 不含 data-*,不会反触发;写前比较旧值防抖动;同轮去重避免多卡命中同一 stack 反复写),CSS 改为读属性。交互敏感的 `:has()`(`:hover`、`:focus-within`)与低频的 dialog `:has()` 保留。
73
+ - **落地**:已执行完毕(代码见 `d0fb6f7`),一次性计划文档 `docs/plans/2026-09-composer-mode-attr.md` 按惯例删除,决策与重审条件保留在本条目。仍未消除的结构感知 `:has()` 只剩 placeholder 那条(`card` 上的 `:not(:has([data-composer-placeholder]))`):`copy.js` 本就管理 placeholder,可在它的 sync 里同步写 `data-has-placeholder` 再改 CSS,属可选的后续优化,不在本次范围。
74
+ - **重审条件**:实测证明 :has() 不再是热点,或宿主提供 hero/inline 的稳定属性契约。
Binary file
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Google Sans Flex Project Authors (github.com/googlefonts/googlesans-flex)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://openfontlicense.org
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.