@typbase/codemirror 0.3.2 → 0.4.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.
Files changed (4) hide show
  1. package/LICENSE +190 -661
  2. package/dist/index.d.mts +135 -65
  3. package/dist/index.mjs +648 -387
  4. package/package.json +3 -3
package/dist/index.d.mts CHANGED
@@ -5,41 +5,63 @@ import { Diagnostic } from "@codemirror/lint";
5
5
  import { LRUCache } from "lru-cache";
6
6
  import { FileId, SvgRangedFrame, TypstDiagnostic, TypstState } from "@typbase/engine";
7
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";
8
+ export type NotebookCellType = "prose" | "code" | "log" | "hidden";
9
+ /** Every type, in the order the menu lists them. */
10
+ export declare const NOTEBOOK_CELL_TYPES: readonly NotebookCellType[];
11
+ /** True when the cell renders in place rather than showing source plus output. */
12
+ export declare function rendersInPlace(kind: NotebookCellType): boolean;
13
+ /** True when the cell's source is not part of what the reader sees. */
14
+ export declare function hidesSource(kind: NotebookCellType): boolean;
15
+ /** True when the cell has an output area below its source. */
16
+ export declare function hasOutput(kind: NotebookCellType): boolean;
14
17
  export interface NotebookCell {
15
18
  kind: NotebookCellType;
19
+ /** `name=` from the attribute line, when it carries one. */
20
+ name?: string | null;
16
21
  marker_start: number;
17
22
  marker_end: number;
18
23
  content_start: number;
19
24
  content_end: number;
20
25
  }
21
- /** Per-cell state the host owns: run counters and visibility. */
22
26
  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
27
  /** Source hidden behind the header. */
28
28
  collapsed?: boolean;
29
+ /**
30
+ * Keep the output this cell had when it was held. For the cells where a live
31
+ * render is wrong or expensive: a heavy query, a non-deterministic one, one
32
+ * with a side effect. See the note in `NotebookOptions.onCompile`.
33
+ */
34
+ held?: boolean;
35
+ /** The held cell's last output, kept by the host. */
36
+ frozen?: NotebookCellOutput;
37
+ /** Output hidden until the cell is refreshed. */
38
+ cleared?: boolean;
39
+ }
40
+ /** One cell's rendered output: its frames and the diagnostics inside it. */
41
+ export interface NotebookCellOutput {
42
+ frames: SvgRangedFrame[];
43
+ diagnostics: TypstDiagnostic[];
29
44
  }
30
45
  /** UI strings, injected by the app so the package stays i18n-free. */
31
46
  export interface NotebookLabels {
32
- run: string;
33
47
  code: string;
34
- markup: string;
48
+ prose: string;
49
+ log: string;
50
+ hidden: string;
51
+ menu: string;
52
+ split: string;
53
+ merge: string;
35
54
  moveUp: string;
36
55
  moveDown: string;
37
56
  duplicate: string;
38
57
  remove: string;
58
+ copy: string;
59
+ hold: string;
60
+ release: string;
39
61
  clearOutput: string;
40
62
  toggleSource: string;
41
63
  noOutput: string;
42
- error: string;
64
+ held: string;
43
65
  }
