import type { ResolvedPos } from '@prosekit/pm/model' import { PluginKey, type EditorState, type Transaction } from '@prosekit/pm/state' import type { AutocompleteRule } from './autocomplete-rule.ts' export function defaultCanMatch({ state }: { state: EditorState }): boolean { const $pos = state.selection.$from return !isInsideCodeBlock($pos) && !isInsideCodeMark($pos) } function isInsideCodeBlock($pos: ResolvedPos): boolean { for (let d = $pos.depth; d > 0; d--) { if ($pos.node(d).type.spec.code) { return true } } return false } function isInsideCodeMark($pos: ResolvedPos): boolean { for (const mark of $pos.marks()) { if (mark.type.spec.code) { return true } } return false } /** * @internal */ export interface PredictionPluginMatching { rule: AutocompleteRule from: number to: number match: RegExpExecArray } /** * @internal */ export interface PredictionPluginState { /** * The matching positions that should be ignored. */ ignores: Array /** * The current active matching. */ matching: PredictionPluginMatching | null } /** * @internal */ export type PredictionTransactionMeta = { type: 'enter' matching: PredictionPluginMatching } | { type: 'leave' } export function getPluginState(state: EditorState): PredictionPluginState | undefined { return pluginKey.getState(state) } export function getTrMeta(tr: Transaction): PredictionTransactionMeta | undefined { return tr.getMeta(pluginKey) as PredictionTransactionMeta | undefined } export function setTrMeta( tr: Transaction, meta: PredictionTransactionMeta, ): Transaction { return tr.setMeta(pluginKey, meta) } export const pluginKey: PluginKey = new PluginKey('prosekit-autocomplete')