@wordpress/core-data
Version:
Access to and manipulation of core WordPress entities.
8 lines (7 loc) • 6.59 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/awareness/block-lookup.ts"],
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { select } from '@wordpress/data';\nimport { Y } from '@wordpress/sync';\n// @ts-ignore No exported types for block editor store selectors.\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport type { AbsoluteBlockIndexPath } from '../types';\n\n/**\n * A block as represented in the block-editor store (from `getBlocks()`).\n *\n * This is a minimal interface covering only the fields used by RTC awareness.\n */\ninterface EditorStoreBlock {\n\tclientId: string;\n\tname: string;\n\tinnerBlocks: EditorStoreBlock[];\n}\n\n/**\n * Given a Y.Map within a Ydoc, traverse up the Yjs block tree to compute the\n * index path from the root.\n *\n * For example, the second inner block of the first root block returns [0, 1].\n *\n * @param yType - The Yjs block Y.Map to start from.\n * @return The index path from root, or null if traversal fails.\n */\nexport function getBlockPathInYdoc(\n\tyType: Y.Map< unknown >\n): AbsoluteBlockIndexPath | null {\n\tconst path: AbsoluteBlockIndexPath = [];\n\tlet current: Y.Map< unknown > = yType;\n\n\twhile ( current ) {\n\t\tconst parentArray = current.parent;\n\n\t\tif ( ! parentArray || ! ( parentArray instanceof Y.Array ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Find index of current block in its parent array.\n\t\tlet index = -1;\n\t\tfor ( let i = 0; i < parentArray.length; i++ ) {\n\t\t\tif ( parentArray.get( i ) === current ) {\n\t\t\t\tindex = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( index === -1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tpath.unshift( index );\n\n\t\t// Walk up: is the parent array's parent a block Y.Map or the root?\n\t\tconst grandparent = parentArray.parent;\n\t\tif (\n\t\t\tgrandparent instanceof Y.Map &&\n\t\t\tgrandparent.get( 'clientId' ) !== undefined\n\t\t) {\n\t\t\tcurrent = grandparent; // It's a block, keep going.\n\t\t} else {\n\t\t\tbreak; // It's the root map, done.\n\t\t}\n\t}\n\n\treturn path;\n}\n\n/**\n * Navigate the block-editor store's block tree by an index path\n * and return the local block's clientId.\n *\n * In template mode, getBlocks() returns the full template tree, but Yjs\n * paths are relative to the post content. This method finds the\n * core/post-content block (if present) and uses its inner blocks as the\n * navigation root, so paths align with the Yjs document structure.\n *\n * @param path - The index path, e.g. [0, 1] for blocks[0].innerBlocks[1].\n * @return The local block clientId, or null if the path is invalid.\n */\nexport function resolveBlockClientIdByPath(\n\tpath: AbsoluteBlockIndexPath\n): string | null {\n\tif ( path.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tconst { getBlocks } = select( blockEditorStore );\n\tconst postContentBlocks = getPostContentBlocks( getBlocks(), getBlocks );\n\n\tlet blocks = postContentBlocks;\n\n\tfor ( let i = 0; i < path.length; i++ ) {\n\t\tconst block = blocks[ path[ i ] ];\n\t\tif ( ! block ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( i === path.length - 1 ) {\n\t\t\treturn block.clientId;\n\t\t}\n\t\tblocks = block.innerBlocks;\n\t}\n\treturn null;\n}\n\n/**\n * Find the post content blocks to use as the navigation root.\n *\n * In template mode, the block tree contains template parts wrapping a\n * core/post-content block. The Yjs document only stores the post content\n * blocks, so we need to find the core/post-content block and use\n * getBlocks(clientId) to retrieve its inner blocks from the store.\n *\n * We must use getBlocks(clientId) rather than reading .innerBlocks from\n * the block object because useBlockSync() injects post content as\n * controlled inner blocks \u2014 they exist in the store's block order map\n * but are not populated in the .innerBlocks property of the tree\n * returned by getBlocks().\n *\n * @param rootBlocks - The root-level blocks from getBlocks().\n * @param getBlocks - The getBlocks selector.\n * @return The blocks that correspond to the Yjs document root.\n */\nfunction getPostContentBlocks(\n\trootBlocks: EditorStoreBlock[],\n\tgetBlocks: ( rootClientId?: string ) => EditorStoreBlock[]\n): EditorStoreBlock[] {\n\tconst postContentBlock = findBlockByName( rootBlocks, 'core/post-content' );\n\tif ( postContentBlock ) {\n\t\t// Use getBlocks(clientId) to read controlled inner blocks from\n\t\t// the store, since postContentBlock.innerBlocks is empty.\n\t\treturn getBlocks( postContentBlock.clientId );\n\t}\n\n\treturn rootBlocks;\n}\n\n/**\n * Recursively search the block tree for a block with a given name.\n *\n * @param blocks - The blocks to search.\n * @param name - The block name to find.\n * @return The first matching block, or null if not found.\n */\nfunction findBlockByName(\n\tblocks: EditorStoreBlock[],\n\tname: string\n): EditorStoreBlock | null {\n\tfor ( const block of blocks ) {\n\t\tif ( block.name === name ) {\n\t\t\treturn block;\n\t\t}\n\t\tif ( block.innerBlocks?.length ) {\n\t\t\tconst found = findBlockByName( block.innerBlocks, name );\n\t\t\tif ( found ) {\n\t\t\t\treturn found;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n"],
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAuB;AACvB,kBAAkB;AAElB,0BAA0C;AA2BnC,SAAS,mBACf,OACgC;AAChC,QAAM,OAA+B,CAAC;AACtC,MAAI,UAA4B;AAEhC,SAAQ,SAAU;AACjB,UAAM,cAAc,QAAQ;AAE5B,QAAK,CAAE,eAAe,EAAI,uBAAuB,cAAE,QAAU;AAC5D,aAAO;AAAA,IACR;AAGA,QAAI,QAAQ;AACZ,aAAU,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAM;AAC9C,UAAK,YAAY,IAAK,CAAE,MAAM,SAAU;AACvC,gBAAQ;AACR;AAAA,MACD;AAAA,IACD;AAEA,QAAK,UAAU,IAAK;AACnB,aAAO;AAAA,IACR;AAEA,SAAK,QAAS,KAAM;AAGpB,UAAM,cAAc,YAAY;AAChC,QACC,uBAAuB,cAAE,OACzB,YAAY,IAAK,UAAW,MAAM,QACjC;AACD,gBAAU;AAAA,IACX,OAAO;AACN;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAcO,SAAS,2BACf,MACgB;AAChB,MAAK,KAAK,WAAW,GAAI;AACxB,WAAO;AAAA,EACR;AAEA,QAAM,EAAE,UAAU,QAAI,oBAAQ,oBAAAA,KAAiB;AAC/C,QAAM,oBAAoB,qBAAsB,UAAU,GAAG,SAAU;AAEvE,MAAI,SAAS;AAEb,WAAU,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAM;AACvC,UAAM,QAAQ,OAAQ,KAAM,CAAE,CAAE;AAChC,QAAK,CAAE,OAAQ;AACd,aAAO;AAAA,IACR;AACA,QAAK,MAAM,KAAK,SAAS,GAAI;AAC5B,aAAO,MAAM;AAAA,IACd;AACA,aAAS,MAAM;AAAA,EAChB;AACA,SAAO;AACR;AAoBA,SAAS,qBACR,YACA,WACqB;AACrB,QAAM,mBAAmB,gBAAiB,YAAY,mBAAoB;AAC1E,MAAK,kBAAmB;AAGvB,WAAO,UAAW,iBAAiB,QAAS;AAAA,EAC7C;AAEA,SAAO;AACR;AASA,SAAS,gBACR,QACA,MAC0B;AAC1B,aAAY,SAAS,QAAS;AAC7B,QAAK,MAAM,SAAS,MAAO;AAC1B,aAAO;AAAA,IACR;AACA,QAAK,MAAM,aAAa,QAAS;AAChC,YAAM,QAAQ,gBAAiB,MAAM,aAAa,IAAK;AACvD,UAAK,OAAQ;AACZ,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;",
"names": ["blockEditorStore"]
}