dsh-vscode-mode 0.1.43 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/lib/client.js +418 -92
- package/lib/client.js.map +1 -1
- package/lib/index.js +6 -3
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/keybindings.ts +41 -15
- package/src/client/monaco/lsp/providers.ts +129 -62
- package/src/client/navHistory.ts +104 -0
- package/src/client/styles/editor.css +2 -6
- package/src/client/ui/EditorView.ts +200 -10
- package/src/client/ui/KeybindingsPanel.ts +3 -3
- package/src/client/ui/QuickOpen.ts +2 -2
- package/src/shared/keybindings.ts +5 -2
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[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-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/* LSP 引用结果浮动面板(Shift+F12 / 右键「查找所有引用」) */\n[data-edrv-view] .edrv-refs { position: absolute; right: 12px; top: 40px; z-index: 60; width: 360px; max-height: 60%; display: flex; flex-direction: column; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 8px; background: var(--dsw-alias-bg-panel, #161b22); box-shadow: 0 6px 24px rgba(0,0,0,.4); overflow: hidden; font-size: 12px; }\n[data-edrv-view] .edrv-refs-head { padding: 6px 10px; font-weight: 600; color: var(--dsw-alias-label-primary, #eee); border-bottom: 1px solid var(--dsw-alias-border-l2, #333); background: var(--dsw-alias-bg-layer-1, transparent); }\n[data-edrv-view] .edrv-refs-list { overflow-y: auto; }\n[data-edrv-view] .edrv-refs-row { padding: 4px 10px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-secondary, #c0c8d0); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-refs-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.10)); color: var(--dsw-alias-label-primary, #fff); }\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[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";
|
|
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");
|
|
@@ -1560,15 +1560,18 @@ window.__ModuleLoader__.load({
|
|
|
1560
1560
|
/**
|
|
1561
1561
|
* dsh-vscode-mode shared — 快捷键命令目录与默认键位(双面契约)。
|
|
1562
1562
|
* 纯数据模块:host(settings schema 默认值)与 client(执行匹配/设置页)共用。
|
|
1563
|
-
* 键位格式:修饰符 + 主键,`+` 连接,如 `Ctrl+Shift+F`;空串 =
|
|
1563
|
+
* 键位格式:修饰符 + 主键,`+` 连接,如 `Ctrl+Shift+F`;空串 = 未绑定;
|
|
1564
|
+
* `|` 连接多个候选(任一命中即触发),如 `Alt+ArrowLeft|Ctrl+Alt+-`。
|
|
1564
1565
|
* 作者 ddj 2026年08月26号
|
|
1565
1566
|
*/
|
|
1566
|
-
/** 命令 id →
|
|
1567
|
+
/** 命令 id → 默认键位(可为多候选)。命令目录以此为准,新增命令只需加一项。 */
|
|
1567
1568
|
const KEYBINDING_DEFAULTS = {
|
|
1568
1569
|
"edrv.save": "Ctrl+S",
|
|
1569
1570
|
"edrv.quickOpen": "Ctrl+P",
|
|
1570
1571
|
"edrv.toggleSidebar": "Ctrl+B",
|
|
1571
|
-
"edrv.searchInFiles": "Ctrl+Shift+F"
|
|
1572
|
+
"edrv.searchInFiles": "Ctrl+Shift+F",
|
|
1573
|
+
"edrv.navigateBack": "Alt+ArrowLeft|Ctrl+Alt+-",
|
|
1574
|
+
"edrv.navigateForward": "Alt+ArrowRight|Ctrl+Shift+-"
|
|
1572
1575
|
};
|
|
1573
1576
|
/**
|
|
1574
1577
|
* 返回默认键位的独立副本(调用方修改不污染目录)。
|
|
@@ -1595,7 +1598,7 @@ window.__ModuleLoader__.load({
|
|
|
1595
1598
|
//#region src/client/keybindings.ts
|
|
1596
1599
|
/**
|
|
1597
1600
|
* dsh-vscode-mode client — 快捷键配置模块(解析/匹配/状态同步)。
|
|
1598
|
-
* 纯逻辑(parseChord/formatChord/matchEvent/chordFromEvent/normalizeKey)不依赖 DOM,可单测;
|
|
1601
|
+
* 纯逻辑(parseChord/parseChords/formatChord/matchEvent/chordFromEvent/normalizeKey)不依赖 DOM,可单测;
|
|
1599
1602
|
* 模块状态由 settings 订阅驱动(client/index.ts 调 keybindingsApply)。
|
|
1600
1603
|
* 键位语义:Ctrl 与 Cmd 互认(延续现有 Ctrl+P/Ctrl+B 捕获行为)。
|
|
1601
1604
|
* 作者 ddj 2026年08月26号
|
|
@@ -1617,6 +1620,14 @@ window.__ModuleLoader__.load({
|
|
|
1617
1620
|
{
|
|
1618
1621
|
id: "edrv.searchInFiles",
|
|
1619
1622
|
label: "在工作区中搜索"
|
|
1623
|
+
},
|
|
1624
|
+
{
|
|
1625
|
+
id: "edrv.navigateBack",
|
|
1626
|
+
label: "后退(导航历史)"
|
|
1627
|
+
},
|
|
1628
|
+
{
|
|
1629
|
+
id: "edrv.navigateForward",
|
|
1630
|
+
label: "前进(导航历史)"
|
|
1620
1631
|
}
|
|
1621
1632
|
];
|
|
1622
1633
|
const MODIFIERS = {
|
|
@@ -1631,6 +1642,7 @@ window.__ModuleLoader__.load({
|
|
|
1631
1642
|
const listeners$1 = /* @__PURE__ */ new Set();
|
|
1632
1643
|
/**
|
|
1633
1644
|
* 应用设置快照(与默认值合并;未知 id 丢弃;空对象 = 全部默认)。
|
|
1645
|
+
* 每个命令可含多候选键位(`|` 分隔),任一命中即触发。
|
|
1634
1646
|
* @author ddj 2026年08月26号
|
|
1635
1647
|
* @param raw 设置 scope 的 keybindings 字段
|
|
1636
1648
|
*/
|
|
@@ -1640,7 +1652,7 @@ window.__ModuleLoader__.load({
|
|
|
1640
1652
|
...normalizeKeybindings(raw)
|
|
1641
1653
|
};
|
|
1642
1654
|
parsed = {};
|
|
1643
|
-
for (const id of Object.keys(current)) parsed[id] =
|
|
1655
|
+
for (const id of Object.keys(current)) parsed[id] = parseChords(current[id]);
|
|
1644
1656
|
for (const listener of listeners$1) try {
|
|
1645
1657
|
listener();
|
|
1646
1658
|
} catch {}
|
|
@@ -1666,13 +1678,13 @@ window.__ModuleLoader__.load({
|
|
|
1666
1678
|
return typeof chord === "string" && chord.trim() !== "" ? chord : null;
|
|
1667
1679
|
}
|
|
1668
1680
|
/**
|
|
1669
|
-
*
|
|
1681
|
+
* 当前命令的解析键位集合(未绑定/非法 → 空数组;含多候选)。
|
|
1670
1682
|
* @author ddj 2026年08月26号
|
|
1671
1683
|
* @param id 命令 id
|
|
1672
|
-
* @returns
|
|
1684
|
+
* @returns 解析键位数组(可能为空)
|
|
1673
1685
|
*/
|
|
1674
|
-
function
|
|
1675
|
-
return parsed[id] ??
|
|
1686
|
+
function bindingsOf(id) {
|
|
1687
|
+
return parsed[id] ?? [];
|
|
1676
1688
|
}
|
|
1677
1689
|
/**
|
|
1678
1690
|
* 主键规范化:小写字母大写、空格归一为 Space,其余原样(与事件 e.key 对照)。
|
|
@@ -1714,6 +1726,25 @@ window.__ModuleLoader__.load({
|
|
|
1714
1726
|
return binding.key ? binding : null;
|
|
1715
1727
|
}
|
|
1716
1728
|
/**
|
|
1729
|
+
* 解析多候选键位弦(`|` 分隔):逐段解析,丢弃非法段,去重。
|
|
1730
|
+
* @author ddj 2026年08月26号
|
|
1731
|
+
* @param chord 键位弦(如 `Alt+ArrowLeft|Ctrl+Alt+-`)
|
|
1732
|
+
* @returns 解析键位数组(纯 `|`/空/非法 → 空数组)
|
|
1733
|
+
*/
|
|
1734
|
+
function parseChords(chord) {
|
|
1735
|
+
const out = [];
|
|
1736
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1737
|
+
for (const part of String(chord ?? "").split("|")) {
|
|
1738
|
+
const binding = parseChord(part);
|
|
1739
|
+
if (!binding) continue;
|
|
1740
|
+
const key = formatChord(binding);
|
|
1741
|
+
if (seen.has(key)) continue;
|
|
1742
|
+
seen.add(key);
|
|
1743
|
+
out.push(binding);
|
|
1744
|
+
}
|
|
1745
|
+
return out;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1717
1748
|
* 格式化键位(Ctrl/Cmd/Shift/Alt + 主键;meta 显示 Cmd)。
|
|
1718
1749
|
* @author ddj 2026年08月26号
|
|
1719
1750
|
* @param binding 解析键位
|
|
@@ -1729,18 +1760,21 @@ window.__ModuleLoader__.load({
|
|
|
1729
1760
|
return parts.join("+");
|
|
1730
1761
|
}
|
|
1731
1762
|
/**
|
|
1732
|
-
* 事件是否命中键位(Ctrl 与 Cmd
|
|
1763
|
+
* 事件是否命中键位(Ctrl 与 Cmd 互认;多候选任一命中即 true)。
|
|
1733
1764
|
* @author ddj 2026年08月26号
|
|
1734
1765
|
* @param e 键盘事件(鸭子类型,便于单测)
|
|
1735
|
-
* @param
|
|
1766
|
+
* @param bindings 解析键位或键位数组(null/空 = 未绑定,永不命中)
|
|
1736
1767
|
* @returns 是否命中
|
|
1737
1768
|
*/
|
|
1738
|
-
function matchEvent(e,
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1769
|
+
function matchEvent(e, bindings) {
|
|
1770
|
+
const list = Array.isArray(bindings) ? bindings : bindings ? [bindings] : [];
|
|
1771
|
+
for (const binding of list) {
|
|
1772
|
+
if (Boolean(e.ctrlKey || e.metaKey) !== (binding.ctrl || binding.meta)) continue;
|
|
1773
|
+
if (Boolean(e.shiftKey) !== binding.shift) continue;
|
|
1774
|
+
if (Boolean(e.altKey) !== binding.alt) continue;
|
|
1775
|
+
if (normalizeKey(e.key ?? "") === binding.key) return true;
|
|
1776
|
+
}
|
|
1777
|
+
return false;
|
|
1744
1778
|
}
|
|
1745
1779
|
/**
|
|
1746
1780
|
* 从键盘事件构造键位弦(纯修饰键 → null,供设置页录制)。
|
|
@@ -1825,7 +1859,7 @@ window.__ModuleLoader__.load({
|
|
|
1825
1859
|
};
|
|
1826
1860
|
react.default.useEffect(() => {
|
|
1827
1861
|
const onKey = (e) => {
|
|
1828
|
-
if (matchEvent(e,
|
|
1862
|
+
if (matchEvent(e, bindingsOf("edrv.quickOpen"))) {
|
|
1829
1863
|
e.preventDefault();
|
|
1830
1864
|
e.stopPropagation();
|
|
1831
1865
|
inputRef.current?.focus?.();
|
|
@@ -2503,6 +2537,69 @@ window.__ModuleLoader__.load({
|
|
|
2503
2537
|
window.localStorage.setItem(KEY_PREFIX$2 + String(sessionId), serializeViewStates(states));
|
|
2504
2538
|
} catch (error) {}
|
|
2505
2539
|
}
|
|
2540
|
+
/** 路径一致(容忍相对路径大小写差异,对齐既有 sameFile 语义常用写法)。 */
|
|
2541
|
+
function samePath(a, b) {
|
|
2542
|
+
if (a === b) return true;
|
|
2543
|
+
return String(a).replace(/\\/g, "/").toLowerCase() === String(b).replace(/\\/g, "/").toLowerCase();
|
|
2544
|
+
}
|
|
2545
|
+
/** 位置一致(无焦点时按 null 归一,`undefined`/`null` 视为相等)。 */
|
|
2546
|
+
function samePos(a, b) {
|
|
2547
|
+
if (!samePath(a.path, b.path)) return false;
|
|
2548
|
+
return (a.line ?? null) === (b.line ?? null) && (a.column ?? null) === (b.column ?? null);
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* 创建导航历史实例(容量裁剪到 cap)。
|
|
2552
|
+
* @author ddj 2026年09月04号
|
|
2553
|
+
* @param cap 后退栈容量上限(默认 NAV_HISTORY_CAP)
|
|
2554
|
+
* @returns 导航历史实例
|
|
2555
|
+
*/
|
|
2556
|
+
function createNavHistory(cap = 200) {
|
|
2557
|
+
const past = [];
|
|
2558
|
+
const future = [];
|
|
2559
|
+
return {
|
|
2560
|
+
record(entry) {
|
|
2561
|
+
if (!entry || !entry.path) return;
|
|
2562
|
+
const top = past[past.length - 1];
|
|
2563
|
+
if (top && samePos(top, entry)) {
|
|
2564
|
+
if (top.viewState !== void 0 || entry.viewState !== void 0) top.viewState = entry.viewState;
|
|
2565
|
+
return;
|
|
2566
|
+
}
|
|
2567
|
+
past.push({
|
|
2568
|
+
path: entry.path,
|
|
2569
|
+
line: entry.line,
|
|
2570
|
+
column: entry.column,
|
|
2571
|
+
viewState: entry.viewState
|
|
2572
|
+
});
|
|
2573
|
+
if (past.length > cap) past.splice(0, past.length - cap);
|
|
2574
|
+
future.length = 0;
|
|
2575
|
+
},
|
|
2576
|
+
back() {
|
|
2577
|
+
if (past.length < 2) return null;
|
|
2578
|
+
const current = past.pop();
|
|
2579
|
+
if (!current) return null;
|
|
2580
|
+
future.push(current);
|
|
2581
|
+
return past[past.length - 1];
|
|
2582
|
+
},
|
|
2583
|
+
forward() {
|
|
2584
|
+
const entry = future.pop();
|
|
2585
|
+
if (!entry) return null;
|
|
2586
|
+
past.push(entry);
|
|
2587
|
+
return entry;
|
|
2588
|
+
},
|
|
2589
|
+
canBack() {
|
|
2590
|
+
return past.length >= 2;
|
|
2591
|
+
},
|
|
2592
|
+
canForward() {
|
|
2593
|
+
return future.length > 0;
|
|
2594
|
+
},
|
|
2595
|
+
peekBack() {
|
|
2596
|
+
return past.length >= 2 ? past[past.length - 2] : null;
|
|
2597
|
+
},
|
|
2598
|
+
peekForward() {
|
|
2599
|
+
return future.length ? future[future.length - 1] : null;
|
|
2600
|
+
}
|
|
2601
|
+
};
|
|
2602
|
+
}
|
|
2506
2603
|
//#endregion
|
|
2507
2604
|
//#region src/shared/lsp.ts
|
|
2508
2605
|
/** LSP semantic token 标准类型(host 归一化后,client 与 Monaco 共用)。 */
|
|
@@ -2802,8 +2899,9 @@ window.__ModuleLoader__.load({
|
|
|
2802
2899
|
/**
|
|
2803
2900
|
* dsh-vscode-mode client — Monaco LSP provider 注册 + 跳转/引用命令。
|
|
2804
2901
|
* 数据层:Definition/Reference/DocumentSymbol/Hover provider(同一文件内跳转 Monaco 原生可用)。
|
|
2805
|
-
* 交互层:edrv.goToDefinition(F12)/ edrv.findReferences(Shift+F12 /
|
|
2806
|
-
*
|
|
2902
|
+
* 交互层:edrv.goToDefinition(F12)/ edrv.findReferences(Shift+F12 / 右键)/ Ctrl+点击引用导航,
|
|
2903
|
+
* 跨文件跳转自研(target 经 openFileAt 打开并定位),多条引用走 Monaco 原生 References Peek
|
|
2904
|
+
* (左侧代码预览 + 右侧引用列表;registerEditorOpener 接管 edrv:// 点击跳转)。
|
|
2807
2905
|
* 作者 ddj 2026-08-27
|
|
2808
2906
|
*/
|
|
2809
2907
|
const LSP_LANGS = ["lua", "csharp"];
|
|
@@ -2813,7 +2911,6 @@ window.__ModuleLoader__.load({
|
|
|
2813
2911
|
};
|
|
2814
2912
|
let registered = false;
|
|
2815
2913
|
const disposables = [];
|
|
2816
|
-
let overlayEl = null;
|
|
2817
2914
|
/** 目标文件打开并定位(复用现有 openFileAt 的 edrv:open-editor 事件通道)。 */
|
|
2818
2915
|
function openAt(path, line, column) {
|
|
2819
2916
|
window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
@@ -2858,7 +2955,13 @@ window.__ModuleLoader__.load({
|
|
|
2858
2955
|
};
|
|
2859
2956
|
window.addEventListener("edrv:lsp-redetect", onRedetect);
|
|
2860
2957
|
disposables.push(() => window.removeEventListener("edrv:lsp-redetect", onRedetect));
|
|
2861
|
-
disposables.push(monaco.
|
|
2958
|
+
disposables.push(monaco.editor.registerEditorOpener({ openCodeEditor: (source, resource, selectionOrPosition) => {
|
|
2959
|
+
const path = lspUriToAbs(resource);
|
|
2960
|
+
if (!path) return false;
|
|
2961
|
+
const start = selectionOrPosition?.getStartPosition?.() ?? selectionOrPosition;
|
|
2962
|
+
openAt(path, Math.max(1, start?.lineNumber ?? 1), Math.max(1, start?.column ?? 1));
|
|
2963
|
+
return true;
|
|
2964
|
+
} }), monaco.languages.registerDefinitionProvider(LSP_LANGS, { provideDefinition: (model, position, token) => {
|
|
2862
2965
|
const path = pathOfModel(model);
|
|
2863
2966
|
if (!path) return [];
|
|
2864
2967
|
return findDefinition(path, model.getValue(), position);
|
|
@@ -2935,11 +3038,96 @@ window.__ModuleLoader__.load({
|
|
|
2935
3038
|
async function runGoToDefinition(ed) {
|
|
2936
3039
|
await goToDefinition(ed, ed.getPosition(), true);
|
|
2937
3040
|
}
|
|
2938
|
-
/**
|
|
2939
|
-
|
|
2940
|
-
|
|
3041
|
+
/**
|
|
3042
|
+
* Ctrl+鼠标点击:查询其它内容对该项的引用并导航。
|
|
3043
|
+
* 0 条 → 无特殊效果;1 条 → 直接跳转;多条 → 打开 Monaco 原生 References Peek
|
|
3044
|
+
* (左侧代码预览 + 右侧引用列表,点击经 registerEditorOpener 跳转)。
|
|
3045
|
+
* @author ddj 2026年09月02号
|
|
3046
|
+
* @param ed Monaco 编辑器
|
|
3047
|
+
* @param position 点击位置(Monaco 1-based)
|
|
3048
|
+
*/
|
|
3049
|
+
async function gotoRefsAt(ed, position) {
|
|
3050
|
+
const model = ed.getModel();
|
|
3051
|
+
const path = pathOfModel(model);
|
|
3052
|
+
if (!path || !position) return;
|
|
3053
|
+
const others = filterOtherRefs(await findReferences(path, model.getValue(), position, false), path, position);
|
|
3054
|
+
if (!others.length) return;
|
|
3055
|
+
if (others.length === 1) {
|
|
3056
|
+
jumpToLocation(others[0]);
|
|
3057
|
+
return;
|
|
3058
|
+
}
|
|
3059
|
+
ed.setPosition(position);
|
|
3060
|
+
await triggerReferencePeek(ed);
|
|
3061
|
+
}
|
|
3062
|
+
/**
|
|
3063
|
+
* 触发 Monaco 原生 References Peek(左侧代码 + 右侧引用列表,原生点击跳转)。
|
|
3064
|
+
* @author ddj 2026年09月02号
|
|
3065
|
+
* @param ed Monaco 编辑器
|
|
3066
|
+
* @returns 是否成功触发(动作缺失时返回 false)
|
|
3067
|
+
*/
|
|
3068
|
+
async function triggerReferencePeek(ed) {
|
|
3069
|
+
const action = ed.getAction("editor.action.referenceSearch.trigger");
|
|
3070
|
+
if (!action || typeof action.run !== "function") return false;
|
|
3071
|
+
await action.run();
|
|
3072
|
+
return true;
|
|
3073
|
+
}
|
|
3074
|
+
/**
|
|
3075
|
+
* 过滤「其它内容」引用:剔除当前点击处自身(同文件且点击位置落入其 range),并按路径+起点去重。
|
|
3076
|
+
* @author ddj 2026年09月02号
|
|
3077
|
+
* @param locations 引用结果
|
|
3078
|
+
* @param path 当前文档路径
|
|
3079
|
+
* @param position 点击位置(Monaco 1-based)
|
|
3080
|
+
* @returns 过滤后的其它引用
|
|
3081
|
+
*/
|
|
3082
|
+
function filterOtherRefs(locations, path, position) {
|
|
3083
|
+
const lspPos = monoToLsp(position.lineNumber, position.column);
|
|
3084
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3085
|
+
const out = [];
|
|
3086
|
+
for (const loc of locations) {
|
|
3087
|
+
const rel = targetOpenPath(loc);
|
|
3088
|
+
if (sameFile(rel, path) && posInRange(lspPos, loc.lspRange)) continue;
|
|
3089
|
+
const start = loc.lspRange?.start ?? {};
|
|
3090
|
+
const key = String(rel).toLowerCase() + ":" + (start.line ?? 0) + ":" + (start.character ?? 0);
|
|
3091
|
+
if (seen.has(key)) continue;
|
|
3092
|
+
seen.add(key);
|
|
3093
|
+
out.push(loc);
|
|
3094
|
+
}
|
|
3095
|
+
return out;
|
|
3096
|
+
}
|
|
3097
|
+
/**
|
|
3098
|
+
* 两个路径是否指向同一文件(容忍相对/绝对混合与大小写差异)。
|
|
3099
|
+
* @author ddj 2026年09月02号
|
|
3100
|
+
* @param a 路径 A
|
|
3101
|
+
* @param b 路径 B
|
|
3102
|
+
* @returns 是否同一文件
|
|
3103
|
+
*/
|
|
3104
|
+
function sameFile(a, b) {
|
|
3105
|
+
if (!a || !b) return false;
|
|
3106
|
+
const na = String(a).replace(/\\/g, "/").toLowerCase();
|
|
3107
|
+
const nb = String(b).replace(/\\/g, "/").toLowerCase();
|
|
3108
|
+
if (na === nb) return true;
|
|
3109
|
+
const absA = /^[A-Za-z]:\//.test(na) || na.startsWith("/");
|
|
3110
|
+
if (absA === (/^[A-Za-z]:\//.test(nb) || nb.startsWith("/"))) return false;
|
|
3111
|
+
return absA ? na.endsWith("/" + nb) : nb.endsWith("/" + na);
|
|
2941
3112
|
}
|
|
2942
|
-
/**
|
|
3113
|
+
/**
|
|
3114
|
+
* 0-based LSP 位置是否落在 range 内(end 排除;零宽 range 按点匹配)。
|
|
3115
|
+
* @author ddj 2026年09月02号
|
|
3116
|
+
* @param pos LSP 位置(0-based)
|
|
3117
|
+
* @param range LSP range
|
|
3118
|
+
* @returns 是否在范围内
|
|
3119
|
+
*/
|
|
3120
|
+
function posInRange(pos, range) {
|
|
3121
|
+
const start = range?.start;
|
|
3122
|
+
if (!start) return false;
|
|
3123
|
+
const end = range?.end ?? start;
|
|
3124
|
+
if (start.line === end.line && start.character === end.character) return pos.line === start.line && pos.character === start.character;
|
|
3125
|
+
if (pos.line < start.line || pos.line > end.line) return false;
|
|
3126
|
+
if (pos.line === start.line && pos.character < start.character) return false;
|
|
3127
|
+
if (pos.line === end.line && pos.character >= end.character) return false;
|
|
3128
|
+
return true;
|
|
3129
|
+
}
|
|
3130
|
+
/** 给一个 Monaco 编辑器绑定 Ctrl/Cmd+鼠标引用导航(幂等)。 */
|
|
2943
3131
|
function bindLspEditor(ed) {
|
|
2944
3132
|
if (!ed || ed.__edrvLspClick) return;
|
|
2945
3133
|
ed.__edrvLspClick = true;
|
|
@@ -2953,66 +3141,16 @@ window.__ModuleLoader__.load({
|
|
|
2953
3141
|
if (!native || !position || !isLeftButton || !ctrl && !meta) return;
|
|
2954
3142
|
native.preventDefault?.();
|
|
2955
3143
|
native.stopPropagation?.();
|
|
2956
|
-
|
|
3144
|
+
gotoRefsAt(ed, position);
|
|
2957
3145
|
});
|
|
2958
3146
|
disposables.push(disposable);
|
|
2959
3147
|
}
|
|
2960
|
-
/** Shift+F12 /
|
|
3148
|
+
/** Shift+F12 / 右键「查找所有引用」:走 Monaco 原生 References Peek(两栏引用视图)。 */
|
|
2961
3149
|
async function runFindReferences(ed) {
|
|
2962
|
-
const model = ed.getModel();
|
|
2963
|
-
const path = pathOfModel(model);
|
|
2964
3150
|
const position = ed.getPosition();
|
|
2965
|
-
if (!
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
/** 引用结果浮动面板(轻量 DOM,点击跳转;Esc/失焦关闭)。 */
|
|
2969
|
-
function showReferencesOverlay(ed, path, position, locations) {
|
|
2970
|
-
hideReferencesOverlay();
|
|
2971
|
-
if (!locations.length) {
|
|
2972
|
-
setStatus("未找到引用");
|
|
2973
|
-
return;
|
|
2974
|
-
}
|
|
2975
|
-
const root = ed.getDomNode();
|
|
2976
|
-
if (!root) return;
|
|
2977
|
-
const el = document.createElement("div");
|
|
2978
|
-
el.className = "edrv-refs";
|
|
2979
|
-
const header = document.createElement("div");
|
|
2980
|
-
header.className = "edrv-refs-head";
|
|
2981
|
-
header.textContent = "引用 " + locations.length + " 处";
|
|
2982
|
-
el.appendChild(header);
|
|
2983
|
-
const list = document.createElement("div");
|
|
2984
|
-
list.className = "edrv-refs-list";
|
|
2985
|
-
for (const loc of locations) {
|
|
2986
|
-
const row = document.createElement("div");
|
|
2987
|
-
row.className = "edrv-refs-row";
|
|
2988
|
-
const pos = targetMonoPosition(loc);
|
|
2989
|
-
const rel = targetOpenPath(loc);
|
|
2990
|
-
row.textContent = (String(rel).split("/").pop() || rel) + ":" + pos.line + ":" + pos.column;
|
|
2991
|
-
row.title = rel + ":" + pos.line;
|
|
2992
|
-
row.addEventListener("click", () => {
|
|
2993
|
-
hideReferencesOverlay();
|
|
2994
|
-
jumpToLocation(loc);
|
|
2995
|
-
});
|
|
2996
|
-
list.appendChild(row);
|
|
2997
|
-
}
|
|
2998
|
-
el.appendChild(list);
|
|
2999
|
-
root.appendChild(el);
|
|
3000
|
-
overlayEl = el;
|
|
3001
|
-
const onKey = (e) => {
|
|
3002
|
-
if (e.key === "Escape") hideReferencesOverlay();
|
|
3003
|
-
};
|
|
3004
|
-
window.addEventListener("keydown", onKey);
|
|
3005
|
-
el.addEventListener("click", (e) => {
|
|
3006
|
-
if (e.target === el) hideReferencesOverlay();
|
|
3007
|
-
});
|
|
3008
|
-
el._onKey = onKey;
|
|
3009
|
-
}
|
|
3010
|
-
function hideReferencesOverlay() {
|
|
3011
|
-
if (overlayEl) {
|
|
3012
|
-
window.removeEventListener("keydown", overlayEl._onKey);
|
|
3013
|
-
overlayEl.remove();
|
|
3014
|
-
overlayEl = null;
|
|
3015
|
-
}
|
|
3151
|
+
if (!position) return;
|
|
3152
|
+
ed.setPosition(position);
|
|
3153
|
+
await triggerReferencePeek(ed);
|
|
3016
3154
|
}
|
|
3017
3155
|
/** 编辑器状态栏提示(复用 EditorView 的 status 通道)。 */
|
|
3018
3156
|
function setStatus(text) {
|
|
@@ -3104,6 +3242,13 @@ window.__ModuleLoader__.load({
|
|
|
3104
3242
|
const programmaticRef = react.default.useRef(false);
|
|
3105
3243
|
const bootRef = react.default.useRef(false);
|
|
3106
3244
|
const pendingFocusRef = react.default.useRef(null);
|
|
3245
|
+
const navRef = react.default.useRef(null);
|
|
3246
|
+
if (!navRef.current) navRef.current = createNavHistory();
|
|
3247
|
+
const navPendingRef = react.default.useRef(null);
|
|
3248
|
+
const navCursorTimerRef = react.default.useRef(null);
|
|
3249
|
+
const navBackRef = react.default.useRef(null);
|
|
3250
|
+
const navForwardRef = react.default.useRef(null);
|
|
3251
|
+
const [navTick, setNavTick] = react.default.useState(0);
|
|
3107
3252
|
const hoverRegionsRef = react.default.useRef([]);
|
|
3108
3253
|
const lineRegionMapRef = react.default.useRef(/* @__PURE__ */ new Map());
|
|
3109
3254
|
const hoverKeyRef = react.default.useRef(null);
|
|
@@ -3184,9 +3329,101 @@ window.__ModuleLoader__.load({
|
|
|
3184
3329
|
ed.restoreViewState(saved);
|
|
3185
3330
|
} catch (e) {}
|
|
3186
3331
|
};
|
|
3332
|
+
/**
|
|
3333
|
+
* 采集当前焦点条目:路径从编辑器 model 实时读取(避免空依赖闭包读到过期 active),
|
|
3334
|
+
* 位置/viewState 从编辑器读取;编辑器或模型未就绪 → null。
|
|
3335
|
+
* @author ddj 2026年09月04号
|
|
3336
|
+
* @returns 导航历史条目或 null
|
|
3337
|
+
*/
|
|
3338
|
+
const captureNavEntry = () => {
|
|
3339
|
+
const ed = editorRef.current;
|
|
3340
|
+
const uriPath = (ed?.getModel?.())?.uri?.path;
|
|
3341
|
+
if (!ed || !uriPath) return null;
|
|
3342
|
+
let line = null;
|
|
3343
|
+
let column = null;
|
|
3344
|
+
try {
|
|
3345
|
+
const pos = ed.getPosition?.();
|
|
3346
|
+
if (pos) {
|
|
3347
|
+
line = pos.lineNumber;
|
|
3348
|
+
column = pos.column;
|
|
3349
|
+
}
|
|
3350
|
+
} catch (e) {}
|
|
3351
|
+
let viewState = null;
|
|
3352
|
+
try {
|
|
3353
|
+
viewState = ed.saveViewState();
|
|
3354
|
+
} catch (e) {}
|
|
3355
|
+
return {
|
|
3356
|
+
path: decodeURIComponent(String(uriPath).replace(/^\//, "")),
|
|
3357
|
+
line,
|
|
3358
|
+
column,
|
|
3359
|
+
viewState
|
|
3360
|
+
};
|
|
3361
|
+
};
|
|
3362
|
+
/**
|
|
3363
|
+
* 记录当前位置到导航历史(同位置去重由历史模块处理;可用性变化时刷新按钮)。
|
|
3364
|
+
* @author ddj 2026年09月04号
|
|
3365
|
+
*/
|
|
3366
|
+
const recordNav = () => {
|
|
3367
|
+
const entry = captureNavEntry();
|
|
3368
|
+
if (!entry) return;
|
|
3369
|
+
const wasBack = navRef.current.canBack();
|
|
3370
|
+
const wasForward = navRef.current.canForward();
|
|
3371
|
+
navRef.current.record(entry);
|
|
3372
|
+
if (navRef.current.canBack() !== wasBack || navRef.current.canForward() !== wasForward) setNavTick((v) => v + 1);
|
|
3373
|
+
};
|
|
3374
|
+
/**
|
|
3375
|
+
* 跳到历史条目:保存当前视图状态后打开目标文件,内容就绪后恢复焦点。
|
|
3376
|
+
* @author ddj 2026年09月04号
|
|
3377
|
+
* @param entry 目标历史条目
|
|
3378
|
+
*/
|
|
3379
|
+
const navigateTo = (entry) => {
|
|
3380
|
+
if (!entry || !entry.path) return;
|
|
3381
|
+
flushSave();
|
|
3382
|
+
saveViewState(active);
|
|
3383
|
+
navPendingRef.current = entry;
|
|
3384
|
+
addTab(entry.path, true);
|
|
3385
|
+
setFocusRequest((value) => value + 1);
|
|
3386
|
+
};
|
|
3387
|
+
/**
|
|
3388
|
+
* 立即落盘待记录的光标位置(后退/前进前调用:<500ms 内刚移动的光标也算入历史)。
|
|
3389
|
+
* @author ddj 2026年09月04号
|
|
3390
|
+
*/
|
|
3391
|
+
const flushNavCursor = () => {
|
|
3392
|
+
if (!navCursorTimerRef.current) return;
|
|
3393
|
+
clearTimeout(navCursorTimerRef.current);
|
|
3394
|
+
navCursorTimerRef.current = null;
|
|
3395
|
+
recordNav();
|
|
3396
|
+
};
|
|
3397
|
+
/**
|
|
3398
|
+
* 后退:恢复上一处焦点(跨文件)。
|
|
3399
|
+
* @author ddj 2026年09月04号
|
|
3400
|
+
*/
|
|
3401
|
+
const navBack = () => {
|
|
3402
|
+
flushNavCursor();
|
|
3403
|
+
const entry = navRef.current.back();
|
|
3404
|
+
if (!entry) return;
|
|
3405
|
+
navigateTo(entry);
|
|
3406
|
+
setNavTick((v) => v + 1);
|
|
3407
|
+
};
|
|
3408
|
+
/**
|
|
3409
|
+
* 前进:恢复下一处焦点(跨文件)。
|
|
3410
|
+
* @author ddj 2026年09月04号
|
|
3411
|
+
*/
|
|
3412
|
+
const navForward = () => {
|
|
3413
|
+
flushNavCursor();
|
|
3414
|
+
const entry = navRef.current.forward();
|
|
3415
|
+
if (!entry) return;
|
|
3416
|
+
navigateTo(entry);
|
|
3417
|
+
setNavTick((v) => v + 1);
|
|
3418
|
+
};
|
|
3419
|
+
navBackRef.current = navBack;
|
|
3420
|
+
navForwardRef.current = navForward;
|
|
3187
3421
|
const closeTab = (path) => {
|
|
3188
3422
|
flushSave();
|
|
3189
|
-
if (path === active)
|
|
3423
|
+
if (path === active) {
|
|
3424
|
+
saveViewState(path);
|
|
3425
|
+
recordNav();
|
|
3426
|
+
}
|
|
3190
3427
|
setTabs((prev) => {
|
|
3191
3428
|
const idx = prev.findIndex((t) => t.path === path);
|
|
3192
3429
|
if (idx < 0) return prev;
|
|
@@ -3321,6 +3558,7 @@ window.__ModuleLoader__.load({
|
|
|
3321
3558
|
const p = e?.detail?.path;
|
|
3322
3559
|
if (!p) return;
|
|
3323
3560
|
if (e?.detail?.focusDiff === true) {
|
|
3561
|
+
recordNav();
|
|
3324
3562
|
pendingFocusRef.current = {
|
|
3325
3563
|
path: p,
|
|
3326
3564
|
region: null
|
|
@@ -3333,6 +3571,7 @@ window.__ModuleLoader__.load({
|
|
|
3333
3571
|
openFileAt(p, e?.detail?.line, e?.detail?.column);
|
|
3334
3572
|
return;
|
|
3335
3573
|
}
|
|
3574
|
+
recordNav();
|
|
3336
3575
|
addTab(p, true);
|
|
3337
3576
|
};
|
|
3338
3577
|
const onShowLauncher = (event) => {
|
|
@@ -3423,6 +3662,15 @@ window.__ModuleLoader__.load({
|
|
|
3423
3662
|
}
|
|
3424
3663
|
} catch (e) {}
|
|
3425
3664
|
}, [sessionId]);
|
|
3665
|
+
react.default.useEffect(() => {
|
|
3666
|
+
navRef.current = createNavHistory();
|
|
3667
|
+
navPendingRef.current = null;
|
|
3668
|
+
if (navCursorTimerRef.current) {
|
|
3669
|
+
clearTimeout(navCursorTimerRef.current);
|
|
3670
|
+
navCursorTimerRef.current = null;
|
|
3671
|
+
}
|
|
3672
|
+
setNavTick((v) => v + 1);
|
|
3673
|
+
}, [sessionId]);
|
|
3426
3674
|
react.default.useEffect(() => {
|
|
3427
3675
|
if (!sessionId) return;
|
|
3428
3676
|
try {
|
|
@@ -3467,7 +3715,7 @@ window.__ModuleLoader__.load({
|
|
|
3467
3715
|
]);
|
|
3468
3716
|
react.default.useEffect(() => {
|
|
3469
3717
|
const onKey = (e) => {
|
|
3470
|
-
if (!matchEvent(e,
|
|
3718
|
+
if (!matchEvent(e, bindingsOf("edrv.toggleSidebar"))) return;
|
|
3471
3719
|
e.preventDefault();
|
|
3472
3720
|
e.stopPropagation();
|
|
3473
3721
|
setSidebarOn((v) => !v);
|
|
@@ -3477,7 +3725,7 @@ window.__ModuleLoader__.load({
|
|
|
3477
3725
|
}, []);
|
|
3478
3726
|
react.default.useEffect(() => {
|
|
3479
3727
|
const onKey = (e) => {
|
|
3480
|
-
if (!matchEvent(e,
|
|
3728
|
+
if (!matchEvent(e, bindingsOf("edrv.save"))) return;
|
|
3481
3729
|
if (!editorRef.current?.getModel?.()) return;
|
|
3482
3730
|
e.preventDefault();
|
|
3483
3731
|
e.stopPropagation();
|
|
@@ -3489,7 +3737,7 @@ window.__ModuleLoader__.load({
|
|
|
3489
3737
|
}, []);
|
|
3490
3738
|
react.default.useEffect(() => {
|
|
3491
3739
|
const onKey = (e) => {
|
|
3492
|
-
if (!matchEvent(e,
|
|
3740
|
+
if (!matchEvent(e, bindingsOf("edrv.searchInFiles"))) return;
|
|
3493
3741
|
e.preventDefault();
|
|
3494
3742
|
e.stopPropagation();
|
|
3495
3743
|
setSidebarOn(true);
|
|
@@ -3499,6 +3747,46 @@ window.__ModuleLoader__.load({
|
|
|
3499
3747
|
window.addEventListener("keydown", onKey, true);
|
|
3500
3748
|
return () => window.removeEventListener("keydown", onKey, true);
|
|
3501
3749
|
}, []);
|
|
3750
|
+
react.default.useEffect(() => {
|
|
3751
|
+
const onKey = (e) => {
|
|
3752
|
+
if (!matchEvent(e, bindingsOf("edrv.navigateBack"))) return;
|
|
3753
|
+
e.preventDefault();
|
|
3754
|
+
e.stopPropagation();
|
|
3755
|
+
if (navBackRef.current) navBackRef.current();
|
|
3756
|
+
};
|
|
3757
|
+
window.addEventListener("keydown", onKey, true);
|
|
3758
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
3759
|
+
}, []);
|
|
3760
|
+
react.default.useEffect(() => {
|
|
3761
|
+
const onKey = (e) => {
|
|
3762
|
+
if (!matchEvent(e, bindingsOf("edrv.navigateForward"))) return;
|
|
3763
|
+
e.preventDefault();
|
|
3764
|
+
e.stopPropagation();
|
|
3765
|
+
if (navForwardRef.current) navForwardRef.current();
|
|
3766
|
+
};
|
|
3767
|
+
window.addEventListener("keydown", onKey, true);
|
|
3768
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
3769
|
+
}, []);
|
|
3770
|
+
react.default.useEffect(() => {
|
|
3771
|
+
const onPointer = (e) => {
|
|
3772
|
+
if (e?.button !== 3 && e?.button !== 4) return;
|
|
3773
|
+
e.preventDefault();
|
|
3774
|
+
e.stopPropagation();
|
|
3775
|
+
const ref = e.button === 3 ? navBackRef : navForwardRef;
|
|
3776
|
+
if (ref.current) ref.current();
|
|
3777
|
+
};
|
|
3778
|
+
const onMouse = (e) => {
|
|
3779
|
+
if (e?.button !== 3 && e?.button !== 4) return;
|
|
3780
|
+
e.preventDefault();
|
|
3781
|
+
e.stopPropagation();
|
|
3782
|
+
};
|
|
3783
|
+
window.addEventListener("pointerdown", onPointer, true);
|
|
3784
|
+
window.addEventListener("mousedown", onMouse, true);
|
|
3785
|
+
return () => {
|
|
3786
|
+
window.removeEventListener("pointerdown", onPointer, true);
|
|
3787
|
+
window.removeEventListener("mousedown", onMouse, true);
|
|
3788
|
+
};
|
|
3789
|
+
}, []);
|
|
3502
3790
|
const pendingByPath = react.default.useMemo(() => {
|
|
3503
3791
|
const out = {};
|
|
3504
3792
|
for (const f of sum.files) if (f.pending > 0) out[f.path] = f.pending;
|
|
@@ -3647,7 +3935,6 @@ window.__ModuleLoader__.load({
|
|
|
3647
3935
|
flushSave();
|
|
3648
3936
|
saveViewState(active);
|
|
3649
3937
|
diffRendererRef.current?.dispose?.();
|
|
3650
|
-
hideReferencesOverlay();
|
|
3651
3938
|
if (editorRef.current) {
|
|
3652
3939
|
editorRef.current.dispose();
|
|
3653
3940
|
editorRef.current = null;
|
|
@@ -3699,6 +3986,11 @@ window.__ModuleLoader__.load({
|
|
|
3699
3986
|
});
|
|
3700
3987
|
ed.onDidChangeCursorPosition((e) => {
|
|
3701
3988
|
setCursor("Ln " + e.position.lineNumber + ", Col " + e.position.column);
|
|
3989
|
+
if (navCursorTimerRef.current) clearTimeout(navCursorTimerRef.current);
|
|
3990
|
+
navCursorTimerRef.current = setTimeout(() => {
|
|
3991
|
+
navCursorTimerRef.current = null;
|
|
3992
|
+
recordNav();
|
|
3993
|
+
}, 500);
|
|
3702
3994
|
});
|
|
3703
3995
|
const menuHandlers = () => menuHandlersRef.current;
|
|
3704
3996
|
const pathOf = (edx) => {
|
|
@@ -3818,10 +4110,26 @@ window.__ModuleLoader__.load({
|
|
|
3818
4110
|
editorRef.current = ed;
|
|
3819
4111
|
}, []);
|
|
3820
4112
|
react.default.useEffect(() => {
|
|
3821
|
-
const pf = pendingFocusRef.current;
|
|
3822
|
-
if (!pf || pf.path !== active || content === null) return;
|
|
3823
4113
|
const ed = editorRef.current;
|
|
3824
|
-
if (!ed) return;
|
|
4114
|
+
if (!ed || content === null) return;
|
|
4115
|
+
const nav = navPendingRef.current;
|
|
4116
|
+
if (nav && nav.path === active) {
|
|
4117
|
+
navPendingRef.current = null;
|
|
4118
|
+
if (nav.viewState) try {
|
|
4119
|
+
ed.restoreViewState(nav.viewState);
|
|
4120
|
+
} catch (e) {}
|
|
4121
|
+
if (nav.line != null) {
|
|
4122
|
+
ed.revealLineInCenter(Math.max(1, nav.line));
|
|
4123
|
+
ed.setPosition({
|
|
4124
|
+
lineNumber: Math.max(1, nav.line),
|
|
4125
|
+
column: Math.max(1, nav.column ?? 1)
|
|
4126
|
+
});
|
|
4127
|
+
}
|
|
4128
|
+
ed.focus();
|
|
4129
|
+
return;
|
|
4130
|
+
}
|
|
4131
|
+
const pf = pendingFocusRef.current;
|
|
4132
|
+
if (!pf || pf.path !== active) return;
|
|
3825
4133
|
if (pf.line != null) {
|
|
3826
4134
|
pendingFocusRef.current = null;
|
|
3827
4135
|
ed.revealLineInCenter(Math.max(1, pf.line));
|
|
@@ -4122,6 +4430,7 @@ window.__ModuleLoader__.load({
|
|
|
4122
4430
|
};
|
|
4123
4431
|
const openFile = (path, focusDiff) => {
|
|
4124
4432
|
if (!path) return;
|
|
4433
|
+
recordNav();
|
|
4125
4434
|
addTab(path, true);
|
|
4126
4435
|
if (focusDiff) pendingFocusRef.current = {
|
|
4127
4436
|
path,
|
|
@@ -4137,6 +4446,7 @@ window.__ModuleLoader__.load({
|
|
|
4137
4446
|
*/
|
|
4138
4447
|
const openFileAt = (path, line, column) => {
|
|
4139
4448
|
if (!path) return;
|
|
4449
|
+
recordNav();
|
|
4140
4450
|
addTab(path, true);
|
|
4141
4451
|
pendingFocusRef.current = {
|
|
4142
4452
|
path,
|
|
@@ -4183,6 +4493,7 @@ window.__ModuleLoader__.load({
|
|
|
4183
4493
|
if (t.path !== active) {
|
|
4184
4494
|
flushSave();
|
|
4185
4495
|
saveViewState(active);
|
|
4496
|
+
recordNav();
|
|
4186
4497
|
setActive(t.path);
|
|
4187
4498
|
}
|
|
4188
4499
|
},
|
|
@@ -4244,6 +4555,9 @@ window.__ModuleLoader__.load({
|
|
|
4244
4555
|
className: "edrv-statusbar",
|
|
4245
4556
|
title: lspServer?.progressMessage || lspLabel
|
|
4246
4557
|
}, react.default.createElement("span", { className: "edrv-lsp-status-dot " + (lspServer?.phase === "ready" ? "ready" : lspServer?.phase === "indexing" || lspServer?.phase === "starting" ? "busy" : "idle") }), react.default.createElement("span", { className: "edrv-sp-lsp" }, lspLabel), lspServer?.progressMessage ? react.default.createElement("span", { className: "edrv-sp-progress-message" }, lspServer.progressMessage) : null, lspProgress !== null ? react.default.createElement("span", { className: "edrv-sp-progress" }, lspProgress + "%") : null) : null;
|
|
4558
|
+
const navBackTarget = navRef.current.peekBack();
|
|
4559
|
+
const navForwardTarget = navRef.current.peekForward();
|
|
4560
|
+
const navNameOf = (entry) => entry && entry.path ? String(entry.path).split(/[\\/]/).pop() : "";
|
|
4247
4561
|
const tabRow = react.default.createElement("div", { style: {
|
|
4248
4562
|
display: "flex",
|
|
4249
4563
|
alignItems: "center",
|
|
@@ -4254,6 +4568,18 @@ window.__ModuleLoader__.load({
|
|
|
4254
4568
|
title: "打开差异总览/归档",
|
|
4255
4569
|
onClick: () => setLauncherOpen((o) => !o)
|
|
4256
4570
|
}, "⚠ 差异 " + sum.totalFiles + " 文件") : null, react.default.createElement("button", {
|
|
4571
|
+
className: "edrv-chip-btn",
|
|
4572
|
+
title: "后退(" + (chordOf("edrv.navigateBack") ?? "未绑定") + ")" + (navBackTarget ? " · " + navNameOf(navBackTarget) : ""),
|
|
4573
|
+
disabled: !navRef.current.canBack(),
|
|
4574
|
+
"aria-label": "后退",
|
|
4575
|
+
onClick: navBack
|
|
4576
|
+
}, "←"), react.default.createElement("button", {
|
|
4577
|
+
className: "edrv-chip-btn",
|
|
4578
|
+
title: "前进(" + (chordOf("edrv.navigateForward") ?? "未绑定") + ")" + (navForwardTarget ? " · " + navNameOf(navForwardTarget) : ""),
|
|
4579
|
+
disabled: !navRef.current.canForward(),
|
|
4580
|
+
"aria-label": "前进",
|
|
4581
|
+
onClick: navForward
|
|
4582
|
+
}, "→"), react.default.createElement("button", {
|
|
4257
4583
|
className: "edrv-chip-btn" + (sidebarOn ? " edrv-chip-on" : ""),
|
|
4258
4584
|
title: "切换侧边栏 (" + (chordOf("edrv.toggleSidebar") ?? "Ctrl+B") + ")",
|
|
4259
4585
|
onClick: () => setSidebarOn((v) => !v)
|
|
@@ -5269,7 +5595,7 @@ window.__ModuleLoader__.load({
|
|
|
5269
5595
|
const rows = COMMANDS.map((command) => {
|
|
5270
5596
|
const chord = draft[command.id] ?? null;
|
|
5271
5597
|
const conflict = chord !== null && conflicts.has(command.id);
|
|
5272
|
-
const invalid = chord !== null &&
|
|
5598
|
+
const invalid = chord !== null && parseChords(chord).length === 0;
|
|
5273
5599
|
const recordingRow = recording === command.id;
|
|
5274
5600
|
let display;
|
|
5275
5601
|
if (recordingRow) display = react.default.createElement("span", { className: "vsm-kb-rec" }, "按下组合键…(Esc 取消 / Backspace 清除)");
|
|
@@ -5288,7 +5614,7 @@ window.__ModuleLoader__.load({
|
|
|
5288
5614
|
onClick: () => resetRow(command.id)
|
|
5289
5615
|
}, "恢复"))));
|
|
5290
5616
|
});
|
|
5291
|
-
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "快捷键"), react.default.createElement("p", null, "配置编辑器视图的快捷键(保存 / 快速打开 / 侧边栏 /
|
|
5617
|
+
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "快捷键"), react.default.createElement("p", null, "配置编辑器视图的快捷键(保存 / 快速打开 / 侧边栏 / 搜索 / 后退 / 前进)。修改即时写入配置,重新聚焦编辑器后生效。"), unavailable && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, "设置服务暂不可用,当前使用默认键位。"), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), message && react.default.createElement("div", { className: "vsm-kb-message" }, message), 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("div", { className: "vsm-kb-list" }, rows)), react.default.createElement("div", { className: "vsm-panel-body vsm-kb-actionsbar" }, react.default.createElement("span", { className: "vsm-kb-dirty" }, dirty ? "有未保存的修改" : ""), react.default.createElement("button", {
|
|
5292
5618
|
className: "vsm-primary vsm-small",
|
|
5293
5619
|
disabled: unavailable || notReady || busy || snapshot?.writable === false || !dirty,
|
|
5294
5620
|
onClick: save
|