Greetings!
I’m having some issues formatting from a GDocs source copy and paste into ProseMirror. I have a “paste without formatting” option, which turns everything into a text string, which is otherwise desirable, but I wish to parse any line returns/breaks and include them as hard_breaks or HTML Element
in the final rendering to the editor.
Does anyone know how to accomplish this? Right now, I tried to add in
using a regex on /r/n /n etc., but it gets escaped and printed using unicode instead of rendered as the intended HTML.
I tried leveraging transformPasted
and also implemented handlePaste
from How to preserve hard breaks when pasting HTML into a plain-text schema? - #5 by rfgamaral and How to preserve hard breaks when pasting HTML into a plain-text schema?, but with no luck, as they are different.
My scenario closely matches with How to preserve hard breaks when pasting HTML into a plain-text schema?, however I don’t have an all text schema, mine is below:
const nodes: OrderedMap<NodeSpec> = addListNodes(
schema.spec.nodes,
'paragraph block*',
'block'
);
const customNodes = nodes
.remove('paragraph')
.addBefore('blockquote', 'paragraph', paragraphSpec)
.append({
iota: iotaSpec,
tab: tabSpec,
});
export const stDocSchema = new Schema({
nodes: customNodes,
marks: schema.spec.marks.remove('link').append({
fontFamily: FontSpecs.familyMarkSpec,
fontSize: FontSpecs.fontSizeMarkSpec,
fontColor: fontColorMarkSpec,
highlightColor: highlightColorMarkSpec,
mote: moteMarkSpec,
strikethrough: strikethroughMark,
link: HyperlinkSpec.hyperlinkMarkSpec,
}),
});
Here is the code calling the context selection menu option which need to strip everything besides spaces and linebreaks & returns:
navigator.clipboard.readText().then((clipText) => {
const newLines = clipText.match(/\n/g);
const newLine2 = clipText.match(/\r\n/g);
const lineBreak = clipText.match(/\r/g);
if (newLines) {
clipText = clipText.replace(/\n/g, '\n');
} else if (newLine2) {
clipText = clipText.replace(/\r\n/g, '\n');
} else if (lineBreak) {
clipText = clipText.replace(/\r/g, '\n');
}
dispatch(tr.insertText(clipText).scrollIntoView());
});
break;
Finally, here is what I have based on feedback from the forum here for a similar issue… but no luck because the users cursor will jump to another line and char index when they try to type on one of the copied lines containing text.
const { state } = view;
const { tr } = state;
if (!state.schema.nodes.hardBreak) {
return false;
}
const clipboardText = event.clipboardData
?.getData('text/plain')
.trim();
if (!clipboardText) {
return false;
}
const textLines = clipboardText.split(/(?:\r\n|\r|\n)/g);
const nodes = textLines.reduce<PMNode[]>((nodes, line, index) => {
if (line.length > 0) {
nodes.push(view.state.schema.text(line));
}
if (index < textLines.length - 1) {
nodes.push(state.schema.nodes.hardBreak.create());
}
return nodes;
}, []);
view.dispatch(
tr
.replaceSelection(Slice.maxOpen(Fragment.fromArray(nodes)))
.scrollIntoView()
);
return true;
},
Update: I managed to get the breaks to stay properly now, but when I begin typing after one of the lines which contain text, it skips to another line and char. Any help is truly appreciated!