@wordpress/block-library 8.12.12 → 8.12.14
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/build/footnotes/edit.js +11 -0
- package/build/footnotes/edit.js.map +1 -1
- package/build/footnotes/format.js +57 -7
- package/build/footnotes/format.js.map +1 -1
- package/build/footnotes/index.js +1 -2
- package/build/footnotes/index.js.map +1 -1
- package/build/image/image.js +2 -2
- package/build/image/image.js.map +1 -1
- package/build/pattern/edit.js +28 -4
- package/build/pattern/edit.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 +58 -9
- package/build-module/footnotes/format.js.map +1 -1
- package/build-module/footnotes/index.js +1 -2
- package/build-module/footnotes/index.js.map +1 -1
- package/build-module/image/image.js +2 -2
- package/build-module/image/image.js.map +1 -1
- package/build-module/pattern/edit.js +27 -4
- package/build-module/pattern/edit.js.map +1 -1
- package/package.json +9 -9
- 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 +74 -1
- package/src/image/image.js +2 -2
- package/src/pattern/edit.js +21 -0
- package/src/template-part/index.php +1 -1
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
|
@@ -211,4 +211,77 @@ add_filter( '_wp_post_revision_fields', 'wp_add_footnotes_to_revision' );
|
|
|
211
211
|
function wp_get_footnotes_from_revision( $revision_field, $field, $revision ) {
|
|
212
212
|
return get_metadata( 'post', $revision->ID, $field, true );
|
|
213
213
|
}
|
|
214
|
-
add_filter( '
|
|
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/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/pattern/edit.js
CHANGED
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
useBlockProps,
|
|
10
10
|
} from '@wordpress/block-editor';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
import { unlock } from '../lock-unlock';
|
|
16
|
+
|
|
12
17
|
const PatternEdit = ( { attributes, clientId } ) => {
|
|
13
18
|
const selectedPattern = useSelect(
|
|
14
19
|
( select ) =>
|
|
@@ -20,6 +25,10 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
20
25
|
|
|
21
26
|
const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } =
|
|
22
27
|
useDispatch( blockEditorStore );
|
|
28
|
+
const { setBlockEditingMode } = unlock( useDispatch( blockEditorStore ) );
|
|
29
|
+
const { getBlockRootClientId, getBlockEditingMode } = unlock(
|
|
30
|
+
useSelect( blockEditorStore )
|
|
31
|
+
);
|
|
23
32
|
|
|
24
33
|
// Run this effect when the component loads.
|
|
25
34
|
// This adds the Pattern's contents to the post.
|
|
@@ -33,13 +42,22 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
33
42
|
// because nested pattern blocks cannot be inserted if the parent block supports
|
|
34
43
|
// inner blocks but doesn't have blockSettings in the state.
|
|
35
44
|
window.queueMicrotask( () => {
|
|
45
|
+
const rootClientId = getBlockRootClientId( clientId );
|
|
36
46
|
// Clone blocks from the pattern before insertion to ensure they receive
|
|
37
47
|
// distinct client ids. See https://github.com/WordPress/gutenberg/issues/50628.
|
|
38
48
|
const clonedBlocks = selectedPattern.blocks.map( ( block ) =>
|
|
39
49
|
cloneBlock( block )
|
|
40
50
|
);
|
|
51
|
+
const rootEditingMode = getBlockEditingMode( rootClientId );
|
|
52
|
+
// Temporarily set the root block to default mode to allow replacing the pattern.
|
|
53
|
+
// This could happen when the page is disabling edits of non-content blocks.
|
|
54
|
+
__unstableMarkNextChangeAsNotPersistent();
|
|
55
|
+
setBlockEditingMode( rootClientId, 'default' );
|
|
41
56
|
__unstableMarkNextChangeAsNotPersistent();
|
|
42
57
|
replaceBlocks( clientId, clonedBlocks );
|
|
58
|
+
// Restore the root block's original mode.
|
|
59
|
+
__unstableMarkNextChangeAsNotPersistent();
|
|
60
|
+
setBlockEditingMode( rootClientId, rootEditingMode );
|
|
43
61
|
} );
|
|
44
62
|
}
|
|
45
63
|
}, [
|
|
@@ -47,6 +65,9 @@ const PatternEdit = ( { attributes, clientId } ) => {
|
|
|
47
65
|
selectedPattern?.blocks,
|
|
48
66
|
__unstableMarkNextChangeAsNotPersistent,
|
|
49
67
|
replaceBlocks,
|
|
68
|
+
getBlockEditingMode,
|
|
69
|
+
setBlockEditingMode,
|
|
70
|
+
getBlockRootClientId,
|
|
50
71
|
] );
|
|
51
72
|
|
|
52
73
|
const props = useBlockProps();
|
|
@@ -250,7 +250,7 @@ function build_template_part_block_instance_variations() {
|
|
|
250
250
|
'area' => $template_part->area,
|
|
251
251
|
),
|
|
252
252
|
'scope' => array( 'inserter' ),
|
|
253
|
-
'icon' => $icon_by_area[ $template_part->area ],
|
|
253
|
+
'icon' => isset( $icon_by_area[ $template_part->area ] ) ? $icon_by_area[ $template_part->area ] : null,
|
|
254
254
|
'example' => array(
|
|
255
255
|
'attributes' => array(
|
|
256
256
|
'slug' => $template_part->slug,
|