dsh-theme-palette 1.8.1 → 1.8.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 (3) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/client.js +52 -7
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,30 @@
4
4
 
5
5
  ## 版本一览
6
6
 
7
+ ### 1.8.2
8
+ **暖砂字体体系修正**(用户反馈“和其他两套不一样,尤其字体颜色”):
9
+
10
+ - **根因 1:深色正文字色度没有按色域归一**。`paperC` 是绝对值,×2.4 后暖砂请求 130%、靛蓝 166% 色域上限,
11
+ 实际色度被裁成 0.0244 / 0.0115 / 0.0303——暖砂深正文几乎是靛蓝的两倍黄。现在三套统一 `paperC=0.0053`
12
+ (标准档实际 ≈0.0127),浅/深正文色度比降到 1.21 / 1.10
13
+ - **根因 2:暖砂是唯一「深色面 60°、正文 84°」的双色相预置**。深色面橙棕、正文黄绿,色相分裂 24°;
14
+ 现在 `paper` 角色跟随 `darkHue`,并把暖砂 `hue` 84→72、`darkHue` 60→66,全套色相收敛到 12° 内
15
+ - 新增断言:深正文色相偏离 `darkHue` ≤12°、三套浅色正文色度比 ≤1.25、深色 ≤1.5
16
+ - 新增 `tools/preview-typography.mjs`:三套 × 明暗并排渲染同一段文字,发版前目检
17
+
18
+ 语法高亮跟随配色(1.8.1 里“未做”的那条,前提已实测):
19
+
20
+ - **实测依据**:宿主渲染器用 Shiki 的 `css-variables` 模式(`class="shiki css-variables"`,
21
+ `style="background-color:var(--shiki-background)"`),token 颜色走 CSS 变量,
22
+ 所以覆盖 `--shiki-token-*` 生效,不需要 `!important`
23
+ - **色相策略**:从强调色相取 3 个色族(强调 / +150° 冷族 / -60° 暖族),
24
+ 同族靠明度分常/表达;每个 token 对代码块底求解到 **≥4.6:1**,四族最小 ΔE **≥10**
25
+ - 覆盖 9 类 token(keyword / function / constant / parameter / string / string-expression /
26
+ comment / punctuation / link)+ `--shiki-background` / `--shiki-foreground`
27
+ - **md=off 时不输出**任何 shiki token,交回宿主原色
28
+ - 新增 `tools/preview-code.mjs`:用生产 token 渲染一段真实代码,发版前肉眼确认
29
+ - 断言:9 类 token 对比度 ≥4.6、四族 ΔE ≥10、shiki 背景与代码块一致、md=off 无输出
30
+
7
31
  ### 1.8.1
8
32
  Markdown 配色丰富化(非加色相,而是加层级 + 修代码块底):
9
33
 
