Skip to content

Commit 7f3e00d

Browse files
authored
Merge pull request #420 from phyohtetarkar/main
feature: add mathematics extension
2 parents 770b310 + df22eaf commit 7f3e00d

File tree

8 files changed

+362
-0
lines changed

8 files changed

+362
-0
lines changed

apps/web/components/tailwind/advanced-editor.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { defaultExtensions } from "./extensions";
1717
import { ColorSelector } from "./selectors/color-selector";
1818
import { LinkSelector } from "./selectors/link-selector";
1919
import { NodeSelector } from "./selectors/node-selector";
20+
import { MathSelector } from "./selectors/math-selector";
2021
import { Separator } from "./ui/separator";
2122

2223
import { handleImageDrop, handleImagePaste } from "novel/plugins";
@@ -126,6 +127,8 @@ const TailwindAdvancedEditor = () => {
126127

127128
<LinkSelector open={openLink} onOpenChange={setOpenLink} />
128129
<Separator orientation="vertical" />
130+
<MathSelector />
131+
<Separator orientation="vertical" />
129132
<TextButtons />
130133
<Separator orientation="vertical" />
131134
<ColorSelector open={openColor} onOpenChange={setOpenColor} />

apps/web/components/tailwind/extensions.ts

+11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Twitter,
2020
UpdatedImage,
2121
Youtube,
22+
Mathematics,
2223
} from "novel/extensions";
2324
import { UploadImagesPlugin } from "novel/plugins";
2425

@@ -136,6 +137,15 @@ const twitter = Twitter.configure({
136137
inline: false,
137138
});
138139

140+
const mathematics = Mathematics.configure({
141+
HTMLAttributes: {
142+
class: cx("text-foreground rounded p-1 hover:bg-accent cursor-pointer"),
143+
},
144+
katexOptions: {
145+
throwOnError: false,
146+
},
147+
});
148+
139149
const characterCount = CharacterCount.configure();
140150

141151
export const defaultExtensions = [
@@ -151,6 +161,7 @@ export const defaultExtensions = [
151161
codeBlockLowlight,
152162
youtube,
153163
twitter,
164+
mathematics,
154165
characterCount,
155166
TiptapUnderline,
156167
MarkdownExtension,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Button } from "@/components/tailwind/ui/button";
2+
import { cn } from "@/lib/utils";
3+
import { SigmaIcon } from "lucide-react";
4+
import { useEditor } from "novel";
5+
6+
export const MathSelector = () => {
7+
const { editor } = useEditor();
8+
9+
if (!editor) return null;
10+
11+
return (
12+
<Button
13+
variant="ghost"
14+
size="sm"
15+
className="rounded-none w-12"
16+
onClick={(evt) => {
17+
if (editor.isActive("math")) {
18+
editor.chain().focus().unsetLatex().run();
19+
} else {
20+
const { from, to } = editor.state.selection;
21+
const latex = editor.state.doc.textBetween(from, to);
22+
23+
if (!latex) return;
24+
25+
editor.chain().focus().setLatex({ latex }).run();
26+
}
27+
}}
28+
>
29+
<SigmaIcon
30+
className={cn("size-4", { "text-blue-500": editor.isActive("math") })}
31+
strokeWidth={2.3}
32+
/>
33+
</Button>
34+
);
35+
};

apps/web/lib/content.ts

+105
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,111 @@ export const defaultEditorContent = {
149149
},
150150
],
151151
},
152+
{
153+
type: "listItem",
154+
content: [
155+
{
156+
type: "paragraph",
157+
content: [
158+
{
159+
type: "text",
160+
text: "Mathematical symbols with LaTeX expression:",
161+
},
162+
],
163+
},
164+
{
165+
type: "orderedList",
166+
attrs: {
167+
tight: true,
168+
start: 1,
169+
},
170+
content: [
171+
{
172+
type: "listItem",
173+
content: [
174+
{
175+
type: "paragraph",
176+
content: [
177+
{
178+
type: "math",
179+
attrs: {
180+
latex: "E = mc^2",
181+
},
182+
},
183+
],
184+
},
185+
],
186+
},
187+
{
188+
type: "listItem",
189+
content: [
190+
{
191+
type: "paragraph",
192+
content: [
193+
{
194+
type: "math",
195+
attrs: {
196+
latex: "a^2 = \\sqrt{b^2 + c^2}",
197+
},
198+
},
199+
],
200+
},
201+
],
202+
},
203+
{
204+
type: "listItem",
205+
content: [
206+
{
207+
type: "paragraph",
208+
content: [
209+
{
210+
type: "math",
211+
attrs: {
212+
latex:
213+
"\\hat{f} (\\xi)=\\int_{-\\infty}^{\\infty}f(x)e^{-2\\pi ix\\xi}dx",
214+
},
215+
},
216+
],
217+
},
218+
],
219+
},
220+
{
221+
type: "listItem",
222+
content: [
223+
{
224+
type: "paragraph",
225+
content: [
226+
{
227+
type: "math",
228+
attrs: {
229+
latex:
230+
"A=\\begin{bmatrix}a&b\\\\c&d \\end{bmatrix}",
231+
},
232+
},
233+
],
234+
},
235+
],
236+
},
237+
{
238+
type: "listItem",
239+
content: [
240+
{
241+
type: "paragraph",
242+
content: [
243+
{
244+
type: "math",
245+
attrs: {
246+
latex: "\\sum_{i=0}^n x_i",
247+
},
248+
},
249+
],
250+
},
251+
],
252+
},
253+
],
254+
},
255+
],
256+
},
152257
],
153258
},
154259
{

packages/headless/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@
7070
"react-markdown": "^8.0.7",
7171
"react-moveable": "^0.56.0",
7272
"react-tweet": "^3.2.1",
73+
"katex": "^0.16.10",
7374
"tippy.js": "^6.3.7",
7475
"tiptap-extension-global-drag-handle": "^0.1.7",
7576
"tiptap-markdown": "^0.8.9",
7677
"tunnel-rat": "^0.1.2"
7778
},
7879
"devDependencies": {
7980
"@biomejs/biome": "^1.7.2",
81+
"@types/katex": "^0.16.7",
8082
"@types/react": "^18.2.55",
8183
"@types/react-dom": "18.2.19",
8284
"tsconfig": "workspace:*",

packages/headless/src/extensions/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { Markdown } from "tiptap-markdown";
1414
import CustomKeymap from "./custom-keymap";
1515
import { ImageResizer } from "./image-resizer";
1616
import { Twitter } from "./twitter";
17+
import { Mathematics } from "./mathematics";
1718
import UpdatedImage from "./updated-image";
1819

1920
import CharacterCount from "@tiptap/extension-character-count";
@@ -81,6 +82,7 @@ export {
8182
UpdatedImage,
8283
Youtube,
8384
Twitter,
85+
Mathematics,
8486
CharacterCount,
8587
GlobalDragHandle,
8688
};

0 commit comments

Comments
 (0)