@wordpress/core-data 7.43.2-next.v.202604091042.0 → 7.44.1-next.v.202604201441.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 (43) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/build/hooks/use-entity-prop.cjs +1 -1
  3. package/build/hooks/use-entity-prop.cjs.map +2 -2
  4. package/build/queried-data/reducer.cjs +5 -4
  5. package/build/queried-data/reducer.cjs.map +2 -2
  6. package/build/utils/crdt-blocks.cjs +54 -26
  7. package/build/utils/crdt-blocks.cjs.map +2 -2
  8. package/build/utils/crdt-selection.cjs.map +2 -2
  9. package/build/utils/crdt.cjs.map +2 -2
  10. package/build/utils/index.cjs +0 -3
  11. package/build/utils/index.cjs.map +2 -2
  12. package/build-module/hooks/use-entity-prop.mjs +1 -1
  13. package/build-module/hooks/use-entity-prop.mjs.map +2 -2
  14. package/build-module/queried-data/reducer.mjs +7 -11
  15. package/build-module/queried-data/reducer.mjs.map +2 -2
  16. package/build-module/utils/crdt-blocks.mjs +54 -26
  17. package/build-module/utils/crdt-blocks.mjs.map +2 -2
  18. package/build-module/utils/crdt-selection.mjs.map +2 -2
  19. package/build-module/utils/crdt.mjs.map +2 -2
  20. package/build-module/utils/index.mjs +12 -14
  21. package/build-module/utils/index.mjs.map +2 -2
  22. package/build-types/queried-data/reducer.d.ts.map +1 -1
  23. package/build-types/utils/crdt-blocks.d.ts.map +1 -1
  24. package/build-types/utils/crdt-selection.d.ts.map +1 -1
  25. package/build-types/utils/crdt.d.ts.map +1 -1
  26. package/build-types/utils/index.d.ts +0 -1
  27. package/package.json +18 -18
  28. package/src/hooks/use-entity-prop.js +1 -1
  29. package/src/queried-data/reducer.js +9 -12
  30. package/src/queried-data/test/reducer.js +7 -0
  31. package/src/utils/crdt-blocks.ts +103 -36
  32. package/src/utils/crdt-selection.ts +0 -1
  33. package/src/utils/crdt.ts +0 -1
  34. package/src/utils/index.js +0 -1
  35. package/src/utils/test/crdt-blocks.ts +544 -1
  36. package/build/utils/on-sub-key.cjs +0 -46
  37. package/build/utils/on-sub-key.cjs.map +0 -7
  38. package/build-module/utils/on-sub-key.mjs +0 -21
  39. package/build-module/utils/on-sub-key.mjs.map +0 -7
  40. package/build-types/utils/on-sub-key.d.ts +0 -4
  41. package/build-types/utils/on-sub-key.d.ts.map +0 -1
  42. package/src/utils/on-sub-key.js +0 -35
  43. package/src/utils/test/on-sub-key.js +0 -46
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/crdt-selection.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select } from '@wordpress/data';\n// @ts-expect-error No exported types.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n// @ts-expect-error No exported types.\nimport { isUnmodifiedBlock } from '@wordpress/blocks';\nimport { type CRDTDoc, Y } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport {\n\tcreateBlockSelectionHistory,\n\tYSelectionType,\n\ttype BlockSelectionHistory,\n\ttype YFullSelection,\n\ttype YSelection,\n} from './block-selection-history';\nimport {\n\tfindBlockByClientIdInDoc,\n\thtmlIndexToRichTextOffset,\n} from './crdt-utils';\nimport type { WPBlockSelection, WPSelection } from '../types';\n\n// WeakMap to store BlockSelectionHistory instances per Y.Doc\nconst selectionHistoryMap = new WeakMap< CRDTDoc, BlockSelectionHistory >();\n\n/**\n * Get or create a BlockSelectionHistory instance for a given Y.Doc.\n *\n * @param ydoc The Y.Doc to get the selection history for\n * @return The BlockSelectionHistory instance\n */\nfunction getBlockSelectionHistory( ydoc: CRDTDoc ): BlockSelectionHistory {\n\tlet history = selectionHistoryMap.get( ydoc );\n\n\tif ( ! history ) {\n\t\thistory = createBlockSelectionHistory( ydoc );\n\t\tselectionHistoryMap.set( ydoc, history );\n\t}\n\n\treturn history;\n}\n\nexport function getSelectionHistory( ydoc: CRDTDoc ): YFullSelection[] {\n\treturn getBlockSelectionHistory( ydoc ).getSelectionHistory();\n}\n\nexport function updateSelectionHistory(\n\tydoc: CRDTDoc,\n\twpSelection: WPSelection\n): void {\n\treturn getBlockSelectionHistory( ydoc ).updateSelection( wpSelection );\n}\n\n/**\n * Convert a YSelection to a WPBlockSelection.\n * @param ySelection The YSelection (relative) to convert\n * @param ydoc The Y.Doc to convert the selection to a block selection for\n * @return The converted WPBlockSelection, or null if the conversion fails\n */\nfunction convertYSelectionToBlockSelection(\n\tySelection: YSelection,\n\tydoc: Y.Doc\n): WPBlockSelection | null {\n\tif ( ySelection.type === YSelectionType.RelativeSelection ) {\n\t\tconst { relativePosition, attributeKey, clientId } = ySelection;\n\n\t\tconst absolutePosition = Y.createAbsolutePositionFromRelativePosition(\n\t\t\trelativePosition,\n\t\t\tydoc\n\t\t);\n\n\t\tif ( absolutePosition ) {\n\t\t\treturn {\n\t\t\t\tclientId,\n\t\t\t\tattributeKey,\n\t\t\t\toffset: htmlIndexToRichTextOffset(\n\t\t\t\t\tabsolutePosition.type.toString(),\n\t\t\t\t\tabsolutePosition.index\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\t} else if ( ySelection.type === YSelectionType.BlockSelection ) {\n\t\treturn {\n\t\t\tclientId: ySelection.clientId,\n\t\t\tattributeKey: undefined,\n\t\t\toffset: undefined,\n\t\t};\n\t}\n\n\treturn null;\n}\n\n/**\n * Convert a YFullSelection to a WPSelection by resolving relative positions\n * and verifying the blocks exist in the document.\n * @param yFullSelection The YFullSelection to convert\n * @param ydoc The Y.Doc to resolve positions against\n * @return The converted WPSelection, or null if the conversion fails\n */\nfunction convertYFullSelectionToWPSelection(\n\tyFullSelection: YFullSelection,\n\tydoc: Y.Doc\n): WPSelection | null {\n\tconst { start, end } = yFullSelection;\n\tconst startBlock = findBlockByClientIdInDoc( start.clientId, ydoc );\n\tconst endBlock = findBlockByClientIdInDoc( end.clientId, ydoc );\n\n\tif ( ! startBlock || ! endBlock ) {\n\t\treturn null;\n\t}\n\n\tconst startBlockSelection = convertYSelectionToBlockSelection(\n\t\tstart,\n\t\tydoc\n\t);\n\tconst endBlockSelection = convertYSelectionToBlockSelection( end, ydoc );\n\n\tif ( startBlockSelection === null || endBlockSelection === null ) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tselectionStart: startBlockSelection,\n\t\tselectionEnd: endBlockSelection,\n\t};\n}\n\n/**\n * Given a Y.Doc and a selection history, find the most recent selection\n * that exists in the document. Skip any selections that are not in the document.\n * @param ydoc The Y.Doc to find the selection in\n * @param selectionHistory The selection history to check\n * @return The most recent selection that exists in the document, or null if no selection exists.\n */\nfunction findSelectionFromHistory(\n\tydoc: Y.Doc,\n\tselectionHistory: YFullSelection[]\n): WPSelection | null {\n\tfor ( const positionToTry of selectionHistory ) {\n\t\tconst result = convertYFullSelectionToWPSelection(\n\t\t\tpositionToTry,\n\t\t\tydoc\n\t\t);\n\t\tif ( result !== null ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Restore the selection to the most recent selection in history that is\n * available in the document.\n * @param selectionHistory The selection history to restore\n * @param ydoc The Y.Doc where blocks are stored\n */\nexport function restoreSelection(\n\tselectionHistory: YFullSelection[],\n\tydoc: Y.Doc\n): void {\n\t// Find the most recent selection in history that is available in\n\t// the document.\n\tconst selectionToRestore = findSelectionFromHistory(\n\t\tydoc,\n\t\tselectionHistory\n\t);\n\n\tif ( selectionToRestore === null ) {\n\t\t// Case 1: No blocks in history are available for restoration.\n\t\t// Do nothing.\n\t\treturn;\n\t}\n\n\tconst { getBlock } = select( blockEditorStore );\n\tconst { resetSelection } = dispatch( blockEditorStore );\n\tconst { selectionStart, selectionEnd } = selectionToRestore;\n\tconst isSelectionInSameBlock =\n\t\tselectionStart.clientId === selectionEnd.clientId;\n\n\tif ( isSelectionInSameBlock ) {\n\t\t// Case 2: After content is restored, the selection is available\n\t\t// within the same block\n\n\t\tconst block = getBlock( selectionStart.clientId );\n\t\tconst isBlockEmpty = block && isUnmodifiedBlock( block );\n\t\tconst isBeginningOfEmptyBlock =\n\t\t\t0 === selectionStart.offset &&\n\t\t\t0 === selectionEnd.offset &&\n\t\t\tisBlockEmpty &&\n\t\t\t! selectionStart.attributeKey &&\n\t\t\t! selectionEnd.attributeKey;\n\n\t\tif ( isBeginningOfEmptyBlock ) {\n\t\t\t// Case 2a: When the content in a block has been removed after an\n\t\t\t// undo, WordPress will set the selection to the block's client ID\n\t\t\t// with an undefined startOffset and endOffset.\n\t\t\t//\n\t\t\t// To match the default behavior and tests, exclude the selection\n\t\t\t// offset when resetting to position 0.\n\t\t\tconst selectionStartWithoutOffset = {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t};\n\t\t\tconst selectionEndWithoutOffset = {\n\t\t\t\tclientId: selectionEnd.clientId,\n\t\t\t};\n\n\t\t\tresetSelection(\n\t\t\t\tselectionStartWithoutOffset,\n\t\t\t\tselectionEndWithoutOffset,\n\t\t\t\t0\n\t\t\t);\n\t\t} else {\n\t\t\t// Case 2b: Otherwise, reset including the saved selection offset.\n\t\t\tresetSelection( selectionStart, selectionEnd, 0 );\n\t\t}\n\t} else {\n\t\t// Case 3: A multi-block selection was made. resetSelection() can only\n\t\t// restore selections within the same block.\n\t\t// When a multi-block selection is made, selectionEnd represents\n\t\t// where the user's cursor ended.\n\t\tresetSelection( selectionEnd, selectionEnd, 0 );\n\t}\n}\n\n/**\n * If the latest selection has been shifted by remote edits, resolve and return\n * it as a WPSelection. Returns null when the history is empty or neither\n * endpoint has moved.\n *\n * @param ydoc The Y.Doc to resolve positions against\n * @param selectionHistory The selection history to check\n * @return The shifted WPSelection, or null if nothing moved.\n */\nexport function getShiftedSelection(\n\tydoc: Y.Doc,\n\tselectionHistory: YFullSelection[]\n): WPSelection | null {\n\tif ( selectionHistory.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tconst { start, end } = selectionHistory[ 0 ];\n\n\t// Block-level selections have no offset that can shift.\n\tif (\n\t\tstart.type === YSelectionType.BlockSelection ||\n\t\tend.type === YSelectionType.BlockSelection\n\t) {\n\t\treturn null;\n\t}\n\n\tconst selectionStart = convertYSelectionToBlockSelection( start, ydoc );\n\tconst selectionEnd = convertYSelectionToBlockSelection( end, ydoc );\n\n\tif ( ! selectionStart || ! selectionEnd ) {\n\t\treturn null;\n\t}\n\n\t// Only dispatch if at least one endpoint actually moved.\n\tconst startShifted = selectionStart.offset !== start.offset;\n\tconst endShifted = selectionEnd.offset !== end.offset;\n\n\tif ( ! startShifted && ! endShifted ) {\n\t\treturn null;\n\t}\n\n\treturn { selectionStart, selectionEnd };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { dispatch, select } from '@wordpress/data';\n// @ts-expect-error No exported types.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\nimport { isUnmodifiedBlock } from '@wordpress/blocks';\nimport { type CRDTDoc, Y } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport {\n\tcreateBlockSelectionHistory,\n\tYSelectionType,\n\ttype BlockSelectionHistory,\n\ttype YFullSelection,\n\ttype YSelection,\n} from './block-selection-history';\nimport {\n\tfindBlockByClientIdInDoc,\n\thtmlIndexToRichTextOffset,\n} from './crdt-utils';\nimport type { WPBlockSelection, WPSelection } from '../types';\n\n// WeakMap to store BlockSelectionHistory instances per Y.Doc\nconst selectionHistoryMap = new WeakMap< CRDTDoc, BlockSelectionHistory >();\n\n/**\n * Get or create a BlockSelectionHistory instance for a given Y.Doc.\n *\n * @param ydoc The Y.Doc to get the selection history for\n * @return The BlockSelectionHistory instance\n */\nfunction getBlockSelectionHistory( ydoc: CRDTDoc ): BlockSelectionHistory {\n\tlet history = selectionHistoryMap.get( ydoc );\n\n\tif ( ! history ) {\n\t\thistory = createBlockSelectionHistory( ydoc );\n\t\tselectionHistoryMap.set( ydoc, history );\n\t}\n\n\treturn history;\n}\n\nexport function getSelectionHistory( ydoc: CRDTDoc ): YFullSelection[] {\n\treturn getBlockSelectionHistory( ydoc ).getSelectionHistory();\n}\n\nexport function updateSelectionHistory(\n\tydoc: CRDTDoc,\n\twpSelection: WPSelection\n): void {\n\treturn getBlockSelectionHistory( ydoc ).updateSelection( wpSelection );\n}\n\n/**\n * Convert a YSelection to a WPBlockSelection.\n * @param ySelection The YSelection (relative) to convert\n * @param ydoc The Y.Doc to convert the selection to a block selection for\n * @return The converted WPBlockSelection, or null if the conversion fails\n */\nfunction convertYSelectionToBlockSelection(\n\tySelection: YSelection,\n\tydoc: Y.Doc\n): WPBlockSelection | null {\n\tif ( ySelection.type === YSelectionType.RelativeSelection ) {\n\t\tconst { relativePosition, attributeKey, clientId } = ySelection;\n\n\t\tconst absolutePosition = Y.createAbsolutePositionFromRelativePosition(\n\t\t\trelativePosition,\n\t\t\tydoc\n\t\t);\n\n\t\tif ( absolutePosition ) {\n\t\t\treturn {\n\t\t\t\tclientId,\n\t\t\t\tattributeKey,\n\t\t\t\toffset: htmlIndexToRichTextOffset(\n\t\t\t\t\tabsolutePosition.type.toString(),\n\t\t\t\t\tabsolutePosition.index\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\t} else if ( ySelection.type === YSelectionType.BlockSelection ) {\n\t\treturn {\n\t\t\tclientId: ySelection.clientId,\n\t\t\tattributeKey: undefined,\n\t\t\toffset: undefined,\n\t\t};\n\t}\n\n\treturn null;\n}\n\n/**\n * Convert a YFullSelection to a WPSelection by resolving relative positions\n * and verifying the blocks exist in the document.\n * @param yFullSelection The YFullSelection to convert\n * @param ydoc The Y.Doc to resolve positions against\n * @return The converted WPSelection, or null if the conversion fails\n */\nfunction convertYFullSelectionToWPSelection(\n\tyFullSelection: YFullSelection,\n\tydoc: Y.Doc\n): WPSelection | null {\n\tconst { start, end } = yFullSelection;\n\tconst startBlock = findBlockByClientIdInDoc( start.clientId, ydoc );\n\tconst endBlock = findBlockByClientIdInDoc( end.clientId, ydoc );\n\n\tif ( ! startBlock || ! endBlock ) {\n\t\treturn null;\n\t}\n\n\tconst startBlockSelection = convertYSelectionToBlockSelection(\n\t\tstart,\n\t\tydoc\n\t);\n\tconst endBlockSelection = convertYSelectionToBlockSelection( end, ydoc );\n\n\tif ( startBlockSelection === null || endBlockSelection === null ) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tselectionStart: startBlockSelection,\n\t\tselectionEnd: endBlockSelection,\n\t};\n}\n\n/**\n * Given a Y.Doc and a selection history, find the most recent selection\n * that exists in the document. Skip any selections that are not in the document.\n * @param ydoc The Y.Doc to find the selection in\n * @param selectionHistory The selection history to check\n * @return The most recent selection that exists in the document, or null if no selection exists.\n */\nfunction findSelectionFromHistory(\n\tydoc: Y.Doc,\n\tselectionHistory: YFullSelection[]\n): WPSelection | null {\n\tfor ( const positionToTry of selectionHistory ) {\n\t\tconst result = convertYFullSelectionToWPSelection(\n\t\t\tpositionToTry,\n\t\t\tydoc\n\t\t);\n\t\tif ( result !== null ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Restore the selection to the most recent selection in history that is\n * available in the document.\n * @param selectionHistory The selection history to restore\n * @param ydoc The Y.Doc where blocks are stored\n */\nexport function restoreSelection(\n\tselectionHistory: YFullSelection[],\n\tydoc: Y.Doc\n): void {\n\t// Find the most recent selection in history that is available in\n\t// the document.\n\tconst selectionToRestore = findSelectionFromHistory(\n\t\tydoc,\n\t\tselectionHistory\n\t);\n\n\tif ( selectionToRestore === null ) {\n\t\t// Case 1: No blocks in history are available for restoration.\n\t\t// Do nothing.\n\t\treturn;\n\t}\n\n\tconst { getBlock } = select( blockEditorStore );\n\tconst { resetSelection } = dispatch( blockEditorStore );\n\tconst { selectionStart, selectionEnd } = selectionToRestore;\n\tconst isSelectionInSameBlock =\n\t\tselectionStart.clientId === selectionEnd.clientId;\n\n\tif ( isSelectionInSameBlock ) {\n\t\t// Case 2: After content is restored, the selection is available\n\t\t// within the same block\n\n\t\tconst block = getBlock( selectionStart.clientId );\n\t\tconst isBlockEmpty = block && isUnmodifiedBlock( block );\n\t\tconst isBeginningOfEmptyBlock =\n\t\t\t0 === selectionStart.offset &&\n\t\t\t0 === selectionEnd.offset &&\n\t\t\tisBlockEmpty &&\n\t\t\t! selectionStart.attributeKey &&\n\t\t\t! selectionEnd.attributeKey;\n\n\t\tif ( isBeginningOfEmptyBlock ) {\n\t\t\t// Case 2a: When the content in a block has been removed after an\n\t\t\t// undo, WordPress will set the selection to the block's client ID\n\t\t\t// with an undefined startOffset and endOffset.\n\t\t\t//\n\t\t\t// To match the default behavior and tests, exclude the selection\n\t\t\t// offset when resetting to position 0.\n\t\t\tconst selectionStartWithoutOffset = {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t};\n\t\t\tconst selectionEndWithoutOffset = {\n\t\t\t\tclientId: selectionEnd.clientId,\n\t\t\t};\n\n\t\t\tresetSelection(\n\t\t\t\tselectionStartWithoutOffset,\n\t\t\t\tselectionEndWithoutOffset,\n\t\t\t\t0\n\t\t\t);\n\t\t} else {\n\t\t\t// Case 2b: Otherwise, reset including the saved selection offset.\n\t\t\tresetSelection( selectionStart, selectionEnd, 0 );\n\t\t}\n\t} else {\n\t\t// Case 3: A multi-block selection was made. resetSelection() can only\n\t\t// restore selections within the same block.\n\t\t// When a multi-block selection is made, selectionEnd represents\n\t\t// where the user's cursor ended.\n\t\tresetSelection( selectionEnd, selectionEnd, 0 );\n\t}\n}\n\n/**\n * If the latest selection has been shifted by remote edits, resolve and return\n * it as a WPSelection. Returns null when the history is empty or neither\n * endpoint has moved.\n *\n * @param ydoc The Y.Doc to resolve positions against\n * @param selectionHistory The selection history to check\n * @return The shifted WPSelection, or null if nothing moved.\n */\nexport function getShiftedSelection(\n\tydoc: Y.Doc,\n\tselectionHistory: YFullSelection[]\n): WPSelection | null {\n\tif ( selectionHistory.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tconst { start, end } = selectionHistory[ 0 ];\n\n\t// Block-level selections have no offset that can shift.\n\tif (\n\t\tstart.type === YSelectionType.BlockSelection ||\n\t\tend.type === YSelectionType.BlockSelection\n\t) {\n\t\treturn null;\n\t}\n\n\tconst selectionStart = convertYSelectionToBlockSelection( start, ydoc );\n\tconst selectionEnd = convertYSelectionToBlockSelection( end, ydoc );\n\n\tif ( ! selectionStart || ! selectionEnd ) {\n\t\treturn null;\n\t}\n\n\t// Only dispatch if at least one endpoint actually moved.\n\tconst startShifted = selectionStart.offset !== start.offset;\n\tconst endShifted = selectionEnd.offset !== end.offset;\n\n\tif ( ! startShifted && ! endShifted ) {\n\t\treturn null;\n\t}\n\n\treturn { selectionStart, selectionEnd };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/crdt.ts"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\n// @ts-expect-error No exported types.\nimport { __unstableSerializeAndClean } from '@wordpress/blocks';\nimport {\n\ttype CRDTDoc,\n\ttype ObjectData,\n\ttype ObjectID,\n\ttype ObjectType,\n\ttype SyncConfig,\n\tY,\n} from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwareness } from '../awareness/base-awareness';\nimport {\n\tdeserializeBlockAttributes,\n\tmergeCrdtBlocks,\n\tmergeRichTextUpdate,\n\ttype Block,\n\ttype YBlock,\n\ttype YBlocks,\n} from './crdt-blocks';\nimport { type Post } from '../entity-types/post';\nimport { CRDT_DOC_META_PERSISTENCE_KEY, CRDT_RECORD_MAP_KEY } from '../sync';\nimport type { WPSelection } from '../types';\nimport {\n\tgetSelectionHistory,\n\tgetShiftedSelection,\n\tupdateSelectionHistory,\n} from './crdt-selection';\nimport {\n\tcreateYMap,\n\tgetRootMap,\n\tisYMap,\n\ttype YMapRecord,\n\ttype YMapWrap,\n} from './crdt-utils';\n\n// Changes that can be applied to a post entity record.\nexport type PostChanges = Partial< Post > & {\n\tblocks?: Block[];\n\tcontent?: Post[ 'content' ] | string;\n\texcerpt?: Post[ 'excerpt' ] | string;\n\tselection?: WPSelection;\n\ttitle?: Post[ 'title' ] | string;\n};\n\n// A post record as represented in the CRDT document (Y.Map).\nexport interface YPostRecord extends YMapRecord {\n\tauthor: number;\n\t// Blocks are undefined when they need to be re-parsed from content.\n\tblocks: YBlocks | undefined;\n\tcontent: Y.Text;\n\tcategories: number[];\n\tcomment_status: string;\n\tdate: string | null;\n\texcerpt: Y.Text;\n\tfeatured_media: number;\n\tformat: string;\n\tmeta: YMapWrap< YMapRecord >;\n\tping_status: string;\n\tslug: string;\n\tstatus: string;\n\tsticky: boolean;\n\ttags: number[];\n\ttemplate: string;\n\ttitle: Y.Text;\n}\n\nexport const POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE = '_crdt_document';\n\n// Post meta keys that should *not* be synced.\nconst disallowedPostMetaKeys = new Set< string >( [\n\tPOST_META_KEY_FOR_CRDT_DOC_PERSISTENCE,\n] );\n\n/**\n * Given a set of local changes to a generic entity record, apply those changes\n * to the local Y.Doc.\n *\n * @param {CRDTDoc} ydoc\n * @param {Partial< ObjectData >} changes\n * @return {void}\n */\nfunction defaultApplyChangesToCRDTDoc(\n\tydoc: CRDTDoc,\n\tchanges: ObjectData\n): void {\n\tconst ymap = getRootMap( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tObject.entries( changes ).forEach( ( [ key, newValue ] ) => {\n\t\t// Cannot serialize function values, so cannot sync them.\n\t\tif ( 'function' === typeof newValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( key ) {\n\t\t\t// Add support for additional data types here.\n\n\t\t\tdefault: {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t}\n\t\t}\n\t} );\n}\n\n/**\n * Given a set of local changes to a post record, apply those changes to the\n * local Y.Doc.\n *\n * @param {CRDTDoc} ydoc\n * @param {PostChanges} changes\n * @param {Set<string>} syncedProperties\n * @return {void}\n */\nexport function applyPostChangesToCRDTDoc(\n\tydoc: CRDTDoc,\n\tchanges: PostChanges,\n\tsyncedProperties: Set< string >\n): void {\n\tconst ymap = getRootMap< YPostRecord >( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tObject.keys( changes ).forEach( ( key ) => {\n\t\tif ( ! syncedProperties.has( key ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newValue = changes[ key ];\n\n\t\t// Cannot serialize function values, so cannot sync them.\n\t\tif ( 'function' === typeof newValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( key ) {\n\t\t\tcase 'blocks': {\n\t\t\t\t// Blocks are undefined when they need to be re-parsed from content.\n\t\t\t\tif ( ! newValue ) {\n\t\t\t\t\t// Set to undefined instead of deleting the key. This is important\n\t\t\t\t\t// since we iterate over the Y.Map keys in getPostChangesFromCRDTDoc.\n\t\t\t\t\tymap.set( key, undefined );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tlet currentBlocks = ymap.get( key );\n\n\t\t\t\t// Initialize.\n\t\t\t\tif ( ! ( currentBlocks instanceof Y.Array ) ) {\n\t\t\t\t\tcurrentBlocks = new Y.Array< YBlock >();\n\t\t\t\t\tymap.set( key, currentBlocks );\n\t\t\t\t}\n\n\t\t\t\t// Block changes from typing are bundled with a 'selection' update.\n\t\t\t\t// Pass the resulting cursor position to the mergeCrdtBlocks function.\n\t\t\t\tconst cursorPosition =\n\t\t\t\t\tchanges.selection?.selectionStart?.offset ?? null;\n\n\t\t\t\t// Merge blocks does not need `setValue` because it is operating on a\n\t\t\t\t// Yjs type that is already in the Y.Doc.\n\t\t\t\tmergeCrdtBlocks( currentBlocks, newValue, cursorPosition );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'content':\n\t\t\tcase 'excerpt':\n\t\t\tcase 'title': {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tlet rawValue = getRawValue( newValue );\n\n\t\t\t\t// Copy logic from prePersistPostType to ensure that the \"Auto\n\t\t\t\t// Draft\" template title is not synced.\n\t\t\t\tif (\n\t\t\t\t\tkey === 'title' &&\n\t\t\t\t\t! currentValue?.toString() &&\n\t\t\t\t\t'Auto Draft' === rawValue\n\t\t\t\t) {\n\t\t\t\t\trawValue = '';\n\t\t\t\t}\n\n\t\t\t\tif ( currentValue instanceof Y.Text ) {\n\t\t\t\t\tmergeRichTextUpdate( currentValue, rawValue ?? '' );\n\t\t\t\t} else {\n\t\t\t\t\tconst newYText = new Y.Text( rawValue ?? '' );\n\t\t\t\t\tymap.set( key, newYText );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// \"Meta\" is overloaded term; here, it refers to post meta.\n\t\t\tcase 'meta': {\n\t\t\t\tlet metaMap = ymap.get( 'meta' );\n\n\t\t\t\t// Initialize.\n\t\t\t\tif ( ! isYMap( metaMap ) ) {\n\t\t\t\t\tmetaMap = createYMap< YMapRecord >();\n\t\t\t\t\tymap.set( 'meta', metaMap );\n\t\t\t\t}\n\n\t\t\t\t// Iterate over each meta property in the new value and merge it if it\n\t\t\t\t// should be synced.\n\t\t\t\tObject.entries( newValue ?? {} ).forEach(\n\t\t\t\t\t( [ metaKey, metaValue ] ) => {\n\t\t\t\t\t\tif ( disallowedPostMetaKeys.has( metaKey ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdateMapValue(\n\t\t\t\t\t\t\tmetaMap,\n\t\t\t\t\t\t\tmetaKey,\n\t\t\t\t\t\t\tmetaMap.get( metaKey ), // current value in CRDT\n\t\t\t\t\t\t\tmetaValue // new value from changes\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'slug': {\n\t\t\t\t// Do not sync an empty slug. This indicates that the post is using\n\t\t\t\t// the default auto-generated slug.\n\t\t\t\tif ( ! newValue ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Add support for additional properties here.\n\n\t\t\tdefault: {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t}\n\t\t}\n\t} );\n\n\t// Process changes that we don't want to persist to the CRDT document.\n\tif ( changes.selection ) {\n\t\tconst selection = changes.selection;\n\t\t// Persist selection changes at the end of the current event loop.\n\t\t// This allows undo meta to be saved with the current selection before\n\t\t// it is overwritten by the new selection from Gutenberg.\n\t\t// Without this, selection history will already contain the latest\n\t\t// selection (after this change) when the undo stack is saved.\n\t\tsetTimeout( () => {\n\t\t\tupdateSelectionHistory( ydoc, selection );\n\t\t}, 0 );\n\t}\n}\n\nfunction defaultGetChangesFromCRDTDoc( crdtDoc: CRDTDoc ): ObjectData {\n\treturn getRootMap( crdtDoc, CRDT_RECORD_MAP_KEY ).toJSON();\n}\n\n/**\n * Given a local Y.Doc that *may* contain changes from remote peers, compare\n * against the local record and determine if there are changes (edits) we want\n * to dispatch.\n *\n * @param {CRDTDoc} ydoc\n * @param {Post} editedRecord\n * @param {Set<string>} syncedProperties\n * @return {Partial<PostChanges>} The changes that should be applied to the local record.\n */\nexport function getPostChangesFromCRDTDoc(\n\tydoc: CRDTDoc,\n\teditedRecord: Post,\n\tsyncedProperties: Set< string >\n): PostChanges {\n\tconst ymap = getRootMap< YPostRecord >( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tlet allowedMetaChanges: Post[ 'meta' ] = {};\n\n\tconst changes = Object.fromEntries(\n\t\tObject.entries( ymap.toJSON() ).filter( ( [ key, newValue ] ) => {\n\t\t\tif ( ! syncedProperties.has( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst currentValue = editedRecord[ key ];\n\n\t\t\tswitch ( key ) {\n\t\t\t\tcase 'blocks': {\n\t\t\t\t\t// When we are passed a persisted CRDT document, make a special\n\t\t\t\t\t// comparison of the content and blocks.\n\t\t\t\t\t//\n\t\t\t\t\t// When other fields (besides `blocks`) are mutated outside the block\n\t\t\t\t\t// editor, the change is caught by an equality check (see other cases\n\t\t\t\t\t// in this `switch` statement). As a transient property, `blocks`\n\t\t\t\t\t// cannot be directly mutated outside the block editor -- only\n\t\t\t\t\t// `content` can.\n\t\t\t\t\t//\n\t\t\t\t\t// Therefore, for this special comparison, we serialize the `blocks`\n\t\t\t\t\t// from the persisted CRDT document and compare that to the content\n\t\t\t\t\t// from the persisted record. If they differ, we know that the content\n\t\t\t\t\t// in the database has changed, and therefore the blocks have changed.\n\t\t\t\t\t//\n\t\t\t\t\t// We cannot directly compare the `blocks` from the CRDT document to\n\t\t\t\t\t// the `blocks` derived from the `content` in the persisted record,\n\t\t\t\t\t// because the latter will have different client IDs.\n\t\t\t\t\tif (\n\t\t\t\t\t\tydoc.meta?.get( CRDT_DOC_META_PERSISTENCE_KEY ) &&\n\t\t\t\t\t\teditedRecord.content\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst blocksJson = ymap.get( 'blocks' )?.toJSON() ?? [];\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t__unstableSerializeAndClean( blocksJson ).trim() !==\n\t\t\t\t\t\t\tgetRawValue( editedRecord.content )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tcase 'date': {\n\t\t\t\t\t// Do not overwrite a \"floating\" date. Borrowing logic from the\n\t\t\t\t\t// isEditedPostDateFloating selector.\n\t\t\t\t\tconst currentDateIsFloating =\n\t\t\t\t\t\tnull === currentValue ||\n\t\t\t\t\t\teditedRecord.modified === currentValue;\n\n\t\t\t\t\tif ( currentDateIsFloating ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'meta': {\n\t\t\t\t\tallowedMetaChanges = Object.fromEntries(\n\t\t\t\t\t\tObject.entries( newValue ?? {} ).filter(\n\t\t\t\t\t\t\t( [ metaKey ] ) =>\n\t\t\t\t\t\t\t\t! disallowedPostMetaKeys.has( metaKey )\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\n\t\t\t\t\t// Merge the allowed meta changes with the current meta values since\n\t\t\t\t\t// not all meta properties are synced.\n\t\t\t\t\tconst mergedValue = {\n\t\t\t\t\t\t...( currentValue as PostChanges[ 'meta' ] ),\n\t\t\t\t\t\t...allowedMetaChanges,\n\t\t\t\t\t};\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, mergedValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'status': {\n\t\t\t\t\t// Do not sync an invalid status.\n\t\t\t\t\tif ( 'auto-draft' === newValue ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'content':\n\t\t\t\tcase 'excerpt':\n\t\t\t\tcase 'title': {\n\t\t\t\t\treturn haveValuesChanged(\n\t\t\t\t\t\tgetRawValue( currentValue ),\n\t\t\t\t\t\tnewValue\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Add support for additional data types here.\n\n\t\t\t\tdefault: {\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\t\t\t}\n\t\t} )\n\t);\n\n\t// Blocks extracted from the CRDT document have rich-text attributes as\n\t// plain strings (from Y.Text.toJSON()). Convert them back to RichTextData\n\t// so block edit components receive the same types as locally-created blocks.\n\tif ( changes.blocks ) {\n\t\tchanges.blocks = deserializeBlockAttributes(\n\t\t\tchanges.blocks as Block[]\n\t\t);\n\t}\n\n\t// Meta changes must be merged with the edited record since not all meta\n\t// properties are synced.\n\tif ( 'object' === typeof changes.meta ) {\n\t\tchanges.meta = {\n\t\t\t...editedRecord.meta,\n\t\t\t...allowedMetaChanges,\n\t\t};\n\t}\n\n\t// When remote content changes are detected, recalculate the local user's\n\t// selection using Y.RelativePosition to account for text shifts. The ydoc\n\t// has already been updated with remote content at this point, so converting\n\t// relative positions to absolute gives corrected offsets. Including the\n\t// selection in PostChanges ensures it dispatches atomically with content.\n\tconst selectionHistory = getSelectionHistory( ydoc );\n\tconst shiftedSelection = getShiftedSelection( ydoc, selectionHistory );\n\tif ( shiftedSelection ) {\n\t\tchanges.selection = {\n\t\t\t...shiftedSelection,\n\t\t\tinitialPosition: 0,\n\t\t};\n\t}\n\n\treturn changes;\n}\n\n/**\n * This default sync config can be used for entities that are flat maps of\n * primitive values and do not require custom logic to merge changes.\n */\nexport const defaultSyncConfig: SyncConfig = {\n\tapplyChangesToCRDTDoc: defaultApplyChangesToCRDTDoc,\n\tcreateAwareness: ( ydoc: CRDTDoc ) => new BaseAwareness( ydoc ),\n\tgetChangesFromCRDTDoc: defaultGetChangesFromCRDTDoc,\n};\n\n/**\n * This default collection sync config can be used to sync entity collections\n * (e.g., block comments) where we are not interested in merging changes at the\n * individual record level, but instead want to replace the entire collection\n * when changes are detected.\n */\nexport const defaultCollectionSyncConfig: SyncConfig = {\n\tapplyChangesToCRDTDoc: () => {},\n\tgetChangesFromCRDTDoc: () => ( {} ),\n\tshouldSync: ( _: ObjectType, objectId: ObjectID | null ) =>\n\t\tnull === objectId,\n};\n\n/**\n * Extract the raw string value from a property that may be a string or an object\n * with a `raw` property (`RenderedText`).\n *\n * @param {unknown} value The value to extract from.\n * @return {string|undefined} The raw string value, or undefined if it could not be determined.\n */\nfunction getRawValue( value?: unknown ): string | undefined {\n\t// Value may be a string property or a nested object with a `raw` property.\n\tif ( 'string' === typeof value ) {\n\t\treturn value;\n\t}\n\n\tif (\n\t\tvalue &&\n\t\t'object' === typeof value &&\n\t\t'raw' in value &&\n\t\t'string' === typeof value.raw\n\t) {\n\t\treturn value.raw;\n\t}\n\n\treturn undefined;\n}\n\nfunction haveValuesChanged< ValueType >(\n\tcurrentValue: ValueType | undefined,\n\tnewValue: ValueType | undefined\n): boolean {\n\treturn ! fastDeepEqual( currentValue, newValue );\n}\n\nfunction updateMapValue< T extends YMapRecord, K extends keyof T >(\n\tmap: YMapWrap< T >,\n\tkey: K,\n\tcurrentValue: T[ K ] | undefined,\n\tnewValue: T[ K ] | undefined\n): void {\n\tif ( undefined === newValue ) {\n\t\tmap.delete( key );\n\t\treturn;\n\t}\n\n\tif ( haveValuesChanged< T[ K ] >( currentValue, newValue ) ) {\n\t\tmap.set( key, newValue );\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\nimport { __unstableSerializeAndClean } from '@wordpress/blocks';\nimport {\n\ttype CRDTDoc,\n\ttype ObjectData,\n\ttype ObjectID,\n\ttype ObjectType,\n\ttype SyncConfig,\n\tY,\n} from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { BaseAwareness } from '../awareness/base-awareness';\nimport {\n\tdeserializeBlockAttributes,\n\tmergeCrdtBlocks,\n\tmergeRichTextUpdate,\n\ttype Block,\n\ttype YBlock,\n\ttype YBlocks,\n} from './crdt-blocks';\nimport { type Post } from '../entity-types/post';\nimport { CRDT_DOC_META_PERSISTENCE_KEY, CRDT_RECORD_MAP_KEY } from '../sync';\nimport type { WPSelection } from '../types';\nimport {\n\tgetSelectionHistory,\n\tgetShiftedSelection,\n\tupdateSelectionHistory,\n} from './crdt-selection';\nimport {\n\tcreateYMap,\n\tgetRootMap,\n\tisYMap,\n\ttype YMapRecord,\n\ttype YMapWrap,\n} from './crdt-utils';\n\n// Changes that can be applied to a post entity record.\nexport type PostChanges = Partial< Post > & {\n\tblocks?: Block[];\n\tcontent?: Post[ 'content' ] | string;\n\texcerpt?: Post[ 'excerpt' ] | string;\n\tselection?: WPSelection;\n\ttitle?: Post[ 'title' ] | string;\n};\n\n// A post record as represented in the CRDT document (Y.Map).\nexport interface YPostRecord extends YMapRecord {\n\tauthor: number;\n\t// Blocks are undefined when they need to be re-parsed from content.\n\tblocks: YBlocks | undefined;\n\tcontent: Y.Text;\n\tcategories: number[];\n\tcomment_status: string;\n\tdate: string | null;\n\texcerpt: Y.Text;\n\tfeatured_media: number;\n\tformat: string;\n\tmeta: YMapWrap< YMapRecord >;\n\tping_status: string;\n\tslug: string;\n\tstatus: string;\n\tsticky: boolean;\n\ttags: number[];\n\ttemplate: string;\n\ttitle: Y.Text;\n}\n\nexport const POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE = '_crdt_document';\n\n// Post meta keys that should *not* be synced.\nconst disallowedPostMetaKeys = new Set< string >( [\n\tPOST_META_KEY_FOR_CRDT_DOC_PERSISTENCE,\n] );\n\n/**\n * Given a set of local changes to a generic entity record, apply those changes\n * to the local Y.Doc.\n *\n * @param {CRDTDoc} ydoc\n * @param {Partial< ObjectData >} changes\n * @return {void}\n */\nfunction defaultApplyChangesToCRDTDoc(\n\tydoc: CRDTDoc,\n\tchanges: ObjectData\n): void {\n\tconst ymap = getRootMap( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tObject.entries( changes ).forEach( ( [ key, newValue ] ) => {\n\t\t// Cannot serialize function values, so cannot sync them.\n\t\tif ( 'function' === typeof newValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( key ) {\n\t\t\t// Add support for additional data types here.\n\n\t\t\tdefault: {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t}\n\t\t}\n\t} );\n}\n\n/**\n * Given a set of local changes to a post record, apply those changes to the\n * local Y.Doc.\n *\n * @param {CRDTDoc} ydoc\n * @param {PostChanges} changes\n * @param {Set<string>} syncedProperties\n * @return {void}\n */\nexport function applyPostChangesToCRDTDoc(\n\tydoc: CRDTDoc,\n\tchanges: PostChanges,\n\tsyncedProperties: Set< string >\n): void {\n\tconst ymap = getRootMap< YPostRecord >( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tObject.keys( changes ).forEach( ( key ) => {\n\t\tif ( ! syncedProperties.has( key ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newValue = changes[ key ];\n\n\t\t// Cannot serialize function values, so cannot sync them.\n\t\tif ( 'function' === typeof newValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( key ) {\n\t\t\tcase 'blocks': {\n\t\t\t\t// Blocks are undefined when they need to be re-parsed from content.\n\t\t\t\tif ( ! newValue ) {\n\t\t\t\t\t// Set to undefined instead of deleting the key. This is important\n\t\t\t\t\t// since we iterate over the Y.Map keys in getPostChangesFromCRDTDoc.\n\t\t\t\t\tymap.set( key, undefined );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tlet currentBlocks = ymap.get( key );\n\n\t\t\t\t// Initialize.\n\t\t\t\tif ( ! ( currentBlocks instanceof Y.Array ) ) {\n\t\t\t\t\tcurrentBlocks = new Y.Array< YBlock >();\n\t\t\t\t\tymap.set( key, currentBlocks );\n\t\t\t\t}\n\n\t\t\t\t// Block changes from typing are bundled with a 'selection' update.\n\t\t\t\t// Pass the resulting cursor position to the mergeCrdtBlocks function.\n\t\t\t\tconst cursorPosition =\n\t\t\t\t\tchanges.selection?.selectionStart?.offset ?? null;\n\n\t\t\t\t// Merge blocks does not need `setValue` because it is operating on a\n\t\t\t\t// Yjs type that is already in the Y.Doc.\n\t\t\t\tmergeCrdtBlocks( currentBlocks, newValue, cursorPosition );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'content':\n\t\t\tcase 'excerpt':\n\t\t\tcase 'title': {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tlet rawValue = getRawValue( newValue );\n\n\t\t\t\t// Copy logic from prePersistPostType to ensure that the \"Auto\n\t\t\t\t// Draft\" template title is not synced.\n\t\t\t\tif (\n\t\t\t\t\tkey === 'title' &&\n\t\t\t\t\t! currentValue?.toString() &&\n\t\t\t\t\t'Auto Draft' === rawValue\n\t\t\t\t) {\n\t\t\t\t\trawValue = '';\n\t\t\t\t}\n\n\t\t\t\tif ( currentValue instanceof Y.Text ) {\n\t\t\t\t\tmergeRichTextUpdate( currentValue, rawValue ?? '' );\n\t\t\t\t} else {\n\t\t\t\t\tconst newYText = new Y.Text( rawValue ?? '' );\n\t\t\t\t\tymap.set( key, newYText );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// \"Meta\" is overloaded term; here, it refers to post meta.\n\t\t\tcase 'meta': {\n\t\t\t\tlet metaMap = ymap.get( 'meta' );\n\n\t\t\t\t// Initialize.\n\t\t\t\tif ( ! isYMap( metaMap ) ) {\n\t\t\t\t\tmetaMap = createYMap< YMapRecord >();\n\t\t\t\t\tymap.set( 'meta', metaMap );\n\t\t\t\t}\n\n\t\t\t\t// Iterate over each meta property in the new value and merge it if it\n\t\t\t\t// should be synced.\n\t\t\t\tObject.entries( newValue ?? {} ).forEach(\n\t\t\t\t\t( [ metaKey, metaValue ] ) => {\n\t\t\t\t\t\tif ( disallowedPostMetaKeys.has( metaKey ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdateMapValue(\n\t\t\t\t\t\t\tmetaMap,\n\t\t\t\t\t\t\tmetaKey,\n\t\t\t\t\t\t\tmetaMap.get( metaKey ), // current value in CRDT\n\t\t\t\t\t\t\tmetaValue // new value from changes\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'slug': {\n\t\t\t\t// Do not sync an empty slug. This indicates that the post is using\n\t\t\t\t// the default auto-generated slug.\n\t\t\t\tif ( ! newValue ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Add support for additional properties here.\n\n\t\t\tdefault: {\n\t\t\t\tconst currentValue = ymap.get( key );\n\t\t\t\tupdateMapValue( ymap, key, currentValue, newValue );\n\t\t\t}\n\t\t}\n\t} );\n\n\t// Process changes that we don't want to persist to the CRDT document.\n\tif ( changes.selection ) {\n\t\tconst selection = changes.selection;\n\t\t// Persist selection changes at the end of the current event loop.\n\t\t// This allows undo meta to be saved with the current selection before\n\t\t// it is overwritten by the new selection from Gutenberg.\n\t\t// Without this, selection history will already contain the latest\n\t\t// selection (after this change) when the undo stack is saved.\n\t\tsetTimeout( () => {\n\t\t\tupdateSelectionHistory( ydoc, selection );\n\t\t}, 0 );\n\t}\n}\n\nfunction defaultGetChangesFromCRDTDoc( crdtDoc: CRDTDoc ): ObjectData {\n\treturn getRootMap( crdtDoc, CRDT_RECORD_MAP_KEY ).toJSON();\n}\n\n/**\n * Given a local Y.Doc that *may* contain changes from remote peers, compare\n * against the local record and determine if there are changes (edits) we want\n * to dispatch.\n *\n * @param {CRDTDoc} ydoc\n * @param {Post} editedRecord\n * @param {Set<string>} syncedProperties\n * @return {Partial<PostChanges>} The changes that should be applied to the local record.\n */\nexport function getPostChangesFromCRDTDoc(\n\tydoc: CRDTDoc,\n\teditedRecord: Post,\n\tsyncedProperties: Set< string >\n): PostChanges {\n\tconst ymap = getRootMap< YPostRecord >( ydoc, CRDT_RECORD_MAP_KEY );\n\n\tlet allowedMetaChanges: Post[ 'meta' ] = {};\n\n\tconst changes = Object.fromEntries(\n\t\tObject.entries( ymap.toJSON() ).filter( ( [ key, newValue ] ) => {\n\t\t\tif ( ! syncedProperties.has( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst currentValue = editedRecord[ key ];\n\n\t\t\tswitch ( key ) {\n\t\t\t\tcase 'blocks': {\n\t\t\t\t\t// When we are passed a persisted CRDT document, make a special\n\t\t\t\t\t// comparison of the content and blocks.\n\t\t\t\t\t//\n\t\t\t\t\t// When other fields (besides `blocks`) are mutated outside the block\n\t\t\t\t\t// editor, the change is caught by an equality check (see other cases\n\t\t\t\t\t// in this `switch` statement). As a transient property, `blocks`\n\t\t\t\t\t// cannot be directly mutated outside the block editor -- only\n\t\t\t\t\t// `content` can.\n\t\t\t\t\t//\n\t\t\t\t\t// Therefore, for this special comparison, we serialize the `blocks`\n\t\t\t\t\t// from the persisted CRDT document and compare that to the content\n\t\t\t\t\t// from the persisted record. If they differ, we know that the content\n\t\t\t\t\t// in the database has changed, and therefore the blocks have changed.\n\t\t\t\t\t//\n\t\t\t\t\t// We cannot directly compare the `blocks` from the CRDT document to\n\t\t\t\t\t// the `blocks` derived from the `content` in the persisted record,\n\t\t\t\t\t// because the latter will have different client IDs.\n\t\t\t\t\tif (\n\t\t\t\t\t\tydoc.meta?.get( CRDT_DOC_META_PERSISTENCE_KEY ) &&\n\t\t\t\t\t\teditedRecord.content\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst blocksJson = ymap.get( 'blocks' )?.toJSON() ?? [];\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t__unstableSerializeAndClean( blocksJson ).trim() !==\n\t\t\t\t\t\t\tgetRawValue( editedRecord.content )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tcase 'date': {\n\t\t\t\t\t// Do not overwrite a \"floating\" date. Borrowing logic from the\n\t\t\t\t\t// isEditedPostDateFloating selector.\n\t\t\t\t\tconst currentDateIsFloating =\n\t\t\t\t\t\tnull === currentValue ||\n\t\t\t\t\t\teditedRecord.modified === currentValue;\n\n\t\t\t\t\tif ( currentDateIsFloating ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'meta': {\n\t\t\t\t\tallowedMetaChanges = Object.fromEntries(\n\t\t\t\t\t\tObject.entries( newValue ?? {} ).filter(\n\t\t\t\t\t\t\t( [ metaKey ] ) =>\n\t\t\t\t\t\t\t\t! disallowedPostMetaKeys.has( metaKey )\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\n\t\t\t\t\t// Merge the allowed meta changes with the current meta values since\n\t\t\t\t\t// not all meta properties are synced.\n\t\t\t\t\tconst mergedValue = {\n\t\t\t\t\t\t...( currentValue as PostChanges[ 'meta' ] ),\n\t\t\t\t\t\t...allowedMetaChanges,\n\t\t\t\t\t};\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, mergedValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'status': {\n\t\t\t\t\t// Do not sync an invalid status.\n\t\t\t\t\tif ( 'auto-draft' === newValue ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\n\t\t\t\tcase 'content':\n\t\t\t\tcase 'excerpt':\n\t\t\t\tcase 'title': {\n\t\t\t\t\treturn haveValuesChanged(\n\t\t\t\t\t\tgetRawValue( currentValue ),\n\t\t\t\t\t\tnewValue\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Add support for additional data types here.\n\n\t\t\t\tdefault: {\n\t\t\t\t\treturn haveValuesChanged( currentValue, newValue );\n\t\t\t\t}\n\t\t\t}\n\t\t} )\n\t);\n\n\t// Blocks extracted from the CRDT document have rich-text attributes as\n\t// plain strings (from Y.Text.toJSON()). Convert them back to RichTextData\n\t// so block edit components receive the same types as locally-created blocks.\n\tif ( changes.blocks ) {\n\t\tchanges.blocks = deserializeBlockAttributes(\n\t\t\tchanges.blocks as Block[]\n\t\t);\n\t}\n\n\t// Meta changes must be merged with the edited record since not all meta\n\t// properties are synced.\n\tif ( 'object' === typeof changes.meta ) {\n\t\tchanges.meta = {\n\t\t\t...editedRecord.meta,\n\t\t\t...allowedMetaChanges,\n\t\t};\n\t}\n\n\t// When remote content changes are detected, recalculate the local user's\n\t// selection using Y.RelativePosition to account for text shifts. The ydoc\n\t// has already been updated with remote content at this point, so converting\n\t// relative positions to absolute gives corrected offsets. Including the\n\t// selection in PostChanges ensures it dispatches atomically with content.\n\tconst selectionHistory = getSelectionHistory( ydoc );\n\tconst shiftedSelection = getShiftedSelection( ydoc, selectionHistory );\n\tif ( shiftedSelection ) {\n\t\tchanges.selection = {\n\t\t\t...shiftedSelection,\n\t\t\tinitialPosition: 0,\n\t\t};\n\t}\n\n\treturn changes;\n}\n\n/**\n * This default sync config can be used for entities that are flat maps of\n * primitive values and do not require custom logic to merge changes.\n */\nexport const defaultSyncConfig: SyncConfig = {\n\tapplyChangesToCRDTDoc: defaultApplyChangesToCRDTDoc,\n\tcreateAwareness: ( ydoc: CRDTDoc ) => new BaseAwareness( ydoc ),\n\tgetChangesFromCRDTDoc: defaultGetChangesFromCRDTDoc,\n};\n\n/**\n * This default collection sync config can be used to sync entity collections\n * (e.g., block comments) where we are not interested in merging changes at the\n * individual record level, but instead want to replace the entire collection\n * when changes are detected.\n */\nexport const defaultCollectionSyncConfig: SyncConfig = {\n\tapplyChangesToCRDTDoc: () => {},\n\tgetChangesFromCRDTDoc: () => ( {} ),\n\tshouldSync: ( _: ObjectType, objectId: ObjectID | null ) =>\n\t\tnull === objectId,\n};\n\n/**\n * Extract the raw string value from a property that may be a string or an object\n * with a `raw` property (`RenderedText`).\n *\n * @param {unknown} value The value to extract from.\n * @return {string|undefined} The raw string value, or undefined if it could not be determined.\n */\nfunction getRawValue( value?: unknown ): string | undefined {\n\t// Value may be a string property or a nested object with a `raw` property.\n\tif ( 'string' === typeof value ) {\n\t\treturn value;\n\t}\n\n\tif (\n\t\tvalue &&\n\t\t'object' === typeof value &&\n\t\t'raw' in value &&\n\t\t'string' === typeof value.raw\n\t) {\n\t\treturn value.raw;\n\t}\n\n\treturn undefined;\n}\n\nfunction haveValuesChanged< ValueType >(\n\tcurrentValue: ValueType | undefined,\n\tnewValue: ValueType | undefined\n): boolean {\n\treturn ! fastDeepEqual( currentValue, newValue );\n}\n\nfunction updateMapValue< T extends YMapRecord, K extends keyof T >(\n\tmap: YMapWrap< T >,\n\tkey: K,\n\tcurrentValue: T[ K ] | undefined,\n\tnewValue: T[ K ] | undefined\n): void {\n\tif ( undefined === newValue ) {\n\t\tmap.delete( key );\n\t\treturn;\n\t}\n\n\tif ( haveValuesChanged< T[ K ] >( currentValue, newValue ) ) {\n\t\tmap.set( key, newValue );\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,34 +3,32 @@ import { default as default2 } from "./conservative-map-item.mjs";
3
3
  import { default as default3 } from "./get-normalized-comma-separable.mjs";
