deer-flow/web/src/components/editor/extensions.tsx
JeffJiang 8802eea0ba
fix: report editor styles (#163)
* fix: report editor styles
2025-05-15 15:18:01 +08:00

190 lines
4.1 KiB
TypeScript

// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
import {
AIHighlight,
CharacterCount,
CodeBlockLowlight,
Color,
CustomKeymap,
GlobalDragHandle,
HighlightExtension,
HorizontalRule,
Mathematics,
Placeholder,
StarterKit,
TaskItem,
TaskList,
TextStyle,
TiptapImage,
TiptapLink,
TiptapUnderline,
Twitter,
UpdatedImage,
UploadImagesPlugin,
Youtube,
} from "novel";
import { Markdown } from "tiptap-markdown";
import { Table } from "@tiptap/extension-table";
import { TableHeader } from "@tiptap/extension-table-header";
import { TableRow } from "@tiptap/extension-table-row";
import { TableCell } from "@tiptap/extension-table-cell";
import { cx } from "class-variance-authority";
import { common, createLowlight } from "lowlight";
//TODO I am using cx here to get tailwind autocomplete working, idk if someone else can write a regex to just capture the class key in objects
const aiHighlight = AIHighlight;
//You can overwrite the placeholder with your own configuration
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: {},
});
const starterKit = StarterKit.configure({
bulletList: {
HTMLAttributes: {},
},
orderedList: {
HTMLAttributes: {
class: cx("list-decimal list-outside leading-3 -mt-2"),
},
},
listItem: {
HTMLAttributes: {},
},
blockquote: {
HTMLAttributes: {
class: cx("border-l-4 border-primary"),
},
},
codeBlock: false,
code: {
HTMLAttributes: {
spellcheck: "false",
},
},
horizontalRule: false,
dropcursor: {
color: "#DBEAFE",
width: 4,
},
gapcursor: false,
});
const codeBlockLowlight = CodeBlockLowlight.configure({
// configure lowlight: common / all / use highlightJS in case there is a need to specify certain language grammars only
// common: covers 37 language grammars which should be good enough in most cases
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 mathematics = Mathematics.configure({
HTMLAttributes: {
class: cx("text-foreground rounded p-1 hover:bg-accent cursor-pointer"),
},
katexOptions: {
throwOnError: false,
},
});
const characterCount = CharacterCount.configure();
const table = Table.configure();
const tableRow = TableRow.configure();
const tableCell = TableCell.configure();
const tableHeader = TableHeader.configure();
const markdownExtension = Markdown.configure({
html: true,
tightLists: true,
tightListClass: "tight",
bulletListMarker: "-",
linkify: false,
breaks: false,
transformPastedText: false,
transformCopiedText: false,
});
const globalDragHandle = GlobalDragHandle.configure({});
export const defaultExtensions = [
starterKit,
placeholder,
tiptapLink,
updatedImage,
taskList,
taskItem,
table,
tableRow,
tableCell,
tableHeader,
horizontalRule,
aiHighlight,
codeBlockLowlight,
youtube,
twitter,
mathematics,
characterCount,
TiptapUnderline,
markdownExtension,
HighlightExtension,
TextStyle,
Color,
CustomKeymap,
globalDragHandle,
];