UNPKG

@wordpress/block-library

Version:
8 lines (7 loc) 10.4 kB
{ "version": 3, "sources": ["../../src/navigation/menu-items-to-blocks.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { createBlock, parse } from '@wordpress/blocks';\nimport { applyFilters } from '@wordpress/hooks';\n\n/**\n * Internal dependencies\n */\nimport { buildNavigationLinkEntityBinding } from '../navigation-link/shared/use-entity-binding';\n\n/**\n * Convert a flat menu item structure to a nested blocks structure.\n *\n * @param {Object[]} menuItems An array of menu items.\n *\n * @return {WPBlock[]} An array of blocks.\n */\nexport default function menuItemsToBlocks( menuItems ) {\n\tif ( ! menuItems ) {\n\t\treturn null;\n\t}\n\n\tconst menuTree = createDataTree( menuItems );\n\tconst blocks = mapMenuItemsToBlocks( menuTree );\n\treturn applyFilters(\n\t\t'blocks.navigation.__unstableMenuItemsToBlocks',\n\t\tblocks,\n\t\tmenuItems\n\t);\n}\n\n/**\n * A recursive function that maps menu item nodes to blocks.\n *\n * @param {WPNavMenuItem[]} menuItems An array of WPNavMenuItem items.\n * @param {number} level An integer representing the nesting level.\n * @return {Object} Object containing innerBlocks and mapping.\n */\nfunction mapMenuItemsToBlocks( menuItems, level = 0 ) {\n\tlet mapping = {};\n\n\t// The menuItem should be in menu_order sort order.\n\tconst sortedItems = [ ...menuItems ].sort(\n\t\t( a, b ) => a.menu_order - b.menu_order\n\t);\n\n\tconst innerBlocks = sortedItems.map( ( menuItem ) => {\n\t\tif ( menuItem.type === 'block' ) {\n\t\t\tconst [ block ] = parse( menuItem.content.raw );\n\n\t\t\tif ( ! block ) {\n\t\t\t\treturn createBlock( 'core/freeform', {\n\t\t\t\t\tcontent: menuItem.content,\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn block;\n\t\t}\n\n\t\tconst blockType = menuItem.children?.length\n\t\t\t? 'core/navigation-submenu'\n\t\t\t: 'core/navigation-link';\n\n\t\tconst attributes = menuItemToBlockAttributes(\n\t\t\tmenuItem,\n\t\t\tblockType,\n\t\t\tlevel\n\t\t);\n\n\t\t// If there are children recurse to build those nested blocks.\n\t\tconst {\n\t\t\tinnerBlocks: nestedBlocks = [], // alias to avoid shadowing\n\t\t\tmapping: nestedMapping = {}, // alias to avoid shadowing\n\t\t} = menuItem.children?.length\n\t\t\t? mapMenuItemsToBlocks( menuItem.children, level + 1 )\n\t\t\t: {};\n\n\t\t// Update parent mapping with nested mapping.\n\t\tmapping = {\n\t\t\t...mapping,\n\t\t\t...nestedMapping,\n\t\t};\n\n\t\t// Create block with nested \"innerBlocks\".\n\t\tconst block = createBlock( blockType, attributes, nestedBlocks );\n\n\t\t// Create mapping for menuItem -> block.\n\t\tmapping[ menuItem.id ] = block.clientId;\n\n\t\treturn block;\n\t} );\n\n\treturn {\n\t\tinnerBlocks,\n\t\tmapping,\n\t};\n}\n\n/**\n * A WP nav_menu_item object.\n * For more documentation on the individual fields present on a menu item please see:\n * https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/nav-menu.php#L789\n *\n * @typedef WPNavMenuItem\n *\n * @property {Object} title stores the raw and rendered versions of the title/label for this menu item.\n * @property {Array} xfn the XFN relationships expressed in the link of this menu item.\n * @property {Array} classes the HTML class attributes for this menu item.\n * @property {string} attr_title the HTML title attribute for this menu item.\n * @property {string} object The type of object originally represented, such as 'category', 'post', or 'attachment'.\n * @property {string} object_id The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.\n * @property {string} description The description of this menu item.\n * @property {string} url The URL to which this menu item points.\n * @property {string} type The family of objects originally represented, such as 'post_type' or 'taxonomy'.\n * @property {string} target The target attribute of the link element for this menu item.\n */\n\n/**\n * Convert block attributes to menu item.\n *\n * @param {WPNavMenuItem} menuItem the menu item to be converted to block attributes.\n * @param {string} blockType The block type.\n * @param {number} level An integer representing the nesting level.\n * @return {Object} the block attributes converted from the WPNavMenuItem item.\n */\nfunction menuItemToBlockAttributes(\n\t{\n\t\ttitle: menuItemTitleField,\n\t\txfn,\n\t\tclasses,\n\t\t// eslint-disable-next-line camelcase\n\t\tattr_title,\n\t\tobject,\n\t\t// eslint-disable-next-line camelcase\n\t\tobject_id,\n\t\tdescription,\n\t\turl,\n\t\ttype: menuItemTypeField,\n\t\ttarget,\n\t},\n\tblockType,\n\tlevel\n) {\n\t// For historical reasons, the `core/navigation-link` variation type is `tag`\n\t// whereas WP Core expects `post_tag` as the `object` type.\n\t// To avoid writing a block migration we perform a conversion here.\n\t// See also inverse equivalent in `blockAttributesToMenuItem`.\n\tif ( object && object === 'post_tag' ) {\n\t\tobject = 'tag';\n\t}\n\n\tconst inferredKind = menuItemTypeField?.replace( '_', '-' ) || 'custom';\n\n\treturn {\n\t\tlabel: menuItemTitleField?.rendered || '',\n\t\t...( object?.length && {\n\t\t\ttype: object,\n\t\t} ),\n\t\tkind: inferredKind,\n\t\turl: url || '',\n\t\t...( xfn?.length &&\n\t\t\txfn.join( ' ' ).trim() && {\n\t\t\t\trel: xfn.join( ' ' ).trim(),\n\t\t\t} ),\n\t\t...( classes?.length &&\n\t\t\tclasses.join( ' ' ).trim() && {\n\t\t\t\tclassName: classes.join( ' ' ).trim(),\n\t\t\t} ),\n\t\t/* eslint-disable camelcase */\n\t\t...( attr_title?.length && {\n\t\t\ttitle: attr_title,\n\t\t} ),\n\t\t...( object_id &&\n\t\t\t( inferredKind === 'post-type' || inferredKind === 'taxonomy' ) && {\n\t\t\t\tid: object_id,\n\t\t\t\tmetadata: {\n\t\t\t\t\tbindings: buildNavigationLinkEntityBinding( inferredKind ),\n\t\t\t\t},\n\t\t\t} ),\n\t\t/* eslint-enable camelcase */\n\t\t...( description?.length && {\n\t\t\tdescription,\n\t\t} ),\n\t\t...( target === '_blank' && {\n\t\t\topensInNewTab: true,\n\t\t} ),\n\t\t...( blockType === 'core/navigation-submenu' && {\n\t\t\tisTopLevelItem: level === 0,\n\t\t} ),\n\t\t...( blockType === 'core/navigation-link' && {\n\t\t\tisTopLevelLink: level === 0,\n\t\t} ),\n\t};\n}\n\n/**\n * Creates a nested, hierarchical tree representation from unstructured data that\n * has an inherent relationship defined between individual items.\n *\n * For example, by default, each element in the dataset should have an `id` and\n * `parent` property where the `parent` property indicates a relationship between\n * the current item and another item with a matching `id` properties.\n *\n * This is useful for building linked lists of data from flat data structures.\n *\n * @param {Array} dataset linked data to be rearranged into a hierarchical tree based on relational fields.\n * @param {string} id the property which uniquely identifies each entry within the array.\n * @param {*} relation the property which identifies how the current item is related to other items in the data (if at all).\n * @return {Array} a nested array of parent/child relationships\n */\nfunction createDataTree( dataset, id = 'id', relation = 'parent' ) {\n\tconst hashTable = Object.create( null );\n\tconst dataTree = [];\n\n\tfor ( const data of dataset ) {\n\t\thashTable[ data[ id ] ] = {\n\t\t\t...data,\n\t\t\tchildren: [],\n\t\t};\n\t\tif ( data[ relation ] ) {\n\t\t\thashTable[ data[ relation ] ] = hashTable[ data[ relation ] ] || {};\n\t\t\thashTable[ data[ relation ] ].children =\n\t\t\t\thashTable[ data[ relation ] ].children || [];\n\t\t\thashTable[ data[ relation ] ].children.push(\n\t\t\t\thashTable[ data[ id ] ]\n\t\t\t);\n\t\t} else {\n\t\t\tdataTree.push( hashTable[ data[ id ] ] );\n\t\t}\n\t}\n\n\treturn dataTree;\n}\n"], "mappings": "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", "names": ["block"] }