@wordpress/blocks
Version:
Block API for WordPress.
303 lines (302 loc) • 9.78 kB
JavaScript
// packages/blocks/src/api/factory.js
import { v4 as uuid } from "uuid";
import { createHooks, applyFilters } from "@wordpress/hooks";
import {
getBlockType,
getBlockTypes,
getGroupingBlockName
} from "./registration";
import {
isBlockRegistered,
normalizeBlockType,
__experimentalSanitizeBlockAttributes
} from "./utils";
function createBlock(name, attributes = {}, innerBlocks = []) {
if (!isBlockRegistered(name)) {
return createBlock("core/missing", {
originalName: name,
originalContent: "",
originalUndelimitedContent: ""
});
}
const sanitizedAttributes = __experimentalSanitizeBlockAttributes(
name,
attributes
);
const clientId = uuid();
return {
clientId,
name,
isValid: true,
attributes: sanitizedAttributes,
innerBlocks
};
}
function createBlocksFromInnerBlocksTemplate(innerBlocksOrTemplate = []) {
return innerBlocksOrTemplate.map((innerBlock) => {
const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [
innerBlock.name,
innerBlock.attributes,
innerBlock.innerBlocks
];
const [name, attributes, innerBlocks = []] = innerBlockTemplate;
return createBlock(
name,
attributes,
createBlocksFromInnerBlocksTemplate(innerBlocks)
);
});
}
function __experimentalCloneSanitizedBlock(block, mergeAttributes = {}, newInnerBlocks) {
const { name } = block;
if (!isBlockRegistered(name)) {
return createBlock("core/missing", {
originalName: name,
originalContent: "",
originalUndelimitedContent: ""
});
}
const clientId = uuid();
const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, {
...block.attributes,
...mergeAttributes
});
return {
...block,
clientId,
attributes: sanitizedAttributes,
innerBlocks: newInnerBlocks || block.innerBlocks.map(
(innerBlock) => __experimentalCloneSanitizedBlock(innerBlock)
)
};
}
function cloneBlock(block, mergeAttributes = {}, newInnerBlocks) {
const clientId = uuid();
return {
...block,
clientId,
attributes: {
...block.attributes,
...mergeAttributes
},
innerBlocks: newInnerBlocks || block.innerBlocks.map((innerBlock) => cloneBlock(innerBlock))
};
}
var isPossibleTransformForSource = (transform, direction, blocks) => {
if (!blocks.length) {
return false;
}
const isMultiBlock = blocks.length > 1;
const firstBlockName = blocks[0].name;
const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
if (!isValidForMultiBlocks) {
return false;
}
if (!isWildcardBlockTransform(transform) && !blocks.every((block) => block.name === firstBlockName)) {
return false;
}
const isBlockType = transform.type === "block";
if (!isBlockType) {
return false;
}
const sourceBlock = blocks[0];
const hasMatchingName = direction !== "from" || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
if (!hasMatchingName) {
return false;
}
if (!isMultiBlock && direction === "from" && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
return false;
}
if (!maybeCheckTransformIsMatch(transform, blocks)) {
return false;
}
return true;
};
var getBlockTypesForPossibleFromTransforms = (blocks) => {
if (!blocks.length) {
return [];
}
const allBlockTypes = getBlockTypes();
const blockTypesWithPossibleFromTransforms = allBlockTypes.filter(
(blockType) => {
const fromTransforms = getBlockTransforms("from", blockType.name);
return !!findTransform(fromTransforms, (transform) => {
return isPossibleTransformForSource(
transform,
"from",
blocks
);
});
}
);
return blockTypesWithPossibleFromTransforms;
};
var getBlockTypesForPossibleToTransforms = (blocks) => {
if (!blocks.length) {
return [];
}
const sourceBlock = blocks[0];
const blockType = getBlockType(sourceBlock.name);
const transformsTo = blockType ? getBlockTransforms("to", blockType.name) : [];
const possibleTransforms = transformsTo.filter((transform) => {
return transform && isPossibleTransformForSource(transform, "to", blocks);
});
const blockNames = possibleTransforms.map((transformation) => transformation.blocks).flat();
return blockNames.map(getBlockType);
};
var isWildcardBlockTransform = (t) => t && t.type === "block" && Array.isArray(t.blocks) && t.blocks.includes("*");
var isContainerGroupBlock = (name) => name === getGroupingBlockName();
function getPossibleBlockTransformations(blocks) {
if (!blocks.length) {
return [];
}
const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
return [
.../* @__PURE__ */ new Set([
...blockTypesForFromTransforms,
...blockTypesForToTransforms
])
];
}
function findTransform(transforms, predicate) {
const hooks = createHooks();
for (let i = 0; i < transforms.length; i++) {
const candidate = transforms[i];
if (predicate(candidate)) {
hooks.addFilter(
"transform",
"transform/" + i.toString(),
(result) => result ? result : candidate,
candidate.priority
);
}
}
return hooks.applyFilters("transform", null);
}
function getBlockTransforms(direction, blockTypeOrName) {
if (blockTypeOrName === void 0) {
return getBlockTypes().map(({ name }) => getBlockTransforms(direction, name)).flat();
}
const blockType = normalizeBlockType(blockTypeOrName);
const { name: blockName, transforms } = blockType || {};
if (!transforms || !Array.isArray(transforms[direction])) {
return [];
}
const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
const filteredTransforms = usingMobileTransformations ? transforms[direction].filter((t) => {
if (t.type === "raw") {
return true;
}
if (t.type === "prefix") {
return true;
}
if (!t.blocks || !t.blocks.length) {
return false;
}
if (isWildcardBlockTransform(t)) {
return true;
}
return t.blocks.every(
(transformBlockName) => transforms.supportedMobileTransforms.includes(
transformBlockName
)
);
}) : transforms[direction];
return filteredTransforms.map((transform) => ({
...transform,
blockName,
usingMobileTransformations
}));
}
function maybeCheckTransformIsMatch(transform, blocks) {
if (typeof transform.isMatch !== "function") {
return true;
}
const sourceBlock = blocks[0];
const attributes = transform.isMultiBlock ? blocks.map((block2) => block2.attributes) : sourceBlock.attributes;
const block = transform.isMultiBlock ? blocks : sourceBlock;
return transform.isMatch(attributes, block);
}
function switchToBlockType(blocks, name) {
const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
const isMultiBlock = blocksArray.length > 1;
const firstBlock = blocksArray[0];
const sourceName = firstBlock.name;
const transformationsFrom = getBlockTransforms("from", name);
const transformationsTo = getBlockTransforms("to", sourceName);
const transformation = findTransform(
transformationsTo,
(t) => t.type === "block" && (isWildcardBlockTransform(t) || t.blocks.indexOf(name) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)
) || findTransform(
transformationsFrom,
(t) => t.type === "block" && (isWildcardBlockTransform(t) || t.blocks.indexOf(sourceName) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)
);
if (!transformation) {
return null;
}
let transformationResults;
if (transformation.isMultiBlock) {
if ("__experimentalConvert" in transformation) {
transformationResults = transformation.__experimentalConvert(blocksArray);
} else {
transformationResults = transformation.transform(
blocksArray.map((currentBlock) => currentBlock.attributes),
blocksArray.map((currentBlock) => currentBlock.innerBlocks)
);
}
} else if ("__experimentalConvert" in transformation) {
transformationResults = transformation.__experimentalConvert(firstBlock);
} else {
transformationResults = transformation.transform(
firstBlock.attributes,
firstBlock.innerBlocks
);
}
if (transformationResults === null || typeof transformationResults !== "object") {
return null;
}
transformationResults = Array.isArray(transformationResults) ? transformationResults : [transformationResults];
if (transformationResults.some(
(result) => !getBlockType(result.name)
)) {
return null;
}
const hasSwitchedBlock = transformationResults.some(
(result) => result.name === name
);
if (!hasSwitchedBlock) {
return null;
}
const ret = transformationResults.map((result, index, results) => {
return applyFilters(
"blocks.switchToBlockType.transformedBlock",
result,
blocks,
index,
results
);
});
return ret;
}
var getBlockFromExample = (name, example) => createBlock(
name,
example.attributes,
(example.innerBlocks ?? []).map(
(innerBlock) => getBlockFromExample(innerBlock.name, innerBlock)
)
);
export {
__experimentalCloneSanitizedBlock,
cloneBlock,
createBlock,
createBlocksFromInnerBlocksTemplate,
findTransform,
getBlockFromExample,
getBlockTransforms,
getPossibleBlockTransformations,
isContainerGroupBlock,
isWildcardBlockTransform,
switchToBlockType
};
//# sourceMappingURL=factory.js.map