{"version":3,"file":"amll-ttml.cjs","names":[],"sources":["../src/constants.ts","../src/generator.ts","../src/parser.ts","../src/utils/amll-converter.ts","../src/index.ts"],"sourcesContent":["/**\n * 一些常量定义\n * @module constants\n * @internal\n */\n\nexport const NS = {\n\tTT: \"http://www.w3.org/ns/ttml\",\n\tTTM: \"http://www.w3.org/ns/ttml#metadata\",\n\tITUNES: \"http://music.apple.com/lyric-ttml-internal\",\n\tAMLL: \"http://www.example.com/ns/amll\",\n\tXML: \"http://www.w3.org/XML/1998/namespace\",\n\tXMLNS: \"http://www.w3.org/2000/xmlns/\",\n\tITUNES_INTERNAL: \"http://music.apple.com/lyric-ttml-internal\",\n\tTTS: \"http://www.w3.org/ns/ttml#styling\",\n} as const;\n\nexport const Elements = {\n\tTT: \"tt\",\n\tHead: \"head\",\n\tBody: \"body\",\n\tDiv: \"div\",\n\tP: \"p\",\n\tSpan: \"span\",\n\tTitle: \"title\",\n\tName: \"name\",\n\tMeta: \"meta\",\n\tITunesMetadata: \"iTunesMetadata\",\n\tTTMLMetadata: \"metadata\",\n\tSongwriters: \"songwriters\",\n\tSongwriter: \"songwriter\",\n\tTranslation: \"translation\",\n\tTranslations: \"translations\",\n\tTransliteration: \"transliteration\",\n\tTransliterations: \"transliterations\",\n\tText: \"text\",\n\tParserError: \"parsererror\",\n\tAgent: \"agent\",\n} as const;\n\nexport const Attributes = {\n\tTiming: \"timing\",\n\tId: \"id\",\n\tKey: \"key\",\n\tValue: \"value\",\n\tLang: \"lang\",\n\tFor: \"for\",\n\tSongPart: \"songPart\",\n\tSongPartKebab: \"song-part\",\n\tBegin: \"begin\",\n\tEnd: \"end\",\n\tRole: \"role\",\n\tType: \"type\",\n\tDur: \"dur\",\n\tXmlns: \"xmlns\",\n\tRuby: \"ruby\",\n\tObscene: \"obscene\",\n\tEmptyBeat: \"empty-beat\",\n} as const;\n\nexport const QualifiedAttributes = {\n\tITunesTiming: \"itunes:timing\",\n\tITunesPart: \"itunes:songPart\",\n\tITunesKey: \"itunes:key\",\n\tTTMAgent: \"ttm:agent\",\n\tTTMRole: \"ttm:role\",\n\tTTMName: \"ttm:name\",\n\tAmllMeta: \"amll:meta\",\n\tAmllObscene: \"amll:obscene\",\n\tAmllEmptyBeat: \"amll:empty-beat\",\n\tXmlLang: \"xml:lang\",\n\tXmlId: \"xml:id\",\n\tXmlnsTtm: \"xmlns:ttm\",\n\tXmlnsTts: \"xmlns:tts\",\n\tXmlnsItunes: \"xmlns:itunes\",\n\tXmlnsAmll: \"xmlns:amll\",\n\tTtsRuby: \"tts:ruby\",\n} as const;\n\nexport const Values = {\n\tWord: \"Word\",\n\tLine: \"Line\",\n\tMimeXML: \"application/xml\",\n\tMusicName: \"musicName\",\n\tArtists: \"artists\",\n\tAlbum: \"album\",\n\tISRC: \"isrc\",\n\tTTMLAuthorGithub: \"ttmlAuthorGithub\",\n\tTTMLAuthorGithubLogin: \"ttmlAuthorGithubLogin\",\n\tNCMMusicId: \"ncmMusicId\",\n\tQQMusicId: \"qqMusicId\",\n\tSpotifyId: \"spotifyId\",\n\tAppleMusicId: \"appleMusicId\",\n\tRoleBg: \"x-bg\",\n\tRoleTranslation: \"x-translation\",\n\tRoleRoman: \"x-roman\",\n\tGroup: \"group\",\n\tPerson: \"person\",\n\tOther: \"other\",\n\tFull: \"full\",\n\tAgentGroup: \"v1000\",\n\tAgentDefault: \"v1\",\n\tAgentDefaultDuet: \"v2\",\n\tRubyContainer: \"container\",\n\tRubyBase: \"base\",\n\tRubyTextContainer: \"textContainer\",\n\tRubyText: \"text\",\n\tTrue: \"true\",\n\tTimingMode: \"timingMode\",\n\tLanguage: \"language\",\n} as const;\n\n// 为了兼容 nodejs 环境而重新定义\nexport enum NodeType {\n\tELEMENT_NODE = 1,\n\tATTRIBUTE_NODE = 2,\n\tTEXT_NODE = 3,\n\tCDATA_SECTION_NODE = 4,\n\tENTITY_REFERENCE_NODE = 5,\n\tENTITY_NODE = 6,\n\tPROCESSING_INSTRUCTION_NODE = 7,\n\tCOMMENT_NODE = 8,\n\tDOCUMENT_NODE = 9,\n\tDOCUMENT_TYPE_NODE = 10,\n\tDOCUMENT_FRAGMENT_NODE = 11,\n\tNOTATION_NODE = 12,\n}\n","/**\n * 核心的 TTML 生成器实现\n * @module generator\n */\n\nimport {\n\tAttributes,\n\tElements,\n\tNS,\n\tQualifiedAttributes,\n\tValues,\n} from \"./constants\";\nimport type {\n\tAgent,\n\tGeneratorOptions,\n\tLyricBase,\n\tSubLyricContent,\n\tSyllable,\n\tTTMLResult,\n} from \"./types\";\n\n/**\n * TTML 歌词生成器类\n *\n * 用于将内部的 {@link TTMLResult} 数据结构序列化为 AMLL 项目使用的 TTML 字符串\n * @see https://github.com/amll-dev/amll-ttml-db/wiki/%E6%A0%BC%E5%BC%8F%E8%A7%84%E8%8C%83\n */\nexport class TTMLGenerator {\n\tprivate domImpl: DOMImplementation;\n\tprivate options: GeneratorOptions;\n\tprivate xmlSerializer: XMLSerializer;\n\tprivate doc!: Document;\n\tprivate timingMode: \"Word\" | \"Line\" = \"Line\";\n\n\t/**\n\t * 构造一个 TTML 生成器实例\n\t *\n\t * @param options 生成器配置选项\n\t *\n\t * 在 Node.js 环境下必须注入 `domImplementation` 和 `xmlSerializer` 实例（例如用 `@xmldom/xmldom` 等）\n\t */\n\tconstructor(options: GeneratorOptions = {}) {\n\t\tthis.options = options;\n\n\t\tif (this.options.domImplementation) {\n\t\t\tthis.domImpl = this.options.domImplementation as DOMImplementation;\n\t\t} else if (typeof document !== \"undefined\" && document.implementation) {\n\t\t\tthis.domImpl = document.implementation;\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t\"No DOMImplementation found. If you are running in Node.js, please inject via options (e.g., using @xmldom/xmldom in Node.js).\",\n\t\t\t);\n\t\t}\n\n\t\tif (this.options.xmlSerializer) {\n\t\t\tthis.xmlSerializer = this.options.xmlSerializer;\n\t\t} else if (typeof XMLSerializer !== \"undefined\") {\n\t\t\tthis.xmlSerializer = new XMLSerializer();\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t\"No XMLSerializer found. If you are running in Node.js, please inject via options (e.g., using @xmldom/xmldom in Node.js).\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * 生成 TTML 字符串的静态便捷方法\n\t * @param result 包含元数据和歌词行的 TTML 数据结构\n\t * @param options 生成器配置选项，用于注入 DOM 依赖及自定义部分生成行为\n\t * @returns 序列化后的 TTML 字符串\n\t */\n\tpublic static generate(\n\t\tresult: TTMLResult,\n\t\toptions?: GeneratorOptions,\n\t): string {\n\t\tconst instance = new TTMLGenerator(options);\n\t\treturn instance.generate(result);\n\t}\n\n\t/**\n\t * 生成 TTML 字符串\n\t * @param result 包含元数据和歌词行的 TTML 数据结构\n\t * @returns 序列化后的 TTML 字符串\n\t */\n\tpublic generate(result: TTMLResult): string {\n\t\tthis.doc = this.domImpl.createDocument(NS.TT, Elements.TT, null);\n\t\tthis.timingMode = result.metadata.timingMode || \"Line\";\n\n\t\t// 允许调用者自定义所有行的 ID，但是如果只自定义了部分行 ID，为了避免 ID 乱序，我们直接忽略残缺行 ID\n\t\tconst allLinesHaveId = result.lines.every(\n\t\t\t(line) => typeof line.id === \"string\" && line.id.trim() !== \"\",\n\t\t);\n\n\t\tresult.lines.forEach((line, index) => {\n\t\t\tif (!allLinesHaveId) {\n\t\t\t\tline.id = `L${index + 1}`;\n\t\t\t}\n\t\t\t// 未提供 agentId，默认所有行的 agentId 均为默认 v1\n\t\t\tif (!line.agentId) {\n\t\t\t\tline.agentId = Values.AgentDefault;\n\t\t\t}\n\t\t});\n\n\t\tconst root = this.doc.documentElement;\n\n\t\tthis.setupRootAttributes(root, result);\n\n\t\tconst head = this.buildHead(result);\n\t\troot.appendChild(head);\n\n\t\tconst body = this.buildBody(result);\n\t\troot.appendChild(body);\n\n\t\tconst xmlStr = this.xmlSerializer.serializeToString(this.doc);\n\n\t\treturn xmlStr;\n\t}\n\n\tprivate setupRootAttributes(root: Element, result: TTMLResult) {\n\t\troot.setAttributeNS(NS.XMLNS, QualifiedAttributes.XmlnsAmll, NS.AMLL);\n\t\troot.setAttributeNS(NS.XMLNS, QualifiedAttributes.XmlnsItunes, NS.ITUNES);\n\t\troot.setAttributeNS(NS.XMLNS, QualifiedAttributes.XmlnsTtm, NS.TTM);\n\t\troot.setAttributeNS(NS.XMLNS, QualifiedAttributes.XmlnsTts, NS.TTS);\n\n\t\tif (result.metadata.language) {\n\t\t\troot.setAttributeNS(\n\t\t\t\tNS.XML,\n\t\t\t\tQualifiedAttributes.XmlLang,\n\t\t\t\tresult.metadata.language,\n\t\t\t);\n\t\t}\n\n\t\tif (result.metadata.timingMode) {\n\t\t\troot.setAttributeNS(\n\t\t\t\tNS.ITUNES,\n\t\t\t\tQualifiedAttributes.ITunesTiming,\n\t\t\t\tresult.metadata.timingMode,\n\t\t\t);\n\t\t} else {\n\t\t\troot.setAttributeNS(NS.ITUNES, QualifiedAttributes.ITunesTiming, \"Word\");\n\t\t}\n\t}\n\n\tprivate isLyricBase(\n\t\tcontent: LyricBase | SubLyricContent,\n\t): content is LyricBase {\n\t\treturn \"startTime\" in content;\n\t}\n\n\tprivate isWordByWord(words?: Syllable[]): boolean {\n\t\tif (!words || words.length === 0) return false;\n\t\tif (this.timingMode === \"Word\") return true;\n\t\treturn true;\n\t}\n\n\tprivate shouldMoveToSidecar(content: SubLyricContent): boolean {\n\t\tif (content.words && content.words.length > 0) return true;\n\t\treturn !!this.options.useSidecar;\n\t}\n\n\tprivate buildHead(result: TTMLResult): Element {\n\t\tconst head = this.doc.createElement(Elements.Head);\n\t\tconst metadata = this.doc.createElement(Elements.TTMLMetadata);\n\n\t\tconst meta = result.metadata;\n\n\t\tlet agentsToGenerate: Agent[] = [];\n\n\t\tif (meta.agents && Object.keys(meta.agents).length > 0) {\n\t\t\tagentsToGenerate = Object.values(meta.agents);\n\t\t} else {\n\t\t\tconst uniqueAgentIds = new Set<string>();\n\t\t\tresult.lines.forEach((line) => {\n\t\t\t\tif (line.agentId) {\n\t\t\t\t\tuniqueAgentIds.add(line.agentId);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tuniqueAgentIds.forEach((id) => {\n\t\t\t\tagentsToGenerate.push({\n\t\t\t\t\tid,\n\t\t\t\t\ttype: id === Values.AgentGroup ? Values.Group : Values.Person,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tagentsToGenerate.forEach((agent) => {\n\t\t\tconst { id, name, type: agentType } = agent;\n\t\t\tconst agentEl = this.doc.createElementNS(\n\t\t\t\tNS.TTM,\n\t\t\t\tQualifiedAttributes.TTMAgent,\n\t\t\t);\n\t\t\tconst type =\n\t\t\t\tagentType || (id === Values.AgentGroup ? Values.Group : Values.Person);\n\n\t\t\tagentEl.setAttribute(Attributes.Type, type);\n\t\t\tagentEl.setAttribute(QualifiedAttributes.XmlId, id);\n\n\t\t\tif (name) {\n\t\t\t\tconst nameEl = this.doc.createElementNS(\n\t\t\t\t\tNS.TTM,\n\t\t\t\t\tQualifiedAttributes.TTMName,\n\t\t\t\t);\n\t\t\t\tnameEl.setAttribute(Attributes.Type, Values.Full);\n\t\t\t\tnameEl.textContent = name;\n\t\t\t\tagentEl.appendChild(nameEl);\n\t\t\t}\n\n\t\t\tmetadata.appendChild(agentEl);\n\t\t});\n\n\t\tthis.buildITunesMetadata(metadata, result);\n\n\t\tconst addAmllMeta = (key: string, value: string) => {\n\t\t\tconst el = this.doc.createElementNS(\n\t\t\t\tNS.AMLL,\n\t\t\t\tQualifiedAttributes.AmllMeta,\n\t\t\t);\n\t\t\tel.setAttribute(Attributes.Key, key);\n\t\t\tel.setAttribute(Attributes.Value, value);\n\t\t\tmetadata.appendChild(el);\n\t\t};\n\n\t\tmeta.title?.forEach((v) => {\n\t\t\taddAmllMeta(Values.MusicName, v);\n\t\t});\n\t\tmeta.artist?.forEach((v) => {\n\t\t\taddAmllMeta(Values.Artists, v);\n\t\t});\n\t\tmeta.album?.forEach((v) => {\n\t\t\taddAmllMeta(Values.Album, v);\n\t\t});\n\n\t\tif (result.metadata.platformIds) {\n\t\t\tObject.entries(result.metadata.platformIds).forEach(([key, values]) => {\n\t\t\t\tvalues?.forEach((v) => {\n\t\t\t\t\taddAmllMeta(key, v);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tmeta.isrc?.forEach((v) => {\n\t\t\taddAmllMeta(Values.ISRC, v);\n\t\t});\n\n\t\tmeta.authorIds?.forEach((v) => {\n\t\t\taddAmllMeta(Values.TTMLAuthorGithub, v);\n\t\t});\n\t\tmeta.authorNames?.forEach((v) => {\n\t\t\taddAmllMeta(Values.TTMLAuthorGithubLogin, v);\n\t\t});\n\n\t\tif (meta.rawProperties) {\n\t\t\tObject.entries(meta.rawProperties).forEach(([key, values]) => {\n\t\t\t\tvalues?.forEach((v) => {\n\t\t\t\t\taddAmllMeta(key, v);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\thead.appendChild(metadata);\n\t\treturn head;\n\t}\n\n\tprivate buildITunesMetadata(metadataEl: Element, result: TTMLResult) {\n\t\tconst iTunesMeta = this.doc.createElement(Elements.ITunesMetadata);\n\t\tiTunesMeta.setAttribute(Attributes.Xmlns, NS.ITUNES_INTERNAL);\n\n\t\tlet hasContent = false;\n\n\t\tconst translationsMap = new Map<\n\t\t\tstring | undefined,\n\t\t\tArray<{ id: string; main?: SubLyricContent; bg?: SubLyricContent }>\n\t\t>();\n\t\tconst romansMap = new Map<\n\t\t\tstring | undefined,\n\t\t\tArray<{ id: string; main?: SubLyricContent; bg?: SubLyricContent }>\n\t\t>();\n\n\t\tfor (const line of result.lines) {\n\t\t\tconst pairedTrans = this.pairSubContents(\n\t\t\t\tline.translations,\n\t\t\t\tline.backgroundVocal?.translations,\n\t\t\t);\n\t\t\tfor (const pair of pairedTrans) {\n\t\t\t\tif (\n\t\t\t\t\t(pair.main && this.shouldMoveToSidecar(pair.main)) ||\n\t\t\t\t\t(pair.bg && this.shouldMoveToSidecar(pair.bg))\n\t\t\t\t) {\n\t\t\t\t\tif (!translationsMap.has(pair.lang))\n\t\t\t\t\t\ttranslationsMap.set(pair.lang, []);\n\t\t\t\t\ttranslationsMap.get(pair.lang)?.push({\n\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: generate 方法已验证行 id 一定有\n\t\t\t\t\t\tid: line.id!,\n\t\t\t\t\t\tmain: pair.main,\n\t\t\t\t\t\tbg: pair.bg,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pairedRomans = this.pairSubContents(\n\t\t\t\tline.romanizations,\n\t\t\t\tline.backgroundVocal?.romanizations,\n\t\t\t);\n\t\t\tfor (const pair of pairedRomans) {\n\t\t\t\tif (\n\t\t\t\t\t(pair.main && this.shouldMoveToSidecar(pair.main)) ||\n\t\t\t\t\t(pair.bg && this.shouldMoveToSidecar(pair.bg))\n\t\t\t\t) {\n\t\t\t\t\tif (!romansMap.has(pair.lang)) romansMap.set(pair.lang, []);\n\t\t\t\t\tromansMap.get(pair.lang)?.push({\n\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: generate 方法已验证行 id 一定有\n\t\t\t\t\t\tid: line.id!,\n\t\t\t\t\t\tmain: pair.main,\n\t\t\t\t\t\tbg: pair.bg,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (translationsMap.size > 0) {\n\t\t\tconst container = this.doc.createElement(Elements.Translations);\n\t\t\tfor (const [lang, items] of translationsMap) {\n\t\t\t\tconst transEl = this.doc.createElement(Elements.Translation);\n\t\t\t\tif (lang) {\n\t\t\t\t\ttransEl.setAttribute(QualifiedAttributes.XmlLang, lang);\n\t\t\t\t}\n\t\t\t\titems.forEach((item) => {\n\t\t\t\t\tconst textEl = this.doc.createElement(Elements.Text);\n\t\t\t\t\ttextEl.setAttribute(Attributes.For, item.id);\n\n\t\t\t\t\tif (item.main) {\n\t\t\t\t\t\tthis.appendContentToElement(textEl, item.main);\n\t\t\t\t\t}\n\t\t\t\t\tif (item.bg) {\n\t\t\t\t\t\tthis.appendBackgroundVocal(textEl, item.bg);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransEl.appendChild(textEl);\n\t\t\t\t});\n\t\t\t\tcontainer.appendChild(transEl);\n\t\t\t}\n\t\t\tiTunesMeta.appendChild(container);\n\t\t\thasContent = true;\n\t\t}\n\n\t\tif (romansMap.size > 0) {\n\t\t\tconst container = this.doc.createElement(Elements.Transliterations);\n\t\t\tfor (const [lang, items] of romansMap) {\n\t\t\t\tconst transEl = this.doc.createElement(Elements.Transliteration);\n\t\t\t\tif (lang) {\n\t\t\t\t\ttransEl.setAttribute(QualifiedAttributes.XmlLang, lang);\n\t\t\t\t}\n\t\t\t\titems.forEach((item) => {\n\t\t\t\t\tconst textEl = this.doc.createElement(Elements.Text);\n\t\t\t\t\ttextEl.setAttribute(Attributes.For, item.id);\n\n\t\t\t\t\tif (item.main) {\n\t\t\t\t\t\tthis.appendContentToElement(textEl, item.main);\n\t\t\t\t\t}\n\t\t\t\t\tif (item.bg) {\n\t\t\t\t\t\tthis.appendBackgroundVocal(textEl, item.bg);\n\t\t\t\t\t}\n\n\t\t\t\t\ttransEl.appendChild(textEl);\n\t\t\t\t});\n\t\t\t\tcontainer.appendChild(transEl);\n\t\t\t}\n\t\t\tiTunesMeta.appendChild(container);\n\t\t\thasContent = true;\n\t\t}\n\n\t\tif (result.metadata.songwriters && result.metadata.songwriters.length > 0) {\n\t\t\tconst container = this.doc.createElement(Elements.Songwriters);\n\t\t\tresult.metadata.songwriters.forEach((name) => {\n\t\t\t\tconst sw = this.doc.createElement(Elements.Songwriter);\n\t\t\t\tsw.textContent = name;\n\t\t\t\tcontainer.appendChild(sw);\n\t\t\t});\n\t\t\tiTunesMeta.appendChild(container);\n\t\t\thasContent = true;\n\t\t}\n\n\t\tif (hasContent) {\n\t\t\tmetadataEl.appendChild(iTunesMeta);\n\t\t}\n\t}\n\n\tprivate buildBody(result: TTMLResult): Element {\n\t\tconst body = this.doc.createElement(Elements.Body);\n\t\tconst lines = result.lines;\n\n\t\tconst lastTime =\n\t\t\tlines.length > 0 ? Math.max(...lines.map((l) => l.endTime)) : 0;\n\t\tbody.setAttribute(Attributes.Dur, this.formatTime(lastTime));\n\n\t\tlet currentDiv: Element | null = null;\n\t\tlet currentSongPart: string | undefined;\n\t\tlet currentBlockIndex: number | undefined;\n\t\tlet currentSectionEndTime = 0;\n\n\t\tconst finalizeCurrentDiv = () => {\n\t\t\tif (currentDiv && currentSectionEndTime > 0) {\n\t\t\t\tcurrentDiv.setAttribute(\n\t\t\t\t\tAttributes.End,\n\t\t\t\t\tthis.formatTime(currentSectionEndTime),\n\t\t\t\t);\n\t\t\t\tif (currentSongPart) {\n\t\t\t\t\tcurrentDiv.setAttributeNS(\n\t\t\t\t\t\tNS.ITUNES,\n\t\t\t\t\t\tQualifiedAttributes.ITunesPart,\n\t\t\t\t\t\tcurrentSongPart,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfor (const line of lines) {\n\t\t\tif (\n\t\t\t\tline.songPart !== currentSongPart ||\n\t\t\t\tline.blockIndex !== currentBlockIndex ||\n\t\t\t\t!currentDiv\n\t\t\t) {\n\t\t\t\tfinalizeCurrentDiv();\n\n\t\t\t\tcurrentSongPart = line.songPart;\n\t\t\t\tcurrentBlockIndex = line.blockIndex;\n\t\t\t\tcurrentSectionEndTime = 0;\n\n\t\t\t\tcurrentDiv = this.doc.createElement(Elements.Div);\n\n\t\t\t\tcurrentDiv.setAttribute(\n\t\t\t\t\tAttributes.Begin,\n\t\t\t\t\tthis.formatTime(line.startTime),\n\t\t\t\t);\n\n\t\t\t\tbody.appendChild(currentDiv);\n\t\t\t}\n\n\t\t\tif (line.endTime > currentSectionEndTime) {\n\t\t\t\tcurrentSectionEndTime = line.endTime;\n\t\t\t}\n\n\t\t\tconst p = this.doc.createElement(Elements.P);\n\t\t\tp.setAttribute(Attributes.Begin, this.formatTime(line.startTime));\n\t\t\tp.setAttribute(Attributes.End, this.formatTime(line.endTime));\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: generate 方法已验证行 id 一定有\n\t\t\tp.setAttributeNS(NS.ITUNES, QualifiedAttributes.ITunesKey, line.id!);\n\t\t\tif (line.agentId) {\n\t\t\t\tp.setAttributeNS(NS.TTM, QualifiedAttributes.TTMAgent, line.agentId);\n\t\t\t}\n\n\t\t\tthis.appendContentToElement(p, line);\n\t\t\tcurrentDiv.appendChild(p);\n\t\t}\n\n\t\tfinalizeCurrentDiv();\n\n\t\treturn body;\n\t}\n\n\tprivate pairSubContents(\n\t\tmainList?: SubLyricContent[],\n\t\tbgList?: SubLyricContent[],\n\t): Array<{ lang?: string; main?: SubLyricContent; bg?: SubLyricContent }> {\n\t\tconst map = new Map<\n\t\t\tstring | undefined,\n\t\t\t{ lang?: string; main?: SubLyricContent; bg?: SubLyricContent }\n\t\t>();\n\n\t\tconst getEntry = (lang?: string) => {\n\t\t\tlet entry = map.get(lang);\n\t\t\tif (!entry) {\n\t\t\t\tentry = { lang };\n\t\t\t\tmap.set(lang, entry);\n\t\t\t}\n\t\t\treturn entry;\n\t\t};\n\n\t\tmainList?.forEach((item) => {\n\t\t\tgetEntry(item.language).main = item;\n\t\t});\n\n\t\tbgList?.forEach((item) => {\n\t\t\tgetEntry(item.language).bg = item;\n\t\t});\n\n\t\treturn Array.from(map.values());\n\t}\n\n\tprivate appendContentToElement(\n\t\telement: Element,\n\t\tcontent: LyricBase | SubLyricContent,\n\t\tisBackground: boolean = false,\n\t) {\n\t\tif (this.isWordByWord(content.words) && content.words) {\n\t\t\tthis.appendWords(element, content.words, isBackground);\n\t\t} else {\n\t\t\tlet text = content.text || \"\";\n\t\t\tif (isBackground) {\n\t\t\t\ttext = `(${text})`;\n\t\t\t}\n\t\t\telement.textContent = text;\n\t\t}\n\n\t\tif (this.isLyricBase(content)) {\n\t\t\tthis.appendSubLyrics(element, content);\n\t\t}\n\n\t\tif (\"backgroundVocal\" in content && content.backgroundVocal) {\n\t\t\tthis.appendBackgroundVocal(element, content.backgroundVocal);\n\t\t}\n\t}\n\n\tprivate appendWords(\n\t\telement: Element,\n\t\twords: Syllable[],\n\t\tisBackground: boolean,\n\t) {\n\t\twords.forEach((syllable, index) => {\n\t\t\tlet text = syllable.text;\n\n\t\t\tif (isBackground) {\n\t\t\t\tif (index === 0) text = `(${text}`;\n\t\t\t\tif (index === words.length - 1) text = `${text})`;\n\t\t\t}\n\n\t\t\tif (syllable.ruby && syllable.ruby.length > 0) {\n\t\t\t\tthis.appendRubySyllable(element, syllable, text);\n\t\t\t} else {\n\t\t\t\tthis.appendNormalSyllable(element, syllable, text);\n\t\t\t}\n\n\t\t\tif (syllable.endsWithSpace) {\n\t\t\t\tconst spaceNode = this.doc.createTextNode(\" \");\n\t\t\t\telement.appendChild(spaceNode);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate appendRubySyllable(\n\t\telement: Element,\n\t\tsyllable: Syllable,\n\t\ttext: string,\n\t) {\n\t\tconst containerSpan = this.doc.createElement(Elements.Span);\n\t\tcontainerSpan.setAttributeNS(\n\t\t\tNS.TTS,\n\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\tValues.RubyContainer,\n\t\t);\n\n\t\tif (syllable.obscene) {\n\t\t\tcontainerSpan.setAttributeNS(\n\t\t\t\tNS.AMLL,\n\t\t\t\tQualifiedAttributes.AmllObscene,\n\t\t\t\tValues.True,\n\t\t\t);\n\t\t}\n\n\t\tif (syllable.emptyBeat !== undefined) {\n\t\t\tcontainerSpan.setAttributeNS(\n\t\t\t\tNS.AMLL,\n\t\t\t\tQualifiedAttributes.AmllEmptyBeat,\n\t\t\t\tsyllable.emptyBeat.toString(),\n\t\t\t);\n\t\t}\n\n\t\tconst baseSpan = this.doc.createElement(Elements.Span);\n\t\tbaseSpan.setAttributeNS(\n\t\t\tNS.TTS,\n\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\tValues.RubyBase,\n\t\t);\n\t\tbaseSpan.textContent = text;\n\t\tcontainerSpan.appendChild(baseSpan);\n\n\t\tconst textContainerSpan = this.doc.createElement(Elements.Span);\n\t\ttextContainerSpan.setAttributeNS(\n\t\t\tNS.TTS,\n\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\tValues.RubyTextContainer,\n\t\t);\n\n\t\tsyllable.ruby?.forEach((rt) => {\n\t\t\tconst rtSpan = this.doc.createElement(Elements.Span);\n\t\t\trtSpan.setAttributeNS(\n\t\t\t\tNS.TTS,\n\t\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\t\tValues.RubyText,\n\t\t\t);\n\t\t\trtSpan.setAttribute(Attributes.Begin, this.formatTime(rt.startTime));\n\t\t\trtSpan.setAttribute(Attributes.End, this.formatTime(rt.endTime));\n\t\t\trtSpan.textContent = rt.text;\n\t\t\ttextContainerSpan.appendChild(rtSpan);\n\t\t});\n\n\t\tcontainerSpan.appendChild(textContainerSpan);\n\t\telement.appendChild(containerSpan);\n\t}\n\n\tprivate appendNormalSyllable(\n\t\telement: Element,\n\t\tsyllable: Syllable,\n\t\ttext: string,\n\t) {\n\t\tconst span = this.doc.createElement(Elements.Span);\n\t\tspan.setAttribute(Attributes.Begin, this.formatTime(syllable.startTime));\n\t\tspan.setAttribute(Attributes.End, this.formatTime(syllable.endTime));\n\n\t\tif (syllable.obscene) {\n\t\t\tspan.setAttributeNS(\n\t\t\t\tNS.AMLL,\n\t\t\t\tQualifiedAttributes.AmllObscene,\n\t\t\t\tValues.True,\n\t\t\t);\n\t\t}\n\n\t\tif (syllable.emptyBeat !== undefined) {\n\t\t\tspan.setAttributeNS(\n\t\t\t\tNS.AMLL,\n\t\t\t\tQualifiedAttributes.AmllEmptyBeat,\n\t\t\t\tsyllable.emptyBeat.toString(),\n\t\t\t);\n\t\t}\n\n\t\tspan.textContent = text;\n\t\telement.appendChild(span);\n\t}\n\n\tprivate appendSubLyrics(element: Element, content: LyricBase) {\n\t\tif (content.translations) {\n\t\t\tcontent.translations.forEach((trans) => {\n\t\t\t\tif (!this.shouldMoveToSidecar(trans)) {\n\t\t\t\t\tconst span = this.doc.createElement(Elements.Span);\n\t\t\t\t\tspan.setAttributeNS(\n\t\t\t\t\t\tNS.TTM,\n\t\t\t\t\t\tQualifiedAttributes.TTMRole,\n\t\t\t\t\t\tValues.RoleTranslation,\n\t\t\t\t\t);\n\t\t\t\t\tif (trans.language) {\n\t\t\t\t\t\tspan.setAttributeNS(\n\t\t\t\t\t\t\tNS.XML,\n\t\t\t\t\t\t\tQualifiedAttributes.XmlLang,\n\t\t\t\t\t\t\ttrans.language,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthis.appendContentToElement(span, trans);\n\t\t\t\t\telement.appendChild(span);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (content.romanizations) {\n\t\t\tcontent.romanizations.forEach((roman) => {\n\t\t\t\tif (!this.shouldMoveToSidecar(roman)) {\n\t\t\t\t\tconst span = this.doc.createElement(Elements.Span);\n\t\t\t\t\tspan.setAttributeNS(\n\t\t\t\t\t\tNS.TTM,\n\t\t\t\t\t\tQualifiedAttributes.TTMRole,\n\t\t\t\t\t\tValues.RoleRoman,\n\t\t\t\t\t);\n\t\t\t\t\tif (roman.language) {\n\t\t\t\t\t\tspan.setAttributeNS(\n\t\t\t\t\t\t\tNS.XML,\n\t\t\t\t\t\t\tQualifiedAttributes.XmlLang,\n\t\t\t\t\t\t\troman.language,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthis.appendContentToElement(span, roman);\n\t\t\t\t\telement.appendChild(span);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate appendBackgroundVocal(\n\t\telement: Element,\n\t\tbg: LyricBase | SubLyricContent,\n\t) {\n\t\tconst bgSpan = this.doc.createElement(Elements.Span);\n\t\tbgSpan.setAttributeNS(NS.TTM, QualifiedAttributes.TTMRole, Values.RoleBg);\n\n\t\tif (this.isLyricBase(bg)) {\n\t\t\tif (bg.startTime > 0 && bg.endTime > 0) {\n\t\t\t\tbgSpan.setAttribute(Attributes.Begin, this.formatTime(bg.startTime));\n\t\t\t\tbgSpan.setAttribute(Attributes.End, this.formatTime(bg.endTime));\n\t\t\t}\n\t\t}\n\n\t\tthis.appendContentToElement(bgSpan, bg, true);\n\t\telement.appendChild(bgSpan);\n\t}\n\n\tprivate formatTime(ms: number): string {\n\t\tif (ms < 0) ms = 0;\n\n\t\tconst totalSeconds = Math.floor(ms / 1000);\n\t\tconst milliseconds = ms % 1000;\n\t\tconst minutes = Math.floor(totalSeconds / 60);\n\t\tconst seconds = totalSeconds % 60;\n\n\t\tconst fff = milliseconds.toString().padStart(3, \"0\");\n\n\t\tif (minutes > 0) {\n\t\t\tconst ss = seconds.toString().padStart(2, \"0\");\n\t\t\treturn `${minutes}:${ss}.${fff}`;\n\t\t} else {\n\t\t\treturn `${seconds}.${fff}`;\n\t\t}\n\t}\n}\n","/** biome-ignore-all lint/suspicious/noAssignInExpressions: intentional */\n/**\n * 核心的 TTML 生成器实现\n * @module generator\n */\n\nimport {\n\tAttributes,\n\tElements,\n\tNodeType,\n\tNS,\n\tQualifiedAttributes,\n\tValues,\n} from \"./constants\";\nimport type {\n\tAgent,\n\tBackgroundVocal,\n\tLyricBase,\n\tLyricLine,\n\tPlatformId,\n\tSubLyricContent,\n\tSyllable,\n\tTTMLMetadata,\n\tTTMLParserOptions,\n\tTTMLResult,\n} from \"./types\";\n\n/**\n * 临时的用于关联 Apple Music 样式的翻译和音译与主歌词行的容器\n */\ninterface IExtensionSidecar {\n\t[lineId: string]: {\n\t\ttranslations?: SubLyricContent[];\n\t\tromanizations?: SubLyricContent[];\n\t\tbgTranslations?: SubLyricContent[];\n\t\tbgRomanizations?: SubLyricContent[];\n\t};\n}\n\ninterface IParsedState {\n\tfullText: string;\n\twords: Syllable[];\n\ttranslations: SubLyricContent[];\n\tromanizations: SubLyricContent[];\n\tbgTranslations: SubLyricContent[];\n\tbgRomanizations: SubLyricContent[];\n\tbackgroundVocal?: BackgroundVocal;\n}\n\n/**\n * TTML 歌词生成器类\n *\n * 用于将 AMLL 项目使用的 TTML 字符串解析为结构化的 {@link TTMLResult} 数据结构\n * @see https://github.com/amll-dev/amll-ttml-db/wiki/%E6%A0%BC%E5%BC%8F%E8%A7%84%E8%8C%83\n */\nexport class TTMLParser {\n\tprivate domParser: DOMParser;\n\n\tprivate static readonly TIME_REGEX =\n\t\t/^(?:(?:(?<hours>\\d+):)?(?<minutes>\\d+):)?(?<seconds>\\d+(?:\\.\\d+)?)$/;\n\tprivate static readonly LEADING_SPACE_REGEX = /^\\s/;\n\tprivate static readonly TRAILING_SPACE_REGEX = /\\s$/;\n\tprivate static readonly MULTI_SPACE_REGEX = /\\s+/g;\n\n\tprivate normalizeText(\n\t\ttext: string | null | undefined,\n\t\ttrim: boolean = true,\n\t): string {\n\t\tif (!text) return \"\";\n\t\tconst normalized = text.replace(TTMLParser.MULTI_SPACE_REGEX, \" \");\n\t\treturn trim ? normalized.trim() : normalized;\n\t}\n\n\t/**\n\t * 构造一个 TTML 解析器实例\n\t *\n\t * @param options 生成器配置选项\n\t *\n\t * 在 Node.js 环境下必须注入 `domParser` 实例（例如用 `@xmldom/xmldom` 等）\n\t */\n\tconstructor(options?: TTMLParserOptions) {\n\t\tif (options?.domParser) {\n\t\t\tthis.domParser = options.domParser as DOMParser;\n\t\t} else if (typeof DOMParser !== \"undefined\") {\n\t\t\tthis.domParser = new DOMParser();\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t\"No DOMParser found. If you are running in Node.js, please inject a DOMParser (e.g., @xmldom/xmldom).\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * 解析 TTML 字符串的静态便捷方法\n\t * @param xmlStr 需要解析的 TTML XML 字符串\n\t * @param options 解析器配置选项，用于注入 DOM 依赖\n\t * @returns 解析后的结构化 TTML 数据结构\n\t * @throws 当输入的 XML 字符串格式无效时抛出异常\n\t */\n\tpublic static parse(xmlStr: string, options?: TTMLParserOptions): TTMLResult {\n\t\tconst instance = new TTMLParser(options);\n\t\treturn instance.parse(xmlStr);\n\t}\n\n\t/**\n\t * 解析 TTML 字符串\n\t * @param xmlStr 需要解析的 TTML XML 字符串\n\t * @returns 解析后的结构化 TTML 数据结构\n\t * @throws 当输入的 XML 字符串格式无效时抛出异常\n\t */\n\tpublic parse(xmlStr: string): TTMLResult {\n\t\tif (!xmlStr || typeof xmlStr !== \"string\") {\n\t\t\tthrow new Error(\"TTMLParser: Input must be a valid XML string.\");\n\t\t}\n\n\t\tconst doc = this.domParser.parseFromString(xmlStr, Values.MimeXML);\n\t\tconst { metadata, sidecar } = this.parseHead(doc);\n\n\t\tconst parserError = doc.getElementsByTagName(Elements.ParserError)[0];\n\t\tif (parserError) {\n\t\t\tthrow new Error(\n\t\t\t\t`TTMLParser: XML parsing error: ${parserError.textContent}`,\n\t\t\t);\n\t\t}\n\n\t\tconst result: TTMLResult = {\n\t\t\tmetadata: metadata,\n\t\t\tlines: [],\n\t\t};\n\n\t\tconst root = doc.documentElement;\n\t\tif (root) {\n\t\t\tconst lang = this.getAttr(root, NS.XML, Attributes.Lang);\n\t\t\tif (lang) {\n\t\t\t\tresult.metadata.language = lang;\n\t\t\t}\n\n\t\t\tconst timing = this.getAttr(root, NS.ITUNES, Attributes.Timing);\n\t\t\tif ((timing && timing === Values.Word) || timing === Values.Line) {\n\t\t\t\tresult.metadata.timingMode = timing;\n\t\t\t}\n\t\t}\n\n\t\tthis.parseBody(doc, result, sidecar);\n\n\t\tresult.metadata.timingMode ??= this.inferTimingMode(result.lines);\n\n\t\tif (result.metadata.platformIds) {\n\t\t\tresult.metadata.platformIds = this.sortPlatformIds(\n\t\t\t\tresult.metadata.platformIds,\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate inferTimingMode(lines: LyricLine[]): \"Word\" | \"Line\" {\n\t\tconst hasWordTiming = lines.some(\n\t\t\t(line) =>\n\t\t\t\t(line.words?.length ?? 0) > 1 ||\n\t\t\t\t(line.backgroundVocal?.words?.length ?? 0) > 1,\n\t\t);\n\n\t\treturn hasWordTiming ? \"Word\" : \"Line\";\n\t}\n\n\tprivate sortPlatformIds(\n\t\tplatformIds: Partial<Record<PlatformId, string[]>>,\n\t): Partial<Record<PlatformId, string[]>> {\n\t\tconst preferredOrder: PlatformId[] = [\n\t\t\t\"ncmMusicId\",\n\t\t\t\"qqMusicId\",\n\t\t\t\"spotifyId\",\n\t\t\t\"appleMusicId\",\n\t\t];\n\n\t\tconst orderedPlatformIds: Partial<Record<PlatformId, string[]>> = {};\n\n\t\tfor (const key of preferredOrder) {\n\t\t\tif (platformIds[key]) {\n\t\t\t\torderedPlatformIds[key] = platformIds[key];\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of Object.keys(platformIds) as PlatformId[]) {\n\t\t\tif (!orderedPlatformIds[key]) {\n\t\t\t\torderedPlatformIds[key] = platformIds[key];\n\t\t\t}\n\t\t}\n\n\t\treturn orderedPlatformIds;\n\t}\n\n\tprivate parseHead(doc: Document): {\n\t\tmetadata: TTMLMetadata;\n\t\tsidecar: IExtensionSidecar;\n\t} {\n\t\tconst head = doc.getElementsByTagName(Elements.Head)[0];\n\n\t\tconst resultMeta: TTMLMetadata = {\n\t\t\ttitle: [],\n\t\t\tartist: [],\n\t\t\talbum: [],\n\t\t\tisrc: [],\n\t\t\tauthorIds: [],\n\t\t\tauthorNames: [],\n\t\t\tsongwriters: [],\n\t\t\tagents: {},\n\t\t\trawProperties: {},\n\t\t};\n\t\tconst sidecar: IExtensionSidecar = {};\n\n\t\tif (!head) {\n\t\t\treturn { metadata: resultMeta, sidecar };\n\t\t}\n\n\t\tthis.parseTTMElements(head, resultMeta);\n\t\tthis.parseAMLLMeta(head, resultMeta);\n\t\tthis.parseiTunesExtensions(head, resultMeta, sidecar);\n\t\tthis.deduplicateMetadata(resultMeta);\n\n\t\treturn { metadata: resultMeta, sidecar };\n\t}\n\n\tprivate deduplicateMetadata(meta: TTMLMetadata) {\n\t\tconst dedupe = (arr?: string[]) => (arr ? Array.from(new Set(arr)) : []);\n\n\t\tmeta.title = dedupe(meta.title);\n\t\tmeta.artist = dedupe(meta.artist);\n\t\tmeta.album = dedupe(meta.album);\n\t\tmeta.isrc = dedupe(meta.isrc);\n\t\tmeta.authorIds = dedupe(meta.authorIds);\n\t\tmeta.authorNames = dedupe(meta.authorNames);\n\t\tmeta.songwriters = dedupe(meta.songwriters);\n\n\t\tif (meta.platformIds) {\n\t\t\tfor (const key of Object.keys(meta.platformIds) as PlatformId[]) {\n\t\t\t\tif (meta.platformIds[key]) {\n\t\t\t\t\tmeta.platformIds[key] = dedupe(meta.platformIds[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (meta.rawProperties) {\n\t\t\tfor (const key of Object.keys(meta.rawProperties)) {\n\t\t\t\tif (meta.rawProperties[key]) {\n\t\t\t\t\tmeta.rawProperties[key] = dedupe(meta.rawProperties[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate parseTTMElements(head: Element, meta: TTMLMetadata) {\n\t\tconst titles = head.getElementsByTagNameNS(NS.TTM, Elements.Title);\n\t\tif (titles.length > 0 && titles[0].textContent) {\n\t\t\tmeta.title?.push(titles[0].textContent.trim());\n\t\t}\n\n\t\tconst agents = Array.from(\n\t\t\thead.getElementsByTagNameNS(NS.TTM, Elements.Agent),\n\t\t);\n\n\t\tfor (const agent of agents) {\n\t\t\tconst id = this.getAttr(agent, NS.XML, Attributes.Id);\n\n\t\t\tif (!id) continue;\n\n\t\t\tconst type = this.getAttr(\n\t\t\t\tagent,\n\t\t\t\tNS.TTM,\n\t\t\t\tAttributes.Type,\n\t\t\t\tAttributes.Type,\n\t\t\t);\n\n\t\t\tconst names = agent.getElementsByTagNameNS(NS.TTM, Elements.Name);\n\n\t\t\tconst agentObj: Agent = {\n\t\t\t\tid: id,\n\t\t\t};\n\n\t\t\tif (type) {\n\t\t\t\tagentObj.type = type;\n\t\t\t}\n\n\t\t\tif (names.length > 0 && names[0].textContent) {\n\t\t\t\tconst rawName = names[0].textContent.trim();\n\t\t\t\tif (rawName.length > 0) {\n\t\t\t\t\tagentObj.name = rawName;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmeta.agents ??= {};\n\t\t\tmeta.agents[id] = agentObj;\n\t\t}\n\t}\n\n\tprivate parseAMLLMeta(head: Element, meta: TTMLMetadata) {\n\t\tconst metas = Array.from(\n\t\t\thead.getElementsByTagNameNS(NS.AMLL, Elements.Meta),\n\t\t);\n\n\t\tconst validMetas = metas.filter((el) => {\n\t\t\treturn (\n\t\t\t\tthis.getAttr(el, NS.AMLL, Attributes.Key) &&\n\t\t\t\tthis.getAttr(el, NS.AMLL, Attributes.Value)\n\t\t\t);\n\t\t});\n\n\t\tfor (const el of validMetas) {\n\t\t\tconst key = this.getAttr(el, NS.AMLL, Attributes.Key);\n\t\t\tconst value = this.getAttr(el, NS.AMLL, Attributes.Value)?.trim();\n\n\t\t\tif (!key || !value) continue;\n\n\t\t\tswitch (key) {\n\t\t\t\tcase Values.MusicName:\n\t\t\t\t\tmeta.title?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.Artists:\n\t\t\t\t\tmeta.artist?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.Album:\n\t\t\t\t\tmeta.album?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.ISRC:\n\t\t\t\t\tmeta.isrc?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.TTMLAuthorGithub:\n\t\t\t\t\tmeta.authorIds?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.TTMLAuthorGithubLogin:\n\t\t\t\t\tmeta.authorNames?.push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Values.NCMMusicId:\n\t\t\t\tcase Values.QQMusicId:\n\t\t\t\tcase Values.SpotifyId:\n\t\t\t\tcase Values.AppleMusicId:\n\t\t\t\t\tmeta.platformIds ??= {};\n\t\t\t\t\t(meta.platformIds[key] ??= []).push(value);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tmeta.rawProperties ??= {};\n\t\t\t\t\t(meta.rawProperties[key] ??= []).push(value);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate extractSubContent(\n\t\tbase: LyricBase | BackgroundVocal,\n\t\tlang: string | null,\n\t\tignoreWords: boolean = false,\n\t): { main?: SubLyricContent; bg?: SubLyricContent } {\n\t\tconst result: { main?: SubLyricContent; bg?: SubLyricContent } = {};\n\n\t\tconst mainText = this.normalizeText(base.text);\n\t\tconst hasMainWords = !ignoreWords && base.words && base.words.length > 0;\n\n\t\tif (mainText || hasMainWords) {\n\t\t\tconst main: SubLyricContent = { text: mainText };\n\t\t\tif (lang) main.language = lang;\n\n\t\t\tif (hasMainWords) {\n\t\t\t\tconst isZeroFallback =\n\t\t\t\t\tbase.words?.length === 1 &&\n\t\t\t\t\tbase.words?.[0].startTime === 0 &&\n\t\t\t\t\tbase.words?.[0].endTime === 0;\n\n\t\t\t\tif (!isZeroFallback) main.words = base.words;\n\t\t\t}\n\t\t\tresult.main = main;\n\t\t}\n\n\t\tif (\"backgroundVocal\" in base && base.backgroundVocal) {\n\t\t\tconst bgVocal = base.backgroundVocal;\n\t\t\tconst bgText = this.normalizeText(bgVocal.text);\n\t\t\tconst hasBgWords =\n\t\t\t\t!ignoreWords && bgVocal.words && bgVocal.words.length > 0;\n\n\t\t\tif (bgText || hasBgWords) {\n\t\t\t\tconst bg: SubLyricContent = { text: bgText };\n\t\t\t\tif (lang) bg.language = lang;\n\n\t\t\t\tif (hasBgWords) {\n\t\t\t\t\tconst isZeroFallback =\n\t\t\t\t\t\tbgVocal.words?.length === 1 &&\n\t\t\t\t\t\tbgVocal.words?.[0].startTime === 0 &&\n\t\t\t\t\t\tbgVocal.words?.[0].endTime === 0;\n\n\t\t\t\t\tif (!isZeroFallback) bg.words = bgVocal.words;\n\t\t\t\t}\n\t\t\t\tresult.bg = bg;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate parseiTunesExtensions(\n\t\thead: Element,\n\t\tmeta: TTMLMetadata,\n\t\tsidecar: IExtensionSidecar,\n\t) {\n\t\tconst iTunesMetas = Array.from(\n\t\t\thead.getElementsByTagName(Elements.ITunesMetadata),\n\t\t);\n\t\tif (iTunesMetas.length === 0) return;\n\n\t\tfor (const iTunesMeta of iTunesMetas) {\n\t\t\tconst songwritersContainer = iTunesMeta.getElementsByTagName(\n\t\t\t\tElements.Songwriters,\n\t\t\t)[0];\n\t\t\tif (songwritersContainer) {\n\t\t\t\tconst writers = Array.from(\n\t\t\t\t\tsongwritersContainer.getElementsByTagName(Elements.Songwriter),\n\t\t\t\t);\n\t\t\t\tfor (const writer of writers) {\n\t\t\t\t\tconst name = writer.textContent?.trim();\n\t\t\t\t\tif (name) {\n\t\t\t\t\t\tmeta.songwriters?.push(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst processEntries = (\n\t\t\t\tcontainerTagName: string,\n\t\t\t\titemTagName: string,\n\t\t\t\ttype: \"translations\" | \"romanizations\",\n\t\t\t) => {\n\t\t\t\tconst container = iTunesMeta.getElementsByTagName(containerTagName)[0];\n\t\t\t\tif (!container) return;\n\n\t\t\t\tconst items = Array.from(container.getElementsByTagName(itemTagName));\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconst lang = this.getAttr(item, NS.XML, Attributes.Lang);\n\n\t\t\t\t\tconst textNodes = Array.from(\n\t\t\t\t\t\titem.getElementsByTagName(Elements.Text),\n\t\t\t\t\t);\n\t\t\t\t\tfor (const textNode of textNodes) {\n\t\t\t\t\t\tconst forId = textNode.getAttribute(Attributes.For);\n\t\t\t\t\t\tconst parsedContent = this.parseCommonContent(textNode);\n\n\t\t\t\t\t\tif (forId) {\n\t\t\t\t\t\t\tconst subContents = this.extractSubContent(\n\t\t\t\t\t\t\t\tparsedContent,\n\t\t\t\t\t\t\t\tlang,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tsidecar[forId] ??= {};\n\n\t\t\t\t\t\t\tif (subContents.main) {\n\t\t\t\t\t\t\t\t(sidecar[forId][type] ??= []).push(subContents.main);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (subContents.bg) {\n\t\t\t\t\t\t\t\tconst bgType =\n\t\t\t\t\t\t\t\t\ttype === \"translations\"\n\t\t\t\t\t\t\t\t\t\t? \"bgTranslations\"\n\t\t\t\t\t\t\t\t\t\t: \"bgRomanizations\";\n\t\t\t\t\t\t\t\t(sidecar[forId][bgType] ??= []).push(subContents.bg);\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};\n\n\t\t\tprocessEntries(\n\t\t\t\tElements.Translations,\n\t\t\t\tElements.Translation,\n\t\t\t\t\"translations\",\n\t\t\t);\n\t\t\tprocessEntries(\n\t\t\t\tElements.Transliterations,\n\t\t\t\tElements.Transliteration,\n\t\t\t\t\"romanizations\",\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate parseTime(timeStr: string | null): number {\n\t\tif (!timeStr) return 0;\n\n\t\tconst cleanStr = timeStr.trim();\n\t\tif (cleanStr.length === 0) return 0;\n\n\t\tif (cleanStr.endsWith(\"s\")) {\n\t\t\tconst seconds = Number(cleanStr.slice(0, -1));\n\t\t\tif (Number.isNaN(seconds)) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn Math.round(seconds * 1000);\n\t\t}\n\n\t\tconst match = cleanStr.match(TTMLParser.TIME_REGEX);\n\n\t\tif (match?.groups) {\n\t\t\tconst { seconds, minutes, hours } = match.groups;\n\n\t\t\tconst secNum = Number(seconds);\n\t\t\tconst minNum = minutes ? parseInt(minutes, 10) : 0;\n\t\t\tconst hrNum = hours ? parseInt(hours, 10) : 0;\n\n\t\t\tif (\n\t\t\t\t!Number.isNaN(secNum) &&\n\t\t\t\t!Number.isNaN(minNum) &&\n\t\t\t\t!Number.isNaN(hrNum)\n\t\t\t) {\n\t\t\t\tconst totalSeconds = hrNum * 3600 + minNum * 60 + secNum;\n\t\t\t\treturn Math.round(totalSeconds * 1000);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tprivate parseBody(\n\t\tdoc: Document,\n\t\tresult: TTMLResult,\n\t\tsidecar: IExtensionSidecar,\n\t) {\n\t\tconst body = doc.getElementsByTagName(Elements.Body)[0];\n\t\tif (!body) return;\n\n\t\tconst childNodes = Array.from(body.childNodes);\n\t\tlet currentBlockIndex = 0;\n\n\t\tfor (const node of childNodes) {\n\t\t\tif (node.nodeType !== NodeType.ELEMENT_NODE) continue;\n\t\t\tconst el = node as Element;\n\n\t\t\tconst tagName = el.localName || el.tagName.toLowerCase().split(\":\").pop();\n\n\t\t\tif (tagName === Elements.Div) {\n\t\t\t\tcurrentBlockIndex++;\n\n\t\t\t\tconst songPart =\n\t\t\t\t\tthis.getAttr(el, NS.ITUNES, Attributes.SongPartKebab) ||\n\t\t\t\t\tthis.getAttr(el, NS.ITUNES, Attributes.SongPart);\n\n\t\t\t\tconst pNodes = el.getElementsByTagNameNS(NS.TT, Elements.P);\n\t\t\t\tconst pList =\n\t\t\t\t\tpNodes.length > 0\n\t\t\t\t\t\t? Array.from(pNodes)\n\t\t\t\t\t\t: Array.from(el.getElementsByTagName(Elements.P));\n\n\t\t\t\tfor (const p of pList) {\n\t\t\t\t\tthis.processLineElement(\n\t\t\t\t\t\tp,\n\t\t\t\t\t\tresult.lines,\n\t\t\t\t\t\tsidecar,\n\t\t\t\t\t\tsongPart,\n\t\t\t\t\t\tcurrentBlockIndex,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (tagName === Elements.P) {\n\t\t\t\tcurrentBlockIndex++;\n\t\t\t\tthis.processLineElement(\n\t\t\t\t\tel,\n\t\t\t\t\tresult.lines,\n\t\t\t\t\tsidecar,\n\t\t\t\t\tundefined,\n\t\t\t\t\tcurrentBlockIndex,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processLineElement(\n\t\tp: Element,\n\t\tlines: LyricLine[],\n\t\tsidecar: IExtensionSidecar,\n\t\tsongPart?: string | null,\n\t\tblockIndex?: number,\n\t) {\n\t\tconst id = this.getAttr(p, NS.ITUNES, Attributes.Key);\n\t\tif (!id) return;\n\n\t\tconst baseContent = this.parseCommonContent(p);\n\n\t\tconst line: LyricLine = {\n\t\t\tid: id,\n\t\t\t...baseContent,\n\t\t};\n\n\t\tif (songPart) line.songPart = songPart;\n\t\tif (blockIndex !== undefined) line.blockIndex = blockIndex;\n\n\t\tconst agentId = this.getAttr(p, NS.TTM, Elements.Agent);\n\t\tif (agentId) line.agentId = agentId;\n\n\t\tconst externalData = sidecar[id];\n\t\tif (externalData) {\n\t\t\tif (externalData.translations) {\n\t\t\t\t(line.translations ??= []).push(...externalData.translations);\n\t\t\t}\n\t\t\tif (externalData.romanizations) {\n\t\t\t\t(line.romanizations ??= []).push(...externalData.romanizations);\n\t\t\t}\n\t\t\tif (externalData.bgTranslations && line.backgroundVocal) {\n\t\t\t\t(line.backgroundVocal.translations ??= []).push(\n\t\t\t\t\t...externalData.bgTranslations,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (externalData.bgRomanizations && line.backgroundVocal) {\n\t\t\t\t(line.backgroundVocal.romanizations ??= []).push(\n\t\t\t\t\t...externalData.bgRomanizations,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tlines.push(line);\n\t}\n\n\tprivate parseCommonContent(element: Element): LyricBase {\n\t\tconst beginAttr = this.getAttr(\n\t\t\telement,\n\t\t\tNS.XML,\n\t\t\tAttributes.Begin,\n\t\t\tAttributes.Begin,\n\t\t);\n\t\tconst endAttr = this.getAttr(\n\t\t\telement,\n\t\t\tNS.XML,\n\t\t\tAttributes.End,\n\t\t\tAttributes.End,\n\t\t);\n\t\tconst originalStartTime = this.parseTime(beginAttr);\n\t\tconst originalEndTime = this.parseTime(endAttr);\n\n\t\tconst state = this.extractNodeState(element);\n\n\t\tif (state.backgroundVocal) {\n\t\t\tif (state.bgTranslations.length > 0) {\n\t\t\t\t(state.backgroundVocal.translations ??= []).push(\n\t\t\t\t\t...state.bgTranslations,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (state.bgRomanizations.length > 0) {\n\t\t\t\t(state.backgroundVocal.romanizations ??= []).push(\n\t\t\t\t\t...state.bgRomanizations,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.finalizeWords(state.words);\n\n\t\tconst { startTime, endTime } = this.calculateTimeRange(\n\t\t\toriginalStartTime,\n\t\t\toriginalEndTime,\n\t\t\tstate.words,\n\t\t\tstate.backgroundVocal,\n\t\t);\n\n\t\tconst cleanFullText = this.normalizeText(state.fullText);\n\t\tconst hasTimeAttrs = beginAttr !== null || endAttr !== null;\n\t\tthis.applyFallbackWord(\n\t\t\tstate.words,\n\t\t\tcleanFullText,\n\t\t\thasTimeAttrs,\n\t\t\toriginalStartTime,\n\t\t\toriginalEndTime,\n\t\t\tstartTime,\n\t\t\tendTime,\n\t\t);\n\n\t\treturn this.buildLyricBase(state, cleanFullText, startTime, endTime);\n\t}\n\n\tprivate extractNodeState(element: Element): IParsedState {\n\t\tconst state: IParsedState = {\n\t\t\tfullText: \"\",\n\t\t\twords: [],\n\t\t\ttranslations: [],\n\t\t\tromanizations: [],\n\t\t\tbgTranslations: [],\n\t\t\tbgRomanizations: [],\n\t\t\tbackgroundVocal: undefined,\n\t\t};\n\n\t\tconst childNodes = Array.from(element.childNodes);\n\t\tfor (const node of childNodes) {\n\t\t\tif (node.nodeType === NodeType.TEXT_NODE) {\n\t\t\t\tthis.processTextNode(state, node);\n\t\t\t} else if (node.nodeType === NodeType.ELEMENT_NODE) {\n\t\t\t\tthis.processElementNode(state, node as Element);\n\t\t\t}\n\t\t}\n\n\t\treturn state;\n\t}\n\n\tprivate calculateTimeRange(\n\t\toriginalStart: number,\n\t\toriginalEnd: number,\n\t\twords: Syllable[],\n\t\tbgVocal?: BackgroundVocal,\n\t): { startTime: number; endTime: number } {\n\t\tlet startTime = originalStart;\n\t\tlet endTime = originalEnd;\n\n\t\tconst timedElements = [...words];\n\t\tif (bgVocal) {\n\t\t\ttimedElements.push(bgVocal);\n\t\t}\n\n\t\tif (timedElements.length > 0) {\n\t\t\tlet minChildStart = Infinity;\n\t\t\tlet maxChildEnd = 0;\n\n\t\t\tfor (const el of timedElements) {\n\t\t\t\tif (el.startTime < minChildStart) minChildStart = el.startTime;\n\t\t\t\tif (el.endTime > maxChildEnd) maxChildEnd = el.endTime;\n\t\t\t}\n\n\t\t\tif (startTime === 0 || (minChildStart > 0 && minChildStart < startTime)) {\n\t\t\t\tstartTime = minChildStart === Infinity ? 0 : minChildStart;\n\t\t\t}\n\n\t\t\tif (endTime === 0 || maxChildEnd > endTime) {\n\t\t\t\tendTime = maxChildEnd;\n\t\t\t}\n\t\t}\n\n\t\treturn { startTime, endTime };\n\t}\n\n\tprivate applyFallbackWord(\n\t\twords: Syllable[],\n\t\tcleanText: string,\n\t\thasTimeAttrs: boolean,\n\t\torigStart: number,\n\t\torigEnd: number,\n\t\tcalcStart: number,\n\t\tcalcEnd: number,\n\t): void {\n\t\tif (words.length === 0 && cleanText.length > 0 && hasTimeAttrs) {\n\t\t\twords.push({\n\t\t\t\ttext: cleanText,\n\t\t\t\tstartTime: origStart > 0 ? origStart : calcStart,\n\t\t\t\tendTime: origEnd > 0 ? origEnd : calcEnd,\n\t\t\t\tendsWithSpace: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate buildLyricBase(\n\t\tstate: IParsedState,\n\t\tcleanText: string,\n\t\tstartTime: number,\n\t\tendTime: number,\n\t): LyricBase {\n\t\treturn {\n\t\t\ttext: cleanText,\n\t\t\tstartTime,\n\t\t\tendTime,\n\t\t\twords: state.words.length > 0 ? state.words : undefined,\n\t\t\ttranslations:\n\t\t\t\tstate.translations.length > 0 ? state.translations : undefined,\n\t\t\tromanizations:\n\t\t\t\tstate.romanizations.length > 0 ? state.romanizations : undefined,\n\t\t\tbackgroundVocal: state.backgroundVocal,\n\t\t};\n\t}\n\n\tprivate processTextNode(state: IParsedState, node: Node): void {\n\t\tconst rawText = node.textContent || \"\";\n\t\tconst isFormatting = rawText.includes(\"\\n\");\n\n\t\tif (isFormatting && rawText.trim().length === 0) return;\n\n\t\tconst normalizedText = this.normalizeText(rawText, false);\n\n\t\tstate.fullText += normalizedText;\n\n\t\tif (\n\t\t\t!isFormatting &&\n\t\t\tnormalizedText.length > 0 &&\n\t\t\tnormalizedText.trim().length === 0\n\t\t) {\n\t\t\tif (state.words.length > 0) {\n\t\t\t\tstate.words[state.words.length - 1].endsWithSpace = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processElementNode(state: IParsedState, el: Element): void {\n\t\tconst role = this.getAttr(el, NS.TTM, Attributes.Role);\n\n\t\tconst rubyAttr = this.getAttr(\n\t\t\tel,\n\t\t\tNS.TTS,\n\t\t\tAttributes.Ruby,\n\t\t\tQualifiedAttributes.TtsRuby,\n\t\t);\n\n\t\tif (rubyAttr === Values.RubyContainer) {\n\t\t\tthis.processRubyElement(state, el);\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (role) {\n\t\t\tcase Values.RoleBg:\n\t\t\t\tstate.backgroundVocal = this.parseBackgroundVocal(el);\n\t\t\t\tbreak;\n\t\t\tcase Values.RoleTranslation: {\n\t\t\t\tconst translation = this.parseInlineSubContent(el);\n\t\t\t\tif (translation) {\n\t\t\t\t\tif (translation.main) state.translations.push(translation.main);\n\t\t\t\t\tif (translation.bg) state.bgTranslations.push(translation.bg);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Values.RoleRoman: {\n\t\t\t\tconst romanization = this.parseInlineSubContent(el);\n\t\t\t\tif (romanization) {\n\t\t\t\t\tif (romanization.main) state.romanizations.push(romanization.main);\n\t\t\t\t\tif (romanization.bg) state.bgRomanizations.push(romanization.bg);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthis.processWordElement(state, el);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate processRubyElement(state: IParsedState, containerEl: Element): void {\n\t\tconst obsceneAttr = this.getAttr(\n\t\t\tcontainerEl,\n\t\t\tNS.AMLL,\n\t\t\tAttributes.Obscene,\n\t\t\tQualifiedAttributes.AmllObscene,\n\t\t);\n\t\tconst isObscene = obsceneAttr === \"true\";\n\n\t\tconst emptyBeatAttr = this.getAttr(\n\t\t\tcontainerEl,\n\t\t\tNS.AMLL,\n\t\t\tAttributes.EmptyBeat,\n\t\t\tQualifiedAttributes.AmllEmptyBeat,\n\t\t);\n\t\tlet emptyBeat: number | undefined;\n\t\tif (emptyBeatAttr) {\n\t\t\tconst parsedBeat = parseInt(emptyBeatAttr, 10);\n\t\t\tif (!Number.isNaN(parsedBeat)) {\n\t\t\t\temptyBeat = parsedBeat;\n\t\t\t}\n\t\t}\n\n\t\tlet baseText = \"\";\n\t\tconst rubyTags: { text: string; startTime: number; endTime: number }[] = [];\n\n\t\tconst childNodes = Array.from(containerEl.childNodes);\n\n\t\tfor (const node of childNodes) {\n\t\t\tif (node.nodeType !== NodeType.ELEMENT_NODE) continue;\n\t\t\tconst childEl = node as Element;\n\n\t\t\tconst childRubyAttr = this.getAttr(\n\t\t\t\tchildEl,\n\t\t\t\tNS.TTS,\n\t\t\t\tAttributes.Ruby,\n\t\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\t);\n\n\t\t\tif (childRubyAttr === Values.RubyBase) {\n\t\t\t\tbaseText = this.normalizeText(childEl.textContent, false);\n\t\t\t} else if (childRubyAttr === Values.RubyTextContainer) {\n\t\t\t\tconst textNodes = Array.from(childEl.childNodes);\n\t\t\t\tfor (const textNode of textNodes) {\n\t\t\t\t\tif (textNode.nodeType !== NodeType.ELEMENT_NODE) continue;\n\t\t\t\t\tconst tNode = textNode as Element;\n\n\t\t\t\t\tconst tAttr = this.getAttr(\n\t\t\t\t\t\ttNode,\n\t\t\t\t\t\tNS.TTS,\n\t\t\t\t\t\tAttributes.Ruby,\n\t\t\t\t\t\tQualifiedAttributes.TtsRuby,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (tAttr === Values.RubyText) {\n\t\t\t\t\t\tconst begin = this.getAttr(\n\t\t\t\t\t\t\ttNode,\n\t\t\t\t\t\t\tNS.XML,\n\t\t\t\t\t\t\tAttributes.Begin,\n\t\t\t\t\t\t\tAttributes.Begin,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst end = this.getAttr(\n\t\t\t\t\t\t\ttNode,\n\t\t\t\t\t\t\tNS.XML,\n\t\t\t\t\t\t\tAttributes.End,\n\t\t\t\t\t\t\tAttributes.End,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst text = this.normalizeText(tNode.textContent, false).trim();\n\n\t\t\t\t\t\tif (text && begin && end) {\n\t\t\t\t\t\t\trubyTags.push({\n\t\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\t\tstartTime: this.parseTime(begin),\n\t\t\t\t\t\t\t\tendTime: this.parseTime(end),\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}\n\t\t}\n\n\t\tif (!baseText) return;\n\n\t\tstate.fullText += baseText;\n\n\t\tlet startTime = 0;\n\t\tlet endTime = 0;\n\t\tif (rubyTags.length > 0) {\n\t\t\tstartTime = Math.min(...rubyTags.map((t) => t.startTime));\n\t\t\tendTime = Math.max(...rubyTags.map((t) => t.endTime));\n\t\t}\n\n\t\tconst cleanBaseText = baseText.trim();\n\t\tif (cleanBaseText.length > 0) {\n\t\t\tconst endsWithSpace = TTMLParser.TRAILING_SPACE_REGEX.test(baseText);\n\t\t\tconst startsWithSpace = TTMLParser.LEADING_SPACE_REGEX.test(baseText);\n\n\t\t\tif (startsWithSpace && state.words.length > 0) {\n\t\t\t\tstate.words[state.words.length - 1].endsWithSpace = true;\n\t\t\t}\n\n\t\t\tstate.words.push({\n\t\t\t\ttext: cleanBaseText,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\truby: rubyTags.length > 0 ? rubyTags : undefined,\n\t\t\t\tendsWithSpace: endsWithSpace,\n\t\t\t\tobscene: isObscene ? true : undefined,\n\t\t\t\temptyBeat,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate processWordElement(state: IParsedState, el: Element): void {\n\t\tconst wBegin = this.getAttr(el, NS.XML, Attributes.Begin, Attributes.Begin);\n\t\tconst wEnd = this.getAttr(el, NS.XML, Attributes.End, Attributes.End);\n\n\t\tconst obsceneAttr = this.getAttr(\n\t\t\tel,\n\t\t\tNS.AMLL,\n\t\t\tAttributes.Obscene,\n\t\t\tQualifiedAttributes.AmllObscene,\n\t\t);\n\t\tconst isObscene = obsceneAttr === \"true\";\n\n\t\tconst emptyBeatAttr = this.getAttr(\n\t\t\tel,\n\t\t\tNS.AMLL,\n\t\t\tAttributes.EmptyBeat,\n\t\t\tQualifiedAttributes.AmllEmptyBeat,\n\t\t);\n\t\tlet emptyBeat: number | undefined;\n\t\tif (emptyBeatAttr) {\n\t\t\tconst parsedBeat = parseInt(emptyBeatAttr, 10);\n\t\t\tif (!Number.isNaN(parsedBeat)) {\n\t\t\t\temptyBeat = parsedBeat;\n\t\t\t}\n\t\t}\n\n\t\tconst rawWText = el.textContent || \"\";\n\t\tconst normalizedWText = this.normalizeText(rawWText, false);\n\n\t\tstate.fullText += normalizedWText;\n\n\t\tif (wBegin && wEnd) {\n\t\t\tconst isFormatting = rawWText.includes(\"\\n\");\n\n\t\t\tlet startsWithSpace = false;\n\t\t\tlet endsWithSpace = false;\n\n\t\t\tif (!isFormatting) {\n\t\t\t\tstartsWithSpace = TTMLParser.LEADING_SPACE_REGEX.test(normalizedWText);\n\t\t\t\tendsWithSpace = TTMLParser.TRAILING_SPACE_REGEX.test(normalizedWText);\n\t\t\t}\n\n\t\t\tconst cleanText = normalizedWText.trim();\n\n\t\t\tif (startsWithSpace && state.words.length > 0) {\n\t\t\t\tstate.words[state.words.length - 1].endsWithSpace = true;\n\t\t\t}\n\n\t\t\tif (cleanText.length > 0) {\n\t\t\t\tstate.words.push({\n\t\t\t\t\ttext: cleanText,\n\t\t\t\t\tstartTime: this.parseTime(wBegin),\n\t\t\t\t\tendTime: this.parseTime(wEnd),\n\t\t\t\t\tendsWithSpace: endsWithSpace,\n\t\t\t\t\tobscene: isObscene ? true : undefined,\n\t\t\t\t\temptyBeat,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate parseBackgroundVocal(el: Element): BackgroundVocal {\n\t\tconst parsed = this.parseCommonContent(el);\n\t\tconst { backgroundVocal, ...bgVocal } = parsed;\n\n\t\tbgVocal.text = bgVocal.text.replace(/^[(（]+/, \"\").replace(/[)）]+$/, \"\");\n\n\t\tif (bgVocal.words && bgVocal.words.length > 0) {\n\t\t\tbgVocal.words[0].text = bgVocal.words[0].text\n\t\t\t\t.replace(/^[(（]+/, \"\")\n\t\t\t\t.trimStart();\n\n\t\t\tconst lastIdx = bgVocal.words.length - 1;\n\t\t\tbgVocal.words[lastIdx].text = bgVocal.words[lastIdx].text\n\t\t\t\t.replace(/[)）]+$/, \"\")\n\t\t\t\t.trimEnd();\n\t\t}\n\n\t\treturn bgVocal;\n\t}\n\n\tprivate parseInlineSubContent(\n\t\tel: Element,\n\t): { main?: SubLyricContent; bg?: SubLyricContent } | null {\n\t\tconst lang = this.getAttr(el, NS.XML, Attributes.Lang);\n\t\tconst parsed = this.parseCommonContent(el);\n\n\t\t// 内联的音译和翻译不会出现逐字内容，只有 sidecar 里才会有逐字翻译和音译\n\t\tconst content = this.extractSubContent(parsed, lang, true);\n\n\t\tif (content.main || content.bg) {\n\t\t\treturn content;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate finalizeWords(words: Syllable[]): Syllable[] {\n\t\tif (words.length === 0) return [];\n\n\t\twords[0].text = words[0].text.trimStart();\n\n\t\tconst lastIdx = words.length - 1;\n\t\twords[lastIdx].text = words[lastIdx].text.trimEnd();\n\t\twords[lastIdx].endsWithSpace = false;\n\n\t\treturn words;\n\t}\n\n\tprivate getAttr(\n\t\telement: Element,\n\t\tns: string,\n\t\tlocalName: string,\n\t\tfallbackAttrName?: string,\n\t): string | null {\n\t\tconst val = element.getAttributeNS(ns, localName);\n\t\tif (val) return val;\n\n\t\tif (fallbackAttrName) {\n\t\t\tconst fallbackVal = element.getAttribute(fallbackAttrName);\n\t\t\tif (fallbackVal) return fallbackVal;\n\t\t}\n\n\t\tif (element.hasAttributes()) {\n\t\t\tconst attributes = Array.from(element.attributes);\n\t\t\tfor (const attr of attributes) {\n\t\t\t\tconst attrLocalName = attr.localName || attr.nodeName.split(\":\").pop();\n\n\t\t\t\tif (attrLocalName === localName) {\n\t\t\t\t\treturn attr.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n}\n","/**\n * 包含解析器内部的复杂数据结构和 AMLL 简单的数据结构的互转功能的模块\n * @module amll-converter\n */\n\nimport { Elements, Values } from \"../constants\";\nimport type {\n\tAmllLyricLine,\n\tAmllLyricResult,\n\tAmllLyricWord,\n\tAmllMetadata,\n\tAmllToTTMLOptions,\n\tLyricBase,\n\tLyricLine,\n\tSyllable,\n\tTTMLMetadata,\n\tTTMLResult,\n\tTTMLToAmllOptions,\n} from \"../types\";\n\n/**\n * 将本解析器复杂的数据结构降级为 AMLL 所使用的较简单的数据结构\n */\nexport function toAmllLyrics(\n\tresult: TTMLResult,\n\toptions?: TTMLToAmllOptions,\n): AmllLyricResult {\n\tconst amllLines: AmllLyricLine[] = [];\n\n\tconst convertToAmllLine = (\n\t\tsource: LyricBase,\n\t\tisBG: boolean,\n\t\tisDuet: boolean,\n\t): AmllLyricLine => {\n\t\tlet amllWords: AmllLyricWord[] = [];\n\n\t\tif (source.words && source.words.length > 0) {\n\t\t\tamllWords = source.words.map((w) => {\n\t\t\t\tconst amllWord: AmllLyricWord = {\n\t\t\t\t\tstartTime: w.startTime,\n\t\t\t\t\tendTime: w.endTime,\n\t\t\t\t\tword: w.text + (w.endsWithSpace ? \" \" : \"\"),\n\t\t\t\t\tromanWord: \"\",\n\t\t\t\t\tobscene: w.obscene,\n\t\t\t\t\temptyBeat: w.emptyBeat,\n\t\t\t\t};\n\n\t\t\t\tif (w.ruby && w.ruby.length > 0) {\n\t\t\t\t\tamllWord.ruby = w.ruby.map((r) => ({\n\t\t\t\t\t\tstartTime: r.startTime,\n\t\t\t\t\t\tendTime: r.endTime,\n\t\t\t\t\t\tword: r.text,\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\treturn amllWord;\n\t\t\t});\n\t\t} else {\n\t\t\tamllWords = [\n\t\t\t\t{\n\t\t\t\t\tstartTime: source.startTime,\n\t\t\t\t\tendTime: source.endTime,\n\t\t\t\t\tword: source.text,\n\t\t\t\t\tromanWord: \"\",\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tlet transText = \"\";\n\t\tif (source.translations && source.translations.length > 0) {\n\t\t\tconst targetTrans =\n\t\t\t\t(options?.translationLanguage &&\n\t\t\t\t\tsource.translations.find(\n\t\t\t\t\t\t(t) => t.language === options.translationLanguage,\n\t\t\t\t\t)) ||\n\t\t\t\tsource.translations[0];\n\t\t\ttransText = targetTrans.text;\n\t\t}\n\n\t\tlet romanText = \"\";\n\t\tlet romanWords: Syllable[] | undefined;\n\t\tif (source.romanizations && source.romanizations.length > 0) {\n\t\t\tconst targetRoman =\n\t\t\t\t(options?.romanizationLanguage &&\n\t\t\t\t\tsource.romanizations.find(\n\t\t\t\t\t\t(r) => r.language === options.romanizationLanguage,\n\t\t\t\t\t)) ||\n\t\t\t\tsource.romanizations[0];\n\n\t\t\tromanWords = targetRoman.words;\n\n\t\t\tif (!romanWords || romanWords.length === 0) {\n\t\t\t\tromanText = targetRoman.text;\n\t\t\t}\n\t\t}\n\n\t\tif (romanWords && amllWords.length > 0) {\n\t\t\talignRomanization(amllWords, romanWords);\n\t\t}\n\n\t\treturn {\n\t\t\twords: amllWords,\n\t\t\ttranslatedLyric: transText,\n\t\t\tromanLyric: romanText,\n\t\t\tisBG: isBG,\n\t\t\tisDuet: isDuet,\n\t\t\tstartTime: source.startTime,\n\t\t\tendTime: source.endTime,\n\t\t};\n\t};\n\n\tlet lastPersonAgentId: string | null = null;\n\tlet lastPersonIsDuet: boolean = false;\n\n\tfor (const line of result.lines) {\n\t\tconst agentId = line.agentId || Values.AgentDefault;\n\t\tconst agent = result.metadata.agents?.[agentId];\n\t\tconst isGroup = agent?.type === Values.Group;\n\t\tconst isOther = agent?.type === Values.Other;\n\n\t\tlet currentIsDuet = false;\n\n\t\t// Apple Music 风格的对唱识别逻辑\n\t\tif (isGroup) {\n\t\t\t// 合唱始终非对唱，且不影响其他 agent type 的交替计算\n\t\t\tcurrentIsDuet = false;\n\t\t} else {\n\t\t\tif (lastPersonAgentId === null) {\n\t\t\t\t// 如果第一次遇到的演唱者类型是 Other，强制为对唱，否则非对唱\n\t\t\t\tcurrentIsDuet = !!isOther;\n\t\t\t\tlastPersonAgentId = agentId;\n\t\t\t\tlastPersonIsDuet = currentIsDuet;\n\t\t\t} else if (lastPersonAgentId === agentId) {\n\t\t\t\t// 与上一个非 Group 演唱者相同，保持对唱状态\n\t\t\t\tcurrentIsDuet = lastPersonIsDuet;\n\t\t\t} else {\n\t\t\t\t// 与上一个非 Group 演唱者不同，翻转对唱侧\n\t\t\t\tcurrentIsDuet = !lastPersonIsDuet;\n\t\t\t\tlastPersonAgentId = agentId;\n\t\t\t\tlastPersonIsDuet = currentIsDuet;\n\t\t\t}\n\t\t}\n\n\t\tconst amllMain = convertToAmllLine(line, false, currentIsDuet);\n\t\tamllLines.push(amllMain);\n\n\t\tif (line.backgroundVocal) {\n\t\t\tconst simpleBg = convertToAmllLine(\n\t\t\t\tline.backgroundVocal,\n\t\t\t\ttrue,\n\t\t\t\tcurrentIsDuet,\n\t\t\t);\n\t\t\tamllLines.push(simpleBg);\n\t\t}\n\t}\n\n\tconst amllMetadata: [string, string[]][] = [];\n\tconst meta = result.metadata;\n\n\tif (meta.title) amllMetadata.push([Values.MusicName, meta.title]);\n\tif (meta.artist) amllMetadata.push([Values.Artists, meta.artist]);\n\tif (meta.album) amllMetadata.push([Values.Album, meta.album]);\n\tif (meta.isrc) amllMetadata.push([Values.ISRC, meta.isrc]);\n\tif (meta.authorIds)\n\t\tamllMetadata.push([Values.TTMLAuthorGithub, meta.authorIds]);\n\tif (meta.authorNames)\n\t\tamllMetadata.push([Values.TTMLAuthorGithubLogin, meta.authorNames]);\n\n\tif (meta.language) amllMetadata.push([Values.Language, [meta.language]]);\n\tif (meta.timingMode)\n\t\tamllMetadata.push([Values.TimingMode, [meta.timingMode]]);\n\tif (meta.songwriters)\n\t\tamllMetadata.push([Elements.Songwriters, meta.songwriters]);\n\n\tif (meta.platformIds) {\n\t\tif (meta.platformIds.ncmMusicId)\n\t\t\tamllMetadata.push([Values.NCMMusicId, meta.platformIds.ncmMusicId]);\n\t\tif (meta.platformIds.qqMusicId)\n\t\t\tamllMetadata.push([Values.QQMusicId, meta.platformIds.qqMusicId]);\n\t\tif (meta.platformIds.spotifyId)\n\t\t\tamllMetadata.push([Values.SpotifyId, meta.platformIds.spotifyId]);\n\t\tif (meta.platformIds.appleMusicId)\n\t\t\tamllMetadata.push([Values.AppleMusicId, meta.platformIds.appleMusicId]);\n\t}\n\n\tif (meta.rawProperties) {\n\t\tfor (const [key, value] of Object.entries(meta.rawProperties)) {\n\t\t\tamllMetadata.push([key, value]);\n\t\t}\n\t}\n\n\treturn {\n\t\tlines: amllLines,\n\t\tmetadata: amllMetadata,\n\t};\n}\n\nfunction alignRomanization(amllWords: AmllLyricWord[], romanWords: Syllable[]) {\n\tlet romanSearchStartIndex = 0;\n\n\t/** 交并比阈值，至少有 10% 的面积重合 */\n\tconst MIN_IOU_THRESHOLD = 0.1;\n\n\t/** 快速通道，优先匹配时间戳完全相同的主歌词和音译音节，同时避免浮点数误差 */\n\tconst FAST_TRACK_TOLERANCE_MS = 2;\n\n\tfor (let i = 0; i < amllWords.length; i++) {\n\t\tconst main = amllWords[i];\n\t\tconst mainEndTime = main.endTime;\n\n\t\tlet maxIou = 0;\n\t\tlet bestMatchIndex = -1;\n\t\tlet isFastTrackMatched = false;\n\n\t\tlet j = romanSearchStartIndex;\n\t\twhile (j < romanWords.length) {\n\t\t\tconst sub = romanWords[j];\n\n\t\t\tif (Math.abs(main.startTime - sub.startTime) <= FAST_TRACK_TOLERANCE_MS) {\n\t\t\t\tmain.romanWord = sub.text;\n\t\t\t\tromanSearchStartIndex = j + 1;\n\t\t\t\tisFastTrackMatched = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst subEndTime = sub.endTime;\n\n\t\t\t// 交集\n\t\t\tconst overlapStart = Math.max(main.startTime, sub.startTime);\n\t\t\tconst overlapEnd = Math.min(mainEndTime, subEndTime);\n\t\t\tconst intersection = Math.max(0, overlapEnd - overlapStart);\n\n\t\t\tif (intersection > 0) {\n\t\t\t\t// 并集\n\t\t\t\tconst unionStart = Math.min(main.startTime, sub.startTime);\n\t\t\t\tconst unionEnd = Math.max(mainEndTime, subEndTime);\n\t\t\t\tconst unionDuration = Math.max(1, unionEnd - unionStart);\n\n\t\t\t\tconst iou = intersection / unionDuration;\n\n\t\t\t\tif (iou > maxIou) {\n\t\t\t\t\tmaxIou = iou;\n\t\t\t\t\tbestMatchIndex = j;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (sub.startTime >= mainEndTime) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\n\t\tif (\n\t\t\t!isFastTrackMatched &&\n\t\t\tbestMatchIndex !== -1 &&\n\t\t\tmaxIou >= MIN_IOU_THRESHOLD\n\t\t) {\n\t\t\tmain.romanWord = romanWords[bestMatchIndex].text;\n\t\t\tromanSearchStartIndex = bestMatchIndex + 1;\n\t\t}\n\t}\n}\n\n/**\n * 将 AMLL 格式的歌词和元数据转换为 TTMLResult 结构\n */\nexport function toTTMLResult(\n\tamllLines: AmllLyricLine[],\n\tamllMetadata: AmllMetadata[],\n\toptions: AmllToTTMLOptions = {},\n): TTMLResult {\n\tconst opts = {\n\t\ttranslationLanguage: \"zh-Hans\",\n\t\t...options,\n\t};\n\n\tconst metadata: TTMLMetadata = {\n\t\tagents: {\n\t\t\t[Values.AgentDefault]: { id: Values.AgentDefault },\n\t\t\t[Values.AgentDefaultDuet]: { id: Values.AgentDefaultDuet },\n\t\t},\n\t};\n\n\tfor (const entry of amllMetadata) {\n\t\tconst [key, value] = entry;\n\t\tif (!value || value.length === 0) continue;\n\n\t\tswitch (key) {\n\t\t\tcase Values.MusicName:\n\t\t\t\tmetadata.title = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.Artists:\n\t\t\t\tmetadata.artist = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.Album:\n\t\t\t\tmetadata.album = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.ISRC:\n\t\t\t\tmetadata.isrc = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.TTMLAuthorGithub:\n\t\t\t\tmetadata.authorIds = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.TTMLAuthorGithubLogin:\n\t\t\t\tmetadata.authorNames = value;\n\t\t\t\tbreak;\n\t\t\tcase Values.NCMMusicId:\n\t\t\tcase Values.QQMusicId:\n\t\t\tcase Values.SpotifyId:\n\t\t\tcase Values.AppleMusicId:\n\t\t\t\tif (!metadata.platformIds) {\n\t\t\t\t\tmetadata.platformIds = {};\n\t\t\t\t}\n\t\t\t\tmetadata.platformIds[key] = value;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (!metadata.rawProperties) {\n\t\t\t\t\tmetadata.rawProperties = {};\n\t\t\t\t}\n\t\t\t\tmetadata.rawProperties[key] = value;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst resultLines: LyricLine[] = [];\n\tlet currentMainLine: LyricLine | null = null;\n\n\tfor (const amllLine of amllLines) {\n\t\tconst { mainSyllables, romanSyllables, fullText, romanText } =\n\t\t\tconvertWords(amllLine);\n\n\t\tconst lyricBase: LyricBase = {\n\t\t\tstartTime: amllLine.startTime,\n\t\t\tendTime: amllLine.endTime,\n\t\t\ttext: fullText,\n\t\t\twords: mainSyllables,\n\t\t};\n\n\t\tif (amllLine.translatedLyric) {\n\t\t\tlyricBase.translations = [\n\t\t\t\t{\n\t\t\t\t\tlanguage: opts.translationLanguage,\n\t\t\t\t\ttext: amllLine.translatedLyric,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tif (amllLine.romanLyric || romanSyllables.length > 0) {\n\t\t\tlyricBase.romanizations = [\n\t\t\t\t{\n\t\t\t\t\tlanguage: opts.romanizationLanguage,\n\t\t\t\t\ttext: amllLine.romanLyric || romanText,\n\t\t\t\t\twords: romanSyllables.length > 0 ? romanSyllables : undefined,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tif (amllLine.isBG) {\n\t\t\tif (currentMainLine && !currentMainLine.backgroundVocal) {\n\t\t\t\tcurrentMainLine.backgroundVocal = lyricBase;\n\t\t\t} else {\n\t\t\t\tconst inheritedAgentId = currentMainLine\n\t\t\t\t\t? currentMainLine.agentId\n\t\t\t\t\t: Values.AgentDefault;\n\n\t\t\t\tconst promotedLine: LyricLine = {\n\t\t\t\t\tagentId: inheritedAgentId,\n\t\t\t\t\t...lyricBase,\n\t\t\t\t};\n\t\t\t\tresultLines.push(promotedLine);\n\t\t\t}\n\t\t} else {\n\t\t\tconst agentId = amllLine.isDuet\n\t\t\t\t? Values.AgentDefaultDuet\n\t\t\t\t: Values.AgentDefault;\n\n\t\t\tconst lyricLine: LyricLine = {\n\t\t\t\tagentId,\n\t\t\t\t...lyricBase,\n\t\t\t};\n\n\t\t\tresultLines.push(lyricLine);\n\t\t\tcurrentMainLine = lyricLine;\n\t\t}\n\t}\n\n\treturn {\n\t\tmetadata: metadata,\n\t\tlines: resultLines,\n\t};\n}\n\nfunction convertWords(amllLine: AmllLyricLine) {\n\tconst mainSyllables: Syllable[] = [];\n\tconst romanSyllables: Syllable[] = [];\n\n\tfor (const word of amllLine.words) {\n\t\tconst rawText = word.word;\n\t\tconst trimmedText = rawText.trimEnd();\n\t\tconst hasSpace = rawText !== trimmedText;\n\n\t\tconst syllable: Syllable = {\n\t\t\ttext: trimmedText,\n\t\t\tstartTime: word.startTime,\n\t\t\tendTime: word.endTime,\n\t\t\tendsWithSpace: hasSpace,\n\t\t\tobscene: word.obscene,\n\t\t\temptyBeat: word.emptyBeat,\n\t\t};\n\n\t\tif (word.ruby && word.ruby.length > 0) {\n\t\t\tsyllable.ruby = word.ruby.map((r) => ({\n\t\t\t\tstartTime: r.startTime,\n\t\t\t\tendTime: r.endTime,\n\t\t\t\ttext: r.word,\n\t\t\t}));\n\t\t}\n\n\t\tmainSyllables.push(syllable);\n\n\t\tif (word.romanWord) {\n\t\t\tromanSyllables.push({\n\t\t\t\ttext: word.romanWord.trim(), // AMLL 那边的实现已经总是 trim 各个逐字音译音节了\n\t\t\t\tstartTime: word.startTime,\n\t\t\t\tendTime: word.endTime,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst fullText = amllLine.words.map((w) => w.word).join(\"\");\n\n\tconst romanText =\n\t\tromanSyllables.length > 0\n\t\t\t? romanSyllables\n\t\t\t\t\t.map((s) => s.text + (s.endsWithSpace ? \" \" : \"\"))\n\t\t\t\t\t.join(\"\")\n\t\t\t: \"\";\n\n\treturn { mainSyllables, romanSyllables, fullText, romanText };\n}\n","export * from \"./generator\";\nexport * from \"./parser\";\nexport type * from \"./types\";\nexport * from \"./utils/amll-converter\";\n\nimport { TTMLGenerator } from \"./generator\";\nimport { TTMLParser } from \"./parser\";\nimport type { AmllLyricResult, TTMLResult } from \"./types\";\nimport { toAmllLyrics, toTTMLResult } from \"./utils/amll-converter\";\n\n/**\n * 将 TTML 格式的 XML 字符串解析为 {@link AmllLyricResult} 对象的便捷方法\n *\n * 若需要原始的、内容更丰富的 {@link TTMLResult} 结构，建议直接使用 {@link TTMLParser} 类\n *\n * @remarks 默认使用全局的 `DOMParser`，若为 Nodejs 环境，必须使用\n * {@link TTMLParser} 类注入 `DOMParser` 实现，例如 `@xmldom/xmldom`\n * @param ttmlText 符合 TTML 规范的 XML 字符串\n * @returns 解析后的 {@link AmllLyricResult} 对象，包含歌词行列表和元数据\n * @throws 如果没有全局的 `DOMParser`，抛出错误\n */\nexport function parseTTML(ttmlText: string): AmllLyricResult {\n\tconst result = TTMLParser.parse(ttmlText);\n\treturn toAmllLyrics(result);\n}\n\n/**\n * 将 {@link AmllLyricResult} 对象序列化为 TTML 格式的 XML 字符串的便捷方法\n *\n * 若需要自定义生成选项，建议直接使用 {@link TTMLParser} 类\n * @remarks 默认使用全局的 `document.implementation` 和 `XMLSerializer`，若为 Nodejs 环境，\n * 必须使用 {@link TTMLGenerator} 类注入 `domImplementation` 和 `xmlSerializer`，例如 `@xmldom/xmldom`\n * @param ttmlLyric 包含歌词行列表和元数据的 {@link AmllLyricResult} 对象\n * @returns 序列化后的 TTML XML 字符串\n * @throws 如果没有全局的 `DOMImplementation` 和 `XMLSerializer`，抛出错误\n */\nexport function exportTTML(ttmlLyric: AmllLyricResult): string {\n\tconst result = toTTMLResult(ttmlLyric.lines, ttmlLyric.metadata);\n\tconst generator = new TTMLGenerator();\n\treturn generator.generate(result);\n}\n"],"mappings":"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"}