@wordpress/core-data 7.41.2-next.v.202603161435.0 → 7.43.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 (161) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/build/awareness/post-editor-awareness.cjs +12 -5
  3. package/build/awareness/post-editor-awareness.cjs.map +2 -2
  4. package/build/entities.cjs +30 -5
  5. package/build/entities.cjs.map +2 -2
  6. package/build/hooks/use-post-editor-awareness-state.cjs +1 -1
  7. package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
  8. package/build/private-actions.cjs +10 -0
  9. package/build/private-actions.cjs.map +2 -2
  10. package/build/private-selectors.cjs +20 -3
  11. package/build/private-selectors.cjs.map +2 -2
  12. package/build/queried-data/get-query-parts.cjs +8 -0
  13. package/build/queried-data/get-query-parts.cjs.map +2 -2
  14. package/build/queried-data/reducer.cjs +15 -9
  15. package/build/queried-data/reducer.cjs.map +2 -2
  16. package/build/queried-data/selectors.cjs +10 -2
  17. package/build/queried-data/selectors.cjs.map +2 -2
  18. package/build/reducer.cjs +22 -3
  19. package/build/reducer.cjs.map +2 -2
  20. package/build/resolvers.cjs +16 -8
  21. package/build/resolvers.cjs.map +2 -2
  22. package/build/selectors.cjs +16 -8
  23. package/build/selectors.cjs.map +2 -2
  24. package/build/sync.cjs +3 -0
  25. package/build/sync.cjs.map +2 -2
  26. package/build/types.cjs.map +2 -2
  27. package/build/utils/block-selection-history.cjs +1 -1
  28. package/build/utils/block-selection-history.cjs.map +2 -2
  29. package/build/utils/crdt-blocks.cjs +66 -5
  30. package/build/utils/crdt-blocks.cjs.map +2 -2
  31. package/build/utils/crdt-selection.cjs +4 -1
  32. package/build/utils/crdt-selection.cjs.map +2 -2
  33. package/build/utils/crdt-text.cjs +52 -0
  34. package/build/utils/crdt-text.cjs.map +7 -0
  35. package/build/utils/crdt-user-selections.cjs +1 -1
  36. package/build/utils/crdt-user-selections.cjs.map +2 -2
  37. package/build/utils/crdt-utils.cjs +54 -2
  38. package/build/utils/crdt-utils.cjs.map +2 -2
  39. package/build/utils/crdt.cjs +9 -23
  40. package/build/utils/crdt.cjs.map +2 -2
  41. package/build/utils/index.cjs +0 -3
  42. package/build/utils/index.cjs.map +2 -2
  43. package/build-module/awareness/post-editor-awareness.mjs +12 -5
  44. package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
  45. package/build-module/entities.mjs +30 -5
  46. package/build-module/entities.mjs.map +2 -2
  47. package/build-module/hooks/use-post-editor-awareness-state.mjs +1 -1
  48. package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
  49. package/build-module/private-actions.mjs +9 -0
  50. package/build-module/private-actions.mjs.map +2 -2
  51. package/build-module/private-selectors.mjs +19 -3
  52. package/build-module/private-selectors.mjs.map +2 -2
  53. package/build-module/queried-data/get-query-parts.mjs +8 -0
  54. package/build-module/queried-data/get-query-parts.mjs.map +2 -2
  55. package/build-module/queried-data/reducer.mjs +15 -9
  56. package/build-module/queried-data/reducer.mjs.map +2 -2
  57. package/build-module/queried-data/selectors.mjs +10 -2
  58. package/build-module/queried-data/selectors.mjs.map +2 -2
  59. package/build-module/reducer.mjs +20 -2
  60. package/build-module/reducer.mjs.map +2 -2
  61. package/build-module/resolvers.mjs +14 -7
  62. package/build-module/resolvers.mjs.map +2 -2
  63. package/build-module/selectors.mjs +16 -9
  64. package/build-module/selectors.mjs.map +2 -2
  65. package/build-module/sync.mjs +2 -0
  66. package/build-module/sync.mjs.map +2 -2
  67. package/build-module/types.mjs.map +2 -2
  68. package/build-module/utils/block-selection-history.mjs +5 -2
  69. package/build-module/utils/block-selection-history.mjs.map +2 -2
  70. package/build-module/utils/crdt-blocks.mjs +65 -5
  71. package/build-module/utils/crdt-blocks.mjs.map +2 -2
  72. package/build-module/utils/crdt-selection.mjs +8 -2
  73. package/build-module/utils/crdt-selection.mjs.map +2 -2
  74. package/build-module/utils/crdt-text.mjs +26 -0
  75. package/build-module/utils/crdt-text.mjs.map +7 -0
  76. package/build-module/utils/crdt-user-selections.mjs +2 -2
  77. package/build-module/utils/crdt-user-selections.mjs.map +2 -2
  78. package/build-module/utils/crdt-utils.mjs +51 -1
  79. package/build-module/utils/crdt-utils.mjs.map +2 -2
  80. package/build-module/utils/crdt.mjs +10 -23
  81. package/build-module/utils/crdt.mjs.map +2 -2
  82. package/build-module/utils/index.mjs +8 -10
  83. package/build-module/utils/index.mjs.map +2 -2
  84. package/build-types/awareness/post-editor-awareness.d.ts +2 -2
  85. package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
  86. package/build-types/entities.d.ts.map +1 -1
  87. package/build-types/index.d.ts.map +1 -1
  88. package/build-types/private-actions.d.ts +10 -0
  89. package/build-types/private-actions.d.ts.map +1 -1
  90. package/build-types/private-selectors.d.ts +11 -4
  91. package/build-types/private-selectors.d.ts.map +1 -1
  92. package/build-types/queried-data/get-query-parts.d.ts +13 -14
  93. package/build-types/queried-data/get-query-parts.d.ts.map +1 -1
  94. package/build-types/queried-data/reducer.d.ts +11 -5
  95. package/build-types/queried-data/reducer.d.ts.map +1 -1
  96. package/build-types/queried-data/selectors.d.ts.map +1 -1
  97. package/build-types/reducer.d.ts +11 -0
  98. package/build-types/reducer.d.ts.map +1 -1
  99. package/build-types/resolvers.d.ts +3 -0
  100. package/build-types/resolvers.d.ts.map +1 -1
  101. package/build-types/selectors.d.ts +1 -0
  102. package/build-types/selectors.d.ts.map +1 -1
  103. package/build-types/sync.d.ts +2 -2
  104. package/build-types/sync.d.ts.map +1 -1
  105. package/build-types/types.d.ts +4 -2
  106. package/build-types/types.d.ts.map +1 -1
  107. package/build-types/utils/block-selection-history.d.ts.map +1 -1
  108. package/build-types/utils/crdt-blocks.d.ts +11 -0
  109. package/build-types/utils/crdt-blocks.d.ts.map +1 -1
  110. package/build-types/utils/crdt-selection.d.ts.map +1 -1
  111. package/build-types/utils/crdt-text.d.ts +16 -0
  112. package/build-types/utils/crdt-text.d.ts.map +1 -0
  113. package/build-types/utils/crdt-user-selections.d.ts +1 -2
  114. package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
  115. package/build-types/utils/crdt-utils.d.ts +20 -0
  116. package/build-types/utils/crdt-utils.d.ts.map +1 -1
  117. package/build-types/utils/crdt.d.ts +6 -7
  118. package/build-types/utils/crdt.d.ts.map +1 -1
  119. package/build-types/utils/index.d.ts +0 -1
  120. package/build-types/utils/test/crdt-utils.d.ts +2 -0
  121. package/build-types/utils/test/crdt-utils.d.ts.map +1 -0
  122. package/package.json +18 -18
  123. package/src/awareness/post-editor-awareness.ts +13 -6
  124. package/src/awareness/test/post-editor-awareness.ts +15 -10
  125. package/src/entities.js +36 -5
  126. package/src/hooks/test/use-post-editor-awareness-state.ts +3 -3
  127. package/src/hooks/use-post-editor-awareness-state.ts +1 -1
  128. package/src/private-actions.js +18 -0
  129. package/src/private-selectors.ts +37 -4
  130. package/src/queried-data/get-query-parts.js +14 -7
  131. package/src/queried-data/reducer.js +28 -15
  132. package/src/queried-data/selectors.js +11 -3
  133. package/src/queried-data/test/get-query-parts.js +34 -0
  134. package/src/queried-data/test/reducer.js +78 -8
  135. package/src/queried-data/test/selectors.js +171 -0
  136. package/src/reducer.js +31 -0
  137. package/src/resolvers.js +23 -7
  138. package/src/selectors.ts +20 -19
  139. package/src/sync.ts +2 -0
  140. package/src/test/entities.js +185 -1
  141. package/src/types.ts +8 -2
  142. package/src/utils/block-selection-history.ts +5 -2
  143. package/src/utils/crdt-blocks.ts +115 -5
  144. package/src/utils/crdt-selection.ts +8 -2
  145. package/src/utils/crdt-text.ts +43 -0
  146. package/src/utils/crdt-user-selections.ts +13 -13
  147. package/src/utils/crdt-utils.ts +99 -0
  148. package/src/utils/crdt.ts +18 -30
  149. package/src/utils/index.js +0 -1
  150. package/src/utils/test/crdt-blocks.ts +199 -0
  151. package/src/utils/test/crdt-user-selections.ts +5 -0
  152. package/src/utils/test/crdt-utils.ts +387 -0
  153. package/src/utils/test/crdt.ts +229 -54
  154. package/build/utils/is-raw-attribute.cjs +0 -29
  155. package/build/utils/is-raw-attribute.cjs.map +0 -7
  156. package/build-module/utils/is-raw-attribute.mjs +0 -8
  157. package/build-module/utils/is-raw-attribute.mjs.map +0 -7
  158. package/build-types/utils/is-raw-attribute.d.ts +0 -10
  159. package/build-types/utils/is-raw-attribute.d.ts.map +0 -1
  160. package/src/utils/is-raw-attribute.js +0 -11
  161. package/src/utils/test/is-raw-attribute.js +0 -22
