@wordpress/block-serialization-default-parser
Advanced tools
| export function parse(doc: string): ParsedBlock[]; | ||
| export type Attributes = Object | null; | ||
| export type ParsedBlock = { | ||
| /** | ||
| * Block name. | ||
| */ | ||
| blockName: string | null; | ||
| /** | ||
| * Block attributes. | ||
| */ | ||
| attrs: Attributes; | ||
| /** | ||
| * Inner blocks. | ||
| */ | ||
| innerBlocks: ParsedBlock[]; | ||
| /** | ||
| * Inner HTML. | ||
| */ | ||
| innerHTML: string; | ||
| /** | ||
| * Inner content. | ||
| */ | ||
| innerContent: Array<string | null>; | ||
| }; | ||
| export type ParsedFrame = { | ||
| /** | ||
| * Block. | ||
| */ | ||
| block: ParsedBlock; | ||
| /** | ||
| * Token start. | ||
| */ | ||
| tokenStart: number; | ||
| /** | ||
| * Token length. | ||
| */ | ||
| tokenLength: number; | ||
| /** | ||
| * Previous offset. | ||
| */ | ||
| prevOffset: number; | ||
| /** | ||
| * Leading HTML start. | ||
| */ | ||
| leadingHtmlStart: number | null; | ||
| }; | ||
| export type TokenType = 'void-block' | 'block-opener' | 'block-closer'; | ||
| export type Token = [TokenType, string, Attributes, number, number]; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AA0NO,2BA1EI,MAAM,GAwEL,WAAW,EAAE,CAcxB;yBApNY,MAAM,GAAC,IAAI;;;;;eAKV,MAAM,GAAC,IAAI;;;;WACX,UAAU;;;;iBACV,WAAW,EAAE;;;;eACb,MAAM;;;;kBACN,MAAM,MAAM,GAAC,IAAI,CAAC;;;;;;WAKlB,WAAW;;;;gBACX,MAAM;;;;iBACN,MAAM;;;;gBACN,MAAM;;;;sBACN,MAAM,GAAC,IAAI;;wBAIZ,YAAY,GAAC,cAAc,GAAC,cAAc;oBAI1C,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC"} |
| { | ||
| "extends": "../../tsconfig.base.json", | ||
| "compilerOptions": { | ||
| "rootDir": "src", | ||
| "declarationDir": "build-types" | ||
| }, | ||
| "include": [ "src/**/*" ] | ||
| } |
Sorry, the diff of this file is not supported yet
+140
-29
@@ -0,6 +1,51 @@ | ||
| /** | ||
| * @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 {'void-block'|'block-opener'|'block-closer'} TokenType | ||
| */ | ||
| /** | ||
| * @typedef {[TokenType, string, Attributes, number, number]} Token | ||
| */ | ||
| /** | ||
| * Matches block comment delimiters | ||
@@ -48,2 +93,12 @@ * | ||
| 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. | ||
| */ | ||
@@ -59,7 +114,25 @@ function Block(blockName, attrs, innerBlocks, innerHTML, innerContent) { | ||
| } | ||
| /** | ||
| * 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) { | ||
@@ -149,3 +222,3 @@ return { | ||
| * ``` | ||
| * @return {Array} A block-based representation of the input HTML. | ||
| * @return {ParsedBlock[]} A block-based representation of the input HTML. | ||
| */ | ||
@@ -166,38 +239,45 @@ | ||
| }; | ||
| /** | ||
| * 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. | ||
| const leadingHtmlStart = startOffset > offset ? offset : null; | ||
| if (next === null) { | ||
| // If not in a block then flush output. | ||
| if (0 === stackDepth) { | ||
| addFreeform(); | ||
| return false; | ||
| } // 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. | ||
| 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 | ||
| // 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 | ||
| // have to assume that multiple closers are missing | ||
| // and so we'll collapse the whole stack piecewise. | ||
| if (1 === stackDepth) { | ||
| addBlockFromStack(); | ||
| return false; | ||
| } // 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(); | ||
| } | ||
| while (0 < stack.length) { | ||
| addBlockFromStack(); | ||
| } | ||
| return false; | ||
| } | ||
| return false; | ||
| const [tokenType, blockName, attrs, startOffset, tokenLength] = next; // We may have some HTML soup before the next block. | ||
| const leadingHtmlStart = startOffset > offset ? offset : null; | ||
| switch (tokenType) { | ||
| case 'void-block': | ||
@@ -248,3 +328,5 @@ // easy case is if we stumbled upon a void block | ||
| const stackTop = stack.pop(); | ||
| const stackTop = | ||
| /** @type {ParsedFrame} */ | ||
| stack.pop(); | ||
| const html = document.substr(stackTop.prevOffset, startOffset - stackTop.prevOffset); | ||
@@ -283,3 +365,9 @@ stackTop.block.innerHTML += html; | ||
| } | ||
| /** | ||
| * Finds the next token in the document. | ||
| * | ||
| * @return {Token|null} The next matched token. | ||
| */ | ||
| function nextToken() { | ||
@@ -295,3 +383,3 @@ // Aye the magic | ||
| if (null === matches) { | ||
| return ['no-more-tokens']; | ||
| return null; | ||
| } | ||
@@ -326,3 +414,9 @@ | ||
| } | ||
| /** | ||
| * Adds a freeform block to the output. | ||
| * | ||
| * @param {number} [rawLength] | ||
| */ | ||
| function addFreeform(rawLength) { | ||
@@ -337,3 +431,12 @@ const length = rawLength ? rawLength : document.length - offset; | ||
| } | ||
| /** | ||
| * 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) { | ||
@@ -352,3 +455,9 @@ const parent = stack[stack.length - 1]; | ||
| } | ||
| /** | ||
| * Adds block from the stack to the output. | ||
| * | ||
| * @param {number} [endOffset] | ||
| */ | ||
| function addBlockFromStack(endOffset) { | ||
@@ -360,3 +469,5 @@ const { | ||
| tokenStart | ||
| } = stack.pop(); | ||
| } = | ||
| /** @type {ParsedFrame} */ | ||
| stack.pop(); | ||
| const html = endOffset ? document.substr(prevOffset, endOffset - prevOffset) : document.substr(prevOffset); | ||
@@ -363,0 +474,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["@wordpress/block-serialization-default-parser/src/index.js"],"names":["document","offset","output","stack","tokenizer","Block","blockName","attrs","innerBlocks","innerHTML","innerContent","Freeform","Frame","block","tokenStart","tokenLength","prevOffset","leadingHtmlStart","parse","doc","lastIndex","proceed","next","nextToken","tokenType","startOffset","stackDepth","length","addFreeform","addBlockFromStack","push","substr","addInnerBlock","stackTop","pop","html","parseJSON","input","JSON","e","matches","exec","startedAt","index","match","closerMatch","namespaceMatch","nameMatch","attrsMatch","voidMatch","isCloser","isVoid","namespace","name","hasAttrs","rawLength","lastOffset","parent","endOffset"],"mappings":"AAAA,IAAIA,QAAJ;AACA,IAAIC,MAAJ;AACA,IAAIC,MAAJ;AACA,IAAIC,KAAJ;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,MAAMC,SAAS,GACd,8HADD;;AAGA,SAASC,KAAT,CAAgBC,SAAhB,EAA2BC,KAA3B,EAAkCC,WAAlC,EAA+CC,SAA/C,EAA0DC,YAA1D,EAAyE;AACxE,SAAO;AACNJ,IAAAA,SADM;AAENC,IAAAA,KAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,SAJM;AAKNC,IAAAA;AALM,GAAP;AAOA;;AAED,SAASC,QAAT,CAAmBF,SAAnB,EAA+B;AAC9B,SAAOJ,KAAK,CAAE,IAAF,EAAQ,EAAR,EAAY,EAAZ,EAAgBI,SAAhB,EAA2B,CAAEA,SAAF,CAA3B,CAAZ;AACA;;AAED,SAASG,KAAT,CAAgBC,KAAhB,EAAuBC,UAAvB,EAAmCC,WAAnC,EAAgDC,UAAhD,EAA4DC,gBAA5D,EAA+E;AAC9E,SAAO;AACNJ,IAAAA,KADM;AAENC,IAAAA,UAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,UAAU,EAAEA,UAAU,IAAIF,UAAU,GAAGC,WAJjC;AAKNE,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A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","sourcesContent":["let document;\nlet offset;\nlet output;\nlet stack;\n\n/**\n * Matches block comment delimiters\n *\n * While most of this pattern is straightforward the attribute parsing\n * incorporates a tricks to make sure we don't choke on specific input\n *\n * - since JavaScript has no possessive quantifier or atomic grouping\n * we are emulating it with a trick\n *\n * we want a possessive quantifier or atomic group to prevent backtracking\n * on the `}`s should we fail to match the remainder of the pattern\n *\n * we can emulate this with a positive lookahead and back reference\n * (a++)*c === ((?=(a+))\\1)*c\n *\n * let's examine an example:\n * - /(a+)*c/.test('aaaaaaaaaaaaad') fails after over 49,000 steps\n * - /(a++)*c/.test('aaaaaaaaaaaaad') fails after 85 steps\n * - /(?>a+)*c/.test('aaaaaaaaaaaaad') fails after 126 steps\n *\n * this is because the possessive `++` and the atomic group `(?>)`\n * tell the engine that all those `a`s belong together as a single group\n * and so it won't split it up when stepping backwards to try and match\n *\n * if we use /((?=(a+))\\1)*c/ then we get the same behavior as the atomic group\n * or possessive and prevent the backtracking because the `a+` is matched but\n * not captured. thus, we find the long string of `a`s and remember it, then\n * reference it as a whole unit inside our pattern\n *\n * @see http://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead\n * @see http://blog.stevenlevithan.com/archives/mimic-atomic-groups\n * @see https://javascript.info/regexp-infinite-backtracking-problem\n *\n * once browsers reliably support atomic grouping or possessive\n * quantifiers natively we should remove this trick and simplify\n *\n * @type {RegExp}\n *\n * @since 3.8.0\n * @since 4.6.1 added optimization to prevent backtracking on attribute parsing\n */\nconst tokenizer =\n\t/<!--\\s+(\\/)?wp:([a-z][a-z0-9_-]*\\/)?([a-z][a-z0-9_-]*)\\s+({(?:(?=([^}]+|}+(?=})|(?!}\\s+\\/?-->)[^])*)\\5|[^]*?)}\\s+)?(\\/)?-->/g;\n\nfunction Block( blockName, attrs, innerBlocks, innerHTML, innerContent ) {\n\treturn {\n\t\tblockName,\n\t\tattrs,\n\t\tinnerBlocks,\n\t\tinnerHTML,\n\t\tinnerContent,\n\t};\n}\n\nfunction Freeform( innerHTML ) {\n\treturn Block( null, {}, [], innerHTML, [ innerHTML ] );\n}\n\nfunction Frame( block, tokenStart, tokenLength, prevOffset, leadingHtmlStart ) {\n\treturn {\n\t\tblock,\n\t\ttokenStart,\n\t\ttokenLength,\n\t\tprevOffset: prevOffset || tokenStart + tokenLength,\n\t\tleadingHtmlStart,\n\t};\n}\n\n/**\n * Parser function, that converts input HTML into a block based structure.\n *\n * @param {string} doc The HTML document to parse.\n *\n * @example\n * Input post:\n * ```html\n * <!-- wp:columns {\"columns\":3} -->\n * <div class=\"wp-block-columns has-3-columns\"><!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p>Left</p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p><strong>Middle</strong></p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"></div>\n * <!-- /wp:column --></div>\n * <!-- /wp:columns -->\n * ```\n *\n * Parsing code:\n * ```js\n * import { parse } from '@wordpress/block-serialization-default-parser';\n *\n * parse( post ) === [\n * {\n * blockName: \"core/columns\",\n * attrs: {\n * columns: 3\n * },\n * innerBlocks: [\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p>Left</p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p><strong>Middle</strong></p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-columns has-3-columns\">\\n\\n\\n\\n</div>\\n'\n * }\n * ];\n * ```\n * @return {Array} A block-based representation of the input HTML.\n */\nexport const parse = ( doc ) => {\n\tdocument = doc;\n\toffset = 0;\n\toutput = [];\n\tstack = [];\n\ttokenizer.lastIndex = 0;\n\n\tdo {\n\t\t// twiddle our thumbs\n\t} while ( proceed() );\n\n\treturn output;\n};\n\nfunction proceed() {\n\tconst next = nextToken();\n\tconst [ tokenType, blockName, attrs, startOffset, tokenLength ] = next;\n\tconst stackDepth = stack.length;\n\n\t// We may have some HTML soup before the next block.\n\tconst leadingHtmlStart = startOffset > offset ? offset : null;\n\n\tswitch ( tokenType ) {\n\t\tcase 'no-more-tokens':\n\t\t\t// If not in a block then flush output.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Otherwise we have a problem\n\t\t\t// This is an error\n\t\t\t// we have options\n\t\t\t// - treat it all as freeform text\n\t\t\t// - assume an implicit closer (easiest when not nesting)\n\n\t\t\t// For the easy case we'll assume an implicit closer.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// For the nested case where it's more difficult we'll\n\t\t\t// have to assume that multiple closers are missing\n\t\t\t// and so we'll collapse the whole stack piecewise.\n\t\t\twhile ( 0 < stack.length ) {\n\t\t\t\taddBlockFromStack();\n\t\t\t}\n\t\t\treturn false;\n\n\t\tcase 'void-block':\n\t\t\t// easy case is if we stumbled upon a void block\n\t\t\t// in the top-level of the document.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\tif ( null !== leadingHtmlStart ) {\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tFreeform(\n\t\t\t\t\t\t\tdocument.substr(\n\t\t\t\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\t\t\t\tstartOffset - leadingHtmlStart\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutput.push( Block( blockName, attrs, [], '', [] ) );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we found an inner block.\n\t\t\taddInnerBlock(\n\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\tstartOffset,\n\t\t\t\ttokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-opener':\n\t\t\t// Track all newly-opened blocks on the stack.\n\t\t\tstack.push(\n\t\t\t\tFrame(\n\t\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\t\tstartOffset,\n\t\t\t\t\ttokenLength,\n\t\t\t\t\tstartOffset + tokenLength,\n\t\t\t\t\tleadingHtmlStart\n\t\t\t\t)\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-closer':\n\t\t\t// If we're missing an opener we're in trouble\n\t\t\t// This is an error.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\t// We have options\n\t\t\t\t// - assume an implicit opener\n\t\t\t\t// - assume _this_ is the opener\n\t\t\t\t// - give up and close out the document.\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// If we're not nesting then this is easy - close the block.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack( startOffset );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we're nested and we have to close out the current\n\t\t\t// block and add it as a innerBlock to the parent.\n\t\t\tconst stackTop = stack.pop();\n\t\t\tconst html = document.substr(\n\t\t\t\tstackTop.prevOffset,\n\t\t\t\tstartOffset - stackTop.prevOffset\n\t\t\t);\n\t\t\tstackTop.block.innerHTML += html;\n\t\t\tstackTop.block.innerContent.push( html );\n\t\t\tstackTop.prevOffset = startOffset + tokenLength;\n\n\t\t\taddInnerBlock(\n\t\t\t\tstackTop.block,\n\t\t\t\tstackTop.tokenStart,\n\t\t\t\tstackTop.tokenLength,\n\t\t\t\tstartOffset + tokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\t// This is an error.\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t}\n}\n\n/**\n * Parse JSON if valid, otherwise return null\n *\n * Note that JSON coming from the block comment\n * delimiters is constrained to be an object\n * and cannot be things like `true` or `null`\n *\n * @param {string} input JSON input string to parse\n * @return {Object|null} parsed JSON if valid\n */\nfunction parseJSON( input ) {\n\ttry {\n\t\treturn JSON.parse( input );\n\t} catch ( e ) {\n\t\treturn null;\n\t}\n}\n\nfunction nextToken() {\n\t// Aye the magic\n\t// we're using a single RegExp to tokenize the block comment delimiters\n\t// we're also using a trick here because the only difference between a\n\t// block opener and a block closer is the leading `/` before `wp:` (and\n\t// a closer has no attributes). we can trap them both and process the\n\t// match back in JavaScript to see which one it was.\n\tconst matches = tokenizer.exec( document );\n\n\t// We have no more tokens.\n\tif ( null === matches ) {\n\t\treturn [ 'no-more-tokens' ];\n\t}\n\n\tconst startedAt = matches.index;\n\tconst [\n\t\tmatch,\n\t\tcloserMatch,\n\t\tnamespaceMatch,\n\t\tnameMatch,\n\t\tattrsMatch /* Internal/unused. */,\n\t\t,\n\t\tvoidMatch,\n\t] = matches;\n\n\tconst length = match.length;\n\tconst isCloser = !! closerMatch;\n\tconst isVoid = !! voidMatch;\n\tconst namespace = namespaceMatch || 'core/';\n\tconst name = namespace + nameMatch;\n\tconst hasAttrs = !! attrsMatch;\n\tconst attrs = hasAttrs ? parseJSON( attrsMatch ) : {};\n\n\t// This state isn't allowed\n\t// This is an error.\n\tif ( isCloser && ( isVoid || hasAttrs ) ) {\n\t\t// We can ignore them since they don't hurt anything\n\t\t// we may warn against this at some point or reject it.\n\t}\n\n\tif ( isVoid ) {\n\t\treturn [ 'void-block', name, attrs, startedAt, length ];\n\t}\n\n\tif ( isCloser ) {\n\t\treturn [ 'block-closer', name, null, startedAt, length ];\n\t}\n\n\treturn [ 'block-opener', name, attrs, startedAt, length ];\n}\n\nfunction addFreeform( rawLength ) {\n\tconst length = rawLength ? rawLength : document.length - offset;\n\n\tif ( 0 === length ) {\n\t\treturn;\n\t}\n\n\toutput.push( Freeform( document.substr( offset, length ) ) );\n}\n\nfunction addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {\n\tconst parent = stack[ stack.length - 1 ];\n\tparent.block.innerBlocks.push( block );\n\tconst html = document.substr(\n\t\tparent.prevOffset,\n\t\ttokenStart - parent.prevOffset\n\t);\n\n\tif ( html ) {\n\t\tparent.block.innerHTML += html;\n\t\tparent.block.innerContent.push( html );\n\t}\n\n\tparent.block.innerContent.push( null );\n\tparent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength;\n}\n\nfunction addBlockFromStack( endOffset ) {\n\tconst { block, leadingHtmlStart, prevOffset, tokenStart } = stack.pop();\n\n\tconst html = endOffset\n\t\t? document.substr( prevOffset, endOffset - prevOffset )\n\t\t: document.substr( prevOffset );\n\n\tif ( html ) {\n\t\tblock.innerHTML += html;\n\t\tblock.innerContent.push( html );\n\t}\n\n\tif ( null !== leadingHtmlStart ) {\n\t\toutput.push(\n\t\t\tFreeform(\n\t\t\t\tdocument.substr(\n\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\ttokenStart - leadingHtmlStart\n\t\t\t\t)\n\t\t\t)\n\t\t);\n\t}\n\n\toutput.push( block );\n}\n"]} | ||
| {"version":3,"sources":["@wordpress/block-serialization-default-parser/src/index.js"],"names":["document","offset","output","stack","tokenizer","Block","blockName","attrs","innerBlocks","innerHTML","innerContent","Freeform","Frame","block","tokenStart","tokenLength","prevOffset","leadingHtmlStart","parse","doc","lastIndex","proceed","stackDepth","length","next","nextToken","addFreeform","addBlockFromStack","tokenType","startOffset","push","substr","addInnerBlock","stackTop","pop","html","parseJSON","input","JSON","e","matches","exec","startedAt","index","match","closerMatch","namespaceMatch","nameMatch","attrsMatch","voidMatch","isCloser","isVoid","namespace","name","hasAttrs","rawLength","lastOffset","parent","endOffset"],"mappings":"AAAA;AACA;AACA;AACA,IAAIA,QAAJ;AACA;AACA;AACA;;AACA,IAAIC,MAAJ;AACA;AACA;AACA;;AACA,IAAIC,MAAJ;AACA;AACA;AACA;;AACA,IAAIC,KAAJ;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,MAAMC,SAAS,GACd,8HADD;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,KAAT,CAAgBC,SAAhB,EAA2BC,KAA3B,EAAkCC,WAAlC,EAA+CC,SAA/C,EAA0DC,YAA1D,EAAyE;AACxE,SAAO;AACNJ,IAAAA,SADM;AAENC,IAAAA,KAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,SAJM;AAKNC,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;;;AACA,SAASC,QAAT,CAAmBF,SAAnB,EAA+B;AAC9B,SAAOJ,KAAK,CAAE,IAAF,EAAQ,EAAR,EAAY,EAAZ,EAAgBI,SAAhB,EAA2B,CAAEA,SAAF,CAA3B,CAAZ;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,SAASG,KAAT,CAAgBC,KAAhB,EAAuBC,UAAvB,EAAmCC,WAAnC,EAAgDC,UAAhD,EAA4DC,gBAA5D,EAA+E;AAC9E,SAAO;AACNJ,IAAAA,KADM;AAENC,IAAAA,UAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,UAAU,EAAEA,UAAU,IAAIF,UAAU,GAAGC,WAJjC;AAKNE,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,OAAO,MAAMC,KAAK,GAAKC,GAAF,IAAW;AAC/BnB,EAAAA,QAAQ,GAAGmB,GAAX;AACAlB,EAAAA,MAAM,GAAG,CAAT;AACAC,EAAAA,MAAM,GAAG,EAAT;AACAC,EAAAA,KAAK,GAAG,EAAR;AACAC,EAAAA,SAAS,CAACgB,SAAV,GAAsB,CAAtB;;AAEA,KAAG,CACF;AACA,GAFD,QAEUC,OAAO,EAFjB;;AAIA,SAAOnB,MAAP;AACA,CAZM;AAcP;AACA;AACA;AACA;AACA;;AACA,SAASmB,OAAT,GAAmB;AAClB,QAAMC,UAAU,GAAGnB,KAAK,CAACoB,MAAzB;AACA,QAAMC,IAAI,GAAGC,SAAS,EAAtB;;AACA,MAAKD,IAAI,KAAK,IAAd,EAAqB;AACpB;AACA,QAAK,MAAMF,UAAX,EAAwB;AACvBI,MAAAA,WAAW;AACX,aAAO,KAAP;AACA,KALmB,CAOpB;AACA;AACA;AACA;AACA;AAEA;;;AACA,QAAK,MAAMJ,UAAX,EAAwB;AACvBK,MAAAA,iBAAiB;AACjB,aAAO,KAAP;AACA,KAjBmB,CAmBpB;AACA;AACA;;;AACA,WAAQ,IAAIxB,KAAK,CAACoB,MAAlB,EAA2B;AAC1BI,MAAAA,iBAAiB;AACjB;;AACD,WAAO,KAAP;AACA;;AACD,QAAM,CAAEC,SAAF,EAAatB,SAAb,EAAwBC,KAAxB,EAA+BsB,WAA/B,EAA4Cd,WAA5C,IAA4DS,IAAlE,CA9BkB,CAgClB;;AACA,QAAMP,gBAAgB,GAAGY,WA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","sourcesContent":["/**\n * @type {string}\n */\nlet document;\n/**\n * @type {number}\n */\nlet offset;\n/**\n * @type {ParsedBlock[]}\n */\nlet output;\n/**\n * @type {ParsedFrame[]}\n */\nlet stack;\n\n/**\n * @typedef {Object|null} Attributes\n */\n\n/**\n * @typedef {Object} ParsedBlock\n * @property {string|null} blockName Block name.\n * @property {Attributes} attrs Block attributes.\n * @property {ParsedBlock[]} innerBlocks Inner blocks.\n * @property {string} innerHTML Inner HTML.\n * @property {Array<string|null>} innerContent Inner content.\n */\n\n/**\n * @typedef {Object} ParsedFrame\n * @property {ParsedBlock} block Block.\n * @property {number} tokenStart Token start.\n * @property {number} tokenLength Token length.\n * @property {number} prevOffset Previous offset.\n * @property {number|null} leadingHtmlStart Leading HTML start.\n */\n\n/**\n * @typedef {'void-block'|'block-opener'|'block-closer'} TokenType\n */\n\n/**\n * @typedef {[TokenType, string, Attributes, number, number]} Token\n */\n\n/**\n * Matches block comment delimiters\n *\n * While most of this pattern is straightforward the attribute parsing\n * incorporates a tricks to make sure we don't choke on specific input\n *\n * - since JavaScript has no possessive quantifier or atomic grouping\n * we are emulating it with a trick\n *\n * we want a possessive quantifier or atomic group to prevent backtracking\n * on the `}`s should we fail to match the remainder of the pattern\n *\n * we can emulate this with a positive lookahead and back reference\n * (a++)*c === ((?=(a+))\\1)*c\n *\n * let's examine an example:\n * - /(a+)*c/.test('aaaaaaaaaaaaad') fails after over 49,000 steps\n * - /(a++)*c/.test('aaaaaaaaaaaaad') fails after 85 steps\n * - /(?>a+)*c/.test('aaaaaaaaaaaaad') fails after 126 steps\n *\n * this is because the possessive `++` and the atomic group `(?>)`\n * tell the engine that all those `a`s belong together as a single group\n * and so it won't split it up when stepping backwards to try and match\n *\n * if we use /((?=(a+))\\1)*c/ then we get the same behavior as the atomic group\n * or possessive and prevent the backtracking because the `a+` is matched but\n * not captured. thus, we find the long string of `a`s and remember it, then\n * reference it as a whole unit inside our pattern\n *\n * @see http://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead\n * @see http://blog.stevenlevithan.com/archives/mimic-atomic-groups\n * @see https://javascript.info/regexp-infinite-backtracking-problem\n *\n * once browsers reliably support atomic grouping or possessive\n * quantifiers natively we should remove this trick and simplify\n *\n * @type {RegExp}\n *\n * @since 3.8.0\n * @since 4.6.1 added optimization to prevent backtracking on attribute parsing\n */\nconst tokenizer =\n\t/<!--\\s+(\\/)?wp:([a-z][a-z0-9_-]*\\/)?([a-z][a-z0-9_-]*)\\s+({(?:(?=([^}]+|}+(?=})|(?!}\\s+\\/?-->)[^])*)\\5|[^]*?)}\\s+)?(\\/)?-->/g;\n\n/**\n * Constructs a block object.\n *\n * @param {string|null} blockName\n * @param {Attributes} attrs\n * @param {ParsedBlock[]} innerBlocks\n * @param {string} innerHTML\n * @param {string[]} innerContent\n * @return {ParsedBlock} The block object.\n */\nfunction Block( blockName, attrs, innerBlocks, innerHTML, innerContent ) {\n\treturn {\n\t\tblockName,\n\t\tattrs,\n\t\tinnerBlocks,\n\t\tinnerHTML,\n\t\tinnerContent,\n\t};\n}\n\n/**\n * Constructs a freeform block object.\n *\n * @param {string} innerHTML\n * @return {ParsedBlock} The freeform block object.\n */\nfunction Freeform( innerHTML ) {\n\treturn Block( null, {}, [], innerHTML, [ innerHTML ] );\n}\n\n/**\n * Constructs a frame object.\n *\n * @param {ParsedBlock} block\n * @param {number} tokenStart\n * @param {number} tokenLength\n * @param {number} prevOffset\n * @param {number|null} leadingHtmlStart\n * @return {ParsedFrame} The frame object.\n */\nfunction Frame( block, tokenStart, tokenLength, prevOffset, leadingHtmlStart ) {\n\treturn {\n\t\tblock,\n\t\ttokenStart,\n\t\ttokenLength,\n\t\tprevOffset: prevOffset || tokenStart + tokenLength,\n\t\tleadingHtmlStart,\n\t};\n}\n\n/**\n * Parser function, that converts input HTML into a block based structure.\n *\n * @param {string} doc The HTML document to parse.\n *\n * @example\n * Input post:\n * ```html\n * <!-- wp:columns {\"columns\":3} -->\n * <div class=\"wp-block-columns has-3-columns\"><!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p>Left</p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p><strong>Middle</strong></p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"></div>\n * <!-- /wp:column --></div>\n * <!-- /wp:columns -->\n * ```\n *\n * Parsing code:\n * ```js\n * import { parse } from '@wordpress/block-serialization-default-parser';\n *\n * parse( post ) === [\n * {\n * blockName: \"core/columns\",\n * attrs: {\n * columns: 3\n * },\n * innerBlocks: [\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p>Left</p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p><strong>Middle</strong></p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-columns has-3-columns\">\\n\\n\\n\\n</div>\\n'\n * }\n * ];\n * ```\n * @return {ParsedBlock[]} A block-based representation of the input HTML.\n */\nexport const parse = ( doc ) => {\n\tdocument = doc;\n\toffset = 0;\n\toutput = [];\n\tstack = [];\n\ttokenizer.lastIndex = 0;\n\n\tdo {\n\t\t// twiddle our thumbs\n\t} while ( proceed() );\n\n\treturn output;\n};\n\n/**\n * Parses the next token in the input document.\n *\n * @return {boolean} Returns true when there is more tokens to parse.\n */\nfunction proceed() {\n\tconst stackDepth = stack.length;\n\tconst next = nextToken();\n\tif ( next === null ) {\n\t\t// If not in a block then flush output.\n\t\tif ( 0 === stackDepth ) {\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise we have a problem\n\t\t// This is an error\n\t\t// we have options\n\t\t// - treat it all as freeform text\n\t\t// - assume an implicit closer (easiest when not nesting)\n\n\t\t// For the easy case we'll assume an implicit closer.\n\t\tif ( 1 === stackDepth ) {\n\t\t\taddBlockFromStack();\n\t\t\treturn false;\n\t\t}\n\n\t\t// For the nested case where it's more difficult we'll\n\t\t// have to assume that multiple closers are missing\n\t\t// and so we'll collapse the whole stack piecewise.\n\t\twhile ( 0 < stack.length ) {\n\t\t\taddBlockFromStack();\n\t\t}\n\t\treturn false;\n\t}\n\tconst [ tokenType, blockName, attrs, startOffset, tokenLength ] = next;\n\n\t// We may have some HTML soup before the next block.\n\tconst leadingHtmlStart = startOffset > offset ? offset : null;\n\n\tswitch ( tokenType ) {\n\t\tcase 'void-block':\n\t\t\t// easy case is if we stumbled upon a void block\n\t\t\t// in the top-level of the document.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\tif ( null !== leadingHtmlStart ) {\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tFreeform(\n\t\t\t\t\t\t\tdocument.substr(\n\t\t\t\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\t\t\t\tstartOffset - leadingHtmlStart\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutput.push( Block( blockName, attrs, [], '', [] ) );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we found an inner block.\n\t\t\taddInnerBlock(\n\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\tstartOffset,\n\t\t\t\ttokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-opener':\n\t\t\t// Track all newly-opened blocks on the stack.\n\t\t\tstack.push(\n\t\t\t\tFrame(\n\t\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\t\tstartOffset,\n\t\t\t\t\ttokenLength,\n\t\t\t\t\tstartOffset + tokenLength,\n\t\t\t\t\tleadingHtmlStart\n\t\t\t\t)\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-closer':\n\t\t\t// If we're missing an opener we're in trouble\n\t\t\t// This is an error.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\t// We have options\n\t\t\t\t// - assume an implicit opener\n\t\t\t\t// - assume _this_ is the opener\n\t\t\t\t// - give up and close out the document.\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// If we're not nesting then this is easy - close the block.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack( startOffset );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we're nested and we have to close out the current\n\t\t\t// block and add it as a innerBlock to the parent.\n\t\t\tconst stackTop = /** @type {ParsedFrame} */ ( stack.pop() );\n\t\t\tconst html = document.substr(\n\t\t\t\tstackTop.prevOffset,\n\t\t\t\tstartOffset - stackTop.prevOffset\n\t\t\t);\n\t\t\tstackTop.block.innerHTML += html;\n\t\t\tstackTop.block.innerContent.push( html );\n\t\t\tstackTop.prevOffset = startOffset + tokenLength;\n\n\t\t\taddInnerBlock(\n\t\t\t\tstackTop.block,\n\t\t\t\tstackTop.tokenStart,\n\t\t\t\tstackTop.tokenLength,\n\t\t\t\tstartOffset + tokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\t// This is an error.\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t}\n}\n\n/**\n * Parse JSON if valid, otherwise return null\n *\n * Note that JSON coming from the block comment\n * delimiters is constrained to be an object\n * and cannot be things like `true` or `null`\n *\n * @param {string} input JSON input string to parse\n * @return {Object|null} parsed JSON if valid\n */\nfunction parseJSON( input ) {\n\ttry {\n\t\treturn JSON.parse( input );\n\t} catch ( e ) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Finds the next token in the document.\n *\n * @return {Token|null} The next matched token.\n */\nfunction nextToken() {\n\t// Aye the magic\n\t// we're using a single RegExp to tokenize the block comment delimiters\n\t// we're also using a trick here because the only difference between a\n\t// block opener and a block closer is the leading `/` before `wp:` (and\n\t// a closer has no attributes). we can trap them both and process the\n\t// match back in JavaScript to see which one it was.\n\tconst matches = tokenizer.exec( document );\n\n\t// We have no more tokens.\n\tif ( null === matches ) {\n\t\treturn null;\n\t}\n\n\tconst startedAt = matches.index;\n\tconst [\n\t\tmatch,\n\t\tcloserMatch,\n\t\tnamespaceMatch,\n\t\tnameMatch,\n\t\tattrsMatch /* Internal/unused. */,\n\t\t,\n\t\tvoidMatch,\n\t] = matches;\n\n\tconst length = match.length;\n\tconst isCloser = !! closerMatch;\n\tconst isVoid = !! voidMatch;\n\tconst namespace = namespaceMatch || 'core/';\n\tconst name = namespace + nameMatch;\n\tconst hasAttrs = !! attrsMatch;\n\tconst attrs = hasAttrs ? parseJSON( attrsMatch ) : {};\n\n\t// This state isn't allowed\n\t// This is an error.\n\tif ( isCloser && ( isVoid || hasAttrs ) ) {\n\t\t// We can ignore them since they don't hurt anything\n\t\t// we may warn against this at some point or reject it.\n\t}\n\n\tif ( isVoid ) {\n\t\treturn [ 'void-block', name, attrs, startedAt, length ];\n\t}\n\n\tif ( isCloser ) {\n\t\treturn [ 'block-closer', name, null, startedAt, length ];\n\t}\n\n\treturn [ 'block-opener', name, attrs, startedAt, length ];\n}\n\n/**\n * Adds a freeform block to the output.\n *\n * @param {number} [rawLength]\n */\nfunction addFreeform( rawLength ) {\n\tconst length = rawLength ? rawLength : document.length - offset;\n\n\tif ( 0 === length ) {\n\t\treturn;\n\t}\n\n\toutput.push( Freeform( document.substr( offset, length ) ) );\n}\n\n/**\n * Adds inner block to the parent block.\n *\n * @param {ParsedBlock} block\n * @param {number} tokenStart\n * @param {number} tokenLength\n * @param {number} [lastOffset]\n */\nfunction addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {\n\tconst parent = stack[ stack.length - 1 ];\n\tparent.block.innerBlocks.push( block );\n\tconst html = document.substr(\n\t\tparent.prevOffset,\n\t\ttokenStart - parent.prevOffset\n\t);\n\n\tif ( html ) {\n\t\tparent.block.innerHTML += html;\n\t\tparent.block.innerContent.push( html );\n\t}\n\n\tparent.block.innerContent.push( null );\n\tparent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength;\n}\n\n/**\n * Adds block from the stack to the output.\n *\n * @param {number} [endOffset]\n */\nfunction addBlockFromStack( endOffset ) {\n\tconst { block, leadingHtmlStart, prevOffset, tokenStart } =\n\t\t/** @type {ParsedFrame} */ ( stack.pop() );\n\n\tconst html = endOffset\n\t\t? document.substr( prevOffset, endOffset - prevOffset )\n\t\t: document.substr( prevOffset );\n\n\tif ( html ) {\n\t\tblock.innerHTML += html;\n\t\tblock.innerContent.push( html );\n\t}\n\n\tif ( null !== leadingHtmlStart ) {\n\t\toutput.push(\n\t\t\tFreeform(\n\t\t\t\tdocument.substr(\n\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\ttokenStart - leadingHtmlStart\n\t\t\t\t)\n\t\t\t)\n\t\t);\n\t}\n\n\toutput.push( block );\n}\n"]} |
+142
-29
@@ -7,7 +7,53 @@ "use strict"; | ||
| exports.parse = void 0; | ||
| /** | ||
| * @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 {'void-block'|'block-opener'|'block-closer'} TokenType | ||
| */ | ||
| /** | ||
| * @typedef {[TokenType, string, Attributes, number, number]} Token | ||
| */ | ||
| /** | ||
| * Matches block comment delimiters | ||
@@ -55,2 +101,12 @@ * | ||
| 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. | ||
| */ | ||
@@ -66,7 +122,25 @@ function Block(blockName, attrs, innerBlocks, innerHTML, innerContent) { | ||
| } | ||
| /** | ||
| * 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) { | ||
@@ -156,3 +230,3 @@ return { | ||
| * ``` | ||
| * @return {Array} A block-based representation of the input HTML. | ||
| * @return {ParsedBlock[]} A block-based representation of the input HTML. | ||
| */ | ||
@@ -173,40 +247,48 @@ | ||
| }; | ||
| /** | ||
| * Parses the next token in the input document. | ||
| * | ||
| * @return {boolean} Returns true when there is more tokens to parse. | ||
| */ | ||
| exports.parse = 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. | ||
| const leadingHtmlStart = startOffset > offset ? offset : null; | ||
| if (next === null) { | ||
| // If not in a block then flush output. | ||
| if (0 === stackDepth) { | ||
| addFreeform(); | ||
| return false; | ||
| } // 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. | ||
| 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 | ||
| // 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 | ||
| // have to assume that multiple closers are missing | ||
| // and so we'll collapse the whole stack piecewise. | ||
| if (1 === stackDepth) { | ||
| addBlockFromStack(); | ||
| return false; | ||
| } // 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(); | ||
| } | ||
| while (0 < stack.length) { | ||
| addBlockFromStack(); | ||
| } | ||
| return false; | ||
| } | ||
| return false; | ||
| const [tokenType, blockName, attrs, startOffset, tokenLength] = next; // We may have some HTML soup before the next block. | ||
| const leadingHtmlStart = startOffset > offset ? offset : null; | ||
| switch (tokenType) { | ||
| case 'void-block': | ||
@@ -257,3 +339,5 @@ // easy case is if we stumbled upon a void block | ||
| const stackTop = stack.pop(); | ||
| const stackTop = | ||
| /** @type {ParsedFrame} */ | ||
| stack.pop(); | ||
| const html = document.substr(stackTop.prevOffset, startOffset - stackTop.prevOffset); | ||
@@ -292,3 +376,9 @@ stackTop.block.innerHTML += html; | ||
| } | ||
| /** | ||
| * Finds the next token in the document. | ||
| * | ||
| * @return {Token|null} The next matched token. | ||
| */ | ||
| function nextToken() { | ||
@@ -304,3 +394,3 @@ // Aye the magic | ||
| if (null === matches) { | ||
| return ['no-more-tokens']; | ||
| return null; | ||
| } | ||
@@ -335,3 +425,9 @@ | ||
| } | ||
| /** | ||
| * Adds a freeform block to the output. | ||
| * | ||
| * @param {number} [rawLength] | ||
| */ | ||
| function addFreeform(rawLength) { | ||
@@ -346,3 +442,12 @@ const length = rawLength ? rawLength : document.length - offset; | ||
| } | ||
| /** | ||
| * 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) { | ||
@@ -361,3 +466,9 @@ const parent = stack[stack.length - 1]; | ||
| } | ||
| /** | ||
| * Adds block from the stack to the output. | ||
| * | ||
| * @param {number} [endOffset] | ||
| */ | ||
| function addBlockFromStack(endOffset) { | ||
@@ -369,3 +480,5 @@ const { | ||
| tokenStart | ||
| } = stack.pop(); | ||
| } = | ||
| /** @type {ParsedFrame} */ | ||
| stack.pop(); | ||
| const html = endOffset ? document.substr(prevOffset, endOffset - prevOffset) : document.substr(prevOffset); | ||
@@ -372,0 +485,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["@wordpress/block-serialization-default-parser/src/index.js"],"names":["document","offset","output","stack","tokenizer","Block","blockName","attrs","innerBlocks","innerHTML","innerContent","Freeform","Frame","block","tokenStart","tokenLength","prevOffset","leadingHtmlStart","parse","doc","lastIndex","proceed","next","nextToken","tokenType","startOffset","stackDepth","length","addFreeform","addBlockFromStack","push","substr","addInnerBlock","stackTop","pop","html","parseJSON","input","JSON","e","matches","exec","startedAt","index","match","closerMatch","namespaceMatch","nameMatch","attrsMatch","voidMatch","isCloser","isVoid","namespace","name","hasAttrs","rawLength","lastOffset","parent","endOffset"],"mappings":";;;;;;AAAA,IAAIA,QAAJ;AACA,IAAIC,MAAJ;AACA,IAAIC,MAAJ;AACA,IAAIC,KAAJ;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,MAAMC,SAAS,GACd,8HADD;;AAGA,SAASC,KAAT,CAAgBC,SAAhB,EAA2BC,KAA3B,EAAkCC,WAAlC,EAA+CC,SAA/C,EAA0DC,YAA1D,EAAyE;AACxE,SAAO;AACNJ,IAAAA,SADM;AAENC,IAAAA,KAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,SAJM;AAKNC,IAAAA;AALM,GAAP;AAOA;;AAED,SAASC,QAAT,CAAmBF,SAAnB,EAA+B;AAC9B,SAAOJ,KAAK,CAAE,IAAF,EAAQ,EAAR,EAAY,EAAZ,EAAgBI,SAAhB,EAA2B,CAAEA,SAAF,CAA3B,CAAZ;AACA;;AAED,SAASG,KAAT,CAAgBC,KAAhB,EAAuBC,UAAvB,EAAmCC,WAAnC,EAAgDC,UAAhD,EAA4DC,gBAA5D,EAA+E;AAC9E,SAAO;AACNJ,IAAAA,KADM;AAENC,IAAAA,UAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,UAAU,EAAEA,UAAU,IAAIF,UAAU,GAAGC,WAJjC;AAKNE,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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","sourcesContent":["let document;\nlet offset;\nlet output;\nlet stack;\n\n/**\n * Matches block comment delimiters\n *\n * While most of this pattern is straightforward the attribute parsing\n * incorporates a tricks to make sure we don't choke on specific input\n *\n * - since JavaScript has no possessive quantifier or atomic grouping\n * we are emulating it with a trick\n *\n * we want a possessive quantifier or atomic group to prevent backtracking\n * on the `}`s should we fail to match the remainder of the pattern\n *\n * we can emulate this with a positive lookahead and back reference\n * (a++)*c === ((?=(a+))\\1)*c\n *\n * let's examine an example:\n * - /(a+)*c/.test('aaaaaaaaaaaaad') fails after over 49,000 steps\n * - /(a++)*c/.test('aaaaaaaaaaaaad') fails after 85 steps\n * - /(?>a+)*c/.test('aaaaaaaaaaaaad') fails after 126 steps\n *\n * this is because the possessive `++` and the atomic group `(?>)`\n * tell the engine that all those `a`s belong together as a single group\n * and so it won't split it up when stepping backwards to try and match\n *\n * if we use /((?=(a+))\\1)*c/ then we get the same behavior as the atomic group\n * or possessive and prevent the backtracking because the `a+` is matched but\n * not captured. thus, we find the long string of `a`s and remember it, then\n * reference it as a whole unit inside our pattern\n *\n * @see http://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead\n * @see http://blog.stevenlevithan.com/archives/mimic-atomic-groups\n * @see https://javascript.info/regexp-infinite-backtracking-problem\n *\n * once browsers reliably support atomic grouping or possessive\n * quantifiers natively we should remove this trick and simplify\n *\n * @type {RegExp}\n *\n * @since 3.8.0\n * @since 4.6.1 added optimization to prevent backtracking on attribute parsing\n */\nconst tokenizer =\n\t/<!--\\s+(\\/)?wp:([a-z][a-z0-9_-]*\\/)?([a-z][a-z0-9_-]*)\\s+({(?:(?=([^}]+|}+(?=})|(?!}\\s+\\/?-->)[^])*)\\5|[^]*?)}\\s+)?(\\/)?-->/g;\n\nfunction Block( blockName, attrs, innerBlocks, innerHTML, innerContent ) {\n\treturn {\n\t\tblockName,\n\t\tattrs,\n\t\tinnerBlocks,\n\t\tinnerHTML,\n\t\tinnerContent,\n\t};\n}\n\nfunction Freeform( innerHTML ) {\n\treturn Block( null, {}, [], innerHTML, [ innerHTML ] );\n}\n\nfunction Frame( block, tokenStart, tokenLength, prevOffset, leadingHtmlStart ) {\n\treturn {\n\t\tblock,\n\t\ttokenStart,\n\t\ttokenLength,\n\t\tprevOffset: prevOffset || tokenStart + tokenLength,\n\t\tleadingHtmlStart,\n\t};\n}\n\n/**\n * Parser function, that converts input HTML into a block based structure.\n *\n * @param {string} doc The HTML document to parse.\n *\n * @example\n * Input post:\n * ```html\n * <!-- wp:columns {\"columns\":3} -->\n * <div class=\"wp-block-columns has-3-columns\"><!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p>Left</p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p><strong>Middle</strong></p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"></div>\n * <!-- /wp:column --></div>\n * <!-- /wp:columns -->\n * ```\n *\n * Parsing code:\n * ```js\n * import { parse } from '@wordpress/block-serialization-default-parser';\n *\n * parse( post ) === [\n * {\n * blockName: \"core/columns\",\n * attrs: {\n * columns: 3\n * },\n * innerBlocks: [\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p>Left</p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p><strong>Middle</strong></p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-columns has-3-columns\">\\n\\n\\n\\n</div>\\n'\n * }\n * ];\n * ```\n * @return {Array} A block-based representation of the input HTML.\n */\nexport const parse = ( doc ) => {\n\tdocument = doc;\n\toffset = 0;\n\toutput = [];\n\tstack = [];\n\ttokenizer.lastIndex = 0;\n\n\tdo {\n\t\t// twiddle our thumbs\n\t} while ( proceed() );\n\n\treturn output;\n};\n\nfunction proceed() {\n\tconst next = nextToken();\n\tconst [ tokenType, blockName, attrs, startOffset, tokenLength ] = next;\n\tconst stackDepth = stack.length;\n\n\t// We may have some HTML soup before the next block.\n\tconst leadingHtmlStart = startOffset > offset ? offset : null;\n\n\tswitch ( tokenType ) {\n\t\tcase 'no-more-tokens':\n\t\t\t// If not in a block then flush output.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Otherwise we have a problem\n\t\t\t// This is an error\n\t\t\t// we have options\n\t\t\t// - treat it all as freeform text\n\t\t\t// - assume an implicit closer (easiest when not nesting)\n\n\t\t\t// For the easy case we'll assume an implicit closer.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// For the nested case where it's more difficult we'll\n\t\t\t// have to assume that multiple closers are missing\n\t\t\t// and so we'll collapse the whole stack piecewise.\n\t\t\twhile ( 0 < stack.length ) {\n\t\t\t\taddBlockFromStack();\n\t\t\t}\n\t\t\treturn false;\n\n\t\tcase 'void-block':\n\t\t\t// easy case is if we stumbled upon a void block\n\t\t\t// in the top-level of the document.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\tif ( null !== leadingHtmlStart ) {\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tFreeform(\n\t\t\t\t\t\t\tdocument.substr(\n\t\t\t\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\t\t\t\tstartOffset - leadingHtmlStart\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutput.push( Block( blockName, attrs, [], '', [] ) );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we found an inner block.\n\t\t\taddInnerBlock(\n\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\tstartOffset,\n\t\t\t\ttokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-opener':\n\t\t\t// Track all newly-opened blocks on the stack.\n\t\t\tstack.push(\n\t\t\t\tFrame(\n\t\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\t\tstartOffset,\n\t\t\t\t\ttokenLength,\n\t\t\t\t\tstartOffset + tokenLength,\n\t\t\t\t\tleadingHtmlStart\n\t\t\t\t)\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-closer':\n\t\t\t// If we're missing an opener we're in trouble\n\t\t\t// This is an error.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\t// We have options\n\t\t\t\t// - assume an implicit opener\n\t\t\t\t// - assume _this_ is the opener\n\t\t\t\t// - give up and close out the document.\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// If we're not nesting then this is easy - close the block.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack( startOffset );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we're nested and we have to close out the current\n\t\t\t// block and add it as a innerBlock to the parent.\n\t\t\tconst stackTop = stack.pop();\n\t\t\tconst html = document.substr(\n\t\t\t\tstackTop.prevOffset,\n\t\t\t\tstartOffset - stackTop.prevOffset\n\t\t\t);\n\t\t\tstackTop.block.innerHTML += html;\n\t\t\tstackTop.block.innerContent.push( html );\n\t\t\tstackTop.prevOffset = startOffset + tokenLength;\n\n\t\t\taddInnerBlock(\n\t\t\t\tstackTop.block,\n\t\t\t\tstackTop.tokenStart,\n\t\t\t\tstackTop.tokenLength,\n\t\t\t\tstartOffset + tokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\t// This is an error.\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t}\n}\n\n/**\n * Parse JSON if valid, otherwise return null\n *\n * Note that JSON coming from the block comment\n * delimiters is constrained to be an object\n * and cannot be things like `true` or `null`\n *\n * @param {string} input JSON input string to parse\n * @return {Object|null} parsed JSON if valid\n */\nfunction parseJSON( input ) {\n\ttry {\n\t\treturn JSON.parse( input );\n\t} catch ( e ) {\n\t\treturn null;\n\t}\n}\n\nfunction nextToken() {\n\t// Aye the magic\n\t// we're using a single RegExp to tokenize the block comment delimiters\n\t// we're also using a trick here because the only difference between a\n\t// block opener and a block closer is the leading `/` before `wp:` (and\n\t// a closer has no attributes). we can trap them both and process the\n\t// match back in JavaScript to see which one it was.\n\tconst matches = tokenizer.exec( document );\n\n\t// We have no more tokens.\n\tif ( null === matches ) {\n\t\treturn [ 'no-more-tokens' ];\n\t}\n\n\tconst startedAt = matches.index;\n\tconst [\n\t\tmatch,\n\t\tcloserMatch,\n\t\tnamespaceMatch,\n\t\tnameMatch,\n\t\tattrsMatch /* Internal/unused. */,\n\t\t,\n\t\tvoidMatch,\n\t] = matches;\n\n\tconst length = match.length;\n\tconst isCloser = !! closerMatch;\n\tconst isVoid = !! voidMatch;\n\tconst namespace = namespaceMatch || 'core/';\n\tconst name = namespace + nameMatch;\n\tconst hasAttrs = !! attrsMatch;\n\tconst attrs = hasAttrs ? parseJSON( attrsMatch ) : {};\n\n\t// This state isn't allowed\n\t// This is an error.\n\tif ( isCloser && ( isVoid || hasAttrs ) ) {\n\t\t// We can ignore them since they don't hurt anything\n\t\t// we may warn against this at some point or reject it.\n\t}\n\n\tif ( isVoid ) {\n\t\treturn [ 'void-block', name, attrs, startedAt, length ];\n\t}\n\n\tif ( isCloser ) {\n\t\treturn [ 'block-closer', name, null, startedAt, length ];\n\t}\n\n\treturn [ 'block-opener', name, attrs, startedAt, length ];\n}\n\nfunction addFreeform( rawLength ) {\n\tconst length = rawLength ? rawLength : document.length - offset;\n\n\tif ( 0 === length ) {\n\t\treturn;\n\t}\n\n\toutput.push( Freeform( document.substr( offset, length ) ) );\n}\n\nfunction addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {\n\tconst parent = stack[ stack.length - 1 ];\n\tparent.block.innerBlocks.push( block );\n\tconst html = document.substr(\n\t\tparent.prevOffset,\n\t\ttokenStart - parent.prevOffset\n\t);\n\n\tif ( html ) {\n\t\tparent.block.innerHTML += html;\n\t\tparent.block.innerContent.push( html );\n\t}\n\n\tparent.block.innerContent.push( null );\n\tparent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength;\n}\n\nfunction addBlockFromStack( endOffset ) {\n\tconst { block, leadingHtmlStart, prevOffset, tokenStart } = stack.pop();\n\n\tconst html = endOffset\n\t\t? document.substr( prevOffset, endOffset - prevOffset )\n\t\t: document.substr( prevOffset );\n\n\tif ( html ) {\n\t\tblock.innerHTML += html;\n\t\tblock.innerContent.push( html );\n\t}\n\n\tif ( null !== leadingHtmlStart ) {\n\t\toutput.push(\n\t\t\tFreeform(\n\t\t\t\tdocument.substr(\n\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\ttokenStart - leadingHtmlStart\n\t\t\t\t)\n\t\t\t)\n\t\t);\n\t}\n\n\toutput.push( block );\n}\n"]} | ||
| {"version":3,"sources":["@wordpress/block-serialization-default-parser/src/index.js"],"names":["document","offset","output","stack","tokenizer","Block","blockName","attrs","innerBlocks","innerHTML","innerContent","Freeform","Frame","block","tokenStart","tokenLength","prevOffset","leadingHtmlStart","parse","doc","lastIndex","proceed","stackDepth","length","next","nextToken","addFreeform","addBlockFromStack","tokenType","startOffset","push","substr","addInnerBlock","stackTop","pop","html","parseJSON","input","JSON","e","matches","exec","startedAt","index","match","closerMatch","namespaceMatch","nameMatch","attrsMatch","voidMatch","isCloser","isVoid","namespace","name","hasAttrs","rawLength","lastOffset","parent","endOffset"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA,IAAIA,QAAJ;AACA;AACA;AACA;;AACA,IAAIC,MAAJ;AACA;AACA;AACA;;AACA,IAAIC,MAAJ;AACA;AACA;AACA;;AACA,IAAIC,KAAJ;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,MAAMC,SAAS,GACd,8HADD;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,KAAT,CAAgBC,SAAhB,EAA2BC,KAA3B,EAAkCC,WAAlC,EAA+CC,SAA/C,EAA0DC,YAA1D,EAAyE;AACxE,SAAO;AACNJ,IAAAA,SADM;AAENC,IAAAA,KAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,SAJM;AAKNC,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;;;AACA,SAASC,QAAT,CAAmBF,SAAnB,EAA+B;AAC9B,SAAOJ,KAAK,CAAE,IAAF,EAAQ,EAAR,EAAY,EAAZ,EAAgBI,SAAhB,EAA2B,CAAEA,SAAF,CAA3B,CAAZ;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,SAASG,KAAT,CAAgBC,KAAhB,EAAuBC,UAAvB,EAAmCC,WAAnC,EAAgDC,UAAhD,EAA4DC,gBAA5D,EAA+E;AAC9E,SAAO;AACNJ,IAAAA,KADM;AAENC,IAAAA,UAFM;AAGNC,IAAAA,WAHM;AAINC,IAAAA,UAAU,EAAEA,UAAU,IAAIF,UAAU,GAAGC,WAJjC;AAKNE,IAAAA;AALM,GAAP;AAOA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,MAAMC,KAAK,GAAKC,GAAF,IAAW;AAC/BnB,EAAAA,QAAQ,GAAGmB,GAAX;AACAlB,EAAAA,MAAM,GAAG,CAAT;AACAC,EAAAA,MAAM,GAAG,EAAT;AACAC,EAAAA,KAAK,GAAG,EAAR;AACAC,EAAAA,SAAS,CAACgB,SAAV,GAAsB,CAAtB;;AAEA,KAAG,CACF;AACA,GAFD,QAEUC,OAAO,EAFjB;;AAIA,SAAOnB,MAAP;AACA,CAZM;AAcP;AACA;AACA;AACA;AACA;;;;;AACA,SAASmB,OAAT,GAAmB;AAClB,QAAMC,UAAU,GAAGnB,KAAK,CAACoB,MAAzB;AACA,QAAMC,IAAI,GAAGC,SAAS,EAAtB;;AACA,MAAKD,IAAI,KAAK,IAAd,EAAqB;AACpB;AACA,QAAK,MAAMF,UAAX,EAAwB;AACvBI,MAAAA,WAAW;AACX,aAAO,KAAP;AACA,KALmB,CAOpB;AACA;AACA;AACA;AACA;AAEA;;;AACA,QAAK,MAAMJ,UAAX,EAAwB;AACvBK,MAAAA,iBAAiB;AACjB,aAAO,KAAP;AACA,KAjBmB,CAmBpB;AACA;AACA;;;AACA,WAAQ,IAAIxB,KAAK,CAACoB,MAAlB,EAA2B;AAC1BI,MAAAA,iBAAiB;AACjB;;AACD,WAAO,KAAP;AACA;;AACD,QAAM,CAAEC,SAAF,EAAatB,SAAb,EAAwBC,KAAxB,EAA+BsB,WAA/B,EAA4Cd,WAA5C,IAA4DS,IAAlE,CA9BkB,CAgClB;;AACA,QAAMP,gBAAgB,GAA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","sourcesContent":["/**\n * @type {string}\n */\nlet document;\n/**\n * @type {number}\n */\nlet offset;\n/**\n * @type {ParsedBlock[]}\n */\nlet output;\n/**\n * @type {ParsedFrame[]}\n */\nlet stack;\n\n/**\n * @typedef {Object|null} Attributes\n */\n\n/**\n * @typedef {Object} ParsedBlock\n * @property {string|null} blockName Block name.\n * @property {Attributes} attrs Block attributes.\n * @property {ParsedBlock[]} innerBlocks Inner blocks.\n * @property {string} innerHTML Inner HTML.\n * @property {Array<string|null>} innerContent Inner content.\n */\n\n/**\n * @typedef {Object} ParsedFrame\n * @property {ParsedBlock} block Block.\n * @property {number} tokenStart Token start.\n * @property {number} tokenLength Token length.\n * @property {number} prevOffset Previous offset.\n * @property {number|null} leadingHtmlStart Leading HTML start.\n */\n\n/**\n * @typedef {'void-block'|'block-opener'|'block-closer'} TokenType\n */\n\n/**\n * @typedef {[TokenType, string, Attributes, number, number]} Token\n */\n\n/**\n * Matches block comment delimiters\n *\n * While most of this pattern is straightforward the attribute parsing\n * incorporates a tricks to make sure we don't choke on specific input\n *\n * - since JavaScript has no possessive quantifier or atomic grouping\n * we are emulating it with a trick\n *\n * we want a possessive quantifier or atomic group to prevent backtracking\n * on the `}`s should we fail to match the remainder of the pattern\n *\n * we can emulate this with a positive lookahead and back reference\n * (a++)*c === ((?=(a+))\\1)*c\n *\n * let's examine an example:\n * - /(a+)*c/.test('aaaaaaaaaaaaad') fails after over 49,000 steps\n * - /(a++)*c/.test('aaaaaaaaaaaaad') fails after 85 steps\n * - /(?>a+)*c/.test('aaaaaaaaaaaaad') fails after 126 steps\n *\n * this is because the possessive `++` and the atomic group `(?>)`\n * tell the engine that all those `a`s belong together as a single group\n * and so it won't split it up when stepping backwards to try and match\n *\n * if we use /((?=(a+))\\1)*c/ then we get the same behavior as the atomic group\n * or possessive and prevent the backtracking because the `a+` is matched but\n * not captured. thus, we find the long string of `a`s and remember it, then\n * reference it as a whole unit inside our pattern\n *\n * @see http://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead\n * @see http://blog.stevenlevithan.com/archives/mimic-atomic-groups\n * @see https://javascript.info/regexp-infinite-backtracking-problem\n *\n * once browsers reliably support atomic grouping or possessive\n * quantifiers natively we should remove this trick and simplify\n *\n * @type {RegExp}\n *\n * @since 3.8.0\n * @since 4.6.1 added optimization to prevent backtracking on attribute parsing\n */\nconst tokenizer =\n\t/<!--\\s+(\\/)?wp:([a-z][a-z0-9_-]*\\/)?([a-z][a-z0-9_-]*)\\s+({(?:(?=([^}]+|}+(?=})|(?!}\\s+\\/?-->)[^])*)\\5|[^]*?)}\\s+)?(\\/)?-->/g;\n\n/**\n * Constructs a block object.\n *\n * @param {string|null} blockName\n * @param {Attributes} attrs\n * @param {ParsedBlock[]} innerBlocks\n * @param {string} innerHTML\n * @param {string[]} innerContent\n * @return {ParsedBlock} The block object.\n */\nfunction Block( blockName, attrs, innerBlocks, innerHTML, innerContent ) {\n\treturn {\n\t\tblockName,\n\t\tattrs,\n\t\tinnerBlocks,\n\t\tinnerHTML,\n\t\tinnerContent,\n\t};\n}\n\n/**\n * Constructs a freeform block object.\n *\n * @param {string} innerHTML\n * @return {ParsedBlock} The freeform block object.\n */\nfunction Freeform( innerHTML ) {\n\treturn Block( null, {}, [], innerHTML, [ innerHTML ] );\n}\n\n/**\n * Constructs a frame object.\n *\n * @param {ParsedBlock} block\n * @param {number} tokenStart\n * @param {number} tokenLength\n * @param {number} prevOffset\n * @param {number|null} leadingHtmlStart\n * @return {ParsedFrame} The frame object.\n */\nfunction Frame( block, tokenStart, tokenLength, prevOffset, leadingHtmlStart ) {\n\treturn {\n\t\tblock,\n\t\ttokenStart,\n\t\ttokenLength,\n\t\tprevOffset: prevOffset || tokenStart + tokenLength,\n\t\tleadingHtmlStart,\n\t};\n}\n\n/**\n * Parser function, that converts input HTML into a block based structure.\n *\n * @param {string} doc The HTML document to parse.\n *\n * @example\n * Input post:\n * ```html\n * <!-- wp:columns {\"columns\":3} -->\n * <div class=\"wp-block-columns has-3-columns\"><!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p>Left</p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"><!-- wp:paragraph -->\n * <p><strong>Middle</strong></p>\n * <!-- /wp:paragraph --></div>\n * <!-- /wp:column -->\n *\n * <!-- wp:column -->\n * <div class=\"wp-block-column\"></div>\n * <!-- /wp:column --></div>\n * <!-- /wp:columns -->\n * ```\n *\n * Parsing code:\n * ```js\n * import { parse } from '@wordpress/block-serialization-default-parser';\n *\n * parse( post ) === [\n * {\n * blockName: \"core/columns\",\n * attrs: {\n * columns: 3\n * },\n * innerBlocks: [\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p>Left</p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [\n * {\n * blockName: \"core/paragraph\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: \"\\n<p><strong>Middle</strong></p>\\n\"\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * },\n * {\n * blockName: \"core/column\",\n * attrs: null,\n * innerBlocks: [],\n * innerHTML: '\\n<div class=\"wp-block-column\"></div>\\n'\n * }\n * ],\n * innerHTML: '\\n<div class=\"wp-block-columns has-3-columns\">\\n\\n\\n\\n</div>\\n'\n * }\n * ];\n * ```\n * @return {ParsedBlock[]} A block-based representation of the input HTML.\n */\nexport const parse = ( doc ) => {\n\tdocument = doc;\n\toffset = 0;\n\toutput = [];\n\tstack = [];\n\ttokenizer.lastIndex = 0;\n\n\tdo {\n\t\t// twiddle our thumbs\n\t} while ( proceed() );\n\n\treturn output;\n};\n\n/**\n * Parses the next token in the input document.\n *\n * @return {boolean} Returns true when there is more tokens to parse.\n */\nfunction proceed() {\n\tconst stackDepth = stack.length;\n\tconst next = nextToken();\n\tif ( next === null ) {\n\t\t// If not in a block then flush output.\n\t\tif ( 0 === stackDepth ) {\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise we have a problem\n\t\t// This is an error\n\t\t// we have options\n\t\t// - treat it all as freeform text\n\t\t// - assume an implicit closer (easiest when not nesting)\n\n\t\t// For the easy case we'll assume an implicit closer.\n\t\tif ( 1 === stackDepth ) {\n\t\t\taddBlockFromStack();\n\t\t\treturn false;\n\t\t}\n\n\t\t// For the nested case where it's more difficult we'll\n\t\t// have to assume that multiple closers are missing\n\t\t// and so we'll collapse the whole stack piecewise.\n\t\twhile ( 0 < stack.length ) {\n\t\t\taddBlockFromStack();\n\t\t}\n\t\treturn false;\n\t}\n\tconst [ tokenType, blockName, attrs, startOffset, tokenLength ] = next;\n\n\t// We may have some HTML soup before the next block.\n\tconst leadingHtmlStart = startOffset > offset ? offset : null;\n\n\tswitch ( tokenType ) {\n\t\tcase 'void-block':\n\t\t\t// easy case is if we stumbled upon a void block\n\t\t\t// in the top-level of the document.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\tif ( null !== leadingHtmlStart ) {\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tFreeform(\n\t\t\t\t\t\t\tdocument.substr(\n\t\t\t\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\t\t\t\tstartOffset - leadingHtmlStart\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutput.push( Block( blockName, attrs, [], '', [] ) );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we found an inner block.\n\t\t\taddInnerBlock(\n\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\tstartOffset,\n\t\t\t\ttokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-opener':\n\t\t\t// Track all newly-opened blocks on the stack.\n\t\t\tstack.push(\n\t\t\t\tFrame(\n\t\t\t\t\tBlock( blockName, attrs, [], '', [] ),\n\t\t\t\t\tstartOffset,\n\t\t\t\t\ttokenLength,\n\t\t\t\t\tstartOffset + tokenLength,\n\t\t\t\t\tleadingHtmlStart\n\t\t\t\t)\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'block-closer':\n\t\t\t// If we're missing an opener we're in trouble\n\t\t\t// This is an error.\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\t// We have options\n\t\t\t\t// - assume an implicit opener\n\t\t\t\t// - assume _this_ is the opener\n\t\t\t\t// - give up and close out the document.\n\t\t\t\taddFreeform();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// If we're not nesting then this is easy - close the block.\n\t\t\tif ( 1 === stackDepth ) {\n\t\t\t\taddBlockFromStack( startOffset );\n\t\t\t\toffset = startOffset + tokenLength;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Otherwise we're nested and we have to close out the current\n\t\t\t// block and add it as a innerBlock to the parent.\n\t\t\tconst stackTop = /** @type {ParsedFrame} */ ( stack.pop() );\n\t\t\tconst html = document.substr(\n\t\t\t\tstackTop.prevOffset,\n\t\t\t\tstartOffset - stackTop.prevOffset\n\t\t\t);\n\t\t\tstackTop.block.innerHTML += html;\n\t\t\tstackTop.block.innerContent.push( html );\n\t\t\tstackTop.prevOffset = startOffset + tokenLength;\n\n\t\t\taddInnerBlock(\n\t\t\t\tstackTop.block,\n\t\t\t\tstackTop.tokenStart,\n\t\t\t\tstackTop.tokenLength,\n\t\t\t\tstartOffset + tokenLength\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\t// This is an error.\n\t\t\taddFreeform();\n\t\t\treturn false;\n\t}\n}\n\n/**\n * Parse JSON if valid, otherwise return null\n *\n * Note that JSON coming from the block comment\n * delimiters is constrained to be an object\n * and cannot be things like `true` or `null`\n *\n * @param {string} input JSON input string to parse\n * @return {Object|null} parsed JSON if valid\n */\nfunction parseJSON( input ) {\n\ttry {\n\t\treturn JSON.parse( input );\n\t} catch ( e ) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Finds the next token in the document.\n *\n * @return {Token|null} The next matched token.\n */\nfunction nextToken() {\n\t// Aye the magic\n\t// we're using a single RegExp to tokenize the block comment delimiters\n\t// we're also using a trick here because the only difference between a\n\t// block opener and a block closer is the leading `/` before `wp:` (and\n\t// a closer has no attributes). we can trap them both and process the\n\t// match back in JavaScript to see which one it was.\n\tconst matches = tokenizer.exec( document );\n\n\t// We have no more tokens.\n\tif ( null === matches ) {\n\t\treturn null;\n\t}\n\n\tconst startedAt = matches.index;\n\tconst [\n\t\tmatch,\n\t\tcloserMatch,\n\t\tnamespaceMatch,\n\t\tnameMatch,\n\t\tattrsMatch /* Internal/unused. */,\n\t\t,\n\t\tvoidMatch,\n\t] = matches;\n\n\tconst length = match.length;\n\tconst isCloser = !! closerMatch;\n\tconst isVoid = !! voidMatch;\n\tconst namespace = namespaceMatch || 'core/';\n\tconst name = namespace + nameMatch;\n\tconst hasAttrs = !! attrsMatch;\n\tconst attrs = hasAttrs ? parseJSON( attrsMatch ) : {};\n\n\t// This state isn't allowed\n\t// This is an error.\n\tif ( isCloser && ( isVoid || hasAttrs ) ) {\n\t\t// We can ignore them since they don't hurt anything\n\t\t// we may warn against this at some point or reject it.\n\t}\n\n\tif ( isVoid ) {\n\t\treturn [ 'void-block', name, attrs, startedAt, length ];\n\t}\n\n\tif ( isCloser ) {\n\t\treturn [ 'block-closer', name, null, startedAt, length ];\n\t}\n\n\treturn [ 'block-opener', name, attrs, startedAt, length ];\n}\n\n/**\n * Adds a freeform block to the output.\n *\n * @param {number} [rawLength]\n */\nfunction addFreeform( rawLength ) {\n\tconst length = rawLength ? rawLength : document.length - offset;\n\n\tif ( 0 === length ) {\n\t\treturn;\n\t}\n\n\toutput.push( Freeform( document.substr( offset, length ) ) );\n}\n\n/**\n * Adds inner block to the parent block.\n *\n * @param {ParsedBlock} block\n * @param {number} tokenStart\n * @param {number} tokenLength\n * @param {number} [lastOffset]\n */\nfunction addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {\n\tconst parent = stack[ stack.length - 1 ];\n\tparent.block.innerBlocks.push( block );\n\tconst html = document.substr(\n\t\tparent.prevOffset,\n\t\ttokenStart - parent.prevOffset\n\t);\n\n\tif ( html ) {\n\t\tparent.block.innerHTML += html;\n\t\tparent.block.innerContent.push( html );\n\t}\n\n\tparent.block.innerContent.push( null );\n\tparent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength;\n}\n\n/**\n * Adds block from the stack to the output.\n *\n * @param {number} [endOffset]\n */\nfunction addBlockFromStack( endOffset ) {\n\tconst { block, leadingHtmlStart, prevOffset, tokenStart } =\n\t\t/** @type {ParsedFrame} */ ( stack.pop() );\n\n\tconst html = endOffset\n\t\t? document.substr( prevOffset, endOffset - prevOffset )\n\t\t: document.substr( prevOffset );\n\n\tif ( html ) {\n\t\tblock.innerHTML += html;\n\t\tblock.innerContent.push( html );\n\t}\n\n\tif ( null !== leadingHtmlStart ) {\n\t\toutput.push(\n\t\t\tFreeform(\n\t\t\t\tdocument.substr(\n\t\t\t\t\tleadingHtmlStart,\n\t\t\t\t\ttokenStart - leadingHtmlStart\n\t\t\t\t)\n\t\t\t)\n\t\t);\n\t}\n\n\toutput.push( block );\n}\n"]} |
+6
-0
@@ -5,2 +5,8 @@ <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. --> | ||
| ## 4.17.0 (2022-09-13) | ||
| ### New Feature | ||
| - Include TypeScript type declarations ([#43722](https://github.com/WordPress/gutenberg/pull/43722)). | ||
| ## 4.16.0 (2022-08-24) | ||
@@ -7,0 +13,0 @@ |
+3
-2
| { | ||
| "name": "@wordpress/block-serialization-default-parser", | ||
| "version": "4.16.1-next.957ca95e4c.0", | ||
| "version": "4.17.0", | ||
| "description": "Block serialization specification parser for WordPress posts.", | ||
@@ -28,2 +28,3 @@ "author": "The WordPress Contributors", | ||
| "react-native": "src/index", | ||
| "types": "build-types", | ||
| "sideEffects": false, | ||
@@ -36,3 +37,3 @@ "dependencies": { | ||
| }, | ||
| "gitHead": "272a74bbbaab10ee24424eafe9578e705fbfbbb4" | ||
| "gitHead": "0d732d4b184adcb28cc83087603e81b764390d4b" | ||
| } |
+1
-1
@@ -111,3 +111,3 @@ # Block Serialization Default Parser | ||
| - `Array`: A block-based representation of the input HTML. | ||
| - `ParsedBlock[]`: A block-based representation of the input HTML. | ||
@@ -114,0 +114,0 @@ <!-- END TOKEN(Autogenerated API docs) --> |
+129
-32
@@ -0,7 +1,49 @@ | ||
| /** | ||
| * @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 {'void-block'|'block-opener'|'block-closer'} TokenType | ||
| */ | ||
| /** | ||
| * @typedef {[TokenType, string, Attributes, number, number]} Token | ||
| */ | ||
| /** | ||
| * Matches block comment delimiters | ||
@@ -50,2 +92,12 @@ * | ||
| /** | ||
| * 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 ) { | ||
@@ -61,2 +113,8 @@ return { | ||
| /** | ||
| * Constructs a freeform block object. | ||
| * | ||
| * @param {string} innerHTML | ||
| * @return {ParsedBlock} The freeform block object. | ||
| */ | ||
| function Freeform( innerHTML ) { | ||
@@ -66,2 +124,12 @@ 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 ) { | ||
@@ -152,3 +220,3 @@ return { | ||
| * ``` | ||
| * @return {Array} A block-based representation of the input HTML. | ||
| * @return {ParsedBlock[]} A block-based representation of the input HTML. | ||
| */ | ||
@@ -169,6 +237,38 @@ export const parse = ( doc ) => { | ||
| /** | ||
| * 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(); | ||
| if ( next === null ) { | ||
| // If not in a block then flush output. | ||
| if ( 0 === stackDepth ) { | ||
| addFreeform(); | ||
| return false; | ||
| } | ||
| // 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 | ||
| // have to assume that multiple closers are missing | ||
| // and so we'll collapse the whole stack piecewise. | ||
| while ( 0 < stack.length ) { | ||
| addBlockFromStack(); | ||
| } | ||
| return false; | ||
| } | ||
| const [ tokenType, blockName, attrs, startOffset, tokenLength ] = next; | ||
| const stackDepth = stack.length; | ||
@@ -179,29 +279,2 @@ // We may have some HTML soup before the next block. | ||
| 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 | ||
| // 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 | ||
| // 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': | ||
@@ -270,3 +343,3 @@ // easy case is if we stumbled upon a void block | ||
| // block and add it as a innerBlock to the parent. | ||
| const stackTop = stack.pop(); | ||
| const stackTop = /** @type {ParsedFrame} */ ( stack.pop() ); | ||
| const html = document.substr( | ||
@@ -314,2 +387,7 @@ stackTop.prevOffset, | ||
| /** | ||
| * Finds the next token in the document. | ||
| * | ||
| * @return {Token|null} The next matched token. | ||
| */ | ||
| function nextToken() { | ||
@@ -326,3 +404,3 @@ // Aye the magic | ||
| if ( null === matches ) { | ||
| return [ 'no-more-tokens' ]; | ||
| return null; | ||
| } | ||
@@ -367,2 +445,7 @@ | ||
| /** | ||
| * Adds a freeform block to the output. | ||
| * | ||
| * @param {number} [rawLength] | ||
| */ | ||
| function addFreeform( rawLength ) { | ||
@@ -378,2 +461,10 @@ const length = rawLength ? rawLength : document.length - offset; | ||
| /** | ||
| * 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 ) { | ||
@@ -396,4 +487,10 @@ const parent = stack[ stack.length - 1 ]; | ||
| /** | ||
| * Adds block from the stack to the output. | ||
| * | ||
| * @param {number} [endOffset] | ||
| */ | ||
| function addBlockFromStack( endOffset ) { | ||
| const { block, leadingHtmlStart, prevOffset, tokenStart } = stack.pop(); | ||
| const { block, leadingHtmlStart, prevOffset, tokenStart } = | ||
| /** @type {ParsedFrame} */ ( stack.pop() ); | ||
@@ -400,0 +497,0 @@ const html = endOffset |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
156772
16.27%16
33.33%1370
33.14%0
-100%