Skip to content
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

Writing Flow/Rich Text: unify split logic #54543

Merged
merged 8 commits into from
May 3, 2024
Merged

Writing Flow/Rich Text: unify split logic #54543

merged 8 commits into from
May 3, 2024

Conversation

ellatrix
Copy link
Member

@ellatrix ellatrix commented Sep 18, 2023

What/why?

Fixes #53076: when pasting blocks, the split block should be merged with the pasted blocks.

This PR aims to unify split logic (enter key and paste). Currently we have logic both in the block editor generally and rich text specifically when it contains selection. This PR moves all the logic to the block editor (writing flow), adding a block.json setting that tells us if we can split a block.

This removes the need for the block to pass an onSplit function, the behaviour can be turned on with just a setting. This is also quite convenient for extenders wishing to recreate the core blocks.

This will also allow us to solve splitting for paste more easily, which is actually a split operation + merging the ends together.

How?

One implementation details is that change of how rich text listens for key events. Right now in trunk, the event listener is attached to the rich text node, so writing flow (listening on a wrapper node) cannot prevent default behaviour. To fix this, rich text can listen to the document instead. This is how it works for browser behaviour too. Default behaviour is cancelable until the event bubbled all the way through the DOM. Rich text is meant to be a sort of polyfill for the native contenteditable API: actions should be cancelable.

Testing Instructions

Copy a few paragraphs and paste them into another paragraph. The result should be:

[target paragraph][pasted paragraph

pasted paragraph

pasted paragraph][target paragraph]

Testing Instructions for Keyboard

Screenshots or screencast

paste-between

@ellatrix ellatrix added the [Type] Code Quality Issues or PRs that relate to code quality label Sep 18, 2023
@ellatrix ellatrix changed the title wip Remove rich text onSplit in favour of writing flow handling Sep 18, 2023
@github-actions
Copy link

github-actions bot commented Sep 18, 2023

Size Change: +665 B (+0.04%)

Total Size: 1.74 MB

