@wordpress/blocks
Version:
Block API for WordPress.
143 lines (142 loc) • 5.17 kB
JavaScript
// packages/blocks/src/api/parser/index.js
import { parse as grammarParse } from "@wordpress/block-serialization-default-parser";
import { autop } from "@wordpress/autop";
import {
getFreeformContentHandlerName,
getUnregisteredTypeHandlerName,
getBlockType
} from "../registration";
import { getSaveContent } from "../serializer";
import { validateBlock } from "../validation";
import { createBlock } from "../factory";
import { convertLegacyBlockNameAndAttributes } from "./convert-legacy-block";
import { serializeRawBlock } from "./serialize-raw-block";
import { getBlockAttributes } from "./get-block-attributes";
import { applyBlockDeprecatedVersions } from "./apply-block-deprecated-versions";
import { applyBuiltInValidationFixes } from "./apply-built-in-validation-fixes";
function convertLegacyBlocks(rawBlock) {
const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(
rawBlock.blockName,
rawBlock.attrs
);
return {
...rawBlock,
blockName: correctName,
attrs: correctedAttributes
};
}
function normalizeRawBlock(rawBlock, options) {
const fallbackBlockName = getFreeformContentHandlerName();
const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
const rawAttributes = rawBlock.attrs || {};
const rawInnerBlocks = rawBlock.innerBlocks || [];
let rawInnerHTML = rawBlock.innerHTML.trim();
if (rawBlockName === fallbackBlockName && rawBlockName === "core/freeform" && !options?.__unstableSkipAutop) {
rawInnerHTML = autop(rawInnerHTML).trim();
}
return {
...rawBlock,
blockName: rawBlockName,
attrs: rawAttributes,
innerHTML: rawInnerHTML,
innerBlocks: rawInnerBlocks
};
}
function createMissingBlockType(rawBlock) {
const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName();
const originalUndelimitedContent = serializeRawBlock(rawBlock, {
isCommentDelimited: false
});
const originalContent = serializeRawBlock(rawBlock, {
isCommentDelimited: true
});
return {
blockName: unregisteredFallbackBlock,
attrs: {
originalName: rawBlock.blockName,
originalContent,
originalUndelimitedContent
},
innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
innerBlocks: rawBlock.innerBlocks,
innerContent: rawBlock.innerContent
};
}
function applyBlockValidation(unvalidatedBlock, blockType) {
const [isValid] = validateBlock(unvalidatedBlock, blockType);
if (isValid) {
return { ...unvalidatedBlock, isValid, validationIssues: [] };
}
const fixedBlock = applyBuiltInValidationFixes(
unvalidatedBlock,
blockType
);
const [isFixedValid, validationIssues] = validateBlock(
fixedBlock,
blockType
);
return { ...fixedBlock, isValid: isFixedValid, validationIssues };
}
function parseRawBlock(rawBlock, options) {
let normalizedBlock = normalizeRawBlock(rawBlock, options);
normalizedBlock = convertLegacyBlocks(normalizedBlock);
let blockType = getBlockType(normalizedBlock.blockName);
if (!blockType) {
normalizedBlock = createMissingBlockType(normalizedBlock);
blockType = getBlockType(normalizedBlock.blockName);
}
const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
return;
}
const parsedInnerBlocks = normalizedBlock.innerBlocks.map((innerBlock) => parseRawBlock(innerBlock, options)).filter((innerBlock) => !!innerBlock);
const parsedBlock = createBlock(
normalizedBlock.blockName,
getBlockAttributes(
blockType,
normalizedBlock.innerHTML,
normalizedBlock.attrs
),
parsedInnerBlocks
);
parsedBlock.originalContent = normalizedBlock.innerHTML;
const validatedBlock = applyBlockValidation(parsedBlock, blockType);
const { validationIssues } = validatedBlock;
const updatedBlock = applyBlockDeprecatedVersions(
validatedBlock,
normalizedBlock,
blockType
);
if (!updatedBlock.isValid) {
updatedBlock.__unstableBlockSource = rawBlock;
}
if (!validatedBlock.isValid && updatedBlock.isValid && !options?.__unstableSkipMigrationLogs) {
console.groupCollapsed("Updated Block: %s", blockType.name);
console.info(
"Block successfully updated for `%s` (%o).\n\nNew content generated by `save` function:\n\n%s\n\nContent retrieved from post body:\n\n%s",
blockType.name,
blockType,
getSaveContent(blockType, updatedBlock.attributes),
updatedBlock.originalContent
);
console.groupEnd();
} else if (!validatedBlock.isValid && !updatedBlock.isValid) {
validationIssues.forEach(({ log, args }) => log(...args));
}
return updatedBlock;
}
function parse(content, options) {
return grammarParse(content).reduce((accumulator, rawBlock) => {
const block = parseRawBlock(rawBlock, options);
if (block) {
accumulator.push(block);
}
return accumulator;
}, []);
}
export {
parse as default,
normalizeRawBlock,
parseRawBlock
};
//# sourceMappingURL=index.js.map