erl-mathtextx-editor 0.1.7 → 0.1.8

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.
Files changed (29) hide show
  1. package/README.md +268 -253
  2. package/dist/{CellPropertiesDialogImpl-HPT77uxM.js → CellPropertiesDialogImpl-DBgs-7H9.js} +1 -1
  3. package/dist/{ContentViewer-CWZ30KYR.js → ContentViewer-CsFSAN_B.js} +15 -15
  4. package/dist/ImageInsertDialog-B24KHrgt.js +238 -0
  5. package/dist/{InsertTableDialogImpl-DZrLgDKN.js → InsertTableDialogImpl-B6_PRu5m.js} +1 -1
  6. package/dist/{LinkDialogImpl-DTHugWZM.js → LinkDialogImpl-BTA8u_qQ.js} +60 -45
  7. package/dist/TablePropertiesDialogImpl-CuRRWS4H.js +56 -0
  8. package/dist/{TableTemplatesDialogImpl-D0sFSAKl.js → TableTemplatesDialogImpl-CU8seEdV.js} +1 -1
  9. package/dist/assets/erl-mathtextx-editor.css +1 -1
  10. package/dist/assets/viewer.css +1 -1
  11. package/dist/components/TablePropertiesDialog.d.ts +4 -0
  12. package/dist/components/TablePropertiesDialogImpl.d.ts +11 -0
  13. package/dist/core/extensions.d.ts +6 -0
  14. package/dist/erl-mathtextx-editor.js +14 -13
  15. package/dist/erl-mathtextx-editor.umd.cjs +163 -153
  16. package/dist/extensions/CustomIndent.d.ts +10 -0
  17. package/dist/extensions/IndentBackspace.d.ts +2 -0
  18. package/dist/extensions/SlashGraph.d.ts +2 -0
  19. package/dist/extensions/TableAlignPlugin.d.ts +7 -0
  20. package/dist/{index-CLGg8QXp.js → index-CB1g0gXh.js} +177 -199
  21. package/dist/index-UCSefQk0.js +53830 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/math/MathFieldView.d.ts +5 -0
  24. package/dist/{tiptap-Bc1mIOtx.js → tiptap-K3rU-Wjn.js} +4325 -3155
  25. package/dist/utils/logger.d.ts +40 -0
  26. package/dist/viewer.js +1 -1
  27. package/package.json +3 -17
  28. package/dist/ImageInsertDialog-DzLFhSDK.js +0 -217
  29. package/dist/index-Ci20X1Rj.js +0 -5281
