{
  "version": 3,
  "sources": ["../../../src/api/validation/index.js"],
  "sourcesContent": ["/**\n * External dependencies\n */\nimport { Tokenizer } from 'simple-html-tokenizer';\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\nimport deprecated from '@wordpress/deprecated';\nimport { decodeEntities } from '@wordpress/html-entities';\n\n/**\n * Internal dependencies\n */\nimport { createLogger, createQueuedLogger } from './logger';\nimport { getSaveContent } from '../serializer';\nimport {\n\tgetFreeformContentHandlerName,\n\tgetUnregisteredTypeHandlerName,\n} from '../registration';\nimport { normalizeBlockType } from '../utils';\n\n/** @typedef {import('../parser').WPBlock} WPBlock */\n/** @typedef {import('../registration').WPBlockType} WPBlockType */\n/** @typedef {import('./logger').LoggerItem} LoggerItem */\n\nconst identity = ( x ) => x;\n\n/**\n * Globally matches any consecutive whitespace\n *\n * @type {RegExp}\n */\nconst REGEXP_WHITESPACE = /[\\t\\n\\r\\v\\f ]+/g;\n\n/**\n * Matches a string containing only whitespace\n *\n * @type {RegExp}\n */\nconst REGEXP_ONLY_WHITESPACE = /^[\\t\\n\\r\\v\\f ]*$/;\n\n/**\n * Matches a CSS URL type value\n *\n * @type {RegExp}\n */\nconst REGEXP_STYLE_URL_TYPE = /^url\\s*\\(['\"\\s]*(.*?)['\"\\s]*\\)$/;\n\n/**\n * Boolean attributes are attributes whose presence as being assigned is\n * meaningful, even if only empty.\n *\n * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes\n * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3\n *\n * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )\n *     .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )\n *     .reduce( ( result, tr ) => Object.assign( result, {\n *         [ tr.firstChild.textContent.trim() ]: true\n *     } ), {} ) ).sort();\n *\n * @type {Array}\n */\nconst BOOLEAN_ATTRIBUTES = [\n\t'allowfullscreen',\n\t'allowpaymentrequest',\n\t'allowusermedia',\n\t'async',\n\t'autofocus',\n\t'autoplay',\n\t'checked',\n\t'controls',\n\t'default',\n\t'defer',\n\t'disabled',\n\t'download',\n\t'formnovalidate',\n\t'hidden',\n\t'ismap',\n\t'itemscope',\n\t'loop',\n\t'multiple',\n\t'muted',\n\t'nomodule',\n\t'novalidate',\n\t'open',\n\t'playsinline',\n\t'readonly',\n\t'required',\n\t'reversed',\n\t'selected',\n\t'typemustmatch',\n];\n\n/**\n * Enumerated attributes are attributes which must be of a specific value form.\n * Like boolean attributes, these are meaningful if specified, even if not of a\n * valid enumerated value.\n *\n * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute\n * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3\n *\n * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )\n *     .filter( ( tr ) => /^(\"(.+?)\";?\\s*)+/.test( tr.lastChild.textContent.trim() ) )\n *     .reduce( ( result, tr ) => Object.assign( result, {\n *         [ tr.firstChild.textContent.trim() ]: true\n *     } ), {} ) ).sort();\n *\n * @type {Array}\n */\nconst ENUMERATED_ATTRIBUTES = [\n\t'autocapitalize',\n\t'autocomplete',\n\t'charset',\n\t'contenteditable',\n\t'crossorigin',\n\t'decoding',\n\t'dir',\n\t'draggable',\n\t'enctype',\n\t'formenctype',\n\t'formmethod',\n\t'http-equiv',\n\t'inputmode',\n\t'kind',\n\t'method',\n\t'preload',\n\t'scope',\n\t'shape',\n\t'spellcheck',\n\t'translate',\n\t'type',\n\t'wrap',\n];\n\n/**\n * Meaningful attributes are those who cannot be safely ignored when omitted in\n * one HTML markup string and not another.\n *\n * @type {Array}\n */\nconst MEANINGFUL_ATTRIBUTES = [\n\t...BOOLEAN_ATTRIBUTES,\n\t...ENUMERATED_ATTRIBUTES,\n];\n\n/**\n * Array of functions which receive a text string on which to apply normalizing\n * behavior for consideration in text token equivalence, carefully ordered from\n * least-to-most expensive operations.\n *\n * @type {Array}\n */\nconst TEXT_NORMALIZATIONS = [ identity, getTextWithCollapsedWhitespace ];\n\n/**\n * Regular expression matching a named character reference. In lieu of bundling\n * a full set of references, the pattern covers the minimal necessary to test\n * positively against the full set.\n *\n * \"The ampersand must be followed by one of the names given in the named\n * character references section, using the same case.\"\n *\n * Tested against \"12.5 Named character references\":\n *\n * ```\n * const references = Array.from( document.querySelectorAll(\n *     '#named-character-references-table tr[id^=entity-] td:first-child'\n * ) ).map( ( code ) => code.textContent )\n * references.every( ( reference ) => /^[\\da-z]+$/i.test( reference ) )\n * ```\n *\n * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references\n * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references\n *\n * @type {RegExp}\n */\nconst REGEXP_NAMED_CHARACTER_REFERENCE = /^[\\da-z]+$/i;\n\n/**\n * Regular expression matching a decimal character reference.\n *\n * \"The ampersand must be followed by a U+0023 NUMBER SIGN character (#),\n * followed by one or more ASCII digits, representing a base-ten integer\"\n *\n * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references\n *\n * @type {RegExp}\n */\nconst REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\\d+$/;\n\n/**\n * Regular expression matching a hexadecimal character reference.\n *\n * \"The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which\n * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a\n * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by\n * one or more ASCII hex digits, representing a hexadecimal integer\"\n *\n * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references\n *\n * @type {RegExp}\n */\nconst REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\\da-f]+$/i;\n\n/**\n * Returns true if the given string is a valid character reference segment, or\n * false otherwise. The text should be stripped of `&` and `;` demarcations.\n *\n * @param {string} text Text to test.\n *\n * @return {boolean} Whether text is valid character reference.\n */\nexport function isValidCharacterReference( text ) {\n\treturn (\n\t\tREGEXP_NAMED_CHARACTER_REFERENCE.test( text ) ||\n\t\tREGEXP_DECIMAL_CHARACTER_REFERENCE.test( text ) ||\n\t\tREGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test( text )\n\t);\n}\n\n/**\n * Substitute EntityParser class for `simple-html-tokenizer` which uses the\n * implementation of `decodeEntities` from `html-entities`, in order to avoid\n * bundling a massive named character reference.\n *\n * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts\n */\nexport class DecodeEntityParser {\n\t/**\n\t * Returns a substitute string for an entity string sequence between `&`\n\t * and `;`, or undefined if no substitution should occur.\n\t *\n\t * @param {string} entity Entity fragment discovered in HTML.\n\t *\n\t * @return {string | undefined} Entity substitute value.\n\t */\n\tparse( entity ) {\n\t\tif ( isValidCharacterReference( entity ) ) {\n\t\t\treturn decodeEntities( '&' + entity + ';' );\n\t\t}\n\t}\n}\n\n/**\n * Given a specified string, returns an array of strings split by consecutive\n * whitespace, ignoring leading or trailing whitespace.\n *\n * @param {string} text Original text.\n *\n * @return {string[]} Text pieces split on whitespace.\n */\nexport function getTextPiecesSplitOnWhitespace( text ) {\n\treturn text.trim().split( REGEXP_WHITESPACE );\n}\n\n/**\n * Given a specified string, returns a new trimmed string where all consecutive\n * whitespace is collapsed to a single space.\n *\n * @param {string} text Original text.\n *\n * @return {string} Trimmed text with consecutive whitespace collapsed.\n */\nexport function getTextWithCollapsedWhitespace( text ) {\n\t// This is an overly simplified whitespace comparison. The specification is\n\t// more prescriptive of whitespace behavior in inline and block contexts.\n\t//\n\t// See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33\n\treturn getTextPiecesSplitOnWhitespace( text ).join( ' ' );\n}\n\n/**\n * Returns attribute pairs of the given StartTag token, including only pairs\n * where the value is non-empty or the attribute is a boolean attribute, an\n * enumerated attribute, or a custom data- attribute.\n *\n * @see MEANINGFUL_ATTRIBUTES\n *\n * @param {Object} token StartTag token.\n *\n * @return {Array[]} Attribute pairs.\n */\nexport function getMeaningfulAttributePairs( token ) {\n\treturn token.attributes.filter( ( pair ) => {\n\t\tconst [ key, value ] = pair;\n\t\treturn (\n\t\t\tvalue ||\n\t\t\tkey.indexOf( 'data-' ) === 0 ||\n\t\t\tMEANINGFUL_ATTRIBUTES.includes( key )\n\t\t);\n\t} );\n}\n\n/**\n * Returns true if two text tokens (with `chars` property) are equivalent, or\n * false otherwise.\n *\n * @param {Object} actual   Actual token.\n * @param {Object} expected Expected token.\n * @param {Object} logger   Validation logger object.\n *\n * @return {boolean} Whether two text tokens are equivalent.\n */\nexport function isEquivalentTextTokens(\n\tactual,\n\texpected,\n\tlogger = createLogger()\n) {\n\t// This function is intentionally written as syntactically \"ugly\" as a hot\n\t// path optimization. Text is progressively normalized in order from least-\n\t// to-most operationally expensive, until the earliest point at which text\n\t// can be confidently inferred as being equal.\n\tlet actualChars = actual.chars;\n\tlet expectedChars = expected.chars;\n\n\tfor ( let i = 0; i < TEXT_NORMALIZATIONS.length; i++ ) {\n\t\tconst normalize = TEXT_NORMALIZATIONS[ i ];\n\n\t\tactualChars = normalize( actualChars );\n\t\texpectedChars = normalize( expectedChars );\n\n\t\tif ( actualChars === expectedChars ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tlogger.warning(\n\t\t'Expected text `%s`, saw `%s`.',\n\t\texpected.chars,\n\t\tactual.chars\n\t);\n\n\treturn false;\n}\n\n/**\n * Given a CSS length value, returns a normalized CSS length value for strict equality\n * comparison.\n *\n * @param {string} value CSS length value.\n *\n * @return {string} Normalized CSS length value.\n */\nexport function getNormalizedLength( value ) {\n\tif ( 0 === parseFloat( value ) ) {\n\t\treturn '0';\n\t}\n\t// Normalize strings with floats to always include a leading zero.\n\tif ( value.indexOf( '.' ) === 0 ) {\n\t\treturn '0' + value;\n\t}\n\n\treturn value;\n}\n\n/**\n * Given a style value, returns a normalized style value for strict equality\n * comparison.\n *\n * @param {string} value Style value.\n *\n * @return {string} Normalized style value.\n */\nexport function getNormalizedStyleValue( value ) {\n\tconst textPieces = getTextPiecesSplitOnWhitespace( value );\n\tconst normalizedPieces = textPieces.map( getNormalizedLength );\n\tconst result = normalizedPieces.join( ' ' );\n\n\treturn (\n\t\tresult\n\t\t\t// Normalize URL type to omit whitespace or quotes.\n\t\t\t.replace( REGEXP_STYLE_URL_TYPE, 'url($1)' )\n\t);\n}\n\n/**\n * Given a style attribute string, returns an object of style properties.\n *\n * @param {string} text Style attribute.\n *\n * @return {Object} Style properties.\n */\nexport function getStyleProperties( text ) {\n\tconst pairs = text\n\t\t// Trim ending semicolon (avoid including in split)\n\t\t.replace( /;?\\s*$/, '' )\n\t\t// Split on property assignment.\n\t\t.split( ';' )\n\t\t// For each property assignment...\n\t\t.map( ( style ) => {\n\t\t\t// ...split further into key-value pairs.\n\t\t\tconst [ key, ...valueParts ] = style.split( ':' );\n\t\t\tconst value = valueParts.join( ':' );\n\n\t\t\treturn [ key.trim(), getNormalizedStyleValue( value.trim() ) ];\n\t\t} );\n\n\treturn Object.fromEntries( pairs );\n}\n\n/**\n * Attribute-specific equality handlers\n *\n * @type {Object}\n */\nexport const isEqualAttributesOfName = {\n\tclass: ( actual, expected ) => {\n\t\t// Class matches if members are the same, even if out of order or\n\t\t// superfluous whitespace between.\n\t\tconst [ actualPieces, expectedPieces ] = [ actual, expected ].map(\n\t\t\tgetTextPiecesSplitOnWhitespace\n\t\t);\n\t\tconst actualDiff = actualPieces.filter(\n\t\t\t( c ) => ! expectedPieces.includes( c )\n\t\t);\n\t\tconst expectedDiff = expectedPieces.filter(\n\t\t\t( c ) => ! actualPieces.includes( c )\n\t\t);\n\n\t\treturn actualDiff.length === 0 && expectedDiff.length === 0;\n\t},\n\tstyle: ( actual, expected ) => {\n\t\treturn fastDeepEqual(\n\t\t\t...[ actual, expected ].map( getStyleProperties )\n\t\t);\n\t},\n\t// For each boolean attribute, mere presence of attribute in both is enough\n\t// to assume equivalence.\n\t...Object.fromEntries(\n\t\tBOOLEAN_ATTRIBUTES.map( ( attribute ) => [ attribute, () => true ] )\n\t),\n};\n\n/**\n * Given two sets of attribute tuples, returns true if the attribute sets are\n * equivalent.\n *\n * @param {Array[]} actual   Actual attributes tuples.\n * @param {Array[]} expected Expected attributes tuples.\n * @param {Object}  logger   Validation logger object.\n *\n * @return {boolean} Whether attributes are equivalent.\n */\nexport function isEqualTagAttributePairs(\n\tactual,\n\texpected,\n\tlogger = createLogger()\n) {\n\t// Attributes is tokenized as tuples. Their lengths should match. This also\n\t// avoids us needing to check both attributes sets, since if A has any keys\n\t// which do not exist in B, we know the sets to be different.\n\tif ( actual.length !== expected.length ) {\n\t\tlogger.warning(\n\t\t\t'Expected attributes %o, instead saw %o.',\n\t\t\texpected,\n\t\t\tactual\n\t\t);\n\t\treturn false;\n\t}\n\n\t// Attributes are not guaranteed to occur in the same order. For validating\n\t// actual attributes, first convert the set of expected attribute values to\n\t// an object, for lookup by key.\n\tconst expectedAttributes = {};\n\tfor ( let i = 0; i < expected.length; i++ ) {\n\t\texpectedAttributes[ expected[ i ][ 0 ].toLowerCase() ] =\n\t\t\texpected[ i ][ 1 ];\n\t}\n\n\tfor ( let i = 0; i < actual.length; i++ ) {\n\t\tconst [ name, actualValue ] = actual[ i ];\n\t\tconst nameLower = name.toLowerCase();\n\n\t\t// As noted above, if missing member in B, assume different.\n\t\tif ( ! expectedAttributes.hasOwnProperty( nameLower ) ) {\n\t\t\tlogger.warning( 'Encountered unexpected attribute `%s`.', name );\n\t\t\treturn false;\n\t\t}\n\n\t\tconst expectedValue = expectedAttributes[ nameLower ];\n\t\tconst isEqualAttributes = isEqualAttributesOfName[ nameLower ];\n\n\t\tif ( isEqualAttributes ) {\n\t\t\t// Defer custom attribute equality handling.\n\t\t\tif ( ! isEqualAttributes( actualValue, expectedValue ) ) {\n\t\t\t\tlogger.warning(\n\t\t\t\t\t'Expected attribute `%s` of value `%s`, saw `%s`.',\n\t\t\t\t\tname,\n\t\t\t\t\texpectedValue,\n\t\t\t\t\tactualValue\n\t\t\t\t);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else if ( actualValue !== expectedValue ) {\n\t\t\t// Otherwise strict inequality should bail.\n\t\t\tlogger.warning(\n\t\t\t\t'Expected attribute `%s` of value `%s`, saw `%s`.',\n\t\t\t\tname,\n\t\t\t\texpectedValue,\n\t\t\t\tactualValue\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Token-type-specific equality handlers\n *\n * @type {Object}\n */\nexport const isEqualTokensOfType = {\n\tStartTag: ( actual, expected, logger = createLogger() ) => {\n\t\tif (\n\t\t\tactual.tagName !== expected.tagName &&\n\t\t\t// Optimization: Use short-circuit evaluation to defer case-\n\t\t\t// insensitive check on the assumption that the majority case will\n\t\t\t// have exactly equal tag names.\n\t\t\tactual.tagName.toLowerCase() !== expected.tagName.toLowerCase()\n\t\t) {\n\t\t\tlogger.warning(\n\t\t\t\t'Expected tag name `%s`, instead saw `%s`.',\n\t\t\t\texpected.tagName,\n\t\t\t\tactual.tagName\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn isEqualTagAttributePairs(\n\t\t\t...[ actual, expected ].map( getMeaningfulAttributePairs ),\n\t\t\tlogger\n\t\t);\n\t},\n\tChars: isEquivalentTextTokens,\n\tComment: isEquivalentTextTokens,\n};\n\n/**\n * Given an array of tokens, returns the first token which is not purely\n * whitespace.\n *\n * Mutates the tokens array.\n *\n * @param {Object[]} tokens Set of tokens to search.\n *\n * @return {Object | undefined} Next non-whitespace token.\n */\nexport function getNextNonWhitespaceToken( tokens ) {\n\tlet token;\n\twhile ( ( token = tokens.shift() ) ) {\n\t\tif ( token.type !== 'Chars' ) {\n\t\t\treturn token;\n\t\t}\n\n\t\tif ( ! REGEXP_ONLY_WHITESPACE.test( token.chars ) ) {\n\t\t\treturn token;\n\t\t}\n\t}\n}\n\n/**\n * Tokenize an HTML string, gracefully handling any errors thrown during\n * underlying tokenization.\n *\n * @param {string} html   HTML string to tokenize.\n * @param {Object} logger Validation logger object.\n *\n * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error\n */\nfunction getHTMLTokens( html, logger = createLogger() ) {\n\ttry {\n\t\treturn new Tokenizer( new DecodeEntityParser() ).tokenize( html );\n\t} catch ( e ) {\n\t\tlogger.warning( 'Malformed HTML detected: %s', html );\n\t}\n\n\treturn null;\n}\n\n/**\n * Returns true if the next HTML token closes the current token.\n *\n * @param {Object}           currentToken Current token to compare with.\n * @param {Object|undefined} nextToken    Next token to compare against.\n *\n * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise\n */\nexport function isClosedByToken( currentToken, nextToken ) {\n\t// Ensure this is a self closed token.\n\tif ( ! currentToken.selfClosing ) {\n\t\treturn false;\n\t}\n\n\t// Check token names and determine if nextToken is the closing tag for currentToken.\n\tif (\n\t\tnextToken &&\n\t\tnextToken.tagName === currentToken.tagName &&\n\t\tnextToken.type === 'EndTag'\n\t) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Returns true if the given HTML strings are effectively equivalent, or\n * false otherwise. Invalid HTML is not considered equivalent, even if the\n * strings directly match.\n *\n * @param {string} actual   Actual HTML string.\n * @param {string} expected Expected HTML string.\n * @param {Object} logger   Validation logger object.\n *\n * @return {boolean} Whether HTML strings are equivalent.\n */\nexport function isEquivalentHTML( actual, expected, logger = createLogger() ) {\n\t// Short-circuit if markup is identical.\n\tif ( actual === expected ) {\n\t\treturn true;\n\t}\n\n\t// Tokenize input content and reserialized save content.\n\tconst [ actualTokens, expectedTokens ] = [ actual, expected ].map(\n\t\t( html ) => getHTMLTokens( html, logger )\n\t);\n\n\t// If either is malformed then stop comparing - the strings are not equivalent.\n\tif ( ! actualTokens || ! expectedTokens ) {\n\t\treturn false;\n\t}\n\n\tlet actualToken, expectedToken;\n\twhile ( ( actualToken = getNextNonWhitespaceToken( actualTokens ) ) ) {\n\t\texpectedToken = getNextNonWhitespaceToken( expectedTokens );\n\n\t\t// Inequal if exhausted all expected tokens.\n\t\tif ( ! expectedToken ) {\n\t\t\tlogger.warning(\n\t\t\t\t'Expected end of content, instead saw %o.',\n\t\t\t\tactualToken\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\n\t\t// Inequal if next non-whitespace token of each set are not same type.\n\t\tif ( actualToken.type !== expectedToken.type ) {\n\t\t\tlogger.warning(\n\t\t\t\t'Expected token of type `%s` (%o), instead saw `%s` (%o).',\n\t\t\t\texpectedToken.type,\n\t\t\t\texpectedToken,\n\t\t\t\tactualToken.type,\n\t\t\t\tactualToken\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\n\t\t// Defer custom token type equality handling, otherwise continue and\n\t\t// assume as equal.\n\t\tconst isEqualTokens = isEqualTokensOfType[ actualToken.type ];\n\t\tif (\n\t\t\tisEqualTokens &&\n\t\t\t! isEqualTokens( actualToken, expectedToken, logger )\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Peek at the next tokens (actual and expected) to see if they close\n\t\t// a self-closing tag.\n\t\tif ( isClosedByToken( actualToken, expectedTokens[ 0 ] ) ) {\n\t\t\t// Consume the next expected token that closes the current actual\n\t\t\t// self-closing token.\n\t\t\tgetNextNonWhitespaceToken( expectedTokens );\n\t\t} else if ( isClosedByToken( expectedToken, actualTokens[ 0 ] ) ) {\n\t\t\t// Consume the next actual token that closes the current expected\n\t\t\t// self-closing token.\n\t\t\tgetNextNonWhitespaceToken( actualTokens );\n\t\t}\n\t}\n\n\tif ( ( expectedToken = getNextNonWhitespaceToken( expectedTokens ) ) ) {\n\t\t// If any non-whitespace tokens remain in expected token set, this\n\t\t// indicates inequality.\n\t\tlogger.warning(\n\t\t\t'Expected %o, instead saw end of content.',\n\t\t\texpectedToken\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Returns an object with `isValid` property set to `true` if the parsed block\n * is valid given the input content. A block is considered valid if, when serialized\n * with assumed attributes, the content matches the original value. If block is\n * invalid, this function returns all validations issues as well.\n *\n * @param {string|Object} blockTypeOrName      Block type.\n * @param {Object}        attributes           Parsed block attributes.\n * @param {string}        originalBlockContent Original block content.\n * @param {Object}        logger               Validation logger object.\n *\n * @return {Object} Whether block is valid and contains validation messages.\n */\n\n/**\n * Returns an object with `isValid` property set to `true` if the parsed block\n * is valid given the input content. A block is considered valid if, when serialized\n * with assumed attributes, the content matches the original value. If block is\n * invalid, this function returns all validations issues as well.\n *\n * @param {WPBlock}            block                          block object.\n * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.\n *\n * @return {[boolean,Array<LoggerItem>]} validation results.\n */\nexport function validateBlock( block, blockTypeOrName = block.name ) {\n\tconst isFallbackBlock =\n\t\tblock.name === getFreeformContentHandlerName() ||\n\t\tblock.name === getUnregisteredTypeHandlerName();\n\n\t// Shortcut to avoid costly validation.\n\tif ( isFallbackBlock ) {\n\t\treturn [ true, [] ];\n\t}\n\n\tconst logger = createQueuedLogger();\n\tconst blockType = normalizeBlockType( blockTypeOrName );\n\tlet generatedBlockContent;\n\ttry {\n\t\tgeneratedBlockContent = getSaveContent( blockType, block.attributes );\n\t} catch ( error ) {\n\t\tlogger.error(\n\t\t\t'Block validation failed because an error occurred while generating block content:\\n\\n%s',\n\t\t\terror.toString()\n\t\t);\n\n\t\treturn [ false, logger.getItems() ];\n\t}\n\n\tconst isValid = isEquivalentHTML(\n\t\tblock.originalContent,\n\t\tgeneratedBlockContent,\n\t\tlogger\n\t);\n\n\tif ( ! isValid ) {\n\t\tlogger.error(\n\t\t\t'Block validation failed for `%s` (%o).\\n\\nContent generated by `save` function:\\n\\n%s\\n\\nContent retrieved from post body:\\n\\n%s',\n\t\t\tblockType.name,\n\t\t\tblockType,\n\t\t\tgeneratedBlockContent,\n\t\t\tblock.originalContent\n\t\t);\n\t}\n\n\treturn [ isValid, logger.getItems() ];\n}\n\n/**\n * Returns true if the parsed block is valid given the input content. A block\n * is considered valid if, when serialized with assumed attributes, the content\n * matches the original value.\n *\n * Logs to console in development environments when invalid.\n *\n * @deprecated Use validateBlock instead to avoid data loss.\n *\n * @param {string|Object} blockTypeOrName      Block type.\n * @param {Object}        attributes           Parsed block attributes.\n * @param {string}        originalBlockContent Original block content.\n *\n * @return {boolean} Whether block is valid.\n */\nexport function isValidBlockContent(\n\tblockTypeOrName,\n\tattributes,\n\toriginalBlockContent\n) {\n\tdeprecated( 'isValidBlockContent introduces opportunity for data loss', {\n\t\tsince: '12.6',\n\t\tplugin: 'Gutenberg',\n\t\talternative: 'validateBlock',\n\t} );\n\n\tconst blockType = normalizeBlockType( blockTypeOrName );\n\tconst block = {\n\t\tname: blockType.name,\n\t\tattributes,\n\t\tinnerBlocks: [],\n\t\toriginalContent: originalBlockContent,\n\t};\n\tconst [ isValid ] = validateBlock( block, blockType );\n\n\treturn isValid;\n}\n"],
  "mappings": ";AAGA,SAAS,iBAAiB;AAC1B,OAAO,mBAAmB;AAK1B,OAAO,gBAAgB;AACvB,SAAS,sBAAsB;AAK/B,SAAS,cAAc,0BAA0B;AACjD,SAAS,sBAAsB;AAC/B;AAAA,EACC;AAAA,EACA;AAAA,OACM;AACP,SAAS,0BAA0B;AAMnC,IAAM,WAAW,CAAE,MAAO;AAO1B,IAAM,oBAAoB;AAO1B,IAAM,yBAAyB;AAO/B,IAAM,wBAAwB;AAiB9B,IAAM,qBAAqB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAkBA,IAAM,wBAAwB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAQA,IAAM,wBAAwB;AAAA,EAC7B,GAAG;AAAA,EACH,GAAG;AACJ;AASA,IAAM,sBAAsB,CAAE,UAAU,8BAA+B;AAwBvE,IAAM,mCAAmC;AAYzC,IAAM,qCAAqC;AAc3C,IAAM,yCAAyC;AAUxC,SAAS,0BAA2B,MAAO;AACjD,SACC,iCAAiC,KAAM,IAAK,KAC5C,mCAAmC,KAAM,IAAK,KAC9C,uCAAuC,KAAM,IAAK;AAEpD;AASO,IAAM,qBAAN,MAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/B,MAAO,QAAS;AACf,QAAK,0BAA2B,MAAO,GAAI;AAC1C,aAAO,eAAgB,MAAM,SAAS,GAAI;AAAA,IAC3C;AAAA,EACD;AACD;AAUO,SAAS,+BAAgC,MAAO;AACtD,SAAO,KAAK,KAAK,EAAE,MAAO,iBAAkB;AAC7C;AAUO,SAAS,+BAAgC,MAAO;AAKtD,SAAO,+BAAgC,IAAK,EAAE,KAAM,GAAI;AACzD;AAaO,SAAS,4BAA6B,OAAQ;AACpD,SAAO,MAAM,WAAW,OAAQ,CAAE,SAAU;AAC3C,UAAM,CAAE,KAAK,KAAM,IAAI;AACvB,WACC,SACA,IAAI,QAAS,OAAQ,MAAM,KAC3B,sBAAsB,SAAU,GAAI;AAAA,EAEtC,CAAE;AACH;AAYO,SAAS,uBACf,QACA,UACA,SAAS,aAAa,GACrB;AAKD,MAAI,cAAc,OAAO;AACzB,MAAI,gBAAgB,SAAS;AAE7B,WAAU,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAM;AACtD,UAAM,YAAY,oBAAqB,CAAE;AAEzC,kBAAc,UAAW,WAAY;AACrC,oBAAgB,UAAW,aAAc;AAEzC,QAAK,gBAAgB,eAAgB;AACpC,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA,SAAS;AAAA,IACT,OAAO;AAAA,EACR;AAEA,SAAO;AACR;AAUO,SAAS,oBAAqB,OAAQ;AAC5C,MAAK,MAAM,WAAY,KAAM,GAAI;AAChC,WAAO;AAAA,EACR;AAEA,MAAK,MAAM,QAAS,GAAI,MAAM,GAAI;AACjC,WAAO,MAAM;AAAA,EACd;AAEA,SAAO;AACR;AAUO,SAAS,wBAAyB,OAAQ;AAChD,QAAM,aAAa,+BAAgC,KAAM;AACzD,QAAM,mBAAmB,WAAW,IAAK,mBAAoB;AAC7D,QAAM,SAAS,iBAAiB,KAAM,GAAI;AAE1C,SACC,OAEE,QAAS,uBAAuB,SAAU;AAE9C;AASO,SAAS,mBAAoB,MAAO;AAC1C,QAAM,QAAQ,KAEZ,QAAS,UAAU,EAAG,EAEtB,MAAO,GAAI,EAEX,IAAK,CAAE,UAAW;AAElB,UAAM,CAAE,KAAK,GAAG,UAAW,IAAI,MAAM,MAAO,GAAI;AAChD,UAAM,QAAQ,WAAW,KAAM,GAAI;AAEnC,WAAO,CAAE,IAAI,KAAK,GAAG,wBAAyB,MAAM,KAAK,CAAE,CAAE;AAAA,EAC9D,CAAE;AAEH,SAAO,OAAO,YAAa,KAAM;AAClC;AAOO,IAAM,0BAA0B;AAAA,EACtC,OAAO,CAAE,QAAQ,aAAc;AAG9B,UAAM,CAAE,cAAc,cAAe,IAAI,CAAE,QAAQ,QAAS,EAAE;AAAA,MAC7D;AAAA,IACD;AACA,UAAM,aAAa,aAAa;AAAA,MAC/B,CAAE,MAAO,CAAE,eAAe,SAAU,CAAE;AAAA,IACvC;AACA,UAAM,eAAe,eAAe;AAAA,MACnC,CAAE,MAAO,CAAE,aAAa,SAAU,CAAE;AAAA,IACrC;AAEA,WAAO,WAAW,WAAW,KAAK,aAAa,WAAW;AAAA,EAC3D;AAAA,EACA,OAAO,CAAE,QAAQ,aAAc;AAC9B,WAAO;AAAA,MACN,GAAG,CAAE,QAAQ,QAAS,EAAE,IAAK,kBAAmB;AAAA,IACjD;AAAA,EACD;AAAA;AAAA;AAAA,EAGA,GAAG,OAAO;AAAA,IACT,mBAAmB,IAAK,CAAE,cAAe,CAAE,WAAW,MAAM,IAAK,CAAE;AAAA,EACpE;AACD;AAYO,SAAS,yBACf,QACA,UACA,SAAS,aAAa,GACrB;AAID,MAAK,OAAO,WAAW,SAAS,QAAS;AACxC,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAKA,QAAM,qBAAqB,CAAC;AAC5B,WAAU,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAM;AAC3C,uBAAoB,SAAU,CAAE,EAAG,CAAE,EAAE,YAAY,CAAE,IACpD,SAAU,CAAE,EAAG,CAAE;AAAA,EACnB;AAEA,WAAU,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAM;AACzC,UAAM,CAAE,MAAM,WAAY,IAAI,OAAQ,CAAE;AACxC,UAAM,YAAY,KAAK,YAAY;AAGnC,QAAK,CAAE,mBAAmB,eAAgB,SAAU,GAAI;AACvD,aAAO,QAAS,0CAA0C,IAAK;AAC/D,aAAO;AAAA,IACR;AAEA,UAAM,gBAAgB,mBAAoB,SAAU;AACpD,UAAM,oBAAoB,wBAAyB,SAAU;AAE7D,QAAK,mBAAoB;AAExB,UAAK,CAAE,kBAAmB,aAAa,aAAc,GAAI;AACxD,eAAO;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,eAAO;AAAA,MACR;AAAA,IACD,WAAY,gBAAgB,eAAgB;AAE3C,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAOO,IAAM,sBAAsB;AAAA,EAClC,UAAU,CAAE,QAAQ,UAAU,SAAS,aAAa,MAAO;AAC1D,QACC,OAAO,YAAY,SAAS;AAAA;AAAA;AAAA,IAI5B,OAAO,QAAQ,YAAY,MAAM,SAAS,QAAQ,YAAY,GAC7D;AACD,aAAO;AAAA,QACN;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,MACN,GAAG,CAAE,QAAQ,QAAS,EAAE,IAAK,2BAA4B;AAAA,MACzD;AAAA,IACD;AAAA,EACD;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AACV;AAYO,SAAS,0BAA2B,QAAS;AACnD,MAAI;AACJ,SAAU,QAAQ,OAAO,MAAM,GAAM;AACpC,QAAK,MAAM,SAAS,SAAU;AAC7B,aAAO;AAAA,IACR;AAEA,QAAK,CAAE,uBAAuB,KAAM,MAAM,KAAM,GAAI;AACnD,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAWA,SAAS,cAAe,MAAM,SAAS,aAAa,GAAI;AACvD,MAAI;AACH,WAAO,IAAI,UAAW,IAAI,mBAAmB,CAAE,EAAE,SAAU,IAAK;AAAA,EACjE,SAAU,GAAI;AACb,WAAO,QAAS,+BAA+B,IAAK;AAAA,EACrD;AAEA,SAAO;AACR;AAUO,SAAS,gBAAiB,cAAc,WAAY;AAE1D,MAAK,CAAE,aAAa,aAAc;AACjC,WAAO;AAAA,EACR;AAGA,MACC,aACA,UAAU,YAAY,aAAa,WACnC,UAAU,SAAS,UAClB;AACD,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AAaO,SAAS,iBAAkB,QAAQ,UAAU,SAAS,aAAa,GAAI;AAE7E,MAAK,WAAW,UAAW;AAC1B,WAAO;AAAA,EACR;AAGA,QAAM,CAAE,cAAc,cAAe,IAAI,CAAE,QAAQ,QAAS,EAAE;AAAA,IAC7D,CAAE,SAAU,cAAe,MAAM,MAAO;AAAA,EACzC;AAGA,MAAK,CAAE,gBAAgB,CAAE,gBAAiB;AACzC,WAAO;AAAA,EACR;AAEA,MAAI,aAAa;AACjB,SAAU,cAAc,0BAA2B,YAAa,GAAM;AACrE,oBAAgB,0BAA2B,cAAe;AAG1D,QAAK,CAAE,eAAgB;AACtB,aAAO;AAAA,QACN;AAAA,QACA;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAGA,QAAK,YAAY,SAAS,cAAc,MAAO;AAC9C,aAAO;AAAA,QACN;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAIA,UAAM,gBAAgB,oBAAqB,YAAY,IAAK;AAC5D,QACC,iBACA,CAAE,cAAe,aAAa,eAAe,MAAO,GACnD;AACD,aAAO;AAAA,IACR;AAIA,QAAK,gBAAiB,aAAa,eAAgB,CAAE,CAAE,GAAI;AAG1D,gCAA2B,cAAe;AAAA,IAC3C,WAAY,gBAAiB,eAAe,aAAc,CAAE,CAAE,GAAI;AAGjE,gCAA2B,YAAa;AAAA,IACzC;AAAA,EACD;AAEA,MAAO,gBAAgB,0BAA2B,cAAe,GAAM;AAGtE,WAAO;AAAA,MACN;AAAA,MACA;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AA2BO,SAAS,cAAe,OAAO,kBAAkB,MAAM,MAAO;AACpE,QAAM,kBACL,MAAM,SAAS,8BAA8B,KAC7C,MAAM,SAAS,+BAA+B;AAG/C,MAAK,iBAAkB;AACtB,WAAO,CAAE,MAAM,CAAC,CAAE;AAAA,EACnB;AAEA,QAAM,SAAS,mBAAmB;AAClC,QAAM,YAAY,mBAAoB,eAAgB;AACtD,MAAI;AACJ,MAAI;AACH,4BAAwB,eAAgB,WAAW,MAAM,UAAW;AAAA,EACrE,SAAU,OAAQ;AACjB,WAAO;AAAA,MACN;AAAA,MACA,MAAM,SAAS;AAAA,IAChB;AAEA,WAAO,CAAE,OAAO,OAAO,SAAS,CAAE;AAAA,EACnC;AAEA,QAAM,UAAU;AAAA,IACf,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACD;AAEA,MAAK,CAAE,SAAU;AAChB,WAAO;AAAA,MACN;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACP;AAAA,EACD;AAEA,SAAO,CAAE,SAAS,OAAO,SAAS,CAAE;AACrC;AAiBO,SAAS,oBACf,iBACA,YACA,sBACC;AACD,aAAY,4DAA4D;AAAA,IACvE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,aAAa;AAAA,EACd,CAAE;AAEF,QAAM,YAAY,mBAAoB,eAAgB;AACtD,QAAM,QAAQ;AAAA,IACb,MAAM,UAAU;AAAA,IAChB;AAAA,IACA,aAAa,CAAC;AAAA,IACd,iBAAiB;AAAA,EAClB;AACA,QAAM,CAAE,OAAQ,IAAI,cAAe,OAAO,SAAU;AAEpD,SAAO;AACR;",
  "names": []
}
