feat(file-icons): 目录保留扩展名注册 + 全局默认兜底 + 编辑器文件 tab 对应

- registerFileIcon 保留 'folder'/'folder-open' 特殊扩展名:目录行(含根行)
  图标可注册,匹配保留值不认领真实 .folder 文件
- 新增权威解析器 fileIcon(path,size)(具体注册 → 内置 glyph → catch-all
  全局默认 → VscFile,逐工厂崩溃隔离)与 folderIcon(path,open,size);
  matchFileIcon 收窄为仅具体扩展名匹配
- 编辑器文件 tab(非 meta.dir)与文件树行显示同一 fileIcon 图标
- 同步 external-plugin-guide §7(保留值/回退链/三例注册)与 README
  (功能一览、v0.19.0-alpha.0 发布注记、服务化扩展章节)
- tests/file-icons.spec.tsx 重写为 17 用例(链序/保留值/目录/崩溃回退)
This commit is contained in:
Menghuan1918
2026-09-08 21:11:32 +08:00
parent 05773e0f2a
commit 8025b83a45
8 changed files with 427 additions and 172 deletions
+9 -1
View File
@@ -813,8 +813,16 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) {
* ctx and the conversation input service at click time; a missing service
* or scope degrades to a logged no-op, never a crash.
*/
/** The tab icon from the tab-type registry (shared by every workbench). */
/**
* The tab icon: an editor tab WITH a file path (the per-path windows of
* split mode — `meta.dir` marks folder windows, which keep the folder
* glyph) shows the same file icon the tree row shows (`fileIcon`, feature
* `fileIcons`); every other tab uses its tab-type descriptor icon.
*/
const tabIconOf = (tab: SidebarTab): ReactNode => {
if (tab.type === 'editor' && tab.path !== undefined && (tab.meta as { dir?: boolean } | undefined)?.dir !== true) {
return ctx.get('betterSidebar')?.fileIcon(tab.path, 14) ?? null
}
const descriptor = ctx.get('betterSidebar')?.getTab(tab.type)
if (descriptor === undefined) return null
return typeof descriptor.icon === 'function' ? descriptor.icon(14) : descriptor.icon