UNPKG

@wordpress/blocks

Version:
156 lines (155 loc) 4.47 kB
// packages/blocks/src/api/parser/get-block-attributes.js import { parse as hpqParse } from "hpq"; import memoize from "memize"; import { applyFilters } from "@wordpress/hooks"; import { RichTextData } from "@wordpress/rich-text"; import { attr, html, text, query, node, children, prop, richText } from "../matchers"; import { normalizeBlockType, getDefault } from "../utils"; var toBooleanAttributeMatcher = (matcher) => (value) => matcher(value) !== void 0; function isOfType(value, type) { switch (type) { case "rich-text": return value instanceof RichTextData; case "string": return typeof value === "string"; case "boolean": return typeof value === "boolean"; case "object": return !!value && value.constructor === Object; case "null": return value === null; case "array": return Array.isArray(value); case "integer": case "number": return typeof value === "number"; } return true; } function isOfTypes(value, types) { return types.some((type) => isOfType(value, type)); } function getBlockAttribute(attributeKey, attributeSchema, innerDOM, commentAttributes, innerHTML) { let value; switch (attributeSchema.source) { // An undefined source means that it's an attribute serialized to the // block's "comment". case void 0: value = commentAttributes ? commentAttributes[attributeKey] : void 0; break; // raw source means that it's the original raw block content. case "raw": value = innerHTML; break; case "attribute": case "property": case "html": case "text": case "rich-text": case "children": case "node": case "query": case "tag": value = parseWithAttributeSchema(innerDOM, attributeSchema); break; } if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) { value = void 0; } if (value === void 0) { value = getDefault(attributeSchema); } return value; } function isValidByType(value, type) { return type === void 0 || isOfTypes(value, Array.isArray(type) ? type : [type]); } function isValidByEnum(value, enumSet) { return !Array.isArray(enumSet) || enumSet.includes(value); } var matcherFromSource = memoize((sourceConfig) => { switch (sourceConfig.source) { case "attribute": { let matcher = attr(sourceConfig.selector, sourceConfig.attribute); if (sourceConfig.type === "boolean") { matcher = toBooleanAttributeMatcher(matcher); } return matcher; } case "html": return html(sourceConfig.selector, sourceConfig.multiline); case "text": return text(sourceConfig.selector); case "rich-text": return richText( sourceConfig.selector, sourceConfig.__unstablePreserveWhiteSpace ); case "children": return children(sourceConfig.selector); case "node": return node(sourceConfig.selector); case "query": const subMatchers = Object.fromEntries( Object.entries(sourceConfig.query).map( ([key, subSourceConfig]) => [ key, matcherFromSource(subSourceConfig) ] ) ); return query(sourceConfig.selector, subMatchers); case "tag": { const matcher = prop(sourceConfig.selector, "nodeName"); return (domNode) => matcher(domNode)?.toLowerCase(); } default: console.error(`Unknown source type "${sourceConfig.source}"`); } }); function parseHtml(innerHTML) { return hpqParse(innerHTML, (h) => h); } function parseWithAttributeSchema(innerHTML, attributeSchema) { return matcherFromSource(attributeSchema)(parseHtml(innerHTML)); } function getBlockAttributes(blockTypeOrName, innerHTML, attributes = {}) { const doc = parseHtml(innerHTML); const blockType = normalizeBlockType(blockTypeOrName); const blockAttributes = Object.fromEntries( Object.entries(blockType.attributes ?? {}).map( ([key, schema]) => [ key, getBlockAttribute(key, schema, doc, attributes, innerHTML) ] ) ); return applyFilters( "blocks.getBlockAttributes", blockAttributes, blockType, innerHTML, attributes ); } export { getBlockAttribute, getBlockAttributes, isOfType, isOfTypes, isValidByEnum, isValidByType, matcherFromSource, parseWithAttributeSchema, toBooleanAttributeMatcher }; //# sourceMappingURL=get-block-attributes.js.map