@typbase/codemirror 0.4.0 → 0.4.2
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/dist/index.d.mts +12 -0
- package/dist/index.mjs +73 -40
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -171,6 +171,7 @@ interface TextRef {
|
|
|
171
171
|
type TypstRequestHandler = (requests: import("@typbase/engine").TypstRequest[], spaceId: string) => Promise<boolean> | boolean;
|
|
172
172
|
//#endregion
|
|
173
173
|
//#region src/plugin.d.ts
|
|
174
|
+
export declare const typstEditingExtensions: Extension;
|
|
174
175
|
export interface TypstPluginOptions {
|
|
175
176
|
/**
|
|
176
177
|
* Called when Typst needs a source, file, or package that is not loaded
|
|
@@ -331,6 +332,17 @@ export declare const typstHoverTooltip: (fileId: FileId, typstState: TypstState)
|
|
|
331
332
|
};
|
|
332
333
|
//#endregion
|
|
333
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
|
+
*/
|
|
334
346
|
export declare const typstKeymap: import("@codemirror/state").Extension;
|
|
335
347
|
//#endregion
|
|
336
348
|
//#region src/language.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { acceptCompletion, autocompletion, closeBracketsKeymap, completionKeymap, snippet, startCompletion } from "@codemirror/autocomplete";
|
|
1
|
+
import { acceptCompletion, autocompletion, closeBracketsKeymap, closeCompletion, completionKeymap, snippet, startCompletion } from "@codemirror/autocomplete";
|
|
2
2
|
import { indentService } from "@codemirror/language";
|
|
3
3
|
import { Decoration, EditorView, ViewPlugin, WidgetType, hoverTooltip, keymap, showTooltip } from "@codemirror/view";
|
|
4
4
|
import { ChangeSet, EditorSelection, EditorState, Facet, RangeSetBuilder, StateEffect, StateField, countColumn, findColumn } from "@codemirror/state";
|
|
@@ -20,15 +20,29 @@ const typstSyntaxHighlighting = (fileId, typstState) => StateField.define({
|
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
function buildDecorations$2(state, fileId, typstState) {
|
|
23
|
-
const builder = new RangeSetBuilder();
|
|
24
23
|
let tokens;
|
|
24
|
+
let equations;
|
|
25
25
|
try {
|
|
26
26
|
tokens = typstState.highlight(fileId, state.doc.toString());
|
|
27
|
+
equations = typstState.extractEquations(fileId, state.doc.toString());
|
|
27
28
|
} catch (error) {
|
|
28
29
|
console.error("[typst] highlight panicked:", error);
|
|
29
30
|
return Decoration.none;
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
const builder = new RangeSetBuilder();
|
|
33
|
+
const equationMark = Decoration.mark({ class: "typ-equation" });
|
|
34
|
+
let nextEquation = 0;
|
|
35
|
+
for (const token of tokens) {
|
|
36
|
+
while (nextEquation < equations.length && equations[nextEquation].from <= token.range.start) {
|
|
37
|
+
const equation = equations[nextEquation++];
|
|
38
|
+
builder.add(equation.from, equation.to, equationMark);
|
|
39
|
+
}
|
|
40
|
+
builder.add(token.range.start, token.range.end, Decoration.mark({ class: token.tag }));
|
|
41
|
+
}
|
|
42
|
+
for (; nextEquation < equations.length; nextEquation++) {
|
|
43
|
+
const equation = equations[nextEquation];
|
|
44
|
+
builder.add(equation.from, equation.to, equationMark);
|
|
45
|
+
}
|
|
32
46
|
return builder.finish();
|
|
33
47
|
}
|
|
34
48
|
const parseBackticks = (str, into) => {
|
|
@@ -372,8 +386,19 @@ function cursorAddVertical(view, offset) {
|
|
|
372
386
|
}
|
|
373
387
|
//#endregion
|
|
374
388
|
//#region src/keymap.ts
|
|
389
|
+
/**
|
|
390
|
+
* Whether the editor is running vim bindings. Vim handles keys from a DOM
|
|
391
|
+
* listener that CodeMirror's keymap runs before, so Escape has to be left
|
|
392
|
+
* unhandled or it never reaches the vim plugin. Set through the same
|
|
393
|
+
* compartment as the vim extension.
|
|
394
|
+
*/
|
|
395
|
+
const vimKeymapFacet = Facet.define({ combine: (values) => values.some(Boolean) });
|
|
396
|
+
/**
|
|
397
|
+
* The app's shortcuts dialog mirrors the common entries here. When a chord
|
|
398
|
+
* changes, update `EDITOR_SHORTCUTS` in `apps/web/src/lib/keybindings.ts` too.
|
|
399
|
+
*/
|
|
375
400
|
const typstKeymap = keymap.of([
|
|
376
|
-
...completionKeymap,
|
|
401
|
+
...completionKeymap.filter((binding) => binding.key !== "Escape"),
|
|
377
402
|
...closeBracketsKeymap,
|
|
378
403
|
{
|
|
379
404
|
key: "Tab",
|
|
@@ -488,7 +513,13 @@ const typstKeymap = keymap.of([
|
|
|
488
513
|
},
|
|
489
514
|
{
|
|
490
515
|
key: "Escape",
|
|
491
|
-
run:
|
|
516
|
+
run: (view) => {
|
|
517
|
+
if (view.state.facet(vimKeymapFacet)) {
|
|
518
|
+
closeCompletion(view);
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
return closeCompletion(view) || simplifySelection(view);
|
|
522
|
+
}
|
|
492
523
|
},
|
|
493
524
|
{
|
|
494
525
|
key: "Mod-Alt-ArrowUp",
|
|
@@ -524,7 +555,7 @@ const typstKeymap = keymap.of([
|
|
|
524
555
|
run: selectNextOccurrence,
|
|
525
556
|
preventDefault: true
|
|
526
557
|
},
|
|
527
|
-
...standardKeymap
|
|
558
|
+
...standardKeymap.filter((binding) => binding.key !== "Escape")
|
|
528
559
|
]);
|
|
529
560
|
//#endregion
|
|
530
561
|
//#region src/language.ts
|
|
@@ -1593,8 +1624,9 @@ const SCROLLBAR_ALLOWANCE = 12;
|
|
|
1593
1624
|
function editorRenderWidth(scrollDOM, contentDOM) {
|
|
1594
1625
|
const pane = scrollDOM.getBoundingClientRect();
|
|
1595
1626
|
const gutters = scrollDOM.querySelector(".cm-gutters");
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1627
|
+
const contentStyle = getComputedStyle(contentDOM);
|
|
1628
|
+
const scrollStyle = getComputedStyle(scrollDOM);
|
|
1629
|
+
return Math.max(0, pane.width - (gutters?.getBoundingClientRect().width ?? 0) - parseFloat(contentStyle.paddingLeft) - parseFloat(contentStyle.paddingRight) - parseFloat(scrollStyle.paddingLeft) - parseFloat(scrollStyle.paddingRight) - SCROLLBAR_ALLOWANCE);
|
|
1598
1630
|
}
|
|
1599
1631
|
const tooltipsStateEffect = StateEffect.define();
|
|
1600
1632
|
const tooltipsStateField = StateField.define({
|
|
@@ -1952,6 +1984,37 @@ const tooltipViewPlugin = () => ViewPlugin.define((view) => ({ update(update) {
|
|
|
1952
1984
|
} }));
|
|
1953
1985
|
//#endregion
|
|
1954
1986
|
//#region src/plugin.ts
|
|
1987
|
+
const bracketPairs = {
|
|
1988
|
+
"(": ")",
|
|
1989
|
+
"[": "]",
|
|
1990
|
+
"{": "}",
|
|
1991
|
+
$: "$"
|
|
1992
|
+
};
|
|
1993
|
+
const typstEditingExtensions = [EditorView.inputHandler.of((view, from, to, text) => {
|
|
1994
|
+
if (text !== " " || from !== to) return false;
|
|
1995
|
+
const { state } = view;
|
|
1996
|
+
const { main } = state.selection;
|
|
1997
|
+
if (!main.empty) return false;
|
|
1998
|
+
const pos = main.head;
|
|
1999
|
+
const before = state.doc.sliceString(pos - 1, pos);
|
|
2000
|
+
const after = state.doc.sliceString(pos, pos + 1);
|
|
2001
|
+
if (!bracketPairs[before] || after !== bracketPairs[before]) return false;
|
|
2002
|
+
view.dispatch({
|
|
2003
|
+
changes: {
|
|
2004
|
+
from: pos,
|
|
2005
|
+
to: pos,
|
|
2006
|
+
insert: " "
|
|
2007
|
+
},
|
|
2008
|
+
selection: { anchor: pos + 1 }
|
|
2009
|
+
});
|
|
2010
|
+
return true;
|
|
2011
|
+
}), indentService.of((ctx, pos) => {
|
|
2012
|
+
const last = Math.max(0, pos - 1);
|
|
2013
|
+
const prev = ctx.lineAt(last).text;
|
|
2014
|
+
if (prev.endsWith("$") && prev !== "$") return 0;
|
|
2015
|
+
const indent = /[{[($]\s*$/.test(prev);
|
|
2016
|
+
return ctx.lineIndent(last) + (indent ? ctx.unit : 0);
|
|
2017
|
+
})];
|
|
1955
2018
|
const typstPlugin = (fileId, spaceId, path, text, prelude, locked, typstState, options = {}) => {
|
|
1956
2019
|
const extensions = [
|
|
1957
2020
|
typstStateField,
|
|
@@ -1965,41 +2028,11 @@ const typstPlugin = (fileId, spaceId, path, text, prelude, locked, typstState, o
|
|
|
1965
2028
|
typstSourceSync(fileId, prelude, typstState),
|
|
1966
2029
|
typstSyntaxHighlighting(fileId, typstState),
|
|
1967
2030
|
typstHoverTooltip(fileId, typstState),
|
|
1968
|
-
|
|
1969
|
-
indentService.of((ctx, pos) => {
|
|
1970
|
-
const last = Math.max(0, pos - 1);
|
|
1971
|
-
const prev = ctx.lineAt(last).text;
|
|
1972
|
-
if (prev.endsWith("$") && prev !== "$") return 0;
|
|
1973
|
-
const indent = /[{[($]\s*$/.test(prev);
|
|
1974
|
-
return ctx.lineIndent(last) + (indent ? ctx.unit : 0);
|
|
1975
|
-
})
|
|
2031
|
+
typstEditingExtensions
|
|
1976
2032
|
];
|
|
1977
2033
|
if (options.notebook) extensions.push(notebookOptionsFacet.of(options.notebook), notebookKeymap);
|
|
1978
2034
|
return extensions;
|
|
1979
2035
|
};
|
|
1980
|
-
const addSpaceBeforeClosingBracket = EditorView.inputHandler.of((view, from, to, text) => {
|
|
1981
|
-
if (text === " ") {
|
|
1982
|
-
const { state } = view;
|
|
1983
|
-
const pos = from;
|
|
1984
|
-
const bracketPairs = {
|
|
1985
|
-
"(": ")",
|
|
1986
|
-
"[": "]",
|
|
1987
|
-
"{": "}",
|
|
1988
|
-
$: "$"
|
|
1989
|
-
};
|
|
1990
|
-
const before = state.doc.sliceString(pos - 1, pos);
|
|
1991
|
-
const after = state.doc.sliceString(pos, pos + 1);
|
|
1992
|
-
if (bracketPairs[before] && after === bracketPairs[before]) view.dispatch({
|
|
1993
|
-
changes: {
|
|
1994
|
-
from: pos,
|
|
1995
|
-
to: pos,
|
|
1996
|
-
insert: " "
|
|
1997
|
-
},
|
|
1998
|
-
selection: { anchor: pos + 1 }
|
|
1999
|
-
});
|
|
2000
|
-
}
|
|
2001
|
-
return false;
|
|
2002
|
-
});
|
|
2003
2036
|
//#endregion
|
|
2004
2037
|
//#region src/static-highlight.ts
|
|
2005
2038
|
const KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -2331,4 +2364,4 @@ function stringEnd(line, from) {
|
|
|
2331
2364
|
return line.length;
|
|
2332
2365
|
}
|
|
2333
2366
|
//#endregion
|
|
2334
|
-
export { NOTEBOOK_CELL_TYPES, TypstWidget, attachFrameInteractions, attributeText, autocomplete, cellIndexAt, cellStart, cellsOf, compileCache, createFrameContainer, currentCell, cursorAddVertical, cycleHeading, deleteCell, deleteCellText, duplicateCell, duplicateCellText, focusCell, frameActiveDecorations, frameIsInactive, frameSize, hasAttribute, hasOutput, hidesSource, insertAtCursor, insertCell, insertCellText, insertFontFamily, insertTabLike, installSharedDefs, mergeCell, mergeCellText, moveCell, notebookKeymap, notebookOptions, notebookOptionsFacet, notebookRefreshEffect, parseBackticks, rememberDiagnostics, rendersInPlace, setCellType, setCellTypeText, splitCell, splitCellText, stripCellAttributes, syncFrameContainer, toLintDiagnostics, toggleAroundSelection, toggleCode, toggleEmph, toggleEnum, toggleList, toggleListLike, toggleMath, toggleStrike, toggleStrong, toggleUnderline, tooltipStateField, tooltipViewPlugin, tooltipsStateEffect, tooltipsStateField, typstHoverTooltip, typstKeymap, typstLanguageData, typstLinter, typstPlugin, typstRecompileEffect, typstSourceSync, typstStateField, typstStaticHighlighting, typstSyntaxHighlighting, typstViewPlugin, wrapOrInsert };
|
|
2367
|
+
export { NOTEBOOK_CELL_TYPES, TypstWidget, attachFrameInteractions, attributeText, autocomplete, cellIndexAt, cellStart, cellsOf, compileCache, createFrameContainer, currentCell, cursorAddVertical, cycleHeading, deleteCell, deleteCellText, duplicateCell, duplicateCellText, focusCell, frameActiveDecorations, frameIsInactive, frameSize, hasAttribute, hasOutput, hidesSource, insertAtCursor, insertCell, insertCellText, insertFontFamily, insertTabLike, installSharedDefs, mergeCell, mergeCellText, moveCell, notebookKeymap, notebookOptions, notebookOptionsFacet, notebookRefreshEffect, parseBackticks, rememberDiagnostics, rendersInPlace, setCellType, setCellTypeText, splitCell, splitCellText, stripCellAttributes, syncFrameContainer, toLintDiagnostics, toggleAroundSelection, toggleCode, toggleEmph, toggleEnum, toggleList, toggleListLike, toggleMath, toggleStrike, toggleStrong, toggleUnderline, tooltipStateField, tooltipViewPlugin, tooltipsStateEffect, tooltipsStateField, typstEditingExtensions, typstHoverTooltip, typstKeymap, typstLanguageData, typstLinter, typstPlugin, typstRecompileEffect, typstSourceSync, typstStateField, typstStaticHighlighting, typstSyntaxHighlighting, typstViewPlugin, vimKeymapFacet, wrapOrInsert };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typbase/codemirror",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "CodeMirror 6 editing experience for Typst: WYSIWYG inline preview, highlighting, hover, autocomplete.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atproto",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typescript": "^5.9.3"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@typbase/engine": "^0.4.
|
|
43
|
+
"@typbase/engine": "^0.4.2"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsdown",
|