Filename Size Change
build/block-editor/index.min.js 257 kB +965 B (+0.38%)
build/block-library/index.min.js 218 kB -331 B (-0.15%)
build/rich-text/index.min.js 10.1 kB +31 B (+0.31%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 955 B
build/annotations/index.min.js 2.27 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.1 kB
build/blob/index.min.js 578 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1.03 kB
build/block-directory/style.css 1.03 kB
build/block-editor/content-rtl.css 4.43 kB
build/block-editor/content.css 4.43 kB
build/block-editor/default-editor-styles-rtl.css 395 B
build/block-editor/default-editor-styles.css 395 B
build/block-editor/style-rtl.css 15.4 kB
build/block-editor/style.css 15.4 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 133 B
build/block-library/blocks/audio/theme.css 133 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 415 B
build/block-library/blocks/button/editor.css 414 B
build/block-library/blocks/button/style-rtl.css 627 B
build/block-library/blocks/button/style.css 626 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 421 B
build/block-library/blocks/columns/style.css 421 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 671 B
build/block-library/blocks/cover/editor.css 674 B
build/block-library/blocks/cover/style-rtl.css 1.7 kB
build/block-library/blocks/cover/style.css 1.69 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 312 B
build/block-library/blocks/embed/editor.css 312 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 327 B
build/block-library/blocks/file/style-rtl.css 280 B
build/block-library/blocks/file/style.css 281 B
build/block-library/blocks/file/view.min.js 324 B
build/block-library/blocks/footnotes/style-rtl.css 201 B
build/block-library/blocks/footnotes/style.css 199 B
build/block-library/blocks/form-input/editor-rtl.css 227 B
build/block-library/blocks/form-input/editor.css 227 B
build/block-library/blocks/form-input/style-rtl.css 343 B
build/block-library/blocks/form-input/style.css 343 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 340 B
build/block-library/blocks/form-submission-notification/editor.css 340 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 471 B
build/block-library/blocks/freeform/editor-rtl.css 2.61 kB
build/block-library/blocks/freeform/editor.css 2.61 kB
build/block-library/blocks/gallery/editor-rtl.css 956 B
build/block-library/blocks/gallery/editor.css 960 B
build/block-library/blocks/gallery/style-rtl.css 1.72 kB
build/block-library/blocks/gallery/style.css 1.72 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 394 B
build/block-library/blocks/group/editor.css 394 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 189 B
build/block-library/blocks/heading/style.css 189 B
build/block-library/blocks/html/editor-rtl.css 336 B
build/block-library/blocks/html/editor.css 337 B
build/block-library/blocks/image/editor-rtl.css 878 B
build/block-library/blocks/image/editor.css 878 B
build/block-library/blocks/image/style-rtl.css 1.6 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 133 B
build/block-library/blocks/image/theme.css 133 B
build/block-library/blocks/image/view.min.js 1.54 kB
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 306 B
build/block-library/blocks/media-text/editor.css 305 B
build/block-library/blocks/media-text/style-rtl.css 505 B
build/block-library/blocks/media-text/style.css 503 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 668 B
build/block-library/blocks/navigation-link/editor.css 669 B
build/block-library/blocks/navigation-link/style-rtl.css 193 B
build/block-library/blocks/navigation-link/style.css 192 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/editor-rtl.css 2.26 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.26 kB
build/block-library/blocks/navigation/style.css 2.25 kB
build/block-library/blocks/navigation/view.min.js 1.03 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 235 B
build/block-library/blocks/paragraph/editor.css 235 B
build/block-library/blocks/paragraph/style-rtl.css 335 B
build/block-library/blocks/paragraph/style.css 335 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 508 B
build/block-library/blocks/post-comments-form/style.css 508 B
build/block-library/blocks/post-content/editor-rtl.css 74 B
build/block-library/blocks/post-content/editor.css 74 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 734 B
build/block-library/blocks/post-featured-image/editor.css 732 B
build/block-library/blocks/post-featured-image/style-rtl.css 342 B
build/block-library/blocks/post-featured-image/style.css 342 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 409 B
build/block-library/blocks/post-template/style.css 408 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 354 B
build/block-library/blocks/pullquote/style.css 353 B
build/block-library/blocks/pullquote/theme-rtl.css 174 B
build/block-library/blocks/pullquote/theme.css 174 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 486 B
build/block-library/blocks/query/editor.css 486 B
build/block-library/blocks/query/view.min.js 958 B
build/block-library/blocks/quote/style-rtl.css 237 B
build/block-library/blocks/quote/style.css 237 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 235 B
build/block-library/blocks/read-more/style-rtl.css 140 B
build/block-library/blocks/read-more/style.css 140 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 184 B
build/block-library/blocks/search/editor.css 184 B
build/block-library/blocks/search/style-rtl.css 690 B
build/block-library/blocks/search/style.css 689 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/search/view.min.js 478 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 239 B
build/block-library/blocks/separator/style.css 239 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 323 B
build/block-library/blocks/shortcode/editor.css 323 B
build/block-library/blocks/site-logo/editor-rtl.css 805 B
build/block-library/blocks/site-logo/editor.css 805 B
build/block-library/blocks/site-logo/style-rtl.css 204 B
build/block-library/blocks/site-logo/style.css 204 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 324 B
build/block-library/blocks/social-link/editor.css 324 B
build/block-library/blocks/social-links/editor-rtl.css 676 B
build/block-library/blocks/social-links/editor.css 675 B
build/block-library/blocks/social-links/style-rtl.css 1.48 kB
build/block-library/blocks/social-links/style.css 1.48 kB
build/block-library/blocks/spacer/editor-rtl.css 350 B
build/block-library/blocks/spacer/editor.css 350 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 395 B
build/block-library/blocks/table/editor.css 395 B
build/block-library/blocks/table/style-rtl.css 639 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 431 B
build/block-library/blocks/template-part/editor.css 431 B
build/block-library/blocks/template-part/theme-rtl.css 107 B
build/block-library/blocks/template-part/theme.css 107 B
build/block-library/blocks/term-description/style-rtl.css 111 B
build/block-library/blocks/term-description/style.css 111 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 185 B
build/block-library/blocks/video/style.css 185 B
build/block-library/blocks/video/theme-rtl.css 133 B
build/block-library/blocks/video/theme.css 133 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 12.3 kB
build/block-library/editor.css 12.3 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.8 kB
build/block-library/style.css 14.8 kB
build/block-library/theme-rtl.css 707 B
build/block-library/theme.css 713 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.7 kB
build/commands/index.min.js 15.2 kB
build/commands/style-rtl.css 953 B
build/commands/style.css 951 B
build/components/index.min.js 220 kB
build/components/style-rtl.css 11.9 kB
build/components/style.css 12 kB
build/compose/index.min.js 12.8 kB
build/core-commands/index.min.js 2.77 kB
build/core-data/index.min.js 72.5 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.36 kB
build/customize-widgets/style.css 1.36 kB
build/data-controls/index.min.js 640 B
build/data/index.min.js 9 kB
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 451 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.65 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 578 B
build/edit-post/index.min.js 16.3 kB
build/edit-post/style-rtl.css 3.79 kB
build/edit-post/style.css 3.79 kB
build/edit-site/index.min.js 223 kB
build/edit-site/style-rtl.css 13.6 kB
build/edit-site/style.css 13.6 kB
build/edit-widgets/index.min.js 17.6 kB
build/edit-widgets/style-rtl.css 4.17 kB
build/edit-widgets/style.css 4.17 kB
build/editor/index.min.js 81 kB
build/editor/style-rtl.css 7.54 kB
build/editor/style.css 7.54 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.07 kB
build/format-library/style-rtl.css 493 B
build/format-library/style.css 492 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.58 kB
build/interactivity/debug.min.js 16.2 kB
build/interactivity/file.min.js 447 B
build/interactivity/image.min.js 1.67 kB
build/interactivity/index.min.js 13 kB
build/interactivity/navigation.min.js 1.17 kB
build/interactivity/query.min.js 740 B
build/interactivity/router.min.js 2.79 kB
build/interactivity/search.min.js 618 B
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.3 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 851 B
build/list-reusable-blocks/style.css 851 B
build/media-utils/index.min.js 2.92 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 948 B
build/nux/index.min.js 1.57 kB
build/nux/style-rtl.css 748 B
build/nux/style.css 744 B
build/patterns/index.min.js 6.45 kB
build/patterns/style-rtl.css 595 B
build/patterns/style.css 595 B
build/plugins/index.min.js 1.8 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.85 kB
build/preferences/style-rtl.css 710 B
build/preferences/style.css 712 B
build/primitives/index.min.js 975 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 1 kB
build/react-i18n/index.min.js 623 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.7 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/router/index.min.js 1.88 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.39 kB
build/style-engine/index.min.js 2.03 kB
build/token-list/index.min.js 582 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react.min.js 4.03 kB
build/viewport/index.min.js 957 B
build/warning/index.min.js 249 B
build/widgets/index.min.js 7.23 kB
build/widgets/style-rtl.css 1.17 kB
build/widgets/style.css 1.17 kB
build/wordcount/index.min.js 1.02 kB

compressed-size-action

@github-actions
Copy link

github-actions bot commented Sep 18, 2023

Flaky tests detected in f950d2f.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/8922587588
📝 Reported issues:

@ellatrix ellatrix changed the title Remove rich text onSplit in favour of writing flow handling Writing Flow/Rich Text: unify split logic Oct 3, 2023
@ellatrix ellatrix added [Type] Bug An existing feature does not function as intended and removed [Type] Code Quality Issues or PRs that relate to code quality labels Oct 4, 2023
@ellatrix ellatrix marked this pull request as ready for review October 6, 2023 10:54
Copy link
Member

@richtabor richtabor left a comment

Choose a reason for hiding this comment

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

UX/writing flow wise, this feels solid, with more expected results on copying/pasting across multiple blocks.

Copy link
Member

@Mamaduka Mamaduka left a comment

Choose a reason for hiding this comment

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

Maybe we should leave the onSplit callback if the block has more specific needs for this logic.

A good example would be the button block. Currently, it copies all attributes on the split action, including URLs. Which I think is a bug; only styling attributes and text included on the split action should be copied.

@ellatrix
Copy link
Member Author

@Mamaduka Right, that's a good point. I don't like keeping onSplit though, maybe you should be able to opt-out of attributes in the block supports key? Or opt-in? What do you think?

splitting: {
  url: false
}

Or maybe a transform?

@Mamaduka
Copy link
Member

@ellatrix, I thought we'd have to support the legacy method for backward compatibility.

@ellatrix
Copy link
Member Author

@Mamaduka I meant, how to incorporate it in the new way?

Comment on lines +35 to +36
defaultView.addEventListener( 'copy', onCopy );
defaultView.addEventListener( 'cut', onCopy );
Copy link
Member

Choose a reason for hiding this comment

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

I believe this change produces a TypeError: Cannot read properties of null (reading 'addEventListener') error. I'm having trouble reproducing it manually, but it's consistent when running e2e tests.

npm run test:e2e -- -g "can be inserted after refresh"

Screenshot

CleanShot 2024-05-07 at 16 27 41

@matthewmcvickar
Copy link

matthewmcvickar commented Jun 28, 2024

This comment is a followup and context for my comment on the WP Dev Blog post that mentions this change, where I expressed confusion about this logic and its settings in block.json.

My comment, for convenience:

I’m having trouble understanding the splitting attribute and what the true and false values mean for editor behavior.

Let’s say I have a custom block that’s just a <p> tag (its own block—not a block variation—because I want to disable typography and colors for that block and set a particular class on the tag). If I set splitting to true, pressing the Return key in the block does nothing, and trying to paste content that has line returns it also does nothing. (Pasting content without line returns is allowed.) If I set splitting to false, I can do both of these things. This seems counterintuitive or at least under-explained. Is there documentation about this that I’m missing?

Also: previously I had used the onSplit prop for handling the Return key in a block. For some blocks, I want hitting the Return key to exit that block and start a new empty paragraph—how should I accomplish that? Being 'trapped' in the block and having the Return key do nothing is not desirable or expected behavior, given that, e.g., the Heading block allows for 'escaping' its block when hitting Return.

Seeing this comment, @ellatrix asked to see my code to help clarify. Here is my block code:

block.json

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "baz-qux/page-tagline",
	"title": "Page Tagline",
	"category": "baz-qux",
	"icon": "megaphone",
	"description": "A short introduction to the page.",
	"keywords": ["intro", "excerpt", "description"],
	"supports": {
		"anchor": false,
		"align": false,
		"splitting": false
	},
	"editorScript": "file:./page-tagline.js"
}

