@typbase/codemirror 0.3.2 → 0.4.0

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 +123 -65
  3. package/dist/index.mjs +581 -348
  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.
107
132
  */
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;
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.
137
+ */
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
@@ -165,10 +196,16 @@ export interface TypstPluginOptions {
165
196
  onExternalLink?: (url: string) => void;
166
197
  /**
167
198
  * Cell rendering and cell commands. When set, the editor behaves like a
168
- * notebook: markup cells render inline, code cells render below, and the
199
+ * notebook: prose cells render inline, code cells render below, and the
169
200
  * notebook keymap takes precedence over the line editing bindings.
170
201
  */
171
202
  notebook?: NotebookOptions;
203
+ /**
204
+ * Draw the frames, or show plain source. Defaults to true. A notebook page in
205
+ * source mode passes false: the cells and their rails stay, but nothing is
206
+ * rendered, which is the only difference between its write and source modes.
207
+ */
208
+ renderFrames?: boolean;
172
209
  }
173
210
  export declare const typstPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstPluginOptions) => Extension;
174
211
  //#endregion
@@ -206,15 +243,14 @@ export interface TypstLinterOptions {
206
243
  }
207
244
  /**
208
245
  * 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
246
  */
215
247
  export declare const typstLinter: (fileId: FileId, spaceId: string, path: string, prelude: TextRef, typstState: TypstState, options?: TypstLinterOptions) => import("@codemirror/state").Extension;
216
248
  //#endregion
217
249
  //#region src/frames.d.ts
250
+ /**
251
+ * Places the glyph and gradient definitions a frame set references.
252
+ */
253
+ export declare function installSharedDefs(defs: string | null | undefined): void;
218
254
  /**
219
255
  * Opens an external link for the host. Browsers get a new tab. The app passes
220
256
  * its `openExternal`, which hands the URL to the system browser in Tauri
@@ -304,6 +340,12 @@ export declare const typstLanguageData: import("@codemirror/state").Extension;
304
340
  //#region src/static-highlight.d.ts
305
341
  export declare const typstStaticHighlighting: StateField<DecorationSet>;
306
342
  //#endregion
343
+ //#region src/sync.d.ts
344
+ /**
345
+ * Keeps the engine's sources in step with the editor, without rendering.
346
+ */
347
+ export declare const typstSourceSync: (fileId: FileId, prelude: TextRef, typstState: TypstState) => Extension;
348
+ //#endregion
307
349
  //#region src/tooltip.d.ts
308
350
  export declare const tooltipStateField: StateField<Tooltip | null>;
309
351
  export declare const tooltipViewPlugin: () => ViewPlugin<{
@@ -311,9 +353,14 @@ export declare const tooltipViewPlugin: () => ViewPlugin<{
311
353
  }, undefined>;
312
354
  //#endregion
313
355
  //#region src/widgets.d.ts
356
+ /**
357
+ * Compiled frames per cache key, where the key is `path:revision:appRevision`.
358
+ */
314
359
  export declare const compileCache: LRUCache<string, {
315
360
  frames: SvgRangedFrame[];
316
361
  tooltips: SvgRangedFrame[];
362
+ /** Every equation in the note, not only the one the caret was in. */
363
+ equationRanges: [number, number][];
317
364
  diagnostics: TypstDiagnostic[];
318
365
  }, unknown>;
319
366
  /**
@@ -321,8 +368,18 @@ export declare const compileCache: LRUCache<string, {
321
368
  * app data changed (fonts installed, workspace data, query results).
322
369
  */
323
370
  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[]>;
371
+ export interface EquationOverlays {
372
+ /** Rendered overlays, at most one when the render was given a caret. */
373
+ tooltips: SvgRangedFrame[];
374
+ /**
375
+ * Every equation range in the note, not only the one the caret was in. The
376
+ * popup compares the cursor against these to know when it has entered math
377
+ * whose overlay the last render skipped.
378
+ */
379
+ ranges: [number, number][];
380
+ }
381
+ export declare const tooltipsStateEffect: import("@codemirror/state").StateEffectType<EquationOverlays>;
382
+ export declare const tooltipsStateField: StateField<EquationOverlays>;
326
383
  export declare const typstStateField: StateField<DecorationSet>;
327
384
  export interface TypstViewPluginOptions {
328
385
  onRequests?: TypstRequestHandler;
@@ -337,6 +394,7 @@ export interface TypstViewPluginOptions {
337
394
  onExternalLink?: ExternalLinkOpener;
338
395
  /** Cell rendering, run effects, and cell commands for notebook mode. */
339
396
  notebook?: NotebookOptions;
397
+ renderFrames?: boolean;
340
398
  }
341
399
  export declare const typstViewPlugin: (fileId: FileId, spaceId: string, path: string, text: TextRef, prelude: TextRef, locked: boolean, typstState: TypstState, options?: TypstViewPluginOptions) => ViewPlugin<{
342
400
  update(update: ViewUpdate): void;