dsh-vscode-mode 0.1.48 → 0.1.49
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 +10 -1
- package/lib/client.js +557 -32
- package/lib/client.js.map +1 -1
- package/lib/index.js +562 -3
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/compat.ts +1 -1
- package/src/client/index.ts +9 -2
- package/src/client/paths.ts +2 -0
- package/src/client/sidebar/SidebarView.ts +82 -16
- package/src/client/sidebar/panels/RulesPanel.ts +284 -0
- package/src/client/sidebar/panels/index.ts +18 -2
- package/src/client/sidebar/types.ts +2 -0
- package/src/client/sidebarMin.ts +48 -0
- package/src/client/styles/editor.css +43 -0
- package/src/client/ui/EditorView.ts +22 -4
- package/src/client/ui/McpSettings.ts +37 -2
- package/src/client/ui/SideEditorTab.ts +1 -0
- package/src/fileOpenSettings.ts +2 -0
- package/src/index.ts +5 -1
- package/src/rpc.ts +37 -0
- package/src/rules.ts +528 -0
- package/src/shared/rpc.ts +11 -0
- package/src/shared/rules.ts +60 -0
package/lib/client.js
CHANGED
|
@@ -30,7 +30,7 @@ window.__ModuleLoader__.load({
|
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
let react_dom = require("react-dom");
|
|
32
32
|
//#region \0dsh-css:/home/runner/work/DSH_VsCodeMode/DSH_VsCodeMode/src/client/styles/editor.css.mjs
|
|
33
|
-
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-meta { flex-shrink: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-status { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-lsp { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-progress-message { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-statusbar .edrv-sp-progress { flex: 0 0 auto; min-width: 36px; text-align: right; font-variant-numeric: tabular-nums; color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-lsp-status-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-lsp-status-dot.ready { background: var(--dsw-alias-state-success-primary, #0f9d58); }\n[data-edrv-view] .edrv-lsp-status-dot.busy { background: var(--dsw-alias-state-warn-primary, #d97706); animation: edrv-lsp-pulse 1.2s ease-in-out infinite; }\n@keyframes edrv-lsp-pulse { 50% { opacity: .45; } }\n/* Ctrl+hover 可导航标识符下划线提示(绑定 Monaco inlineClassName 装饰) */\n[data-edrv-view] .edrv-nav-underline { text-decoration: underline; text-decoration-color: var(--dsw-alias-interactive-primary, #4fc1ff); text-underline-offset: 1px; cursor: pointer; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-chip-btn:disabled { opacity: .35; cursor: default; }\n[data-edrv-view] .edrv-chip-btn:disabled:hover { background: transparent; }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1 1 auto; min-width: 0; min-height: 0; position: relative; overflow: hidden; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; min-width: 0; min-height: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 12px; background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); box-shadow: none; overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-editor-area > .edrv-diffbar { max-height: calc(100% - 20px); }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 36px; padding: 4px 5px 4px 12px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n/* 编辑区 / Tab 右键菜单(添加文件/选中内容到对话) */\n[data-edrv-view] .edrv-ctxmenu { position: fixed; z-index: 71; min-width: 200px; max-width: 320px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 8px 26px rgba(31,41,51,.2); padding: 4px; display: flex; flex-direction: column; gap: 1px; }\n[data-edrv-view] .edrv-ctxmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 18px; padding: 7px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-ctxmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-ctxmenu-item:disabled,\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-disabled { color: var(--dsw-alias-label-disabled, #b0b7c0); cursor: default; background: transparent; }\n[data-edrv-view] .edrv-ctxmenu-sep { height: 1px; margin: 3px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n/* ===== 唯一会话级差异 dock(遵循 DSH todo/queue 原生布局) ===== */\n[data-edrv-diff-dock-shell] {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n max-width: calc(var(--dsh-composer-card-max-width) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n margin: 0 auto;\n padding: 0;\n flex: none;\n border: 1px solid var(--dsw-alias-border-l1, #e0e6e8);\n border-radius: 12px;\n background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, transparent));\n box-shadow: none;\n overflow: hidden;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock {\n box-sizing: border-box;\n position: relative;\n left: auto;\n right: auto;\n bottom: auto;\n z-index: auto;\n width: 100%;\n max-width: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-body { max-height: 180px; overflow: auto; padding: 6px 12px 10px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: 24px; border: none; border-radius: 8px; padding: 0 12px; background: transparent; color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 500; line-height: 24px; text-align: center; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-count { display: inline-flex; align-items: center; color: var(--dsw-alias-label-primary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 500; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-file { display: inline-flex; align-items: center; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-row { display: flex; align-items: center; height: 36px; min-height: 36px; padding: 4px 12px; overflow-x: auto; scrollbar-width: thin; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { display: flex; align-items: center; gap: 10px; width: 100%; min-width: max-content; min-height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-nav,\n[data-edrv-diff-dock-shell] .edrv-diffbar-files,\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { display: flex; align-items: center; gap: 6px; flex: none; height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { margin-left: auto; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; min-width: 28px; padding: 0; font-size: 13px; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle svg { width: 14px; height: 14px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files { min-width: 0; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { min-width: 72px; max-width: 240px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-progress { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; font-variant-numeric: tabular-nums; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-summary { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-pill { box-sizing: border-box; height: 28px; padding: 0 9px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-size: 11px; line-height: 26px; font-weight: 600; }\n[data-edrv-diff-dock-shell] .edrv-pill-keep { background: var(--dsw-alias-state-success-tertiary); color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-undo { background: var(--dsw-alias-state-error-tertiary); color: var(--dsw-alias-state-error-primary); border: 1px solid var(--dsw-alias-state-error-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-ghost { background: transparent; color: var(--dsw-alias-label-secondary); border: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-pill:hover:not(:disabled) { background-color: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-pill:focus-visible { outline: 2px solid var(--dsw-alias-label-tertiary); outline-offset: -2px; }\n[data-edrv-diff-dock-shell] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; background: transparent; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-diff-dock-shell] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-l { color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-o { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-n { color: var(--dsw-alias-state-success-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-tag { color: var(--dsw-alias-label-tertiary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-stale { border-color: var(--dsw-alias-state-warn-secondary); cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffbox-others { border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file { border-color: var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details { display: flex; flex-direction: column; gap: 2px; padding: 6px 12px 8px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item { display: flex; align-items: center; width: 100%; min-height: 28px; gap: 8px; padding: 4px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); cursor: pointer; text-align: left; font-size: 12px; line-height: 20px; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1); }\n@media (max-width: 620px) {\n [data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { width: max-content; }\n [data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { max-width: 160px; }\n}\n\n/* ===== 侧边栏(活动栏 + 面板区 + 文件树) ===== */\n[data-edrv-view] .edrv-editor-row { display: flex; flex: 1 1 auto; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col { box-sizing: border-box; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col > .edrv-pathbar,\n[data-edrv-view] .edrv-main-col > .edrv-tabs { flex: 0 0 auto; }\n[data-edrv-view] .edrv-editor-area { position: relative; display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-sidebar { display: flex; flex-direction: row; flex-shrink: 0; min-width: 0; height: 100%; background: var(--dsw-alias-bg-layer-1, #ffffff); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); overflow: hidden; }\n[data-edrv-view] .edrv-rail { display: flex; flex-direction: column; align-items: center; width: 44px; flex-shrink: 0; padding: 6px 0; background: var(--dsw-alias-bg-layer-2, #f0f4f4); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); gap: 4px; }\n[data-edrv-view] .edrv-rail-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-rail-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rail-btn.edrv-rail-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; }\n[data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }\n[data-edrv-view] .edrv-side-body { flex: 1; min-width: 0; min-height: 0; display: flex; overflow: hidden; }\n[data-edrv-view] .edrv-side-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; position: relative; }\n[data-edrv-view] .edrv-side-head { display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 12px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); flex-shrink: 0; }\n[data-edrv-view] .edrv-side-title { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-root { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-side-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree { flex: 1; min-height: 0; overflow: auto; padding: 4px 6px 12px; font-size: 12px; }\n[data-edrv-view] .edrv-tree-row { display: flex; align-items: center; gap: 4px; height: 22px; padding-right: 6px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-tree-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-active { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-context { box-shadow: inset 0 0 0 1px var(--dsw-alias-brand-primary, #0f9d58); background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); }\n[data-edrv-view] .edrv-tree-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-tree-name.edrv-tree-dim { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }\n[data-edrv-view] .edrv-tree-loading { height: 22px; line-height: 22px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n/* 大纲面板:kind 字形 / detail / 行号 */\n[data-edrv-view] .edrv-outline-kind { display: inline-flex; align-items: center; justify-content: center; width: 14px; flex-shrink: 0; font-size: 12px; font-weight: 600; text-align: center; }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-func { color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-type { color: var(--dsw-alias-label-primary, #1f2933); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-data { color: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-ns { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-key { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-outline-detail { flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-outline-ln { flex-shrink: 0; padding-right: 2px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-side-resize { width: 5px; flex-shrink: 0; cursor: col-resize; background: transparent; }\n[data-edrv-view] .edrv-side-resize:hover { background: var(--dsw-alias-brand-primary, #0f9d58); opacity: .35; }\n[data-edrv-view] .edrv-chip-btn.edrv-chip-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n/* ===== 侧栏形态(betterSidebar 面板内编辑区) ===== */\n[data-edrv-view][data-edrv-layout='side'] { box-sizing: border-box; height: 100%; }\n\n/* ===== 侧边栏引导条(旧页签形态、未装 betterSidebar 时) ===== */\n[data-edrv-view] .edrv-side-hint { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; padding: 6px 12px; font-size: 12px; color: var(--dsw-alias-label-secondary, #52606d); background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-side-hint-text { white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-cmd { font-size: 11px; padding: 2px 6px; border-radius: 6px; background: var(--dsw-alias-bg-layer-1, #ffffff); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-close { margin-left: auto; border: none; background: transparent; color: var(--dsw-alias-label-tertiary, #9aa5b1); cursor: pointer; font-size: 14px; line-height: 1; padding: 2px 6px; border-radius: 6px; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-hint-close:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n/* ===== search panel (sidebar, VSCode search view) ===== */\n[data-edrv-view] .edrv-search-panel { display: flex; flex-direction: column; min-height: 0; flex: 1; padding: 6px; gap: 4px; }\n[data-edrv-view] .edrv-search-qrow { display: flex; gap: 4px; }\n[data-edrv-view] .edrv-search-input { flex: 1; min-width: 0; height: 26px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-input:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-opts { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }\n[data-edrv-view] .edrv-search-opt { min-width: 24px; height: 22px; padding: 0 6px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 11px; font-family: var(--ds-font-family-code, ui-monospace, monospace); cursor: pointer; }\n[data-edrv-view] .edrv-search-opt:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-opt.on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-label-primary, #1f2933); border-color: var(--dsw-alias-border-l2, #d5dde3); }\n[data-edrv-view] .edrv-search-spacer { flex: 1; }\n[data-edrv-view] .edrv-search-summary { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); padding: 2px 4px; }\n[data-edrv-view] .edrv-search-results { flex: 1; min-height: 0; overflow: auto; font-size: 12px; }\n[data-edrv-view] .edrv-search-group { margin-bottom: 2px; }\n[data-edrv-view] .edrv-search-file { display: flex; align-items: center; gap: 4px; height: 22px; padding: 0 4px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-search-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-search-fname { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-search-fdir { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-search-fcount { flex-shrink: 0; min-width: 16px; height: 15px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); font-size: 10px; line-height: 15px; text-align: center; }\n[data-edrv-view] .edrv-search-line { display: flex; gap: 6px; padding: 1px 4px 1px 16px; border-radius: 4px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; overflow: hidden; }\n[data-edrv-view] .edrv-search-line.alt { background: var(--dsw-alias-bg-layer-1, #ffffff); }\n[data-edrv-view] .edrv-search-line:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-ln { flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; min-width: 26px; text-align: right; user-select: none; }\n[data-edrv-view] .edrv-search-text { overflow: hidden; text-overflow: ellipsis; white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 11px; }\n[data-edrv-view] .edrv-search-hit { background: var(--dsw-alias-state-warn-primary, #e5b93f); color: #1f2933; border-radius: 2px; padding: 0 1px; }\n[data-edrv-view] .edrv-search-empty { padding: 8px 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-search-error { padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n[data-edrv-view] .edrv-search-warn { padding: 6px 8px; border: 1px solid rgba(240,173,78,.45); border-radius: 6px; background: #fdf6e3; color: #b8860b; font-size: 11px; word-break: break-all; }\n\n/* include/exclude filter rows (collapsible) */\n[data-edrv-view] .edrv-search-rows { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 4px; }\n[data-edrv-view] .edrv-search-row { display: flex; align-items: center; gap: 4px; }\n[data-edrv-view] .edrv-search-field { flex: 1; min-width: 0; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 11px; outline: none; }\n[data-edrv-view] .edrv-search-field:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-field.dim { opacity: .45; }\n[data-edrv-view] .edrv-search-field::placeholder { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-search-toggle { min-width: 24px; height: 24px; padding: 0 5px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; line-height: 1; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-search-toggle:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-toggle.on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-label-primary, #1f2933); border-color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-search-toggle:disabled { opacity: .4; cursor: default; }\n\n\n\n";
|
|
33
|
+
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-meta { flex-shrink: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-status { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-lsp { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-progress-message { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-statusbar .edrv-sp-progress { flex: 0 0 auto; min-width: 36px; text-align: right; font-variant-numeric: tabular-nums; color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-lsp-status-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-lsp-status-dot.ready { background: var(--dsw-alias-state-success-primary, #0f9d58); }\n[data-edrv-view] .edrv-lsp-status-dot.busy { background: var(--dsw-alias-state-warn-primary, #d97706); animation: edrv-lsp-pulse 1.2s ease-in-out infinite; }\n@keyframes edrv-lsp-pulse { 50% { opacity: .45; } }\n/* Ctrl+hover 可导航标识符下划线提示(绑定 Monaco inlineClassName 装饰) */\n[data-edrv-view] .edrv-nav-underline { text-decoration: underline; text-decoration-color: var(--dsw-alias-interactive-primary, #4fc1ff); text-underline-offset: 1px; cursor: pointer; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-chip-btn:disabled { opacity: .35; cursor: default; }\n[data-edrv-view] .edrv-chip-btn:disabled:hover { background: transparent; }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1 1 auto; min-width: 0; min-height: 0; position: relative; overflow: hidden; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; min-width: 0; min-height: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 12px; background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); box-shadow: none; overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-editor-area > .edrv-diffbar { max-height: calc(100% - 20px); }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 36px; padding: 4px 5px 4px 12px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n/* 编辑区 / Tab 右键菜单(添加文件/选中内容到对话) */\n[data-edrv-view] .edrv-ctxmenu { position: fixed; z-index: 71; min-width: 200px; max-width: 320px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 8px 26px rgba(31,41,51,.2); padding: 4px; display: flex; flex-direction: column; gap: 1px; }\n[data-edrv-view] .edrv-ctxmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 18px; padding: 7px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-ctxmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-ctxmenu-item:disabled,\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-disabled { color: var(--dsw-alias-label-disabled, #b0b7c0); cursor: default; background: transparent; }\n[data-edrv-view] .edrv-ctxmenu-sep { height: 1px; margin: 3px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n/* ===== 唯一会话级差异 dock(遵循 DSH todo/queue 原生布局) ===== */\n[data-edrv-diff-dock-shell] {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n max-width: calc(var(--dsh-composer-card-max-width) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n margin: 0 auto;\n padding: 0;\n flex: none;\n border: 1px solid var(--dsw-alias-border-l1, #e0e6e8);\n border-radius: 12px;\n background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, transparent));\n box-shadow: none;\n overflow: hidden;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock {\n box-sizing: border-box;\n position: relative;\n left: auto;\n right: auto;\n bottom: auto;\n z-index: auto;\n width: 100%;\n max-width: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-body { max-height: 180px; overflow: auto; padding: 6px 12px 10px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: 24px; border: none; border-radius: 8px; padding: 0 12px; background: transparent; color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 500; line-height: 24px; text-align: center; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-count { display: inline-flex; align-items: center; color: var(--dsw-alias-label-primary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 500; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-file { display: inline-flex; align-items: center; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-row { display: flex; align-items: center; height: 36px; min-height: 36px; padding: 4px 12px; overflow-x: auto; scrollbar-width: thin; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { display: flex; align-items: center; gap: 10px; width: 100%; min-width: max-content; min-height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-nav,\n[data-edrv-diff-dock-shell] .edrv-diffbar-files,\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { display: flex; align-items: center; gap: 6px; flex: none; height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { margin-left: auto; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; min-width: 28px; padding: 0; font-size: 13px; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle svg { width: 14px; height: 14px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files { min-width: 0; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { min-width: 72px; max-width: 240px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-progress { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; font-variant-numeric: tabular-nums; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-summary { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-pill { box-sizing: border-box; height: 28px; padding: 0 9px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-size: 11px; line-height: 26px; font-weight: 600; }\n[data-edrv-diff-dock-shell] .edrv-pill-keep { background: var(--dsw-alias-state-success-tertiary); color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-undo { background: var(--dsw-alias-state-error-tertiary); color: var(--dsw-alias-state-error-primary); border: 1px solid var(--dsw-alias-state-error-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-ghost { background: transparent; color: var(--dsw-alias-label-secondary); border: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-pill:hover:not(:disabled) { background-color: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-pill:focus-visible { outline: 2px solid var(--dsw-alias-label-tertiary); outline-offset: -2px; }\n[data-edrv-diff-dock-shell] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; background: transparent; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-diff-dock-shell] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-l { color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-o { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-n { color: var(--dsw-alias-state-success-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-tag { color: var(--dsw-alias-label-tertiary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-stale { border-color: var(--dsw-alias-state-warn-secondary); cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffbox-others { border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file { border-color: var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details { display: flex; flex-direction: column; gap: 2px; padding: 6px 12px 8px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item { display: flex; align-items: center; width: 100%; min-height: 28px; gap: 8px; padding: 4px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); cursor: pointer; text-align: left; font-size: 12px; line-height: 20px; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1); }\n@media (max-width: 620px) {\n [data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { width: max-content; }\n [data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { max-width: 160px; }\n}\n\n/* ===== 侧边栏(活动栏 + 面板区 + 文件树) ===== */\n[data-edrv-view] .edrv-editor-row { display: flex; flex: 1 1 auto; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col { box-sizing: border-box; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col > .edrv-pathbar,\n[data-edrv-view] .edrv-main-col > .edrv-tabs { flex: 0 0 auto; }\n[data-edrv-view] .edrv-editor-area { position: relative; display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-sidebar { display: flex; flex-direction: row; flex-shrink: 0; min-width: 0; height: 100%; background: var(--dsw-alias-bg-layer-1, #ffffff); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); overflow: hidden; }\n[data-edrv-view] .edrv-rail { display: flex; flex-direction: column; align-items: center; width: 44px; flex-shrink: 0; padding: 6px 0; background: var(--dsw-alias-bg-layer-2, #f0f4f4); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); gap: 4px; }\n[data-edrv-view] .edrv-rail-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-rail-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rail-btn.edrv-rail-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; }\n[data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }\n[data-edrv-view] .edrv-side-body { flex: 1; min-width: 0; min-height: 0; display: flex; overflow: hidden; }\n[data-edrv-view] .edrv-side-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; position: relative; }\n[data-edrv-view] .edrv-side-head { display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 12px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); flex-shrink: 0; }\n[data-edrv-view] .edrv-side-title { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-root { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-side-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree { flex: 1; min-height: 0; overflow: auto; padding: 4px 6px 12px; font-size: 12px; }\n[data-edrv-view] .edrv-tree-row { display: flex; align-items: center; gap: 4px; height: 22px; padding-right: 6px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-tree-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-active { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-context { box-shadow: inset 0 0 0 1px var(--dsw-alias-brand-primary, #0f9d58); background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); }\n[data-edrv-view] .edrv-tree-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-tree-name.edrv-tree-dim { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }\n[data-edrv-view] .edrv-tree-loading { height: 22px; line-height: 22px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n/* 大纲面板:kind 字形 / detail / 行号 */\n[data-edrv-view] .edrv-outline-kind { display: inline-flex; align-items: center; justify-content: center; width: 14px; flex-shrink: 0; font-size: 12px; font-weight: 600; text-align: center; }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-func { color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-type { color: var(--dsw-alias-label-primary, #1f2933); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-data { color: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-ns { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-key { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-outline-detail { flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-outline-ln { flex-shrink: 0; padding-right: 2px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-side-resize { width: 5px; flex-shrink: 0; cursor: col-resize; background: transparent; }\n[data-edrv-view] .edrv-side-resize:hover { background: var(--dsw-alias-brand-primary, #0f9d58); opacity: .35; }\n[data-edrv-view] .edrv-chip-btn.edrv-chip-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n/* ===== 侧栏形态(betterSidebar 面板内编辑区) ===== */\n[data-edrv-view][data-edrv-layout='side'] { box-sizing: border-box; height: 100%; }\n\n/* ===== 侧边栏引导条(旧页签形态、未装 betterSidebar 时) ===== */\n[data-edrv-view] .edrv-side-hint { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; padding: 6px 12px; font-size: 12px; color: var(--dsw-alias-label-secondary, #52606d); background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-side-hint-text { white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-cmd { font-size: 11px; padding: 2px 6px; border-radius: 6px; background: var(--dsw-alias-bg-layer-1, #ffffff); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-close { margin-left: auto; border: none; background: transparent; color: var(--dsw-alias-label-tertiary, #9aa5b1); cursor: pointer; font-size: 14px; line-height: 1; padding: 2px 6px; border-radius: 6px; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-hint-close:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n/* ===== search panel (sidebar, VSCode search view) ===== */\n[data-edrv-view] .edrv-search-panel { display: flex; flex-direction: column; min-height: 0; flex: 1; padding: 6px; gap: 4px; }\n[data-edrv-view] .edrv-search-qrow { display: flex; gap: 4px; }\n[data-edrv-view] .edrv-search-input { flex: 1; min-width: 0; height: 26px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-input:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-opts { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }\n[data-edrv-view] .edrv-search-opt { min-width: 24px; height: 22px; padding: 0 6px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 11px; font-family: var(--ds-font-family-code, ui-monospace, monospace); cursor: pointer; }\n[data-edrv-view] .edrv-search-opt:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-opt.on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-label-primary, #1f2933); border-color: var(--dsw-alias-border-l2, #d5dde3); }\n[data-edrv-view] .edrv-search-spacer { flex: 1; }\n[data-edrv-view] .edrv-search-summary { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); padding: 2px 4px; }\n[data-edrv-view] .edrv-search-results { flex: 1; min-height: 0; overflow: auto; font-size: 12px; }\n[data-edrv-view] .edrv-search-group { margin-bottom: 2px; }\n[data-edrv-view] .edrv-search-file { display: flex; align-items: center; gap: 4px; height: 22px; padding: 0 4px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-search-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-search-fname { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-search-fdir { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-search-fcount { flex-shrink: 0; min-width: 16px; height: 15px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); font-size: 10px; line-height: 15px; text-align: center; }\n[data-edrv-view] .edrv-search-line { display: flex; gap: 6px; padding: 1px 4px 1px 16px; border-radius: 4px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; overflow: hidden; }\n[data-edrv-view] .edrv-search-line.alt { background: var(--dsw-alias-bg-layer-1, #ffffff); }\n[data-edrv-view] .edrv-search-line:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-ln { flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; min-width: 26px; text-align: right; user-select: none; }\n[data-edrv-view] .edrv-search-text { overflow: hidden; text-overflow: ellipsis; white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 11px; }\n[data-edrv-view] .edrv-search-hit { background: var(--dsw-alias-state-warn-primary, #e5b93f); color: #1f2933; border-radius: 2px; padding: 0 1px; }\n[data-edrv-view] .edrv-search-empty { padding: 8px 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-search-error { padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n[data-edrv-view] .edrv-search-warn { padding: 6px 8px; border: 1px solid rgba(240,173,78,.45); border-radius: 6px; background: #fdf6e3; color: #b8860b; font-size: 11px; word-break: break-all; }\n\n/* include/exclude filter rows (collapsible) */\n[data-edrv-view] .edrv-search-rows { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 4px; }\n[data-edrv-view] .edrv-search-row { display: flex; align-items: center; gap: 4px; }\n[data-edrv-view] .edrv-search-field { flex: 1; min-width: 0; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 11px; outline: none; }\n[data-edrv-view] .edrv-search-field:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-field.dim { opacity: .45; }\n[data-edrv-view] .edrv-search-field::placeholder { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-search-toggle { min-width: 24px; height: 24px; padding: 0 5px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; line-height: 1; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-search-toggle:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-search-toggle.on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-label-primary, #1f2933); border-color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-search-toggle:disabled { opacity: .4; cursor: default; }\n\n/* ===== rules panel (sidebar, Codebuddy rules view) ===== */\n[data-edrv-view] .edrv-rules-panel { display: flex; flex-direction: column; min-height: 0; flex: 1; padding: 6px; gap: 4px; }\n[data-edrv-view] .edrv-rules-tabs { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-tab { height: 24px; padding: 0 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; cursor: pointer; }\n[data-edrv-view] .edrv-rules-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rules-tab.on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-label-primary, #1f2933); font-weight: 600; }\n[data-edrv-view] .edrv-rules-new { margin-left: auto; height: 24px; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); border-radius: 6px; background: var(--dsw-alias-bg-layer-1, #fff); color: var(--dsw-alias-label-primary, #1f2933); font-size: 11px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-rules-new:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rules-ws-line { font-size: 11px; color: var(--dsw-alias-label-secondary, #52606d); padding: 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 0 auto; user-select: none; }\n[data-edrv-view] .edrv-rules-hint { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); padding: 0 2px; flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-list { flex: 1; min-height: 0; overflow: auto; }\n[data-edrv-view] .edrv-rules-row { position: relative; padding: 7px 100px 6px 4px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-rules-row.off .edrv-rules-file, [data-edrv-view] .edrv-rules-row.off .edrv-rules-desc { opacity: .5; }\n[data-edrv-view] .edrv-rules-main { display: flex; align-items: center; gap: 6px; min-width: 0; cursor: pointer; }\n[data-edrv-view] .edrv-rules-file { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary, #1f2933); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-rules-path { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-rules-type { flex-shrink: 0; height: 15px; padding: 0 5px; border-radius: 999px; font-size: 10px; line-height: 15px; }\n[data-edrv-view] .edrv-rules-type-always { background: rgba(15,157,88,.15); color: #0b7c46; }\n[data-edrv-view] .edrv-rules-type-auto { background: rgba(79,140,255,.16); color: #3367c9; }\n[data-edrv-view] .edrv-rules-type-manual { background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-rules-offtag { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); flex-shrink: 0; }\n[data-edrv-view] .edrv-rules-desc { margin-top: 3px; font-size: 11px; color: var(--dsw-alias-label-secondary, #52606d); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-rules-actions { position: absolute; top: 5px; right: 4px; display: flex; align-items: center; gap: 2px; }\n[data-edrv-view] .edrv-rules-act { min-width: 22px; height: 22px; padding: 0 4px; border: none; border-radius: 5px; background: transparent; font-size: 12px; line-height: 1; cursor: pointer; color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-rules-act:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rules-switch { position: relative; width: 30px; height: 16px; border-radius: 999px; border: none; background: #b9c4cc; cursor: pointer; transition: background .15s; flex-shrink: 0; padding: 0; }\n[data-edrv-view] .edrv-rules-switch.on { background: #7c5cff; }\n[data-edrv-view] .edrv-rules-knob { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: #fff; transition: left .15s; }\n[data-edrv-view] .edrv-rules-switch.on .edrv-rules-knob { left: 16px; }\n[data-edrv-view] .edrv-rules-empty { padding: 10px 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #9aa5b1); line-height: 1.6; }\n[data-edrv-view] .edrv-rules-err { padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; word-break: break-all; }\n[data-edrv-view] .edrv-rules-editor { display: flex; flex-direction: column; min-height: 0; flex: 1; gap: 6px; }\n[data-edrv-view] .edrv-rules-editor-head { display: flex; align-items: center; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-editor-file { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--dsw-alias-label-secondary, #52606d); flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-input { flex: 1; min-width: 0; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 11px; outline: none; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-rules-input:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-rules-body { flex: 1; min-height: 0; resize: none; padding: 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; line-height: 1.5; outline: none; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-rules-body:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-rules-editor-hint { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); line-height: 1.5; flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-editor-foot { display: flex; justify-content: flex-end; flex: 0 0 auto; }\n[data-edrv-view] .edrv-rules-save { height: 24px; padding: 0 14px; border: none; border-radius: 6px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 12px; cursor: pointer; }\n[data-edrv-view] .edrv-rules-save:disabled { opacity: .5; cursor: default; }\n\n\n\n";
|
|
34
34
|
const tagId$1 = "dsh-vscode-mode/editor.css";
|
|
35
35
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
36
36
|
const tag = document.createElement("style");
|
|
@@ -2166,44 +2166,87 @@ window.__ModuleLoader__.load({
|
|
|
2166
2166
|
//#endregion
|
|
2167
2167
|
//#region src/client/sidebar/SidebarView.ts
|
|
2168
2168
|
/**
|
|
2169
|
-
* dsh-vscode-mode client —
|
|
2170
|
-
*
|
|
2171
|
-
*
|
|
2172
|
-
*
|
|
2169
|
+
* dsh-vscode-mode client — 侧边栏容器(活动栏常显 + 可隐藏面板区 + 拖拽调宽)。
|
|
2170
|
+
* 面板列表来自注册表(活动栏图标/徽标/激活态);最左侧图标列(活动栏)常显,
|
|
2171
|
+
* 右侧详情面板区可拖拽调宽/隐藏:visible=false 时仅保留图标列(宽 = 图标列宽),
|
|
2172
|
+
* 点击任一图标重新展开面板(onShow),底部按钮在 ◀ 收起 / ▶ 展开间切换。
|
|
2173
|
+
* 拖拽调宽下限 = minWidth prop(通用设置 sidebarMinWidth,默认 300),低于下限直接收起面板区。
|
|
2174
|
+
* 作者 ddj 2026-08-26 / 2026-09-04
|
|
2173
2175
|
*/
|
|
2174
|
-
const W_MIN = 180;
|
|
2175
2176
|
const W_MAX = 560;
|
|
2177
|
+
/** 隐藏态拖出面板区的触发阈值(px,拖过即展开并继续实时调宽)。 */
|
|
2178
|
+
const PULL_OUT_THRESHOLD = 12;
|
|
2176
2179
|
/**
|
|
2177
2180
|
* 侧边栏容器。
|
|
2178
2181
|
* @param props.registry 面板注册表(list() 提供面板顺序)
|
|
2179
2182
|
* @param props.ctx 面板共享上下文
|
|
2180
2183
|
* @param props.activePanel 当前激活面板 id
|
|
2181
2184
|
* @param props.onActive 激活面板变化回调
|
|
2185
|
+
* @param props.visible 面板区是否可见(false = 只显示活动栏)
|
|
2186
|
+
* @param props.onShow 重新展开面板区回调(活动栏图标点击/底部按钮)
|
|
2182
2187
|
* @param props.width 面板区宽度
|
|
2183
2188
|
* @param props.onWidth 宽度变化回调
|
|
2184
|
-
* @param props.onHide
|
|
2189
|
+
* @param props.onHide 收起面板区回调
|
|
2190
|
+
* @param props.minWidth 最小宽度(通用设置 sidebarMinWidth;拖拽低于它触发隐藏)
|
|
2185
2191
|
*/
|
|
2186
2192
|
function SidebarView(props) {
|
|
2187
2193
|
const panels = props.registry?.list?.() ?? [];
|
|
2188
2194
|
const ctx = props.ctx;
|
|
2189
2195
|
const activePanel = props.activePanel;
|
|
2190
2196
|
const onActive = props.onActive;
|
|
2197
|
+
const visible = props.visible !== false;
|
|
2198
|
+
const onShow = props.onShow;
|
|
2191
2199
|
const width = props.width;
|
|
2192
2200
|
const onWidth = props.onWidth;
|
|
2193
2201
|
const onHide = props.onHide;
|
|
2202
|
+
const wMin = Math.max(120, Math.min(W_MAX, Math.round(Number(props.minWidth) || 300)));
|
|
2194
2203
|
const active = panels.find((p) => p.id === activePanel) || panels[0];
|
|
2195
2204
|
const onPointerDown = (e) => {
|
|
2196
2205
|
e.preventDefault();
|
|
2197
2206
|
const startX = e.clientX;
|
|
2198
2207
|
const startW = width;
|
|
2208
|
+
const cleanup = () => {
|
|
2209
|
+
window.removeEventListener("pointermove", onMove);
|
|
2210
|
+
window.removeEventListener("pointerup", onUp);
|
|
2211
|
+
};
|
|
2212
|
+
const onUp = () => cleanup();
|
|
2199
2213
|
const onMove = (ev) => {
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2214
|
+
const raw = startW + (ev.clientX - startX);
|
|
2215
|
+
if (raw < wMin) {
|
|
2216
|
+
cleanup();
|
|
2217
|
+
onHide();
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
onWidth(Math.min(W_MAX, raw));
|
|
2202
2221
|
};
|
|
2203
|
-
|
|
2222
|
+
window.addEventListener("pointermove", onMove);
|
|
2223
|
+
window.addEventListener("pointerup", onUp);
|
|
2224
|
+
};
|
|
2225
|
+
/**
|
|
2226
|
+
* 隐藏态接缝拖拽:向右拖过阈值把面板区拉出来(以记忆宽度展开),继续拖动实时调宽。
|
|
2227
|
+
* @param e pointerdown 事件
|
|
2228
|
+
*/
|
|
2229
|
+
const onSeamPointerDown = (e) => {
|
|
2230
|
+
e.preventDefault();
|
|
2231
|
+
const startX = e.clientX;
|
|
2232
|
+
const baseW = Math.max(wMin, Math.min(W_MAX, Math.round(Number(width) || wMin)));
|
|
2233
|
+
let expanded = false;
|
|
2234
|
+
let expandStartX = 0;
|
|
2235
|
+
const cleanup = () => {
|
|
2204
2236
|
window.removeEventListener("pointermove", onMove);
|
|
2205
2237
|
window.removeEventListener("pointerup", onUp);
|
|
2206
2238
|
};
|
|
2239
|
+
const onUp = () => cleanup();
|
|
2240
|
+
const onMove = (ev) => {
|
|
2241
|
+
if (!expanded) {
|
|
2242
|
+
if (ev.clientX - startX < PULL_OUT_THRESHOLD) return;
|
|
2243
|
+
expanded = true;
|
|
2244
|
+
expandStartX = ev.clientX;
|
|
2245
|
+
onShow();
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
onWidth(Math.max(wMin, Math.min(W_MAX, baseW + (ev.clientX - expandStartX))));
|
|
2249
|
+
};
|
|
2207
2250
|
window.addEventListener("pointermove", onMove);
|
|
2208
2251
|
window.addEventListener("pointerup", onUp);
|
|
2209
2252
|
};
|
|
@@ -2216,21 +2259,28 @@ window.__ModuleLoader__.load({
|
|
|
2216
2259
|
const count = typeof p.badge === "function" ? p.badge(ctx) : null;
|
|
2217
2260
|
return react.default.createElement("button", {
|
|
2218
2261
|
key: p.id,
|
|
2219
|
-
className: "edrv-rail-btn" + (active && p.id === active.id ? " edrv-rail-on" : ""),
|
|
2262
|
+
className: "edrv-rail-btn" + (visible && active && p.id === active.id ? " edrv-rail-on" : ""),
|
|
2220
2263
|
title: p.title,
|
|
2221
|
-
onClick: () =>
|
|
2264
|
+
onClick: () => {
|
|
2265
|
+
onActive(p.id);
|
|
2266
|
+
if (!visible && typeof onShow === "function") onShow();
|
|
2267
|
+
}
|
|
2222
2268
|
}, react.default.createElement("span", { className: "edrv-rail-icon" }, p.icon), count > 0 ? react.default.createElement("span", { className: "edrv-rail-badge" }, String(count)) : null);
|
|
2223
2269
|
})), react.default.createElement("button", {
|
|
2224
2270
|
className: "edrv-rail-btn",
|
|
2225
|
-
title: "
|
|
2226
|
-
onClick: onHide
|
|
2227
|
-
}, "◀"));
|
|
2271
|
+
title: (visible ? "隐藏面板区" : "展开面板区") + " (Ctrl+B)",
|
|
2272
|
+
onClick: () => visible ? onHide() : onShow?.()
|
|
2273
|
+
}, visible ? "◀" : "▶"));
|
|
2228
2274
|
return react.default.createElement("div", {
|
|
2229
|
-
className: "edrv-sidebar",
|
|
2230
|
-
style: { width }
|
|
2231
|
-
}, rail, react.default.createElement("div", { className: "edrv-side-body" }, active ? active.render(ctx) : null), react.default.createElement("div", {
|
|
2275
|
+
className: "edrv-sidebar" + (visible ? "" : " edrv-sidebar-rail-only"),
|
|
2276
|
+
style: { width: visible ? width : 49 }
|
|
2277
|
+
}, rail, visible ? react.default.createElement("div", { className: "edrv-side-body" }, active ? active.render(ctx) : null) : null, visible ? react.default.createElement("div", {
|
|
2232
2278
|
className: "edrv-side-resize",
|
|
2233
2279
|
onPointerDown
|
|
2280
|
+
}) : react.default.createElement("div", {
|
|
2281
|
+
className: "edrv-side-resize",
|
|
2282
|
+
title: "拖拽展开面板区",
|
|
2283
|
+
onPointerDown: onSeamPointerDown
|
|
2234
2284
|
}));
|
|
2235
2285
|
}
|
|
2236
2286
|
//#endregion
|
|
@@ -2431,7 +2481,9 @@ window.__ModuleLoader__.load({
|
|
|
2431
2481
|
/** 侧边栏提示已关闭标记(全局,无会话)。 */
|
|
2432
2482
|
sideHint: "edrv.side-hint-dismissed",
|
|
2433
2483
|
/** 「性能优化」页工作区栏目展开状态(workspaceFoldCache v1,全局不按会话)。 */
|
|
2434
|
-
workspaceFold: "edrv.ws-fold.v1."
|
|
2484
|
+
workspaceFold: "edrv.ws-fold.v1.",
|
|
2485
|
+
/** 规则面板 UI 状态(RulesPanel v1:Tab 与项目工作区选择,全局不按会话)。 */
|
|
2486
|
+
rules: "edrv.rules.v1."
|
|
2435
2487
|
};
|
|
2436
2488
|
//#endregion
|
|
2437
2489
|
//#region src/client/state/viewStateCache.ts
|
|
@@ -2537,6 +2589,36 @@ window.__ModuleLoader__.load({
|
|
|
2537
2589
|
window.localStorage.setItem(KEY_PREFIX$2 + String(sessionId), serializeViewStates(states));
|
|
2538
2590
|
} catch (error) {}
|
|
2539
2591
|
}
|
|
2592
|
+
let currentMin = 300;
|
|
2593
|
+
/**
|
|
2594
|
+
* 归一化最小宽度:非法(NaN/非有限/负数)回退默认,越界夹取到 [180, 560]。
|
|
2595
|
+
* @author ddj 2026年09月04号
|
|
2596
|
+
* @param value 原始值(设置文档来的任意 JSON 值)
|
|
2597
|
+
* @returns 合法最小宽度
|
|
2598
|
+
*/
|
|
2599
|
+
function normalizeSidebarMinWidth(value) {
|
|
2600
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
2601
|
+
if (!Number.isFinite(n) || n <= 0) return 300;
|
|
2602
|
+
return Math.max(180, Math.min(560, Math.round(n)));
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* 应用设置值(client/index.ts 设置订阅同步调用)。
|
|
2606
|
+
* @author ddj 2026年09月04号
|
|
2607
|
+
* @param value 设置文档中的 sidebarMinWidth
|
|
2608
|
+
* @returns 归一化后的生效值
|
|
2609
|
+
*/
|
|
2610
|
+
function sidebarMinApply(value) {
|
|
2611
|
+
currentMin = normalizeSidebarMinWidth(value);
|
|
2612
|
+
return currentMin;
|
|
2613
|
+
}
|
|
2614
|
+
/**
|
|
2615
|
+
* 读取当前生效的最小宽度(编辑器初始/恢复/拖拽夹取共用)。
|
|
2616
|
+
* @author ddj 2026年09月04号
|
|
2617
|
+
* @returns 当前最小宽度
|
|
2618
|
+
*/
|
|
2619
|
+
function getSidebarMinWidth() {
|
|
2620
|
+
return currentMin;
|
|
2621
|
+
}
|
|
2540
2622
|
/** 路径一致(容忍相对路径大小写差异,对齐既有 sameFile 语义常用写法)。 */
|
|
2541
2623
|
function samePath(a, b) {
|
|
2542
2624
|
if (a === b) return true;
|
|
@@ -3534,7 +3616,7 @@ window.__ModuleLoader__.load({
|
|
|
3534
3616
|
const [fileIdx, setFileIdx] = react.default.useState(0);
|
|
3535
3617
|
const [tabMenu, setTabMenu] = react.default.useState(null);
|
|
3536
3618
|
const [sidebarOn, setSidebarOn] = react.default.useState(layout !== "side");
|
|
3537
|
-
const [sidebarW, setSidebarW] = react.default.useState(
|
|
3619
|
+
const [sidebarW, setSidebarW] = react.default.useState(() => getSidebarMinWidth());
|
|
3538
3620
|
const [activePanel, setActivePanel] = react.default.useState("explorer");
|
|
3539
3621
|
const [focusRequest, setFocusRequest] = react.default.useState(0);
|
|
3540
3622
|
useKeybindingsVersion();
|
|
@@ -4005,11 +4087,20 @@ window.__ModuleLoader__.load({
|
|
|
4005
4087
|
if (raw) {
|
|
4006
4088
|
const saved = JSON.parse(raw);
|
|
4007
4089
|
if (typeof saved.on === "boolean") setSidebarOn(saved.on);
|
|
4008
|
-
if (typeof saved.width === "number") setSidebarW(Math.max(
|
|
4090
|
+
if (typeof saved.width === "number") setSidebarW(Math.max(getSidebarMinWidth(), Math.min(560, saved.width)));
|
|
4009
4091
|
if (typeof saved.panel === "string") setActivePanel(saved.panel);
|
|
4010
4092
|
}
|
|
4011
4093
|
} catch (e) {}
|
|
4012
4094
|
}, [sessionId, sidebarKey]);
|
|
4095
|
+
const [sidebarMinW, setSidebarMinW] = react.default.useState(() => getSidebarMinWidth());
|
|
4096
|
+
react.default.useEffect(() => {
|
|
4097
|
+
const onMinChange = () => {
|
|
4098
|
+
setSidebarMinW(getSidebarMinWidth());
|
|
4099
|
+
setSidebarW((w) => Math.max(getSidebarMinWidth(), w));
|
|
4100
|
+
};
|
|
4101
|
+
window.addEventListener("edrv:sidebar-min-width", onMinChange);
|
|
4102
|
+
return () => window.removeEventListener("edrv:sidebar-min-width", onMinChange);
|
|
4103
|
+
}, []);
|
|
4013
4104
|
react.default.useEffect(() => {
|
|
4014
4105
|
if (!sessionId) return;
|
|
4015
4106
|
try {
|
|
@@ -4888,7 +4979,7 @@ window.__ModuleLoader__.load({
|
|
|
4888
4979
|
onClick: navForward
|
|
4889
4980
|
}, "→"), react.default.createElement("button", {
|
|
4890
4981
|
className: "edrv-chip-btn" + (sidebarOn ? " edrv-chip-on" : ""),
|
|
4891
|
-
title: "
|
|
4982
|
+
title: "切换面板区 (" + (chordOf("edrv.toggleSidebar") ?? "Ctrl+B") + "),图标列常显",
|
|
4892
4983
|
onClick: () => setSidebarOn((v) => !v)
|
|
4893
4984
|
}, "☰"), react.default.createElement("button", {
|
|
4894
4985
|
className: "edrv-chip-btn",
|
|
@@ -5086,6 +5177,7 @@ window.__ModuleLoader__.load({
|
|
|
5086
5177
|
const sidebarPanels = props.sidebarPanels;
|
|
5087
5178
|
const sidebarCtx = {
|
|
5088
5179
|
sessionId,
|
|
5180
|
+
cwd: props.sessions?.list?.getSnapshot?.()?.byId?.[sessionId]?.cwd ?? null,
|
|
5089
5181
|
openFile: (p) => openFile(p, false),
|
|
5090
5182
|
openFileAt,
|
|
5091
5183
|
activePath: active,
|
|
@@ -5132,14 +5224,17 @@ window.__ModuleLoader__.load({
|
|
|
5132
5224
|
overflow: "hidden"
|
|
5133
5225
|
}
|
|
5134
5226
|
}, pathBar, tabRow, sideHintEl, editorArea, lspFooter);
|
|
5135
|
-
const editorRow = react.default.createElement("div", { className: "edrv-editor-row" },
|
|
5227
|
+
const editorRow = react.default.createElement("div", { className: "edrv-editor-row" }, sidebarPanels ? react.default.createElement(SidebarView, {
|
|
5136
5228
|
registry: sidebarPanels,
|
|
5137
5229
|
ctx: sidebarCtx,
|
|
5138
5230
|
activePanel,
|
|
5139
5231
|
onActive: setActivePanel,
|
|
5232
|
+
visible: sidebarOn,
|
|
5233
|
+
onShow: () => setSidebarOn(true),
|
|
5140
5234
|
width: sidebarW,
|
|
5141
5235
|
onWidth: setSidebarW,
|
|
5142
|
-
onHide: () => setSidebarOn(false)
|
|
5236
|
+
onHide: () => setSidebarOn(false),
|
|
5237
|
+
minWidth: sidebarMinW
|
|
5143
5238
|
}) : null, mainCol);
|
|
5144
5239
|
const baseStyle = {
|
|
5145
5240
|
minHeight: 0,
|
|
@@ -6909,7 +7004,7 @@ window.__ModuleLoader__.load({
|
|
|
6909
7004
|
}));
|
|
6910
7005
|
return react.default.createElement("section", { className: "vsm-project" }, head, body);
|
|
6911
7006
|
}
|
|
6912
|
-
/** 通用设置:选择当前对话文件链接的打开器 +
|
|
7007
|
+
/** 通用设置:选择当前对话文件链接的打开器 + 开发形态开关 + 编辑器布局(侧边栏最小宽度)。 */
|
|
6913
7008
|
function GeneralSettings({ registry }) {
|
|
6914
7009
|
const [tool, setTool] = react.default.useState(AUTO_OPEN_TOOL);
|
|
6915
7010
|
const [busy, setBusy] = react.default.useState(false);
|
|
@@ -6917,6 +7012,8 @@ window.__ModuleLoader__.load({
|
|
|
6917
7012
|
const [devForm, setDevForm] = react.default.useState(null);
|
|
6918
7013
|
const [devBusy, setDevBusy] = react.default.useState(false);
|
|
6919
7014
|
const [devMessage, setDevMessage] = react.default.useState("");
|
|
7015
|
+
const [minW, setMinW] = react.default.useState(300);
|
|
7016
|
+
const [minDraft, setMinDraft] = react.default.useState(null);
|
|
6920
7017
|
const settings = react.default.useContext(SettingsContext);
|
|
6921
7018
|
const snapshot = settings?.getSnapshot?.();
|
|
6922
7019
|
const loading = !snapshot || snapshot.status === "loading";
|
|
@@ -6924,8 +7021,10 @@ window.__ModuleLoader__.load({
|
|
|
6924
7021
|
const notReady = snapshot?.status !== "ready";
|
|
6925
7022
|
react.default.useEffect(() => {
|
|
6926
7023
|
const onChange = () => {
|
|
6927
|
-
const
|
|
7024
|
+
const snap = settings?.getSnapshot?.();
|
|
7025
|
+
const next = snap?.value?.fileOpenTool;
|
|
6928
7026
|
if (typeof next === "string") setTool(next);
|
|
7027
|
+
setMinW(normalizeSidebarMinWidth(snap?.value?.sidebarMinWidth));
|
|
6929
7028
|
};
|
|
6930
7029
|
onChange();
|
|
6931
7030
|
return settings?.subscribe?.(onChange);
|
|
@@ -6946,6 +7045,25 @@ window.__ModuleLoader__.load({
|
|
|
6946
7045
|
}
|
|
6947
7046
|
settings.set("fileOpenTool", value).catch((e) => setError(String(e))).finally(() => setBusy(false));
|
|
6948
7047
|
};
|
|
7048
|
+
/** 提交侧边栏最小宽度(归一化夹取 180–560 后持久化)。 */
|
|
7049
|
+
const saveMinW = (raw) => {
|
|
7050
|
+
const next = normalizeSidebarMinWidth(raw);
|
|
7051
|
+
setMinW(next);
|
|
7052
|
+
setBusy(true);
|
|
7053
|
+
setError("");
|
|
7054
|
+
if (!settings?.set) {
|
|
7055
|
+
setError("设置服务不可用");
|
|
7056
|
+
setBusy(false);
|
|
7057
|
+
return;
|
|
7058
|
+
}
|
|
7059
|
+
settings.set("sidebarMinWidth", next).catch((e) => setError(String(e))).finally(() => setBusy(false));
|
|
7060
|
+
};
|
|
7061
|
+
/** 结束输入(blur/Enter)时提交草稿。 */
|
|
7062
|
+
const commitMinW = () => {
|
|
7063
|
+
if (minDraft === null) return;
|
|
7064
|
+
setMinDraft(null);
|
|
7065
|
+
saveMinW(minDraft);
|
|
7066
|
+
};
|
|
6949
7067
|
const closeDevForm = () => {
|
|
6950
7068
|
if (!window.confirm("关闭开发形态:插件将切换为正式版安装(版本依赖 + 删除工作区链接),pnpm 装配后需重启 DSH 生效。确认关闭?")) return;
|
|
6951
7069
|
setDevBusy(true);
|
|
@@ -6981,7 +7099,20 @@ window.__ModuleLoader__.load({
|
|
|
6981
7099
|
}, options.map((item) => react.default.createElement("option", {
|
|
6982
7100
|
key: item.id,
|
|
6983
7101
|
value: item.id
|
|
6984
|
-
}, item.label))), loading && react.default.createElement("small", null, "读取中…")), devFormRow)))
|
|
7102
|
+
}, item.label))), loading && react.default.createElement("small", null, "读取中…")), devFormRow)), react.default.createElement("section", { className: "vsm-panel" }, react.default.createElement("h3", { className: "vsm-panel-title" }, "编辑器"), react.default.createElement("div", { className: "vsm-panel-body" }, react.default.createElement("label", { className: "vsm-general-row" }, react.default.createElement("span", null, "侧边栏最小宽度"), react.default.createElement("input", {
|
|
7103
|
+
type: "number",
|
|
7104
|
+
min: 180,
|
|
7105
|
+
max: 560,
|
|
7106
|
+
step: 10,
|
|
7107
|
+
value: minDraft ?? minW,
|
|
7108
|
+
disabled: loading || unavailable || notReady || busy || snapshot?.writable === false,
|
|
7109
|
+
title: "180–560 px;拖拽侧边栏低于该宽度时自动隐藏",
|
|
7110
|
+
onChange: (event) => setMinDraft(event.target.value),
|
|
7111
|
+
onBlur: commitMinW,
|
|
7112
|
+
onKeyDown: (event) => {
|
|
7113
|
+
if (event.key === "Enter") commitMinW();
|
|
7114
|
+
}
|
|
7115
|
+
}), react.default.createElement("small", null, "180–560 px;拖拽低于该宽度自动隐藏")))));
|
|
6985
7116
|
}
|
|
6986
7117
|
/** 兼容性小节:host 报告(RPC compat)+ 客户端本地适配项。 */
|
|
6987
7118
|
function CompatSection({ getSummary }) {
|
|
@@ -7368,7 +7499,8 @@ window.__ModuleLoader__.load({
|
|
|
7368
7499
|
addToConversation: props?.addToConversation,
|
|
7369
7500
|
sidebarPanels: props?.sidebarPanels,
|
|
7370
7501
|
outlineSources: props?.outlineSources,
|
|
7371
|
-
fileMenuItems: props?.fileMenuItems
|
|
7502
|
+
fileMenuItems: props?.fileMenuItems,
|
|
7503
|
+
sessions: props?.sessions
|
|
7372
7504
|
});
|
|
7373
7505
|
}
|
|
7374
7506
|
//#endregion
|
|
@@ -8439,10 +8571,384 @@ window.__ModuleLoader__.load({
|
|
|
8439
8571
|
})), optsBar, filterRows, summary, warnBanner, body);
|
|
8440
8572
|
}
|
|
8441
8573
|
//#endregion
|
|
8574
|
+
//#region src/client/sidebar/panels/RulesPanel.ts
|
|
8575
|
+
/**
|
|
8576
|
+
* dsh-vscode-mode client — 侧边栏「规则」面板(Codebuddy 规则管理形态)。
|
|
8577
|
+
* 双 Tab:用户规则(~/.dsh/rules/)与项目规则(<工作区>/.dsh/rules/);
|
|
8578
|
+
* 列表行 = 文件名 + 相对提示 + 类型徽标(总是/自动/手动)+ 描述 + 编辑/删除/启用开关;
|
|
8579
|
+
* 新建/编辑 = 内嵌表单(文件名 + 原始 .mdc 文本域,frontmatter 可见),保存走 rules.save。
|
|
8580
|
+
* 作者 ddj 2026年09月03号
|
|
8581
|
+
*/
|
|
8582
|
+
/** 新建规则模板(frontmatter 字段与 host parseRuleMdc 对齐)。 */
|
|
8583
|
+
const NEW_TEMPLATE = "---\ndescription: \nalwaysApply: true\n---\n\n";
|
|
8584
|
+
const TYPE_LABEL = {
|
|
8585
|
+
always: "总是",
|
|
8586
|
+
auto: "自动",
|
|
8587
|
+
manual: "手动"
|
|
8588
|
+
};
|
|
8589
|
+
/**
|
|
8590
|
+
* 读 localStorage(损坏/不可用安全)。
|
|
8591
|
+
* @author ddj 2026年09月03号
|
|
8592
|
+
* @param key 键
|
|
8593
|
+
* @returns 值或 null
|
|
8594
|
+
*/
|
|
8595
|
+
function readLocal(key) {
|
|
8596
|
+
try {
|
|
8597
|
+
return localStorage.getItem(key);
|
|
8598
|
+
} catch (e) {
|
|
8599
|
+
return null;
|
|
8600
|
+
}
|
|
8601
|
+
}
|
|
8602
|
+
/**
|
|
8603
|
+
* 写 localStorage(不可用安全)。
|
|
8604
|
+
* @author ddj 2026年09月03号
|
|
8605
|
+
* @param key 键
|
|
8606
|
+
* @param value 值
|
|
8607
|
+
*/
|
|
8608
|
+
function writeLocal(key, value) {
|
|
8609
|
+
try {
|
|
8610
|
+
localStorage.setItem(key, value);
|
|
8611
|
+
} catch (e) {}
|
|
8612
|
+
}
|
|
8613
|
+
/**
|
|
8614
|
+
* 类型徽标(总是=绿 / 自动=蓝 / 手动=灰)。
|
|
8615
|
+
* @author ddj 2026年09月03号
|
|
8616
|
+
* @param type 规则类型
|
|
8617
|
+
* @returns 徽标元素
|
|
8618
|
+
*/
|
|
8619
|
+
function typeBadge(type) {
|
|
8620
|
+
return react.default.createElement("span", { className: "edrv-rules-type edrv-rules-type-" + type }, TYPE_LABEL[type] ?? type);
|
|
8621
|
+
}
|
|
8622
|
+
/**
|
|
8623
|
+
* 渲染一条规则行:文件名 + 相对提示 + 类型徽标,第二行描述;右侧编辑/删除/开关。
|
|
8624
|
+
* @author ddj 2026年09月03号
|
|
8625
|
+
* @param props.rule 规则元信息
|
|
8626
|
+
* @param props.onEdit 编辑回调
|
|
8627
|
+
* @param props.onRemove 删除回调
|
|
8628
|
+
* @param props.onToggle 开关回调
|
|
8629
|
+
* @returns 行元素
|
|
8630
|
+
*/
|
|
8631
|
+
function RuleRow(props) {
|
|
8632
|
+
const rule = props.rule;
|
|
8633
|
+
const desc = [rule.error ? "解析失败:" + rule.error : null, rule.description || (rule.type === "auto" ? "globs: " + rule.globs.join(", ") : "")].filter(Boolean).join(" · ");
|
|
8634
|
+
return react.default.createElement("div", { className: "edrv-rules-row" + (rule.enabled ? "" : " off") }, react.default.createElement("div", {
|
|
8635
|
+
className: "edrv-rules-main",
|
|
8636
|
+
onClick: () => props.onEdit(rule),
|
|
8637
|
+
title: rule.absPath
|
|
8638
|
+
}, react.default.createElement("span", { className: "edrv-rules-file" }, rule.file), react.default.createElement("span", { className: "edrv-rules-path" }, "[" + rule.relHint + rule.file + "]"), typeBadge(rule.type), !rule.enabled ? react.default.createElement("span", { className: "edrv-rules-offtag" }, "已停用") : null), react.default.createElement("div", {
|
|
8639
|
+
className: "edrv-rules-desc",
|
|
8640
|
+
title: desc
|
|
8641
|
+
}, desc ? "描述: " + desc : "描述: —"), react.default.createElement("div", { className: "edrv-rules-actions" }, react.default.createElement("button", {
|
|
8642
|
+
className: "edrv-rules-act",
|
|
8643
|
+
title: "编辑",
|
|
8644
|
+
onClick: () => props.onEdit(rule)
|
|
8645
|
+
}, "✏️"), react.default.createElement("button", {
|
|
8646
|
+
className: "edrv-rules-act",
|
|
8647
|
+
title: "删除",
|
|
8648
|
+
onClick: () => props.onRemove(rule)
|
|
8649
|
+
}, "🗑"), react.default.createElement("button", {
|
|
8650
|
+
className: "edrv-rules-switch" + (rule.enabled ? " on" : ""),
|
|
8651
|
+
role: "switch",
|
|
8652
|
+
"aria-checked": rule.enabled,
|
|
8653
|
+
title: rule.enabled ? "已启用(点击停用)" : "已停用(点击启用)",
|
|
8654
|
+
onClick: () => props.onToggle(rule)
|
|
8655
|
+
}, react.default.createElement("span", { className: "edrv-rules-knob" }))));
|
|
8656
|
+
}
|
|
8657
|
+
/**
|
|
8658
|
+
* 新建/编辑表单:文件名(仅新建可改)+ 原始 .mdc 文本域 + 保存/取消。
|
|
8659
|
+
* @author ddj 2026年09月03号
|
|
8660
|
+
* @param props.form 表单状态(mode/scope/workspacePath/file/content/error/saving)
|
|
8661
|
+
* @param props.setForm 表单更新函数
|
|
8662
|
+
* @param props.onSave 保存回调
|
|
8663
|
+
* @param props.onCancel 取消回调
|
|
8664
|
+
* @returns 表单元素
|
|
8665
|
+
*/
|
|
8666
|
+
function RuleEditor(props) {
|
|
8667
|
+
const form = props.form;
|
|
8668
|
+
const isNew = form.mode === "new";
|
|
8669
|
+
return react.default.createElement("div", { className: "edrv-rules-editor" }, react.default.createElement("div", { className: "edrv-rules-editor-head" }, isNew ? "新建" + (form.scope === "project" ? "项目" : "用户") + "规则" : "编辑:" + form.file, react.default.createElement("button", {
|
|
8670
|
+
className: "edrv-rules-act",
|
|
8671
|
+
title: "取消",
|
|
8672
|
+
onClick: props.onCancel
|
|
8673
|
+
}, "✕")), react.default.createElement("div", { className: "edrv-rules-editor-file" }, react.default.createElement("label", null, "文件名"), react.default.createElement("input", {
|
|
8674
|
+
className: "edrv-rules-input",
|
|
8675
|
+
value: form.file,
|
|
8676
|
+
disabled: !isNew,
|
|
8677
|
+
spellCheck: false,
|
|
8678
|
+
placeholder: "my-rule.mdc",
|
|
8679
|
+
onChange: (e) => props.setForm({
|
|
8680
|
+
...form,
|
|
8681
|
+
file: e.target.value
|
|
8682
|
+
})
|
|
8683
|
+
})), react.default.createElement("textarea", {
|
|
8684
|
+
className: "edrv-rules-body",
|
|
8685
|
+
spellCheck: false,
|
|
8686
|
+
value: form.content,
|
|
8687
|
+
onChange: (e) => props.setForm({
|
|
8688
|
+
...form,
|
|
8689
|
+
content: e.target.value
|
|
8690
|
+
})
|
|
8691
|
+
}), react.default.createElement("div", { className: "edrv-rules-editor-hint" }, "frontmatter 支持 description / alwaysApply / globs / enabled;无 frontmatter 的纯 markdown 视为「手动」规则"), form.error ? react.default.createElement("div", { className: "edrv-rules-err" }, form.error) : null, react.default.createElement("div", { className: "edrv-rules-editor-foot" }, react.default.createElement("button", {
|
|
8692
|
+
className: "edrv-rules-save",
|
|
8693
|
+
disabled: form.saving,
|
|
8694
|
+
onClick: props.onSave
|
|
8695
|
+
}, form.saving ? "保存中…" : "保存")));
|
|
8696
|
+
}
|
|
8697
|
+
/**
|
|
8698
|
+
* 规则面板主体。
|
|
8699
|
+
* @param props.ctx 面板共享上下文(notify 可选)
|
|
8700
|
+
*/
|
|
8701
|
+
function RulesPanel(props) {
|
|
8702
|
+
const ctx = props?.ctx;
|
|
8703
|
+
const notify = ctx?.notify ?? ((message) => {});
|
|
8704
|
+
const cwd = ctx?.cwd ?? null;
|
|
8705
|
+
const [tab, setTab] = react.default.useState(() => readLocal(CACHE_KEY.rules + "tab") === "project" ? "project" : "user");
|
|
8706
|
+
const [data, setData] = react.default.useState(null);
|
|
8707
|
+
const [error, setError] = react.default.useState("");
|
|
8708
|
+
const [form, setForm] = react.default.useState(null);
|
|
8709
|
+
const mountedRef = react.default.useRef(true);
|
|
8710
|
+
/**
|
|
8711
|
+
* 当前工作区对应的项目聚合(按 ctx.cwd 自动匹配;无会话/未注册返回 null)。
|
|
8712
|
+
* @returns RuleProject 或 null
|
|
8713
|
+
*/
|
|
8714
|
+
const activeProject = () => {
|
|
8715
|
+
if (!cwd) return null;
|
|
8716
|
+
return (data?.projects ?? []).find((p) => p.workspacePath === cwd) ?? null;
|
|
8717
|
+
};
|
|
8718
|
+
/** 拉取规则总列表(rules.list)。 */
|
|
8719
|
+
const load = () => {
|
|
8720
|
+
rpc("rules.list", {}).then((res) => {
|
|
8721
|
+
if (!mountedRef.current) return;
|
|
8722
|
+
if (res && res.ok) {
|
|
8723
|
+
setData(res);
|
|
8724
|
+
setError("");
|
|
8725
|
+
} else setError(res?.error ?? "读取规则失败");
|
|
8726
|
+
}).catch((e) => {
|
|
8727
|
+
if (mountedRef.current) setError("读取规则异常: " + String(e));
|
|
8728
|
+
});
|
|
8729
|
+
};
|
|
8730
|
+
react.default.useEffect(() => {
|
|
8731
|
+
mountedRef.current = true;
|
|
8732
|
+
load();
|
|
8733
|
+
return () => {
|
|
8734
|
+
mountedRef.current = false;
|
|
8735
|
+
};
|
|
8736
|
+
}, []);
|
|
8737
|
+
/**
|
|
8738
|
+
* 切换 Tab(记忆到 localStorage)。
|
|
8739
|
+
* @param next 目标 Tab
|
|
8740
|
+
*/
|
|
8741
|
+
const switchTab = (next) => {
|
|
8742
|
+
setTab(next);
|
|
8743
|
+
writeLocal(CACHE_KEY.rules + "tab", next);
|
|
8744
|
+
};
|
|
8745
|
+
/**
|
|
8746
|
+
* 打开新建表单(按当前 Tab 决定作用域;项目规则跟随当前会话工作区)。
|
|
8747
|
+
*/
|
|
8748
|
+
const openNew = () => {
|
|
8749
|
+
const scope = tab === "project" ? "project" : "user";
|
|
8750
|
+
if (scope === "project" && !cwd) {
|
|
8751
|
+
notify("当前会话没有工作区,无法新建项目规则");
|
|
8752
|
+
return;
|
|
8753
|
+
}
|
|
8754
|
+
setForm({
|
|
8755
|
+
mode: "new",
|
|
8756
|
+
scope,
|
|
8757
|
+
workspacePath: scope === "project" ? cwd : void 0,
|
|
8758
|
+
file: "",
|
|
8759
|
+
content: NEW_TEMPLATE,
|
|
8760
|
+
error: "",
|
|
8761
|
+
saving: false
|
|
8762
|
+
});
|
|
8763
|
+
};
|
|
8764
|
+
/**
|
|
8765
|
+
* 打开编辑表单:先拉全文再进入编辑态。
|
|
8766
|
+
* @param rule 目标规则
|
|
8767
|
+
*/
|
|
8768
|
+
const openEdit = (rule) => {
|
|
8769
|
+
rpc("rules.read", {
|
|
8770
|
+
scope: rule.scope,
|
|
8771
|
+
workspacePath: rule.scope === "project" ? rule.workspacePath : void 0,
|
|
8772
|
+
file: rule.file
|
|
8773
|
+
}).then((res) => {
|
|
8774
|
+
if (res && res.ok) setForm({
|
|
8775
|
+
mode: "edit",
|
|
8776
|
+
scope: rule.scope,
|
|
8777
|
+
workspacePath: rule.workspacePath,
|
|
8778
|
+
file: rule.file,
|
|
8779
|
+
content: res.content,
|
|
8780
|
+
error: "",
|
|
8781
|
+
saving: false
|
|
8782
|
+
});
|
|
8783
|
+
else notify(res?.error ?? "读取规则失败");
|
|
8784
|
+
}).catch((e) => notify("读取规则异常: " + String(e)));
|
|
8785
|
+
};
|
|
8786
|
+
/** 保存表单(rules.save;文件名仅新建校验非空)。 */
|
|
8787
|
+
const saveForm = () => {
|
|
8788
|
+
const next = {
|
|
8789
|
+
...form,
|
|
8790
|
+
saving: true,
|
|
8791
|
+
error: ""
|
|
8792
|
+
};
|
|
8793
|
+
const file = String(form.file ?? "").trim();
|
|
8794
|
+
if (!file) {
|
|
8795
|
+
setForm({
|
|
8796
|
+
...next,
|
|
8797
|
+
saving: false,
|
|
8798
|
+
error: "文件名不能为空"
|
|
8799
|
+
});
|
|
8800
|
+
return;
|
|
8801
|
+
}
|
|
8802
|
+
setForm(next);
|
|
8803
|
+
rpc("rules.save", {
|
|
8804
|
+
scope: form.scope,
|
|
8805
|
+
workspacePath: form.workspacePath,
|
|
8806
|
+
file,
|
|
8807
|
+
content: form.content
|
|
8808
|
+
}).then((res) => {
|
|
8809
|
+
if (res && res.ok) {
|
|
8810
|
+
setForm(null);
|
|
8811
|
+
notify("规则已保存:" + file);
|
|
8812
|
+
load();
|
|
8813
|
+
} else setForm((prev) => ({
|
|
8814
|
+
...prev,
|
|
8815
|
+
saving: false,
|
|
8816
|
+
error: res?.error ?? "保存失败"
|
|
8817
|
+
}));
|
|
8818
|
+
}).catch((e) => setForm((prev) => ({
|
|
8819
|
+
...prev,
|
|
8820
|
+
saving: false,
|
|
8821
|
+
error: "保存异常: " + String(e)
|
|
8822
|
+
})));
|
|
8823
|
+
};
|
|
8824
|
+
/**
|
|
8825
|
+
* 删除规则(confirm 后走 rules.remove)。
|
|
8826
|
+
* @param rule 目标规则
|
|
8827
|
+
*/
|
|
8828
|
+
const removeRule = (rule) => {
|
|
8829
|
+
if (!window.confirm("删除规则 " + rule.file + "?(不可恢复)")) return;
|
|
8830
|
+
rpc("rules.remove", {
|
|
8831
|
+
scope: rule.scope,
|
|
8832
|
+
workspacePath: rule.workspacePath,
|
|
8833
|
+
file: rule.file
|
|
8834
|
+
}).then((res) => {
|
|
8835
|
+
if (res && res.ok) {
|
|
8836
|
+
notify("已删除:" + rule.file);
|
|
8837
|
+
load();
|
|
8838
|
+
} else notify(res?.error ?? "删除失败");
|
|
8839
|
+
}).catch((e) => notify("删除异常: " + String(e)));
|
|
8840
|
+
};
|
|
8841
|
+
/**
|
|
8842
|
+
* 切换启用开关:本地乐观翻转(按 workspacePath+file 定位,失败回滚)。
|
|
8843
|
+
* @param rule 目标规则(project 已注入 workspacePath)
|
|
8844
|
+
*/
|
|
8845
|
+
const toggleRule = (rule) => {
|
|
8846
|
+
const enabled = !rule.enabled;
|
|
8847
|
+
const applyLocal = (on) => setData((prev) => prev ? {
|
|
8848
|
+
...prev,
|
|
8849
|
+
user: prev.user.map((r) => r.scope === "user" && r.file === rule.file ? {
|
|
8850
|
+
...r,
|
|
8851
|
+
enabled: on
|
|
8852
|
+
} : r),
|
|
8853
|
+
projects: prev.projects.map((p) => p.workspacePath === rule.workspacePath ? {
|
|
8854
|
+
...p,
|
|
8855
|
+
rules: p.rules.map((r) => r.file === rule.file ? {
|
|
8856
|
+
...r,
|
|
8857
|
+
enabled: on
|
|
8858
|
+
} : r)
|
|
8859
|
+
} : p)
|
|
8860
|
+
} : prev);
|
|
8861
|
+
applyLocal(enabled);
|
|
8862
|
+
rpc("rules.toggle", {
|
|
8863
|
+
scope: rule.scope,
|
|
8864
|
+
workspacePath: rule.workspacePath,
|
|
8865
|
+
file: rule.file,
|
|
8866
|
+
enabled
|
|
8867
|
+
}).then((res) => {
|
|
8868
|
+
if (res && res.ok) {
|
|
8869
|
+
applyLocal(res.rule?.enabled === true);
|
|
8870
|
+
notify(res.rule?.enabled === false ? "已停用:" + rule.file : "已启用:" + rule.file);
|
|
8871
|
+
} else {
|
|
8872
|
+
applyLocal(!enabled);
|
|
8873
|
+
notify(res?.error ?? "切换失败");
|
|
8874
|
+
}
|
|
8875
|
+
}).catch((e) => {
|
|
8876
|
+
applyLocal(!enabled);
|
|
8877
|
+
notify("切换异常: " + String(e));
|
|
8878
|
+
});
|
|
8879
|
+
};
|
|
8880
|
+
/** 当前列表数据(按 Tab 取用户规则或当前工作区的项目规则)。 */
|
|
8881
|
+
const rowsOf = () => {
|
|
8882
|
+
if (!data) return [];
|
|
8883
|
+
if (tab === "user") return data.user;
|
|
8884
|
+
return activeProject()?.rules ?? [];
|
|
8885
|
+
};
|
|
8886
|
+
const renderTabs = () => react.default.createElement("div", { className: "edrv-rules-tabs" }, react.default.createElement("button", {
|
|
8887
|
+
className: "edrv-rules-tab" + (tab === "user" ? " on" : ""),
|
|
8888
|
+
onClick: () => switchTab("user")
|
|
8889
|
+
}, "用户规则"), react.default.createElement("button", {
|
|
8890
|
+
className: "edrv-rules-tab" + (tab === "project" ? " on" : ""),
|
|
8891
|
+
onClick: () => switchTab("project")
|
|
8892
|
+
}, "项目规则"), react.default.createElement("button", {
|
|
8893
|
+
className: "edrv-rules-new",
|
|
8894
|
+
title: "新建规则",
|
|
8895
|
+
onClick: openNew
|
|
8896
|
+
}, "+ 新建规则"));
|
|
8897
|
+
/** 项目 Tab 的工作区展示(不可编辑,自动跟随当前会话)。 */
|
|
8898
|
+
const renderWsLine = () => {
|
|
8899
|
+
if (tab !== "project") return null;
|
|
8900
|
+
return react.default.createElement("div", {
|
|
8901
|
+
className: "edrv-rules-ws-line",
|
|
8902
|
+
title: cwd ?? ""
|
|
8903
|
+
}, "工作区:" + (cwd ?? "当前会话未打开工作区"));
|
|
8904
|
+
};
|
|
8905
|
+
const renderEmpty = () => {
|
|
8906
|
+
if (tab === "project") {
|
|
8907
|
+
if (!cwd) return "当前会话没有工作区,项目规则不可用(项目规则跟随会话所在工作区)";
|
|
8908
|
+
if (!data?.projects?.length) return "当前 DSH 没有已注册的工作区;在目标工作区打开一次会话后再来管理";
|
|
8909
|
+
if (!activeProject()) return "当前工作区未注册为 DSH workspace,暂不能管理其项目规则";
|
|
8910
|
+
return "<工作区>/.dsh/rules/ 还没有规则,点击「+ 新建规则」创建";
|
|
8911
|
+
}
|
|
8912
|
+
return "还没有用户规则(~/.dsh/rules/),点击「+ 新建规则」创建";
|
|
8913
|
+
};
|
|
8914
|
+
const renderBody = () => {
|
|
8915
|
+
if (form) return react.default.createElement(RuleEditor, {
|
|
8916
|
+
form,
|
|
8917
|
+
setForm,
|
|
8918
|
+
onSave: saveForm,
|
|
8919
|
+
onCancel: () => setForm(null)
|
|
8920
|
+
});
|
|
8921
|
+
if (!data) return react.default.createElement("div", { className: "edrv-rules-empty" }, "加载中…");
|
|
8922
|
+
if (error) return react.default.createElement("div", { className: "edrv-rules-err" }, error);
|
|
8923
|
+
const rows = rowsOf();
|
|
8924
|
+
if (!rows.length) return react.default.createElement("div", { className: "edrv-rules-empty" }, renderEmpty());
|
|
8925
|
+
const common = {
|
|
8926
|
+
onEdit: (rule) => openEdit({
|
|
8927
|
+
...rule,
|
|
8928
|
+
workspacePath: rule.scope === "project" ? cwd : void 0
|
|
8929
|
+
}),
|
|
8930
|
+
onRemove: (rule) => removeRule({
|
|
8931
|
+
...rule,
|
|
8932
|
+
workspacePath: rule.scope === "project" ? cwd : void 0
|
|
8933
|
+
}),
|
|
8934
|
+
onToggle: (rule) => toggleRule({
|
|
8935
|
+
...rule,
|
|
8936
|
+
workspacePath: rule.scope === "project" ? cwd : void 0
|
|
8937
|
+
})
|
|
8938
|
+
};
|
|
8939
|
+
return react.default.createElement("div", { className: "edrv-rules-list" }, rows.map((rule) => react.default.createElement(RuleRow, {
|
|
8940
|
+
key: rule.scope + ":" + rule.file,
|
|
8941
|
+
rule,
|
|
8942
|
+
...common
|
|
8943
|
+
})));
|
|
8944
|
+
};
|
|
8945
|
+
return react.default.createElement("div", { className: "edrv-rules-panel" }, renderTabs(), renderWsLine(), react.default.createElement("div", { className: "edrv-rules-hint" }, tab === "user" ? "用户规则对所有会话生效(存放于 ~/.dsh/rules/)" : "项目规则仅对所在工作区的会话生效(存放于 <工作区>/.dsh/rules/)"), renderBody());
|
|
8946
|
+
}
|
|
8947
|
+
//#endregion
|
|
8442
8948
|
//#region src/client/sidebar/panels/index.ts
|
|
8443
8949
|
/**
|
|
8444
|
-
* dsh-vscode-mode client — 侧边栏面板定义(文件管理 +
|
|
8445
|
-
* 作者 ddj 2026-08-26 / 2026-
|
|
8950
|
+
* dsh-vscode-mode client — 侧边栏面板定义(文件管理 + 搜索 + 规则)。
|
|
8951
|
+
* 作者 ddj 2026-08-26 / 2026-09-03
|
|
8446
8952
|
*/
|
|
8447
8953
|
/**
|
|
8448
8954
|
* 构造文件管理面板定义。
|
|
@@ -8473,6 +8979,20 @@ window.__ModuleLoader__.load({
|
|
|
8473
8979
|
render: (ctx) => react.default.createElement(SearchPanel, { ctx })
|
|
8474
8980
|
};
|
|
8475
8981
|
}
|
|
8982
|
+
/**
|
|
8983
|
+
* 构造规则管理面板定义(Codebuddy 规则形态:用户规则/项目规则双 Tab + 开关)。
|
|
8984
|
+
* @author ddj 2026年09月03号
|
|
8985
|
+
* @returns 面板定义(无徽标;活动栏图标 📏,与大纲 📜 区分)
|
|
8986
|
+
*/
|
|
8987
|
+
function createRulesPanel() {
|
|
8988
|
+
return {
|
|
8989
|
+
id: "rules",
|
|
8990
|
+
title: "规则",
|
|
8991
|
+
icon: "📏",
|
|
8992
|
+
order: 20,
|
|
8993
|
+
render: (ctx) => react.default.createElement(RulesPanel, { ctx })
|
|
8994
|
+
};
|
|
8995
|
+
}
|
|
8476
8996
|
//#endregion
|
|
8477
8997
|
//#region src/client/sidebar/menuItems.ts
|
|
8478
8998
|
/**
|
|
@@ -9407,6 +9927,7 @@ window.__ModuleLoader__.load({
|
|
|
9407
9927
|
ctx.provide("edrvSidebarPanels", sidebarPanels);
|
|
9408
9928
|
ctx.effect(() => sidebarPanels.register(createFilePanel()), "vscode-mode: sidebar panel");
|
|
9409
9929
|
ctx.effect(() => sidebarPanels.register(createSearchPanel()), "vscode-mode: sidebar panel search");
|
|
9930
|
+
ctx.effect(() => sidebarPanels.register(createRulesPanel()), "vscode-mode: sidebar panel rules");
|
|
9410
9931
|
const fileMenuItems = createTreeMenuRegistry();
|
|
9411
9932
|
ctx.provide("edrvFileContextMenuItems", fileMenuItems);
|
|
9412
9933
|
for (const item of createDefaultFileMenuItems()) ctx.effect(() => fileMenuItems.register(item), "vscode-mode: file context menu item " + item.id);
|
|
@@ -9442,6 +9963,8 @@ window.__ModuleLoader__.load({
|
|
|
9442
9963
|
const snapshot = settings.getSnapshot();
|
|
9443
9964
|
if (snapshot.status === "loading") return;
|
|
9444
9965
|
keybindingsApply(snapshot.value?.keybindings);
|
|
9966
|
+
const minW = sidebarMinApply(snapshot.value?.sidebarMinWidth);
|
|
9967
|
+
window.dispatchEvent(new CustomEvent("edrv:sidebar-min-width", { detail: { value: minW } }));
|
|
9445
9968
|
};
|
|
9446
9969
|
sync();
|
|
9447
9970
|
return settings.subscribe(sync);
|
|
@@ -9474,7 +9997,8 @@ window.__ModuleLoader__.load({
|
|
|
9474
9997
|
addToConversation,
|
|
9475
9998
|
sidebarPanels,
|
|
9476
9999
|
outlineSources,
|
|
9477
|
-
fileMenuItems
|
|
10000
|
+
fileMenuItems,
|
|
10001
|
+
sessions
|
|
9478
10002
|
})));
|
|
9479
10003
|
};
|
|
9480
10004
|
let sideDisposer = null;
|
|
@@ -9493,7 +10017,8 @@ window.__ModuleLoader__.load({
|
|
|
9493
10017
|
addToConversation,
|
|
9494
10018
|
sidebarPanels,
|
|
9495
10019
|
outlineSources,
|
|
9496
|
-
fileMenuItems
|
|
10020
|
+
fileMenuItems,
|
|
10021
|
+
sessions
|
|
9497
10022
|
})),
|
|
9498
10023
|
activeSession: () => {
|
|
9499
10024
|
const snapshot = sessions?.list?.getSnapshot?.();
|