@typbase/codemirror 0.2.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.
@@ -0,0 +1,346 @@
1
+ import { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
2
+ import { Decoration, DecorationSet, EditorView, Tooltip, ViewPlugin, ViewUpdate, WidgetType } from "@codemirror/view";
3
+ import { EditorState, Extension, Facet, Range, StateField } from "@codemirror/state";
4
+ import { Diagnostic } from "@codemirror/lint";
5
+ import { LRUCache } from "lru-cache";
6
+ import { FileId, SvgRangedFrame, TypstDiagnostic, TypstState } from "@typbase/engine";
7
+ //#region src/notebook.d.ts
8
+ /**
9
+ * Notebook cells. A cell is a `// %%` marker comment plus the content under
10
+ * it, up to the next marker or the end of the document. Offsets are UTF-16
11
+ * and match the engine's `CellSpan`, so `extractCells` results pass through.
12
+ */
13
+ export type NotebookCellType = "markup" | "code";
14
+ export interface NotebookCell {
15
+ kind: NotebookCellType;
16
+ marker_start: number;
17
+ marker_end: number;
18
+ content_start: number;
19
+ content_end: number;
20
+ }
21
+ /** Per-cell state the host owns: run counters and visibility. */
22
+ export interface NotebookCellState {
23
+ /** Execution counter shown as `[n]`; undefined until the cell is run. */
24
+ count?: number;
25
+ /** Output hidden until the next run. */
26
+ cleared?: boolean;
27
+ /** Source hidden behind the header. */
28
+ collapsed?: boolean;
29
+ }
30
+ /** UI strings, injected by the app so the package stays i18n-free. */
31
+ export interface NotebookLabels {
32
+ run: string;
33
+ code: string;
34
+ markup: string;
35
+ moveUp: string;
36
+ moveDown: string;
37
+ duplicate: string;
38
+ remove: string;
39
+ clearOutput: string;
40
+ toggleSource: string;
41
+ noOutput: string;
42
+ error: string;
43
+ }
44
+ export interface NotebookCompileResult {
45
+ text: string;
46
+ frames: SvgRangedFrame[];
47
+ diagnostics: TypstDiagnostic[];
48
+ }
49
+ export interface NotebookOptions {
50
+ /** Cells for a document text; the host reads them from the engine. */
51
+ cells: (text: string) => NotebookCell[];
52
+ /** Run/visibility state per cell index. */
53
+ state?: (index: number) => NotebookCellState | undefined;
54
+ /** Show `[n]` execution counters. */
55
+ counters?: () => boolean;
56
+ labels?: NotebookLabels;
57
+ /** Fires whenever the extension re-extracts cells. */
58
+ onCells?: (cells: NotebookCell[]) => void;
59
+ /** Fires when the cursor moves to a different cell. */
60
+ onActiveCell?: (index: number | null) => void;
61
+ /** Fires after every compile that ran; `run` carries the requested cell. */
62
+ onRun?: (index: number | "all") => void;
63
+ /** Fires after a compile with the fresh frames and diagnostics. */
64
+ onCompile?: (result: NotebookCompileResult) => void;
65
+ onClearOutput?: (index: number) => void;
66
+ onToggleCollapse?: (index: number) => void;
67
+ /** Escape: leave edit mode and select the current cell. */
68
+ onCommandMode?: () => void;
69
+ }
70
+ /** The options of the notebook extension active in this state, if any. */
71
+ export declare const notebookOptionsFacet: Facet<NotebookOptions, NotebookOptions | undefined>;
72
+ export declare function notebookOptions(state: EditorState): NotebookOptions | undefined;
73
+ /** Re-renders notebooks from cached frames without recompiling. */
74
+ export declare const notebookRefreshEffect: import("@codemirror/state").StateEffectType<null>;
75
+ /** Asks the plugin to recompile and report the result through `onRun`. */
76
+ export declare const notebookRunEffect: import("@codemirror/state").StateEffectType<{
77
+ index: number | "all";
78
+ }>;
79
+ /** First position that belongs to the cell (marker line, or content). */
80
+ export declare function cellStart(cell: NotebookCell): number;
81
+ export declare function hasMarker(cell: NotebookCell): boolean;
82
+ /** Index of the cell containing `pos`; gaps belong to the cell above. */
83
+ export declare function cellIndexAt(cells: NotebookCell[], pos: number): number;
84
+ export declare function cellsOf(state: EditorState): NotebookCell[];
85
+ /** The marker line for a cell type. Markup is the unlabeled default. */
86
+ export declare function markerText(type: NotebookCellType): string;
87
+ /** A text replacement plus where the cursor should land after it. */
88
+ export interface CellEdit {
89
+ changes: {
90
+ from: number;
91
+ to?: number;
92
+ insert: string;
93
+ };
94
+ anchor: number;
95
+ }
96
+ export declare function insertCellText(text: string, cells: NotebookCell[], index: number, where: "above" | "below" | "end", type: NotebookCellType, content?: string): CellEdit;
97
+ export declare function duplicateCellText(text: string, cells: NotebookCell[], index: number): CellEdit;
98
+ export declare function deleteCellText(text: string, cells: NotebookCell[], index: number): CellEdit;
99
+ export declare function moveCellText(text: string, cells: NotebookCell[], index: number, delta: -1 | 1): CellEdit | null;
100
+ export declare function splitCellText(text: string, cells: NotebookCell[], index: number, pos: number): CellEdit | null;
101
+ export declare function mergeCellText(text: string, cells: NotebookCell[], index: number): CellEdit | null;
102
+ export declare function setCellTypeText(text: string, cells: NotebookCell[], index: number, type: NotebookCellType): CellEdit;
103
+ /**
104
+ * Removes `// %%` cell markers. Notebooks are comments-plus-content, so a
105
+ * cleaned file is the same document for anyone who does not know the
106
+ * convention.
107
+ */
108
+ export declare function stripCellMarkers(text: string): string;
109
+ /** Compiles and reports through `onRun`; does not move the cursor. */
110
+ export declare function runCell(view: EditorView, index: number): boolean;
111
+ export declare function runAllCells(view: EditorView): boolean;
112
+ export declare function focusCell(view: EditorView, index: number, edge?: "start" | "end"): boolean;
113
+ export declare function insertCell(view: EditorView, where: "above" | "below" | "end"): boolean;
114
+ export declare function insertCellAt(view: EditorView, index: number, where: "above" | "below" | "end"): boolean;
115
+ export declare function duplicateCell(view: EditorView): boolean;
116
+ export declare function duplicateCellAt(view: EditorView, index: number): boolean;
117
+ export declare function deleteCell(view: EditorView): boolean;
118
+ export declare function deleteCellAt(view: EditorView, index: number): boolean;
119
+ export declare function moveCell(view: EditorView, delta: -1 | 1): boolean;
120
+ export declare function moveCellAt(view: EditorView, index: number, delta: -1 | 1): boolean;
121
+ export declare function splitCell(view: EditorView): boolean;
122
+ export declare function mergeCell(view: EditorView): boolean;
123
+ export declare function toggleCellType(view: EditorView, index: number): boolean;
124
+ export declare function setCellType(view: EditorView, index: number, type: NotebookCellType): boolean;
125
+ /**
126
+ * Notebook keymap. Mounted with high precedence so Alt-ArrowUp/Down move
127
+ * cells instead of lines and Escape reaches command mode.
128
+ */
129
+ export declare const notebookKeymap: import("@codemirror/state").Extension;
130
+ //#endregion
131
+ //#region src/types.d.ts
132
+ /**
133
+ * A minimal readable text handle. Vue refs (`Ref<string>`) satisfy this shape
134
+ * structurally, so both mnemo and Typbase can pass their refs unchanged.
135
+ */
136
+ interface TextRef {
137
+ value: string;
138
+ }
139
+ /** Resolves the files a compile asked for (query JSON, embedded pages). */
140
+ type TypstRequestHandler = (requests: import("@typbase/engine").TypstRequest[], spaceId: string) => Promise<boolean> | boolean;
141
+ //#endregion
142
+ //#region src/plugin.d.ts
143
+ export interface TypstPluginOptions {
144
+ /**
145
+ * Called when Typst needs a source, file, or package that is not loaded
146
+ * yet. Return true when the request caused the world to change, so the
147
+ * editor recompiles.
148
+ */
149
+ onRequests?: TypstRequestHandler;
150
+ /** The revision of the document. */
151
+ revision?: () => string | number | undefined;
152
+ /**
153
+ * Called when a compile into the wasm instance threw. On wasm32 a panic
154
+ * aborts the instance, so the host must recreate `typstState` and remount
155
+ * the editor; the plugin drops the decorations for the failed pass.
156
+ */
157
+ onPanic?: (fileId: FileId) => void;
158
+ /** Called after a compile pass succeeds; the host resets its health and
159
+ * heap watchdog on it. */
160
+ onCompile?: () => void;
161
+ /**
162
+ * Opens a link clicked inside a rendered frame. Defaults to a new browser
163
+ * tab; the app passes its Tauri-aware `openExternal`.
164
+ */
165
+ onExternalLink?: (url: string) => void;
166
+ /**
167
+ * Cell rendering and cell commands. When set, the editor behaves like a
168
+ * notebook: markup cells render inline, code cells render below, and the
169
+ * notebook keymap takes precedence over the line editing bindings.
170
+ */
171
+ notebook?: NotebookOptions;
172
+ }
173
+ export declare const typstPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstPluginOptions) => Extension;
174
+ //#endregion
175
+ //#region src/commands.d.ts
176
+ export declare function toggleStrong(view: EditorView): boolean;
177
+ export declare function toggleEmph(view: EditorView): boolean;
178
+ export declare function toggleUnderline(view: EditorView): boolean;
179
+ export declare function toggleStrike(view: EditorView): boolean;
180
+ export declare function toggleMath(view: EditorView): boolean;
181
+ export declare function insertTabLike(view: EditorView): boolean;
182
+ export declare function toggleCode(view: EditorView): boolean;
183
+ export declare function insertFontFamily(n: EditorView, font: string): boolean;
184
+ export declare function cycleHeading(view: EditorView): boolean;
185
+ export declare function insertAtCursor(n: EditorView, e: string): void;
186
+ export declare function wrapOrInsert(view: EditorView, prefix: string, suffix: string, insert: string): void;
187
+ interface Replacement {
188
+ regex: RegExp;
189
+ replacement: string;
190
+ }
191
+ export declare function toggleAroundSelection(view: EditorView, prefixes: (string | Replacement)[], suffixes: (string | Replacement)[], preferNextLevel?: boolean): null;
192
+ export declare function toggleList(n: EditorView): boolean;
193
+ export declare function toggleEnum(n: EditorView): boolean;
194
+ export declare function toggleListLike(view: EditorView, prefix: string): void;
195
+ export declare function cursorAddVertical(view: EditorView, offset: number): boolean;
196
+ //#endregion
197
+ //#region src/diagnostics.d.ts
198
+ export declare function rememberDiagnostics(path: string, text: string, diagnostics: TypstDiagnostic[]): void;
199
+ /** Converts engine diagnostics into CodeMirror lint diagnostics. */
200
+ export declare function toLintDiagnostics(typstDiagnostics: TypstDiagnostic[]): Diagnostic[];
201
+ export interface TypstLinterOptions {
202
+ onRequests?: TypstRequestHandler;
203
+ onPanic?: (fileId: FileId) => void;
204
+ /** Called after a diagnostics compile succeeds. */
205
+ onCompile?: () => void;
206
+ }
207
+ /**
208
+ * Typst diagnostics as a CodeMirror linter source.
209
+ *
210
+ * This runs in every editor mode and combines with other sources (the
211
+ * spellcheck linter), so neither one replaces the other. The WYSIWYG plugin's
212
+ * compile feeds the cache; split and source mode fall back to a compile here
213
+ * so they get diagnostics too.
214
+ */
215
+ export declare const typstLinter: (fileId: FileId, spaceId: string, path: string, prelude: TextRef, typstState: TypstState, options?: TypstLinterOptions) => import("@codemirror/state").Extension;
216
+ //#endregion
217
+ //#region src/frames.d.ts
218
+ /**
219
+ * Opens an external link for the host. Browsers get a new tab; the app passes
220
+ * its `openExternal`, which hands the URL to the system browser in Tauri
221
+ * (a webview has no tab strip, so `window.open` is dropped there).
222
+ */
223
+ export type ExternalLinkOpener = (url: string) => void;
224
+ /**
225
+ * The compiled size of an SVG frame, from the markup's viewBox. The viewBox
226
+ * is the page width the engine laid out at (pt), and the app renders one
227
+ * Typst point per CSS pixel, so the numbers map to px directly.
228
+ *
229
+ * `frame.render.width` is the chunk's bounding-box width, which does not
230
+ * change with the pane for fixed-size blocks (images, boxes). The viewBox
231
+ * width is the correct resize key and the size to pin: a render laid out
232
+ * for a wider pane must keep its size, not be stretched by CSS while a
233
+ * resize is in flight.
234
+ */
235
+ export declare function frameSize(frame: SvgRangedFrame): {
236
+ width: number;
237
+ height: number;
238
+ };
239
+ /**
240
+ * Pins a container's SVG to the compiled frame size (via CSS variables). The
241
+ * container keeps max-width: 100% so it never exceeds the line. An explicit
242
+ * container width would make CodeMirror's flex layout grow the content width
243
+ * forever (resize -> wider widget -> wider content). The pinned SVG overflows
244
+ * the clamped container while the pane is narrower than the compiled width;
245
+ * the scroller clips it, so the render stays its size instead of scaling.
246
+ */
247
+ export declare function syncFrameContainer(container: HTMLElement, frame: SvgRangedFrame): void;
248
+ /** Fresh frame container for widgets that own their DOM (notebook outputs). */
249
+ export declare function createFrameContainer(frame: SvgRangedFrame): HTMLElement;
250
+ /**
251
+ * Click handling shared by inline widgets and notebook outputs: typbase://
252
+ * links are left for the host's anchor router, external links confirm first
253
+ * and go through `openExternal`, anything else maps back into the compiled
254
+ * document and moves the cursor. Alt-click edits the link instead of
255
+ * following it.
256
+ */
257
+ export declare function attachFrameInteractions(container: HTMLElement, view: EditorView, frame: SvgRangedFrame, fileId: FileId, typstState: TypstState, openExternal?: ExternalLinkOpener): void;
258
+ /**
259
+ * True when the selection does not touch `start..end`, so the frame can render
260
+ * as a widget instead of showing source. Shared by the inline WYSIWYG pass and
261
+ * the notebook markup cells.
262
+ */
263
+ export declare function frameIsInactive(view: EditorView, state: EditorState, start: number, end: number): boolean;
264
+ /**
265
+ * Line decorations that stand in for a frame while the cursor is inside it:
266
+ * the source stays visible with the frame's height reserved, so the pane does
267
+ * not jump between render and source. Matches the inline WYSIWYG behavior.
268
+ *
269
+ * `lineHeights` carries measured source heights from the remeasure pass; when
270
+ * it is absent the view still reports the widget's height for those lines.
271
+ */
272
+ export declare function frameActiveDecorations(view: EditorView, state: EditorState, frame: SvgRangedFrame, lineHeights?: Map<number, number>): Range<Decoration>[];
273
+ export declare class TypstWidget extends WidgetType {
274
+ private readonly view;
275
+ private readonly frame;
276
+ private readonly locked;
277
+ private readonly fileId;
278
+ private readonly typstState;
279
+ private readonly openExternal?;
280
+ private container;
281
+ private readonly size;
282
+ constructor(view: EditorView, frame: SvgRangedFrame, locked: boolean, fileId: FileId, typstState: TypstState, openExternal?: ExternalLinkOpener | undefined);
283
+ eq(other: TypstWidget): boolean;
284
+ toDOM(): HTMLElement;
285
+ get estimatedHeight(): number;
286
+ }
287
+ //#endregion
288
+ //#region src/highlight.d.ts
289
+ export declare const typstSyntaxHighlighting: (fileId: FileId, typstState: TypstState) => StateField<DecorationSet>;
290
+ export declare const parseBackticks: (str: string, into: HTMLElement) => void;
291
+ //#endregion
292
+ //#region src/hover.d.ts
293
+ export declare const typstHoverTooltip: (fileId: FileId, typstState: TypstState) => import("@codemirror/state").Extension & {
294
+ active: import("@codemirror/state").StateField<readonly import("@codemirror/view").Tooltip[]>;
295
+ };
296
+ //#endregion
297
+ //#region src/keymap.d.ts
298
+ export declare const typstKeymap: import("@codemirror/state").Extension;
299
+ //#endregion
300
+ //#region src/language.d.ts
301
+ export declare function autocomplete(context: CompletionContext, fileId: FileId, typstState: TypstState): Promise<CompletionResult | null>;
302
+ export declare const typstLanguageData: import("@codemirror/state").Extension;
303
+ //#endregion
304
+ //#region src/static-highlight.d.ts
305
+ export declare const typstStaticHighlighting: StateField<DecorationSet>;
306
+ //#endregion
307
+ //#region src/tooltip.d.ts
308
+ export declare const tooltipStateField: StateField<Tooltip | null>;
309
+ export declare const tooltipViewPlugin: () => ViewPlugin<{
310
+ update(update: ViewUpdate): void;
311
+ }, undefined>;
312
+ //#endregion
313
+ //#region src/widgets.d.ts
314
+ export declare const compileCache: LRUCache<string, {
315
+ frames: SvgRangedFrame[];
316
+ tooltips: SvgRangedFrame[];
317
+ diagnostics: TypstDiagnostic[];
318
+ }, unknown>;
319
+ /**
320
+ * Dispatch this to recompile even when the document did not change. Used when
321
+ * app data changed (fonts installed, workspace data, query results).
322
+ */
323
+ export declare const typstRecompileEffect: import("@codemirror/state").StateEffectType<null>;
324
+ export declare const tooltipsStateEffect: import("@codemirror/state").StateEffectType<SvgRangedFrame[]>;
325
+ export declare const tooltipsStateField: StateField<SvgRangedFrame[]>;
326
+ export declare const typstStateField: StateField<DecorationSet>;
327
+ export interface TypstViewPluginOptions {
328
+ onRequests?: TypstRequestHandler;
329
+ /** Extra component of the compile cache key: app data revisions. */
330
+ revision?: () => string | number | undefined;
331
+ /** See TypstPluginOptions#onPanic. */
332
+ onPanic?: (fileId: FileId) => void;
333
+ /** Called after a compile pass succeeds; the host resets its health and
334
+ * heap watchdog on it. */
335
+ onCompile?: () => void;
336
+ /** See TypstPluginOptions#onExternalLink. */
337
+ onExternalLink?: ExternalLinkOpener;
338
+ /** Cell rendering, run effects, and cell commands for notebook mode. */
339
+ notebook?: NotebookOptions;
340
+ }
341
+ export declare const typstViewPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstViewPluginOptions) => ViewPlugin<{
342
+ update(update: ViewUpdate): void;
343
+ destroy(): void;
344
+ }, undefined>;
345
+ //#endregion
346
+ export type { TextRef, TypstRequestHandler };