plane/apps/app/components/issues/extensions.tsx

134 lines
3.4 KiB
TypeScript
Raw Normal View History

import StarterKit from "@tiptap/starter-kit";
import HorizontalRule from "@tiptap/extension-horizontal-rule";
import TiptapLink from "@tiptap/extension-link";
import TiptapImage from "@tiptap/extension-image";
import Placeholder from "@tiptap/extension-placeholder";
import TiptapUnderline from "@tiptap/extension-underline";
import TextStyle from "@tiptap/extension-text-style";
import { Color } from "@tiptap/extension-color";
import TaskItem from "@tiptap/extension-task-item";
import TaskList from "@tiptap/extension-task-list";
import { Markdown } from "tiptap-markdown";
import Highlight from "@tiptap/extension-highlight";
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
import { lowlight } from 'lowlight/lib/core'
import SlashCommand from "./slash-command";
import { InputRule } from "@tiptap/core";
import ts from 'highlight.js/lib/languages/typescript'
import 'highlight.js/styles/github-dark.css';
lowlight.registerLanguage('ts', ts)
export const TiptapExtensions = [
StarterKit.configure({
bulletList: {
HTMLAttributes: {
class: "list-disc list-outside leading-3 -mt-2",
},
},
orderedList: {
HTMLAttributes: {
class: "list-decimal list-outside leading-3 -mt-2",
},
},
listItem: {
HTMLAttributes: {
class: "leading-normal -mb-2",
},
},
blockquote: {
HTMLAttributes: {
class: "border-l-4 border-stone-700",
},
},
code: {
HTMLAttributes: {
class:
"rounded-md bg-stone-200 px-1 py-1 font-mono font-medium text-stone-900",
spellcheck: "false",
},
},
codeBlock: false,
horizontalRule: false,
dropcursor: {
color: "#DBEAFE",
width: 4,
},
gapcursor: false,
}),
CodeBlockLowlight.configure({
lowlight,
}),
HorizontalRule.extend({
addInputRules() {
return [
new InputRule({
find: /^(?:---|—-|___\s|\*\*\*\s)$/,
handler: ({ state, range }) => {
const attributes = {};
const { tr } = state;
const start = range.from;
const end = range.to;
tr.insert(start - 1, this.type.create(attributes)).delete(
tr.mapping.map(start),
tr.mapping.map(end),
);
},
}),
];
},
}).configure({
HTMLAttributes: {
class: "mb-6 border-t border-custom-border-400",
},
}),
TiptapLink.configure({
HTMLAttributes: {
class:
"text-stone-400 underline underline-offset-[3px] hover:text-stone-600 transition-colors cursor-pointer",
},
}),
TiptapImage.configure({
allowBase64: true,
HTMLAttributes: {
class: "rounded-lg border border-stone-200",
},
}),
Placeholder.configure({
placeholder: ({ node }) => {
if (node.type.name === "heading") {
return `Heading ${node.attrs.level}`;
}
return "Press '/' for commands, or 'Ctrl + Space' for AI autocomplete...";
},
includeChildren: true,
}),
SlashCommand,
TiptapUnderline,
TextStyle,
Color,
Highlight.configure({
multicolor: true,
}),
TaskList.configure({
HTMLAttributes: {
class: "not-prose pl-2",
},
}),
TaskItem.configure({
HTMLAttributes: {
class: "flex items-start my-4",
},
nested: true,
}),
Markdown.configure({
html: false,
transformCopiedText: true,
}),
];