dsh-opencode-palette 1.5.0 → 1.6.0
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/README.md +1 -0
- package/lib/client.js +125 -71
- package/lib/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
**The complete opencode palette for DeepSeek Harness — 34 official themes, one click.**
|
|
6
6
|
|
|
7
7
|
[](../LICENSE)
|
|
8
|
+
[](https://www.npmjs.com/package/dsh-opencode-palette)
|
|
8
9
|
[](https://github.com/anomalyco/opencode)
|
|
9
10
|
[]()
|
|
10
11
|
|
package/lib/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-opencode-palette v1.
|
|
2
|
+
* dsh-opencode-palette v1.6.0 — 浏览器半(构建产物,勿手改)
|
|
3
3
|
* 数据驱动管线:opencode v1.18.12 官方主题 JSON → 颜色解析 → DSH 适配注入
|
|
4
4
|
* 源:src/engine/* + runtime/client.mjs(npm run build 重新生成)
|
|
5
5
|
*/
|
|
@@ -363,6 +363,25 @@ function generateTheme(colors, typography, themeName) {
|
|
|
363
363
|
__mods["generate"] = { buildTokens, buildTypographyCss, buildColorCss, generateTheme }
|
|
364
364
|
})();
|
|
365
365
|
(function () {
|
|
366
|
+
// zh-names.mjs — 主题中文名表(单一来源)
|
|
367
|
+
// 供运行时面板(中文界面显示中文主题名)与 assets 生成器(矩阵/故事卡中文名)共用。
|
|
368
|
+
// 无中文译名者(opencode / One Dark / Monokai / Cursor / GitHub / Vercel)保留原名。
|
|
369
|
+
|
|
370
|
+
const THEME_ZH = {
|
|
371
|
+
opencode: "opencode", tokyonight: "东京之夜", dracula: "德古拉", gruvbox: "复古凹槽",
|
|
372
|
+
matrix: "黑客帝国", "rose-pine": "玫瑰松林", catppuccin: "卡布奇诺", "catppuccin-frappe": "卡布奇诺·冰沙",
|
|
373
|
+
"catppuccin-macchiato": "卡布奇诺·玛奇朵", solarized: "日光浴", synthwave84: "合成波 84",
|
|
374
|
+
everforest: "常青森林", nord: "北极", kanagawa: "神奈川", nightowl: "夜猫子",
|
|
375
|
+
"one-dark": "One Dark", monokai: "Monokai", palenight: "苍白之夜", material: "材料设计",
|
|
376
|
+
ayu: "鮎", carbonfox: "碳狐", cobalt2: "钴蓝", cursor: "Cursor", aura: "光环",
|
|
377
|
+
flexoki: "纸墨", github: "GitHub", zenburn: "禅燃", mercury: "水星",
|
|
378
|
+
"osaka-jade": "大阪翡翠", vesper: "黄昏星", vercel: "Vercel", "lucent-orng": "透光橙",
|
|
379
|
+
orng: "纯橙", system: "跟随系统",
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
__mods["zh-names"] = { THEME_ZH }
|
|
383
|
+
})();
|
|
384
|
+
(function () {
|
|
366
385
|
// registry.mjs — 主题注册表:33 个静态主题(vendored JSON)+ system 特殊主题
|
|
367
386
|
// 数据由 scripts/sync-themes.mjs 从 opencode v1.18.12 官方 tag 同步(见 MANIFEST.json 指纹)
|
|
368
387
|
const aura = {
|
|
@@ -7962,6 +7981,7 @@ __mods["index"] = { renderTheme, previewColors, themeNames, themeGroups, GROUP_O
|
|
|
7962
7981
|
// 依赖注入:theme(dsh-client-ui-theme)、slots(settings.plugins.tab / tool.view.cordis)
|
|
7963
7982
|
const { renderTheme, previewColors, themeNames, themeGroups } = __mods["index"]
|
|
7964
7983
|
const { FONTS, SANS_STACK } = __mods["map-dsh"]
|
|
7984
|
+
const { THEME_ZH } = __mods["zh-names"]
|
|
7965
7985
|
|
|
7966
7986
|
const STORAGE_KEY = 'dsh.opencode-palette.v2'
|
|
7967
7987
|
// 兼容迁移:旧插件(dsh-opencode-tui-theme)的本地设置键,读到即迁移到新键
|
|
@@ -8008,8 +8028,8 @@ const I18N = {
|
|
|
8008
8028
|
enableTitle: { zh: '点击启用主题', en: 'Click to enable' },
|
|
8009
8029
|
typography: { zh: '字体字号', en: 'Typography' },
|
|
8010
8030
|
bodyStyle: { zh: '正文样式', en: 'Body style' },
|
|
8011
|
-
mono: { zh: '
|
|
8012
|
-
sans: { zh: '
|
|
8031
|
+
mono: { zh: '等宽(终端风)', en: 'Monospace (terminal)' },
|
|
8032
|
+
sans: { zh: '常规(界面风)', en: 'Regular (UI)' },
|
|
8013
8033
|
fontSize: { zh: '字号', en: 'Font size' },
|
|
8014
8034
|
codeFont: { zh: '代码字体', en: 'Code font' },
|
|
8015
8035
|
fontPreview: { zh: '等宽', en: 'mono' },
|
|
@@ -8146,20 +8166,23 @@ function createClient(slotTarget) {
|
|
|
8146
8166
|
const h = react.createElement
|
|
8147
8167
|
const [query, setQuery] = react.useState('')
|
|
8148
8168
|
const [fontOpen, setFontOpen] = react.useState(false)
|
|
8169
|
+
const [sizeOpen, setSizeOpen] = react.useState(false)
|
|
8149
8170
|
const fontRef = react.useRef(null)
|
|
8171
|
+
const sizeRef = react.useRef(null)
|
|
8150
8172
|
// UI 快照:所有引擎动作后 setUi(props.getState()) 重同步,避免受控控件显示值漂移
|
|
8151
8173
|
const [ui, setUi] = react.useState(props.getState())
|
|
8152
8174
|
const st = ui
|
|
8153
8175
|
|
|
8154
8176
|
// 字体下拉:点击外部关闭
|
|
8155
8177
|
react.useEffect(function () {
|
|
8156
|
-
if (!fontOpen) return
|
|
8178
|
+
if (!fontOpen && !sizeOpen) return
|
|
8157
8179
|
function onDoc(e) {
|
|
8158
8180
|
if (fontRef.current && !fontRef.current.contains(e.target)) setFontOpen(false)
|
|
8181
|
+
if (sizeRef.current && !sizeRef.current.contains(e.target)) setSizeOpen(false)
|
|
8159
8182
|
}
|
|
8160
8183
|
document.addEventListener('mousedown', onDoc)
|
|
8161
8184
|
return function () { document.removeEventListener('mousedown', onDoc) }
|
|
8162
|
-
}, [fontOpen])
|
|
8185
|
+
}, [fontOpen, sizeOpen])
|
|
8163
8186
|
|
|
8164
8187
|
// 语言切换:DSH 界面语言变化时重渲染(文案跟随)
|
|
8165
8188
|
react.useEffect(function () {
|
|
@@ -8171,11 +8194,15 @@ function createClient(slotTarget) {
|
|
|
8171
8194
|
const shown = q === ''
|
|
8172
8195
|
? props.groups()
|
|
8173
8196
|
: props.groups()
|
|
8174
|
-
.map(function (g) { return { name: g.name, color: g.color, themes: g.themes.filter(function (t) { return t.name.indexOf(q) >= 0 }) } })
|
|
8197
|
+
.map(function (g) { return { name: g.name, color: g.color, themes: g.themes.filter(function (t) { return (t.name + ' ' + (THEME_ZH[t.name] || '')).toLowerCase().indexOf(q) >= 0 }) } })
|
|
8175
8198
|
.filter(function (g) { return g.themes.length > 0 })
|
|
8176
8199
|
|
|
8177
8200
|
const muted = 'var(--dsw-alias-label-secondary)'
|
|
8178
8201
|
const base = 'var(--dsw-alias-label-primary)'
|
|
8202
|
+
// 主题显示名:中文界面用中文名(system 走 i18n 文案)
|
|
8203
|
+
const themeLabel = function (name) {
|
|
8204
|
+
return currentLang === 'zh' && name !== 'system' ? (THEME_ZH[name] || name) : name
|
|
8205
|
+
}
|
|
8179
8206
|
const fieldLabel = { fontSize: 11, color: muted }
|
|
8180
8207
|
const secTitle = { fontSize: 11, color: muted, letterSpacing: '.08em', marginBottom: 8, display: 'flex', alignItems: 'baseline', gap: 8 }
|
|
8181
8208
|
const countStyle = { color: 'var(--dsw-alias-label-dimmed)', fontSize: 11, letterSpacing: 0 }
|
|
@@ -8197,9 +8224,26 @@ function createClient(slotTarget) {
|
|
|
8197
8224
|
}, opt.label)
|
|
8198
8225
|
}))
|
|
8199
8226
|
}
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8227
|
+
// 通用下拉(字号 / 代码字体):紧凑按钮 + 弹出菜单,对齐 setup-panel 样例
|
|
8228
|
+
const dd = function (open, setOpen, ref, labelNode, items) {
|
|
8229
|
+
return h('div', { ref: ref, style: { position: 'relative' } }, [
|
|
8230
|
+
h('button', {
|
|
8231
|
+
onClick: function () { setOpen(!open) },
|
|
8232
|
+
style: {
|
|
8233
|
+
display: 'flex', alignItems: 'center', gap: 8,
|
|
8234
|
+
background: 'var(--dsw-alias-bg-layer-2)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8235
|
+
borderRadius: 6, padding: '5px 10px', fontSize: 12, cursor: 'pointer',
|
|
8236
|
+
color: base, fontFamily: 'var(--dsw-font-family)',
|
|
8237
|
+
},
|
|
8238
|
+
}, [labelNode, h('span', { style: { color: muted } }, '▾')]),
|
|
8239
|
+
open ? h('div', {
|
|
8240
|
+
style: {
|
|
8241
|
+
position: 'absolute', top: 'calc(100% + 4px)', left: 0, zIndex: 20,
|
|
8242
|
+
background: 'var(--dsw-alias-bg-overlay)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8243
|
+
borderRadius: 8, minWidth: 200, padding: 4, boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
|
|
8244
|
+
},
|
|
8245
|
+
}, items) : null,
|
|
8246
|
+
])
|
|
8203
8247
|
}
|
|
8204
8248
|
const dot = function (color, size) {
|
|
8205
8249
|
return h('span', { style: { width: size, height: size, borderRadius: '50%', background: color || '#555', display: 'inline-block', flex: 'none' } })
|
|
@@ -8223,48 +8267,11 @@ function createClient(slotTarget) {
|
|
|
8223
8267
|
},
|
|
8224
8268
|
}, [
|
|
8225
8269
|
dot(c && c.primary, 9),
|
|
8226
|
-
t.name === 'system' ? tr('systemDefault') : t.name,
|
|
8270
|
+
t.name === 'system' ? tr('systemDefault') : themeLabel(t.name),
|
|
8227
8271
|
isCur ? h('span', { style: { color: 'var(--dsw-alias-brand-primary)', fontWeight: 700 } }, '✓') : null,
|
|
8228
8272
|
])
|
|
8229
8273
|
}
|
|
8230
8274
|
|
|
8231
|
-
// 自定义字体下拉(每个选项用其字体预览)
|
|
8232
|
-
const fontDropdown = h('div', { ref: fontRef, style: { position: 'relative' } }, [
|
|
8233
|
-
h('button', {
|
|
8234
|
-
onClick: function () { setFontOpen(!fontOpen) },
|
|
8235
|
-
style: {
|
|
8236
|
-
display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
|
|
8237
|
-
background: 'var(--dsw-alias-bg-layer-2)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8238
|
-
borderRadius: 6, padding: '6px 12px', fontSize: 12, cursor: 'pointer', minWidth: 200,
|
|
8239
|
-
color: base, fontFamily: 'var(--dsw-font-family)',
|
|
8240
|
-
},
|
|
8241
|
-
}, [
|
|
8242
|
-
h('span', { style: { fontFamily: FONTS[st.fontKey] || FONTS['JetBrains Mono'] } }, st.fontKey),
|
|
8243
|
-
h('span', { style: { color: muted } }, '▾'),
|
|
8244
|
-
]),
|
|
8245
|
-
fontOpen ? h('div', {
|
|
8246
|
-
style: {
|
|
8247
|
-
position: 'absolute', top: 'calc(100% + 4px)', left: 0, zIndex: 20,
|
|
8248
|
-
background: 'var(--dsw-alias-bg-overlay)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8249
|
-
borderRadius: 8, minWidth: 230, padding: 4, boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
|
|
8250
|
-
},
|
|
8251
|
-
}, Object.keys(FONTS).map(function (k) {
|
|
8252
|
-
const on = k === st.fontKey
|
|
8253
|
-
return h('div', {
|
|
8254
|
-
key: k,
|
|
8255
|
-
onClick: function () {
|
|
8256
|
-
props.refresh(st.mode, st.size, k)
|
|
8257
|
-
setUi(props.getState())
|
|
8258
|
-
setFontOpen(false)
|
|
8259
|
-
},
|
|
8260
|
-
style: {
|
|
8261
|
-
padding: '6px 10px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
|
|
8262
|
-
background: on ? 'rgba(255,255,255,0.1)' : 'transparent',
|
|
8263
|
-
color: on ? base : muted,
|
|
8264
|
-
},
|
|
8265
|
-
}, h('span', { style: { fontFamily: FONTS[k] } }, k + ' — Aa ' + tr('fontPreview')))
|
|
8266
|
-
})) : null,
|
|
8267
|
-
])
|
|
8268
8275
|
|
|
8269
8276
|
|
|
8270
8277
|
return h('div', { style: { display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 920 } }, [
|
|
@@ -8299,14 +8306,43 @@ function createClient(slotTarget) {
|
|
|
8299
8306
|
h('div', { style: secTitle }, [
|
|
8300
8307
|
h('span', null, tr('typography')),
|
|
8301
8308
|
]),
|
|
8302
|
-
h('div', { style: { display: 'flex', alignItems: '
|
|
8303
|
-
|
|
8309
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' } }, [
|
|
8310
|
+
seg(st.mode, [
|
|
8304
8311
|
{ value: 'mono', label: tr('mono') },
|
|
8305
8312
|
{ value: 'tui', label: tr('sans') },
|
|
8306
|
-
], function (v) { props.refresh(v, st.size, st.fontKey); setUi(props.getState()) })
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8313
|
+
], function (v) { props.refresh(v, st.size, st.fontKey); setUi(props.getState()) }),
|
|
8314
|
+
dd(sizeOpen, setSizeOpen, sizeRef,
|
|
8315
|
+
h('span', null, tr('fontSize') + ' ' + st.size + 'px'),
|
|
8316
|
+
[11, 12, 13, 14, 15, 16, 17, 18].map(function (s) {
|
|
8317
|
+
const on = s === st.size
|
|
8318
|
+
return h('div', {
|
|
8319
|
+
key: String(s),
|
|
8320
|
+
onClick: function () { props.refresh(st.mode, s, st.fontKey); setUi(props.getState()); setSizeOpen(false) },
|
|
8321
|
+
style: {
|
|
8322
|
+
padding: '6px 10px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
|
|
8323
|
+
background: on ? 'rgba(255,255,255,0.1)' : 'transparent',
|
|
8324
|
+
color: on ? base : muted,
|
|
8325
|
+
},
|
|
8326
|
+
}, String(s) + 'px')
|
|
8327
|
+
})),
|
|
8328
|
+
dd(fontOpen, setFontOpen, fontRef,
|
|
8329
|
+
h('span', { style: { fontFamily: FONTS[st.fontKey] || FONTS['JetBrains Mono'] } }, st.fontKey),
|
|
8330
|
+
Object.keys(FONTS).map(function (k) {
|
|
8331
|
+
const on = k === st.fontKey
|
|
8332
|
+
return h('div', {
|
|
8333
|
+
key: k,
|
|
8334
|
+
onClick: function () {
|
|
8335
|
+
props.refresh(st.mode, st.size, k)
|
|
8336
|
+
setUi(props.getState())
|
|
8337
|
+
setFontOpen(false)
|
|
8338
|
+
},
|
|
8339
|
+
style: {
|
|
8340
|
+
padding: '6px 10px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
|
|
8341
|
+
background: on ? 'rgba(255,255,255,0.1)' : 'transparent',
|
|
8342
|
+
color: on ? base : muted,
|
|
8343
|
+
},
|
|
8344
|
+
}, h('span', { style: { fontFamily: FONTS[k] } }, k + ' — Aa ' + tr('fontPreview')))
|
|
8345
|
+
})),
|
|
8310
8346
|
]),
|
|
8311
8347
|
// ── 主题选择(色系分组标签 + mini 芯片)──
|
|
8312
8348
|
h('div', { style: secTitle }, [
|
|
@@ -8338,32 +8374,49 @@ function createClient(slotTarget) {
|
|
|
8338
8374
|
}),
|
|
8339
8375
|
])
|
|
8340
8376
|
}
|
|
8377
|
+
// 面板 API(settings.plugins.tab 与 settings.section 两个入口共享同一份 state)
|
|
8378
|
+
const paletteApi = function () {
|
|
8379
|
+
return {
|
|
8380
|
+
getState: getState,
|
|
8381
|
+
toggle: toggle,
|
|
8382
|
+
refresh: refresh,
|
|
8383
|
+
setTheme: setTheme,
|
|
8384
|
+
themeNames: themeNames,
|
|
8385
|
+
groups: function () { return themeGroups() },
|
|
8386
|
+
subscribeLocale: function (fn) {
|
|
8387
|
+
localeListeners.push(fn)
|
|
8388
|
+
return function () {
|
|
8389
|
+
const i = localeListeners.indexOf(fn)
|
|
8390
|
+
if (i >= 0) localeListeners.splice(i, 1)
|
|
8391
|
+
}
|
|
8392
|
+
},
|
|
8393
|
+
previews: function () { return themeNames().map(function (n) { return { name: n, colors: previewColors(n) } }) },
|
|
8394
|
+
}
|
|
8395
|
+
}
|
|
8341
8396
|
disposePanel = slots.inject(slotTarget, function () {
|
|
8342
8397
|
return slots.register({
|
|
8343
8398
|
name: slotTarget,
|
|
8344
8399
|
id: 'opencode-palette',
|
|
8345
8400
|
order: 30,
|
|
8346
8401
|
label: function () { return tr('panelName') },
|
|
8347
|
-
inject:
|
|
8348
|
-
return {
|
|
8349
|
-
getState: getState,
|
|
8350
|
-
toggle: toggle,
|
|
8351
|
-
refresh: refresh,
|
|
8352
|
-
setTheme: setTheme,
|
|
8353
|
-
themeNames: themeNames,
|
|
8354
|
-
groups: function () { return themeGroups() },
|
|
8355
|
-
subscribeLocale: function (fn) {
|
|
8356
|
-
localeListeners.push(fn)
|
|
8357
|
-
return function () {
|
|
8358
|
-
const i = localeListeners.indexOf(fn)
|
|
8359
|
-
if (i >= 0) localeListeners.splice(i, 1)
|
|
8360
|
-
}
|
|
8361
|
-
},
|
|
8362
|
-
previews: function () { return themeNames().map(function (n) { return { name: n, colors: previewColors(n) } }) },
|
|
8363
|
-
}
|
|
8364
|
-
},
|
|
8402
|
+
inject: paletteApi,
|
|
8365
8403
|
}, Panel)
|
|
8366
8404
|
})
|
|
8405
|
+
// 设置页左侧导航直达入口(保留「设置 → 插件」内的原入口)
|
|
8406
|
+
// settings.section = 设置页左侧 section 列表(general=0 / models=10 / plugins=15 / agent-presets=20)
|
|
8407
|
+
let disposeSection = null
|
|
8408
|
+
if (slotTarget === 'settings.plugins.tab') {
|
|
8409
|
+
disposeSection = slots.inject('settings.section', function () {
|
|
8410
|
+
return slots.register({
|
|
8411
|
+
name: 'settings.section',
|
|
8412
|
+
id: 'opencode-palette',
|
|
8413
|
+
order: 16,
|
|
8414
|
+
label: function () { return tr('panelName') },
|
|
8415
|
+
inject: paletteApi,
|
|
8416
|
+
}, Panel)
|
|
8417
|
+
})
|
|
8418
|
+
}
|
|
8419
|
+
disposeSection = disposeSection || null
|
|
8367
8420
|
}
|
|
8368
8421
|
|
|
8369
8422
|
// 卸载清理(cordis 语义:effect fn 立即执行,返回值才是清理器)
|
|
@@ -8371,6 +8424,7 @@ function createClient(slotTarget) {
|
|
|
8371
8424
|
return function () {
|
|
8372
8425
|
try { clearStyle() } catch (e) { /* 忽略 */ }
|
|
8373
8426
|
try { if (disposePanel) disposePanel() } catch (e) { /* 忽略 */ }
|
|
8427
|
+
try { if (disposeSection) disposeSection() } catch (e) { /* 忽略 */ }
|
|
8374
8428
|
try { if (globalThis.__opencodePalette) delete globalThis.__opencodePalette } catch (e) { /* 忽略 */ }
|
|
8375
8429
|
try { if (localeObserver) localeObserver.disconnect() } catch (e) { /* 忽略 */ }
|
|
8376
8430
|
}
|
package/lib/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-opencode-palette",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"description": "让 DeepSeek Harness 穿上 34 款经典皮肤——东京的霓虹夜色、德古拉的暗红月光、复古工坊的暖黄灯火、黑客帝国的数字雨、玫瑰松林间的风……一键换肤,即点即换,重启不丢。34 legendary skins for DeepSeek Harness — tokyonight's neon dusk, dracula's crimson moon, gruvbox's retro glow, the matrix's digital rain, rose-pine's rosewood calm… one click, instant, persisted.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|