{
  "version": 3,
  "sources": ["../src/create-interpolate-element.ts"],
  "sourcesContent": ["/**\n * Internal dependencies\n */\nimport {\n\tcreateElement,\n\tcloneElement,\n\tFragment,\n\tisValidElement,\n\ttype Element as ReactElement,\n} from './react';\nimport type {\n\tConversionMap,\n\tInterpolationInput,\n\tInterpolationString,\n} from './types';\n\nlet indoc: string;\nlet offset: number;\nlet output: ( string | ReactElement )[];\nlet stack: Frame[];\n\n/**\n * Matches tags in the localized string\n *\n * This is used for extracting the tag pattern groups for parsing the localized\n * string and along with the map converting it to a react element.\n *\n * There are four references extracted using this tokenizer:\n *\n * match: Full match of the tag (i.e. <strong>, </strong>, <br/>)\n * isClosing: The closing slash, if it exists.\n * name: The name portion of the tag (strong, br) (if )\n * isSelfClosed: The slash on a self closing tag, if it exists.\n */\nconst tokenizer = /<(\\/)?(\\w+)\\s*(\\/)?>/g;\n\ninterface Frame {\n\t/**\n\t * A parent element which may still have nested children not yet parsed.\n\t */\n\telement: ReactElement;\n\n\t/**\n\t * Offset at which parent element first appears.\n\t */\n\ttokenStart: number;\n\n\t/**\n\t * Length of string marking start of parent element.\n\t */\n\ttokenLength: number;\n\n\t/**\n\t * Running offset at which parsing should continue.\n\t */\n\tprevOffset?: number;\n\n\t/**\n\t * Offset at which last closing element finished, used for finding text between elements.\n\t */\n\tleadingTextStart?: number | null;\n\n\t/**\n\t * Children.\n\t */\n\tchildren: ( string | ReactElement )[];\n}\n\n/**\n * Tracks recursive-descent parse state.\n *\n * This is a Stack frame holding parent elements until all children have been\n * parsed.\n *\n * @private\n * @param element          A parent element which may still have\n *                         nested children not yet parsed.\n * @param tokenStart       Offset at which parent element first\n *                         appears.\n * @param tokenLength      Length of string marking start of parent\n *                         element.\n * @param prevOffset       Running offset at which parsing should\n *                         continue.\n * @param leadingTextStart Offset at which last closing element\n *                         finished, used for finding text between\n *                         elements.\n *\n * @return The stack frame tracking parse progress.\n */\nfunction createFrame(\n\telement: ReactElement,\n\ttokenStart: number,\n\ttokenLength: number,\n\tprevOffset?: number,\n\tleadingTextStart?: number | null\n): Frame {\n\treturn {\n\t\telement,\n\t\ttokenStart,\n\t\ttokenLength,\n\t\tprevOffset,\n\t\tleadingTextStart,\n\t\tchildren: [],\n\t};\n}\n\n/**\n * This function creates an interpolated element from a passed in string with\n * specific tags matching how the string should be converted to an element via\n * the conversion map value.\n *\n * @example\n * For example, for the given string:\n *\n * \"This is a <span>string</span> with <a>a link</a> and a self-closing\n * <CustomComponentB/> tag\"\n *\n * You would have something like this as the conversionMap value:\n *\n * ```js\n * {\n *     span: <span />,\n *     a: <a href={ 'https://github.com' } />,\n *     CustomComponentB: <CustomComponent />,\n * }\n * ```\n *\n * @param  interpolatedString The interpolation string to be parsed.\n * @param  conversionMap      The map used to convert the string to\n *                            a react element.\n * @throws {TypeError}\n * @return A wp element.\n */\nfunction createInterpolateElement< Input extends InterpolationInput >(\n\tinterpolatedString: Input,\n\tconversionMap: ConversionMap< InterpolationString< Input > >\n): ReactElement {\n\tindoc = interpolatedString;\n\toffset = 0;\n\toutput = [];\n\tstack = [];\n\ttokenizer.lastIndex = 0;\n\n\tif ( ! isValidConversionMap( conversionMap ) ) {\n\t\tthrow new TypeError(\n\t\t\t'The conversionMap provided is not valid. It must be an object with values that are React Elements'\n\t\t);\n\t}\n\n\tdo {\n\t\t// twiddle our thumbs\n\t} while ( proceed( conversionMap ) );\n\treturn createElement( Fragment, null, ...output );\n}\n\n/**\n * Validate conversion map.\n *\n * A map is considered valid if it's an object and every value in the object\n * is a React Element\n *\n * @private\n *\n * @param conversionMap The map being validated.\n *\n * @return True means the map is valid.\n */\nconst isValidConversionMap = (\n\tconversionMap: Record< string, ReactElement >\n): boolean => {\n\tconst isObject =\n\t\ttypeof conversionMap === 'object' && conversionMap !== null;\n\tconst values = isObject && Object.values( conversionMap );\n\treturn (\n\t\tisObject &&\n\t\tvalues.length > 0 &&\n\t\tvalues.every( ( element ) => isValidElement( element ) )\n\t);\n};\n\ntype TokenType = 'no-more-tokens' | 'self-closed' | 'opener' | 'closer';\ntype TokenResult =\n\t| [ TokenType & 'no-more-tokens' ]\n\t| [\n\t\t\tTokenType & ( 'self-closed' | 'opener' | 'closer' ),\n\t\t\tstring,\n\t\t\tnumber,\n\t\t\tnumber,\n\t  ];\n\n/**\n * This is the iterator over the matches in the string.\n *\n * @private\n *\n * @param conversionMap The conversion map for the string.\n *\n * @return true for continuing to iterate, false for finished.\n */\nfunction proceed( conversionMap: Record< string, ReactElement > ): boolean {\n\tconst next = nextToken();\n\tconst [ tokenType, name, startOffset, tokenLength ] = next;\n\tconst stackDepth = stack.length;\n\tconst leadingTextStart = startOffset > offset ? offset : null;\n\tif ( name && ! conversionMap[ name ] ) {\n\t\taddText();\n\t\treturn false;\n\t}\n\tswitch ( tokenType ) {\n\t\tcase 'no-more-tokens':\n\t\t\tif ( stackDepth !== 0 ) {\n\t\t\t\tconst { leadingTextStart: stackLeadingText, tokenStart } =\n\t\t\t\t\tstack.pop();\n\t\t\t\toutput.push( indoc.substr( stackLeadingText, tokenStart ) );\n\t\t\t}\n\t\t\taddText();\n\t\t\treturn false;\n\n\t\tcase 'self-closed':\n\t\t\tif ( 0 === stackDepth ) {\n\t\t\t\tif ( null !== leadingTextStart ) {\n\t\t\t\t\toutput.push(\n\t\t\t\t\t\tindoc.substr(\n\t\t\t\t\t\t\tleadingTextStart,\n\t\t\t\t\t\t\tstartOffset - leadingTextStart\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\toutput.push( conversionMap[ name ] );\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 element.\n\t\t\taddChild(\n\t\t\t\tcreateFrame( conversionMap[ name ], startOffset, tokenLength )\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'opener':\n\t\t\tstack.push(\n\t\t\t\tcreateFrame(\n\t\t\t\t\tconversionMap[ name ],\n\t\t\t\t\tstartOffset,\n\t\t\t\t\ttokenLength,\n\t\t\t\t\tstartOffset + tokenLength,\n\t\t\t\t\tleadingTextStart\n\t\t\t\t)\n\t\t\t);\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tcase 'closer':\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\tcloseOuterElement( 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 text = indoc.substr(\n\t\t\t\tstackTop.prevOffset,\n\t\t\t\tstartOffset - stackTop.prevOffset\n\t\t\t);\n\t\t\tstackTop.children.push( text );\n\t\t\tstackTop.prevOffset = startOffset + tokenLength;\n\t\t\tconst frame = createFrame(\n\t\t\t\tstackTop.element,\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\tframe.children = stackTop.children;\n\t\t\taddChild( frame );\n\t\t\toffset = startOffset + tokenLength;\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\taddText();\n\t\t\treturn false;\n\t}\n}\n\n/**\n * Grabs the next token match in the string and returns it's details.\n *\n * @private\n *\n * @return An array of details for the token matched.\n */\nfunction nextToken(): TokenResult {\n\tconst matches = tokenizer.exec( indoc );\n\t// We have no more tokens.\n\tif ( null === matches ) {\n\t\treturn [ 'no-more-tokens' ];\n\t}\n\tconst startedAt = matches.index;\n\tconst [ match, isClosing, name, isSelfClosed ] = matches;\n\tconst length = match.length;\n\tif ( isSelfClosed ) {\n\t\treturn [ 'self-closed', name, startedAt, length ];\n\t}\n\tif ( isClosing ) {\n\t\treturn [ 'closer', name, startedAt, length ];\n\t}\n\treturn [ 'opener', name, startedAt, length ];\n}\n\n/**\n * Pushes text extracted from the indoc string to the output stack given the\n * current rawLength value and offset (if rawLength is provided ) or the\n * indoc.length and offset.\n *\n * @private\n */\nfunction addText(): void {\n\tconst length = indoc.length - offset;\n\tif ( 0 === length ) {\n\t\treturn;\n\t}\n\toutput.push( indoc.substr( offset, length ) );\n}\n\n/**\n * Pushes a child element to the associated parent element's children for the\n * parent currently active in the stack.\n *\n * @private\n *\n * @param {Frame} frame The Frame containing the child element and it's\n *                      token information.\n */\nfunction addChild( frame: Frame ): void {\n\tconst { element, tokenStart, tokenLength, prevOffset, children } = frame;\n\tconst parent = stack[ stack.length - 1 ];\n\tconst text = indoc.substr(\n\t\tparent.prevOffset,\n\t\ttokenStart - parent.prevOffset\n\t);\n\n\tif ( text ) {\n\t\tparent.children.push( text );\n\t}\n\n\tparent.children.push( cloneElement( element, null, ...children ) );\n\tparent.prevOffset = prevOffset ? prevOffset : tokenStart + tokenLength;\n}\n\n/**\n * This is called for closing tags. It creates the element currently active in\n * the stack.\n *\n * @private\n *\n * @param {number} endOffset Offset at which the closing tag for the element\n *                           begins in the string. If this is greater than the\n *                           prevOffset attached to the element, then this\n *                           helps capture any remaining nested text nodes in\n *                           the element.\n */\nfunction closeOuterElement( endOffset: number ): void {\n\tconst { element, leadingTextStart, prevOffset, tokenStart, children } =\n\t\tstack.pop();\n\n\tconst text = endOffset\n\t\t? indoc.substr( prevOffset, endOffset - prevOffset )\n\t\t: indoc.substr( prevOffset );\n\n\tif ( text ) {\n\t\tchildren.push( text );\n\t}\n\n\tif ( null !== leadingTextStart ) {\n\t\toutput.push(\n\t\t\tindoc.substr( leadingTextStart, tokenStart - leadingTextStart )\n\t\t);\n\t}\n\n\toutput.push( cloneElement( element, null, ...children ) );\n}\n\nexport default createInterpolateElement;\n"],
  "mappings": "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",
  "names": []
}