page-tagline.jsx (compiles into page-tagline.js)

import metadata from './block.json';

const { registerBlockType } = wp.blocks;
const { useBlockProps, RichText } = wp.blockEditor;

registerBlockType( metadata.name, {
	attributes: {
		content: {
			type: 'string',
			source: 'text',
			selector: 'p'
		}
	},
	edit: (props) => {
		return <RichText
			{ ...useBlockProps() }
			tagName="p"
			className="wp-block wp-block-paragraph page-tagline"
			value={ props.attributes.content }
			placeholder="Add tagline"
			onChange={ ( newContent ) => props.setAttributes({ content: newContent }) }
		/>;
	},
	save: (props) => {
		return <RichText.Content
			{ ...useBlockProps.save() }
			tagName="p"
			className="page-tagline"
			value={ props.attributes.content }
		/>;
	}
} );

Thank you for your help!

@ellatrix
Copy link
Member Author

ellatrix commented Jul 1, 2024

Hi! I tried your code, and for me it looks like splitting: false works correctly. It will not split the block into two blocks but rather insert a soft line break.

splitting-false

Now, you are right that setting splitting to true will do nothing. That's because RichText in the edit function is missing the identifier prop:

<RichText
	{ ...useBlockProps() }
	identifier="content"

This should allow the block to be split into two blocks. We should indeed mention that in documentation.

