dsh-opencode-palette 1.4.1 → 1.5.1
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 +3 -8
- package/cordis.patch.yml +7 -0
- package/lib/client.js +63 -51
- package/lib/index.js +1 -1
- package/package.json +7 -7
- package/scripts/install-patch.cjs +0 -58
- package/scripts/uninstall-patch.cjs +0 -50
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
|
|
|
@@ -24,15 +25,9 @@ Then install the plugin into your profile:
|
|
|
24
25
|
dsh plugin --profile web add dsh-opencode-palette
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
That's it — **zero configuration**: this plugin uses DSH's official bundle mechanism — it ships its own `cordis.patch.yml` (declared via `dsh.bundle.patch`), so `dsh plugin add` automatically joins the package into the profile's `dsh.profile.bundles` layer stack, where the DSH loader assembles it at startup; `dsh plugin remove` removes it automatically. No manual file editing, and no pnpm build scripts (no postinstall, so pnpm v10 never blocks it). Restart DSH (or refresh the browser page) and the plugin is on, using the official `opencode` theme (deep black with orange / blue / violet).
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
- insert:
|
|
31
|
-
- id: opencode-palette
|
|
32
|
-
name: 'dsh-opencode-palette'
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Refresh the browser page — the plugin is on, using the official `opencode` theme (deep black with orange / blue / violet).
|
|
30
|
+
> **Upgrading from 1.4.x or earlier**: old versions wrote a registration block into `~/.dsh/profiles/web/cordis.patch.yml` via postinstall. Before upgrading, delete the `opencode-palette` block from that file (a leftover would duplicate the bundle registration), then re-run `dsh plugin --profile web add dsh-opencode-palette`.
|
|
36
31
|
|
|
37
32
|
## What it does
|
|
38
33
|
|
package/cordis.patch.yml
ADDED
package/lib/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-opencode-palette v1.
|
|
2
|
+
* dsh-opencode-palette v1.5.1 — 浏览器半(构建产物,勿手改)
|
|
3
3
|
* 数据驱动管线:opencode v1.18.12 官方主题 JSON → 颜色解析 → DSH 适配注入
|
|
4
4
|
* 源:src/engine/* + runtime/client.mjs(npm run build 重新生成)
|
|
5
5
|
*/
|
|
@@ -8008,8 +8008,8 @@ const I18N = {
|
|
|
8008
8008
|
enableTitle: { zh: '点击启用主题', en: 'Click to enable' },
|
|
8009
8009
|
typography: { zh: '字体字号', en: 'Typography' },
|
|
8010
8010
|
bodyStyle: { zh: '正文样式', en: 'Body style' },
|
|
8011
|
-
mono: { zh: '
|
|
8012
|
-
sans: { zh: '
|
|
8011
|
+
mono: { zh: '等宽(终端风)', en: 'Monospace (terminal)' },
|
|
8012
|
+
sans: { zh: '常规(界面风)', en: 'Regular (UI)' },
|
|
8013
8013
|
fontSize: { zh: '字号', en: 'Font size' },
|
|
8014
8014
|
codeFont: { zh: '代码字体', en: 'Code font' },
|
|
8015
8015
|
fontPreview: { zh: '等宽', en: 'mono' },
|
|
@@ -8146,20 +8146,23 @@ function createClient(slotTarget) {
|
|
|
8146
8146
|
const h = react.createElement
|
|
8147
8147
|
const [query, setQuery] = react.useState('')
|
|
8148
8148
|
const [fontOpen, setFontOpen] = react.useState(false)
|
|
8149
|
+
const [sizeOpen, setSizeOpen] = react.useState(false)
|
|
8149
8150
|
const fontRef = react.useRef(null)
|
|
8151
|
+
const sizeRef = react.useRef(null)
|
|
8150
8152
|
// UI 快照:所有引擎动作后 setUi(props.getState()) 重同步,避免受控控件显示值漂移
|
|
8151
8153
|
const [ui, setUi] = react.useState(props.getState())
|
|
8152
8154
|
const st = ui
|
|
8153
8155
|
|
|
8154
8156
|
// 字体下拉:点击外部关闭
|
|
8155
8157
|
react.useEffect(function () {
|
|
8156
|
-
if (!fontOpen) return
|
|
8158
|
+
if (!fontOpen && !sizeOpen) return
|
|
8157
8159
|
function onDoc(e) {
|
|
8158
8160
|
if (fontRef.current && !fontRef.current.contains(e.target)) setFontOpen(false)
|
|
8161
|
+
if (sizeRef.current && !sizeRef.current.contains(e.target)) setSizeOpen(false)
|
|
8159
8162
|
}
|
|
8160
8163
|
document.addEventListener('mousedown', onDoc)
|
|
8161
8164
|
return function () { document.removeEventListener('mousedown', onDoc) }
|
|
8162
|
-
}, [fontOpen])
|
|
8165
|
+
}, [fontOpen, sizeOpen])
|
|
8163
8166
|
|
|
8164
8167
|
// 语言切换:DSH 界面语言变化时重渲染(文案跟随)
|
|
8165
8168
|
react.useEffect(function () {
|
|
@@ -8197,9 +8200,26 @@ function createClient(slotTarget) {
|
|
|
8197
8200
|
}, opt.label)
|
|
8198
8201
|
}))
|
|
8199
8202
|
}
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
+
// 通用下拉(字号 / 代码字体):紧凑按钮 + 弹出菜单,对齐 setup-panel 样例
|
|
8204
|
+
const dd = function (open, setOpen, ref, labelNode, items) {
|
|
8205
|
+
return h('div', { ref: ref, style: { position: 'relative' } }, [
|
|
8206
|
+
h('button', {
|
|
8207
|
+
onClick: function () { setOpen(!open) },
|
|
8208
|
+
style: {
|
|
8209
|
+
display: 'flex', alignItems: 'center', gap: 8,
|
|
8210
|
+
background: 'var(--dsw-alias-bg-layer-2)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8211
|
+
borderRadius: 6, padding: '5px 10px', fontSize: 12, cursor: 'pointer',
|
|
8212
|
+
color: base, fontFamily: 'var(--dsw-font-family)',
|
|
8213
|
+
},
|
|
8214
|
+
}, [labelNode, h('span', { style: { color: muted } }, '▾')]),
|
|
8215
|
+
open ? h('div', {
|
|
8216
|
+
style: {
|
|
8217
|
+
position: 'absolute', top: 'calc(100% + 4px)', left: 0, zIndex: 20,
|
|
8218
|
+
background: 'var(--dsw-alias-bg-overlay)', border: '1px solid var(--dsw-alias-border-l1)',
|
|
8219
|
+
borderRadius: 8, minWidth: 200, padding: 4, boxShadow: '0 8px 24px rgba(0,0,0,0.5)',
|
|
8220
|
+
},
|
|
8221
|
+
}, items) : null,
|
|
8222
|
+
])
|
|
8203
8223
|
}
|
|
8204
8224
|
const dot = function (color, size) {
|
|
8205
8225
|
return h('span', { style: { width: size, height: size, borderRadius: '50%', background: color || '#555', display: 'inline-block', flex: 'none' } })
|
|
@@ -8228,43 +8248,6 @@ function createClient(slotTarget) {
|
|
|
8228
8248
|
])
|
|
8229
8249
|
}
|
|
8230
8250
|
|
|
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
8251
|
|
|
8269
8252
|
|
|
8270
8253
|
return h('div', { style: { display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 920 } }, [
|
|
@@ -8299,14 +8282,43 @@ function createClient(slotTarget) {
|
|
|
8299
8282
|
h('div', { style: secTitle }, [
|
|
8300
8283
|
h('span', null, tr('typography')),
|
|
8301
8284
|
]),
|
|
8302
|
-
h('div', { style: { display: 'flex', alignItems: '
|
|
8303
|
-
|
|
8285
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' } }, [
|
|
8286
|
+
seg(st.mode, [
|
|
8304
8287
|
{ value: 'mono', label: tr('mono') },
|
|
8305
8288
|
{ value: 'tui', label: tr('sans') },
|
|
8306
|
-
], function (v) { props.refresh(v, st.size, st.fontKey); setUi(props.getState()) })
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8289
|
+
], function (v) { props.refresh(v, st.size, st.fontKey); setUi(props.getState()) }),
|
|
8290
|
+
dd(sizeOpen, setSizeOpen, sizeRef,
|
|
8291
|
+
h('span', null, tr('fontSize') + ' ' + st.size + 'px'),
|
|
8292
|
+
[11, 12, 13, 14, 15, 16, 17, 18].map(function (s) {
|
|
8293
|
+
const on = s === st.size
|
|
8294
|
+
return h('div', {
|
|
8295
|
+
key: String(s),
|
|
8296
|
+
onClick: function () { props.refresh(st.mode, s, st.fontKey); setUi(props.getState()); setSizeOpen(false) },
|
|
8297
|
+
style: {
|
|
8298
|
+
padding: '6px 10px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
|
|
8299
|
+
background: on ? 'rgba(255,255,255,0.1)' : 'transparent',
|
|
8300
|
+
color: on ? base : muted,
|
|
8301
|
+
},
|
|
8302
|
+
}, String(s) + 'px')
|
|
8303
|
+
})),
|
|
8304
|
+
dd(fontOpen, setFontOpen, fontRef,
|
|
8305
|
+
h('span', { style: { fontFamily: FONTS[st.fontKey] || FONTS['JetBrains Mono'] } }, st.fontKey),
|
|
8306
|
+
Object.keys(FONTS).map(function (k) {
|
|
8307
|
+
const on = k === st.fontKey
|
|
8308
|
+
return h('div', {
|
|
8309
|
+
key: k,
|
|
8310
|
+
onClick: function () {
|
|
8311
|
+
props.refresh(st.mode, st.size, k)
|
|
8312
|
+
setUi(props.getState())
|
|
8313
|
+
setFontOpen(false)
|
|
8314
|
+
},
|
|
8315
|
+
style: {
|
|
8316
|
+
padding: '6px 10px', fontSize: 12, borderRadius: 5, cursor: 'pointer',
|
|
8317
|
+
background: on ? 'rgba(255,255,255,0.1)' : 'transparent',
|
|
8318
|
+
color: on ? base : muted,
|
|
8319
|
+
},
|
|
8320
|
+
}, h('span', { style: { fontFamily: FONTS[k] } }, k + ' — Aa ' + tr('fontPreview')))
|
|
8321
|
+
})),
|
|
8310
8322
|
]),
|
|
8311
8323
|
// ── 主题选择(色系分组标签 + mini 芯片)──
|
|
8312
8324
|
h('div', { style: secTitle }, [
|
package/lib/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-opencode-palette",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.1",
|
|
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": {
|
|
8
8
|
".": "./lib/index.js",
|
|
9
9
|
"./client": "./lib/client.js",
|
|
10
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
10
11
|
"./package.json": "./package.json"
|
|
11
12
|
},
|
|
12
13
|
"files": [
|
|
13
14
|
"lib",
|
|
14
|
-
"
|
|
15
|
+
"cordis.patch.yml"
|
|
15
16
|
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"postinstall": "node scripts/install-patch.cjs",
|
|
18
|
-
"preuninstall": "node scripts/uninstall-patch.cjs"
|
|
19
|
-
},
|
|
20
17
|
"keywords": [
|
|
21
18
|
"dsh",
|
|
22
19
|
"deepseek-harness",
|
|
@@ -28,6 +25,9 @@
|
|
|
28
25
|
"multi-theme"
|
|
29
26
|
],
|
|
30
27
|
"dsh": {
|
|
28
|
+
"bundle": {
|
|
29
|
+
"patch": "./cordis.patch.yml"
|
|
30
|
+
},
|
|
31
31
|
"client": {
|
|
32
32
|
"platform": "web",
|
|
33
33
|
"immediately": true,
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-opencode-palette postinstall — 自动注册到 DSH profile(npm 标准安装即完成,无需手动编辑 patch)
|
|
3
|
-
*
|
|
4
|
-
* 行为:
|
|
5
|
-
* 1. 定位 $DSH_HOME/profiles/web/cordis.patch.yml(DSH_HOME 未设 → ~/.dsh/profiles/web/…)
|
|
6
|
-
* 2. 文件不存在 → 跳过(非 DSH 环境不打扰)
|
|
7
|
-
* 3. 已含注册行 → 跳过(幂等,重装/升级不叠加)
|
|
8
|
-
* 4. 否则文件末尾追加注册块(- insert: id opencode-palette / name dsh-opencode-palette)
|
|
9
|
-
* 容错:任何异常只警告,绝不令 npm install 失败(退出码恒 0)。
|
|
10
|
-
*/
|
|
11
|
-
const fs = require('fs')
|
|
12
|
-
const path = require('path')
|
|
13
|
-
|
|
14
|
-
const PLUGIN_ID = 'opencode-palette'
|
|
15
|
-
const PLUGIN_NAME = 'dsh-opencode-palette'
|
|
16
|
-
|
|
17
|
-
function findPatchPath() {
|
|
18
|
-
const home = process.env.DSH_HOME
|
|
19
|
-
|| (process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME)
|
|
20
|
-
if (!home) return null
|
|
21
|
-
return path.join(home, '.dsh', 'profiles', 'web', 'cordis.patch.yml')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const REGISTER_BLOCK =
|
|
25
|
-
'\n# dsh-opencode-palette(npm 安装 · 自动注册)\n' +
|
|
26
|
-
'- insert:\n' +
|
|
27
|
-
' - id: ' + PLUGIN_ID + '\n' +
|
|
28
|
-
" name: '" + PLUGIN_NAME + "'\n"
|
|
29
|
-
|
|
30
|
-
function main() {
|
|
31
|
-
const patch = findPatchPath()
|
|
32
|
-
if (!patch) {
|
|
33
|
-
console.log('[dsh-opencode-palette] 未找到 DSH_HOME,跳过自动注册(非 DSH 环境)')
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
let existed = true
|
|
37
|
-
let text = ''
|
|
38
|
-
try {
|
|
39
|
-
text = fs.readFileSync(patch, 'utf8')
|
|
40
|
-
} catch (e) {
|
|
41
|
-
existed = false
|
|
42
|
-
}
|
|
43
|
-
if (existed && new RegExp("id\\s*:\\s*['\"]?" + PLUGIN_ID + "['\"]?").test(text)) {
|
|
44
|
-
console.log('[dsh-opencode-palette] 已在 cordis.patch.yml 注册,跳过')
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
fs.mkdirSync(path.dirname(patch), { recursive: true })
|
|
49
|
-
fs.appendFileSync(patch, REGISTER_BLOCK, 'utf8')
|
|
50
|
-
console.log('[dsh-opencode-palette] 已自动注册到 ' + patch + '(刷新浏览器页面即生效)')
|
|
51
|
-
} catch (e) {
|
|
52
|
-
console.warn('[dsh-opencode-palette] 自动注册失败(不影响本包安装):' + String((e && e.message) || e))
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
try { main() } catch (e) {
|
|
57
|
-
console.warn('[dsh-opencode-palette] postinstall 异常(已忽略):' + String((e && e.message) || e))
|
|
58
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-opencode-palette preuninstall — 自动从 DSH profile 移除注册(npm remove 即完成,无需手动编辑 patch)
|
|
3
|
-
* 幂等:不存在注册块 → 直接返回;任何异常只警告,退出码恒 0。
|
|
4
|
-
*/
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
|
|
8
|
-
const PLUGIN_ID = 'opencode-palette'
|
|
9
|
-
|
|
10
|
-
function findPatchPath() {
|
|
11
|
-
const home = process.env.DSH_HOME
|
|
12
|
-
|| (process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME)
|
|
13
|
-
if (!home) return null
|
|
14
|
-
return path.join(home, '.dsh', 'profiles', 'web', 'cordis.patch.yml')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 匹配注册块:可选注释行 + insert 块(容错 name 引号/缩进变化)
|
|
18
|
-
const BLOCK_RE = new RegExp(
|
|
19
|
-
'(?:^|\\n)\\s*# dsh-opencode-palette[^\\n]*\\n' +
|
|
20
|
-
'\\s*- insert:\\n' +
|
|
21
|
-
'\\s*\\s*- id:\\s*' + PLUGIN_ID + '\\s*\\n' +
|
|
22
|
-
"\\s*\\s*name:\\s*['\"]?dsh-opencode-palette['\"]?\\s*\\n",
|
|
23
|
-
'g'
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
function main() {
|
|
27
|
-
const patch = findPatchPath()
|
|
28
|
-
if (!patch) return
|
|
29
|
-
let text = ''
|
|
30
|
-
try {
|
|
31
|
-
text = fs.readFileSync(patch, 'utf8')
|
|
32
|
-
} catch (e) {
|
|
33
|
-
return // 文件不存在 → 无需清理
|
|
34
|
-
}
|
|
35
|
-
const next = text.replace(BLOCK_RE, '\n')
|
|
36
|
-
if (next === text) {
|
|
37
|
-
console.log('[dsh-opencode-palette] 未在 cordis.patch.yml 找到注册块,无需清理')
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
fs.writeFileSync(patch, next, 'utf8')
|
|
42
|
-
console.log('[dsh-opencode-palette] 已从 cordis.patch.yml 移除注册(卸载完成)')
|
|
43
|
-
} catch (e) {
|
|
44
|
-
console.warn('[dsh-opencode-palette] 移除注册失败:' + String((e && e.message) || e))
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
try { main() } catch (e) {
|
|
49
|
-
console.warn('[dsh-opencode-palette] preuninstall 异常(已忽略):' + String((e && e.message) || e))
|
|
50
|
-
}
|