pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
1 lines • 9.58 kB
Source Map (JSON)
{"version":3,"file":"parseTaggedText.mjs","sources":["../../../../../src/scene/text/canvas/utils/parseTaggedText.ts"],"sourcesContent":["import type { TextStyle, TextStyleOptions } from '../../TextStyle';\n\n/**\n * Represents a run of text with a specific style.\n * Used internally for tagged text rendering.\n * @internal\n */\nexport interface TextStyleRun\n{\n /** The text content of this run */\n text: string;\n /** The computed style for this run (base style merged with tag overrides) */\n style: TextStyle;\n}\n\n/**\n * Checks whether the given style has tagStyles defined with at least one entry.\n * @param style - The TextStyle to check\n * @returns True if tagStyles is defined and has entries\n * @internal\n */\nexport function hasTagStyles(style: TextStyle): boolean\n{\n return !!style.tagStyles && Object.keys(style.tagStyles).length > 0;\n}\n\n/**\n * Checks whether the text contains potential tag markup.\n * This is a quick check before attempting to parse.\n * @param text - The text to check\n * @returns True if text contains '<' character\n * @internal\n */\nexport function hasTagMarkup(text: string): boolean\n{\n return text.includes('<');\n}\n\n/**\n * Creates a merged TextStyle from a base style and tag style overrides.\n * @param baseStyle - The base TextStyle\n * @param overrides - Style overrides from the tag\n * @returns A new TextStyle with merged properties\n * @internal\n */\nfunction createMergedStyle(baseStyle: TextStyle, overrides: TextStyleOptions): TextStyle\n{\n return baseStyle.clone().assign(overrides);\n}\n\n/**\n * Parses text with tag markup into an array of styled runs.\n * Supports simple open/close tags like `<red>text</red>`.\n * Nested tags are supported via a stack - inner tags inherit from outer tags.\n * Unknown tags (not in tagStyles) are treated as literal text.\n * @param text - The text to parse\n * @param style - The base TextStyle containing tagStyles\n * @returns Array of TextStyleRun objects\n * @internal\n */\nexport function parseTaggedText(text: string, style: TextStyle): TextStyleRun[]\n{\n const runs: TextStyleRun[] = [];\n const tagStyles = style.tagStyles;\n\n // If no tagStyles or no potential tags, return single run with base style\n if (!hasTagStyles(style) || !hasTagMarkup(text))\n {\n runs.push({ text, style });\n\n return runs;\n }\n\n // Stack of active styles (for nested tags)\n const styleStack: TextStyle[] = [style];\n // Stack of active tag names (to match closing tags)\n const tagStack: string[] = [];\n\n let currentText = '';\n let i = 0;\n\n while (i < text.length)\n {\n const char = text[i];\n\n if (char === '<')\n {\n // Find the closing bracket\n const closeIndex = text.indexOf('>', i);\n\n if (closeIndex === -1)\n {\n // No closing bracket - treat as literal\n currentText += char;\n i++;\n continue;\n }\n\n const tagContent = text.slice(i + 1, closeIndex);\n\n // Check if it's a closing tag\n if (tagContent.startsWith('/'))\n {\n const closingTagName = tagContent.slice(1).trim();\n\n // Check if this closing tag matches the most recent opening tag\n if (tagStack.length > 0 && tagStack[tagStack.length - 1] === closingTagName)\n {\n // Flush current text with current style\n if (currentText.length > 0)\n {\n runs.push({\n text: currentText,\n style: styleStack[styleStack.length - 1]\n });\n currentText = '';\n }\n\n // Pop the style and tag stacks\n styleStack.pop();\n tagStack.pop();\n i = closeIndex + 1;\n continue;\n }\n else\n {\n // Mismatched closing tag - treat as literal\n currentText += text.slice(i, closeIndex + 1);\n i = closeIndex + 1;\n continue;\n }\n }\n else\n {\n // Opening tag\n const tagName = tagContent.trim();\n\n // Check if this tag is in tagStyles\n if (tagStyles[tagName])\n {\n // Flush current text with current style\n if (currentText.length > 0)\n {\n runs.push({\n text: currentText,\n style: styleStack[styleStack.length - 1]\n });\n currentText = '';\n }\n\n // Create merged style from current style and tag overrides\n const currentStyle = styleStack[styleStack.length - 1];\n const mergedStyle = createMergedStyle(currentStyle, tagStyles[tagName]);\n\n styleStack.push(mergedStyle);\n tagStack.push(tagName);\n i = closeIndex + 1;\n continue;\n }\n else\n {\n // Unknown tag - treat as literal\n currentText += text.slice(i, closeIndex + 1);\n i = closeIndex + 1;\n continue;\n }\n }\n }\n else\n {\n currentText += char;\n i++;\n }\n }\n\n // Flush any remaining text\n if (currentText.length > 0)\n {\n runs.push({\n text: currentText,\n style: styleStack[styleStack.length - 1]\n });\n }\n\n return runs;\n}\n\n/**\n * Extracts plain text from tagged text (strips all tags).\n * Useful for cache keys and debugging.\n * @param text - The tagged text\n * @param style - The TextStyle containing tagStyles\n * @returns Plain text with tags removed\n * @internal\n */\nexport function getPlainText(text: string, style: TextStyle): string\n{\n if (!hasTagStyles(style) || !hasTagMarkup(text))\n {\n return text;\n }\n\n const runs = parseTaggedText(text, style);\n\n return runs.map((run) => run.text).join('');\n}\n"],"names":[],"mappings":"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"}