diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/js/dist/block-serialization-default-parser.js --- a/wp/wp-includes/js/dist/block-serialization-default-parser.js Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/js/dist/block-serialization-default-parser.js Fri Sep 05 18:40:08 2025 +0200 @@ -1,47 +1,90 @@ -/******/ (function() { // webpackBootstrap +/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ -/******/ !function() { +/******/ (() => { /******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = function(exports, definition) { +/******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; -/******/ }(); +/******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ !function() { -/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -/******/ }(); +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ -/******/ !function() { +/******/ (() => { /******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { +/******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; -/******/ }(); +/******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "parse": function() { return /* binding */ parse; } +/* harmony export */ parse: () => (/* binding */ parse) /* harmony export */ }); +/** + * @type {string} + */ let document; +/** + * @type {number} + */ let offset; +/** + * @type {ParsedBlock[]} + */ let output; +/** + * @type {ParsedFrame[]} + */ let stack; + +/** + * @typedef {Object|null} Attributes + */ + +/** + * @typedef {Object} ParsedBlock + * @property {string|null} blockName Block name. + * @property {Attributes} attrs Block attributes. + * @property {ParsedBlock[]} innerBlocks Inner blocks. + * @property {string} innerHTML Inner HTML. + * @property {Array} innerContent Inner content. + */ + +/** + * @typedef {Object} ParsedFrame + * @property {ParsedBlock} block Block. + * @property {number} tokenStart Token start. + * @property {number} tokenLength Token length. + * @property {number} prevOffset Previous offset. + * @property {number|null} leadingHtmlStart Leading HTML start. + */ + +/** + * @typedef {'no-more-tokens'|'void-block'|'block-opener'|'block-closer'} TokenType + */ + +/** + * @typedef {[TokenType, string, Attributes, number, number]} Token + */ + /** * Matches block comment delimiters * @@ -83,9 +126,18 @@ * @since 3.8.0 * @since 4.6.1 added optimization to prevent backtracking on attribute parsing */ - const tokenizer = /)[^])*)\5|[^]*?)}\s+)?(\/)?-->/g; +/** + * Constructs a block object. + * + * @param {string|null} blockName + * @param {Attributes} attrs + * @param {ParsedBlock[]} innerBlocks + * @param {string} innerHTML + * @param {string[]} innerContent + * @return {ParsedBlock} The block object. + */ function Block(blockName, attrs, innerBlocks, innerHTML, innerContent) { return { blockName, @@ -96,10 +148,26 @@ }; } +/** + * Constructs a freeform block object. + * + * @param {string} innerHTML + * @return {ParsedBlock} The freeform block object. + */ function Freeform(innerHTML) { return Block(null, {}, [], innerHTML, [innerHTML]); } +/** + * Constructs a frame object. + * + * @param {ParsedBlock} block + * @param {number} tokenStart + * @param {number} tokenLength + * @param {number} prevOffset + * @param {number|null} leadingHtmlStart + * @return {ParsedFrame} The frame object. + */ function Frame(block, tokenStart, tokenLength, prevOffset, leadingHtmlStart) { return { block, @@ -109,6 +177,7 @@ leadingHtmlStart }; } + /** * Parser function, that converts input HTML into a block based structure. * @@ -184,58 +253,59 @@ * } * ]; * ``` - * @return {Array} A block-based representation of the input HTML. + * @return {ParsedBlock[]} A block-based representation of the input HTML. */ - - const parse = doc => { document = doc; offset = 0; output = []; stack = []; tokenizer.lastIndex = 0; - - do {// twiddle our thumbs + do { + // twiddle our thumbs } while (proceed()); - return output; }; +/** + * Parses the next token in the input document. + * + * @return {boolean} Returns true when there is more tokens to parse. + */ function proceed() { + const stackDepth = stack.length; const next = nextToken(); const [tokenType, blockName, attrs, startOffset, tokenLength] = next; - const stackDepth = stack.length; // We may have some HTML soup before the next block. + // We may have some HTML soup before the next block. const leadingHtmlStart = startOffset > offset ? offset : null; - switch (tokenType) { case 'no-more-tokens': // If not in a block then flush output. if (0 === stackDepth) { addFreeform(); return false; - } // Otherwise we have a problem + } + + // Otherwise we have a problem // This is an error // we have options // - treat it all as freeform text // - assume an implicit closer (easiest when not nesting) + // For the easy case we'll assume an implicit closer. - - if (1 === stackDepth) { addBlockFromStack(); return false; - } // For the nested case where it's more difficult we'll + } + + // For the nested case where it's more difficult we'll // have to assume that multiple closers are missing // and so we'll collapse the whole stack piecewise. - - while (0 < stack.length) { addBlockFromStack(); } - return false; - case 'void-block': // easy case is if we stumbled upon a void block // in the top-level of the document. @@ -243,23 +313,20 @@ if (null !== leadingHtmlStart) { output.push(Freeform(document.substr(leadingHtmlStart, startOffset - leadingHtmlStart))); } - output.push(Block(blockName, attrs, [], '', [])); offset = startOffset + tokenLength; return true; - } // Otherwise we found an inner block. + } - + // Otherwise we found an inner block. addInnerBlock(Block(blockName, attrs, [], '', []), startOffset, tokenLength); offset = startOffset + tokenLength; return true; - case 'block-opener': // Track all newly-opened blocks on the stack. stack.push(Frame(Block(blockName, attrs, [], '', []), startOffset, tokenLength, startOffset + tokenLength, leadingHtmlStart)); offset = startOffset + tokenLength; return true; - case 'block-closer': // If we're missing an opener we're in trouble // This is an error. @@ -270,18 +337,18 @@ // - give up and close out the document. addFreeform(); return false; - } // If we're not nesting then this is easy - close the block. + } - + // If we're not nesting then this is easy - close the block. if (1 === stackDepth) { addBlockFromStack(startOffset); offset = startOffset + tokenLength; return true; - } // Otherwise we're nested and we have to close out the current - // block and add it as a innerBlock to the parent. + } - - const stackTop = stack.pop(); + // Otherwise we're nested and we have to close out the current + // block and add it as a innerBlock to the parent. + const stackTop = /** @type {ParsedFrame} */stack.pop(); const html = document.substr(stackTop.prevOffset, startOffset - stackTop.prevOffset); stackTop.block.innerHTML += html; stackTop.block.innerContent.push(html); @@ -289,13 +356,13 @@ addInnerBlock(stackTop.block, stackTop.tokenStart, stackTop.tokenLength, startOffset + tokenLength); offset = startOffset + tokenLength; return true; - default: // This is an error. addFreeform(); return false; } } + /** * Parse JSON if valid, otherwise return null * @@ -306,8 +373,6 @@ * @param {string} input JSON input string to parse * @return {Object|null} parsed JSON if valid */ - - function parseJSON(input) { try { return JSON.parse(input); @@ -316,6 +381,11 @@ } } +/** + * Finds the next token in the document. + * + * @return {Token} The next matched token. + */ function nextToken() { // Aye the magic // we're using a single RegExp to tokenize the block comment delimiters @@ -323,82 +393,90 @@ // block opener and a block closer is the leading `/` before `wp:` (and // a closer has no attributes). we can trap them both and process the // match back in JavaScript to see which one it was. - const matches = tokenizer.exec(document); // We have no more tokens. + const matches = tokenizer.exec(document); + // We have no more tokens. if (null === matches) { - return ['no-more-tokens']; + return ['no-more-tokens', '', null, 0, 0]; } - const startedAt = matches.index; - const [match, closerMatch, namespaceMatch, nameMatch, attrsMatch - /* Internal/unused. */ - ,, voidMatch] = matches; + const [match, closerMatch, namespaceMatch, nameMatch, attrsMatch /* Internal/unused. */,, voidMatch] = matches; const length = match.length; const isCloser = !!closerMatch; const isVoid = !!voidMatch; const namespace = namespaceMatch || 'core/'; const name = namespace + nameMatch; const hasAttrs = !!attrsMatch; - const attrs = hasAttrs ? parseJSON(attrsMatch) : {}; // This state isn't allowed + const attrs = hasAttrs ? parseJSON(attrsMatch) : {}; + + // This state isn't allowed // This is an error. - - if (isCloser && (isVoid || hasAttrs)) {// We can ignore them since they don't hurt anything + if (isCloser && (isVoid || hasAttrs)) { + // We can ignore them since they don't hurt anything // we may warn against this at some point or reject it. } - if (isVoid) { return ['void-block', name, attrs, startedAt, length]; } - if (isCloser) { return ['block-closer', name, null, startedAt, length]; } - return ['block-opener', name, attrs, startedAt, length]; } +/** + * Adds a freeform block to the output. + * + * @param {number} [rawLength] + */ function addFreeform(rawLength) { const length = rawLength ? rawLength : document.length - offset; - if (0 === length) { return; } - output.push(Freeform(document.substr(offset, length))); } +/** + * Adds inner block to the parent block. + * + * @param {ParsedBlock} block + * @param {number} tokenStart + * @param {number} tokenLength + * @param {number} [lastOffset] + */ function addInnerBlock(block, tokenStart, tokenLength, lastOffset) { const parent = stack[stack.length - 1]; parent.block.innerBlocks.push(block); const html = document.substr(parent.prevOffset, tokenStart - parent.prevOffset); - if (html) { parent.block.innerHTML += html; parent.block.innerContent.push(html); } - parent.block.innerContent.push(null); parent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength; } +/** + * Adds block from the stack to the output. + * + * @param {number} [endOffset] + */ function addBlockFromStack(endOffset) { const { block, leadingHtmlStart, prevOffset, tokenStart - } = stack.pop(); + } = /** @type {ParsedFrame} */stack.pop(); const html = endOffset ? document.substr(prevOffset, endOffset - prevOffset) : document.substr(prevOffset); - if (html) { block.innerHTML += html; block.innerContent.push(html); } - if (null !== leadingHtmlStart) { output.push(Freeform(document.substr(leadingHtmlStart, tokenStart - leadingHtmlStart))); } - output.push(block); }