It's also worth noting that if you'd like to allow merging these blocks back together, you should provide a merge function and pass down mergeBlocks to RichText as onMerge:

merge( attributes, attributesToMerge ) {
	return {
		content:
			( attributes.content || '' ) +
			( attributesToMerge.content || '' ),
	};
},
edit: function Edit( props ) {
	return (
		<RichText
			{ ...useBlockProps() }
			identifier="content"
			onMerge={ props.mergeBlocks }

@ellatrix
Copy link
Member Author

ellatrix commented Jul 1, 2024

I've added docs here: #63016

@matthewmcvickar
Copy link

matthewmcvickar commented Jul 1, 2024

Thank you for the followup! This is helpful. I am now getting the behavior I expect, and it's nice that hitting Enter at the end of a block that has splitting set to true creates a new core/paragraph block by default.

(Am I correct in assuming that the merge() function in the registerBlockType() arguments is a shortcut to define the mergeBlocks prop? That registerBlockType( name, { merge(...) {...} } ) is equal to registerBlockType( name, { mergeBlocks: function(...) {...} } ) in the same way that edit: or edit() can be used?)

One more thing: I'm unclear from the discussion on this ticket whether onSplit will be sticking around. It's still being used on some core blocks, right? How will custom splitting behavior be supported if the onSplit prop is deprecated?

@ellatrix
Copy link
Member Author

ellatrix commented Jul 2, 2024

As far as I know, there's no mergeBlocks property for block registration. There is a mergeBlocks prop given to the edit function that you need to pass down to RichText as onMerge, as illustrated above. Otherwise it won't work. Note that these APIs are a bit in need of a change, similar to splitting.

onSplit is officially deprecated but will probably keep working as it is now for many years, if not forever. Until it is a burden to maintain, but right now it is not.

@t-hamano
Copy link
Contributor

Another regression: It appears that it is no longer possible to paste text from outside WordPress into non-modal classic block. See #64771.

@elzadj
Copy link

elzadj commented Sep 20, 2024

@ellatrix Can we please have some input here? #65274 (comment)
Thanks

@keepyourreceipt
Copy link

Hi everyone. Theme / plugin developer here. Thanks for all the work you do on this project :)

I have a question, from what I can tell this might be the best place to post it.

With the changes to how onSplit works, I don't have access to the attributes of the new block that's created on split (as I understand). Could we add an option to the splitting block.json setting to have the new block copy the attribute values of the one being copied? So new block has all the same attribute values of old block.

@ellatrix your comment here #54543 (comment) seems to reference this, but I wasn't sure if I fully understood.

Usage: I have a custom paragraph block with an alignment attribute. With the new split behavior, if the original block is set to center align, the new block comes in with the align set to left, the block's default value. The author has set the alignment to "center" each time they add a new paragraph. Kind of annoying. Looks like I could have resolved this with the old implementation.

Screenshot 2024-10-13 at 2 39 07 PM

Alternatively, is there a way to set default attributes on the new block added on split? I've been searching around, but haven't found any good info on this. Hence my post here.

Thanks.

@ellatrix
Copy link
Member Author

Usage: I have a custom paragraph block with an alignment attribute. With the new split behavior, if the original block is set to center align, the new block comes in with the align set to left, the block's default value. The author has set the alignment to "center" each time they add a new paragraph. Kind of annoying. Looks like I could have resolved this with the old implementation.

Hm, when I split a core paragraph block, it keeps the alignment. Even when I split a core heading block with alignment, it keeps it on the newly created paragraph. Could you share some minimal block code that triggers the problem?

@keepyourreceipt
Copy link

keepyourreceipt commented Oct 19, 2024

Hey @ellatrix thanks for the reply :)

