From f102c8033b89f96abe5f9049b6a0066f3c5cf01b Mon Sep 17 00:00:00 2001 From: jkcs <1778768609@qq.com> Date: Thu, 18 Jul 2024 10:41:53 +0800 Subject: [PATCH 1/5] test equation --- .../13-equation/.bnexample.json | 11 + examples/03-ui-components/13-equation/App.tsx | 98 +++++++++ .../03-ui-components/13-equation/Equation.tsx | 206 ++++++++++++++++++ .../03-ui-components/13-equation/README.md | 11 + .../03-ui-components/13-equation/index.html | 14 ++ .../03-ui-components/13-equation/main.tsx | 11 + .../03-ui-components/13-equation/package.json | 40 ++++ .../03-ui-components/13-equation/styles.css | 74 +++++++ .../13-equation/tsconfig.json | 36 +++ .../13-equation/vite.config.ts | 32 +++ package-lock.json | 10 +- playground/package.json | 3 + playground/src/examples.gen.tsx | 27 +++ 13 files changed, 570 insertions(+), 3 deletions(-) create mode 100644 examples/03-ui-components/13-equation/.bnexample.json create mode 100644 examples/03-ui-components/13-equation/App.tsx create mode 100644 examples/03-ui-components/13-equation/Equation.tsx create mode 100644 examples/03-ui-components/13-equation/README.md create mode 100644 examples/03-ui-components/13-equation/index.html create mode 100644 examples/03-ui-components/13-equation/main.tsx create mode 100644 examples/03-ui-components/13-equation/package.json create mode 100644 examples/03-ui-components/13-equation/styles.css create mode 100644 examples/03-ui-components/13-equation/tsconfig.json create mode 100644 examples/03-ui-components/13-equation/vite.config.ts diff --git a/examples/03-ui-components/13-equation/.bnexample.json b/examples/03-ui-components/13-equation/.bnexample.json new file mode 100644 index 0000000000..1aadbc234b --- /dev/null +++ b/examples/03-ui-components/13-equation/.bnexample.json @@ -0,0 +1,11 @@ +{ + "playground": true, + "docs": false, + "author": "matthewlipski", + "tags": ["Intermediate", "Blocks", "Custom Schemas", "Suggestion Menus", "Slash Menu"], + "dependencies": { + "katex": "^0.16.11", + "@types/katex": "^0.16.7", + "react-icons": "^5.2.1" + } +} diff --git a/examples/03-ui-components/13-equation/App.tsx b/examples/03-ui-components/13-equation/App.tsx new file mode 100644 index 0000000000..567bb52e9a --- /dev/null +++ b/examples/03-ui-components/13-equation/App.tsx @@ -0,0 +1,98 @@ +import { + BlockNoteSchema, + defaultInlineContentSpecs, + filterSuggestionItems, + insertOrUpdateBlock, +} from "@blocknote/core"; +import "@blocknote/core/fonts/inter.css"; +import { + SuggestionMenuController, + getDefaultReactSlashMenuItems, + useCreateBlockNote, +} from "@blocknote/react"; +import { BlockNoteView } from "@blocknote/mantine"; +import "@blocknote/mantine/style.css"; + +import { LaTex } from "./Equation"; + +// Our schema with block specs, which contain the configs and implementations for blocks +// that we want our editor to use. +const schema = BlockNoteSchema.create({ + inlineContentSpecs: { + ...defaultInlineContentSpecs, + latex: LaTex, + }, +}); + +// Slash menu item to insert an Alert block +const insertLaTex = (editor: typeof schema.BlockNoteEditor) => ({ + title: "latex", + key: "latex", + subtext: "Used for a top-level heading", + aliases: ["latex", "heading1", "h1"], + group: "Other", + onItemClick: () => { + insertOrUpdateBlock(editor, { + type: "paragraph", + content: [ + { + type: "latex", + props: { + open: true, + }, + content: "\\sqrt{a^2 + b^2}", + }, + ], + }); + }, +}); + +export default function App() { + // Creates a new editor instance. + const editor = useCreateBlockNote({ + schema, + initialContent: [ + { + type: "paragraph", + content: [ + "latex text editor ", + { + type: "latex", + content: "c = \\pm\\sqrt{a^2 + b^2}", + }, + ], + }, + { + type: "paragraph", + }, + { + type: "paragraph", + content: [ + { + type: "latex", + content: + "\\int \\frac{1}{\\sqrt{1-x^{2}}}\\mathrm{d}x= \\arcsin x +C", + }, + ], + }, + { + type: "paragraph", + }, + ], + }); + + // Renders the editor instance. + return ( + + + filterSuggestionItems( + [...getDefaultReactSlashMenuItems(editor), insertLaTex(editor)], + query + ) + } + /> + + ); +} diff --git a/examples/03-ui-components/13-equation/Equation.tsx b/examples/03-ui-components/13-equation/Equation.tsx new file mode 100644 index 0000000000..8bd958ded7 --- /dev/null +++ b/examples/03-ui-components/13-equation/Equation.tsx @@ -0,0 +1,206 @@ +import { useComponentsContext } from "@blocknote/react"; +import { NodeView } from "prosemirror-view"; +import { BlockNoteEditor, propsToAttributes } from "@blocknote/core"; +import { + NodeViewProps, + NodeViewRenderer, + NodeViewWrapper, + ReactNodeViewRenderer, +} from "@tiptap/react"; +import { + createStronglyTypedTiptapNode, + createInternalInlineContentSpec, +} from "@blocknote/core"; +import { mergeAttributes } from "@tiptap/core"; +import { ChangeEvent, useEffect, useState, useRef } from "react"; +import katex from "katex"; +import "katex/dist/katex.min.css"; +import "./styles.css"; + +function LaTexView() { + const nodeView: + | ((this: { + name: string; + options: any; + storage: any; + editor: any; + type: any; + parent: any; + }) => NodeViewRenderer) + | null = function () { + const BlockContent = (props: NodeViewProps & { selectionHack: any }) => { + /* eslint-disable react-hooks/rules-of-hooks */ + const editor: BlockNoteEditor = this.options.editor; + const content = props.node.textContent; + const open = props.node.attrs.open; + const textareaRef = useRef(null); + const contentRef = useRef(null); + const [html, setHtml] = useState(""); + const [loading, setLoading] = useState(false); + const Components = useComponentsContext()!; + + useEffect(() => { + setLoading(true); + const html = katex.renderToString(content, { + throwOnError: false, + }); + setHtml(html); + setLoading(false); + }, [content]); + + useEffect(() => { + if (open) { + if (contentRef.current) { + contentRef.current.click(); + } + setTimeout(() => { + if (textareaRef.current) { + textareaRef.current?.focus(); + textareaRef.current?.setSelectionRange( + textareaRef.current.value.length, + textareaRef.current.value.length + ); + } + }); + } + }, [open]); + + const handleChange = (e: ChangeEvent) => { + const val = e.target.value; + const pos = props.getPos?.(); + const node = props.node; + const view = editor._tiptapEditor.view; + + const tr = view.state.tr.replaceWith( + pos, + pos + node.nodeSize, + view.state.schema.nodes.latex.create( + { + ...node.attrs, + }, + val ? view.state.schema.text(val) : null + ) + ); + + view.dispatch(tr); + }; + + return ( + + + + + {loading ? ( + latex loading... + ) : ( + + )} + + + +