UNPKG

@wordpress/block-library

Version:
179 lines (178 loc) 6.25 kB
// packages/block-library/src/embed/util.js import clsx from "clsx"; import memoize from "memize"; import { privateApis as componentsPrivateApis } from "@wordpress/components"; import { renderToString } from "@wordpress/element"; import { createBlock, getBlockType, getBlockVariations } from "@wordpress/blocks"; import metadata from "./block.json"; import { ASPECT_RATIOS, WP_EMBED_TYPE } from "./constants"; import { unlock } from "../lock-unlock"; import { jsx } from "react/jsx-runtime"; var { name: DEFAULT_EMBED_BLOCK } = metadata; var { kebabCase } = unlock(componentsPrivateApis); var getEmbedInfoByProvider = (provider) => getBlockVariations(DEFAULT_EMBED_BLOCK)?.find( ({ name }) => name === provider ); var matchesPatterns = (url, patterns = []) => patterns.some((pattern) => url.match(pattern)); var findMoreSuitableBlock = (url) => getBlockVariations(DEFAULT_EMBED_BLOCK)?.find( ({ patterns }) => matchesPatterns(url, patterns) ); var isFromWordPress = (html) => html && html.includes('class="wp-embedded-content"'); var getPhotoHtml = (photo) => { const imageUrl = photo.url || photo.thumbnail_url; const photoPreview = /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("img", { src: imageUrl, alt: photo.title, width: "100%" }) }); return renderToString(photoPreview); }; var createUpgradedEmbedBlock = (props, attributesFromPreview = {}) => { const { preview, attributes = {} } = props; const { url, providerNameSlug, type, ...restAttributes } = attributes; if (!url || !getBlockType(DEFAULT_EMBED_BLOCK)) { return; } const matchedBlock = findMoreSuitableBlock(url); const isCurrentBlockWP = providerNameSlug === "wordpress" || type === WP_EMBED_TYPE; const shouldCreateNewBlock = !isCurrentBlockWP && matchedBlock && (matchedBlock.attributes.providerNameSlug !== providerNameSlug || !providerNameSlug); if (shouldCreateNewBlock) { return createBlock(DEFAULT_EMBED_BLOCK, { url, ...restAttributes, ...matchedBlock.attributes }); } const wpVariation = getBlockVariations(DEFAULT_EMBED_BLOCK)?.find( ({ name }) => name === "wordpress" ); if (!wpVariation || !preview || !isFromWordPress(preview.html) || isCurrentBlockWP) { return; } return createBlock(DEFAULT_EMBED_BLOCK, { url, ...wpVariation.attributes, // By now we have the preview, but when the new block first renders, it // won't have had all the attributes set, and so won't get the correct // type and it won't render correctly. So, we pass through the current attributes // here so that the initial render works when we switch to the WordPress // block. This only affects the WordPress block because it can't be // rendered in the usual Sandbox (it has a sandbox of its own) and it // relies on the preview to set the correct render type. ...attributesFromPreview }); }; var hasAspectRatioClass = (existingClassNames) => { if (!existingClassNames) { return false; } return ASPECT_RATIOS.some( ({ className }) => existingClassNames.includes(className) ); }; var removeAspectRatioClasses = (existingClassNames) => { if (!existingClassNames) { return existingClassNames; } const aspectRatioClassNames = ASPECT_RATIOS.reduce( (accumulator, { className }) => { accumulator.push(className); return accumulator; }, ["wp-has-aspect-ratio"] ); let outputClassNames = existingClassNames; for (const className of aspectRatioClassNames) { outputClassNames = outputClassNames.replace(className, ""); } return outputClassNames.trim(); }; function getClassNames(html, existingClassNames, allowResponsive = true) { if (!allowResponsive) { return removeAspectRatioClasses(existingClassNames); } const previewDocument = document.implementation.createHTMLDocument(""); previewDocument.body.innerHTML = html; const iframe = previewDocument.body.querySelector("iframe"); if (iframe && iframe.height && iframe.width) { const aspectRatio = (iframe.width / iframe.height).toFixed(2); for (let ratioIndex = 0; ratioIndex < ASPECT_RATIOS.length; ratioIndex++) { const potentialRatio = ASPECT_RATIOS[ratioIndex]; if (aspectRatio >= potentialRatio.ratio) { const ratioDiff = aspectRatio - potentialRatio.ratio; if (ratioDiff > 0.1) { return removeAspectRatioClasses(existingClassNames); } return clsx( removeAspectRatioClasses(existingClassNames), potentialRatio.className, "wp-has-aspect-ratio" ); } } } return existingClassNames; } function fallback(url, onReplace) { const link = /* @__PURE__ */ jsx("a", { href: url, children: url }); onReplace( createBlock("core/paragraph", { content: renderToString(link) }) ); } var getAttributesFromPreview = memoize( (preview, title, currentClassNames, isResponsive, allowResponsive = true) => { if (!preview) { return {}; } const attributes = {}; let { type = "rich" } = preview; const { html, provider_name: providerName } = preview; const providerNameSlug = kebabCase( (providerName || title).toLowerCase() ); if (isFromWordPress(html)) { type = WP_EMBED_TYPE; } if (html || "photo" === type) { attributes.type = type; attributes.providerNameSlug = providerNameSlug; } if (hasAspectRatioClass(currentClassNames)) { return attributes; } attributes.className = getClassNames( html, currentClassNames, isResponsive && allowResponsive ); return attributes; } ); var getMergedAttributesWithPreview = (currentAttributes, preview, title, isResponsive) => { const { allowResponsive, className } = currentAttributes; return { ...currentAttributes, ...getAttributesFromPreview( preview, title, className, isResponsive, allowResponsive ) }; }; export { createUpgradedEmbedBlock, fallback, findMoreSuitableBlock, getAttributesFromPreview, getClassNames, getEmbedInfoByProvider, getMergedAttributesWithPreview, getPhotoHtml, hasAspectRatioClass, isFromWordPress, matchesPatterns, removeAspectRatioClasses }; //# sourceMappingURL=util.js.map