@benz-ai-x/dsh-md-preview 0.4.0 → 0.7.1

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.
@@ -1,10 +1,12 @@
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. */
7
7
  sessionId: SessionId;
8
+ /** Whether the browse face is showing (refreshes revalidate on entry). */
9
+ active: boolean;
8
10
  /** One directory listing; the transport carries the AbortSignal. */
9
11
  list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<RemoteResult<MdPreviewListResult>>;
10
12
  /** Open one file as the panel's preview target. */
@@ -14,10 +16,21 @@ export interface WorkspaceBrowserProps {
14
16
  /** Locale seat. */
15
17
  t(key: string): string;
16
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[];
17
30
  /**
18
31
  * Render the workspace tree for one session.
19
32
  * @param props - session identity, listing RPC, file-open handoff, locale seat.
20
33
  * @returns the tree element.
21
34
  */
22
- export declare function WorkspaceBrowser({ sessionId, list, onOpenFile, currentPath, t }: WorkspaceBrowserProps): import("react").JSX.Element;
35
+ export declare function WorkspaceBrowser({ sessionId, active, list, onOpenFile, currentPath, t }: WorkspaceBrowserProps): import("react").JSX.Element;
23
36
  //# 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,17 @@
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
+ }
1
15
  /** Props the panel hands to the editor. */
2
16
  export interface MarkdownEditorProps {
3
17
  /** Document text at edit-session start; a changed value remounts the editor. */
@@ -6,11 +20,23 @@ export interface MarkdownEditorProps {
6
20
  onChange: (value: string) => void;
7
21
  /** Cmd/Ctrl-S from the editor's keymap. */
8
22
  onSave: () => void;
23
+ /** Reports the mounted editor view (null on unmount) for panel-side calls. */
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;
9
35
  }
10
36
  /**
11
37
  * Render one CodeMirror editor bound to the panel's edit session.
12
- * @param props - initial document plus change and save callbacks.
38
+ * @param props - initial document plus change, save, and view callbacks.
13
39
  * @returns the editor host element.
14
40
  */
15
- export declare function MarkdownEditor({ initialValue, onChange, onSave }: MarkdownEditorProps): import("react").JSX.Element;
41
+ export declare function MarkdownEditor({ initialValue, onChange, onSave, onView, onCursorLine, onStatus, onOpenKeys, searchPhrases, onSearchStatus }: MarkdownEditorProps): import("react").JSX.Element;
16
42
  //# sourceMappingURL=editor.d.ts.map
@@ -11,8 +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;
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;
16
38
  'panel.saved': string;
17
39
  'panel.saveError': string;
18
40
  'panel.save.retry': string;
@@ -28,6 +50,25 @@ export declare const zh: {
28
50
  'browse.empty': string;
29
51
  'browse.error': string;
30
52
  'browse.retry': string;
53
+ 'browse.refresh': string;
54
+ 'browse.filter': string;
55
+ 'browse.noMatch': string;
56
+ 'rail.files': string;
57
+ 'rail.outline': string;
58
+ 'rail.noHeadings': string;
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;
71
+ 'diagram.error': string;
31
72
  'chip.preview': string;
32
73
  'chip.open': string;
33
74
  'action.label': string;
@@ -0,0 +1,45 @@
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
+ /**
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;
45
+ //# sourceMappingURL=outline.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benz-ai-x/dsh-md-preview",
3
- "version": "0.4.0",
3
+ "version": "0.7.1",
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": {
@@ -13,9 +13,16 @@
13
13
  "keywords": [
14
14
  "deepseek-harness",
15
15
  "dsh",
16
- "plugin",
16
+ "dsh-plugin",
17
+ "cordis",
17
18
  "markdown",
18
- "preview"
19
+ "markdown-preview",
20
+ "markdown-editor",
21
+ "codemirror",
22
+ "file-browser",
23
+ "workspace",
24
+ "preview-panel",
25
+ "react"
19
26
  ],
20
27
  "type": "module",
21
28
  "main": "./lib/index.js",
@@ -42,7 +49,8 @@
42
49
  "lib/typert/remote-client.js",
43
50
  "lib/types/**/*.d.ts",
44
51
  "cordis.patch.yml",
45
- "README.md"
52
+ "README.md",
53
+ "README.zh.md"
46
54
  ],
47
55
  "dsh": {
48
56
  "bundle": {
@@ -65,7 +73,6 @@
65
73
  "scripts": {
66
74
  "context:check": "node scripts/verify-dsh-context.mjs",
67
75
  "context:check:strict": "node scripts/verify-dsh-context.mjs --require-source",
68
- "context:sync": "node scripts/verify-dsh-context.mjs --sync-links --require-source && pnpm install --no-frozen-lockfile",
69
76
  "typecheck": "tsc -p tsconfig.json --noEmit",
70
77
  "test": "vitest run",
71
78
  "build": "tsc -p tsconfig.json && tsdown",
@@ -75,13 +82,17 @@
75
82
  "built:check": "node scripts/verify-built.mjs",
76
83
  "pack:publishable": "node scripts/pack.mjs",
77
84
  "publish:registry": "node scripts/pack.mjs --publish",
78
- "verify": "pnpm context:check:strict && pnpm typecheck && pnpm test && pnpm build && pnpm built:check"
85
+ "verify": "pnpm context:check:strict && pnpm typecheck && pnpm test && pnpm build && pnpm built:check",
86
+ "prepare": "node scripts/prepare.mjs",
87
+ "context:link": "node scripts/verify-dsh-context.mjs --sync-links --require-source && pnpm install --no-frozen-lockfile"
79
88
  },
80
89
  "dependencies": {
81
- "@deepseek-ai/schemastery": "3.18.1",
90
+ "@deepseek-ai/schemastery": "3.18.2",
91
+ "tsdown": "^0.22.2",
92
+ "typescript": "6.0.3",
82
93
  "zod": "^4.4.3"
83
94
  },
84
95
  "peerDependencies": {
85
- "@deepseek-ai/dsh-typert-protocol": "0.1.2-alpha.3"
96
+ "@deepseek-ai/dsh-typert-protocol": "0.1.2-rc.1"
86
97
  }
87
98
  }