@doubleelec/dsh-workspace-explorer 0.8.0 → 0.9.0

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/DEV.md ADDED
@@ -0,0 +1,160 @@
1
+ # DEV — dsh-workspace-explorer maintainer guide
2
+
3
+ For users: see [README.md](./README.md) (install from npm, usage, features).
4
+ This file is for maintainers: dev loop, local prod install, publishing, internals.
5
+
6
+ ## Environments
7
+
8
+ Two isolated profiles — edit once, verify in dev, then ship to prod:
9
+
10
+ | | Dev | Prod |
11
+ |---|---|---|
12
+ | Profile | `dev` | `web` |
13
+ | URL | http://127.0.0.1:3090 | http://127.0.0.1:3080 |
14
+ | Plugin source | symlink → this repo | real copy (decoupled from source) |
15
+
16
+ The dev profile works **because of the symlink, not because of any script**:
17
+ `$env:USERPROFILE\.dsh\profiles\dev\node_modules\@doubleelec\dsh-workspace-explorer`
18
+ points at this repo, so `npm run build` + refresh 3090 is the whole dev loop —
19
+ no install step, no elevation after the link exists.
20
+
21
+ ## Daily loop
22
+
23
+ ```powershell
24
+ # 1) edit src/, then build (lib/ is what DSH actually loads)
25
+ npm run build
26
+
27
+ # 2) refresh 3090 — changes appear instantly (symlink, no reinstall, no restart)
28
+
29
+ # 3) after testing, ship to prod (one elevation, no npm publish needed)
30
+ powershell -ExecutionPolicy Bypass -File scripts/setup.ps1
31
+
32
+ # 4) refresh 3080 — done (restart `dsh web` only if the panel is missing)
33
+ ```
34
+
35
+ **Rule of thumb:** 3090 follows the source automatically; 3080 only eats what you
36
+ manually install into it — half-baked edits never leak into prod.
37
+
38
+ ## One-elevation prod install
39
+
40
+ `scripts/setup.ps1` exists for exactly one job: put this repo into the prod
41
+ web profile (3080). Run it in an elevated PowerShell; everything needing
42
+ elevation happens inside that single session:
43
+
44
+ 1. `npm run build` (skip with `-SkipBuild`)
45
+ 2. `dsh plugin --profile web add -w "file://<repo>"` + `dsh plugin --profile web install`
46
+ (a real copy, not a symlink — dev churn stays out of prod)
47
+
48
+ The script deliberately does **not** touch the dev profile: creating or
49
+ repairing the dev symlink is a one-time manual act (see below), not part of
50
+ every prod install. Mixing the two is what made the old script pointless —
51
+ it re-did dev setup on every prod ship, as if the dev profile's existence
52
+ depended on the install script rather than the other way round.
53
+
54
+ ### One-time dev symlink (only when the link is missing/broken)
55
+
56
+ ```powershell
57
+ $p = "$env:USERPROFILE\.dsh\profiles\dev\node_modules\@doubleelec\dsh-workspace-explorer"
58
+ Remove-Item -Recurse -Force $p # link/copy only, never the source tree
59
+ cmd /c mklink /D "$p" "<repo>" # needs one admin approval
60
+ ```
61
+
62
+ Check it with `(Get-Item $p -Force).Target` — it should print the repo path.
63
+ Never run `dsh web --port 3090` for dev: `dsh web` is pinned to the web
64
+ profile; dev must use `dsh --profile dev --port 3090`.
65
+
66
+ ### Troubleshooting
67
+
68
+ - No panel after refresh → check the symlink target (dev) or re-run the setup script (prod).
69
+ - Edits not showing → you forgot `npm run build` (the symlink links the directory, it doesn't build).
70
+ - Port 3090 busy → `netstat -ano | Select-String ':3090 '` then `taskkill /PID <PID> /F`.
71
+
72
+ ## Publishing to npm
73
+
74
+ Daily installs use a local mirror, but **publishing must go to the official
75
+ registry** (mirrors are read-only). Never write the official registry into `.npmrc`.
76
+
77
+ ```powershell
78
+ cd <repo>
79
+
80
+ # 1) login (official registry; 2FA needs an OTP)
81
+ npm login --registry=https://registry.npmjs.org/
82
+
83
+ # 2) sync versions (package.json / dsh.plugin.json / manifest.json),
84
+ # finalize CHANGELOG, verify
85
+ npm run build
86
+ npm run typecheck
87
+
88
+ # 3) publish — stable releases go straight to `latest`, no --tag
89
+ npm publish --registry=https://registry.npmjs.org/
90
+
91
+ # 4) verify + tag the source
92
+ npm view @doubleelec/dsh-workspace-explorer version --registry=https://registry.npmjs.org/
93
+ git tag v0.9.0
94
+ git push elec v0.9.0
95
+ ```
96
+
97
+ Notes: version numbers stay in sync across `package.json` / `dsh.plugin.json` /
98
+ `manifest.json` (+ CHANGELOG). Package contents: `lib/` + `dsh.plugin.json` +
99
+ `manifest.json` + scripts/docs (see `files` in `package.json`). A bad publish
100
+ can be undone within 72h:
101
+ `npm unpublish @doubleelec/dsh-workspace-explorer@<version> --registry=https://registry.npmjs.org/`.
102
+
103
+ ## Project structure
104
+
105
+ ```
106
+ dsh-workspace-explorer/
107
+ ├── README.md # User docs (install from npm, usage, features)
108
+ ├── DEV.md # This file — maintainer guide
109
+ ├── LICENSE # MIT
110
+ ├── CHANGELOG.md # Release notes
111
+ ├── manifest.json # Plugin metadata
112
+ ├── package.json # npm package (@doubleelec/dsh-workspace-explorer)
113
+ ├── scripts/
114
+ │ └── setup.ps1 # One-elevation prod install (3080 only)
115
+ ├── demo/
116
+ │ ├── index.html # Interactive mock preview (GitHub Pages)
117
+ │ └── preview.gif # Demo animation (README)
118
+ ├── .github/
119
+ │ └── workflows/
120
+ │ └── pages.yml # Deploy demo/ to GitHub Pages (manual; preview hidden)
121
+ ├── src/
122
+ │ ├── index.ts # Native host half: webServer JSON routes (/dsh-we/api/*)
123
+ │ └── client/
124
+ │ ├── index.tsx # Native client half: popup + tree + preview + drag & drop
125
+ │ ├── markdown.ts # Zero-dep Markdown parser/renderer (XSS-safe)
126
+ │ ├── mermaid.ts # Mermaid CDN lazy-loader
127
+ │ ├── previewState.ts # Preview restore state (tab + file + MD view)
128
+ │ ├── format.ts # Pure formatting helpers
129
+ │ └── popupLayout.ts# Popup geometry math (unit-tested)
130
+ ├── test/ # vitest suites (format / host / popupLayout / markdown / mermaid / previewState)
131
+ └── lib/ # Built artifacts (lib/index.js + lib/client.js)
132
+ ```
133
+
134
+ ## Implementation notes
135
+
136
+ | Capability | Mechanism |
137
+ |---|---|
138
+ | Directory listing | Host `fs` via `resolveRel`-guarded root+rel (`/dsh-we/api/list`), directories first, 400-entry cap |
139
+ | File peek | Whole read ≤ 512 KB, paged scan with line-offset cache beyond (`/dsh-we/api/peek`); binary sniffed, ≤ 32 KB inlinable |
140
+ | Tree / search index | Depth/budget-limited recursion (`/dsh-we/api/tree`, up to 10 levels / 5000 entries) |
141
+ | File write | `/dsh-we/api/write` with size-based external-change detection |
142
+ | Host→Client RPC | Same-origin `fetch POST /dsh-we/api/*` (path-confined, no arbitrary-path reads) |
143
+ | Popup | `shell.overlay` slot (`useWorkspaces` / `useSessions`), position measured between session header & composer; corner resize with localStorage memory |
144
+ | Toggle button | `conversation.session.header.utilities` slot (“Workspace Files” pill: name + icon) |
145
+ | Composer write | `conversation.input.dock` → `inputActions.setDraft`, with `conversation.input` service fallback |
146
+ | `@` mention | `inputTriggers.registerSource` (fuzzy candidates + lexicon highlight), root auto-discovered from sessions cwd |
147
+ | Drag & drop | HTML5 DnD; native caret insert in the textarea, append elsewhere |
148
+ | Markdown | Hand-written parser → React elements (no `innerHTML`); source toggle; paged fallback |
149
+ | Mermaid | CDN lazy-load (jsDelivr + unpkg fallback), `securityLevel: strict`, click-to-render per block |
150
+ | Preview restore | Module-level memory (tab + file ref + MD view), same-root only; mermaid stays unrendered |
151
+ | Theming / i18n | `--dsw-alias-*` CSS variables (light/dark); zh/en via the DSH locale service |
152
+
153
+ ### Hard-won lessons (native packaging)
154
+
155
+ - **Quoted scoped names in YAML** — `cordis.patch.yml` must quote `'@doubleelec/dsh-workspace-explorer'`; a bare `@` crashes `dsh web` boot (`bad indentation of a mapping entry`).
156
+ - **One route per `register()` call** — passing an array silently registers nothing (routes end up under key `undefined`); call `webServer.register` once per route.
157
+ - **Supersede stale entries** — when an entry point moves (e.g. sidebar button → header pill), register an empty placeholder on the old slot so the legacy button disappears.
158
+ - **Bundle id = npm name** — the client bundle `id` must equal the package name including scope, or the panel never mounts (platform keys modules by name).
159
+ - **Toolchain: tsdown ^0.22 + lightningcss** — tsdown 0.6.x is incompatible with rolldown (`transformPlugin` FATAL). Platform modules (`react`, `react-dom`, `@deepseek-ai/cordis`, `dsh-client-*`) stay external; CSS Modules inline via lightningcss.
160
+ - **rc version families matter** — `dsh-client-*` / `dsh-host-webserver` / `dsh-invariants` must be a mutually compatible rc family; mixing rc.1 with rc.6 breaks installs (`dsh-paths` E404).
package/README.md CHANGED
@@ -1,11 +1,9 @@
1
1
  # dsh-workspace-explorer
2
2
 
3
- > Self-maintained fork by [doubleelec](https://github.com/doubleelec) — based on
3
+ > Self-maintained by [doubleelec](https://github.com/doubleelec) — based on
4
4
  > [Jiyr0119/dsh-workspace-explorer](https://github.com/Jiyr0119/dsh-workspace-explorer) v0.7.1 (MIT).
5
5
  > npm package: `@doubleelec/dsh-workspace-explorer`.
6
6
 
7
- **[English](README.md)** | [中文](README.zh.md)
8
-
9
7
  [![License](https://img.shields.io/github/license/doubleelec/dsh-workspace-explorer)](LICENSE)
10
8
  [![GitHub stars](https://img.shields.io/github/stars/doubleelec/dsh-workspace-explorer)](https://github.com/doubleelec/dsh-workspace-explorer/stargazers)
11
9
  [![Last commit](https://img.shields.io/github/last-commit/doubleelec/dsh-workspace-explorer)](https://github.com/doubleelec/dsh-workspace-explorer)
@@ -20,8 +18,8 @@ Inspired by the VS Code / Cursor project tree, filling the gap of a missing dire
20
18
 
21
19
  ## Why this plugin
22
20
 
23
- - **Preview first, never misfire** — clicking a file row opens it in a dedicated Preview tab instead of unexpectedly injecting text into your draft. Sharing is an explicit act: the arrow button at the row's head, `⏎`, points toward the composer at the bottom-left — the icon says where the file is going.
24
- - **Markdown that reads like Markdown** — `.md` / `.mdx` files render formatted (headings, lists, code blocks, quotes, tables, task lists) with a one-click source toggle. Zero-dependency renderer built on React elements — XSS-safe by construction, no sanitizer needed.
21
+ - **Preview first, never misfire** — clicking a file row opens it in a dedicated Preview tab instead of unexpectedly injecting text into your draft. Sharing is an explicit act: the arrow button at the row's head, `⏎`, points toward the composer at the bottom-left — the icon says where the file is going. Closing and reopening the panel restores the tab, the previewed file and the Markdown view.
22
+ - **Markdown that reads like Markdown** — `.md` / `.mdx` files render formatted (headings, lists, code blocks, quotes, tables, task lists) with a one-click source toggle. `mermaid` blocks render on demand via CDN lazy-load. Zero-dependency renderer built on React elements — XSS-safe by construction, no sanitizer needed.
25
23
  - **Reference anything in one motion** — single click to share, drag & drop to the caret, Shift / ⌘ multi-select batch insert, or type `@` in the composer to fuzzy-find any file (up to 5000 entries, 10 levels deep) even with the panel closed.
26
24
  - **Edit without leaving** — preview panel turns into an editor (Save / Discard / Cancel) with external-change detection on save; writes go straight to disk.
27
25
  - **Fullscreen when it matters** — one click in the header expands the popup over the whole session area for big files and long Markdown; click again (or `Esc`) to go back.
@@ -31,10 +29,10 @@ Inspired by the VS Code / Cursor project tree, filling the gap of a missing dire
31
29
 
32
30
  ![dsh-workspace-explorer demo](demo/preview.gif)
33
31
 
34
- *Demo GIF (recorded at v0.5.1): the **“Workspace Files” pill entry**, multi-select batch insert, folder drag → compact tree text, paginated preview, and the settings tab. The newer Preview tab, file editing and Markdown rendering are shown in the screenshots below.*
32
+ *Demo GIF (recorded at v0.5.1): the **“Workspace Files” pill entry**, multi-select batch insert, folder drag → compact tree text, paged preview, and the settings tab. The newer Preview tab, file editing and Markdown rendering are shown in the screenshots below.*
35
33
 
36
34
  <details>
37
- <summary><b>Screenshots</b> · 截图</summary>
35
+ <summary><b>Screenshots</b></summary>
38
36
 
39
37
  ![Panel](assets/screenshots/panel.png)
40
38
 
@@ -54,7 +52,7 @@ Inspired by the VS Code / Cursor project tree, filling the gap of a missing dire
54
52
  - 🗂 **Top tab bar** — Files / Preview / Settings; the Settings page tunes behavior live (hide noise dirs, show sizes, reference format) and mirrors into DSH Settings → Workspace Explorer
55
53
  - 🗂 **Lazy-loading tree** — directories load on demand; noise dirs (`node_modules`, `.git`, `dist`, `__pycache__`, …) are hidden automatically
56
54
  - 🎨 **File-type icons** — filled, color-coded document badges per extension (TS / JS / Python / JSON / Markdown / image / config / shell, …); amber folders that brighten when expanded; the actively previewed file gets a blue dot
57
- - 🖱 **Click to preview** — click a file row (or `Enter` / `Space`) to open it in the Preview tab; the **⏎ button** at the row's head inserts the `@path` reference into the composer (`@` / `i` shortcut works too)
55
+ - 🖱 **Click to preview** — click a file row (or `Enter` / `Space`) to open it in the Preview tab; the **⏎ button** at the row's head inserts the `@path` reference into the composer (`@` / `i` shortcut works too). The tab, the file and the rendered/source view survive panel close/reopen.
58
56
  - ⛶ **Fullscreen mode** — the header toggle (next to close) expands the popup over the whole session area for big files / long Markdown; click again to restore, `Esc` exits fullscreen first
59
57
  - 🖱 **Drag & drop** — drop a file into the composer to insert at the caret (fullscreen dashed hint); dropping elsewhere appends to the end. **Folders are draggable too** — dropping a directory inserts a depth-limited compact tree listing
60
58
  - 🖱 **Multi-select & batch insert** — Shift / ⌘ click to select multiple rows, then insert all of them at once (files → references, folders → tree listings)
@@ -62,13 +60,14 @@ Inspired by the VS Code / Cursor project tree, filling the gap of a missing dire
62
60
  - 🌓 **Theme-aware** — built entirely on DSH's `--dsw-alias-*` design tokens; adapts to light/dark with a native dialog look (16px radius, lv3 shadow)
63
61
  - 🔍 **Search & filter** — filter files by name across the whole tree (up to 5000 entries / 10 levels, match count shown)
64
62
  - 📝 **Markdown rendering** — `.md` / `.mdx` preview rendered by default (headings, bold/italic/strike, code blocks with language tag, quotes, ordered/unordered/task lists, tables, horizontal rules); one-click toggle back to source; oversized paged files fall back to source automatically
65
- - ✏️ **Preview tab** — whole-file view (≤ 4 MB in one read, paged beyond that with total lines & current page); insert the reference, or paste the full content for small files (≤ 32 KB)
63
+ - 📊 **Mermaid diagrams** — `mermaid` code blocks show a Render button; the library (mermaid@10, jsDelivr primary + unpkg fallback) loads on first click only, so the bundle stays +6 KB; `securityLevel: strict`, source fallback on offline/CSP/syntax errors
64
+ - ✏️ **Preview tab** — whole-file view (≤ 512 KB in one read, paged beyond that with total lines & current page); insert the reference, or paste the full content for small files (≤ 32 KB)
66
65
  - 📝 **File editing** — click "Edit" in the preview panel to enter textarea mode; save writes directly to disk with change detection (warns if the file was modified externally)
67
66
  - 🌐 **i18n** — zh/en dictionaries registered through DSH's locale service; the panel follows the DSH UI language
68
67
 
69
68
  ## Quick Start
70
69
 
71
- ### Installation & usage
70
+ ### Install from npm
72
71
 
73
72
  One command installs the full plugin — no build step, no config changes. The npm package ships a native host half (`lib/index.js`, webServer JSON routes `/dsh-we/api/list|peek|tree|config|write`) **and** a browser bundle (`lib/client.js` via `dsh.plugin.json`).
74
73
 
@@ -82,8 +81,6 @@ dsh plugin --profile web add -w @doubleelec/dsh-workspace-explorer@latest
82
81
 
83
82
  > ⚠️ **Common misconception**: a listing alone never auto-installs anything — users still click install. The full UI now appears after install (native bundle — no boot errors).
84
83
 
85
- See [`docs/install.md`](./docs/install.md) for details.
86
-
87
84
  ### Usage
88
85
 
89
86
  1. Click the **“Workspace Files” pill** (feature name + folder icon) at the top right of the session header, beside the Session log button, to open the popup.
@@ -91,57 +88,9 @@ See [`docs/install.md`](./docs/install.md) for details.
91
88
  3. Click the **⏎ button** at a row's head (or drag the file into the composer, or type `@` + filename) to reference it, then send.
92
89
  4. Use the **Settings** tab at the top of the popup (or DSH Settings → Workspace Explorer) to adjust panel behavior.
93
90
 
94
- ## Project Structure
95
-
96
- ```
97
- dsh-workspace-explorer/
98
- ├── README.md # Docs — English (default)
99
- ├── README.zh.md # Docs — 中文
100
- ├── LICENSE # MIT
101
- ├── CHANGELOG.md # Release notes
102
- ├── manifest.json # Plugin metadata
103
- ├── package.json # npm package (@doubleelec/dsh-workspace-explorer)
104
- ├── demo/
105
- │ ├── index.html # Interactive mock preview (GitHub Pages)
106
- │ └── preview.gif # Demo animation (README)
107
- ├── .github/
108
- │ └── workflows/
109
- │ └── pages.yml # Deploy demo/ to GitHub Pages (manual; preview hidden)
110
- ├── docs/
111
- │ ├── install.md # Install guide
112
- │ ├── local-debugging.md# Local dev setup (symlink + dev profile)
113
- │ └── publish.md # Publishing workflow (GitHub + npm)
114
- ├── src/
115
- │ ├── index.ts # Native host half: webServer JSON routes (/dsh-we/api/*)
116
- │ └── client/
117
- │ ├── index.tsx # Native client half: popup + tree + preview + drag & drop
118
- │ ├── markdown.ts # Zero-dep Markdown parser/renderer (XSS-safe)
119
- │ ├── format.ts # Pure formatting helpers
120
- │ └── popupLayout.ts# Popup geometry math (unit-tested)
121
- ├── test/ # vitest suites (format / host / popupLayout / markdown)
122
- └── lib/ # Built artifacts (lib/index.js + lib/client.js)
123
- ```
124
-
125
- ## Implementation Notes
126
-
127
- | Capability | Mechanism |
128
- |---|---|
129
- | Directory listing | Host `fs` via `resolveRel`-guarded root+rel (`/dsh-we/api/list`), directories first, 400-entry cap |
130
- | File peek | Whole read ≤ 4 MB, paged scan with line-offset cache beyond (`/dsh-we/api/peek`); binary sniffed, ≤ 32 KB inlinable |
131
- | Tree / search index | Depth/budget-limited recursion (`/dsh-we/api/tree`, up to 10 levels / 5000 entries) |
132
- | File write | `/dsh-we/api/write` with size-based external-change detection |
133
- | Host→Client RPC | Same-origin `fetch POST /dsh-we/api/*` (path-confined, no arbitrary-path reads) |
134
- | Popup | `shell.overlay` slot (`useWorkspaces` / `useSessions`), position measured between session header & composer; corner resize with localStorage memory |
135
- | Toggle button | `conversation.session.header.utilities` slot (“Workspace Files” pill: name + icon) |
136
- | Composer write | `conversation.input.dock` → `inputActions.setDraft`, with `conversation.input` service fallback |
137
- | `@` mention | `inputTriggers.registerSource` (fuzzy candidates + lexicon highlight), root auto-discovered from sessions cwd |
138
- | Drag & drop | HTML5 DnD; native caret insert in the textarea, append elsewhere |
139
- | Markdown | Hand-written parser → React elements (no `innerHTML`); source toggle; paged fallback |
140
- | Theming / i18n | `--dsw-alias-*` CSS variables (light/dark); zh/en via the DSH locale service |
141
-
142
91
  ## Version
143
92
 
144
- Current version **v0.8.0** — **Preview-first interaction** (row click previews, ↙ shares), **Markdown rendering**, **scoped fullscreen**, and **single-package cleanup** (dynamic paste variant removed).
93
+ Current version **v0.9.0** — **Mermaid diagrams** (CDN lazy-load, click-to-render), **preview restore** (tab + file + Markdown view), and the XSS-test fix.
145
94
  See [CHANGELOG.md](./CHANGELOG.md) for release notes.
146
95
 
147
96
  ## Roadmap
@@ -150,18 +99,20 @@ Focused on the two lines that actually matter to the product: the **read path**
150
99
 
151
100
  **Done ✅**
152
101
 
153
- - [x] v0.1 core: right-side file tree, click / drag-to-composer references, native DSH look
102
+ - [x] v0.1 core: right-side file tree, click / drag-to-composer references, DSH native look
154
103
  - [x] Search & filter across the whole tree; content insertion for small files (≤ 32 KB)
155
104
  - [x] i18n (zh/en via the DSH locale service, follows the DSH UI language)
156
105
  - [x] `@` mention source with sessions-cwd auto-discovery + lexicon highlight; unified `@path` reference format
157
106
  - [x] Demo language toggle, GitHub Pages preview, demo GIF, storefront screenshots
158
107
  - [x] npm package + `dsh.bundle` contract + awesome-dsh-plugin listing
159
108
  - [x] Multi-target references: folder drag (compact tree) + multi-select batch insert
160
- - [x] Whole-file preview (≤ 4 MB) with paged fallback for large files
161
- - [x] Preview-first interaction: row click previews, ⏎ button shares, keyboard `@` / `i`
162
- - [x] Markdown rendering (zero-dep, XSS-safe) with source toggle
109
+ - [x] Whole-file preview (≤ 512 KB) with paged fallback for large files
110
+ - [x] Preview-first interaction: row click previews, ⏎ shares, `@` / `i` shortcuts
111
+ - [x] Markdown rendering (zero-dep, XSS-safe) + source toggle
163
112
  - [x] In-panel file editing with external-change detection
164
113
  - [x] Resizable popup with size memory; Preview as a standalone tab
114
+ - [x] Mermaid diagrams (CDN lazy-load, click-to-render)
115
+ - [x] Preview restore (tab + file + Markdown view)
165
116
 
166
117
  **Parked backlog** (do when real demand shows up)
167
118
 
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/elec-workspace-explorer",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "main": "./lib/index.js",
5
5
  "description": "工作区文件资源管理器:右侧面板展示目录树,点击/拖拽插入文件引用,含搜索/预览/国际化。Workspace file explorer panel with click/drag references, search, preview, i18n.",
6
6
  "engines": {