@wordpress/block-library 8.15.0 → 8.16.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/build/avatar/index.js +3 -0
- package/build/avatar/index.js.map +1 -1
- package/build/block/edit.js +2 -30
- package/build/block/edit.js.map +1 -1
- package/build/cover/index.js +2 -1
- package/build/cover/index.js.map +1 -1
- package/build/footnotes/edit.js +11 -0
- package/build/footnotes/edit.js.map +1 -1
- package/build/footnotes/format.js +101 -8
- package/build/footnotes/format.js.map +1 -1
- package/build/footnotes/index.js +45 -3
- package/build/footnotes/index.js.map +1 -1
- package/build/gallery/edit.js +7 -5
- package/build/gallery/edit.js.map +1 -1
- package/build/image/deprecated.js +106 -2
- package/build/image/deprecated.js.map +1 -1
- package/build/image/image.js +2 -2
- package/build/image/image.js.map +1 -1
- package/build/image/index.js +2 -1
- package/build/image/index.js.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/list-item/hooks/use-merge.js +10 -1
- package/build/list-item/hooks/use-merge.js.map +1 -1
- package/build/navigation/edit/menu-inspector-controls.js +1 -1
- package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
- package/build/navigation/edit/navigation-menu-selector.js +4 -4
- package/build/navigation/edit/navigation-menu-selector.js.map +1 -1
- package/build/navigation/view-modal.js +93 -32
- package/build/navigation/view-modal.js.map +1 -1
- package/build/navigation/view.js +63 -31
- package/build/navigation/view.js.map +1 -1
- package/build/pattern/edit.js +28 -4
- package/build/pattern/edit.js.map +1 -1
- package/build/preformatted/index.js +4 -0
- package/build/preformatted/index.js.map +1 -1
- package/build/search/view.js +166 -62
- package/build/search/view.js.map +1 -1
- package/build/social-link/icons/index.js +13 -0
- package/build/social-link/icons/index.js.map +1 -1
- package/build/social-link/icons/threads.js +25 -0
- package/build/social-link/icons/threads.js.map +1 -0
- package/build/social-link/variations.js +7 -0
- package/build/social-link/variations.js.map +1 -1
- package/build/template-part/edit/import-controls.js +1 -1
- package/build/template-part/edit/import-controls.js.map +1 -1
- package/build-module/avatar/index.js +3 -0
- package/build-module/avatar/index.js.map +1 -1
- package/build-module/block/edit.js +4 -29
- package/build-module/block/edit.js.map +1 -1
- package/build-module/cover/index.js +2 -1
- package/build-module/cover/index.js.map +1 -1
- package/build-module/footnotes/edit.js +11 -0
- package/build-module/footnotes/edit.js.map +1 -1
- package/build-module/footnotes/format.js +102 -10
- package/build-module/footnotes/format.js.map +1 -1
- package/build-module/footnotes/index.js +45 -3
- package/build-module/footnotes/index.js.map +1 -1
- package/build-module/gallery/edit.js +7 -5
- package/build-module/gallery/edit.js.map +1 -1
- package/build-module/image/deprecated.js +107 -3
- package/build-module/image/deprecated.js.map +1 -1
- package/build-module/image/image.js +2 -2
- package/build-module/image/image.js.map +1 -1
- package/build-module/image/index.js +2 -1
- package/build-module/image/index.js.map +1 -1
- package/build-module/index.js +3 -1
- package/build-module/index.js.map +1 -1
- package/build-module/list-item/hooks/use-merge.js +10 -1
- package/build-module/list-item/hooks/use-merge.js.map +1 -1
- package/build-module/navigation/edit/menu-inspector-controls.js +1 -1
- package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
- package/build-module/navigation/edit/navigation-menu-selector.js +4 -4
- package/build-module/navigation/edit/navigation-menu-selector.js.map +1 -1
- package/build-module/navigation/view-modal.js +93 -31
- package/build-module/navigation/view-modal.js.map +1 -1
- package/build-module/navigation/view.js +63 -31
- package/build-module/navigation/view.js.map +1 -1
- package/build-module/pattern/edit.js +27 -4
- package/build-module/pattern/edit.js.map +1 -1
- package/build-module/preformatted/index.js +4 -0
- package/build-module/preformatted/index.js.map +1 -1
- package/build-module/search/view.js +166 -62
- package/build-module/search/view.js.map +1 -1
- 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/icons/threads.js +15 -0
- package/build-module/social-link/icons/threads.js.map +1 -0
- package/build-module/social-link/variations.js +8 -1
- package/build-module/social-link/variations.js.map +1 -1
- package/build-module/template-part/edit/import-controls.js +2 -2
- package/build-module/template-part/edit/import-controls.js.map +1 -1
- package/build-style/preformatted/style-rtl.css +2 -1
- package/build-style/preformatted/style.css +2 -1
- package/build-style/social-links/style-rtl.css +7 -0
- package/build-style/social-links/style.css +7 -0
- package/build-style/style-rtl.css +10 -1
- package/build-style/style.css +10 -1
- package/build-style/video/style-rtl.css +1 -0
- package/build-style/video/style.css +1 -0
- package/package.json +32 -32
- package/src/audio/test/__snapshots__/edit.native.js.snap +60 -0
- package/src/avatar/block.json +3 -0
- package/src/block/edit.js +1 -39
- package/src/buttons/test/edit.native.js +4 -0
- package/src/columns/test/edit.native.js +5 -0
- package/src/comment-template/index.php +2 -0
- package/src/cover/block.json +2 -1
- package/src/cover/test/edit.native.js +8 -0
- package/src/embed/test/index.native.js +8 -0
- package/src/file/index.php +1 -1
- package/src/file/test/__snapshots__/edit.native.js.snap +61 -0
- package/src/footnotes/block.json +44 -1
- package/src/footnotes/edit.js +12 -0
- package/src/footnotes/format.js +70 -7
- package/src/footnotes/index.js +0 -1
- package/src/footnotes/index.php +207 -0
- package/src/gallery/edit.js +41 -37
- package/src/gallery/test/index.native.js +15 -3
- package/src/heading/test/index.native.js +4 -0
- package/src/image/block.json +2 -1
- package/src/image/deprecated.js +109 -3
- package/src/image/image.js +2 -2
- package/src/image/index.php +1 -3
- package/src/image/test/edit.native.js +0 -1
- package/src/index.js +5 -1
- package/src/list/test/edit.native.js +5 -0
- package/src/list-item/hooks/use-merge.js +12 -5
- package/src/missing/test/__snapshots__/edit.native.js.snap +21 -0
- package/src/navigation/edit/menu-inspector-controls.js +1 -1
- package/src/navigation/edit/navigation-menu-selector.js +8 -4
- package/src/navigation/index.php +27 -13
- package/src/navigation/view-modal.js +88 -39
- package/src/navigation/view.js +69 -36
- package/src/paragraph/test/edit.native.js +55 -35
- package/src/pattern/edit.js +21 -0
- package/src/pattern/index.php +13 -1
- package/src/post-template/index.php +2 -0
- package/src/post-title/index.php +2 -0
- package/src/preformatted/block.json +4 -0
- package/src/preformatted/style.scss +4 -1
- package/src/pullquote/test/edit.native.js +12 -4
- package/src/quote/test/edit.native.js +12 -4
- package/src/search/index.php +4 -0
- package/src/search/test/__snapshots__/edit.native.js.snap +63 -0
- package/src/search/view.js +171 -67
- package/src/social-link/icons/index.js +1 -0
- package/src/social-link/icons/threads.js +10 -0
- package/src/social-link/index.php +4 -0
- 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/template-part/edit/import-controls.js +2 -2
- package/src/template-part/index.php +6 -9
- package/src/video/style.scss +1 -0
package/src/footnotes/format.js
CHANGED
|
@@ -12,16 +12,24 @@ import { insertObject } from '@wordpress/rich-text';
|
|
|
12
12
|
import {
|
|
13
13
|
RichTextToolbarButton,
|
|
14
14
|
store as blockEditorStore,
|
|
15
|
+
privateApis,
|
|
15
16
|
} from '@wordpress/block-editor';
|
|
16
17
|
import { useSelect, useDispatch, useRegistry } from '@wordpress/data';
|
|
17
|
-
import { createBlock } from '@wordpress/blocks';
|
|
18
|
+
import { createBlock, store as blocksStore } from '@wordpress/blocks';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Internal dependencies
|
|
21
22
|
*/
|
|
22
23
|
import { name } from './block.json';
|
|
24
|
+
import { unlock } from '../lock-unlock';
|
|
25
|
+
|
|
26
|
+
const { usesContextKey } = unlock( privateApis );
|
|
23
27
|
|
|
24
28
|
export const formatName = 'core/footnote';
|
|
29
|
+
|
|
30
|
+
const POST_CONTENT_BLOCK_NAME = 'core/post-content';
|
|
31
|
+
const SYNCED_PATTERN_BLOCK_NAME = 'core/block';
|
|
32
|
+
|
|
25
33
|
export const format = {
|
|
26
34
|
title: __( 'Footnote' ),
|
|
27
35
|
tagName: 'sup',
|
|
@@ -30,17 +38,56 @@ export const format = {
|
|
|
30
38
|
'data-fn': 'data-fn',
|
|
31
39
|
},
|
|
32
40
|
contentEditable: false,
|
|
33
|
-
|
|
41
|
+
[ usesContextKey ]: [ 'postType' ],
|
|
42
|
+
edit: function Edit( {
|
|
43
|
+
value,
|
|
44
|
+
onChange,
|
|
45
|
+
isObjectActive,
|
|
46
|
+
context: { postType },
|
|
47
|
+
} ) {
|
|
34
48
|
const registry = useRegistry();
|
|
35
49
|
const {
|
|
36
50
|
getSelectedBlockClientId,
|
|
51
|
+
getBlocks,
|
|
37
52
|
getBlockRootClientId,
|
|
38
53
|
getBlockName,
|
|
39
|
-
|
|
54
|
+
getBlockParentsByBlockName,
|
|
40
55
|
} = useSelect( blockEditorStore );
|
|
56
|
+
const footnotesBlockType = useSelect( ( select ) =>
|
|
57
|
+
select( blocksStore ).getBlockType( name )
|
|
58
|
+
);
|
|
59
|
+
/*
|
|
60
|
+
* This useSelect exists because we need to use its return value
|
|
61
|
+
* outside the event callback.
|
|
62
|
+
*/
|
|
63
|
+
const isBlockWithinPattern = useSelect( ( select ) => {
|
|
64
|
+
const {
|
|
65
|
+
getBlockParentsByBlockName: _getBlockParentsByBlockName,
|
|
66
|
+
getSelectedBlockClientId: _getSelectedBlockClientId,
|
|
67
|
+
} = select( blockEditorStore );
|
|
68
|
+
const parentCoreBlocks = _getBlockParentsByBlockName(
|
|
69
|
+
_getSelectedBlockClientId(),
|
|
70
|
+
SYNCED_PATTERN_BLOCK_NAME
|
|
71
|
+
);
|
|
72
|
+
return parentCoreBlocks && parentCoreBlocks.length > 0;
|
|
73
|
+
}, [] );
|
|
74
|
+
|
|
41
75
|
const { selectionChange, insertBlock } =
|
|
42
76
|
useDispatch( blockEditorStore );
|
|
43
77
|
|
|
78
|
+
if ( ! footnotesBlockType ) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if ( postType !== 'post' && postType !== 'page' ) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Checks if the selected block lives within a pattern.
|
|
87
|
+
if ( isBlockWithinPattern ) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
44
91
|
function onClick() {
|
|
45
92
|
registry.batch( () => {
|
|
46
93
|
let id;
|
|
@@ -65,10 +112,27 @@ export const format = {
|
|
|
65
112
|
onChange( newValue );
|
|
66
113
|
}
|
|
67
114
|
|
|
115
|
+
const selectedClientId = getSelectedBlockClientId();
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* Attempts to find a common parent post content block.
|
|
119
|
+
* This allows for locating blocks within a page edited in the site editor.
|
|
120
|
+
*/
|
|
121
|
+
const parentPostContent = getBlockParentsByBlockName(
|
|
122
|
+
selectedClientId,
|
|
123
|
+
POST_CONTENT_BLOCK_NAME
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// When called with a post content block, getBlocks will return
|
|
127
|
+
// the block with controlled inner blocks included.
|
|
128
|
+
const blocks = parentPostContent.length
|
|
129
|
+
? getBlocks( parentPostContent[ 0 ] )
|
|
130
|
+
: getBlocks();
|
|
131
|
+
|
|
68
132
|
// BFS search to find the first footnote block.
|
|
69
133
|
let fnBlock = null;
|
|
70
134
|
{
|
|
71
|
-
const queue = [ ...
|
|
135
|
+
const queue = [ ...blocks ];
|
|
72
136
|
while ( queue.length ) {
|
|
73
137
|
const block = queue.shift();
|
|
74
138
|
if ( block.name === name ) {
|
|
@@ -83,12 +147,11 @@ export const format = {
|
|
|
83
147
|
// When there is no footnotes block in the post, create one and
|
|
84
148
|
// insert it at the bottom.
|
|
85
149
|
if ( ! fnBlock ) {
|
|
86
|
-
|
|
87
|
-
let rootClientId = getBlockRootClientId( clientId );
|
|
150
|
+
let rootClientId = getBlockRootClientId( selectedClientId );
|
|
88
151
|
|
|
89
152
|
while (
|
|
90
153
|
rootClientId &&
|
|
91
|
-
getBlockName( rootClientId ) !==
|
|
154
|
+
getBlockName( rootClientId ) !== POST_CONTENT_BLOCK_NAME
|
|
92
155
|
) {
|
|
93
156
|
rootClientId = getBlockRootClientId( rootClientId );
|
|
94
157
|
}
|
package/src/footnotes/index.js
CHANGED
package/src/footnotes/index.php
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Renders the `core/footnotes` block on the server.
|
|
10
10
|
*
|
|
11
|
+
* @since 6.3.0
|
|
12
|
+
*
|
|
11
13
|
* @param array $attributes Block attributes.
|
|
12
14
|
* @param string $content Block default content.
|
|
13
15
|
* @param WP_Block $block Block instance.
|
|
@@ -57,6 +59,8 @@ function render_block_core_footnotes( $attributes, $content, $block ) {
|
|
|
57
59
|
|
|
58
60
|
/**
|
|
59
61
|
* Registers the `core/footnotes` block on the server.
|
|
62
|
+
*
|
|
63
|
+
* @since 6.3.0
|
|
60
64
|
*/
|
|
61
65
|
function register_block_core_footnotes() {
|
|
62
66
|
foreach ( array( 'post', 'page' ) as $post_type ) {
|
|
@@ -78,3 +82,206 @@ function register_block_core_footnotes() {
|
|
|
78
82
|
);
|
|
79
83
|
}
|
|
80
84
|
add_action( 'init', 'register_block_core_footnotes' );
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Saves the footnotes meta value to the revision.
|
|
88
|
+
*
|
|
89
|
+
* @since 6.3.0
|
|
90
|
+
*
|
|
91
|
+
* @param int $revision_id The revision ID.
|
|
92
|
+
*/
|
|
93
|
+
function wp_save_footnotes_meta( $revision_id ) {
|
|
94
|
+
$post_id = wp_is_post_revision( $revision_id );
|
|
95
|
+
|
|
96
|
+
if ( $post_id ) {
|
|
97
|
+
$footnotes = get_post_meta( $post_id, 'footnotes', true );
|
|
98
|
+
|
|
99
|
+
if ( $footnotes ) {
|
|
100
|
+
// Can't use update_post_meta() because it doesn't allow revisions.
|
|
101
|
+
update_metadata( 'post', $revision_id, 'footnotes', $footnotes );
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
add_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' );
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Keeps track of the revision ID for "rest_after_insert_{$post_type}".
|
|
109
|
+
*
|
|
110
|
+
* @since 6.3.0
|
|
111
|
+
*
|
|
112
|
+
* @global int $wp_temporary_footnote_revision_id The footnote revision ID.
|
|
113
|
+
*
|
|
114
|
+
* @param int $revision_id The revision ID.
|
|
115
|
+
*/
|
|
116
|
+
function wp_keep_footnotes_revision_id( $revision_id ) {
|
|
117
|
+
global $wp_temporary_footnote_revision_id;
|
|
118
|
+
$wp_temporary_footnote_revision_id = $revision_id;
|
|
119
|
+
}
|
|
120
|
+
add_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' );
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* This is a specific fix for the REST API. The REST API doesn't update
|
|
124
|
+
* the post and post meta in one go (through `meta_input`). While it
|
|
125
|
+
* does fix the `wp_after_insert_post` hook to be called correctly after
|
|
126
|
+
* updating meta, it does NOT fix hooks such as post_updated and
|
|
127
|
+
* save_post, which are normally also fired after post meta is updated
|
|
128
|
+
* in `wp_insert_post()`. Unfortunately, `wp_save_post_revision` is
|
|
129
|
+
* added to the `post_updated` action, which means the meta is not
|
|
130
|
+
* available at the time, so we have to add it afterwards through the
|
|
131
|
+
* `"rest_after_insert_{$post_type}"` action.
|
|
132
|
+
*
|
|
133
|
+
* @since 6.3.0
|
|
134
|
+
*
|
|
135
|
+
* @global int $wp_temporary_footnote_revision_id The footnote revision ID.
|
|
136
|
+
*
|
|
137
|
+
* @param WP_Post $post The post object.
|
|
138
|
+
*/
|
|
139
|
+
function wp_add_footnotes_revisions_to_post_meta( $post ) {
|
|
140
|
+
global $wp_temporary_footnote_revision_id;
|
|
141
|
+
|
|
142
|
+
if ( $wp_temporary_footnote_revision_id ) {
|
|
143
|
+
$revision = get_post( $wp_temporary_footnote_revision_id );
|
|
144
|
+
|
|
145
|
+
if ( ! $revision ) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
$post_id = $revision->post_parent;
|
|
150
|
+
|
|
151
|
+
// Just making sure we're updating the right revision.
|
|
152
|
+
if ( $post->ID === $post_id ) {
|
|
153
|
+
$footnotes = get_post_meta( $post_id, 'footnotes', true );
|
|
154
|
+
|
|
155
|
+
if ( $footnotes ) {
|
|
156
|
+
// Can't use update_post_meta() because it doesn't allow revisions.
|
|
157
|
+
update_metadata( 'post', $wp_temporary_footnote_revision_id, 'footnotes', $footnotes );
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
foreach ( array( 'post', 'page' ) as $post_type ) {
|
|
164
|
+
add_action( "rest_after_insert_{$post_type}", 'wp_add_footnotes_revisions_to_post_meta' );
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Restores the footnotes meta value from the revision.
|
|
169
|
+
*
|
|
170
|
+
* @since 6.3.0
|
|
171
|
+
*
|
|
172
|
+
* @param int $post_id The post ID.
|
|
173
|
+
* @param int $revision_id The revision ID.
|
|
174
|
+
*/
|
|
175
|
+
function wp_restore_footnotes_from_revision( $post_id, $revision_id ) {
|
|
176
|
+
$footnotes = get_post_meta( $revision_id, 'footnotes', true );
|
|
177
|
+
|
|
178
|
+
if ( $footnotes ) {
|
|
179
|
+
update_post_meta( $post_id, 'footnotes', $footnotes );
|
|
180
|
+
} else {
|
|
181
|
+
delete_post_meta( $post_id, 'footnotes' );
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
add_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision', 10, 2 );
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Adds the footnotes field to the revision.
|
|
188
|
+
*
|
|
189
|
+
* @since 6.3.0
|
|
190
|
+
*
|
|
191
|
+
* @param array $fields The revision fields.
|
|
192
|
+
* @return array The revision fields.
|
|
193
|
+
*/
|
|
194
|
+
function wp_add_footnotes_to_revision( $fields ) {
|
|
195
|
+
$fields['footnotes'] = __( 'Footnotes' );
|
|
196
|
+
return $fields;
|
|
197
|
+
}
|
|
198
|
+
add_filter( '_wp_post_revision_fields', 'wp_add_footnotes_to_revision' );
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Gets the footnotes field from the revision.
|
|
202
|
+
*
|
|
203
|
+
* @since 6.3.0
|
|
204
|
+
*
|
|
205
|
+
* @param string $revision_field The field value, but $revision->$field
|
|
206
|
+
* (footnotes) does not exist.
|
|
207
|
+
* @param string $field The field name, in this case "footnotes".
|
|
208
|
+
* @param object $revision The revision object to compare against.
|
|
209
|
+
* @return string The field value.
|
|
210
|
+
*/
|
|
211
|
+
function wp_get_footnotes_from_revision( $revision_field, $field, $revision ) {
|
|
212
|
+
return get_metadata( 'post', $revision->ID, $field, true );
|
|
213
|
+
}
|
|
214
|
+
add_filter( '_wp_post_revision_field_footnotes', 'wp_get_footnotes_from_revision', 10, 3 );
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* The REST API autosave endpoint doesn't save meta, so we can use the
|
|
218
|
+
* `wp_creating_autosave` when it updates an exiting autosave, and
|
|
219
|
+
* `_wp_put_post_revision` when it creates a new autosave.
|
|
220
|
+
*
|
|
221
|
+
* @since 6.3.0
|
|
222
|
+
*
|
|
223
|
+
* @param int|array $autosave The autosave ID or array.
|
|
224
|
+
*/
|
|
225
|
+
function _wp_rest_api_autosave_meta( $autosave ) {
|
|
226
|
+
// Ensure it's a REST API request.
|
|
227
|
+
if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
$body = rest_get_server()->get_raw_data();
|
|
232
|
+
$body = json_decode( $body, true );
|
|
233
|
+
|
|
234
|
+
if ( ! isset( $body['meta']['footnotes'] ) ) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// `wp_creating_autosave` passes the array,
|
|
239
|
+
// `_wp_put_post_revision` passes the ID.
|
|
240
|
+
$id = is_int( $autosave ) ? $autosave : $autosave['ID'];
|
|
241
|
+
|
|
242
|
+
if ( ! $id ) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
update_post_meta( $id, 'footnotes', $body['meta']['footnotes'] );
|
|
247
|
+
}
|
|
248
|
+
// See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L391C1-L391C1.
|
|
249
|
+
add_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' );
|
|
250
|
+
// See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L398.
|
|
251
|
+
// Then https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/revision.php#L367.
|
|
252
|
+
add_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' );
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* This is a workaround for the autosave endpoint returning early if the
|
|
256
|
+
* revision field are equal. The problem is that "footnotes" is not real
|
|
257
|
+
* revision post field, so there's nothing to compare against.
|
|
258
|
+
*
|
|
259
|
+
* This trick sets the "footnotes" field (value doesn't matter), which will
|
|
260
|
+
* cause the autosave endpoint to always update the latest revision. That should
|
|
261
|
+
* be fine, it should be ok to update the revision even if nothing changed. Of
|
|
262
|
+
* course, this is temporary fix.
|
|
263
|
+
*
|
|
264
|
+
* @since 6.3.0
|
|
265
|
+
*
|
|
266
|
+
* @param WP_Post $prepared_post The prepared post object.
|
|
267
|
+
* @param WP_REST_Request $request The request object.
|
|
268
|
+
*
|
|
269
|
+
* See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L365-L384.
|
|
270
|
+
* See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L219.
|
|
271
|
+
*/
|
|
272
|
+
function _wp_rest_api_force_autosave_difference( $prepared_post, $request ) {
|
|
273
|
+
// We only want to be altering POST requests.
|
|
274
|
+
if ( $request->get_method() !== 'POST' ) {
|
|
275
|
+
return $prepared_post;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Only alter requests for the '/autosaves' route.
|
|
279
|
+
if ( substr( $request->get_route(), -strlen( '/autosaves' ) ) !== '/autosaves' ) {
|
|
280
|
+
return $prepared_post;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
$prepared_post->footnotes = '[]';
|
|
284
|
+
return $prepared_post;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
add_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference', 10, 2 );
|
package/src/gallery/edit.js
CHANGED
|
@@ -91,6 +91,7 @@ function GalleryEdit( props ) {
|
|
|
91
91
|
isSelected,
|
|
92
92
|
insertBlocksAfter,
|
|
93
93
|
isContentLocked,
|
|
94
|
+
onFocus,
|
|
94
95
|
} = props;
|
|
95
96
|
|
|
96
97
|
const { columns, imageCrop, linkTarget, linkTo, sizeSlug, caption } =
|
|
@@ -498,6 +499,7 @@ function GalleryEdit( props ) {
|
|
|
498
499
|
value: hasImageIds ? images : {},
|
|
499
500
|
autoOpenMediaUpload:
|
|
500
501
|
! hasImages && isSelected && wasBlockJustInserted,
|
|
502
|
+
onFocus,
|
|
501
503
|
},
|
|
502
504
|
} );
|
|
503
505
|
const mediaPlaceholder = (
|
|
@@ -616,44 +618,46 @@ function GalleryEdit( props ) {
|
|
|
616
618
|
) }
|
|
617
619
|
</PanelBody>
|
|
618
620
|
</InspectorControls>
|
|
619
|
-
<BlockControls group="block">
|
|
620
|
-
{ ! isContentLocked && (
|
|
621
|
-
<ToolbarButton
|
|
622
|
-
onClick={ () => {
|
|
623
|
-
setShowCaption( ! showCaption );
|
|
624
|
-
if ( showCaption && caption ) {
|
|
625
|
-
setAttributes( { caption: undefined } );
|
|
626
|
-
}
|
|
627
|
-
} }
|
|
628
|
-
icon={ captionIcon }
|
|
629
|
-
isPressed={ showCaption }
|
|
630
|
-
label={
|
|
631
|
-
showCaption
|
|
632
|
-
? __( 'Remove caption' )
|
|
633
|
-
: __( 'Add caption' )
|
|
634
|
-
}
|
|
635
|
-
/>
|
|
636
|
-
) }
|
|
637
|
-
</BlockControls>
|
|
638
|
-
<BlockControls group="other">
|
|
639
|
-
<MediaReplaceFlow
|
|
640
|
-
allowedTypes={ ALLOWED_MEDIA_TYPES }
|
|
641
|
-
accept="image/*"
|
|
642
|
-
handleUpload={ false }
|
|
643
|
-
onSelect={ updateImages }
|
|
644
|
-
name={ __( 'Add' ) }
|
|
645
|
-
multiple={ true }
|
|
646
|
-
mediaIds={ images
|
|
647
|
-
.filter( ( image ) => image.id )
|
|
648
|
-
.map( ( image ) => image.id ) }
|
|
649
|
-
addToGallery={ hasImageIds }
|
|
650
|
-
/>
|
|
651
|
-
</BlockControls>
|
|
652
621
|
{ Platform.isWeb && (
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
622
|
+
<>
|
|
623
|
+
<BlockControls group="block">
|
|
624
|
+
{ ! isContentLocked && (
|
|
625
|
+
<ToolbarButton
|
|
626
|
+
onClick={ () => {
|
|
627
|
+
setShowCaption( ! showCaption );
|
|
628
|
+
if ( showCaption && caption ) {
|
|
629
|
+
setAttributes( { caption: undefined } );
|
|
630
|
+
}
|
|
631
|
+
} }
|
|
632
|
+
icon={ captionIcon }
|
|
633
|
+
isPressed={ showCaption }
|
|
634
|
+
label={
|
|
635
|
+
showCaption
|
|
636
|
+
? __( 'Remove caption' )
|
|
637
|
+
: __( 'Add caption' )
|
|
638
|
+
}
|
|
639
|
+
/>
|
|
640
|
+
) }
|
|
641
|
+
</BlockControls>
|
|
642
|
+
<BlockControls group="other">
|
|
643
|
+
<MediaReplaceFlow
|
|
644
|
+
allowedTypes={ ALLOWED_MEDIA_TYPES }
|
|
645
|
+
accept="image/*"
|
|
646
|
+
handleUpload={ false }
|
|
647
|
+
onSelect={ updateImages }
|
|
648
|
+
name={ __( 'Add' ) }
|
|
649
|
+
multiple={ true }
|
|
650
|
+
mediaIds={ images
|
|
651
|
+
.filter( ( image ) => image.id )
|
|
652
|
+
.map( ( image ) => image.id ) }
|
|
653
|
+
addToGallery={ hasImageIds }
|
|
654
|
+
/>
|
|
655
|
+
</BlockControls>
|
|
656
|
+
<GapStyles
|
|
657
|
+
blockGap={ attributes.style?.spacing?.blockGap }
|
|
658
|
+
clientId={ clientId }
|
|
659
|
+
/>
|
|
660
|
+
</>
|
|
657
661
|
) }
|
|
658
662
|
<Gallery
|
|
659
663
|
{ ...props }
|
|
@@ -159,9 +159,7 @@ describe( 'Gallery block', () => {
|
|
|
159
159
|
/* eslint-enable jest/no-conditional-expect */
|
|
160
160
|
} );
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
// is addressed.
|
|
164
|
-
it.skip( 'block remains selected after dismissing the media options picker', async () => {
|
|
162
|
+
it( 'block remains selected after dismissing the media options picker', async () => {
|
|
165
163
|
// Initialize with an empty gallery
|
|
166
164
|
const { getByLabelText, getByText, getByTestId } =
|
|
167
165
|
await initializeEditor( {
|
|
@@ -622,6 +620,20 @@ describe( 'Gallery block', () => {
|
|
|
622
620
|
expect( getEditorHtml() ).toMatchSnapshot();
|
|
623
621
|
} );
|
|
624
622
|
|
|
623
|
+
it( 'does not display MediaReplaceFlow component within the block toolbar', async () => {
|
|
624
|
+
const screen = await initializeWithGalleryBlock( {
|
|
625
|
+
numberOfItems: 3,
|
|
626
|
+
media,
|
|
627
|
+
} );
|
|
628
|
+
const { queryByTestId } = screen;
|
|
629
|
+
|
|
630
|
+
fireEvent.press( getBlock( screen, 'Gallery' ) );
|
|
631
|
+
|
|
632
|
+
// Expect the native MediaReplaceFlow component to not be present in the block toolbar
|
|
633
|
+
const mediaReplaceFlow = queryByTestId( 'media-replace-flow' );
|
|
634
|
+
expect( mediaReplaceFlow ).toBeNull();
|
|
635
|
+
} );
|
|
636
|
+
|
|
625
637
|
// Test cases related to TC013 - Settings - Columns
|
|
626
638
|
// Reference: https://github.com/wordpress-mobile/test-cases/blob/trunk/test-cases/gutenberg/gallery.md#tc013
|
|
627
639
|
describe( 'Columns setting', () => {
|
|
@@ -71,6 +71,10 @@ describe( 'Heading block', () => {
|
|
|
71
71
|
|
|
72
72
|
// Tap one color
|
|
73
73
|
fireEvent.press( screen.getByLabelText( 'Pale pink' ) );
|
|
74
|
+
// TODO(jest-console): Fix the warning and remove the expect below.
|
|
75
|
+
expect( console ).toHaveWarnedWith(
|
|
76
|
+
`Non-serializable values were found in the navigation state. Check:\n\nColor > params.onColorChange (Function)\n\nThis can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details.`
|
|
77
|
+
);
|
|
74
78
|
|
|
75
79
|
// Dismiss the Block Settings modal.
|
|
76
80
|
fireEvent( blockSettingsModal, 'backdropPress' );
|
package/src/image/block.json
CHANGED
package/src/image/deprecated.js
CHANGED
|
@@ -9,7 +9,8 @@ import classnames from 'classnames';
|
|
|
9
9
|
import {
|
|
10
10
|
RichText,
|
|
11
11
|
useBlockProps,
|
|
12
|
-
__experimentalGetElementClassName
|
|
12
|
+
__experimentalGetElementClassName,
|
|
13
|
+
__experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
|
|
13
14
|
} from '@wordpress/block-editor';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -545,11 +546,114 @@ const v5 = {
|
|
|
545
546
|
|
|
546
547
|
/**
|
|
547
548
|
* Deprecation for adding width and height as style rules on the inner img.
|
|
548
|
-
* It also updates the widht and height attributes to be strings instead of numbers.
|
|
549
549
|
*
|
|
550
550
|
* @see https://github.com/WordPress/gutenberg/pull/31366
|
|
551
551
|
*/
|
|
552
552
|
const v6 = {
|
|
553
|
+
attributes: {
|
|
554
|
+
align: {
|
|
555
|
+
type: 'string',
|
|
556
|
+
},
|
|
557
|
+
url: {
|
|
558
|
+
type: 'string',
|
|
559
|
+
source: 'attribute',
|
|
560
|
+
selector: 'img',
|
|
561
|
+
attribute: 'src',
|
|
562
|
+
__experimentalRole: 'content',
|
|
563
|
+
},
|
|
564
|
+
alt: {
|
|
565
|
+
type: 'string',
|
|
566
|
+
source: 'attribute',
|
|
567
|
+
selector: 'img',
|
|
568
|
+
attribute: 'alt',
|
|
569
|
+
default: '',
|
|
570
|
+
__experimentalRole: 'content',
|
|
571
|
+
},
|
|
572
|
+
caption: {
|
|
573
|
+
type: 'string',
|
|
574
|
+
source: 'html',
|
|
575
|
+
selector: 'figcaption',
|
|
576
|
+
__experimentalRole: 'content',
|
|
577
|
+
},
|
|
578
|
+
title: {
|
|
579
|
+
type: 'string',
|
|
580
|
+
source: 'attribute',
|
|
581
|
+
selector: 'img',
|
|
582
|
+
attribute: 'title',
|
|
583
|
+
__experimentalRole: 'content',
|
|
584
|
+
},
|
|
585
|
+
href: {
|
|
586
|
+
type: 'string',
|
|
587
|
+
source: 'attribute',
|
|
588
|
+
selector: 'figure > a',
|
|
589
|
+
attribute: 'href',
|
|
590
|
+
__experimentalRole: 'content',
|
|
591
|
+
},
|
|
592
|
+
rel: {
|
|
593
|
+
type: 'string',
|
|
594
|
+
source: 'attribute',
|
|
595
|
+
selector: 'figure > a',
|
|
596
|
+
attribute: 'rel',
|
|
597
|
+
},
|
|
598
|
+
linkClass: {
|
|
599
|
+
type: 'string',
|
|
600
|
+
source: 'attribute',
|
|
601
|
+
selector: 'figure > a',
|
|
602
|
+
attribute: 'class',
|
|
603
|
+
},
|
|
604
|
+
id: {
|
|
605
|
+
type: 'number',
|
|
606
|
+
__experimentalRole: 'content',
|
|
607
|
+
},
|
|
608
|
+
width: {
|
|
609
|
+
type: 'number',
|
|
610
|
+
},
|
|
611
|
+
height: {
|
|
612
|
+
type: 'number',
|
|
613
|
+
},
|
|
614
|
+
aspectRatio: {
|
|
615
|
+
type: 'string',
|
|
616
|
+
},
|
|
617
|
+
scale: {
|
|
618
|
+
type: 'string',
|
|
619
|
+
},
|
|
620
|
+
sizeSlug: {
|
|
621
|
+
type: 'string',
|
|
622
|
+
},
|
|
623
|
+
linkDestination: {
|
|
624
|
+
type: 'string',
|
|
625
|
+
},
|
|
626
|
+
linkTarget: {
|
|
627
|
+
type: 'string',
|
|
628
|
+
source: 'attribute',
|
|
629
|
+
selector: 'figure > a',
|
|
630
|
+
attribute: 'target',
|
|
631
|
+
},
|
|
632
|
+
},
|
|
633
|
+
supports: {
|
|
634
|
+
anchor: true,
|
|
635
|
+
behaviors: {
|
|
636
|
+
lightbox: true,
|
|
637
|
+
},
|
|
638
|
+
color: {
|
|
639
|
+
text: false,
|
|
640
|
+
background: false,
|
|
641
|
+
},
|
|
642
|
+
filter: {
|
|
643
|
+
duotone: true,
|
|
644
|
+
},
|
|
645
|
+
__experimentalBorder: {
|
|
646
|
+
color: true,
|
|
647
|
+
radius: true,
|
|
648
|
+
width: true,
|
|
649
|
+
__experimentalSkipSerialization: true,
|
|
650
|
+
__experimentalDefaultControls: {
|
|
651
|
+
color: true,
|
|
652
|
+
radius: true,
|
|
653
|
+
width: true,
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
},
|
|
553
657
|
save( { attributes } ) {
|
|
554
658
|
const {
|
|
555
659
|
url,
|
|
@@ -618,7 +722,9 @@ const v6 = {
|
|
|
618
722
|
) }
|
|
619
723
|
{ ! RichText.isEmpty( caption ) && (
|
|
620
724
|
<RichText.Content
|
|
621
|
-
className={
|
|
725
|
+
className={ __experimentalGetElementClassName(
|
|
726
|
+
'caption'
|
|
727
|
+
) }
|
|
622
728
|
tagName="figcaption"
|
|
623
729
|
value={ caption }
|
|
624
730
|
/>
|
package/src/image/image.js
CHANGED
|
@@ -566,9 +566,9 @@ export default function Image( {
|
|
|
566
566
|
className={ borderProps.className }
|
|
567
567
|
style={ {
|
|
568
568
|
width:
|
|
569
|
-
( width && height ) || aspectRatio ? '100%' :
|
|
569
|
+
( width && height ) || aspectRatio ? '100%' : undefined,
|
|
570
570
|
height:
|
|
571
|
-
( width && height ) || aspectRatio ? '100%' :
|
|
571
|
+
( width && height ) || aspectRatio ? '100%' : undefined,
|
|
572
572
|
objectFit: scale,
|
|
573
573
|
...borderProps.style,
|
|
574
574
|
} }
|
package/src/image/index.php
CHANGED
|
@@ -32,7 +32,6 @@ function render_block_core_image( $attributes, $content, $block ) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
$should_load_view_script = false;
|
|
35
|
-
$experiments = get_option( 'gutenberg-experiments' );
|
|
36
35
|
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
|
|
37
36
|
// Get the lightbox setting from the block attributes.
|
|
38
37
|
if ( isset( $attributes['behaviors']['lightbox'] ) ) {
|
|
@@ -50,8 +49,7 @@ function render_block_core_image( $attributes, $content, $block ) {
|
|
|
50
49
|
// If the lightbox is enabled, the image is not linked, and the Interactivity API is enabled, load the view script.
|
|
51
50
|
if ( isset( $lightbox_settings['enabled'] ) &&
|
|
52
51
|
true === $lightbox_settings['enabled'] &&
|
|
53
|
-
'none' === $link_destination
|
|
54
|
-
! empty( $experiments['gutenberg-interactivity-api-core-blocks'] )
|
|
52
|
+
'none' === $link_destination
|
|
55
53
|
) {
|
|
56
54
|
$should_load_view_script = true;
|
|
57
55
|
}
|
|
@@ -26,7 +26,6 @@ import { select, dispatch } from '@wordpress/data';
|
|
|
26
26
|
import { store as editorStore } from '@wordpress/editor';
|
|
27
27
|
import { store as coreStore } from '@wordpress/core-data';
|
|
28
28
|
import apiFetch from '@wordpress/api-fetch';
|
|
29
|
-
import '@wordpress/jest-console';
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Internal dependencies
|