44
66
  export interface NotebookCompileResult {
45
67
  text: string;
@@ -49,41 +71,47 @@ export interface NotebookCompileResult {
49
71
  export interface NotebookOptions {
50
72
  /** Cells for a document text. The host reads them from the engine. */
51
73
  cells: (text: string) => NotebookCell[];
52
- /** Run/visibility state per cell index. */
74
+ /** Per-cell state. The host owns it. */
53
75
  state?: (index: number) => NotebookCellState | undefined;
54
- /** Show `[n]` execution counters. */
55
- counters?: () => boolean;
56
76
  labels?: NotebookLabels;
57
77
  /** Fires whenever the extension re-extracts cells. */
58
78
  onCells?: (cells: NotebookCell[]) => void;
59
79
  /** Fires when the cursor moves to a different cell. */
60
80
  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. */
81
+ /**
82
+ * Fires after a compile with the fresh frames and diagnostics.
83
+ */
64
84
  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;
85
+ /** A cell's state changed and the decorations need a rebuild. */
86
+ onStateChange?: () => void;
87
+ /** A command from the rail's overflow menu, so the app owns the actions. */
88
+ onCommand?: (command: string, index: number) => void;
89
+ /** Read-only pages show cells without source or chrome. */
90
+ readOnly?: () => boolean;
69
91
  }
70
92
  /** The options of the notebook extension active in this state, if any. */
71
93
  export declare const notebookOptionsFacet: Facet<NotebookOptions, NotebookOptions | undefined>;
72
94
  export declare function notebookOptions(state: EditorState): NotebookOptions | undefined;
73
95
  /** Re-renders notebooks from cached frames without recompiling. */
74
96
  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). */
97
+ /** First position that belongs to the cell (attribute line, or content). */
80
98
  export declare function cellStart(cell: NotebookCell): number;
81
- export declare function hasMarker(cell: NotebookCell): boolean;
99
+ /** True when the cell opened with an attribute line rather than a heading. */
100
+ export declare function hasAttribute(cell: NotebookCell): boolean;
82
101
  /** Index of the cell containing `pos`. Gaps belong to the cell above. */
83
102
  export declare function cellIndexAt(cells: NotebookCell[], pos: number): number;
84
103
  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;
104
+ /**
105
+ * The attribute line for a cell type. Prose needs no `kind=`, so a plain cell is
106
+ * three characters.
107
+ */
108
+ export declare function attributeText(type: NotebookCellType, name?: string | null): string;
109
+ /**
110
+ * Removes cell attribute lines. Notebooks are comments-plus-content, so a
111
+ * cleaned file is the same document for anyone who does not know the
112
+ * convention. Only `//%` goes: any other comment is left as written.
113
+ */
114
+ export declare function stripCellAttributes(text: string): string;
87
115
  /** A text replacement plus where the cursor should land after it. */
88
116
  export interface CellEdit {
89
117
  changes: {
@@ -93,38 +121,41 @@ export interface CellEdit {
93
121
  };
94
122
  anchor: number;
95
123
  }
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;
124
+ /**
125
+ * Splits a cell at `pos` inside its content. The new cell takes the text from
126
+ * `pos` and inherits the old cell's kind, because a split is a continuation.
127
+ */
100
128
  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
129
  /**
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.
130
+ * Merges a cell into the one above. The result takes the lower cell's kind,
131
+ * since that is the one the reader was last looking at.
132
+ */
133
+ export declare function mergeCellText(cells: NotebookCell[], index: number): CellEdit | null;
134
+ /**
135
+ * Rewrites a cell's attribute line. A cell that began at a heading has no line
136
+ * to rewrite, so one is inserted.
107
137
  */
108
- export declare function stripCellMarkers(text: string): string;
109
- /** Compiles and reports through `onRun`, but does not move the cursor. */
110
- export declare function runCell(view: EditorView, index: number): boolean;
111
- export declare function runAllCells(view: EditorView): boolean;
138
+ export declare function setCellTypeText(text: string, cells: NotebookCell[], index: number, type: NotebookCellType): CellEdit | null;
139
+ /** Appends a cell of `type` after `index` (or at the end of the document). */
140
+ export declare function insertCellText(text: string, cells: NotebookCell[], index: number, type: NotebookCellType, content?: string): CellEdit | null;
141
+ export declare function deleteCellText(cells: NotebookCell[], index: number, docLength: number): CellEdit | null;
142
+ /** Copies a cell's kind, name, and body below it. */
143
+ export declare function duplicateCellText(text: string, cells: NotebookCell[], index: number): CellEdit | null;
144
+ /** Selects a cell's content so the keyboard commands act on it. */
112
145
  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;
146
+ export declare function currentCell(view: EditorView): number;
147
+ /** Inserts a cell below `index`, or at the end of the document. */
148
+ export declare function insertCell(view: EditorView, type: NotebookCellType, content?: string, index?: number): boolean;
149
+ export declare function duplicateCell(view: EditorView, index?: number): boolean;
150
+ export declare function deleteCell(view: EditorView, index?: number): boolean;
151
+ /** Moves the active cell up or down. */
152
+ export declare function moveCell(view: EditorView, delta: number): boolean;
153
+ export declare function setCellType(view: EditorView, index: number, type: NotebookCellType): boolean;
121
154
  export declare function splitCell(view: EditorView): boolean;
122
155
  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
156
  /**
126
- * Notebook keymap. Mounted with high precedence so Alt-ArrowUp/Down move
127
- * cells instead of lines and Escape reaches command mode.
157
+ * The editor's cell commands. Everything here is also in the cell menu, and
158
+ * every one of them is a text edit, so the undo stack covers them all.
128
159
  */
129
160
  export declare const notebookKeymap: import("@codemirror/state").Extension;
130
161
  //#endregion
@@ -140,6 +171,7 @@ interface TextRef {
140
171
  type TypstRequestHandler = (requests: import("@typbase/engine").TypstRequest[], spaceId: string) => Promise<boolean> | boolean;
141
172
  //#endregion
142
173
  //#region src/plugin.d.ts
174
+ export declare const typstEditingExtensions: Extension;
143
175
  export interface TypstPluginOptions {
144
176
  /**
145
177
  * Called when Typst needs a source, file, or package that is not loaded
@@ -165,10 +197,16 @@ export interface TypstPluginOptions {
165
197
  onExternalLink?: (url: string) => void;
166
198
  /**
167
199
  * Cell rendering and cell commands. When set, the editor behaves like a
168
- * notebook: markup cells render inline, code cells render below, and the
200
+ * notebook: prose cells render inline, code cells render below, and the
169
201
  * notebook keymap takes precedence over the line editing bindings.
170
202
  */
171
203
  notebook?: NotebookOptions;
204
+ /**
205
+ * Draw the frames, or show plain source. Defaults to true. A notebook page in
206
+ * source mode passes false: the cells and their rails stay, but nothing is
207
+ * rendered, which is the only difference between its write and source modes.
208
+ */
209
+ renderFrames?: boolean;
172
210
  }
173
211
  export declare const typstPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstPluginOptions) => Extension;
174
212
  //#endregion
@@ -206,15 +244,14 @@ export interface TypstLinterOptions {
206
244
  }
207
245
  /**
208
246
  * 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
247
  */
215
248
  export declare const typstLinter: (fileId: FileId, spaceId: string, path: string, prelude: TextRef, typstState: TypstState, options?: TypstLinterOptions) => import("@codemirror/state").Extension;
216
249
  //#endregion
217
250
  //#region src/frames.d.ts
251
+ /**
252
+ * Places the glyph and gradient definitions a frame set references.
253
+ */
254
+ export declare function installSharedDefs(defs: string | null | undefined): void;
218
255
  /**
219
256
  * Opens an external link for the host. Browsers get a new tab. The app passes
220
257
  * its `openExternal`, which hands the URL to the system browser in Tauri
@@ -295,6 +332,17 @@ export declare const typstHoverTooltip: (fileId: FileId, typstState: TypstState)
295
332
  };
296
333
  //#endregion
297
334
  //#region src/keymap.d.ts
335
+ /**
336
+ * Whether the editor is running vim bindings. Vim handles keys from a DOM
337
+ * listener that CodeMirror's keymap runs before, so Escape has to be left
338
+ * unhandled or it never reaches the vim plugin. Set through the same
339
+ * compartment as the vim extension.
340
+ */
341
+ export declare const vimKeymapFacet: Facet<boolean, boolean>;
342
+ /**
343
+ * The app's shortcuts dialog mirrors the common entries here. When a chord
344
+ * changes, update `EDITOR_SHORTCUTS` in `apps/web/src/lib/keybindings.ts` too.
345
+ */
298
346
  export declare const typstKeymap: import("@codemirror/state").Extension;
299
347
  //#endregion
300
348
  //#region src/language.d.ts
@@ -304,6 +352,12 @@ export declare const typstLanguageData: import("@codemirror/state").Extension;
304
352
  //#region src/static-highlight.d.ts
305
353
  export declare const typstStaticHighlighting: StateField<DecorationSet>;
306
354
  //#endregion
355
+ //#region src/sync.d.ts
356
+ /**
357
+ * Keeps the engine's sources in step with the editor, without rendering.
358
+ */
359
+ export declare const typstSourceSync: (fileId: FileId, prelude: TextRef, typstState: TypstState) => Extension;
360
+ //#endregion
307
361
  //#region src/tooltip.d.ts
308
362
  export declare const tooltipStateField: StateField<Tooltip | null>;
309
363
  export declare const tooltipViewPlugin: () => ViewPlugin<{
@@ -311,9 +365,14 @@ export declare const tooltipViewPlugin: () => ViewPlugin<{
311
365
  }, undefined>;
312
366
  //#endregion
313
367
  //#region src/widgets.d.ts
368
+ /**
369
+ * Compiled frames per cache key, where the key is `path:revision:appRevision`.
370
+ */
314
371
  export declare const compileCache: LRUCache<string, {
315
372
  frames: SvgRangedFrame[];
316
373
  tooltips: SvgRangedFrame[];
374
+ /** Every equation in the note, not only the one the caret was in. */
375
+ equationRanges: [number, number][];
317
376
  diagnostics: TypstDiagnostic[];
318
377
  }, unknown>;
319
378
  /**
@@ -321,8 +380,18 @@ export declare const compileCache: LRUCache<string, {
321
380
  * app data changed (fonts installed, workspace data, query results).
322
381
  */
323
382
  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[]>;
383
+ export interface EquationOverlays {
384
+ /** Rendered overlays, at most one when the render was given a caret. */
385
+ tooltips: SvgRangedFrame[];
386
+ /**
387
+ * Every equation range in the note, not only the one the caret was in. The
388
+ * popup compares the cursor against these to know when it has entered math
389
+ * whose overlay the last render skipped.
390
+ */
391
+ ranges: [number, number][];
392
+ }
393
+ export declare const tooltipsStateEffect: import("@codemirror/state").StateEffectType<EquationOverlays>;
394
+ export declare const tooltipsStateField: StateField<EquationOverlays>;
326
395
  export declare const typstStateField: StateField<DecorationSet>;
327
396
  export interface TypstViewPluginOptions {
328
397
  onRequests?: TypstRequestHandler;
@@ -337,6 +406,7 @@ export interface TypstViewPluginOptions {
337
406
  onExternalLink?: ExternalLinkOpener;
338
407
  /** Cell rendering, run effects, and cell commands for notebook mode. */
339
408
  notebook?: NotebookOptions;
409
+ renderFrames?: boolean;
340
410
  }
341
411
  export declare const typstViewPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstViewPluginOptions) => ViewPlugin<{
342
412
  update(update: ViewUpdate): void;