Issue: Paragraph 1: Hello world
It has an alignment Center
Paragraph 2:
It has an empty line
When Paragraph 1 is cut and pasted to the second line, the paragraph attributes are not retained (eg: alignment). Research upon this behavior led to the conclusion that the ProseMirror does not retain the attributes but only the marks inside the node. We have come up with two solutions:
Solution 1: Using appendTransaction:
import { Plugin, PluginKey, NodeSelection } from "prosemirror-state";
class FullParagraphSelectionPlugin extends Plugin {
constructor() {
super({
key: new PluginKey("fullParagraphSelection"),
appendTransaction: (transactions, oldState, newState) => {
const { selection, doc } = newState;
// Skip if the selection is empty
if (selection.empty) return;
const { $from, $to } = selection;
// Ensure the selection is within the same parent node and that parent is a paragraph
if (
$from.parent === $to.parent &&
$from.parent.type.name === "paragraph" &&
$from.parentOffset === 0 &&
$to.parentOffset === $to.parent.content.size &&
$from.pos !== $to.pos // non-empty selection check
) {
// Get the position before the paragraph node
const nodePos = $from.before();
// Replace the current selection with a NodeSelection for the entire paragraph
return newState.tr.setSelection(NodeSelection.create(doc, nodePos));
}
}
});
}
}
export default FullParagraphSelectionPlugin;
Soultion 2: Using handlePaste:
import { Plugin, PluginKey } from 'prosemirror-state';
const SPEC = {
key: new PluginKey('preserveAttributesPlugin'),
props: {
handlePaste(view, event, slice) {
let tr = view.state.tr;
const currentNode = view.state.doc.nodeAt(
view.state.selection.$from.before(1)
);
tr = tr.delete(
view.state.selection.$from.before(1),
view.state.selection.$from.after(1)
);
slice.content.forEach((node) => {
if (node.type.name === 'paragraph') {
tr.replaceSelectionWith(
node.type.create({ ...node.attrs }, node.content, node.marks)
);
} else {
tr.replaceSelectionWith(node);
}
});
view.dispatch(tr);
return true;
},
},
};
class preserveAttributesPlugin extends Plugin {
constructor() {
super(SPEC);
}
}
export default preserveAttributesPlugin;
@marijn Can you analyze the code and suggest which solution will be more impactful with less complications? Would like everyone’s suggestion on this. Appreciate your Support! Thanks!