Copilot-style text completion plugin for ProseMirror
npm install prosemirror-completionCopilot-style text completion plugin for ProseMirror.
- π― Invisible Trigger: Automatically triggers completion as you type based on cursor context
- π» Ghost Text: Visual suggestion overlay that doesn't interfere with editing
- β¨οΈ Intuitive Keybindings: Tab to accept, Esc to cancel
- π Customizable: Debounce timing, abort controller, custom prompt builders
- π¨ Rich Results: Support plain text, HTML, Markdown, or ProseMirror nodes
- β‘ Framework Agnostic: Works with any JavaScript framework or vanilla JS
``bash`
npm install prosemirror-completion
`typescript
import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { keymap } from "prosemirror-keymap";
import { schema } from "prosemirror-schema-basic";
import { exampleSetup } from "prosemirror-example-setup";
import {
completion,
approveCompletion,
exitCompletion,
} from "prosemirror-completion";
const completionPlugin = completion({
debounceMs: 300,
minTriggerLength: 2,
getPromptType: (ctx) =>
ctx.parent.type.name === "code_block" ? "code" : "common",
callCompletion: async ({ beforeText }) => {
const lastWord = beforeText.split(/\s+/).pop() ?? "";
return lastWord ? ${lastWord}β¦ : "";
},
debug: import.meta.env.DEV,
});
const completionKeymap = keymap({
Tab: approveCompletion,
Escape: exitCompletion,
});
const state = EditorState.create({
schema,
plugins: [completionPlugin, completionKeymap, ...exampleSetup({ schema })],
});
const view = new EditorView(document.querySelector("#editor")!, {
state,
});
`
callCompletion can return a simple string, or an object containing HTML or ProseMirror Node:
`ts`
type CompletionResult =
| string
| { plain: string; html?: string }
| { html: string }
| { prosemirror: Node };
completion accepts the following configuration options:
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| debounceMs | number | 300 | Debounce time before triggering completion, in milliseconds |minTriggerLength
| | number | 3 | Minimum characters before cursor to trigger completion request |callCompletion
| | (context) => CompletionResult \| Promise | Required | The actual completion function, returns string, HTML or ProseMirror Node |getPromptType
| | (context) => PromptType | defaultGetPromptType | Custom prompt type inference logic (e.g., code/Markdown detection) |onChange
| | (context, view) => void | undefined | Triggered when user types continuously, can be used for analytics or real-time status display |ghostClassName
| | string | "prosemirror-ghost-text" | Custom CSS class for Ghost Text |showGhost
| | boolean | true | Whether to show Ghost Text (can be disabled to keep only keyboard behavior) |debug
| | boolean | false | Whether to output debug logs for troubleshooting trigger and request processes |
> CompletionResult supports string, { plain; html? }, { html }, { prosemirror: Node }, see docs for examples.approveCompletion
>
> If you need to execute logic when the user accepts/cancels completion at the callback level, you can listen to and extend the exported /exitCompletion commands.
`text
packages/
βββ plugin/
β βββ src/
β β βββ decorations.ts # Ghost text rendering
β β βββ index.ts # Entry exports
β β βββ keymap.ts # Keyboard handlers
β β βββ plugin.ts # Core plugin implementation
β β βββ prompts.ts # Prompt builders
β β βββ types.ts # Shared types & contexts
β β βββ utils.ts # Helpers (commands, prompt detection, text extractionβ¦)
β βββ scripts/postbuild.mjs
β βββ package.json
βββ eslint-config/ # Shared eslint preset
βββ typescript-config/ # Shared tsconfig presets
apps/
βββ demo/ # Playground + Vitest suite
β βββ src/main.ts
β βββ src/completion.test.ts
βββ docs/ # VitePress documentation site (en & zh)
βββ docs/
βββ guide/
βββ api/
βββ examples/
`
`bashInstall dependencies (pnpm workspace)
pnpm install
The plugin is built with a three-layer architecture:
1. Matcher (State Tracker): Tracks cursor position and triggers completion using Transaction meta
2. Ghost Decoration: Virtual rendering layer using ProseMirror DecorationSet
3. Key Handler: Intercepts Tab and Esc for completion actions
MIT