@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.
- package/LICENSE +661 -0
- package/dist/index.d.mts +346 -0
- package/dist/index.mjs +2110 -0
- package/package.json +48 -0
package/dist/index.d.mts
ADDED
|
@@ -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 };
|