UNPKG

@wordpress/blocks

Version:
170 lines (163 loc) 7.23 kB
/** * External dependencies */ import { isPlainObject } from 'is-plain-object'; import { isValidElementType } from 'react-is'; /** * WordPress dependencies */ import deprecated from '@wordpress/deprecated'; import { applyFilters } from '@wordpress/hooks'; import warning from '@wordpress/warning'; /** * Internal dependencies */ import { isValidIcon, normalizeIconObject, omit } from '../api/utils'; import { BLOCK_ICON_DEFAULT, DEPRECATED_ENTRY_KEYS } from '../api/constants'; /** @typedef {import('../api/registration').WPBlockType} WPBlockType */ /** * Mapping of legacy category slugs to their latest normal values, used to * accommodate updates of the default set of block categories. * * @type {Record<string,string>} */ const LEGACY_CATEGORY_MAPPING = { common: 'text', formatting: 'text', layout: 'design' }; /** * Merge block variations bootstrapped from the server and client. * * When a variation is registered in both places, its properties are merged. * * @param {Array} bootstrappedVariations - A block type variations from the server. * @param {Array} clientVariations - A block type variations from the client. * @return {Array} The merged array of block variations. */ function mergeBlockVariations(bootstrappedVariations = [], clientVariations = []) { const result = [...bootstrappedVariations]; clientVariations.forEach(clientVariation => { const index = result.findIndex(bootstrappedVariation => bootstrappedVariation.name === clientVariation.name); if (index !== -1) { result[index] = { ...result[index], ...clientVariation }; } else { result.push(clientVariation); } }); return result; } /** * Takes the unprocessed block type settings, merges them with block type metadata * and applies all the existing filters for the registered block type. * Next, it validates all the settings and performs additional processing to the block type definition. * * @param {string} name Block name. * @param {WPBlockType} blockSettings Unprocessed block type settings. * * @return {WPBlockType | undefined} The block, if it has been processed and can be registered; otherwise `undefined`. */ export const processBlockType = (name, blockSettings) => ({ select }) => { const bootstrappedBlockType = select.getBootstrappedBlockType(name); const blockType = { apiVersion: 1, name, icon: BLOCK_ICON_DEFAULT, keywords: [], attributes: {}, providesContext: {}, usesContext: [], selectors: {}, supports: {}, styles: [], blockHooks: {}, save: () => null, ...bootstrappedBlockType, ...blockSettings, // blockType.variations can be defined as a filePath. variations: mergeBlockVariations(Array.isArray(bootstrappedBlockType?.variations) ? bootstrappedBlockType.variations : [], Array.isArray(blockSettings?.variations) ? blockSettings.variations : []) }; const settings = applyFilters('blocks.registerBlockType', blockType, name, null); if (settings.apiVersion <= 2) { globalThis.SCRIPT_DEBUG === true ? warning(`The block "${name}" is registered with API version 2 or lower. This means that the post editor may work as a non-iframe editor.\n` + `Since all editors are planned to work as iframes in the future, set the \`apiVersion\` field to 3 and test the block inside the iframe editor.\n` + `See: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/#version-3-wordpress-6-3`) : void 0; } if (settings.description && typeof settings.description !== 'string') { deprecated('Declaring non-string block descriptions', { since: '6.2' }); } if (settings.deprecated) { settings.deprecated = settings.deprecated.map(deprecation => Object.fromEntries(Object.entries( // Only keep valid deprecation keys. applyFilters('blocks.registerBlockType', // Merge deprecation keys with pre-filter settings // so that filters that depend on specific keys being // present don't fail. { // Omit deprecation keys here so that deprecations // can opt out of specific keys like "supports". ...omit(blockType, DEPRECATED_ENTRY_KEYS), ...deprecation }, blockType.name, deprecation)).filter(([key]) => DEPRECATED_ENTRY_KEYS.includes(key)))); } if (!isPlainObject(settings)) { globalThis.SCRIPT_DEBUG === true ? warning('Block settings must be a valid object.') : void 0; return; } if (typeof settings.save !== 'function') { globalThis.SCRIPT_DEBUG === true ? warning('The "save" property must be a valid function.') : void 0; return; } if ('edit' in settings && !isValidElementType(settings.edit)) { globalThis.SCRIPT_DEBUG === true ? warning('The "edit" property must be a valid component.') : void 0; return; } // Canonicalize legacy categories to equivalent fallback. if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) { settings.category = LEGACY_CATEGORY_MAPPING[settings.category]; } if ('category' in settings && !select.getCategories().some(({ slug }) => slug === settings.category)) { globalThis.SCRIPT_DEBUG === true ? warning('The block "' + name + '" is registered with an invalid category "' + settings.category + '".') : void 0; delete settings.category; } if (!('title' in settings) || settings.title === '') { globalThis.SCRIPT_DEBUG === true ? warning('The block "' + name + '" must have a title.') : void 0; return; } if (typeof settings.title !== 'string') { globalThis.SCRIPT_DEBUG === true ? warning('Block titles must be strings.') : void 0; return; } settings.icon = normalizeIconObject(settings.icon); if (!isValidIcon(settings.icon.src)) { globalThis.SCRIPT_DEBUG === true ? warning('The icon passed is invalid. ' + 'The icon should be a string, an element, a function, or an object following the specifications documented in https://developer.wordpress.org/block-editor/developers/block-api/block-registration/#icon-optional') : void 0; return; } if (typeof settings?.parent === 'string' || settings?.parent instanceof String) { settings.parent = [settings.parent]; globalThis.SCRIPT_DEBUG === true ? warning('Parent must be undefined or an array of strings (block types), but it is a string.') : void 0; // Intentionally continue: // // While string values were never supported, they appeared to work with some unintended side-effects // that have been fixed by [#66250](https://github.com/WordPress/gutenberg/pull/66250). // // To be backwards-compatible, this code that automatically migrates strings to arrays. } if (!Array.isArray(settings?.parent) && settings?.parent !== undefined) { globalThis.SCRIPT_DEBUG === true ? warning('Parent must be undefined or an array of block types, but it is ', settings.parent) : void 0; return; } if (1 === settings?.parent?.length && name === settings.parent[0]) { globalThis.SCRIPT_DEBUG === true ? warning('Block "' + name + '" cannot be a parent of itself. Please remove the block name from the parent list.') : void 0; return; } return settings; }; //# sourceMappingURL=process-block-type.js.map