@wordpress/core-data 7.45.0 → 7.45.1-next.v.202605131032.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/build/actions.cjs +8 -6
- package/build/actions.cjs.map +2 -2
- package/build/awareness/post-editor-awareness.cjs +1 -1
- package/build/awareness/post-editor-awareness.cjs.map +2 -2
- package/build/resolvers.cjs +2 -1
- package/build/resolvers.cjs.map +2 -2
- package/build/types.cjs.map +2 -2
- package/build/utils/block-selection-history.cjs +4 -1
- package/build/utils/block-selection-history.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs +157 -89
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-selection.cjs +1 -1
- package/build/utils/crdt-selection.cjs.map +2 -2
- package/build/utils/crdt-user-selections.cjs +4 -1
- package/build/utils/crdt-user-selections.cjs.map +2 -2
- package/build/utils/crdt-utils.cjs +18 -6
- package/build/utils/crdt-utils.cjs.map +2 -2
- package/build/utils/crdt.cjs +12 -2
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/actions.mjs +8 -6
- package/build-module/actions.mjs.map +2 -2
- package/build-module/awareness/post-editor-awareness.mjs +5 -2
- package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
- package/build-module/resolvers.mjs +2 -1
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/types.mjs.map +2 -2
- package/build-module/utils/block-selection-history.mjs +5 -1
- package/build-module/utils/block-selection-history.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +162 -90
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-selection.mjs +2 -1
- package/build-module/utils/crdt-selection.mjs.map +2 -2
- package/build-module/utils/crdt-user-selections.mjs +9 -2
- package/build-module/utils/crdt-user-selections.mjs.map +2 -2
- package/build-module/utils/crdt-utils.mjs +16 -6
- package/build-module/utils/crdt-utils.mjs.map +2 -2
- package/build-module/utils/crdt.mjs +13 -2
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/actions.d.ts +177 -64
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/awareness/awareness-state.d.ts.map +1 -1
- package/build-types/awareness/base-awareness.d.ts +0 -3
- package/build-types/awareness/base-awareness.d.ts.map +1 -1
- package/build-types/awareness/post-editor-awareness.d.ts +1 -8
- package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
- package/build-types/awareness/typed-awareness.d.ts.map +1 -1
- package/build-types/batch/create-batch.d.ts +1 -1
- package/build-types/batch/create-batch.d.ts.map +1 -1
- package/build-types/batch/default-processor.d.ts.map +1 -1
- package/build-types/batch/index.d.ts +2 -2
- package/build-types/batch/index.d.ts.map +1 -1
- package/build-types/entities.d.ts +114 -87
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/entity-context.d.ts +1 -1
- package/build-types/entity-context.d.ts.map +1 -1
- package/build-types/entity-provider.d.ts +2 -2
- package/build-types/entity-provider.d.ts.map +1 -1
- package/build-types/entity-types/attachment.d.ts.map +1 -1
- package/build-types/entity-types/base-entity-records.d.ts.map +1 -1
- package/build-types/entity-types/base.d.ts.map +1 -1
- package/build-types/entity-types/comment.d.ts.map +1 -1
- package/build-types/entity-types/font-collection.d.ts.map +1 -1
- package/build-types/entity-types/font-family.d.ts.map +1 -1
- package/build-types/entity-types/global-styles-revision.d.ts.map +1 -1
- package/build-types/entity-types/icon.d.ts.map +1 -1
- package/build-types/entity-types/menu-location.d.ts.map +1 -1
- package/build-types/entity-types/nav-menu-item.d.ts.map +1 -1
- package/build-types/entity-types/nav-menu.d.ts.map +1 -1
- package/build-types/entity-types/page.d.ts.map +1 -1
- package/build-types/entity-types/plugin.d.ts.map +1 -1
- package/build-types/entity-types/post-revision.d.ts.map +1 -1
- package/build-types/entity-types/post-status.d.ts.map +1 -1
- package/build-types/entity-types/post.d.ts.map +1 -1
- package/build-types/entity-types/settings.d.ts.map +1 -1
- package/build-types/entity-types/sidebar.d.ts.map +1 -1
- package/build-types/entity-types/taxonomy.d.ts.map +1 -1
- package/build-types/entity-types/term.d.ts.map +1 -1
- package/build-types/entity-types/theme.d.ts.map +1 -1
- package/build-types/entity-types/type.d.ts.map +1 -1
- package/build-types/entity-types/user.d.ts.map +1 -1
- package/build-types/entity-types/widget-type.d.ts.map +1 -1
- package/build-types/entity-types/widget.d.ts.map +1 -1
- package/build-types/entity-types/wp-template-part.d.ts.map +1 -1
- package/build-types/entity-types/wp-template.d.ts.map +1 -1
- package/build-types/fetch/__experimental-fetch-url-data.d.ts +2 -5
- package/build-types/fetch/__experimental-fetch-url-data.d.ts.map +1 -1
- package/build-types/fetch/index.d.ts +3 -3
- package/build-types/fetch/index.d.ts.map +1 -1
- package/build-types/footnotes/get-footnotes-order.d.ts.map +1 -1
- package/build-types/footnotes/get-rich-text-values-cached.d.ts.map +1 -1
- package/build-types/footnotes/index.d.ts +1 -1
- package/build-types/footnotes/index.d.ts.map +1 -1
- package/build-types/hooks/use-entity-block-editor.d.ts +1 -1
- package/build-types/hooks/use-entity-block-editor.d.ts.map +1 -1
- package/build-types/hooks/use-entity-id.d.ts.map +1 -1
- package/build-types/hooks/use-entity-prop.d.ts.map +1 -1
- package/build-types/hooks/use-resource-permissions.d.ts.map +1 -1
- package/build-types/index.d.ts +155 -153
- package/build-types/index.d.ts.map +1 -1
- package/build-types/locks/actions.d.ts +1 -1
- package/build-types/locks/actions.d.ts.map +1 -1
- package/build-types/locks/engine.d.ts +1 -1
- package/build-types/locks/engine.d.ts.map +1 -1
- package/build-types/locks/reducer.d.ts.map +1 -1
- package/build-types/locks/selectors.d.ts +2 -2
- package/build-types/locks/selectors.d.ts.map +1 -1
- package/build-types/locks/utils.d.ts +5 -5
- package/build-types/locks/utils.d.ts.map +1 -1
- package/build-types/name.d.ts +1 -1
- package/build-types/name.d.ts.map +1 -1
- package/build-types/private-actions.d.ts +45 -29
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-apis.d.ts +1 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/queried-data/actions.d.ts +3 -3
- package/build-types/queried-data/actions.d.ts.map +1 -1
- package/build-types/queried-data/get-query-parts.d.ts +10 -34
- package/build-types/queried-data/get-query-parts.d.ts.map +1 -1
- package/build-types/queried-data/index.d.ts +3 -3
- package/build-types/queried-data/index.d.ts.map +1 -1
- package/build-types/queried-data/reducer.d.ts +7 -23
- package/build-types/queried-data/reducer.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts +3 -3
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/reducer.d.ts +40 -32
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +130 -47
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +1 -1
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/types.d.ts +61 -6
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/block-selection-history.d.ts.map +1 -1
- package/build-types/utils/conservative-map-item.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +19 -9
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-selection.d.ts.map +1 -1
- package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
- package/build-types/utils/crdt-utils.d.ts +35 -2
- package/build-types/utils/crdt-utils.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/build-types/utils/forward-resolver.d.ts +2 -2
- package/build-types/utils/forward-resolver.d.ts.map +1 -1
- package/build-types/utils/get-nested-value.d.ts.map +1 -1
- package/build-types/utils/get-normalized-comma-separable.d.ts +1 -1
- package/build-types/utils/get-normalized-comma-separable.d.ts.map +1 -1
- package/build-types/utils/if-matching-action.d.ts +3 -3
- package/build-types/utils/if-matching-action.d.ts.map +1 -1
- package/build-types/utils/index.d.ts +12 -12
- package/build-types/utils/index.d.ts.map +1 -1
- package/build-types/utils/is-numeric-id.d.ts.map +1 -1
- package/build-types/utils/log-entity-deprecation.d.ts +1 -1
- package/build-types/utils/log-entity-deprecation.d.ts.map +1 -1
- package/build-types/utils/normalize-query-for-resolution.d.ts.map +1 -1
- package/build-types/utils/receive-intermediate-results.d.ts +1 -1
- package/build-types/utils/receive-intermediate-results.d.ts.map +1 -1
- package/build-types/utils/replace-action.d.ts +3 -3
- package/build-types/utils/replace-action.d.ts.map +1 -1
- package/build-types/utils/set-nested-value.d.ts.map +1 -1
- package/build-types/utils/user-permissions.d.ts +3 -3
- package/build-types/utils/user-permissions.d.ts.map +1 -1
- package/build-types/utils/with-weak-map-cache.d.ts +1 -1
- package/build-types/utils/with-weak-map-cache.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/actions.js +7 -9
- package/src/awareness/post-editor-awareness.ts +5 -2
- package/src/resolvers.js +2 -1
- package/src/test/actions.js +58 -0
- package/src/test/resolvers.js +115 -2
- package/src/test/rtc-rich-text-offset-space.test.js +204 -0
- package/src/types.ts +63 -6
- package/src/utils/block-selection-history.ts +5 -1
- package/src/utils/crdt-blocks.ts +316 -116
- package/src/utils/crdt-selection.ts +2 -1
- package/src/utils/crdt-user-selections.ts +9 -2
- package/src/utils/crdt-utils.ts +53 -10
- package/src/utils/crdt.ts +30 -4
- package/src/utils/test/crdt-blocks.ts +74 -18
- package/src/utils/test/crdt-utils.ts +18 -2
- package/src/utils/test/rtc-rich-text-cursor-scope.test.js +267 -0
- package/src/utils/test/rtc-rich-text-offset-space.test.js +469 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { act, render, waitFor } from '@testing-library/react';
|
|
5
|
+
import {
|
|
6
|
+
afterEach,
|
|
7
|
+
beforeEach,
|
|
8
|
+
describe,
|
|
9
|
+
expect,
|
|
10
|
+
it,
|
|
11
|
+
jest,
|
|
12
|
+
} from '@jest/globals';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* WordPress dependencies
|
|
16
|
+
*/
|
|
17
|
+
import {
|
|
18
|
+
getBlockTypes,
|
|
19
|
+
registerBlockType,
|
|
20
|
+
unregisterBlockType,
|
|
21
|
+
} from '@wordpress/blocks';
|
|
22
|
+
import { RichText } from '@wordpress/block-editor';
|
|
23
|
+
import { createRegistry, RegistryProvider } from '@wordpress/data';
|
|
24
|
+
import { Y } from '@wordpress/sync';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Mock sync manager accessor.
|
|
28
|
+
*/
|
|
29
|
+
jest.mock( '../sync', () => ( {
|
|
30
|
+
...jest.requireActual( '../sync' ),
|
|
31
|
+
getSyncManager: jest.fn(),
|
|
32
|
+
LOCAL_EDITOR_ORIGIN: 'local-editor',
|
|
33
|
+
} ) );
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Internal dependencies
|
|
37
|
+
*/
|
|
38
|
+
import { store as coreDataStore } from '../index';
|
|
39
|
+
import { CRDT_RECORD_MAP_KEY, getSyncManager } from '../sync';
|
|
40
|
+
import useEntityBlockEditor from '../hooks/use-entity-block-editor';
|
|
41
|
+
import { applyPostChangesToCRDTDoc } from '../utils/crdt';
|
|
42
|
+
import { getRootMap } from '../utils/crdt-utils';
|
|
43
|
+
|
|
44
|
+
const mockGetSyncManager = jest.mocked( getSyncManager );
|
|
45
|
+
|
|
46
|
+
const postTypeConfig = {
|
|
47
|
+
kind: 'postType',
|
|
48
|
+
name: 'post',
|
|
49
|
+
baseURL: '/wp/v2/posts',
|
|
50
|
+
transientEdits: { blocks: true, selection: true },
|
|
51
|
+
mergedEdits: { meta: true },
|
|
52
|
+
rawAttributes: [ 'title', 'excerpt', 'content' ],
|
|
53
|
+
syncConfig: {},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const postTypeEntity = {
|
|
57
|
+
slug: 'post',
|
|
58
|
+
rest_base: 'posts',
|
|
59
|
+
labels: {
|
|
60
|
+
item_updated: 'Updated Post',
|
|
61
|
+
item_published: 'Post published',
|
|
62
|
+
item_reverted_to_draft: 'Post reverted to draft.',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const OLD_HTML = '<em>italic</em><em>italic</em>';
|
|
67
|
+
const NEW_HTML = '<em>italic</em>beta';
|
|
68
|
+
const TEXT_OFFSET = 10;
|
|
69
|
+
const SYNCED_PROPERTIES = new Set( [ 'blocks' ] );
|
|
70
|
+
|
|
71
|
+
function createRegistryWithStores() {
|
|
72
|
+
const registry = createRegistry();
|
|
73
|
+
|
|
74
|
+
registry.register( coreDataStore );
|
|
75
|
+
registry.dispatch( coreDataStore ).addEntities( [ postTypeConfig ] );
|
|
76
|
+
registry
|
|
77
|
+
.dispatch( coreDataStore )
|
|
78
|
+
.receiveEntityRecords( 'root', 'postType', [ postTypeEntity ] );
|
|
79
|
+
registry
|
|
80
|
+
.dispatch( coreDataStore )
|
|
81
|
+
.receiveEntityRecords( 'postType', 'post', [
|
|
82
|
+
{
|
|
83
|
+
id: 1,
|
|
84
|
+
type: 'post',
|
|
85
|
+
content: {
|
|
86
|
+
raw: `<!-- wp:paragraph --><p>${ OLD_HTML }</p><!-- /wp:paragraph -->`,
|
|
87
|
+
rendered: `<p>${ OLD_HTML }</p>`,
|
|
88
|
+
},
|
|
89
|
+
meta: {},
|
|
90
|
+
},
|
|
91
|
+
] );
|
|
92
|
+
|
|
93
|
+
return registry;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function readFirstBlockContentFromDoc( doc ) {
|
|
97
|
+
const ymap = getRootMap( doc, CRDT_RECORD_MAP_KEY );
|
|
98
|
+
const yblocks = ymap.get( 'blocks' );
|
|
99
|
+
const attrs = yblocks.get( 0 ).get( 'attributes' );
|
|
100
|
+
return attrs.get( 'content' ).toString();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
describe( 'useEntityBlockEditor RTC rich-text offset-space bug', () => {
|
|
104
|
+
let crdtDoc;
|
|
105
|
+
|
|
106
|
+
beforeEach( () => {
|
|
107
|
+
crdtDoc = new Y.Doc();
|
|
108
|
+
|
|
109
|
+
registerBlockType( 'core/paragraph', {
|
|
110
|
+
apiVersion: 3,
|
|
111
|
+
title: 'Paragraph',
|
|
112
|
+
category: 'text',
|
|
113
|
+
attributes: {
|
|
114
|
+
content: {
|
|
115
|
+
type: 'rich-text',
|
|
116
|
+
source: 'rich-text',
|
|
117
|
+
selector: 'p',
|
|
118
|
+
role: 'content',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
edit: () => null,
|
|
122
|
+
save: ( { attributes } ) => (
|
|
123
|
+
<p>
|
|
124
|
+
<RichText.Content value={ attributes.content } />
|
|
125
|
+
</p>
|
|
126
|
+
),
|
|
127
|
+
} );
|
|
128
|
+
|
|
129
|
+
mockGetSyncManager.mockReturnValue( {
|
|
130
|
+
update: jest.fn( ( _objectType, _objectId, changes ) => {
|
|
131
|
+
applyPostChangesToCRDTDoc(
|
|
132
|
+
crdtDoc,
|
|
133
|
+
changes,
|
|
134
|
+
SYNCED_PROPERTIES
|
|
135
|
+
);
|
|
136
|
+
} ),
|
|
137
|
+
} );
|
|
138
|
+
} );
|
|
139
|
+
|
|
140
|
+
afterEach( () => {
|
|
141
|
+
crdtDoc.destroy();
|
|
142
|
+
mockGetSyncManager.mockReset();
|
|
143
|
+
if (
|
|
144
|
+
getBlockTypes().some( ( block ) => block.name === 'core/paragraph' )
|
|
145
|
+
) {
|
|
146
|
+
unregisterBlockType( 'core/paragraph' );
|
|
147
|
+
}
|
|
148
|
+
} );
|
|
149
|
+
|
|
150
|
+
it( 'preserves formatted paragraph content when onInput forwards blocks plus selection', async () => {
|
|
151
|
+
const registry = createRegistryWithStores();
|
|
152
|
+
let blocks;
|
|
153
|
+
let onInput;
|
|
154
|
+
|
|
155
|
+
const TestComponent = () => {
|
|
156
|
+
[ blocks, onInput ] = useEntityBlockEditor( 'postType', 'post', {
|
|
157
|
+
id: 1,
|
|
158
|
+
} );
|
|
159
|
+
|
|
160
|
+
return <div />;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
render(
|
|
164
|
+
<RegistryProvider value={ registry }>
|
|
165
|
+
<TestComponent />
|
|
166
|
+
</RegistryProvider>
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
await waitFor( () => expect( blocks ).toHaveLength( 1 ) );
|
|
170
|
+
|
|
171
|
+
const selection = {
|
|
172
|
+
selectionStart: {
|
|
173
|
+
clientId: blocks[ 0 ].clientId,
|
|
174
|
+
attributeKey: 'content',
|
|
175
|
+
offset: TEXT_OFFSET,
|
|
176
|
+
},
|
|
177
|
+
selectionEnd: {
|
|
178
|
+
clientId: blocks[ 0 ].clientId,
|
|
179
|
+
attributeKey: 'content',
|
|
180
|
+
offset: TEXT_OFFSET,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
act( () => {
|
|
185
|
+
onInput( blocks, { selection } );
|
|
186
|
+
} );
|
|
187
|
+
|
|
188
|
+
const nextBlocks = [
|
|
189
|
+
{
|
|
190
|
+
...blocks[ 0 ],
|
|
191
|
+
attributes: {
|
|
192
|
+
...blocks[ 0 ].attributes,
|
|
193
|
+
content: NEW_HTML,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
act( () => {
|
|
199
|
+
onInput( nextBlocks, { selection } );
|
|
200
|
+
} );
|
|
201
|
+
|
|
202
|
+
expect( readFirstBlockContentFromDoc( crdtDoc ) ).toBe( NEW_HTML );
|
|
203
|
+
} );
|
|
204
|
+
} );
|
package/src/types.ts
CHANGED
|
@@ -32,18 +32,75 @@ export interface AnyFunction {
|
|
|
32
32
|
export type AbsoluteBlockIndexPath = number[];
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Describes part of a visible selection in the editor. Namely, either a cursor
|
|
36
|
+
* position within a block or a block entirely contained within a selection.
|
|
36
37
|
*
|
|
37
|
-
*
|
|
38
|
-
* `
|
|
38
|
+
* This description covers multiple selection scenarios, each of which impacts
|
|
39
|
+
* how the `attributeKey` and `offset` are set. These two parameters indicate
|
|
40
|
+
* where in a RichText component the cursor sits and with which block attribute
|
|
41
|
+
* that RichText component is associated.
|
|
39
42
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
+
* - When a selection covers an entire block or covers multiple blocks, there
|
|
44
|
+
* is no associated RichText, so both of the parameters are unset.
|
|
45
|
+
*
|
|
46
|
+
* - When a selection starts, ends, or is a simple position within a block,
|
|
47
|
+
* both parameters will be set accordingly.
|
|
48
|
+
*
|
|
49
|
+
* - When a block is being inserted into a document, however, there are multiple
|
|
50
|
+
* stages determining which parameters are set.
|
|
51
|
+
*
|
|
52
|
+
* 1. A block is created in the data store, but has no appearance in the
|
|
53
|
+
* editor otherwise. Both parameters are unset.
|
|
54
|
+
*
|
|
55
|
+
* 2. The block has loaded into the editor and there is a RichText field,
|
|
56
|
+
* but editor focus hasn’t yet placed a browser selection inside it.
|
|
57
|
+
* Only the `attributeKey` is set.
|
|
58
|
+
*
|
|
59
|
+
* 3. The browser has focused into a RichText field and both parameters are set.
|
|
60
|
+
*
|
|
61
|
+
* Selections are thus dynamic because block creation itself loads through multiple
|
|
62
|
+
* intermediate stages before someone is able to highlight, type, or modify text.
|
|
63
|
+
*
|
|
64
|
+
* This type is duplicated to avoid creating circular dependencies.
|
|
65
|
+
* @see {import("@wordpress/block-editor/src/store/actions").WPBlockSelection}
|
|
66
|
+
* @see {import("@wordpress/block-editor/src/store/selectors").WPBlockSelection}
|
|
67
|
+
* @see {import("@wordpress/editor/src/store/selectors").WPBlockSelection}
|
|
68
|
+
*
|
|
69
|
+
* @todo Move this into a canonical types file which can be imported in separate
|
|
70
|
+
* packages without causing circular dependencies.
|
|
43
71
|
*/
|
|
44
72
|
export interface WPBlockSelection {
|
|
73
|
+
/**
|
|
74
|
+
* The selection cursor (start or end) is found within this block.
|
|
75
|
+
* or this entire block is contained within a multi-block selection.
|
|
76
|
+
*/
|
|
45
77
|
clientId: string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* When a selection cursor appears within a RichText component which
|
|
81
|
+
* maps back to a block’s attribute, e.g. a paragraph block’s `content`
|
|
82
|
+
* attribute, this will hold the attribute key for that associated
|
|
83
|
+
* block attribute.
|
|
84
|
+
*
|
|
85
|
+
* An attribute key is mostly the same as an attribute name, but in some
|
|
86
|
+
* circumstances, such as in a multiline attribute, there can be multiple
|
|
87
|
+
* RichText instances associated with a given attribute. The key will
|
|
88
|
+
* usually be the attribute name verbatim, but in these cases, an index
|
|
89
|
+
* will be appended to differentiate the multiple RichText instances
|
|
90
|
+
* associated with the array-like attribute.
|
|
91
|
+
*
|
|
92
|
+
* Technically, the `attributeKey` is the value stored in the DOM node
|
|
93
|
+
* for a RichText instance in the `data-wp-block-attribute-key` attribute.
|
|
94
|
+
* This “key” links the actual instance with the block attribute, provided
|
|
95
|
+
* by the `identifier` React prop when creating a `<RichText>` element.
|
|
96
|
+
*/
|
|
46
97
|
attributeKey?: string;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* When a selection cursor appears within a block, it can be found this
|
|
101
|
+
* many Unicode code points into the RichText component’s decoded text
|
|
102
|
+
* which is associated with the given attribute key.
|
|
103
|
+
*/
|
|
47
104
|
offset?: number;
|
|
48
105
|
}
|
|
49
106
|
|
|
@@ -10,6 +10,7 @@ import { Y } from '@wordpress/sync';
|
|
|
10
10
|
* Internal dependencies
|
|
11
11
|
*/
|
|
12
12
|
import {
|
|
13
|
+
asRichTextOffset,
|
|
13
14
|
findBlockByClientIdInDoc,
|
|
14
15
|
richTextOffsetToHtmlIndex,
|
|
15
16
|
} from './crdt-utils';
|
|
@@ -166,7 +167,10 @@ function convertWPBlockSelectionToSelection(
|
|
|
166
167
|
const offset = selection.offset ?? 0;
|
|
167
168
|
const relativePosition = Y.createRelativePositionFromTypeIndex(
|
|
168
169
|
changedYText,
|
|
169
|
-
richTextOffsetToHtmlIndex(
|
|
170
|
+
richTextOffsetToHtmlIndex(
|
|
171
|
+
changedYText.toString(),
|
|
172
|
+
asRichTextOffset( offset )
|
|
173
|
+
)
|
|
170
174
|
);
|
|
171
175
|
|
|
172
176
|
return {
|