Proposal: Add transformCopiedHTML callback

Hi,

I have custom styles that I want to append to the html content as <style> tag when it’s copied from editor. I also want to add a <meta> tag, so that it indicates that the source of content currently in clipboard is from my editor component along with other meta data.

In short, I want to modify the final HTML string generated after clipboard serialization. I think introducing a method transformCopiedHTML, similar to transformPastedHTML, would solve my usecase. It can be the final callback before content is written to clipboard (probably add before this), with following signature:

 transformCopiedHTML?: fn(html: string, view?: EditorView) → string

Note that I don’t want to change anything about the default serialization. So far I have tried monkey patching the serializeFragment method so that I could pass custom ClipboardSerializer that reuses default implementation, but I am running into errors (code referred from here):

const serializer = DOMSerializer.fromSchema(schema);
const {serializeFragment} = serializer;
serializer.serializeFragment = function (...args) {
    const html = serializeFragment(...args);
    // modify html and return that
};

Uncaught TypeError: Cannot read properties of undefined (reading 'serializeNodeInner')

In general, dealing with custom ClipboardSerializer seems unnecessary since I don’t want to modify generated html string.

Please let me know what you think, I would be glad to contribute here if the proposal for the callback method sounds good. Alternatively let me know what else I can try here.

Don’t monkey-patch serializer, just pass a separate object with a serializeFragment method that calls serializer.serializeFragment and then modifies its result.

I passed in a separate object as mentioned, and while the error is resolved now, this still doesn’t solve my usecase as it just returns the document fragment.

Prosemirror performs further operation on the obtained document fragment like adding attributes, stringifying the dom (ref), and it this final html string result that I want to transform before it’s put to clipboard.

I think introducing the callback achieves the usecase in a cleaner way, is fairly intuitive, fits in the API, and code changes should be minimal, very similar to this (invoking transformPastedHTML callback).

Please let me know if there are any concerns in this approach.

The fallback for copy/cut on browsers that don’t support Event.clipboardData (which includes relatively recent iOS browser versions) lets the browser copy directly from the DOM, so there ProseMirror never creates the HTML text, and would not be able to support such a transform function.

Prosemirror could transform the dom.innerHTML and then recreate the node in the fallback case. If it is not possible, what about something like transformCopiedDOM? Would it work?