Recover from Typst parser panics

This commit is contained in:
2026-07-18 20:08:02 -04:00
parent eea352a87d
commit be17ff79f8
+35 -2
View File
@@ -6,7 +6,7 @@
lineNumbers, lineNumbers,
highlightActiveLine, highlightActiveLine,
} from "@codemirror/view"; } from "@codemirror/view";
import { EditorState, Compartment } from "@codemirror/state"; import { EditorState, Compartment, StateField } from "@codemirror/state";
import { import {
defaultKeymap, defaultKeymap,
history, history,
@@ -16,6 +16,7 @@
import { import {
bracketMatching, bracketMatching,
indentOnInput, indentOnInput,
language,
Language, Language,
StreamLanguage, StreamLanguage,
} from "@codemirror/language"; } from "@codemirror/language";
@@ -70,6 +71,38 @@
const isToml = $derived(filePath.toLowerCase().endsWith(".toml")); const isToml = $derived(filePath.toLowerCase().endsWith(".toml"));
function resilientSync(parser: any) {
return StateField.define<null>({
create: () => null,
update(_value, transaction) {
if (
transaction.startState.facet(language) !==
transaction.state.facet(language)
) {
parser.clearParser();
return null;
}
if (!transaction.docChanged) return null;
try {
transaction.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
const edits = parser.parser?.edit(fromA, toA, inserted.toString());
if (!edits || edits.full_update) {
parser.clearTree();
return;
}
for (const edit of edits.edits) parser.applyTreeEdit(edit);
});
} catch {
parser.clearParser();
}
return null;
},
});
}
async function loadTypstLanguage() { async function loadTypstLanguage() {
const { typst, TypstParser, typstHighlight } = await import( const { typst, TypstParser, typstHighlight } = await import(
"codemirror-lang-typst" "codemirror-lang-typst"
@@ -79,7 +112,7 @@
return new Language( return new Language(
support.language.data, support.language.data,
parser, parser,
[parser.updateListener()], [resilientSync(parser)],
"typst", "typst",
); );
} }