How to use prosemirror to edit TXT inside SVG

Hello,

I’ve implemented a prosemirror for HTML with my own schema and it’s working great.

Now my client need to be able to edit text inside SVG.

For instance, Take a simple SVG like:

<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
  <text x="0" y="20" id="svgText">Hello</text>
</svg>

I started by creating a very simple schema to test SVG text editing:

const schema = new Schema({
    nodes: {
        doc: {
            content: "inline*",
        },
        text: {
            group: "inline"
        },
    },
    marks: {
        mine: {
            attrs: {
                style: {
                    default: null
                },
                color: {
                    default: null
                }
            },
            parseDOM: [
                {
                    tag: "tspan",
                    getAttrs(dom) {
                        let {
                            fontWeight,
                            fill
                        } = dom.style;
                        let style = null,
                            color = null;

                        if (fontWeight) {
                            style = fontWeight;
                        }
                        if (fill) {
                            color = fill;
                        }

                        return {
                            style,
                            color
                        };
                    }
                },
            ],
            toDOM(node) {
                const styles = [],
                    attrs = {};

                if (node.attrs.style) {
                    styles.push('font-weight: '+node.attrs.style);
                }
                if (node.attrs.color) {
                    styles.push('fill: '+node.attrs.color);
                }

                if (styles.length) {
                    attrs.style = styles.join(' ');
                }

                return ["tspan", attrs, 0];
            },
        }
    }
});

I can create a state with that very simply:

const state = EditorState.create({
    doc: DOMParser.fromSchema(schema).parse(svgText),
  });

And i’ts working without any trouble, everything is correctly parsed if I add tspan

My question now is on how I could make it editable.
If I use a regular EditorView, it will create a div inside my SVG and it won’t work at all.

I don’t have any problem with the editorView UI/menu, my setup already have it totaly outside the place where the text is shown.

I already now that I will have to put the contenteditable myself on a container outside my svg to make it really ediatble.

My questions are:

  • Is there anything done to work with SVG texts somewhere?
  • If not, what is the correct way to make this works and have it enabled?

My main purpose is to make it works correctly for selection and keyboard shortcut (like bold)

I don’t expect browser’s contentEditable support to work very well with SVG nodes. It’s probably easiest to set up an external editor that somehow syncs its content to your SVG document.

contentEditable on SVG is possible when setting the contentEditable attribute on a HTML node that wrap the SVG:

<div contenteditable>
  <svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
    <text x="0" y="20" id="svgText">Hello</text>
  </svg>
</div>

I know it’s possible. I just don’t expect it to work very well. Firefox doesn’t appear to show a cursor in the example you give, for a start.

I’ll follow your advice by creating a synced editor somewhere else.

I’ll have to transfer document from 1 schema to another, but that not the purpose here, so I’ll test it on my side before asking anything if needed.

Thanks for your quick reply.

Not necessarily. A ProseMirror editor can host any node as document, not just the schema’s top node.