UNPKG

@godfreykaris/tiptap-math-block

Version:

A TipTap extension + React NodeView for editable math blocks (MathQuill + KaTeX)

217 lines (145 loc) 6.34 kB
# Tiptap Math Extension A ready-to-use **Tiptap extension** and **React components** for editing LaTeX math (block **and inline**) with a modal editor, KaTeX rendering, spacebar support, and matrix editing. ## Features - ✏️ **Inline and block math editing** with [KaTeX](https://katex.org/) rendering. - 🧮 **Matrix editor** with visual previews and `⟦M1⟧` placeholders. - 🔄 **Undo/Redo** support inside the modal (`Ctrl/Cmd+Z` and `Shift+Ctrl/Cmd+Z`). - **Spacebar inserts spaces** inside math fields (`\\ `), so you can format equations naturally. - 🧹 **Helper functions** to safely insert new math blocks/inline nodes without overwriting the selected one. - 🔌 **Bridge hook** that wires the extension to the modal with zero boilerplate. - 📦 Works with **Tiptap 2 + React**. - 🔒 **Security Note:** This package uses [MathQuill](http://mathquill.com/), which historically depended on an older version of jQuery. We apply an **override to force jQuery 3.7.1** (the latest safe version) to eliminate known vulnerabilities. --- ## Installation ```bash npm install @godfreykaris/tiptap-math-block # or yarn add @godfreykaris/tiptap-math-block ``` Peer dependencies (make sure you have them installed): ```bash npm install @tiptap/react @tiptap/starter-kit @tiptap/pm katex react react-dom ``` If your project’s security scanner flags jQuery vulnerabilities when installing MathQuill, note that **this package overrides MathQuill’s old jQuery requirement to use 3.7.1**. Consumers should add their own override/resolution in their app if they still see warnings. --- ## Quick Start ### 1) Import the extension, modal, helpers, and styles ```tsx import "katex/dist/katex.min.css"; // Required for KaTeX rendering import "@godfreykaris/tiptap-math-block/style.css"; // Required package styles import React from "react"; import { useEditor, EditorContent } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import { MathExtension, MathInlineExtension, MathModal, addMathBlockAfterSelection, addMathInlineAtSelection, useMathModalBridge, } from "@godfreykaris/tiptap-math-block"; ``` ### 2) Create your editor and modal bridge ```tsx const MyMathEditor = () => { const editor = useEditor({ extensions: [StarterKit, MathExtension, MathInlineExtension], content: `<p>Example content before math block and <span data-type="math-inline" data-latex="a^2+b^2=c^2"></span></p>`, }); // Hook that syncs open/close state with MathModal const { modalProps } = useMathModalBridge(); return ( <div> <button type="button" onClick={() => editor && addMathBlockAfterSelection(editor, "x = \\square") } > Add Math Block </button> <button type="button" onClick={() => editor && addMathInlineAtSelection(editor, "y = mx + b")} > Add Inline Math </button> <EditorContent editor={editor} /> {/* Modal for editing math */} <MathModal {...modalProps} /> </div> ); }; ``` ### 3) Adding a new math block or inline math - **Block math** ```ts addMathBlockAfterSelection(editor, "x = \\square"); ``` - **Inline math** ```ts addMathInlineAtSelection(editor, "a^2 + b^2 = c^2"); ``` **Notes:** - Both helpers ensure insertion after selection without overwriting nodes. - Inline math works seamlessly inside paragraphs or text spans. --- ## How the modal bridge works `useMathModalBridge()`: - Listens for `openMathModal` events emitted by the extension's NodeView when you click a math block or inline math. - Returns `modalProps` containing everything `<MathModal />` needs: `isOpen`, `onClose`, `initialLatex`, `initialMatrices`, `onSave`, `id`, and `mode` (block/inline). - Keeps your `App.tsx` lean and package-friendly. --- ## API ### `addMathBlockAfterSelection(editor, initialLatex?)` Safely inserts a new math block after the selection and seeds it with `initialLatex`. **Returns:** `boolean` whether the command ran. **Example:** ```ts addMathBlockAfterSelection(editor, "a^2 + b^2 = c^2"); ``` ### `addMathInlineAtSelection(editor, initialLatex?)` Safely inserts a new inline math node at the selection and seeds it with `initialLatex`. **Returns:** `boolean` whether the command ran. **Example:** ```ts addMathInlineAtSelection(editor, "E = mc^2"); ``` --- ## Styling & Assets - The modal and toolbar use Tailwind utility classes by default. You may override or adapt these styles. - KaTeX CSS is required once globally: ```ts import "katex/dist/katex.min.css"; ``` - Package styles are required once globally: ```ts import "@godfreykaris/tiptap-math-block/style.css"; ``` --- ## TypeScript Notes - The helper uses types from `@tiptap/pm/model` and `@tiptap/pm/state` to avoid bringing in direct `prosemirror-*` packages. - If you maintain strict ESLint rules (`import/prefer-default-export`, `no-explicit-any`, etc.), the distributed helpers comply. --- ## SSR If you render on the server, guard browser-only APIs (like `window`) and only mount the editor on the client. --- ## Security & MathQuill Dependency MathQuill’s `package.json` specifies `jquery: ^1.12.3`, which can trigger vulnerability warnings. In this package, we: - Apply `"overrides": { "jquery": "3.7.1" }` to force a modern, secure jQuery. - Verify via `npm ls jquery` that only `3.7.1` is installed. If you are a consumer of this package and still see warnings: - Add a `resolutions` (Yarn) or `overrides` (npm/pnpm) entry for jQuery 3.7.1 in your own `package.json`. - Clear your lockfile and reinstall. - Ensure your security scanner checks **resolved** versions, not just declared ranges. --- ## FAQ **Q: The new math block is empty. Can I set a default?** A: Yes. Pass a second argument to the helper, e.g. `addMathBlockAfterSelection(editor, 'x = \\square')`. **Q: My linter complains about `prosemirror-state` as an extraneous dependency.** A: Import from `@tiptap/pm/state` instead, or add `prosemirror-state` to your project. **Q: Can I open the modal immediately after inserting the block?** A: You can dispatch a custom event or extend the command to open it right away. The package exposes the modal bridge so it’s easy to wire up. --- ## License MIT © 2025 Godfrey Kariuki