@benz-ai-x/dsh-md-preview 0.3.0 → 0.6.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/README.md +87 -57
- package/README.zh.md +138 -0
- package/lib/client.js +3831 -29
- package/lib/index.js +91 -12
- package/lib/typert/remote-client.js +119 -70
- package/lib/types/client/PreviewOverlay.d.ts +8 -4
- package/lib/types/client/WorkspaceBrowser.d.ts +25 -0
- package/lib/types/client/diagrams.d.ts +34 -0
- package/lib/types/client/editor.d.ts +5 -2
- package/lib/types/client/locale.d.ts +11 -0
- package/lib/types/client/outline.d.ts +29 -0
- package/lib/types/client/preview-state.d.ts +2 -0
- package/lib/types/config.d.ts +4 -1
- package/lib/types/constants.d.ts +2 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/protocol.d.ts +16 -0
- package/lib/types/remote.d.ts +23 -1
- package/lib/types/typert/remote-client.d.ts +3 -1
- package/package.json +19 -8
package/lib/index.js
CHANGED
|
@@ -6,6 +6,12 @@ import z from "@deepseek-ai/schemastery";
|
|
|
6
6
|
const DEFAULT_MAX_BYTES = 1048576;
|
|
7
7
|
/** Markdown documents are the previewable vocabulary; deployments may widen it. */
|
|
8
8
|
const DEFAULT_ALLOWED_EXTENSIONS = [".md", ".markdown"];
|
|
9
|
+
/** The preview union: readable (and rendered) even though only markdown edits. */
|
|
10
|
+
const DEFAULT_PREVIEW_EXTENSIONS = [
|
|
11
|
+
".md",
|
|
12
|
+
".markdown",
|
|
13
|
+
".txt"
|
|
14
|
+
];
|
|
9
15
|
//#endregion
|
|
10
16
|
//#region src/remote.ts
|
|
11
17
|
var __runInitializers = function(thisArg, initializers, value) {
|
|
@@ -64,6 +70,12 @@ function fsErrorCode(error) {
|
|
|
64
70
|
if (typeof code === "string") return code;
|
|
65
71
|
}
|
|
66
72
|
}
|
|
73
|
+
/** Workspace-relative form of an entry target, falling back to its name. */
|
|
74
|
+
function workspaceRelative(rootPath, targetPath, name) {
|
|
75
|
+
if (targetPath === rootPath) return name;
|
|
76
|
+
const prefix = rootPath.endsWith("/") ? rootPath : `${rootPath}/`;
|
|
77
|
+
return targetPath.startsWith(prefix) ? targetPath.slice(prefix.length) : name;
|
|
78
|
+
}
|
|
67
79
|
/** Lowercased dot-prefixed extension of a path, or the empty string. */
|
|
68
80
|
function extensionOf(path) {
|
|
69
81
|
const name = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
|
|
@@ -83,11 +95,13 @@ let MdPreviewService = (() => {
|
|
|
83
95
|
let _instanceExtraInitializers = [];
|
|
84
96
|
let _read_decorators;
|
|
85
97
|
let _write_decorators;
|
|
98
|
+
let _list_decorators;
|
|
86
99
|
return class MdPreviewService extends _classSuper {
|
|
87
100
|
static {
|
|
88
101
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
89
102
|
_read_decorators = [Remote];
|
|
90
103
|
_write_decorators = [Remote];
|
|
104
|
+
_list_decorators = [Remote];
|
|
91
105
|
__esDecorate(this, null, _read_decorators, {
|
|
92
106
|
kind: "method",
|
|
93
107
|
name: "read",
|
|
@@ -110,6 +124,17 @@ let MdPreviewService = (() => {
|
|
|
110
124
|
},
|
|
111
125
|
metadata: _metadata
|
|
112
126
|
}, null, _instanceExtraInitializers);
|
|
127
|
+
__esDecorate(this, null, _list_decorators, {
|
|
128
|
+
kind: "method",
|
|
129
|
+
name: "list",
|
|
130
|
+
static: false,
|
|
131
|
+
private: false,
|
|
132
|
+
access: {
|
|
133
|
+
has: (obj) => "list" in obj,
|
|
134
|
+
get: (obj) => obj.list
|
|
135
|
+
},
|
|
136
|
+
metadata: _metadata
|
|
137
|
+
}, null, _instanceExtraInitializers);
|
|
113
138
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
114
139
|
enumerable: true,
|
|
115
140
|
configurable: true,
|
|
@@ -146,7 +171,7 @@ let MdPreviewService = (() => {
|
|
|
146
171
|
* @throws RemoteError with a stable MdPreview failure code.
|
|
147
172
|
*/
|
|
148
173
|
async read(sessionId, path, signal) {
|
|
149
|
-
const { target, info } = await this.resolveWorkspaceTarget(sessionId, path, signal, "read");
|
|
174
|
+
const { target, info } = await this.resolveWorkspaceTarget(sessionId, path, signal, "read", [...this.config.allowedExtensions, ...this.config.previewExtensions]);
|
|
150
175
|
if (info.size !== void 0 && info.size > this.config.maxBytes) throw failure("md-preview/too-large", `mdPreview/read refuses "${path}" above the configured byte cap`);
|
|
151
176
|
let content;
|
|
152
177
|
try {
|
|
@@ -175,7 +200,7 @@ let MdPreviewService = (() => {
|
|
|
175
200
|
* @throws RemoteError with a stable MdPreview failure code.
|
|
176
201
|
*/
|
|
177
202
|
async write(sessionId, path, content, fingerprint, force, signal) {
|
|
178
|
-
const { target, cwd } = await this.resolveWorkspaceTarget(sessionId, path, signal, "write");
|
|
203
|
+
const { target, cwd } = await this.resolveWorkspaceTarget(sessionId, path, signal, "write", this.config.allowedExtensions);
|
|
179
204
|
if (content.length > this.config.maxBytes) throw failure("md-preview/too-large", `mdPreview/write refuses "${path}" above the configured byte cap`);
|
|
180
205
|
if (fingerprint === void 0 && !force) throw failure("md-preview/bad-request", "mdPreview/write requires a fingerprint or force");
|
|
181
206
|
const expected = fingerprint === void 0 ? void 0 : {
|
|
@@ -204,6 +229,39 @@ let MdPreviewService = (() => {
|
|
|
204
229
|
};
|
|
205
230
|
}
|
|
206
231
|
/**
|
|
232
|
+
* List one workspace directory for the browser face; folders sort first,
|
|
233
|
+
* then entries alphabetize by name. A blank path lists the workspace root.
|
|
234
|
+
* @param sessionId - owning session; its header cwd roots the listing.
|
|
235
|
+
* @param path - directory path as the tree spelled it; blank = root.
|
|
236
|
+
* @param signal - caller cancellation carried through every fs call.
|
|
237
|
+
* @returns the requested path with its workspace-relative entries.
|
|
238
|
+
* @throws RemoteError with a stable MdPreview failure code.
|
|
239
|
+
*/
|
|
240
|
+
async list(sessionId, path, signal) {
|
|
241
|
+
const { root, target } = await this.resolveContainedTarget(sessionId, path, signal, "list");
|
|
242
|
+
const info = await this.ctx.fs.stat(target, signal);
|
|
243
|
+
if (info === void 0) throw failure("md-preview/not-found", `mdPreview/list cannot find "${path}"`);
|
|
244
|
+
if (info.type !== "directory") throw failure("md-preview/bad-request", `mdPreview/list requires a directory path, not "${path}"`);
|
|
245
|
+
let raw;
|
|
246
|
+
try {
|
|
247
|
+
raw = await this.ctx.fs.listDir(target, signal);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (signal.aborted) throw error;
|
|
250
|
+
throw failure("md-preview/unavailable", `mdPreview/list failed to list "${path}": ${error instanceof Error ? error.message : String(error)}`);
|
|
251
|
+
}
|
|
252
|
+
const rootPath = root.displayPath;
|
|
253
|
+
const entries = raw.map((entry) => ({
|
|
254
|
+
name: entry.name,
|
|
255
|
+
type: entry.type,
|
|
256
|
+
path: workspaceRelative(rootPath, entry.target.displayPath, entry.name)
|
|
257
|
+
}));
|
|
258
|
+
entries.sort((a, b) => a.type === b.type || a.type !== "directory" && b.type !== "directory" ? a.name.localeCompare(b.name) : a.type === "directory" ? -1 : 1);
|
|
259
|
+
return {
|
|
260
|
+
path: path.trim().length === 0 ? "" : path,
|
|
261
|
+
entries
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
207
265
|
* The shared authority preamble of the remote methods: resolve a path to a
|
|
208
266
|
* live, contained, regular workspace file, or reject it with the stable
|
|
209
267
|
* failure code. One home for the check order and the aborted-rethrow
|
|
@@ -215,16 +273,38 @@ let MdPreviewService = (() => {
|
|
|
215
273
|
* @returns the resolved target, its stat info, and the workspace cwd.
|
|
216
274
|
* @throws RemoteError with a stable MdPreview failure code.
|
|
217
275
|
*/
|
|
218
|
-
async resolveWorkspaceTarget(sessionId, path, signal, op) {
|
|
276
|
+
async resolveWorkspaceTarget(sessionId, path, signal, op, extensions) {
|
|
219
277
|
if (path.trim().length === 0) throw failure("md-preview/bad-request", `mdPreview/${op} requires a non-empty path`);
|
|
220
|
-
if (!isAllowedExtension(path,
|
|
278
|
+
if (!isAllowedExtension(path, extensions)) throw failure("md-preview/unsupported-extension", `mdPreview/${op} refuses non-previewable path "${path}"`);
|
|
279
|
+
const contained = await this.resolveContainedTarget(sessionId, path, signal, op);
|
|
280
|
+
const info = await this.ctx.fs.stat(contained.target, signal);
|
|
281
|
+
if (info === void 0) throw failure("md-preview/not-found", `mdPreview/${op} cannot find "${path}"`);
|
|
282
|
+
if (info.type !== "file") throw failure("md-preview/unsupported-extension", `mdPreview/${op} target "${path}" is not a regular file`);
|
|
283
|
+
return {
|
|
284
|
+
...contained,
|
|
285
|
+
info
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* The authority middle shared by every method: session → workspace cwd →
|
|
290
|
+
* root resolve → target resolve (a blank path means the root itself) →
|
|
291
|
+
* containment. Extension and type checks belong to the callers.
|
|
292
|
+
* @param sessionId - owning session; its header cwd roots the resolution.
|
|
293
|
+
* @param path - requested path; blank spells the workspace root.
|
|
294
|
+
* @param signal - caller cancellation carried through every fs call.
|
|
295
|
+
* @param op - calling method name for diagnostic messages.
|
|
296
|
+
* @returns the resolved root, target, and the workspace cwd.
|
|
297
|
+
* @throws RemoteError with a stable MdPreview failure code.
|
|
298
|
+
*/
|
|
299
|
+
async resolveContainedTarget(sessionId, path, signal, op) {
|
|
221
300
|
const session = this.ctx.sessions.get(sessionId);
|
|
222
301
|
if (session === void 0) throw failure("md-preview/unknown-session", `mdPreview/${op} cannot resolve session "${sessionId}"`);
|
|
223
302
|
const cwd = session.header.cwd;
|
|
224
303
|
if (cwd === void 0) throw failure("md-preview/no-workspace", `mdPreview/${op} session "${sessionId}" has no working directory`);
|
|
225
304
|
const root = await this.ctx.fs.resolve(cwd, { signal });
|
|
226
305
|
let target;
|
|
227
|
-
|
|
306
|
+
if (path.trim().length === 0) target = root;
|
|
307
|
+
else try {
|
|
228
308
|
target = await this.ctx.fs.resolve(path, {
|
|
229
309
|
cwd,
|
|
230
310
|
signal
|
|
@@ -234,12 +314,9 @@ let MdPreviewService = (() => {
|
|
|
234
314
|
throw failure("md-preview/not-found", `mdPreview/${op} cannot resolve path "${path}"`);
|
|
235
315
|
}
|
|
236
316
|
if (!this.ctx.fs.contains(root, target)) throw failure("md-preview/forbidden", `mdPreview/${op} refuses paths outside the session workspace`);
|
|
237
|
-
const info = await this.ctx.fs.stat(target, signal);
|
|
238
|
-
if (info === void 0) throw failure("md-preview/not-found", `mdPreview/${op} cannot find "${path}"`);
|
|
239
|
-
if (info.type !== "file") throw failure("md-preview/unsupported-extension", `mdPreview/${op} target "${path}" is not a regular file`);
|
|
240
317
|
return {
|
|
318
|
+
root,
|
|
241
319
|
target,
|
|
242
|
-
info,
|
|
243
320
|
cwd
|
|
244
321
|
};
|
|
245
322
|
}
|
|
@@ -251,7 +328,8 @@ let MdPreviewService = (() => {
|
|
|
251
328
|
/** Standard Schema twin of {@link Config}; defaults live here, not in code. */
|
|
252
329
|
const Config = z.object({
|
|
253
330
|
maxBytes: z.number().min(1).default(DEFAULT_MAX_BYTES),
|
|
254
|
-
allowedExtensions: z.array(z.string()).default([...DEFAULT_ALLOWED_EXTENSIONS])
|
|
331
|
+
allowedExtensions: z.array(z.string()).default([...DEFAULT_ALLOWED_EXTENSIONS]),
|
|
332
|
+
previewExtensions: z.array(z.string()).default([...DEFAULT_PREVIEW_EXTENSIONS])
|
|
255
333
|
});
|
|
256
334
|
//#endregion
|
|
257
335
|
//#region src/protocol.ts
|
|
@@ -284,11 +362,12 @@ const inject = [
|
|
|
284
362
|
*/
|
|
285
363
|
function apply(ctx, config = {
|
|
286
364
|
maxBytes: DEFAULT_MAX_BYTES,
|
|
287
|
-
allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS]
|
|
365
|
+
allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
|
|
366
|
+
previewExtensions: [...DEFAULT_PREVIEW_EXTENSIONS]
|
|
288
367
|
}) {
|
|
289
368
|
ctx.plugin(MdPreviewService, config);
|
|
290
369
|
}
|
|
291
370
|
//#endregion
|
|
292
|
-
export { Config, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, MD_PREVIEW_FAILURE_CODES, MdPreviewService, apply, inject, isAllowedExtension, name };
|
|
371
|
+
export { Config, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, DEFAULT_PREVIEW_EXTENSIONS, MD_PREVIEW_FAILURE_CODES, MdPreviewService, apply, inject, isAllowedExtension, name };
|
|
293
372
|
|
|
294
373
|
//# sourceMappingURL=index.js.map
|
|
@@ -24,48 +24,31 @@ const writeResult$schema = z.object({
|
|
|
24
24
|
path: z.string(),
|
|
25
25
|
fingerprint: z.string()
|
|
26
26
|
});
|
|
27
|
+
const listPath$schema = z.string();
|
|
28
|
+
const listEntry$schema = z.object({
|
|
29
|
+
name: z.string(),
|
|
30
|
+
type: z.enum([
|
|
31
|
+
"file",
|
|
32
|
+
"directory",
|
|
33
|
+
"other"
|
|
34
|
+
]),
|
|
35
|
+
path: z.string()
|
|
36
|
+
});
|
|
37
|
+
const listResult$schema = z.object({
|
|
38
|
+
path: z.string(),
|
|
39
|
+
entries: z.array(listEntry$schema)
|
|
40
|
+
});
|
|
27
41
|
/** The MdPreview contribution mounted by this package's browser entry. */
|
|
28
42
|
const TYPERT_REMOTE = {
|
|
29
43
|
package: "@benz-ai-x/dsh-md-preview",
|
|
30
|
-
descriptors: [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
wire: "sessionId",
|
|
39
|
-
source: "json",
|
|
40
|
-
codec: {
|
|
41
|
-
mode: "strict",
|
|
42
|
-
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
43
|
-
schema: readSessionId$schema
|
|
44
|
-
}
|
|
45
|
-
}, {
|
|
46
|
-
name: "path",
|
|
47
|
-
wire: "path",
|
|
48
|
-
source: "json",
|
|
49
|
-
codec: {
|
|
50
|
-
mode: "strict",
|
|
51
|
-
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:path",
|
|
52
|
-
schema: readPath$schema
|
|
53
|
-
}
|
|
54
|
-
}],
|
|
55
|
-
cancellation: { parameter: "signal" },
|
|
56
|
-
result: {
|
|
57
|
-
mode: "strict",
|
|
58
|
-
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:result",
|
|
59
|
-
schema: readResult$schema
|
|
60
|
-
}
|
|
61
|
-
}, {
|
|
62
|
-
id: "@benz-ai-x/dsh-md-preview#mdPreview/write",
|
|
63
|
-
service: "mdPreview",
|
|
64
|
-
namespace: "mdPreview",
|
|
65
|
-
method: "write",
|
|
66
|
-
invocation: { kind: "direct" },
|
|
67
|
-
parameters: [
|
|
68
|
-
{
|
|
44
|
+
descriptors: [
|
|
45
|
+
{
|
|
46
|
+
id: "@benz-ai-x/dsh-md-preview#mdPreview/read",
|
|
47
|
+
service: "mdPreview",
|
|
48
|
+
namespace: "mdPreview",
|
|
49
|
+
method: "read",
|
|
50
|
+
invocation: { kind: "direct" },
|
|
51
|
+
parameters: [{
|
|
69
52
|
name: "sessionId",
|
|
70
53
|
wire: "sessionId",
|
|
71
54
|
source: "json",
|
|
@@ -74,55 +57,121 @@ const TYPERT_REMOTE = {
|
|
|
74
57
|
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
75
58
|
schema: readSessionId$schema
|
|
76
59
|
}
|
|
77
|
-
},
|
|
78
|
-
{
|
|
60
|
+
}, {
|
|
79
61
|
name: "path",
|
|
80
62
|
wire: "path",
|
|
81
63
|
source: "json",
|
|
82
64
|
codec: {
|
|
83
65
|
mode: "strict",
|
|
84
|
-
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/
|
|
66
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:path",
|
|
85
67
|
schema: readPath$schema
|
|
86
68
|
}
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
69
|
+
}],
|
|
70
|
+
cancellation: { parameter: "signal" },
|
|
71
|
+
result: {
|
|
72
|
+
mode: "strict",
|
|
73
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:result",
|
|
74
|
+
schema: readResult$schema
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "@benz-ai-x/dsh-md-preview#mdPreview/write",
|
|
79
|
+
service: "mdPreview",
|
|
80
|
+
namespace: "mdPreview",
|
|
81
|
+
method: "write",
|
|
82
|
+
invocation: { kind: "direct" },
|
|
83
|
+
parameters: [
|
|
84
|
+
{
|
|
85
|
+
name: "sessionId",
|
|
86
|
+
wire: "sessionId",
|
|
87
|
+
source: "json",
|
|
88
|
+
codec: {
|
|
89
|
+
mode: "strict",
|
|
90
|
+
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
91
|
+
schema: readSessionId$schema
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "path",
|
|
96
|
+
wire: "path",
|
|
97
|
+
source: "json",
|
|
98
|
+
codec: {
|
|
99
|
+
mode: "strict",
|
|
100
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:path",
|
|
101
|
+
schema: readPath$schema
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "content",
|
|
106
|
+
wire: "content",
|
|
107
|
+
source: "json",
|
|
108
|
+
codec: {
|
|
109
|
+
mode: "strict",
|
|
110
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:content",
|
|
111
|
+
schema: writeContent$schema
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "fingerprint",
|
|
116
|
+
wire: "fingerprint",
|
|
117
|
+
source: "json",
|
|
118
|
+
codec: {
|
|
119
|
+
mode: "strict",
|
|
120
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:fingerprint",
|
|
121
|
+
schema: writeFingerprint$schema
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "force",
|
|
126
|
+
wire: "force",
|
|
127
|
+
source: "json",
|
|
128
|
+
codec: {
|
|
129
|
+
mode: "strict",
|
|
130
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:force",
|
|
131
|
+
schema: writeForce$schema
|
|
132
|
+
}
|
|
96
133
|
}
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
|
|
100
|
-
|
|
134
|
+
],
|
|
135
|
+
cancellation: { parameter: "signal" },
|
|
136
|
+
result: {
|
|
137
|
+
mode: "strict",
|
|
138
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:result",
|
|
139
|
+
schema: writeResult$schema
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: "@benz-ai-x/dsh-md-preview#mdPreview/list",
|
|
144
|
+
service: "mdPreview",
|
|
145
|
+
namespace: "mdPreview",
|
|
146
|
+
method: "list",
|
|
147
|
+
invocation: { kind: "direct" },
|
|
148
|
+
parameters: [{
|
|
149
|
+
name: "sessionId",
|
|
150
|
+
wire: "sessionId",
|
|
101
151
|
source: "json",
|
|
102
152
|
codec: {
|
|
103
153
|
mode: "strict",
|
|
104
|
-
typeSymbol: "@
|
|
105
|
-
schema:
|
|
154
|
+
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
155
|
+
schema: readSessionId$schema
|
|
106
156
|
}
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
wire: "force",
|
|
157
|
+
}, {
|
|
158
|
+
name: "path",
|
|
159
|
+
wire: "path",
|
|
111
160
|
source: "json",
|
|
112
161
|
codec: {
|
|
113
162
|
mode: "strict",
|
|
114
|
-
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/
|
|
115
|
-
schema:
|
|
163
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/list:path",
|
|
164
|
+
schema: listPath$schema
|
|
116
165
|
}
|
|
166
|
+
}],
|
|
167
|
+
cancellation: { parameter: "signal" },
|
|
168
|
+
result: {
|
|
169
|
+
mode: "strict",
|
|
170
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/list:result",
|
|
171
|
+
schema: listResult$schema
|
|
117
172
|
}
|
|
118
|
-
],
|
|
119
|
-
cancellation: { parameter: "signal" },
|
|
120
|
-
result: {
|
|
121
|
-
mode: "strict",
|
|
122
|
-
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/write:result",
|
|
123
|
-
schema: writeResult$schema
|
|
124
173
|
}
|
|
125
|
-
|
|
174
|
+
]
|
|
126
175
|
};
|
|
127
176
|
//#endregion
|
|
128
177
|
export { TYPERT_REMOTE, TYPERT_REMOTE as default };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
2
2
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
3
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
4
|
-
import type { MdPreviewFile, MdPreviewWriteResult } from '../protocol.ts';
|
|
5
|
-
import type { MdPreviewState } from './preview-state.ts';
|
|
6
|
-
/** Read/write RPCs and panel dismissal, created in the plugin's apply world. */
|
|
4
|
+
import type { MdPreviewFile, MdPreviewListResult, MdPreviewWriteResult } from '../protocol.ts';
|
|
5
|
+
import type { MdPreviewState, MdPreviewTarget } from './preview-state.ts';
|
|
6
|
+
/** Read/write/list RPCs and panel dismissal, created in the plugin's apply world. */
|
|
7
7
|
export interface PreviewOverlayInjected {
|
|
8
8
|
hooks: {
|
|
9
9
|
/** Current preview target; null while the panel is closed. */
|
|
@@ -11,10 +11,14 @@ export interface PreviewOverlayInjected {
|
|
|
11
11
|
};
|
|
12
12
|
/** Dismiss the panel and drop the target. */
|
|
13
13
|
close(): void;
|
|
14
|
+
/** Set the preview target (the browser face's file-open handoff). */
|
|
15
|
+
setTarget(target: MdPreviewTarget | null): void;
|
|
14
16
|
/** One bounded read; the transport carries the AbortSignal. */
|
|
15
17
|
read(sessionId: SessionId, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewFile>>;
|
|
16
18
|
/** One guarded write; `fingerprint` comes from the backing read. */
|
|
17
19
|
write(sessionId: SessionId, path: string, content: string, fingerprint: string | undefined, force: boolean, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewWriteResult>>;
|
|
20
|
+
/** One workspace directory listing; blank path lists the root. */
|
|
21
|
+
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewListResult>>;
|
|
18
22
|
}
|
|
19
23
|
/** Full composed panel props. */
|
|
20
24
|
export type PreviewOverlayProps = PropsRuntime<'shell.overlay'> & InjectFace<PreviewOverlayInjected> & PropsLocale<'md-preview'>;
|
|
@@ -23,5 +27,5 @@ export type PreviewOverlayProps = PropsRuntime<'shell.overlay'> & InjectFace<Pre
|
|
|
23
27
|
* @param props - target hook, read/write RPCs, dismissal, and the locale seat.
|
|
24
28
|
* @returns the docked panel, or null while closed.
|
|
25
29
|
*/
|
|
26
|
-
export declare function PreviewOverlay({ usePreviewTarget, close, read, write, t }: PreviewOverlayProps): import("react").JSX.Element | null;
|
|
30
|
+
export declare function PreviewOverlay({ usePreviewTarget, close, setTarget, read, write, list, t }: PreviewOverlayProps): import("react").JSX.Element | null;
|
|
27
31
|
//# sourceMappingURL=PreviewOverlay.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
import type { MdPreviewListResult } from '../protocol.ts';
|
|
4
|
+
/** Listing RPC and the file-open handoff, created in the plugin's apply world. */
|
|
5
|
+
export interface WorkspaceBrowserProps {
|
|
6
|
+
/** Owning session whose workspace the tree roots at. */
|
|
7
|
+
sessionId: SessionId;
|
|
8
|
+
/** Whether the browse face is showing (refreshes revalidate on entry). */
|
|
9
|
+
active: boolean;
|
|
10
|
+
/** One directory listing; the transport carries the AbortSignal. */
|
|
11
|
+
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<RemoteResult<MdPreviewListResult>>;
|
|
12
|
+
/** Open one file as the panel's preview target. */
|
|
13
|
+
onOpenFile(path: string): void;
|
|
14
|
+
/** Workspace-relative path of the current preview target, if any. */
|
|
15
|
+
currentPath: string | null;
|
|
16
|
+
/** Locale seat. */
|
|
17
|
+
t(key: string): string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render the workspace tree for one session.
|
|
21
|
+
* @param props - session identity, listing RPC, file-open handoff, locale seat.
|
|
22
|
+
* @returns the tree element.
|
|
23
|
+
*/
|
|
24
|
+
export declare function WorkspaceBrowser({ sessionId, active, list, onOpenFile, currentPath, t }: WorkspaceBrowserProps): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=WorkspaceBrowser.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The diagram pass: once the platform renderer settles the document, the
|
|
3
|
+
* panel enhances mermaid code blocks inside its own rendered subtree. The
|
|
4
|
+
* block's banner stays (copy keeps reading the source), the code hides, and
|
|
5
|
+
* mermaid's SVG shows above it. Every failure — a bad diagram, a failed
|
|
6
|
+
* import, a shape the parity check refuses — falls back to the plain code
|
|
7
|
+
* block; the platform renderer itself is never touched.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The fenced-block languages of one markdown document, in document order —
|
|
11
|
+
* the info word of each fence, lowercased. Indented (unfenced) code never
|
|
12
|
+
* lists, so the array aligns 1:1 with the rendered `.md-code-block` sequence.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fenceLanguages(content: string): readonly string[];
|
|
15
|
+
/**
|
|
16
|
+
* The panel's mermaid blocks: rendered `.md-code-block`s whose backing fence
|
|
17
|
+
* said mermaid. Matched by order parity — the only stable class the platform
|
|
18
|
+
* renderer guarantees — and refused wholesale on any count mismatch.
|
|
19
|
+
*/
|
|
20
|
+
export declare function findDiagramBlocks(root: ParentNode, fenceLangs: readonly string[]): readonly HTMLElement[];
|
|
21
|
+
/** Labels the panel injects (locale lives in the React world, not here). */
|
|
22
|
+
export interface DiagramLabels {
|
|
23
|
+
/** Caption under a block whose diagram failed to render. */
|
|
24
|
+
readonly error: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render every not-yet-enhanced mermaid block of one rendered document.
|
|
28
|
+
* Idempotent per block; safe to re-run after the DOM is replaced.
|
|
29
|
+
* @param root - the panel's rendered document container.
|
|
30
|
+
* @param content - the document source backing the rendered container.
|
|
31
|
+
* @param labels - the fallback caption.
|
|
32
|
+
*/
|
|
33
|
+
export declare function enhanceDiagrams(root: ParentNode, content: string, labels: DiagramLabels): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=diagrams.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EditorView } from '@codemirror/view';
|
|
1
2
|
/** Props the panel hands to the editor. */
|
|
2
3
|
export interface MarkdownEditorProps {
|
|
3
4
|
/** Document text at edit-session start; a changed value remounts the editor. */
|
|
@@ -6,11 +7,13 @@ export interface MarkdownEditorProps {
|
|
|
6
7
|
onChange: (value: string) => void;
|
|
7
8
|
/** Cmd/Ctrl-S from the editor's keymap. */
|
|
8
9
|
onSave: () => void;
|
|
10
|
+
/** Reports the mounted editor view (null on unmount) for panel-side calls. */
|
|
11
|
+
onView?: (view: EditorView | null) => void;
|
|
9
12
|
}
|
|
10
13
|
/**
|
|
11
14
|
* Render one CodeMirror editor bound to the panel's edit session.
|
|
12
|
-
* @param props - initial document plus change and
|
|
15
|
+
* @param props - initial document plus change, save, and view callbacks.
|
|
13
16
|
* @returns the editor host element.
|
|
14
17
|
*/
|
|
15
|
-
export declare function MarkdownEditor({ initialValue, onChange, onSave }: MarkdownEditorProps): import("react").JSX.Element;
|
|
18
|
+
export declare function MarkdownEditor({ initialValue, onChange, onSave, onView }: MarkdownEditorProps): import("react").JSX.Element;
|
|
16
19
|
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -8,10 +8,12 @@ export declare const zh: {
|
|
|
8
8
|
'panel.loading': string;
|
|
9
9
|
'panel.empty': string;
|
|
10
10
|
'panel.error': string;
|
|
11
|
+
'panel.unsupported': string;
|
|
11
12
|
'panel.retry': string;
|
|
12
13
|
'panel.edit': string;
|
|
13
14
|
'panel.save': string;
|
|
14
15
|
'panel.cancel': string;
|
|
16
|
+
'panel.find': string;
|
|
15
17
|
'panel.saved': string;
|
|
16
18
|
'panel.saveError': string;
|
|
17
19
|
'panel.save.retry': string;
|
|
@@ -21,6 +23,15 @@ export declare const zh: {
|
|
|
21
23
|
'panel.unsaved.title': string;
|
|
22
24
|
'panel.unsaved.discard': string;
|
|
23
25
|
'panel.unsaved.keep': string;
|
|
26
|
+
'browse.open': string;
|
|
27
|
+
'browse.back': string;
|
|
28
|
+
'browse.loading': string;
|
|
29
|
+
'browse.empty': string;
|
|
30
|
+
'browse.error': string;
|
|
31
|
+
'browse.retry': string;
|
|
32
|
+
'browse.refresh': string;
|
|
33
|
+
'outline.open': string;
|
|
34
|
+
'diagram.error': string;
|
|
24
35
|
'chip.preview': string;
|
|
25
36
|
'chip.open': string;
|
|
26
37
|
'action.label': string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The outline: the ATX heading sequence of one previewed document, feeding
|
|
3
|
+
* the panel header's outline popover. Source-derived so both faces share one
|
|
4
|
+
* list; fenced code is skipped so `#` lines inside blocks never count, and
|
|
5
|
+
* setext (underlined) headings stay out by design — the view-face jump
|
|
6
|
+
* resolves rendered headings by text, the edit-face jump by source line.
|
|
7
|
+
*/
|
|
8
|
+
/** One outline entry: heading level, display text, and its 1-based source line. */
|
|
9
|
+
export interface OutlineEntry {
|
|
10
|
+
readonly level: number;
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly line: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extract the outline of one markdown document.
|
|
16
|
+
* @param content - the document's full text.
|
|
17
|
+
* @returns ATX headings in order; fenced code is not scanned.
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractOutline(content: string): readonly OutlineEntry[];
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the rendered DOM heading of one outline entry.
|
|
22
|
+
* @param container - the rendered document container.
|
|
23
|
+
* @param entries - the outline the popover shows.
|
|
24
|
+
* @param index - the entry being navigated to.
|
|
25
|
+
* @returns the matching heading element, or undefined when the rendered
|
|
26
|
+
* document spells it differently (setext forms the source scan skips).
|
|
27
|
+
*/
|
|
28
|
+
export declare function findHeadingElement(container: ParentNode | null, entries: readonly OutlineEntry[], index: number): HTMLElement | undefined;
|
|
29
|
+
//# sourceMappingURL=outline.d.ts.map
|
|
@@ -13,6 +13,8 @@ export declare function createPreviewStore(): import("@deepseek-ai/dsh-client-st
|
|
|
13
13
|
export declare function basename(path: string): string;
|
|
14
14
|
/** Whether the client treats a produced path as a previewable markdown document. */
|
|
15
15
|
export declare function isPreviewable(path: string): boolean;
|
|
16
|
+
/** Whether a path may enter an edit session (the markdown-only editable set). */
|
|
17
|
+
export declare function isEditable(path: string): boolean;
|
|
16
18
|
/** Produced paths of one turn split into previewable and externally-opened groups, first-seen order preserved. */
|
|
17
19
|
export declare function splitPreviewable(paths: readonly string[]): {
|
|
18
20
|
previewable: string[];
|
package/lib/types/config.d.ts
CHANGED
|
@@ -4,8 +4,11 @@ import z from '@deepseek-ai/schemastery';
|
|
|
4
4
|
export interface Config {
|
|
5
5
|
/** Largest file size the service will read and return, in bytes. */
|
|
6
6
|
maxBytes: number;
|
|
7
|
-
/** Extensions (lowercased, dot-prefixed) eligible for
|
|
7
|
+
/** Extensions (lowercased, dot-prefixed) eligible for editing. */
|
|
8
8
|
allowedExtensions: string[];
|
|
9
|
+
/** Extensions (lowercased, dot-prefixed) eligible for preview (a superset
|
|
10
|
+
* of the editable set — plain-text members render but never edit). */
|
|
11
|
+
previewExtensions: string[];
|
|
9
12
|
}
|
|
10
13
|
/** Standard Schema twin of {@link Config}; defaults live here, not in code. */
|
|
11
14
|
export declare const Config: z<Config>;
|
package/lib/types/constants.d.ts
CHANGED
|
@@ -3,4 +3,6 @@
|
|
|
3
3
|
export declare const DEFAULT_MAX_BYTES = 1048576;
|
|
4
4
|
/** Markdown documents are the previewable vocabulary; deployments may widen it. */
|
|
5
5
|
export declare const DEFAULT_ALLOWED_EXTENSIONS: readonly [".md", ".markdown"];
|
|
6
|
+
/** The preview union: readable (and rendered) even though only markdown edits. */
|
|
7
|
+
export declare const DEFAULT_PREVIEW_EXTENSIONS: readonly [".md", ".markdown", ".txt"];
|
|
6
8
|
//# sourceMappingURL=constants.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
7
7
|
import { type Config as ConfigType } from './config.ts';
|
|
8
8
|
export { Config } from './config.ts';
|
|
9
9
|
export type { Config as ConfigInterface } from './config.ts';
|
|
10
|
-
export { DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES } from './constants.ts';
|
|
10
|
+
export { DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, DEFAULT_PREVIEW_EXTENSIONS } from './constants.ts';
|
|
11
11
|
export { isAllowedExtension, MdPreviewService } from './remote.ts';
|
|
12
12
|
export type { MdPreviewFile, MdPreviewFailureCode, MdPreviewReadRequest } from './protocol.ts';
|
|
13
13
|
export { MD_PREVIEW_FAILURE_CODES } from './protocol.ts';
|
package/lib/types/protocol.d.ts
CHANGED
|
@@ -16,6 +16,22 @@ export interface MdPreviewWriteResult {
|
|
|
16
16
|
/** Freshness token of the file after the write; guards the next save. */
|
|
17
17
|
readonly fingerprint: string;
|
|
18
18
|
}
|
|
19
|
+
/** One directory entry of the workspace browser tree. */
|
|
20
|
+
export interface MdPreviewEntry {
|
|
21
|
+
/** Entry basename as the fs layer reports it. */
|
|
22
|
+
readonly name: string;
|
|
23
|
+
/** Regular file, directory, or anything else. */
|
|
24
|
+
readonly type: 'file' | 'directory' | 'other';
|
|
25
|
+
/** Workspace-relative path of the entry (the tree's node identity). */
|
|
26
|
+
readonly path: string;
|
|
27
|
+
}
|
|
28
|
+
/** One workspace directory listing. */
|
|
29
|
+
export interface MdPreviewListResult {
|
|
30
|
+
/** The requested path as the caller spelled it (blank = workspace root). */
|
|
31
|
+
readonly path: string;
|
|
32
|
+
/** Directory entries, folders first then alphabetical. */
|
|
33
|
+
readonly entries: readonly MdPreviewEntry[];
|
|
34
|
+
}
|
|
19
35
|
/** Stable failure codes carried by `RemoteError` across the wire. */
|
|
20
36
|
export declare const MD_PREVIEW_FAILURE_CODES: readonly ["md-preview/bad-request", "md-preview/unknown-session", "md-preview/no-workspace", "md-preview/unsupported-extension", "md-preview/forbidden", "md-preview/not-found", "md-preview/too-large", "md-preview/conflict", "md-preview/unavailable"];
|
|
21
37
|
/** One stable MdPreview failure code. */
|