@benz-ai-x/dsh-md-preview 0.6.0 → 0.7.2
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 +4 -0
- package/README.zh.md +4 -0
- package/lib/client.js +524 -333
- package/lib/types/client/FileManagerAction.d.ts +31 -0
- package/lib/types/client/SideBrowser.d.ts +43 -0
- package/lib/types/client/WorkspaceBrowser.d.ts +12 -1
- package/lib/types/client/WorkspaceDocsAction.d.ts +23 -0
- package/lib/types/client/WorkspaceDocsDock.d.ts +40 -0
- package/lib/types/client/WorkspaceDocsView.d.ts +29 -0
- package/lib/types/client/editor.d.ts +24 -1
- package/lib/types/client/locale.d.ts +38 -0
- package/lib/types/client/outline.d.ts +16 -0
- package/lib/types/client/preview-state.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The header file-manager action: a collapse/expand button in the
|
|
3
|
+
* conversation header that opens a workspace file-tree popover. Opening a
|
|
4
|
+
* file hands it to the right preview panel; the popover stays open for
|
|
5
|
+
* further picks. jsdom coverage asserts content and behavior, not layout
|
|
6
|
+
* (no layout engine there).
|
|
7
|
+
*/
|
|
8
|
+
import { type ReactElement } from 'react';
|
|
9
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
10
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
11
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
12
|
+
import type { MdPreviewListResult } from '../protocol.ts';
|
|
13
|
+
import type { MdPreviewState } from './preview-state.ts';
|
|
14
|
+
/** The composed props of the header action: slot kit + inject face + locale. */
|
|
15
|
+
export type FileManagerActionProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<{
|
|
16
|
+
hooks: {
|
|
17
|
+
previewTarget: SnapshotStore<MdPreviewState>;
|
|
18
|
+
};
|
|
19
|
+
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewListResult>>;
|
|
20
|
+
setTarget(target: {
|
|
21
|
+
sessionId: SessionId;
|
|
22
|
+
path: string;
|
|
23
|
+
} | null): void;
|
|
24
|
+
}> & PropsLocale<'md-preview'>;
|
|
25
|
+
/**
|
|
26
|
+
* Render the header file-manager button and its popover for one session.
|
|
27
|
+
* @param props - the composed action props.
|
|
28
|
+
* @returns the trigger button (popover renders beside it in the panel tree).
|
|
29
|
+
*/
|
|
30
|
+
export declare function FileManagerAction(props: FileManagerActionProps): ReactElement;
|
|
31
|
+
//# sourceMappingURL=FileManagerAction.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The left-edge document browser: a collapse-style strip hugging the
|
|
3
|
+
* conversation's left boundary (the app sidebar's right edge) that expands
|
|
4
|
+
* into the session workspace tree. Opening a file hands it to the right
|
|
5
|
+
* preview panel — left browser picks, right panel reads. The strip is
|
|
6
|
+
* driven by a session probe: a null-rendering composer-dock entry that
|
|
7
|
+
* publishes which conversation is showing.
|
|
8
|
+
*/
|
|
9
|
+
import { type ReactElement } from 'react';
|
|
10
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
11
|
+
import type { MdPreviewListResult } from '../protocol.ts';
|
|
12
|
+
/**
|
|
13
|
+
* Publishes one conversation's session while that conversation shows.
|
|
14
|
+
* Renders nothing; the activate/deactivate pair comes from the slot's
|
|
15
|
+
* session-scoped inject closure.
|
|
16
|
+
*/
|
|
17
|
+
export declare function SessionProbe(props: {
|
|
18
|
+
activate(): void;
|
|
19
|
+
deactivate(): void;
|
|
20
|
+
}): null;
|
|
21
|
+
/** The composed props of the side browser entry: stores + RPC + locale. */
|
|
22
|
+
export interface SideBrowserProps {
|
|
23
|
+
/** Selector hook over the conversation probe's session (null without one). */
|
|
24
|
+
useCurrentSession(selector: (state: unknown) => unknown): unknown;
|
|
25
|
+
/** Selector hook over the preview target (for the current-file mark). */
|
|
26
|
+
usePreviewTarget(selector: (state: unknown) => unknown): unknown;
|
|
27
|
+
/** One directory listing; the transport carries the AbortSignal. */
|
|
28
|
+
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewListResult>>;
|
|
29
|
+
/** Open one file in the right preview panel. */
|
|
30
|
+
setTarget(target: {
|
|
31
|
+
sessionId: SessionId;
|
|
32
|
+
path: string;
|
|
33
|
+
} | null): void;
|
|
34
|
+
/** Locale seat. */
|
|
35
|
+
t(key: string): string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Render the left-edge strip and, expanded, the workspace tree.
|
|
39
|
+
* @param props - stores, listing RPC, panel handoff, locale seat.
|
|
40
|
+
* @returns the side browser, or null while no conversation shows.
|
|
41
|
+
*/
|
|
42
|
+
export declare function SideBrowser({ useCurrentSession, usePreviewTarget, list, setTarget, t }: SideBrowserProps): ReactElement | null;
|
|
43
|
+
//# sourceMappingURL=SideBrowser.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
2
2
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
-
import type { MdPreviewListResult } from '../protocol.ts';
|
|
3
|
+
import type { MdPreviewEntry, MdPreviewListResult } from '../protocol.ts';
|
|
4
4
|
/** Listing RPC and the file-open handoff, created in the plugin's apply world. */
|
|
5
5
|
export interface WorkspaceBrowserProps {
|
|
6
6
|
/** Owning session whose workspace the tree roots at. */
|
|
@@ -16,6 +16,17 @@ export interface WorkspaceBrowserProps {
|
|
|
16
16
|
/** Locale seat. */
|
|
17
17
|
t(key: string): string;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Entries visible under a filter query (#13): a name match, or a loaded
|
|
21
|
+
* descendant match, keeps an entry. A name-matched directory keeps its
|
|
22
|
+
* whole subtree (the caller renders children unfiltered from there).
|
|
23
|
+
* @param entries - one directory level, in listing order.
|
|
24
|
+
* @param query - the raw filter text; blank shows everything.
|
|
25
|
+
* @param childrenOf - resolves a loaded directory's entries (undefined
|
|
26
|
+
* while unloaded or failed).
|
|
27
|
+
* @returns the entries this level should render.
|
|
28
|
+
*/
|
|
29
|
+
export declare function filterEntries(entries: readonly MdPreviewEntry[], query: string, childrenOf: (path: string) => readonly MdPreviewEntry[] | undefined): readonly MdPreviewEntry[];
|
|
19
30
|
/**
|
|
20
31
|
* Render the workspace tree for one session.
|
|
21
32
|
* @param props - session identity, listing RPC, file-open handoff, locale seat.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The header browse action: a file-tree button in the conversation header
|
|
3
|
+
* that opens the right preview panel on its browse face — the workspace
|
|
4
|
+
* tree shows first, and opening a file reads it in the document face.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactElement } from 'react';
|
|
7
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
8
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
9
|
+
/** The composed props of the header action: slot kit + inject face + locale. */
|
|
10
|
+
export type WorkspaceDocsActionProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<{
|
|
11
|
+
setTarget(target: {
|
|
12
|
+
sessionId: SessionId;
|
|
13
|
+
path: string;
|
|
14
|
+
face: 'browse';
|
|
15
|
+
}): void;
|
|
16
|
+
}> & PropsLocale<'md-preview'>;
|
|
17
|
+
/**
|
|
18
|
+
* Render the header browse button for one session.
|
|
19
|
+
* @param props - the composed action props.
|
|
20
|
+
* @returns the header button.
|
|
21
|
+
*/
|
|
22
|
+
export declare function WorkspaceDocsAction(props: WorkspaceDocsActionProps): ReactElement;
|
|
23
|
+
//# sourceMappingURL=WorkspaceDocsAction.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composer-dock entry: opens the preview panel on the session's
|
|
3
|
+
* workspace without waiting for a turn that produced markdown — the dock
|
|
4
|
+
* button lists the root, picks its first previewable file, and sets the
|
|
5
|
+
* preview target; an empty root shows a transient hint instead.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactElement } from 'react';
|
|
8
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
9
|
+
import type { MdPreviewEntry } from '../protocol.ts';
|
|
10
|
+
/**
|
|
11
|
+
* The first previewable file of a root listing.
|
|
12
|
+
* @param entries - one directory level, in listing order.
|
|
13
|
+
* @returns its workspace-relative path, or null when nothing previews.
|
|
14
|
+
*/
|
|
15
|
+
export declare function firstPreviewablePath(entries: readonly MdPreviewEntry[]): string | null;
|
|
16
|
+
/** Props: the mount-bound open action plus the dock's locale seat. */
|
|
17
|
+
export interface WorkspaceDocsDockProps {
|
|
18
|
+
/** Lists the workspace root and opens the first previewable file.
|
|
19
|
+
* Resolves 'none' when the root has nothing previewable. */
|
|
20
|
+
openWorkspace: () => Promise<'opened' | 'none'>;
|
|
21
|
+
/** Locale seat. */
|
|
22
|
+
t(key: string): string;
|
|
23
|
+
}
|
|
24
|
+
/** The registered header action: session slot kit + injected face + locale. */
|
|
25
|
+
export type WorkspaceDocsDockActionProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<{
|
|
26
|
+
openWorkspace: () => Promise<'opened' | 'none'>;
|
|
27
|
+
}> & PropsLocale<'md-preview'>;
|
|
28
|
+
/**
|
|
29
|
+
* Bind the slot's injected face into the presentational entry.
|
|
30
|
+
* @param props - the header action's composed props.
|
|
31
|
+
* @returns the header entry element.
|
|
32
|
+
*/
|
|
33
|
+
export declare function WorkspaceDocsDockAction(props: WorkspaceDocsDockActionProps): ReactElement;
|
|
34
|
+
/**
|
|
35
|
+
* Render the dock entry for one session's workspace.
|
|
36
|
+
* @param props - the bound open action and locale seat.
|
|
37
|
+
* @returns the entry button (or its transient empty hint).
|
|
38
|
+
*/
|
|
39
|
+
export declare function WorkspaceDocsDock({ openWorkspace, t }: WorkspaceDocsDockProps): import("react").JSX.Element;
|
|
40
|
+
//# sourceMappingURL=WorkspaceDocsDock.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 文档 conversation view: the session workspace tree rendered inside
|
|
3
|
+
* the conversation area as a view tab (beside 对话/轨迹). Opening a file
|
|
4
|
+
* sets the preview target — the docked panel takes it from there.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactElement } from 'react';
|
|
7
|
+
import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
8
|
+
import type { InjectFace, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
9
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
10
|
+
import type { MdPreviewState } from './preview-state.ts';
|
|
11
|
+
import type { MdPreviewListResult } from '../protocol.ts';
|
|
12
|
+
/** The composed props of the docs view tab: session kit + inject face + locale. */
|
|
13
|
+
export type WorkspaceDocsViewProps = ConvViewProps & InjectFace<{
|
|
14
|
+
hooks: {
|
|
15
|
+
previewTarget: SnapshotStore<MdPreviewState>;
|
|
16
|
+
};
|
|
17
|
+
list(sessionId: string, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewListResult>>;
|
|
18
|
+
setTarget(target: {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
path: string;
|
|
21
|
+
} | null): void;
|
|
22
|
+
}> & PropsLocale<'md-preview'>;
|
|
23
|
+
/**
|
|
24
|
+
* Render the docs view tab body for one session.
|
|
25
|
+
* @param props - the view's composed props.
|
|
26
|
+
* @returns the workspace tree element.
|
|
27
|
+
*/
|
|
28
|
+
export declare function WorkspaceDocsView({ sessionId, usePreviewTarget, list, setTarget, t }: WorkspaceDocsViewProps): ReactElement;
|
|
29
|
+
//# sourceMappingURL=WorkspaceDocsView.d.ts.map
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { EditorView } from '@codemirror/view';
|
|
2
|
+
/** What the find chip shows: total matches and the current one (1-based). */
|
|
3
|
+
export interface SearchStatus {
|
|
4
|
+
readonly count: number;
|
|
5
|
+
readonly index: number;
|
|
6
|
+
}
|
|
7
|
+
/** What the edit status bar shows (#15), plus history availability. */
|
|
8
|
+
export interface EditorStatus {
|
|
9
|
+
readonly line: number;
|
|
10
|
+
readonly col: number;
|
|
11
|
+
readonly chars: number;
|
|
12
|
+
readonly canUndo: boolean;
|
|
13
|
+
readonly canRedo: boolean;
|
|
14
|
+
}
|
|
2
15
|
/** Props the panel hands to the editor. */
|
|
3
16
|
export interface MarkdownEditorProps {
|
|
4
17
|
/** Document text at edit-session start; a changed value remounts the editor. */
|
|
@@ -9,11 +22,21 @@ export interface MarkdownEditorProps {
|
|
|
9
22
|
onSave: () => void;
|
|
10
23
|
/** Reports the mounted editor view (null on unmount) for panel-side calls. */
|
|
11
24
|
onView?: (view: EditorView | null) => void;
|
|
25
|
+
/** Reports the cursor's 1-based line at mount and on doc/selection change. */
|
|
26
|
+
onCursorLine?: (line: number) => void;
|
|
27
|
+
/** Status-bar payload at mount and on doc/selection/history change; null on unmount. */
|
|
28
|
+
onStatus?: (status: EditorStatus | null) => void;
|
|
29
|
+
/** Opens the panel's keymap help (bound to Mod-/ inside the editor). */
|
|
30
|
+
onOpenKeys?: () => void;
|
|
31
|
+
/** Search panel localization: CM stock phrase key → panel word. */
|
|
32
|
+
searchPhrases?: Readonly<Record<string, string>>;
|
|
33
|
+
/** Match count and 1-based current index; null while search is inactive. */
|
|
34
|
+
onSearchStatus?: (status: SearchStatus | null) => void;
|
|
12
35
|
}
|
|
13
36
|
/**
|
|
14
37
|
* Render one CodeMirror editor bound to the panel's edit session.
|
|
15
38
|
* @param props - initial document plus change, save, and view callbacks.
|
|
16
39
|
* @returns the editor host element.
|
|
17
40
|
*/
|
|
18
|
-
export declare function MarkdownEditor({ initialValue, onChange, onSave, onView }: MarkdownEditorProps): import("react").JSX.Element;
|
|
41
|
+
export declare function MarkdownEditor({ initialValue, onChange, onSave, onView, onCursorLine, onStatus, onOpenKeys, searchPhrases, onSearchStatus }: MarkdownEditorProps): import("react").JSX.Element;
|
|
19
42
|
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -11,9 +11,30 @@ export declare const zh: {
|
|
|
11
11
|
'panel.unsupported': string;
|
|
12
12
|
'panel.retry': string;
|
|
13
13
|
'panel.edit': string;
|
|
14
|
+
'panel.view': string;
|
|
15
|
+
'panel.face': string;
|
|
14
16
|
'panel.save': string;
|
|
15
17
|
'panel.cancel': string;
|
|
16
18
|
'panel.find': string;
|
|
19
|
+
'panel.undo': string;
|
|
20
|
+
'panel.redo': string;
|
|
21
|
+
'status.chars': string;
|
|
22
|
+
'status.saved': string;
|
|
23
|
+
'status.unsaved': string;
|
|
24
|
+
'status.clean': string;
|
|
25
|
+
'panel.keys': string;
|
|
26
|
+
'keys.bold': string;
|
|
27
|
+
'keys.italic': string;
|
|
28
|
+
'keys.link': string;
|
|
29
|
+
'keys.find': string;
|
|
30
|
+
'keys.save': string;
|
|
31
|
+
'keys.undo': string;
|
|
32
|
+
'keys.outline': string;
|
|
33
|
+
'keys.files': string;
|
|
34
|
+
'keys.help': string;
|
|
35
|
+
'keys.dismiss': string;
|
|
36
|
+
'warn.html': string;
|
|
37
|
+
'warn.dismiss': string;
|
|
17
38
|
'panel.saved': string;
|
|
18
39
|
'panel.saveError': string;
|
|
19
40
|
'panel.save.retry': string;
|
|
@@ -30,11 +51,28 @@ export declare const zh: {
|
|
|
30
51
|
'browse.error': string;
|
|
31
52
|
'browse.retry': string;
|
|
32
53
|
'browse.refresh': string;
|
|
54
|
+
'browse.filter': string;
|
|
55
|
+
'browse.noMatch': string;
|
|
56
|
+
'rail.files': string;
|
|
57
|
+
'rail.outline': string;
|
|
58
|
+
'rail.noHeadings': string;
|
|
33
59
|
'outline.open': string;
|
|
60
|
+
'find.status': string;
|
|
61
|
+
'find.phrases.find': string;
|
|
62
|
+
'find.phrases.replace': string;
|
|
63
|
+
'find.phrases.next': string;
|
|
64
|
+
'find.phrases.previous': string;
|
|
65
|
+
'find.phrases.all': string;
|
|
66
|
+
'find.phrases.matchCase': string;
|
|
67
|
+
'find.phrases.regexp': string;
|
|
68
|
+
'find.phrases.byWord': string;
|
|
69
|
+
'find.phrases.replaceAll': string;
|
|
70
|
+
'find.phrases.close': string;
|
|
34
71
|
'diagram.error': string;
|
|
35
72
|
'chip.preview': string;
|
|
36
73
|
'chip.open': string;
|
|
37
74
|
'action.label': string;
|
|
75
|
+
'dock.browse': string;
|
|
38
76
|
'action.open': string;
|
|
39
77
|
copy: string;
|
|
40
78
|
copied: string;
|
|
@@ -26,4 +26,20 @@ export declare function extractOutline(content: string): readonly OutlineEntry[]
|
|
|
26
26
|
* document spells it differently (setext forms the source scan skips).
|
|
27
27
|
*/
|
|
28
28
|
export declare function findHeadingElement(container: ParentNode | null, entries: readonly OutlineEntry[], index: number): HTMLElement | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The outline entry a source position falls under: the last entry whose
|
|
31
|
+
* 1-based line is at or above it.
|
|
32
|
+
* @param entries - the outline in document order.
|
|
33
|
+
* @param line - the 1-based source line of the position.
|
|
34
|
+
* @returns the owning entry's index, or -1 above the first heading.
|
|
35
|
+
*/
|
|
36
|
+
export declare function activeIndexForLine(entries: readonly OutlineEntry[], line: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* The outline entry a scroll position falls under: the last heading whose
|
|
39
|
+
* document offset is at or above the scroll position.
|
|
40
|
+
* @param tops - each heading's offset from the top of the scrolled document.
|
|
41
|
+
* @param scrollTop - the scroller's current offset.
|
|
42
|
+
* @returns the active entry's index, or -1 above the first heading.
|
|
43
|
+
*/
|
|
44
|
+
export declare function activeIndexForScroll(tops: readonly number[], scrollTop: number): number;
|
|
29
45
|
//# sourceMappingURL=outline.d.ts.map
|
|
@@ -4,6 +4,8 @@ import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
|
4
4
|
export interface MdPreviewTarget {
|
|
5
5
|
readonly sessionId: SessionId;
|
|
6
6
|
readonly path: string;
|
|
7
|
+
/** Entry face for the panel (default 'document'); 'browse' opens on the tree. */
|
|
8
|
+
readonly face?: 'document' | 'browse';
|
|
7
9
|
}
|
|
8
10
|
/** Whole preview panel state: the current target or the closed state. */
|
|
9
11
|
export type MdPreviewState = MdPreviewTarget | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benz-ai-x/dsh-md-preview",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "DSH markdown preview: clicking a markdown document in the conversation opens a rendered preview panel docked to the right of the chat.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|