pangu
Version:
Paranoid text spacing for good readability, to automatically insert whitespace between CJK (Chinese, Japanese, Korean) and half-width characters (alphabetical letters, numerical digits and symbols).
1 lines • 64.3 kB
Source Map (JSON)
{"version":3,"file":"cli.cjs","sources":["../shared/index.js","../browser/pangu.js","cli.js"],"sourcesContent":["var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\nconst CJK = \"\\u2E80-\\u2EFF\\u2F00-\\u2FDF\\u3040-\\u309F\\u30A0-\\u30FA\\u30FC-\\u30FF\\u3100-\\u312F\\u3200-\\u32FF\\u3400-\\u4DBF\\u4E00-\\u9FFF\\uF900-\\uFAFF\";\nconst AN = \"A-Za-z0-9\";\nconst A = \"A-Za-z\";\nconst UPPER_AN = \"A-Z0-9\";\nconst OPERATORS_BASE = \"\\\\+\\\\*=&\";\nconst OPERATORS_WITH_HYPHEN = `${OPERATORS_BASE}\\\\-`;\nconst OPERATORS_NO_HYPHEN = OPERATORS_BASE;\nconst GRADE_OPERATORS = \"\\\\+\\\\-\\\\*\";\nconst QUOTES = '`\"\\u05F4';\nconst LEFT_BRACKETS_BASIC = \"\\\\(\\\\[\\\\{\";\nconst RIGHT_BRACKETS_BASIC = \"\\\\)\\\\]\\\\}\";\nconst LEFT_BRACKETS_EXTENDED = \"\\\\(\\\\[\\\\{<>\\u201C\";\nconst RIGHT_BRACKETS_EXTENDED = \"\\\\)\\\\]\\\\}<>\\u201D\";\nconst ANS_CJK_AFTER = `${A}\\u0370-\\u03FF0-9@\\\\$%\\\\^&\\\\*\\\\-\\\\+\\\\\\\\=\\xA1-\\xFF\\u2150-\\u218F\\u2700\\u2014\\u27BF`;\nconst ANS_BEFORE_CJK = `${A}\\u0370-\\u03FF0-9\\\\$%\\\\^&\\\\*\\\\-\\\\+\\\\\\\\=\\xA1-\\xFF\\u2150-\\u218F\\u2700\\u2014\\u27BF`;\nconst FILE_PATH_DIRS = \"home|root|usr|etc|var|opt|tmp|dev|mnt|proc|sys|bin|boot|lib|media|run|sbin|srv|node_modules|path|project|src|dist|test|tests|docs|templates|assets|public|static|config|scripts|tools|build|out|target|your|\\\\.claude|\\\\.git|\\\\.vscode\";\nconst FILE_PATH_CHARS = \"[A-Za-z0-9_\\\\-\\\\.@\\\\+\\\\*]+\";\nconst UNIX_ABSOLUTE_FILE_PATH = new RegExp(`/(?:\\\\.?(?:${FILE_PATH_DIRS})|\\\\.(?:[A-Za-z0-9_\\\\-]+))(?:/${FILE_PATH_CHARS})*`);\nconst UNIX_RELATIVE_FILE_PATH = new RegExp(`(?:\\\\./)?(?:${FILE_PATH_DIRS})(?:/${FILE_PATH_CHARS})+`);\nconst WINDOWS_FILE_PATH = /[A-Z]:\\\\(?:[A-Za-z0-9_\\-\\. ]+\\\\?)+/;\nconst ANY_CJK = new RegExp(`[${CJK}]`);\nconst CJK_PUNCTUATION = new RegExp(`([${CJK}])([!;,\\\\?:]+)(?=[${CJK}${AN}])`, \"g\");\nconst AN_PUNCTUATION_CJK = new RegExp(`([${AN}])([!;,\\\\?]+)([${CJK}])`, \"g\");\nconst CJK_TILDE = new RegExp(`([${CJK}])(~+)(?!=)(?=[${CJK}${AN}])`, \"g\");\nconst CJK_TILDE_EQUALS = new RegExp(`([${CJK}])(~=)`, \"g\");\nconst CJK_PERIOD = new RegExp(`([${CJK}])(\\\\.)(?![${AN}\\\\./])(?=[${CJK}${AN}])`, \"g\");\nconst AN_PERIOD_CJK = new RegExp(`([${AN}])(\\\\.)([${CJK}])`, \"g\");\nconst AN_COLON_CJK = new RegExp(`([${AN}])(:)([${CJK}])`, \"g\");\nconst DOTS_CJK = new RegExp(`([\\\\.]{2,}|\\u2026)([${CJK}])`, \"g\");\nconst FIX_CJK_COLON_ANS = new RegExp(`([${CJK}])\\\\:([${UPPER_AN}\\\\(\\\\)])`, \"g\");\nconst CJK_QUOTE = new RegExp(`([${CJK}])([${QUOTES}])`, \"g\");\nconst QUOTE_CJK = new RegExp(`([${QUOTES}])([${CJK}])`, \"g\");\nconst FIX_QUOTE_ANY_QUOTE = new RegExp(`([${QUOTES}]+)[ ]*(.+?)[ ]*([${QUOTES}]+)`, \"g\");\nconst QUOTE_AN = new RegExp(`([\\u201D])([${AN}])`, \"g\");\nconst CJK_QUOTE_AN = new RegExp(`([${CJK}])(\")([${AN}])`, \"g\");\nconst CJK_SINGLE_QUOTE_BUT_POSSESSIVE = new RegExp(`([${CJK}])('[^s])`, \"g\");\nconst SINGLE_QUOTE_CJK = new RegExp(`(')([${CJK}])`, \"g\");\nconst FIX_POSSESSIVE_SINGLE_QUOTE = new RegExp(`([${AN}${CJK}])( )('s)`, \"g\");\nconst HASH_ANS_CJK_HASH = new RegExp(`([${CJK}])(#)([${CJK}]+)(#)([${CJK}])`, \"g\");\nconst CJK_HASH = new RegExp(`([${CJK}])(#([^ ]))`, \"g\");\nconst HASH_CJK = new RegExp(`(([^ ])#)([${CJK}])`, \"g\");\nconst CJK_OPERATOR_ANS = new RegExp(`([${CJK}])([${OPERATORS_WITH_HYPHEN}])([${AN}])`, \"g\");\nconst ANS_OPERATOR_CJK = new RegExp(`([${AN}])([${OPERATORS_WITH_HYPHEN}])([${CJK}])`, \"g\");\nconst ANS_OPERATOR_ANS = new RegExp(`([${AN}])([${OPERATORS_NO_HYPHEN}])([${AN}])`, \"g\");\nconst ANS_HYPHEN_ANS_NOT_COMPOUND = new RegExp(`([A-Za-z])(-(?![a-z]))([A-Za-z0-9])|([A-Za-z]+[0-9]+)(-(?![a-z]))([0-9])|([0-9])(-(?![a-z0-9]))([A-Za-z])`, \"g\");\nconst CJK_SLASH_CJK = new RegExp(`([${CJK}])([/])([${CJK}])`, \"g\");\nconst CJK_SLASH_ANS = new RegExp(`([${CJK}])([/])([${AN}])`, \"g\");\nconst ANS_SLASH_CJK = new RegExp(`([${AN}])([/])([${CJK}])`, \"g\");\nconst ANS_SLASH_ANS = new RegExp(`([${AN}])([/])([${AN}])`, \"g\");\nconst SINGLE_LETTER_GRADE_CJK = new RegExp(`\\\\b([${A}])([${GRADE_OPERATORS}])([${CJK}])`, \"g\");\nconst CJK_LESS_THAN = new RegExp(`([${CJK}])(<)([${AN}])`, \"g\");\nconst LESS_THAN_CJK = new RegExp(`([${AN}])(<)([${CJK}])`, \"g\");\nconst CJK_GREATER_THAN = new RegExp(`([${CJK}])(>)([${AN}])`, \"g\");\nconst GREATER_THAN_CJK = new RegExp(`([${AN}])(>)([${CJK}])`, \"g\");\nconst ANS_LESS_THAN_ANS = new RegExp(`([${AN}])(<)([${AN}])`, \"g\");\nconst ANS_GREATER_THAN_ANS = new RegExp(`([${AN}])(>)([${AN}])`, \"g\");\nconst CJK_LEFT_BRACKET = new RegExp(`([${CJK}])([${LEFT_BRACKETS_EXTENDED}])`, \"g\");\nconst RIGHT_BRACKET_CJK = new RegExp(`([${RIGHT_BRACKETS_EXTENDED}])([${CJK}])`, \"g\");\nconst ANS_CJK_LEFT_BRACKET_ANY_RIGHT_BRACKET = new RegExp(`([${AN}${CJK}])[ ]*([\\u201C])([${AN}${CJK}\\\\-_ ]+)([\\u201D])`, \"g\");\nconst LEFT_BRACKET_ANY_RIGHT_BRACKET_ANS_CJK = new RegExp(`([\\u201C])([${AN}${CJK}\\\\-_ ]+)([\\u201D])[ ]*([${AN}${CJK}])`, \"g\");\nconst AN_LEFT_BRACKET = new RegExp(`([${AN}])(?<!\\\\.[${AN}]*)([${LEFT_BRACKETS_BASIC}])`, \"g\");\nconst RIGHT_BRACKET_AN = new RegExp(`([${RIGHT_BRACKETS_BASIC}])([${AN}])`, \"g\");\nconst CJK_UNIX_ABSOLUTE_FILE_PATH = new RegExp(`([${CJK}])(${UNIX_ABSOLUTE_FILE_PATH.source})`, \"g\");\nconst CJK_UNIX_RELATIVE_FILE_PATH = new RegExp(`([${CJK}])(${UNIX_RELATIVE_FILE_PATH.source})`, \"g\");\nconst CJK_WINDOWS_PATH = new RegExp(`([${CJK}])(${WINDOWS_FILE_PATH.source})`, \"g\");\nconst UNIX_ABSOLUTE_FILE_PATH_SLASH_CJK = new RegExp(`(${UNIX_ABSOLUTE_FILE_PATH.source}/)([${CJK}])`, \"g\");\nconst UNIX_RELATIVE_FILE_PATH_SLASH_CJK = new RegExp(`(${UNIX_RELATIVE_FILE_PATH.source}/)([${CJK}])`, \"g\");\nconst CJK_ANS = new RegExp(`([${CJK}])([${ANS_CJK_AFTER}])`, \"g\");\nconst ANS_CJK = new RegExp(`([${ANS_BEFORE_CJK}])([${CJK}])`, \"g\");\nconst S_A = new RegExp(`(%)([${A}])`, \"g\");\nconst MIDDLE_DOT = /([ ]*)([\\u00b7\\u2022\\u2027])([ ]*)/g;\nclass PlaceholderReplacer {\n constructor(placeholder, startDelimiter, endDelimiter) {\n __publicField(this, \"items\", []);\n __publicField(this, \"index\", 0);\n __publicField(this, \"pattern\");\n this.placeholder = placeholder;\n this.startDelimiter = startDelimiter;\n this.endDelimiter = endDelimiter;\n const escapedStart = this.startDelimiter.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const escapedEnd = this.endDelimiter.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n this.pattern = new RegExp(`${escapedStart}${this.placeholder}(\\\\d+)${escapedEnd}`, \"g\");\n }\n store(item) {\n this.items[this.index] = item;\n return `${this.startDelimiter}${this.placeholder}${this.index++}${this.endDelimiter}`;\n }\n restore(text) {\n return text.replace(this.pattern, (_match, index) => {\n return this.items[parseInt(index, 10)] || \"\";\n });\n }\n reset() {\n this.items = [];\n this.index = 0;\n }\n}\nclass Pangu {\n constructor() {\n __publicField(this, \"version\");\n this.version = \"7.2.0\";\n }\n spacingText(text) {\n if (typeof text !== \"string\") {\n console.warn(`spacingText(text) only accepts string but got ${typeof text}`);\n return text;\n }\n if (text.length <= 1 || !ANY_CJK.test(text)) {\n return text;\n }\n const self = this;\n let newText = text;\n const backtickManager = new PlaceholderReplacer(\"BACKTICK_CONTENT_\", \"\\uE004\", \"\\uE005\");\n newText = newText.replace(/`([^`]+)`/g, (_match, content) => {\n return `\\`${backtickManager.store(content)}\\``;\n });\n const htmlTagManager = new PlaceholderReplacer(\"HTML_TAG_PLACEHOLDER_\", \"\\uE000\", \"\\uE001\");\n let hasHtmlTags = false;\n if (newText.includes(\"<\")) {\n hasHtmlTags = true;\n const HTML_TAG_PATTERN = /<\\/?[a-zA-Z][a-zA-Z0-9]*(?:\\s+[^>]*)?>/g;\n newText = newText.replace(HTML_TAG_PATTERN, (match) => {\n const processedTag = match.replace(/(\\w+)=\"([^\"]*)\"/g, (_attrMatch, attrName, attrValue) => {\n const processedValue = self.spacingText(attrValue);\n return `${attrName}=\"${processedValue}\"`;\n });\n return htmlTagManager.store(processedTag);\n });\n }\n newText = newText.replace(DOTS_CJK, \"$1 $2\");\n newText = newText.replace(CJK_PUNCTUATION, \"$1$2 \");\n newText = newText.replace(AN_PUNCTUATION_CJK, \"$1$2 $3\");\n newText = newText.replace(CJK_TILDE, \"$1$2 \");\n newText = newText.replace(CJK_TILDE_EQUALS, \"$1 $2 \");\n newText = newText.replace(CJK_PERIOD, \"$1$2 \");\n newText = newText.replace(AN_PERIOD_CJK, \"$1$2 $3\");\n newText = newText.replace(AN_COLON_CJK, \"$1$2 $3\");\n newText = newText.replace(FIX_CJK_COLON_ANS, \"$1\\uFF1A$2\");\n newText = newText.replace(CJK_QUOTE, \"$1 $2\");\n newText = newText.replace(QUOTE_CJK, \"$1 $2\");\n newText = newText.replace(FIX_QUOTE_ANY_QUOTE, \"$1$2$3\");\n newText = newText.replace(QUOTE_AN, \"$1 $2\");\n newText = newText.replace(CJK_QUOTE_AN, \"$1$2 $3\");\n newText = newText.replace(FIX_POSSESSIVE_SINGLE_QUOTE, \"$1's\");\n const singleQuoteCJKManager = new PlaceholderReplacer(\"SINGLE_QUOTE_CJK_PLACEHOLDER_\", \"\\uE030\", \"\\uE031\");\n const SINGLE_QUOTE_PURE_CJK = new RegExp(`(')([${CJK}]+)(')`, \"g\");\n newText = newText.replace(SINGLE_QUOTE_PURE_CJK, (match) => {\n return singleQuoteCJKManager.store(match);\n });\n newText = newText.replace(CJK_SINGLE_QUOTE_BUT_POSSESSIVE, \"$1 $2\");\n newText = newText.replace(SINGLE_QUOTE_CJK, \"$1 $2\");\n newText = singleQuoteCJKManager.restore(newText);\n const textLength = newText.length;\n const slashCount = (newText.match(/\\//g) || []).length;\n if (slashCount === 0) {\n if (textLength >= 5) {\n newText = newText.replace(HASH_ANS_CJK_HASH, \"$1 $2$3$4 $5\");\n }\n newText = newText.replace(CJK_HASH, \"$1 $2\");\n newText = newText.replace(HASH_CJK, \"$1 $3\");\n } else if (slashCount <= 1) {\n if (textLength >= 5) {\n newText = newText.replace(HASH_ANS_CJK_HASH, \"$1 $2$3$4 $5\");\n }\n newText = newText.replace(CJK_HASH, \"$1 $2\");\n newText = newText.replace(HASH_CJK, \"$1 $3\");\n } else {\n if (textLength >= 5) {\n newText = newText.replace(HASH_ANS_CJK_HASH, \"$1 $2$3$4 $5\");\n }\n newText = newText.replace(new RegExp(`([^/])([${CJK}])(#[A-Za-z0-9]+)$`), \"$1$2 $3\");\n }\n const compoundWordManager = new PlaceholderReplacer(\"COMPOUND_WORD_PLACEHOLDER_\", \"\\uE010\", \"\\uE011\");\n const COMPOUND_WORD_PATTERN = /\\b(?:[A-Za-z0-9]*[a-z][A-Za-z0-9]*-[A-Za-z0-9]+|[A-Za-z0-9]+-[A-Za-z0-9]*[a-z][A-Za-z0-9]*|[A-Za-z]+-[0-9]+|[A-Za-z]+[0-9]+-[A-Za-z0-9]+)(?:-[A-Za-z0-9]+)*\\b/g;\n newText = newText.replace(COMPOUND_WORD_PATTERN, (match) => {\n return compoundWordManager.store(match);\n });\n newText = newText.replace(SINGLE_LETTER_GRADE_CJK, \"$1$2 $3\");\n newText = newText.replace(CJK_OPERATOR_ANS, \"$1 $2 $3\");\n newText = newText.replace(ANS_OPERATOR_CJK, \"$1 $2 $3\");\n newText = newText.replace(ANS_OPERATOR_ANS, \"$1 $2 $3\");\n newText = newText.replace(ANS_HYPHEN_ANS_NOT_COMPOUND, (match, ...groups) => {\n if (groups[0] && groups[1] && groups[2]) {\n return `${groups[0]} ${groups[1]} ${groups[2]}`;\n } else if (groups[3] && groups[4] && groups[5]) {\n return `${groups[3]} ${groups[4]} ${groups[5]}`;\n } else if (groups[6] && groups[7] && groups[8]) {\n return `${groups[6]} ${groups[7]} ${groups[8]}`;\n }\n return match;\n });\n newText = newText.replace(CJK_LESS_THAN, \"$1 $2 $3\");\n newText = newText.replace(LESS_THAN_CJK, \"$1 $2 $3\");\n newText = newText.replace(ANS_LESS_THAN_ANS, \"$1 $2 $3\");\n newText = newText.replace(CJK_GREATER_THAN, \"$1 $2 $3\");\n newText = newText.replace(GREATER_THAN_CJK, \"$1 $2 $3\");\n newText = newText.replace(ANS_GREATER_THAN_ANS, \"$1 $2 $3\");\n newText = newText.replace(CJK_UNIX_ABSOLUTE_FILE_PATH, \"$1 $2\");\n newText = newText.replace(CJK_UNIX_RELATIVE_FILE_PATH, \"$1 $2\");\n newText = newText.replace(CJK_WINDOWS_PATH, \"$1 $2\");\n newText = newText.replace(UNIX_ABSOLUTE_FILE_PATH_SLASH_CJK, \"$1 $2\");\n newText = newText.replace(UNIX_RELATIVE_FILE_PATH_SLASH_CJK, \"$1 $2\");\n if (slashCount === 1) {\n const filePathManager = new PlaceholderReplacer(\"FILE_PATH_PLACEHOLDER_\", \"\\uE020\", \"\\uE021\");\n const allFilePathPattern = new RegExp(`(${UNIX_ABSOLUTE_FILE_PATH.source}|${UNIX_RELATIVE_FILE_PATH.source})`, \"g\");\n newText = newText.replace(allFilePathPattern, (match) => {\n return filePathManager.store(match);\n });\n newText = newText.replace(CJK_SLASH_CJK, \"$1 $2 $3\");\n newText = newText.replace(CJK_SLASH_ANS, \"$1 $2 $3\");\n newText = newText.replace(ANS_SLASH_CJK, \"$1 $2 $3\");\n newText = newText.replace(ANS_SLASH_ANS, \"$1 $2 $3\");\n newText = filePathManager.restore(newText);\n }\n newText = compoundWordManager.restore(newText);\n newText = newText.replace(CJK_LEFT_BRACKET, \"$1 $2\");\n newText = newText.replace(RIGHT_BRACKET_CJK, \"$1 $2\");\n newText = newText.replace(ANS_CJK_LEFT_BRACKET_ANY_RIGHT_BRACKET, \"$1 $2$3$4\");\n newText = newText.replace(LEFT_BRACKET_ANY_RIGHT_BRACKET_ANS_CJK, \"$1$2$3 $4\");\n newText = newText.replace(AN_LEFT_BRACKET, \"$1 $2\");\n newText = newText.replace(RIGHT_BRACKET_AN, \"$1 $2\");\n newText = newText.replace(CJK_ANS, \"$1 $2\");\n newText = newText.replace(ANS_CJK, \"$1 $2\");\n newText = newText.replace(S_A, \"$1 $2\");\n newText = newText.replace(MIDDLE_DOT, \"\\u30FB\");\n const fixBracketSpacing = (text2) => {\n const bracketPatterns = [\n { pattern: /<([^<>]*)>/g, open: \"<\", close: \">\" },\n { pattern: /\\(([^()]*)\\)/g, open: \"(\", close: \")\" },\n { pattern: /\\[([^\\[\\]]*)\\]/g, open: \"[\", close: \"]\" },\n { pattern: /\\{([^{}]*)\\}/g, open: \"{\", close: \"}\" }\n ];\n for (const { pattern, open, close } of bracketPatterns) {\n text2 = text2.replace(pattern, (_match, innerContent) => {\n if (!innerContent) {\n return `${open}${close}`;\n }\n const trimmedContent = innerContent.replace(/^ +| +$/g, \"\");\n return `${open}${trimmedContent}${close}`;\n });\n }\n return text2;\n };\n newText = fixBracketSpacing(newText);\n if (hasHtmlTags) {\n newText = htmlTagManager.restore(newText);\n }\n newText = backtickManager.restore(newText);\n return newText;\n }\n hasProperSpacing(text) {\n return this.spacingText(text) === text;\n }\n}\nconst pangu = new Pangu();\nexport {\n ANY_CJK,\n Pangu,\n pangu as default,\n pangu\n};\n//# sourceMappingURL=index.js.map\n","var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\nimport { Pangu } from \"../shared/index.js\";\nclass DomWalker {\n static collectTextNodes(contextNode, reverse = false) {\n const nodes = [];\n if (!contextNode || contextNode instanceof DocumentFragment) {\n return nodes;\n }\n const walker = document.createTreeWalker(contextNode, NodeFilter.SHOW_TEXT, {\n acceptNode: (node) => {\n if (!node.nodeValue || !/\\S/.test(node.nodeValue)) {\n return NodeFilter.FILTER_REJECT;\n }\n let currentNode = node;\n while (currentNode) {\n if (currentNode instanceof Element) {\n if (this.ignoredTags.test(currentNode.nodeName)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (this.isContentEditable(currentNode)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (currentNode.classList.contains(this.ignoredClass)) {\n return NodeFilter.FILTER_REJECT;\n }\n }\n currentNode = currentNode.parentNode;\n }\n return NodeFilter.FILTER_ACCEPT;\n }\n });\n while (walker.nextNode()) {\n nodes.push(walker.currentNode);\n }\n return reverse ? nodes.reverse() : nodes;\n }\n static canIgnoreNode(node) {\n let currentNode = node;\n if (currentNode && (this.isSpecificTag(currentNode, this.ignoredTags) || this.isContentEditable(currentNode) || this.hasIgnoredClass(currentNode))) {\n return true;\n }\n while (currentNode.parentNode) {\n currentNode = currentNode.parentNode;\n if (currentNode && (this.isSpecificTag(currentNode, this.ignoredTags) || this.isContentEditable(currentNode))) {\n return true;\n }\n }\n return false;\n }\n static isFirstTextChild(parentNode, targetNode) {\n const { childNodes } = parentNode;\n for (let i = 0; i < childNodes.length; i++) {\n const childNode = childNodes[i];\n if (childNode.nodeType !== Node.COMMENT_NODE && childNode.textContent) {\n return childNode === targetNode;\n }\n }\n return false;\n }\n static isLastTextChild(parentNode, targetNode) {\n const { childNodes } = parentNode;\n for (let i = childNodes.length - 1; i > -1; i--) {\n const childNode = childNodes[i];\n if (childNode.nodeType !== Node.COMMENT_NODE && childNode.textContent) {\n return childNode === targetNode;\n }\n }\n return false;\n }\n static isSpecificTag(node, tagRegex) {\n return !!(node && node.nodeName && tagRegex.test(node.nodeName));\n }\n static isContentEditable(node) {\n return node instanceof HTMLElement && (node.isContentEditable || node.getAttribute(\"g_editable\") === \"true\");\n }\n static hasIgnoredClass(node) {\n if (node instanceof Element && node.classList.contains(this.ignoredClass)) {\n return true;\n }\n if (node.parentNode && node.parentNode instanceof Element && node.parentNode.classList.contains(this.ignoredClass)) {\n return true;\n }\n return false;\n }\n}\n__publicField(DomWalker, \"blockTags\", /^(div|p|h1|h2|h3|h4|h5|h6)$/i);\n__publicField(DomWalker, \"ignoredTags\", /^(code|pre|script|style|textarea|iframe|input)$/i);\n__publicField(DomWalker, \"presentationalTags\", /^(b|code|del|em|i|s|strong|kbd)$/i);\n__publicField(DomWalker, \"spaceLikeTags\", /^(br|hr|i|img|pangu)$/i);\n__publicField(DomWalker, \"spaceSensitiveTags\", /^(a|del|pre|s|strike|u)$/i);\n__publicField(DomWalker, \"ignoredClass\", \"no-pangu-spacing\");\nclass TaskQueue {\n constructor() {\n __publicField(this, \"queue\", []);\n __publicField(this, \"isProcessing\", false);\n __publicField(this, \"onComplete\");\n }\n add(task) {\n this.queue.push(task);\n this.scheduleProcessing();\n }\n clear() {\n this.queue.length = 0;\n this.onComplete = void 0;\n }\n setOnComplete(onComplete) {\n this.onComplete = onComplete;\n }\n get length() {\n return this.queue.length;\n }\n scheduleProcessing() {\n if (!this.isProcessing && this.queue.length > 0) {\n this.isProcessing = true;\n requestIdleCallback((deadline) => this.process(deadline), { timeout: 5e3 });\n }\n }\n process(deadline) {\n var _a;\n while (deadline.timeRemaining() > 0 && this.queue.length > 0) {\n const task = this.queue.shift();\n task == null ? void 0 : task();\n }\n this.isProcessing = false;\n if (this.queue.length > 0) {\n this.scheduleProcessing();\n } else {\n (_a = this.onComplete) == null ? void 0 : _a.call(this);\n }\n }\n}\nclass TaskScheduler {\n constructor() {\n __publicField(this, \"config\", {\n enabled: true,\n chunkSize: 40,\n // Process 40 text nodes per idle cycle\n timeout: 2e3\n // 2 second timeout for idle processing\n });\n __publicField(this, \"taskQueue\", new TaskQueue());\n }\n get queue() {\n return this.taskQueue;\n }\n processInChunks(items, processor, onComplete) {\n if (!this.config.enabled) {\n processor(items);\n onComplete == null ? void 0 : onComplete();\n return;\n }\n if (items.length === 0) {\n onComplete == null ? void 0 : onComplete();\n return;\n }\n if (onComplete) {\n this.taskQueue.setOnComplete(onComplete);\n }\n const chunks = [];\n for (let i = 0; i < items.length; i += this.config.chunkSize) {\n chunks.push(items.slice(i, i + this.config.chunkSize));\n }\n for (const chunk of chunks) {\n this.taskQueue.add(() => {\n processor(chunk);\n });\n }\n }\n clear() {\n this.taskQueue.clear();\n }\n updateConfig(config) {\n Object.assign(this.config, config);\n }\n}\nclass VisibilityDetector {\n constructor() {\n __publicField(this, \"config\", {\n enabled: true,\n commonHiddenPatterns: {\n clipRect: true,\n // clip: rect(1px, 1px, 1px, 1px) patterns\n displayNone: true,\n // display: none\n visibilityHidden: true,\n // visibility: hidden\n opacityZero: true,\n // opacity: 0\n heightWidth1px: true\n // height: 1px; width: 1px\n }\n });\n }\n isElementVisuallyHidden(element) {\n if (!this.config.enabled) {\n return false;\n }\n const style = getComputedStyle(element);\n const patterns = this.config.commonHiddenPatterns;\n if (patterns.displayNone && style.display === \"none\") {\n return true;\n }\n if (patterns.visibilityHidden && style.visibility === \"hidden\") {\n return true;\n }\n if (patterns.opacityZero && parseFloat(style.opacity) === 0) {\n return true;\n }\n if (patterns.clipRect) {\n const clip = style.clip;\n if (clip && (clip.includes(\"rect(1px, 1px, 1px, 1px)\") || clip.includes(\"rect(0px, 0px, 0px, 0px)\") || clip.includes(\"rect(0, 0, 0, 0)\"))) {\n return true;\n }\n }\n if (patterns.heightWidth1px) {\n const height = parseInt(style.height, 10);\n const width = parseInt(style.width, 10);\n if (height === 1 && width === 1) {\n const overflow = style.overflow;\n const position = style.position;\n if (overflow === \"hidden\" && position === \"absolute\") {\n return true;\n }\n }\n }\n return false;\n }\n shouldSkipSpacingAfterNode(node) {\n if (!this.config.enabled) {\n return false;\n }\n let elementToCheck = null;\n if (node instanceof Element) {\n elementToCheck = node;\n } else if (node.parentElement) {\n elementToCheck = node.parentElement;\n }\n if (elementToCheck && this.isElementVisuallyHidden(elementToCheck)) {\n return true;\n }\n let currentElement = elementToCheck == null ? void 0 : elementToCheck.parentElement;\n while (currentElement) {\n if (this.isElementVisuallyHidden(currentElement)) {\n return true;\n }\n currentElement = currentElement.parentElement;\n }\n return false;\n }\n shouldSkipSpacingBeforeNode(node) {\n if (!this.config.enabled) {\n return false;\n }\n let previousNode = node.previousSibling;\n if (!previousNode && node.parentElement) {\n let parent = node.parentElement;\n while (parent && !previousNode) {\n previousNode = parent.previousSibling;\n if (!previousNode) {\n parent = parent.parentElement;\n }\n }\n }\n if (previousNode) {\n if (previousNode instanceof Element && this.isElementVisuallyHidden(previousNode)) {\n return true;\n } else if (previousNode instanceof Text && previousNode.parentElement && this.isElementVisuallyHidden(previousNode.parentElement)) {\n return true;\n }\n }\n return false;\n }\n updateConfig(config) {\n Object.assign(this.config, config);\n if (config.commonHiddenPatterns) {\n Object.assign(this.config.commonHiddenPatterns, config.commonHiddenPatterns);\n }\n }\n}\nfunction once(func) {\n let executed = false;\n return function(...args) {\n if (executed) {\n return void 0;\n }\n executed = true;\n return func(...args);\n };\n}\nfunction debounce(func, delay, mustRunDelay = Infinity) {\n let timer = null;\n let startTime = null;\n return function(...args) {\n const currentTime = Date.now();\n if (timer) {\n clearTimeout(timer);\n }\n if (!startTime) {\n startTime = currentTime;\n }\n if (currentTime - startTime >= mustRunDelay) {\n func(...args);\n startTime = currentTime;\n } else {\n timer = window.setTimeout(() => {\n func(...args);\n }, delay);\n }\n };\n}\nclass BrowserPangu extends Pangu {\n constructor() {\n super(...arguments);\n __publicField(this, \"isAutoSpacingPageExecuted\", false);\n __publicField(this, \"autoSpacingPageObserver\", null);\n __publicField(this, \"taskScheduler\", new TaskScheduler());\n __publicField(this, \"visibilityDetector\", new VisibilityDetector());\n }\n // PUBLIC\n autoSpacingPage({ pageDelayMs = 1e3, nodeDelayMs = 500, nodeMaxWaitMs = 2e3 } = {}) {\n if (!(document.body instanceof Node)) {\n return;\n }\n if (this.isAutoSpacingPageExecuted) {\n return;\n }\n this.isAutoSpacingPageExecuted = true;\n this.waitForVideosToLoad(pageDelayMs, once(() => this.spacingPage()));\n this.setupAutoSpacingPageObserver(nodeDelayMs, nodeMaxWaitMs);\n }\n spacingPage() {\n const title = document.querySelector(\"head > title\");\n if (title) {\n this.spacingNode(title);\n }\n this.spacingNode(document.body);\n }\n spacingNode(contextNode) {\n const textNodes = DomWalker.collectTextNodes(contextNode, true);\n if (this.taskScheduler.config.enabled) {\n this.spacingTextNodesInQueue(textNodes);\n } else {\n this.spacingTextNodes(textNodes);\n }\n }\n stopAutoSpacingPage() {\n if (this.autoSpacingPageObserver) {\n this.autoSpacingPageObserver.disconnect();\n this.autoSpacingPageObserver = null;\n }\n this.isAutoSpacingPageExecuted = false;\n }\n isElementVisuallyHidden(element) {\n return this.visibilityDetector.isElementVisuallyHidden(element);\n }\n // INTERNAL\n // TODO: Refactor this method - it's too large and handles too many responsibilities\n spacingTextNodes(textNodes) {\n let currentTextNode;\n let nextTextNode = null;\n for (let i = 0; i < textNodes.length; i++) {\n currentTextNode = textNodes[i];\n if (!currentTextNode) {\n continue;\n }\n if (DomWalker.canIgnoreNode(currentTextNode)) {\n nextTextNode = currentTextNode;\n continue;\n }\n if (currentTextNode instanceof Text) {\n if (this.visibilityDetector.config.enabled && currentTextNode.data.startsWith(\" \") && this.visibilityDetector.shouldSkipSpacingBeforeNode(currentTextNode)) {\n currentTextNode.data = currentTextNode.data.substring(1);\n }\n if (currentTextNode.data.length === 1 && /[\"\\u201c\\u201d]/.test(currentTextNode.data)) {\n if (currentTextNode.previousSibling) {\n const prevNode = currentTextNode.previousSibling;\n if (prevNode.nodeType === Node.ELEMENT_NODE && prevNode.textContent) {\n const lastChar = prevNode.textContent.slice(-1);\n if (/[\\u4e00-\\u9fff]/.test(lastChar)) {\n currentTextNode.data = ` ${currentTextNode.data}`;\n }\n }\n }\n } else {\n const newText = this.spacingText(currentTextNode.data);\n if (currentTextNode.data !== newText) {\n currentTextNode.data = newText;\n }\n }\n }\n if (nextTextNode) {\n if (currentTextNode.nextSibling && DomWalker.spaceLikeTags.test(currentTextNode.nextSibling.nodeName)) {\n nextTextNode = currentTextNode;\n continue;\n }\n if (!(currentTextNode instanceof Text) || !(nextTextNode instanceof Text)) {\n continue;\n }\n const currentEndsWithSpace = currentTextNode.data.endsWith(\" \");\n const nextStartsWithSpace = nextTextNode.data.startsWith(\" \");\n let hasWhitespaceBetween = false;\n let currentAncestor = currentTextNode;\n while (currentAncestor.parentNode && DomWalker.isLastTextChild(currentAncestor.parentNode, currentAncestor) && !DomWalker.spaceSensitiveTags.test(currentAncestor.parentNode.nodeName)) {\n currentAncestor = currentAncestor.parentNode;\n }\n let nextAncestor = nextTextNode;\n while (nextAncestor.parentNode && DomWalker.isFirstTextChild(nextAncestor.parentNode, nextAncestor) && !DomWalker.spaceSensitiveTags.test(nextAncestor.parentNode.nodeName)) {\n nextAncestor = nextAncestor.parentNode;\n }\n let nodeBetween = currentAncestor.nextSibling;\n while (nodeBetween && nodeBetween !== nextAncestor) {\n if (nodeBetween.nodeType === Node.TEXT_NODE && nodeBetween.textContent && /\\s/.test(nodeBetween.textContent)) {\n hasWhitespaceBetween = true;\n break;\n }\n nodeBetween = nodeBetween.nextSibling;\n }\n if (currentEndsWithSpace || nextStartsWithSpace || hasWhitespaceBetween) {\n nextTextNode = currentTextNode;\n continue;\n }\n const testText = currentTextNode.data.slice(-1) + nextTextNode.data.slice(0, 1);\n const testNewText = this.spacingText(testText);\n const currentLast = currentTextNode.data.slice(-1);\n const nextFirst = nextTextNode.data.slice(0, 1);\n const isQuote = (char) => /[\"\\u201c\\u201d]/.test(char);\n const isCJK = (char) => /[\\u4e00-\\u9fff]/.test(char);\n const skipSpacing = isQuote(currentLast) && isCJK(nextFirst) || isCJK(currentLast) && isQuote(nextFirst);\n if (testNewText !== testText && !skipSpacing) {\n let nextNode = nextTextNode;\n while (nextNode.parentNode && !DomWalker.spaceSensitiveTags.test(nextNode.nodeName) && DomWalker.isFirstTextChild(nextNode.parentNode, nextNode)) {\n nextNode = nextNode.parentNode;\n }\n let currentNode = currentTextNode;\n while (currentNode.parentNode && !DomWalker.spaceSensitiveTags.test(currentNode.nodeName) && DomWalker.isLastTextChild(currentNode.parentNode, currentNode)) {\n currentNode = currentNode.parentNode;\n }\n if (currentNode.nextSibling) {\n if (DomWalker.spaceLikeTags.test(currentNode.nextSibling.nodeName)) {\n nextTextNode = currentTextNode;\n continue;\n }\n }\n if (!DomWalker.blockTags.test(currentNode.nodeName)) {\n if (!DomWalker.spaceSensitiveTags.test(nextNode.nodeName)) {\n if (!DomWalker.ignoredTags.test(nextNode.nodeName) && !DomWalker.blockTags.test(nextNode.nodeName)) {\n if (nextTextNode.previousSibling) {\n if (!DomWalker.spaceLikeTags.test(nextTextNode.previousSibling.nodeName)) {\n if (nextTextNode instanceof Text && !nextTextNode.data.startsWith(\" \")) {\n if (!this.visibilityDetector.shouldSkipSpacingBeforeNode(nextTextNode)) {\n nextTextNode.data = ` ${nextTextNode.data}`;\n }\n }\n }\n } else {\n if (!DomWalker.canIgnoreNode(nextTextNode)) {\n if (nextTextNode instanceof Text && !nextTextNode.data.startsWith(\" \")) {\n if (!this.visibilityDetector.shouldSkipSpacingBeforeNode(nextTextNode)) {\n nextTextNode.data = ` ${nextTextNode.data}`;\n }\n }\n }\n }\n }\n } else if (!DomWalker.spaceSensitiveTags.test(currentNode.nodeName)) {\n if (currentTextNode instanceof Text && !currentTextNode.data.endsWith(\" \")) {\n if (!this.visibilityDetector.shouldSkipSpacingAfterNode(currentTextNode)) {\n currentTextNode.data = `${currentTextNode.data} `;\n }\n }\n } else {\n if (!this.visibilityDetector.shouldSkipSpacingAfterNode(currentTextNode)) {\n const panguSpace = document.createElement(\"pangu\");\n panguSpace.innerHTML = \" \";\n if (nextNode.parentNode) {\n if (nextNode.previousSibling) {\n if (!DomWalker.spaceLikeTags.test(nextNode.previousSibling.nodeName)) {\n nextNode.parentNode.insertBefore(panguSpace, nextNode);\n }\n } else {\n nextNode.parentNode.insertBefore(panguSpace, nextNode);\n }\n }\n if (!panguSpace.previousElementSibling) {\n if (panguSpace.parentNode) {\n panguSpace.parentNode.removeChild(panguSpace);\n }\n }\n }\n }\n }\n }\n }\n nextTextNode = currentTextNode;\n }\n }\n spacingTextNodesInQueue(textNodes, onComplete) {\n if (this.visibilityDetector.config.enabled) {\n if (this.taskScheduler.config.enabled) {\n this.taskScheduler.queue.add(() => {\n this.spacingTextNodes(textNodes);\n });\n if (onComplete) {\n this.taskScheduler.queue.setOnComplete(onComplete);\n }\n } else {\n this.spacingTextNodes(textNodes);\n onComplete == null ? void 0 : onComplete();\n }\n return;\n }\n const task = (chunkedTextNodes) => this.spacingTextNodes(chunkedTextNodes);\n this.taskScheduler.processInChunks(textNodes, task, onComplete);\n }\n waitForVideosToLoad(delayMs, onLoaded) {\n const videos = Array.from(document.getElementsByTagName(\"video\"));\n if (videos.length === 0) {\n setTimeout(onLoaded, delayMs);\n } else {\n const allVideosLoaded = videos.every((video) => video.readyState >= 3);\n if (allVideosLoaded) {\n setTimeout(onLoaded, delayMs);\n } else {\n let loadedCount = 0;\n const videoCount = videos.length;\n const checkAllLoaded = () => {\n loadedCount++;\n if (loadedCount >= videoCount) {\n setTimeout(onLoaded, delayMs);\n }\n };\n for (const video of videos) {\n if (video.readyState >= 3) {\n checkAllLoaded();\n } else {\n video.addEventListener(\"loadeddata\", checkAllLoaded, { once: true });\n }\n }\n setTimeout(onLoaded, delayMs + 5e3);\n }\n }\n }\n setupAutoSpacingPageObserver(nodeDelayMs, nodeMaxWaitMs) {\n if (this.autoSpacingPageObserver) {\n this.autoSpacingPageObserver.disconnect();\n this.autoSpacingPageObserver = null;\n }\n const queue = [];\n const debouncedSpacingTitle = debounce(\n () => {\n const titleElement = document.querySelector(\"head > title\");\n if (titleElement) {\n this.spacingNode(titleElement);\n }\n },\n nodeDelayMs,\n nodeMaxWaitMs\n );\n const debouncedSpacingNode = debounce(\n () => {\n if (this.taskScheduler.config.enabled) {\n const nodesToProcess = [...queue];\n queue.length = 0;\n if (nodesToProcess.length > 0) {\n const allTextNodes = [];\n for (const node of nodesToProcess) {\n const textNodes = DomWalker.collectTextNodes(node, true);\n allTextNodes.push(...textNodes);\n }\n this.spacingTextNodesInQueue(allTextNodes);\n }\n } else {\n while (queue.length) {\n const node = queue.shift();\n if (node) {\n this.spacingNode(node);\n }\n }\n }\n },\n nodeDelayMs,\n nodeMaxWaitMs\n );\n this.autoSpacingPageObserver = new MutationObserver((mutations) => {\n var _a;\n let titleChanged = false;\n for (const mutation of mutations) {\n if (((_a = mutation.target.parentNode) == null ? void 0 : _a.nodeName) === \"TITLE\" || mutation.target.nodeName === \"TITLE\") {\n titleChanged = true;\n continue;\n }\n switch (mutation.type) {\n case \"characterData\":\n const { target: node } = mutation;\n if (node.nodeType === Node.TEXT_NODE && node.parentNode) {\n queue.push(node.parentNode);\n }\n break;\n case \"childList\":\n for (const node2 of mutation.addedNodes) {\n if (node2.nodeType === Node.ELEMENT_NODE) {\n queue.push(node2);\n } else if (node2.nodeType === Node.TEXT_NODE && node2.parentNode) {\n queue.push(node2.parentNode);\n }\n }\n break;\n }\n }\n if (titleChanged) {\n debouncedSpacingTitle();\n }\n debouncedSpacingNode();\n });\n this.autoSpacingPageObserver.observe(document.head, {\n characterData: true,\n childList: true,\n subtree: true\n // Need subtree to observe text node changes inside title\n });\n this.autoSpacingPageObserver.observe(document.body, {\n characterData: true,\n childList: true,\n subtree: true\n });\n }\n}\nconst pangu = new BrowserPangu();\nexport {\n BrowserPangu,\n pangu as default,\n pangu\n};\n//# sourceMappingURL=pangu.js.map\n","#!/usr/bin/env node\nimport { pangu } from \"./index.js\";\nconst usage = `\nusage: pangu [-h] [-v] [-t] [-f] [-c] text_or_path\n\npangu.js -- Paranoid text spacing for good readability, to automatically\ninsert whitespace between CJK and half-width characters (alphabetical letters,\nnumerical digits and symbols).\n\npositional arguments:\n text_or_path the text or file path to apply spacing\n\noptional arguments:\n -h, --help show this help message and exit\n -v, --version show program's version number and exit\n -t, --text specify the input value is a text\n -f, --file specify the input value is a file path\n -c, --check check if text has proper spacing (exit 0 if yes, 1 if no)\n`.trim();\nconst [, , ...args] = process.argv;\nfunction printSpacingText(text) {\n if (typeof text === \"string\") {\n console.log(pangu.spacingText(text));\n } else {\n console.log(usage);\n process.exit(1);\n }\n}\nfunction printSpacingFile(path) {\n if (typeof path === \"string\") {\n console.log(pangu.spacingFileSync(path));\n } else {\n console.log(usage);\n process.exit(1);\n }\n}\nfunction checkSpacing(text) {\n if (typeof text === \"string\") {\n const hasProperSpacing = pangu.hasProperSpacing(text);\n if (!hasProperSpacing) {\n console.error(`Corrected: ${pangu.spacingText(text)}`);\n }\n process.exit(hasProperSpacing ? 0 : 1);\n } else {\n console.log(usage);\n process.exit(1);\n }\n}\nif (args.length === 0) {\n console.log(usage);\n process.exit(1);\n} else {\n switch (args[0]) {\n case \"-h\":\n case \"--help\":\n console.log(usage);\n break;\n case \"-v\":\n case \"--version\":\n console.log(pangu.version);\n break;\n case \"-t\":\n case \"--text\":\n printSpacingText(args[1]);\n break;\n case \"-f\":\n case \"--file\":\n printSpacingFile(args[1]);\n break;\n case \"-c\":\n case \"--check\":\n checkSpacing(args[1]);\n break;\n default:\n printSpacingText(args[0]);\n }\n}\nprocess.exit(0);\n//# sourceMappingURL=cli.js.map\n"],"names":["__defProp","__defNormalProp","__publicField","args"],"mappings":";;AAAA,IAAIA,cAAY,OAAO;AACvB,IAAIC,oBAAkB,CAAC,KAAK,KAAK,UAAU,OAAO,MAAMD,YAAU,KAAK,KAAK,EAAE,YAAY,MAAM,cAAc,MAAM,UAAU,MAAM,MAAK,CAAE,IAAI,IAAI,GAAG,IAAI;AAC1J,IAAIE,kBAAgB,CAAC,KAAK,KAAK,UAAUD,kBAAgB,KAAK,OAAO,QAAQ,WAAW,MAAM,KAAK,KAAK,KAAK;AAC7G,MAAM,MAAM;AACZ,MAAM,KAAK;AACX,MAAM,IAAI;AACV,MAAM,WAAW;AACjB,MAAM,iBAAiB;AACvB,MAAM,wBAAwB,GAAG,cAAc;AAC/C,MAAM,sBAAsB;AAC5B,MAAM,kBAAkB;AACxB,MAAM,SAAS;AACf,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAC/B,MAAM,0BAA0B;AAChC,MAAM,gBAAgB,GAAG,CAAC;AAC1B,MAAM,iBAAiB,GAAG,CAAC;AAC3B,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AACxB,MAAM,0BAA0B,IAAI,OAAO,cAAc,cAAc,iCAAiC,eAAe,IAAI;AAC3H,MAAM,0BAA0B,IAAI,OAAO,eAAe,cAAc,QAAQ,eAAe,IAAI;AACnG,MAAM,oBAAoB;AAC1B,MAAM,UAAU,IAAI,OAAO,IAAI,GAAG,GAAG;AACrC,MAAM,kBAAkB,IAAI,OAAO,KAAK,GAAG,qBAAqB,GAAG,GAAG,EAAE,MAAM,GAAG;AACjF,MAAM,qBAAqB,IAAI,OAAO,KAAK,EAAE,kBAAkB,GAAG,MAAM,GAAG;AAC3E,MAAM,YAAY,IAAI,OAAO,KAAK,GAAG,kBAAkB,GAAG,GAAG,EAAE,MAAM,GAAG;AACxE,MAAM,mBAAmB,IAAI,OAAO,KAAK,GAAG,UAAU,GAAG;AACzD,MAAM,aAAa,IAAI,OAAO,KAAK,GAAG,cAAc,EAAE,aAAa,GAAG,GAAG,EAAE,MAAM,GAAG;AACpF,MAAM,gBAAgB,IAAI,OAAO,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG;AAChE,MAAM,eAAe,IAAI,OAAO,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG;AAC7D,MAAM,WAAW,IAAI,OAAO,uBAAuB,GAAG,MAAM,GAAG;AAC/D,MAAM,oBAAoB,IAAI,OAAO,KAAK,GAAG,UAAU,QAAQ,YAAY,GAAG;AAC9E,MAAM,YAAY,IAAI,OAAO,KAAK,GAAG,OAAO,MAAM,MAAM,GAAG;AAC3D,MAAM,YAAY,IAAI,OAAO,KAAK,MAAM,OAAO,GAAG,MAAM,GAAG;AAC3D,MAAM,sBAAsB,IAAI,OAAO,KAAK,MAAM,qBAAqB,MAAM,OAAO,GAAG;AACvF,MAAM,WAAW,IAAI,OAAO,eAAe,EAAE,MAAM,GAAG;AACtD,MAAM,eAAe,IAAI,OAAO,KAAK,GAAG,UAAU,EAAE,MAAM,GAAG;AAC7D,MAAM,kCAAkC,IAAI,OAAO,KAAK,GAAG,aAAa,GAAG;AAC3E,MAAM,mBAAmB,IAAI,OAAO,QAAQ,GAAG,MAAM,GAAG;AACxD,MAAM,8BAA8B,IAAI,OAAO,KAAK,EAAE,GAAG,GAAG,aAAa,GAAG;AAC5E,MAAM,oBAAoB,IAAI,OAAO,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,GAAG;AACjF,MAAM,WAAW,IAAI,OAAO,KAAK,GAAG,eAAe,GAAG;AACtD,MAAM,WAAW,IAAI,OAAO,cAAc,GAAG,MAAM,GAAG;AACtD,MAAM,mBAAmB,IAAI,OAAO,KAAK,GAAG,OAAO,qBAAqB,OAAO,EAAE,MAAM,GAAG;AAC1F,MAAM,mBAAmB,IAAI,OAAO,KAAK,EAAE,OAAO,qBAAqB,OAAO,GAAG,MAAM,GAAG;AAC1F,MAAM,mBAAmB,IAAI,OAAO,KAAK,EAAE,OAAO,mBAAmB,OAAO,EAAE,MAAM,GAAG;AACvF,MAAM,8BAA8B,IAAI,OAAO,6GAA6G,GAAG;AAC/J,MAAM,gBAAgB,IAAI,OAAO,KAAK,GAAG,YAAY,GAAG,MAAM,GAAG;AACjE,MAAM,gBAAgB,IAAI,OAAO,KAAK,GAAG,YAAY,EAAE,MAAM,GAAG;AAChE,MAAM,gBAAgB,IAAI,OAAO,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG;AAChE,MAAM,gBAAgB,IAAI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG;AAC/D,MAAM,0BAA0B,IAAI,OAAO,QAAQ,CAAC,OAAO,eAAe,OAAO,GAAG,MAAM,GAAG;AAC7F,MAAM,gBAAgB,IAAI,OAAO,KAAK,GAAG,UAAU,EAAE,MAAM,GAAG;AAC9D,MAAM,gBAAgB,IAAI,OAAO,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG;AAC9D,MAAM,mBAAmB,IAAI,OAAO,KAAK,GAAG,UAAU,EAAE,MAAM,GAAG;AACjE,MAAM,mBAAmB,IAAI,OAAO,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG;AACjE,MAAM,oBAAoB,IAAI,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG;AACjE,MAAM,uBAAuB,IAAI,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG;AACpE,MAAM,mBAAmB,IAAI,OAAO,KAAK,GAAG,OAAO,sBAAsB,MAAM,GAAG;AAClF,MAAM,oBAAoB,IAAI,OAAO,KAAK,uBAAuB,OAAO,GAAG,MAAM,GAAG;AACpF,MAAM,yCAAyC,IAAI,OAAO,KAAK,EAAE,GAAG,GAAG,qBAAqB,EAAE,GAAG,GAAG,sBAAsB,GAAG;AAC7H,MAAM,yCAAyC,IAAI,OAAO,eAAe,EAAE,GAAG,GAAG,2BAA2B,EAAE,GAAG,GAAG,MAAM,GAAG;AAC7H,MAAM,kBAAkB,IAAI,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,mBAAmB,MAAM,GAAG;AAC7F,MAAM,mBAAmB,IAAI,OAAO,KAAK,oBAAoB,OAAO,EAAE,MAAM,GAAG;AAC/E,MAAM,8BAA8B,IAAI,OAAO,KAAK,GAAG,MAAM,wBAAwB,MAAM,KAAK,GAAG;AACnG,MAAM,8BAA8B,IAAI,OAAO,KAAK,GAAG,MAAM,wBAAwB,MAAM,KAAK,GAAG;AACnG,MAAM,mBAAmB,IAAI,OAAO,KAAK,GAAG,MAAM,kBAAkB,MAAM,KAAK,GAAG;AAClF,MAAM,oCAAoC,IAAI,OAAO,IAAI,wBAAwB,MAAM,OAAO,GAAG,MAAM,GAAG;AAC1G,MAAM,oCAAoC,IAAI,OAAO,IAAI,wBAAwB,MAAM,OAAO,GAAG,MAAM,GAAG;AAC1G,MAAM,UAAU,IAAI,OAAO,KAAK,GAAG,OAAO,aAAa,MAAM,GAAG;AAChE,MAAM,UAAU,IAAI,OAAO,KAAK,cAAc,OAAO,GAAG,MAAM,GAAG;AACjE,MAAM,MAAM,IAAI,OAAO,QAAQ,CAAC,MAAM,GAAG;AACzC,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAAA,EACxB,YAAY,aAAa,gBAAgB,cAAc;AACrDC,oBAAc,MAAM,SAAS,EAAE;AAC/BA,oBAAc,MAAM,SAAS,CAAC;AAC9BA,oBAAc,MAAM,SAAS;AAC7B,SAAK,cAAc;AACnB,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,UAAM,eAAe,KAAK,eAAe,QAAQ,uBAAuB,MAAM;AAC9E,UAAM,aAAa,KAAK,aAAa,QAAQ,uBAAuB,MAAM;AAC1E,SAAK,UAAU,IAAI,OAAO,GAAG,YAAY,GAAG,KAAK,WAAW,SAAS,UAAU,IAAI,GAAG;AAAA,EAC1F;AAAA,EACE,MAAM,MAAM;AACV,SAAK,MAAM,KAAK,KAAK,IAAI;AACzB,WAAO,GAAG,KAAK,cAAc,GAAG,KAAK,WAAW,GAAG,KAAK,OAAO,GAAG,KAAK,YAAY;AAAA,EACvF;AAAA,EACE,QAAQ,MAAM;AACZ,WAAO,KAAK,QAAQ,KAAK,SAAS,CAAC,QAAQ,UAAU;AACnD,aAAO,KAAK,MAAM,SAAS,OAAO,EAAE,CAAC,KAAK;AAAA,IAChD,CAAK;AAAA,EACL;AAAA,EACE,QAAQ;AACN,SAAK,QAAQ,CAAE;AACf,SAAK,QAAQ;AAAA,EACjB;AACA;AACA,MAAM,MAAM;AAAA,EACV,cAAc;AACZA,oBAAc,MAAM,SAAS;AAC7B,SAAK,UAAU;AAAA,EACnB;AAAA,EACE,YAAY,MAAM;AAChB,QAAI,OAAO,SAAS,UAAU;AAC5B,cAAQ,KAAK,iDAAiD,OAAO,IAAI,EAAE;AAC3E,aAAO;AAAA,IACb;AACI,QAAI,KAAK,UAAU,KAAK,CAAC,QAAQ,KAAK,IAAI,GAAG;AAC3C,aAAO;AAAA,IACb;AACI,UAAM,OAAO;AACb,QAAI,UAAU;AACd,UAAM,kBAAkB,IAAI,oBAAoB,qBAAqB,UAAU,QAAQ;AACvF,cAAU,QAAQ,QAAQ,cAAc,CAAC,QAAQ,YAAY;AAC3D,aAAO,KAAK,gBAAgB,MAAM,OAAO,CAAC;AAAA,IAChD,CAAK;AACD,UAAM,iBAAiB,IAAI,oBAAoB,yBAAyB,UAAU,QAAQ;AAC1F,QAAI,cAAc;AAClB,QAAI,QAAQ,SAAS,GAAG,GAAG;AACzB,oBAAc;AACd,YAAM,mBAAmB;AACzB,gBAAU,QAAQ,QAAQ,kBAAkB,CAAC,UAAU;AACrD,cAAM,eAAe,MAAM,QAAQ,oBAAoB,CAAC,YAAY,UAAU,cAAc;AAC1F,gBAAM,iBAAiB,KAAK,YAAY,SAAS;AACjD,iBAAO,GAAG,QAAQ,KAAK,cAAc;AAAA,QAC/C,CAAS;AACD,eAAO,eAAe,MAAM,YAAY;AAAA,MAChD,CAAO;AAAA,IACP;AACI,cAAU,QAAQ,QAAQ,UAAU,OAAO;AAC3C,cAAU,QAAQ,QAAQ,iBAAiB,OAAO;AAClD,cAAU,QAAQ,QAAQ,oBAAoB,SAAS;AACvD,cAAU,QAAQ,QAAQ,WAAW,OAAO;AAC5C,cAAU,QAAQ,QAAQ,kBAAkB,QAAQ;AACpD,cAAU,QAAQ,QAAQ,YAAY,OAAO;AAC7C,cAAU,QAAQ,QAAQ,eAAe,SAAS;AAClD,cAAU,QAAQ,QAAQ,cAAc,SAAS;AACjD,cAAU,QAAQ,QAAQ,mBAAmB,YAAY;AACzD,cAAU,QAAQ,QAAQ,WAAW,OAAO;AAC5C,cAAU,QAAQ,QAAQ,WAAW,OAAO;AAC5C,cAAU,QAAQ,QAAQ,qBAAqB,QAAQ;AACvD,cAAU,QAAQ,QAAQ,UAAU,OAAO;AAC3C,cAAU,QAAQ,QAAQ,cAAc,SAAS;AACjD,cAAU,QAAQ,QAAQ,6BAA6B,MAAM;AAC7D,UAAM,wBAAwB,IAAI,oBAAoB,iCAAiC,UAAU,QAAQ;AACzG,UAAM,wBAAwB,IAAI,OAAO,QAAQ,GAAG,UAAU,GAAG;AACjE,cAAU,QAAQ,QAAQ,uBAAuB,CAAC,UAAU;AAC1D,aAAO,sBAAsB,MAAM,KAAK;AAAA,IAC9C,CAAK;AACD,cAAU,QAAQ,QAAQ,iCAAiC,OAAO;AAClE,cAAU,QAAQ,QAAQ,kBAAkB,OAAO;AACnD,cAAU,sBAAsB,QAAQ,OAAO;AAC/C,UAAM,aAAa,QAAQ;AAC3B,UAAM,cAAc,QAAQ,MAAM,KAAK,KAAK,CAAA,GAAI;AAChD,QAAI,eAAe,GAAG;AACpB,UAAI,cAAc,GAAG;AACnB,kBAAU,QAAQ,QAAQ,mBAAmB,cAAc;AAAA,MACnE;AACM,gBAAU,QAAQ,QAAQ,UAAU,OAAO;AAC3C,gBAAU,QAAQ,QAAQ,UAAU,OAAO;AAAA,IACjD,WAAe,cAAc,GAAG;AAC1B,UAAI,cAAc,GAAG;AACnB,kBAAU,QAAQ,QAAQ,mBAAmB,cAAc;AAAA,MACnE;AACM,gBAAU,QAAQ,QAAQ,UAAU,OAAO;AAC3C,gBAAU,QAAQ,QAAQ,UAAU,OAAO;AAAA,IACjD,OAAW;AACL,UAAI,cAAc,GAAG;AACnB,kBAAU,QAAQ,QAAQ,mBAAmB,cAAc;AAAA,MACnE;AACM,gBAAU,QAAQ,QAAQ,IAAI,OAAO,WAAW,GAAG,oBAAoB,GAAG,SAAS;AAAA,IACzF;AACI,UAAM,sBAAsB,IAAI,oBAAoB,8BAA8B,UAAU,QAAQ;AACpG,UAAM,wBAAwB;AAC9B,cAAU,QAAQ,QAAQ,uBAAuB,CAAC,UAAU;AAC1D,aAAO,oBAAoB,MAAM,KAAK;AAAA,IAC5C,CAAK;AACD,cAAU,QAAQ,QAAQ,yBAAyB,SAAS;AAC5D,cAAU,QAAQ,QAAQ,kBAAkB,UAAU;AACtD,cAAU,QAAQ,QAAQ,kBAAkB,UAAU;AACtD,cAAU,QAAQ,QAAQ,kBAAkB,UAAU;AACtD,cAAU,QAAQ,QAAQ,6BAA6B,CAAC,UAAU,WAAW;AAC3E,UAAI,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG;AACvC,eAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;AAAA,MACrD,WAAiB,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG;AAC9C,eAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;AAAA,MACrD,WAAiB,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG;AAC9C,eAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;AAAA,MACrD;AACM,aAAO;AAAA,IACb,CAAK;AACD,cAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,cAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,cAAU,QAAQ,QAAQ,mBAAmB,UAAU;AACvD,cAAU,QAAQ,QAAQ,kBAAkB,UAAU;AACtD,cAAU,QAAQ,QAAQ,kBAAkB,UAAU;AACtD,cAAU,QAAQ,QAAQ,sBAAsB,UAAU;AAC1D,cAAU,QAAQ,QAAQ,6BAA6B,OAAO;AAC9D,cAAU,QAAQ,QAAQ,6BAA6B,OAAO;AAC9D,cAAU,QAAQ,QAAQ,kBAAkB,OAAO;AACnD,cAAU,QAAQ,QAAQ,mCAAmC,OAAO;AACpE,cAAU,QAAQ,QAAQ,mCAAmC,OAAO;AACpE,QAAI,eAAe,GAAG;AACpB,YAAM,kBAAkB,IAAI,oBAAoB,0BAA0B,UAAU,QAAQ;AAC5F,YAAM,qBAAqB,IAAI,OAAO,IAAI,wBAAwB,MAAM,IAAI,wBAAwB,MAAM,KAAK,GAAG;AAClH,gBAAU,QAAQ,QAAQ,oBAAoB,CAAC,UAAU;AACvD,eAAO,gBAAgB,MAAM,KAAK;AAAA,MAC1C,CAAO;AACD,gBAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,gBAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,gBAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,gBAAU,QAAQ,QAAQ,eAAe,UAAU;AACnD,gBAAU,gBAAgB,QAAQ,OAAO;AAAA,IAC/C;AACI,cAAU,oBAAoB,QAAQ,OAAO;AAC7C,cAAU,QAAQ,QAAQ,kBAAkB,OAAO;AACnD,cAAU,QAAQ,QAAQ,mBAAmB,OAAO;AACpD,cAAU,QAAQ,QAAQ,wCAAwC,WAAW;AAC7E,cAAU,QAAQ,QAAQ,wCAAwC,WAAW;AAC7E,cAAU,QAAQ,QAAQ,iBAAiB,OAAO;AAClD,cAAU,QAAQ,QAAQ,kBAAkB,OAAO;AACnD,cAAU,QAAQ,QAAQ,SAAS,OAAO;AAC1C,cAAU,QAAQ,QAAQ,SAAS,OAAO;AAC1C,cAAU,QAAQ,QAAQ,KAAK,OAAO;AACtC,cAAU,QAAQ,QAAQ,YAAY,QAAQ;AAC9C,UAAM,oBAAoB,CAAC,UAAU;AACnC,YAAM,kBAAkB;AAAA,QACtB,EAAE,SAAS,eAAe,MAAM,KAAK,OAAO,IAAK;AAAA,QACjD,EAAE,SAAS,iBAAiB,MAAM,KAAK,OAAO,IAAK;AAAA,QACnD,EAAE,SAAS,mBAAmB,MAAM,KAAK,OAAO,IAAK;AAAA,QACrD,EAAE,SAAS,iBAAiB,MAAM,KAAK,OAAO,IAAG;AAAA,MAClD;AACD,iBAAW,EAAE,SAAS,MAAM,MAAK,KAAM,iBAAiB;AACtD,gBAAQ,MAAM,QAAQ,SAAS,CAAC,QAAQ,iBAAiB;AACvD,cAAI,CAAC,cAAc;AACjB,mBAAO,GAAG,IAAI,GAAG,KAAK;AAAA,UAClC;AACU,gBAAM,iBAAiB,aAAa,QAAQ,YAAY,EAAE;AAC1D,iBAAO,GAAG,IAAI,GAAG,cAAc,GAAG,KAAK;AAAA,QACjD,CAAS;AAAA,MACT;AACM,aAAO;AAAA,IACR;AACD,cAAU,kBAAkB,OAAO;AACnC,QAAI,aAAa;AACf,gBAAU,eAAe,QAAQ,OAAO;AAAA,IAC9C;AACI,cAAU,gBAAgB,QAAQ,OAAO;AACzC,WAAO;AAAA,EACX;AAAA,EACE,iBAAiB,MAAM;AACrB,WAAO,KAAK,YAAY,IAAI,MAAM;AAAA,EACtC;AACA;AACc,IAAI,MAAK;ACjQvB,IAAI,YAAY,OAAO;AACvB,IAAI,kBAAkB,CAAC,KAAK,KAAK,UAAU,OAAO,MAAM,UAAU,KAAK,KAAK,EAAE,YAAY,MAAM,cAAc,MAAM,UAAU,MAAM,MAAK,CAAE,IAAI,IAAI,GAAG,IAAI;AAC1J,IAAI,gBAAgB,CAAC,KAAK,KAAK,UAAU,gBAAgB,KAAK,OAAO,QAAQ,WAAW,MAAM,KAAK,KAAK,KAAK;AAE7G,MAAM,UAAU;AAAA,EACd,OAAO,iBAAiB,aAAa,UAAU,OAAO;AACpD,UAAM,QAAQ,CAAE;AAChB,QAAI,CAAC,eAAe,uBAAuB,kBAAkB;AAC3D,aAAO;AAAA,IACb;AACI,UAAM,SAAS,SAAS,iBAAiB,aAAa,WAAW,WAAW;AAAA,MAC1E,YAAY,CAAC,SAAS;AACpB,YAAI,CAAC,KAAK,aAAa,CAAC,KAAK,KAAK,KAAK,SAAS,GAAG;AACjD,iBAAO,WAAW;AAAA,QAC5B;AACQ,YAAI,cAAc;AAClB,eAAO,aAAa;AAClB,cAAI,uBAAuB,SA