--- 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<string|null>} 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 = /<!--\s+(\/)?wp:([a-z][a-z0-9_-]*\/)?([a-z][a-z0-9_-]*)\s+({(?:(?=([^}]+|}+(?=})|(?!}\s+\/?-->)[^])*)\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);
}