Skip to content

Fix: Footnotes content not being pasted properly #70579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: trunk
Choose a base branch
from

Conversation

USERSATOSHI
Copy link
Contributor

What?

Closes #57958

Why?

Currently footnotes are stored as <!-- wp:footnotes /> and the content is saved as metadata.
Due to this, copy pasting footnotes doesn't copy the content as it is not available.

How?

This PR aims to solve this by adding an attribute footnotes which is an array. This attribute is synced with the meta.footnotes to ensure that it is compatible with older footnotes versions.

This attributes allows the copied footnotes blocks to have the content available hence it will be able to render it.

Testing Instructions

  • Create a paragraph with footnotes
  • Click on options (3 vertical dots)
  • Select copy all blocks
  • Create a new Post and paste the content
  • Footnotes is copied correctly

Testing Instructions for Keyboard

Screenshots or screencast

Before

Screen.Recording.2025-07-01.at.3.52.39.PM.mov

After

Screen.Recording.2025-07-01.at.3.15.26.PM.mov

Copy link

github-actions bot commented Jul 1, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @stacimc, @jfagreg, @sunilw.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: stacimc, jfagreg, sunilw.

Co-authored-by: USERSATOSHI <[email protected]>
Co-authored-by: naokomc <[email protected]>
Co-authored-by: shubhtoy <[email protected]>
Co-authored-by: zdenys <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@USERSATOSHI
Copy link
Contributor Author

Unit Tests / JavaScript ( Node.js 22) 4/4 (pull_request) action is failing due to another test not related to this.
image

@USERSATOSHI USERSATOSHI marked this pull request as draft July 1, 2025 11:54
@USERSATOSHI
Copy link
Contributor Author

USERSATOSHI commented Jul 1, 2025

Converting to draft as there is an issue with e2e, trying to fix

@Mamaduka Mamaduka added [Type] Bug An existing feature does not function as intended [Block] Footnotes Affects the Footnotes Block labels Jul 1, 2025
@Mamaduka
Copy link
Member

Mamaduka commented Jul 1, 2025

I don't think syncing with attributes is the proper way to resolve the problem. Why?

  • Using post meta for storage was an intentional choice. You can check the original PRs for more details.
  • It's possible for attributes and meta to get out of sync. For example, if the Footnotes block is rendered as part of the template, rather than a post itself.
  • Syncing data via effects is proven to be challenging, making posts "dirty" unintentionally and breaking the history (undo/redo). I would recommend avoiding it as much as possible.

cc @ellatrix, @mcsf

@USERSATOSHI
Copy link
Contributor Author

@Mamaduka Got it, I will check the Original PR for the details. 👍🏻

@USERSATOSHI
Copy link
Contributor Author

Using post meta for storage was an intentional choice. You can check the original PRs for more details.

I Checked the prs and the decision make sense on why post meta was used.

It's possible for attributes and meta to get out of sync. For example, if the Footnotes block is rendered as part of the template, rather than a post itself.

I am only using attributes to show what meta has.
And if we add footnotes to a pattern or templatepart it only has <!-- wp:footnotes /--> so I don't think it should go out of sync.

image

tested here and with another post with footnotes it does render data from meta.

Syncing data via effects is proven to be challenging, making posts "dirty" unintentionally and breaking the history (undo/redo). I would recommend avoiding it as much as possible.

This is the current issue that I am facing right now but not because of Effect.
I updated the code to make Effect only do update on initial render by using empty dep array.
but the setAttributes does add another state to the undo/redo stack.

Is there a way to possible store the content on the block's template without adding it to the undo/redo stack?

flowchart TD
A[fetch meta] --> B[initial render update useEffect]
B --> C[add metadata to attributes]

D[onChange] --> E[updateMeta new footnotes]
D --> F[setAttributes new footnotes]
Loading

Right now this is the best way I can think of.

cc: @Mamaduka

@Mamaduka
Copy link
Member

Mamaduka commented Jul 2, 2025

And if we add footnotes to a pattern or templatepart it only has so I don't think it should go out of sync.

There can be cases when attributes aren't synced with meta, while race is still possible. That would qualify as a bug.

There are always workarounds to fix Effects, but those escape hatches should be the last resort and not something we reach out to immediately, IMO.

I pinged folks who worked on the Footnotes feature. Let's wait for their feedback.

@ellatrix
Copy link
Member

ellatrix commented Jul 2, 2025

Let's not sync to attributes. Instead, maybe try adding a copy handler that fetches the meta and sets data transfer?

@ellatrix
Copy link
Member

ellatrix commented Jul 2, 2025

Oh, and when you use data transfer, I'd suggest only adding the footnotes to the text/html type, the blocks type should still have the normal block so you don't paste the content within GB.

@USERSATOSHI
Copy link
Contributor Author

USERSATOSHI commented Jul 7, 2025

Hi, @ellatrix @Mamaduka,

