: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (node.getAttribute('data-stringify-type') !== 'paragraph-break') {
parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
parentNode.removeChild(node);
;// CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/raw-handling/paste-handler.js
const log = (...args) => window?.console?.log?.(...args);
* Filters HTML to only contain phrasing content.
* @param {string} HTML The HTML to filter.
* @return {string} HTML only containing phrasing content.
function filterInlineHTML(HTML) {
HTML = deepFilterHTML(HTML, [headRemover, googleDocsUIdRemover, msListIgnore, phrasingContentReducer, commentRemover]);
HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
// Allows us to ask for this information when we get a report.
log('Processed inline HTML:\n\n', HTML);
* Converts an HTML string to known blocks. Strips everything else.
* @param {Object} options
* @param {string} [options.HTML] The HTML to convert.
* @param {string} [options.plainText] Plain text version.
* @param {string} [options.mode] Handle content as blocks or inline content.
* * 'AUTO': Decide based on the content passed.
* * 'INLINE': Always handle as inline content, and return string.
* * 'BLOCKS': Always handle as blocks, and return array of blocks.
* @param {Array} [options.tagName] The tag into which content will be inserted.
* @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
// First of all, strip any meta tags.
HTML = HTML.replace(/<meta[^>]+>/g, '');
// Strip Windows markers.
HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, '');
// If we detect block delimiters in HTML, parse entirely as blocks.
// Check plain text if there is no HTML.
const content = HTML ? HTML : plainText;
if (content.indexOf('<!-- wp:') !== -1) {
const parseResult = parser_parse(content);
const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform';
if (!isSingleFreeFormBlock) {
// Normalize unicode to use composed characters.
// This is unsupported in IE 11 but it's a nice-to-have feature, not mandatory.
// Not normalizing the content will only affect older browsers and won't
// entirely break the app.
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
// See: https://core.trac.wordpress.org/ticket/30130
// See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
if (String.prototype.normalize) {
// Must be run before checking if it's inline content.
HTML = deepFilterHTML(HTML, [slackParagraphCorrector]);
// Consider plain text if:
// * There is a plain text version.
// * There is no HTML version, or it has no formatting.
const isPlainText = plainText && (!HTML || isPlain(HTML));
// Parse Markdown (and encoded HTML) if it's considered plain text.
// The markdown converter (Showdown) trims whitespace.
if (!/^\s+$/.test(plainText)) {
HTML = markdownConverter(HTML);
// An array of HTML strings and block objects. The blocks replace matched
const pieces = shortcode_converter(HTML);
// The call to shortcodeConverter will always return more than one element
// if shortcodes are matched. The reason is when shortcodes are matched
// empty HTML strings are included.
const hasShortcodes = pieces.length > 1;
if (isPlainText && !hasShortcodes) {
// Switch to inline mode if:
// * The current mode is AUTO.
// * The original plain text had no line breaks.
// * The original plain text was not an HTML paragraph.
// * The converted text is just a paragraph.
if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
return filterInlineHTML(HTML);
if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
return filterInlineHTML(HTML);
const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
const blockContentSchema = getBlockContentSchema('paste');
const blocks = pieces.map(piece => {
// Already a block from shortcode.
if (typeof piece !== 'string') {
const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser(), divNormaliser];
// Keep top-level phrasing content, normalised by `normaliseBlocks`.
piece = deepFilterHTML(piece, filters, blockContentSchema);
piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
piece = normaliseBlocks(piece);
piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema);
// Allows us to ask for this information when we get a report.
log('Processed HTML piece:\n\n', piece);
return htmlToBlocks(piece, pasteHandler);
}).flat().filter(Boolean);
// If we're allowed to return inline content, and there is only one
// inlineable block, and the original plain text content does not have any
// line breaks, then treat it as inline paste.
if (mode === 'AUTO' && blocks.length === 1 && hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
const trimRegex = /^[\n]+|[\n]+$/g;
// Don't catch line breaks at the start or end.
const trimmedPlainText = plainText.replace(trimRegex, '');
if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema).replace(trimRegex, '');
;// CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/categories.js
/** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
* Returns all the block categories.
* Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
* @return {WPBlockCategory[]} Block categories.
function categories_getCategories() {
return (0,external_wp_data_namespaceObject.select)(store).getCategories();
* Sets the block categories.
* @param {WPBlockCategory[]} categories Block categories.
* import { __ } from '@wordpress/i18n';
* import { store as blocksStore, setCategories } from '@wordpress/blocks';
* import { useSelect } from '@wordpress/data';
* import { Button } from '@wordpress/components';
* const ExampleComponent = () => {
* // Retrieve the list of current categories.
* const blockCategories = useSelect(
* ( select ) => select( blocksStore ).getCategories(),
* // Add a custom category to the existing list.
* { title: 'Custom Category', slug: 'custom-category' },
* { __( 'Add a new custom block category' ) }
function categories_setCategories(categories) {
(0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
* @param {string} slug Block category slug.
* @param {WPBlockCategory} category Object containing the category properties
* that should be updated.
* import { __ } from '@wordpress/i18n';
* import { updateCategory } from '@wordpress/blocks';
* import { Button } from '@wordpress/components';
* const ExampleComponent = () => {
* updateCategory( 'text', { title: __( 'Written Word' ) } );
* { __( 'Update Text category title' ) }
function categories_updateCategory(slug, category) {
(0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
;// CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/templates.js
* Checks whether a list of blocks matches a template by comparing the block names.
* @param {Array} blocks Block list.
* @param {Array} template Block template.
* @return {boolean} Whether the list of blocks matches a templates.
function doBlocksMatchTemplate(blocks = [], template = []) {
return blocks.length === template.length && template.every(([name,, innerBlocksTemplate], index) => {
const block = blocks[index];
return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
const isHTMLAttribute = attributeDefinition => attributeDefinition?.source === 'html';
const isQueryAttribute = attributeDefinition => attributeDefinition?.source === 'query';
function normalizeAttributes(schema, values) {
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, normalizeAttribute(schema[key], value)]));
function normalizeAttribute(definition, value) {
if (isHTMLAttribute(definition) && Array.isArray(value)) {
// Introduce a deprecated call at this point
// When we're confident that "children" format should be removed from the templates.
return (0,external_wp_element_namespaceObject.renderToString)(value);
if (isQueryAttribute(definition) && value) {
return value.map(subValues => {
return normalizeAttributes(definition.query, subValues);
* Synchronize a block list with a block template.
* Synchronizing a block list with a block template means that we loop over the blocks
* keep the block as is if it matches the block at the same position in the template
* (If it has the same name) and if doesn't match, we create a new block based on the template.
* Extra blocks not present in the template are removed.
* @param {Array} blocks Block list.
* @param {Array} template Block template.
* @return {Array} Updated Block list.
function synchronizeBlocksWithTemplate(blocks = [], template) {
// If no template is provided, return blocks unmodified.
return template.map(([name, attributes, innerBlocksTemplate], index) => {
var _blockType$attributes;
const block = blocks[index];
if (block && block.name === name) {
const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
// To support old templates that were using the "children" format
// for the attributes using "html" strings now, we normalize the template attributes
// before creating the blocks.
const blockType = getBlockType(name);
const normalizedAttributes = normalizeAttributes((_blockType$attributes = blockType?.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}, attributes);
let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes);
// If a Block is undefined at this point, use the core/missing block as
// a placeholder for a better user experience.
if (undefined === getBlockType(blockName)) {
originalUndelimitedContent: ''
blockName = 'core/missing';
return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
;// CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/index.js
// The blocktype is the most important concept within the block API. It defines
// all aspects of the block configuration and its interfaces, including `edit`
// and `save`. The transforms specification allows converting one blocktype to
// another through formulas defined by either the source or the destination.
// Switching a blocktype is to be considered a one-way operation implying a
// transformation in the opposite way has to be handled explicitly.
// The block tree is composed of a collection of block nodes. Blocks contained
// within other blocks are called inner blocks. An important design
// consideration is that inner blocks are -- conceptually -- not part of the
// territory established by the parent block that contains them.
// This has multiple practical implications: when parsing, we can safely dispose
// of any block boundary found within a block from the innerHTML property when
// transfering to state. Not doing so would have a compounding effect on memory
// and uncertainty over the source of truth. This can be illustrated in how,
// given a tree of `n` nested blocks, the entry node would have to contain the
// actual content of each block while each subsequent block node in the state
// tree would replicate the entire chain `n-1`, meaning the extreme end node
// would have been replicated `n` times as the tree is traversed and would
// generate uncertainty as to which one is to hold the current value of the
// block. For composition, it also means inner blocks can effectively be child
// components whose mechanisms can be shielded from the `edit` implementation
// and just passed along.
// While block transformations account for a specific surface of the API, there
// are also raw transformations which handle arbitrary sources not made out of
// blocks but producing block basaed on various heursitics. This includes
// pasting rich text or HTML data.
// The process of serialization aims to deflate the internal memory of the block
// editor and its state representation back into an HTML valid string. This
// process restores the document integrity and inserts invisible delimiters
// around each block with HTML comment boundaries which can contain any extra
// attributes needed to operate with the block later on.
// Validation is the process of comparing a block source with its output before
// there is any user input or interaction with a block. When this operation
// fails -- for whatever reason -- the block is to be considered invalid. As
// part of validating a block the system will attempt to run the source against
// any provided deprecation definitions.
// Worth emphasizing that validation is not a case of whether the markup is
// merely HTML spec-compliant but about how the editor knows to create such
// markup and that its inability to create an identical result can be a strong
// indicator of potential data loss (the invalidation is then a protective
// The invalidation process can also be deconstructed in phases: 1) validate the
// block exists; 2) validate the source matches the output; 3) validate the
// source matches deprecated outputs; 4) work through the significance of
// differences. These are stacked in a way that favors performance and optimizes
// for the majority of cases. That is to say, the evaluation logic can become
// more sophisticated the further down it goes in the process as the cost is
// accounted for. The first logic checks have to be extremely efficient since
// they will be run for all valid and invalid blocks alike. However, once a
// block is detected as invalid -- failing the three first steps -- it is
// adequate to spend more time determining validity before throwing a conflict.
// Blocks are inherently indifferent about where the data they operate with ends
// up being saved. For example, all blocks can have a static and dynamic aspect
// to them depending on the needs. The static nature of a block is the `save()`
// definition that is meant to be serialized into HTML and which can be left
// void. Any block can also register a `render_callback` on the server, which
// makes its output dynamic either in part or in its totality.
// Child blocks are defined as a relationship that builds on top of the inner
// blocks mechanism. A child block is a block node of a particular type that can
// only exist within the inner block boundaries of a specific parent type. This
// allows block authors to compose specific blocks that are not meant to be used
// outside of a specified parent block context. Thus, child blocks extend the
// concept of inner blocks to support a more direct relationship between sets of
// blocks. The addition of parent–child would be a subset of the inner block
// functionality under the premise that certain blocks only make sense as
// children of another block.
// Templates are, in a general sense, a basic collection of block nodes with any
// given set of predefined attributes that are supplied as the initial state of
// an inner blocks group. These nodes can, in turn, contain any number of nested
// blocks within their definition. Templates allow both to specify a default
// state for an editor session or a default set of blocks for any inner block
// implementation within a specific block.
;// CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/deprecated.js
* A Higher Order Component used to inject BlockContent using context to the