@wordpress/editor 13.13.0 → 13.15.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/entities-saved-states/entity-record-item.js +3 -37
  3. package/build/components/entities-saved-states/entity-record-item.js.map +1 -1
  4. package/build/components/entities-saved-states/entity-type-list.js +2 -4
  5. package/build/components/entities-saved-states/entity-type-list.js.map +1 -1
  6. package/build/components/entities-saved-states/index.js +0 -1
  7. package/build/components/entities-saved-states/index.js.map +1 -1
  8. package/build/components/global-keyboard-shortcuts/{save-shortcut.js → index.js} +13 -25
  9. package/build/components/global-keyboard-shortcuts/index.js.map +1 -0
  10. package/build/components/index.js +32 -19
  11. package/build/components/index.js.map +1 -1
  12. package/build/components/media-categories/index.js +1 -22
  13. package/build/components/media-categories/index.js.map +1 -1
  14. package/build/components/post-preview-button/index.js +62 -157
  15. package/build/components/post-preview-button/index.js.map +1 -1
  16. package/build/components/post-publish-button/index.js +4 -9
  17. package/build/components/post-publish-button/index.js.map +1 -1
  18. package/build/components/post-publish-button/label.js +2 -4
  19. package/build/components/post-publish-button/label.js.map +1 -1
  20. package/build/components/post-publish-panel/index.js +3 -4
  21. package/build/components/post-publish-panel/index.js.map +1 -1
  22. package/build/components/post-saved-state/index.js +2 -5
  23. package/build/components/post-saved-state/index.js.map +1 -1
  24. package/build/components/post-schedule/label.js +4 -4
  25. package/build/components/post-schedule/label.js.map +1 -1
  26. package/build/components/post-switch-to-draft-button/index.js +3 -5
  27. package/build/components/post-switch-to-draft-button/index.js.map +1 -1
  28. package/build/components/post-sync-status/index.js +82 -22
  29. package/build/components/post-sync-status/index.js.map +1 -1
  30. package/build/components/post-text-editor/index.js +51 -58
  31. package/build/components/post-text-editor/index.js.map +1 -1
  32. package/build/components/provider/use-block-editor-settings.js +1 -1
  33. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  34. package/build/store/actions.js +37 -3
  35. package/build/store/actions.js.map +1 -1
  36. package/build/store/selectors.js +53 -61
  37. package/build/store/selectors.js.map +1 -1
  38. package/build-module/components/entities-saved-states/entity-record-item.js +6 -40
  39. package/build-module/components/entities-saved-states/entity-record-item.js.map +1 -1
  40. package/build-module/components/entities-saved-states/entity-type-list.js +2 -4
  41. package/build-module/components/entities-saved-states/entity-type-list.js.map +1 -1
  42. package/build-module/components/entities-saved-states/index.js +0 -1
  43. package/build-module/components/entities-saved-states/index.js.map +1 -1
  44. package/build-module/components/global-keyboard-shortcuts/{save-shortcut.js → index.js} +12 -23
  45. package/build-module/components/global-keyboard-shortcuts/index.js.map +1 -0
  46. package/build-module/components/index.js +9 -4
  47. package/build-module/components/index.js.map +1 -1
  48. package/build-module/components/media-categories/index.js +1 -22
  49. package/build-module/components/media-categories/index.js.map +1 -1
  50. package/build-module/components/post-preview-button/index.js +63 -149
  51. package/build-module/components/post-preview-button/index.js.map +1 -1
  52. package/build-module/components/post-publish-button/index.js +4 -9
  53. package/build-module/components/post-publish-button/index.js.map +1 -1
  54. package/build-module/components/post-publish-button/label.js +2 -4
  55. package/build-module/components/post-publish-button/label.js.map +1 -1
  56. package/build-module/components/post-publish-panel/index.js +3 -4
  57. package/build-module/components/post-publish-panel/index.js.map +1 -1
  58. package/build-module/components/post-saved-state/index.js +2 -5
  59. package/build-module/components/post-saved-state/index.js.map +1 -1
  60. package/build-module/components/post-schedule/label.js +4 -4
  61. package/build-module/components/post-schedule/label.js.map +1 -1
  62. package/build-module/components/post-switch-to-draft-button/index.js +5 -7
  63. package/build-module/components/post-switch-to-draft-button/index.js.map +1 -1
  64. package/build-module/components/post-sync-status/index.js +81 -24
  65. package/build-module/components/post-sync-status/index.js.map +1 -1
  66. package/build-module/components/post-text-editor/index.js +48 -56
  67. package/build-module/components/post-text-editor/index.js.map +1 -1
  68. package/build-module/components/provider/use-block-editor-settings.js +1 -1
  69. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  70. package/build-module/store/actions.js +31 -1
  71. package/build-module/store/actions.js.map +1 -1
  72. package/build-module/store/selectors.js +46 -55
  73. package/build-module/store/selectors.js.map +1 -1
  74. package/build-style/style-rtl.css +4 -22
  75. package/build-style/style.css +4 -22
  76. package/package.json +30 -30
  77. package/src/components/entities-saved-states/entity-record-item.js +3 -61
  78. package/src/components/entities-saved-states/entity-type-list.js +0 -2
  79. package/src/components/entities-saved-states/index.js +0 -1
  80. package/src/components/entities-saved-states/style.scss +0 -15
  81. package/src/components/global-keyboard-shortcuts/index.js +49 -0
  82. package/src/components/index.js +12 -3
  83. package/src/components/media-categories/index.js +1 -21
  84. package/src/components/post-preview-button/index.js +73 -156
  85. package/src/components/post-preview-button/test/index.js +94 -158
  86. package/src/components/post-publish-button/index.js +2 -7
  87. package/src/components/post-publish-button/label.js +2 -2
  88. package/src/components/post-publish-button/test/index.js +0 -10
  89. package/src/components/post-publish-panel/index.js +3 -4
  90. package/src/components/post-saved-state/index.js +2 -5
  91. package/src/components/post-schedule/label.js +4 -4
  92. package/src/components/post-switch-to-draft-button/index.js +3 -4
  93. package/src/components/post-sync-status/index.js +100 -27
  94. package/src/components/post-sync-status/style.scss +2 -2
  95. package/src/components/post-text-editor/index.js +34 -57
  96. package/src/components/post-title/style.native.scss +5 -5
  97. package/src/components/post-trash/style.scss +2 -2
  98. package/src/components/provider/use-block-editor-settings.js +1 -0
  99. package/src/store/actions.js +34 -2
  100. package/src/store/selectors.js +45 -41
  101. package/src/store/test/selectors.js +36 -25
  102. package/build/components/global-keyboard-shortcuts/save-shortcut.js.map +0 -1
  103. package/build/components/global-keyboard-shortcuts/text-editor-shortcuts.js +0 -22
  104. package/build/components/global-keyboard-shortcuts/text-editor-shortcuts.js.map +0 -1
  105. package/build/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +0 -45
  106. package/build/components/global-keyboard-shortcuts/visual-editor-shortcuts.js.map +0 -1
  107. package/build-module/components/global-keyboard-shortcuts/save-shortcut.js.map +0 -1
  108. package/build-module/components/global-keyboard-shortcuts/text-editor-shortcuts.js +0 -12
  109. package/build-module/components/global-keyboard-shortcuts/text-editor-shortcuts.js.map +0 -1
  110. package/build-module/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +0 -32
  111. package/build-module/components/global-keyboard-shortcuts/visual-editor-shortcuts.js.map +0 -1
  112. package/src/components/global-keyboard-shortcuts/save-shortcut.js +0 -55
  113. package/src/components/global-keyboard-shortcuts/text-editor-shortcuts.js +0 -8
  114. package/src/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +0 -29
  115. package/src/components/post-text-editor/test/index.js +0 -156