I tried implementing copy handler for footnotes and was able to add it.

but when using list view to select all and copy, the list view's use-clipboard-handler uses both html and plain text to copy the content , due to which the footnotes data copied in text/html gets overridden.
( html one uses <!-- wp:template --> format )

As footnotes also doesn't have a raw transform, making this a bit complex.

So can we store metadata of a post to a new gutenberg/meta( name can be changed ) key in clipboard

and use this to update metadata for new/current post when updating meta related blocks like footnotes.

Copy handler

	const blockRef = useRef();

	useEffect( () => {
		if ( ! blockRef.current ) return;

		const handleCopy = ( event ) => {
			console.log( 'copied' );

			const currentFootnotes = meta?.footnotes;
			if ( ! currentFootnotes ) return;

			const parsed = JSON.parse( currentFootnotes );
			let html = '<ol>';

			parsed.forEach( ( { id, content } ) => {
				html += `<li id="${ id }">`;
				html += `<span role="textbox" aria-multiline="true" id="${ id }" contenteditable="true" class="block-editor-rich-text__editable rich-text" style="white-space: pre-wrap; min-width: 1px;">${ content }</span> `;
				html += `<a href="#${ id }-link">↩︎</a>`;
				html += `</li>`;
			} );

			html += '</ol>';

			event.clipboardData.setData(
				'gutenberg/meta',
				JSON.stringify( {
					...meta,
					footnotes: currentFootnotes,
				} )
			);
			console.log( {
				b: event.clipboardData.getData( 'gutenberg/meta' ),
			} );
		};

		document.addEventListener( 'copy', handleCopy );
		return () => {
			document.removeEventListener( 'copy', handleCopy );
		};
	}, [ meta, blockRef ] );

Updated Clipboard handler (paste part)

write flow's clipboard handler

blocks = pasteHandler( {
	HTML: html,
	plainText,
	mode: isFullySelected ? 'BLOCKS' : 'AUTO',
	canUserUseUnfilteredHTML,
} );

console.log( { blocks } );

if (
	Array.isArray( blocks ) &&
	blocks.some( ( x ) => x.name === 'core/footnotes' )
) {
	const { footnotes } = JSON.parse( meta );
	console.log( { footnotes } );

	if ( footnotes ) {
		const meta = select( 'core/editor' ).getEditedPostAttribute( 'meta' );
		setTimeout(
			() =>
				dispatch( 'core/editor' ).editPost( {
					meta: {
						...meta,
						footnotes,
					},
				} ),
			0
		);
	}
}

@SirLouen
Copy link
Member

Test Report

Description

❌This report can't validate that the indicated patch works as expected.

Patch tested: https://patch-diff.githubusercontent.com/raw/WordPress/gutenberg/pull/70579.diff

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.29
  • Server: Apache/2.4.62 (Debian)
  • Database: mysqli (Server: 11.8.2-MariaDB-ubu2404 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 138.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Twenty-Five 1.3
  • MU Plugins: None activated
  • Plugins:
    • Gutenberg 21.3.0-rc.2
    • Test Reports 1.2.0

Testing Instructions

  • Followed the ones provided in OP.

Actual Results

  1. ❌ Issue is not resolved with the patch

Additional Notes

  • I'm not using the "copy all blocks" but directly a Copy/Paste, and it's failing, but it should

Supplemental Artifacts

Screencast https://f003.backblazeb2.com/file/wordpress-videos/wp-videos/2025/07/gb57958.mp4

Copy link
Member

@SirLouen SirLouen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs changes or more testing info

@USERSATOSHI
Copy link
Contributor Author

@SirLouen Right now, this PR is on hold because the suggestions mentioned by ellatrix needs raw transformation support in footnotes block to convert the html version of footnotes into footnotes block

this support is added indirectly in In this PR while adding support for footnotes markdown

I am waiting for that PR to be merged so that we can start the progress here again.

@SirLouen
Copy link
Member

I am waiting for that PR to be merged so that we can start the progress here again.

Good to know, I was about to test that, but I happened to find this first 👍

@USERSATOSHI
Copy link
Contributor Author

USERSATOSHI commented Jul 30, 2025

I am waiting for that PR to be merged so that we can start the progress here again.

Good to know, I was about to test that, but I happened to find this first 👍

Got it! Please note that , that PR depends on this as classes property in transforms is kinda broken ( can be seen in the failed action ) ( the linked issue on that PR has details on how to reproduce it but simple version would be to just add classes: ['*'] to list block transforms)

PS: I found that bug earlier on a project I was working on, which later happened again when i started working solution for footnotes markdown support

@SirLouen
Copy link
Member

So this PR depends on #70635 and #70635 depends on #70615, right?

@USERSATOSHI
Copy link
Contributor Author

Yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Footnotes Affects the Footnotes Block [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Footnotes content is not pasted when copied via Copy all blocks and pasted into a new post
4 participants