I've included the block.json and edit function below. With this code, on split, the attribute "align" is set to the default value of "left" when the new block is added to the editor.

Please let me know if there's any additional code or examples I can provide.

Thanks.

block.json

{
    "apiVersion": 3,
    "name": "thirtysix-blocks/paragraph",
    "title": "Paragraph",
    "description": "Displays a rich text editor.",
    "category": "layout",    
    "textdomain": "thirtysix-blocks",
    "editorScript": "file:./index.js",
    "viewScript": "file:./view.js",
    "style": "file:./style-index.css",
    "editorStyle": "file:./index.css",
    "viewStyle": "file:./view.css",
    "ancestor": [
        "thirtysix-blocks/text",
        "thirtysix-blocks/banner",
        "thirtysix-blocks/column",
        "thirtysix-blocks/posts"
    ],
    "attributes": {
        "text": {
            "type": "string"            
        },        
        "align": {
            "type": "string",
            "default": "left"
        },        
        "client_id": {
            "type": "string"
        }                      
    },
    "supports": {
        "color": {
	    "text": true,	
            "background": false		
	},
        "typography": {
            "fontSize": true
        },
        "renaming": false,
        "customClassName": false,
        "splitting": true
    }
}

edit.js

import "./editor.scss";
import "./style.scss";