@@ -8,6 +8,49 @@ import { Y } from '@wordpress/sync';
8
8
  */
9
9
  import { describe, expect, it, jest, beforeEach } from '@jest/globals';
10
10
 
11
+ /**
12
+ * Mock getBlockTypes so isRichTextAttribute can identify rich-text attrs.
13
+ */
14
+ jest.mock( '@wordpress/blocks', () => {
15
+ const actual = jest.requireActual( '@wordpress/blocks' ) as Record<
16
+ string,
17
+ unknown
18
+ >;
19
+ return {
20
+ ...actual,
21
+ getBlockTypes: () => [
22
+ {
23
+ name: 'core/paragraph',
24
+ attributes: { content: { type: 'rich-text' } },
25
+ },
26
+ {
27
+ name: 'core/table',
28
+ attributes: {
29
+ hasFixedLayout: { type: 'boolean' },
30
+ caption: { type: 'rich-text' },
31
+ body: {
32
+ type: 'array',
33
+ query: {
34
+ cells: {
35
+ type: 'array',
36
+ query: {
37
+ content: { type: 'rich-text' },
38
+ tag: { type: 'string' },
39
+ },
40
+ },
41
+ },
42
+ },
43
+ },
44
+ },
45
+ ],
46
+ };
47
+ } );
48
+
49
+ /**
50
+ * WordPress dependencies
51
+ */
52
+ import { RichTextData } from '@wordpress/rich-text';
53
+
11
54
  /**
12
55
  * Internal dependencies
13
56
  */
