@tiptap/extension-mathematics 3.0.0-beta.16 → 3.0.0-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +320 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +286 -16
- package/dist/index.d.ts +286 -16
- package/dist/index.js +314 -143
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/extensions/BlockMath.ts +251 -0
- package/src/extensions/InlineMath.ts +252 -0
- package/src/extensions/index.ts +2 -0
- package/src/index.ts +2 -1
- package/src/mathematics.ts +54 -14
- package/src/types.ts +16 -4
- package/src/utils.ts +101 -0
- package/src/MathematicsPlugin.ts +0 -205
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { InputRule, mergeAttributes, Node } from '@tiptap/core'
|
|
2
|
+
import type { Node as PMNode } from '@tiptap/pm/model'
|
|
3
|
+
import katex, { type KatexOptions } from 'katex'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the BlockMath extension.
|
|
7
|
+
*/
|
|
8
|
+
export type BlockMathOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* KaTeX specific options
|
|
11
|
+
* @see https://katex.org/docs/options.html
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* katexOptions: {
|
|
15
|
+
* displayMode: true,
|
|
16
|
+
* throwOnError: false,
|
|
17
|
+
* },
|
|
18
|
+
*/
|
|
19
|
+
katexOptions?: KatexOptions
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Optional click handler for block math nodes.
|
|
23
|
+
* Called when a user clicks on a block math expression in the editor.
|
|
24
|
+
*
|
|
25
|
+
* @param node - The ProseMirror node representing the block math element
|
|
26
|
+
* @param pos - The position of the node within the document
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* onClick: (node, pos) => {
|
|
30
|
+
* console.log('Block math clicked:', node.attrs.latex, 'at position:', pos)
|
|
31
|
+
* },
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
onClick?: (node: PMNode, pos: number) => void
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare module '@tiptap/core' {
|
|
38
|
+
interface Commands<ReturnType> {
|
|
39
|
+
insertBlockMath: {
|
|
40
|
+
/**
|
|
41
|
+
* Inserts a math block node with LaTeX string.
|
|
42
|
+
* @param options - Options for inserting block math.
|
|
43
|
+
* @returns ReturnType
|
|
44
|
+
*/
|
|
45
|
+
insertBlockMath: (options: { latex: string; pos?: number }) => ReturnType
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Deletes a block math node.
|
|
49
|
+
* @returns ReturnType
|
|
50
|
+
*/
|
|
51
|
+
deleteBlockMath: (options?: { pos?: number }) => ReturnType
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Update block math node with optional LaTeX string.
|
|
55
|
+
* @param options - Options for updating block math.
|
|
56
|
+
* @returns ReturnType
|
|
57
|
+
*/
|
|
58
|
+
updateBlockMath: (options?: { latex: string; pos?: number }) => ReturnType
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* BlockMath is a Tiptap extension for rendering block mathematical expressions using KaTeX.
|
|
65
|
+
* It allows users to insert LaTeX formatted math expressions block within text.
|
|
66
|
+
* It supports rendering, input rules for LaTeX syntax, and click handling for interaction.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```javascript
|
|
70
|
+
* import { BlockMath } from '@tiptap/extension-mathematics'
|
|
71
|
+
* import { Editor } from '@tiptap/core'
|
|
72
|
+
*
|
|
73
|
+
* const editor = new Editor({
|
|
74
|
+
* extensions: [
|
|
75
|
+
* BlockMath.configure({
|
|
76
|
+
* onClick: (node, pos) => {
|
|
77
|
+
* console.log('Block math clicked:', node.attrs.latex, 'at position:', pos)
|
|
78
|
+
* },
|
|
79
|
+
* }),
|
|
80
|
+
* ],
|
|
81
|
+
* })
|
|
82
|
+
*/
|
|
83
|
+
export const BlockMath = Node.create<BlockMathOptions>({
|
|
84
|
+
name: 'blockMath',
|
|
85
|
+
|
|
86
|
+
group: 'block',
|
|
87
|
+
|
|
88
|
+
atom: true,
|
|
89
|
+
|
|
90
|
+
addOptions() {
|
|
91
|
+
return {
|
|
92
|
+
onClick: undefined,
|
|
93
|
+
katexOptions: undefined,
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
addAttributes() {
|
|
98
|
+
return {
|
|
99
|
+
latex: {
|
|
100
|
+
default: '',
|
|
101
|
+
parseHTML: element => element.getAttribute('data-latex'),
|
|
102
|
+
renderHTML: attributes => {
|
|
103
|
+
return {
|
|
104
|
+
'data-latex': attributes.latex,
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
addCommands() {
|
|
112
|
+
return {
|
|
113
|
+
insertBlockMath:
|
|
114
|
+
options =>
|
|
115
|
+
({ commands, editor }) => {
|
|
116
|
+
const { latex, pos } = options
|
|
117
|
+
|
|
118
|
+
if (!latex) {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return commands.insertContentAt(pos ?? editor.state.selection.from, {
|
|
123
|
+
type: this.name,
|
|
124
|
+
attrs: { latex },
|
|
125
|
+
})
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
deleteBlockMath:
|
|
129
|
+
options =>
|
|
130
|
+
({ editor, tr }) => {
|
|
131
|
+
const pos = options?.pos ?? editor.state.selection.$from.pos
|
|
132
|
+
const node = editor.state.doc.nodeAt(pos)
|
|
133
|
+
|
|
134
|
+
if (!node || node.type.name !== this.name) {
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
tr.delete(pos, pos + node.nodeSize)
|
|
139
|
+
return true
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
updateBlockMath:
|
|
143
|
+
options =>
|
|
144
|
+
({ editor, tr }) => {
|
|
145
|
+
const latex = options?.latex
|
|
146
|
+
let pos = options?.pos
|
|
147
|
+
|
|
148
|
+
if (pos === undefined) {
|
|
149
|
+
pos = editor.state.selection.$from.pos
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const node = editor.state.doc.nodeAt(pos)
|
|
153
|
+
|
|
154
|
+
if (!node || node.type.name !== this.name) {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
tr.setNodeMarkup(pos, this.type, {
|
|
159
|
+
...node.attrs,
|
|
160
|
+
latex: latex || node.attrs.latex,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
return true
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
parseHTML() {
|
|
169
|
+
return [
|
|
170
|
+
{
|
|
171
|
+
tag: 'div[data-type="block-math"]',
|
|
172
|
+
},
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
renderHTML({ HTMLAttributes }) {
|
|
177
|
+
return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'block-math' })]
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
addInputRules() {
|
|
181
|
+
return [
|
|
182
|
+
new InputRule({
|
|
183
|
+
find: /^\$\$\$([^$]+)\$\$\$$/,
|
|
184
|
+
handler: ({ state, range, match }) => {
|
|
185
|
+
const [, latex] = match
|
|
186
|
+
const { tr } = state
|
|
187
|
+
const start = range.from
|
|
188
|
+
const end = range.to
|
|
189
|
+
|
|
190
|
+
tr.replaceWith(start, end, this.type.create({ latex }))
|
|
191
|
+
},
|
|
192
|
+
}),
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
addNodeView() {
|
|
197
|
+
const { katexOptions } = this.options
|
|
198
|
+
|
|
199
|
+
return ({ node, getPos }) => {
|
|
200
|
+
const wrapper = document.createElement('div')
|
|
201
|
+
const innerWrapper = document.createElement('div')
|
|
202
|
+
wrapper.className = 'tiptap-mathematics-render'
|
|
203
|
+
|
|
204
|
+
if (this.editor.isEditable) {
|
|
205
|
+
wrapper.classList.add('tiptap-mathematics-render--editable')
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
innerWrapper.className = 'block-math-inner'
|
|
209
|
+
wrapper.dataset.type = 'block-math'
|
|
210
|
+
wrapper.setAttribute('data-latex', node.attrs.latex)
|
|
211
|
+
wrapper.appendChild(innerWrapper)
|
|
212
|
+
|
|
213
|
+
function renderMath() {
|
|
214
|
+
try {
|
|
215
|
+
katex.render(node.attrs.latex, innerWrapper, katexOptions)
|
|
216
|
+
wrapper.classList.remove('block-math-error')
|
|
217
|
+
} catch {
|
|
218
|
+
wrapper.textContent = node.attrs.latex
|
|
219
|
+
wrapper.classList.add('block-math-error')
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const handleClick = (event: MouseEvent) => {
|
|
224
|
+
event.preventDefault()
|
|
225
|
+
event.stopPropagation()
|
|
226
|
+
const pos = getPos()
|
|
227
|
+
|
|
228
|
+
if (pos == null) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (this.options.onClick) {
|
|
233
|
+
this.options.onClick(node, pos)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (this.options.onClick) {
|
|
238
|
+
wrapper.addEventListener('click', handleClick)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
renderMath()
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
dom: wrapper,
|
|
245
|
+
destroy() {
|
|
246
|
+
wrapper.removeEventListener('click', handleClick)
|
|
247
|
+
},
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
})
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { InputRule, mergeAttributes, Node } from '@tiptap/core'
|
|
2
|
+
import type { Node as PMNode } from '@tiptap/pm/model'
|
|
3
|
+
import katex, { type KatexOptions } from 'katex'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the InlineMath extension.
|
|
7
|
+
*/
|
|
8
|
+
export type InlineMathOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* KaTeX specific options
|
|
11
|
+
* @see https://katex.org/docs/options.html
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* katexOptions: {
|
|
15
|
+
* displayMode: false,
|
|
16
|
+
* throwOnError: false,
|
|
17
|
+
* macros: {
|
|
18
|
+
* '\\RR': '\\mathbb{R}',
|
|
19
|
+
* '\\ZZ': '\\mathbb{Z}'
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
katexOptions?: KatexOptions
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Optional click handler for inline math nodes.
|
|
28
|
+
* Called when a user clicks on an inline math expression in the editor.
|
|
29
|
+
*
|
|
30
|
+
* @param node - The ProseMirror node representing the inline math element
|
|
31
|
+
* @param pos - The position of the node within the document
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* onClick: (node, pos) => {
|
|
35
|
+
* console.log('Inline math clicked:', node.attrs.latex, 'at position:', pos)
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
onClick?: (node: PMNode, pos: number) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare module '@tiptap/core' {
|
|
43
|
+
interface Commands<ReturnType> {
|
|
44
|
+
inlineMath: {
|
|
45
|
+
/**
|
|
46
|
+
* Insert a inline math node with LaTeX string.
|
|
47
|
+
* @param options - Options for inserting inline math.
|
|
48
|
+
* @returns ReturnType
|
|
49
|
+
*/
|
|
50
|
+
insertInlineMath: (options: { latex: string; pos?: number }) => ReturnType
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Delete an inline math node.
|
|
54
|
+
* @returns ReturnType
|
|
55
|
+
*/
|
|
56
|
+
deleteInlineMath: (options?: { pos?: number }) => ReturnType
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Update inline math node with optional LaTeX string.
|
|
60
|
+
* @param options - Options for updating inline math.
|
|
61
|
+
* @returns ReturnType
|
|
62
|
+
*/
|
|
63
|
+
updateInlineMath: (options?: { latex?: string; pos?: number }) => ReturnType
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* InlineMath is a Tiptap extension for rendering inline mathematical expressions using KaTeX.
|
|
70
|
+
* It allows users to insert LaTeX formatted math expressions inline within text.
|
|
71
|
+
* It supports rendering, input rules for LaTeX syntax, and click handling for interaction.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```javascript
|
|
75
|
+
* import { InlineMath } from '@tiptap/extension-mathematics'
|
|
76
|
+
* import { Editor } from '@tiptap/core'
|
|
77
|
+
*
|
|
78
|
+
* const editor = new Editor({
|
|
79
|
+
* extensions: [
|
|
80
|
+
* InlineMath.configure({
|
|
81
|
+
* onClick: (node, pos) => {
|
|
82
|
+
* console.log('Inline math clicked:', node.attrs.latex, 'at position:', pos)
|
|
83
|
+
* },
|
|
84
|
+
* }),
|
|
85
|
+
* ],
|
|
86
|
+
* })
|
|
87
|
+
*/
|
|
88
|
+
export const InlineMath = Node.create<InlineMathOptions>({
|
|
89
|
+
name: 'inlineMath',
|
|
90
|
+
|
|
91
|
+
group: 'inline',
|
|
92
|
+
|
|
93
|
+
inline: true,
|
|
94
|
+
|
|
95
|
+
atom: true,
|
|
96
|
+
|
|
97
|
+
addOptions() {
|
|
98
|
+
return {
|
|
99
|
+
onClick: undefined,
|
|
100
|
+
katexOptions: undefined,
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
addAttributes() {
|
|
105
|
+
return {
|
|
106
|
+
latex: {
|
|
107
|
+
default: '',
|
|
108
|
+
parseHTML: element => element.getAttribute('data-latex'),
|
|
109
|
+
renderHTML: attributes => {
|
|
110
|
+
return {
|
|
111
|
+
'data-latex': attributes.latex,
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
addCommands() {
|
|
119
|
+
return {
|
|
120
|
+
insertInlineMath:
|
|
121
|
+
options =>
|
|
122
|
+
({ editor, tr }) => {
|
|
123
|
+
const latex = options.latex
|
|
124
|
+
|
|
125
|
+
const from = options?.pos ?? editor.state.selection.from
|
|
126
|
+
|
|
127
|
+
if (!latex) {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
tr.replaceWith(from, from, this.type.create({ latex }))
|
|
132
|
+
return true
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
deleteInlineMath:
|
|
136
|
+
options =>
|
|
137
|
+
({ editor, tr }) => {
|
|
138
|
+
const pos = options?.pos ?? editor.state.selection.$from.pos
|
|
139
|
+
const node = editor.state.doc.nodeAt(pos)
|
|
140
|
+
|
|
141
|
+
if (!node || node.type.name !== this.name) {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
tr.delete(pos, pos + node.nodeSize)
|
|
146
|
+
return true
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
updateInlineMath:
|
|
150
|
+
options =>
|
|
151
|
+
({ editor, tr }) => {
|
|
152
|
+
const latex = options?.latex
|
|
153
|
+
let pos = options?.pos
|
|
154
|
+
|
|
155
|
+
if (pos === undefined) {
|
|
156
|
+
pos = editor.state.selection.$from.pos
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const node = editor.state.doc.nodeAt(pos)
|
|
160
|
+
|
|
161
|
+
if (!node || node.type.name !== this.name) {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
tr.setNodeMarkup(pos, this.type, { ...node.attrs, latex })
|
|
166
|
+
|
|
167
|
+
return true
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
parseHTML() {
|
|
173
|
+
return [
|
|
174
|
+
{
|
|
175
|
+
tag: 'span[data-type="inline-math"]',
|
|
176
|
+
},
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
renderHTML({ HTMLAttributes }) {
|
|
181
|
+
return ['span', mergeAttributes(HTMLAttributes, { 'data-type': 'inline-math' })]
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
addInputRules() {
|
|
185
|
+
return [
|
|
186
|
+
new InputRule({
|
|
187
|
+
find: /(?<!\$)\$\$([^$\n]+)\$\$(?!\$)$/,
|
|
188
|
+
handler: ({ state, range, match }) => {
|
|
189
|
+
const [, latex] = match
|
|
190
|
+
const { tr } = state
|
|
191
|
+
const start = range.from
|
|
192
|
+
const end = range.to
|
|
193
|
+
|
|
194
|
+
tr.replaceWith(start, end, this.type.create({ latex }))
|
|
195
|
+
},
|
|
196
|
+
}),
|
|
197
|
+
]
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
addNodeView() {
|
|
201
|
+
const { katexOptions } = this.options
|
|
202
|
+
|
|
203
|
+
return ({ node, getPos }) => {
|
|
204
|
+
const wrapper = document.createElement('span')
|
|
205
|
+
wrapper.className = 'tiptap-mathematics-render'
|
|
206
|
+
|
|
207
|
+
if (this.editor.isEditable) {
|
|
208
|
+
wrapper.classList.add('tiptap-mathematics-render--editable')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
wrapper.dataset.type = 'inline-math'
|
|
212
|
+
wrapper.setAttribute('data-latex', node.attrs.latex)
|
|
213
|
+
|
|
214
|
+
function renderMath() {
|
|
215
|
+
try {
|
|
216
|
+
katex.render(node.attrs.latex, wrapper, katexOptions)
|
|
217
|
+
wrapper.classList.remove('inline-math-error')
|
|
218
|
+
} catch {
|
|
219
|
+
wrapper.textContent = node.attrs.latex
|
|
220
|
+
wrapper.classList.add('inline-math-error')
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const handleClick = (event: MouseEvent) => {
|
|
225
|
+
event.preventDefault()
|
|
226
|
+
event.stopPropagation()
|
|
227
|
+
const pos = getPos()
|
|
228
|
+
|
|
229
|
+
if (pos == null) {
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (this.options.onClick) {
|
|
234
|
+
this.options.onClick(node, pos)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (this.options.onClick) {
|
|
239
|
+
wrapper.addEventListener('click', handleClick)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
renderMath()
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
dom: wrapper,
|
|
246
|
+
destroy() {
|
|
247
|
+
wrapper.removeEventListener('click', handleClick)
|
|
248
|
+
},
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
})
|
package/src/index.ts
CHANGED
package/src/mathematics.ts
CHANGED
|
@@ -1,30 +1,70 @@
|
|
|
1
1
|
import { Extension } from '@tiptap/core'
|
|
2
|
-
import type { EditorState } from '@tiptap/pm/state'
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import { BlockMath, InlineMath } from './extensions/index.js'
|
|
5
4
|
import type { MathematicsOptions } from './types.js'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Mathematics extension for Tiptap that provides both inline and block math support using KaTeX.
|
|
8
|
+
* This extension combines the InlineMath and BlockMath extensions to provide a complete
|
|
9
|
+
* mathematical expression solution for rich text editing. It supports LaTeX syntax,
|
|
10
|
+
* custom rendering options, and interactive math nodes.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { Editor } from '@tiptap/core'
|
|
15
|
+
* import { Mathematics } from '@tiptap/extension-mathematics'
|
|
16
|
+
* import { migrateMathStrings } from '@tiptap/extension-mathematics/utils'
|
|
17
|
+
*
|
|
18
|
+
* const editor = new Editor({
|
|
19
|
+
* extensions: [
|
|
20
|
+
* Mathematics.configure({
|
|
21
|
+
* inlineOptions: {
|
|
22
|
+
* onClick: (node, pos) => {
|
|
23
|
+
* console.log('Inline math clicked:', node.attrs.latex)
|
|
24
|
+
* }
|
|
25
|
+
* },
|
|
26
|
+
* blockOptions: {
|
|
27
|
+
* onClick: (node, pos) => {
|
|
28
|
+
* console.log('Block math clicked:', node.attrs.latex)
|
|
29
|
+
* }
|
|
30
|
+
* },
|
|
31
|
+
* katexOptions: {
|
|
32
|
+
* displayMode: false,
|
|
33
|
+
* throwOnError: false,
|
|
34
|
+
* macros: {
|
|
35
|
+
* '\\RR': '\\mathbb{R}',
|
|
36
|
+
* '\\ZZ': '\\mathbb{Z}'
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* })
|
|
40
|
+
* ],
|
|
41
|
+
* content: `
|
|
42
|
+
* <p>Inline math: $E = mc^2$</p>
|
|
43
|
+
* <div data-type="block-math" data-latex="\\sum_{i=1}^{n} x_i = X"></div>
|
|
44
|
+
* `,
|
|
45
|
+
* onCreate({ editor }) {
|
|
46
|
+
* // Optional: Migrate existing math strings to math nodes
|
|
47
|
+
* migrateMathStrings(editor)
|
|
48
|
+
* }
|
|
49
|
+
* })
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
14
52
|
export const Mathematics = Extension.create<MathematicsOptions>({
|
|
15
53
|
name: 'Mathematics',
|
|
16
54
|
|
|
17
55
|
addOptions() {
|
|
18
56
|
return {
|
|
19
|
-
|
|
20
|
-
|
|
57
|
+
inlineOptions: undefined,
|
|
58
|
+
blockOptions: undefined,
|
|
21
59
|
katexOptions: undefined,
|
|
22
|
-
shouldRender: defaultShouldRender,
|
|
23
60
|
}
|
|
24
61
|
},
|
|
25
62
|
|
|
26
|
-
|
|
27
|
-
return [
|
|
63
|
+
addExtensions() {
|
|
64
|
+
return [
|
|
65
|
+
BlockMath.configure({ ...this.options.blockOptions, katexOptions: this.options.katexOptions }),
|
|
66
|
+
InlineMath.configure({ ...this.options.inlineOptions, katexOptions: this.options.katexOptions }),
|
|
67
|
+
]
|
|
28
68
|
},
|
|
29
69
|
})
|
|
30
70
|
|
package/src/types.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import type { Editor } from '@tiptap/core'
|
|
2
|
-
import type { Node } from '@tiptap/pm/model'
|
|
3
|
-
import type { EditorState } from '@tiptap/pm/state'
|
|
4
2
|
import type { KatexOptions } from 'katex'
|
|
5
3
|
|
|
4
|
+
import type { BlockMathOptions, InlineMathOptions } from './extensions'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for the Mathematics extension.
|
|
8
|
+
* This type defines the available customization options for both inline and block math rendering.
|
|
9
|
+
*/
|
|
6
10
|
export type MathematicsOptions = {
|
|
7
|
-
|
|
11
|
+
/** Configuration options specific to inline math nodes */
|
|
12
|
+
inlineOptions?: Omit<InlineMathOptions, 'katexOptions'>
|
|
13
|
+
/** Configuration options specific to block math nodes */
|
|
14
|
+
blockOptions?: Omit<BlockMathOptions, 'katexOptions'>
|
|
15
|
+
/** KaTeX-specific rendering options passed to the KaTeX library */
|
|
8
16
|
katexOptions?: KatexOptions
|
|
9
|
-
shouldRender: (state: EditorState, pos: number, node: Node) => boolean
|
|
10
17
|
}
|
|
11
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Extended mathematics options that include an editor instance.
|
|
21
|
+
* This type combines the base mathematics options with an editor reference,
|
|
22
|
+
* typically used internally by the extension for operations that require editor access.
|
|
23
|
+
*/
|
|
12
24
|
export type MathematicsOptionsWithEditor = MathematicsOptions & { editor: Editor }
|