← All changes
|
build/block-serialization-default-parser/index.js
+148
-39
12.6.0
→
14.5.2
View file →
| @@ -1,5 +1,5 @@ | ||
| 1 | -/******/ (function() { // webpackBootstrap | |
| 1 | +/******/ (() => { // webpackBootstrap | |
| 2 | 2 | /******/ "use strict"; |
| 3 | 3 | /******/ // The require scope |
| 4 | 4 | /******/ var __webpack_require__ = {}; |
| 5 | 5 | /******/ |
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | /******/ var __webpack_require__ = {}; |
| 5 | 5 | /******/ |
| 6 | 6 | /************************************************************************/ |
| 7 | 7 | /******/ /* webpack/runtime/define property getters */ |
| 8 | -/******/ !function() { | |
| 8 | +/******/ (() => { | |
| 9 | 9 | /******/ // define getter functions for harmony exports |
| 10 | -/******/ __webpack_require__.d = function(exports, definition) { | |
| 10 | +/******/ __webpack_require__.d = (exports, definition) => { | |
| 11 | 11 | /******/ for(var key in definition) { |
| 12 | 12 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { |
| 13 | 13 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); |
| 14 | 14 | /******/ } |
| @@ -13,37 +13,82 @@ | ||
| 13 | 13 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); |
| 14 | 14 | /******/ } |
| 15 | 15 | /******/ } |
| 16 | 16 | /******/ }; |
| 17 | -/******/ }(); | |
| 17 | +/******/ })(); | |
| 18 | 18 | /******/ |
| 19 | 19 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ |
| 20 | -/******/ !function() { | |
| 21 | -/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } | |
| 22 | -/******/ }(); | |
| 20 | +/******/ (() => { | |
| 21 | +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) | |
| 22 | +/******/ })(); | |
| 23 | 23 | /******/ |
| 24 | 24 | /******/ /* webpack/runtime/make namespace object */ |
| 25 | -/******/ !function() { | |
| 25 | +/******/ (() => { | |
| 26 | 26 | /******/ // define __esModule on exports |
| 27 | -/******/ __webpack_require__.r = function(exports) { | |
| 27 | +/******/ __webpack_require__.r = (exports) => { | |
| 28 | 28 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { |
| 29 | 29 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |
| 30 | 30 | /******/ } |
| 31 | 31 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); |
| 32 | 32 | /******/ }; |
| 33 | -/******/ }(); | |
| 33 | +/******/ })(); | |
| 34 | 34 | /******/ |
| 35 | 35 | /************************************************************************/ |
| 36 | 36 | var __webpack_exports__ = {}; |
| 37 | 37 | __webpack_require__.r(__webpack_exports__); |
| 38 | 38 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { |
| 39 | -/* harmony export */ "parse": function() { return /* binding */ parse; } | |
| 39 | +/* harmony export */ "parse": () => (/* binding */ parse) | |
| 40 | 40 | /* harmony export */ }); |
| 41 | +/** | |
| 42 | + * @type {string} | |
| 43 | + */ | |
| 41 | 44 | let document; |
| 45 | +/** | |
| 46 | + * @type {number} | |
| 47 | + */ | |
| 48 | + | |
| 42 | 49 | let offset; |
| 50 | +/** | |
| 51 | + * @type {ParsedBlock[]} | |
| 52 | + */ | |
| 53 | + | |
| 43 | 54 | let output; |
| 55 | +/** | |
| 56 | + * @type {ParsedFrame[]} | |
| 57 | + */ | |
| 58 | + | |
| 44 | 59 | let stack; |
| 45 | 60 | /** |
| 61 | + * @typedef {Object|null} Attributes | |
| 62 | + */ | |
| 63 | + | |
| 64 | +/** | |
| 65 | + * @typedef {Object} ParsedBlock | |
| 66 | + * @property {string|null} blockName Block name. | |
| 67 | + * @property {Attributes} attrs Block attributes. | |
| 68 | + * @property {ParsedBlock[]} innerBlocks Inner blocks. | |
| 69 | + * @property {string} innerHTML Inner HTML. | |
| 70 | + * @property {Array<string|null>} innerContent Inner content. | |
| 71 | + */ | |
| 72 | + | |
| 73 | +/** | |
| 74 | + * @typedef {Object} ParsedFrame | |
| 75 | + * @property {ParsedBlock} block Block. | |
| 76 | + * @property {number} tokenStart Token start. | |
| 77 | + * @property {number} tokenLength Token length. | |
| 78 | + * @property {number} prevOffset Previous offset. | |
| 79 | + * @property {number|null} leadingHtmlStart Leading HTML start. | |
| 80 | + */ | |
| 81 | + | |
| 82 | +/** | |
| 83 | + * @typedef {'no-more-tokens'|'void-block'|'block-opener'|'block-closer'} TokenType | |
| 84 | + */ | |
| 85 | + | |
| 86 | +/** | |
| 87 | + * @typedef {[TokenType, string, Attributes, number, number]} Token | |
| 88 | + */ | |
| 89 | + | |
| 90 | +/** | |
| 46 | 91 | * Matches block comment delimiters |
| 47 | 92 | * |
| 48 | 93 | * While most of this pattern is straightforward the attribute parsing |
| 49 | 94 | * incorporates a tricks to make sure we don't choke on specific input |
| @@ -84,8 +129,18 @@ | ||
| 84 | 129 | * @since 4.6.1 added optimization to prevent backtracking on attribute parsing |
| 85 | 130 | */ |
| 86 | 131 | |
| 87 | 132 | const tokenizer = /<!--\s+(\/)?wp:([a-z][a-z0-9_-]*\/)?([a-z][a-z0-9_-]*)\s+({(?:(?=([^}]+|}+(?=})|(?!}\s+\/?-->)[^])*)\5|[^]*?)}\s+)?(\/)?-->/g; |
| 133 | +/** | |
| 134 | + * Constructs a block object. | |
| 135 | + * | |
| 136 | + * @param {string|null} blockName | |
| 137 | + * @param {Attributes} attrs | |
| 138 | + * @param {ParsedBlock[]} innerBlocks | |
| 139 | + * @param {string} innerHTML | |
| 140 | + * @param {string[]} innerContent | |
| 141 | + * @return {ParsedBlock} The block object. | |
| 142 | + */ | |
| 88 | 143 | |
| 89 | 144 | function Block(blockName, attrs, innerBlocks, innerHTML, innerContent) { |
| 90 | 145 | return { |
| 91 | 146 | blockName, |
| @@ -94,13 +149,31 @@ | ||
| 94 | 149 | innerHTML, |
| 95 | 150 | innerContent |
| 96 | 151 | }; |
| 97 | 152 | } |
| 153 | +/** | |
| 154 | + * Constructs a freeform block object. | |
| 155 | + * | |
| 156 | + * @param {string} innerHTML | |
| 157 | + * @return {ParsedBlock} The freeform block object. | |
| 158 | + */ | |
| 98 | 159 | |
| 160 | + | |
| 99 | 161 | function Freeform(innerHTML) { |
| 100 | 162 | return Block(null, {}, [], innerHTML, [innerHTML]); |
| 101 | 163 | } |
| 164 | +/** | |
| 165 | + * Constructs a frame object. | |
| 166 | + * | |
| 167 | + * @param {ParsedBlock} block | |
| 168 | + * @param {number} tokenStart | |
| 169 | + * @param {number} tokenLength | |
| 170 | + * @param {number} prevOffset | |
| 171 | + * @param {number|null} leadingHtmlStart | |
| 172 | + * @return {ParsedFrame} The frame object. | |
| 173 | + */ | |
| 102 | 174 | |
| 175 | + | |
| 103 | 176 | function Frame(block, tokenStart, tokenLength, prevOffset, leadingHtmlStart) { |
| 104 | 177 | return { |
| 105 | 178 | block, |
| 106 | 179 | tokenStart, |
| @@ -183,9 +256,9 @@ | ||
| 183 | 256 | * innerHTML: '\n<div class="wp-block-columns has-3-columns">\n\n\n\n</div>\n' |
| 184 | 257 | * } |
| 185 | 258 | * ]; |
| 186 | 259 | * ``` |
| 187 | - * @return {Array} A block-based representation of the input HTML. | |
| 260 | + * @return {ParsedBlock[]} A block-based representation of the input HTML. | |
| 188 | 261 | */ |
| 189 | 262 | |
| 190 | 263 | |
| 191 | 264 | const parse = doc => { |
| @@ -199,19 +272,24 @@ | ||
| 199 | 272 | } while (proceed()); |
| 200 | 273 | |
| 201 | 274 | return output; |
| 202 | 275 | }; |
| 276 | +/** | |
| 277 | + * Parses the next token in the input document. | |
| 278 | + * | |
| 279 | + * @return {boolean} Returns true when there is more tokens to parse. | |
| 280 | + */ | |
| 203 | 281 | |
| 204 | 282 | function proceed() { |
| 283 | + const stackDepth = stack.length; | |
| 205 | 284 | const next = nextToken(); |
| 206 | - const [tokenType, blockName, attrs, startOffset, tokenLength] = next; | |
| 207 | - const stackDepth = stack.length; // we may have some HTML soup before the next block | |
| 285 | + const [tokenType, blockName, attrs, startOffset, tokenLength] = next; // We may have some HTML soup before the next block. | |
| 208 | 286 | |
| 209 | 287 | const leadingHtmlStart = startOffset > offset ? offset : null; |
| 210 | 288 | |
| 211 | 289 | switch (tokenType) { |
| 212 | 290 | case 'no-more-tokens': |
| 213 | - // if not in a block then flush output | |
| 291 | + // If not in a block then flush output. | |
| 214 | 292 | if (0 === stackDepth) { |
| 215 | 293 | addFreeform(); |
| 216 | 294 | return false; |
| 217 | 295 | } // Otherwise we have a problem |
| @@ -218,17 +296,17 @@ | ||
| 218 | 296 | // This is an error |
| 219 | 297 | // we have options |
| 220 | 298 | // - treat it all as freeform text |
| 221 | 299 | // - assume an implicit closer (easiest when not nesting) |
| 222 | - // for the easy case we'll assume an implicit closer | |
| 300 | + // For the easy case we'll assume an implicit closer. | |
| 223 | 301 | |
| 224 | 302 | |
| 225 | 303 | if (1 === stackDepth) { |
| 226 | 304 | addBlockFromStack(); |
| 227 | 305 | return false; |
| 228 | - } // for the nested case where it's more difficult we'll | |
| 306 | + } // For the nested case where it's more difficult we'll | |
| 229 | 307 | // have to assume that multiple closers are missing |
| 230 | - // and so we'll collapse the whole stack piecewise | |
| 308 | + // and so we'll collapse the whole stack piecewise. | |
| 231 | 309 | |
| 232 | 310 | |
| 233 | 311 | while (0 < stack.length) { |
| 234 | 312 | addBlockFromStack(); |
| @@ -237,9 +315,9 @@ | ||
| 237 | 315 | return false; |
| 238 | 316 | |
| 239 | 317 | case 'void-block': |
| 240 | 318 | // easy case is if we stumbled upon a void block |
| 241 | - // in the top-level of the document | |
| 319 | + // in the top-level of the document. | |
| 242 | 320 | if (0 === stackDepth) { |
| 243 | 321 | if (null !== leadingHtmlStart) { |
| 244 | 322 | output.push(Freeform(document.substr(leadingHtmlStart, startOffset - leadingHtmlStart))); |
| 245 | 323 | } |
| @@ -246,9 +324,9 @@ | ||
| 246 | 324 | |
| 247 | 325 | output.push(Block(blockName, attrs, [], '', [])); |
| 248 | 326 | offset = startOffset + tokenLength; |
| 249 | 327 | return true; |
| 250 | - } // otherwise we found an inner block | |
| 328 | + } // Otherwise we found an inner block. | |
| 251 | 329 | |
| 252 | 330 | |
| 253 | 331 | addInnerBlock(Block(blockName, attrs, [], '', []), startOffset, tokenLength); |
| 254 | 332 | offset = startOffset + tokenLength; |
| @@ -254,24 +332,24 @@ | ||
| 254 | 332 | offset = startOffset + tokenLength; |
| 255 | 333 | return true; |
| 256 | 334 | |
| 257 | 335 | case 'block-opener': |
| 258 | - // track all newly-opened blocks on the stack | |
| 336 | + // Track all newly-opened blocks on the stack. | |
| 259 | 337 | stack.push(Frame(Block(blockName, attrs, [], '', []), startOffset, tokenLength, startOffset + tokenLength, leadingHtmlStart)); |
| 260 | 338 | offset = startOffset + tokenLength; |
| 261 | 339 | return true; |
| 262 | 340 | |
| 263 | 341 | case 'block-closer': |
| 264 | - // if we're missing an opener we're in trouble | |
| 265 | - // This is an error | |
| 342 | + // If we're missing an opener we're in trouble | |
| 343 | + // This is an error. | |
| 266 | 344 | if (0 === stackDepth) { |
| 267 | - // we have options | |
| 345 | + // We have options | |
| 268 | 346 | // - assume an implicit opener |
| 269 | 347 | // - assume _this_ is the opener |
| 270 | - // - give up and close out the document | |
| 348 | + // - give up and close out the document. | |
| 271 | 349 | addFreeform(); |
| 272 | 350 | return false; |
| 273 | - } // if we're not nesting then this is easy - close the block | |
| 351 | + } // If we're not nesting then this is easy - close the block. | |
| 274 | 352 | |
| 275 | 353 | |
| 276 | 354 | if (1 === stackDepth) { |
| 277 | 355 | addBlockFromStack(startOffset); |
| @@ -276,13 +354,15 @@ | ||
| 276 | 354 | if (1 === stackDepth) { |
| 277 | 355 | addBlockFromStack(startOffset); |
| 278 | 356 | offset = startOffset + tokenLength; |
| 279 | 357 | return true; |
| 280 | - } // otherwise we're nested and we have to close out the current | |
| 281 | - // block and add it as a innerBlock to the parent | |
| 358 | + } // Otherwise we're nested and we have to close out the current | |
| 359 | + // block and add it as a innerBlock to the parent. | |
| 282 | 360 | |
| 283 | 361 | |
| 284 | - const stackTop = stack.pop(); | |
| 362 | + const stackTop = | |
| 363 | + /** @type {ParsedFrame} */ | |
| 364 | + stack.pop(); | |
| 285 | 365 | const html = document.substr(stackTop.prevOffset, startOffset - stackTop.prevOffset); |
| 286 | 366 | stackTop.block.innerHTML += html; |
| 287 | 367 | stackTop.block.innerContent.push(html); |
| 288 | 368 | stackTop.prevOffset = startOffset + tokenLength; |
| @@ -290,9 +370,9 @@ | ||
| 290 | 370 | offset = startOffset + tokenLength; |
| 291 | 371 | return true; |
| 292 | 372 | |
| 293 | 373 | default: |
| 294 | - // This is an error | |
| 374 | + // This is an error. | |
| 295 | 375 | addFreeform(); |
| 296 | 376 | return false; |
| 297 | 377 | } |
| 298 | 378 | } |
| @@ -314,25 +394,31 @@ | ||
| 314 | 394 | } catch (e) { |
| 315 | 395 | return null; |
| 316 | 396 | } |
| 317 | 397 | } |
| 398 | +/** | |
| 399 | + * Finds the next token in the document. | |
| 400 | + * | |
| 401 | + * @return {Token} The next matched token. | |
| 402 | + */ | |
| 318 | 403 | |
| 404 | + | |
| 319 | 405 | function nextToken() { |
| 320 | - // aye the magic | |
| 406 | + // Aye the magic | |
| 321 | 407 | // we're using a single RegExp to tokenize the block comment delimiters |
| 322 | 408 | // we're also using a trick here because the only difference between a |
| 323 | 409 | // block opener and a block closer is the leading `/` before `wp:` (and |
| 324 | 410 | // a closer has no attributes). we can trap them both and process the |
| 325 | 411 | // match back in JavaScript to see which one it was. |
| 326 | - const matches = tokenizer.exec(document); // we have no more tokens | |
| 412 | + const matches = tokenizer.exec(document); // We have no more tokens. | |
| 327 | 413 | |
| 328 | 414 | if (null === matches) { |
| 329 | - return ['no-more-tokens']; | |
| 415 | + return ['no-more-tokens', '', null, 0, 0]; | |
| 330 | 416 | } |
| 331 | 417 | |
| 332 | 418 | const startedAt = matches.index; |
| 333 | 419 | const [match, closerMatch, namespaceMatch, nameMatch, attrsMatch |
| 334 | - /* internal/unused */ | |
| 420 | + /* Internal/unused. */ | |
| 335 | 421 | ,, voidMatch] = matches; |
| 336 | 422 | const length = match.length; |
| 337 | 423 | const isCloser = !!closerMatch; |
| 338 | 424 | const isVoid = !!voidMatch; |
| @@ -339,12 +425,12 @@ | ||
| 339 | 425 | const namespace = namespaceMatch || 'core/'; |
| 340 | 426 | const name = namespace + nameMatch; |
| 341 | 427 | const hasAttrs = !!attrsMatch; |
| 342 | 428 | const attrs = hasAttrs ? parseJSON(attrsMatch) : {}; // This state isn't allowed |
| 343 | - // This is an error | |
| 429 | + // This is an error. | |
| 344 | 430 | |
| 345 | - if (isCloser && (isVoid || hasAttrs)) {// we can ignore them since they don't hurt anything | |
| 346 | - // we may warn against this at some point or reject it | |
| 431 | + if (isCloser && (isVoid || hasAttrs)) {// We can ignore them since they don't hurt anything | |
| 432 | + // we may warn against this at some point or reject it. | |
| 347 | 433 | } |
| 348 | 434 | |
| 349 | 435 | if (isVoid) { |
| 350 | 436 | return ['void-block', name, attrs, startedAt, length]; |
| @@ -355,9 +441,15 @@ | ||
| 355 | 441 | } |
| 356 | 442 | |
| 357 | 443 | return ['block-opener', name, attrs, startedAt, length]; |
| 358 | 444 | } |
| 445 | +/** | |
| 446 | + * Adds a freeform block to the output. | |
| 447 | + * | |
| 448 | + * @param {number} [rawLength] | |
| 449 | + */ | |
| 359 | 450 | |
| 451 | + | |
| 360 | 452 | function addFreeform(rawLength) { |
| 361 | 453 | const length = rawLength ? rawLength : document.length - offset; |
| 362 | 454 | |
| 363 | 455 | if (0 === length) { |
| @@ -365,9 +457,18 @@ | ||
| 365 | 457 | } |
| 366 | 458 | |
| 367 | 459 | output.push(Freeform(document.substr(offset, length))); |
| 368 | 460 | } |
| 461 | +/** | |
| 462 | + * Adds inner block to the parent block. | |
| 463 | + * | |
| 464 | + * @param {ParsedBlock} block | |
| 465 | + * @param {number} tokenStart | |
| 466 | + * @param {number} tokenLength | |
| 467 | + * @param {number} [lastOffset] | |
| 468 | + */ | |
| 369 | 469 | |
| 470 | + | |
| 370 | 471 | function addInnerBlock(block, tokenStart, tokenLength, lastOffset) { |
| 371 | 472 | const parent = stack[stack.length - 1]; |
| 372 | 473 | parent.block.innerBlocks.push(block); |
| 373 | 474 | const html = document.substr(parent.prevOffset, tokenStart - parent.prevOffset); |
| @@ -379,9 +480,15 @@ | ||
| 379 | 480 | |
| 380 | 481 | parent.block.innerContent.push(null); |
| 381 | 482 | parent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength; |
| 382 | 483 | } |
| 484 | +/** | |
| 485 | + * Adds block from the stack to the output. | |
| 486 | + * | |
| 487 | + * @param {number} [endOffset] | |
| 488 | + */ | |
| 383 | 489 | |
| 490 | + | |
| 384 | 491 | function addBlockFromStack(endOffset) { |
| 385 | 492 | const { |
| 386 | 493 | block, |
| 387 | 494 | leadingHtmlStart, |
| @@ -386,9 +493,11 @@ | ||
| 386 | 493 | block, |
| 387 | 494 | leadingHtmlStart, |
| 388 | 495 | prevOffset, |
| 389 | 496 | tokenStart |
| 390 | - } = stack.pop(); | |
| 497 | + } = | |
| 498 | + /** @type {ParsedFrame} */ | |
| 499 | + stack.pop(); | |
| 391 | 500 | const html = endOffset ? document.substr(prevOffset, endOffset - prevOffset) : document.substr(prevOffset); |
| 392 | 501 | |
| 393 | 502 | if (html) { |
| 394 | 503 | block.innerHTML += html; |
| @@ -400,8 +509,8 @@ | ||
| 400 | 509 | } |
| 401 | 510 | |
| 402 | 511 | output.push(block); |
| 403 | 512 | } |
| 404 | -//# sourceMappingURL=index.js.map | |
| 513 | + | |
| 405 | 514 | (window.wp = window.wp || {}).blockSerializationDefaultParser = __webpack_exports__; |
| 406 | 515 | /******/ })() |
| 407 | 516 | ; |