import { EditorState, PluginKey, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { EditorSchema } from "../schema"; /** * Helper to provide statically typed wrappers over ProseMirror APIs. * * Public APIs are bound so can be safely used directly, e.g. * * interface PluginState { * myPluginField: string; * } * const { key, getPluginState } = new PluginDescriptor('MyPlugin'); */ export class PluginDescriptor { public readonly key = new PluginKey(this.name); constructor(private readonly name: string) {} public setPluginState = ( env: { state: EditorState; tr?: Transaction; dispatch?: EditorView["dispatch"]; }, newPluginState: PluginState | ((prevPluginState: PluginState) => PluginState) ): void => { const { state, tr = env.state.tr, dispatch } = env; const prevPluginState = this.getPluginStateOrThrow(state); // https://github.com/Microsoft/TypeScript/issues/26970 tr.setMeta(this.key, newPluginState instanceof Function ? newPluginState(prevPluginState) : newPluginState); if (dispatch !== undefined) { dispatch(tr); } }; public getPluginState = (source: Transaction | EditorState): PluginState | null => { const pluginState = source instanceof Transaction ? source.getMeta(this.key) : this.key.getState(source); return pluginState != null ? (pluginState as PluginState) : null; }; public getPluginStateOrThrow = (source: Transaction | EditorState): PluginState => { const pluginState = this.getPluginState(source); if (pluginState !== null) { return pluginState; } throw new Error("Missing plugin state"); }; }