@wordpress/editor 12.10.0 → 12.13.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 +6 -0
- package/build/components/document-outline/index.js +7 -9
- package/build/components/document-outline/index.js.map +1 -1
- package/build/components/error-boundary/index.js +3 -0
- package/build/components/error-boundary/index.js.map +1 -1
- package/build/components/index.js +61 -9
- package/build/components/index.js.map +1 -1
- package/build/components/local-autosave-monitor/index.js +24 -19
- package/build/components/local-autosave-monitor/index.js.map +1 -1
- package/build/components/page-attributes/order.js +3 -7
- package/build/components/page-attributes/order.js.map +1 -1
- package/build/components/page-attributes/parent.js +8 -4
- package/build/components/page-attributes/parent.js.map +1 -1
- package/build/components/post-format/index.js +5 -8
- package/build/components/post-format/index.js.map +1 -1
- package/build/components/post-locked-modal/index.js +1 -1
- package/build/components/post-locked-modal/index.js.map +1 -1
- package/build/components/post-publish-panel/maybe-category-panel.js +2 -4
- package/build/components/post-publish-panel/maybe-category-panel.js.map +1 -1
- package/build/components/post-schedule/label.js +93 -13
- package/build/components/post-schedule/label.js.map +1 -1
- package/build/components/post-slug/index.js +8 -13
- package/build/components/post-slug/index.js.map +1 -1
- package/build/components/post-taxonomies/flat-term-selector.js +8 -4
- package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build/components/post-taxonomies/hierarchical-term-selector.js +1 -0
- package/build/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
- package/build/components/post-taxonomies/index.js +3 -1
- package/build/components/post-taxonomies/index.js.map +1 -1
- package/build/components/post-template/index.js +1 -2
- package/build/components/post-template/index.js.map +1 -1
- package/build/components/post-title/index.js +8 -2
- package/build/components/post-title/index.js.map +1 -1
- package/build/components/post-url/check.js +54 -0
- package/build/components/post-url/check.js.map +1 -0
- package/build/components/post-url/index.js +115 -0
- package/build/components/post-url/index.js.map +1 -0
- package/build/components/post-url/label.js +30 -0
- package/build/components/post-url/label.js.map +1 -0
- package/build/components/post-visibility/index.js +3 -1
- package/build/components/post-visibility/index.js.map +1 -1
- package/build/components/post-visibility/label.js +5 -0
- package/build/components/post-visibility/label.js.map +1 -1
- package/build/components/provider/index.native.js +3 -2
- package/build/components/provider/index.native.js.map +1 -1
- package/build/components/provider/use-block-editor-settings.js +2 -2
- package/build/components/provider/use-block-editor-settings.js.map +1 -1
- package/build/components/table-of-contents/panel.js +5 -1
- package/build/components/table-of-contents/panel.js.map +1 -1
- package/build/components/time-to-read/index.js +60 -0
- package/build/components/time-to-read/index.js.map +1 -0
- package/build/store/actions.js +5 -1
- package/build/store/actions.js.map +1 -1
- package/build/store/reducer.js +1 -1
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +3 -3
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/document-outline/index.js +7 -8
- package/build-module/components/document-outline/index.js.map +1 -1
- package/build-module/components/error-boundary/index.js +2 -0
- package/build-module/components/error-boundary/index.js.map +1 -1
- package/build-module/components/index.js +7 -4
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/local-autosave-monitor/index.js +24 -18
- package/build-module/components/local-autosave-monitor/index.js.map +1 -1
- package/build-module/components/page-attributes/order.js +3 -6
- package/build-module/components/page-attributes/order.js.map +1 -1
- package/build-module/components/page-attributes/parent.js +6 -5
- package/build-module/components/page-attributes/parent.js.map +1 -1
- package/build-module/components/post-format/index.js +5 -8
- package/build-module/components/post-format/index.js.map +1 -1
- package/build-module/components/post-locked-modal/index.js +1 -1
- package/build-module/components/post-locked-modal/index.js.map +1 -1
- package/build-module/components/post-publish-panel/maybe-category-panel.js +2 -4
- package/build-module/components/post-publish-panel/maybe-category-panel.js.map +1 -1
- package/build-module/components/post-schedule/label.js +90 -13
- package/build-module/components/post-schedule/label.js.map +1 -1
- package/build-module/components/post-slug/index.js +8 -14
- package/build-module/components/post-slug/index.js.map +1 -1
- package/build-module/components/post-taxonomies/flat-term-selector.js +8 -6
- package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build-module/components/post-taxonomies/hierarchical-term-selector.js +1 -2
- package/build-module/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
- package/build-module/components/post-taxonomies/index.js +4 -1
- package/build-module/components/post-taxonomies/index.js.map +1 -1
- package/build-module/components/post-template/index.js +1 -2
- package/build-module/components/post-template/index.js.map +1 -1
- package/build-module/components/post-title/index.js +8 -2
- package/build-module/components/post-title/index.js.map +1 -1
- package/build-module/components/post-url/check.js +44 -0
- package/build-module/components/post-url/check.js.map +1 -0
- package/build-module/components/post-url/index.js +102 -0
- package/build-module/components/post-url/index.js.map +1 -0
- package/build-module/components/post-url/label.js +18 -0
- package/build-module/components/post-url/label.js.map +1 -0
- package/build-module/components/post-visibility/index.js +4 -2
- package/build-module/components/post-visibility/index.js.map +1 -1
- package/build-module/components/post-visibility/label.js +3 -0
- package/build-module/components/post-visibility/label.js.map +1 -1
- package/build-module/components/provider/index.native.js +3 -2
- package/build-module/components/provider/index.native.js.map +1 -1
- package/build-module/components/provider/use-block-editor-settings.js +2 -2
- package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
- package/build-module/components/table-of-contents/panel.js +4 -1
- package/build-module/components/table-of-contents/panel.js.map +1 -1
- package/build-module/components/time-to-read/index.js +50 -0
- package/build-module/components/time-to-read/index.js.map +1 -0
- package/build-module/store/actions.js +5 -1
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/reducer.js +2 -2
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +4 -4
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +19 -18
- package/build-style/style.css +23 -18
- package/package.json +30 -29
- package/src/components/README.md +1 -1
- package/src/components/document-outline/index.js +9 -8
- package/src/components/error-boundary/index.js +3 -0
- package/src/components/index.js +13 -4
- package/src/components/local-autosave-monitor/index.js +24 -18
- package/src/components/page-attributes/order.js +1 -9
- package/src/components/page-attributes/parent.js +6 -13
- package/src/components/post-format/index.js +13 -19
- package/src/components/post-format/style.scss +2 -17
- package/src/components/post-locked-modal/index.js +1 -1
- package/src/components/post-publish-panel/maybe-category-panel.js +7 -6
- package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +1 -1
- package/src/components/post-schedule/label.js +111 -17
- package/src/components/post-schedule/test/label.js +127 -15
- package/src/components/post-slug/index.js +7 -13
- package/src/components/post-slug/test/index.js +7 -6
- package/src/components/post-taxonomies/flat-term-selector.js +6 -5
- package/src/components/post-taxonomies/hierarchical-term-selector.js +1 -1
- package/src/components/post-taxonomies/index.js +3 -1
- package/src/components/post-template/index.js +1 -1
- package/src/components/post-title/index.js +8 -2
- package/src/components/post-title/style.scss +1 -1
- package/src/components/post-trash/style.scss +3 -0
- package/src/components/post-url/check.js +38 -0
- package/src/components/post-url/index.js +122 -0
- package/src/components/post-url/label.js +22 -0
- package/src/components/post-url/style.scss +16 -0
- package/src/components/post-visibility/index.js +2 -2
- package/src/components/post-visibility/label.js +4 -0
- package/src/components/provider/index.native.js +4 -8
- package/src/components/provider/use-block-editor-settings.js +4 -1
- package/src/components/table-of-contents/panel.js +7 -2
- package/src/components/time-to-read/index.js +59 -0
- package/src/store/actions.js +3 -1
- package/src/store/reducer.js +2 -2
- package/src/store/selectors.js +5 -6
- package/src/store/test/selectors.js +8 -10
- package/src/style.scss +1 -0
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
import { withDispatch, withSelect } from '@wordpress/data';
|
|
5
5
|
import { Component } from '@wordpress/element';
|
|
6
6
|
import { __ } from '@wordpress/i18n';
|
|
7
|
-
import {
|
|
7
|
+
import { compose } from '@wordpress/compose';
|
|
8
8
|
import { safeDecodeURIComponent, cleanForSlug } from '@wordpress/url';
|
|
9
|
+
import { TextControl } from '@wordpress/components';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Internal dependencies
|
|
@@ -41,25 +42,19 @@ export class PostSlug extends Component {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
render() {
|
|
44
|
-
const { instanceId } = this.props;
|
|
45
45
|
const { editedSlug } = this.state;
|
|
46
|
-
|
|
47
|
-
const inputId = 'editor-post-slug-' + instanceId;
|
|
48
|
-
|
|
49
46
|
return (
|
|
50
47
|
<PostSlugCheck>
|
|
51
|
-
<
|
|
52
|
-
|
|
48
|
+
<TextControl
|
|
49
|
+
label={ __( 'Slug' ) }
|
|
53
50
|
autoComplete="off"
|
|
54
51
|
spellCheck="false"
|
|
55
|
-
type="text"
|
|
56
|
-
id={ inputId }
|
|
57
52
|
value={ editedSlug }
|
|
58
|
-
onChange={ (
|
|
59
|
-
this.setState( { editedSlug:
|
|
53
|
+
onChange={ ( slug ) =>
|
|
54
|
+
this.setState( { editedSlug: slug } )
|
|
60
55
|
}
|
|
61
56
|
onBlur={ this.setSlug }
|
|
62
|
-
className="editor-post-
|
|
57
|
+
className="editor-post-slug"
|
|
63
58
|
/>
|
|
64
59
|
</PostSlugCheck>
|
|
65
60
|
);
|
|
@@ -86,5 +81,4 @@ export default compose( [
|
|
|
86
81
|
},
|
|
87
82
|
};
|
|
88
83
|
} ),
|
|
89
|
-
withInstanceId,
|
|
90
84
|
] )( PostSlug );
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { shallow } from 'enzyme';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { TextControl } from '@wordpress/components';
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
12
|
* Internal dependencies
|
|
8
13
|
*/
|
|
@@ -13,11 +18,7 @@ describe( 'PostSlug', () => {
|
|
|
13
18
|
it( 'should update internal slug', () => {
|
|
14
19
|
const wrapper = shallow( <PostSlug postSlug="index" /> );
|
|
15
20
|
|
|
16
|
-
wrapper.find( '
|
|
17
|
-
target: {
|
|
18
|
-
value: 'single',
|
|
19
|
-
},
|
|
20
|
-
} );
|
|
21
|
+
wrapper.find( TextControl ).prop( 'onChange' )( 'single' );
|
|
21
22
|
|
|
22
23
|
expect( wrapper.state().editedSlug ).toEqual( 'single' );
|
|
23
24
|
} );
|
|
@@ -28,7 +29,7 @@ describe( 'PostSlug', () => {
|
|
|
28
29
|
<PostSlug postSlug="index" onUpdateSlug={ onUpdateSlug } />
|
|
29
30
|
);
|
|
30
31
|
|
|
31
|
-
wrapper.find(
|
|
32
|
+
wrapper.find( TextControl ).prop( 'onBlur' )( {
|
|
32
33
|
target: {
|
|
33
34
|
value: 'single',
|
|
34
35
|
},
|
|
@@ -55,11 +55,11 @@ const termNamesToIds = ( names, terms ) => {
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
// Tries to create a term or fetch it if it already exists.
|
|
58
|
-
function findOrCreateTerm( termName, restBase ) {
|
|
58
|
+
function findOrCreateTerm( termName, restBase, namespace ) {
|
|
59
59
|
const escapedTermName = escapeString( termName );
|
|
60
60
|
|
|
61
61
|
return apiFetch( {
|
|
62
|
-
path:
|
|
62
|
+
path: `/${ namespace }/${ restBase }`,
|
|
63
63
|
method: 'POST',
|
|
64
64
|
data: { name: escapedTermName },
|
|
65
65
|
} )
|
|
@@ -68,7 +68,7 @@ function findOrCreateTerm( termName, restBase ) {
|
|
|
68
68
|
if ( errorCode === 'term_exists' ) {
|
|
69
69
|
// If the terms exist, fetch it instead of creating a new one.
|
|
70
70
|
const addRequest = apiFetch( {
|
|
71
|
-
path: addQueryArgs(
|
|
71
|
+
path: addQueryArgs( `/${ namespace }/${ restBase }`, {
|
|
72
72
|
...DEFAULT_QUERY,
|
|
73
73
|
search: escapedTermName,
|
|
74
74
|
} ),
|
|
@@ -86,7 +86,7 @@ function findOrCreateTerm( termName, restBase ) {
|
|
|
86
86
|
.then( unescapeTerm );
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function FlatTermSelector( { slug } ) {
|
|
89
|
+
export function FlatTermSelector( { slug } ) {
|
|
90
90
|
const [ values, setValues ] = useState( [] );
|
|
91
91
|
const [ search, setSearch ] = useState( '' );
|
|
92
92
|
const debouncedSearch = useDebounce( setSearch, 500 );
|
|
@@ -224,9 +224,10 @@ function FlatTermSelector( { slug } ) {
|
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
const namespace = taxonomy?.rest_namespace ?? 'wp/v2';
|
|
227
228
|
Promise.all(
|
|
228
229
|
newTermNames.map( ( termName ) =>
|
|
229
|
-
findOrCreateTerm( termName, taxonomy.rest_base )
|
|
230
|
+
findOrCreateTerm( termName, taxonomy.rest_base, namespace )
|
|
230
231
|
)
|
|
231
232
|
).then( ( newTerms ) => {
|
|
232
233
|
const newAvailableTerms = availableTerms.concat( newTerms );
|
|
@@ -152,7 +152,7 @@ export function getFilterMatcher( filterValue ) {
|
|
|
152
152
|
* @param {string} props.slug Taxonomy slug.
|
|
153
153
|
* @return {WPElement} Hierarchical term selector component.
|
|
154
154
|
*/
|
|
155
|
-
function HierarchicalTermSelector( { slug } ) {
|
|
155
|
+
export function HierarchicalTermSelector( { slug } ) {
|
|
156
156
|
const [ adding, setAdding ] = useState( false );
|
|
157
157
|
const [ formName, setFormName ] = useState( '' );
|
|
158
158
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { filter,
|
|
4
|
+
import { filter, includes } from 'lodash';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
@@ -18,6 +18,8 @@ import HierarchicalTermSelector from './hierarchical-term-selector';
|
|
|
18
18
|
import FlatTermSelector from './flat-term-selector';
|
|
19
19
|
import { store as editorStore } from '../../store';
|
|
20
20
|
|
|
21
|
+
const identity = ( x ) => x;
|
|
22
|
+
|
|
21
23
|
export function PostTaxonomies( {
|
|
22
24
|
postType,
|
|
23
25
|
taxonomies,
|
|
@@ -16,7 +16,7 @@ import { store as coreStore } from '@wordpress/core-data';
|
|
|
16
16
|
*/
|
|
17
17
|
import { store as editorStore } from '../../store';
|
|
18
18
|
|
|
19
|
-
export function PostTemplate(
|
|
19
|
+
export function PostTemplate() {
|
|
20
20
|
const { availableTemplates, selectedTemplate, isViewable } = useSelect(
|
|
21
21
|
( select ) => {
|
|
22
22
|
const {
|
|
@@ -149,9 +149,13 @@ function PostTitle( _, forwardedRef ) {
|
|
|
149
149
|
plainText,
|
|
150
150
|
} );
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
event.preventDefault();
|
|
153
|
+
|
|
154
|
+
if ( ! content.length ) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
154
157
|
|
|
158
|
+
if ( typeof content !== 'string' ) {
|
|
155
159
|
const [ firstBlock ] = content;
|
|
156
160
|
|
|
157
161
|
if (
|
|
@@ -164,6 +168,8 @@ function PostTitle( _, forwardedRef ) {
|
|
|
164
168
|
} else {
|
|
165
169
|
onInsertBlockAfter( content );
|
|
166
170
|
}
|
|
171
|
+
} else {
|
|
172
|
+
onUpdate( content );
|
|
167
173
|
}
|
|
168
174
|
}
|
|
169
175
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { store as editorStore } from '../../store';
|
|
11
|
+
|
|
12
|
+
export default function PostURLCheck( { children } ) {
|
|
13
|
+
const isVisible = useSelect( ( select ) => {
|
|
14
|
+
const postTypeSlug = select( editorStore ).getCurrentPostType();
|
|
15
|
+
const postType = select( coreStore ).getPostType( postTypeSlug );
|
|
16
|
+
if ( ! postType?.viewable ) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const post = select( editorStore ).getCurrentPost();
|
|
21
|
+
if ( ! post.link ) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const permalinkParts = select( editorStore ).getPermalinkParts();
|
|
26
|
+
if ( ! permalinkParts ) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return true;
|
|
31
|
+
}, [] );
|
|
32
|
+
|
|
33
|
+
if ( ! isVisible ) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return children;
|
|
38
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect, useDispatch } from '@wordpress/data';
|
|
5
|
+
import { safeDecodeURIComponent, cleanForSlug } from '@wordpress/url';
|
|
6
|
+
import { useState } from '@wordpress/element';
|
|
7
|
+
import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
|
|
8
|
+
import { __ } from '@wordpress/i18n';
|
|
9
|
+
import { TextControl, ExternalLink } from '@wordpress/components';
|
|
10
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
import { store as editorStore } from '../../store';
|
|
16
|
+
|
|
17
|
+
export default function PostURL( { onClose } ) {
|
|
18
|
+
const {
|
|
19
|
+
isEditable,
|
|
20
|
+
postSlug,
|
|
21
|
+
viewPostLabel,
|
|
22
|
+
postLink,
|
|
23
|
+
permalinkPrefix,
|
|
24
|
+
permalinkSuffix,
|
|
25
|
+
} = useSelect( ( select ) => {
|
|
26
|
+
const postTypeSlug = select( editorStore ).getCurrentPostType();
|
|
27
|
+
const postType = select( coreStore ).getPostType( postTypeSlug );
|
|
28
|
+
const permalinkParts = select( editorStore ).getPermalinkParts();
|
|
29
|
+
return {
|
|
30
|
+
isEditable: select( editorStore ).isPermalinkEditable(),
|
|
31
|
+
postSlug: safeDecodeURIComponent(
|
|
32
|
+
select( editorStore ).getEditedPostSlug()
|
|
33
|
+
),
|
|
34
|
+
viewPostLabel: postType?.labels.view_item,
|
|
35
|
+
postLink: select( editorStore ).getCurrentPost().link,
|
|
36
|
+
permalinkPrefix: permalinkParts?.prefix,
|
|
37
|
+
permalinkSuffix: permalinkParts?.suffix,
|
|
38
|
+
};
|
|
39
|
+
}, [] );
|
|
40
|
+
|
|
41
|
+
const { editPost } = useDispatch( editorStore );
|
|
42
|
+
|
|
43
|
+
const [ forceEmptyField, setForceEmptyField ] = useState( false );
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="editor-post-url">
|
|
47
|
+
<InspectorPopoverHeader title={ __( 'URL' ) } onClose={ onClose } />
|
|
48
|
+
{ isEditable && (
|
|
49
|
+
<TextControl
|
|
50
|
+
label={ __( 'Permalink' ) }
|
|
51
|
+
value={ forceEmptyField ? '' : postSlug }
|
|
52
|
+
autoComplete="off"
|
|
53
|
+
spellCheck="false"
|
|
54
|
+
help={
|
|
55
|
+
<>
|
|
56
|
+
{ __( 'The last part of the URL.' ) }{ ' ' }
|
|
57
|
+
<ExternalLink
|
|
58
|
+
href={ __(
|
|
59
|
+
'https://wordpress.org/support/article/settings-sidebar/#permalink'
|
|
60
|
+
) }
|
|
61
|
+
>
|
|
62
|
+
{ __( 'Learn more.' ) }
|
|
63
|
+
</ExternalLink>
|
|
64
|
+
</>
|
|
65
|
+
}
|
|
66
|
+
onChange={ ( newValue ) => {
|
|
67
|
+
editPost( { slug: newValue } );
|
|
68
|
+
// When we delete the field the permalink gets
|
|
69
|
+
// reverted to the original value.
|
|
70
|
+
// The forceEmptyField logic allows the user to have
|
|
71
|
+
// the field temporarily empty while typing.
|
|
72
|
+
if ( ! newValue ) {
|
|
73
|
+
if ( ! forceEmptyField ) {
|
|
74
|
+
setForceEmptyField( true );
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if ( forceEmptyField ) {
|
|
79
|
+
setForceEmptyField( false );
|
|
80
|
+
}
|
|
81
|
+
} }
|
|
82
|
+
onBlur={ ( event ) => {
|
|
83
|
+
editPost( {
|
|
84
|
+
slug: cleanForSlug( event.target.value ),
|
|
85
|
+
} );
|
|
86
|
+
if ( forceEmptyField ) {
|
|
87
|
+
setForceEmptyField( false );
|
|
88
|
+
}
|
|
89
|
+
} }
|
|
90
|
+
/>
|
|
91
|
+
) }
|
|
92
|
+
{ isEditable && (
|
|
93
|
+
<h3 className="editor-post-url__link-label">
|
|
94
|
+
{ viewPostLabel ?? __( 'View post' ) }
|
|
95
|
+
</h3>
|
|
96
|
+
) }
|
|
97
|
+
<p>
|
|
98
|
+
<ExternalLink
|
|
99
|
+
className="editor-post-url__link"
|
|
100
|
+
href={ postLink }
|
|
101
|
+
target="_blank"
|
|
102
|
+
>
|
|
103
|
+
{ isEditable ? (
|
|
104
|
+
<>
|
|
105
|
+
<span className="editor-post-url__link-prefix">
|
|
106
|
+
{ permalinkPrefix }
|
|
107
|
+
</span>
|
|
108
|
+
<span className="editor-post-url__link-slug">
|
|
109
|
+
{ postSlug }
|
|
110
|
+
</span>
|
|
111
|
+
<span className="editor-post-url__link-suffix">
|
|
112
|
+
{ permalinkSuffix }
|
|
113
|
+
</span>
|
|
114
|
+
</>
|
|
115
|
+
) : (
|
|
116
|
+
postLink
|
|
117
|
+
) }
|
|
118
|
+
</ExternalLink>
|
|
119
|
+
</p>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { filterURLForDisplay } from '@wordpress/url';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { store as editorStore } from '../../store';
|
|
11
|
+
|
|
12
|
+
export default function PostURLLabel() {
|
|
13
|
+
return usePostURLLabel();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function usePostURLLabel() {
|
|
17
|
+
const postLink = useSelect(
|
|
18
|
+
( select ) => select( editorStore ).getCurrentPost().link,
|
|
19
|
+
[]
|
|
20
|
+
);
|
|
21
|
+
return filterURLForDisplay( postLink );
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.editor-post-url__link-label {
|
|
2
|
+
font-size: $default-font-size;
|
|
3
|
+
font-weight: 400;
|
|
4
|
+
margin: 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* rtl:begin:ignore */
|
|
8
|
+
.editor-post-url__link {
|
|
9
|
+
direction: ltr;
|
|
10
|
+
word-break: break-word;
|
|
11
|
+
}
|
|
12
|
+
/* rtl:end:ignore */
|
|
13
|
+
|
|
14
|
+
.editor-post-url__link-slug {
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
}
|
|
@@ -68,7 +68,7 @@ export default function PostVisibility( { onClose } ) {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
return (
|
|
71
|
-
|
|
71
|
+
<div className="editor-post-visibility">
|
|
72
72
|
<InspectorPopoverHeader
|
|
73
73
|
title={ __( 'Visibility' ) }
|
|
74
74
|
help={ __( 'Control how this post is viewed.' ) }
|
|
@@ -128,7 +128,7 @@ export default function PostVisibility( { onClose } ) {
|
|
|
128
128
|
>
|
|
129
129
|
{ __( 'Would you like to privately publish this post now?' ) }
|
|
130
130
|
</ConfirmDialog>
|
|
131
|
-
|
|
131
|
+
</div>
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -10,6 +10,10 @@ import { visibilityOptions } from './utils';
|
|
|
10
10
|
import { store as editorStore } from '../../store';
|
|
11
11
|
|
|
12
12
|
export default function PostVisibilityLabel() {
|
|
13
|
+
return usePostVisibilityLabel();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function usePostVisibilityLabel() {
|
|
13
17
|
const visibility = useSelect( ( select ) =>
|
|
14
18
|
select( editorStore ).getEditedPostVisibility()
|
|
15
19
|
);
|
|
@@ -91,12 +91,14 @@ class NativeEditorProvider extends Component {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
componentDidMount() {
|
|
94
|
-
const { capabilities, locale, updateSettings } =
|
|
94
|
+
const { capabilities, locale, hostAppNamespace, updateSettings } =
|
|
95
|
+
this.props;
|
|
95
96
|
|
|
96
97
|
updateSettings( {
|
|
97
98
|
...capabilities,
|
|
98
99
|
...this.getThemeColors( this.props ),
|
|
99
100
|
locale,
|
|
101
|
+
hostAppNamespace,
|
|
100
102
|
} );
|
|
101
103
|
|
|
102
104
|
this.subscriptionParentGetHtml = subscribeParentGetHtml( () => {
|
|
@@ -319,13 +321,7 @@ class NativeEditorProvider extends Component {
|
|
|
319
321
|
}
|
|
320
322
|
|
|
321
323
|
render() {
|
|
322
|
-
const {
|
|
323
|
-
children,
|
|
324
|
-
post, // eslint-disable-line no-unused-vars
|
|
325
|
-
capabilities,
|
|
326
|
-
settings,
|
|
327
|
-
...props
|
|
328
|
-
} = this.props;
|
|
324
|
+
const { children, post, capabilities, settings, ...props } = this.props;
|
|
329
325
|
const editorSettings = this.getEditorSettings( settings, capabilities );
|
|
330
326
|
|
|
331
327
|
return (
|
|
@@ -41,7 +41,9 @@ function useBlockEditorSettings( settings, hasTemplate ) {
|
|
|
41
41
|
const isWeb = Platform.OS === 'web';
|
|
42
42
|
const { canUser, getEntityRecord } = select( coreStore );
|
|
43
43
|
|
|
44
|
-
const siteSettings =
|
|
44
|
+
const siteSettings = canUser( 'read', 'settings' )
|
|
45
|
+
? getEntityRecord( 'root', 'site' )
|
|
46
|
+
: undefined;
|
|
45
47
|
|
|
46
48
|
return {
|
|
47
49
|
canUseUnfilteredHTML: canUserUseUnfilteredHTML(),
|
|
@@ -136,6 +138,7 @@ function useBlockEditorSettings( settings, hasTemplate ) {
|
|
|
136
138
|
'generateAnchors',
|
|
137
139
|
'hasFixedToolbar',
|
|
138
140
|
'hasReducedUI',
|
|
141
|
+
'hasInlineToolbar',
|
|
139
142
|
'imageDefaultSize',
|
|
140
143
|
'imageDimensions',
|
|
141
144
|
'imageEditing',
|
|
@@ -9,6 +9,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
|
9
9
|
* Internal dependencies
|
|
10
10
|
*/
|
|
11
11
|
import WordCount from '../word-count';
|
|
12
|
+
import TimeToRead from '../time-to-read';
|
|
12
13
|
import DocumentOutline from '../document-outline';
|
|
13
14
|
import CharacterCount from '../character-count';
|
|
14
15
|
|
|
@@ -38,6 +39,10 @@ function TableOfContentsPanel( { hasOutlineItemsDisabled, onRequestClose } ) {
|
|
|
38
39
|
tabIndex="0"
|
|
39
40
|
>
|
|
40
41
|
<ul role="list" className="table-of-contents__counts">
|
|
42
|
+
<li className="table-of-contents__count">
|
|
43
|
+
{ __( 'Words' ) }
|
|
44
|
+
<WordCount />
|
|
45
|
+
</li>
|
|
41
46
|
<li className="table-of-contents__count">
|
|
42
47
|
{ __( 'Characters' ) }
|
|
43
48
|
<span className="table-of-contents__number">
|
|
@@ -45,8 +50,8 @@ function TableOfContentsPanel( { hasOutlineItemsDisabled, onRequestClose } ) {
|
|
|
45
50
|
</span>
|
|
46
51
|
</li>
|
|
47
52
|
<li className="table-of-contents__count">
|
|
48
|
-
{ __( '
|
|
49
|
-
<
|
|
53
|
+
{ __( 'Time to read' ) }
|
|
54
|
+
<TimeToRead />
|
|
50
55
|
</li>
|
|
51
56
|
<li className="table-of-contents__count">
|
|
52
57
|
{ __( 'Headings' ) }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { _x, _n, __, sprintf } from '@wordpress/i18n';
|
|
6
|
+
import { count as wordCount } from '@wordpress/wordcount';
|
|
7
|
+
import { createInterpolateElement } from '@wordpress/element';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
import { store as editorStore } from '../../store';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Average reading rate - based on average taken from
|
|
16
|
+
* https://irisreading.com/average-reading-speed-in-various-languages/
|
|
17
|
+
* (Characters/minute used for Chinese rather than words).
|
|
18
|
+
*
|
|
19
|
+
* @type {number} A rough estimate of the average reading rate across multiple languages.
|
|
20
|
+
*/
|
|
21
|
+
const AVERAGE_READING_RATE = 189;
|
|
22
|
+
|
|
23
|
+
export default function TimeToRead() {
|
|
24
|
+
const content = useSelect(
|
|
25
|
+
( select ) => select( editorStore ).getEditedPostAttribute( 'content' ),
|
|
26
|
+
[]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* translators: If your word count is based on single characters (e.g. East Asian characters),
|
|
31
|
+
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
|
|
32
|
+
* Do not translate into your own language.
|
|
33
|
+
*/
|
|
34
|
+
const wordCountType = _x( 'words', 'Word count type. Do not translate!' );
|
|
35
|
+
const minutesToRead = Math.round(
|
|
36
|
+
wordCount( content, wordCountType ) / AVERAGE_READING_RATE
|
|
37
|
+
);
|
|
38
|
+
const minutesToReadString =
|
|
39
|
+
minutesToRead === 0
|
|
40
|
+
? createInterpolateElement( __( '<span>< 1</span> minute' ), {
|
|
41
|
+
span: <span className="table-of-contents__number" />,
|
|
42
|
+
} )
|
|
43
|
+
: createInterpolateElement(
|
|
44
|
+
sprintf(
|
|
45
|
+
/* translators: %s is the number of minutes the post will take to read. */
|
|
46
|
+
_n(
|
|
47
|
+
'<span>%d</span> minute',
|
|
48
|
+
'<span>%d</span> minutes',
|
|
49
|
+
minutesToRead
|
|
50
|
+
),
|
|
51
|
+
minutesToRead
|
|
52
|
+
),
|
|
53
|
+
{
|
|
54
|
+
span: <span className="table-of-contents__number" />,
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return <span className="time-to-read">{ minutesToReadString }</span>;
|
|
59
|
+
}
|
package/src/store/actions.js
CHANGED
|
@@ -250,10 +250,12 @@ export const trashPost =
|
|
|
250
250
|
.resolveSelect( coreStore )
|
|
251
251
|
.getPostType( postTypeSlug );
|
|
252
252
|
registry.dispatch( noticesStore ).removeNotice( TRASH_POST_NOTICE_ID );
|
|
253
|
+
const { rest_base: restBase, rest_namespace: restNamespace = 'wp/v2' } =
|
|
254
|
+
postType;
|
|
253
255
|
try {
|
|
254
256
|
const post = select.getCurrentPost();
|
|
255
257
|
await apiFetch( {
|
|
256
|
-
path:
|
|
258
|
+
path: `/${ restNamespace }/${ restBase }/${ post.id }`,
|
|
257
259
|
method: 'DELETE',
|
|
258
260
|
} );
|
|
259
261
|
|
package/src/store/reducer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { omit,
|
|
4
|
+
import { omit, isEqual } from 'lodash';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
@@ -39,7 +39,7 @@ export function getPostRawValue( value ) {
|
|
|
39
39
|
* @return {boolean} Whether the two objects have the same keys.
|
|
40
40
|
*/
|
|
41
41
|
export function hasSameKeys( a, b ) {
|
|
42
|
-
return isEqual( keys( a ), keys( b ) );
|
|
42
|
+
return isEqual( Object.keys( a ), Object.keys( b ) );
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
package/src/store/selectors.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { find, get, has,
|
|
4
|
+
import { find, get, has, includes, some } from 'lodash';
|
|
5
5
|
import createSelector from 'rememo';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -534,7 +534,7 @@ export function isEditedPostEmpty( state ) {
|
|
|
534
534
|
|
|
535
535
|
if ( blocks.length ) {
|
|
536
536
|
// Pierce the abstraction of the serializer in knowing that blocks are
|
|
537
|
-
// joined with
|
|
537
|
+
// joined with newlines such that even if every individual block
|
|
538
538
|
// produces an empty save result, the serialized content is non-empty.
|
|
539
539
|
if ( blocks.length > 1 ) {
|
|
540
540
|
return false;
|
|
@@ -1605,10 +1605,9 @@ export function __experimentalGetTemplateInfo( state, template ) {
|
|
|
1605
1605
|
const { title: defaultTitle, description: defaultDescription } =
|
|
1606
1606
|
__experimentalGetDefaultTemplateType( state, slug );
|
|
1607
1607
|
|
|
1608
|
-
const templateTitle =
|
|
1609
|
-
const templateDescription =
|
|
1610
|
-
? description
|
|
1611
|
-
: description?.raw;
|
|
1608
|
+
const templateTitle = typeof title === 'string' ? title : title?.rendered;
|
|
1609
|
+
const templateDescription =
|
|
1610
|
+
typeof description === 'string' ? description : description?.raw;
|
|
1612
1611
|
const templateIcon =
|
|
1613
1612
|
__experimentalGetDefaultTemplatePartAreas( state ).find(
|
|
1614
1613
|
( item ) => area === item.area
|