@@ -3,53 +3,126 @@
3
3
  */
4
4
  import { useSelect, useDispatch } from '@wordpress/data';
5
5
  import { __ } from '@wordpress/i18n';
6
- import { ToggleControl, PanelRow } from '@wordpress/components';
6
+ import {
7
+ PanelRow,
8
+ Modal,
9
+ Button,
10
+ __experimentalHStack as HStack,
11
+ __experimentalVStack as VStack,
12
+ ToggleControl,
13
+ } from '@wordpress/components';
14
+ import { useEffect, useState } from '@wordpress/element';
15
+ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
7
16
 
8
17
  /**
9
18
  * Internal dependencies
10
19
  */
11
20
  import { store as editorStore } from '../../store';
21
+ import { unlock } from '../../lock-unlock';
12
22
 
13
23
  export default function PostSyncStatus() {
14
- const { editPost } = useDispatch( editorStore );
15
- const { meta, postType } = useSelect( ( select ) => {
24
+ const { syncStatus, postType, meta } = useSelect( ( select ) => {
16
25
  const { getEditedPostAttribute } = select( editorStore );
17
26
  return {
27
+ syncStatus: getEditedPostAttribute( 'wp_pattern_sync_status' ),
18
28
  meta: getEditedPostAttribute( 'meta' ),
19
29
  postType: getEditedPostAttribute( 'type' ),
20
30
  };
21
- }, [] );
31
+ } );
32
+
22
33
  if ( postType !== 'wp_block' ) {
23
34
  return null;
24
35
  }
25
- const onUpdateSync = ( syncStatus ) =>
36
+ // When the post is first created, the top level wp_pattern_sync_status is not set so get meta value instead.
37
+ const currentSyncStatus =
38
+ meta?.wp_pattern_sync_status === 'unsynced' ? 'unsynced' : syncStatus;
39
+
40
+ return (
41
+ <PanelRow className="edit-post-sync-status">
42
+ <span>{ __( 'Sync status' ) }</span>
43
+ <div>
44
+ { currentSyncStatus === 'unsynced'
45
+ ? __( 'Not synced' )
46
+ : __( 'Fully synced' ) }
47
+ </div>
48
+ </PanelRow>
49
+ );
50
+ }
51
+
52
+ export function PostSyncStatusModal() {
53
+ const { editPost } = useDispatch( editorStore );
54
+ const [ isModalOpen, setIsModalOpen ] = useState( false );
55
+ const [ syncType, setSyncType ] = useState( undefined );
56
+
57
+ const { postType, isNewPost } = useSelect( ( select ) => {
58
+ const { getEditedPostAttribute, isCleanNewPost } =
59
+ select( editorStore );
60
+ return {
61
+ postType: getEditedPostAttribute( 'type' ),
62
+ isNewPost: isCleanNewPost(),
63
+ };
64
+ }, [] );
65
+
66
+ useEffect( () => {
67
+ if ( isNewPost && postType === 'wp_block' ) {
68
+ setIsModalOpen( true );
69
+ }
70
+ // We only want the modal to open when the page is first loaded.
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, [] );
73
+
74
+ const setSyncStatus = () => {
26
75
  editPost( {
27
76
  meta: {
28
- ...meta,
29
- wp_block:
30
- syncStatus === 'unsynced'
31
- ? { sync_status: syncStatus }
32
- : null,
77
+ wp_pattern_sync_status: syncType,
33
78
  },
34
79
  } );
35
- const syncStatus = meta?.wp_block?.sync_status;
36
- const isFullySynced = ! syncStatus;
80
+ };
37
81
 
82
+ if ( postType !== 'wp_block' || ! isNewPost ) {
83
+ return null;
84
+ }
85
+ const { ReusableBlocksRenameHint } = unlock( blockEditorPrivateApis );
38
86
  return (
39
- <PanelRow className="edit-post-sync-status">
40
- <span>{ __( 'Syncing' ) }</span>
41
- <ToggleControl
42
- __nextHasNoMarginBottom
43
- label={
44
- isFullySynced ? __( 'Fully synced' ) : __( 'Not synced' )
45
- }
46
- checked={ isFullySynced }
47
- onChange={ () => {
48
- onUpdateSync(
49
- syncStatus === 'unsynced' ? 'fully' : 'unsynced'
50
- );
51
- } }
52
- />
53
- </PanelRow>
87
+ <>
88
+ { isModalOpen && (
89
+ <Modal
90
+ title={ __( 'Set pattern sync status' ) }
91
+ onRequestClose={ () => {
92
+ setIsModalOpen( false );
93
+ } }
94
+ overlayClassName="reusable-blocks-menu-items__convert-modal"
95
+ >
96
+ <form
97
+ onSubmit={ ( event ) => {
98
+ event.preventDefault();
99
+ setIsModalOpen( false );
100
+ setSyncStatus();
101
+ } }
102
+ >
103
+ <VStack spacing="5">
104
+ <ReusableBlocksRenameHint />
105
+ <ToggleControl
106
+ label={ __( 'Synced' ) }
107
+ help={ __(
108
+ 'Editing the pattern will update it anywhere it is used.'
109
+ ) }
110
+ checked={ ! syncType }
111
+ onChange={ () => {
112
+ setSyncType(
113
+ ! syncType ? 'unsynced' : undefined
114
+ );
115
+ } }
116
+ />
117
+ <HStack justify="right">
118
+ <Button variant="primary" type="submit">
119
+ { __( 'Create' ) }
120
+ </Button>
121
+ </HStack>
122
+ </VStack>
123
+ </form>
124
+ </Modal>
125
+ ) }
126
+ </>
54
127
  );
55
128
  }
@@ -9,8 +9,8 @@
9
9
  flex-shrink: 0;
10
10
  }
