supermemory/apps/web/components/editor/extensions.ts
2024-08-27 11:54:00 -07:00

166 lines
3.2 KiB
TypeScript

import {
AIHighlight,
CharacterCount,
CodeBlockLowlight,
GlobalDragHandle,
HorizontalRule,
Placeholder,
StarterKit,
TaskItem,
TaskList,
TiptapImage,
TiptapLink,
Twitter,
UpdatedImage,
Youtube,
} from "novel/extensions";
import suggestion from "./emoji/suggestion";
import { UploadImagesPlugin } from "novel/plugins";
import Emoji, { gitHubEmojis } from "@tiptap-pro/extension-emoji";
import TextAlign from "@tiptap/extension-text-align";
import Typography from "@tiptap/extension-typography";
import { cx } from "class-variance-authority";
import { common, createLowlight } from "lowlight";
const aiHighlight = AIHighlight;
const placeholder = Placeholder;
const tiptapLink = TiptapLink.configure({
HTMLAttributes: {
class: cx(
"text-muted-foreground underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer",
),
},
});
const tiptapImage = TiptapImage.extend({
addProseMirrorPlugins() {
return [
UploadImagesPlugin({
imageClass: cx("opacity-40 rounded-lg border border-stone-200"),
}),
];
},
}).configure({
allowBase64: true,
HTMLAttributes: {
class: cx("rounded-lg border border-muted"),
},
});
const updatedImage = UpdatedImage.configure({
HTMLAttributes: {
class: cx("rounded-lg border border-muted"),
},
});
const taskList = TaskList.configure({
HTMLAttributes: {
class: cx("not-prose pl-2 "),
},
});
const taskItem = TaskItem.configure({
HTMLAttributes: {
class: cx("flex gap-2 items-start my-4"),
},
nested: true,
});
const horizontalRule = HorizontalRule.configure({
HTMLAttributes: {
class: cx("mt-4 mb-6 border-t border-muted-foreground"),
},
});
const starterKit = StarterKit.configure({
bulletList: {
HTMLAttributes: {
class: cx("list-disc list-outside leading-3 -mt-2"),
},
},
orderedList: {
HTMLAttributes: {
class: cx("list-decimal list-outside leading-3 -mt-2"),
},
},
listItem: {
HTMLAttributes: {
class: cx("leading-normal -mb-2"),
},
},
blockquote: {
HTMLAttributes: {
class: cx("border-l-4 border-primary"),
},
},
codeBlock: {
HTMLAttributes: {
class: cx(
"rounded-md bg-muted text-muted-foreground border p-5 font-mono font-medium",
),
},
},
code: {
HTMLAttributes: {
class: cx("rounded-md bg-muted px-1.5 py-1 font-mono font-medium"),
spellcheck: "false",
},
},
horizontalRule: false,
dropcursor: {
color: "#DBEAFE",
width: 4,
},
gapcursor: false,
});
const codeBlockLowlight = CodeBlockLowlight.configure({
lowlight: createLowlight(common),
});
const youtube = Youtube.configure({
HTMLAttributes: {
class: cx("rounded-lg border border-muted"),
},
inline: false,
});
const twitter = Twitter.configure({
HTMLAttributes: {
class: cx("not-prose"),
},
inline: false,
});
const characterCount = CharacterCount.configure();
const textAlign = TextAlign.configure({
types: ["heading", "paragraph"],
});
const emojis = Emoji.configure({
emojis: gitHubEmojis,
enableEmoticons: true,
// @ts-ignore
suggestion,
});
export const defaultExtensions = [
starterKit,
placeholder,
tiptapLink,
tiptapImage,
updatedImage,
taskList,
taskItem,
horizontalRule,
aiHighlight,
codeBlockLowlight,
youtube,
twitter,
characterCount,
GlobalDragHandle,
textAlign,
Typography,
emojis,
];