@wordpress/core-data 7.42.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.
- package/CHANGELOG.md +2 -0
- package/build/private-actions.cjs +10 -0
- package/build/private-actions.cjs.map +2 -2
- package/build/private-selectors.cjs +20 -3
- package/build/private-selectors.cjs.map +2 -2
- package/build/queried-data/get-query-parts.cjs +8 -7
- package/build/queried-data/get-query-parts.cjs.map +2 -2
- package/build/queried-data/reducer.cjs +15 -9
- package/build/queried-data/reducer.cjs.map +2 -2
- package/build/queried-data/selectors.cjs +3 -6
- package/build/queried-data/selectors.cjs.map +2 -2
- package/build/reducer.cjs +16 -3
- package/build/reducer.cjs.map +2 -2
- package/build/resolvers.cjs +16 -8
- package/build/resolvers.cjs.map +2 -2
- package/build/selectors.cjs +16 -8
- package/build/selectors.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs +49 -2
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-text.cjs +52 -0
- package/build/utils/crdt-text.cjs.map +7 -0
- package/build/utils/crdt.cjs +5 -0
- package/build/utils/crdt.cjs.map +2 -2
- package/build/utils/index.cjs +0 -3
- package/build/utils/index.cjs.map +2 -2
- package/build-module/private-actions.mjs +9 -0
- package/build-module/private-actions.mjs.map +2 -2
- package/build-module/private-selectors.mjs +19 -3
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/queried-data/get-query-parts.mjs +8 -7
- package/build-module/queried-data/get-query-parts.mjs.map +2 -2
- package/build-module/queried-data/reducer.mjs +15 -9
- package/build-module/queried-data/reducer.mjs.map +2 -2
- package/build-module/queried-data/selectors.mjs +3 -6
- package/build-module/queried-data/selectors.mjs.map +2 -2
- package/build-module/reducer.mjs +14 -2
- package/build-module/reducer.mjs.map +2 -2
- package/build-module/resolvers.mjs +14 -7
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/selectors.mjs +16 -9
- package/build-module/selectors.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +48 -2
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-text.mjs +26 -0
- package/build-module/utils/crdt-text.mjs.map +7 -0
- package/build-module/utils/crdt.mjs +6 -0
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-module/utils/index.mjs +8 -10
- package/build-module/utils/index.mjs.map +2 -2
- package/build-types/index.d.ts.map +1 -1
- package/build-types/private-actions.d.ts +10 -0
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts +11 -4
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/queried-data/get-query-parts.d.ts +11 -19
- package/build-types/queried-data/get-query-parts.d.ts.map +1 -1
- package/build-types/queried-data/reducer.d.ts +11 -5
- package/build-types/queried-data/reducer.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/reducer.d.ts +11 -0
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +3 -0
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +1 -0
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +11 -0
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-text.d.ts +16 -0
- package/build-types/utils/crdt-text.d.ts.map +1 -0
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/build-types/utils/index.d.ts +0 -1
- package/package.json +18 -18
- package/src/private-actions.js +18 -0
- package/src/private-selectors.ts +37 -4
- package/src/queried-data/get-query-parts.js +14 -20
- package/src/queried-data/reducer.js +28 -15
- package/src/queried-data/selectors.js +4 -14
- package/src/queried-data/test/get-query-parts.js +11 -11
- package/src/queried-data/test/reducer.js +78 -8
- package/src/queried-data/test/selectors.js +22 -9
- package/src/reducer.js +20 -0
- package/src/resolvers.js +23 -7
- package/src/selectors.ts +20 -19
- package/src/utils/crdt-blocks.ts +83 -2
- package/src/utils/crdt-text.ts +43 -0
- package/src/utils/crdt.ts +10 -0
- package/src/utils/index.js +0 -1
- package/src/utils/test/crdt-blocks.ts +53 -0
- package/src/utils/test/crdt.ts +109 -1
- package/build/utils/is-raw-attribute.cjs +0 -29
- package/build/utils/is-raw-attribute.cjs.map +0 -7
- package/build-module/utils/is-raw-attribute.mjs +0 -8
- package/build-module/utils/is-raw-attribute.mjs.map +0 -7
- package/build-types/utils/is-raw-attribute.d.ts +0 -10
- package/build-types/utils/is-raw-attribute.d.ts.map +0 -1
- package/src/utils/is-raw-attribute.js +0 -11
- package/src/utils/test/is-raw-attribute.js +0 -22
package/src/utils/crdt-blocks.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { Y } from '@wordpress/sync';
|
|
|
16
16
|
* Internal dependencies
|
|
17
17
|
*/
|
|
18
18
|
import { createYMap, type YMapRecord, type YMapWrap } from './crdt-utils';
|
|
19
|
+
import { getCachedRichTextData } from './crdt-text';
|
|
19
20
|
import { Delta } from '../sync';
|
|
20
21
|
|
|
21
22
|
interface BlockAttributes {
|
|
@@ -25,6 +26,7 @@ interface BlockAttributes {
|
|
|
25
26
|
interface BlockAttributeType {
|
|
26
27
|
role?: string;
|
|
27
28
|
type?: string;
|
|
29
|
+
query?: Record< string, BlockAttributeType >;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
interface BlockType {
|
|
@@ -122,6 +124,85 @@ function makeBlocksSerializable( blocks: Block[] ): Block[] {
|
|
|
122
124
|
} );
|
|
123
125
|
}
|
|
124
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Recursively walk an attribute value and convert any strings that correspond
|
|
129
|
+
* to rich-text schema nodes into RichTextData instances. This is the inverse
|
|
130
|
+
* of serializeAttributeValue and handles nested structures like table cells.
|
|
131
|
+
*
|
|
132
|
+
* @param schema The attribute type definition for this value.
|
|
133
|
+
* @param value The attribute value from CRDT (toJSON).
|
|
134
|
+
* @return The value with rich-text strings replaced by RichTextData.
|
|
135
|
+
*/
|
|
136
|
+
function deserializeAttributeValue(
|
|
137
|
+
schema: BlockAttributeType | undefined,
|
|
138
|
+
value: unknown
|
|
139
|
+
): unknown {
|
|
140
|
+
if ( schema?.type === 'rich-text' && typeof value === 'string' ) {
|
|
141
|
+
return getCachedRichTextData( value );
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// e.g. core/table `body`: [ { cells: [ { content: RichTextData } ] } ]
|
|
145
|
+
if ( Array.isArray( value ) ) {
|
|
146
|
+
return value.map( ( item ) =>
|
|
147
|
+
deserializeAttributeValue( schema, item )
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// e.g. a single row inside core/table `body`: { cells: [ ... ] }
|
|
152
|
+
if ( value && typeof value === 'object' ) {
|
|
153
|
+
const result: Record< string, unknown > = {};
|
|
154
|
+
|
|
155
|
+
for ( const [ key, innerValue ] of Object.entries(
|
|
156
|
+
value as Record< string, unknown >
|
|
157
|
+
) ) {
|
|
158
|
+
result[ key ] = deserializeAttributeValue(
|
|
159
|
+
schema?.query?.[ key ],
|
|
160
|
+
innerValue
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Convert blocks from their CRDT-serialized form back to the runtime form
|
|
172
|
+
* expected by the block editor. Rich-text attributes are stored as Y.Text in
|
|
173
|
+
* the CRDT document, which serializes to plain strings via toJSON(). This
|
|
174
|
+
* function restores them to RichTextData instances so that block edit
|
|
175
|
+
* components that rely on RichTextData methods (e.g. `.text`) work correctly.
|
|
176
|
+
*
|
|
177
|
+
* @param blocks Blocks as extracted from the CRDT document via toJSON().
|
|
178
|
+
* @return Blocks with rich-text attributes restored to RichTextData.
|
|
179
|
+
*/
|
|
180
|
+
export function deserializeBlockAttributes( blocks: Block[] ): Block[] {
|
|
181
|
+
return blocks.map( ( block: Block ) => {
|
|
182
|
+
const { name, innerBlocks, attributes, ...rest } = block;
|
|
183
|
+
|
|
184
|
+
const newAttributes = { ...attributes };
|
|
185
|
+
|
|
186
|
+
for ( const [ key, value ] of Object.entries( attributes ) ) {
|
|
187
|
+
const schema = getBlockAttributeType( name, key );
|
|
188
|
+
|
|
189
|
+
if ( schema ) {
|
|
190
|
+
newAttributes[ key ] = deserializeAttributeValue(
|
|
191
|
+
schema,
|
|
192
|
+
value
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
...rest,
|
|
199
|
+
name,
|
|
200
|
+
attributes: newAttributes,
|
|
201
|
+
innerBlocks: deserializeBlockAttributes( innerBlocks ?? [] ),
|
|
202
|
+
};
|
|
203
|
+
} );
|
|
204
|
+
}
|
|
205
|
+
|
|
125
206
|
/**
|
|
126
207
|
* @param {any} gblock
|
|
127
208
|
* @param {Y.Map} yblock
|
|
@@ -481,8 +562,8 @@ function getBlockAttributeType(
|
|
|
481
562
|
new Map< string, BlockAttributeType >(
|
|
482
563
|
Object.entries( blockType.attributes ?? {} ).map(
|
|
483
564
|
( [ name, definition ] ) => {
|
|
484
|
-
const { role, type } = definition;
|
|
485
|
-
return [ name, { role, type } ];
|
|
565
|
+
const { role, type, query } = definition;
|
|
566
|
+
return [ name, { role, type, query } ];
|
|
486
567
|
}
|
|
487
568
|
)
|
|
488
569
|
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RichTextData } from '@wordpress/rich-text';
|
|
5
|
+
|
|
6
|
+
const RICH_TEXT_CACHE_MAX_SIZE = 500;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns a function that converts HTML strings to RichTextData instances,
|
|
10
|
+
* using a FIFO cache bounded by `maxSize` to avoid re-parsing identical
|
|
11
|
+
* strings. Repeated calls with the same string return the cached instance
|
|
12
|
+
* without re-running the HTML parser and DOM traversal.
|
|
13
|
+
*
|
|
14
|
+
* @param maxSize Maximum number of entries to hold in the cache.
|
|
15
|
+
* @return A cached version of RichTextData.fromHTMLString.
|
|
16
|
+
*/
|
|
17
|
+
export function createRichTextDataCache(
|
|
18
|
+
maxSize: number
|
|
19
|
+
): ( value: string ) => RichTextData {
|
|
20
|
+
const cache = new Map< string, RichTextData >();
|
|
21
|
+
|
|
22
|
+
return function ( value: string ): RichTextData {
|
|
23
|
+
const cached = cache.get( value );
|
|
24
|
+
|
|
25
|
+
if ( cached ) {
|
|
26
|
+
return cached;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = RichTextData.fromHTMLString( value );
|
|
30
|
+
|
|
31
|
+
if ( cache.size >= maxSize ) {
|
|
32
|
+
// Evict the oldest entry (Map preserves insertion order).
|
|
33
|
+
cache.delete( cache.keys().next().value! );
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
cache.set( value, result );
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const getCachedRichTextData = createRichTextDataCache(
|
|
42
|
+
RICH_TEXT_CACHE_MAX_SIZE
|
|
43
|
+
);
|
package/src/utils/crdt.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
*/
|
|
21
21
|
import { BaseAwareness } from '../awareness/base-awareness';
|
|
22
22
|
import {
|
|
23
|
+
deserializeBlockAttributes,
|
|
23
24
|
mergeCrdtBlocks,
|
|
24
25
|
mergeRichTextUpdate,
|
|
25
26
|
type Block,
|
|
@@ -382,6 +383,15 @@ export function getPostChangesFromCRDTDoc(
|
|
|
382
383
|
} )
|
|
383
384
|
);
|
|
384
385
|
|
|
386
|
+
// Blocks extracted from the CRDT document have rich-text attributes as
|
|
387
|
+
// plain strings (from Y.Text.toJSON()). Convert them back to RichTextData
|
|
388
|
+
// so block edit components receive the same types as locally-created blocks.
|
|
389
|
+
if ( changes.blocks ) {
|
|
390
|
+
changes.blocks = deserializeBlockAttributes(
|
|
391
|
+
changes.blocks as Block[]
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
385
395
|
// Meta changes must be merged with the edited record since not all meta
|
|
386
396
|
// properties are synced.
|
|
387
397
|
if ( 'object' === typeof changes.meta ) {
|
package/src/utils/index.js
CHANGED
|
@@ -5,7 +5,6 @@ export { default as forwardResolver } from './forward-resolver';
|
|
|
5
5
|
export { default as onSubKey } from './on-sub-key';
|
|
6
6
|
export { default as replaceAction } from './replace-action';
|
|
7
7
|
export { default as withWeakMapCache } from './with-weak-map-cache';
|
|
8
|
-
export { default as isRawAttribute } from './is-raw-attribute';
|
|
9
8
|
export { default as setNestedValue } from './set-nested-value';
|
|
10
9
|
export { default as getNestedValue } from './get-nested-value';
|
|
11
10
|
export { default as isNumericID } from './is-numeric-id';
|
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
type YBlocks,
|
|
68
68
|
type YBlockAttributes,
|
|
69
69
|
} from '../crdt-blocks';
|
|
70
|
+
import { getCachedRichTextData, createRichTextDataCache } from '../crdt-text';
|
|
70
71
|
|
|
71
72
|
describe( 'crdt-blocks', () => {
|
|
72
73
|
let doc: Y.Doc;
|
|
@@ -1581,3 +1582,55 @@ describe( 'crdt-blocks', () => {
|
|
|
1581
1582
|
} );
|
|
1582
1583
|
} );
|
|
1583
1584
|
} );
|
|
1585
|
+
|
|
1586
|
+
describe( 'getCachedRichTextData', () => {
|
|
1587
|
+
let spy: ReturnType< typeof jest.spyOn >;
|
|
1588
|
+
|
|
1589
|
+
beforeEach( () => {
|
|
1590
|
+
spy = jest.spyOn( RichTextData, 'fromHTMLString' );
|
|
1591
|
+
} );
|
|
1592
|
+
|
|
1593
|
+
afterEach( () => {
|
|
1594
|
+
spy.mockRestore();
|
|
1595
|
+
} );
|
|
1596
|
+
|
|
1597
|
+
it( 'does not call fromHTMLString again for the same HTML string', () => {
|
|
1598
|
+
getCachedRichTextData( '<strong>cached-hit</strong>' );
|
|
1599
|
+
getCachedRichTextData( '<strong>cached-hit</strong>' );
|
|
1600
|
+
|
|
1601
|
+
expect( spy ).toHaveBeenCalledTimes( 1 );
|
|
1602
|
+
} );
|
|
1603
|
+
|
|
1604
|
+
it( 'calls fromHTMLString for each unique HTML string', () => {
|
|
1605
|
+
getCachedRichTextData( '<strong>cached-miss-a</strong>' );
|
|
1606
|
+
getCachedRichTextData( '<em>cached-miss-b</em>' );
|
|
1607
|
+
|
|
1608
|
+
expect( spy ).toHaveBeenCalledTimes( 2 );
|
|
1609
|
+
} );
|
|
1610
|
+
|
|
1611
|
+
it( 'calls fromHTMLString again for an evicted entry', () => {
|
|
1612
|
+
const cacheSize = 10;
|
|
1613
|
+
const getCachedValue = createRichTextDataCache( cacheSize );
|
|
1614
|
+
|
|
1615
|
+
const firstString = 'eviction-test-first';
|
|
1616
|
+
|
|
1617
|
+
getCachedValue( firstString );
|
|
1618
|
+
|
|
1619
|
+
for ( let i = 1; i < cacheSize; i++ ) {
|
|
1620
|
+
getCachedValue( `eviction-test-${ i }` );
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
// This should push firstString out of the cache.
|
|
1624
|
+
getCachedValue( 'eviction-test-overflow' );
|
|
1625
|
+
|
|
1626
|
+
spy.mockClear();
|
|
1627
|
+
|
|
1628
|
+
// firstString was evicted, so fromHTMLString should be called again.
|
|
1629
|
+
getCachedValue( firstString );
|
|
1630
|
+
expect( spy ).toHaveBeenCalledTimes( 1 );
|
|
1631
|
+
|
|
1632
|
+
// The overflow entry is still cached, so fromHTMLString should not be called.
|
|
1633
|
+
getCachedValue( 'eviction-test-overflow' );
|
|
1634
|
+
expect( spy ).toHaveBeenCalledTimes( 1 );
|
|
1635
|
+
} );
|
|
1636
|
+
} );
|
package/src/utils/test/crdt.ts
CHANGED
|
@@ -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
|
*/
|
|
@@ -515,6 +558,68 @@ describe( 'crdt', () => {
|
|
|
515
558
|
expect( changes ).toHaveProperty( 'blocks' );
|
|
516
559
|
} );
|
|
517
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
|
+
|
|
518
623
|
it( 'includes undefined blocks in changes', () => {
|
|
519
624
|
map.set( 'blocks', undefined );
|
|
520
625
|
|
|
@@ -801,11 +906,13 @@ describe( 'crdt', () => {
|
|
|
801
906
|
* @param map
|
|
802
907
|
* @param clientId Block client ID.
|
|
803
908
|
* @param content Initial text content.
|
|
909
|
+
* @param name Block name (default: 'core/paragraph').
|
|
804
910
|
*/
|
|
805
911
|
function addBlockToDoc(
|
|
806
912
|
map: YMapWrap< YPostRecord >,
|
|
807
913
|
clientId: string,
|
|
808
|
-
content: string
|
|
914
|
+
content: string,
|
|
915
|
+
name = 'core/paragraph'
|
|
809
916
|
): Y.Text {
|
|
810
917
|
let blocks = map.get( 'blocks' );
|
|
811
918
|
if ( ! ( blocks instanceof Y.Array ) ) {
|
|
@@ -814,6 +921,7 @@ function addBlockToDoc(
|
|
|
814
921
|
}
|
|
815
922
|
|
|
816
923
|
const block = createYMap< YBlockRecord >();
|
|
924
|
+
block.set( 'name', name );
|
|
817
925
|
block.set( 'clientId', clientId );
|
|
818
926
|
const attrs = new Y.Map();
|
|
819
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,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
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { isRawAttribute } from '../';
|
|
5
|
-
|
|
6
|
-
describe( 'isRawAttribute', () => {
|
|
7
|
-
it( 'should correctly assess that the attribute is not raw', () => {
|
|
8
|
-
const entityConfig = {
|
|
9
|
-
kind: 'someKind',
|
|
10
|
-
name: 'someName',
|
|
11
|
-
};
|
|
12
|
-
expect( isRawAttribute( entityConfig, 'title' ) ).toBe( false );
|
|
13
|
-
} );
|
|
14
|
-
it( 'should correctly assess that the attribute is raw', () => {
|
|
15
|
-
const entityConfig = {
|
|
16
|
-
kind: 'someKind',
|
|
17
|
-
name: 'someName',
|
|
18
|
-
rawAttributes: [ 'title' ],
|
|
19
|
-
};
|
|
20
|
-
expect( isRawAttribute( entityConfig, 'title' ) ).toBe( true );
|
|
21
|
-
} );
|
|
22
|
-
} );
|