prosemirror-equation
v0.8.0
Published
Render and edit math equations (TeX) in ProseMirror.
Downloads
31
Readme
prosemirror-equation
🚧 Work in progress 🚧
Write math equations with LaTeX in ProseMirror — this module provides block and inline node schemas, rendering with KaTeX, editing with CodeMirror in a popover UI, and an input rule to create inline equation nodes.
Design Principles
- Opening or closing the equation editor should not cause any layout shift.
- Users should be able to see the rendered equation while they edit the TeX.
- Users should be able to open or close the editor—and start or finish editing—without taking their hands off the keyboard.
Key Features (try it yourself)
We’ve taken a lot of inspiration from how Notion designs its math equation experience.
- Opens a popover editor next to the equation for editing TeX.
- Uses CodeMirror to provide syntax highlighting in the editor.
- Updates the rendered equation in real time as you type.
- Lets you move into and out of an inline equation with the arrow keys.
In addition to user-facing features, we also offer the following developer-friendly benefits:
- Unstyled, framework-agnostic, fully customizable UI.
- Load KaTeX (264kB) and CodeMirror (242kB) dynamically—only when they’re actually needed—to keep your main JS bundle small.
Getting Started
We will walk you through the process of integrating prosemirror-equation into an existing ProseMirror project.
Install packages
npm i prosemirror-equation katexYou will import katex's CSS files in your project, so you need to install it as a dependency.
Set up CSS
Make sure you include the CSS files for katex and prosemirror-equation on any pages that will need them. They can be found at the following paths:
node_modules/katex/dist/katex.min.css
node_modules/prosemirror-equation/style/equation.cssIf you are using a bundler like vite, you may be able to include the CSS files in your JavaScript entry point like this:
import 'katex/dist/katex.min.css'
import 'prosemirror-equation/style/equation.css'Or in your CSS entry point like this:
@import 'katex/dist/katex.min.css';
@import 'prosemirror-equation/style/equation.css';Set up schema
Add equation nodes to your ProseMirror schema.
For example, if you are using the schema from prosemirror-schema-basic:
import { Schema } from 'prosemirror-model'
import { schema as baseSchema } from 'prosemirror-schema-basic'
import { equationNodes } from 'prosemirror-equation'
const schema = new Schema({
nodes: baseSchema.spec.nodes.append(
equationNodes({
blockEquationGroup: 'block',
inlineEquationGroup: 'inline',
})
),
marks: baseSchema.spec.marks,
})Set up plugins
Add the pre-configured equation plugin to your ProseMirror state:
import { EditorState } from 'prosemirror-state'
import { equationExampleSetup } from 'prosemirror-equation/example-setup'
const state = EditorState.create({
schema,
plugins: [equationExampleSetup()],
})The pre-configured plugin includes default UI components for rendering and editing math equations.
Optional: Set up input rules
We provide an input rule that lets you type $$...$$ to create inline equation nodes. You can add it to your editor setup with the inputRules plugin from prosemirror-inputrules.
import { EditorState } from 'prosemirror-state'
+import { inputRules } from 'prosemirror-inputrules'
+import { inlineEquationInputRule } from 'prosemirror-equation'
import { equationExampleSetup } from 'prosemirror-equation/example-setup'
const state = EditorState.create({
schema,
plugins: [
equationExampleSetup(),
+ inputRules({
+ rules: [
+ inlineEquationInputRule(),
+ ],
+ }),
],
})Next steps
Congratulations, you're all set up with the math equation functionality! In the next section, we'll guide you through how to further customize it to fit your needs.
If you want to have a clearer picture of how to put the pieces together, check out our demo code in demo/demo.ts or tinker with it live in the online code editor:
Customizing
Styling
You can copy style/equation.css to your project and modify it.
Modifying element structures and behaviors
Instead of using the pre-configured equationExampleSetup() function from prosemirror-equation/example-setup, you can use equation() function from prosemirror-equation to provide your own implementations of renderEditor and renderNode.
For example, below is how the equationExampleSetup() function is implemented:
import { equation } from 'prosemirror-equation'
import { createEquationEditorRenderer } from 'prosemirror-equation/components/equation-editor'
import { renderEquationNode } from 'prosemirror-equation/components/equation-node'
export function equationExampleSetup() {
return equation({
renderEditor: createEquationEditorRenderer({
loadTexEditorTheme: async () =>
(await import('prosemirror-equation/components/tex-editor-codemirror'))
.editorTheme,
}),
renderNode: renderEquationNode,
})
}You can reuse the components that come with the prosemirror-equation package by importing them from prosemirror-equation/components/*.
Styling our CodeMirror-based TeX editor
You can replace loadTexEditorTheme in the previous snippet with your own implementation to provide your own CodeMirror theme.
Syntax highlighting
Modify the .cm-line .token.xxx classes in style/equation.css.
Ready-made CodeMirror themes
Prior Art
ProseMirror-based alternatives
- gh:@benrbray/prosemirror-math
- Tiptap's Mathematics extension
- gh:@buttondown/tiptap-math
- gh:@aarkue/tiptap-math-extension
- ProseMirror + Math at Desmos
Not ProseMirror-based — for UX reference
About This Repository
The important files in this repository are:
demo/: The demo website.src/schema.ts: Schemas of block and inline equation nodes.equation.ts: A ProseMirror Plugin that registers NodeViews and enables opening equation editor programmatically.equationNodeView.ts: A NodeView which renders TeX equations and provides interactivity.equationInputRules.ts: Contains an InputRule that lets user create inline equation nodes by typing$$equation$$.
To-do
- [ ] Research prosekit integration
Development
Install dependencies
pnpm installDevelop the library with demo
pnpm run devRun the unit tests
pnpm run testBuild the library
pnpm run buildBuild the demo
pnpm run build:demoAnalyze bundle with demo
pnpm run analyzeBundleand navigate to http://localhost:8888/
Other notes
- This repository uses gh:@googleapis/release-please to create releases automatically. Add
Release-As: x.y.zto the commit body to mark the version of the commit.
License
MIT
Closing Note
Chat with DeepWiki about anything not covered in the documentation or that needs more clarification:
