diff --git a/demo/main.tsx b/demo/main.tsx index 0d072d9a..fdee5415 100644 --- a/demo/main.tsx +++ b/demo/main.tsx @@ -68,7 +68,7 @@ const editorState = EditorState.create({ schema, doc: schema.nodes.doc.create({}, [ schema.nodes.paragraph.create({}, [ - schema.text("This", [schema.marks.em.create()]), + schema.text("This", [schema.marks.em.create(), schema.marks.em.create()]), schema.text(" is the first paragraph"), ]), schema.nodes.paragraph.create( diff --git a/src/components/MarkView.tsx b/src/components/MarkView.tsx new file mode 100644 index 00000000..1c1b865c --- /dev/null +++ b/src/components/MarkView.tsx @@ -0,0 +1,24 @@ +import { Mark } from "prosemirror-model"; +import React, { ReactNode, forwardRef } from "react"; + +import { OutputSpec } from "./OutputSpec.js"; + +type Props = { + mark: Mark; + children: ReactNode; +}; + +export const MarkView = forwardRef(function MarkView( + { mark, children }: Props, + ref +) { + const outputSpec = mark.type.spec.toDOM?.(mark, true); + if (!outputSpec) + throw new Error(`Mark spec for ${mark.type.name} is missing toDOM`); + + return ( + + {children} + + ); +}); diff --git a/src/components/NodeView.tsx b/src/components/NodeView.tsx index de8aa116..356d4153 100644 --- a/src/components/NodeView.tsx +++ b/src/components/NodeView.tsx @@ -14,6 +14,7 @@ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js" import { NodeViewContext } from "../contexts/NodeViewContext.js"; import { NodeViewDesc, ViewDesc } from "../descriptors/ViewDesc.js"; +import { MarkView } from "./MarkView.js"; import { NodeViewComponentProps } from "./NodeViewComponentProps.js"; import { OutputSpec } from "./OutputSpec.js"; import { TextNodeView } from "./TextNodeView.js"; @@ -29,10 +30,10 @@ export function NodeView({ node, pos }: Props) { useContext(NodeViewContext); const siblingDescriptors = useContext(ChildDescriptorsContext); const childDescriptors: ViewDesc[] = []; - const ref = useRef(null); + const domRef = useRef(null); useLayoutEffect(() => { - if (!ref.current) return; + if (!domRef.current) return; const firstChildDesc = childDescriptors[0]; @@ -41,15 +42,15 @@ export function NodeView({ node, pos }: Props) { node, [], DecorationSet.empty, - ref.current, + domRef.current, firstChildDesc?.dom.parentElement ?? null, - ref.current, + domRef.current, posToDesc, domToDesc ); desc.children = childDescriptors; posToDesc.set(pos, desc); - domToDesc.set(ref.current, desc); + domToDesc.set(domRef.current, desc); siblingDescriptors.push(desc); for (const childDesc of childDescriptors) { @@ -57,12 +58,12 @@ export function NodeView({ node, pos }: Props) { } }); - const children: ReactNode[] = []; + const content: ReactNode[] = []; const innerPos = pos + 1; node.content.forEach((childNode, offset) => { const childPos = innerPos + offset; if (childNode.isText) { - children.push( + content.push( {(siblingDescriptors) => ( ); } else { - children.push( - - ); + content.push(); } }); - if (!children.length) { - children.push(); + if (!content.length) { + content.push(); } + const children = ( + + {content} + + ); + const Component: | ForwardRefExoticComponent< NodeViewComponentProps & RefAttributes @@ -91,9 +96,10 @@ export function NodeView({ node, pos }: Props) { | undefined = nodeViews[node.type.name]; if (Component) { - return ( + return node.marks.reduce( + (element, mark) => {element}, - - {children} - + {children} ); } @@ -112,11 +116,10 @@ export function NodeView({ node, pos }: Props) { const outputSpec: DOMOutputSpec | undefined = node.type.spec.toDOM?.(node); if (outputSpec) { - return ( - - - {children} - + return node.marks.reduce( + (element, mark) => {element}, + + {children} ); } diff --git a/src/components/TextNodeView.tsx b/src/components/TextNodeView.tsx index cf8cab03..b00a2aa6 100644 --- a/src/components/TextNodeView.tsx +++ b/src/components/TextNodeView.tsx @@ -9,7 +9,7 @@ import { } from "../contexts/NodeViewContext.js"; import { TextViewDesc, ViewDesc } from "../descriptors/ViewDesc.js"; -import { OutputSpec } from "./OutputSpec.js"; +import { MarkView } from "./MarkView.js"; type Props = { node: Node; @@ -75,13 +75,10 @@ export class TextNodeView extends Component { } render() { - return this.props.node.marks.reduce((children, mark) => { - const outputSpec = mark.type.spec.toDOM?.(mark, true); - if (!outputSpec) - throw new Error(`Mark spec for ${mark.type.name} is missing toDOM`); - - return {children}; - }, <>{this.props.node.text}); + return this.props.node.marks.reduce( + (children, mark) => {children}, + <>{this.props.node.text} + ); } }