package/client.js CHANGED
@@ -27,7 +27,7 @@ window.__ModuleLoader__.load({
27
27
  const React = require('react')
28
28
  const h = React.createElement
29
29
 
30
- const PLUGIN_VERSION = '1.8.1'
30
+ const PLUGIN_VERSION = '1.8.2'
31
31
  const STORE_KEY = 'dsh-theme-palette.v1'
32
32
  const OVERRIDE_SOURCE = 'dsh-theme-palette'
33
33
 
@@ -107,22 +107,22 @@ window.__ModuleLoader__.load({
107
107
  { id: 'mono', label: '黑白', desc: '无色调 · 默认', tinted: false },
108
108
  {
109
109
  id: 'warm', label: '暖砂', desc: '米白 + 棕调', tinted: true,
110
- hue: 84, darkHue: 60, lightC: 0.030, midC: 0.010, textC: 0.004,
111
- darkC: 0.014, darkLift: 0.026, paperC: 0.014, // 深底 #1e1b14 L 0.223 / 30% 色域
110
+ hue: 72, darkHue: 66, lightC: 0.030, midC: 0.010, textC: 0.004,
111
+ darkC: 0.014, darkLift: 0.026, paperC: 0.0053, // 深正文按色域归一:×2.4 后 ≈0.0127
112
112
  accentHue: 60, accentC: 0.101, accentL: 0.58, // 标准色 #A9683E
113
113
  accentScale: 1.0,
114
114
  },
115
115
  {
116
116
  id: 'indigo', label: '靛蓝', desc: '冷白 + 蓝调', tinted: true,
117
117
  hue: 266, lightC: 0.020, midC: 0.010, textC: 0.004,
118
- darkC: 0.028, darkLift: 0.032, paperC: 0.009, // 深底 #161c2a L 0.227 / 19% 色域
118
+ darkC: 0.028, darkLift: 0.032, paperC: 0.0053, // 同上:三套统一,避免被色域裁成两倍差
119
119
  accentHue: 259, accentC: 0.107, accentL: 0.5108, // 标准色 #3F66A3
120
120
  accentScale: 1.0,
121
121
  },
122
122
  {
123
123
  id: 'moss', label: '苔绿', desc: '浅灰绿 + 绿调', tinted: true,
124
124
  hue: 162, lightC: 0.016, midC: 0.010, textC: 0.004,
125
- darkC: 0.015, darkLift: 0.042, paperC: 0.0125, // 深底 #1a211b L 0.239 / 24% 色域
125
+ darkC: 0.015, darkLift: 0.042, paperC: 0.0053, // 同上
126
126
  accentHue: 139, accentC: 0.096, accentL: 0.5335, // 标准色 #4F7A42
127
127
  accentScale: 1.0,
128
128
  },
@@ -495,9 +495,10 @@ window.__ModuleLoader__.load({
495
495
  // 换成 60°(橙棕)才是咖啡色。浅色侧仍是 88°(米白)。
496
496
  // 文字档(含深色正文 paper)跟随「文字」这一项自己的色相;预设没有 textHue,行为不变。
497
497
  const tintRole = role === 'text' || role === 'paper'
498
+ // 深色角色(含深色正文 paper)统一走 darkHue,避免「深色面橙棕、正文黄绿」的双色相
498
499
  const hue = tintRole && scheme.textHue !== undefined
499
500
  ? scheme.textHue
500
- : (role === 'dark' && scheme.darkHue !== undefined ? scheme.darkHue : scheme.hue)
501
+ : ((role === 'dark' || role === 'paper') && scheme.darkHue !== undefined ? scheme.darkHue : scheme.hue)
501
502
  bluish[step] = fromOklch(clamp(compressL(lifted), 0, 0.995), roleChroma(role, weight, scheme, scales), hue)
502
503
  }
503
504
  const neutral = {}
@@ -935,6 +936,50 @@ window.__ModuleLoader__.load({
935
936
  light: mixHex(ramps.deepseek['500'], ramps.bluish['50'], 0.05),
936
937
  dark: mixHex(ramps.deepseek['400'], ramps.bluish['900'], 0.07),
937
938
  }
939
+ /* ---- 语法高亮(1.8.2)----
940
+ * 宿主渲染器用 Shiki 的 `css-variables` 模式(className="shiki css-variables",
941
+ * 样式走 var(--shiki-*)),所以覆盖这些变量有效,不需要 !important。
942
+ *
943
+ * 色相策略:不引入与配色无关的固定色,而是从强调色相出发取 3 个色族
944
+ * (强调 / +150° 的冷族 / -55° 的暖族),再用明度与色度拉开可辨度;
945
+ * 每个 token 都必须对代码块底达到 4.6:1,否则沿远离背景的方向调整明度。
946
+ */
947
+ if (params.tinted && mdMode === 'on') {
948
+ const baseHue = params.accentHue === undefined ? scheme.hue : params.accentHue
949
+ const pickL = (bg) => (contrast('#ffffff', bg) >= contrast('#000000', bg) ? 0.80 : 0.45)
950
+ const dirOf = (bg) => (contrast('#ffffff', bg) >= contrast('#000000', bg) ? 1 : -1)
951
+ const ink = (bg, hue, chroma, startL, target) => {
952
+ const dir = dirOf(bg)
953
+ let L = startL
954
+ for (let i = 0; i < 160; i++) {
955
+ const c = fromOklch(clamp(L, 0.02, 0.99), chroma, hue)
956
+ if (contrast(c, bg) >= target) return c
957
+ L += dir * 0.004
958
+ }
959
+ return fromOklch(clamp(L, 0.02, 0.99), chroma, hue)
960
+ }
961
+ // 每个色族自带目标对比度:同族靠明度分"常/表达",异族靠色相差 55–150°
962
+ const families = {
963
+ keyword: [baseHue, 0.15, 4.6],
964
+ function: [baseHue + 70, 0.12, 5.0],
965
+ constant: [baseHue - 60, 0.13, 4.8],
966
+ parameter: [baseHue + 30, 0.10, 5.6],
967
+ string: [baseHue + 150, 0.10, 4.8],
968
+ 'string-expression': [baseHue + 150, 0.085, 5.8],
969
+ comment: [baseHue, 0.015, 4.6],
970
+ punctuation: [baseHue, 0.02, 6.0],
971
+ }
972
+ for (const [name, [hue, chroma, target]] of Object.entries(families)) {
973
+ const key = '--shiki-token-' + name
974
+ pairs[key] = {
975
+ light: ink(codeFill.light, hue, chroma, pickL(codeFill.light), target),
976
+ dark: ink(codeFill.dark, hue, chroma, pickL(codeFill.dark), target),
977
+ }
978
+ }
979
+ pairs['--shiki-token-link'] = { light: lightLink(ramps, false), dark: ramps.deepseek['400'] }
980
+ pairs['--shiki-background'] = codeFill
981
+ pairs['--shiki-foreground'] = { light: ramps.bluish['1000'], dark: ramps.bluish['50'] }
982
+ }
938
983
  const scroll = scrollbarTokens(ramps, params, scrollMode)
939
984
  for (const [name, pair] of Object.entries(scroll)) pairs[name] = pair
940
985
  // 开关/勾选/单选的共用支点:brand-primary 本来是近黑/近白,改成强调色。
@@ -2078,7 +2123,7 @@ body[data-ds-dark-theme] .dsh-tp-check{background:var(--t-accent-d);color:var(--
2078
2123
 
2079
2124
  // 开发期接口:palette-dev.mjs 通过它拿到同一套引擎(避免「报表好看、上线不一样」)
2080
2125
  if (DEV_OPT_IN && typeof window !== 'undefined' && typeof window.__DSH_THEME_PALETTE_DEV__ === 'function') {
2081
- window.__DSH_THEME_PALETTE_DEV__({ buildTokens, SCHEMES, SIDEBAR_MODES, TEXT_MODES, RIGHTBAR_MODES, SCROLL_MODES, CONTROL_MODES, MD_MODES, HC_MODES, contrast, toOklch, rampsFor, floors, encodeConfig, decodeConfig, customScheme, readCustom, writeCustom, CONTRAST_SURFACES, CONTRAST_ROLES, settingsCss: SETTINGS_CSS, cardColors })
2126
+ window.__DSH_THEME_PALETTE_DEV__({ buildTokens, SCHEMES, SIDEBAR_MODES, TEXT_MODES, RIGHTBAR_MODES, SCROLL_MODES, CONTROL_MODES, MD_MODES, HC_MODES, contrast, toOklch, fromOklch, rampsFor, floors, encodeConfig, decodeConfig, customScheme, readCustom, writeCustom, CONTRAST_SURFACES, CONTRAST_ROLES, settingsCss: SETTINGS_CSS, cardColors })
2082
2127
  }
2083
2128
 
2084
2129
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-theme-palette",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "DSH 主题配色:4 套配色 × 明暗两模式,OKLCH 色域安全重建 + 真实承载面对比度求解,可调强度与面板表面。",
5
5
  "type": "module",
6
6
  "main": "index.js",