4
4
  import { default as default4 } from "./if-matching-action.mjs";
5
5
  import { default as default5 } from "./forward-resolver.mjs";
6
- import { default as default6 } from "./on-sub-key.mjs";
7
- import { default as default7 } from "./replace-action.mjs";
8
- import { default as default8 } from "./with-weak-map-cache.mjs";
9
- import { default as default9 } from "./set-nested-value.mjs";
10
- import { default as default10 } from "./get-nested-value.mjs";
11
- import { default as default11 } from "./is-numeric-id.mjs";
6
+ import { default as default6 } from "./replace-action.mjs";
7
+ import { default as default7 } from "./with-weak-map-cache.mjs";
8
+ import { default as default8 } from "./set-nested-value.mjs";
9
+ import { default as default9 } from "./get-nested-value.mjs";
10
+ import { default as default10 } from "./is-numeric-id.mjs";
12
11
  import {
13
12
  getUserPermissionCacheKey,
14
13
  getUserPermissionsFromAllowHeader,
15
14
  ALLOWED_RESOURCE_ACTIONS
16
15
  } from "./user-permissions.mjs";
17
16
  import { RECEIVE_INTERMEDIATE_RESULTS } from "./receive-intermediate-results.mjs";
18
- import { default as default12 } from "./normalize-query-for-resolution.mjs";
17
+ import { default as default11 } from "./normalize-query-for-resolution.mjs";
19
18
  export {
20
19
  ALLOWED_RESOURCE_ACTIONS,
21
20
  RECEIVE_INTERMEDIATE_RESULTS,
22
21
  default2 as conservativeMapItem,
23
22
  default5 as forwardResolver,
24
- default10 as getNestedValue,
23
+ default9 as getNestedValue,
25
24
  default3 as getNormalizedCommaSeparable,
26
25
  getUserPermissionCacheKey,
27
26
  getUserPermissionsFromAllowHeader,
28
27
  default4 as ifMatchingAction,
29
- default11 as isNumericID,
30
- default12 as normalizeQueryForResolution,
31
- default6 as onSubKey,
32
- default7 as replaceAction,
33
- default9 as setNestedValue,
34
- default8 as withWeakMapCache
28
+ default10 as isNumericID,
29
+ default11 as normalizeQueryForResolution,
30
+ default6 as replaceAction,
31
+ default8 as setNestedValue,
32
+ default7 as withWeakMapCache
35
33
  };