@@ -22,7 +65,22 @@ import {
22
65
  import type { YBlock, YBlockRecord, YBlocks } from '../crdt-blocks';
23
66
  import { updateSelectionHistory } from '../crdt-selection';
24
67
  import { createYMap, getRootMap, type YMapWrap } from '../crdt-utils';
25
- import type { Post, Type } from '../../entity-types';
68
+ import type { Post } from '../../entity-types';
69
+
70
+ // Default synced properties matching the base set built in entities.js,
71
+ // plus 'categories' and 'tags' as example taxonomy rest_base values.
72
+ const defaultSyncedProperties = new Set< string >( [
73
+ 'blocks',
74
+ 'categories',
75
+ 'content',
76
+ 'date',
77
+ 'excerpt',
78
+ 'meta',
79
+ 'slug',
80
+ 'status',
81
+ 'tags',
82
+ 'title',
83
+ ] );
26
84
 
27
85
  describe( 'crdt', () => {
28
86
  let doc: Y.Doc;
@@ -37,8 +95,6 @@ describe( 'crdt', () => {
37
95
  } );
38
96
 
39
97
  describe( 'applyPostChangesToCRDTDoc', () => {
40
- const mockPostType = {} as Type;
41
-
42
98
  let map: YMapWrap< YPostRecord >;
43
99
 
44
100
  beforeEach( () => {
@@ -50,7 +106,7 @@ describe( 'crdt', () => {
50
106
  title: 'New Title',
51
107
  } as PostChanges;
52
108
 
53
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
109
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
54
110
 
55
111
  const title = map.get( 'title' );
56
112
  expect( title ).toBeInstanceOf( Y.Text );
@@ -63,7 +119,7 @@ describe( 'crdt', () => {
63
119
  unsyncedProperty: 'value',
64
120
  } as unknown as PostChanges;
65
121
 
66
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
122
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
67
123
 
68
124
  expect( map.has( 'unsyncedProperty' ) ).toBe( false );
69
125
  expect( map.get( 'title' )?.toString() ).toBe( 'New Title' );
@@ -74,7 +130,7 @@ describe( 'crdt', () => {
74
130
  title: () => 'function value',
75
131
  } as unknown as PostChanges;
76
132
 
77
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
133
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
78
134
 
79
135
  expect( map.has( 'title' ) ).toBe( false );
80
136
  } );
@@ -84,7 +140,7 @@ describe( 'crdt', () => {
84
140
  title: { raw: 'Raw Title', rendered: 'Rendered Title' },
85
141
  };
86
142
 
87
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
143
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
88
144
 
89
145
  const title = map.get( 'title' );
90
146
  expect( title ).toBeInstanceOf( Y.Text );
@@ -96,7 +152,7 @@ describe( 'crdt', () => {
96
152
  title: 'Auto Draft',
97
153
  } as PostChanges;
98
154
 
99
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
155
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
100
156
 
101
157
  const title = map.get( 'title' );
102
158
  expect( title ).toBeInstanceOf( Y.Text );
@@ -108,7 +164,7 @@ describe( 'crdt', () => {
108
164
  applyPostChangesToCRDTDoc(
109
165
  doc,
110
166
  { title: '' } as PostChanges,
111
- mockPostType
167
+ defaultSyncedProperties
112
168
  );
113
169
 
114
170
  const title = map.get( 'title' );
@@ -119,7 +175,7 @@ describe( 'crdt', () => {
119
175
  applyPostChangesToCRDTDoc(
120
176
  doc,
121
177
  { title: 'Auto Draft' } as PostChanges,
122
- mockPostType
178
+ defaultSyncedProperties
123
179
  );
124
180
 
125
181
  expect( map.get( 'title' )?.toString() ).toBe( '' );
@@ -134,7 +190,7 @@ describe( 'crdt', () => {
134
190
  },
135
191
  };
136
192
 
137
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
193
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
138
194
 
139
195
  const excerpt = map.get( 'excerpt' );
140
196
  expect( excerpt ).toBeInstanceOf( Y.Text );
@@ -146,7 +202,7 @@ describe( 'crdt', () => {
146
202
  slug: '',
147
203
  };
148
204
 
149
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
205
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
150
206
 
151
207
  expect( map.has( 'slug' ) ).toBe( false );
152
208
  } );
@@ -156,7 +212,7 @@ describe( 'crdt', () => {
156
212
  slug: 'my-post-slug',
157
213
  };
158
214
 
159
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
215
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
160
216
 
161
217
  expect( map.get( 'slug' ) ).toBe( 'my-post-slug' );
162
218
  } );
@@ -174,7 +230,7 @@ describe( 'crdt', () => {
174
230
  ],
175
231
  };
176
232
 
177
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
233
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
178
234
 
179
235
  expect( ( map.get( 'blocks' ) as YBlocks ).toJSON() ).toEqual(
180
236
  changes.blocks
@@ -186,7 +242,7 @@ describe( 'crdt', () => {
186
242
  blocks: [],
187
243
  };
188
244
 
189
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
245
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
190
246
 
191
247
  const blocks = map.get( 'blocks' );
192
248
  expect( blocks ).toBeInstanceOf( Y.Array );
@@ -200,7 +256,7 @@ describe( 'crdt', () => {
200
256
  blocks: undefined,
201
257
  };
202
258
 
203
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
259
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
204
260
 
205
261
  // The key should still exist, but the value should be undefined.
206
262
  expect( map.has( 'blocks' ) ).toBe( true );
@@ -212,7 +268,7 @@ describe( 'crdt', () => {
212
268
  content: 'Hello, world!',
213
269
  } as PostChanges;
214
270
 
215
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
271
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
216
272
 
217
273
  const content = map.get( 'content' );
218
274
  expect( content ).toBeInstanceOf( Y.Text );
@@ -227,7 +283,7 @@ describe( 'crdt', () => {
227
283
  },
228
284
  } as PostChanges;
229
285
 
230
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
286
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
231
287
 
232
288
  const content = map.get( 'content' );
233
289
  expect( content ).toBeInstanceOf( Y.Text );
@@ -241,7 +297,7 @@ describe( 'crdt', () => {
241
297
  applyPostChangesToCRDTDoc(
242
298
  doc,
243
299
  { title: 'Old Title' } as PostChanges,
244
- mockPostType
300
+ defaultSyncedProperties
245
301
  );
246
302
  const titleRef = map.get( 'title' );
247
303
 
@@ -249,7 +305,7 @@ describe( 'crdt', () => {
249
305
  applyPostChangesToCRDTDoc(
250
306
  doc,
251
307
  { title: 'New Title' } as PostChanges,
252
- mockPostType
308
+ defaultSyncedProperties
253
309
  );
254
310
 
255
311
  expect( map.get( 'title' ) ).toBe( titleRef );
@@ -261,7 +317,7 @@ describe( 'crdt', () => {
261
317
  applyPostChangesToCRDTDoc(
262
318
  doc,
263
319
  { content: 'Old content' } as PostChanges,
264
- mockPostType
320
+ defaultSyncedProperties
265
321
  );
266
322
  const contentRef = map.get( 'content' );
267
323
 
@@ -269,7 +325,7 @@ describe( 'crdt', () => {
269
325
  applyPostChangesToCRDTDoc(
270
326
  doc,
271
327
  { content: 'New content' } as PostChanges,
272
- mockPostType
328
+ defaultSyncedProperties
273
329
  );
274
330
 
275
331
  expect( map.get( 'content' ) ).toBe( contentRef );
@@ -281,7 +337,7 @@ describe( 'crdt', () => {
281
337
  applyPostChangesToCRDTDoc(
282
338
  doc,
283
339
  { excerpt: 'Old excerpt' } as PostChanges,
284
- mockPostType
340
+ defaultSyncedProperties
285
341
  );
286
342
  const excerptRef = map.get( 'excerpt' );
287
343
 
@@ -289,7 +345,7 @@ describe( 'crdt', () => {
289
345
  applyPostChangesToCRDTDoc(
290
346
  doc,
291
347
  { excerpt: 'New excerpt' } as PostChanges,
292
- mockPostType
348
+ defaultSyncedProperties
293
349
  );
294
350
 
295
351
  expect( map.get( 'excerpt' ) ).toBe( excerptRef );
@@ -307,7 +363,7 @@ describe( 'crdt', () => {
307
363
  metaMap.set( 'some_meta', 'old value' );
308
364
  map.set( 'meta', metaMap );
309
365
 
310
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
366
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
311
367
 
312
368
  expect( metaMap.get( 'some_meta' ) ).toBe( 'new value' );
313
369
  } );
@@ -323,7 +379,7 @@ describe( 'crdt', () => {
323
379
  metaMap.set( 'some_meta', 'old value' );
324
380
  map.set( 'meta', metaMap );
325
381
 
326
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
382
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
327
383
 
328
384
  expect( metaMap.get( 'some_meta' ) ).toStrictEqual( [
329
385
  'value',
@@ -338,23 +394,40 @@ describe( 'crdt', () => {
338
394
  },
339
395
  };
340
396
 
341
- applyPostChangesToCRDTDoc( doc, changes, mockPostType );
397
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
342
398
 
343
399
  const metaMap = map.get( 'meta' );
344
400
  expect( metaMap ).toBeInstanceOf( Y.Map );
345
401
  expect( metaMap?.get( 'custom_field' ) ).toBe( 'value' );
346
402
  } );
403
+
404
+ it( 'syncs taxonomy rest_base values included in syncedProperties', () => {
405
+ const changes = {
406
+ categories: [ 1, 2, 3 ],
407
+ genre: [ 10, 20 ], // should be ignored
408
+ tags: [ 4, 5 ],
409
+ } as unknown as PostChanges;
410
+
411
+ applyPostChangesToCRDTDoc( doc, changes, defaultSyncedProperties );
412
+
413
+ expect( map.get( 'categories' ) ).toEqual( [ 1, 2, 3 ] );
414
+ expect( map.get( 'genre' ) ).toBeUndefined();
415
+ expect( map.get( 'tags' ) ).toEqual( [ 4, 5 ] );
416
+
417
+ const customSyncedProperties = new Set( [
418
+ ...defaultSyncedProperties,
419
+ 'genre', // now included
420
+ ] );
421
+
422
+ applyPostChangesToCRDTDoc( doc, changes, customSyncedProperties );
423
+
424
+ expect( map.get( 'categories' ) ).toEqual( [ 1, 2, 3 ] );
425
+ expect( map.get( 'genre' ) ).toEqual( [ 10, 20 ] );
426
+ expect( map.get( 'tags' ) ).toEqual( [ 4, 5 ] );
427
+ } );
347
428
  } );
348
429
 
349
430
  describe( 'getPostChangesFromCRDTDoc', () => {
350
- const mockPostType = {
351
- slug: 'post',
352
- supports: {
353
- title: true,
354
- editor: true,
355
- },
356
- } as unknown as Type;
357
-
358
431
  let map: YMapWrap< YPostRecord >;
359
432
 
360
433
  beforeEach( () => {
@@ -373,7 +446,7 @@ describe( 'crdt', () => {
373
446
  const changes = getPostChangesFromCRDTDoc(
374
447
  doc,
375
448
  editedRecord,
376
- mockPostType
449
+ defaultSyncedProperties
377
450
  );
378
451
 
379
452
  expect( changes.title ).toBe( 'CRDT Title' );
@@ -388,7 +461,7 @@ describe( 'crdt', () => {
388
461
  const changes = getPostChangesFromCRDTDoc(
389
462
  doc,
390
463
  editedRecord,
391
- mockPostType
464
+ defaultSyncedProperties
392
465
  );
393
466
 
394
467
  expect( changes ).not.toHaveProperty( 'unsyncedProp' );
@@ -405,7 +478,7 @@ describe( 'crdt', () => {
405
478
  const changes = getPostChangesFromCRDTDoc(
406
479
  doc,
407
480
  editedRecord,
408
- mockPostType
481
+ defaultSyncedProperties
409
482
  );
410
483
 
411
484
  expect( changes ).not.toHaveProperty( 'status' );
@@ -424,7 +497,7 @@ describe( 'crdt', () => {
424
497
  const changesWithEmptyDate = getPostChangesFromCRDTDoc(
425
498
  doc,
426
499
  editedRecord,
427
- mockPostType
500
+ defaultSyncedProperties
428
501
  );
429
502
 
430
503
  expect( changesWithEmptyDate ).not.toHaveProperty( 'date' );
@@ -434,7 +507,7 @@ describe( 'crdt', () => {
434
507
  const changesWithDefinedDate = getPostChangesFromCRDTDoc(
435
508
  doc,
436
509
  editedRecord,
437
- mockPostType
510
+ defaultSyncedProperties
438
511
  );
439
512
 
440
513
  expect( changesWithDefinedDate ).not.toHaveProperty( 'date' );
@@ -453,7 +526,7 @@ describe( 'crdt', () => {
453
526
  const changesWithEmptyDate = getPostChangesFromCRDTDoc(
454
527
  doc,
455
528
  editedRecord,
456
- mockPostType
529
+ defaultSyncedProperties
457
530
  );
458
531
 
459
532
  expect( changesWithEmptyDate ).not.toHaveProperty( 'date' );
@@ -463,7 +536,7 @@ describe( 'crdt', () => {
463
536
  const changesWithDefinedDate = getPostChangesFromCRDTDoc(
464
537
  doc,
465
538
  editedRecord,
466
- mockPostType
539
+ defaultSyncedProperties
467
540
  );
468
541
 
469
542
  expect( changesWithDefinedDate ).not.toHaveProperty( 'date' );
@@ -479,12 +552,74 @@ describe( 'crdt', () => {
479
552
  const changes = getPostChangesFromCRDTDoc(
480
553
  doc,
481
554
  editedRecord,
482
- mockPostType
555
+ defaultSyncedProperties
483
556
  );
484
557
 
485
558
  expect( changes ).toHaveProperty( 'blocks' );
486
559
  } );
487
560
 
561
+ it( 'returns rich-text block attributes as RichTextData, not strings', () => {
562
+ // Simulate User A writing a paragraph block into the CRDT doc.
563
+ addBlockToDoc( map, 'block-1', 'Hello world' );
564
+
565
+ // Simulate User B reading the CRDT doc with no local blocks.
566
+ const editedRecord = { blocks: [] } as unknown as Post;
567
+
568
+ const changes = getPostChangesFromCRDTDoc(
569
+ doc,
570
+ editedRecord,
571
+ defaultSyncedProperties
572
+ );
573
+
574
+ const block = ( changes.blocks as any[] )?.[ 0 ];
575
+ expect( block ).toBeDefined();
576
+ expect( block.attributes.content ).toBeInstanceOf( RichTextData );
577
+ expect( block.attributes.content.text ).toBe( 'Hello world' );
578
+ } );
579
+
580
+ it( 'returns nested rich-text in array attributes as RichTextData', () => {
581
+ // Add a table block to the CRDT doc with nested cell content
582
+ // stored as plain strings.
583
+ let blocks = map.get( 'blocks' );
584
+ if ( ! ( blocks instanceof Y.Array ) ) {
585
+ blocks = new Y.Array< YBlock >();
586
+ map.set( 'blocks', blocks );
587
+ }
588
+
589
+ const tableBlock = createYMap< YBlockRecord >();
590
+ tableBlock.set( 'name', 'core/table' );
591
+ tableBlock.set( 'clientId', 'table-1' );
592
+ const attrs = new Y.Map();
593
+ attrs.set( 'body', [
594
+ {
595
+ cells: [
596
+ { content: '<strong>Cell</strong>', tag: 'td' },
597
+ { content: 'Plain', tag: 'td' },
598
+ ],
599
+ },
600
+ ] );
601
+ tableBlock.set( 'attributes', attrs );
602
+ tableBlock.set( 'innerBlocks', new Y.Array() );
603
+ ( blocks as YBlocks ).push( [ tableBlock ] );
604
+
605
+ const editedRecord = { blocks: [] } as unknown as Post;
606
+
607
+ const changes = getPostChangesFromCRDTDoc(
608
+ doc,
609
+ editedRecord,
610
+ defaultSyncedProperties
611
+ );
612
+
613
+ const block = ( changes.blocks as any[] )?.[ 0 ];
614
+ expect( block ).toBeDefined();
615
+
616
+ const cell = block.attributes.body[ 0 ].cells[ 0 ];
617
+ expect( cell.content ).toBeInstanceOf( RichTextData );
618
+ expect( ( cell.content as RichTextData ).toHTMLString() ).toBe(
619
+ '<strong>Cell</strong>'
620
+ );
621
+ } );
622
+
488
623
  it( 'includes undefined blocks in changes', () => {
489
624
  map.set( 'blocks', undefined );
490
625
 
@@ -501,7 +636,7 @@ describe( 'crdt', () => {
501
636
  const changes = getPostChangesFromCRDTDoc(
502
637
  doc,
503
638
  editedRecord,
504
- mockPostType
639
+ defaultSyncedProperties
505
640
  );
506
641
 
507
642
  expect( changes ).toHaveProperty( 'blocks' );
@@ -518,7 +653,7 @@ describe( 'crdt', () => {
518
653
  const changes = getPostChangesFromCRDTDoc(
519
654
  doc,
520
655
  editedRecord,
521
- mockPostType
656
+ defaultSyncedProperties
522
657
  );
523
658
 
524
659
  expect( changes.content ).toBe( 'New content' );
@@ -534,7 +669,7 @@ describe( 'crdt', () => {
534
669
  const changes = getPostChangesFromCRDTDoc(
535
670
  doc,
536
671
  editedRecord,
537
- mockPostType
672
+ defaultSyncedProperties
538
673
  );
539
674
 
540
675
  expect( changes.content ).toBe( 'New content' );
@@ -550,7 +685,7 @@ describe( 'crdt', () => {
550
685
  const changes = getPostChangesFromCRDTDoc(
551
686
  doc,
552
687
  editedRecord,
553
- mockPostType
688
+ defaultSyncedProperties
554
689
  );
555
690
 
556
691
  expect( changes ).not.toHaveProperty( 'content' );
@@ -570,7 +705,7 @@ describe( 'crdt', () => {
570
705
  const changes = getPostChangesFromCRDTDoc(
571
706
  doc,
572
707
  editedRecord,
573
- mockPostType
708
+ defaultSyncedProperties
574
709
  );
575
710
 
576
711
  expect( changes.meta ).toEqual( {
@@ -592,7 +727,7 @@ describe( 'crdt', () => {
592
727
  const changes = getPostChangesFromCRDTDoc(
593
728
  doc,
594
729
  editedRecord,
595
- mockPostType
730
+ defaultSyncedProperties
596
731
  );
597
732
 
598
733
  expect( changes.meta ).toEqual( {
@@ -615,7 +750,7 @@ describe( 'crdt', () => {
615
750
  const changes = getPostChangesFromCRDTDoc(
616
751
  doc,
617
752
  editedRecord,
618
- mockPostType
753
+ defaultSyncedProperties
619
754
  );
620
755
 
621
756
  expect( changes.meta ).toEqual( {
@@ -626,6 +761,43 @@ describe( 'crdt', () => {
626
761
  );
627
762
  } );
628
763
 
764
+ it( 'returns taxonomy rest_base changes when in syncedProperties', () => {
765
+ map.set( 'categories', [ 1, 2 ] );
766
+ map.set( 'genre', [ 10, 20 ] );
767
+ map.set( 'tags', [ 3 ] );
768
+
769
+ const editedRecord = {
770
+ categories: [ 1 ],
771
+ genre: [ 10 ], // should be ignored
772
+ tags: [],
773
+ } as unknown as Post;
774
+
775
+ const changes = getPostChangesFromCRDTDoc(
776
+ doc,
777
+ editedRecord,
778
+ defaultSyncedProperties
779
+ ) as Record< string, unknown >;
780
+
781
+ expect( changes.categories ).toEqual( [ 1, 2 ] );
782
+ expect( changes.genre ).toBeUndefined();
783
+ expect( changes.tags ).toEqual( [ 3 ] );
784
+
785
+ const customSyncedProperties = new Set( [
786
+ ...defaultSyncedProperties,
787
+ 'genre', // now included
788
+ ] );
789
+
790
+ const changes2 = getPostChangesFromCRDTDoc(
791
+ doc,
792
+ editedRecord,
793
+ customSyncedProperties
794
+ ) as Record< string, unknown >;
795
+
796
+ expect( changes2.categories ).toEqual( [ 1, 2 ] );
797
+ expect( changes2.genre ).toEqual( [ 10, 20 ] );
798
+ expect( changes2.tags ).toEqual( [ 3 ] );
799
+ } );
800
+
629
801
  describe( 'selection recalculation', () => {
630
802
  it( 'includes recalculated selection when text is inserted before cursor', () => {
631
803
  const ytext = addBlockToDoc( map, 'block-1', 'Hello world' );
@@ -656,7 +828,7 @@ describe( 'crdt', () => {
656
828
  const changes = getPostChangesFromCRDTDoc(
657
829
  doc,
658
830
  editedRecord,
659
- mockPostType
831
+ defaultSyncedProperties
660
832
  );
661
833
 
662
834
  expect( changes.selection ).toBeDefined();
@@ -699,7 +871,7 @@ describe( 'crdt', () => {
699
871
  const changes = getPostChangesFromCRDTDoc(
700
872
  doc,
701
873
  editedRecord,
702
- mockPostType
874
+ defaultSyncedProperties
703
875
  );
704
876
 
705
877
  expect( changes.selection ).toBeDefined();
@@ -718,7 +890,7 @@ describe( 'crdt', () => {
718
890
  const changes = getPostChangesFromCRDTDoc(
719
891
  doc,
720
892
  editedRecord,
721
- mockPostType
893
+ defaultSyncedProperties
722
894
  );
723
895
 
724
896
  expect( changes.selection ).toBeUndefined();
@@ -734,11 +906,13 @@ describe( 'crdt', () => {
734
906
  * @param map
735
907
  * @param clientId Block client ID.
736
908
  * @param content Initial text content.
909
+ * @param name Block name (default: 'core/paragraph').
737
910
  */
738
911
  function addBlockToDoc(
739
912
  map: YMapWrap< YPostRecord >,
740
913
  clientId: string,
741
- content: string
914
+ content: string,
915
+ name = 'core/paragraph'
742
916
  ): Y.Text {
743
917
  let blocks = map.get( 'blocks' );
744
918
  if ( ! ( blocks instanceof Y.Array ) ) {
@@ -747,6 +921,7 @@ function addBlockToDoc(
747
921
  }
748
922
 
749
923
  const block = createYMap< YBlockRecord >();
924
+ block.set( 'name', name );
750
925
  block.set( 'clientId', clientId );
751
926
  const attrs = new Y.Map();
752
927
  const ytext = new Y.Text( content );
@@ -1,29 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // packages/core-data/src/utils/is-raw-attribute.js
21
- var is_raw_attribute_exports = {};
22
- __export(is_raw_attribute_exports, {
23
- default: () => isRawAttribute
24
- });
25
- module.exports = __toCommonJS(is_raw_attribute_exports);
26
- function isRawAttribute(entity, attribute) {
27
- return (entity.rawAttributes || []).includes(attribute);
28
- }
29
- //# sourceMappingURL=is-raw-attribute.cjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/utils/is-raw-attribute.js"],
4
- "sourcesContent": ["/**\n * Checks whether the attribute is a \"raw\" attribute or not.\n *\n * @param {Object} entity Entity record.\n * @param {string} attribute Attribute name.\n *\n * @return {boolean} Is the attribute raw\n */\nexport default function isRawAttribute( entity, attribute ) {\n\treturn ( entity.rawAttributes || [] ).includes( attribute );\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQe,SAAR,eAAiC,QAAQ,WAAY;AAC3D,UAAS,OAAO,iBAAiB,CAAC,GAAI,SAAU,SAAU;AAC3D;",
6
- "names": []
7
- }
@@ -1,8 +0,0 @@
1
- // packages/core-data/src/utils/is-raw-attribute.js
2
- function isRawAttribute(entity, attribute) {
3
- return (entity.rawAttributes || []).includes(attribute);
4
- }
5
- export {
6
- isRawAttribute as default
7
- };
8
- //# sourceMappingURL=is-raw-attribute.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/utils/is-raw-attribute.js"],
4
- "sourcesContent": ["/**\n * Checks whether the attribute is a \"raw\" attribute or not.\n *\n * @param {Object} entity Entity record.\n * @param {string} attribute Attribute name.\n *\n * @return {boolean} Is the attribute raw\n */\nexport default function isRawAttribute( entity, attribute ) {\n\treturn ( entity.rawAttributes || [] ).includes( attribute );\n}\n"],
5
- "mappings": ";AAQe,SAAR,eAAiC,QAAQ,WAAY;AAC3D,UAAS,OAAO,iBAAiB,CAAC,GAAI,SAAU,SAAU;AAC3D;",
6
- "names": []
7
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Checks whether the attribute is a "raw" attribute or not.
3
- *
4
- * @param {Object} entity Entity record.
5
- * @param {string} attribute Attribute name.
6
- *
7
- * @return {boolean} Is the attribute raw
8
- */
9
- export default function isRawAttribute(entity: any, attribute: string): boolean;
10
- //# sourceMappingURL=is-raw-attribute.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-raw-attribute.d.ts","sourceRoot":"","sources":["../../src/utils/is-raw-attribute.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,+DAJW,MAAM,GAEL,OAAO,CAIlB"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Checks whether the attribute is a "raw" attribute or not.
3
- *
4
- * @param {Object} entity Entity record.
5
- * @param {string} attribute Attribute name.
6
- *
7
- * @return {boolean} Is the attribute raw
8
- */
9
- export default function isRawAttribute( entity, attribute ) {
10
- return ( entity.rawAttributes || [] ).includes( attribute );
11
- }