dsh-vscode-mode 0.1.20 → 0.1.21
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/lib/client.js +741 -3
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +8 -1
- package/src/client/outline/OutlinePanel.tsx +213 -0
- package/src/client/outline/index.ts +24 -0
- package/src/client/outline/parse.ts +271 -0
- package/src/client/outline/sources.ts +134 -0
- package/src/client/outline/types.ts +51 -0
- package/src/client/sidebar/types.ts +5 -0
- package/src/client/styles/editor.css +9 -0
- package/src/client/ui/EditorView.ts +2 -0
package/lib/client.js
CHANGED
|
@@ -29,7 +29,7 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
let react = require("react");
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
//#region \0dsh-css:/home/runner/work/DSH_VsCodeMode/DSH_VsCodeMode/src/client/styles/editor.css.mjs
|
|
32
|
-
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-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-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; }\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-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[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";
|
|
32
|
+
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-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-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; }\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-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";
|
|
33
33
|
const tagId$1 = "dsh-vscode-mode/editor.css";
|
|
34
34
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
35
35
|
const tag = document.createElement("style");
|
|
@@ -2466,7 +2466,9 @@ window.__ModuleLoader__.load({
|
|
|
2466
2466
|
totalFiles: sum.totalFiles,
|
|
2467
2467
|
files: sum.files
|
|
2468
2468
|
},
|
|
2469
|
-
refreshRecords: () => refreshRecords()
|
|
2469
|
+
refreshRecords: () => refreshRecords(),
|
|
2470
|
+
editor: () => editorRef.current,
|
|
2471
|
+
outlineSources: props.outlineSources
|
|
2470
2472
|
};
|
|
2471
2473
|
const editorArea = react.default.createElement("div", { className: "edrv-editor-area" }, body, hoverEl, overlay);
|
|
2472
2474
|
const mainCol = react.default.createElement("div", {
|
|
@@ -3867,6 +3869,737 @@ window.__ModuleLoader__.load({
|
|
|
3867
3869
|
};
|
|
3868
3870
|
}
|
|
3869
3871
|
//#endregion
|
|
3872
|
+
//#region src/client/outline/parse.ts
|
|
3873
|
+
/** monaco SymbolKind 数值常量(与 LSP SymbolKind 一致,面板渲染按此分组)。 */
|
|
3874
|
+
const SK = {
|
|
3875
|
+
File: 0,
|
|
3876
|
+
Module: 1,
|
|
3877
|
+
Namespace: 2,
|
|
3878
|
+
Package: 3,
|
|
3879
|
+
Class: 4,
|
|
3880
|
+
Method: 5,
|
|
3881
|
+
Property: 6,
|
|
3882
|
+
Field: 7,
|
|
3883
|
+
Constructor: 8,
|
|
3884
|
+
Enum: 9,
|
|
3885
|
+
Interface: 10,
|
|
3886
|
+
Function: 11,
|
|
3887
|
+
Variable: 12,
|
|
3888
|
+
Constant: 13,
|
|
3889
|
+
String: 14,
|
|
3890
|
+
Number: 15,
|
|
3891
|
+
Boolean: 16,
|
|
3892
|
+
Array: 17,
|
|
3893
|
+
Object: 18,
|
|
3894
|
+
Key: 19,
|
|
3895
|
+
Null: 20,
|
|
3896
|
+
EnumMember: 21,
|
|
3897
|
+
Struct: 22,
|
|
3898
|
+
Event: 23,
|
|
3899
|
+
Operator: 24,
|
|
3900
|
+
TypeParameter: 25
|
|
3901
|
+
};
|
|
3902
|
+
/** 花括号语言的泛型函数名排除集(避免误把控制流/关键字当符号)。 */
|
|
3903
|
+
const BRACE_KW = /* @__PURE__ */ new Set([
|
|
3904
|
+
"if",
|
|
3905
|
+
"for",
|
|
3906
|
+
"while",
|
|
3907
|
+
"switch",
|
|
3908
|
+
"catch",
|
|
3909
|
+
"foreach",
|
|
3910
|
+
"using",
|
|
3911
|
+
"with",
|
|
3912
|
+
"when",
|
|
3913
|
+
"match",
|
|
3914
|
+
"return",
|
|
3915
|
+
"new",
|
|
3916
|
+
"in",
|
|
3917
|
+
"of",
|
|
3918
|
+
"do",
|
|
3919
|
+
"else",
|
|
3920
|
+
"elif",
|
|
3921
|
+
"then",
|
|
3922
|
+
"yield",
|
|
3923
|
+
"await",
|
|
3924
|
+
"typeof",
|
|
3925
|
+
"instanceof",
|
|
3926
|
+
"case",
|
|
3927
|
+
"default",
|
|
3928
|
+
"try",
|
|
3929
|
+
"finally",
|
|
3930
|
+
"throw"
|
|
3931
|
+
]);
|
|
3932
|
+
/** 花括号语言的类型关键字 → SymbolKind。 */
|
|
3933
|
+
const BRACE_TYPE_KIND = {
|
|
3934
|
+
class: SK.Class,
|
|
3935
|
+
struct: SK.Struct,
|
|
3936
|
+
interface: SK.Interface,
|
|
3937
|
+
enum: SK.Enum,
|
|
3938
|
+
namespace: SK.Namespace,
|
|
3939
|
+
module: SK.Module,
|
|
3940
|
+
trait: SK.Interface,
|
|
3941
|
+
record: SK.Class
|
|
3942
|
+
};
|
|
3943
|
+
/** 按文档序(先序)补齐每个符号的 endLine:叶子取“下一个符号起行 - 1”,容器取末子 endLine。 */
|
|
3944
|
+
function computeEnds(symbols, lastLine) {
|
|
3945
|
+
const order = [];
|
|
3946
|
+
const collect = (list) => {
|
|
3947
|
+
for (const s of list) {
|
|
3948
|
+
order.push(s);
|
|
3949
|
+
if (s.children && s.children.length) collect(s.children);
|
|
3950
|
+
}
|
|
3951
|
+
};
|
|
3952
|
+
collect(symbols);
|
|
3953
|
+
for (let i = order.length - 1; i >= 0; i--) {
|
|
3954
|
+
const s = order[i];
|
|
3955
|
+
const kids = s.children ?? [];
|
|
3956
|
+
if (kids.length) s.endLine = Math.max(s.startLine, kids[kids.length - 1].endLine);
|
|
3957
|
+
else {
|
|
3958
|
+
const next = order[i + 1];
|
|
3959
|
+
const end = next ? Math.max(s.startLine, next.startLine - 1) : lastLine;
|
|
3960
|
+
s.endLine = Math.max(s.startLine, Math.min(end, lastLine));
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
/** 构造单行符号(起始行=跳转行=所在行;detail 为截断后的声明文本)。 */
|
|
3965
|
+
function mk(lineIndex, name, kind, raw) {
|
|
3966
|
+
const detail = raw.trim().replace(/\s+/g, " ").slice(0, 80);
|
|
3967
|
+
const line = lineIndex + 1;
|
|
3968
|
+
const out = {
|
|
3969
|
+
name,
|
|
3970
|
+
kind,
|
|
3971
|
+
startLine: line,
|
|
3972
|
+
endLine: line,
|
|
3973
|
+
selectLine: line
|
|
3974
|
+
};
|
|
3975
|
+
if (detail && detail !== name) out.detail = detail;
|
|
3976
|
+
return out;
|
|
3977
|
+
}
|
|
3978
|
+
/** Markdown/mdx:`#` 级标题,层级嵌套。 */
|
|
3979
|
+
function parseMarkdown(text) {
|
|
3980
|
+
const roots = [];
|
|
3981
|
+
const stack = [];
|
|
3982
|
+
const lines = text.split("\n");
|
|
3983
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3984
|
+
const m = /^(\#{1,6})\s+(.+?)\s*#*\s*$/.exec(lines[i]);
|
|
3985
|
+
if (!m) continue;
|
|
3986
|
+
const item = {
|
|
3987
|
+
name: m[2].trim(),
|
|
3988
|
+
kind: SK.Namespace,
|
|
3989
|
+
startLine: i + 1,
|
|
3990
|
+
endLine: i + 1,
|
|
3991
|
+
selectLine: i + 1,
|
|
3992
|
+
children: []
|
|
3993
|
+
};
|
|
3994
|
+
while (stack.length && stack[stack.length - 1].level >= m[1].length) stack.pop();
|
|
3995
|
+
const parent = stack.length ? stack[stack.length - 1].item : null;
|
|
3996
|
+
(parent ? parent.children : roots).push(item);
|
|
3997
|
+
stack.push({
|
|
3998
|
+
level: m[1].length,
|
|
3999
|
+
item
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
computeEnds(roots, lines.length);
|
|
4003
|
+
return roots;
|
|
4004
|
+
}
|
|
4005
|
+
/** Python:def/class 按缩进栈嵌套。 */
|
|
4006
|
+
function parsePython(text) {
|
|
4007
|
+
const roots = [];
|
|
4008
|
+
const stack = [];
|
|
4009
|
+
const lines = text.split("\n");
|
|
4010
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4011
|
+
const m = /^([ \t]*)(?:class|def)\s+([A-Za-z_]\w*)\s*[(:]/.exec(lines[i]);
|
|
4012
|
+
if (!m) continue;
|
|
4013
|
+
const indent = m[1].replace(/\t/g, " ").length;
|
|
4014
|
+
const isClass = /class\s/.test(lines[i]);
|
|
4015
|
+
const item = {
|
|
4016
|
+
name: m[2],
|
|
4017
|
+
kind: isClass ? SK.Class : SK.Function,
|
|
4018
|
+
startLine: i + 1,
|
|
4019
|
+
endLine: i + 1,
|
|
4020
|
+
selectLine: i + 1,
|
|
4021
|
+
children: []
|
|
4022
|
+
};
|
|
4023
|
+
while (stack.length && stack[stack.length - 1].indent >= indent) stack.pop();
|
|
4024
|
+
const parent = stack.length ? stack[stack.length - 1].item : null;
|
|
4025
|
+
(parent ? parent.children : roots).push(item);
|
|
4026
|
+
stack.push({
|
|
4027
|
+
indent,
|
|
4028
|
+
item
|
|
4029
|
+
});
|
|
4030
|
+
}
|
|
4031
|
+
computeEnds(roots, lines.length);
|
|
4032
|
+
return roots;
|
|
4033
|
+
}
|
|
4034
|
+
/** Shell:`name() {` 函数。 */
|
|
4035
|
+
function parseShell(text) {
|
|
4036
|
+
const out = [];
|
|
4037
|
+
const lines = text.split("\n");
|
|
4038
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4039
|
+
const m = /^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*\(\)[ \t]*\{/.exec(lines[i]);
|
|
4040
|
+
if (m) out.push(mk(i, m[1], SK.Function, lines[i]));
|
|
4041
|
+
}
|
|
4042
|
+
computeEnds(out, lines.length);
|
|
4043
|
+
return out;
|
|
4044
|
+
}
|
|
4045
|
+
/** PowerShell:`function Name {` / `filter Name {`。 */
|
|
4046
|
+
function parsePwsh(text) {
|
|
4047
|
+
const out = [];
|
|
4048
|
+
const lines = text.split("\n");
|
|
4049
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4050
|
+
const m = /^[ \t]*(?:function|filter)[ \t]+([\w.-]+)/.exec(lines[i]);
|
|
4051
|
+
if (m) out.push(mk(i, m[1], SK.Function, lines[i]));
|
|
4052
|
+
}
|
|
4053
|
+
computeEnds(out, lines.length);
|
|
4054
|
+
return out;
|
|
4055
|
+
}
|
|
4056
|
+
/** Lua:`function Foo:bar` / `M.bar = class|function`。 */
|
|
4057
|
+
function parseLua(text) {
|
|
4058
|
+
const out = [];
|
|
4059
|
+
const lines = text.split("\n");
|
|
4060
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4061
|
+
const line = lines[i];
|
|
4062
|
+
if (/^\s*--/.test(line)) continue;
|
|
4063
|
+
const fm = /^[ \t]*(?:local[ \t]+)?function[ \t]+([A-Za-z_][\w.:]*)/.exec(line);
|
|
4064
|
+
if (fm) {
|
|
4065
|
+
out.push(mk(i, fm[1], SK.Function, line));
|
|
4066
|
+
continue;
|
|
4067
|
+
}
|
|
4068
|
+
const cm = /^[ \t]*([A-Za-z_][\w.]*)[ \t]*=[ \t]*(?:class|function)\b/.exec(line);
|
|
4069
|
+
if (cm) out.push(mk(i, cm[1], /class\b/.test(line) ? SK.Class : SK.Function, line));
|
|
4070
|
+
}
|
|
4071
|
+
computeEnds(out, lines.length);
|
|
4072
|
+
return out;
|
|
4073
|
+
}
|
|
4074
|
+
/** Go:func(含 receiver)/ type。 */
|
|
4075
|
+
function parseGo(text) {
|
|
4076
|
+
const out = [];
|
|
4077
|
+
const lines = text.split("\n");
|
|
4078
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4079
|
+
const fm = /^[ \t]*func[ \t]+(?:\([^)]*\)[ \t]*)?([A-Za-z_]\w*)/.exec(lines[i]);
|
|
4080
|
+
if (fm) {
|
|
4081
|
+
out.push(mk(i, fm[1], SK.Function, lines[i]));
|
|
4082
|
+
continue;
|
|
4083
|
+
}
|
|
4084
|
+
const tm = /^[ \t]*type[ \t]+([A-Za-z_]\w*)/.exec(lines[i]);
|
|
4085
|
+
if (tm) out.push(mk(i, tm[1], SK.Struct, lines[i]));
|
|
4086
|
+
}
|
|
4087
|
+
computeEnds(out, lines.length);
|
|
4088
|
+
return out;
|
|
4089
|
+
}
|
|
4090
|
+
/** Rust:fn/struct/enum/trait/impl/mod/type。 */
|
|
4091
|
+
function parseRust(text) {
|
|
4092
|
+
const out = [];
|
|
4093
|
+
const lines = text.split("\n");
|
|
4094
|
+
const kindOf = {
|
|
4095
|
+
fn: SK.Function,
|
|
4096
|
+
struct: SK.Struct,
|
|
4097
|
+
enum: SK.Enum,
|
|
4098
|
+
trait: SK.Interface,
|
|
4099
|
+
impl: SK.Module,
|
|
4100
|
+
mod: SK.Module,
|
|
4101
|
+
type: SK.TypeParameter
|
|
4102
|
+
};
|
|
4103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4104
|
+
const m = /^[ \t]*(?:pub(?:\([^)]*\))?[ \t]+)?(fn|struct|enum|trait|impl|mod|type)[ \t]+([A-Za-z_]\w*)/.exec(lines[i]);
|
|
4105
|
+
if (m && kindOf[m[1]]) out.push(mk(i, m[2], kindOf[m[1]], lines[i]));
|
|
4106
|
+
}
|
|
4107
|
+
computeEnds(out, lines.length);
|
|
4108
|
+
return out;
|
|
4109
|
+
}
|
|
4110
|
+
/** YAML:仅顶层键。 */
|
|
4111
|
+
function parseYaml(text) {
|
|
4112
|
+
const out = [];
|
|
4113
|
+
const lines = text.split("\n");
|
|
4114
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4115
|
+
const line = lines[i];
|
|
4116
|
+
if (!line.trim() || /^\s/.test(line) || /^\s*[#-]/.test(line)) continue;
|
|
4117
|
+
const m = /^([A-Za-z0-9_.\-]+)\s*:/.exec(line);
|
|
4118
|
+
if (m) out.push(mk(i, m[1], SK.Key, line));
|
|
4119
|
+
}
|
|
4120
|
+
computeEnds(out, lines.length);
|
|
4121
|
+
return out;
|
|
4122
|
+
}
|
|
4123
|
+
/** INI/TOML:`[section]` + `key=value`。 */
|
|
4124
|
+
function parseIni(text) {
|
|
4125
|
+
const out = [];
|
|
4126
|
+
const lines = text.split("\n");
|
|
4127
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4128
|
+
const line = lines[i];
|
|
4129
|
+
if (!line.trim() || /^\s*[;#]/.test(line)) continue;
|
|
4130
|
+
const sm = /^\[([^\]]+)\]/.exec(line);
|
|
4131
|
+
if (sm) {
|
|
4132
|
+
out.push(mk(i, sm[1], SK.Namespace, line));
|
|
4133
|
+
continue;
|
|
4134
|
+
}
|
|
4135
|
+
const km = /^([A-Za-z0-9_.\-]+)\s*[=:]/.exec(line.trim());
|
|
4136
|
+
if (km) out.push(mk(i, km[1], SK.Key, line));
|
|
4137
|
+
}
|
|
4138
|
+
computeEnds(out, lines.length);
|
|
4139
|
+
return out;
|
|
4140
|
+
}
|
|
4141
|
+
/** 花括号语言(C 族/JVM/.NET):类型声明 + 泛型函数扫描(扁平,best-effort)。 */
|
|
4142
|
+
function parseBrace(text) {
|
|
4143
|
+
const out = [];
|
|
4144
|
+
const lines = text.split("\n");
|
|
4145
|
+
const typeRe = /^[ \t]*(?:(?:public|private|protected|internal|static|final|abstract|sealed|readonly|export|declare|async|open|extern|virtual|override|const|global|pub|local)\s+)*(class|struct|interface|enum|namespace|module|trait|record)\s+([A-Za-z_]\w*)/;
|
|
4146
|
+
const funcRe = /^[ \t]*(?:[\w<>,*&\[\].:]+\s+)*([A-Za-z_]\w*)\s*(?:<[^>]*>)?\s*\(/;
|
|
4147
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4148
|
+
const line = lines[i];
|
|
4149
|
+
const t = line.trim();
|
|
4150
|
+
if (!t || /^\s*\*/.test(line)) continue;
|
|
4151
|
+
const tm = typeRe.exec(line);
|
|
4152
|
+
if (tm) {
|
|
4153
|
+
out.push(mk(i, tm[2], BRACE_TYPE_KIND[tm[1]] ?? SK.Class, line));
|
|
4154
|
+
continue;
|
|
4155
|
+
}
|
|
4156
|
+
const fm = funcRe.exec(line);
|
|
4157
|
+
if (!fm) continue;
|
|
4158
|
+
if (BRACE_KW.has(fm[1]) || /;\s*$/.test(t)) continue;
|
|
4159
|
+
out.push(mk(i, fm[1], SK.Function, line));
|
|
4160
|
+
}
|
|
4161
|
+
computeEnds(out, lines.length);
|
|
4162
|
+
return out;
|
|
4163
|
+
}
|
|
4164
|
+
/**
|
|
4165
|
+
* 按 Monaco languageId 解析大纲符号(纯函数)。
|
|
4166
|
+
* @author ddj 2026年08月27号
|
|
4167
|
+
* @param languageId Monaco 语言 id
|
|
4168
|
+
* @param text 文件全文
|
|
4169
|
+
* @returns 归一化大纲符号树
|
|
4170
|
+
*/
|
|
4171
|
+
function parseOutline(languageId, text) {
|
|
4172
|
+
switch (languageId) {
|
|
4173
|
+
case "markdown":
|
|
4174
|
+
case "mdx": return parseMarkdown(text);
|
|
4175
|
+
case "python": return parsePython(text);
|
|
4176
|
+
case "shell": return parseShell(text);
|
|
4177
|
+
case "powershell": return parsePwsh(text);
|
|
4178
|
+
case "lua": return parseLua(text);
|
|
4179
|
+
case "go": return parseGo(text);
|
|
4180
|
+
case "rust": return parseRust(text);
|
|
4181
|
+
case "yaml": return parseYaml(text);
|
|
4182
|
+
case "ini": return parseIni(text);
|
|
4183
|
+
case "c":
|
|
4184
|
+
case "cpp":
|
|
4185
|
+
case "csharp":
|
|
4186
|
+
case "java":
|
|
4187
|
+
case "php":
|
|
4188
|
+
case "ruby":
|
|
4189
|
+
case "kotlin":
|
|
4190
|
+
case "swift":
|
|
4191
|
+
case "dart": return parseBrace(text);
|
|
4192
|
+
default: return [];
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
//#endregion
|
|
4196
|
+
//#region src/client/outline/sources.ts
|
|
4197
|
+
/** 无内置 provider、由 parse.ts 兜底的语言。 */
|
|
4198
|
+
const OUTLINE_FALLBACK_LANGS = /* @__PURE__ */ new Set([
|
|
4199
|
+
"markdown",
|
|
4200
|
+
"mdx",
|
|
4201
|
+
"python",
|
|
4202
|
+
"shell",
|
|
4203
|
+
"powershell",
|
|
4204
|
+
"lua",
|
|
4205
|
+
"go",
|
|
4206
|
+
"rust",
|
|
4207
|
+
"yaml",
|
|
4208
|
+
"ini",
|
|
4209
|
+
"c",
|
|
4210
|
+
"cpp",
|
|
4211
|
+
"csharp",
|
|
4212
|
+
"java",
|
|
4213
|
+
"php",
|
|
4214
|
+
"ruby",
|
|
4215
|
+
"kotlin",
|
|
4216
|
+
"swift",
|
|
4217
|
+
"dart"
|
|
4218
|
+
]);
|
|
4219
|
+
/**
|
|
4220
|
+
* 创建生命周期独立的大纲源注册表。
|
|
4221
|
+
* @author ddj 2026年08月27号
|
|
4222
|
+
* @returns 大纲源注册表
|
|
4223
|
+
*/
|
|
4224
|
+
function createOutlineSourceRegistry() {
|
|
4225
|
+
const entries = /* @__PURE__ */ new Map();
|
|
4226
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4227
|
+
const notify = () => {
|
|
4228
|
+
for (const listener of listeners) listener();
|
|
4229
|
+
};
|
|
4230
|
+
const list = () => [...entries.values()].sort((a, b) => b.priority - a.priority || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
4231
|
+
return {
|
|
4232
|
+
register(source) {
|
|
4233
|
+
if (!source || !source.id || typeof source.get !== "function") throw new TypeError("大纲源必须提供 id 与 get");
|
|
4234
|
+
entries.set(source.id, source);
|
|
4235
|
+
notify();
|
|
4236
|
+
return () => {
|
|
4237
|
+
if (entries.get(source.id) !== source) return;
|
|
4238
|
+
entries.delete(source.id);
|
|
4239
|
+
notify();
|
|
4240
|
+
};
|
|
4241
|
+
},
|
|
4242
|
+
list,
|
|
4243
|
+
subscribe(listener) {
|
|
4244
|
+
listeners.add(listener);
|
|
4245
|
+
return () => listeners.delete(listener);
|
|
4246
|
+
},
|
|
4247
|
+
get: (id) => entries.get(id)
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
/** 归一化 Monaco OutlineElement(getTopLevelSymbols 产物)→ OutlineSymbol。 */
|
|
4251
|
+
function normalizeMonaco(el) {
|
|
4252
|
+
if (!el || typeof el.name !== "string") return null;
|
|
4253
|
+
const range = el.range || {};
|
|
4254
|
+
const sel = el.selectionRange || range;
|
|
4255
|
+
const startLine = Math.max(1, Number(sel.startLineNumber ?? range.startLineNumber ?? 1));
|
|
4256
|
+
const endLine = Math.max(1, Number(range.endLineNumber ?? startLine));
|
|
4257
|
+
const out = {
|
|
4258
|
+
name: el.name,
|
|
4259
|
+
kind: typeof el.kind === "number" ? el.kind : 0,
|
|
4260
|
+
startLine: Math.max(1, Number(range.startLineNumber ?? startLine)),
|
|
4261
|
+
endLine,
|
|
4262
|
+
selectLine: startLine
|
|
4263
|
+
};
|
|
4264
|
+
if (typeof el.detail === "string" && el.detail) out.detail = el.detail;
|
|
4265
|
+
if (Array.isArray(el.children) && el.children.length) {
|
|
4266
|
+
const kids = el.children.map(normalizeMonaco).filter(Boolean);
|
|
4267
|
+
if (kids.length) out.children = kids;
|
|
4268
|
+
}
|
|
4269
|
+
return out;
|
|
4270
|
+
}
|
|
4271
|
+
/**
|
|
4272
|
+
* 按优先级解析大纲符号:首个非空结果生效(出错源跳过,落入下一优先级)。
|
|
4273
|
+
* @author ddj 2026年08月27号
|
|
4274
|
+
* @param sources 大纲源注册表
|
|
4275
|
+
* @param input 当前快照(languageId/model/editor/monaco)
|
|
4276
|
+
* @returns 归一化符号树(无符号时为空数组)
|
|
4277
|
+
*/
|
|
4278
|
+
async function resolveOutline(sources, input) {
|
|
4279
|
+
for (const source of sources.list()) {
|
|
4280
|
+
let supports = false;
|
|
4281
|
+
try {
|
|
4282
|
+
supports = source.provides(input.languageId);
|
|
4283
|
+
} catch {
|
|
4284
|
+
supports = false;
|
|
4285
|
+
}
|
|
4286
|
+
if (!supports) continue;
|
|
4287
|
+
let items = null;
|
|
4288
|
+
try {
|
|
4289
|
+
items = await source.get(input);
|
|
4290
|
+
} catch {
|
|
4291
|
+
items = null;
|
|
4292
|
+
}
|
|
4293
|
+
if (items && items.length) return items;
|
|
4294
|
+
}
|
|
4295
|
+
return [];
|
|
4296
|
+
}
|
|
4297
|
+
/**
|
|
4298
|
+
* 注册内置大纲源(monaco=50 / fallback=30)。
|
|
4299
|
+
* @author ddj 2026年08月27号
|
|
4300
|
+
* @param registry 目标注册表
|
|
4301
|
+
* @returns 注销函数(同时注销全部内置源)
|
|
4302
|
+
*/
|
|
4303
|
+
function registerBuiltinOutlineSources(registry) {
|
|
4304
|
+
const disposers = [registry.register({
|
|
4305
|
+
id: "monaco",
|
|
4306
|
+
priority: 50,
|
|
4307
|
+
provides: () => true,
|
|
4308
|
+
async get(input) {
|
|
4309
|
+
const ed = input.editor;
|
|
4310
|
+
const model = input.model;
|
|
4311
|
+
const cmd = ed?._commandService;
|
|
4312
|
+
if (!cmd || typeof cmd.executeCommand !== "function") return [];
|
|
4313
|
+
const uri = model?.uri;
|
|
4314
|
+
if (!uri) return [];
|
|
4315
|
+
const list = await cmd.executeCommand("_executeDocumentSymbolProvider", uri);
|
|
4316
|
+
return Array.isArray(list) ? list.map(normalizeMonaco).filter(Boolean) : [];
|
|
4317
|
+
}
|
|
4318
|
+
}), registry.register({
|
|
4319
|
+
id: "fallback",
|
|
4320
|
+
priority: 30,
|
|
4321
|
+
provides: (languageId) => OUTLINE_FALLBACK_LANGS.has(languageId),
|
|
4322
|
+
async get(input) {
|
|
4323
|
+
const model = input.model;
|
|
4324
|
+
if (!model || typeof model.getValue !== "function") return [];
|
|
4325
|
+
return parseOutline(input.languageId, model.getValue());
|
|
4326
|
+
}
|
|
4327
|
+
})];
|
|
4328
|
+
return () => {
|
|
4329
|
+
for (const dispose of disposers) dispose();
|
|
4330
|
+
};
|
|
4331
|
+
}
|
|
4332
|
+
//#endregion
|
|
4333
|
+
//#region src/client/outline/OutlinePanel.tsx
|
|
4334
|
+
/**
|
|
4335
|
+
* dsh-vscode-mode client — 侧边栏「大纲」面板。
|
|
4336
|
+
* 数据源经 resolveOutline(源注册表,优先级降序、首个非空生效)解析当前活动文件符号:
|
|
4337
|
+
* monaco 源吃原生 document symbol provider,fallback 源兜底无内置提供方的语言。
|
|
4338
|
+
* 交互:点击符号跳转编辑器、▸/▾ 折叠、光标所在符号高亮、空/加载/错误态。
|
|
4339
|
+
* 作者 ddj 2026-08-27
|
|
4340
|
+
*/
|
|
4341
|
+
/** 渲染符号数上限(防超大文件卡顿,超出显示截断提示)。 */
|
|
4342
|
+
const RENDER_CAP = 800;
|
|
4343
|
+
/** kind 分组元信息(字形 + 样式类)。 */
|
|
4344
|
+
const KIND_GROUPS = {
|
|
4345
|
+
func: {
|
|
4346
|
+
glyph: "ƒ",
|
|
4347
|
+
cls: "edrv-ol-func"
|
|
4348
|
+
},
|
|
4349
|
+
type: {
|
|
4350
|
+
glyph: "C",
|
|
4351
|
+
cls: "edrv-ol-type"
|
|
4352
|
+
},
|
|
4353
|
+
data: {
|
|
4354
|
+
glyph: "•",
|
|
4355
|
+
cls: "edrv-ol-data"
|
|
4356
|
+
},
|
|
4357
|
+
ns: {
|
|
4358
|
+
glyph: "▤",
|
|
4359
|
+
cls: "edrv-ol-ns"
|
|
4360
|
+
},
|
|
4361
|
+
key: {
|
|
4362
|
+
glyph: "·",
|
|
4363
|
+
cls: "edrv-ol-key"
|
|
4364
|
+
}
|
|
4365
|
+
};
|
|
4366
|
+
/** SymbolKind 数值 → 分组(File0..Package3=ns;Class4/Enum9/Interface10/Struct22/TypeParameter25=type;Method5/Constructor8/Function11=func;Key19/EnumMember21=key)。 */
|
|
4367
|
+
function kindMeta(kind) {
|
|
4368
|
+
const k = kind | 0;
|
|
4369
|
+
if (k <= 3) return KIND_GROUPS.ns;
|
|
4370
|
+
if (k === 4 || k === 9 || k === 10 || k === 22 || k === 25) return KIND_GROUPS.type;
|
|
4371
|
+
if (k === 5 || k === 8 || k === 11) return KIND_GROUPS.func;
|
|
4372
|
+
if (k === 19 || k === 21) return KIND_GROUPS.key;
|
|
4373
|
+
return KIND_GROUPS.data;
|
|
4374
|
+
}
|
|
4375
|
+
/**
|
|
4376
|
+
* 大纲面板主体。
|
|
4377
|
+
* @param props.ctx 面板共享上下文(editor/outlineSources/activePath)
|
|
4378
|
+
*/
|
|
4379
|
+
function OutlinePanel(props) {
|
|
4380
|
+
const ctx = props?.ctx;
|
|
4381
|
+
const activePath = ctx?.activePath ?? null;
|
|
4382
|
+
const [symbols, setSymbols] = react.default.useState(null);
|
|
4383
|
+
const [error, setError] = react.default.useState(null);
|
|
4384
|
+
const [collapsed, setCollapsed] = react.default.useState({});
|
|
4385
|
+
const [cursorLine, setCursorLine] = react.default.useState(null);
|
|
4386
|
+
const seqRef = react.default.useRef(0);
|
|
4387
|
+
const ctxRef = react.default.useRef(ctx);
|
|
4388
|
+
ctxRef.current = ctx;
|
|
4389
|
+
const activeRef = react.default.useRef(activePath);
|
|
4390
|
+
activeRef.current = activePath;
|
|
4391
|
+
const sourcesRef = react.default.useRef(ctx?.outlineSources);
|
|
4392
|
+
sourcesRef.current = ctx?.outlineSources;
|
|
4393
|
+
const refresh = react.default.useCallback(() => {
|
|
4394
|
+
const ed = ctxRef.current?.editor?.();
|
|
4395
|
+
const model = ed?.getModel?.();
|
|
4396
|
+
const seq = ++seqRef.current;
|
|
4397
|
+
if (!ed || !model) {
|
|
4398
|
+
setSymbols(null);
|
|
4399
|
+
setError(null);
|
|
4400
|
+
return;
|
|
4401
|
+
}
|
|
4402
|
+
const uriPath = model?.uri?.path;
|
|
4403
|
+
const modelPath = uriPath ? decodeURIComponent(String(uriPath).replace(/^\//, "")) : null;
|
|
4404
|
+
const active = activeRef.current;
|
|
4405
|
+
if (active && modelPath !== active) {
|
|
4406
|
+
setSymbols(null);
|
|
4407
|
+
setError(null);
|
|
4408
|
+
return;
|
|
4409
|
+
}
|
|
4410
|
+
const sources = sourcesRef.current;
|
|
4411
|
+
if (!sources) {
|
|
4412
|
+
setSymbols([]);
|
|
4413
|
+
setError(null);
|
|
4414
|
+
return;
|
|
4415
|
+
}
|
|
4416
|
+
setError(null);
|
|
4417
|
+
resolveOutline(sources, {
|
|
4418
|
+
languageId: model.getLanguageId(),
|
|
4419
|
+
model,
|
|
4420
|
+
editor: ed,
|
|
4421
|
+
monaco: window.monaco
|
|
4422
|
+
}).then((list) => {
|
|
4423
|
+
if (seq === seqRef.current) setSymbols(list || []);
|
|
4424
|
+
}).catch((e) => {
|
|
4425
|
+
if (seq === seqRef.current) {
|
|
4426
|
+
setError(String(e?.message ?? e));
|
|
4427
|
+
setSymbols(null);
|
|
4428
|
+
}
|
|
4429
|
+
});
|
|
4430
|
+
}, []);
|
|
4431
|
+
react.default.useEffect(() => {
|
|
4432
|
+
const disposers = [];
|
|
4433
|
+
let debounceTimer = null;
|
|
4434
|
+
let waitTimer = null;
|
|
4435
|
+
const attach = () => {
|
|
4436
|
+
const ed = ctxRef.current?.editor?.();
|
|
4437
|
+
if (!ed) return false;
|
|
4438
|
+
let contentDisposable = null;
|
|
4439
|
+
const subContent = (model) => {
|
|
4440
|
+
if (contentDisposable) {
|
|
4441
|
+
contentDisposable.dispose();
|
|
4442
|
+
contentDisposable = null;
|
|
4443
|
+
}
|
|
4444
|
+
contentDisposable = model?.onDidChangeContent?.(() => {
|
|
4445
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
4446
|
+
debounceTimer = setTimeout(() => {
|
|
4447
|
+
debounceTimer = null;
|
|
4448
|
+
refresh();
|
|
4449
|
+
}, 300);
|
|
4450
|
+
}) ?? null;
|
|
4451
|
+
};
|
|
4452
|
+
const onModel = () => {
|
|
4453
|
+
subContent(ed.getModel?.());
|
|
4454
|
+
refresh();
|
|
4455
|
+
};
|
|
4456
|
+
const onCursor = (e) => setCursorLine(e?.position?.lineNumber ?? null);
|
|
4457
|
+
subContent(ed.getModel?.());
|
|
4458
|
+
const subs = [
|
|
4459
|
+
ed.onDidChangeModel?.(onModel),
|
|
4460
|
+
ed.onDidChangeCursorPosition?.(onCursor),
|
|
4461
|
+
{ dispose: () => {
|
|
4462
|
+
if (contentDisposable) contentDisposable.dispose();
|
|
4463
|
+
} }
|
|
4464
|
+
];
|
|
4465
|
+
for (const s of subs) if (s) disposers.push(s);
|
|
4466
|
+
refresh();
|
|
4467
|
+
return true;
|
|
4468
|
+
};
|
|
4469
|
+
const onRefresh = () => refresh();
|
|
4470
|
+
window.addEventListener("edrv:refresh", onRefresh);
|
|
4471
|
+
if (!attach()) waitTimer = setInterval(() => {
|
|
4472
|
+
if (attach()) {
|
|
4473
|
+
clearInterval(waitTimer);
|
|
4474
|
+
waitTimer = null;
|
|
4475
|
+
}
|
|
4476
|
+
}, 400);
|
|
4477
|
+
return () => {
|
|
4478
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
4479
|
+
if (waitTimer) clearInterval(waitTimer);
|
|
4480
|
+
for (const d of disposers) if (d?.dispose) d.dispose();
|
|
4481
|
+
window.removeEventListener("edrv:refresh", onRefresh);
|
|
4482
|
+
};
|
|
4483
|
+
}, [refresh]);
|
|
4484
|
+
react.default.useEffect(() => {
|
|
4485
|
+
refresh();
|
|
4486
|
+
}, [refresh, activePath]);
|
|
4487
|
+
const jump = (sym) => {
|
|
4488
|
+
const ed = ctxRef.current?.editor?.();
|
|
4489
|
+
if (!ed) return;
|
|
4490
|
+
const line = Math.max(1, sym?.selectLine ?? sym?.startLine ?? 1);
|
|
4491
|
+
ed.revealLineInCenter(line);
|
|
4492
|
+
ed.setPosition({
|
|
4493
|
+
lineNumber: line,
|
|
4494
|
+
column: 1
|
|
4495
|
+
});
|
|
4496
|
+
ed.focus();
|
|
4497
|
+
};
|
|
4498
|
+
const toggleCollapse = (key) => {
|
|
4499
|
+
setCollapsed((prev) => Object.assign({}, prev, { [key]: prev[key] === true ? false : true }));
|
|
4500
|
+
};
|
|
4501
|
+
const allKeys = react.default.useMemo(() => {
|
|
4502
|
+
const keys = [];
|
|
4503
|
+
const walk = (list, prefix) => {
|
|
4504
|
+
for (let i = 0; i < list.length; i++) {
|
|
4505
|
+
const key = prefix ? prefix + "/" + i : String(i);
|
|
4506
|
+
const sym = list[i];
|
|
4507
|
+
if (sym.children && sym.children.length) {
|
|
4508
|
+
keys.push(key);
|
|
4509
|
+
walk(sym.children, key);
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
walk(symbols || [], "");
|
|
4514
|
+
return keys;
|
|
4515
|
+
}, [symbols]);
|
|
4516
|
+
const setAll = (value) => {
|
|
4517
|
+
const next = {};
|
|
4518
|
+
for (const key of allKeys) next[key] = value;
|
|
4519
|
+
setCollapsed(next);
|
|
4520
|
+
};
|
|
4521
|
+
const renderTree = (list, depth, prefix) => {
|
|
4522
|
+
const rows = [];
|
|
4523
|
+
const cap = Math.min(list.length, RENDER_CAP);
|
|
4524
|
+
for (let i = 0; i < cap; i++) {
|
|
4525
|
+
const sym = list[i];
|
|
4526
|
+
const key = prefix ? prefix + "/" + i : String(i);
|
|
4527
|
+
const kids = sym.children && sym.children.length ? sym.children : null;
|
|
4528
|
+
const isCollapsed = collapsed[key] === true;
|
|
4529
|
+
const meta = kindMeta(sym.kind);
|
|
4530
|
+
const active = cursorLine != null && sym.startLine <= cursorLine && cursorLine <= sym.endLine;
|
|
4531
|
+
rows.push(react.default.createElement("div", {
|
|
4532
|
+
key,
|
|
4533
|
+
className: "edrv-tree-row" + (active ? " edrv-tree-active" : ""),
|
|
4534
|
+
title: sym.detail || sym.name,
|
|
4535
|
+
style: { paddingLeft: 6 + depth * 14 },
|
|
4536
|
+
onClick: () => jump(sym)
|
|
4537
|
+
}, react.default.createElement("span", {
|
|
4538
|
+
className: "edrv-tree-chev",
|
|
4539
|
+
onClick: (e) => {
|
|
4540
|
+
e.stopPropagation();
|
|
4541
|
+
toggleCollapse(key);
|
|
4542
|
+
}
|
|
4543
|
+
}, kids ? isCollapsed ? "▸" : "▾" : ""), react.default.createElement("span", { className: "edrv-outline-kind " + meta.cls }, meta.glyph), react.default.createElement("span", { className: "edrv-tree-name" }, sym.name), sym.detail ? react.default.createElement("span", { className: "edrv-outline-detail" }, sym.detail) : null, react.default.createElement("span", { className: "edrv-outline-ln" }, String(sym.selectLine ?? sym.startLine ?? ""))));
|
|
4544
|
+
if (kids && !isCollapsed) rows.push(...renderTree(kids, depth + 1, key));
|
|
4545
|
+
}
|
|
4546
|
+
if (list.length > RENDER_CAP) rows.push(react.default.createElement("div", {
|
|
4547
|
+
key: "cap",
|
|
4548
|
+
className: "edrv-tree-loading"
|
|
4549
|
+
}, "符号过多,仅显示前 800 个"));
|
|
4550
|
+
return rows;
|
|
4551
|
+
};
|
|
4552
|
+
const basename = activePath ? String(activePath).split(/[\\/]/).pop() || activePath : "";
|
|
4553
|
+
let body;
|
|
4554
|
+
if (error) body = react.default.createElement("div", { className: "edrv-tree" }, react.default.createElement("div", { className: "edrv-tree-error" }, react.default.createElement("span", null, String(error)), react.default.createElement("button", {
|
|
4555
|
+
className: "edrv-side-btn",
|
|
4556
|
+
onClick: refresh
|
|
4557
|
+
}, "重试")));
|
|
4558
|
+
else if (!activePath) body = react.default.createElement("div", { className: "edrv-tree" }, react.default.createElement("div", { className: "edrv-tree-loading" }, "未打开文件"));
|
|
4559
|
+
else if (symbols === null) body = react.default.createElement("div", { className: "edrv-tree" }, react.default.createElement("div", { className: "edrv-tree-loading" }, "加载中…"));
|
|
4560
|
+
else if (symbols.length === 0) body = react.default.createElement("div", { className: "edrv-tree" }, react.default.createElement("div", { className: "edrv-tree-loading" }, "该语言暂不支持大纲或文件无符号"));
|
|
4561
|
+
else body = react.default.createElement("div", { className: "edrv-tree" }, ...renderTree(symbols, 0, ""));
|
|
4562
|
+
return react.default.createElement("div", { className: "edrv-side-panel" }, react.default.createElement("div", { className: "edrv-side-head" }, react.default.createElement("span", { className: "edrv-side-title" }, "大纲"), react.default.createElement("span", {
|
|
4563
|
+
className: "edrv-side-root",
|
|
4564
|
+
title: activePath || ""
|
|
4565
|
+
}, basename), react.default.createElement("span", { style: { flex: 1 } }), react.default.createElement("button", {
|
|
4566
|
+
className: "edrv-side-btn",
|
|
4567
|
+
title: "折叠全部",
|
|
4568
|
+
disabled: !(symbols && symbols.length),
|
|
4569
|
+
onClick: () => setAll(true)
|
|
4570
|
+
}, "−"), react.default.createElement("button", {
|
|
4571
|
+
className: "edrv-side-btn",
|
|
4572
|
+
title: "展开全部",
|
|
4573
|
+
disabled: !(symbols && symbols.length),
|
|
4574
|
+
onClick: () => setAll(false)
|
|
4575
|
+
}, "+"), react.default.createElement("button", {
|
|
4576
|
+
className: "edrv-side-btn",
|
|
4577
|
+
title: "刷新大纲",
|
|
4578
|
+
onClick: refresh
|
|
4579
|
+
}, "⟳")), body);
|
|
4580
|
+
}
|
|
4581
|
+
//#endregion
|
|
4582
|
+
//#region src/client/outline/index.ts
|
|
4583
|
+
/**
|
|
4584
|
+
* dsh-vscode-mode client — 「大纲」面板定义(注册表一项)。
|
|
4585
|
+
* 数据源解析复用 outline/sources 的源注册表(ctx.outlineSources 注入)。
|
|
4586
|
+
* 作者 ddj 2026-08-27
|
|
4587
|
+
*/
|
|
4588
|
+
/**
|
|
4589
|
+
* 构造大纲面板定义。
|
|
4590
|
+
* @author ddj 2026年08月27号
|
|
4591
|
+
* @returns 面板定义(无徽标;活动栏图标 📜)
|
|
4592
|
+
*/
|
|
4593
|
+
function createOutlinePanel() {
|
|
4594
|
+
return {
|
|
4595
|
+
id: "outline",
|
|
4596
|
+
title: "大纲",
|
|
4597
|
+
icon: "📜",
|
|
4598
|
+
order: 20,
|
|
4599
|
+
render: (ctx) => react.default.createElement(OutlinePanel, { ctx })
|
|
4600
|
+
};
|
|
4601
|
+
}
|
|
4602
|
+
//#endregion
|
|
3870
4603
|
//#region src/client/index.ts
|
|
3871
4604
|
/**
|
|
3872
4605
|
* dsh-vscode-mode client — 浏览器半入口:slot 注册 + 装配。
|
|
@@ -3948,6 +4681,10 @@ window.__ModuleLoader__.load({
|
|
|
3948
4681
|
const sidebarPanels = createSidebarPanelRegistry();
|
|
3949
4682
|
ctx.provide("edrvSidebarPanels", sidebarPanels);
|
|
3950
4683
|
ctx.effect(() => sidebarPanels.register(createFilePanel()), "vscode-mode: sidebar panel");
|
|
4684
|
+
const outlineSources = createOutlineSourceRegistry();
|
|
4685
|
+
ctx.provide("edrvOutlineSources", outlineSources);
|
|
4686
|
+
ctx.effect(() => registerBuiltinOutlineSources(outlineSources), "vscode-mode: outline sources");
|
|
4687
|
+
ctx.effect(() => sidebarPanels.register(createOutlinePanel()), "vscode-mode: sidebar panel outline");
|
|
3951
4688
|
ctx.effect(() => registry.register({
|
|
3952
4689
|
id: "system",
|
|
3953
4690
|
label: "系统默认应用",
|
|
@@ -3992,7 +4729,8 @@ window.__ModuleLoader__.load({
|
|
|
3992
4729
|
}, (props) => react.default.createElement(EditorView, Object.assign({}, props, {
|
|
3993
4730
|
schedule,
|
|
3994
4731
|
addToConversation,
|
|
3995
|
-
sidebarPanels
|
|
4732
|
+
sidebarPanels,
|
|
4733
|
+
outlineSources
|
|
3996
4734
|
})));
|
|
3997
4735
|
registerSlotSafely(ctx, {
|
|
3998
4736
|
name: "conversation.input.dock",
|