36
34
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/index.js"],
4
- "sourcesContent": ["export { default as conservativeMapItem } from './conservative-map-item';\nexport { default as getNormalizedCommaSeparable } from './get-normalized-comma-separable';\nexport { default as ifMatchingAction } from './if-matching-action';\nexport { default as forwardResolver } from './forward-resolver';\nexport { default as onSubKey } from './on-sub-key';\nexport { default as replaceAction } from './replace-action';\nexport { default as withWeakMapCache } from './with-weak-map-cache';\nexport { default as setNestedValue } from './set-nested-value';\nexport { default as getNestedValue } from './get-nested-value';\nexport { default as isNumericID } from './is-numeric-id';\nexport {\n\tgetUserPermissionCacheKey,\n\tgetUserPermissionsFromAllowHeader,\n\tALLOWED_RESOURCE_ACTIONS,\n} from './user-permissions';\nexport { RECEIVE_INTERMEDIATE_RESULTS } from './receive-intermediate-results';\nexport { default as normalizeQueryForResolution } from './normalize-query-for-resolution';\n"],
5
- "mappings": ";AAAA,SAAoB,WAAXA,gBAAsC;AAC/C,SAAoB,WAAXA,gBAA8C;AACvD,SAAoB,WAAXA,gBAAmC;AAC5C,SAAoB,WAAXA,gBAAkC;AAC3C,SAAoB,WAAXA,gBAA2B;AACpC,SAAoB,WAAXA,gBAAgC;AACzC,SAAoB,WAAXA,gBAAmC;AAC5C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,iBAAiC;AAC1C,SAAoB,WAAXA,iBAA8B;AACvC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,oCAAoC;AAC7C,SAAoB,WAAXA,iBAA8C;",
4
+ "sourcesContent": ["export { default as conservativeMapItem } from './conservative-map-item';\nexport { default as getNormalizedCommaSeparable } from './get-normalized-comma-separable';\nexport { default as ifMatchingAction } from './if-matching-action';\nexport { default as forwardResolver } from './forward-resolver';\nexport { default as replaceAction } from './replace-action';\nexport { default as withWeakMapCache } from './with-weak-map-cache';\nexport { default as setNestedValue } from './set-nested-value';\nexport { default as getNestedValue } from './get-nested-value';\nexport { default as isNumericID } from './is-numeric-id';\nexport {\n\tgetUserPermissionCacheKey,\n\tgetUserPermissionsFromAllowHeader,\n\tALLOWED_RESOURCE_ACTIONS,\n} from './user-permissions';\nexport { RECEIVE_INTERMEDIATE_RESULTS } from './receive-intermediate-results';\nexport { default as normalizeQueryForResolution } from './normalize-query-for-resolution';\n"],
5
+ "mappings": ";AAAA,SAAoB,WAAXA,gBAAsC;AAC/C,SAAoB,WAAXA,gBAA8C;AACvD,SAAoB,WAAXA,gBAAmC;AAC5C,SAAoB,WAAXA,gBAAkC;AAC3C,SAAoB,WAAXA,gBAAgC;AACzC,SAAoB,WAAXA,gBAAmC;AAC5C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,iBAA8B;AACvC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,oCAAoC;AAC7C,SAAoB,WAAXA,iBAA8C;",
6
6
  "names": ["default"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/queried-data/reducer.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;GAYG;AACH,0CATW,MAAM,EAAE,GAAC,SAAS,eAClB,MAAM,EAAE,8BAEhB;IAAqC,IAAI;IACJ,MAAM;IACP,OAAO,EAAnC,MAAM;CAEd,GAAS,MAAM,EAAE,CAuCnB;AAyBD;;;;;;;;GAQG;AACH,oDAiCC;AAED;;;;;;;;;;;GAWG;AACH;;;;;;;;EA8CC"}
1
+ {"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/queried-data/reducer.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;GAYG;AACH,0CATW,MAAM,EAAE,GAAC,SAAS,eAClB,MAAM,EAAE,8BAEhB;IAAqC,IAAI;IACJ,MAAM;IACP,OAAO,EAAnC,MAAM;CAEd,GAAS,MAAM,EAAE,CAyCnB;AAyBD;;;;;;;;GAQG;AACH,oDAiCC;AAED;;;;;;;;;;;GAWG;AACH;;;;;;;;EA8CC"}
@@ -1 +1 @@
1
- {"version":3,"file":"crdt-blocks.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-blocks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAEpC;;GAEG;AACH,OAAO,EAAc,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI1E,UAAU,eAAe;IACxB,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO,CAAC;CACzB;AAcD,MAAM,WAAW,KAAK;IACrB,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAGD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC/C,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAE,YAAY,CAAE,CAAC;AAC9C,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAE,MAAM,CAAE,CAAC;AAIxC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAE,CAAC,CAAC,IAAI,GAAG,OAAO,CAAE,CAAC;AA2GzD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAE,MAAM,EAAE,KAAK,EAAE,GAAI,KAAK,EAAE,CAwBrE;AAiLD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,KAAK,EAAE,EACvB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC3B,IAAI,CA6LN;AAsQD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,CAAC,CAAC,IAAI,EAClB,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,GAAG,IAAW,GAClC,IAAI,CA4BN"}
1
+ {"version":3,"file":"crdt-blocks.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-blocks.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAEpC;;GAEG;AACH,OAAO,EAAc,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI1E,UAAU,eAAe;IACxB,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO,CAAC;CACzB;AAcD,MAAM,WAAW,KAAK;IACrB,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAGD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC/C,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAE,YAAY,CAAE,CAAC;AAC9C,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAE,MAAM,CAAE,CAAC;AAIxC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAE,CAAC,CAAC,IAAI,GAAG,OAAO,CAAE,CAAC;AA2GzD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAE,MAAM,EAAE,KAAK,EAAE,GAAI,KAAK,EAAE,CAwBrE;AAiLD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,KAAK,EAAE,EACvB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC3B,IAAI,CA8LN;AAyUD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,CAAC,CAAC,IAAI,EAClB,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,GAAG,IAAW,GAClC,IAAI,CA4BN"}
@@ -1 +1 @@
1
- {"version":3,"file":"crdt-selection.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-selection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,OAAO,EAIN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,UAAU,CAAC;AAsB9D,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,OAAO,GAAI,cAAc,EAAE,CAErE;AAED,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACtB,IAAI,CAEN;AAoGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC/B,gBAAgB,EAAE,cAAc,EAAE,EAClC,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,IAAI,CA+DN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,CAAC,CAAC,GAAG,EACX,gBAAgB,EAAE,cAAc,EAAE,GAChC,WAAW,GAAG,IAAI,CA+BpB"}
1
+ {"version":3,"file":"crdt-selection.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-selection.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,OAAO,EAIN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,UAAU,CAAC;AAsB9D,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,OAAO,GAAI,cAAc,EAAE,CAErE;AAED,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACtB,IAAI,CAEN;AAoGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC/B,gBAAgB,EAAE,cAAc,EAAE,EAClC,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,IAAI,CA+DN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,CAAC,CAAC,GAAG,EACX,gBAAgB,EAAE,cAAc,EAAE,GAChC,WAAW,GAAG,IAAI,CA+BpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"AAUA,OAAO,EACN,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,CAAC,EACD,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAIN,KAAK,KAAK,EAEV,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,EAIN,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,MAAM,cAAc,CAAC;AAGtB,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,CAAC;IACrC,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,CAoIN;AAMD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,YAAY,EAAE,IAAI,EAClB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,WAAW,CA2Ib;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAI/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAKzC,CAAC"}
1
+ {"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"AASA,OAAO,EACN,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,CAAC,EACD,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAIN,KAAK,KAAK,EAEV,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,EAIN,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,MAAM,cAAc,CAAC;AAGtB,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,CAAC;IACrC,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,CAoIN;AAMD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,YAAY,EAAE,IAAI,EAClB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,WAAW,CA2Ib;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAI/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAKzC,CAAC"}
@@ -2,7 +2,6 @@ export { default as conservativeMapItem } from "./conservative-map-item";
2
2
  export { default as getNormalizedCommaSeparable } from "./get-normalized-comma-separable";
3
3
  export { default as ifMatchingAction } from "./if-matching-action";
4
4
  export { default as forwardResolver } from "./forward-resolver";
5
- export { default as onSubKey } from "./on-sub-key";
6
5
  export { default as replaceAction } from "./replace-action";
7
6
  export { default as withWeakMapCache } from "./with-weak-map-cache";
8
7
  export { default as setNestedValue } from "./set-nested-value";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/core-data",
3
- "version": "7.43.2-next.v.202604091042.0+668146787",
3
+ "version": "7.44.1-next.v.202604201441.0+dab6d8c07",
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.43.1-next.v.202604091042.0+668146787",
53
- "@wordpress/block-editor": "^15.16.1-next.v.202604091042.0+668146787",
54
- "@wordpress/blocks": "^15.16.1-next.v.202604091042.0+668146787",
55
- "@wordpress/compose": "^7.43.1-next.v.202604091042.0+668146787",
56
- "@wordpress/data": "^10.43.1-next.v.202604091042.0+668146787",
57
- "@wordpress/deprecated": "^4.43.1-next.v.202604091042.0+668146787",
58
- "@wordpress/element": "^6.44.1-next.v.202604091042.0+668146787",
59
- "@wordpress/html-entities": "^4.43.1-next.v.202604091042.0+668146787",
60
- "@wordpress/i18n": "^6.17.1-next.v.202604091042.0+668146787",
61
- "@wordpress/is-shallow-equal": "^5.43.1-next.v.202604091042.0+668146787",
62
- "@wordpress/private-apis": "^1.43.1-next.v.202604091042.0+668146787",
63
- "@wordpress/rich-text": "^7.43.1-next.v.202604091042.0+668146787",
64
- "@wordpress/sync": "^1.43.1-next.v.202604091042.0+668146787",
65
- "@wordpress/undo-manager": "^1.43.1-next.v.202604091042.0+668146787",
66
- "@wordpress/url": "^4.43.1-next.v.202604091042.0+668146787",
67
- "@wordpress/warning": "^3.43.1-next.v.202604091042.0+668146787",
52
+ "@wordpress/api-fetch": "^7.44.1-next.v.202604201441.0+dab6d8c07",
53
+ "@wordpress/block-editor": "^15.18.1-next.v.202604201441.0+dab6d8c07",
54
+ "@wordpress/blocks": "^15.17.2-next.v.202604201441.0+dab6d8c07",
55
+ "@wordpress/compose": "^7.44.1-next.v.202604201441.0+dab6d8c07",
56
+ "@wordpress/data": "^10.45.1-next.v.202604201441.0+dab6d8c07",
57
+ "@wordpress/deprecated": "^4.44.1-next.v.202604201441.0+dab6d8c07",
58
+ "@wordpress/element": "^6.44.1-next.v.202604201441.0+dab6d8c07",
59
+ "@wordpress/html-entities": "^4.44.1-next.v.202604201441.0+dab6d8c07",
60
+ "@wordpress/i18n": "^6.17.1-next.v.202604201441.0+dab6d8c07",
61
+ "@wordpress/is-shallow-equal": "^5.44.1-next.v.202604201441.0+dab6d8c07",
62
+ "@wordpress/private-apis": "^1.44.1-next.v.202604201441.0+dab6d8c07",
63
+ "@wordpress/rich-text": "^7.44.1-next.v.202604201441.0+dab6d8c07",
64
+ "@wordpress/sync": "^1.44.1-next.v.202604201441.0+dab6d8c07",
65
+ "@wordpress/undo-manager": "^1.44.1-next.v.202604201441.0+dab6d8c07",
66
+ "@wordpress/url": "^4.44.1-next.v.202604201441.0+dab6d8c07",
67
+ "@wordpress/warning": "^3.44.1-next.v.202604201441.0+dab6d8c07",
68
68
  "change-case": "^4.1.2",
69
69
  "equivalent-key-map": "^0.2.2",
70
70
  "fast-deep-equal": "^3.1.3",
@@ -84,5 +84,5 @@
84
84
  "publishConfig": {
85
85
  "access": "public"
86
86
  },
87
- "gitHead": "73606df74f1c38a084bfa5db97205259ef817593"
87
+ "gitHead": "c788005ba4ee2a34851c1217c51602656aa7c3a6"
88
88
  }
@@ -64,7 +64,7 @@ export default function useEntityProp( kind, name, prop, _id ) {
64
64
  );
65
65
  return revision
66
66
  ? {
67
- value: revision[ prop ],
67
+ value: revision[ prop ]?.raw ?? revision[ prop ],
68
68
  fullValue: revision[ prop ],
69
69
  }
70
70
  : {};
@@ -1,18 +1,13 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { combineReducers } from '@wordpress/data';
4
+ import { combineReducers, keyedReducer } from '@wordpress/data';
5
5
  import { compose } from '@wordpress/compose';
6
6
 
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
- import {
11
- conservativeMapItem,
12
- ifMatchingAction,
13
- replaceAction,
14
- onSubKey,
15
- } from '../utils';
10
+ import { conservativeMapItem, ifMatchingAction, replaceAction } from '../utils';
16
11
  import { DEFAULT_ENTITY_KEY } from '../entities';
17
12
  import getQueryParts from './get-query-parts';
18
13
 
@@ -51,6 +46,7 @@ export function getMergedItemIds(
51
46
  }
52
47
 
53
48
  const nextItemIdsStartIndex = offset ?? ( page - 1 ) * perPage;
49
+ const nextItemIdsRange = Math.max( perPage, nextItemIds.length );
54
50
 
55
51
  // If later page has already been received, default to the larger known
56
52
  // size of the existing array, else calculate as extending the existing.
@@ -67,7 +63,8 @@ export function getMergedItemIds(
67
63
  // We need to check against the possible maximum upper boundary because
68
64
  // a page could receive fewer than what was previously stored.
69
65
  const isInNextItemsRange =
70
- i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage;
66
+ i >= nextItemIdsStartIndex &&
67
+ i < nextItemIdsStartIndex + nextItemIdsRange;
71
68
  if ( isInNextItemsRange ) {
72
69
  mergedItemIds[ i ] = nextItemIds[ i - nextItemIdsStartIndex ];
73
70
  } else {
@@ -219,11 +216,11 @@ const receiveQueries = compose( [
219
216
  // an unhandled action.
220
217
  ifMatchingAction( ( action ) => 'query' in action ),
221
218
 
222
- // Inject query parts into action for use both in `onSubKey` and reducer.
219
+ // Inject query parts into action for use both in `keyedReducer` and reducer.
223
220
  replaceAction( ( action ) => {
224
221
  // `ifMatchingAction` still passes on initialization, where state is
225
222
  // undefined and a query is not assigned. Avoid attempting to parse
226
- // parts. `onSubKey` will omit by lack of `stableKey`.
223
+ // parts. `keyedReducer` will omit by lack of `stableKey`.
227
224
  if ( action.query ) {
228
225
  return {
229
226
  ...action,
@@ -234,11 +231,11 @@ const receiveQueries = compose( [
234
231
  return action;
235
232
  } ),
236
233
 
237
- onSubKey( 'context' ),
234
+ keyedReducer( 'context' ),
238
235
 
239
236
  // Queries shape is shared, but keyed by query `stableKey` part. Original
240
237
  // reducer tracks only a single query object.
241
- onSubKey( 'stableKey' ),
238
+ keyedReducer( 'stableKey' ),
242
239
  ] )( ( state = {}, action ) => {
243
240
  if ( action.type !== 'RECEIVE_ITEMS' ) {
244
241
  return state;
@@ -100,6 +100,13 @@ describe( 'getMergedItemIds', () => {
100
100
 
101
101
  expect( result ).toEqual( [ 1, 2, 9, undefined, 5, 6 ] );
102
102
  } );
103
+
104
+ it( 'should keep all received IDs when response exceeds default perPage', () => {
105
+ const nextItemIds = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
106
+ const result = getMergedItemIds( [], nextItemIds );
107
+
108
+ expect( result ).toEqual( nextItemIds );
109
+ } );
103
110
  } );
104
111
 
105
112
  describe( 'itemIsComplete', () => {
@@ -7,7 +7,6 @@ import fastDeepEqual from 'fast-deep-equal/es6/index.js';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- // @ts-expect-error No exported types.
11
10
  import { getBlockTypes } from '@wordpress/blocks';
12
11
  import { RichTextData } from '@wordpress/rich-text';
13
12
  import { Y } from '@wordpress/sync';
@@ -458,6 +457,7 @@ export function mergeCrdtBlocks(
458
457
  for ( let i = 0; i < numOfUpdatesNeeded; i++, left++ ) {
459
458
  const block = blocksToSync[ left ];
460
459
  const yblock = yblocks.get( left );
460
+
461
461
  Object.entries( block ).forEach( ( [ key, value ] ) => {
462
462
  switch ( key ) {
463
463
  case 'attributes': {
@@ -581,13 +581,33 @@ export function mergeCrdtBlocks(
581
581
  }
582
582
  }
583
583
 
584
+ /**
585
+ * Compare a plain array element against a Y.Map element for equality.
586
+ * Used by the left-right sweep diff in mergeYArray.
587
+ *
588
+ * @param newElement The plain object from the incoming array.
589
+ * @param yElement The Y.Map element from the existing Y.Array.
590
+ * @return True if the elements are deeply equal.
591
+ */
592
+ function areArrayElementsEqual(
593
+ newElement: unknown,
594
+ yElement: unknown
595
+ ): boolean {
596
+ if ( yElement instanceof Y.Map && isRecord( newElement ) ) {
597
+ return fastDeepEqual( newElement, yElement.toJSON() );
598
+ }
599
+
600
+ return fastDeepEqual( newElement, yElement );
601
+ }
602
+
584
603
  /**
585
604
  * Merge an incoming plain array into an existing Y.Array in-place.
586
605
  *
587
- * When the array length is unchanged (stable structure), each element is
588
- * merged individually via `mergeYMapValues`, preserving concurrent edits to
589
- * different elements. When the length changes (structural edit such as row
590
- * insertion/deletion), the Y.Array is rebuilt from scratch.
606
+ * Uses the same left-right sweep diff approach as mergeCrdtBlocks:
607
+ * equal elements are skipped from both ends, then the middle section
608
+ * is updated, deleted, or inserted as needed. This preserves existing
609
+ * Y.Map/Y.Text objects for unchanged elements, so concurrent edits
610
+ * to those elements are not lost.
591
611
  *
592
612
  * @param yArray The existing Y.Array to update.
593
613
  * @param newValue The new plain array to merge into the Y.Array.
@@ -605,40 +625,87 @@ function mergeYArray(
605
625
  }
606
626
 
607
627
  const query = schema.query;
628
+ const numOfCommonEntries = Math.min( newValue.length, yArray.length );
608
629
 
609
- if ( yArray.length === newValue.length ) {
610
- // Same length: update each element in-place.
611
- for ( let i = 0; i < newValue.length; i++ ) {
612
- const currentElement = yArray.get( i );
613
- const newElement = newValue[ i ];
614
-
615
- if ( currentElement instanceof Y.Map && isRecord( newElement ) ) {
616
- mergeYMapValues(
617
- currentElement,
618
- newElement,
619
- query,
620
- cursorPosition
621
- );
622
- } else {
623
- // Element is the wrong type (e.g. partial migration) or the
624
- // incoming value is not an object. Rebuild the entire array.
625
- yArray.delete( 0, yArray.length );
626
- yArray.insert(
627
- 0,
628
- newValue.map( ( item ) =>
629
- createYMapFromQuery( query, item )
630
- )
631
- );
632
- return;
633
- }
630
+ let left = 0;
631
+ let right = 0;
632
+
633
+ // Skip equal elements from left.
634
+ for (
635
+ ;
636
+ left < numOfCommonEntries &&
637
+ areArrayElementsEqual( newValue[ left ], yArray.get( left ) );
638
+ left++
639
+ ) {
640
+ /* nop */
641
+ }
642
+
643
+ // Skip equal elements from right.
644
+ for (
645
+ ;
646
+ right < numOfCommonEntries - left &&
647
+ areArrayElementsEqual(
648
+ newValue[ newValue.length - right - 1 ],
649
+ yArray.get( yArray.length - right - 1 )
650
+ );
651
+ right++
652
+ ) {
653
+ /* nop */
654
+ }
655
+
656
+ // Updates: merge changed elements in-place.
657
+ const numOfUpdatesNeeded = numOfCommonEntries - left - right;
658
+
659
+ for ( let i = 0; i < numOfUpdatesNeeded; i++ ) {
660
+ const currentElement = yArray.get( left + i );
661
+ const newElement = newValue[ left + i ];
662
+
663
+ if ( currentElement instanceof Y.Map && isRecord( newElement ) ) {
664
+ mergeYMapValues(
665
+ currentElement,
666
+ newElement,
667
+ query,
668
+ cursorPosition
669
+ );
670
+ } else {
671
+ // Element is the wrong type (e.g. partial migration) or the
672
+ // incoming value is not an object. Rebuild the entire array.
673
+ yArray.delete( 0, yArray.length );
674
+ yArray.insert(
675
+ 0,
676
+ newValue.map( ( item ) => createYMapFromQuery( query, item ) )
677
+ );
678
+ return;
634
679
  }
635
- } else {
636
- // Structure changed: rebuild the Y.Array.
637
- yArray.delete( 0, yArray.length );
638
- yArray.insert(
639
- 0,
640
- newValue.map( ( item ) => createYMapFromQuery( query, item ) )
680
+ }
681
+
682
+ // Deletes.
683
+ const numOfDeletionsNeeded = Math.max( 0, yArray.length - newValue.length );
684
+
685
+ if ( numOfDeletionsNeeded > 0 ) {
686
+ yArray.delete( left + numOfUpdatesNeeded, numOfDeletionsNeeded );
687
+ }
688
+
689
+ // Inserts.
690
+ const numOfInsertionsNeeded = Math.max(
691
+ 0,
692
+ newValue.length - yArray.length
693
+ );
694
+
695
+ if ( numOfInsertionsNeeded > 0 ) {
696
+ const insertAt = left + numOfUpdatesNeeded;
697
+ const itemsToInsert: Y.Map< unknown >[] = new Array(
698
+ numOfInsertionsNeeded
641
699
  );
700
+
701
+ for ( let i = 0; i < numOfInsertionsNeeded; i++ ) {
702
+ itemsToInsert[ i ] = createYMapFromQuery(
703
+ query,
704
+ newValue[ insertAt + i ]
705
+ );
706
+ }
707
+
708
+ yArray.insert( insertAt, itemsToInsert );
642
709
  }
643
710
  }
644
711
 
@@ -4,7 +4,6 @@
4
4
  import { dispatch, select } from '@wordpress/data';
5
5
  // @ts-expect-error No exported types.
6
6
  import { store as blockEditorStore } from '@wordpress/block-editor';
7
- // @ts-expect-error No exported types.
8
7
  import { isUnmodifiedBlock } from '@wordpress/blocks';
9
8
  import { type CRDTDoc, Y } from '@wordpress/sync';
10
9
 
package/src/utils/crdt.ts CHANGED
@@ -6,7 +6,6 @@ import fastDeepEqual from 'fast-deep-equal/es6/index.js';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- // @ts-expect-error No exported types.
10
9
  import { __unstableSerializeAndClean } from '@wordpress/blocks';
11
10
  import {
12
11
  type CRDTDoc,
@@ -2,7 +2,6 @@ export { default as conservativeMapItem } from './conservative-map-item';
2
2
  export { default as getNormalizedCommaSeparable } from './get-normalized-comma-separable';
3
3
  export { default as ifMatchingAction } from './if-matching-action';
4
4
  export { default as forwardResolver } from './forward-resolver';
5
- export { default as onSubKey } from './on-sub-key';
6
5
  export { default as replaceAction } from './replace-action';
7
6
  export { default as withWeakMapCache } from './with-weak-map-cache';
8
7
  export { default as setNestedValue } from './set-nested-value';