import { useEffect } from "@wordpress/element";
import { useBlockProps, RichText } from "@wordpress/block-editor";

import ParagraphInspectorControls from "./_inspector-controls";
import ParagraphBlockControls from "./_block-controls";

export default function Edit({ attributes, setAttributes, clientId }) {
  const blockProps = useBlockProps({
    style: {
      color: attributes.color,
      textAlign: attributes.align,
    },
  });

  useEffect(() => {
    setAttributes({ client_id: clientId });
  }, [clientId]);

  return (
    <>
      <ParagraphInspectorControls
        attributes={attributes}
        setAttributes={setAttributes}
      />

      <ParagraphBlockControls
        attributes={attributes}
        setAttributes={setAttributes}
      />

      <section {...blockProps}>
        <RichText
          value={attributes.text}          
          allowedFormats={[
            "core/text-color",
            "core/bold",
            "core/italic",
            "core/link",
            "core/superscript",
            "core/subscript",
          ]}
          tagName="p"          
          identifier={"text"}  
          placeholder="Lorem ipsum dolor sit amet, consectetur adipiscing elit..."
          onChange={(value) => setAttributes({ text: value })}                    
        />
      </section>
    </>
  );
}

@ellatrix
Copy link
Member Author

Hi @keepyourreceipt!

Unfortunately I will need more information, because I don't see an alignment button. Here's the code you provided that is executable in the console:

wp.blocks.registerBlockType('thirtysix-blocks/paragraph', {
	apiVersion: 3,
	name: "thirtysix-blocks/paragraph",
	title: "Paragraph",
	description: "Displays a rich text editor.",
	category: "layout",
	textdomain: "thirtysix-blocks",
	attributes: {
		text: {
			type: "string"
		},
		align: {
			type: "string",
			default: "left"
		},
		client_id: {
			type: "string"
		}
	},
	supports: {
		color: {
			text: true,
			background: false
		},
		typography: {
			fontSize: true
		},
		renaming: false,
		customClassName: false,
		splitting: true
	},
	edit: function Edit({ attributes, setAttributes, clientId }) {
		const blockProps = wp.blockEditor.useBlockProps({
			style: {
				color: attributes.color,
				textAlign: attributes.align,
			},
		});

		wp.element.useEffect(() => {
			setAttributes({ client_id: clientId });
		}, [clientId]);

		return wp.element.createElement(
			'section',
			blockProps,
			wp.element.createElement(wp.blockEditor.RichText, {
				value: attributes.text,
				allowedFormats: [
					"core/text-color",
					"core/bold",
					"core/italic",
					"core/link",
					"core/superscript",
					"core/subscript",
				],
				tagName: "p",
				identifier: "text",
				placeholder: "Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
				onChange: (value) => setAttributes({ text: value })
			})
		);
	}
});

Could you add your alignment functionality to this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Writing Flow Block selection, navigation, splitting, merging, deletion... Needs Dev Note Requires a developer note for a major WordPress release cycle [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Paragraph: paste contents at cursor point rather than as new blocks
8 participants