{"id":13810537,"url":"https://github.com/benrbray/prosemirror-math","last_synced_at":"2025-05-15T17:08:54.537Z","repository":{"id":39003719,"uuid":"272062007","full_name":"benrbray/prosemirror-math","owner":"benrbray","description":"Schema and plugins for \"first-class\" math support in ProseMirror!","archived":false,"fork":false,"pushed_at":"2024-09-24T00:02:11.000Z","size":7971,"stargazers_count":279,"open_issues_count":30,"forks_count":41,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-14T16:17:39.493Z","etag":null,"topics":["katex","math","prosemirror","wysiwyg"],"latest_commit_sha":null,"homepage":"https://benrbray.com/prosemirror-math/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benrbray.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-13T18:11:47.000Z","updated_at":"2025-05-13T21:27:18.000Z","dependencies_parsed_at":"2024-04-11T07:34:53.048Z","dependency_job_id":"5e5b1a53-e7a7-4935-a638-4cd3aa556798","html_url":"https://github.com/benrbray/prosemirror-math","commit_stats":{"total_commits":118,"total_committers":4,"mean_commits":29.5,"dds":"0.18644067796610164","last_synced_commit":"8f11600b571dc3349f694b8a0804176be95571b0"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benrbray%2Fprosemirror-math","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benrbray%2Fprosemirror-math/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benrbray%2Fprosemirror-math/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benrbray%2Fprosemirror-math/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benrbray","download_url":"https://codeload.github.com/benrbray/prosemirror-math/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254384989,"owners_count":22062422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["katex","math","prosemirror","wysiwyg"],"created_at":"2024-08-04T02:00:58.405Z","updated_at":"2025-05-15T17:08:49.528Z","avatar_url":"https://github.com/benrbray.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","编辑器相关","Community modules"],"sub_categories":[],"readme":"# `prosemirror-math`\n\n[![](https://img.shields.io/npm/v/@benrbray/prosemirror-math?style=flat-square)](https://www.npmjs.com/package/@benrbray/prosemirror-math)\n![license](https://img.shields.io/github/license/benrbray/prosemirror-math?style=flat-square)\n![types](https://img.shields.io/npm/types/@benrbray/prosemirror-math?style=flat-square)\n\n\u003e Please don't hesitate to report issues or make feature requests!  Contributions welcome!\n\n## Overview\n\nThe `prosemirror-math` package provides schema and plugins for comfortably writing mathematics with [ProseMirror](https://prosemirror.net/).  Written in TypeScript, with math rendering handled by [KaTeX](https://katex.org/).  You can install the [npm package](https://www.npmjs.com/package/@benrbray/prosemirror-math) or use this repository as a starting point for your own plugin.  The important files in this project are:\n\n* `lib/math-schema.ts`: A minimal ProseMirror schema supporting inline and display math nodes.\n* `lib/math-nodeview.ts`: A `NodeView` responsible for rendering and editing math nodes.\n* `public/prosemirror-math.css`: Contains all necessary styling for math nodes to display correctly.  This file can easily be modified to achieve your desired appearance.\n\n## Basic Usage  ([try it yourself!](http://benrbray.com/prosemirror-math/))\n\nUnlike other editors, this plugin **treats math as part of the text itself**, rather than as an \"atom\" that can only be edited through a dialog box.  For example, inline math nodes can be edited directly by bringing the cursor inside of them:\n\n![edit inline math](img/prosemirror-math_inline.gif)\n\nDisplay math supports multiline editing, as shown below:\n\n![edit display math](img/prosemirror-math_display.gif)\n\nTo create a new math expression, simply enclose LaTeX math notation in dollar signs, like `$x+y=5$`.  When you finish typing, a new math node will be automatically created:\n\n![create inline math](img/prosemirror-math_insert-inline.gif)\n\nTo start a display math block, create a blank line and type `$$` followed by a space.  A multiline editor will appear.  To exit the block, press `Ctrl-Enter` or navigate away the mouse or arrow keys.\n\n![create display math](img/prosemirror-math_insert-display.gif)\n\nMath nodes behave like regular text when using the arrow keys or `Backspace`.  You can select, copy, and paste math nodes just like regular text!  From within a math node, press `Ctrl-Backspace` to delete the entire node.\n\n\u003e **TIP:** You can define your own commands with `\\providecommand{\\cmd}{...}`!\n\nSee the KaTeX documentation for a list of [supported LaTeX commands](https://katex.org/docs/supported.html). In the future, `prosemirror-math` will also accept a custom callback that can be used to invoke alternative renderers like MathJax.\n\n## Installation \u0026 Setup\n\nNote that `prosemirror-math` is built on top of [ProseMirror](https://prosemirror.net/), which itself has a steep learning curve.  At the very least, you will need to understand [`Schema`](https://prosemirror.net/docs/ref/#model.Document_Schema) and [`Plugins`](https://prosemirror.net/docs/ref/#state.Plugin_System) to integrate `prosemirror-math` into your project.  Start by installing the `npm` package:\n\n```\nnpm install @benrbray/prosemirror-math\n```\n\n### CSS\n\nFirst, make sure you include the CSS files for `prosemirror-math` and `katex` on any pages that will need them.  They can be found at the following paths:\n\n```\nnode_modules/katex/dist/katex.min.css\nnode_modules/@benrbray/prosemirror-math/dist/prosemirror-math.css\n```\n\nIf you are using a bundler like `vite` or `webpack`, you may be able to include the CSS files like this:\n\n```\nimport \"@benrbray/prosemirror-math/dist/prosemirror-math.css\";\nimport \"katex/dist/katex.min.css\";\n```\n\n### Schema\n\nAdd `math_inline` and `math_display` nodes to your `prosemirror` document schema.  The names are important!  If you modify the schema, be careful not to change any of the values marked `important!` below, or you might run into unexpected behavior!\n\n```typescript\nimport { Schema } from \"prosemirror-model\";\n\nlet schema = new Schema({\n    nodes: {\n        doc: {\n            content: \"block+\"\n        },\n        paragraph: {\n            content: \"inline*\",\n            group: \"block\",\n            parseDOM: [{ tag: \"p\" }],\n            toDOM() { return [\"p\", 0]; }\n        },\n        math_inline: {               // important!\n            group: \"inline math\",\n            content: \"text*\",        // important!\n            inline: true,            // important!\n            atom: true,              // important!\n            toDOM: () =\u003e [\"math-inline\", { class: \"math-node\" }, 0],\n            parseDOM: [{\n                tag: \"math-inline\"   // important!\n            }]\n        },\n        math_display: {              // important!\n            group: \"block math\",\n            content: \"text*\",        // important!\n            atom: true,              // important!\n            code: true,              // important!\n            toDOM: () =\u003e [\"math-display\", { class: \"math-node\" }, 0],\n            parseDOM: [{\n                tag: \"math-display\"  // important!\n            }]\n        },\n        text: {\n            group: \"inline\"\n        }\n    }\n});\n```\n\n### Input Rules\n\nIf you want the user to be able to easily add new math nodes by typing `$...$` for inline math or `$$` followed by a space for block math, you need to create [`InputRule`](https://prosemirror.net/docs/ref/#inputrules.InputRule) instances.  You can write your own, or use the helper functions provided by `prosemirror-math`.\n\n\u003e **CAUTION:**  Make sure the `NodeType`s you provide to each input rule belong to the same schema instance that you pass to your ProseMirror `EditorView` instance.  Otherwise, you'll see strange errors in the console!\n\n```typescript\nimport {\n\tmakeBlockMathInputRule, makeInlineMathInputRule,\n\tREGEX_INLINE_MATH_DOLLARS, REGEX_BLOCK_MATH_DOLLARS\n} from \"@benrbray/prosemirror-math\";\n\n// create input rules (using default regex)\nlet inlineMathInputRule = makeInlineMathInputRule(REGEX_INLINE_MATH_DOLLARS, editorSchema.nodes.math_inline);\nlet blockMathInputRule = makeBlockMathInputRule(REGEX_BLOCK_MATH_DOLLARS, editorSchema.nodes.math_display);\n```\n\n### Plugins\n\nChoose which plugins you need from the following list, and pass them to your `EditorState` instance, along with the input rules you created.\n\n* `mathPlugin` **(required)** Provides the core functionality of `prosemirror-math`.\n* `mathBackspaceCmd` *(recommended)* When included in your [keymap](https://prosemirror.net/docs/ref/#keymap.keymap) for the `\"Backspace\"` key, pressing backspace on the right boundary of a math node will place the cursor inside the math node, rather than deleting it.\n* `insertMathCmd(nodeType: NodeType)` *(optional)* Helper function for creating a command which can be used to insert a math node at the current document position.\n* `mathSerializer` *(recommended)* Attach to the `clipboardTextSerializer` prop of your EditorView.  When pasting a selection from a `prosemirror-math` editor to a plain text editor, ensures that the pasted math expressions will be properly delimited by `$...$` and `$$...$$`.\n\nHere is the recommended setup:\n\n```typescript\nimport { mathPlugin, mathBackspaceCmd, insertMathCmd, mathSerializer } from \"@benrbray/prosemirror-math\";\n\n// prosemirror imports\nimport { EditorView } from \"prosemirror-view\";\nimport { EditorState, Plugin } from \"prosemirror-state\";\nimport { chainCommands, deleteSelection, selectNodeBackward, joinBackward, Command } from \"prosemirror-commands\";\nimport { keymap } from \"prosemirror-keymap\";\nimport { inputRules } from \"prosemirror-inputrules\";\n\n// plugins (order matters)\nlet plugins:Plugin[] = [\n    mathPlugin,\n    keymap({\n        \"Mod-Space\" : insertMathCmd(schema.nodes.math_inline),\n        // modify the default keymap chain for backspace\n        \"Backspace\": chainCommands(deleteSelection, mathBackspaceCmd, joinBackward, selectNodeBackward),\n    }),\n    inputRules({ rules: [ inlineMathInputRule, blockMathInputRule ] })\n];\n\n// create prosemirror state\nlet state = EditorState.create({\n    schema: editorSchema,\n    plugins: plugins,\n    doc: /* ... */\n})\n\n// create prosemirror view\nlet view = new EditorView(editorElt, {\n    state,\n    clipboardTextSerializer: (slice) =\u003e { return mathSerializer.serializeSlice(slice) },\n})\n```\n\n## Development\n\nClone this repository and install the necessary dependencies:\n\n```\ngit clone git@github.com:benrbray/prosemirror-math.git\ncd prosemirror-math\nnpm install\n```\n\nFrom the root directory, you can run the scripts in `package.json`.\n\n* Use `npm run build` to build the `prosemirror-math` package\n* Use `npm run build:site` to generate the static demo website\n* Use `npm run dev` to start a local development server\n\n## Release\n\n\u003e (this section is to help me remember the steps required to publish a new release)\n\nTo make a prerelease version for testing:\n\n```bash\n# begin a prerelease\nnpm version premajor --preid=rc # from 1.0.0 to 2.0.0-rc.0\nnpm version preminor --preid=rc # from 1.0.0 to 1.1.0-rc.0\nnpm version prepatch --preid=rc # from 1.0.0 to 1.0.1-rc.0\n\n# increment the prerelease version number\nnpm version prerelease # from 2.0.0-rc.0 to 2.0.0-rc.1\n\n# promote the prerelease version\nnpm version major # from 2.0.0-rc.1 to 2.0.0\nnpm version minor # from 1.1.0-beta.0 to 1.1.0\nnpm version patch # from 1.0.1-alpha.0 to 1.0.1\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenrbray%2Fprosemirror-math","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenrbray%2Fprosemirror-math","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenrbray%2Fprosemirror-math/lists"}