@wordpress/core-data 7.45.1-next.v.202605131032.0 → 7.47.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 +4 -0
- package/README.md +0 -27
- package/build/actions.cjs +0 -19
- package/build/actions.cjs.map +2 -2
- package/build/awareness/block-lookup.cjs +13 -0
- package/build/awareness/block-lookup.cjs.map +2 -2
- package/build/awareness/post-editor-awareness.cjs +21 -9
- package/build/awareness/post-editor-awareness.cjs.map +2 -2
- package/build/hooks/use-entity-block-editor.cjs +4 -4
- package/build/hooks/use-entity-block-editor.cjs.map +2 -2
- package/build/hooks/use-post-editor-awareness-state.cjs +2 -1
- package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
- package/build/hooks/use-resource-permissions.cjs +3 -5
- package/build/hooks/use-resource-permissions.cjs.map +2 -2
- package/build/index.cjs +0 -6
- package/build/index.cjs.map +2 -2
- package/build/parsed-blocks-cache.cjs +36 -0
- package/build/parsed-blocks-cache.cjs.map +7 -0
- package/build/private-actions.cjs +25 -2
- package/build/private-actions.cjs.map +2 -2
- package/build/private-apis.cjs +9 -5
- package/build/private-apis.cjs.map +3 -3
- package/build/private-selectors.cjs +15 -0
- package/build/private-selectors.cjs.map +2 -2
- package/build/resolvers.cjs +12 -2
- package/build/resolvers.cjs.map +2 -2
- package/build/selectors.cjs +0 -15
- package/build/selectors.cjs.map +2 -2
- package/build/sync.cjs +5 -0
- package/build/sync.cjs.map +2 -2
- package/build/types.cjs +0 -16
- package/build/types.cjs.map +3 -3
- package/build/utils/block-selection-history.cjs +5 -4
- package/build/utils/block-selection-history.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs +3 -0
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-user-selections.cjs +10 -2
- package/build/utils/crdt-user-selections.cjs.map +3 -3
- package/build/utils/crdt-utils.cjs +23 -0
- package/build/utils/crdt-utils.cjs.map +2 -2
- package/build/utils/crdt.cjs +28 -4
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/actions.mjs +0 -18
- package/build-module/actions.mjs.map +2 -2
- package/build-module/awareness/block-lookup.mjs +12 -0
- package/build-module/awareness/block-lookup.mjs.map +2 -2
- package/build-module/awareness/post-editor-awareness.mjs +26 -9
- package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
- package/build-module/hooks/use-entity-block-editor.mjs +2 -2
- package/build-module/hooks/use-entity-block-editor.mjs.map +2 -2
- package/build-module/hooks/use-post-editor-awareness-state.mjs +2 -1
- package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
- package/build-module/hooks/use-resource-permissions.mjs +3 -5
- package/build-module/hooks/use-resource-permissions.mjs.map +2 -2
- package/build-module/index.mjs +0 -4
- package/build-module/index.mjs.map +2 -2
- package/build-module/parsed-blocks-cache.mjs +10 -0
- package/build-module/parsed-blocks-cache.mjs.map +7 -0
- package/build-module/private-actions.mjs +23 -1
- package/build-module/private-actions.mjs.map +2 -2
- package/build-module/private-apis.mjs +12 -5
- package/build-module/private-apis.mjs.map +3 -3
- package/build-module/private-selectors.mjs +14 -0
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/resolvers.mjs +12 -2
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/selectors.mjs +0 -14
- package/build-module/selectors.mjs.map +2 -2
- package/build-module/sync.mjs +4 -0
- package/build-module/sync.mjs.map +2 -2
- package/build-module/types.mjs +0 -9
- package/build-module/types.mjs.map +4 -4
- package/build-module/utils/block-selection-history.mjs +6 -4
- package/build-module/utils/block-selection-history.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +3 -0
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-user-selections.mjs +10 -2
- package/build-module/utils/crdt-user-selections.mjs.map +3 -3
- package/build-module/utils/crdt-utils.mjs +22 -0
- package/build-module/utils/crdt-utils.mjs.map +2 -2
- package/build-module/utils/crdt.mjs +32 -5
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/actions.d.ts +0 -11
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/awareness/block-lookup.d.ts +12 -0
- package/build-types/awareness/block-lookup.d.ts.map +1 -1
- package/build-types/awareness/post-editor-awareness.d.ts +2 -5
- package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
- package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
- package/build-types/hooks/use-resource-permissions.d.ts.map +1 -1
- package/build-types/index.d.ts +0 -8
- package/build-types/index.d.ts.map +1 -1
- package/build-types/parsed-blocks-cache.d.ts +10 -0
- package/build-types/parsed-blocks-cache.d.ts.map +1 -0
- package/build-types/private-actions.d.ts +12 -0
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-apis.d.ts +20 -0
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts +10 -0
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts +1 -1
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +0 -9
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/sync.d.ts +6 -0
- package/build-types/sync.d.ts.map +1 -1
- package/build-types/types.d.ts +3 -10
- 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/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-user-selections.d.ts +10 -1
- package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
- package/build-types/utils/crdt-utils.d.ts +11 -0
- package/build-types/utils/crdt-utils.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts +5 -1
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/actions.js +0 -29
- package/src/awareness/block-lookup.ts +34 -0
- package/src/awareness/post-editor-awareness.ts +32 -14
- package/src/awareness/test/block-lookup.ts +70 -0
- package/src/awareness/test/post-editor-awareness.ts +243 -0
- package/src/hooks/test/use-post-editor-awareness-state.ts +3 -0
- package/src/hooks/test/use-resource-permissions.js +57 -0
- package/src/hooks/use-entity-block-editor.js +2 -2
- package/src/hooks/use-post-editor-awareness-state.ts +1 -0
- package/src/hooks/use-resource-permissions.ts +5 -7
- package/src/index.js +0 -7
- package/src/parsed-blocks-cache.js +12 -0
- package/src/private-actions.js +34 -0
- package/src/{private-apis.js → private-apis.ts} +13 -3
- package/src/private-selectors.ts +33 -0
- package/src/resolvers.js +27 -5
- package/src/selectors.ts +0 -32
- package/src/sync.ts +9 -0
- package/src/test/resolvers.js +13 -7
- package/src/types.ts +16 -11
- package/src/utils/block-selection-history.ts +10 -7
- package/src/utils/crdt-blocks.ts +24 -0
- package/src/utils/crdt-user-selections.ts +15 -2
- package/src/utils/crdt-utils.ts +41 -0
- package/src/utils/crdt.ts +83 -10
- package/src/utils/test/block-selection-history.test.ts +42 -0
- package/src/utils/test/crdt-blocks.ts +37 -0
- package/src/utils/test/crdt-user-selections.ts +39 -0
- package/src/utils/test/crdt-utils.ts +52 -0
- package/src/utils/test/crdt.ts +208 -2
|
@@ -86,6 +86,17 @@ export declare function asRichTextOffset(offset: number): RichTextOffset;
|
|
|
86
86
|
* @return The branded HTML string index.
|
|
87
87
|
*/
|
|
88
88
|
export declare function asHtmlStringIndex(index: number): HtmlStringIndex;
|
|
89
|
+
/**
|
|
90
|
+
* Resolve a selection attribute key to a Y.Text value.
|
|
91
|
+
*
|
|
92
|
+
* RichText identifiers are normally top-level block attribute keys, but nested
|
|
93
|
+
* rich-text fields can provide a dot path such as `body.0.cells.0.content`.
|
|
94
|
+
*
|
|
95
|
+
* @param attributes The block attributes map.
|
|
96
|
+
* @param attributeKey The top-level attribute key or nested attribute path.
|
|
97
|
+
* @return The matching Y.Text, or null if the path is not a rich-text field.
|
|
98
|
+
*/
|
|
99
|
+
export declare function getYTextByAttributeKey(attributes: Y.Map<unknown>, attributeKey: string): Y.Text | null;
|
|
89
100
|
/**
|
|
90
101
|
* Given a block ID and a Y.Doc, find the block in the document.
|
|
91
102
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt-utils.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAGpC;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,eAAe,CAAC;AAIrD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAE,MAAM,EAAE,OAAO,CAAE,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ,CAAE,CAAC,SAAS,UAAU,CAAG,SAAQ,CAAC,CAAC,YAAY,CAAE,CAAC,CAAE;IAC5E,MAAM,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,IAAI,CAAC;IAChD,OAAO,EAAE,CACR,QAAQ,EAAE,CACT,KAAK,EAAE,CAAC,CAAE,MAAM,CAAC,CAAE,EACnB,GAAG,EAAE,MAAM,CAAC,EACZ,GAAG,EAAE,QAAQ,CAAE,CAAC,CAAE,KACd,IAAI,KACL,IAAI,CAAC;IACV,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,OAAO,CAAC;IAChD,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,CAAC,CAAE,CAAC,CAAE,GAAG,SAAS,CAAC;IAC3D,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAE,CAAC,CAAE,KAAM,IAAI,CAAC;IAC5D,MAAM,EAAE,MAAM,CAAC,CAAC;CAEhB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,GAAG,EAAE,MAAM,GACT,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,OAAO,GAAE,OAAO,CAAE,CAAC,CAAO,GACxB,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAE,CAAC,SAAS,UAAU,EAC3C,KAAK,EAAE,QAAQ,CAAE,CAAC,CAAE,GAAG,SAAS,GAC9B,KAAK,IAAI,QAAQ,CAAE,CAAC,CAAE,CAExB;AAED,OAAO,CAAC,MAAM,mBAAmB,EAAE,OAAO,MAAM,CAAC;AACjD,OAAO,CAAC,MAAM,oBAAoB,EAAE,OAAO,MAAM,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IACrC,QAAQ,CAAC,CAAE,mBAAmB,CAAE,EAAE,gBAAgB,CAAC;CACnD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IACtC,QAAQ,CAAC,CAAE,oBAAoB,CAAE,EAAE,iBAAiB,CAAC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAE,MAAM,EAAE,MAAM,GAAI,cAAc,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,MAAM,GAAI,eAAe,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,MAAM,GAAG,IAAI,CASf;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,eAAe,GACxB,cAAc,CAiBhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,GAC5B,eAAe,CA8BjB"}
|
|
1
|
+
{"version":3,"file":"crdt-utils.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAGpC;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,eAAe,CAAC;AAIrD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAE,MAAM,EAAE,OAAO,CAAE,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ,CAAE,CAAC,SAAS,UAAU,CAAG,SAAQ,CAAC,CAAC,YAAY,CAAE,CAAC,CAAE;IAC5E,MAAM,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,IAAI,CAAC;IAChD,OAAO,EAAE,CACR,QAAQ,EAAE,CACT,KAAK,EAAE,CAAC,CAAE,MAAM,CAAC,CAAE,EACnB,GAAG,EAAE,MAAM,CAAC,EACZ,GAAG,EAAE,QAAQ,CAAE,CAAC,CAAE,KACd,IAAI,KACL,IAAI,CAAC;IACV,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,OAAO,CAAC;IAChD,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,CAAC,CAAE,CAAC,CAAE,GAAG,SAAS,CAAC;IAC3D,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAE,CAAC,CAAE,KAAM,IAAI,CAAC;IAC5D,MAAM,EAAE,MAAM,CAAC,CAAC;CAEhB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,GAAG,EAAE,MAAM,GACT,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,OAAO,GAAE,OAAO,CAAE,CAAC,CAAO,GACxB,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAE,CAAC,SAAS,UAAU,EAC3C,KAAK,EAAE,QAAQ,CAAE,CAAC,CAAE,GAAG,SAAS,GAC9B,KAAK,IAAI,QAAQ,CAAE,CAAC,CAAE,CAExB;AAED,OAAO,CAAC,MAAM,mBAAmB,EAAE,OAAO,MAAM,CAAC;AACjD,OAAO,CAAC,MAAM,oBAAoB,EAAE,OAAO,MAAM,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IACrC,QAAQ,CAAC,CAAE,mBAAmB,CAAE,EAAE,gBAAgB,CAAC;CACnD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IACtC,QAAQ,CAAC,CAAE,oBAAoB,CAAE,EAAE,iBAAiB,CAAC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAE,MAAM,EAAE,MAAM,GAAI,cAAc,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,MAAM,GAAI,eAAe,CAElE;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACrC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAE,OAAO,CAAE,EAC5B,YAAY,EAAE,MAAM,GAClB,CAAC,CAAC,IAAI,GAAG,IAAI,CA0Bf;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,MAAM,GAAG,IAAI,CASf;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,eAAe,GACxB,cAAc,CAiBhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,GAC5B,eAAe,CA8BjB"}
|
|
@@ -3,9 +3,12 @@ import { type Block, type YBlocks } from './crdt-blocks';
|
|
|
3
3
|
import { type Post } from '../entity-types/post';
|
|
4
4
|
import type { WPSelection } from '../types';
|
|
5
5
|
import { type YMapRecord, type YMapWrap } from './crdt-utils';
|
|
6
|
+
type ContentFromBlocksFn = (args?: {
|
|
7
|
+
blocks: Block[];
|
|
8
|
+
}) => string;
|
|
6
9
|
export type PostChanges = Partial<Post> & {
|
|
7
10
|
blocks?: Block[];
|
|
8
|
-
content?: Post['content'] | string;
|
|
11
|
+
content?: Post['content'] | string | ContentFromBlocksFn;
|
|
9
12
|
excerpt?: Post['excerpt'] | string;
|
|
10
13
|
selection?: WPSelection;
|
|
11
14
|
title?: Post['title'] | string;
|
|
@@ -63,4 +66,5 @@ export declare const defaultSyncConfig: SyncConfig;
|
|
|
63
66
|
* when changes are detected.
|
|
64
67
|
*/
|
|
65
68
|
export declare const defaultCollectionSyncConfig: SyncConfig;
|
|
69
|
+
export {};
|
|
66
70
|
//# sourceMappingURL=crdt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"AAaA,OAAO,EACN,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,CAAC,EACD,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EACN,KAAK,KAAK,EAMV,KAAK,OAAO,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAM5C,OAAO,EAKN,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,MAAM,cAAc,CAAC;AAMtB,KAAK,mBAAmB,GAAG,CAAE,IAAI,CAAC,EAAE;IAAE,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,KAAM,MAAM,CAAC;AAGpE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAE,IAAI,CAAE,GAAG;IAC3C,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAE,SAAS,CAAE,GAAG,MAAM,GAAG,mBAAmB,CAAC;IAC3D,OAAO,CAAC,EAAE,IAAI,CAAE,SAAS,CAAE,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,KAAK,CAAC,EAAE,IAAI,CAAE,OAAO,CAAE,GAAG,MAAM,CAAC;CACjC,CAAC;AAGF,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC9C,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAE,UAAU,CAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC;CACd;AAED,eAAO,MAAM,sCAAsC,mBAAmB,CAAC;AAsCvE;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,IAAI,CAuJN;AA2DD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,YAAY,EAAE,IAAI,EAClB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,WAAW,CAsKb;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAI/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAKzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/core-data",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.47.0",
|
|
4
4
|
"description": "Access to and manipulation of core WordPress entities.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -49,22 +49,22 @@
|
|
|
49
49
|
"build-module/index.mjs"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@wordpress/api-fetch": "^7.
|
|
53
|
-
"@wordpress/block-editor": "^15.
|
|
54
|
-
"@wordpress/blocks": "^15.
|
|
55
|
-
"@wordpress/compose": "^
|
|
56
|
-
"@wordpress/data": "^10.
|
|
57
|
-
"@wordpress/deprecated": "^4.
|
|
58
|
-
"@wordpress/element": "^
|
|
59
|
-
"@wordpress/html-entities": "^4.
|
|
60
|
-
"@wordpress/i18n": "^6.
|
|
61
|
-
"@wordpress/is-shallow-equal": "^5.
|
|
62
|
-
"@wordpress/private-apis": "^1.
|
|
63
|
-
"@wordpress/rich-text": "^7.
|
|
64
|
-
"@wordpress/sync": "^1.
|
|
65
|
-
"@wordpress/undo-manager": "^1.
|
|
66
|
-
"@wordpress/url": "^4.
|
|
67
|
-
"@wordpress/warning": "^3.
|
|
52
|
+
"@wordpress/api-fetch": "^7.47.0",
|
|
53
|
+
"@wordpress/block-editor": "^15.20.0",
|
|
54
|
+
"@wordpress/blocks": "^15.20.0",
|
|
55
|
+
"@wordpress/compose": "^8.0.0",
|
|
56
|
+
"@wordpress/data": "^10.47.0",
|
|
57
|
+
"@wordpress/deprecated": "^4.47.0",
|
|
58
|
+
"@wordpress/element": "^7.0.0",
|
|
59
|
+
"@wordpress/html-entities": "^4.47.0",
|
|
60
|
+
"@wordpress/i18n": "^6.20.0",
|
|
61
|
+
"@wordpress/is-shallow-equal": "^5.47.0",
|
|
62
|
+
"@wordpress/private-apis": "^1.47.0",
|
|
63
|
+
"@wordpress/rich-text": "^7.47.0",
|
|
64
|
+
"@wordpress/sync": "^1.47.0",
|
|
65
|
+
"@wordpress/undo-manager": "^1.47.0",
|
|
66
|
+
"@wordpress/url": "^4.47.0",
|
|
67
|
+
"@wordpress/warning": "^3.47.0",
|
|
68
68
|
"change-case": "^4.1.2",
|
|
69
69
|
"equivalent-key-map": "^0.2.2",
|
|
70
70
|
"fast-deep-equal": "^3.1.3",
|
|
@@ -78,11 +78,11 @@
|
|
|
78
78
|
"deep-freeze": "0.0.1"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"react": "^
|
|
82
|
-
"react-dom": "^
|
|
81
|
+
"react": "^19.2.4",
|
|
82
|
+
"react-dom": "^19.2.4"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|
|
85
85
|
"access": "public"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "d653c5fd6161571a0c2ebde28553d6e25624eacc"
|
|
88
88
|
}
|
package/src/actions.js
CHANGED
|
@@ -1114,32 +1114,3 @@ export const receiveRevisions =
|
|
|
1114
1114
|
invalidateCache,
|
|
1115
1115
|
} );
|
|
1116
1116
|
};
|
|
1117
|
-
|
|
1118
|
-
/**
|
|
1119
|
-
* Returns an action object used to set the sync connection status for an entity or collection.
|
|
1120
|
-
*
|
|
1121
|
-
* @param {string} kind Kind of the entity.
|
|
1122
|
-
* @param {string} name Name of the entity.
|
|
1123
|
-
* @param {number|string|null} key The entity key, or null for collections.
|
|
1124
|
-
* @param {Object|null} status The connection state object or null on unload.
|
|
1125
|
-
*
|
|
1126
|
-
* @return {Object} Action object.
|
|
1127
|
-
*/
|
|
1128
|
-
export function setSyncConnectionStatus( kind, name, key, status ) {
|
|
1129
|
-
if ( ! status ) {
|
|
1130
|
-
return {
|
|
1131
|
-
type: 'CLEAR_SYNC_CONNECTION_STATUS',
|
|
1132
|
-
kind,
|
|
1133
|
-
name,
|
|
1134
|
-
key,
|
|
1135
|
-
};
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
return {
|
|
1139
|
-
type: 'SET_SYNC_CONNECTION_STATUS',
|
|
1140
|
-
kind,
|
|
1141
|
-
name,
|
|
1142
|
-
key,
|
|
1143
|
-
status,
|
|
1144
|
-
};
|
|
1145
|
-
}
|
|
@@ -22,6 +22,40 @@ interface EditorStoreBlock {
|
|
|
22
22
|
innerBlocks: EditorStoreBlock[];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Find the block Y.Map that contains a nested Yjs type.
|
|
27
|
+
*
|
|
28
|
+
* Rich-text attributes are often stored directly at attributes.content, but
|
|
29
|
+
* blocks can also store rich text deeper inside object or array attributes.
|
|
30
|
+
* Walk upward until we find the block map instead of assuming a fixed parent
|
|
31
|
+
* depth.
|
|
32
|
+
*
|
|
33
|
+
* @param yType - The nested Yjs type to start from.
|
|
34
|
+
* @return The containing block Y.Map, or null if no block ancestor exists.
|
|
35
|
+
*/
|
|
36
|
+
export function getContainingBlockYMap(
|
|
37
|
+
yType: Y.AbstractType< any >
|
|
38
|
+
): Y.Map< unknown > | null {
|
|
39
|
+
let current: Y.AbstractType< any > | null = yType;
|
|
40
|
+
|
|
41
|
+
while ( current ) {
|
|
42
|
+
const parent = current.parent;
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
parent instanceof Y.Map &&
|
|
46
|
+
parent.parent instanceof Y.Array &&
|
|
47
|
+
parent.get( 'clientId' ) !== undefined &&
|
|
48
|
+
parent.get( 'innerBlocks' ) instanceof Y.Array
|
|
49
|
+
) {
|
|
50
|
+
return parent;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
current = parent instanceof Y.AbstractType ? parent : null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
25
59
|
/**
|
|
26
60
|
* Given a Y.Map within a Ydoc, traverse up the Yjs block tree to compute the
|
|
27
61
|
* index path from the root.
|
|
@@ -10,7 +10,11 @@ import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
|
10
10
|
* Internal dependencies
|
|
11
11
|
*/
|
|
12
12
|
import { BaseAwarenessState, baseEqualityFieldChecks } from './base-awareness';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
getBlockPathInYdoc,
|
|
15
|
+
getContainingBlockYMap,
|
|
16
|
+
resolveBlockClientIdByPath,
|
|
17
|
+
} from './block-lookup';
|
|
14
18
|
import {
|
|
15
19
|
AWARENESS_CURSOR_UPDATE_THROTTLE_IN_MS,
|
|
16
20
|
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,
|
|
@@ -24,10 +28,14 @@ import {
|
|
|
24
28
|
areSelectionsStatesEqual,
|
|
25
29
|
getSelectionState,
|
|
26
30
|
SelectionType,
|
|
31
|
+
SelectionDirection,
|
|
27
32
|
} from '../utils/crdt-user-selections';
|
|
28
33
|
|
|
29
|
-
import {
|
|
30
|
-
|
|
34
|
+
import type {
|
|
35
|
+
ResolvedSelection,
|
|
36
|
+
SelectionState,
|
|
37
|
+
WPBlockSelection,
|
|
38
|
+
} from '../types';
|
|
31
39
|
import type { YBlocks } from '../utils/crdt-blocks';
|
|
32
40
|
import type {
|
|
33
41
|
DebugCollaboratorData,
|
|
@@ -239,12 +247,15 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
239
247
|
* @param selection - The selection state.
|
|
240
248
|
* @return The rich-text offset and block client ID, or nulls if not resolvable.
|
|
241
249
|
*/
|
|
242
|
-
public convertSelectionStateToAbsolute(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} {
|
|
250
|
+
public convertSelectionStateToAbsolute(
|
|
251
|
+
selection: SelectionState
|
|
252
|
+
): ResolvedSelection {
|
|
246
253
|
if ( selection.type === SelectionType.None ) {
|
|
247
|
-
return {
|
|
254
|
+
return {
|
|
255
|
+
richTextOffset: null,
|
|
256
|
+
localClientId: null,
|
|
257
|
+
attributeKey: null,
|
|
258
|
+
};
|
|
248
259
|
}
|
|
249
260
|
|
|
250
261
|
if ( selection.type === SelectionType.WholeBlock ) {
|
|
@@ -267,7 +278,11 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
267
278
|
}
|
|
268
279
|
}
|
|
269
280
|
|
|
270
|
-
return {
|
|
281
|
+
return {
|
|
282
|
+
richTextOffset: null,
|
|
283
|
+
localClientId,
|
|
284
|
+
attributeKey: null,
|
|
285
|
+
};
|
|
271
286
|
}
|
|
272
287
|
|
|
273
288
|
// Text-based selections: resolve cursor position and navigate up.
|
|
@@ -282,13 +297,15 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
282
297
|
);
|
|
283
298
|
|
|
284
299
|
if ( ! absolutePosition ) {
|
|
285
|
-
return {
|
|
300
|
+
return {
|
|
301
|
+
richTextOffset: null,
|
|
302
|
+
localClientId: null,
|
|
303
|
+
attributeKey: null,
|
|
304
|
+
};
|
|
286
305
|
}
|
|
287
306
|
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
const path =
|
|
291
|
-
yType instanceof Y.Map ? getBlockPathInYdoc( yType ) : null;
|
|
307
|
+
const yType = getContainingBlockYMap( absolutePosition.type );
|
|
308
|
+
const path = yType ? getBlockPathInYdoc( yType ) : null;
|
|
292
309
|
const localClientId = path ? resolveBlockClientIdByPath( path ) : null;
|
|
293
310
|
|
|
294
311
|
return {
|
|
@@ -297,6 +314,7 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
297
314
|
asHtmlStringIndex( absolutePosition.index )
|
|
298
315
|
),
|
|
299
316
|
localClientId,
|
|
317
|
+
attributeKey: cursorPos.attributeKey ?? null,
|
|
300
318
|
};
|
|
301
319
|
}
|
|
302
320
|
|
|
@@ -9,6 +9,7 @@ import { select } from '@wordpress/data';
|
|
|
9
9
|
*/
|
|
10
10
|
import {
|
|
11
11
|
getBlockPathInYdoc,
|
|
12
|
+
getContainingBlockYMap,
|
|
12
13
|
resolveBlockClientIdByPath,
|
|
13
14
|
} from '../block-lookup';
|
|
14
15
|
|
|
@@ -242,6 +243,75 @@ describe( 'getBlockPathInYdoc', () => {
|
|
|
242
243
|
} );
|
|
243
244
|
} );
|
|
244
245
|
|
|
246
|
+
describe( 'getContainingBlockYMap', () => {
|
|
247
|
+
it( 'should find the containing block for direct rich text content', () => {
|
|
248
|
+
const block = createTestYBlock( 'block' );
|
|
249
|
+
const attributes = new Y.Map< any >();
|
|
250
|
+
const text = new Y.Text( 'Direct text' );
|
|
251
|
+
attributes.set( 'content', text );
|
|
252
|
+
block.set( 'attributes', attributes );
|
|
253
|
+
|
|
254
|
+
const ydoc = new Y.Doc();
|
|
255
|
+
const rootMap = ydoc.getMap( 'test' );
|
|
256
|
+
const blocks = new Y.Array< Y.Map< any > >();
|
|
257
|
+
rootMap.set( 'blocks', blocks );
|
|
258
|
+
blocks.push( [ block ] );
|
|
259
|
+
|
|
260
|
+
expect( getContainingBlockYMap( text ) ).toBe( block );
|
|
261
|
+
} );
|
|
262
|
+
|
|
263
|
+
it( 'should find the containing block for deeply nested rich text attributes', () => {
|
|
264
|
+
const block = createTestYBlock( 'block' );
|
|
265
|
+
const attributes = new Y.Map< any >();
|
|
266
|
+
const cards = new Y.Array< Y.Map< any > >();
|
|
267
|
+
const card = new Y.Map< any >();
|
|
268
|
+
const meta = new Y.Map< any >();
|
|
269
|
+
const caption = new Y.Text( 'Nested caption' );
|
|
270
|
+
|
|
271
|
+
meta.set( 'caption', caption );
|
|
272
|
+
card.set( 'meta', meta );
|
|
273
|
+
cards.push( [ card ] );
|
|
274
|
+
attributes.set( 'cards', cards );
|
|
275
|
+
block.set( 'attributes', attributes );
|
|
276
|
+
|
|
277
|
+
const ydoc = new Y.Doc();
|
|
278
|
+
const rootMap = ydoc.getMap( 'test' );
|
|
279
|
+
const blocks = new Y.Array< Y.Map< any > >();
|
|
280
|
+
rootMap.set( 'blocks', blocks );
|
|
281
|
+
blocks.push( [ block ] );
|
|
282
|
+
|
|
283
|
+
expect( getContainingBlockYMap( caption ) ).toBe( block );
|
|
284
|
+
} );
|
|
285
|
+
|
|
286
|
+
it( 'should return null when no block ancestor exists', () => {
|
|
287
|
+
const orphanAttributes = new Y.Map< any >();
|
|
288
|
+
const text = new Y.Text( 'Orphan text' );
|
|
289
|
+
orphanAttributes.set( 'content', text );
|
|
290
|
+
|
|
291
|
+
expect( getContainingBlockYMap( text ) ).toBeNull();
|
|
292
|
+
} );
|
|
293
|
+
|
|
294
|
+
it( 'should skip nested attribute maps that look like blocks', () => {
|
|
295
|
+
const block = createTestYBlock( 'block' );
|
|
296
|
+
const attributes = new Y.Map< any >();
|
|
297
|
+
const blockLikeAttribute = new Y.Map< any >();
|
|
298
|
+
const text = new Y.Text( 'Nested text' );
|
|
299
|
+
blockLikeAttribute.set( 'clientId', 'attribute-client-id' );
|
|
300
|
+
blockLikeAttribute.set( 'innerBlocks', new Y.Array() );
|
|
301
|
+
blockLikeAttribute.set( 'content', text );
|
|
302
|
+
attributes.set( 'nested', blockLikeAttribute );
|
|
303
|
+
block.set( 'attributes', attributes );
|
|
304
|
+
|
|
305
|
+
const ydoc = new Y.Doc();
|
|
306
|
+
const rootMap = ydoc.getMap( 'test' );
|
|
307
|
+
const blocks = new Y.Array< Y.Map< any > >();
|
|
308
|
+
rootMap.set( 'blocks', blocks );
|
|
309
|
+
blocks.push( [ block ] );
|
|
310
|
+
|
|
311
|
+
expect( getContainingBlockYMap( text ) ).toBe( block );
|
|
312
|
+
} );
|
|
313
|
+
} );
|
|
314
|
+
|
|
245
315
|
describe( 'resolveBlockClientIdByPath', () => {
|
|
246
316
|
afterEach( () => {
|
|
247
317
|
jest.restoreAllMocks();
|
|
@@ -69,6 +69,65 @@ interface MockBlockEditorOverrides {
|
|
|
69
69
|
getSelectionEnd?: jest.Mock;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
type SeededRandom = {
|
|
73
|
+
bool: ( probability?: number ) => boolean;
|
|
74
|
+
int: ( maxExclusive: number ) => number;
|
|
75
|
+
intBetween: ( minInclusive: number, maxInclusive: number ) => number;
|
|
76
|
+
pick: < T >( values: readonly T[] ) => T;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/* eslint-disable no-bitwise */
|
|
80
|
+
function createSeededRandom( seed: number ): SeededRandom {
|
|
81
|
+
let state = seed >>> 0;
|
|
82
|
+
|
|
83
|
+
if ( state === 0 ) {
|
|
84
|
+
state = 0x9e3779b9;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function nextUint32(): number {
|
|
88
|
+
state += 0x6d2b79f5;
|
|
89
|
+
let value = state;
|
|
90
|
+
value = Math.imul( value ^ ( value >>> 15 ), value | 1 );
|
|
91
|
+
value ^= value + Math.imul( value ^ ( value >>> 7 ), value | 61 );
|
|
92
|
+
return ( value ^ ( value >>> 14 ) ) >>> 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function next(): number {
|
|
96
|
+
return nextUint32() / 0x100000000;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function int( maxExclusive: number ): number {
|
|
100
|
+
if ( maxExclusive <= 0 ) {
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return Math.floor( next() * maxExclusive );
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
bool( probability = 0.5 ) {
|
|
109
|
+
return next() < probability;
|
|
110
|
+
},
|
|
111
|
+
int,
|
|
112
|
+
intBetween( minInclusive, maxInclusive ) {
|
|
113
|
+
return minInclusive + int( maxInclusive - minInclusive + 1 );
|
|
114
|
+
},
|
|
115
|
+
pick< T >( values: readonly T[] ): T {
|
|
116
|
+
if ( values.length === 0 ) {
|
|
117
|
+
throw new Error( 'Cannot pick from an empty array.' );
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return values[ int( values.length ) ];
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/* eslint-enable no-bitwise */
|
|
125
|
+
|
|
126
|
+
const NESTED_SELECTION_SEEDS = Array.from(
|
|
127
|
+
{ length: 8 },
|
|
128
|
+
( _value, index ) => 1401 + index
|
|
129
|
+
);
|
|
130
|
+
|
|
72
131
|
/**
|
|
73
132
|
* Mock the block-editor store selectors returned by `select( blockEditorStore )`.
|
|
74
133
|
*
|
|
@@ -170,6 +229,66 @@ function createTestDocWithBlocks( blocks?: Y.Map< any >[] ) {
|
|
|
170
229
|
return ydoc;
|
|
171
230
|
}
|
|
172
231
|
|
|
232
|
+
type NestedTextTarget = {
|
|
233
|
+
label: string;
|
|
234
|
+
text: Y.Text;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
function createNestedAttributeBlock(
|
|
238
|
+
clientId: string,
|
|
239
|
+
seed: number
|
|
240
|
+
): {
|
|
241
|
+
block: Y.Map< any >;
|
|
242
|
+
targets: NestedTextTarget[];
|
|
243
|
+
} {
|
|
244
|
+
const block = new Y.Map();
|
|
245
|
+
block.set( 'clientId', clientId );
|
|
246
|
+
block.set( 'name', 'test/nested-rich-text' );
|
|
247
|
+
|
|
248
|
+
const attrs = new Y.Map();
|
|
249
|
+
const hero = new Y.Map();
|
|
250
|
+
const headline = new Y.Text( `Headline ${ seed } alpha beta` );
|
|
251
|
+
const caption = new Y.Text( `Caption ${ seed } gamma delta` );
|
|
252
|
+
hero.set( 'headline', headline );
|
|
253
|
+
hero.set( 'caption', caption );
|
|
254
|
+
|
|
255
|
+
const cards = new Y.Array();
|
|
256
|
+
const card0 = new Y.Map();
|
|
257
|
+
const card0Title = new Y.Text( `Card ${ seed } title one` );
|
|
258
|
+
const card0Body = new Y.Text( `Card ${ seed } body one two` );
|
|
259
|
+
const card0Meta = new Y.Map();
|
|
260
|
+
const card0Caption = new Y.Text( `Meta ${ seed } caption` );
|
|
261
|
+
card0.set( 'title', card0Title );
|
|
262
|
+
card0.set( 'body', card0Body );
|
|
263
|
+
card0Meta.set( 'caption', card0Caption );
|
|
264
|
+
card0.set( 'meta', card0Meta );
|
|
265
|
+
|
|
266
|
+
const card1 = new Y.Map();
|
|
267
|
+
const card1Title = new Y.Text( `Card ${ seed } title two` );
|
|
268
|
+
const card1Body = new Y.Text( `Card ${ seed } body three four` );
|
|
269
|
+
card1.set( 'title', card1Title );
|
|
270
|
+
card1.set( 'body', card1Body );
|
|
271
|
+
cards.push( [ card0, card1 ] );
|
|
272
|
+
|
|
273
|
+
attrs.set( 'hero', hero );
|
|
274
|
+
attrs.set( 'cards', cards );
|
|
275
|
+
block.set( 'attributes', attrs );
|
|
276
|
+
block.set( 'innerBlocks', new Y.Array() );
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
block,
|
|
280
|
+
targets: [
|
|
281
|
+
{ label: 'hero.headline', text: headline },
|
|
282
|
+
{ label: 'hero.caption', text: caption },
|
|
283
|
+
{ label: 'cards.0.title', text: card0Title },
|
|
284
|
+
{ label: 'cards.0.body', text: card0Body },
|
|
285
|
+
{ label: 'cards.0.meta.caption', text: card0Caption },
|
|
286
|
+
{ label: 'cards.1.title', text: card1Title },
|
|
287
|
+
{ label: 'cards.1.body', text: card1Body },
|
|
288
|
+
],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
173
292
|
describe( 'PostEditorAwareness', () => {
|
|
174
293
|
let doc: Y.Doc;
|
|
175
294
|
let subscribeCallback: ( () => void ) | null = null;
|
|
@@ -528,6 +647,7 @@ describe( 'PostEditorAwareness', () => {
|
|
|
528
647
|
cursorPosition: {
|
|
529
648
|
relativePosition,
|
|
530
649
|
absoluteOffset: 5,
|
|
650
|
+
attributeKey: 'content',
|
|
531
651
|
},
|
|
532
652
|
};
|
|
533
653
|
|
|
@@ -536,6 +656,7 @@ describe( 'PostEditorAwareness', () => {
|
|
|
536
656
|
|
|
537
657
|
expect( result.richTextOffset ).toBe( 5 );
|
|
538
658
|
expect( result.localClientId ).toBe( 'block-1' );
|
|
659
|
+
expect( result.attributeKey ).toBe( 'content' );
|
|
539
660
|
} );
|
|
540
661
|
|
|
541
662
|
test( 'should resolve WholeBlock selection to block client ID', () => {
|
|
@@ -568,6 +689,58 @@ describe( 'PostEditorAwareness', () => {
|
|
|
568
689
|
|
|
569
690
|
expect( result.richTextOffset ).toBeNull();
|
|
570
691
|
expect( result.localClientId ).toBe( 'block-1' );
|
|
692
|
+
expect( result.attributeKey ).toBeNull();
|
|
693
|
+
} );
|
|
694
|
+
|
|
695
|
+
test( 'should return null attributeKey for SelectionType.None', () => {
|
|
696
|
+
const awareness = new PostEditorAwareness(
|
|
697
|
+
doc,
|
|
698
|
+
'postType',
|
|
699
|
+
'post',
|
|
700
|
+
123
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
const result = awareness.convertSelectionStateToAbsolute( {
|
|
704
|
+
type: SelectionType.None,
|
|
705
|
+
} );
|
|
706
|
+
|
|
707
|
+
expect( result.attributeKey ).toBeNull();
|
|
708
|
+
} );
|
|
709
|
+
|
|
710
|
+
test( 'should pass through nested attributeKey for a cursor selection', () => {
|
|
711
|
+
const awareness = new PostEditorAwareness(
|
|
712
|
+
doc,
|
|
713
|
+
'postType',
|
|
714
|
+
'post',
|
|
715
|
+
123
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
const documentMap = doc.getMap( CRDT_RECORD_MAP_KEY );
|
|
719
|
+
const blocks = documentMap.get( 'blocks' ) as Y.Array<
|
|
720
|
+
Y.Map< any >
|
|
721
|
+
>;
|
|
722
|
+
const block = blocks.get( 0 );
|
|
723
|
+
const attrs = block.get( 'attributes' ) as Y.Map< Y.Text >;
|
|
724
|
+
const yText = attrs.get( 'content' );
|
|
725
|
+
|
|
726
|
+
const relativePosition = Y.createRelativePositionFromTypeIndex(
|
|
727
|
+
yText as Y.Text,
|
|
728
|
+
3
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
const selection: SelectionCursor = {
|
|
732
|
+
type: SelectionType.Cursor,
|
|
733
|
+
cursorPosition: {
|
|
734
|
+
relativePosition,
|
|
735
|
+
absoluteOffset: 3,
|
|
736
|
+
attributeKey: 'body.0.cells.0.content',
|
|
737
|
+
},
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
const result =
|
|
741
|
+
awareness.convertSelectionStateToAbsolute( selection );
|
|
742
|
+
|
|
743
|
+
expect( result.attributeKey ).toBe( 'body.0.cells.0.content' );
|
|
571
744
|
} );
|
|
572
745
|
} );
|
|
573
746
|
|
|
@@ -1001,6 +1174,76 @@ describe( 'PostEditorAwareness', () => {
|
|
|
1001
1174
|
} );
|
|
1002
1175
|
} );
|
|
1003
1176
|
|
|
1177
|
+
describe( 'convertSelectionStateToAbsolute with nested rich-text attributes', () => {
|
|
1178
|
+
test.each( NESTED_SELECTION_SEEDS )(
|
|
1179
|
+
'resolves fuzzed nested rich-text cursor (seed %i)',
|
|
1180
|
+
( seed ) => {
|
|
1181
|
+
const rng = createSeededRandom( seed );
|
|
1182
|
+
const { block, targets } = createNestedAttributeBlock(
|
|
1183
|
+
'yjs-nested-attrs',
|
|
1184
|
+
seed
|
|
1185
|
+
);
|
|
1186
|
+
const nestedDoc = createTestDocWithBlocks( [ block ] );
|
|
1187
|
+
|
|
1188
|
+
mockBlockEditorStore( {
|
|
1189
|
+
blocks: [
|
|
1190
|
+
{
|
|
1191
|
+
clientId: 'local-nested-attrs',
|
|
1192
|
+
innerBlocks: [],
|
|
1193
|
+
},
|
|
1194
|
+
],
|
|
1195
|
+
} );
|
|
1196
|
+
|
|
1197
|
+
const target = rng.pick( targets );
|
|
1198
|
+
const initialOffset = rng.intBetween(
|
|
1199
|
+
1,
|
|
1200
|
+
Math.max( 1, target.text.length - 1 )
|
|
1201
|
+
);
|
|
1202
|
+
const relativePosition = Y.createRelativePositionFromTypeIndex(
|
|
1203
|
+
target.text,
|
|
1204
|
+
initialOffset
|
|
1205
|
+
);
|
|
1206
|
+
let expectedOffset = initialOffset;
|
|
1207
|
+
|
|
1208
|
+
if ( rng.bool() ) {
|
|
1209
|
+
const prefix = `p${ seed % 97 } `;
|
|
1210
|
+
target.text.insert( 0, prefix );
|
|
1211
|
+
expectedOffset += prefix.length;
|
|
1212
|
+
} else {
|
|
1213
|
+
const deleteLength = Math.min(
|
|
1214
|
+
initialOffset,
|
|
1215
|
+
rng.intBetween( 1, 3 )
|
|
1216
|
+
);
|
|
1217
|
+
target.text.delete( 0, deleteLength );
|
|
1218
|
+
expectedOffset -= deleteLength;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
const awareness = new PostEditorAwareness(
|
|
1222
|
+
nestedDoc,
|
|
1223
|
+
'postType',
|
|
1224
|
+
'post',
|
|
1225
|
+
123
|
|
1226
|
+
);
|
|
1227
|
+
|
|
1228
|
+
const selection: SelectionCursor = {
|
|
1229
|
+
type: SelectionType.Cursor,
|
|
1230
|
+
cursorPosition: {
|
|
1231
|
+
relativePosition,
|
|
1232
|
+
absoluteOffset: initialOffset,
|
|
1233
|
+
},
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
const result =
|
|
1237
|
+
awareness.convertSelectionStateToAbsolute( selection );
|
|
1238
|
+
|
|
1239
|
+
expect( result.richTextOffset ).toBe( expectedOffset );
|
|
1240
|
+
expect( result.localClientId ).toBe( 'local-nested-attrs' );
|
|
1241
|
+
|
|
1242
|
+
nestedDoc.destroy();
|
|
1243
|
+
}
|
|
1244
|
+
);
|
|
1245
|
+
} );
|
|
1246
|
+
|
|
1004
1247
|
describe( 'template mode (core/post-content handling)', () => {
|
|
1005
1248
|
test( 'should resolve cursor when getBlocks returns template tree with core/post-content', () => {
|
|
1006
1249
|
// Yjs doc has only the post content blocks (no template wrapper)
|
|
@@ -295,6 +295,7 @@ describe( 'use-post-editor-awareness-state hooks', () => {
|
|
|
295
295
|
expect( result.current( mockSelection ) ).toEqual( {
|
|
296
296
|
richTextOffset: null,
|
|
297
297
|
localClientId: null,
|
|
298
|
+
attributeKey: null,
|
|
298
299
|
} );
|
|
299
300
|
} );
|
|
300
301
|
|
|
@@ -309,6 +310,7 @@ describe( 'use-post-editor-awareness-state hooks', () => {
|
|
|
309
310
|
mockAwareness.convertSelectionStateToAbsolute.mockReturnValue( {
|
|
310
311
|
richTextOffset: 10,
|
|
311
312
|
localClientId: 'block-1',
|
|
313
|
+
attributeKey: 'content',
|
|
312
314
|
} );
|
|
313
315
|
|
|
314
316
|
const { result } = renderHook( () =>
|
|
@@ -323,6 +325,7 @@ describe( 'use-post-editor-awareness-state hooks', () => {
|
|
|
323
325
|
expect( position ).toEqual( {
|
|
324
326
|
richTextOffset: 10,
|
|
325
327
|
localClientId: 'block-1',
|
|
328
|
+
attributeKey: 'content',
|
|
326
329
|
} );
|
|
327
330
|
} );
|
|
328
331
|
} );
|