@wordpress/block-library 8.24.1 → 8.25.1-next.79a6196f.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/LICENSE.md +1 -1
- package/build/audio/edit.js +15 -62
- package/build/audio/edit.js.map +1 -1
- package/build/audio/edit.native.js +1 -1
- package/build/audio/edit.native.js.map +1 -1
- package/build/audio/index.js +2 -2
- package/build/block/edit.js +157 -19
- package/build/block/edit.js.map +1 -1
- package/build/block/index.js +3 -2
- package/build/block/index.js.map +1 -1
- package/build/block/v1/edit.js +116 -0
- package/build/block/v1/edit.js.map +1 -0
- package/build/block/{edit.native.js → v1/edit.native.js} +2 -2
- package/build/block/v1/edit.native.js.map +1 -0
- package/build/button/index.js +2 -2
- package/build/button/save.js +1 -1
- package/build/button/save.js.map +1 -1
- package/build/code/edit.native.js +13 -14
- package/build/code/edit.native.js.map +1 -1
- package/build/code/index.js +2 -2
- package/build/code/save.js +6 -2
- package/build/code/save.js.map +1 -1
- package/build/comments-title/deprecated.js +1 -1
- package/build/comments-title/index.js +1 -1
- package/build/cover/edit/inspector-controls.js +1 -1
- package/build/cover/edit/inspector-controls.js.map +1 -1
- package/build/cover/edit.native.js +1 -0
- package/build/cover/edit.native.js.map +1 -1
- package/build/details/index.js +2 -2
- package/build/embed/deprecated.js +2 -2
- package/build/embed/embed-preview.native.js +1 -1
- package/build/embed/embed-preview.native.js.map +1 -1
- package/build/embed/icons.js +1 -1
- package/build/embed/icons.js.map +1 -1
- package/build/embed/index.js +2 -2
- package/build/embed/transforms.js +2 -2
- package/build/embed/util.js +6 -6
- package/build/embed/util.js.map +1 -1
- package/build/file/edit.js +20 -28
- package/build/file/edit.js.map +1 -1
- package/build/file/edit.native.js +1 -1
- package/build/file/edit.native.js.map +1 -1
- package/build/file/index.js +4 -4
- package/build/file/save.js +4 -1
- package/build/file/save.js.map +1 -1
- package/build/form-input/deprecated.js +147 -0
- package/build/form-input/deprecated.js.map +1 -0
- package/build/form-input/edit.js +1 -1
- package/build/form-input/edit.js.map +1 -1
- package/build/form-input/index.js +4 -2
- package/build/form-input/index.js.map +1 -1
- package/build/form-input/save.js +7 -9
- package/build/form-input/save.js.map +1 -1
- package/build/gallery/edit.js +38 -58
- package/build/gallery/edit.js.map +1 -1
- package/build/gallery/gallery.js +19 -24
- package/build/gallery/gallery.js.map +1 -1
- package/build/gallery/gallery.native.js +1 -1
- package/build/gallery/gallery.native.js.map +1 -1
- package/build/gallery/index.js +8 -4
- package/build/gallery/index.js.map +1 -1
- package/build/gallery/transforms.js +4 -68
- package/build/gallery/transforms.js.map +1 -1
- package/build/gallery/v1/gallery.native.js +1 -1
- package/build/gallery/v1/gallery.native.js.map +1 -1
- package/build/group/edit.js +6 -1
- package/build/group/edit.js.map +1 -1
- package/build/group/index.js +5 -1
- package/build/group/index.js.map +1 -1
- package/build/heading/index.js +3 -6
- package/build/heading/index.js.map +1 -1
- package/build/image/deprecated.js +11 -0
- package/build/image/deprecated.js.map +1 -1
- package/build/image/edit.native.js +4 -1
- package/build/image/edit.native.js.map +1 -1
- package/build/image/image.js +35 -71
- package/build/image/image.js.map +1 -1
- package/build/image/index.js +2 -2
- package/build/image/save.js +3 -1
- package/build/image/save.js.map +1 -1
- package/build/image/view.js +7 -1
- package/build/image/view.js.map +1 -1
- package/build/list/edit.js +10 -15
- package/build/list/edit.js.map +1 -1
- package/build/list-item/edit.js +17 -2
- package/build/list-item/edit.js.map +1 -1
- package/build/list-item/hooks/use-enter.js +5 -3
- package/build/list-item/hooks/use-enter.js.map +1 -1
- package/build/list-item/hooks/use-enter.native.js +4 -3
- package/build/list-item/hooks/use-enter.native.js.map +1 -1
- package/build/list-item/hooks/use-indent-list-item.js +2 -3
- package/build/list-item/hooks/use-indent-list-item.js.map +1 -1
- package/build/list-item/hooks/use-merge.js +1 -1
- package/build/list-item/hooks/use-merge.js.map +1 -1
- package/build/list-item/hooks/use-outdent-list-item.js +3 -17
- package/build/list-item/hooks/use-outdent-list-item.js.map +1 -1
- package/build/list-item/hooks/use-space.js +8 -4
- package/build/list-item/hooks/use-space.js.map +1 -1
- package/build/list-item/index.js +10 -3
- package/build/list-item/index.js.map +1 -1
- package/build/media-text/media-container.native.js +3 -0
- package/build/media-text/media-container.native.js.map +1 -1
- package/build/navigation/constants.js +3 -1
- package/build/navigation/constants.js.map +1 -1
- package/build/navigation/edit/index.js +5 -1
- package/build/navigation/edit/index.js.map +1 -1
- package/build/navigation/view.js +25 -1
- package/build/navigation/view.js.map +1 -1
- package/build/page-list/convert-to-links-modal.js +2 -2
- package/build/page-list/convert-to-links-modal.js.map +1 -1
- package/build/paragraph/edit.js +54 -32
- package/build/paragraph/edit.js.map +1 -1
- package/build/paragraph/index.js +2 -4
- package/build/paragraph/index.js.map +1 -1
- package/build/paragraph/transforms.js +2 -4
- package/build/paragraph/transforms.js.map +1 -1
- package/build/pattern/edit.js +24 -2
- package/build/pattern/edit.js.map +1 -1
- package/build/pattern/recursion-detector.js +147 -0
- package/build/pattern/recursion-detector.js.map +1 -0
- package/build/post-featured-image/edit.js +19 -2
- package/build/post-featured-image/edit.js.map +1 -1
- package/build/post-featured-image/index.js +4 -0
- package/build/post-featured-image/index.js.map +1 -1
- package/build/post-title/index.js +1 -3
- package/build/post-title/index.js.map +1 -1
- package/build/preformatted/index.js +2 -3
- package/build/preformatted/index.js.map +1 -1
- package/build/pullquote/index.js +5 -7
- package/build/pullquote/index.js.map +1 -1
- package/build/query/edit/inspector-controls/index.js +3 -1
- package/build/query/edit/inspector-controls/index.js.map +1 -1
- package/build/query/edit/inspector-controls/taxonomy-controls.js +2 -0
- package/build/query/edit/inspector-controls/taxonomy-controls.js.map +1 -1
- package/build/query-pagination-numbers/index.js +1 -1
- package/build/query-title/index.js +1 -3
- package/build/query-title/index.js.map +1 -1
- package/build/quote/index.js +3 -5
- package/build/quote/index.js.map +1 -1
- package/build/quote/transforms.js +7 -6
- package/build/quote/transforms.js.map +1 -1
- package/build/search/edit.js +3 -5
- package/build/search/edit.js.map +1 -1
- package/build/search/index.js +0 -4
- package/build/search/index.js.map +1 -1
- package/build/site-logo/edit.js +7 -6
- package/build/site-logo/edit.js.map +1 -1
- package/build/site-title/index.js +1 -5
- package/build/site-title/index.js.map +1 -1
- package/build/social-link/icons/gravatar.js +22 -0
- package/build/social-link/icons/gravatar.js.map +1 -0
- package/build/social-link/icons/index.js +11 -0
- package/build/social-link/icons/index.js.map +1 -1
- package/build/social-link/variations.js +7 -0
- package/build/social-link/variations.js.map +1 -1
- package/build/spacer/edit.native.js +2 -2
- package/build/spacer/edit.native.js.map +1 -1
- package/build/table/edit.js +3 -1
- package/build/table/edit.js.map +1 -1
- package/build/table/index.js +9 -10
- package/build/table/index.js.map +1 -1
- package/build/table-of-contents/edit.js +2 -2
- package/build/table-of-contents/edit.js.map +1 -1
- package/build/table-of-contents/index.js +5 -2
- package/build/table-of-contents/index.js.map +1 -1
- package/build/tag-cloud/edit.js +5 -9
- package/build/tag-cloud/edit.js.map +1 -1
- package/build/utils/caption.js +90 -0
- package/build/utils/caption.js.map +1 -0
- package/build/utils/constants.js +16 -0
- package/build/utils/constants.js.map +1 -0
- package/build/utils/remove-anchor-tag.js +2 -1
- package/build/utils/remove-anchor-tag.js.map +1 -1
- package/build/verse/index.js +3 -5
- package/build/verse/index.js.map +1 -1
- package/build/video/deprecated.js +2 -2
- package/build/video/edit.js +16 -57
- package/build/video/edit.js.map +1 -1
- package/build/video/edit.native.js +1 -1
- package/build/video/edit.native.js.map +1 -1
- package/build/video/index.js +2 -2
- package/build-module/audio/edit.js +19 -66
- package/build-module/audio/edit.js.map +1 -1
- package/build-module/audio/edit.native.js +2 -2
- package/build-module/audio/edit.native.js.map +1 -1
- package/build-module/audio/index.js +2 -2
- package/build-module/block/edit.js +160 -22
- package/build-module/block/edit.js.map +1 -1
- package/build-module/block/index.js +3 -2
- package/build-module/block/index.js.map +1 -1
- package/build-module/block/v1/edit.js +108 -0
- package/build-module/block/v1/edit.js.map +1 -0
- package/build-module/block/{edit.native.js → v1/edit.native.js} +2 -2
- package/build-module/block/v1/edit.native.js.map +1 -0
- package/build-module/button/index.js +2 -2
- package/build-module/button/save.js +1 -1
- package/build-module/button/save.js.map +1 -1
- package/build-module/code/edit.native.js +14 -16
- package/build-module/code/edit.native.js.map +1 -1
- package/build-module/code/index.js +2 -2
- package/build-module/code/save.js +6 -2
- package/build-module/code/save.js.map +1 -1
- package/build-module/comments-title/deprecated.js +1 -1
- package/build-module/comments-title/index.js +1 -1
- package/build-module/cover/edit/inspector-controls.js +1 -1
- package/build-module/cover/edit/inspector-controls.js.map +1 -1
- package/build-module/cover/edit.native.js +1 -0
- package/build-module/cover/edit.native.js.map +1 -1
- package/build-module/details/index.js +2 -2
- package/build-module/embed/deprecated.js +2 -2
- package/build-module/embed/embed-preview.native.js +2 -2
- package/build-module/embed/embed-preview.native.js.map +1 -1
- package/build-module/embed/icons.js +1 -1
- package/build-module/embed/icons.js.map +1 -1
- package/build-module/embed/index.js +2 -2
- package/build-module/embed/transforms.js +2 -2
- package/build-module/embed/util.js +6 -6
- package/build-module/embed/util.js.map +1 -1
- package/build-module/file/edit.js +20 -28
- package/build-module/file/edit.js.map +1 -1
- package/build-module/file/edit.native.js +1 -1
- package/build-module/file/edit.native.js.map +1 -1
- package/build-module/file/index.js +4 -4
- package/build-module/file/save.js +4 -1
- package/build-module/file/save.js.map +1 -1
- package/build-module/form-input/deprecated.js +138 -0
- package/build-module/form-input/deprecated.js.map +1 -0
- package/build-module/form-input/edit.js +1 -1
- package/build-module/form-input/edit.js.map +1 -1
- package/build-module/form-input/index.js +4 -2
- package/build-module/form-input/index.js.map +1 -1
- package/build-module/form-input/save.js +8 -10
- package/build-module/form-input/save.js.map +1 -1
- package/build-module/gallery/edit.js +41 -61
- package/build-module/gallery/edit.js.map +1 -1
- package/build-module/gallery/gallery.js +18 -21
- package/build-module/gallery/gallery.js.map +1 -1
- package/build-module/gallery/gallery.native.js +2 -2
- package/build-module/gallery/gallery.native.js.map +1 -1
- package/build-module/gallery/index.js +8 -4
- package/build-module/gallery/index.js.map +1 -1
- package/build-module/gallery/transforms.js +4 -68
- package/build-module/gallery/transforms.js.map +1 -1
- package/build-module/gallery/v1/gallery.native.js +2 -2
- package/build-module/gallery/v1/gallery.native.js.map +1 -1
- package/build-module/group/edit.js +6 -1
- package/build-module/group/edit.js.map +1 -1
- package/build-module/group/index.js +5 -1
- package/build-module/group/index.js.map +1 -1
- package/build-module/heading/index.js +3 -6
- package/build-module/heading/index.js.map +1 -1
- package/build-module/image/deprecated.js +11 -0
- package/build-module/image/deprecated.js.map +1 -1
- package/build-module/image/edit.native.js +5 -2
- package/build-module/image/edit.native.js.map +1 -1
- package/build-module/image/image.js +35 -71
- package/build-module/image/image.js.map +1 -1
- package/build-module/image/index.js +2 -2
- package/build-module/image/save.js +3 -1
- package/build-module/image/save.js.map +1 -1
- package/build-module/image/view.js +7 -1
- package/build-module/image/view.js.map +1 -1
- package/build-module/list/edit.js +10 -15
- package/build-module/list/edit.js.map +1 -1
- package/build-module/list-item/edit.js +18 -3
- package/build-module/list-item/edit.js.map +1 -1
- package/build-module/list-item/hooks/use-enter.js +5 -3
- package/build-module/list-item/hooks/use-enter.js.map +1 -1
- package/build-module/list-item/hooks/use-enter.native.js +4 -3
- package/build-module/list-item/hooks/use-enter.native.js.map +1 -1
- package/build-module/list-item/hooks/use-indent-list-item.js +2 -3
- package/build-module/list-item/hooks/use-indent-list-item.js.map +1 -1
- package/build-module/list-item/hooks/use-merge.js +1 -1
- package/build-module/list-item/hooks/use-merge.js.map +1 -1
- package/build-module/list-item/hooks/use-outdent-list-item.js +3 -17
- package/build-module/list-item/hooks/use-outdent-list-item.js.map +1 -1
- package/build-module/list-item/hooks/use-space.js +8 -4
- package/build-module/list-item/hooks/use-space.js.map +1 -1
- package/build-module/list-item/index.js +10 -3
- package/build-module/list-item/index.js.map +1 -1
- package/build-module/media-text/media-container.native.js +3 -0
- package/build-module/media-text/media-container.native.js.map +1 -1
- package/build-module/navigation/constants.js +1 -0
- package/build-module/navigation/constants.js.map +1 -1
- package/build-module/navigation/edit/index.js +7 -3
- package/build-module/navigation/edit/index.js.map +1 -1
- package/build-module/navigation/view.js +25 -1
- package/build-module/navigation/view.js.map +1 -1
- package/build-module/page-list/convert-to-links-modal.js +2 -2
- package/build-module/page-list/convert-to-links-modal.js.map +1 -1
- package/build-module/paragraph/edit.js +54 -32
- package/build-module/paragraph/edit.js.map +1 -1
- package/build-module/paragraph/index.js +2 -4
- package/build-module/paragraph/index.js.map +1 -1
- package/build-module/paragraph/transforms.js +2 -4
- package/build-module/paragraph/transforms.js.map +1 -1
- package/build-module/pattern/edit.js +26 -4
- package/build-module/pattern/edit.js.map +1 -1
- package/build-module/pattern/recursion-detector.js +139 -0
- package/build-module/pattern/recursion-detector.js.map +1 -0
- package/build-module/post-featured-image/edit.js +19 -2
- package/build-module/post-featured-image/edit.js.map +1 -1
- package/build-module/post-featured-image/index.js +4 -0
- package/build-module/post-featured-image/index.js.map +1 -1
- package/build-module/post-title/index.js +1 -3
- package/build-module/post-title/index.js.map +1 -1
- package/build-module/preformatted/index.js +2 -3
- package/build-module/preformatted/index.js.map +1 -1
- package/build-module/pullquote/index.js +5 -7
- package/build-module/pullquote/index.js.map +1 -1
- package/build-module/query/edit/inspector-controls/index.js +3 -1
- package/build-module/query/edit/inspector-controls/index.js.map +1 -1
- package/build-module/query/edit/inspector-controls/taxonomy-controls.js +2 -0
- package/build-module/query/edit/inspector-controls/taxonomy-controls.js.map +1 -1
- package/build-module/query-pagination-numbers/index.js +1 -1
- package/build-module/query-title/index.js +1 -3
- package/build-module/query-title/index.js.map +1 -1
- package/build-module/quote/index.js +3 -5
- package/build-module/quote/index.js.map +1 -1
- package/build-module/quote/transforms.js +7 -6
- package/build-module/quote/transforms.js.map +1 -1
- package/build-module/search/edit.js +3 -5
- package/build-module/search/edit.js.map +1 -1
- package/build-module/search/index.js +0 -4
- package/build-module/search/index.js.map +1 -1
- package/build-module/site-logo/edit.js +7 -6
- package/build-module/site-logo/edit.js.map +1 -1
- package/build-module/site-title/index.js +1 -5
- package/build-module/site-title/index.js.map +1 -1
- package/build-module/social-link/icons/gravatar.js +14 -0
- package/build-module/social-link/icons/gravatar.js.map +1 -0
- package/build-module/social-link/icons/index.js +1 -0
- package/build-module/social-link/icons/index.js.map +1 -1
- package/build-module/social-link/variations.js +8 -1
- package/build-module/social-link/variations.js.map +1 -1
- package/build-module/spacer/edit.native.js +2 -2
- package/build-module/spacer/edit.native.js.map +1 -1
- package/build-module/table/edit.js +3 -1
- package/build-module/table/edit.js.map +1 -1
- package/build-module/table/index.js +9 -10
- package/build-module/table/index.js.map +1 -1
- package/build-module/table-of-contents/edit.js +1 -1
- package/build-module/table-of-contents/edit.js.map +1 -1
- package/build-module/table-of-contents/index.js +5 -1
- package/build-module/table-of-contents/index.js.map +1 -1
- package/build-module/tag-cloud/edit.js +6 -10
- package/build-module/tag-cloud/edit.js.map +1 -1
- package/build-module/utils/caption.js +82 -0
- package/build-module/utils/caption.js.map +1 -0
- package/build-module/utils/constants.js +9 -0
- package/build-module/utils/constants.js.map +1 -0
- package/build-module/utils/remove-anchor-tag.js +2 -1
- package/build-module/utils/remove-anchor-tag.js.map +1 -1
- package/build-module/verse/index.js +3 -5
- package/build-module/verse/index.js.map +1 -1
- package/build-module/video/deprecated.js +2 -2
- package/build-module/video/edit.js +21 -62
- package/build-module/video/edit.js.map +1 -1
- package/build-module/video/edit.native.js +2 -2
- package/build-module/video/edit.native.js.map +1 -1
- package/build-module/video/index.js +2 -2
- package/build-style/button/editor-rtl.css +0 -37
- package/build-style/button/editor.css +0 -37
- package/build-style/button/style-rtl.css +6 -6
- package/build-style/button/style.css +6 -6
- package/build-style/editor-rtl.css +3 -55
- package/build-style/editor.css +3 -55
- package/build-style/navigation/editor-rtl.css +2 -4
- package/build-style/navigation/editor.css +2 -4
- package/build-style/navigation/style-rtl.css +14 -18
- package/build-style/navigation/style.css +14 -18
- package/build-style/search/style-rtl.css +26 -27
- package/build-style/search/style.css +26 -27
- package/build-style/social-links/style-rtl.css +14 -2
- package/build-style/social-links/style.css +14 -2
- package/build-style/style-rtl.css +60 -53
- package/build-style/style.css +60 -53
- package/build-style/table/editor-rtl.css +1 -14
- package/build-style/table/editor.css +1 -14
- package/package.json +32 -32
- package/src/audio/block.json +2 -2
- package/src/audio/edit.js +29 -92
- package/src/audio/edit.native.js +2 -1
- package/src/audio/test/__snapshots__/edit.native.js.snap +12 -0
- package/src/audio/test/edit.native.js +29 -0
- package/src/block/edit.js +218 -37
- package/src/block/index.js +3 -2
- package/src/block/index.php +48 -0
- package/src/block/v1/edit.js +163 -0
- package/src/block/{edit.native.js → v1/edit.native.js} +2 -2
- package/src/button/block.json +2 -2
- package/src/button/editor.scss +0 -43
- package/src/button/save.js +1 -1
- package/src/button/style.scss +6 -6
- package/src/buttons/test/__snapshots__/edit.native.js.snap +6 -0
- package/src/buttons/test/edit.native.js +49 -0
- package/src/code/block.json +2 -2
- package/src/code/edit.native.js +11 -13
- package/src/code/save.js +4 -1
- package/src/code/test/edit.native.js +2 -2
- package/src/comments-title/block.json +1 -1
- package/src/cover/edit/inspector-controls.js +1 -1
- package/src/cover/edit.native.js +1 -0
- package/src/cover/test/edit.native.js +7 -1
- package/src/details/block.json +2 -2
- package/src/embed/block.json +2 -2
- package/src/embed/embed-preview.native.js +2 -1
- package/src/embed/icons.js +1 -1
- package/src/embed/util.js +2 -2
- package/src/file/block.json +4 -4
- package/src/file/edit.js +18 -25
- package/src/file/edit.native.js +1 -1
- package/src/file/save.js +5 -1
- package/src/form-input/block.json +2 -2
- package/src/form-input/deprecated.js +142 -0
- package/src/form-input/edit.js +1 -1
- package/src/form-input/index.js +2 -0
- package/src/form-input/save.js +27 -24
- package/src/gallery/block.json +8 -4
- package/src/gallery/edit.js +70 -98
- package/src/gallery/gallery.js +22 -36
- package/src/gallery/gallery.native.js +6 -2
- package/src/gallery/index.php +15 -0
- package/src/gallery/transforms.js +2 -55
- package/src/gallery/v1/gallery.native.js +2 -1
- package/src/group/block.json +5 -1
- package/src/group/edit.js +4 -1
- package/src/heading/block.json +3 -6
- package/src/image/block.json +2 -2
- package/src/image/deprecated.js +8 -0
- package/src/image/edit.native.js +5 -3
- package/src/image/image.js +77 -127
- package/src/image/index.php +1 -6
- package/src/image/save.js +3 -1
- package/src/image/view.js +5 -2
- package/src/list/edit.js +27 -35
- package/src/list-item/block.json +10 -3
- package/src/list-item/edit.js +18 -2
- package/src/list-item/hooks/use-enter.js +63 -62
- package/src/list-item/hooks/use-enter.native.js +9 -5
- package/src/list-item/hooks/use-indent-list-item.js +43 -53
- package/src/list-item/hooks/use-merge.js +1 -1
- package/src/list-item/hooks/use-outdent-list-item.js +50 -69
- package/src/list-item/hooks/use-space.js +7 -4
- package/src/media-text/media-container.native.js +3 -1
- package/src/navigation/constants.js +2 -0
- package/src/navigation/edit/index.js +18 -3
- package/src/navigation/editor.scss +1 -1
- package/src/navigation/index.php +1 -1
- package/src/navigation/style.scss +18 -16
- package/src/navigation/view.js +29 -3
- package/src/navigation-link/test/__snapshots__/hooks.js.snap +6 -3
- package/src/page-list/convert-to-links-modal.js +2 -2
- package/src/paragraph/block.json +2 -4
- package/src/paragraph/edit.js +53 -40
- package/src/paragraph/test/__snapshots__/edit.native.js.snap +12 -0
- package/src/paragraph/test/edit.native.js +114 -0
- package/src/pattern/edit.js +35 -3
- package/src/pattern/index.php +16 -0
- package/src/pattern/recursion-detector.js +145 -0
- package/src/pattern/test/index.js +74 -0
- package/src/post-featured-image/block.json +4 -0
- package/src/post-featured-image/edit.js +32 -1
- package/src/post-featured-image/index.php +31 -0
- package/src/post-title/block.json +1 -3
- package/src/preformatted/block.json +2 -3
- package/src/pullquote/block.json +5 -7
- package/src/query/edit/inspector-controls/index.js +2 -0
- package/src/query/edit/inspector-controls/taxonomy-controls.js +2 -0
- package/src/query-pagination-numbers/block.json +1 -1
- package/src/query-title/block.json +1 -3
- package/src/quote/block.json +3 -5
- package/src/quote/transforms.js +12 -11
- package/src/search/block.json +0 -4
- package/src/search/edit.js +2 -8
- package/src/search/index.php +3 -7
- package/src/search/style.scss +27 -29
- package/src/site-logo/edit.js +3 -4
- package/src/site-title/block.json +1 -5
- package/src/social-link/icons/gravatar.js +10 -0
- package/src/social-link/icons/index.js +1 -0
- package/src/social-link/index.php +5 -1
- package/src/social-link/socials-with-bg.scss +5 -0
- package/src/social-link/socials-without-bg.scss +4 -0
- package/src/social-link/variations.js +7 -0
- package/src/social-links/style.scss +14 -8
- package/src/spacer/edit.native.js +4 -2
- package/src/table/block.json +9 -10
- package/src/table/edit.js +3 -1
- package/src/table/editor.scss +1 -17
- package/src/table-of-contents/edit.js +1 -1
- package/src/table-of-contents/index.js +5 -1
- package/src/tag-cloud/edit.js +7 -7
- package/src/template-part/index.php +6 -0
- package/src/utils/caption.js +108 -0
- package/src/utils/constants.js +8 -0
- package/src/utils/remove-anchor-tag.js +2 -1
- package/src/verse/block.json +3 -5
- package/src/video/block.json +2 -2
- package/src/video/edit.js +40 -100
- package/src/video/edit.native.js +2 -1
- package/build/block/edit.native.js.map +0 -1
- package/build/table-of-contents/icon.js +0 -22
- package/build/table-of-contents/icon.js.map +0 -1
- package/build-module/block/edit.native.js.map +0 -1
- package/build-module/table-of-contents/icon.js +0 -15
- package/build-module/table-of-contents/icon.js.map +0 -1
- package/src/table-of-contents/icon.js +0 -18
package/src/paragraph/edit.js
CHANGED
|
@@ -49,6 +49,48 @@ function hasDropCapDisabled( align ) {
|
|
|
49
49
|
return align === ( isRTL() ? 'left' : 'right' ) || align === 'center';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function DropCapControl( { clientId, attributes, setAttributes } ) {
|
|
53
|
+
// Please do no add a useSelect call to the paragraph block unconditionaly.
|
|
54
|
+
// Every useSelect added to a (frequestly used) block will degrade the load
|
|
55
|
+
// and type bit. By moving it within InspectorControls, the subscription is
|
|
56
|
+
// now only added for the selected block(s).
|
|
57
|
+
const [ isDropCapFeatureEnabled ] = useSettings( 'typography.dropCap' );
|
|
58
|
+
|
|
59
|
+
if ( ! isDropCapFeatureEnabled ) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { align, dropCap } = attributes;
|
|
64
|
+
|
|
65
|
+
let helpText;
|
|
66
|
+
if ( hasDropCapDisabled( align ) ) {
|
|
67
|
+
helpText = __( 'Not available for aligned text.' );
|
|
68
|
+
} else if ( dropCap ) {
|
|
69
|
+
helpText = __( 'Showing large initial letter.' );
|
|
70
|
+
} else {
|
|
71
|
+
helpText = __( 'Toggle to show a large initial letter.' );
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<ToolsPanelItem
|
|
76
|
+
hasValue={ () => !! dropCap }
|
|
77
|
+
label={ __( 'Drop cap' ) }
|
|
78
|
+
onDeselect={ () => setAttributes( { dropCap: undefined } ) }
|
|
79
|
+
resetAllFilter={ () => ( { dropCap: undefined } ) }
|
|
80
|
+
panelId={ clientId }
|
|
81
|
+
>
|
|
82
|
+
<ToggleControl
|
|
83
|
+
__nextHasNoMarginBottom
|
|
84
|
+
label={ __( 'Drop cap' ) }
|
|
85
|
+
checked={ !! dropCap }
|
|
86
|
+
onChange={ () => setAttributes( { dropCap: ! dropCap } ) }
|
|
87
|
+
help={ helpText }
|
|
88
|
+
disabled={ hasDropCapDisabled( align ) ? true : false }
|
|
89
|
+
/>
|
|
90
|
+
</ToolsPanelItem>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
52
94
|
function ParagraphBlock( {
|
|
53
95
|
attributes,
|
|
54
96
|
mergeBlocks,
|
|
@@ -58,7 +100,6 @@ function ParagraphBlock( {
|
|
|
58
100
|
clientId,
|
|
59
101
|
} ) {
|
|
60
102
|
const { align, content, direction, dropCap, placeholder } = attributes;
|
|
61
|
-
const [ isDropCapFeatureEnabled ] = useSettings( 'typography.dropCap' );
|
|
62
103
|
const blockProps = useBlockProps( {
|
|
63
104
|
ref: useOnEnter( { clientId, content } ),
|
|
64
105
|
className: classnames( {
|
|
@@ -68,15 +109,6 @@ function ParagraphBlock( {
|
|
|
68
109
|
style: { direction },
|
|
69
110
|
} );
|
|
70
111
|
|
|
71
|
-
let helpText;
|
|
72
|
-
if ( hasDropCapDisabled( align ) ) {
|
|
73
|
-
helpText = __( 'Not available for aligned text.' );
|
|
74
|
-
} else if ( dropCap ) {
|
|
75
|
-
helpText = __( 'Showing large initial letter.' );
|
|
76
|
-
} else {
|
|
77
|
-
helpText = __( 'Toggle to show a large initial letter.' );
|
|
78
|
-
}
|
|
79
|
-
|
|
80
112
|
return (
|
|
81
113
|
<>
|
|
82
114
|
<BlockControls group="block">
|
|
@@ -98,32 +130,13 @@ function ParagraphBlock( {
|
|
|
98
130
|
}
|
|
99
131
|
/>
|
|
100
132
|
</BlockControls>
|
|
101
|
-
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
resetAllFilter={ () => ( { dropCap: undefined } ) }
|
|
110
|
-
panelId={ clientId }
|
|
111
|
-
>
|
|
112
|
-
<ToggleControl
|
|
113
|
-
__nextHasNoMarginBottom
|
|
114
|
-
label={ __( 'Drop cap' ) }
|
|
115
|
-
checked={ !! dropCap }
|
|
116
|
-
onChange={ () =>
|
|
117
|
-
setAttributes( { dropCap: ! dropCap } )
|
|
118
|
-
}
|
|
119
|
-
help={ helpText }
|
|
120
|
-
disabled={
|
|
121
|
-
hasDropCapDisabled( align ) ? true : false
|
|
122
|
-
}
|
|
123
|
-
/>
|
|
124
|
-
</ToolsPanelItem>
|
|
125
|
-
</InspectorControls>
|
|
126
|
-
) }
|
|
133
|
+
<InspectorControls group="typography">
|
|
134
|
+
<DropCapControl
|
|
135
|
+
clientId={ clientId }
|
|
136
|
+
attributes={ attributes }
|
|
137
|
+
setAttributes={ setAttributes }
|
|
138
|
+
/>
|
|
139
|
+
</InspectorControls>
|
|
127
140
|
<RichText
|
|
128
141
|
identifier="content"
|
|
129
142
|
tagName="p"
|
|
@@ -154,13 +167,13 @@ function ParagraphBlock( {
|
|
|
154
167
|
onReplace={ onReplace }
|
|
155
168
|
onRemove={ onRemove }
|
|
156
169
|
aria-label={
|
|
157
|
-
content
|
|
158
|
-
? __(
|
|
159
|
-
: __(
|
|
170
|
+
RichText.isEmpty( content )
|
|
171
|
+
? __(
|
|
160
172
|
'Empty block; start writing or type forward slash to choose a block'
|
|
161
173
|
)
|
|
174
|
+
: __( 'Block: Paragraph' )
|
|
162
175
|
}
|
|
163
|
-
data-empty={ content
|
|
176
|
+
data-empty={ RichText.isEmpty( content ) }
|
|
164
177
|
placeholder={ placeholder || __( 'Type / to choose a block' ) }
|
|
165
178
|
data-custom-placeholder={ placeholder ? true : undefined }
|
|
166
179
|
__unstableEmbedURLOnPaste
|
|
@@ -38,3 +38,15 @@ exports[`Paragraph block should render without crashing and match snapshot 1`] =
|
|
|
38
38
|
/>
|
|
39
39
|
</View>
|
|
40
40
|
`;
|
|
41
|
+
|
|
42
|
+
exports[`Paragraph block should set a font size value 1`] = `
|
|
43
|
+
"<!-- wp:paragraph {"style":{"typography":{"fontSize":"30px"}}} -->
|
|
44
|
+
<p style="font-size:30px">A quick brown fox jumps over the lazy dog.</p>
|
|
45
|
+
<!-- /wp:paragraph -->"
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
exports[`Paragraph block should set a line height value 1`] = `
|
|
49
|
+
"<!-- wp:paragraph {"style":{"typography":{"lineHeight":1.8}}} -->
|
|
50
|
+
<p style="line-height:1.8">A quick brown fox jumps over the lazy dog.</p>
|
|
51
|
+
<!-- /wp:paragraph -->"
|
|
52
|
+
`;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import {
|
|
5
5
|
act,
|
|
6
6
|
addBlock,
|
|
7
|
+
dismissModal,
|
|
7
8
|
getBlock,
|
|
8
9
|
typeInRichText,
|
|
9
10
|
fireEvent,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
within,
|
|
16
17
|
withFakeTimers,
|
|
17
18
|
waitForElementToBeRemoved,
|
|
19
|
+
waitForModalVisible,
|
|
18
20
|
} from 'test/helpers';
|
|
19
21
|
import Clipboard from '@react-native-clipboard/clipboard';
|
|
20
22
|
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
|
|
@@ -687,6 +689,118 @@ describe( 'Paragraph block', () => {
|
|
|
687
689
|
` );
|
|
688
690
|
} );
|
|
689
691
|
|
|
692
|
+
it( 'should show the expected font sizes values', async () => {
|
|
693
|
+
// Arrange
|
|
694
|
+
const screen = await initializeEditor( { withGlobalStyles: true } );
|
|
695
|
+
await addBlock( screen, 'Paragraph' );
|
|
696
|
+
|
|
697
|
+
// Act
|
|
698
|
+
const paragraphBlock = getBlock( screen, 'Paragraph' );
|
|
699
|
+
fireEvent.press( paragraphBlock );
|
|
700
|
+
const paragraphTextInput =
|
|
701
|
+
within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
|
|
702
|
+
typeInRichText(
|
|
703
|
+
paragraphTextInput,
|
|
704
|
+
'A quick brown fox jumps over the lazy dog.'
|
|
705
|
+
);
|
|
706
|
+
// Open Block Settings.
|
|
707
|
+
fireEvent.press( screen.getByLabelText( 'Open Settings' ) );
|
|
708
|
+
|
|
709
|
+
// Wait for Block Settings to be visible.
|
|
710
|
+
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
|
|
711
|
+
await waitForModalVisible( blockSettingsModal );
|
|
712
|
+
|
|
713
|
+
// Open Font size settings
|
|
714
|
+
fireEvent.press( screen.getByLabelText( 'Font Size, Custom' ) );
|
|
715
|
+
await waitFor( () => screen.getByLabelText( 'Selected: Default' ) );
|
|
716
|
+
|
|
717
|
+
// Assert
|
|
718
|
+
const modalContent = within( blockSettingsModal );
|
|
719
|
+
expect( modalContent.getByLabelText( 'Small' ) ).toBeVisible();
|
|
720
|
+
expect( modalContent.getByText( '14px' ) ).toBeVisible();
|
|
721
|
+
expect( modalContent.getByLabelText( 'Medium' ) ).toBeVisible();
|
|
722
|
+
expect( modalContent.getByText( '17px' ) ).toBeVisible();
|
|
723
|
+
expect( modalContent.getByLabelText( 'Large' ) ).toBeVisible();
|
|
724
|
+
expect( modalContent.getByText( '30px' ) ).toBeVisible();
|
|
725
|
+
expect( modalContent.getByLabelText( 'Extra Large' ) ).toBeVisible();
|
|
726
|
+
expect( modalContent.getByText( '40px' ) ).toBeVisible();
|
|
727
|
+
expect(
|
|
728
|
+
modalContent.getByLabelText( 'Extra Extra Large' )
|
|
729
|
+
).toBeVisible();
|
|
730
|
+
expect( modalContent.getByText( '52px' ) ).toBeVisible();
|
|
731
|
+
} );
|
|
732
|
+
|
|
733
|
+
it( 'should set a font size value', async () => {
|
|
734
|
+
// Arrange
|
|
735
|
+
const screen = await initializeEditor( { withGlobalStyles: true } );
|
|
736
|
+
await addBlock( screen, 'Paragraph' );
|
|
737
|
+
|
|
738
|
+
// Act
|
|
739
|
+
const paragraphBlock = getBlock( screen, 'Paragraph' );
|
|
740
|
+
fireEvent.press( paragraphBlock );
|
|
741
|
+
const paragraphTextInput =
|
|
742
|
+
within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
|
|
743
|
+
typeInRichText(
|
|
744
|
+
paragraphTextInput,
|
|
745
|
+
'A quick brown fox jumps over the lazy dog.'
|
|
746
|
+
);
|
|
747
|
+
// Open Block Settings.
|
|
748
|
+
fireEvent.press( screen.getByLabelText( 'Open Settings' ) );
|
|
749
|
+
|
|
750
|
+
// Wait for Block Settings to be visible.
|
|
751
|
+
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
|
|
752
|
+
await waitForModalVisible( blockSettingsModal );
|
|
753
|
+
|
|
754
|
+
// Open Font size settings
|
|
755
|
+
fireEvent.press( screen.getByLabelText( 'Font Size, Custom' ) );
|
|
756
|
+
|
|
757
|
+
// Tap one font size
|
|
758
|
+
fireEvent.press( screen.getByLabelText( 'Large' ) );
|
|
759
|
+
|
|
760
|
+
// Dismiss the Block Settings modal.
|
|
761
|
+
await dismissModal( blockSettingsModal );
|
|
762
|
+
|
|
763
|
+
// Assert
|
|
764
|
+
expect( getEditorHtml() ).toMatchSnapshot();
|
|
765
|
+
} );
|
|
766
|
+
|
|
767
|
+
it( 'should set a line height value', async () => {
|
|
768
|
+
// Arrange
|
|
769
|
+
const screen = await initializeEditor( { withGlobalStyles: true } );
|
|
770
|
+
await addBlock( screen, 'Paragraph' );
|
|
771
|
+
|
|
772
|
+
// Act
|
|
773
|
+
const paragraphBlock = getBlock( screen, 'Paragraph' );
|
|
774
|
+
fireEvent.press( paragraphBlock );
|
|
775
|
+
const paragraphTextInput =
|
|
776
|
+
within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
|
|
777
|
+
typeInRichText(
|
|
778
|
+
paragraphTextInput,
|
|
779
|
+
'A quick brown fox jumps over the lazy dog.'
|
|
780
|
+
);
|
|
781
|
+
// Open Block Settings.
|
|
782
|
+
fireEvent.press( screen.getByLabelText( 'Open Settings' ) );
|
|
783
|
+
|
|
784
|
+
// Wait for Block Settings to be visible.
|
|
785
|
+
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
|
|
786
|
+
await waitForModalVisible( blockSettingsModal );
|
|
787
|
+
|
|
788
|
+
const lineHeightControl = screen.getByLabelText( /Line Height/ );
|
|
789
|
+
fireEvent.press(
|
|
790
|
+
within( lineHeightControl ).getByText( '1.5', { hidden: true } )
|
|
791
|
+
);
|
|
792
|
+
const lineHeightTextInput = within(
|
|
793
|
+
lineHeightControl
|
|
794
|
+
).getByDisplayValue( '1.5', { hidden: true } );
|
|
795
|
+
fireEvent.changeText( lineHeightTextInput, '1.8' );
|
|
796
|
+
|
|
797
|
+
// Dismiss the Block Settings modal.
|
|
798
|
+
await dismissModal( blockSettingsModal );
|
|
799
|
+
|
|
800
|
+
// Assert
|
|
801
|
+
expect( getEditorHtml() ).toMatchSnapshot();
|
|
802
|
+
} );
|
|
803
|
+
|
|
690
804
|
it( 'should focus on the previous Paragraph block when backspacing in an empty Paragraph block', async () => {
|
|
691
805
|
// Arrange
|
|
692
806
|
const screen = await initializeEditor();
|
package/src/pattern/edit.js
CHANGED
|
@@ -3,12 +3,19 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { cloneBlock } from '@wordpress/blocks';
|
|
5
5
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
6
|
-
import { useEffect } from '@wordpress/element';
|
|
6
|
+
import { useState, useEffect } from '@wordpress/element';
|
|
7
7
|
import {
|
|
8
|
+
Warning,
|
|
8
9
|
store as blockEditorStore,
|
|
9
10
|
useBlockProps,
|
|
10
11
|
} from '@wordpress/block-editor';
|
|
11
12
|
import { store as coreStore } from '@wordpress/core-data';
|
|
13
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Internal dependencies
|
|
17
|
+
*/
|
|
18
|
+
import { useParsePatternDependencies } from './recursion-detector';
|
|
12
19
|
|
|
13
20
|
const PatternEdit = ( { attributes, clientId } ) => {
|
|
14
21
|
const selectedPattern = useSelect(
|
|
@@ -32,6 +39,9 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
32
39
|
const { getBlockRootClientId, getBlockEditingMode } =
|
|
33
40
|
useSelect( blockEditorStore );
|
|
34
41
|
|
|
42
|
+
const [ hasRecursionError, setHasRecursionError ] = useState( false );
|
|
43
|
+
const parsePatternDependencies = useParsePatternDependencies();
|
|
44
|
+
|
|
35
45
|
// Duplicated in packages/edit-site/src/components/start-template-options/index.js.
|
|
36
46
|
function injectThemeAttributeInBlockTemplateContent( block ) {
|
|
37
47
|
if (
|
|
@@ -64,7 +74,14 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
64
74
|
// This change won't be saved.
|
|
65
75
|
// It will continue to pull from the pattern file unless changes are made to its respective template part.
|
|
66
76
|
useEffect( () => {
|
|
67
|
-
if ( selectedPattern?.blocks ) {
|
|
77
|
+
if ( ! hasRecursionError && selectedPattern?.blocks ) {
|
|
78
|
+
try {
|
|
79
|
+
parsePatternDependencies( selectedPattern );
|
|
80
|
+
} catch ( error ) {
|
|
81
|
+
setHasRecursionError( true );
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
68
85
|
// We batch updates to block list settings to avoid triggering cascading renders
|
|
69
86
|
// for each container block included in a tree and optimize initial render.
|
|
70
87
|
// Since the above uses microtasks, we need to use a microtask here as well,
|
|
@@ -93,7 +110,8 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
93
110
|
}
|
|
94
111
|
}, [
|
|
95
112
|
clientId,
|
|
96
|
-
|
|
113
|
+
hasRecursionError,
|
|
114
|
+
selectedPattern,
|
|
97
115
|
__unstableMarkNextChangeAsNotPersistent,
|
|
98
116
|
replaceBlocks,
|
|
99
117
|
getBlockEditingMode,
|
|
@@ -103,6 +121,20 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
103
121
|
|
|
104
122
|
const props = useBlockProps();
|
|
105
123
|
|
|
124
|
+
if ( hasRecursionError ) {
|
|
125
|
+
return (
|
|
126
|
+
<div { ...props }>
|
|
127
|
+
<Warning>
|
|
128
|
+
{ sprintf(
|
|
129
|
+
// translators: A warning in which %s is the name of a pattern.
|
|
130
|
+
__( 'Pattern "%s" cannot be rendered inside itself.' ),
|
|
131
|
+
selectedPattern?.name
|
|
132
|
+
) }
|
|
133
|
+
</Warning>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
106
138
|
return <div { ...props } />;
|
|
107
139
|
};
|
|
108
140
|
|
package/src/pattern/index.php
CHANGED
|
@@ -27,6 +27,8 @@ function register_block_core_pattern() {
|
|
|
27
27
|
* @return string Returns the output of the pattern.
|
|
28
28
|
*/
|
|
29
29
|
function render_block_core_pattern( $attributes ) {
|
|
30
|
+
static $seen_refs = array();
|
|
31
|
+
|
|
30
32
|
if ( empty( $attributes['slug'] ) ) {
|
|
31
33
|
return '';
|
|
32
34
|
}
|
|
@@ -38,6 +40,17 @@ function render_block_core_pattern( $attributes ) {
|
|
|
38
40
|
return '';
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
if ( isset( $seen_refs[ $attributes['slug'] ] ) ) {
|
|
44
|
+
// WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent
|
|
45
|
+
// is set in `wp_debug_mode()`.
|
|
46
|
+
$is_debug = WP_DEBUG && WP_DEBUG_DISPLAY;
|
|
47
|
+
|
|
48
|
+
return $is_debug ?
|
|
49
|
+
// translators: Visible only in the front end, this warning takes the place of a faulty block. %s represents a pattern's slug.
|
|
50
|
+
sprintf( __( '[block rendering halted for pattern "%s"]' ), $slug ) :
|
|
51
|
+
'';
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
$pattern = $registry->get_registered( $slug );
|
|
42
55
|
$content = $pattern['content'];
|
|
43
56
|
|
|
@@ -48,11 +61,14 @@ function render_block_core_pattern( $attributes ) {
|
|
|
48
61
|
$content = gutenberg_serialize_blocks( $blocks );
|
|
49
62
|
}
|
|
50
63
|
|
|
64
|
+
$seen_refs[ $attributes['slug'] ] = true;
|
|
65
|
+
|
|
51
66
|
$content = do_blocks( $content );
|
|
52
67
|
|
|
53
68
|
global $wp_embed;
|
|
54
69
|
$content = $wp_embed->autoembed( $content );
|
|
55
70
|
|
|
71
|
+
unset( $seen_refs[ $attributes['slug'] ] );
|
|
56
72
|
return $content;
|
|
57
73
|
}
|
|
58
74
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THIS MODULE IS INTENTIONALLY KEPT WITHIN THE PATTERN BLOCK'S SOURCE.
|
|
3
|
+
*
|
|
4
|
+
* This is because this approach for preventing infinite loops due to
|
|
5
|
+
* recursively rendering blocks is specific to the way that the `core/pattern`
|
|
6
|
+
* block behaves in the editor. Any other block types that deal with recursion
|
|
7
|
+
* SHOULD USE THE STANDARD METHOD for avoiding loops:
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/WordPress/gutenberg/pull/31455
|
|
10
|
+
* @see packages/block-editor/src/components/recursion-provider/README.md
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* WordPress dependencies
|
|
15
|
+
*/
|
|
16
|
+
import { useRegistry } from '@wordpress/data';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Naming is hard.
|
|
20
|
+
*
|
|
21
|
+
* @see useParsePatternDependencies
|
|
22
|
+
*
|
|
23
|
+
* @type {WeakMap<Object, Function>}
|
|
24
|
+
*/
|
|
25
|
+
const cachedParsers = new WeakMap();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Hook used by PatternEdit to parse block patterns. It returns a function that
|
|
29
|
+
* takes a pattern and returns nothing but throws an error if the pattern is
|
|
30
|
+
* recursive.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```js
|
|
34
|
+
* const parsePatternDependencies = useParsePatternDependencies();
|
|
35
|
+
* parsePatternDependencies( selectedPattern );
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @see parsePatternDependencies
|
|
39
|
+
*
|
|
40
|
+
* @return {Function} A function to parse block patterns.
|
|
41
|
+
*/
|
|
42
|
+
export function useParsePatternDependencies() {
|
|
43
|
+
const registry = useRegistry();
|
|
44
|
+
|
|
45
|
+
// Instead of caching maps, go straight to the point and cache bound
|
|
46
|
+
// functions. Each of those functions is bound to a different Map that will
|
|
47
|
+
// keep track of patterns in the context of the given registry.
|
|
48
|
+
if ( ! cachedParsers.has( registry ) ) {
|
|
49
|
+
const deps = new Map();
|
|
50
|
+
cachedParsers.set(
|
|
51
|
+
registry,
|
|
52
|
+
parsePatternDependencies.bind( null, deps )
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return cachedParsers.get( registry );
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Parse a given pattern and traverse its contents to detect any subsequent
|
|
60
|
+
* patterns on which it may depend. Such occurrences will be added to an
|
|
61
|
+
* internal dependency graph. If a circular dependency is detected, an
|
|
62
|
+
* error will be thrown.
|
|
63
|
+
*
|
|
64
|
+
* EXPORTED FOR TESTING PURPOSES ONLY.
|
|
65
|
+
*
|
|
66
|
+
* @param {Map<string, Set<string>>} deps Map of pattern dependencies.
|
|
67
|
+
* @param {Object} pattern Pattern.
|
|
68
|
+
* @param {string} pattern.name Pattern name.
|
|
69
|
+
* @param {Array} pattern.blocks Pattern's block list.
|
|
70
|
+
*
|
|
71
|
+
* @throws {Error} If a circular dependency is detected.
|
|
72
|
+
*/
|
|
73
|
+
export function parsePatternDependencies( deps, { name, blocks } ) {
|
|
74
|
+
const queue = [ ...blocks ];
|
|
75
|
+
while ( queue.length ) {
|
|
76
|
+
const block = queue.shift();
|
|
77
|
+
for ( const innerBlock of block.innerBlocks ?? [] ) {
|
|
78
|
+
queue.unshift( innerBlock );
|
|
79
|
+
}
|
|
80
|
+
if ( block.name === 'core/pattern' ) {
|
|
81
|
+
registerDependency( deps, name, block.attributes.slug );
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Declare that pattern `a` depends on pattern `b`. If a circular
|
|
88
|
+
* dependency is detected, an error will be thrown.
|
|
89
|
+
*
|
|
90
|
+
* EXPORTED FOR TESTING PURPOSES ONLY.
|
|
91
|
+
*
|
|
92
|
+
* @param {Map<string, Set<string>>} deps Map of pattern dependencies.
|
|
93
|
+
* @param {string} a Slug for pattern A.
|
|
94
|
+
* @param {string} b Slug for pattern B.
|
|
95
|
+
*
|
|
96
|
+
* @throws {Error} If a circular dependency is detected.
|
|
97
|
+
*/
|
|
98
|
+
export function registerDependency( deps, a, b ) {
|
|
99
|
+
if ( ! deps.has( a ) ) {
|
|
100
|
+
deps.set( a, new Set() );
|
|
101
|
+
}
|
|
102
|
+
deps.get( a ).add( b );
|
|
103
|
+
if ( hasCycle( deps, a ) ) {
|
|
104
|
+
throw new TypeError(
|
|
105
|
+
`Pattern ${ a } has a circular dependency and cannot be rendered.`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Determine if a given pattern has circular dependencies on other patterns.
|
|
112
|
+
* This will be determined by running a depth-first search on the current state
|
|
113
|
+
* of the graph represented by `patternDependencies`.
|
|
114
|
+
*
|
|
115
|
+
* @param {Map<string, Set<string>>} deps Map of pattern dependencies.
|
|
116
|
+
* @param {string} slug Pattern slug.
|
|
117
|
+
* @param {Set<string>} [visitedNodes] Set to track visited nodes in the graph.
|
|
118
|
+
* @param {Set<string>} [currentPath] Set to track and backtrack graph paths.
|
|
119
|
+
* @return {boolean} Whether any cycle was found.
|
|
120
|
+
*/
|
|
121
|
+
function hasCycle(
|
|
122
|
+
deps,
|
|
123
|
+
slug,
|
|
124
|
+
visitedNodes = new Set(),
|
|
125
|
+
currentPath = new Set()
|
|
126
|
+
) {
|
|
127
|
+
visitedNodes.add( slug );
|
|
128
|
+
currentPath.add( slug );
|
|
129
|
+
|
|
130
|
+
const dependencies = deps.get( slug ) ?? new Set();
|
|
131
|
+
|
|
132
|
+
for ( const dependency of dependencies ) {
|
|
133
|
+
if ( ! visitedNodes.has( dependency ) ) {
|
|
134
|
+
if ( hasCycle( deps, dependency, visitedNodes, currentPath ) ) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
} else if ( currentPath.has( dependency ) ) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Remove the current node from the current path when backtracking
|
|
143
|
+
currentPath.delete( slug );
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
parsePatternDependencies,
|
|
6
|
+
registerDependency,
|
|
7
|
+
} from '../recursion-detector';
|
|
8
|
+
|
|
9
|
+
describe( 'core/pattern', () => {
|
|
10
|
+
const deps = new Map();
|
|
11
|
+
|
|
12
|
+
beforeEach( () => {
|
|
13
|
+
deps.clear();
|
|
14
|
+
} );
|
|
15
|
+
|
|
16
|
+
describe( 'parsePatternDependencies', () => {
|
|
17
|
+
it( "is silent for patterns that don't require other patterns", () => {
|
|
18
|
+
const pattern = {
|
|
19
|
+
name: 'test/benign-pattern',
|
|
20
|
+
blocks: [ { name: 'core/paragraph' } ],
|
|
21
|
+
};
|
|
22
|
+
expect( () => {
|
|
23
|
+
parsePatternDependencies( deps, pattern );
|
|
24
|
+
} ).not.toThrow();
|
|
25
|
+
} );
|
|
26
|
+
it( 'catches self-referencing patterns', () => {
|
|
27
|
+
const pattern = {
|
|
28
|
+
name: 'test/evil-pattern',
|
|
29
|
+
blocks: [ { name: 'core/pattern', slug: 'test/evil-pattern' } ],
|
|
30
|
+
};
|
|
31
|
+
expect( () => {
|
|
32
|
+
parsePatternDependencies( deps, pattern );
|
|
33
|
+
} ).toThrow();
|
|
34
|
+
} );
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
describe( 'registerDependency', () => {
|
|
38
|
+
it( 'is silent for patterns with no circular dependencies', () => {
|
|
39
|
+
expect( () => {
|
|
40
|
+
registerDependency( deps, 'a', 'b' );
|
|
41
|
+
} ).not.toThrow();
|
|
42
|
+
} );
|
|
43
|
+
it( 'catches self-referencing patterns', () => {
|
|
44
|
+
expect( () => {
|
|
45
|
+
registerDependency( deps, 'a', 'a' );
|
|
46
|
+
} ).toThrow();
|
|
47
|
+
} );
|
|
48
|
+
it( 'catches mutually-referencing patterns', () => {
|
|
49
|
+
registerDependency( deps, 'a', 'b' );
|
|
50
|
+
expect( () => {
|
|
51
|
+
registerDependency( deps, 'b', 'a' );
|
|
52
|
+
} ).toThrow();
|
|
53
|
+
} );
|
|
54
|
+
it( 'catches longer cycles', () => {
|
|
55
|
+
registerDependency( deps, 'a', 'b' );
|
|
56
|
+
registerDependency( deps, 'b', 'c' );
|
|
57
|
+
registerDependency( deps, 'b', 'd' );
|
|
58
|
+
expect( () => {
|
|
59
|
+
registerDependency( deps, 'd', 'a' );
|
|
60
|
+
} ).toThrow();
|
|
61
|
+
} );
|
|
62
|
+
it( 'catches any pattern depending on a tainted one', () => {
|
|
63
|
+
registerDependency( deps, 'a', 'b' );
|
|
64
|
+
registerDependency( deps, 'b', 'c' );
|
|
65
|
+
registerDependency( deps, 'b', 'd' );
|
|
66
|
+
expect( () => {
|
|
67
|
+
registerDependency( deps, 'd', 'a' );
|
|
68
|
+
} ).toThrow();
|
|
69
|
+
expect( () => {
|
|
70
|
+
registerDependency( deps, 'e', 'd' );
|
|
71
|
+
} ).toThrow();
|
|
72
|
+
} );
|
|
73
|
+
} );
|
|
74
|
+
} );
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
store as blockEditorStore,
|
|
26
26
|
__experimentalUseBorderProps as useBorderProps,
|
|
27
27
|
} from '@wordpress/block-editor';
|
|
28
|
+
import { useMemo } from '@wordpress/element';
|
|
28
29
|
import { __, sprintf } from '@wordpress/i18n';
|
|
29
30
|
import { upload } from '@wordpress/icons';
|
|
30
31
|
import { store as noticesStore } from '@wordpress/notices';
|
|
@@ -64,14 +65,44 @@ export default function PostFeaturedImageEdit( {
|
|
|
64
65
|
sizeSlug,
|
|
65
66
|
rel,
|
|
66
67
|
linkTarget,
|
|
68
|
+
useFirstImageFromPost,
|
|
67
69
|
} = attributes;
|
|
68
|
-
|
|
70
|
+
|
|
71
|
+
const [ storedFeaturedImage, setFeaturedImage ] = useEntityProp(
|
|
69
72
|
'postType',
|
|
70
73
|
postTypeSlug,
|
|
71
74
|
'featured_media',
|
|
72
75
|
postId
|
|
73
76
|
);
|
|
74
77
|
|
|
78
|
+
// Fallback to post content if no featured image is set.
|
|
79
|
+
// This is needed for the "Use first image from post" option.
|
|
80
|
+
const [ postContent ] = useEntityProp(
|
|
81
|
+
'postType',
|
|
82
|
+
postTypeSlug,
|
|
83
|
+
'content',
|
|
84
|
+
postId
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const featuredImage = useMemo( () => {
|
|
88
|
+
if ( storedFeaturedImage ) {
|
|
89
|
+
return storedFeaturedImage;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if ( ! useFirstImageFromPost ) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const imageOpener =
|
|
97
|
+
/<!--\s+wp:(?:core\/)?image\s+(?<attrs>{(?:(?:[^}]+|}+(?=})|(?!}\s+\/?-->).)*)?}\s+)?-->/.exec(
|
|
98
|
+
postContent
|
|
99
|
+
);
|
|
100
|
+
const imageId =
|
|
101
|
+
imageOpener?.groups?.attrs &&
|
|
102
|
+
JSON.parse( imageOpener.groups.attrs )?.id;
|
|
103
|
+
return imageId;
|
|
104
|
+
}, [ storedFeaturedImage, useFirstImageFromPost, postContent ] );
|
|
105
|
+
|
|
75
106
|
const { media, postType, postPermalink } = useSelect(
|
|
76
107
|
( select ) => {
|
|
77
108
|
const { getMedia, getPostType, getEditedEntityRecord } =
|