I am working on a rich text editor using ProseMirror and have implemented a custom nodeView for rendering text with SVG gradient effects. However, I’ve encountered an issue where the SVG defs section disappears during the compositionstart event when typing in Chinese, and it only reappears after the compositionend event.
Here’s a detailed description of the problem:
- When I start typing using the Chinese input method (triggering the
compositionstartevent), thedefspart of the SVG is not visible. - Once I finish typing (triggering the
compositionendevent), thedefssection reappears as expected.
I have tried the following to address this issue:
- Ensuring that the SVG and
defselements are correctly created within thenodeView. - Utilizing
requestAnimationFramefor optimizing DOM updates.
Despite these efforts, the problem remains unresolved. Below is a relevant snippet of my code:
export const initProsemirrorEditor = (dom: Element, content: string, props = {}) => {
const editor = new EditorView(dom, {
state: EditorState.create({
doc: createDocument(content),
plugins: buildPlugins(schema),
}),
...props,
nodeViews: {
'svgGradientText': (node) => {
let dom = document.createElement('span');
dom.className = 'svg-gradient-text';
dom.setAttribute('data-gradient-id', node.attrs.id);
dom.style.display = 'inline-block';
dom.style.maxWidth = '100%'
const xmlNS = 'http://www.w3.org/2000/svg'
let text = document.createElementNS(xmlNS, 'text') as any;
text.setAttribute('x', '50%');
text.setAttribute('y', '50%');
text.setAttribute('style', 'text-anchor: middle; dominant-baseline: middle; fill: url(#' + node.attrs.id + '); text-shadow: 0 8px 0 #333; stroke-width: 6px; stroke: #333; paint-order: stroke; stroke-linejoin: round;font-size:40px');
let svg = document.createElementNS(xmlNS, 'svg');
let defs = document.createElementNS(xmlNS, 'defs');
let linearGradient = document.createElementNS(xmlNS, 'linearGradient');
linearGradient.setAttribute('id', node.attrs.id);
linearGradient.setAttribute('x1', '0');
linearGradient.setAttribute('y1', '0');
linearGradient.setAttribute('x2', '0');
linearGradient.setAttribute('y2', '1');
let stop1 = document.createElementNS(xmlNS, 'stop');
stop1.setAttribute('offset', '0%');
stop1.setAttribute('stop-color', '#FFCF02');
linearGradient.appendChild(stop1);
let stop2 = document.createElementNS(xmlNS, 'stop');
stop2.setAttribute('offset', '100%');
stop2.setAttribute('stop-color', '#FF7352');
linearGradient.appendChild(stop2);
defs.appendChild(linearGradient);
svg.appendChild(defs);
svg.appendChild(text)
dom.appendChild(svg)
nextTick(() => {
const bbox = text.getBBox();
if (bbox.width === 0) return
svg.setAttribute('width', bbox.width + 10);
svg.setAttribute('height', bbox.height + 10);
})
return {
dom,
contentDOM: text,
}
}
},
})
return editor
}
const svgGradientText: MarkSpec = {
group: 'inline',
attrs: {
id: { default: 'gradient' },
},
toDOM: mark => ['span', { 'class': 'svg-gradient-text', 'data-gradient-id': mark.attrs.id }, 0],
parseDOM: [{
tag: 'span.svg-gradient-text',
getAttrs: dom => {
const id = dom.getAttribute('data-gradient-id');
return { id };
}
}]
}

I am hoping to find a solution through the community’s help to ensure that the defs part of the SVG is displayed correctly even during the composition input phase of the Chinese input method.
Has anyone encountered a similar issue? Or do you have any suggestions that could help me resolve this problem?
I would greatly appreciate your time and assistance!