11
11
 
12
- .components-base-control {
12
+ > div {
13
13
  // Match padding on tertiary buttons for alignment.
14
- padding-left: $grid-unit-15 * 0.5;
14
+ padding-left: $grid-unit-15;
15
15
  }
16
16
  }
@@ -7,8 +7,9 @@ import Textarea from 'react-autosize-textarea';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import { useEffect, useState, useRef } from '@wordpress/element';
11
- import { parse } from '@wordpress/blocks';
10
+ import { store as coreStore } from '@wordpress/core-data';
11
+ import { useMemo } from '@wordpress/element';
12
+ import { __unstableSerializeAndClean } from '@wordpress/blocks';
12
13
  import { useDispatch, useSelect } from '@wordpress/data';
13
14
  import { useInstanceId } from '@wordpress/compose';
14
15
  import { VisuallyHidden } from '@wordpress/components';
@@ -19,63 +20,34 @@ import { VisuallyHidden } from '@wordpress/components';
19
20
  import { store as editorStore } from '../../store';
20
21
 
21
22
  export default function PostTextEditor() {
22
- const postContent = useSelect(
23
- ( select ) => select( editorStore ).getEditedPostContent(),
24
- []
25
- );
26
-
27
- const { editPost, resetEditorBlocks } = useDispatch( editorStore );
28
-
29
- const [ value, setValue ] = useState( postContent );
30
- const [ isDirty, setIsDirty ] = useState( false );
31
23
  const instanceId = useInstanceId( PostTextEditor );
32
- const valueRef = useRef();
33
-
34
- if ( ! isDirty && value !== postContent ) {
35
- setValue( postContent );
36
- }
24
+ const { content, blocks, type, id } = useSelect( ( select ) => {
25
+ const { getEditedEntityRecord } = select( coreStore );
26
+ const { getCurrentPostType, getCurrentPostId } = select( editorStore );
27
+ const _type = getCurrentPostType();
28
+ const _id = getCurrentPostId();
29
+ const editedRecord = getEditedEntityRecord( 'postType', _type, _id );
37
30
 
38
- /**
39
- * Handles a textarea change event to notify the onChange prop callback and
40
- * reflect the new value in the component's own state. This marks the start
41
- * of the user's edits, if not already changed, preventing future props
42
- * changes to value from replacing the rendered value. This is expected to
43
- * be followed by a reset to dirty state via `stopEditing`.
44
- *
45
- * @see stopEditing
46
- *
47
- * @param {Event} event Change event.
48
- */
49
- const onChange = ( event ) => {
50
- const newValue = event.target.value;
51
- editPost( { content: newValue } );
52
- setValue( newValue );
53
- setIsDirty( true );
54
- valueRef.current = newValue;
55
- };
56
-
57
- /**
58
- * Function called when the user has completed their edits, responsible for
59
- * ensuring that changes, if made, are surfaced to the onPersist prop
60
- * callback and resetting dirty state.
61
- */
62
- const stopEditing = () => {
63
- if ( isDirty ) {
64
- const blocks = parse( value );
65
- resetEditorBlocks( blocks );
66
- setIsDirty( false );
67
- }
68
- };
69
-
70
- // Ensure changes aren't lost when component unmounts.
71
- useEffect( () => {
72
- return () => {
73
- if ( valueRef.current ) {
74
- const blocks = parse( valueRef.current );
75
- resetEditorBlocks( blocks );
76
- }
31
+ return {
32
+ content: editedRecord?.content,
33
+ blocks: editedRecord?.blocks,
34
+ type: _type,
35
+ id: _id,
77
36
  };
78
37
  }, [] );
38
+ const { editEntityRecord } = useDispatch( coreStore );
39
+ // Replicates the logic found in getEditedPostContent().
40
+ const value = useMemo( () => {
41
+ if ( content instanceof Function ) {
42
+ return content( { blocks } );
43
+ } else if ( blocks ) {
44
+ // If we have parsed blocks already, they should be our source of truth.
45
+ // Parsing applies block deprecations and legacy block conversions that
46
+ // unparsed content will not have.
47
+ return __unstableSerializeAndClean( blocks );
48
+ }
49
+ return content;
50
+ }, [ content, blocks ] );
79
51
 
80
52
  return (
81
53
  <>
@@ -89,8 +61,13 @@ export default function PostTextEditor() {
89
61
  autoComplete="off"
90
62
  dir="auto"
91
63
  value={ value }
92
- onChange={ onChange }
93
- onBlur={ stopEditing }
64
+ onChange={ ( event ) => {
65
+ editEntityRecord( 'postType', type, id, {
66
+ content: event.target.value,
67
+ blocks: undefined,
68
+ selection: undefined,
69
+ } );
70
+ } }
94
71
  className="editor-post-text-editor"
95
72
  id={ `post-content-${ instanceId }` }
96
73
  placeholder={ __( 'Start writing with text or HTML' ) }
@@ -1,10 +1,10 @@
1
1
 
2
2
  .titleContainer {
3
- padding-left: 12;
4
- padding-right: 16;
5
- padding-top: 12;
6
- padding-bottom: 12;
7
- margin-top: 24;
3
+ padding-left: $block-edge-to-content;
4
+ padding-right: $block-edge-to-content;
5
+ padding-top: 6;
6
+ padding-bottom: 6;
7
+ margin-top: 12;
8
8
  }
9
9
 
10
10
  .dimmed {
@@ -1,4 +1,4 @@
1
1
  .editor-post-trash.components-button {
2
- width: 100%;
3
- display: block;
2
+ flex-grow: 1;
3
+ justify-content: center;
4
4
  }
@@ -47,6 +47,7 @@ const BLOCK_EDITOR_SETTINGS = [
47
47
  'enableCustomUnits',
48
48
  'enableOpenverseMediaCategory',
49
49
  'focusMode',
50
+ 'distractionFree',
50
51
  'fontSizes',
51
52
  'gradients',
52
53
  'generateAnchors',
@@ -11,6 +11,7 @@ import {
11
11
  import { store as noticesStore } from '@wordpress/notices';
12
12
  import { store as coreStore } from '@wordpress/core-data';
13
13
  import { store as blockEditorStore } from '@wordpress/block-editor';
14
+ import { applyFilters } from '@wordpress/hooks';
14
15
  import { store as preferencesStore } from '@wordpress/preferences';
15
16
 
16
17
  /**
@@ -177,15 +178,26 @@ export const savePost =
177
178
  edits,
178
179
  options
179
180
  );
180
- dispatch( { type: 'REQUEST_POST_UPDATE_FINISH', options } );
181
181
 
182
- const error = registry
182
+ let error = registry
183
183
  .select( coreStore )
184
184
  .getLastEntitySaveError(
185
185
  'postType',
186
186
  previousRecord.type,
187
187
  previousRecord.id
188
188
  );
189
+
190
+ if ( ! error ) {
191
+ await applyFilters(
192
+ 'editor.__unstableSavePost',
193
+ Promise.resolve(),
194
+ options
195
+ ).catch( ( err ) => {
196
+ error = err;
197
+ } );
198
+ }
199
+ dispatch( { type: 'REQUEST_POST_UPDATE_FINISH', options } );
200
+
189
201
  if ( error ) {
190
202
  const args = getNotificationArgumentsForSaveFail( {
191
203
  post: previousRecord,
@@ -289,6 +301,26 @@ export const autosave =
289
301
  }
290
302
  };
291
303
 
304
+ export const __unstableSaveForPreview =
305
+ ( { forceIsAutosaveable } ) =>
306
+ async ( { select, dispatch } ) => {
307
+ if (
308
+ ( forceIsAutosaveable || select.isEditedPostAutosaveable() ) &&
309
+ ! select.isPostLocked()
310
+ ) {
311
+ const isDraft = [ 'draft', 'auto-draft' ].includes(
312
+ select.getEditedPostAttribute( 'status' )
313
+ );
314
+ if ( isDraft ) {
315
+ await dispatch.savePost( { isPreview: true } );
316
+ } else {
317
+ await dispatch.autosave( { isPreview: true } );
318
+ }
319
+ }
320
+
321
+ return select.getEditedPostPreviewLink();
322
+ };
323
+
292
324
  /**
293
325
  * Action that restores last popped state in undo history.
294
326
  */
@@ -10,6 +10,7 @@ import {
10
10
  getFreeformContentHandlerName,
11
11
  getDefaultBlockName,
12
12
  __unstableSerializeAndClean,
13
+ parse,
13
14
  } from '@wordpress/blocks';
14
15
  import { isInTheFuture, getDate } from '@wordpress/date';
15
16
  import { addQueryArgs, cleanForSlug } from '@wordpress/url';
@@ -42,15 +43,6 @@ import { getTemplatePartIcon } from '../utils/get-template-part-icon';
42
43
  */
43
44
  const EMPTY_OBJECT = {};
44
45
 
45
- /**
46
- * Shared reference to an empty array for cases where it is important to avoid
47
- * returning a new array reference on every invocation, as in a connected or
48
- * other pure component which performs `shouldComponentUpdate` check on props.
49
- * This should be used as a last resort, since the normalized data should be
50
- * maintained by the reducer result in state.
51
- */
52
- const EMPTY_ARRAY = [];
53
-
54
46
  /**
55
47
  * Returns true if any past editor history snapshots exist, or false otherwise.
56
48
  *
@@ -507,16 +499,31 @@ export function isEditedPostSaveable( state ) {
507
499
  *
508
500
  * @return {boolean} Whether post has content.
509
501
  */
510
- export function isEditedPostEmpty( state ) {
511
- // While the condition of truthy content string is sufficient to determine
512
- // emptiness, testing saveable blocks length is a trivial operation. Since
513
- // this function can be called frequently, optimize for the fast case as a
514
- // condition of the mere existence of blocks. Note that the value of edited
515
- // content takes precedent over block content, and must fall through to the
516
- // default logic.
517
- const blocks = getEditorBlocks( state );
502
+ export const isEditedPostEmpty = createRegistrySelector(
503
+ ( select ) => ( state ) => {
504
+ // While the condition of truthy content string is sufficient to determine
505
+ // emptiness, testing saveable blocks length is a trivial operation. Since
506
+ // this function can be called frequently, optimize for the fast case as a
507
+ // condition of the mere existence of blocks. Note that the value of edited
508
+ // content takes precedent over block content, and must fall through to the
509
+ // default logic.
510
+ const postId = getCurrentPostId( state );
511
+ const postType = getCurrentPostType( state );
512
+ const record = select( coreStore ).getEditedEntityRecord(
513
+ 'postType',
514
+ postType,
515
+ postId
516
+ );
517
+ if ( typeof record.content !== 'function' ) {
518
+ return ! record.content;
519
+ }
520
+
521
+ const blocks = getEditedPostAttribute( state, 'blocks' );
522
+
523
+ if ( blocks.length === 0 ) {
524
+ return true;
525
+ }
518
526
 
519
- if ( blocks.length ) {
520
527
  // Pierce the abstraction of the serializer in knowing that blocks are
521
528
  // joined with newlines such that even if every individual block
522
529
  // produces an empty save result, the serialized content is non-empty.
@@ -542,10 +549,10 @@ export function isEditedPostEmpty( state ) {
542
549
  ) {
543
550
  return false;
544
551
  }
545
- }
546
552
 
547
- return ! getEditedPostContent( state );
548
- }
553
+ return ! getEditedPostContent( state );
554
+ }
555
+ );
549
556
 
550
557
  /**
551
558
  * Returns true if the post can be autosaved, or false otherwise.
@@ -681,15 +688,9 @@ export function isDeletingPost( state ) {
681
688
  *
682
689
  * @return {boolean} Whether post is being saved.
683
690
  */
684
- export const isSavingPost = createRegistrySelector( ( select ) => ( state ) => {
685
- const postType = getCurrentPostType( state );
686
- const postId = getCurrentPostId( state );
687
- return select( coreStore ).isSavingEntityRecord(
688
- 'postType',
689
- postType,
690
- postId
691
- );
692
- } );
691
+ export function isSavingPost( state ) {
692
+ return !! state.saving.pending;
693
+ }
693
694
 
694
695
  /**
695
696
  * Returns true if non-post entities are currently being saved, or false otherwise.
@@ -760,10 +761,7 @@ export const didPostSaveRequestFail = createRegistrySelector(
760
761
  * @return {boolean} Whether the post is autosaving.
761
762
  */
762
763
  export function isAutosavingPost( state ) {
763
- if ( ! isSavingPost( state ) ) {
764
- return false;
765
- }
766
- return Boolean( state.saving.options?.isAutosave );
764
+ return isSavingPost( state ) && Boolean( state.saving.options?.isAutosave );
767
765
  }
768
766
 
769
767
  /**
@@ -774,10 +772,7 @@ export function isAutosavingPost( state ) {
774
772
  * @return {boolean} Whether the post is being previewed.
775
773
  */
776
774
  export function isPreviewingPost( state ) {
777
- if ( ! isSavingPost( state ) ) {
778
- return false;
779
- }
780
- return Boolean( state.saving.options?.isPreview );
775
+ return isSavingPost( state ) && Boolean( state.saving.options?.isPreview );
781
776
  }
782
777
 
783
778
  /**
@@ -1100,9 +1095,18 @@ export const isPublishSidebarEnabled = createRegistrySelector(
1100
1095
  * @param {Object} state
1101
1096
  * @return {Array} Block list.
1102
1097
  */
1103
- export function getEditorBlocks( state ) {
1104
- return getEditedPostAttribute( state, 'blocks' ) || EMPTY_ARRAY;
1105
- }
1098
+ export const getEditorBlocks = createSelector(
1099
+ ( state ) => {
1100
+ return (
1101
+ getEditedPostAttribute( state, 'blocks' ) ||
1102
+ parse( getEditedPostContent( state ) )
1103
+ );
1104
+ },
1105
+ ( state ) => [
1106
+ getEditedPostAttribute( state, 'blocks' ),
1107
+ getEditedPostContent( state ),
1108
+ ]
1109
+ );
1106
1110
 
1107
1111
  /**
1108
1112
  * A block selection object.