> = ({
16 | editor,
17 | mimeTypes,
18 | onOK
19 | }) => {
20 | const getFile = useCallback(async () => {
21 | const blob = await fileOpen({
22 | mimeTypes
23 | });
24 | const editorProvider = getEditorProvider(editor);
25 | const url = await editorProvider.fileProvider.uploadFile(blob);
26 | onOK(url);
27 | }, [editor, mimeTypes, onOK]);
28 |
29 | return (
30 |
31 |
32 |
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const PARSE_HTML_PRIORITY_LOWEST = 1;
2 | export const PARSE_HTML_PRIORITY_DEFAULT = 50;
3 | export const PARSE_HTML_PRIORITY_HIGHEST = 100;
4 | export const EXTENSION_PRIORITY_LOWER = 75;
5 | export const EXTENSION_PRIORITY_DEFAULT = 100;
6 | export const EXTENSION_PRIORITY_HIGHEST = 200;
7 |
8 | export const ZINDEX_DEFAULT = 10;
9 | export const ZINDEX_MIDDLE = 1500;
10 | export const ZINDEX_HIGHEST = 10000;
11 |
12 | export const MIN_ZOOM = 0.1;
13 | export const MAX_ZOOM = 2;
14 | export const ZOOM_STEP = 0.15;
15 |
--------------------------------------------------------------------------------
/src/editor/collaboration.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, useMemo } from "react";
2 | import { Editor } from "@tiptap/core";
3 | import { HocuspocusProvider } from "@hocuspocus/provider";
4 |
5 | import { Collaboration } from "../extensions/collaboration";
6 | import { CollaborationCursor } from "../extensions/collaboration-cursor";
7 |
8 | import { EditorRender, EditorRenderProps } from "./render";
9 |
10 | import { getUserColor } from "./utilities";
11 |
12 | export interface CollaborationEditorProps extends EditorRenderProps {
13 | id: string;
14 | url: string;
15 | token: string;
16 | }
17 |
18 | export const CollaborationEditor = forwardRef<
19 | Editor | null,
20 | React.PropsWithChildren
21 | >((props, ref) => {
22 | const { id, url, token, extensions, userProvider, ...restProps } = props;
23 |
24 | const hocuspocusProvider = useMemo(() => {
25 | return new HocuspocusProvider({
26 | url,
27 | name: id,
28 | token,
29 | maxAttempts: 1
30 | } as any);
31 | }, [id, url, token]);
32 |
33 | const currentUser = useMemo(() => {
34 | return userProvider.getCurrentUser() ?? {};
35 | }, [userProvider]);
36 |
37 | if (!hocuspocusProvider) return loading
;
38 |
39 | return (
40 |
58 | );
59 | });
60 |
61 | CollaborationEditor.displayName = "CollaborationEditor";
62 |
--------------------------------------------------------------------------------
/src/editor/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./collaboration";
2 | export * from "./render";
3 |
--------------------------------------------------------------------------------
/src/editor/kit.ts:
--------------------------------------------------------------------------------
1 | import { AnyExtension, Node } from "@tiptap/core";
2 |
3 | import { Focus } from "../extensions/focus";
4 | import { Loading } from "../extensions/loading";
5 | import { Paragraph } from "../extensions/paragraph";
6 | import { Text } from "../extensions/text";
7 | import { HardBreak } from "../extensions/hard-break";
8 | import { TrailingNode } from "../extensions/trailing-node";
9 | import { Perf } from "../extensions/perf";
10 |
11 | export interface EditorKit {
12 | schema: string;
13 | extensions: Array;
14 | }
15 |
16 | export const resolveEditorKit = (props: EditorKit) => {
17 | const { schema, extensions } = props;
18 |
19 | const Doc = Node.create({
20 | name: "doc",
21 | topNode: true,
22 | content: schema
23 | });
24 |
25 | const runtimeExtensions = [
26 | Doc,
27 | Paragraph,
28 | Text,
29 | HardBreak,
30 | Focus,
31 | Loading,
32 | TrailingNode,
33 | Perf,
34 | ...extensions.flat()
35 | ];
36 |
37 | return runtimeExtensions;
38 | };
39 |
--------------------------------------------------------------------------------
/src/editor/provider.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 |
3 | export interface User {
4 | id: string | number;
5 | name: string;
6 | avatar: string;
7 | [key: string]: unknown;
8 | }
9 |
10 | export interface EditorProvider {
11 | /**
12 | * 用户信息
13 | */
14 | userProvider: {
15 | /**
16 | * 获取当前用户
17 | */
18 | getCurrentUser: () => User;
19 |
20 | /**
21 | * 获取用户列表
22 | */
23 | getUsers: (query: string) => Promise | User[];
24 | };
25 | /**
26 | * 文件上传
27 | */
28 | fileProvider: {
29 | uploadFile: (file: Blob) => Promise;
30 | };
31 | }
32 |
33 | export const getEditorProvider = (editor: Editor): EditorProvider => {
34 | // @ts-ignore
35 | return editor.options.editorProps.editorProvider;
36 | };
37 |
--------------------------------------------------------------------------------
/src/editor/render.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, useImperativeHandle } from "react";
2 | import { useEditor, EditorContent } from "@tiptap/react";
3 | import { ThemeProvider } from "styled-components";
4 |
5 | import { StyledEditor } from "../styles/editor";
6 |
7 | import { resolveEditorKit, EditorKit } from "./kit";
8 | import { EditorProvider } from "./provider";
9 | import { Content, Editor } from "@tiptap/core";
10 | import light from "../styles/theme";
11 |
12 | export interface EditorRenderProps extends EditorProvider, EditorKit {
13 | content?: Content;
14 | }
15 |
16 | export const EditorRender = forwardRef<
17 | Editor | null,
18 | React.PropsWithChildren
19 | >((props, ref) => {
20 | const {
21 | schema,
22 | content,
23 | extensions,
24 | userProvider,
25 | fileProvider,
26 | children
27 | } = props;
28 |
29 | const editorProvider: EditorProvider = {
30 | userProvider,
31 | fileProvider
32 | };
33 |
34 | const editor = useEditor(
35 | {
36 | content,
37 | extensions: resolveEditorKit({ schema, extensions }),
38 | editorProps: {
39 | attributes: {
40 | class: "magic-editor",
41 | spellcheck: "false",
42 | suppressContentEditableWarning: "true"
43 | },
44 | // @ts-ignore
45 | editorProvider,
46 | theme: light
47 | },
48 | onCreate(props) {
49 | props.editor.view.focus();
50 | },
51 | onUpdate(props) {
52 | // console.log(props.editor.getHTML());
53 | }
54 | },
55 | []
56 | );
57 |
58 | useImperativeHandle(ref, () => editor as Editor);
59 |
60 | return (
61 |
62 | {children}
63 |
64 |
65 |
66 |
67 | );
68 | });
69 |
70 | EditorRender.displayName = "EditorRender";
71 |
--------------------------------------------------------------------------------
/src/editor/theme.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 |
3 | export const getEditorTheme = (editor: Editor) => {
4 | // @ts-ignore
5 | return editor.options.editorProps.theme;
6 | };
7 |
--------------------------------------------------------------------------------
/src/editor/utilities.ts:
--------------------------------------------------------------------------------
1 | const colors = [
2 | "#47A1FF",
3 | "#59CB74",
4 | "#FFB952",
5 | "#FC6980",
6 | "#6367EC",
7 | "#DA65CC",
8 | "#FBD54A",
9 | "#ADDF84",
10 | "#6CD3FF",
11 | "#659AEC",
12 | "#9F8CF1",
13 | "#ED8CCE",
14 | "#A2E5FF",
15 | "#4DCCCB",
16 | "#F79452",
17 | "#84E0BE",
18 | "#5982F6",
19 | "#E37474",
20 | "#3FDDC7",
21 | "#9861E5"
22 | ];
23 |
24 | const total = colors.length;
25 |
26 | export const getUserColor = () => colors[~~(Math.random() * total)];
27 |
--------------------------------------------------------------------------------
/src/extensions/blockquote/blockquote.ts:
--------------------------------------------------------------------------------
1 | import { wrappingInputRule } from "@tiptap/core";
2 | import { Blockquote as BuiltInBlockquote } from "@tiptap/extension-blockquote";
3 |
4 | const multilineInputRegex = /^\s*>>>\s$/gm;
5 |
6 | export const Blockquote = BuiltInBlockquote.extend({
7 | addInputRules() {
8 | return [
9 | // eslint-disable-next-line no-unsafe-optional-chaining
10 | // @ts-ignore
11 | ...this.parent?.(),
12 | wrappingInputRule({
13 | find: multilineInputRegex,
14 | type: this.type,
15 | getAttributes: () => ({ multiline: true })
16 | })
17 | ];
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/src/extensions/blockquote/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./blockquote";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/blockquote/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Tooltip } from "../../components/tooltip";
5 | import { Button } from "../../components/button";
6 | import { IconBlockquote } from "../../icons";
7 | import { useActive } from "../../hooks/use-active";
8 |
9 | import { Blockquote as BlockquoteExtension } from "./blockquote";
10 | import i18n from "../../i18n";
11 |
12 | export const BlockquoteStaticMenu: React.FC<{ editor: Editor }> = ({
13 | editor
14 | }) => {
15 | const isBlockquoteActive = useActive(editor, BlockquoteExtension.name);
16 |
17 | const toggleBlockquote = useCallback(
18 | () =>
19 | editor
20 | .chain()
21 | .focus()
22 | .toggleBlockquote()
23 | .run(),
24 | [editor]
25 | );
26 |
27 | return (
28 |
29 | }
32 | onClick={toggleBlockquote}
33 | />
34 |
35 | );
36 | };
37 |
--------------------------------------------------------------------------------
/src/extensions/bold/bold.ts:
--------------------------------------------------------------------------------
1 | import { Bold } from "@tiptap/extension-bold";
2 |
3 | export { Bold };
4 |
--------------------------------------------------------------------------------
/src/extensions/bold/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./bold";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/bold/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconBold } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { Bold as BoldExtension } from "./bold";
9 | import i18n from "../../i18n";
10 |
11 | export const BoldStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isBoldActive = useActive(editor, BoldExtension.name);
13 |
14 | const toggleBold = useCallback(
15 | () =>
16 | editor
17 | .chain()
18 | .focus()
19 | .toggleBold()
20 | .run(),
21 | [editor]
22 | );
23 |
24 | return (
25 |
26 | } onClick={toggleBold} active={isBoldActive} />
27 |
28 | );
29 | };
30 |
--------------------------------------------------------------------------------
/src/extensions/bullet-list/bullet-list.ts:
--------------------------------------------------------------------------------
1 | import { BulletList } from "@tiptap/extension-bullet-list";
2 |
3 | export { BulletList };
4 |
--------------------------------------------------------------------------------
/src/extensions/bullet-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./bullet-list";
2 |
--------------------------------------------------------------------------------
/src/extensions/code-block/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./code-block";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/code-block/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconCodeBlock } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 | import { CodeBlock as CodeBlockExtension } from "./code-block";
8 | import i18n from "../../i18n";
9 |
10 | export const CodeBlockStaticMenu: React.FC<{ editor: Editor }> = ({
11 | editor
12 | }) => {
13 | const isCodeBlockActive = useActive(editor, CodeBlockExtension.name);
14 |
15 | const toggleCodeBlock = useCallback(
16 | () =>
17 | editor
18 | .chain()
19 | .focus()
20 | .toggleCodeBlock()
21 | .run(),
22 | [editor]
23 | );
24 |
25 | return (
26 |
27 | }
29 | onClick={toggleCodeBlock}
30 | active={isCodeBlockActive}
31 | />
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/src/extensions/code/code.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | import BuiltInCode from "@tiptap/extension-code";
3 | import codemark from "prosemirror-codemark";
4 |
5 | export const Code = BuiltInCode.extend({});
6 |
7 | export const CodeMarkPlugin = Extension.create({
8 | name: "codemarkPlugin",
9 |
10 | // @ts-ignore
11 | addProseMirrorPlugins() {
12 | return codemark({ markType: this.editor.schema.marks.code });
13 | }
14 | });
15 |
16 | export const CodeExtensions = [Code, CodeMarkPlugin];
17 |
--------------------------------------------------------------------------------
/src/extensions/code/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./code";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/code/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Tooltip, Button } from "../../components";
5 | import { IconCode } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { Code as CodeExtension } from "./code";
9 | import i18n from "../../i18n";
10 |
11 | export const CodeStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isCodeActive = useActive(editor, CodeExtension.name);
13 |
14 | const toggleCode = useCallback(
15 | () =>
16 | editor
17 | .chain()
18 | .focus()
19 | .toggleCode()
20 | .run(),
21 | [editor]
22 | );
23 |
24 | return (
25 |
26 | } onClick={toggleCode} active={isCodeActive} />
27 |
28 | );
29 | };
30 |
--------------------------------------------------------------------------------
/src/extensions/collaboration-cursor/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./collaboration-cursor";
2 |
--------------------------------------------------------------------------------
/src/extensions/collaboration/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./collaboration";
2 | export * from "./is-change-origin";
3 |
--------------------------------------------------------------------------------
/src/extensions/collaboration/is-change-origin.ts:
--------------------------------------------------------------------------------
1 | import { Transaction } from "prosemirror-state";
2 | import { ySyncPluginKey } from "y-prosemirror";
3 |
4 | export function isChangeOrigin(transaction: Transaction): boolean {
5 | return !!transaction.getMeta(ySyncPluginKey);
6 | }
7 |
--------------------------------------------------------------------------------
/src/extensions/collaboration/y-prosemirror/index.js:
--------------------------------------------------------------------------------
1 | export * from "./plugins/cursor-plugin.js";
2 | export {
3 | defaultYSyncPluginOpts,
4 | ySyncPlugin,
5 | isVisible,
6 | getRelativeSelection,
7 | ProsemirrorBinding
8 | } from "./plugins/sync-plugin.js";
9 | export * from "./plugins/undo-plugin.js";
10 | export * from "./plugins/keys.js";
11 | export {
12 | absolutePositionToRelativePosition,
13 | relativePositionToAbsolutePosition,
14 | setMeta,
15 | prosemirrorJSONToYDoc,
16 | yDocToProsemirrorJSON,
17 | yDocToProsemirror,
18 | prosemirrorToYDoc,
19 | prosemirrorJSONToYXmlFragment,
20 | yXmlFragmentToProsemirrorJSON,
21 | yXmlFragmentToProsemirror,
22 | prosemirrorToYXmlFragment
23 | } from "./lib.js";
24 |
--------------------------------------------------------------------------------
/src/extensions/collaboration/y-prosemirror/plugins/keys.js:
--------------------------------------------------------------------------------
1 |
2 | import { PluginKey } from 'prosemirror-state' // eslint-disable-line
3 |
4 | /**
5 | * The unique prosemirror plugin key for syncPlugin
6 | *
7 | * @public
8 | */
9 | export const ySyncPluginKey = new PluginKey('y-sync')
10 |
11 | /**
12 | * The unique prosemirror plugin key for undoPlugin
13 | *
14 | * @public
15 | */
16 | export const yUndoPluginKey = new PluginKey('y-undo')
17 |
18 | /**
19 | * The unique prosemirror plugin key for cursorPlugin
20 | *
21 | * @public
22 | */
23 | export const yCursorPluginKey = new PluginKey('yjs-cursor')
24 |
--------------------------------------------------------------------------------
/src/extensions/columns/column.ts:
--------------------------------------------------------------------------------
1 | import { Node, mergeAttributes } from "@tiptap/core";
2 |
3 | export const Column = Node.create({
4 | name: "column",
5 | content: "block+",
6 | isolating: true,
7 |
8 | addOptions() {
9 | return {
10 | HTMLAttributes: {
11 | class: "column"
12 | }
13 | };
14 | },
15 |
16 | addAttributes() {
17 | return {
18 | index: {
19 | default: 0,
20 | parseHTML: element => element.getAttribute("index")
21 | }
22 | };
23 | },
24 |
25 | parseHTML() {
26 | return [
27 | {
28 | tag: "div[class=column]"
29 | }
30 | ];
31 | },
32 |
33 | renderHTML({ HTMLAttributes }) {
34 | return [
35 | "div",
36 | mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
37 | 0
38 | ];
39 | }
40 | });
41 |
--------------------------------------------------------------------------------
/src/extensions/columns/index.ts:
--------------------------------------------------------------------------------
1 | import { Columns } from "./columns";
2 | import { Column } from "./column";
3 | export * from "./menu";
4 |
5 | export const ColumnsExtensions = [Columns, Column];
6 |
--------------------------------------------------------------------------------
/src/extensions/columns/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./bubble";
2 | export * from "./static";
3 |
--------------------------------------------------------------------------------
/src/extensions/columns/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Tooltip, Button } from "../../../components";
5 | import { IconColumns } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 |
8 | import { Columns as ColumnsExtension } from "../columns";
9 | import i18n from "../../../i18n";
10 |
11 | export const ColumnsStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isColumnsActive = useActive(editor, ColumnsExtension.name);
13 |
14 | const insertColumns = useCallback(
15 | () =>
16 | editor
17 | .chain()
18 | .focus()
19 | .insertColumns()
20 | .run(),
21 | [editor]
22 | );
23 |
24 | return (
25 |
26 | }
28 | onClick={insertColumns}
29 | active={isColumnsActive}
30 | />
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/src/extensions/dragable/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./dragable";
2 |
--------------------------------------------------------------------------------
/src/extensions/dropcursor/dropcursor.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | import { dropCursor } from "./prosemirror-dropcursor";
3 |
4 | export interface DropcursorOptions {
5 | color: string | undefined;
6 | width: number | undefined;
7 | class: string | undefined;
8 | }
9 |
10 | export const DropCursor = Extension.create({
11 | name: "dropCursor",
12 |
13 | addOptions() {
14 | return {
15 | color: "currentColor",
16 | width: 1,
17 | class: undefined
18 | };
19 | },
20 |
21 | // @ts-ignore
22 | addProseMirrorPlugins() {
23 | return [dropCursor(this.options)];
24 | }
25 | }).configure({
26 | width: 2,
27 | class: "dropcursor",
28 | color: "skyblue"
29 | });
30 |
--------------------------------------------------------------------------------
/src/extensions/dropcursor/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./dropcursor";
2 |
--------------------------------------------------------------------------------
/src/extensions/excalidraw/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./excalidraw";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/excalidraw/menu/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | import { useCallback } from "react";
4 |
5 | import { Tooltip, BubbleMenu, Button, Space } from "../../../components";
6 | import { IconEdit } from "../../../icons";
7 | import { Excalidraw as ExcalidrawExtension } from "../excalidraw";
8 |
9 | import { showExcalidrawEditor } from "./edit";
10 | import i18n from "../../../i18n";
11 |
12 | interface IProps {
13 | editor: Editor;
14 | }
15 |
16 | export const ExcalidrawBubbleMenu: React.FC = ({ editor }) => {
17 | const shouldShow = useCallback(
18 | () => editor.isActive(ExcalidrawExtension.name),
19 | [editor]
20 | );
21 |
22 | const openEditModal = useCallback(() => {
23 | showExcalidrawEditor(editor);
24 | }, [editor]);
25 |
26 | return (
27 |
28 |
29 |
30 | } onClick={openEditModal} />
31 |
32 |
33 |
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/src/extensions/excalidraw/menu/edit.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { Editor } from "@tiptap/core";
4 | import { ThemeProvider } from "styled-components";
5 |
6 | import {
7 | DEFAULT_EXCALIDRAW_DATA,
8 | Excalidraw as ExcalidrawExtension
9 | } from "../excalidraw";
10 | import { isNodeActive } from "../../../utilities";
11 |
12 | import { ExcalidrawSettingModal } from "./modal";
13 | import { getEditorTheme } from "../../../editor/theme";
14 |
15 | export const showExcalidrawEditor = (editor: Editor) => {
16 | // @ts-ignore
17 | const isInExcalidraw = isNodeActive(editor, ExcalidrawExtension.name);
18 |
19 | if (!isInExcalidraw) {
20 | editor
21 | .chain()
22 | .insertExcalidraw({ data: DEFAULT_EXCALIDRAW_DATA })
23 | .run();
24 | }
25 |
26 | const attrs = editor.getAttributes(ExcalidrawExtension.name);
27 | const data = JSON.parse(attrs.data);
28 | const blockId = attrs.blockId;
29 |
30 | const div = document.createElement("div");
31 | editor.options.element.appendChild(div);
32 |
33 | ReactDOM.render(
34 |
35 | {
40 | ReactDOM.unmountComponentAtNode(div);
41 | div.remove();
42 | }}
43 | />
44 | ,
45 | div
46 | );
47 | };
48 |
--------------------------------------------------------------------------------
/src/extensions/excalidraw/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/src/extensions/excalidraw/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconExcalidraw } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Excalidraw as ExcalidrawExtension } from "../excalidraw";
8 |
9 | import { showExcalidrawEditor } from "./edit";
10 | import i18n from "../../../i18n";
11 |
12 | export const ExcalidrawStaticMenu: React.FC<{ editor: Editor }> = ({
13 | editor
14 | }) => {
15 | const isActive = useActive(editor, ExcalidrawExtension.name);
16 |
17 | const toggleLink = useCallback(() => {
18 | showExcalidrawEditor(editor);
19 | }, [editor]);
20 |
21 | return (
22 |
23 | }
25 | onClick={toggleLink}
26 | active={isActive}
27 | />
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/src/extensions/flow/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./flow";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/flow/menu/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 |
3 | import { IconCopy, IconDelete, IconEdit } from "../../../icons";
4 | import {
5 | BubbleMenu,
6 | Tooltip,
7 | Divider,
8 | Button,
9 | Space
10 | } from "../../../components";
11 | import { useAttributes } from "../../../hooks";
12 | import { copyNode, deleteNode } from "../../../utilities";
13 | import { IFlowAttrs, Flow } from "../flow";
14 |
15 | import { showFlowEditor } from "./edit";
16 | import i18n from "../../../i18n";
17 |
18 | export const FlowBubbleMenu = ({ editor }) => {
19 | const attrs = useAttributes(editor, Flow.name, {
20 | width: 0,
21 | height: 0,
22 | svg: ""
23 | });
24 |
25 | const shouldShow = useCallback(() => editor.isActive(Flow.name), [editor]);
26 |
27 | const copyMe = useCallback(() => copyNode(editor, Flow.name), [editor]);
28 |
29 | const deleteMe = useCallback(() => deleteNode(editor, Flow.name), [editor]);
30 |
31 | const openEditModal = useCallback(() => {
32 | showFlowEditor(editor);
33 | }, [editor]);
34 |
35 | return (
36 |
42 |
43 |
44 | } size="small" />
45 |
46 |
47 |
48 | } onClick={openEditModal} />
49 |
50 |
51 |
52 |
53 |
54 | } size="small" />
55 |
56 |
57 |
58 | );
59 | };
60 |
--------------------------------------------------------------------------------
/src/extensions/flow/menu/constants.ts:
--------------------------------------------------------------------------------
1 | export const DEFAULT_FLOW_DATA = ``;
2 |
--------------------------------------------------------------------------------
/src/extensions/flow/menu/edit.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { Editor } from "@tiptap/core";
4 | import { ThemeProvider } from "styled-components";
5 |
6 | import { Flow as FlowExtension } from "../flow";
7 | import { isNodeActive } from "../../../utilities";
8 |
9 | import { FlowSettingModal } from "./modal";
10 | import { getEditorTheme } from "../../../editor/theme";
11 | import { DEFAULT_FLOW_DATA } from "./constants";
12 |
13 | export const showFlowEditor = (editor: Editor) => {
14 | const isInFlow = isNodeActive(editor, FlowExtension.name);
15 |
16 | if (!isInFlow) {
17 | editor
18 | .chain()
19 | .insertFlow({
20 | svg: DEFAULT_FLOW_DATA,
21 | xml: ""
22 | })
23 | .run();
24 | }
25 |
26 | const attrs = editor.getAttributes(FlowExtension.name);
27 | const data = attrs.xml;
28 | const blockId = attrs.blockId;
29 |
30 | const div = document.createElement("div");
31 | editor.options.element.appendChild(div);
32 |
33 | ReactDOM.render(
34 |
35 | {
40 | ReactDOM.unmountComponentAtNode(div);
41 | div.remove();
42 | }}
43 | />
44 | ,
45 | div
46 | );
47 | };
48 |
--------------------------------------------------------------------------------
/src/extensions/flow/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/src/extensions/flow/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconFlow } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Flow as FlowExtension } from "../flow";
8 |
9 | import { showFlowEditor } from "./edit";
10 | import i18n from "../../../i18n";
11 |
12 | export const FlowStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
13 | const isActive = useActive(editor, FlowExtension.name);
14 |
15 | const showEditor = useCallback(() => {
16 | showFlowEditor(editor);
17 | }, [editor]);
18 |
19 | return (
20 |
21 | } onClick={showEditor} active={isActive} />
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/extensions/focus/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./focus";
2 |
--------------------------------------------------------------------------------
/src/extensions/gapcursor/gapcursor.ts:
--------------------------------------------------------------------------------
1 | import GapCursor from "@tiptap/extension-gapcursor";
2 |
3 | export { GapCursor };
4 |
--------------------------------------------------------------------------------
/src/extensions/gapcursor/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./gapcursor";
2 |
--------------------------------------------------------------------------------
/src/extensions/hard-break/hard-break.ts:
--------------------------------------------------------------------------------
1 | import HardBreak from "@tiptap/extension-hard-break";
2 |
3 | export { HardBreak };
4 |
--------------------------------------------------------------------------------
/src/extensions/hard-break/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./hard-break";
2 |
--------------------------------------------------------------------------------
/src/extensions/heading/constants.ts:
--------------------------------------------------------------------------------
1 | export const FOLD_SVG = ``;
2 |
--------------------------------------------------------------------------------
/src/extensions/heading/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./heading";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/heading/slug.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "prosemirror-model";
2 | import escape from "lodash.escape";
3 | import slugify from "slugify";
4 |
5 | function safeSlugify(text: string) {
6 | return `h-${escape(
7 | slugify(text, {
8 | remove: /[!"#$%&'\.()*+,\/:;<=>?@\[\]\\^_`{|}~]/g,
9 | lower: true
10 | })
11 | )}`;
12 | }
13 |
14 | export default function headingToSlug(node: Node, index = 0) {
15 | const slugified = safeSlugify(node.textContent);
16 | if (index === 0) return slugified;
17 | return `${slugified}-${index}`;
18 | }
19 |
20 | export function headingToPersistenceKey(node: Node, id?: string) {
21 | const slug = headingToSlug(node);
22 | return `rme-${id || window?.location.pathname}–${slug}`;
23 | }
24 |
--------------------------------------------------------------------------------
/src/extensions/horizontal-rule/horizontal-rule.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node, nodeInputRule } from "@tiptap/core";
2 | import { TextSelection } from "prosemirror-state";
3 |
4 | export interface HorizontalRuleOptions {
5 | HTMLAttributes: Record;
6 | }
7 |
8 | declare module "@tiptap/core" {
9 | interface Commands {
10 | horizontalRule: {
11 | setHorizontalRule: () => ReturnType;
12 | };
13 | }
14 | }
15 |
16 | export const HorizontalRule = Node.create({
17 | name: "horizontalRule",
18 | group: "block",
19 | selectable: true,
20 |
21 | addOptions() {
22 | return {
23 | HTMLAttributes: {}
24 | };
25 | },
26 |
27 | parseHTML() {
28 | return [{ tag: "hr" }];
29 | },
30 |
31 | renderHTML({ HTMLAttributes }) {
32 | return ["hr", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
33 | },
34 |
35 | addCommands() {
36 | return {
37 | setHorizontalRule: () => ({ chain }) => {
38 | return chain()
39 | .insertContent({ type: this.name })
40 | .command(({ tr, dispatch }) => {
41 | if (dispatch) {
42 | const { $to } = tr.selection;
43 | const posAfter = $to.end();
44 |
45 | if ($to.nodeAfter) {
46 | tr.setSelection(TextSelection.create(tr.doc, $to.pos));
47 | } else {
48 | const node = $to.parent.type.contentMatch.defaultType?.create();
49 |
50 | if (node) {
51 | tr.insert(posAfter, node);
52 | tr.setSelection(TextSelection.create(tr.doc, posAfter));
53 | }
54 | }
55 |
56 | tr.scrollIntoView();
57 | }
58 |
59 | return true;
60 | })
61 | .run();
62 | }
63 | };
64 | },
65 |
66 | addInputRules() {
67 | return [
68 | nodeInputRule({
69 | find: /^(?:---|—-|___\s|\*\*\*\s)$/,
70 | type: this.type
71 | })
72 | ];
73 | }
74 | });
75 |
--------------------------------------------------------------------------------
/src/extensions/horizontal-rule/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./horizontal-rule";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/horizontal-rule/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconHorizontalRule } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { HorizontalRule as HorizontalRuleExtension } from "./horizontal-rule";
9 | import i18n from "../../i18n";
10 |
11 | export const HorizontalRuleStaticMenu: React.FC<{ editor: Editor }> = ({
12 | editor
13 | }) => {
14 | const isHorizontalRuleActive = useActive(
15 | editor,
16 | HorizontalRuleExtension.name
17 | );
18 |
19 | const setHorizontalRule = useCallback(
20 | () =>
21 | editor
22 | .chain()
23 | .focus()
24 | .setHorizontalRule()
25 | .run(),
26 | [editor]
27 | );
28 |
29 | return (
30 |
31 | }
34 | onClick={setHorizontalRule}
35 | />
36 |
37 | );
38 | };
39 |
--------------------------------------------------------------------------------
/src/extensions/iframe/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./iframe";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/iframe/menu/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import { Editor } from "@tiptap/core";
3 | import { useCallback } from "react";
4 |
5 | import { Tooltip, BubbleMenu, Button, Space } from "../../../components";
6 | import { useAttributes } from "../../../hooks/use-attributes";
7 | import { IconEdit, IconVisitlink } from "../../../icons";
8 | import { Iframe as IframeExtension } from "../iframe";
9 |
10 | import { showURLEditor } from "./edit";
11 | import i18n from "../../../i18n";
12 |
13 | interface IProps {
14 | editor: Editor;
15 | }
16 |
17 | export const IframeBubbleMenu: React.FC = ({ editor }) => {
18 | const containerRef = useRef(null);
19 |
20 | const { url } = useAttributes(editor, IframeExtension.name, {
21 | url: ""
22 | });
23 |
24 | const shouldShow = useCallback(() => editor.isActive(IframeExtension.name), [
25 | editor
26 | ]);
27 |
28 | const visitLink = useCallback(() => {
29 | const tab = window.open();
30 | if (!tab) return;
31 | tab.opener = null;
32 | tab.location = url;
33 | }, [url]);
34 |
35 | const openEditLinkModal = useCallback(() => {
36 | showURLEditor(editor, containerRef.current as HTMLElement);
37 | }, [editor]);
38 |
39 | return (
40 |
41 |
42 |
43 |
44 | } onClick={visitLink} />
45 |
46 |
47 |
48 | }
51 | onClick={openEditLinkModal}
52 | />
53 |
54 |
55 |
56 |
57 | );
58 | };
59 |
--------------------------------------------------------------------------------
/src/extensions/iframe/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/src/extensions/iframe/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconVisitlink } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Iframe as IframeExtension } from "../iframe";
8 |
9 | import { showURLEditor } from "./edit";
10 | import i18n from "../../../i18n";
11 |
12 | export const IframeStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
13 | const isActive = useActive(editor, IframeExtension.name);
14 |
15 | const toggleLink = useCallback(() => {
16 | showURLEditor(editor);
17 | }, [editor]);
18 |
19 | return (
20 |
21 | } onClick={toggleLink} active={isActive} />
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/extensions/image/image-view.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useMemo } from "react";
2 | import { NodeViewWrapper, NodeViewProps } from "@tiptap/react";
3 |
4 | import { Resizable } from "../../components";
5 |
6 | export const ImageView: React.FC = ({
7 | editor,
8 | node: { attrs },
9 | updateAttributes,
10 | getPos
11 | }) => {
12 | const { src, width, height, align, aspectRatio } = attrs;
13 |
14 | const flexJustifyContent = useMemo(() => {
15 | if (align === "center") return "center";
16 | if (align === "right") return "flex-end";
17 |
18 | return "flex-start";
19 | }, [align]);
20 |
21 | const onResize = useCallback(
22 | size => {
23 | updateAttributes({ width: size.width, height: size.height });
24 | },
25 | [updateAttributes]
26 | );
27 |
28 | return (
29 |
35 |
42 |
43 |
44 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/src/extensions/image/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./image";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/image/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./bubble-menu";
2 | export * from "./static-menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/image/menu/static-menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Tooltip, Button } from "../../../components";
5 | import { IconImage } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { uploadImage } from "../../../utilities";
8 | import { Image as ImageExtension } from "../image";
9 | import i18n from "../../../i18n";
10 |
11 | export const ImageStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isCodeActive = useActive(editor, ImageExtension.name);
13 |
14 | const setImage = useCallback(() => {
15 | uploadImage(editor).then(res => {
16 | editor
17 | .chain()
18 | .focus()
19 | .setImage({
20 | ...res,
21 | src: res.url
22 | })
23 | .run();
24 | });
25 | }, [editor]);
26 |
27 | return (
28 |
29 | } onClick={setImage} active={isCodeActive} />
30 |
31 | );
32 | };
33 |
--------------------------------------------------------------------------------
/src/extensions/index.ts:
--------------------------------------------------------------------------------
1 | export { Bold, BoldStaticMenu } from "./bold";
2 | export { Italic, ItalicStaticMenu } from "./italic";
3 | export { Underline, UnderlineStaticMenu } from "./underline";
4 | export { Strike, StrikeStaticMenu } from "./strike";
5 | export { Subscript, SubscriptStaticMenu } from "./subscript";
6 | export { Superscript, SuperscriptStaticMenu } from "./superscript";
7 | export { Blockquote, BlockquoteStaticMenu } from "./blockquote";
8 | export { CodeExtensions, CodeStaticMenu } from "./code";
9 | export { CodeBlock, CodeBlockStaticMenu } from "./code-block";
10 | export { Heading, HeadingStaticMenu } from "./heading";
11 | export { Link, LinkStaticMenu, LinkBubbleMenu } from "./link";
12 | export { Iframe, IframeStaticMenu, IframeBubbleMenu } from "./iframe";
13 | export { Image, ImageStaticMenu, ImageBubbleMenu } from "./image";
14 | export { Status, StatusStaticMenu } from "./status";
15 | export { TableExtensions, TableStaticMenu, TableBubbleMenu } from "./table";
16 | export { Mind, MindStaticMenu, MindBubbleMenu } from "./mind";
17 | export { Flow, FlowStaticMenu, FlowBubbleMenu } from "./flow";
18 | export {
19 | Excalidraw,
20 | ExcalidrawStaticMenu,
21 | ExcalidrawBubbleMenu
22 | } from "./excalidraw";
23 | export { TextAlign, TextAlignStaticMenu } from "./text-align";
24 | export { HorizontalRule, HorizontalRuleStaticMenu } from "./horizontal-rule";
25 | export { ListItem } from "./list-item";
26 | export { OrderedList } from "./ordered-list";
27 | export { BulletList } from "./bullet-list";
28 | export { DropCursor } from "./dropcursor";
29 | export { GapCursor } from "./gapcursor";
30 | export { HardBreak } from "./hard-break";
31 | export { UniqueID } from "./unique-id";
32 | export { Dragable } from "./dragable";
33 | export { Mention } from "./mention";
34 | export { createSlash } from "./slash";
35 | export {
36 | ColumnsExtensions,
37 | ColumnsStaticMenu,
38 | ColumnsBubbleMenu
39 | } from "./columns";
40 | export { Perf, addAnalytics } from "./perf";
41 |
--------------------------------------------------------------------------------
/src/extensions/italic/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./italic";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/italic/italic.ts:
--------------------------------------------------------------------------------
1 | import { Italic } from "@tiptap/extension-italic";
2 |
3 | export { Italic };
4 |
--------------------------------------------------------------------------------
/src/extensions/italic/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconItalic } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { Italic as ItalicExtension } from "./italic";
9 | import i18n from "../../i18n";
10 |
11 | export const ItalicStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isItalicActive = useActive(editor, ItalicExtension.name);
13 |
14 | const toggleItalic = useCallback(
15 | () =>
16 | editor
17 | .chain()
18 | .focus()
19 | .toggleItalic()
20 | .run(),
21 | [editor]
22 | );
23 |
24 | return (
25 |
26 | }
28 | onClick={toggleItalic}
29 | active={isItalicActive}
30 | />
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/src/extensions/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./link";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/link/link.ts:
--------------------------------------------------------------------------------
1 | import { markInputRule } from "@tiptap/core";
2 | import { Link as BuiltInLink } from "@tiptap/extension-link";
3 |
4 | const extractHrefFromMatch = (match: RegExpMatchArray) => {
5 | return { href: match?.groups?.href };
6 | };
7 |
8 | export const extractHrefFromMarkdownLink = (match: RegExpMatchArray) => {
9 | /**
10 | * Removes the last capture group from the match to satisfy
11 | * tiptap markInputRule expectation of having the content as
12 | * the last capture group in the match.
13 | *
14 | * https://github.com/ueberdosis/tiptap/blob/%40tiptap/core%402.0.0-beta.75/packages/core/src/inputRules/markInputRule.ts#L11
15 | */
16 | match.pop();
17 | return extractHrefFromMatch(match);
18 | };
19 |
20 | export const Link = BuiltInLink.extend({
21 | addOptions() {
22 | return {
23 | ...this.parent?.(),
24 | openOnClick: false
25 | };
26 | },
27 |
28 | addInputRules() {
29 | const markdownLinkSyntaxInputRuleRegExp = /(?:^|\s)\[([\w|\s|-|\u4e00-\u9fa5]+)\]\((?.+?)\)$/gm;
30 | const urlSyntaxRegExp = /(?:^|\s)(?(?:https?:\/\/|www\.)[\S]+)(?:\s|\n)$/gim;
31 |
32 | return [
33 | markInputRule({
34 | find: markdownLinkSyntaxInputRuleRegExp,
35 | type: this.type,
36 | getAttributes: extractHrefFromMarkdownLink
37 | }),
38 | markInputRule({
39 | find: urlSyntaxRegExp,
40 | type: this.type,
41 | getAttributes: extractHrefFromMatch
42 | })
43 | ];
44 | },
45 |
46 | addAttributes() {
47 | return {
48 | ...this.parent?.(),
49 | href: {
50 | default: null,
51 | parseHTML: element => element.getAttribute("href")
52 | },
53 | title: {
54 | title: null,
55 | parseHTML: element => element.getAttribute("title")
56 | }
57 | };
58 | }
59 | }).configure({
60 | openOnClick: false,
61 | linkOnPaste: true,
62 | autolink: false
63 | });
64 |
--------------------------------------------------------------------------------
/src/extensions/link/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/src/extensions/link/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconLink } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Link as LinkExtension } from "../link";
8 | import { showLinkEditor } from "./edit";
9 | import i18n from "../../../i18n";
10 |
11 | export const LinkStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isLinkActive = useActive(editor, LinkExtension.name);
13 |
14 | const toggleLink = useCallback(() => {
15 | showLinkEditor(editor);
16 | }, [editor]);
17 |
18 | return (
19 |
20 | } onClick={toggleLink} active={isLinkActive} />
21 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/src/extensions/list-item/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./list-item";
2 |
--------------------------------------------------------------------------------
/src/extensions/list-item/list-item.ts:
--------------------------------------------------------------------------------
1 | import { ListItem } from "@tiptap/extension-list-item";
2 |
3 | export { ListItem };
4 |
--------------------------------------------------------------------------------
/src/extensions/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./loading";
2 | export * from "./utilities";
3 |
--------------------------------------------------------------------------------
/src/extensions/loading/loading-view.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { NodeViewWrapper, NodeViewProps } from "@tiptap/react";
3 |
4 | import { Loading } from "../../components";
5 |
6 | const LOADING_WRAPPER_STYLE: React.CSSProperties = {
7 | display: "flex",
8 | justifyContent: "center",
9 | alignItems: "center",
10 | padding: "1em",
11 | whiteSpace: "nowrap"
12 | };
13 |
14 | export const LoadingView: React.FC = ({
15 | editor,
16 | node: { attrs }
17 | }) => {
18 | const isEditable = editor.isEditable;
19 | const { text } = attrs;
20 |
21 | if (!isEditable) return ;
22 |
23 | return (
24 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/src/extensions/loading/loading.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from "@tiptap/core";
2 | import { ReactNodeViewRenderer } from "@tiptap/react";
3 | import { LoadingView } from "./loading-view";
4 |
5 | export const Loading = Node.create({
6 | name: "loading",
7 | inline: false,
8 | content: "",
9 | marks: "",
10 | group: "block",
11 | selectable: false,
12 | draggable: false,
13 | atom: true,
14 |
15 | addOptions() {
16 | return {
17 | HTMLAttributes: {
18 | class: "loading"
19 | }
20 | };
21 | },
22 |
23 | addAttributes() {
24 | return {
25 | id: {
26 | default: null
27 | },
28 | text: {
29 | default: null
30 | }
31 | };
32 | },
33 |
34 | parseHTML() {
35 | return [
36 | {
37 | tag: "div[class=loading]"
38 | }
39 | ];
40 | },
41 |
42 | renderHTML({ HTMLAttributes }) {
43 | return [
44 | "div",
45 | mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
46 | ];
47 | },
48 |
49 | addNodeView() {
50 | return ReactNodeViewRenderer(LoadingView);
51 | }
52 | });
53 |
--------------------------------------------------------------------------------
/src/extensions/loading/utilities.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 |
3 | import { PMNode } from "../../prosemirror";
4 |
5 | export function findLoadingById(
6 | editor: Editor,
7 | id: string
8 | ): null | { node: PMNode; pos: number } {
9 | let target: PMNode | null = null;
10 | let pos = -1;
11 |
12 | editor.state.doc.descendants((node, nodePos) => {
13 | if (node.type.name === "loading" && node.attrs.id === id) {
14 | target = node;
15 | pos = nodePos;
16 | }
17 | });
18 |
19 | return target ? { node: target, pos } : null;
20 | }
21 |
--------------------------------------------------------------------------------
/src/extensions/mention/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./mention";
2 |
--------------------------------------------------------------------------------
/src/extensions/mind/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./mind";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/bubble.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 |
3 | import { IconCopy, IconDelete, IconEdit } from "../../../icons";
4 | import {
5 | BubbleMenu,
6 | Tooltip,
7 | Divider,
8 | Button,
9 | Space
10 | } from "../../../components";
11 | import { useAttributes } from "../../../hooks";
12 | import { copyNode, deleteNode } from "../../../utilities";
13 | import { IMindAttrs, Mind } from "../mind";
14 |
15 | import { showMindEditor } from "./edit";
16 | import i18n from "../../../i18n";
17 |
18 | export const MindBubbleMenu = ({ editor }) => {
19 | const attrs = useAttributes(editor, Mind.name, {
20 | width: 0,
21 | height: 0,
22 | data: "",
23 | svg: ""
24 | });
25 |
26 | const shouldShow = useCallback(() => editor.isActive(Mind.name), [editor]);
27 |
28 | const copyMe = useCallback(() => copyNode(editor, Mind.name), [editor]);
29 |
30 | const deleteMe = useCallback(() => deleteNode(editor, Mind.name), [editor]);
31 |
32 | const openEditModal = useCallback(() => {
33 | showMindEditor(editor);
34 | }, [editor]);
35 |
36 | return (
37 |
43 |
44 |
45 | } size="small" />
46 |
47 |
48 |
49 | } onClick={openEditModal} />
50 |
51 |
52 |
53 |
54 |
55 | } size="small" />
56 |
57 |
58 |
59 | );
60 | };
61 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/edit.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { Editor } from "@tiptap/core";
4 | import { ThemeProvider } from "styled-components";
5 |
6 | import { DEFAULT_MIND_DATA, Mind as MindExtension } from "../mind";
7 | import { isNodeActive } from "../../../utilities";
8 |
9 | import { MindSettingModal } from "./modal";
10 | import { getEditorTheme } from "../../../editor/theme";
11 |
12 | export const showMindEditor = (editor: Editor) => {
13 | // @ts-ignore
14 | const isInMind = isNodeActive(editor, MindExtension.name);
15 |
16 | if (!isInMind) {
17 | editor
18 | .chain()
19 | .insertMind({
20 | data: DEFAULT_MIND_DATA
21 | })
22 | .run();
23 | }
24 |
25 | const attrs = editor.getAttributes(MindExtension.name);
26 | const data = JSON.parse(attrs.data);
27 | const blockId = attrs.blockId;
28 |
29 | const div = document.createElement("div");
30 | editor.options.element.appendChild(div);
31 |
32 | ReactDOM.render(
33 |
34 | {
39 | ReactDOM.unmountComponentAtNode(div);
40 | div.remove();
41 | }}
42 | />
43 | ,
44 | div
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/kityminder/README.md:
--------------------------------------------------------------------------------
1 | # 思维导图
2 |
3 | 思维导图功能来自百度团队的[开源作品](https://github.com/fex-team/kityminder-editor)。
4 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/kityminder/index.ts:
--------------------------------------------------------------------------------
1 | export const load = async (): Promise => {
2 | try {
3 | if (typeof window !== "undefined") {
4 | // @ts-ignore
5 | if (window.kityminder) {
6 | // @ts-ignore
7 | if (window.kityminder.Editor) return;
8 | }
9 | }
10 |
11 | // @ts-ignore
12 | await import("kity");
13 | await import("./hotbox");
14 | await import("./kityminder.core");
15 | await import("./kityminder.editor");
16 | } catch (e) {
17 | throw new Error(e);
18 | }
19 | };
20 |
21 | type Options = {
22 | container: HTMLElement;
23 | isEditable: boolean;
24 | data?: Record;
25 | };
26 |
27 | export function renderMind(options: Options) {
28 | // @ts-ignore
29 | const Editor = window.kityminder.Editor;
30 | const editor = new Editor(options.container);
31 | const mind = editor.minder;
32 | mind.editor = editor;
33 |
34 | options.data && mind.importJson(options.data);
35 |
36 | if (!options.isEditable) {
37 | mind.disable();
38 | mind.setStatus("readonly");
39 | }
40 |
41 | setTimeout(() => {
42 | mind.execCommand("camera");
43 |
44 | if (!options.isEditable) {
45 | const selectedNodes = mind.getSelectedNodes();
46 |
47 | if (selectedNodes.length) {
48 | mind.removeSelectedNodes(selectedNodes);
49 | }
50 | }
51 | }, 0);
52 |
53 | return mind;
54 | }
55 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconMind } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Mind as MindExtension } from "../mind";
8 |
9 | import { showMindEditor } from "./edit";
10 | import i18n from "../../../i18n";
11 |
12 | export const MindStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
13 | const isActive = useActive(editor, MindExtension.name);
14 |
15 | const toggleLink = useCallback(() => {
16 | showMindEditor(editor);
17 | }, [editor]);
18 |
19 | return (
20 |
21 | } onClick={toggleLink} active={isActive} />
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/bgcolor.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { ColorPicker, Button, Tooltip } from "../../../../components";
4 | import { IconBackgroundColor } from "../../../../icons";
5 | import i18n from "../../../../i18n";
6 |
7 | export const BgColor = ({
8 | editor,
9 | bgColor,
10 | selectedNode,
11 | setBackgroundColor
12 | }) => {
13 | return (
14 | {
16 | setBackgroundColor(color);
17 | }}>
18 |
19 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/font-color.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { ColorPicker, Button, Tooltip } from "../../../../components";
4 | import { IconFontColor } from "../../../../icons";
5 | import i18n from "../../../../i18n";
6 |
7 | export const FontColor = ({
8 | editor,
9 | selectedNode,
10 | setFontColor,
11 | textColor
12 | }) => {
13 | return (
14 | {
16 | setFontColor(color);
17 | }}>
18 |
19 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/help.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { Button, Popover } from "../../../../components";
4 | import { IconHelpCircle } from "../../../../icons";
5 | import i18n from "../../../../i18n";
6 |
7 | const HELP_MESSAGE = [
8 | { key: i18n('mind', 'help', 'addSame'), value: i18n('mind', 'help', 'addSameHelp') },
9 | { key: i18n('mind', 'help', 'addChild'), value: i18n('mind', 'help', 'addChildHelp') },
10 | { key: i18n('mind', 'help', 'editText'), value: i18n('mind', 'help', 'editTextHelp') },
11 | { key: i18n('mind', 'help', 'editMenu'), value: i18n('mind', 'help', 'editMenuHelp') }
12 | ];
13 |
14 | const HELP_MESSAGE_STYLE = {
15 | width: "200px"
16 | };
17 |
18 | export const Help = () => {
19 | return (
20 |
27 | {HELP_MESSAGE.map(msg => {
28 | return (
29 |
30 | {msg.key}:{msg.value}
31 |
32 | );
33 | })}
34 |
35 | }>
36 | } />
37 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/image.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { Dropdown, Button, Tooltip, Upload } from "../../../../components";
4 | import { IconImage } from "../../../../icons";
5 | import i18n from "../../../../i18n";
6 |
7 | export const Image = ({ editor, disabled, image, setImage }) => {
8 | return (
9 |
16 |
17 |
18 | }>
19 |
20 |
21 | } />
22 |
23 |
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/link.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useEffect, useRef, useState } from "react";
2 |
3 | import { Dropdown, Button, Tooltip, Input } from "../../../../components";
4 | import { IconLink } from "../../../../icons";
5 | import i18n from "../../../../i18n";
6 |
7 | export const Link = ({ editor, disabled, link, setLink }) => {
8 | const inputRef = useRef(null);
9 | const [url, setUrl] = useState(link);
10 |
11 | const save = useCallback(() => {
12 | setLink(url);
13 | }, [url]);
14 |
15 | useEffect(() => {
16 | setUrl(link);
17 | }, [link]);
18 |
19 | useEffect(() => {
20 | const timer = setTimeout(() => {
21 | inputRef.current?.focus();
22 | }, 300);
23 |
24 | return () => {
25 | clearTimeout(timer);
26 | };
27 | }, []);
28 |
29 | return (
30 |
37 |
38 |
41 |
42 | }>
43 |
44 |
45 | } />
46 |
47 |
48 |
49 | );
50 | };
51 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/priority.tsx:
--------------------------------------------------------------------------------
1 | // import { IconClock } from "@douyinfe/semi-icons";
2 | // import { Button, Dropdown, Tooltip } from "@douyinfe/semi-ui";
3 | import React from "react";
4 |
5 | import { Dropdown, Button, Tooltip } from "../../../../components";
6 | import { IconPriority } from "../../../../icons";
7 |
8 | import { PRIORITIES } from "../constant";
9 | import i18n from "../../../../i18n";
10 |
11 | export const Priority = ({ editor, selectedNode, setPriority }) => {
12 | return (
13 |
17 | {PRIORITIES.map(item => {
18 | return (
19 |
20 | {item.text}
21 |
22 | );
23 | })}
24 |
25 | }>
26 |
27 |
28 | }
32 | />
33 |
34 |
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/progress.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { Dropdown, Button, Tooltip } from "../../../../components";
4 | import { IconProgress } from "../../../../icons";
5 |
6 | import { PROGRESSES } from "../constant";
7 | import i18n from "../../../../i18n";
8 |
9 | export const Progress = ({ editor, selectedNode, setProgress }) => {
10 | return (
11 |
15 | {PROGRESSES.map(progress => {
16 | return (
17 |
20 | {progress.text}
21 |
22 | );
23 | })}
24 |
25 | }>
26 |
27 |
28 | }
32 | />
33 |
34 |
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/styled.tsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | export const StyledSection = styled.section`
4 | margin-top: 16px;
5 |
6 | > div {
7 | display: flex;
8 | width: 192px;
9 | margin-top: 8px;
10 | flex-wrap: wrap;
11 |
12 | ul {
13 | display: flex;
14 | padding: 0;
15 | margin: 0;
16 | list-style: none;
17 | flex-wrap: wrap;
18 |
19 | li {
20 | width: 80px;
21 | height: 30px;
22 | padding: 0 5px;
23 | font-size: 12px;
24 | line-height: 30px;
25 | text-align: center;
26 | text-decoration: none;
27 | cursor: pointer;
28 | border: 1px solid rgb(28 31 35 / 8%);
29 |
30 | * {
31 | font-size: inherit;
32 | }
33 |
34 | &.active {
35 | border: 1px solid rgb(0 101 255);
36 | }
37 |
38 | &:nth-of-type(2n) {
39 | margin-left: 8px;
40 | }
41 |
42 | &:nth-of-type(n + 3) {
43 | margin-top: 8px;
44 | }
45 | }
46 | }
47 | }
48 | `;
49 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/template.tsx:
--------------------------------------------------------------------------------
1 | // import { Button, Popover, Typography } from "@douyinfe/semi-ui";
2 | // import cls from "classnames";
3 | // import { IconStructure } from "components/icons";
4 |
5 | import React from "react";
6 |
7 | import { Tooltip, Button, Popover } from "../../../../components";
8 | import { ZINDEX_HIGHEST } from "../../../../constants";
9 | import { IconMindTemplate } from "../../../../icons";
10 |
11 | import { TEMPLATES } from "../constant";
12 | import { StyledSection } from "./styled";
13 | import i18n from "../../../../i18n";
14 |
15 | export const Template = ({ editor, template, setTemplate }) => {
16 | return (
17 | editor.options.element}
24 | content={
25 |
26 | 布局
27 |
28 |
29 | {TEMPLATES.map(item => {
30 | return (
31 | - setTemplate(item.value)}>
32 | {item.label}
33 |
34 | );
35 | })}
36 |
37 |
38 |
39 | }>
40 |
41 |
42 | } size="small" />
43 |
44 |
45 |
46 | );
47 | };
48 |
--------------------------------------------------------------------------------
/src/extensions/mind/menu/toolbar/theme.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { Button, Tooltip, Popover } from "../../../../components";
4 | import { ZINDEX_HIGHEST } from "../../../../constants";
5 | import { IconMindTheme } from "../../../../icons";
6 |
7 | import { THEMES } from "../constant";
8 | import { StyledSection } from "./styled";
9 | import i18n from "../../../../i18n";
10 |
11 | export const Theme = ({ editor, theme, setTheme }) => {
12 | return (
13 | editor.options.element}
19 | content={
20 |
21 | {i18n('mind', 'subject')}
22 |
23 |
24 | {THEMES.map(item => {
25 | return (
26 | - setTheme(item.value)}>
30 | {item.label}
31 |
32 | );
33 | })}
34 |
35 |
36 |
37 | }>
38 |
39 |
40 | } size="small" />
41 |
42 |
43 |
44 | );
45 | };
46 |
--------------------------------------------------------------------------------
/src/extensions/ordered-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./ordered-list";
2 |
--------------------------------------------------------------------------------
/src/extensions/ordered-list/ordered-list.ts:
--------------------------------------------------------------------------------
1 | import { OrderedList } from "@tiptap/extension-ordered-list";
2 |
3 | export { OrderedList };
4 |
--------------------------------------------------------------------------------
/src/extensions/paragraph/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./paragraph";
2 |
--------------------------------------------------------------------------------
/src/extensions/paragraph/paragraph.ts:
--------------------------------------------------------------------------------
1 | import { Paragraph } from "@tiptap/extension-paragraph";
2 |
3 | export { Paragraph };
4 |
--------------------------------------------------------------------------------
/src/extensions/perf/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./perf";
2 | export { addAnalytics } from "./analytics";
3 | export * from "./utilities";
4 |
--------------------------------------------------------------------------------
/src/extensions/perf/perf.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 |
3 | import { PMPlugin, PMPluginKey } from "../../prosemirror";
4 |
5 | import { getAnalyticsFromTransaction } from "./analytics";
6 | import { measureRender } from "./utilities";
7 |
8 | export const Perf = Node.create({
9 | name: "perf",
10 | group: "perf",
11 | defining: true,
12 | isolating: true,
13 | allowGapCursor: false,
14 | atom: true,
15 | content: "",
16 |
17 | addProseMirrorPlugins() {
18 | return [
19 | new PMPlugin({
20 | key: new PMPluginKey(this.name),
21 | state: {
22 | init: () => ({}),
23 | apply: (tr, pluginState) => {
24 | const analyticsPayloads = getAnalyticsFromTransaction(tr);
25 |
26 | if (analyticsPayloads.length) {
27 | for (const analyticPayload of analyticsPayloads) {
28 | if (tr.docChanged) {
29 | const measureName = `${analyticPayload.subject}: ${analyticPayload.action}`;
30 | measureRender(measureName, duration => {
31 | console.log("analytic", measureName, duration);
32 | });
33 | }
34 | }
35 | }
36 | return pluginState;
37 | }
38 | }
39 | })
40 | ];
41 | }
42 | });
43 |
--------------------------------------------------------------------------------
/src/extensions/placeholder/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./placeholder";
2 |
--------------------------------------------------------------------------------
/src/extensions/slash/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./slash";
2 |
--------------------------------------------------------------------------------
/src/extensions/status/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./status";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/status/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconStatus } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 | import { getEditorProvider } from "../../editor/provider";
8 |
9 | import { Status as StatusExtension } from "./status";
10 | import i18n from "../../i18n";
11 |
12 | export const StatusStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
13 | const isStatusActive = useActive(editor, StatusExtension.name);
14 |
15 | const setStatus = useCallback(() => {
16 | const editorProvider = getEditorProvider(editor);
17 | const currentUser = editorProvider.userProvider.getCurrentUser();
18 | return editor
19 | .chain()
20 | .focus()
21 | .setStatus({
22 | createUserId: currentUser.id,
23 | showPickerOnCreate: true
24 | })
25 | .run();
26 | }, [editor]);
27 |
28 | return (
29 |
30 | }
32 | onClick={setStatus}
33 | active={isStatusActive}
34 | />
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/src/extensions/status/status.ts:
--------------------------------------------------------------------------------
1 | import { mergeAttributes, Node } from "@tiptap/core";
2 | import { ReactNodeViewRenderer } from "@tiptap/react";
3 |
4 | import { STATUS_COLORS, StatusView } from "./status-view";
5 |
6 | type IStatusAttrs = {
7 | createUserId?: string | number;
8 | showPickerOnCreate?: boolean;
9 | color?: string;
10 | text?: string;
11 | };
12 |
13 | declare module "@tiptap/core" {
14 | interface Commands {
15 | status: {
16 | setStatus: (arg: IStatusAttrs) => ReturnType;
17 | };
18 | }
19 | }
20 |
21 | export const Status = Node.create({
22 | name: "status",
23 | group: "inline",
24 | inline: true,
25 | selectable: true,
26 | atom: true,
27 |
28 | addAttributes() {
29 | return {
30 | createUserId: {
31 | default: null
32 | },
33 | showPickerOnCreate: {
34 | default: false
35 | },
36 | color: {
37 | default: STATUS_COLORS[0][1]
38 | },
39 | bgcolor: {
40 | default: STATUS_COLORS[0][2]
41 | },
42 | borderColor: {
43 | default: STATUS_COLORS[0][3]
44 | },
45 | text: {
46 | default: ""
47 | }
48 | };
49 | },
50 |
51 | addOptions() {
52 | return {
53 | HTMLAttributes: {
54 | class: "status"
55 | }
56 | };
57 | },
58 |
59 | parseHTML() {
60 | return [
61 | {
62 | tag: "span.status"
63 | }
64 | ];
65 | },
66 |
67 | renderHTML({ HTMLAttributes }) {
68 | return [
69 | "span",
70 | mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
71 | ];
72 | },
73 |
74 | addCommands() {
75 | return {
76 | setStatus: options => ({ commands }) => {
77 | return commands.insertContent({
78 | type: this.name,
79 | attrs: options
80 | });
81 | }
82 | };
83 | },
84 |
85 | addNodeView() {
86 | return ReactNodeViewRenderer(StatusView);
87 | }
88 | });
89 |
--------------------------------------------------------------------------------
/src/extensions/strike/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./strike";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/strike/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconStrike } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { Strike as StrikeExtension } from "./strike";
9 | import i18n from "../../i18n";
10 |
11 | export const StrikeStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
12 | const isStrikeActive = useActive(editor, StrikeExtension.name);
13 |
14 | const toggleStrike = useCallback(
15 | () =>
16 | editor
17 | .chain()
18 | .focus()
19 | .toggleStrike()
20 | .run(),
21 | [editor]
22 | );
23 |
24 | return (
25 |
26 | }
28 | onClick={toggleStrike}
29 | active={isStrikeActive}
30 | />
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/src/extensions/strike/strike.ts:
--------------------------------------------------------------------------------
1 | import { Strike } from "@tiptap/extension-strike";
2 |
3 | export { Strike };
4 |
--------------------------------------------------------------------------------
/src/extensions/subscript/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./subscript";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/subscript/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconSubscript } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 | import { Subscript as SubscriptExtension } from "./index";
8 | import i18n from "../../i18n";
9 |
10 | export const SubscriptStaticMenu: React.FC<{ editor: Editor }> = ({
11 | editor
12 | }) => {
13 | const isSubscriptActive = useActive(editor, SubscriptExtension.name);
14 |
15 | const toggleSubscript = useCallback(
16 | () =>
17 | editor
18 | .chain()
19 | .focus()
20 | .toggleSubscript()
21 | .run(),
22 | [editor]
23 | );
24 |
25 | return (
26 |
27 | }
30 | onClick={toggleSubscript}
31 | />
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/src/extensions/subscript/subscript.ts:
--------------------------------------------------------------------------------
1 | import { Subscript } from "@tiptap/extension-subscript";
2 |
3 | export { Subscript };
4 |
--------------------------------------------------------------------------------
/src/extensions/superscript/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./superscript";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/superscript/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconSuperscript } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 | import { Superscript as SuperscriptExtension } from "./index";
8 | import i18n from "../../i18n";
9 |
10 | export const SuperscriptStaticMenu: React.FC<{ editor: Editor }> = ({
11 | editor
12 | }) => {
13 | const isSuperscriptActive = useActive(editor, SuperscriptExtension.name);
14 |
15 | const toggleSuperscript = useCallback(
16 | () =>
17 | editor
18 | .chain()
19 | .focus()
20 | .toggleSuperscript()
21 | .run(),
22 | [editor]
23 | );
24 |
25 | return (
26 |
27 | }
30 | onClick={toggleSuperscript}
31 | />
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/src/extensions/superscript/superscript.ts:
--------------------------------------------------------------------------------
1 | import { Superscript } from "@tiptap/extension-superscript";
2 |
3 | export { Superscript };
4 |
--------------------------------------------------------------------------------
/src/extensions/table/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./table";
2 | export * from "./table-cell";
3 | export * from "./table-header";
4 | export * from "./table-row";
5 | export * from "./table-kit";
6 | export * from "./menu";
7 |
--------------------------------------------------------------------------------
/src/extensions/table/menu/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./bubble";
2 | export * from "./static";
3 |
--------------------------------------------------------------------------------
/src/extensions/table/menu/static.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../../components";
5 | import { IconTable } from "../../../icons";
6 | import { useActive } from "../../../hooks/use-active";
7 | import { Table } from "../index";
8 | import i18n from "../../../i18n";
9 |
10 | export const TableStaticMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
11 | const isTableActibe = useActive(editor, Table.name);
12 |
13 | const toggleSuperscript = useCallback(
14 | () =>
15 | editor
16 | .chain()
17 | .insertTable({ rows: 3, cols: 4, withHeaderRow: true })
18 | .focus()
19 | .run(),
20 | [editor]
21 | );
22 |
23 | return (
24 |
25 | }
28 | onClick={toggleSuperscript}
29 | />
30 |
31 | );
32 | };
33 |
34 | export * from "./bubble";
35 |
--------------------------------------------------------------------------------
/src/extensions/table/table-kit.ts:
--------------------------------------------------------------------------------
1 | import { AnyExtension } from "@tiptap/core";
2 |
3 | import { Table } from "./table";
4 | import { TableCell } from "./table-cell";
5 | import { TableHeader } from "./table-header";
6 | import { TableRow } from "./table-row";
7 |
8 | export const TableExtensions: AnyExtension[] = [
9 | Table.configure({
10 | resizable: true,
11 | cellMinWidth: 50
12 | }),
13 | TableCell,
14 | TableHeader,
15 | TableRow
16 | ];
17 |
--------------------------------------------------------------------------------
/src/extensions/table/table-row/index.ts:
--------------------------------------------------------------------------------
1 | import { TableRow as BuiltInTableRow } from "@tiptap/extension-table-row";
2 |
3 | export const TableRow = BuiltInTableRow.extend({
4 | allowGapCursor: false
5 | });
6 |
--------------------------------------------------------------------------------
/src/extensions/table/table/index.ts:
--------------------------------------------------------------------------------
1 | import BuiltInTable from "@tiptap/extension-table";
2 |
3 | import { TableCellMenuPlugin } from "../cell-menu-plugin";
4 | import { TableView } from "./table-view";
5 |
6 | export const Table = BuiltInTable.extend({
7 | // @ts-ignore
8 | addOptions() {
9 | return {
10 | HTMLAttributes: {},
11 | resizable: false,
12 | handleWidth: 5,
13 | cellMinWidth: 25,
14 | // TODO: fix
15 | View: TableView,
16 | lastColumnResizable: true,
17 | allowTableNodeSelection: false
18 | };
19 | },
20 |
21 | addProseMirrorPlugins() {
22 | const { isEditable } = this.editor;
23 |
24 | return [
25 | // @ts-ignore
26 | ...this.parent?.(),
27 | TableCellMenuPlugin(this.editor)
28 | ];
29 | }
30 | });
31 |
--------------------------------------------------------------------------------
/src/extensions/text-align/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./text-align";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/text-align/text-align.ts:
--------------------------------------------------------------------------------
1 | import BuiltInTextAlign from "@tiptap/extension-text-align";
2 |
3 | export const TextAlign = BuiltInTextAlign.configure({
4 | types: ["heading", "paragraph", "image"]
5 | });
6 |
--------------------------------------------------------------------------------
/src/extensions/text/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./text";
2 |
--------------------------------------------------------------------------------
/src/extensions/text/text.ts:
--------------------------------------------------------------------------------
1 | import { Text } from "@tiptap/extension-text";
2 |
3 | export { Text };
4 |
--------------------------------------------------------------------------------
/src/extensions/trailing-node/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./trailing-node";
2 |
--------------------------------------------------------------------------------
/src/extensions/underline/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./underline";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/src/extensions/underline/menu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { Button, Tooltip } from "../../components";
5 | import { IconUnderline } from "../../icons";
6 | import { useActive } from "../../hooks/use-active";
7 |
8 | import { Underline as UnderlineExtension } from "./underline";
9 | import i18n from "../../i18n";
10 |
11 | export const UnderlineStaticMenu: React.FC<{ editor: Editor }> = ({
12 | editor
13 | }) => {
14 | const isUnderlineActive = useActive(editor, UnderlineExtension.name);
15 |
16 | const toggleUnderline = useCallback(
17 | () =>
18 | editor
19 | .chain()
20 | .focus()
21 | .toggleUnderline()
22 | .run(),
23 | [editor]
24 | );
25 |
26 | return (
27 |
28 | }
30 | onClick={toggleUnderline}
31 | active={isUnderlineActive}
32 | />
33 |
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/src/extensions/underline/underline.ts:
--------------------------------------------------------------------------------
1 | import { Underline } from "@tiptap/extension-underline";
2 |
3 | export { Underline };
4 |
--------------------------------------------------------------------------------
/src/extensions/unique-id/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./unique-id";
2 |
--------------------------------------------------------------------------------
/src/extensions/unique-id/utilities/array-difference.ts:
--------------------------------------------------------------------------------
1 | import removeDuplicates from "./remove-duplicates";
2 |
3 | export interface ArrayDifference {
4 | added: any[];
5 | removed: any[];
6 | common: any[];
7 | }
8 |
9 | /**
10 | * Checks for added, removed and common items between two arrays.
11 | */
12 | export default function arrayDifference(
13 | array1: any[],
14 | array2: any[]
15 | ): ArrayDifference {
16 | const uniqueCombinedArray = removeDuplicates([...array1, ...array2]);
17 | const data: ArrayDifference = {
18 | added: [],
19 | removed: [],
20 | common: []
21 | };
22 |
23 | uniqueCombinedArray.forEach(item => {
24 | if (!array1.includes(item) && array2.includes(item)) {
25 | data.added.push(item);
26 | }
27 |
28 | if (array1.includes(item) && !array2.includes(item)) {
29 | data.removed.push(item);
30 | }
31 |
32 | if (array1.includes(item) && array2.includes(item)) {
33 | data.common.push(item);
34 | }
35 | });
36 |
37 | return data;
38 | }
39 |
--------------------------------------------------------------------------------
/src/extensions/unique-id/utilities/combine-transaction-steps.ts:
--------------------------------------------------------------------------------
1 | import { Node as ProseMirrorNode } from "prosemirror-model";
2 | import { Transaction } from "prosemirror-state";
3 | import { Transform } from "prosemirror-transform";
4 |
5 | /**
6 | * Returns a new `Transform` based on all steps of the passed transactions.
7 | */
8 | export default function combineTransactionSteps(
9 | oldDoc: ProseMirrorNode,
10 | transactions: Transaction[]
11 | ): Transform {
12 | const transform = new Transform(oldDoc);
13 |
14 | transactions.forEach(transaction => {
15 | transaction.steps.forEach(step => {
16 | transform.step(step);
17 | });
18 | });
19 |
20 | return transform;
21 | }
22 |
--------------------------------------------------------------------------------
/src/extensions/unique-id/utilities/find-duplicates.ts:
--------------------------------------------------------------------------------
1 | import removeDuplicates from "./remove-duplicates";
2 |
3 | /**
4 | * Returns a list of duplicated items within an array.
5 | */
6 | export default function findDuplicates(items: any[]): any[] {
7 | const filtered = items.filter((el, index) => items.indexOf(el) !== index);
8 | const duplicates = removeDuplicates(filtered);
9 |
10 | return duplicates;
11 | }
12 |
--------------------------------------------------------------------------------
/src/extensions/unique-id/utilities/remove-duplicates.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Removes duplicated values within an array.
3 | * Supports numbers, strings and objects.
4 | */
5 | export default function removeDuplicates(
6 | array: T[],
7 | by = JSON.stringify
8 | ): T[] {
9 | const seen: Record = {};
10 |
11 | return array.filter(item => {
12 | const key = by(item);
13 |
14 | return Object.prototype.hasOwnProperty.call(seen, key)
15 | ? false
16 | : (seen[key] = true);
17 | });
18 | }
19 |
--------------------------------------------------------------------------------
/src/hooks/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./use-active";
2 | export * from "./use-attributes";
3 |
--------------------------------------------------------------------------------
/src/hooks/use-active.tsx:
--------------------------------------------------------------------------------
1 | import { Editor } from '@tiptap/core';
2 | import { useEffect, useState } from 'react';
3 | import deepEqual from 'deep-equal';
4 |
5 | function someEqual(sub: Record | undefined, full: Record) {
6 | if (!sub) return false;
7 |
8 | return Object.keys(sub).every(key => deepEqual(sub[key], full[key]));
9 | }
10 |
11 | export const useActive = (editor: Editor, name: string, attributes?: Record) => {
12 | const [active, toggleActive] = useState(false);
13 |
14 | useEffect(() => {
15 | const listener = () => {
16 | const selection = editor.state.selection;
17 | const node = selection.$head.node(selection.$head.depth);
18 | toggleActive(someEqual(attributes, node.attrs) || editor.isActive(name, attributes));
19 | };
20 |
21 | editor.on('selectionUpdate', listener);
22 | editor.on('transaction', listener);
23 |
24 | return () => {
25 | editor.off('selectionUpdate', listener);
26 | editor.off('transaction', listener);
27 | };
28 | }, [editor, name, attributes, toggleActive]);
29 |
30 | return active;
31 | };
32 |
--------------------------------------------------------------------------------
/src/hooks/use-attributes.tsx:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import deepEqual from "deep-equal";
3 | import React, { useEffect, useRef, useState } from "react";
4 |
5 | type MapFn = (arg: T) => R;
6 |
7 | function mapSelf(d: T): T {
8 | return d;
9 | }
10 |
11 | export function useAttributes(
12 | editor: Editor,
13 | attribute: string,
14 | defaultValue?: T,
15 | map?: (arg: T) => R
16 | ) {
17 | const mapFn = (map || mapSelf) as MapFn;
18 | const [value, setValue] = useState(mapFn(defaultValue as T));
19 | const prevValueCache = useRef(value);
20 |
21 | useEffect(() => {
22 | const listener = () => {
23 | const attrs = {
24 | ...defaultValue,
25 | ...editor.getAttributes(attribute)
26 | } as T;
27 | Object.keys(attrs).forEach(key => {
28 | if (attrs[key] === null || attrs[key] === undefined) {
29 | // @ts-ignore
30 | attrs[key] = defaultValue[key];
31 | }
32 | });
33 | const nextAttrs = mapFn(attrs);
34 | if (deepEqual(prevValueCache.current, nextAttrs)) {
35 | return;
36 | }
37 | setValue(nextAttrs);
38 | prevValueCache.current = nextAttrs;
39 | };
40 |
41 | editor.on("selectionUpdate", listener);
42 | editor.on("transaction", listener);
43 |
44 | return () => {
45 | editor.off("selectionUpdate", listener);
46 | editor.off("transaction", listener);
47 | };
48 | }, [editor, defaultValue, attribute, mapFn]);
49 |
50 | return value;
51 | }
52 |
--------------------------------------------------------------------------------
/src/i18n/index.ts:
--------------------------------------------------------------------------------
1 | import zhCn from './zh-cn';
2 | import enUs from './en-us';
3 | import koKr from './ko-kr';
4 |
5 | const locales = [zhCn, enUs, koKr];
6 |
7 | export function getLocale(locales: any[]) {
8 | const language = navigator.language;
9 | const locale = locales.find(item => item.target.includes(language));
10 | return locale || enUs;
11 | }
12 |
13 | const locale = getLocale(locales);
14 |
15 | export default function i18n(...args) {
16 | return args.reduce((prev, next) => {
17 | return prev[next] || '';
18 | }, locale);
19 | }
20 | i18n.locale = locale;
21 | i18n.localeLangCountry = i18n('lang') + '-' + i18n('country');
22 |
23 | //@ts-ignore
24 | window.__me_i18n = i18n;
25 |
--------------------------------------------------------------------------------
/src/icons/icon.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from "react";
2 | import styled from "styled-components";
3 |
4 | export type IconProps = {
5 | style?: React.CSSProperties;
6 | onClick?: () => void;
7 | svg: React.ReactNode;
8 | };
9 |
10 | const DEFAULT_EMPTY_STYLE = {};
11 |
12 | const StyledSpan = styled.span`
13 | display: inline-flex;
14 | align-items: center;
15 | justify-content: center;
16 |
17 | cursor: pointer;
18 | `;
19 |
20 | export const Icon = forwardRef(
21 | ({ style = DEFAULT_EMPTY_STYLE, svg }, ref) => {
22 | return (
23 |
24 | {svg}
25 |
26 | );
27 | }
28 | );
29 |
30 | export const buildIcon = (svg: IconProps["svg"]) =>
31 | forwardRef>((props, ref) => (
32 |
33 | ));
34 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | export * from "./editor";
2 | export * from "./utilities";
3 | export * from "./styles/theme";
4 | export * from "./icons";
5 | export * from "./hooks";
6 | export * from "./extensions";
7 |
--------------------------------------------------------------------------------
/src/prosemirror/index.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "prosemirror-model";
2 |
3 | export {
4 | Plugin as PMPlugin,
5 | PluginKey as PMPluginKey,
6 | Selection,
7 | NodeSelection,
8 | TextSelection,
9 | Transaction,
10 | EditorState
11 | } from "prosemirror-state";
12 |
13 | export {
14 | Node as PMNode,
15 | Mark as PMMark,
16 | Slice,
17 | Fragment,
18 | ResolvedPos
19 | } from "prosemirror-model";
20 |
21 | export {
22 | EditorView,
23 | DecorationSet,
24 | Decoration,
25 | DecorationAttrs,
26 | // @ts-ignore
27 | __serializeForClipboard
28 | } from "prosemirror-view";
29 |
30 | export * from "./prosemirror-utils";
31 |
32 | export type NodeWithPos = { pos: number; node: Node };
33 |
--------------------------------------------------------------------------------
/src/prosemirror/prosemirror-utils/index.js:
--------------------------------------------------------------------------------
1 | export * from './selection';
2 | export * from './node';
3 | export * from './transforms';
4 | export { isNodeSelection, canInsert } from './helpers';
5 |
--------------------------------------------------------------------------------
/src/styles/theme.ts:
--------------------------------------------------------------------------------
1 | const colors = {
2 | text: "rgba(0, 0, 0, .85)",
3 | background: "#fff",
4 | primary: "#0064fa",
5 | greyLight: "#F4F7FA",
6 | grey: "#E8EBED",
7 | greyMid: "#C5CCD3",
8 | greyDark: "#DAE1E9"
9 | };
10 |
11 | export const base = {
12 | ...colors,
13 |
14 | fontFamily:
15 | "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen, Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif",
16 | fontFamilyMono:
17 | "'SFMono-Regular',Consolas,'Liberation Mono', Menlo, Courier,monospace",
18 |
19 | borderColor: "#dee0e3",
20 | borderRadius: "2px",
21 | boxShadow: "rgb(0 0 0/10%) 0 0 10px",
22 |
23 | horizontalRule: "#dee0e3",
24 |
25 | bubbleMenuBoxshadow: "rgb(0 0 0/10%) 0 0 10px",
26 |
27 | codeBlockBorderColor: "#dee0e3",
28 |
29 | blockquoteBorderColor: "#bbbfc5",
30 | blockquoteTextColor: "#1f2329b3",
31 |
32 | tableBorderColor: "#c1c7d0",
33 | tableHeaderBgColor: "#f4f5f7",
34 | tableSelectedBorderColor: "#0065ff",
35 | tableSelectedCellBgColor: "#e8f2ff",
36 | tableSelectedControlBgColor: "#2584ff",
37 | tableResizeHandleBgColor: "#adf",
38 |
39 | slashMenuColor: "rgba(0, 0, 0, 0.85)",
40 | slashMenuTitleColor: "rgba(0, 0, 0, 0.45)",
41 | slashMenuBoxshadow: "rgb(0 0 0/10%) 0 0 10px",
42 | slashMenuHoverBgColor: "rgb(46 50 56 / 5%)"
43 | };
44 |
45 | export const light = {
46 | ...base
47 | };
48 |
49 | export const dark = {
50 | ...base
51 | };
52 |
53 | export default light;
54 |
--------------------------------------------------------------------------------
/src/utilities/clamp.ts:
--------------------------------------------------------------------------------
1 | export function clamp(val: number, min: number, max: number): number {
2 | if (val < min) {
3 | return min;
4 | }
5 | if (val > max) {
6 | return max;
7 | }
8 | return val;
9 | }
10 |
--------------------------------------------------------------------------------
/src/utilities/copy/copy-to-clipboard.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | "use strict";
3 |
4 | var deselectCurrent = require("toggle-selection");
5 |
6 | function copy(text, onCopy) {
7 | var reselectPrevious,
8 | range,
9 | selection,
10 | mark,
11 | success = false;
12 |
13 | reselectPrevious = deselectCurrent();
14 | range = document.createRange();
15 | selection = document.getSelection();
16 |
17 | mark = document.createElement("span");
18 | mark.textContent = text;
19 | mark.style.all = "unset";
20 | mark.style.position = "fixed";
21 | mark.style.top = 0;
22 | mark.style.clip = "rect(0, 0, 0, 0)";
23 | mark.style.whiteSpace = "pre";
24 | mark.style.webkitUserSelect = "text";
25 | mark.style.MozUserSelect = "text";
26 | mark.style.msUserSelect = "text";
27 | mark.style.userSelect = "text";
28 | mark.addEventListener("copy", function(e) {
29 | var data = [];
30 |
31 | if (typeof text === "string") {
32 | data = [{ format: "text/plain", text: text }];
33 | } else if (Array.isArray(text)) {
34 | text.forEach(function(item) {
35 | data.push({
36 | format: item.format || "text/plain",
37 | text: item.text || item
38 | });
39 | });
40 | } else {
41 | data.push({
42 | format: "text/plain",
43 | text: text
44 | });
45 | }
46 |
47 | data.forEach(function(item) {
48 | e.clipboardData.setData(item.format, item.text);
49 | });
50 |
51 | e.preventDefault();
52 |
53 | onCopy && onCopy();
54 | });
55 |
56 | document.body.appendChild(mark);
57 | range.selectNodeContents(mark);
58 | selection.addRange(range);
59 | var successful = document.execCommand("copy");
60 |
61 | if (!successful) {
62 | throw new Error("copy command was unsuccessful");
63 | }
64 |
65 | success = true;
66 | return success;
67 | }
68 |
69 | module.exports = copy;
70 |
--------------------------------------------------------------------------------
/src/utilities/file.ts:
--------------------------------------------------------------------------------
1 | import { fileOpen } from "browser-fs-access";
2 | import { Editor } from "@tiptap/core";
3 |
4 | import { getEditorProvider } from "../editor/provider";
5 | import { findLoadingById, Loading } from "../extensions/loading";
6 |
7 | function getImageNaturalSize(
8 | url: string
9 | ): Promise<{ width: number; height: number; aspectRatio: number }> {
10 | return new Promise((resolve, reject) => {
11 | const img = new Image();
12 | img.onload = function() {
13 | resolve({
14 | width: img.naturalWidth,
15 | height: img.naturalHeight,
16 | aspectRatio: img.naturalWidth / img.naturalHeight
17 | });
18 | };
19 | img.onerror = function(err) {
20 | reject(err);
21 | };
22 | img.src = url;
23 | });
24 | }
25 |
26 | let loadingId = 0;
27 |
28 | export async function uploadImage(
29 | editor: Editor
30 | ): Promise<{ url: string; width: number; height: number }> {
31 | const blob = await fileOpen({
32 | mimeTypes: ["image/*"]
33 | });
34 | const editorProvider = getEditorProvider(editor);
35 |
36 | const id = `loading-${loadingId++}`;
37 | const loadingNode = editor.state.schema?.nodes?.[Loading.name]?.create({
38 | id,
39 | text: blob.name
40 | });
41 |
42 | const removeLoading = () => {
43 | const maybeLoading = findLoadingById(editor, id);
44 | if (maybeLoading) {
45 | editor.commands.deleteRange({
46 | from: maybeLoading?.pos,
47 | to: maybeLoading?.pos + maybeLoading?.node.nodeSize
48 | });
49 | }
50 | };
51 |
52 | editor.view.dispatch(editor.view.state.tr.replaceSelectionWith(loadingNode));
53 |
54 | try {
55 | const url = await editorProvider.fileProvider.uploadFile(blob);
56 | const size = await getImageNaturalSize(url);
57 | removeLoading();
58 | return { url, ...size };
59 | } catch (e) {
60 | removeLoading();
61 | throw e;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/utilities/index.ts:
--------------------------------------------------------------------------------
1 | import "requestidlecallback-polyfill";
2 |
3 | export * from "./clamp";
4 | export * from "./copy";
5 | export * from "./create-node";
6 | export * from "./mark";
7 | export * from "./node";
8 | export * from "./pos";
9 | export * from "./file";
10 | export * from "./throttle";
11 | export * from "./svg-to-datauri";
12 |
--------------------------------------------------------------------------------
/src/utilities/mark.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from "prosemirror-state";
2 | import { Mark, MarkType } from "prosemirror-model";
3 |
4 | export const isMarkActive = (type: MarkType) => (
5 | state: EditorState
6 | ): boolean => {
7 | if (!type) {
8 | return false;
9 | }
10 |
11 | const { from, $from, to, empty } = state.selection;
12 |
13 | return !!(empty
14 | ? type.isInSet(state.storedMarks || $from.marks())
15 | : state.doc.rangeHasMark(from, to, type));
16 | };
17 |
18 | export function findMarkPosition(
19 | state: EditorState,
20 | mark: Mark,
21 | from: number,
22 | to: number
23 | ) {
24 | let markPos = { start: -1, end: -1 };
25 |
26 | state.doc.nodesBetween(from, to, (node, pos) => {
27 | if (markPos.start > -1) {
28 | return false;
29 | }
30 | if (markPos.start === -1 && mark.isInSet(node.marks)) {
31 | markPos = {
32 | start: pos,
33 | end: pos + Math.max(node.textContent.length, 1)
34 | };
35 | }
36 | });
37 |
38 | return markPos;
39 | }
40 |
--------------------------------------------------------------------------------
/src/utilities/pos.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from "prosemirror-state";
2 |
3 | /**
4 | * 根据文档内容大小获取不越界的位置
5 | * @param state
6 | * @param pos
7 | * @returns
8 | */
9 | export function safePos(state: EditorState, pos: number) {
10 | const max = Math.max(pos, 0);
11 | const min = Math.min(state.doc.content.size, max);
12 | return min;
13 | }
14 |
--------------------------------------------------------------------------------
/src/utilities/svg-to-datauri.ts:
--------------------------------------------------------------------------------
1 | function escapeRegExp(str) {
2 | return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
3 | }
4 |
5 | function replaceAll(str, find, replace) {
6 | return str.replace(new RegExp(escapeRegExp(find), "g"), replace);
7 | }
8 |
9 | export function svgToDataURI(svg) {
10 | if (!svg) return "";
11 |
12 | let encoded = svg.replace(/\s+/g, " ");
13 | encoded = replaceAll(encoded, "%", "%25");
14 | encoded = replaceAll(encoded, "> <", "><");
15 | encoded = replaceAll(encoded, "; }", ";}");
16 | encoded = replaceAll(encoded, "<", "%3c");
17 | encoded = replaceAll(encoded, ">", "%3e");
18 | encoded = replaceAll(encoded, '"', "'");
19 | encoded = replaceAll(encoded, "#", "%23");
20 | encoded = replaceAll(encoded, "{", "%7b");
21 | encoded = replaceAll(encoded, "}", "%7d");
22 | encoded = replaceAll(encoded, "|", "%7c");
23 | encoded = replaceAll(encoded, "^", "%5e");
24 | encoded = replaceAll(encoded, "`", "%60");
25 | encoded = replaceAll(encoded, "@", "%40");
26 |
27 | const uri = `data:image/svg+xml;charset=UTF-8,${encoded}`;
28 |
29 | return uri;
30 | }
31 |
--------------------------------------------------------------------------------
/src/utilities/throttle.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import throttle from "lodash.throttle";
3 |
4 | export { throttle };
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ESNext", "DOM"],
7 | "moduleResolution": "Node",
8 | "jsx": "react-jsx",
9 | "strict": true,
10 | "sourceMap": true,
11 | "resolveJsonModule": true,
12 | "esModuleInterop": true,
13 | "noEmit": true,
14 | "noUnusedLocals": false,
15 | "noUnusedParameters": true,
16 | "noImplicitReturns": true,
17 | "noImplicitAny": false,
18 | "outDir": "dist",
19 | "declaration": true,
20 | "declarationDir": "types",
21 | "composite": true,
22 | "skipLibCheck": true,
23 | "skipDefaultLibCheck": true
24 | },
25 | "include": ["src"]
26 | }
27 |
--------------------------------------------------------------------------------
/types/src/components/bubble-menu.d.ts:
--------------------------------------------------------------------------------
1 | import { BubbleMenuProps as BuiltInTiptapBubbleMenuProps } from "@tiptap/react";
2 | import { Editor } from "@tiptap/core";
3 | import { EditorState } from "prosemirror-state";
4 | import { EditorView } from "prosemirror-view";
5 | import React from "react";
6 | export declare type BubbleMenuProps = BuiltInTiptapBubbleMenuProps & {
7 | shouldShow: (props: {
8 | editor: Editor;
9 | view: EditorView;
10 | state: EditorState;
11 | oldState?: EditorState;
12 | from: number;
13 | to: number;
14 | }) => boolean;
15 | forNode?: boolean;
16 | };
17 | export declare const BubbleMenu: React.FC;
18 |
--------------------------------------------------------------------------------
/types/src/components/button.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | declare type Size = "small" | "normal" | "large";
3 | declare type ButtonType = "primary" | "normal";
4 | declare type Props = {
5 | active?: boolean;
6 | disabled?: boolean;
7 | icon?: React.ReactNode;
8 | size?: Size;
9 | type?: ButtonType;
10 | onClick?: () => void;
11 | style?: React.CSSProperties;
12 | };
13 | export declare const Button: React.FC>;
14 | export {};
15 |
--------------------------------------------------------------------------------
/types/src/components/color-picker/index.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export declare const ColorPicker: React.FC<{
3 | title?: string;
4 | onSetColor: (arg: string | null) => void;
5 | disabled?: boolean;
6 | }>;
7 |
--------------------------------------------------------------------------------
/types/src/components/color-picker/style.d.ts:
--------------------------------------------------------------------------------
1 | export declare const StyledEmptyWrap: import("styled-components").StyledComponent<"div", any, {}, never>;
2 | export declare const StyledColorWrap: import("styled-components").StyledComponent<"div", any, {}, never>;
3 | export declare const StyledColorItemWrap: import("styled-components").StyledComponent<"div", any, {}, never>;
4 |
--------------------------------------------------------------------------------
/types/src/components/divider.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export declare const _Divider: ({ vertical, margin }: {
3 | vertical?: boolean | undefined;
4 | margin?: number | undefined;
5 | }) => JSX.Element;
6 | export declare const Divider: React.MemoExoticComponent<({ vertical, margin }: {
7 | vertical?: boolean | undefined;
8 | margin?: number | undefined;
9 | }) => JSX.Element>;
10 |
--------------------------------------------------------------------------------
/types/src/components/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Row, Col, Input, Dropdown, Space, Popover, Tag, Modal, Toast } from "@douyinfe/semi-ui";
2 | export * from "./bubble-menu";
3 | export * from "./color-picker";
4 | export * from "./tooltip";
5 | export * from "./react-tooltip";
6 | export * from "./button";
7 | export * from "./divider";
8 | export * from "./select";
9 | export * from "./resizable";
10 | export * from "./upload";
11 | export * from "./loading";
12 | export { Row, Col, Input, Dropdown, Space, Popover, Tag, Modal, Toast };
13 |
--------------------------------------------------------------------------------
/types/src/components/loading.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Loading: () => JSX.Element;
3 |
--------------------------------------------------------------------------------
/types/src/components/react-bubble-menu/bubble-menu-pluin/bubble-menu-plugin.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import { EditorState, Plugin, PluginKey } from "prosemirror-state";
3 | import { EditorView } from "prosemirror-view";
4 | import { Instance, Props } from "tippy.js";
5 | export interface BubbleMenuPluginProps {
6 | pluginKey: PluginKey | string;
7 | editor: Editor;
8 | element: HTMLElement;
9 | tippyOptions?: Partial;
10 | shouldShow?: ((props: {
11 | editor: Editor;
12 | view: EditorView;
13 | state: EditorState;
14 | oldState?: EditorState;
15 | from: number;
16 | to: number;
17 | }) => boolean) | null;
18 | }
19 | export declare type BubbleMenuViewProps = BubbleMenuPluginProps & {
20 | view: EditorView;
21 | };
22 | export declare class BubbleMenuView {
23 | editor: Editor;
24 | element: HTMLElement;
25 | view: EditorView;
26 | preventHide: boolean;
27 | tippy: Instance | undefined;
28 | tippyOptions?: Partial;
29 | shouldShow: Exclude;
30 | constructor({ editor, element, view, tippyOptions, shouldShow }: BubbleMenuViewProps);
31 | mousedownHandler: () => void;
32 | dragstartHandler: () => void;
33 | focusHandler: () => void;
34 | blurHandler: ({ event }: {
35 | event: FocusEvent;
36 | }) => void;
37 | updateHandler: (view: EditorView, oldState?: EditorState | undefined) => void;
38 | createTooltip(): void;
39 | update(view: EditorView, oldState?: EditorState): void;
40 | show(): void;
41 | hide(): void;
42 | destroy(): void;
43 | }
44 | export declare const BubbleMenuPlugin: (options: BubbleMenuPluginProps) => Plugin;
45 |
--------------------------------------------------------------------------------
/types/src/components/react-bubble-menu/bubble-menu-pluin/bubble-menu.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | import { BubbleMenuPluginProps } from "./bubble-menu-plugin";
3 | export declare type BubbleMenuOptions = Omit & {
4 | element: HTMLElement | null;
5 | };
6 | export declare const BubbleMenu: Extension;
7 |
--------------------------------------------------------------------------------
/types/src/components/react-bubble-menu/bubble-menu-pluin/index.d.ts:
--------------------------------------------------------------------------------
1 | import { BubbleMenu } from "./bubble-menu";
2 | export * from "./bubble-menu";
3 | export * from "./bubble-menu-plugin";
4 | export default BubbleMenu;
5 |
--------------------------------------------------------------------------------
/types/src/components/react-bubble-menu/index.d.ts:
--------------------------------------------------------------------------------
1 | import { BubbleMenuPluginProps } from "./bubble-menu-pluin";
2 | import React from "react";
3 | declare type Optional = Pick, K> & Omit;
4 | export declare type BubbleMenuProps = Omit, "element"> & {
5 | className?: string;
6 | children: React.ReactNode;
7 | };
8 | export declare const BubbleMenu: (props: BubbleMenuProps) => JSX.Element;
9 | export {};
10 |
--------------------------------------------------------------------------------
/types/src/components/react-tooltip.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const _ReactTooltip: React.FC<{
4 | editor: Editor;
5 | title: string;
6 | icon: React.ReactNode;
7 | content: React.ReactNode;
8 | }>;
9 | export declare const ReactTooltip: React.NamedExoticComponent<{
10 | editor: Editor;
11 | title: string;
12 | icon: React.ReactNode;
13 | content: React.ReactNode;
14 | }>;
15 |
--------------------------------------------------------------------------------
/types/src/components/resizable.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import React from "react";
3 | interface Props {
4 | width: number;
5 | height: number;
6 | aspectRatio?: number;
7 | minWidth?: number | string;
8 | editor: Editor;
9 | getPos: () => number;
10 | onResizeStop: (arg: {
11 | width: number;
12 | height: number;
13 | }) => void;
14 | }
15 | export declare const Resizable: React.FC>;
16 | export {};
17 |
--------------------------------------------------------------------------------
/types/src/components/select.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { SelectProps as ReactSelectProps } from "@douyinfe/semi-ui/lib/es/select";
3 | import { Editor } from "@tiptap/core";
4 | interface SelectProps extends ReactSelectProps {
5 | editor: Editor;
6 | options: Array<{
7 | label: React.ReactNode;
8 | value: unknown;
9 | }>;
10 | }
11 | export declare function Select(props: React.PropsWithChildren): JSX.Element;
12 | export {};
13 |
--------------------------------------------------------------------------------
/types/src/components/tooltip.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | import { Placement } from "tippy.js";
4 | declare type ZLevel = "default" | "middle" | "highest";
5 | export declare const Tooltip: React.FC>;
11 | export {};
12 |
--------------------------------------------------------------------------------
/types/src/components/upload.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | interface Props {
4 | editor: Editor;
5 | mimeTypes: string[];
6 | onOK: (arg: string) => void;
7 | }
8 | export declare const Upload: React.FC>;
9 | export {};
10 |
--------------------------------------------------------------------------------
/types/src/constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const PARSE_HTML_PRIORITY_LOWEST = 1;
2 | export declare const PARSE_HTML_PRIORITY_DEFAULT = 50;
3 | export declare const PARSE_HTML_PRIORITY_HIGHEST = 100;
4 | export declare const EXTENSION_PRIORITY_LOWER = 75;
5 | export declare const EXTENSION_PRIORITY_DEFAULT = 100;
6 | export declare const EXTENSION_PRIORITY_HIGHEST = 200;
7 | export declare const ZINDEX_DEFAULT = 10;
8 | export declare const ZINDEX_MIDDLE = 1500;
9 | export declare const ZINDEX_HIGHEST = 10000;
10 | export declare const MIN_ZOOM = 0.1;
11 | export declare const MAX_ZOOM = 2;
12 | export declare const ZOOM_STEP = 0.15;
13 |
--------------------------------------------------------------------------------
/types/src/editor/collaboration.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | import { EditorRenderProps } from "./render";
4 | export interface CollaborationEditorProps extends EditorRenderProps {
5 | id: string;
6 | url: string;
7 | token: string;
8 | }
9 | export declare const CollaborationEditor: React.ForwardRefExoticComponent>;
12 |
--------------------------------------------------------------------------------
/types/src/editor/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./collaboration";
2 | export * from "./render";
3 |
--------------------------------------------------------------------------------
/types/src/editor/kit.d.ts:
--------------------------------------------------------------------------------
1 | import { AnyExtension } from "@tiptap/core";
2 | export interface EditorKit {
3 | schema: string;
4 | extensions: Array;
5 | }
6 | export declare const resolveEditorKit: (props: EditorKit) => AnyExtension[];
7 |
--------------------------------------------------------------------------------
/types/src/editor/provider.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export interface User {
3 | id: string | number;
4 | name: string;
5 | avatar: string;
6 | [key: string]: unknown;
7 | }
8 | export interface EditorProvider {
9 | /**
10 | * 用户信息
11 | */
12 | userProvider: {
13 | /**
14 | * 获取当前用户
15 | */
16 | getCurrentUser: () => User;
17 | /**
18 | * 获取用户列表
19 | */
20 | getUsers: (query: string) => Promise | User[];
21 | };
22 | /**
23 | * 文件上传
24 | */
25 | fileProvider: {
26 | uploadFile: (file: Blob) => Promise;
27 | };
28 | }
29 | export declare const getEditorProvider: (editor: Editor) => EditorProvider;
30 |
--------------------------------------------------------------------------------
/types/src/editor/render.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { EditorKit } from "./kit";
3 | import { EditorProvider } from "./provider";
4 | import { Content, Editor } from "@tiptap/core";
5 | export interface EditorRenderProps extends EditorProvider, EditorKit {
6 | content?: Content;
7 | }
8 | export declare const EditorRender: React.ForwardRefExoticComponent>;
11 |
--------------------------------------------------------------------------------
/types/src/editor/theme.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare const getEditorTheme: (editor: Editor) => any;
3 |
--------------------------------------------------------------------------------
/types/src/editor/utilities.d.ts:
--------------------------------------------------------------------------------
1 | export declare const getUserColor: () => string;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/blockquote/blockquote.d.ts:
--------------------------------------------------------------------------------
1 | export declare const Blockquote: import("@tiptap/core").Node;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/blockquote/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./blockquote";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/blockquote/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const BlockquoteStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/bold/bold.d.ts:
--------------------------------------------------------------------------------
1 | import { Bold } from "@tiptap/extension-bold";
2 | export { Bold };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/bold/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./bold";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/bold/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const BoldStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/bullet-list/bullet-list.d.ts:
--------------------------------------------------------------------------------
1 | import { BulletList } from "@tiptap/extension-bullet-list";
2 | export { BulletList };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/bullet-list/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./bullet-list";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/code-block/code-block-view.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { NodeViewProps } from "@tiptap/react";
3 | export declare const CodeBlockView: React.FC;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/code-block/code-block.d.ts:
--------------------------------------------------------------------------------
1 | import { CodeBlockOptions } from "@tiptap/extension-code-block";
2 | interface CodeBlockLowlightOptions extends CodeBlockOptions {
3 | lowlight: any;
4 | defaultLanguage: string | null | undefined;
5 | }
6 | export declare const CodeBlock: import("@tiptap/react").Node;
7 | export {};
8 |
--------------------------------------------------------------------------------
/types/src/extensions/code-block/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./code-block";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/code-block/lowlight-plugin.d.ts:
--------------------------------------------------------------------------------
1 | import { Plugin } from "prosemirror-state";
2 | export declare function LowlightPlugin({ name, lowlight, defaultLanguage }: {
3 | name: string;
4 | lowlight: any;
5 | defaultLanguage: string | null | undefined;
6 | }): Plugin;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/code-block/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const CodeBlockStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/code/code.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | export declare const Code: import("@tiptap/core").Mark;
3 | export declare const CodeMarkPlugin: Extension;
4 | export declare const CodeExtensions: (Extension | import("@tiptap/core").Mark)[];
5 |
--------------------------------------------------------------------------------
/types/src/extensions/code/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./code";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/code/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const CodeStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/collaboration-cursor/collaboration-cursor.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | declare type CollaborationCursorStorage = {
3 | users: {
4 | clientId: number;
5 | [key: string]: any;
6 | }[];
7 | };
8 | export interface CollaborationCursorOptions {
9 | provider: any;
10 | user: Record;
11 | render(user: Record): HTMLElement;
12 | /**
13 | * @deprecated The "onUpdate" option is deprecated. Please use `editor.storage.collaborationCursor.users` instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor
14 | */
15 | onUpdate: (users: {
16 | clientId: number;
17 | [key: string]: any;
18 | }[]) => null;
19 | }
20 | declare module "@tiptap/core" {
21 | interface Commands {
22 | collaborationCursor: {
23 | /**
24 | * Update details of the current user
25 | */
26 | updateUser: (attributes: Record) => ReturnType;
27 | /**
28 | * Update details of the current user
29 | *
30 | * @deprecated The "user" command is deprecated. Please use "updateUser" instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor
31 | */
32 | user: (attributes: Record) => ReturnType;
33 | };
34 | }
35 | }
36 | export declare const CollaborationCursor: Extension;
37 | export {};
38 |
--------------------------------------------------------------------------------
/types/src/extensions/collaboration-cursor/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./collaboration-cursor";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/collaboration/collaboration.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | declare module "@tiptap/core" {
3 | interface Commands {
4 | collaboration: {
5 | /**
6 | * Undo recent changes
7 | */
8 | undo: () => ReturnType;
9 | /**
10 | * Reapply reverted changes
11 | */
12 | redo: () => ReturnType;
13 | };
14 | }
15 | }
16 | export interface CollaborationOptions {
17 | /**
18 | * An initialized Y.js document.
19 | */
20 | document: any;
21 | /**
22 | * Name of a Y.js fragment, can be changed to sync multiple fields with one Y.js document.
23 | */
24 | field: string;
25 | /**
26 | * A raw Y.js fragment, can be used instead of `document` and `field`.
27 | */
28 | fragment: any;
29 | /**
30 | * show blockIds
31 | */
32 | blockIds?: string[] | null;
33 | }
34 | export declare const Collaboration: Extension;
35 |
--------------------------------------------------------------------------------
/types/src/extensions/collaboration/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./collaboration";
2 | export * from "./is-change-origin";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/collaboration/is-change-origin.d.ts:
--------------------------------------------------------------------------------
1 | import { Transaction } from "prosemirror-state";
2 | export declare function isChangeOrigin(transaction: Transaction): boolean;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/column.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export declare const Column: Node;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/columns.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | declare module "@tiptap/core" {
3 | interface Commands {
4 | columns: {
5 | insertColumns: (attrs?: {
6 | cols: number;
7 | }) => ReturnType;
8 | addColBefore: () => ReturnType;
9 | addColAfter: () => ReturnType;
10 | deleteCol: () => ReturnType;
11 | };
12 | }
13 | }
14 | export declare const Columns: Node;
15 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./menu";
2 | export declare const ColumnsExtensions: import("@tiptap/core").Node[];
3 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ColumnsBubbleMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./bubble";
2 | export * from "./static";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ColumnsStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/columns/utilities.d.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from "../../prosemirror";
2 | export declare function createColumn(colType: any, index: any, colContent?: null): any;
3 | export declare function getColumnsNodeTypes(schema: any): any;
4 | export declare function createColumns(schema: any, colsCount: any, colContent?: null): any;
5 | export declare function addOrDeleteCol({ state, dispatch, type }: {
6 | state: EditorState;
7 | dispatch: any;
8 | type: "addBefore" | "addAfter" | "delete";
9 | }): boolean;
10 | export declare function gotoCol({ state, dispatch, type }: {
11 | state: EditorState;
12 | dispatch: any;
13 | type: "before" | "after";
14 | }): boolean;
15 |
--------------------------------------------------------------------------------
/types/src/extensions/dragable/dragable.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | import { PMPluginKey } from "../../prosemirror";
3 | export declare const DragablePluginKey: PMPluginKey;
4 | export declare const Dragable: Extension;
5 |
--------------------------------------------------------------------------------
/types/src/extensions/dragable/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./dragable";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/dragable/utilities.d.ts:
--------------------------------------------------------------------------------
1 | import { EditorView, Transaction, ResolvedPos, PMNode } from "../../prosemirror";
2 | export declare const removePossibleTable: (view: EditorView, event: DragEvent) => Transaction | null;
3 | export declare type ActiveNode = Readonly<{
4 | $pos: ResolvedPos;
5 | node: PMNode;
6 | el: HTMLElement;
7 | offset: number;
8 | }>;
9 | export declare const selectRootNodeByDom: (dom: Element, view: EditorView) => ActiveNode | null;
10 |
--------------------------------------------------------------------------------
/types/src/extensions/dropcursor/dropcursor.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | export interface DropcursorOptions {
3 | color: string | undefined;
4 | width: number | undefined;
5 | class: string | undefined;
6 | }
7 | export declare const DropCursor: Extension;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/dropcursor/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./dropcursor";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/dropcursor/prosemirror-dropcursor.d.ts:
--------------------------------------------------------------------------------
1 | import { Plugin } from "prosemirror-state";
2 | interface DropCursorOptions {
3 | color?: string;
4 | width?: number;
5 | class?: string;
6 | }
7 | export declare function dropCursor(options?: DropCursorOptions): Plugin;
8 | export {};
9 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/excalidraw-view.d.ts:
--------------------------------------------------------------------------------
1 | import { NodeViewProps } from "@tiptap/react";
2 | import React from "react";
3 | export declare const ExcalidrawView: React.NamedExoticComponent;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/excalidraw.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface IExcalidrawAttrs {
3 | createUserId?: string | number;
4 | showPickerOnCreate?: boolean;
5 | width?: number | string;
6 | height?: number;
7 | data?: string;
8 | }
9 | declare module "@tiptap/core" {
10 | interface Commands {
11 | excalidraw: {
12 | setExcalidraw: (attrs?: IExcalidrawAttrs) => ReturnType;
13 | };
14 | }
15 | }
16 | export declare const Excalidraw: Node;
17 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./excalidraw";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | interface IProps {
4 | editor: Editor;
5 | }
6 | export declare const ExcalidrawBubbleMenu: React.FC;
7 | export {};
8 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/menu/edit.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare const showExcalidrawEditor: (editor: Editor, dom?: HTMLElement | undefined) => void;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/menu/modal.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | declare type IProps = {
4 | editor: Editor;
5 | data: {
6 | elements: unknown[];
7 | appState: {
8 | isLoading: false;
9 | };
10 | files: null;
11 | } | null;
12 | onClose: () => void;
13 | };
14 | export declare const ExcalidrawSettingModal: React.FC;
15 | export {};
16 |
--------------------------------------------------------------------------------
/types/src/extensions/excalidraw/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ExcalidrawStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/flow-view.d.ts:
--------------------------------------------------------------------------------
1 | import { NodeViewProps } from "@tiptap/react";
2 | import React from "react";
3 | export declare const FlowView: React.NamedExoticComponent;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/flow.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface IFlowAttrs {
3 | width?: number | string;
4 | height?: number;
5 | svg?: string;
6 | xml?: string;
7 | }
8 | interface IFlowOptions {
9 | HTMLAttributes: Record;
10 | }
11 | declare module "@tiptap/core" {
12 | interface Commands {
13 | flow: {
14 | setFlow: (attrs?: IFlowAttrs) => ReturnType;
15 | };
16 | }
17 | }
18 | export declare const Flow: Node;
19 | export {};
20 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./flow";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const FlowBubbleMenu: ({ editor }: {
3 | editor: any;
4 | }) => JSX.Element;
5 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const DEFAULT_FLOW_DATA = "";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/edit.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare const showFlowEditor: (editor: Editor) => void;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/modal.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | declare type IProps = {
4 | editor: Editor;
5 | data: string;
6 | onClose: () => void;
7 | };
8 | export declare const FlowSettingModal: React.FC;
9 | export {};
10 |
--------------------------------------------------------------------------------
/types/src/extensions/flow/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const FlowStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/focus/focus.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | export interface FocusOptions {
3 | className: string;
4 | mode: "all" | "deepest" | "shallowest";
5 | }
6 | export declare const Focus: Extension;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/focus/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./focus";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/gapcursor/gapcursor.d.ts:
--------------------------------------------------------------------------------
1 | import GapCursor from "@tiptap/extension-gapcursor";
2 | export { GapCursor };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/gapcursor/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./gapcursor";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/hard-break/hard-break.d.ts:
--------------------------------------------------------------------------------
1 | import HardBreak from "@tiptap/extension-hard-break";
2 | export { HardBreak };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/hard-break/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./hard-break";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const FOLD_SVG = "";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/heading.d.ts:
--------------------------------------------------------------------------------
1 | export declare type Level = 1 | 2 | 3 | 4 | 5 | 6;
2 | export interface HeadingOptions {
3 | levels: Level[];
4 | HTMLAttributes: Record;
5 | offset: number;
6 | }
7 | export declare const Heading: import("@tiptap/core").Node;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./heading";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Editor } from '@tiptap/core';
3 | export declare const HeadingStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/slug.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "prosemirror-model";
2 | export default function headingToSlug(node: Node, index?: number): string;
3 | export declare function headingToPersistenceKey(node: Node, id?: string): string;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/heading/utilities.d.ts:
--------------------------------------------------------------------------------
1 | import { PMNode, NodeWithPos } from "../../prosemirror";
2 | export declare function findCollapsedNodes(doc: PMNode): NodeWithPos[];
3 | export declare const handleFoldContent: (event: any, extension: any) => void;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/horizontal-rule/horizontal-rule.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface HorizontalRuleOptions {
3 | HTMLAttributes: Record;
4 | }
5 | declare module "@tiptap/core" {
6 | interface Commands {
7 | horizontalRule: {
8 | setHorizontalRule: () => ReturnType;
9 | };
10 | }
11 | }
12 | export declare const HorizontalRule: Node;
13 |
--------------------------------------------------------------------------------
/types/src/extensions/horizontal-rule/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./horizontal-rule";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/horizontal-rule/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const HorizontalRuleStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/iframe-view.d.ts:
--------------------------------------------------------------------------------
1 | import { NodeViewProps } from "@tiptap/react";
2 | import React from "react";
3 | export declare const IframeView: React.FC;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/iframe.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface IIframeAttrs {
3 | width?: number | string;
4 | height?: number;
5 | url?: string;
6 | }
7 | declare module "@tiptap/core" {
8 | interface Commands {
9 | iframe: {
10 | setIframe: (attrs: IIframeAttrs) => ReturnType;
11 | };
12 | }
13 | }
14 | export declare const Iframe: Node;
15 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./iframe";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | interface IProps {
4 | editor: Editor;
5 | }
6 | export declare const IframeBubbleMenu: React.FC;
7 | export {};
8 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/menu/edit.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const URLEditor: React.FC<{
4 | url: string;
5 | onOk: (arg: {
6 | url: string;
7 | }) => void;
8 | onCancel: () => void;
9 | }>;
10 | export declare const showURLEditor: (editor: Editor, dom?: HTMLElement | undefined) => void;
11 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/iframe/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const IframeStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/image/image-view.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { NodeViewProps } from "@tiptap/react";
3 | export declare const ImageView: React.FC;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/image/image.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export declare const inputRegex: RegExp;
3 | declare module "@tiptap/core" {
4 | interface Commands {
5 | image: {
6 | setImage: (options: {
7 | src: string;
8 | width?: number;
9 | height?: number;
10 | }) => ReturnType;
11 | };
12 | }
13 | }
14 | export declare const Image: Node;
15 |
--------------------------------------------------------------------------------
/types/src/extensions/image/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./image";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/image/menu/bubble-menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ImageBubbleMenu: React.NamedExoticComponent<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/image/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./bubble-menu";
2 | export * from "./static-menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/image/menu/static-menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ImageStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/italic/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./italic";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/italic/italic.d.ts:
--------------------------------------------------------------------------------
1 | import { Italic } from "@tiptap/extension-italic";
2 | export { Italic };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/italic/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const ItalicStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/link/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./link";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/link/link.d.ts:
--------------------------------------------------------------------------------
1 | export declare const extractHrefFromMarkdownLink: (match: RegExpMatchArray) => {
2 | href: string | undefined;
3 | };
4 | export declare const Link: import("@tiptap/core").Mark;
5 |
--------------------------------------------------------------------------------
/types/src/extensions/link/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | interface IProps {
4 | editor: Editor;
5 | }
6 | export declare const LinkBubbleMenu: React.FC;
7 | export {};
8 |
--------------------------------------------------------------------------------
/types/src/extensions/link/menu/edit.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const LinkEdit: React.FC<{
4 | text: string;
5 | href: string;
6 | onOk: (arg: {
7 | text: string;
8 | href: string;
9 | }) => void;
10 | onCancel: () => void;
11 | }>;
12 | export declare const showLinkEditor: (editor: Editor, dom?: HTMLElement | undefined) => void;
13 |
--------------------------------------------------------------------------------
/types/src/extensions/link/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/link/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const LinkStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/list-item/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./list-item";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/list-item/list-item.d.ts:
--------------------------------------------------------------------------------
1 | import { ListItem } from "@tiptap/extension-list-item";
2 | export { ListItem };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/mention/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./mention";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/mention/mention-menu-view.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import React from "react";
3 | import { User } from "../../editor/provider";
4 | interface IProps {
5 | editor: Editor;
6 | items: User[];
7 | command: (command: any) => void;
8 | }
9 | export declare const MentionMenuView: React.FC;
10 | export declare const MentionLoading: () => JSX.Element;
11 | export {};
12 |
--------------------------------------------------------------------------------
/types/src/extensions/mention/mention.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | import { PMNode } from "../../prosemirror";
3 | export interface MentionOptions {
4 | HTMLAttributes: {};
5 | char: string;
6 | renderLabel: (arg: {
7 | options: MentionOptions;
8 | node: PMNode;
9 | }) => string;
10 | }
11 | export declare const Mention: Node;
12 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./mind";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const MindBubbleMenu: ({ editor }: {
3 | editor: any;
4 | }) => JSX.Element;
5 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/constant.d.ts:
--------------------------------------------------------------------------------
1 | export declare const PROGRESSES: {
2 | text: string;
3 | value: number;
4 | }[];
5 | export declare const PRIORITIES: {
6 | text: string;
7 | value: number;
8 | }[];
9 | export declare const TEMPLATES: {
10 | label: string;
11 | value: string;
12 | }[];
13 | export declare const THEMES: {
14 | label: string;
15 | value: string;
16 | style: {
17 | color: string;
18 | background: string;
19 | };
20 | }[];
21 | export declare const MIN_ZOOM = 10;
22 | export declare const MAX_ZOOM = 200;
23 | export declare const ZOOM_STEP = 15;
24 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/edit.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare const showMindEditor: (editor: Editor) => void;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./static";
2 | export * from "./bubble";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/kityminder/constant.d.ts:
--------------------------------------------------------------------------------
1 | export declare const PROGRESSES: {
2 | text: string;
3 | value: number;
4 | }[];
5 | export declare const PRIORITIES: {
6 | text: string;
7 | value: number;
8 | }[];
9 | export declare const TEMPLATES: {
10 | label: string;
11 | value: string;
12 | }[];
13 | export declare const THEMES: {
14 | label: string;
15 | value: string;
16 | style: {
17 | color: string;
18 | background: string;
19 | };
20 | }[];
21 | export declare const MIN_ZOOM = 10;
22 | export declare const MAX_ZOOM = 200;
23 | export declare const ZOOM_STEP = 15;
24 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/kityminder/index.d.ts:
--------------------------------------------------------------------------------
1 | export declare const load: () => Promise;
2 | declare type Options = {
3 | container: HTMLElement;
4 | isEditable: boolean;
5 | data?: Record;
6 | };
7 | export declare function renderMind(options: Options): any;
8 | export {};
9 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/modal.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | declare type IProps = {
4 | editor: Editor;
5 | data: string;
6 | onClose: () => void;
7 | };
8 | export declare const MindSettingModal: React.FC;
9 | export {};
10 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const MindStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/style.d.ts:
--------------------------------------------------------------------------------
1 | export declare const StyledMindEditorContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/bgcolor.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const BgColor: ({ editor, bgColor, selectedNode, setBackgroundColor }: {
3 | editor: any;
4 | bgColor: any;
5 | selectedNode: any;
6 | setBackgroundColor: any;
7 | }) => JSX.Element;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/font-color.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const FontColor: ({ editor, selectedNode, setFontColor, textColor }: {
3 | editor: any;
4 | selectedNode: any;
5 | setFontColor: any;
6 | textColor: any;
7 | }) => JSX.Element;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/help.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Help: () => JSX.Element;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/image.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Image: ({ editor, disabled, image, setImage }: {
3 | editor: any;
4 | disabled: any;
5 | image: any;
6 | setImage: any;
7 | }) => JSX.Element;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Toolbar: ({ editor, mind }: {
3 | editor: any;
4 | mind: any;
5 | }) => JSX.Element;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/link.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Link: ({ editor, disabled, link, setLink }: {
3 | editor: any;
4 | disabled: any;
5 | link: any;
6 | setLink: any;
7 | }) => JSX.Element;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/priority.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Priority: ({ editor, selectedNode, setPriority }: {
3 | editor: any;
4 | selectedNode: any;
5 | setPriority: any;
6 | }) => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/progress.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Progress: ({ editor, selectedNode, setProgress }: {
3 | editor: any;
4 | selectedNode: any;
5 | setProgress: any;
6 | }) => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/styled.d.ts:
--------------------------------------------------------------------------------
1 | export declare const StyledSection: import("styled-components").StyledComponent<"section", any, {}, never>;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/template.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Template: ({ editor, template, setTemplate }: {
3 | editor: any;
4 | template: any;
5 | setTemplate: any;
6 | }) => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/menu/toolbar/theme.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare const Theme: ({ editor, theme, setTheme }: {
3 | editor: any;
4 | theme: any;
5 | setTheme: any;
6 | }) => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/mind-view.d.ts:
--------------------------------------------------------------------------------
1 | import { NodeViewProps } from "@tiptap/react";
2 | import React from "react";
3 | export declare const MindView: React.NamedExoticComponent;
4 |
--------------------------------------------------------------------------------
/types/src/extensions/mind/mind.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export declare const DEFAULT_MIND_DATA: string;
3 | export interface IMindAttrs {
4 | width?: number | string;
5 | height?: number;
6 | data?: string;
7 | svg?: string;
8 | template?: string;
9 | theme?: string;
10 | zoom?: number;
11 | }
12 | interface IMindOptions {
13 | HTMLAttributes: Record;
14 | }
15 | declare module "@tiptap/core" {
16 | interface Commands {
17 | mind: {
18 | setMind: (attrs?: IMindAttrs) => ReturnType;
19 | };
20 | }
21 | }
22 | export declare const Mind: Node;
23 | export {};
24 |
--------------------------------------------------------------------------------
/types/src/extensions/ordered-list/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./ordered-list";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/ordered-list/ordered-list.d.ts:
--------------------------------------------------------------------------------
1 | import { OrderedList } from "@tiptap/extension-ordered-list";
2 | export { OrderedList };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/paragraph/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./paragraph";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/paragraph/paragraph.d.ts:
--------------------------------------------------------------------------------
1 | import { Paragraph } from "@tiptap/extension-paragraph";
2 | export { Paragraph };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/placeholder/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./placeholder";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/placeholder/placeholder.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor, Extension } from "@tiptap/core";
2 | import { PMNode } from "../../prosemirror";
3 | export interface PlaceholderOptions {
4 | emptyEditorClass: string;
5 | emptyNodeClass: string;
6 | placeholder: ((PlaceholderProps: {
7 | editor: Editor;
8 | node: PMNode;
9 | pos: number;
10 | hasAnchor: boolean;
11 | }) => string) | string;
12 | showOnlyWhenEditable: boolean;
13 | showOnlyCurrent: boolean;
14 | includeChildren: boolean;
15 | }
16 | export declare const Placeholder: Extension;
17 |
--------------------------------------------------------------------------------
/types/src/extensions/slash/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./slash";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/slash/slash-menu-view.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import React from "react";
3 | import { SlashMenuItem } from "./slash";
4 | interface IProps {
5 | editor: Editor;
6 | items: SlashMenuItem[];
7 | command: (command: any) => void;
8 | }
9 | export declare const SlashMenuView: React.FC;
10 | export {};
11 |
--------------------------------------------------------------------------------
/types/src/extensions/slash/slash.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor, Node } from "@tiptap/core";
3 | export declare type SlashMenuItem = {
4 | icon: React.ReactNode;
5 | text: string;
6 | slash: string;
7 | action: (editor: Editor) => void;
8 | } | {
9 | divider: true;
10 | title: string;
11 | };
12 | export interface SlashOptions {
13 | items: SlashMenuItem[];
14 | pluginKey: string;
15 | char: string;
16 | }
17 | export declare const Slash: Node;
18 |
--------------------------------------------------------------------------------
/types/src/extensions/status/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./status";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/status/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const StatusStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/status/status-view.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { NodeViewProps } from "@tiptap/react";
3 | export declare const STATUS_COLORS: Array<[string, string, string, string]>;
4 | export declare const StatusView: React.FC;
5 |
--------------------------------------------------------------------------------
/types/src/extensions/status/status.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | declare type IStatusAttrs = {
3 | createUserId?: string | number;
4 | showPickerOnCreate?: boolean;
5 | color?: string;
6 | text?: string;
7 | };
8 | declare module "@tiptap/core" {
9 | interface Commands {
10 | status: {
11 | setStatus: (arg: IStatusAttrs) => ReturnType;
12 | };
13 | }
14 | }
15 | export declare const Status: Node;
16 | export {};
17 |
--------------------------------------------------------------------------------
/types/src/extensions/strike/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./strike";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/strike/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const StrikeStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/strike/strike.d.ts:
--------------------------------------------------------------------------------
1 | import { Strike } from "@tiptap/extension-strike";
2 | export { Strike };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/subscript/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./subscript";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/subscript/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const SubscriptStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/subscript/subscript.d.ts:
--------------------------------------------------------------------------------
1 | import { Subscript } from "@tiptap/extension-subscript";
2 | export { Subscript };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/superscript/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./superscript";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/superscript/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const SuperscriptStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/superscript/superscript.d.ts:
--------------------------------------------------------------------------------
1 | import { Superscript } from "@tiptap/extension-superscript";
2 | export { Superscript };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/table/cell-menu-plugin/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare const TableCellMenuPlugin: (editor: Editor) => import("prosemirror-state").Plugin;
3 |
--------------------------------------------------------------------------------
/types/src/extensions/table/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./table";
2 | export * from "./table-cell";
3 | export * from "./table-header";
4 | export * from "./table-row";
5 | export * from "./table-kit";
6 | export * from "./menu";
7 |
--------------------------------------------------------------------------------
/types/src/extensions/table/menu/bubble.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const TableBubbleMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/table/menu/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./bubble";
2 | export * from "./static";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/table/menu/static.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const TableStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 | export * from "./bubble";
7 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table-cell/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface TableCellOptions {
3 | HTMLAttributes: Record;
4 | }
5 | export declare const TableCell: Node void>;
7 | }>;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table-header/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "@tiptap/core";
2 | export interface TableHeaderOptions {
3 | HTMLAttributes: Record;
4 | }
5 | export declare const TableHeader: Node void>;
7 | }>;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table-kit.d.ts:
--------------------------------------------------------------------------------
1 | import { AnyExtension } from "@tiptap/core";
2 | export declare const TableExtensions: AnyExtension[];
3 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table-row/index.d.ts:
--------------------------------------------------------------------------------
1 | export declare const TableRow: import("@tiptap/core").Node;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table/index.d.ts:
--------------------------------------------------------------------------------
1 | export declare const Table: import("@tiptap/core").Node;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/table/table/table-view.d.ts:
--------------------------------------------------------------------------------
1 | import { Node as ProseMirrorNode } from "prosemirror-model";
2 | import { NodeView } from "prosemirror-view";
3 | export declare function updateColumns(node: ProseMirrorNode, colgroup: Element, table: Element, cellMinWidth: number, overrideCol?: number, overrideValue?: any): void;
4 | export declare class TableView implements NodeView {
5 | node: ProseMirrorNode;
6 | cellMinWidth: number;
7 | dom: Element;
8 | scrollDom: Element;
9 | table: Element;
10 | colgroup: Element;
11 | contentDOM: Element;
12 | constructor(node: ProseMirrorNode, cellMinWidth: number);
13 | update(node: ProseMirrorNode): boolean;
14 | ignoreMutation(mutation: MutationRecord | {
15 | type: "selection";
16 | target: Element;
17 | }): boolean;
18 | }
19 |
--------------------------------------------------------------------------------
/types/src/extensions/text-align/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./text-align";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/text-align/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const TextAlignStaticMenu: React.NamedExoticComponent<{
4 | editor: Editor;
5 | getPopupContainer?: (() => HTMLElement) | undefined;
6 | }>;
7 |
--------------------------------------------------------------------------------
/types/src/extensions/text-align/text-align.d.ts:
--------------------------------------------------------------------------------
1 | export declare const TextAlign: import("@tiptap/core").Extension;
2 |
--------------------------------------------------------------------------------
/types/src/extensions/text/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./text";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/text/text.d.ts:
--------------------------------------------------------------------------------
1 | import { Text } from "@tiptap/extension-text";
2 | export { Text };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/trailing-node/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./trailing-node";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/trailing-node/trailing-node.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | /**
3 | * Extension based on:
4 | * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js
5 | * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts
6 | */
7 | export interface TrailingNodeOptions {
8 | node: string;
9 | notAfter: string[];
10 | }
11 | export declare const TrailingNode: Extension;
12 |
--------------------------------------------------------------------------------
/types/src/extensions/underline/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./underline";
2 | export * from "./menu";
3 |
--------------------------------------------------------------------------------
/types/src/extensions/underline/menu.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Editor } from "@tiptap/core";
3 | export declare const UnderlineStaticMenu: React.FC<{
4 | editor: Editor;
5 | }>;
6 |
--------------------------------------------------------------------------------
/types/src/extensions/underline/underline.d.ts:
--------------------------------------------------------------------------------
1 | import { Underline } from "@tiptap/extension-underline";
2 | export { Underline };
3 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./unique-id";
2 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/unique-id.d.ts:
--------------------------------------------------------------------------------
1 | import { Extension } from "@tiptap/core";
2 | import { Transaction } from "../../prosemirror";
3 | export interface UniqueIDOptions {
4 | attributeName: string;
5 | types: string[];
6 | generateID: () => any;
7 | filterTransaction: ((transaction: Transaction) => boolean) | null;
8 | }
9 | export declare const UniqueID: Extension;
10 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/utilities/array-difference.d.ts:
--------------------------------------------------------------------------------
1 | export interface ArrayDifference {
2 | added: any[];
3 | removed: any[];
4 | common: any[];
5 | }
6 | /**
7 | * Checks for added, removed and common items between two arrays.
8 | */
9 | export default function arrayDifference(array1: any[], array2: any[]): ArrayDifference;
10 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/utilities/combine-transaction-steps.d.ts:
--------------------------------------------------------------------------------
1 | import { Node as ProseMirrorNode } from "prosemirror-model";
2 | import { Transaction } from "prosemirror-state";
3 | import { Transform } from "prosemirror-transform";
4 | /**
5 | * Returns a new `Transform` based on all steps of the passed transactions.
6 | */
7 | export default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform;
8 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/utilities/find-duplicates.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Returns a list of duplicated items within an array.
3 | */
4 | export default function findDuplicates(items: any[]): any[];
5 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/utilities/get-changed-ranges.d.ts:
--------------------------------------------------------------------------------
1 | import { Transform } from "prosemirror-transform";
2 | export declare type ChangedRange = {
3 | oldStart: number;
4 | oldEnd: number;
5 | newStart: number;
6 | newEnd: number;
7 | };
8 | /**
9 | * Returns a list of changed ranges
10 | * based on the first and last state of all steps.
11 | */
12 | export default function getChangedRanges(transform: Transform): ChangedRange[];
13 |
--------------------------------------------------------------------------------
/types/src/extensions/unique-id/utilities/remove-duplicates.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Removes duplicated values within an array.
3 | * Supports numbers, strings and objects.
4 | */
5 | export default function removeDuplicates(array: T[], by?: {
6 | (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
7 | (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
8 | }): T[];
9 |
--------------------------------------------------------------------------------
/types/src/hooks/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./use-active";
2 | export * from "./use-attributes";
3 |
--------------------------------------------------------------------------------
/types/src/hooks/use-active.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from '@tiptap/core';
2 | export declare const useActive: (editor: Editor, name: string, attributes?: Record | undefined) => boolean;
3 |
--------------------------------------------------------------------------------
/types/src/hooks/use-attributes.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare function useAttributes(editor: Editor, attribute: string, defaultValue?: T, map?: (arg: T) => R): R;
3 |
--------------------------------------------------------------------------------
/types/src/icons/icon.d.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export declare type IconProps = {
3 | style?: React.CSSProperties;
4 | onClick?: () => void;
5 | svg: React.ReactNode;
6 | };
7 | export declare const Icon: React.ForwardRefExoticComponent>;
8 | export declare const buildIcon: (svg: IconProps["svg"]) => React.ForwardRefExoticComponent & React.RefAttributes>;
9 |
--------------------------------------------------------------------------------
/types/src/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from "./editor";
2 | export * from "./utilities";
3 | export * from "./styles/theme";
4 | export * from "./icons";
5 | export * from "./hooks";
6 |
--------------------------------------------------------------------------------
/types/src/prosemirror/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "prosemirror-model";
2 | export { Plugin as PMPlugin, PluginKey as PMPluginKey, Selection, NodeSelection, TextSelection, Transaction, EditorState } from "prosemirror-state";
3 | export { Node as PMNode, Mark as PMMark, Slice, Fragment, ResolvedPos } from "prosemirror-model";
4 | export { EditorView, DecorationSet, Decoration, DecorationAttrs, __serializeForClipboard } from "prosemirror-view";
5 | export * from "./prosemirror-utils";
6 | export declare type NodeWithPos = {
7 | pos: number;
8 | node: Node;
9 | };
10 |
--------------------------------------------------------------------------------
/types/src/stories/collaboration.stories.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | declare const meta: {
3 | title: string;
4 | };
5 | export default meta;
6 | export declare const Collaboration: () => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/stories/editor.stories.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | declare const meta: {
3 | title: string;
4 | };
5 | export default meta;
6 | export declare const Full: () => JSX.Element;
7 |
--------------------------------------------------------------------------------
/types/src/styles/editor.d.ts:
--------------------------------------------------------------------------------
1 | export declare const StyledEditor: import("styled-components").StyledComponent<"div", any, {}, never>;
2 |
--------------------------------------------------------------------------------
/types/src/utilities/clamp.d.ts:
--------------------------------------------------------------------------------
1 | export declare function clamp(val: number, min: number, max: number): number;
2 |
--------------------------------------------------------------------------------
/types/src/utilities/copy/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare function copy(text: string | {
3 | text: string;
4 | format: string;
5 | }[]): any;
6 | export declare const copyNode: (editor: Editor, extensionName: string) => void;
7 | export declare const deleteNode: (editor: Editor, extensionName: string) => boolean;
8 |
--------------------------------------------------------------------------------
/types/src/utilities/create-node.d.ts:
--------------------------------------------------------------------------------
1 | import { ResolvedPos } from "prosemirror-model";
2 | import { EditorState, Transaction } from "prosemirror-state";
3 | export declare function atTheEndOfDoc(state: EditorState): boolean;
4 | export declare function atTheBeginningOfDoc(state: EditorState): boolean;
5 | export declare function atTheEndOfBlock(state: EditorState): boolean;
6 | export declare function endPositionOfParent(resolvedPos: ResolvedPos): number;
7 | export declare function canMoveUp(state: EditorState): boolean;
8 | export declare function canMoveDown(state: EditorState): boolean;
9 | export declare function preventDefault(): () => boolean;
10 | export declare function insertNewLine(): (state: any, dispatch: any) => boolean;
11 | export declare const createNewParagraphAbove: (state: any, dispatch: any) => boolean;
12 | export declare const createNewParagraphBelow: (state: any, dispatch: any) => boolean;
13 | export declare function createParagraphNear(append?: boolean): (state: any, dispatch: any) => boolean;
14 | export declare function addParagraphAtEnd(tr: Transaction): void;
15 | export declare function createParagraphAtEnd(): (state: any, dispatch: any) => boolean;
16 |
--------------------------------------------------------------------------------
/types/src/utilities/file.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | export declare function uploadImage(editor: Editor): Promise<{
3 | url: string;
4 | width: number;
5 | height: number;
6 | }>;
7 |
--------------------------------------------------------------------------------
/types/src/utilities/index.d.ts:
--------------------------------------------------------------------------------
1 | import "requestidlecallback-polyfill";
2 | export * from "./clamp";
3 | export * from "./copy";
4 | export * from "./create-node";
5 | export * from "./mark";
6 | export * from "./node";
7 | export * from "./pos";
8 | export * from "./file";
9 | export * from "./throttle";
10 | export * from "./svg-to-datauri";
11 |
--------------------------------------------------------------------------------
/types/src/utilities/mark.d.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from "prosemirror-state";
2 | import { Mark, MarkType } from "prosemirror-model";
3 | export declare const isMarkActive: (type: MarkType) => (state: EditorState) => boolean;
4 | export declare function findMarkPosition(state: EditorState, mark: Mark, from: number, to: number): {
5 | start: number;
6 | end: number;
7 | };
8 |
--------------------------------------------------------------------------------
/types/src/utilities/node.d.ts:
--------------------------------------------------------------------------------
1 | import { Editor } from "@tiptap/core";
2 | import { EditorState } from "prosemirror-state";
3 | import { Node } from "prosemirror-model";
4 | export declare function getCurrentNode(state: EditorState): Node | null;
5 | export declare function getNodeAtPos(state: EditorState, pos: number): Node | null;
6 | export declare function isNodeActive(editor: Editor, extensionName: string): boolean;
7 | export declare function isInCustomNode(state: EditorState, nodeName: string): boolean;
8 | export declare function isInCodeBlock(state: EditorState): boolean;
9 | export declare function isInTitle(state: EditorState): boolean;
10 | export declare function isInCallout(state: EditorState): boolean;
11 | export declare function isTitleNode(node: Node): boolean;
12 | export declare function isBulletListNode(node: Node): boolean;
13 | export declare function isOrderedListNode(node: Node): boolean;
14 | export declare function isTodoListNode(node: Node): boolean;
15 | export declare function isListNode(node: Node): boolean;
16 |
--------------------------------------------------------------------------------
/types/src/utilities/pos.d.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from "prosemirror-state";
2 | /**
3 | * 根据文档内容大小获取不越界的位置
4 | * @param state
5 | * @param pos
6 | * @returns
7 | */
8 | export declare function safePos(state: EditorState, pos: number): number;
9 |
--------------------------------------------------------------------------------
/types/src/utilities/svg-to-datauri.d.ts:
--------------------------------------------------------------------------------
1 | export declare function svgToDataURI(svg: any): string;
2 |
--------------------------------------------------------------------------------
/types/src/utilities/throttle.d.ts:
--------------------------------------------------------------------------------
1 | import throttle from "lodash.throttle";
2 | export { throttle };
3 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import { defineConfig } from "vite";
3 | import pkg from "./package.json";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [],
8 | build: {
9 | sourcemap: true,
10 | lib: {
11 | entry: path.resolve(__dirname, "src/index.tsx"),
12 | name: "MagicEditor",
13 | fileName: "magiceditor"
14 | },
15 | rollupOptions: {
16 | output: {
17 | globals: {
18 | react: "React",
19 | "react-dom": "ReactDOM"
20 | }
21 | }
22 | }
23 | }
24 | });
25 |
--------------------------------------------------------------------------------