Skip to content

Instantly share code, notes, and snippets.

@Fevol
Last active March 11, 2023 20:31
Show Gist options
  • Save Fevol/393e0de68e6565c899fbe5800900e2db to your computer and use it in GitHub Desktop.
Save Fevol/393e0de68e6565c899fbe5800900e2db to your computer and use it in GitHub Desktop.
CodeMirror Document incremental parser statefield
import { Plugin } from 'obsidian';
import { treeParser } from './tree-parser';
import { OTHER_EXTENSION } from './other-extension';
// Obsidian plugin file
export default class YOURPLUGIN extends Plugin {
async onload() {
// ...
this.registerEditorExtension([treeParser, OTHER_EXTENSION]);
}
}
import { treeParser } from './tree-parser';
import { EditorState } from '@codemirror/state';
export const OTHER_EXTENSION = EditorState.transactionFilter.of(tr => {
const tree = tr.startState.field(treeParser).tree
// Do whatever you want with the tree
return tr;
});
import { StateField } from '@codemirror/state';
import type { ChangedRange } from '@lezer/common';
import { TreeFragment } from '@lezer/common';
import { YOURPARSER } from './parser';
// Removed // @ts-ignore comments for brevity, but there are a couple places where you might have to add them in again
export const treeParser = StateField.define({
create(state) {
const tree = YOURPARSER.parser.parse(state.doc.toString());
const fragments = TreeFragment.addTree(tree);
return {
tree: tree,
fragments: fragments,
}
},
update(value, tr) {
if (!tr.docChanged) return value;
const changed_ranges: ChangedRange[] = [];
tr.changes.iterChangedRanges((from, to, fromB, toB) =>
changed_ranges.push({fromA: from, toA: to, fromB: fromB, toB: toB})
);
let fragments = TreeFragment.applyChanges(value.fragments, changed_ranges);
const tree = criticmarkupLanguage.parser.parse(tr.state.doc.toString(), fragments);
fragments = TreeFragment.addTree(tree, fragments);
return {
tree: tree,
fragments: fragments,
}
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment