A `transformCopied` PR

A PR to add a transformCopied editor prop utility to allow transforming a slice before it is serialized for the clipboard. Seems sensible to add this since its dual has a transformPasted editor prop.

Use case: Mentions to other files keep relative file path in their attributes and use that in their toDOM spec since we want serialization of the whole document to use relative paths. When copied though, we want to change to using absolute paths for the mention so that if it is pasted into a file in a different directory, the mention will be transformed back into the appropriate relative file path.

Would you recommend a different way of approaching this (if you are against the transformCopied)? I can think of a few other ways:

  • Capture the copy command first before prosemirror, and handle all the copy slice stuff in userland
  • Supply a separate DOMSerializer instance for clipboardSerializer that uses the same schema except the mention node’s toDOM field replaced.
  • Use absolute mention paths in the attributes, simply convert them into relative when saving the document.

Third seems okay, but transformCopied seems ideal.

2 Likes

The recommended way to do this is to pass a custom object as clipboardSerializer and put your logic in there. See the docs for that prop. Is there a reason that wouldn’t work here?

Well I want everything else besides mention nodes to parse exactly the same.

So as I understand it, if I did something like this:

new Plugin({
	props: {
		clipboardSerializer: new DOMSerializer(
			{
				mention: (node) => ... ,
			},
			{ }
		),
	},
}),

serializeFragment would get called, but it would only know how to serialize mention nodes, and not anything else. It would (probably) throw an error if I tried serializing anything else. I would need to collect the DOMOutputSpecs of all of the nodes and marks, and replace this one mention node dom output spec with the one I want.

const nodeOutputSpecs = mapValues(schema.nodes, getOutputSpec)
const markOutputSpecs = mapValues(schema.marks, getOutputSpec)

new Plugin({
	props: {
		clipboardSerializer: new DOMSerializer(
			{
				…nodeOutputSpecs,
				mention: (node) => ... ,
			},
			markOutputSpecs
		),
	},
}),

I would have to do something like this? I would prefer a more granular (per-node or per-mark) approach to clipboard serialization

You can pass in an arbitrary object with a serializeFragment method compatible with this. So you could use that to first transform the fragment and then pass it to the regular serializer created with fromSchema.

That seems good! Thanks. I’ll close the PR.

Actually, I still prefer the transformCopied approach so individual plugins can chain the call and transform the nodes relevant to them (like transformPasted), but that’s a fine workaround.

That is a good point. I’ve added a comment to the PR.

I had to make a new PR, I couldn’t reopen the last one since I force-pushed (my bad, didn’t know). cleanup by tanishqkancharla · Pull Request #141 · ProseMirror/prosemirror-view · GitHub

1 Like