package/README.md CHANGED
@@ -1,253 +1,268 @@
1
- # erl-mathtextx-editor
2
-
3
- **Visual Math Editor Component — Zero LaTeX Required**
4
-
5
- [![npm version](https://badge.fury.io/js/erl-mathtextx-editor.svg)](https://www.npmjs.com/package/erl-mathtextx-editor)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
-
8
- Embeddable visual math editor widget untuk CMS dan platform edukasi. User tidak perlu tahu LaTeX — semua input matematika dilakukan secara visual.
9
-
10
- ---
11
-
12
- ## ✨ Fitur Utama
13
-
14
- - 🎯 **Visual Math Keyboard** — Klik simbol, operator, template formula
15
- - 📝 **Rich Text Editor** — Bold, italic, tables, lists, links, images
16
- - 🧮 **100+ Formula Templates** — Algebra, calculus, trigonometry, chemistry
17
- - 👁️ **Content Viewer** — Read-only renderer dengan KaTeX
18
- - 🎨 **Table Editor** — 6 professional table templates
19
- - ⌨️ **Keyboard Shortcuts** — Ctrl+K (link), Ctrl+Shift+T (table), Ctrl+S (save)
20
-
21
- ---
22
-
23
- ## 📦 Installation
24
-
25
- ```bash
26
- npm install erl-mathtextx-editor
27
- ```
28
-
29
- ---
30
-
31
- ## 🚀 Quick Start
32
-
33
- ### Basic Usage
34
-
35
- ```tsx
36
- import { MathTextXEditor } from 'erl-mathtextx-editor'
37
- import 'erl-mathtextx-editor/styles'
38
-
39
- function App() {
40
- return (
41
- <MathTextXEditor
42
- onChange={(html) => console.log(html)}
43
- placeholder="Tulis soal di sini..."
44
- />
45
- )
46
- }
47
- ```
48
-
49
- ### With Save Handler
50
-
51
- ```tsx
52
- import { MathTextXEditor, getHTML } from 'erl-mathtextx-editor'
53
- import 'erl-mathtextx-editor/styles'
54
-
55
- function QuestionForm() {
56
- const handleSave = (html) => {
57
- // Send to your API
58
- fetch('/api/questions', {
59
- method: 'POST',
60
- headers: { 'Content-Type': 'application/json' },
61
- body: JSON.stringify({ content: html }),
62
- })
63
- }
64
-
65
- return (
66
- <MathTextXEditor
67
- onChange={(html) => console.log(html)}
68
- onSave={handleSave}
69
- placeholder="Tulis pertanyaan..."
70
- />
71
- )
72
- }
73
- ```
74
-
75
- ### Content Viewer (Read-Only)
76
-
77
- ```tsx
78
- import { ContentViewer } from 'erl-mathtextx-editor/viewer'
79
- import 'erl-mathtextx-editor/viewer/styles'
80
-
81
- function QuestionCard({ questionHtml }) {
82
- return (
83
- <div className="question-card">
84
- <h3>Soal 1</h3>
85
- <ContentViewer content={questionHtml} />
86
- </div>
87
- )
88
- }
89
- ```
90
-
91
- **Catatan:** Viewer memerlukan import CSS terpisah: `import 'erl-mathtextx-editor/viewer/styles'`
92
-
93
- ---
94
-
95
- ## 📖 Documentation
96
-
97
- - [Quick Start Guide](https://github.com/erlangga/richtext-editor-research/blob/main/QUICK_START.md)
98
- - [Integration Tutorial](https://github.com/erlangga/richtext-editor-research/blob/main/INTEGRATION_TUTORIAL.md)
99
-
100
- ---
101
-
102
- ## 🛠️ Tech Stack
103
-
104
- - **UI Framework:** React 18+
105
- - **Editor Engine:** TipTap / ProseMirror
106
- - **Math Input:** MathLive (WYSIWYG math)
107
- - **Math Rendering:** KaTeX
108
- - **XSS Protection:** DOMPurify
109
-
110
- ---
111
-
112
- ## 📋 Props API
113
-
114
- ### MathTextXEditor
115
-
116
- | Prop | Type | Default | Description |
117
- |------|------|---------|-------------|
118
- | `content` | `string` | `''` | Initial HTML content |
119
- | `onChange` | `(html: string) => void` | — | Callback on content change |
120
- | `onSave` | `(html: string) => void` | — | Callback on Ctrl+S |
121
- | `placeholder` | `string` | `'Tulis soal...'` | Placeholder text |
122
- | `minHeight` | `string` | `'200px'` | Minimum editor height |
123
- | `maxHeight` | `string` | — | Maximum editor height |
124
- | `onImageUpload` | `(file: File) => Promise<string>` | — | Custom image upload handler |
125
-
126
- ### ContentViewer
127
-
128
- | Prop | Type | Default | Description |
129
- |------|------|---------|-------------|
130
- | `content` | `string` | — | HTML content to render (required) |
131
- | `className` | `string` | — | Additional CSS class |
132
-
133
- ---
134
-
135
- ## ⌨️ Keyboard Shortcuts
136
-
137
- | Shortcut | Action |
138
- |----------|--------|
139
- | `Ctrl+K` | Insert/edit link |
140
- | `Ctrl+Shift+T` | Insert table |
141
- | `Ctrl+S` | Save document |
142
- | `Ctrl+B` | Bold |
143
- | `Ctrl+I` | Italic |
144
- | `Ctrl+U` | Underline |
145
-
146
- ---
147
-
148
- ## 🎯 Example: Multiple Choice Question Form
149
-
150
- ```tsx
151
- import { useState } from 'react'
152
- import { MathTextXEditor } from 'erl-mathtextx-editor'
153
- import 'erl-mathtextx-editor/styles'
154
-
155
- export default function QuestionForm() {
156
- const [question, setQuestion] = useState('')
157
- const [options, setOptions] = useState([
158
- { id: 'A', content: '', isCorrect: false },
159
- { id: 'B', content: '', isCorrect: false },
160
- { id: 'C', content: '', isCorrect: false },
161
- { id: 'D', content: '', isCorrect: false },
162
- ])
163
-
164
- const handleSubmit = async () => {
165
- await fetch('/api/questions', {
166
- method: 'POST',
167
- headers: { 'Content-Type': 'application/json' },
168
- body: JSON.stringify({ question, options }),
169
- })
170
- }
171
-
172
- return (
173
- <div>
174
- <h2>Buat Soal Pilihan Ganda</h2>
175
-
176
- {/* Question */}
177
- <MathTextXEditor
178
- content={question}
179
- onChange={setQuestion}
180
- placeholder="Tulis pertanyaan..."
181
- minHeight="150px"
182
- />
183
-
184
- {/* Options */}
185
- {options.map((option) => (
186
- <div key={option.id}>
187
- <label>
188
- <input
189
- type="radio"
190
- name="correct"
191
- checked={option.isCorrect}
192
- onChange={() => {
193
- setOptions(prev =>
194
- prev.map(o => ({
195
- ...o,
196
- isCorrect: o.id === option.id
197
- }))
198
- )
199
- }}
200
- />
201
- Opsi {option.id}
202
- </label>
203
- <MathTextXEditor
204
- content={option.content}
205
- onChange={(html) => {
206
- setOptions(prev =>
207
- prev.map(o =>
208
- o.id === option.id ? { ...o, content: html } : o
209
- )
210
- )
211
- }}
212
- placeholder={`Jawaban ${option.id}...`}
213
- minHeight="80px"
214
- />
215
- </div>
216
- ))}
217
-
218
- <button onClick={handleSubmit}>Simpan Soal</button>
219
- </div>
220
- )
221
- }
222
- ```
223
-
224
- ---
225
-
226
- ## 🔗 Links
227
-
228
- - **Website:** [erl-mathtextx-editor](https://github.com/erlangga/richtext-editor-research)
229
- - **NPM:** [erl-mathtextx-editor](https://www.npmjs.com/package/erl-mathtextx-editor)
230
- - **Issues:** [Report Bug](https://github.com/erlangga/richtext-editor-research/issues)
231
-
232
- ---
233
-
234
- ## 📄 License
235
-
236
- [MIT](https://github.com/erlangga/richtext-editor-research/blob/main/LICENSE) © Erlangga Team
237
-
238
- ---
239
-
240
- ## 🎉 Ready to Use?
241
-
242
- ```bash
243
- npm install erl-mathtextx-editor
244
- ```
245
-
246
- Then import and use:
247
-
248
- ```tsx
249
- import { MathTextXEditor } from 'erl-mathtextx-editor'
250
- import 'erl-mathtextx-editor/styles'
251
- ```
252
-
253
- Happy coding! 🚀
1
+ # erl-mathtextx-editor
2
+
3
+ **Visual Math Editor Component — Zero LaTeX Required**
4
+
5
+ [![npm version](https://badge.fury.io/js/erl-mathtextx-editor.svg)](https://www.npmjs.com/package/erl-mathtextx-editor)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ Embeddable visual math editor widget untuk CMS dan platform edukasi. User tidak perlu tahu LaTeX — semua input matematika dilakukan secara visual.
9
+
10
+ ---
11
+
12
+ ## ✨ Fitur Utama
13
+
14
+ - 🎯 **Visual Math Keyboard** — Klik simbol, operator, template formula
15
+ - 📝 **Rich Text Editor** — Bold, italic, tables, lists, links, images
16
+ - 🧮 **100+ Formula Templates** — Algebra, calculus, trigonometry, chemistry
17
+ - 👁️ **Content Viewer** — Read-only renderer dengan KaTeX
18
+ - 🎨 **Table Editor** — 6 professional table templates, column resize, cell selection
19
+ - 🖥️ **Code Blocks** — Syntax highlighting untuk berbagai bahasa pemrograman
20
+ - 📋 **Collapsible Sections** — Details/summary untuk konten tersembunyi
21
+ - ⌨️ **Keyboard Shortcuts** — Ctrl+K (link), Ctrl+Shift+T (table), Ctrl+S (save)
22
+ - 📊 **Graph Plotting** — Function plotting via Function Plot
23
+ - 🔒 **XSS Protection** — DOMPurify sanitization
24
+ - 💻 **Code Blocks** — Syntax highlighting with 100+ languages
25
+ - 📋 **Collapsible Sections** — Details/summary for hidden content
26
+
27
+ ---
28
+
29
+ ## 📦 Installation
30
+
31
+ ```bash
32
+ npm install erl-mathtextx-editor
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 🚀 Quick Start
38
+
39
+ ### Basic Usage
40
+
41
+ ```tsx
42
+ import { MathTextXEditor } from 'erl-mathtextx-editor'
43
+ import 'erl-mathtextx-editor/styles'
44
+
45
+ function App() {
46
+ return (
47
+ <MathTextXEditor
48
+ onChange={(html) => console.log(html)}
49
+ placeholder="Tulis soal di sini..."
50
+ />
51
+ )
52
+ }
53
+ ```
54
+
55
+ ### With Save Handler
56
+
57
+ ```tsx
58
+ import { MathTextXEditor } from 'erl-mathtextx-editor'
59
+ import 'erl-mathtextx-editor/styles'
60
+
61
+ function QuestionForm() {
62
+ const handleSave = (html) => {
63
+ fetch('/api/questions', {
64
+ method: 'POST',
65
+ headers: { 'Content-Type': 'application/json' },
66
+ body: JSON.stringify({ content: html }),
67
+ })
68
+ }
69
+
70
+ return (
71
+ <MathTextXEditor
72
+ onChange={(html) => console.log(html)}
73
+ onSave={handleSave}
74
+ placeholder="Tulis pertanyaan..."
75
+ />
76
+ )
77
+ }
78
+ ```
79
+
80
+ ### Content Viewer (Read-Only)
81
+
82
+ ```tsx
83
+ import { ContentViewer } from 'erl-mathtextx-editor/viewer'
84
+ import 'erl-mathtextx-editor/viewer/styles'
85
+
86
+ function QuestionCard({ questionHtml }) {
87
+ return (
88
+ <div className="question-card">
89
+ <h3>Soal 1</h3>
90
+ <ContentViewer content={questionHtml} />
91
+ </div>
92
+ )
93
+ }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 📋 Props API
99
+
100
+ ### MathTextXEditor
101
+
102
+ | Prop | Type | Default | Description |
103
+ |------|------|---------|-------------|
104
+ | `content` | `string` | `''` | Initial HTML content |
105
+ | `onChange` | `(html: string) => void` | — | Callback on content change |
106
+ | `onSave` | `(html: string) => void` | — | Callback on Ctrl+S |
107
+ | `onImageUpload` | `(file: File) => Promise<string>` | — | Custom image upload handler |
108
+ | `placeholder` | `string` | `'Tulis soal...'` | Placeholder text |
109
+ | `minHeight` | `string` | `'200px'` | Minimum editor height |
110
+ | `maxHeight` | `string` | — | Maximum editor height |
111
+ | `autoFocus` | `boolean` | `false` | Auto-focus editor on mount |
112
+ | `toolbarMode` | `'basic' \| 'advanced'` | `'basic'` | Toolbar preset |
113
+ | `educationLevel` | `'sd' \| 'smp' \| 'sma' \| 'all'` | `'all'` | Filter math templates by level |
114
+
115
+ ### ContentViewer
116
+
117
+ | Prop | Type | Default | Description |
118
+ |------|------|---------|-------------|
119
+ | `content` | `string` | — | HTML content to render (required) |
120
+ | `className` | `string` | — | Additional CSS class |
121
+
122
+ ---
123
+
124
+ ## 📦 Exports
125
+
126
+ ### Main Package (`erl-mathtextx-editor`)
127
+
128
+ ```tsx
129
+ import {
130
+ MathTextXEditor,
131
+ ContentViewer,
132
+ getHTML,
133
+ toCompatibleHTML,
134
+ sanitizeCKEditorHTML,
135
+ MathTypeDialog,
136
+ TemplatePanel,
137
+ mathTemplates,
138
+ getTemplatesByLevel,
139
+ getTemplatesByCategory,
140
+ getTemplateCategories,
141
+ } from 'erl-mathtextx-editor'
142
+
143
+ import 'erl-mathtextx-editor/styles'
144
+ ```
145
+
146
+ ### Viewer Only (`erl-mathtextx-editor/viewer`)
147
+
148
+ ```tsx
149
+ import { ContentViewer } from 'erl-mathtextx-editor/viewer'
150
+ import 'erl-mathtextx-editor/viewer/styles'
151
+ ```
152
+
153
+ ---
154
+
155
+ ## ⌨️ Keyboard Shortcuts
156
+
157
+ | Shortcut | Action |
158
+ |----------|--------|
159
+ | `Ctrl+B` | Bold |
160
+ | `Ctrl+I` | Italic |
161
+ | `Ctrl+U` | Underline |
162
+ | `Ctrl+K` | Insert/edit link |
163
+ | `Ctrl+Shift+T` | Insert table |
164
+ | `Ctrl+S` | Save document |
165
+ | `Tab` | Indent paragraph (at start) / Insert 4 spaces (in middle) |
166
+ | `Shift+Tab` | Outdent paragraph |
167
+ | `Backspace` | Outdent (if indented) / Join with previous paragraph |
168
+
169
+ ---
170
+
171
+ ## 🎯 Example: Multiple Choice Question Form
172
+
173
+ ```tsx
174
+ import { useState } from 'react'
175
+ import { MathTextXEditor } from 'erl-mathtextx-editor'
176
+ import 'erl-mathtextx-editor/styles'
177
+
178
+ export default function QuestionForm() {
179
+ const [question, setQuestion] = useState('')
180
+ const [options, setOptions] = useState([
181
+ { id: 'A', content: '', isCorrect: false },
182
+ { id: 'B', content: '', isCorrect: false },
183
+ { id: 'C', content: '', isCorrect: false },
184
+ { id: 'D', content: '', isCorrect: false },
185
+ ])
186
+
187
+ const handleSubmit = async () => {
188
+ await fetch('/api/questions', {
189
+ method: 'POST',
190
+ headers: { 'Content-Type': 'application/json' },
191
+ body: JSON.stringify({ question, options }),
192
+ })
193
+ }
194
+
195
+ return (
196
+ <div>
197
+ <h2>Buat Soal Pilihan Ganda</h2>
198
+
199
+ <MathTextXEditor
200
+ content={question}
201
+ onChange={setQuestion}
202
+ placeholder="Tulis pertanyaan..."
203
+ minHeight="150px"
204
+ />
205
+
206
+ {options.map((option) => (
207
+ <div key={option.id}>
208
+ <label>
209
+ <input
210
+ type="radio"
211
+ name="correct"
212
+ checked={option.isCorrect}
213
+ onChange={() => {
214
+ setOptions(prev =>
215
+ prev.map(o => ({
216
+ ...o,
217
+ isCorrect: o.id === option.id
218
+ }))
219
+ )
220
+ }}
221
+ />
222
+ Opsi {option.id}
223
+ </label>
224
+ <MathTextXEditor
225
+ content={option.content}
226
+ onChange={(html) => {
227
+ setOptions(prev =>
228
+ prev.map(o =>
229
+ o.id === option.id ? { ...o, content: html } : o
230
+ )
231
+ )
232
+ }}
233
+ placeholder={`Jawaban ${option.id}...`}
234
+ minHeight="80px"
235
+ />
236
+ </div>
237
+ ))}
238
+
239
+ <button onClick={handleSubmit}>Simpan Soal</button>
240
+ </div>
241
+ )
242
+ }
243
+ ```
244
+
245
+ ---
246
+
247
+ ## 🛠️ Tech Stack
248
+
249
+ - **UI Framework:** React 18+
250
+ - **Editor Engine:** TipTap / ProseMirror
251
+ - **Math Input:** MathLive (WYSIWYG math)
252
+ - **Math Rendering:** KaTeX
253
+ - **XSS Protection:** DOMPurify
254
+ - **Graph Plotting:** Function Plot
255
+
256
+ ---
257
+
258
+ ## 📄 License
259
+
260
+ [MIT](https://github.com/erlangga/richtext-editor-research/blob/main/LICENSE) © Erlangga Team
261
+
262
+ ---
263
+
264
+ ## 🔗 Links
265
+
266
+ - **NPM:** [erl-mathtextx-editor](https://www.npmjs.com/package/erl-mathtextx-editor)
267
+ - **Source:** [GitHub Repository](https://github.com/erlangga/richtext-editor-research)
268
+ - **Issues:** [Report Bug](https://github.com/erlangga/richtext-editor-research/issues)
@@ -1,6 +1,6 @@
1
1
  import { jsx as t, jsxs as l } from "react/jsx-runtime";
2
2
  import z, { useId as H, useRef as A, useCallback as b, useState as d, useEffect as V } from "react";
3
- import { u as B } from "./index-Ci20X1Rj.js";
3
+ import { u as B } from "./index-UCSefQk0.js";
4
4
  const M = z.memo(({
5
5
  isOpen: s,
6
6
  initialData: i = {},
@@ -1,44 +1,44 @@
1
- import { jsx as n } from "react/jsx-runtime";
2
- import { useRef as o, useMemo as i, useEffect as m } from "react";
1
+ import { jsx as o } from "react/jsx-runtime";
2
+ import { useRef as r, useMemo as i, useEffect as m } from "react";
3
3
  import { p as s, k as l } from "./viewer-deps-CjbAqdti.js";
4
- import "./viewer-styles.js";
5
4
  function c(t) {
6
5
  const e = t.getAttribute("data-latex") || t.getAttribute("latex");
7
6
  if (!e) return;
8
- const a = t.classList.contains("mtx-math-block");
7
+ const n = t.classList.contains("mtx-math-block");
9
8
  try {
10
9
  l.render(e, t, {
11
10
  throwOnError: !1,
12
- displayMode: a,
11
+ displayMode: n,
13
12
  output: "htmlAndMathml"
14
13
  });
15
14
  } catch {
16
- t.textContent = a ? `$$${e}$$` : `$${e}$`;
15
+ t.textContent = n ? `$$${e}$$` : `$${e}$`;
17
16
  }
18
17
  }
19
- function x({ content: t, className: e }) {
20
- const a = o(null), r = i(
18
+ function p({ content: t, className: e }) {
19
+ const n = r(null), a = i(
21
20
  () => s.sanitize(t, {
22
21
  ADD_TAGS: ["math-field", "span", "div"],
23
22
  ADD_ATTR: ["data-latex", "latex", "data-type", "data-mathml"],
24
- FORBID_TAGS: ["script", "style", "iframe", "object", "embed"]
23
+ FORBID_TAGS: ["script", "style", "iframe", "object", "embed"],
24
+ FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onmouseout", "onfocus", "onblur"]
25
25
  }),
26
26
  [t]
27
27
  );
28
28
  return m(() => {
29
- if (!a.current) return;
30
- a.current.querySelectorAll(
29
+ if (!n.current) return;
30
+ n.current.querySelectorAll(
31
31
  '.mtx-math-inline, .mtx-math-block, [data-type="math-inline"], [data-type="math-block"]'
32
32
  ).forEach(c);
33
- }, [r]), /* @__PURE__ */ n(
33
+ }, [a]), /* @__PURE__ */ o(
34
34
  "div",
35
35
  {
36
- ref: a,
36
+ ref: n,
37
37
  className: `mtx-content-viewer${e ? ` ${e}` : ""}`,
38
- dangerouslySetInnerHTML: { __html: r }
38
+ dangerouslySetInnerHTML: { __html: a }
39
39
  }
40
40
  );
41
41
  }
42
42
  export {
43
- x as C
43
+ p as C
44
44
  };