@gondola-lyrics/kit 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"formats.js","names":["readText","LESS_THAN","GREATER_THAN","DOUBLE_QUOTE","AMPERSAND","ROOT_NAME","resolveOptions","readWords","readLine"],"sources":["../src/utils/annotation.ts","../src/utils/language.ts","../src/utils/time.ts","../src/utils/xml/utils.ts","../src/utils/xml/reader.ts","../src/utils/xml/writer.ts","../src/formats/lrc/common.ts","../src/formats/lrc/utils.ts","../src/formats/lrc/detect.ts","../src/formats/lrc/generator.ts","../src/formats/result.ts","../src/formats/lrc/parser.ts","../src/formats/ttml/common.ts","../src/formats/ttml/detect.ts","../src/formats/ttml/utils.ts","../src/formats/ttml/generator.ts","../src/formats/ttml/parser.ts","../src/formats/index.ts"],"sourcesContent":["import type { runtime } from '@gondola-lyrics/model'\n\nimport { LineType, getWordsText, makeLineAnnotation, makeLineAnnotationRoman, makeLineAnnotationTranslation } from '@gondola-lyrics/model/runtime'\n\nexport interface AnnotationSources {\n translations?: runtime.Line[]\n romans?: runtime.Line[]\n}\n\nexport interface AnnotationMatchOptions {\n /**\n * How far an annotation's start may sit from a line's start, in milliseconds.\n * Defaults to `0`, which requires an exact match.\n */\n tolerance?: number\n}\n\n/**\n * An annotation line carries its text in either field, depending on whether the track used word tags.\n */\nconst readText = (line: runtime.Line) => {\n return (line.content?.text ?? getWordsText(line.content?.words ?? [])).trim()\n}\n\nconst isReadable = (line: runtime.Line) => {\n return line.time?.start !== undefined && readText(line) !== ''\n}\n\n/**\n * Assigns each annotation line to a lyric line index.\n *\n * Exact matches claim their lines first, so a fuzzy match never takes a line an exact one needed.\n * The remaining annotations take the nearest unclaimed line within the tolerance, and ties keep the earlier line.\n */\nconst matchEntries = (lines: runtime.Line[], annotations: runtime.Line[], tolerance: number) => {\n const matched = new Map<number, runtime.Line>()\n if (annotations.length === 0) {\n return matched\n }\n\n const starts = lines.map((line) => line.time?.start)\n const queues = new Map<number, number[]>()\n\n for (const [index, start] of starts.entries()) {\n if (start === undefined) {\n continue\n }\n const queue = queues.get(start)\n if (queue) {\n queue.push(index)\n } else {\n queues.set(start, [index])\n }\n }\n\n const used = new Set<number>()\n const pending: runtime.Line[] = []\n\n for (const annotation of annotations) {\n const start = annotation.time?.start\n if (start === undefined) {\n continue\n }\n const index = queues.get(start)?.shift()\n if (index === undefined) {\n pending.push(annotation)\n continue\n }\n matched.set(index, annotation)\n used.add(index)\n }\n\n if (tolerance <= 0) {\n return matched\n }\n\n for (const annotation of pending) {\n const start = annotation.time?.start\n if (start === undefined) {\n continue\n }\n\n let target = -1\n let distance = Number.POSITIVE_INFINITY\n\n for (const [index, lineStart] of starts.entries()) {\n if (lineStart === undefined || used.has(index)) {\n continue\n }\n const current = Math.abs(lineStart - start)\n // Only a strictly smaller distance wins, so equally distant lines keep the earlier one.\n if (current <= tolerance && current < distance) {\n target = index\n distance = current\n }\n }\n\n if (target !== -1) {\n matched.set(target, annotation)\n used.add(target)\n }\n }\n\n return matched\n}\n\n/**\n * Attaches annotation tracks to parsed lines by start time.\n *\n * Annotations that match nothing are dropped, and an instrumental line consumes its annotation without carrying one.\n * Any annotation already on a line is kept, with the matched track appended to its layer.\n */\nexport const attachLineAnnotations = (lines: runtime.Line[], sources: AnnotationSources, options: AnnotationMatchOptions = {}): runtime.Line[] => {\n // A negative or non-finite tolerance would make every comparison meaningless, so it degrades to exact matching.\n const tolerance = Number.isFinite(options.tolerance) ? Math.max(0, options.tolerance ?? 0) : 0\n\n const translations = matchEntries(lines, (sources.translations ?? []).filter(isReadable), tolerance)\n const romans = matchEntries(lines, (sources.romans ?? []).filter(isReadable), tolerance)\n if (translations.size === 0 && romans.size === 0) {\n return lines\n }\n\n return lines.map((line, index) => {\n const translation = translations.get(index)\n const roman = romans.get(index)\n\n // An instrumental line has no singing to annotate, and the model rejects annotation on one.\n if (line.type === LineType.INSTRUMENTAL || (translation === undefined && roman === undefined)) {\n return line\n }\n\n return {\n ...line,\n annotation: makeLineAnnotation({\n romans: [\n ...(line.annotation?.romans ?? []),\n ...(roman === undefined ? [] : [makeLineAnnotationRoman({ text: readText(roman), language: roman.languages[0] })]),\n ],\n translations: [\n ...(line.annotation?.translations ?? []),\n ...(translation === undefined ? [] : [makeLineAnnotationTranslation({ text: readText(translation), language: translation.languages[0] })]),\n ],\n }),\n }\n })\n}\n","/**\n * Returns a language tag in the canonical form the model stores, which is lower case.\n *\n * This mirrors the model's own helper, which it does not export.\n * Comparing tags stays with the consumer, since BCP 47 matches by subtag prefix rather than by string equality.\n */\nexport const lowerTag = (tag: string | undefined): string | undefined => {\n return tag ? tag.toLowerCase() : undefined\n}\n","// A colon always separates units, so `1:14:514` means hours, minutes, and seconds, not minutes, seconds, and milliseconds.\nconst CLOCK_PATTERN = /^(?:(?:(\\d+):)?(\\d+):)?(\\d+)(?:\\.(\\d+))?$/\n\n// `ms` has to be tried before `m`, so the longer unit wins.\nconst OFFSET_PATTERN = /^(\\d+(?:\\.\\d+)?)(ms|h|m|s)$/iu\n\n/**\n * Reads a clock value, where the fraction is padded or truncated to millisecond precision.\n *\n * `14.514` is fourteen seconds, not fourteen minutes: a colon, not a dot, introduces the larger units.\n */\nconst parseClock = (value: string): number | undefined => {\n // A dot alone is enough to make a number a clock reading, which is what keeps `500` out.\n if (!value.includes(':') && !value.includes('.')) {\n return undefined\n }\n\n const match = CLOCK_PATTERN.exec(value)\n if (!match) {\n return undefined\n }\n\n const hour = Number(match[1] ?? 0)\n const minute = Number(match[2] ?? 0)\n const second = Number(match[3] ?? 0)\n const millisecond = Number((match[4] ?? '').padEnd(3, '0').slice(0, 3))\n\n return ((hour * 60 + minute) * 60 + second) * 1000 + millisecond\n}\n\n/**\n * Reads an offset such as `1.5s`, `2m`, `500ms`, or `1h`.\n */\nconst parseOffset = (value: string): number | undefined => {\n const match = OFFSET_PATTERN.exec(value)\n if (!match) {\n return undefined\n }\n\n const amount = Number(match[1])\n if (!Number.isFinite(amount)) {\n return undefined\n }\n\n switch ((match[2] ?? '').toLowerCase()) {\n case 'h':\n return Math.round(amount * 3600000)\n case 'm':\n return Math.round(amount * 60000)\n case 'ms':\n return Math.round(amount)\n default:\n return Math.round(amount * 1000)\n }\n}\n\n/**\n * Reports whether a value reads as a time.\n */\nexport const isTime = (body: string) => {\n return parseTime(body) !== undefined\n}\n\n/**\n * Reads a time value into milliseconds.\n *\n * A clock reading accepts `ss.fraction`, `mm:ss.fraction`, and `hh:mm:ss.fraction`.\n * An offset accepts a number with an `h`, `m`, `s`, or `ms` suffix.\n * A bare number returns `undefined`, and so does anything else.\n */\nexport const parseTime = (body: string): number | undefined => {\n const trimmed = body.trim()\n if (trimmed === '') {\n return undefined\n }\n\n return parseOffset(trimmed) ?? parseClock(trimmed)\n}\n\n/**\n * Tokens `h`, `m`, `s`, and `S` select hours, minutes, seconds, and fractional seconds.\n * Repeated unit tokens set minimum width; `S` tokens select up to three fractional digits.\n *\n * Omitting hours carries them into minutes; negative or non-finite input writes zero fields.\n */\nexport const formatTime = (time: number, format = 'mm:ss.SSS') => {\n if (!Number.isFinite(time) || time < 0) {\n return format.replace(/h+|m+|s+|S+/g, (run) => '0'.repeat(run.length))\n }\n\n const total = Math.floor(time)\n const totalSeconds = Math.floor(total / 1000)\n const totalMinutes = Math.floor(totalSeconds / 60)\n const millisecond = String(total % 1000).padStart(3, '0')\n\n const fields: Record<string, string> = {\n h: String(Math.floor(totalMinutes / 60)),\n m: String(format.includes('h') ? totalMinutes % 60 : totalMinutes),\n s: String(totalSeconds % 60),\n S: millisecond,\n }\n\n return format.replace(/h+|m+|s+|S+/g, (run) => {\n const field = fields[run[0] as string] as string\n\n if (run[0] === 'S') {\n return field.slice(0, run.length)\n }\n\n return field.padStart(run.length, '0')\n })\n}\n","export const XmlNodeType = {\n element: 1,\n text: 2,\n cdata: 3,\n} as const\n\nexport interface XmlAttribute {\n /** Name exactly as written, namespace prefix included, such as `ttm:agent`. */\n qualifiedName: string\n /** Decoded value, with entity references already resolved. */\n value: string\n /** Namespace prefix such as `ttm`, empty when the name carries none. */\n namespacePrefix: string\n /** Name without its prefix, such as `agent`, which is what format lookups match. */\n localName: string\n}\n\nexport interface XmlElement {\n /** Discriminant that tells this node apart from text and CDATA. */\n nodeType: typeof XmlNodeType.element\n /** Name exactly as written, namespace prefix included, such as `ttm:name`. */\n qualifiedName: string\n /** Namespace prefix such as `ttm`, empty when the name carries none. */\n namespacePrefix: string\n /** Name without its prefix, such as `name`, which is what format lookups match. */\n localName: string\n /** Attributes in document order, which keeps a source's own ordering readable. */\n attributes: XmlAttribute[]\n /** Child nodes in document order, text and CDATA included. */\n children: XmlNode[]\n}\n\nexport interface XmlText {\n /** Discriminant that tells this node apart from elements and CDATA. */\n nodeType: typeof XmlNodeType.text\n /** Decoded text, with entity references already resolved. */\n text: string\n}\n\nexport interface XmlCdata {\n /** Discriminant that tells this node apart from elements and text. */\n nodeType: typeof XmlNodeType.cdata\n /** Raw text between the CDATA markers, which is never decoded. */\n text: string\n}\n\nexport type XmlNode = XmlElement | XmlText | XmlCdata\n\n/**\n * Only prefixed names need their split cached, since an unprefixed one keeps its name as the local part.\n * The cache is bounded, which keeps an adversarial document from growing it without limit.\n */\nconst prefixedNames = new Map<string, { namespacePrefix: string; localName: string }>()\n\n/**\n * Splits a qualified name into its namespace prefix and local name.\n */\nconst splitXmlName = (name: string) => {\n const cached = prefixedNames.get(name)\n if (cached !== undefined) {\n return cached\n }\n\n const colon = name.indexOf(':')\n const split = colon === -1 ? { namespacePrefix: '', localName: name } : { namespacePrefix: name.slice(0, colon), localName: name.slice(colon + 1) }\n if (split.namespacePrefix !== '' && prefixedNames.size < 1024) {\n prefixedNames.set(name, split)\n }\n\n return split\n}\n\n/**\n * Writes the prefix and local part onto a node that already carries the full name.\n */\nexport const applyXmlNameParts = (name: string, target: { namespacePrefix: string; localName: string }) => {\n if (name.indexOf(':') === -1) {\n target.namespacePrefix = ''\n target.localName = name\n return\n }\n\n const split = splitXmlName(name)\n target.namespacePrefix = split.namespacePrefix\n target.localName = split.localName\n}\n\n/**\n * Creates an attribute from its full name and value.\n */\nexport const createXmlAttribute = (qualifiedName: string, value: string): XmlAttribute => {\n const attribute: XmlAttribute = { qualifiedName, value, namespacePrefix: '', localName: qualifiedName }\n applyXmlNameParts(qualifiedName, attribute)\n\n return attribute\n}\n\n/**\n * Creates an element from its full name, with attributes and children in the order given.\n */\nexport const createXmlElement = (\n qualifiedName: string,\n attributes: readonly (readonly [string, string])[] = [],\n children: readonly XmlNode[] = [],\n): XmlElement => {\n const element: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName,\n namespacePrefix: '',\n localName: qualifiedName,\n attributes: attributes.map(([name, value]) => {\n return createXmlAttribute(name, value)\n }),\n children: [...children],\n }\n applyXmlNameParts(qualifiedName, element)\n\n return element\n}\n\n/**\n * Creates a text node, whose value the writer escapes.\n */\nexport const createXmlText = (text: string): XmlText => {\n return { nodeType: XmlNodeType.text, text }\n}\n\n/**\n * Creates a CDATA node, whose value the writer emits verbatim.\n */\nexport const createXmlCdata = (text: string): XmlCdata => {\n return { nodeType: XmlNodeType.cdata, text }\n}\n\n/**\n * Returns the value of one attribute, matched by its local name so the prefix never has to be known.\n */\nexport const getXmlAttribute = (element: XmlElement, localName: string): string | undefined => {\n const attributes = element.attributes\n for (let index = 0; index < attributes.length; index += 1) {\n const attribute = attributes[index]\n if (attribute !== undefined && attribute.localName === localName) {\n return attribute.value\n }\n }\n\n return undefined\n}\n\n/**\n * Returns the value of one attribute, matched by its full name including the prefix.\n */\nexport const getXmlQualifiedAttribute = (element: XmlElement, qualifiedName: string): string | undefined => {\n const attributes = element.attributes\n for (let index = 0; index < attributes.length; index += 1) {\n const attribute = attributes[index]\n if (attribute !== undefined && attribute.qualifiedName === qualifiedName) {\n return attribute.value\n }\n }\n\n return undefined\n}\n\n/**\n * Returns the direct element children carrying one local name.\n */\nexport const getXmlChildElements = (element: XmlElement, localName: string): XmlElement[] => {\n const result: XmlElement[] = []\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child !== undefined && child.nodeType === XmlNodeType.element && child.localName === localName) {\n result.push(child)\n }\n }\n\n return result\n}\n\n/**\n * Reports whether the element has a direct child with one local name.\n */\nexport const hasXmlChildElement = (element: XmlElement, localName: string): boolean => {\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child !== undefined && child.nodeType === XmlNodeType.element && child.localName === localName) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Returns the first element carrying one local name, the element itself included, in document order.\n */\nexport const findXmlElement = (element: XmlElement, localName: string): XmlElement | undefined => {\n const stack: XmlNode[] = [element]\n\n while (stack.length > 0) {\n const node = stack.pop()\n if (node === undefined || node.nodeType !== XmlNodeType.element) {\n continue\n }\n if (node.localName === localName) {\n return node\n }\n // Pushing in reverse makes the stack pop children in document order.\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child !== undefined) {\n stack.push(child)\n }\n }\n }\n\n return undefined\n}\n\n/**\n * Returns every element carrying one local name, the element itself included, in document order.\n */\nexport const findXmlElements = (element: XmlElement, localName: string): XmlElement[] => {\n const result: XmlElement[] = []\n const stack: XmlNode[] = [element]\n\n while (stack.length > 0) {\n const node = stack.pop()\n if (node === undefined || node.nodeType !== XmlNodeType.element) {\n continue\n }\n if (node.localName === localName) {\n result.push(node)\n }\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child !== undefined) {\n stack.push(child)\n }\n }\n }\n\n return result\n}\n\n/**\n * Groups every element carrying one of the given local names, in document order.\n */\nexport const groupXmlElements = (element: XmlElement, localNames: readonly string[]): Map<string, XmlElement[]> => {\n const wanted = new Set(localNames)\n const result = new Map<string, XmlElement[]>()\n const stack: XmlNode[] = [element]\n\n while (stack.length > 0) {\n const node = stack.pop()\n if (node === undefined || node.nodeType !== XmlNodeType.element) {\n continue\n }\n\n if (wanted.has(node.localName)) {\n const group = result.get(node.localName)\n if (group === undefined) {\n result.set(node.localName, [node])\n } else {\n group.push(node)\n }\n }\n\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child !== undefined) {\n stack.push(child)\n }\n }\n }\n\n return result\n}\n\n/**\n * Joins the text and CDATA content of a node and its descendants, in document order.\n */\nexport const getXmlTextContent = (node: XmlNode): string => {\n if (node.nodeType !== XmlNodeType.element) {\n return node.text\n }\n\n if (node.children.length === 0) {\n return ''\n }\n const child = node.children[0]\n if (node.children.length === 1 && child !== undefined && child.nodeType !== XmlNodeType.element) {\n return child.text\n }\n\n const parts: string[] = []\n const stack: XmlNode[] = [node]\n\n while (stack.length > 0) {\n const current = stack.pop()\n if (current === undefined) {\n continue\n }\n if (current.nodeType === XmlNodeType.element) {\n for (let index = current.children.length - 1; index >= 0; index -= 1) {\n const child = current.children[index]\n if (child !== undefined) {\n stack.push(child)\n }\n }\n continue\n }\n parts.push(current.text)\n }\n\n return parts.join('')\n}\n","import type { XmlAttribute, XmlElement } from './utils'\n\nimport { applyXmlNameParts, createXmlAttribute, XmlNodeType } from './utils'\n\nconst LESS_THAN = 0x3c\nconst GREATER_THAN = 0x3e\nconst SLASH = 0x2f\nconst EQUALS = 0x3d\nconst DOUBLE_QUOTE = 0x22\nconst SINGLE_QUOTE = 0x27\nconst EXCLAMATION = 0x21\nconst QUESTION = 0x3f\nconst AMPERSAND = 0x26\nconst HASH = 0x23\nconst HYPHEN = 0x2d\nconst LOWER_X = 0x78\nconst UPPER_X = 0x58\nconst BYTE_ORDER_MARK = 0xfeff\n\nconst ROOT_NAME = '#document'\n\nconst DECIMAL_DIGITS = /^\\d+$/\nconst HEX_DIGITS = /^[0-9a-fA-F]+$/\n\n/**\n * Resolves one entity reference body, leaving anything unrecognized as written.\n */\nconst decodeReference = (body: string): string => {\n switch (body) {\n case 'lt':\n return '<'\n case 'gt':\n return '>'\n case 'amp':\n return '&'\n case 'quot':\n return '\"'\n case 'apos':\n return \"'\"\n }\n\n if (body.charCodeAt(0) !== HASH) {\n return `&${body};`\n }\n\n const hexadecimal = body.charCodeAt(1) === LOWER_X || body.charCodeAt(1) === UPPER_X\n const digits = hexadecimal ? body.slice(2) : body.slice(1)\n if (!(hexadecimal ? HEX_DIGITS : DECIMAL_DIGITS).test(digits)) {\n return `&${body};`\n }\n\n const code = Number.parseInt(digits, hexadecimal ? 16 : 10)\n // Anything outside the Unicode range cannot be written back, so the reference stays literal.\n if (!Number.isFinite(code) || code > 0x10ffff) {\n return `&${body};`\n }\n\n return String.fromCodePoint(code)\n}\n\n/**\n * Replaces entity references in one run of text, leaving bare ampersands alone.\n */\nconst decodeText = (text: string): string => {\n const parts: string[] = []\n const length = text.length\n let start = 0\n let cursor = 0\n\n while (cursor < length) {\n if (text.charCodeAt(cursor) !== AMPERSAND) {\n cursor += 1\n continue\n }\n\n const end = text.indexOf(';', cursor + 1)\n if (end === -1) {\n cursor += 1\n continue\n }\n\n parts.push(text.slice(start, cursor), decodeReference(text.slice(cursor + 1, end)))\n cursor = end + 1\n start = cursor\n }\n\n if (parts.length === 0) {\n return text\n }\n\n parts.push(text.slice(start))\n return parts.join('')\n}\n\n/**\n * Reads a document into a tree, or returns `null` when it is not well formed.\n */\nexport const parseXml = (source: string): XmlElement | null => {\n const length = source.length\n let position = length > 0 && source.charCodeAt(0) === BYTE_ORDER_MARK ? 1 : 0\n let valid = true\n const stack: XmlElement[] = []\n\n const root: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName: ROOT_NAME,\n namespacePrefix: '',\n localName: ROOT_NAME,\n attributes: [],\n children: [],\n }\n stack.push(root)\n\n /**\n * Appends a text node to the element being read.\n */\n const readTextNode = (end: number) => {\n const start = position\n position = end\n if (start === end) {\n return\n }\n\n const parent = stack[stack.length - 1]\n if (parent === undefined) {\n valid = false\n return\n }\n\n const raw = source.slice(start, end)\n parent.children.push({ nodeType: XmlNodeType.text, text: raw.indexOf('&') === -1 ? raw : decodeText(raw) })\n }\n\n /**\n * Reads one quoted value, starting at `position`, and leaves `position` after the closing quote.\n */\n const readQuotedValue = (): string => {\n const quote = source.charCodeAt(position)\n if (quote !== DOUBLE_QUOTE && quote !== SINGLE_QUOTE) {\n // XML requires a quoted value.\n valid = false\n return ''\n }\n\n position += 1\n const end = source.indexOf(quote === DOUBLE_QUOTE ? '\"' : \"'\", position)\n if (end === -1) {\n valid = false\n return ''\n }\n\n const raw = source.slice(position, end)\n position = end + 1\n return raw.indexOf('&') === -1 ? raw : decodeText(raw)\n }\n\n /**\n * Reads a start tag with its attributes, and opens the element unless it closes itself.\n */\n const readStartTag = () => {\n let cursor = position + 1\n const nameStart = cursor\n\n while (cursor < length) {\n const code = source.charCodeAt(cursor)\n if (code <= 32 || code === GREATER_THAN || code === SLASH || code === EQUALS) {\n break\n }\n cursor += 1\n }\n\n if (cursor === nameStart) {\n valid = false\n return\n }\n\n const qualifiedName = source.slice(nameStart, cursor)\n const attributes: XmlAttribute[] = []\n const element: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName,\n namespacePrefix: '',\n localName: qualifiedName,\n attributes,\n children: [],\n }\n applyXmlNameParts(qualifiedName, element)\n\n let closed = false\n let selfClosing = false\n\n while (cursor < length) {\n let code = source.charCodeAt(cursor)\n while (code <= 32) {\n cursor += 1\n if (cursor >= length) {\n break\n }\n code = source.charCodeAt(cursor)\n }\n if (cursor >= length) {\n break\n }\n\n if (code === GREATER_THAN) {\n cursor += 1\n closed = true\n break\n }\n if (code === SLASH) {\n cursor += 1\n if (cursor < length && source.charCodeAt(cursor) === GREATER_THAN) {\n cursor += 1\n closed = true\n selfClosing = true\n break\n }\n valid = false\n return\n }\n\n const attributeStart = cursor\n do {\n cursor += 1\n if (cursor >= length) {\n break\n }\n code = source.charCodeAt(cursor)\n } while (code > 32 && code !== GREATER_THAN && code !== SLASH && code !== EQUALS)\n if (cursor === attributeStart) {\n valid = false\n return\n }\n\n const attributeName = source.slice(attributeStart, cursor)\n\n while (cursor < length && source.charCodeAt(cursor) <= 32) {\n cursor += 1\n }\n if (cursor >= length || source.charCodeAt(cursor) !== EQUALS) {\n // XML requires every attribute to carry a quoted value.\n valid = false\n return\n }\n cursor += 1\n while (cursor < length && source.charCodeAt(cursor) <= 32) {\n cursor += 1\n }\n\n position = cursor\n const value = readQuotedValue()\n if (!valid) {\n return\n }\n cursor = position\n\n for (let index = 0; index < attributes.length; index += 1) {\n if (attributes[index]?.qualifiedName === attributeName) {\n // A repeated attribute name is not well formed.\n valid = false\n return\n }\n }\n\n attributes.push(createXmlAttribute(attributeName, value))\n }\n\n if (!closed) {\n valid = false\n return\n }\n\n position = cursor\n\n const parent = stack[stack.length - 1]\n if (parent === undefined) {\n valid = false\n return\n }\n parent.children.push(element)\n\n // A self-closing tag is complete as written.\n if (!selfClosing) {\n stack.push(element)\n }\n }\n\n /**\n * Closes the innermost element, which has to be the one the tag names.\n */\n const readEndTag = () => {\n let cursor = position + 2\n const nameStart = cursor\n\n while (cursor < length) {\n const code = source.charCodeAt(cursor)\n if (code <= 32 || code === GREATER_THAN) {\n break\n }\n cursor += 1\n }\n\n const name = source.slice(nameStart, cursor)\n const end = source.indexOf('>', cursor)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 1\n\n // The root never closes, so a close tag here has no open element to match.\n if (stack.length <= 1) {\n valid = false\n return\n }\n\n const top = stack[stack.length - 1]\n if (top === undefined || top.qualifiedName !== name) {\n valid = false\n return\n }\n\n stack.pop()\n }\n\n /**\n * Skips a comment, CDATA section, or any other declaration such as a DOCTYPE.\n */\n const readMarkupDeclaration = () => {\n if (source.charCodeAt(position + 2) === HYPHEN && source.charCodeAt(position + 3) === HYPHEN) {\n const end = source.indexOf('-->', position + 4)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 3\n return\n }\n\n if (source.startsWith('[CDATA[', position + 2)) {\n const start = position + 9\n const end = source.indexOf(']]>', start)\n if (end === -1) {\n valid = false\n return\n }\n\n const parent = stack[stack.length - 1]\n if (parent === undefined) {\n valid = false\n return\n }\n\n parent.children.push({ nodeType: XmlNodeType.cdata, text: source.slice(start, end) })\n position = end + 3\n return\n }\n\n // Any other declaration, a DOCTYPE with an internal subset included, runs to its closing bracket.\n let cursor = position + 2\n let depth = 1\n while (cursor < length && depth > 0) {\n const code = source.charCodeAt(cursor)\n if (code === LESS_THAN) {\n depth += 1\n } else if (code === GREATER_THAN) {\n depth -= 1\n }\n cursor += 1\n }\n\n if (depth > 0) {\n valid = false\n return\n }\n\n position = cursor\n }\n\n /**\n * Skips a processing instruction, which carries nothing the kit reads.\n */\n const readProcessingInstruction = () => {\n const end = source.indexOf('?>', position + 2)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 2\n }\n\n /**\n * Reads content until the end of input or the end tag of the innermost element.\n */\n const readNodes = () => {\n while (position < length) {\n const open = source.indexOf('<', position)\n if (open === -1) {\n readTextNode(length)\n return\n }\n if (open > position) {\n readTextNode(open)\n if (!valid) {\n return\n }\n }\n\n position = open\n const next = source.charCodeAt(open + 1)\n\n if (next === SLASH) {\n readEndTag()\n } else if (next === EXCLAMATION) {\n readMarkupDeclaration()\n } else if (next === QUESTION) {\n readProcessingInstruction()\n } else {\n readStartTag()\n }\n\n if (!valid) {\n return\n }\n }\n }\n\n readNodes()\n\n // An unclosed element leaves more than the root on the stack.\n if (!valid || stack.length !== 1) {\n return null\n }\n\n for (let index = 0; index < root.children.length; index += 1) {\n if (root.children[index]?.nodeType === XmlNodeType.element) {\n return root\n }\n }\n\n return null\n}\n","import type { XmlElement, XmlNode } from './utils'\n\nimport { XmlNodeType } from './utils'\n\nconst AMPERSAND = 0x26\nconst LESS_THAN = 0x3c\nconst GREATER_THAN = 0x3e\nconst DOUBLE_QUOTE = 0x22\nconst TAB = 0x09\nconst LINE_FEED = 0x0a\nconst CARRIAGE_RETURN = 0x0d\n\nconst ROOT_NAME = '#document'\n\nconst REPLACEMENT_CHARACTER = '�'\n\nconst XML_DECLARATION = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'\n\nconst DEFAULT_INDENT = ' '\n\nexport interface XmlWriteOptions {\n /** Emit the XML declaration; defaults to `true`. */\n declaration?: boolean\n /**\n * Indent elements by nesting depth; defaults to `false`.\n *\n * The inserted whitespace becomes text when the output is parsed again.\n * Turn this on only for output no one reads back as lyrics.\n */\n indent?: boolean\n /** One indentation level; defaults to two spaces. */\n indentText?: string\n}\n\n/**\n * Reports whether a code point may appear in an XML 1.0 document.\n */\nconst isAllowedCodePoint = (code: number): boolean => {\n return (\n code === TAB ||\n code === LINE_FEED ||\n code === CARRIAGE_RETURN ||\n (code >= 0x20 && code <= 0xd7ff) ||\n (code >= 0xe000 && code <= 0xfffd) ||\n (code >= 0x10000 && code <= 0x10ffff)\n )\n}\n\n/**\n * Escapes text content, replacing characters XML cannot carry so corruption stays visible.\n */\nconst escapeXmlText = (text: string, chunks: string[]): void => {\n const length = text.length\n let start = 0\n\n for (let index = 0; index < length; index += 1) {\n const code = text.charCodeAt(index)\n let escaped = ''\n\n if (code === AMPERSAND) {\n escaped = '&amp;'\n } else if (code === LESS_THAN) {\n escaped = '&lt;'\n } else if (code === GREATER_THAN) {\n escaped = '&gt;'\n } else if (code === CARRIAGE_RETURN) {\n // A parser folds a bare carriage return into a line feed, so the reference is the only way to keep it.\n escaped = '&#13;'\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const low = index + 1 < length ? text.charCodeAt(index + 1) : 0\n if (low < 0xdc00 || low > 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else {\n // A paired surrogate is one code point, which the loop advances over next.\n index += 1\n continue\n }\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else if (!isAllowedCodePoint(code)) {\n escaped = REPLACEMENT_CHARACTER\n }\n\n if (escaped === '') {\n continue\n }\n\n if (start < index) {\n chunks.push(text.slice(start, index))\n }\n chunks.push(escaped)\n start = index + 1\n }\n\n if (start === 0) {\n chunks.push(text)\n return\n }\n if (start < length) {\n chunks.push(text.slice(start))\n }\n}\n\n/**\n * Escapes an attribute value, where whitespace also has to survive normalization.\n */\nconst escapeXmlAttribute = (value: string, chunks: string[]): void => {\n const length = value.length\n let start = 0\n\n for (let index = 0; index < length; index += 1) {\n const code = value.charCodeAt(index)\n let escaped = ''\n\n if (code === AMPERSAND) {\n escaped = '&amp;'\n } else if (code === LESS_THAN) {\n escaped = '&lt;'\n } else if (code === GREATER_THAN) {\n escaped = '&gt;'\n } else if (code === DOUBLE_QUOTE) {\n escaped = '&quot;'\n } else if (code === TAB) {\n escaped = '&#9;'\n } else if (code === LINE_FEED) {\n escaped = '&#10;'\n } else if (code === CARRIAGE_RETURN) {\n escaped = '&#13;'\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const low = index + 1 < length ? value.charCodeAt(index + 1) : 0\n if (low < 0xdc00 || low > 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else {\n index += 1\n continue\n }\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else if (!isAllowedCodePoint(code)) {\n escaped = REPLACEMENT_CHARACTER\n }\n\n if (escaped === '') {\n continue\n }\n\n if (start < index) {\n chunks.push(value.slice(start, index))\n }\n chunks.push(escaped)\n start = index + 1\n }\n\n if (start === 0) {\n chunks.push(value)\n return\n }\n if (start < length) {\n chunks.push(value.slice(start))\n }\n}\n\n/**\n * Reports whether every child is an element, which is the only case indentation can add whitespace to.\n *\n * An element holding any character data is mixed content, where the inserted whitespace would join the text.\n */\nconst hasOnlyElements = (element: XmlElement): boolean => {\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child !== undefined && child.nodeType !== XmlNodeType.element) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Serializes one node, appending its pieces to `chunks`.\n */\nconst writeXmlNode = (node: XmlNode, chunks: string[], depth: number, indent: string | undefined) => {\n if (node.nodeType === XmlNodeType.text) {\n escapeXmlText(node.text, chunks)\n return\n }\n\n if (node.nodeType === XmlNodeType.cdata) {\n // A `]]>` inside the data would close the section early, so it is split across two sections.\n chunks.push('<![CDATA[', node.text.replaceAll(']]>', ']]]]><![CDATA[>'), ']]>')\n return\n }\n\n if (indent !== undefined && depth > 0) {\n chunks.push('\\n', indent.repeat(depth))\n }\n\n chunks.push('<', node.qualifiedName)\n for (let index = 0; index < node.attributes.length; index += 1) {\n const attribute = node.attributes[index]\n if (attribute === undefined) {\n continue\n }\n chunks.push(' ', attribute.qualifiedName, '=\"')\n escapeXmlAttribute(attribute.value, chunks)\n chunks.push('\"')\n }\n\n const children = node.children\n if (children.length === 0) {\n chunks.push('/>')\n return\n }\n\n chunks.push('>')\n // Mixed content keeps its children flush, since any whitespace here would join the text.\n const childIndent = indent !== undefined && hasOnlyElements(node) ? indent : undefined\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child !== undefined) {\n writeXmlNode(child, chunks, depth + 1, childIndent)\n }\n }\n\n if (childIndent !== undefined) {\n chunks.push('\\n', childIndent.repeat(depth))\n }\n chunks.push('</', node.qualifiedName, '>')\n}\n\n/**\n * Writes a tree back to text.\n *\n * A `#document` root, as `parseXml` returns, writes its children; any other root writes itself.\n */\nexport const serializeXml = (root: XmlElement, options: XmlWriteOptions = {}): string => {\n const chunks: string[] = []\n\n if (options.declaration ?? true) {\n chunks.push(XML_DECLARATION)\n }\n\n const indent = options.indent === true ? (options.indentText ?? DEFAULT_INDENT) : undefined\n if (indent !== undefined) {\n chunks.push('\\n')\n }\n\n if (root.qualifiedName === ROOT_NAME) {\n for (let index = 0; index < root.children.length; index += 1) {\n const child = root.children[index]\n if (child !== undefined) {\n writeXmlNode(child, chunks, 0, indent)\n }\n }\n } else {\n writeXmlNode(root, chunks, 0, indent)\n }\n\n return chunks.join('')\n}\n","export const FORMAT = 'lrc'\n\nexport interface LrcContent {\n original: string\n translations?: string\n romans?: string\n}\n\nexport const readLrcContent = (input: unknown): LrcContent | null => {\n if (typeof input === 'string') {\n return { original: input }\n }\n if (typeof input !== 'object' || input === null) {\n return null\n }\n\n const source = input as Partial<LrcContent>\n if (typeof source.original !== 'string') {\n return null\n }\n\n return {\n original: source.original,\n translations: typeof source.translations === 'string' ? source.translations : undefined,\n romans: typeof source.romans === 'string' ? source.romans : undefined,\n }\n}\n","import { isTime, parseTime } from '@root/utils'\n\nconst WORD_OFFSET_PATTERN = /^(\\d+)(?:,(\\d+))?$/\n\nconst WORD_CLOCK_DURATION_PATTERN = /^([^,]+),(\\d+)$/\n\nconst WORD_TAG_PATTERN = /<([^>]*)>/g\n\nexport const TAG_PATTERN = /\\[([^\\]]*)\\]/g\n\nexport const META_PATTERN = /^([A-Za-z0-9_-]+)\\s*:\\s*([\\s\\S]*)$/\n\n/**\n * Integer tags use `offset[,duration]` in milliseconds relative to the line start.\n * Clock tags are absolute and may append a duration in milliseconds, as in `<00:01.50,500>`.\n * A missing or zero duration leaves the word end unspecified.\n */\nexport const parseWordTime = (body: string, lineStart: number) => {\n if (isTime(body)) {\n const start = parseTime(body)\n\n return start === undefined ? undefined : { start, end: undefined }\n }\n\n const match = WORD_OFFSET_PATTERN.exec(body.trim())\n if (match) {\n const start = lineStart + Number(match[1])\n const duration = Number(match[2] ?? 0)\n\n return { start, end: duration > 0 ? start + duration : undefined }\n }\n\n const clock = WORD_CLOCK_DURATION_PATTERN.exec(body.trim())\n if (clock && isTime(clock[1] ?? '')) {\n const start = parseTime(clock[1] ?? '')\n const duration = Number(clock[2] ?? 0)\n\n return start === undefined ? undefined : { start, end: duration > 0 ? start + duration : undefined }\n }\n\n return undefined\n}\n\n/**\n * Tags precede their text, as in `<0,500>hel`.\n */\nexport interface WordPiece {\n text: string\n tag?: string\n}\n\n/**\n * Untagged leading text is preserved; tags without following text produce no piece.\n * A trailing tag still yields an empty piece so it can close the preceding word.\n */\nexport const splitWordTags = (content: string) => {\n const pieces: WordPiece[] = []\n let tag: string | undefined\n let cursor = 0\n\n for (const match of content.matchAll(WORD_TAG_PATTERN)) {\n const at = match.index\n const before = content.slice(cursor, at)\n\n if (before) {\n pieces.push({ text: before, tag })\n }\n\n tag = match[1] ?? ''\n cursor = at + match[0].length\n }\n\n const tail = content.slice(cursor)\n if (tail) {\n pieces.push({ text: tail, tag })\n } else if (tag !== undefined) {\n pieces.push({ text: '', tag })\n }\n\n return pieces\n}\n","import { isTime } from '@root/utils'\n\nimport { readLrcContent } from './common'\nimport { TAG_PATTERN } from './utils'\n\n/**\n * A single readable time tag is enough for recognition; metadata alone is not.\n * This is a format probe, not a validity check, so an input of another shape is simply not LRC.\n */\nexport const detectLrc = (input: unknown) => {\n const content = readLrcContent(input)\n if (!content) {\n return false\n }\n\n const lines = content.original.replace(/\\r\\n?/g, '\\n').split('\\n')\n return lines.some((line) => [...line.matchAll(TAG_PATTERN)].some((match) => isTime(match[1] ?? '')))\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { LrcContent } from './common'\n\nimport { LineType, WordType } from '@gondola-lyrics/model/runtime'\n\nimport { formatTime } from '@root/utils'\n\nexport type LrcGenerateResult = LrcContent\n\nexport interface LrcGenerateOptions {\n /**\n * Word-level timestamp style; defaults to `angle`.\n *\n * `angle` is the enhanced LRC form and round-trips through this parser.\n *\n * `bracket` matches line timestamps, so this parser reads it as new lines rather than words.\n */\n wordTiming?: 'angle' | 'bracket' | 'none'\n /** Clock format for every timestamp; defaults to `mm:ss.SSS`. */\n timeFormat?: string\n /** Emit the metadata header; defaults to `true`. */\n includeMeta?: boolean\n /** Append the word duration to its tag, as in `<00:01.00,500>`. */\n includeWordEnd?: boolean\n /** Emit instrumental lines as a timestamp with no text; defaults to `true`. */\n includeInstrumental?: boolean\n}\n\ntype LrcGenerateOptionsRequired = Required<LrcGenerateOptions>\n\nconst resolveOptions = (options: LrcGenerateOptions = {}): LrcGenerateOptionsRequired => {\n return {\n wordTiming: options.wordTiming ?? 'angle',\n timeFormat: options.timeFormat ?? 'mm:ss.SSS',\n includeMeta: options.includeMeta ?? true,\n includeWordEnd: options.includeWordEnd ?? false,\n includeInstrumental: options.includeInstrumental ?? true,\n }\n}\n\nconst renderTimeTag = (time: number, options: LrcGenerateOptionsRequired) => {\n return `[${formatTime(time, options.timeFormat)}]`\n}\n\nconst renderWordTag = (start: number, end: number | undefined, options: LrcGenerateOptionsRequired) => {\n if (options.wordTiming === 'none') {\n return ''\n }\n\n const open = options.wordTiming === 'bracket' ? '[' : '<'\n const close = options.wordTiming === 'bracket' ? ']' : '>'\n // A duration of zero still states where the word stops, so it is written when the end is known.\n const duration = options.includeWordEnd && end !== undefined ? `,${Math.max(0, end - start)}` : ''\n\n return `${open}${formatTime(start, options.timeFormat)}${duration}${close}`\n}\n\n/**\n * Plain text joins words as written, including the separators stored as space words.\n */\nconst renderPlainText = (line: runtime.Line) => {\n const content = line.content\n if (!content) {\n return ''\n }\n if (content.text !== undefined) {\n return content.text\n }\n\n return content.words.map((word) => word.text).join('')\n}\n\n/**\n * Word-level lines interleave tags with their text; untimed words stay untagged.\n */\nconst renderSyllableText = (line: runtime.Line, options: LrcGenerateOptionsRequired) => {\n const content = line.content\n if (!content?.words.length) {\n return renderPlainText(line)\n }\n\n return content.words\n .map((word) => {\n if (word.type === WordType.SPACE) {\n return word.text\n }\n const start = word.time?.start\n if (start === undefined) {\n return word.text\n }\n return `${renderWordTag(start, word.time?.end, options)}${word.text}`\n })\n .join('')\n}\n\nconst renderMetaRows = (meta: runtime.Meta, options: LrcGenerateOptionsRequired) => {\n const rows: string[] = []\n\n for (const title of meta.titles) {\n rows.push(`[ti:${title.text}]`)\n }\n for (const artist of meta.artists) {\n rows.push(`[ar:${artist.text}]`)\n }\n for (const album of meta.albums) {\n rows.push(`[al:${album.text}]`)\n }\n for (const author of meta.authors) {\n rows.push(`[by:${author.text}]`)\n }\n if (meta.offset) {\n rows.push(`[offset:${meta.offset}]`)\n }\n if (meta.duration !== undefined) {\n rows.push(`[length:${formatTime(meta.duration, options.timeFormat)}]`)\n }\n for (const isrc of meta.isrcs) {\n rows.push(`[isrc:${isrc}]`)\n }\n for (const unknown of meta.unknowns) {\n rows.push(`[${unknown.key}:${unknown.value}]`)\n }\n\n return rows\n}\n\n/**\n * Returns `undefined` for a line the options leave out, so callers can drop it rather than emit a blank row.\n */\nconst renderLineRow = (line: runtime.Line, options: LrcGenerateOptionsRequired, wordLevel: boolean) => {\n if (line.type === LineType.INSTRUMENTAL && !options.includeInstrumental) {\n return undefined\n }\n\n // An untimed lyric still needs a stamp, so it starts at zero like any other line.\n const time = renderTimeTag(line.time?.start ?? 0, options)\n\n // An instrumental line carries no content, so its timestamp alone marks the gap.\n if (line.type === LineType.INSTRUMENTAL) {\n return time\n }\n\n const text = wordLevel && line.content?.words.length ? renderSyllableText(line, options) : renderPlainText(line)\n return `${time}${text}`\n}\n\nconst renderAnnotationRows = (lines: runtime.Line[], options: LrcGenerateOptionsRequired, pick: (line: runtime.Line) => { text: string }[]) => {\n const rows: string[] = []\n\n for (const line of lines) {\n const start = line.time?.start\n if (start === undefined) {\n continue\n }\n for (const item of pick(line)) {\n rows.push(`${renderTimeTag(start, options)}${item.text}`)\n }\n }\n\n return rows\n}\n\nconst joinBlocks = (header: string[], body: string[]) => {\n const blocks: string[] = []\n if (header.length) {\n blocks.push(header.join('\\n'))\n }\n if (body.length) {\n blocks.push(body.join('\\n'))\n }\n\n return blocks.join('\\n\\n')\n}\n\n/**\n * Generates the LRC text plus the annotations a single file cannot hold.\n *\n * Word tags appear only for a word-timed lyric when `wordTiming` is not `none`; otherwise every line stays whole.\n */\nexport const generateLrc = (lyric: runtime.Lyric, options: LrcGenerateOptions = {}): LrcGenerateResult => {\n const resolved = resolveOptions(options)\n const header = resolved.includeMeta && lyric.meta ? renderMetaRows(lyric.meta, resolved) : []\n\n const hasWords = lyric.lines.some((line) => (line.content?.words.length ?? 0) > 0)\n const wordLevel = hasWords && resolved.wordTiming !== 'none'\n\n const body = lyric.lines\n .map((line) => {\n return renderLineRow(line, resolved, wordLevel)\n })\n .filter((row) => row !== undefined)\n\n const result: LrcGenerateResult = {\n original: joinBlocks(header, body),\n }\n\n const translations = renderAnnotationRows(lyric.lines, resolved, (line) => line.annotation?.translations ?? [])\n if (translations.length) {\n result.translations = joinBlocks(header, translations)\n }\n\n const romans = renderAnnotationRows(lyric.lines, resolved, (line) => line.annotation?.romans ?? [])\n if (romans.length) {\n result.romans = joinBlocks(header, romans)\n }\n\n return result\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { Diagnostic } from '@gondola-lyrics/model/runtime'\n\nimport { canonicalizeLyric, validateLyric } from '@gondola-lyrics/model/runtime'\n\n/**\n * A parsed lyric in canonical form, with every rule it breaks.\n */\nexport interface ParseResult {\n lyric: runtime.Lyric\n diagnostics: Diagnostic[]\n}\n\n/**\n * Canonicalizes and validates one parser's output, so every format hands back the same shape.\n *\n * Canonicalization runs first because validation reports paths against the canonical tree.\n */\nexport const finalizeLyric = (input: runtime.Lyric): ParseResult => {\n const lyric = canonicalizeLyric(input)\n const diagnostics = validateLyric(lyric)\n\n return { lyric, diagnostics }\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { ParseResult } from '../result'\nimport type { LrcContent } from './common'\n\nimport {\n Timing,\n LyricStatus,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeTimeRange,\n makeMeta,\n makeText,\n makeUnknownEntry,\n makeWordNormal,\n makeWordSpace,\n deriveLanguageUsages,\n} from '@gondola-lyrics/model/runtime'\n\nimport { attachLineAnnotations, isTime, parseTime } from '@root/utils'\n\nimport { finalizeLyric } from '../result'\nimport { FORMAT, readLrcContent } from './common'\nimport { META_PATTERN, TAG_PATTERN, parseWordTime, splitWordTags } from './utils'\n\nexport interface LrcParseOptions {\n /**\n * How far an annotation's timestamp may sit from a line's start, in milliseconds.\n * Defaults to `0`, which requires an exact match.\n */\n annotationTolerance?: number\n}\n\nexport type LrcParseInput = LrcContent\n\ninterface TimedLine {\n text: string\n start: number\n}\n\ninterface MetaTag {\n key: string\n value: string\n}\n\nconst isBareNumber = (value: string) => {\n return /^\\d+$/.test(value.trim())\n}\n\n/**\n * A trailing tag alone still makes the line word-level, so it can close the last word.\n * Unreadable angle-bracket text stays plain lyric content.\n */\nconst isWordTimed = (text: string) => {\n return splitWordTags(text).some((piece) => piece.tag !== undefined && parseWordTime(piece.tag, 0) !== undefined)\n}\n\nconst readMeta = (body: string) => {\n const match = META_PATTERN.exec(body)\n if (!match) {\n return undefined\n }\n\n return { key: (match[1] ?? '').toLowerCase(), value: (match[2] ?? '').trim() }\n}\n\nconst readGroup = (tags: string[], text: string, timed: TimedLine[], meta: MetaTag[]) => {\n for (const tag of tags) {\n const start = isTime(tag) ? parseTime(tag) : undefined\n if (start !== undefined) {\n timed.push({ text, start })\n continue\n }\n\n const pair = readMeta(tag)\n if (pair) {\n meta.push(pair)\n }\n }\n}\n\n/**\n * Stacked timestamps share the following text, as in `[00:10][00:20]twice`.\n * Text before the first tag is discarded because it has no timing association.\n */\nconst readTimedLines = (text: string) => {\n const timed: TimedLine[] = []\n const meta: MetaTag[] = []\n\n for (const raw of text.replace(/\\r\\n?/g, '\\n').split('\\n')) {\n const line = raw.trim()\n if (!line) {\n continue\n }\n\n const matches = [...line.matchAll(TAG_PATTERN)]\n let group: string[] = []\n\n for (const [index, match] of matches.entries()) {\n const at = match.index + match[0].length\n const next = matches[index + 1]?.index ?? line.length\n const shared = line.slice(at, next)\n\n group.push(match[1] ?? '')\n\n if (!shared.trim()) {\n continue\n }\n\n readGroup(group, shared, timed, meta)\n group = []\n }\n\n // Trailing timestamps still represent empty timed lines.\n readGroup(group, '', timed, meta)\n }\n\n return { timed, meta }\n}\n\n/**\n * Unmapped tags and unparseable durations remain in `unknowns` to avoid discarding metadata.\n * Keys are lowercased and values trimmed, so original tag spelling is not preserved.\n */\nconst readMetaTags = (tags: MetaTag[]) => {\n const meta = makeMeta()\n\n for (const tag of tags) {\n switch (tag.key) {\n case 'length':\n case 'duration': {\n // Duration tags accept both clock notation and integer milliseconds.\n const duration = parseTime(tag.value) ?? (isBareNumber(tag.value) ? Number(tag.value) : Number.NaN)\n if (Number.isFinite(duration)) {\n meta.duration = Math.trunc(duration)\n } else {\n meta.unknowns.push(makeUnknownEntry({ key: tag.key, value: tag.value }))\n }\n break\n }\n case 'offset':\n meta.offset = Math.trunc(Number(tag.value)) || 0\n break\n case 'ti':\n case 'title':\n meta.titles.push(makeText({ text: tag.value }))\n break\n case 'ar':\n case 'artist':\n meta.artists.push(makeText({ text: tag.value }))\n break\n case 'al':\n case 'album':\n meta.albums.push(makeText({ text: tag.value }))\n break\n case 'by':\n case 'author':\n meta.authors.push(makeText({ text: tag.value }))\n break\n case 'isrc':\n meta.isrcs.push(tag.value)\n break\n default:\n meta.unknowns.push(makeUnknownEntry({ key: tag.key, value: tag.value }))\n break\n }\n }\n\n return meta\n}\n\n/**\n * Whitespace becomes a space word preserving the source run, as in `lo World`.\n * A tag opens a segment; untagged words continue from the previous end so the timeline has no holes.\n * Explicit word ends are kept as written, so duration tags survive unchanged.\n */\nconst readWords = (text: string, lineStart: number) => {\n const drafts: { text: string; start?: number; end?: number; space?: boolean }[] = []\n const open = new Set<{ start?: number; end?: number }>()\n\n const closeSegment = (boundary: number | undefined) => {\n if (boundary === undefined) {\n return\n }\n for (const draft of open) {\n if (draft.start !== undefined && draft.end === undefined && boundary >= draft.start) {\n draft.end = boundary\n }\n }\n open.clear()\n }\n\n let segmentStart: number | undefined = lineStart\n let cursor: number | undefined = lineStart\n\n for (const piece of splitWordTags(text)) {\n const time = piece.tag === undefined ? undefined : parseWordTime(piece.tag, lineStart)\n\n // A tag, even without following text, closes the segment it opens.\n if (time?.start !== undefined) {\n closeSegment(time.start)\n segmentStart = time.start\n cursor = time.start\n }\n\n if (!piece.text) {\n continue\n }\n\n let applied = false\n\n for (const run of piece.text.split(/(\\s+)/)) {\n if (!run) {\n continue\n }\n\n // A separator keeps its own text and never carries a tag.\n if (!run.trim()) {\n if (drafts.length) {\n drafts.push({ text: run, space: true })\n }\n continue\n }\n\n const tagged = !applied && time?.start !== undefined\n applied = true\n\n const start = tagged ? segmentStart : cursor\n const end = tagged ? time?.end : undefined\n const draft = { text: run, start, end }\n\n drafts.push(draft)\n if (end !== undefined) {\n cursor = end\n } else {\n open.add(draft)\n }\n }\n }\n\n return { drafts, closeSegment }\n}\n\n/**\n * A line ends at the next line's start; without one, it ends at its final word's end.\n * An open word is closed by the next timed word, or by the line end, so every sung word stays inside the line.\n * Empty timed rows represent instrumental time rather than sung content.\n */\nconst readLine = (text: string, start: number, nextStart: number | undefined) => {\n const trimmed = text.trim()\n let end = nextStart !== undefined && nextStart >= start ? nextStart : undefined\n if (trimmed === '') {\n return makeLineInstrumental({ time: makeTimeRange({ start, end }) })\n }\n\n const wordTimed = isWordTimed(text)\n const { drafts, closeSegment } = wordTimed ? readWords(text, start) : { drafts: [], closeSegment: () => {} }\n\n // Without a later line, a final word carrying its own end bounds the line; otherwise it stays open.\n if (end === undefined) {\n const last = [...drafts].reverse().find((draft) => !draft.space && draft.start !== undefined)\n end = last?.end\n }\n\n // Earlier segments were closed by their next tag, so this only closes the final one.\n closeSegment(end)\n\n const words = drafts.map((draft) => {\n if (draft.space) {\n return makeWordSpace({ text: draft.text })\n }\n // A missing start omits the range instead of inventing a word timestamp.\n const time = draft.start === undefined ? undefined : makeTimeRange({ start: draft.start, end: draft.end })\n return makeWordNormal({ text: draft.text, time })\n })\n\n const time = makeTimeRange({ start, end })\n const content = wordTimed ? makeLineContentWords(words) : makeLineContentText(trimmed)\n\n return makeLineNormal({ time, content })\n}\n\n/**\n * Builds one line per timed row, so an annotation track reuses the original text's reading unchanged.\n * Empty timed rows become instrumental lines bounded by the next timestamp when one is usable.\n */\nconst readLines = (timed: TimedLine[]): runtime.Line[] => {\n const lines: runtime.Line[] = []\n\n for (const [index, item] of timed.entries()) {\n const next = timed[index + 1]?.start\n // LRC has no line ends; only a nondecreasing next timestamp can supply one.\n lines.push(readLine(item.text, item.start, next))\n }\n\n return lines\n}\n\nconst parseLrcText = (text: string): runtime.Lyric => {\n const { timed, meta } = readTimedLines(text)\n const metaTags = readMetaTags(meta)\n\n if (!timed.length) {\n return makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta: metaTags })\n }\n\n const lines = readLines(timed)\n const wordTimed = lines.some((line) => (line.content?.words.length ?? 0) > 0)\n\n return makeLyric({\n format: FORMAT,\n status: LyricStatus.VALID,\n timing: wordTimed ? Timing.WORD : Timing.LINE,\n meta: metaTags,\n languages: deriveLanguageUsages(lines),\n lines,\n })\n}\n\n/**\n * Empty timed rows become instrumental lines; source order and missing word times remain for model validation.\n *\n * Annotation tracks are read as lines too and attached by timestamp, and rows that match no line are dropped.\n *\n * `INVALID` means no readable timed lines; the returned diagnostics carry whatever the canonical tree breaks.\n */\nexport const parseLrc = (input: string | LrcParseInput, options: LrcParseOptions = {}): ParseResult => {\n const source = readLrcContent(input) ?? { original: '' }\n const lyric = parseLrcText(source.original)\n\n if (lyric.status === LyricStatus.INVALID) {\n return finalizeLyric(lyric)\n }\n\n const translations = source.translations === undefined ? [] : readLines(readTimedLines(source.translations).timed)\n const romans = source.romans === undefined ? [] : readLines(readTimedLines(source.romans).timed)\n if (translations.length === 0 && romans.length === 0) {\n return finalizeLyric(lyric)\n }\n\n const lines = attachLineAnnotations(lyric.lines, { translations, romans }, { tolerance: options.annotationTolerance })\n\n return finalizeLyric({ ...lyric, lines })\n}\n","export const FORMAT = 'ttml'\n\nexport type TtmlProfile = 'amll' | 'itunes'\n\nexport const AMLL_HINT_PATTERN = /xmlns:amll|amll:meta/iu\n\nexport const ITUNES_HINT_PATTERN = /xmlns:itunes|iTunesMetadata|itunes:timing=/iu\n\n/**\n * Accepts the text input shared by TTML detection and parsing.\n */\nexport const readTtmlContent = (input: unknown): string | null => {\n if (typeof input !== 'string') {\n return null\n }\n return input\n}\n","import { XmlNodeType, parseXml } from '@root/utils'\n\nimport { AMLL_HINT_PATTERN, ITUNES_HINT_PATTERN, readTtmlContent } from './common'\n\n/**\n * Recognition needs a profile hint, since plain TTML says nothing about which profile wrote it.\n *\n * A bare `tt` root also counts, which is what a hand-written document has.\n * This is a format probe, not a validity check, so an input of another shape is simply not TTML.\n */\nexport const detectTtml = (input: unknown) => {\n const content = readTtmlContent(input)\n if (!content) {\n return false\n }\n\n if (AMLL_HINT_PATTERN.test(content) || ITUNES_HINT_PATTERN.test(content)) {\n return true\n }\n\n // A document without a hint still counts when its root is a tt element.\n const root = parseXml(content)\n if (!root) {\n return false\n }\n\n for (const child of root.children) {\n if (child.nodeType === XmlNodeType.element && child.localName === 'tt') {\n return true\n }\n }\n\n return false\n}\n","export const ROLE_BACKGROUND = 'x-bg'\nexport const ROLE_TRANSLATION = 'x-translation'\nexport const ROLE_ROMAN = 'x-roman'\n\nexport const RUBY_CONTAINER = 'container'\nexport const RUBY_BASE = 'base'\nexport const RUBY_TEXT_CONTAINER = 'textContainer'\nexport const RUBY_TEXT = 'text'\n\nexport const TIMING_WORD = 'Word'\nexport const TIMING_LINE = 'Line'\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { XmlElement, XmlNode } from '@root/utils'\nimport type { TtmlProfile } from './common'\n\nimport {\n AgentType,\n CreditRole,\n LineType,\n Timing,\n WordType,\n removeOffset,\n resolveAnnotationItemTime,\n resolveAnnotationTokenTime,\n} from '@gondola-lyrics/model/runtime'\n\nimport { createXmlElement, createXmlText, serializeXml } from '@root/utils'\n\nimport { FORMAT } from './common'\nimport {\n ROLE_BACKGROUND,\n ROLE_ROMAN,\n ROLE_TRANSLATION,\n RUBY_BASE,\n RUBY_CONTAINER,\n RUBY_TEXT,\n RUBY_TEXT_CONTAINER,\n TIMING_LINE,\n TIMING_WORD,\n} from './utils'\n\nexport type TtmlGenerateResult = string\n\nexport interface TtmlGenerateOptions {\n /**\n * Defaults to the source TTML profile, or `amll` when the lyric came from another format.\n */\n profile?: TtmlProfile\n /**\n * Indent document structure; defaults to `false`.\n * Lyric content stays flush to keep formatting whitespace out of the words.\n */\n indent?: boolean\n /**\n * Emit song metadata; defaults to `true`.\n * Agents and annotation tracks are retained because the body references them.\n */\n includeMeta?: boolean\n}\n\ntype SungLine = runtime.Line | runtime.LineBackground\n\ntype Attributes = [string, string][]\n\ntype AnnotationKind = 'translations' | 'romans'\n\ntype AnnotationTracks = Map<string | undefined, Map<runtime.Line, XmlNode[]>>\n\ntype ResolvedTtmlGenerateOptions = Required<TtmlGenerateOptions>\n\ninterface RenderContext {\n profile: TtmlProfile\n offset: number\n keys: Map<SungLine, string>\n agents: Map<string, string>\n}\n\nconst NAMESPACE_TTML = 'http://www.w3.org/ns/ttml'\nconst NAMESPACE_TTML_METADATA = 'http://www.w3.org/ns/ttml#metadata'\nconst NAMESPACE_TTML_STYLING = 'http://www.w3.org/ns/ttml#styling'\nconst NAMESPACE_ITUNES = 'http://itunes.apple.com/lyric-ttml-extensions'\nconst NAMESPACE_ITUNES_METADATA = 'http://music.apple.com/lyric-ttml-internal'\nconst NAMESPACE_AMLL = 'http://www.example.com/ns/amll'\n\nconst ANNOTATION_KINDS = ['translations', 'romans'] as const\n\nconst XML_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_.-]*$/\n\nconst resolveOptions = (lyric: runtime.Lyric, options: TtmlGenerateOptions): ResolvedTtmlGenerateOptions => {\n const profile = options.profile ?? (lyric.format === FORMAT && lyric.extra.profile === 'itunes' ? 'itunes' : 'amll')\n if (profile !== 'amll' && profile !== 'itunes') {\n throw new Error('Unsupported TTML profile')\n }\n\n return { profile, includeMeta: options.includeMeta ?? true, indent: options.indent ?? false }\n}\n\n/**\n * Reserves source ids before allocating keys, so unnamed entries cannot take later source ids.\n */\nconst makeIdAllocator = (ids: string[]) => {\n const reserved = new Set(\n ids.filter((id) => {\n return XML_ID_PATTERN.test(id)\n }),\n )\n const used = new Set<string>()\n const counters = new Map<string, number>()\n\n return (preferred: string, prefix: string) => {\n if (XML_ID_PATTERN.test(preferred) && !used.has(preferred)) {\n used.add(preferred)\n return preferred\n }\n\n let count = counters.get(prefix) ?? 0\n let id: string\n do {\n count += 1\n id = `${prefix}${count}`\n } while (reserved.has(id) || used.has(id))\n\n counters.set(prefix, count)\n used.add(id)\n return id\n }\n}\n\n/**\n * Shares one mapping between declarations, body lines, and annotation references.\n */\nconst makeContext = (lyric: runtime.Lyric, lines: runtime.Line[], profile: TtmlProfile): RenderContext => {\n const ids = lyric.agents.map((agent) => {\n return agent.id\n })\n for (const line of lines) {\n ids.push(line.id)\n for (const background of line.backgrounds) {\n ids.push(background.id)\n }\n }\n\n const allocate = makeIdAllocator(ids)\n const agents = new Map<string, string>()\n const keys = new Map<SungLine, string>()\n\n for (const agent of lyric.agents) {\n if (agents.has(agent.id)) {\n throw new Error('TTML agent declarations require unique ids')\n }\n agents.set(agent.id, allocate(agent.id, 'v'))\n }\n for (const line of lines) {\n keys.set(line, allocate(line.id, 'L'))\n for (const background of line.backgrounds) {\n keys.set(background, allocate(background.id, 'B'))\n }\n }\n\n return { profile, offset: lyric.meta?.offset ?? 0, keys, agents }\n}\n\n/**\n * Bakes the playback offset into TTML timestamps without clamping negative results.\n */\nconst renderTime = (time: number, offset: number) => {\n const shifted = removeOffset(time, offset)\n if (!Number.isInteger(shifted) || shifted < 0) {\n throw new RangeError('TTML timestamps must be non-negative integer milliseconds after applying the offset')\n }\n\n const seconds = Math.floor(shifted / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = String(Math.floor(minutes / 60)).padStart(2, '0')\n const milliseconds = String(shifted % 1000).padStart(3, '0')\n\n return `${hours}:${String(minutes % 60).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}.${milliseconds}`\n}\n\n/**\n * Writes known bounds without inventing an end.\n */\nconst renderTimeAttributes = (time: runtime.TimeRange | undefined, offset: number): Attributes => {\n if (time === undefined) {\n throw new Error('TTML sung lines, words, and ruby tokens require a time range')\n }\n\n const attributes: Attributes = [['begin', renderTime(time.start, offset)]]\n if (time.end !== undefined) {\n attributes.push(['end', renderTime(time.end, offset)])\n }\n return attributes\n}\n\n/**\n * Clears inherited language when the model leaves an item's language unspecified.\n */\nconst renderLanguage = (language: string | undefined, inherited?: string): Attributes => {\n if (language !== undefined) {\n return [['xml:lang', language]]\n }\n\n return inherited === undefined ? [] : [['xml:lang', '']]\n}\n\nconst getLineLanguage = (line: SungLine): string | undefined => {\n return line.languages.length === 1 ? line.languages[0] : undefined\n}\n\n/**\n * Writes separators as text and resolves inherited ruby timing through the model.\n */\nconst renderWord = (word: runtime.Word, context: RenderContext, language?: string): XmlNode => {\n if (word.type === WordType.SPACE) {\n return createXmlText(word.text)\n }\n\n const attributes = [...renderTimeAttributes(word.time, context.offset), ...renderLanguage(word.language, language)]\n const ruby = context.profile === 'amll' ? word.annotation?.rubies[0] : undefined\n if (ruby === undefined) {\n return createXmlElement('span', attributes, [createXmlText(word.text)])\n }\n\n const tokens = ruby.tokens.map((token) => {\n return createXmlElement(\n 'span',\n [['tts:ruby', RUBY_TEXT], ...renderTimeAttributes(resolveAnnotationTokenTime(token, ruby, word), context.offset)],\n [createXmlText(token.text)],\n )\n })\n\n return createXmlElement(\n 'span',\n [['tts:ruby', RUBY_CONTAINER], ...attributes],\n [\n createXmlElement('span', [['tts:ruby', RUBY_BASE]], [createXmlText(word.text)]),\n createXmlElement(\n 'span',\n [\n ['tts:ruby', RUBY_TEXT_CONTAINER],\n ...renderTimeAttributes(resolveAnnotationItemTime(ruby, word), context.offset),\n ...renderLanguage(ruby.language, word.language),\n ],\n tokens,\n ),\n ],\n )\n}\n\n/**\n * Retains the model's choice between whole text and timed words.\n */\nconst renderContent = (line: SungLine, context: RenderContext): XmlNode[] => {\n const content = line.content\n if (content === undefined) {\n throw new Error('TTML sung lines require content')\n }\n if (content.text !== undefined) {\n return [createXmlText(content.text)]\n }\n\n return content.words.map((word) => {\n return renderWord(word, context, getLineLanguage(line))\n })\n}\n\n/**\n * Keeps annotations outside the sung word stream.\n */\nconst renderInlineAnnotations = (annotation: runtime.LineAnnotation | undefined, language?: string): XmlElement[] => {\n const nodes: XmlElement[] = []\n for (const item of annotation?.translations ?? []) {\n nodes.push(createXmlElement('span', [['ttm:role', ROLE_TRANSLATION], ...renderLanguage(item.language, language)], [createXmlText(item.text)]))\n }\n for (const item of annotation?.romans ?? []) {\n nodes.push(createXmlElement('span', [['ttm:role', ROLE_ROMAN], ...renderLanguage(item.language, language)], [createXmlText(item.text)]))\n }\n return nodes\n}\n\n/**\n * Uses the same allocated keys and agent ids as the document's declarations.\n */\nconst renderLineAttributes = (line: SungLine, context: RenderContext): Attributes => {\n const attributes: Attributes = [\n ...renderTimeAttributes(line.time, context.offset),\n ['itunes:key', context.keys.get(line)!],\n ['xml:space', 'preserve'],\n ['xml:lang', getLineLanguage(line) ?? ''],\n ]\n const lead = line.agents[0]\n if (lead !== undefined) {\n const id = context.agents.get(lead)\n if (id === undefined) {\n throw new Error('TTML performing agents must have a declaration')\n }\n attributes.push(['ttm:agent', id])\n }\n return attributes\n}\n\n/**\n * An empty text node keeps the XML writer's indentation outside lyric content.\n */\nconst createLyricElement = (name: string, attributes: Attributes, children: XmlNode[]) => {\n return createXmlElement(name, attributes, [createXmlText(''), ...children])\n}\n\nconst renderBackground = (line: runtime.LineBackground, context: RenderContext) => {\n const children = renderContent(line, context)\n if (context.profile === 'amll') {\n children.push(...renderInlineAnnotations(line.annotation, getLineLanguage(line)))\n }\n\n return createXmlElement('span', [['ttm:role', ROLE_BACKGROUND], ...renderLineAttributes(line, context)], children)\n}\n\nconst renderLine = (line: runtime.Line, context: RenderContext) => {\n const before: XmlNode[] = []\n const after: XmlNode[] = []\n for (const background of line.backgrounds) {\n const node = renderBackground(background, context)\n if (background.time !== undefined && line.time !== undefined && background.time.start < line.time.start) {\n before.push(node)\n } else {\n after.push(node)\n }\n }\n\n const children = [...before, ...renderContent(line, context), ...after]\n if (context.profile === 'amll') {\n children.push(...renderInlineAnnotations(line.annotation, getLineLanguage(line)))\n }\n return createLyricElement('p', renderLineAttributes(line, context), children)\n}\n\nconst renderAgents = (lyric: runtime.Lyric, context: RenderContext) => {\n return lyric.agents.map((agent) => {\n const type = agent.type === AgentType.PERSON ? 'person' : agent.type === AgentType.GROUP ? 'group' : (agent.raw ?? 'other')\n const names = agent.names.map((name) => {\n return createXmlElement('ttm:name', [['type', 'full'], ...renderLanguage(name.language)], [createXmlText(name.text)])\n })\n\n return createXmlElement(\n 'ttm:agent',\n [\n ['type', type],\n ['xml:id', context.agents.get(agent.id)!],\n ],\n names,\n )\n })\n}\n\nconst renderAmllMeta = (meta: runtime.Meta): XmlElement[] => {\n const nodes: XmlElement[] = []\n const groups: [string, runtime.Text[]][] = [\n ['musicName', meta.titles],\n ['artists', meta.artists],\n ['album', meta.albums],\n ['ttmlAuthorGithubLogin', meta.authors],\n ]\n for (const [key, items] of groups) {\n for (const item of items) {\n nodes.push(createXmlElement('amll:meta', [['key', key], ['value', item.text], ...renderLanguage(item.language)]))\n }\n }\n for (const value of meta.isrcs) {\n nodes.push(\n createXmlElement('amll:meta', [\n ['key', 'isrc'],\n ['value', value],\n ]),\n )\n }\n for (const item of meta.unknowns) {\n nodes.push(\n createXmlElement('amll:meta', [\n ['key', item.key],\n ['value', item.value],\n ]),\n )\n }\n return nodes\n}\n\nconst renderSongwriters = (meta: runtime.Meta): XmlElement[] => {\n const names: XmlElement[] = []\n for (const credit of meta.credits) {\n if (credit.role !== CreditRole.LYRICIST) {\n continue\n }\n for (const name of credit.names) {\n names.push(createXmlElement('songwriter', renderLanguage(name.language), [createXmlText(name.text)]))\n }\n }\n return names.length === 0 ? [] : [createXmlElement('songwriters', [], names)]\n}\n\nconst renderAnnotationTracks = (tracks: AnnotationTracks, kind: AnnotationKind, context: RenderContext): XmlElement[] => {\n if (tracks.size === 0) {\n return []\n }\n\n const translated = kind === 'translations'\n const blocks = Array.from(tracks, ([language, track]) => {\n const attributes: Attributes = translated ? [['type', 'subtitle']] : []\n attributes.push(...renderLanguage(language))\n const texts = Array.from(track, ([line, children]) => {\n return createLyricElement(\n 'text',\n [\n ['for', context.keys.get(line)!],\n ['xml:space', 'preserve'],\n ],\n children,\n )\n })\n return createXmlElement(translated ? 'translation' : 'transliteration', attributes, texts)\n })\n\n return [createXmlElement(translated ? 'translations' : 'transliterations', [], blocks)]\n}\n\n/**\n * A background-only annotation still references its parent paragraph, with a second reference naming the background.\n */\nconst renderHeadAnnotations = (lines: runtime.Line[], context: RenderContext): XmlElement[] => {\n const tracks: Record<AnnotationKind, AnnotationTracks> = { translations: new Map(), romans: new Map() }\n const append = (annotation: runtime.LineAnnotation | undefined, line: runtime.Line, background?: runtime.LineBackground) => {\n if (annotation === undefined) {\n return\n }\n\n for (const kind of ANNOTATION_KINDS) {\n for (const item of annotation[kind]) {\n const language = item.language?.toLowerCase()\n let track = tracks[kind].get(language)\n if (track === undefined) {\n track = new Map()\n tracks[kind].set(language, track)\n }\n let nodes = track.get(line)\n if (nodes === undefined) {\n nodes = []\n track.set(line, nodes)\n }\n\n nodes.push(\n background === undefined\n ? createXmlText(item.text)\n : createXmlElement(\n 'span',\n [\n ['ttm:role', ROLE_BACKGROUND],\n ['for', context.keys.get(background)!],\n ],\n [createXmlText(item.text)],\n ),\n )\n }\n }\n }\n\n for (const line of lines) {\n append(line.annotation, line)\n for (const background of line.backgrounds) {\n append(background.annotation, line, background)\n }\n }\n\n return ANNOTATION_KINDS.flatMap((kind) => {\n return renderAnnotationTracks(tracks[kind], kind, context)\n })\n}\n\nconst renderMetadata = (lyric: runtime.Lyric, lines: runtime.Line[], context: RenderContext, includeMeta: boolean): XmlElement => {\n const metadata = renderAgents(lyric, context)\n const itunes: XmlElement[] = []\n if (includeMeta && lyric.meta !== undefined) {\n if (context.profile === 'amll') {\n metadata.push(...renderAmllMeta(lyric.meta))\n }\n itunes.push(...renderSongwriters(lyric.meta))\n }\n if (context.profile === 'itunes') {\n itunes.push(...renderHeadAnnotations(lines, context))\n }\n if (itunes.length > 0) {\n metadata.push(createXmlElement('iTunesMetadata', [['xmlns', NAMESPACE_ITUNES_METADATA]], itunes))\n }\n\n return createXmlElement('metadata', renderLanguage(undefined, lyric.meta?.language), metadata)\n}\n\nconst renderRootAttributes = (lyric: runtime.Lyric, profile: TtmlProfile): Attributes => {\n const attributes: Attributes = [\n ['xmlns', NAMESPACE_TTML],\n ['xmlns:ttm', NAMESPACE_TTML_METADATA],\n ['xmlns:tts', NAMESPACE_TTML_STYLING],\n ['xmlns:itunes', NAMESPACE_ITUNES],\n ]\n if (profile === 'amll') {\n attributes.push(['xmlns:amll', NAMESPACE_AMLL])\n }\n attributes.push(...renderLanguage(lyric.meta?.language), ['itunes:timing', lyric.timing === Timing.WORD ? TIMING_WORD : TIMING_LINE])\n\n return attributes\n}\n\n/**\n * Generates one TTML document, retaining the source profile unless explicitly overridden.\n *\n * Offsets are baked into timestamps; a negative result or a missing required time throws.\n * Profile mappings retain the lead agent and first AMLL ruby, omitting unsupported fields and instrumental nodes.\n */\nexport const generateTtml = (lyric: runtime.Lyric, options: TtmlGenerateOptions = {}): TtmlGenerateResult => {\n if (lyric.timing !== Timing.LINE && lyric.timing !== Timing.WORD) {\n throw new Error('TTML generation requires line or word timing')\n }\n\n const resolved = resolveOptions(lyric, options)\n const lines = lyric.lines.filter((line) => {\n return line.type !== LineType.INSTRUMENTAL\n })\n const context = makeContext(lyric, lines, resolved.profile)\n const metadata = renderMetadata(lyric, lines, context, resolved.includeMeta)\n const paragraphs = lines.map((line) => {\n return renderLine(line, context)\n })\n\n const root = createXmlElement('tt', renderRootAttributes(lyric, resolved.profile), [\n createXmlElement('head', [], [metadata]),\n createXmlElement('body', [], [createXmlElement('div', [], paragraphs)]),\n ])\n\n return serializeXml(root, { indent: resolved.indent })\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { XmlElement } from '@root/utils'\nimport type { ParseResult } from '../result'\nimport type { TtmlProfile } from './common'\n\nimport {\n AgentType,\n CreditRole,\n LyricStatus,\n Timing,\n deriveLanguageUsages,\n makeAgent,\n makeLineAnnotation,\n makeLineAnnotationRoman,\n makeLineAnnotationTranslation,\n makeLineBackground,\n makeLineContentText,\n makeLineContentWords,\n makeLineNormal,\n makeLyric,\n makeMeta,\n makeMetaCredit,\n makeText,\n makeTimeRange,\n makeUnknownEntry,\n makeWordAnnotation,\n makeWordAnnotationRuby,\n makeWordAnnotationToken,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport {\n XmlNodeType,\n findXmlElement,\n getXmlAttribute,\n getXmlChildElements,\n getXmlQualifiedAttribute,\n getXmlTextContent,\n hasXmlChildElement,\n lowerTag,\n parseTime,\n parseXml,\n} from '@root/utils'\n\nimport { finalizeLyric } from '../result'\nimport { FORMAT, AMLL_HINT_PATTERN, readTtmlContent } from './common'\nimport {\n ROLE_BACKGROUND,\n ROLE_ROMAN,\n ROLE_TRANSLATION,\n RUBY_BASE,\n RUBY_CONTAINER,\n RUBY_TEXT,\n RUBY_TEXT_CONTAINER,\n TIMING_LINE,\n TIMING_WORD,\n} from './utils'\n\ninterface TokenDraft {\n start?: number\n end?: number\n text: string\n}\n\ninterface RubyDraft {\n start?: number\n end?: number\n language?: string\n tokens: TokenDraft[]\n}\n\ninterface WordDraft {\n text: string\n space: boolean\n start?: number\n end?: number\n language?: string\n rubies: RubyDraft[]\n}\n\ninterface AnnotationDraft {\n language: string | undefined\n text: string\n}\n\ninterface LineDraft {\n start: number\n end: number | undefined\n agentId: string | undefined\n key: string | undefined\n words: WordDraft[]\n translations: AnnotationDraft[]\n romans: AnnotationDraft[]\n backgrounds: LineDraft[]\n wordLevel: boolean\n preserveSpace: boolean\n language: string | undefined\n}\n\ninterface ElementContext {\n element: XmlElement\n preserveSpace: boolean\n language: string | undefined\n}\n\nexport type TtmlParseInput = string\n\nexport interface TtmlParseOptions {\n /** Language tag the lyric declares; the document's own `xml:lang` wins when it states one. */\n language?: string\n}\n\nconst METADATA_NAMES = ['agent', 'songwriter', 'meta', 'translation', 'transliteration'] as const\n\nconst WORD_SEPARATOR_PATTERN = /\\p{White_Space}/u\n\nconst readTtmlProfile = (source: string): TtmlProfile => {\n return AMLL_HINT_PATTERN.test(source) ? 'amll' : 'itunes'\n}\n\nconst readSpanTime = (element: XmlElement) => {\n const begin = getXmlAttribute(element, 'begin')\n if (!begin) {\n return undefined\n }\n\n const start = parseTime(begin)\n if (start === undefined) {\n return undefined\n }\n\n const end = getXmlAttribute(element, 'end')\n\n return { start, end: end ? parseTime(end) : undefined }\n}\n\nconst readLineTime = (element: XmlElement) => {\n return readSpanTime(element)\n}\n\nconst readAgentType = (raw: string | undefined): { type: AgentType; raw: string | undefined } => {\n switch (raw) {\n case 'person':\n return { type: AgentType.PERSON, raw: undefined }\n case 'group':\n return { type: AgentType.GROUP, raw: undefined }\n default:\n return { type: AgentType.OTHER, raw: raw ?? 'other' }\n }\n}\n\nconst readDeclaredTiming = (root: XmlElement): Timing | undefined => {\n switch (getXmlQualifiedAttribute(root, 'itunes:timing')) {\n case TIMING_WORD:\n return Timing.WORD\n case TIMING_LINE:\n return Timing.LINE\n default:\n return undefined\n }\n}\n\nconst readPreserveSpace = (element: XmlElement, inherited: boolean): boolean => {\n switch (getXmlQualifiedAttribute(element, 'xml:space')) {\n case 'preserve':\n return true\n case 'default':\n return false\n default:\n return inherited\n }\n}\n\nconst readLanguage = (element: XmlElement, inherited?: string): string | undefined => {\n const language = getXmlQualifiedAttribute(element, 'xml:lang') ?? getXmlAttribute(element, 'lang')\n return language === undefined ? inherited : lowerTag(language)\n}\n\nconst readText = (element: XmlElement, inherited: boolean): string => {\n const text = getXmlTextContent(element)\n return readPreserveSpace(element, inherited) ? text : text.trim()\n}\n\n/**\n * Preserves the parser's whitespace segmentation when turning text into word drafts.\n */\nconst splitWords = (text: string, language?: string): WordDraft[] => {\n if (text === '') {\n return []\n }\n if (!WORD_SEPARATOR_PATTERN.test(text)) {\n return [{ text, space: false, language, rubies: [] }]\n }\n\n const words: WordDraft[] = []\n\n for (const run of text.split(/(\\p{White_Space}+)/u)) {\n if (run !== '') {\n const space = /^\\p{White_Space}+$/u.test(run)\n words.push({ text: run, space, language: space ? undefined : language, rubies: [] })\n }\n }\n\n return words\n}\n\n/**\n * Distinguishes indentation runs from separators using the parser's existing rule.\n */\nconst isFormattingWhitespace = (text: string) => {\n return text.trim() === '' && text.includes('\\n')\n}\n\n/**\n * Builds words from source drafts without deriving missing timestamps.\n */\nconst buildWords = (draft: LineDraft): runtime.Word[] => {\n const words: runtime.Word[] = []\n\n for (const word of draft.words) {\n if (word.space) {\n words.push(makeWordSpace({ text: word.text }))\n continue\n }\n\n const time = word.start === undefined ? undefined : makeTimeRange({ start: word.start, end: word.end })\n if (word.rubies.length === 0) {\n words.push(makeWordNormal({ text: word.text, time, language: word.language }))\n continue\n }\n\n const rubies = word.rubies.map((ruby) => {\n return makeWordAnnotationRuby({\n time: ruby.start === undefined ? undefined : makeTimeRange({ start: ruby.start, end: ruby.end }),\n language: ruby.language,\n tokens: ruby.tokens.map((token) => {\n return makeWordAnnotationToken({\n text: token.text,\n time: token.start === undefined ? undefined : makeTimeRange({ start: token.start, end: token.end }),\n })\n }),\n })\n })\n\n words.push(makeWordNormal({ text: word.text, time, language: word.language, annotation: makeWordAnnotation({ rubies }) }))\n }\n\n return words\n}\n\n/**\n * Builds only annotations explicitly present in the source drafts.\n */\nconst buildLineAnnotation = (draft: LineDraft): runtime.LineAnnotation | undefined => {\n if (draft.translations.length === 0 && draft.romans.length === 0) {\n return undefined\n }\n\n return makeLineAnnotation({\n translations: draft.translations.map((item) => {\n return makeLineAnnotationTranslation({ text: item.text, language: item.language })\n }),\n romans: draft.romans.map((item) => {\n return makeLineAnnotationRoman({ text: item.text, language: item.language })\n }),\n })\n}\n\n/**\n * Separates head annotation text from its background references.\n */\nconst splitBackgroundText = (element: XmlElement, preserveSpace: boolean, language?: string) => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n let main = ''\n const backgrounds: { text: string; key: string | undefined; language: string | undefined }[] = []\n\n for (const child of element.children) {\n if (child.nodeType === XmlNodeType.element && child.localName === 'span' && getXmlAttribute(child, 'role') === ROLE_BACKGROUND) {\n backgrounds.push({ text: readText(child, preserveSpace), key: getXmlAttribute(child, 'for'), language: readLanguage(child, language) })\n continue\n }\n main += getXmlTextContent(child)\n }\n\n return { main: preserveSpace ? main : main.trim(), backgrounds }\n}\n\n/**\n * Carries language and whitespace declarations through wrappers to the elements they govern.\n */\nconst groupElements = (\n root: XmlElement,\n names: readonly string[],\n preserveSpace: boolean,\n stopAtMatch = false,\n language?: string,\n): Map<string, ElementContext[]> => {\n const wanted = new Set(names)\n const result = new Map<string, ElementContext[]>()\n const stack: ElementContext[] = [{ element: root, preserveSpace, language }]\n\n while (stack.length > 0) {\n const entry = stack.pop()\n if (entry === undefined) {\n continue\n }\n const element = entry.element\n const currentSpace = readPreserveSpace(element, entry.preserveSpace)\n const currentLanguage = readLanguage(element, entry.language)\n if (wanted.has(element.localName)) {\n const group = result.get(element.localName)\n const context = { element, preserveSpace: currentSpace, language: currentLanguage }\n if (group === undefined) {\n result.set(element.localName, [context])\n } else {\n group.push(context)\n }\n if (stopAtMatch) {\n continue\n }\n }\n\n const children = element.children\n for (let index = children.length - 1; index >= 0; index -= 1) {\n const child = children[index]\n if (child && child.nodeType === XmlNodeType.element) {\n stack.push({ element: child, preserveSpace: currentSpace, language: currentLanguage })\n }\n }\n }\n\n return result\n}\n\nconst findElements = (root: XmlElement, name: string, preserveSpace: boolean, stopAtMatch = false, language?: string): ElementContext[] => {\n return groupElements(root, [name], preserveSpace, stopAtMatch, language).get(name) ?? []\n}\n\n/**\n * Reads an AMLL ruby container into one word plus its per-syllable annotation.\n */\nconst readRuby = (container: XmlElement, preserveSpace: boolean, language?: string): WordDraft | undefined => {\n preserveSpace = readPreserveSpace(container, preserveSpace)\n language = readLanguage(container, language)\n let base = ''\n let baseLanguage = language\n let rubyTime: ReturnType<typeof readSpanTime>\n let rubyLanguage = language\n const tokens: TokenDraft[] = []\n\n for (const child of getXmlChildElements(container, 'span')) {\n const kind = getXmlAttribute(child, 'ruby')\n if (kind === RUBY_BASE) {\n base = readText(child, preserveSpace)\n baseLanguage = readLanguage(child, language)\n continue\n }\n if (kind !== RUBY_TEXT_CONTAINER) {\n continue\n }\n\n rubyTime ??= readSpanTime(child)\n rubyLanguage = readLanguage(child, language)\n const rubySpace = readPreserveSpace(child, preserveSpace)\n for (const text of getXmlChildElements(child, 'span')) {\n if (getXmlAttribute(text, 'ruby') !== RUBY_TEXT) {\n continue\n }\n const time = readSpanTime(text)\n const content = readText(text, rubySpace)\n if (!content) {\n continue\n }\n tokens.push({ start: time?.start, end: time?.end, text: content })\n }\n }\n\n if (!base) {\n return undefined\n }\n\n const first = tokens.find((token) => {\n return token.start !== undefined\n })\n const last = tokens.findLast((token) => {\n return token.start !== undefined\n })\n // Older AMLL containers state timing only on their annotation tokens.\n const time = readSpanTime(container) ?? rubyTime ?? (first === undefined ? undefined : { start: first.start, end: last?.end })\n\n return {\n text: base,\n space: false,\n start: time?.start,\n end: time?.end,\n language: baseLanguage,\n rubies: tokens.length === 0 ? [] : [{ start: rubyTime?.start, end: rubyTime?.end, language: rubyLanguage, tokens }],\n }\n}\n\n/**\n * Collects the words of one span-bearing element.\n *\n * Text between spans carries the separators, and a span without a readable begin contributes its text untimed.\n * A span carrying a role is annotation rather than a word, so it is skipped here.\n * Whitespace inside a span remains a separator; indentation is dropped only without a preserve declaration.\n */\nconst readWords = (element: XmlElement, preserveSpace: boolean, language?: string): { words: WordDraft[]; wordLevel: boolean } => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const words: WordDraft[] = []\n let wordLevel = false\n\n for (const child of element.children) {\n if (child.nodeType !== XmlNodeType.element) {\n if (preserveSpace || !isFormattingWhitespace(child.text)) {\n words.push(...splitWords(child.text, language))\n }\n continue\n }\n if (child.localName !== 'span') {\n continue\n }\n\n const role = getXmlAttribute(child, 'role')\n if (role !== undefined) {\n continue\n }\n\n if (getXmlAttribute(child, 'ruby') === RUBY_CONTAINER) {\n const ruby = readRuby(child, preserveSpace, language)\n if (ruby !== undefined) {\n for (const part of splitWords(ruby.text)) {\n words.push(part.space ? part : { ...ruby, text: part.text })\n }\n wordLevel ||= ruby.start !== undefined\n }\n continue\n }\n\n const text = getXmlTextContent(child)\n const childSpace = readPreserveSpace(child, preserveSpace)\n if (!text || (!childSpace && isFormattingWhitespace(text))) {\n continue\n }\n\n const time = readSpanTime(child)\n for (const part of splitWords(text, readLanguage(child, language))) {\n if (!part.space && time !== undefined) {\n part.start = time.start\n part.end = time.end\n wordLevel = true\n }\n words.push(part)\n }\n }\n\n return { words, wordLevel }\n}\n\nconst readInlineAnnotations = (element: XmlElement, preserveSpace: boolean, language?: string): Pick<LineDraft, 'translations' | 'romans'> => {\n const translations: AnnotationDraft[] = []\n const romans: AnnotationDraft[] = []\n\n for (const span of getXmlChildElements(element, 'span')) {\n const role = getXmlAttribute(span, 'role')\n if (role !== ROLE_TRANSLATION && role !== ROLE_ROMAN) {\n continue\n }\n const text = readText(span, preserveSpace)\n if (!text) {\n continue\n }\n\n const item = { language: readLanguage(span, language), text }\n if (role === ROLE_TRANSLATION) {\n translations.push(item)\n } else {\n romans.push(item)\n }\n }\n\n return { translations, romans }\n}\n\n/**\n * Reads one paragraph, pulling its inline annotations and background lines out of the word stream.\n */\nconst readLine = (element: XmlElement, preserveSpace: boolean, language?: string): LineDraft | undefined => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const time = readLineTime(element)\n if (time === undefined) {\n return undefined\n }\n\n const draft: LineDraft = {\n start: time.start,\n end: time.end,\n agentId: getXmlAttribute(element, 'agent'),\n key: getXmlAttribute(element, 'key'),\n words: [],\n translations: [],\n romans: [],\n backgrounds: [],\n wordLevel: false,\n preserveSpace,\n language,\n }\n\n if (!hasXmlChildElement(element, 'span')) {\n const plain = readText(element, preserveSpace)\n if (!plain) {\n return undefined\n }\n\n draft.words = splitWords(plain, language)\n return draft\n }\n\n const read = readWords(element, preserveSpace, language)\n draft.words = read.words\n draft.wordLevel = read.wordLevel\n const annotations = readInlineAnnotations(element, preserveSpace, language)\n draft.translations = annotations.translations\n draft.romans = annotations.romans\n\n for (const span of getXmlChildElements(element, 'span')) {\n const role = getXmlAttribute(span, 'role')\n if (role === ROLE_BACKGROUND) {\n const background = readBackground(span, preserveSpace, language)\n if (background) {\n draft.backgrounds.push(background)\n }\n }\n }\n\n return draft\n}\n\n/**\n * Reads a background line, whose end may stay open because its parent's end covers it.\n *\n * A background line states no time of its own in AMLL files, so its range comes from its words.\n */\nconst readBackground = (element: XmlElement, preserveSpace: boolean, language?: string): LineDraft | undefined => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const read = readWords(element, preserveSpace, language)\n if (read.words.length === 0) {\n return undefined\n }\n\n const begin = getXmlAttribute(element, 'begin')\n const end = getXmlAttribute(element, 'end')\n const first = read.words.find((word) => {\n return !word.space && word.start !== undefined\n })\n const last = read.words.findLast((word) => {\n return !word.space && word.start !== undefined\n })\n\n const start = begin === undefined ? (first?.start ?? 0) : parseTime(begin)\n if (start === undefined) {\n return undefined\n }\n\n const finish = end === undefined ? last?.end : parseTime(end)\n\n return {\n start,\n end: finish,\n agentId: getXmlAttribute(element, 'agent'),\n key: getXmlAttribute(element, 'key'),\n words: read.words,\n ...readInlineAnnotations(element, preserveSpace, language),\n backgrounds: [],\n wordLevel: read.wordLevel,\n preserveSpace,\n language,\n }\n}\n\nconst buildContent = (draft: LineDraft): runtime.LineContent => {\n if (draft.wordLevel) {\n return makeLineContentWords(buildWords(draft))\n }\n\n const text = draft.words\n .map((word) => {\n return word.text\n })\n .join('')\n return makeLineContentText(draft.preserveSpace ? text : text.trim())\n}\n\n/**\n * Builds one background line.\n */\nconst buildBackground = (draft: LineDraft): runtime.LineBackground => {\n return makeLineBackground({\n id: draft.key,\n time: makeTimeRange({ start: draft.start, end: draft.end }),\n agents: draft.agentId === undefined ? [] : [draft.agentId],\n languages: draft.language === undefined ? [] : [draft.language],\n content: buildContent(draft),\n annotation: buildLineAnnotation(draft),\n })\n}\n\n/**\n * Builds one normal line, keeping plain text whole unless the source timed its words.\n */\nconst buildLine = (draft: LineDraft): runtime.Line => {\n return makeLineNormal({\n id: draft.key,\n time: makeTimeRange({ start: draft.start, end: draft.end }),\n agents: draft.agentId === undefined ? [] : [draft.agentId],\n languages: draft.language === undefined ? [] : [draft.language],\n content: buildContent(draft),\n annotation: buildLineAnnotation(draft),\n backgrounds: draft.backgrounds.map(buildBackground),\n })\n}\n\n/**\n * Reads the head's agents, which lines reference by id.\n */\nconst readAgents = (elements: ElementContext[]): runtime.Agent[] => {\n const agents: runtime.Agent[] = []\n for (const { element, preserveSpace, language } of elements) {\n const id = getXmlQualifiedAttribute(element, 'xml:id') ?? getXmlAttribute(element, 'id')\n if (!id) {\n continue\n }\n\n const names = getXmlChildElements(element, 'name')\n .map((name) => {\n return makeText({ text: readText(name, preserveSpace), language: readLanguage(name, language) })\n })\n .filter((name) => {\n return name.text !== ''\n })\n\n const kind = readAgentType(getXmlAttribute(element, 'type'))\n agents.push(\n makeAgent({\n id,\n type: kind.type,\n raw: kind.raw,\n names,\n }),\n )\n }\n\n return agents\n}\n\n/**\n * Reads the head's songwriters as one lyricist credit, since TTML does not split the role further.\n *\n * AMLL wraps these in `iTunesMetadata`, so the whole head is searched rather than its direct children.\n */\nconst readCredits = (elements: ElementContext[], meta: runtime.Meta) => {\n const names = elements\n .map(({ element, preserveSpace, language }) => {\n return makeText({ text: readText(element, preserveSpace), language })\n })\n .filter((name) => {\n return name.text !== ''\n })\n\n if (names.length === 0) {\n return\n }\n\n meta.credits.push(\n makeMetaCredit({\n role: CreditRole.LYRICIST,\n names,\n }),\n )\n}\n\n/**\n * Reads one `amll:meta` entry, keeping an unknown key as written so a round trip loses nothing.\n */\nconst applyAmllMeta = (meta: runtime.Meta, element: XmlElement, language?: string) => {\n const key = getXmlAttribute(element, 'key')\n const value = getXmlAttribute(element, 'value')?.trim()\n if (!key || !value) {\n return\n }\n\n language = readLanguage(element, language)\n switch (key) {\n case 'musicName':\n meta.titles.push(makeText({ text: value, language }))\n return\n case 'artists':\n meta.artists.push(makeText({ text: value, language }))\n return\n case 'album':\n meta.albums.push(makeText({ text: value, language }))\n return\n case 'isrc':\n meta.isrcs.push(value)\n return\n case 'ttmlAuthorGithubLogin':\n meta.authors.push(makeText({ text: value, language }))\n return\n default:\n meta.unknowns.push(makeUnknownEntry({ key, value }))\n }\n}\n\n/**\n * Attaches head translations and transliterations to the lines they name by `itunes:key`.\n *\n * A replacement translation rewrites the line's text, which is how a source swaps one script for another.\n */\nconst attachHeadAnnotations = (metadata: Map<string, ElementContext[]>, lineMap: Map<string, LineDraft>, backgroundMap: Map<string, LineDraft>) => {\n if (lineMap.size === 0) {\n return\n }\n\n const attach = (blocks: ElementContext[], kind: 'translation' | 'roman') => {\n for (const { element: block, preserveSpace, language } of blocks) {\n const type = getXmlQualifiedAttribute(block, 'type') ?? getXmlAttribute(block, 'type')\n\n for (const text of getXmlChildElements(block, 'text')) {\n const key = getXmlAttribute(text, 'for')\n const line = key ? lineMap.get(key) : undefined\n if (!line) {\n continue\n }\n\n const textLanguage = readLanguage(text, language)\n const { main, backgrounds } = splitBackgroundText(text, preserveSpace, textLanguage)\n if (kind === 'translation' && type === 'replacement') {\n if (main) {\n line.words = splitWords(main, textLanguage)\n line.wordLevel = false\n line.preserveSpace = readPreserveSpace(text, preserveSpace)\n line.language = textLanguage\n }\n continue\n }\n\n if (main) {\n const item = { language: textLanguage, text: main }\n if (kind === 'translation') {\n line.translations.push(item)\n } else {\n line.romans.push(item)\n }\n }\n\n for (const background of backgrounds) {\n if (!background.text) {\n continue\n }\n const target = background.key ? backgroundMap.get(background.key) : undefined\n if (!target) {\n continue\n }\n const item = { language: background.language, text: background.text }\n if (kind === 'translation') {\n target.translations.push(item)\n } else {\n target.romans.push(item)\n }\n }\n }\n }\n }\n\n attach(metadata.get('translation') ?? [], 'translation')\n attach(metadata.get('transliteration') ?? [], 'roman')\n}\n\n/**\n * Reads a TTML document into the model.\n *\n * The profile only changes where metadata comes from, so one reader serves both.\n * A document that parses but holds no timed paragraph is `INVALID` rather than an error.\n */\nexport const parseTtml = (input: TtmlParseInput, options: TtmlParseOptions = {}): ParseResult => {\n const content = readTtmlContent(input)\n if (!content) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta: makeMeta() }))\n }\n\n const extra = {\n profile: readTtmlProfile(content),\n }\n\n const document = parseXml(content)\n const root = document ? findXmlElement(document, 'tt') : undefined\n if (!root) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta: makeMeta(), extra }))\n }\n\n const language = readLanguage(root, lowerTag(options.language))\n const body = findElements(root, 'body', false, true, language)[0]\n const metadata = findElements(root, 'metadata', false, true, language)[0]\n const metadataElements =\n metadata === undefined\n ? new Map<string, ElementContext[]>()\n : groupElements(metadata.element, METADATA_NAMES, metadata.preserveSpace, false, metadata.language)\n const meta = makeMeta()\n\n if (language !== undefined) {\n meta.language = language\n }\n\n readCredits(metadataElements.get('songwriter') ?? [], meta)\n for (const { element, language: itemLanguage } of metadataElements.get('meta') ?? []) {\n applyAmllMeta(meta, element, itemLanguage)\n }\n\n const drafts: LineDraft[] = []\n const lineMap = new Map<string, LineDraft>()\n const backgroundMap = new Map<string, LineDraft>()\n\n for (const { element, preserveSpace, language: lineLanguage } of body\n ? findElements(body.element, 'p', body.preserveSpace, true, body.language)\n : []) {\n const draft = readLine(element, preserveSpace, lineLanguage)\n if (!draft) {\n continue\n }\n\n drafts.push(draft)\n if (draft.key) {\n lineMap.set(draft.key, draft)\n }\n for (const background of draft.backgrounds) {\n if (background.key) {\n backgroundMap.set(background.key, background)\n }\n }\n }\n\n attachHeadAnnotations(metadataElements, lineMap, backgroundMap)\n\n if (drafts.length === 0) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta, extra }))\n }\n\n const lines = drafts.map(buildLine)\n const wordLevel = drafts.some((draft) => {\n return (\n draft.wordLevel ||\n draft.backgrounds.some((background) => {\n return background.wordLevel\n })\n )\n })\n\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: LyricStatus.VALID,\n timing: readDeclaredTiming(root) ?? (wordLevel ? Timing.WORD : Timing.LINE),\n meta,\n extra,\n agents: readAgents(metadataElements.get('agent') ?? []),\n languages: deriveLanguageUsages(lines),\n lines,\n }),\n )\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { LyricFormat } from './format'\nimport type { LrcGenerateOptions, LrcGenerateResult, LrcParseInput, LrcParseOptions } from './lrc'\nimport type { ParseResult } from './result'\nimport type { TtmlGenerateOptions, TtmlGenerateResult, TtmlParseOptions } from './ttml'\n\nimport { detectLrc, generateLrc, parseLrc } from './lrc'\nimport { detectTtml, generateTtml, parseTtml } from './ttml'\n\n/**\n * Recognition reads only the original text; the annotation tracks never decide the format.\n *\n * Unrecognized text returns `undefined`.\n */\nexport const detectFormat = (input: unknown): LyricFormat | undefined => {\n if (detectLrc(input)) {\n return 'lrc'\n }\n if (detectTtml(input)) {\n return 'ttml'\n }\n\n return undefined\n}\n\n/**\n * Unrecognized text returns `null`; a recognized format returns its canonical lyric and diagnostics.\n * Annotation tracks travel with the source and are attached by the format's parser.\n */\nexport const parse = (input: unknown, options: LrcParseOptions & TtmlParseOptions = {}): ParseResult | null => {\n const format = detectFormat(input)\n if (!format) {\n return null\n }\n\n switch (format) {\n case 'lrc':\n return parseLrc(input as string | LrcParseInput, options)\n case 'ttml':\n return parseTtml(input as string, options)\n }\n}\n\ninterface GenerateOptions {\n lrc: LrcGenerateOptions\n ttml: TtmlGenerateOptions\n}\n\ninterface GenerateResults {\n lrc: LrcGenerateResult\n ttml: TtmlGenerateResult\n}\n\nconst GENERATORS: {\n [Target in LyricFormat]: (lyric: runtime.Lyric, options: GenerateOptions[Target]) => GenerateResults[Target]\n} = {\n lrc: generateLrc,\n ttml: generateTtml,\n}\n\n/**\n * Generates text in the requested format, which need not match `lyric.format`.\n *\n * The writer map pairs each format's options with its result and requires a writer for every supported format.\n * An unknown target returns `null`.\n */\nexport const generate = <Target extends LyricFormat>(\n lyric: runtime.Lyric,\n target: Target,\n options: GenerateOptions[Target] = {},\n): GenerateResults[Target] | null => {\n if (!Object.hasOwn(GENERATORS, target)) {\n return null\n }\n\n return GENERATORS[target](lyric, options)\n}\n\nexport type { ParseResult } from './result'\n\nexport type { LyricFormat } from './format'\n\nexport * from './lrc'\nexport * from './ttml'\n"],"mappings":"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"}
1
+ {"version":3,"file":"formats.js","names":["LINE_PATTERN","WORD_PATTERN","LINE_PATTERN","readText","CLOCK_PATTERN","LESS_THAN","GREATER_THAN","DOUBLE_QUOTE","AMPERSAND","ROOT_NAME","LINE_PATTERN","readText","resolveOptions","readMeta","readWords","readLine","readLines","WORD_PATTERN","META_PATTERN","SEPARATORS","appendWords","readWords","LINE_PATTERN","readAnnotations","readText","SEPARATORS","appendWords","readLine","WORD_PATTERN","LINE_PATTERN","isObject","readTrack","FORMAT","LINE_PATTERN","WORD_PATTERN","readText","WORD_PATTERN","SEPARATORS","readLine","WORD_PATTERN","readText","FORMAT","readLine"],"sources":["../src/formats/krc/common.ts","../src/formats/krc/detect.ts","../src/formats/result.ts","../src/utils/kana.ts","../src/utils/annotation.ts","../src/utils/encoding.ts","../src/utils/time.ts","../src/utils/xml/utils.ts","../src/utils/xml/reader.ts","../src/utils/xml/writer.ts","../src/formats/qrc/common.ts","../src/formats/qrc/detect.ts","../src/formats/lrc/common.ts","../src/formats/lrc/utils.ts","../src/formats/lrc/detect.ts","../src/formats/lrc/generator.ts","../src/formats/lrc/parser.ts","../src/formats/qrc/parser.ts","../src/formats/krc/parser.ts","../src/formats/kwrc/common.ts","../src/formats/kwrc/detect.ts","../src/formats/kwrc/parser.ts","../src/formats/ttml/common.ts","../src/formats/ttml/detect.ts","../src/formats/ttml/utils.ts","../src/formats/ttml/generator.ts","../src/formats/ttml/parser.ts","../src/formats/yrc/common.ts","../src/formats/yrc/parser.ts","../src/formats/yrc/detect.ts","../src/formats/index.ts"],"sourcesContent":["export const FORMAT = 'krc'\nexport const LINE_PATTERN = /^\\[(\\d+),(\\d+)\\]/\nexport const WORD_PATTERN = /<(\\d+,\\d+,\\d+)>/g\n\nexport interface KrcContent {\n original: string\n}\n\n/**\n * Reads decrypted plaintext without unwrapping XML or accepting auxiliary tracks.\n *\n * @returns Original content, or null when the input cannot be read as plaintext KRC.\n */\nexport const readKrcContent = (input: unknown): KrcContent | null => {\n const source = typeof input === 'string' ? { original: input } : input\n if (!source || typeof source !== 'object' || Array.isArray(source)) {\n return null\n }\n const original = (source as Partial<KrcContent>).original\n if (typeof original !== 'string' || /^\\s*</.test(original)) {\n return null\n }\n return { original }\n}\n","import { LINE_PATTERN, readKrcContent } from './common'\n\n// Kugou wraps its language matrix in a base64 object, so `ey` is the readable head of `{\"`.\nconst LANGUAGE_PATTERN = /\\[language:\\s*ey[A-Za-z0-9+/=]*\\]/\n\n/**\n * Recognizes native KRC from a duration line carrying a complete three-field word tag, or from the Kugou language container.\n *\n * Both signals live in the original plaintext, so an auxiliary track still cannot decide the format.\n *\n * @returns Whether the original plaintext contains a strong KRC syntax signal.\n */\nexport const detectKrc = (input: unknown): boolean => {\n const source = readKrcContent(input)\n if (!source) {\n return false\n }\n\n // Row syntax stays the stronger signal; the container tag also covers Kugou's LRC fallback.\n if (LANGUAGE_PATTERN.test(source.original)) {\n return true\n }\n\n return source.original.split(/\\r\\n?|\\n/).some((raw) => {\n const line = raw.trimStart()\n const header = LINE_PATTERN.exec(line)\n return !!header && /<\\d+,\\d+,\\d+>/.test(line.slice(header[0].length))\n })\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { Diagnostic } from '@gondola-lyrics/model/runtime'\n\nimport { canonicalizeLyric, validateLyric } from '@gondola-lyrics/model/runtime'\n\n/**\n * A parsed lyric in canonical form, with every rule it breaks.\n */\nexport interface ParseResult {\n lyric: runtime.Lyric\n diagnostics: Diagnostic[]\n}\n\n/**\n * Canonicalizes and validates one parser's output, so every format hands back the same shape.\n *\n * Canonicalization runs first because validation reports paths against the canonical tree.\n */\nexport const finalizeLyric = (input: runtime.Lyric): ParseResult => {\n const lyric = canonicalizeLyric(input)\n const diagnostics = validateLyric(lyric)\n\n return { lyric, diagnostics }\n}\n","// Small kana keyed by code point, each listing the base kana it joins into one mora.\n// Loanword pairs such as dyu, fyu, tyu and ye sit alongside the native rows.\nconst KANA_COMBINATIONS = new Map<number, string>([\n [0x3041, 'うくぐつふゔ'],\n [0x3043, 'うくぐすずつてでふゔ'],\n [0x3045, 'とど'],\n [0x3047, 'いうくぐしじちぢつにひびぴみりふゔ'],\n [0x3049, 'うくぐつふゔ'],\n [0x3083, 'きぎしじちぢにひびぴみり'],\n [0x3085, 'きぎしじちぢにひびぴみりてでふゔ'],\n [0x3087, 'きぎしじちぢにひびぴみり'],\n [0x308e, 'くぐ'],\n])\n\nconst readKana = (text: string): string => {\n const kana = text.normalize('NFKC')\n if (kana.length !== 1) {\n return ''\n }\n const code = kana.charCodeAt(0)\n return code >= 0x30a1 && code <= 0x30f6 ? String.fromCharCode(code - 0x60) : kana\n}\n\n/**\n * Reports whether the second kana joins the first into one mora, so a single roman fragment may cover both.\n *\n * Katakana and compatibility forms normalize to hiragana first.\n * Doubled consonants, long-vowel marks and three-kana runs are not combinations.\n */\nexport const combinesKana = (first: string, second: string): boolean => {\n const base = readKana(first)\n const small = readKana(second)\n return !!base && !!small && !!KANA_COMBINATIONS.get(small.charCodeAt(0))?.includes(base)\n}\n","import type { runtime } from '@gondola-lyrics/model'\n\nimport {\n LineType,\n WordType,\n deriveLineRomans,\n getContentText,\n makeLineAnnotation,\n makeLineAnnotationRoman,\n makeLineAnnotationTranslation,\n makeWordAnnotation,\n makeWordAnnotationRoman,\n makeWordAnnotationToken,\n} from '@gondola-lyrics/model/runtime'\n\nimport { lowerBound } from './array'\nimport { combinesKana } from './kana'\nimport { lowerTag } from './language'\n\nexport interface AnnotationSources {\n translations?: runtime.Line[]\n romans?: runtime.Line[]\n}\n\nexport interface AnnotationTiming {\n /**\n * Stored timestamp precision in milliseconds.\n *\n * @default 1\n */\n precision?: number\n /**\n * Allowed timestamp rounding difference in milliseconds.\n *\n * @default 0\n */\n rounding?: 0 | 1\n}\n\nexport interface AnnotationMatchOptions {\n /**\n * Additional drift allowed after exact and optional row order matching, in milliseconds.\n *\n * @default 0\n */\n tolerance?: number\n /**\n * Fills complete tracks by input order when every exact match agrees.\n *\n * @default false\n */\n matchByOrder?: boolean\n /**\n * Keeps empty rows in timing queues so later annotations retain their slots.\n *\n * @default false\n */\n preservePlaceholders?: boolean\n /**\n * Retains source timestamp information without adding fields to model lines.\n */\n getTiming?: (line: runtime.Line) => AnnotationTiming | undefined\n}\n\nexport interface AnnotationAttachOptions extends AnnotationMatchOptions {\n /**\n * Maximum drift of roman token boundaries outside their matched word, in milliseconds.\n * Matched boundaries are adjusted to the word range; the original word is unchanged.\n *\n * @default 0\n */\n wordTolerance?: number\n /**\n * Fills unmatched roman fragments from unique two-kana combination starts or equal-sized gaps between timing anchors.\n * Cross-word checks reuse the word tolerance, and recovered token times are clipped to the original word.\n * Untimed fragments inherit the word range and are placed by order only in single-word gaps or gaps anchored on both sides.\n *\n * @default false\n */\n wordFallback?: boolean\n}\n\ninterface RomanTarget {\n word: runtime.Word\n index: number\n time: runtime.TimeRange\n spaces: number\n tokens: runtime.WordAnnotationToken[]\n}\n\ninterface RomanSource {\n word: runtime.Word\n time?: runtime.TimeRange\n separator: string\n target?: RomanTarget\n}\n\ninterface TimeBucket {\n start: number\n indices: number[]\n mixed: boolean\n}\n\ninterface TimeIndex {\n starts: (number | undefined)[]\n lyricRows: number[]\n targets: Map<number, number[]>\n buckets: Map<number, Map<number, TimeBucket>>\n ordered?: number[]\n}\n\ninterface AnnotationSource {\n line: runtime.Line\n index: number\n text: string\n start?: number\n precision: number\n rounding: 0 | 1\n}\n\ntype SourceGroups = Map<number, Map<number, AnnotationSource[]>>\n\nconst readText = (line: runtime.Line) => {\n return getContentText(line.content).trim()\n}\n\n/**\n * Combines explicit roman tracks with display-only word aggregations, preferring explicit entries for the same language.\n *\n * Derived entries must not be stored back on the line.\n */\nexport const getLineRomans = (line: Pick<runtime.Line, 'content' | 'annotation'>): runtime.LineAnnotationRoman[] => {\n const explicit = line.annotation?.romans ?? []\n const languages = new Set(explicit.map((item) => lowerTag(item.language)))\n const derived = deriveLineRomans(line.content).filter((item) => !languages.has(lowerTag(item.language)))\n return derived.length ? [...explicit, ...derived] : explicit\n}\n\nconst readWordRange = (word: runtime.Word): runtime.TimeRange | undefined => {\n const time = word.time\n if (\n !time ||\n !Number.isSafeInteger(time.start) ||\n time.start < 0 ||\n (time.end !== undefined && (!Number.isSafeInteger(time.end) || time.end < time.start))\n ) {\n return undefined\n }\n return time\n}\n\nconst containsRomanTime = (source: runtime.TimeRange, target: runtime.TimeRange, tolerance: number): boolean => {\n const end = target.end ?? Number.POSITIVE_INFINITY\n if (source.start < target.start - tolerance || (source.end !== undefined && source.end > end + tolerance)) {\n return false\n }\n if (source.end === undefined || source.start === source.end) {\n return target.start === target.end ? source.start <= end + tolerance : source.start < end + tolerance\n }\n return true\n}\n\n// `null` reports a tie between equal-priority words and `undefined` no containing word at all.\n// Both leave the fragment unmatched; only a tie rules out local recovery.\nconst matchRomanTarget = (time: runtime.TimeRange, targets: RomanTarget[], tolerance: number): RomanTarget | null | undefined => {\n let matched: RomanTarget | undefined\n let priority = -1\n for (const target of targets) {\n if (!containsRomanTime(time, target.time, tolerance)) {\n continue\n }\n // A known end is required to prefer an exact range over overlapping words.\n const exact = time.end !== undefined && time.start === target.time.start && time.end === target.time.end\n const point = time.start === time.end && target.time.start === target.time.end\n const rank = exact ? 3 : point ? 2 : containsRomanTime(time, target.time, 0) ? 1 : 0\n if (rank > priority) {\n matched = target\n priority = rank\n } else if (rank === priority) {\n // A later higher-priority candidate can still resolve this tie.\n matched = undefined\n }\n }\n return matched ?? (priority === -1 ? undefined : null)\n}\n\nconst overlapLength = (time: runtime.TimeRange, target: RomanTarget): number => {\n const finish = time.end ?? time.start\n return Math.min(finish, target.time.end ?? Number.POSITIVE_INFINITY) - Math.max(time.start, target.time.start)\n}\n\nconst sharesLanguage = (targets: (RomanTarget | undefined)[]): boolean => {\n const languages = new Set(targets.flatMap((target) => (target ? [lowerTag(target.word.language)] : [])).filter(Boolean))\n return languages.size <= 1\n}\n\nconst isOrderedByTime = (targets: RomanTarget[]): boolean => {\n return targets.every((target, index) => {\n return target.time.start >= (targets[index - 1]?.time.start ?? 0)\n })\n}\n\nconst canExtendToFollowing = (target: RomanTarget, following: RomanTarget): boolean => {\n const first = lowerTag(target.word.language)\n const second = lowerTag(following.word.language)\n return (!first || !second || first === second) && combinesKana(target.word.text, following.word.text)\n}\n\nconst recoverRomanTargets = (\n sources: RomanSource[],\n targets: RomanTarget[],\n tolerance: number,\n rounding: number,\n language: string | undefined,\n): boolean => {\n // Fragment ends drift by the word tolerance, while word adjacency and combination starts only allow timestamp rounding.\n const slack = Math.max(tolerance, rounding)\n const used = new Set(sources.flatMap((source) => (source.target ? [source.target] : [])))\n const reserved = new Set<RomanTarget>()\n const conflict = (target: RomanTarget) => {\n return target.word.annotation?.romans.some((item) => lowerTag(item.language) === language)\n }\n\n for (const [index, source] of sources.entries()) {\n const time = source.time\n if (source.target || !time || time.end === undefined) {\n continue\n }\n // A looser start would let a small kana's own drifted fragment claim the base kana instead.\n const exact = targets.filter((target) => target.time.start === time.start)\n const candidates = exact.length ? exact : targets.filter((target) => Math.abs(target.time.start - time.start) <= rounding)\n if (candidates.length !== 1) {\n continue\n }\n const target = candidates[0]!\n const following = targets[targets.indexOf(target) + 1]\n if (!following || following.index !== target.index + 1 || !canExtendToFollowing(target, following)) {\n continue\n }\n if (used.has(target) || used.has(following) || reserved.has(target) || reserved.has(following)) {\n continue\n }\n if (conflict(target) || following.word.annotation?.romans.length) {\n continue\n }\n const previous = sources.slice(0, index).findLast((item) => item.target)?.target\n const next = sources.slice(index + 1).find((item) => item.target)?.target\n if (target.index <= (previous?.index ?? -1) || following.index >= (next?.index ?? Number.POSITIVE_INFINITY)) {\n continue\n }\n if (target.time.start < (previous?.time.start ?? 0) || following.time.start > (next?.time.start ?? Number.POSITIVE_INFINITY)) {\n continue\n }\n if (!sharesLanguage([previous, target, following, next])) {\n continue\n }\n // The fragment must run from the base kana into its adjacent small kana and touch nothing else.\n if (target.time.end === undefined || following.time.end === undefined || Math.abs(following.time.start - target.time.end) > rounding) {\n continue\n }\n if (time.end <= target.time.end || time.end > following.time.end + slack) {\n continue\n }\n if (targets.some((candidate) => candidate !== target && candidate !== following && overlapLength(time, candidate) > slack)) {\n continue\n }\n source.target = target\n used.add(target)\n reserved.add(following)\n }\n\n for (let start = 0; start < sources.length; start += 1) {\n if (sources[start]!.target) {\n continue\n }\n let end = start + 1\n while (end < sources.length && !sources[end]!.target) {\n end += 1\n }\n const previous = sources[start - 1]?.target\n const next = sources[end]?.target\n const pending = targets.filter((target) => {\n return target.index > (previous?.index ?? -1) && target.index < (next?.index ?? Number.POSITIVE_INFINITY) && !reserved.has(target)\n })\n if (pending.length !== end - start) {\n return false\n }\n // Order alone places an untimed fragment, so its gap must hold one word or be pinned by anchors on both sides.\n const untimed = sources.slice(start, end).some((source) => !source.time)\n if (untimed && pending.length > 1 && (!previous || !next)) {\n return false\n }\n const boundaries = [previous, ...pending, next].filter((target) => target !== undefined)\n if (!sharesLanguage(boundaries) || !isOrderedByTime(boundaries)) {\n return false\n }\n for (const [offset, target] of pending.entries()) {\n const source = sources[start + offset]!\n if (used.has(target) || conflict(target)) {\n return false\n }\n const time = source.time\n // Equal counts cannot override a fragment pointing into another word.\n if (time && (overlapLength(time, target) <= 0 || targets.some((candidate) => candidate !== target && overlapLength(time, candidate) > slack))) {\n return false\n }\n source.target = target\n used.add(target)\n }\n start = end - 1\n }\n return true\n}\n\nconst readRomanLanguage = (source: runtime.Line) => {\n const languages = new Set(source.languages.map(lowerTag).filter(Boolean))\n for (const word of source.content?.words ?? []) {\n const language = word.type === WordType.NORMAL ? lowerTag(word.language) : undefined\n if (language) {\n languages.add(language)\n }\n }\n return {\n language: languages.size === 1 ? languages.values().next().value : lowerTag(source.languages[0]),\n consistent: languages.size <= 1,\n }\n}\n\nconst attachWordRomans = (\n line: runtime.Line,\n source: AnnotationSource,\n tolerance: number,\n language: string | undefined,\n fallback: boolean,\n): runtime.Line | undefined => {\n const content = line.content\n const sourceContent = source.line.content\n if (!content?.words.length || content.text !== undefined || !sourceContent?.words.length || sourceContent.text !== undefined) {\n return undefined\n }\n\n const targets: RomanTarget[] = []\n let spaces = 0\n for (const [index, word] of content.words.entries()) {\n if (word.type === WordType.SPACE) {\n spaces += 1\n continue\n }\n const time = readWordRange(word)\n if (word.type !== WordType.NORMAL || !time) {\n return undefined\n }\n targets.push({ word, index, time, spaces, tokens: [] })\n }\n\n const sources: RomanSource[] = []\n let separator = ''\n for (const word of sourceContent.words) {\n if (word.type === WordType.SPACE) {\n separator += word.text\n continue\n }\n const time = readWordRange(word)\n if (word.type !== WordType.NORMAL || !word.text.trim() || (word.time && !time) || (!time && !fallback)) {\n return undefined\n }\n const target = time ? matchRomanTarget(time, targets, tolerance) : undefined\n if (target === null || (!target && !fallback)) {\n return undefined\n }\n sources.push({ word, time, separator, target })\n separator = ''\n }\n\n const anchors = sources.flatMap((source) => (source.target ? [source.target] : []))\n if (anchors.some((target, index) => target.index < (anchors[index - 1]?.index ?? -1))) {\n return undefined\n }\n const recovered = fallback && sources.some((item) => !item.target)\n if (recovered && !recoverRomanTargets(sources, targets, tolerance, source.rounding, language)) {\n return undefined\n }\n\n let previous: RomanTarget | undefined\n let previousStart = 0\n for (const { word, time, separator, target } of sources) {\n if (!target || target.index < (previous?.index ?? -1) || target.word.annotation?.romans.some((item) => lowerTag(item.language) === language)) {\n return undefined\n }\n const bound = target.time.end ?? Number.POSITIVE_INFINITY\n const start = time ? Math.min(bound, Math.max(target.time.start, time.start)) : target.time.start\n // An open source tail can use its uniquely matched word's end without dividing time by text length.\n const end = time?.end === undefined ? target.time.end : Math.min(bound, Math.max(target.time.start, time.end))\n if (recovered && start < previousStart) {\n return undefined\n }\n previousStart = start\n const token = makeWordAnnotationToken({ text: previous ? word.text : word.text.trimStart(), time: { start, end } })\n if (previous) {\n const last = previous.tokens.at(-1)!\n if (target.spaces > previous.spaces) {\n const space = separator.indexOf(' ')\n if (space === -1) {\n return undefined\n }\n // The model supplies one space even across skipped words; retain the rest in the tokens.\n last.text += separator.slice(0, space)\n token.text = separator.slice(space + 1) + token.text\n } else {\n last.text += separator\n }\n }\n target.tokens.push(token)\n previous = target\n }\n if (!previous) {\n return undefined\n }\n const last = previous.tokens.at(-1)!\n last.text = last.text.trimEnd()\n\n const words = content.words.slice()\n for (const { word, index, tokens } of targets) {\n if (!tokens.length) {\n continue\n }\n const roman = makeWordAnnotationRoman({ language, tokens })\n words[index] = { ...word, annotation: makeWordAnnotation({ ...word.annotation, romans: [...(word.annotation?.romans ?? []), roman] }) }\n }\n const result = { ...line, content: { ...content, words } }\n const derived = deriveLineRomans(result.content).find((item) => lowerTag(item.language) === language)\n // Commit the whole track only when the model can reproduce its text, including separators.\n return derived?.text === source.text ? result : undefined\n}\n\nconst readSources = (lines: runtime.Line[], options: AnnotationMatchOptions): AnnotationSource[] => {\n const result: AnnotationSource[] = []\n const preserve = options.preservePlaceholders\n for (const [index, line] of lines.entries()) {\n const start = line.time?.start\n const text = readText(line)\n const timing = options.getTiming?.(line)\n const precision = timing?.precision\n if ((start !== undefined && (preserve || text)) || (options.matchByOrder && text)) {\n result.push({\n line,\n index,\n text,\n start,\n precision: precision && Number.isFinite(precision) && precision > 0 ? precision : 1,\n rounding: timing?.rounding === 1 ? 1 : 0,\n })\n }\n }\n return result\n}\n\nconst createTimeIndex = (lines: runtime.Line[], options: AnnotationMatchOptions): TimeIndex => {\n const starts: (number | undefined)[] = []\n const lyricRows: number[] = []\n const targets = new Map<number, number[]>()\n for (const [index, line] of lines.entries()) {\n const start = line.time?.start\n const valid = start !== undefined && (!options.preservePlaceholders || Number.isFinite(start))\n starts.push(valid ? start : undefined)\n if (options.matchByOrder && line.type === LineType.NORMAL && readText(line)) {\n lyricRows.push(index)\n }\n if (!valid) {\n continue\n }\n const queue = targets.get(start) ?? []\n queue.push(index)\n targets.set(start, queue)\n }\n return { starts, lyricRows, targets, buckets: new Map() }\n}\n\nconst getTimeBuckets = (index: TimeIndex, precision: number): Map<number, TimeBucket> => {\n const cached = index.buckets.get(precision)\n if (cached) {\n return cached\n }\n const buckets = new Map<number, TimeBucket>()\n for (const [target, start] of index.starts.entries()) {\n if (start === undefined || !Number.isFinite(start)) {\n continue\n }\n const key = Math.floor(start / precision)\n let bucket = buckets.get(key)\n if (!bucket) {\n bucket = { start, indices: [], mixed: false }\n buckets.set(key, bucket)\n }\n bucket.indices.push(target)\n bucket.mixed ||= bucket.start !== start\n }\n index.buckets.set(precision, buckets)\n return buckets\n}\n\nconst matchDuplicates = (start: number, count: number, index: TimeIndex, groups: SourceGroups): AnnotationSource[] | undefined => {\n const result: AnnotationSource[] = []\n const collect = (precision: number, key: number, roundingOnly: boolean): boolean => {\n const queue = groups.get(precision)?.get(key)\n if (!queue) {\n return true\n }\n const bucket = getTimeBuckets(index, precision).get(key)\n if (bucket && (bucket.mixed || bucket.start !== start)) {\n return roundingOnly && queue.every((source) => source.rounding !== 1)\n }\n for (const source of queue) {\n const sourceStart = source.start!\n const rounded = source.rounding === 1\n if (roundingOnly && !rounded) {\n continue\n }\n if (\n rounded &&\n ((sourceStart - 1 !== start && index.targets.has(sourceStart - 1)) || (sourceStart + 1 !== start && index.targets.has(sourceStart + 1)))\n ) {\n return false\n }\n result.push(source)\n if (result.length > count) {\n return false\n }\n }\n return true\n }\n for (const precision of groups.keys()) {\n if (!collect(precision, Math.floor(start / precision), false)) {\n return undefined\n }\n }\n for (const neighbor of [start - 1, start + 1]) {\n if (neighbor !== start && !collect(1, Math.floor(neighbor), true)) {\n return undefined\n }\n }\n return result\n}\n\nconst matchAnnotations = (index: TimeIndex, sources: AnnotationSource[], options: AnnotationMatchOptions): Map<number, AnnotationSource> => {\n const matched = new Map<number, AnnotationSource>()\n if (!sources.length) {\n return matched\n }\n const preserve = options.preservePlaceholders\n const byStart = new Map<number, AnnotationSource[]>()\n for (const source of sources) {\n const start = source.start\n if (start === undefined || (preserve && !Number.isFinite(start))) {\n continue\n }\n const queue = byStart.get(start) ?? []\n queue.push(source)\n byStart.set(start, queue)\n }\n const usedSources = new Set<AnnotationSource>()\n const ambiguous = new Set<AnnotationSource>()\n const assign = (target: number, source: AnnotationSource) => {\n matched.set(target, source)\n usedSources.add(source)\n }\n\n for (const [start, queue] of index.targets) {\n const candidates = byStart.get(start)\n if (!candidates) {\n continue\n }\n if (queue.length > 1) {\n // Preserved placeholders need complete duplicate queues to identify their slots.\n if (!preserve || candidates.length === queue.length) {\n const count = Math.min(queue.length, candidates.length)\n for (let position = 0; position < count; position += 1) {\n assign(queue[position]!, candidates[position]!)\n }\n }\n continue\n }\n let source = candidates[0]!\n for (const candidate of candidates) {\n if (candidate.precision < source.precision) {\n source = candidate\n }\n }\n assign(queue[0]!, source)\n }\n if (usedSources.size === sources.length) {\n return matched\n }\n\n const readable = options.matchByOrder ? sources.filter((source) => source.text) : []\n if (readable.length && readable.length === index.lyricRows.length) {\n // Counts can agree after unrelated omissions, so row order must preserve exact matches.\n const compatible = readable.every((source, position) => {\n const target = index.lyricRows[position]!\n return (!matched.has(target) && !usedSources.has(source)) || matched.get(target) === source\n })\n if (compatible) {\n for (const [position, source] of readable.entries()) {\n if (!usedSources.has(source)) {\n assign(index.lyricRows[position]!, source)\n }\n }\n return matched\n }\n }\n\n if (preserve || options.getTiming) {\n const groups: SourceGroups = new Map()\n for (const source of sources) {\n const start = source.start\n if (usedSources.has(source) || start === undefined || !Number.isFinite(start)) {\n continue\n }\n const precision = source.precision\n let group = groups.get(precision)\n if (!group) {\n group = new Map()\n groups.set(precision, group)\n }\n const key = Math.floor(start / precision)\n const queue = group.get(key) ?? []\n queue.push(source)\n group.set(key, queue)\n }\n\n for (const [start, queue] of index.targets) {\n if (queue.length < 2 || matched.has(queue[0]!)) {\n continue\n }\n const candidates = matchDuplicates(start, queue.length, index, groups)\n if (!candidates || candidates.length !== queue.length) {\n continue\n }\n candidates.sort((first, second) => first.index - second.index)\n for (const [position, source] of candidates.entries()) {\n assign(queue[position]!, source)\n }\n }\n\n for (const precision of [...groups.keys()].sort((first, second) => first - second)) {\n const candidates = getTimeBuckets(index, precision)\n for (const [key, entries] of groups.get(precision)!) {\n const bucket = candidates.get(key)\n if (!bucket) {\n continue\n }\n const sourceQueue = entries.filter((source) => !usedSources.has(source))\n const targetQueue = bucket.indices.filter((target) => !matched.has(target))\n if (!sourceQueue.length || !targetQueue.length) {\n continue\n }\n // Incomplete precision buckets cannot reveal which row is missing.\n if ((precision > 1 || targetQueue.length > 1) && sourceQueue.length !== targetQueue.length) {\n for (const source of sourceQueue) {\n ambiguous.add(source)\n }\n continue\n }\n const count = Math.min(sourceQueue.length, targetQueue.length)\n for (let position = 0; position < count; position += 1) {\n assign(targetQueue[position]!, sourceQueue[position]!)\n }\n }\n }\n\n const rounding = new Map<AnnotationSource, number>()\n const claims = new Map<number, number>()\n for (const source of sources) {\n const start = source.start\n if (source.rounding !== 1 || usedSources.has(source) || ambiguous.has(source) || start === undefined || !Number.isFinite(start)) {\n continue\n }\n let target = -1\n let count = 0\n for (const neighbor of [start - 1, start + 1]) {\n for (const candidate of index.targets.get(neighbor) ?? []) {\n if (matched.has(candidate)) {\n continue\n }\n target = candidate\n count += 1\n claims.set(candidate, (claims.get(candidate) ?? 0) + 1)\n }\n }\n if (count === 1) {\n rounding.set(source, target)\n } else if (count > 1) {\n ambiguous.add(source)\n }\n }\n // Rounding matches need uniqueness on both sides to prevent competing sources from taking a row.\n for (const [source, target] of rounding) {\n if (claims.get(target) === 1) {\n assign(target, source)\n } else {\n ambiguous.add(source)\n }\n }\n }\n\n const tolerance = options.tolerance ?? 0\n if (!Number.isFinite(tolerance) || tolerance <= 0) {\n return matched\n }\n const ordered = (index.ordered ??= [...index.targets.keys()].filter(Number.isFinite).sort((first, second) => first - second))\n const cursors = new Map<number, number>()\n for (const source of sources) {\n const start = source.start\n if (usedSources.has(source) || ambiguous.has(source) || start === undefined || !Number.isFinite(start)) {\n continue\n }\n let target = -1\n let distance = Number.POSITIVE_INFINITY\n const end = start + tolerance\n for (let position = lowerBound(ordered, start - tolerance); position < ordered.length && ordered[position]! <= end; position += 1) {\n const targetStart = ordered[position]!\n const current = Math.abs(targetStart - start)\n if (current > tolerance || current > distance) {\n continue\n }\n const queue = index.targets.get(targetStart)!\n let cursor = cursors.get(targetStart) ?? 0\n while (cursor < queue.length && matched.has(queue[cursor]!)) {\n cursor += 1\n }\n cursors.set(targetStart, cursor)\n const candidate = queue[cursor]\n if (candidate !== undefined && (current < distance || (current === distance && candidate < target))) {\n target = candidate\n distance = current\n }\n }\n if (target !== -1) {\n assign(target, source)\n }\n }\n return matched\n}\n\nconst attachTracks = (\n lines: runtime.Line[],\n sources: AnnotationSources,\n options: AnnotationAttachOptions,\n wordTolerance?: number,\n): runtime.Line[] => {\n if (!lines.length || (!sources.translations?.length && !sources.romans?.length)) {\n return lines\n }\n const index = createTimeIndex(lines, options)\n let result = lines\n // Tracks share timing lookups, but each owns its assignments so both can annotate the same row.\n for (const kind of ['translations', 'romans'] as const) {\n const matches = matchAnnotations(index, readSources(sources[kind] ?? [], options), options)\n for (const [target, source] of matches) {\n const line = result[target]!\n if (line.type === LineType.INSTRUMENTAL || !source.text) {\n continue\n }\n const romanLanguage = kind === 'romans' && wordTolerance !== undefined ? readRomanLanguage(source.line) : undefined\n let annotated =\n romanLanguage?.consistent && wordTolerance !== undefined\n ? attachWordRomans(line, source, wordTolerance, romanLanguage.language, options.wordFallback === true)\n : undefined\n if (!annotated) {\n const language = romanLanguage ? romanLanguage.language : source.line.languages[0]\n const create = kind === 'romans' ? makeLineAnnotationRoman : makeLineAnnotationTranslation\n const annotation = makeLineAnnotation({\n ...line.annotation,\n [kind]: [...(line.annotation?.[kind] ?? []), create({ text: source.text, language })],\n })\n annotated = { ...line, annotation }\n }\n if (result === lines) {\n result = lines.slice()\n }\n result[target] = annotated\n }\n }\n return result\n}\n\n/**\n * Attaches matched tracks as line annotations while preserving existing annotations and unchanged row identities.\n *\n * Reuses the original array when no visible annotations change.\n */\nexport const attachLineAnnotations = (lines: runtime.Line[], sources: AnnotationSources, options: AnnotationMatchOptions = {}): runtime.Line[] => {\n return attachTracks(lines, sources, options)\n}\n\n/**\n * Attaches complete roman tracks to words using timing and optional local recovery, retaining the source line when matching is incomplete.\n * Translations remain line-level, and successful word tracks are not duplicated on the line.\n *\n * Match before final normalization; original text and word timing are preserved.\n */\nexport const attachAnnotations = (lines: runtime.Line[], sources: AnnotationSources, options: AnnotationAttachOptions = {}): runtime.Line[] => {\n const tolerance = Number.isFinite(options.wordTolerance) ? Math.max(0, options.wordTolerance ?? 0) : 0\n return attachTracks(lines, sources, options, tolerance)\n}\n","/**\n * Decodes canonical standard base64 into bytes, identically in browsers and Node.\n * atob decides what is decodable; the round-trip re-encode keeps the result canonical, so slacker forms stay undecoded.\n *\n * @param value Base64 text; whitespace, URL-safe alphabets, and misplaced padding are rejected.\n *\n * @returns The decoded bytes, or null when the input is not canonical base64.\n */\nexport const decodeBase64 = (value: string): Uint8Array | null => {\n if (!value) {\n return null\n }\n try {\n const binary = atob(value)\n if (btoa(binary).replace(/=+$/, '') !== value.replace(/=+$/, '')) {\n return null\n }\n return Uint8Array.from(binary, (character) => character.charCodeAt(0))\n } catch {\n return null\n }\n}\n","// A colon always separates units, so `1:14:514` means hours, minutes, and seconds, not minutes, seconds, and milliseconds.\nconst CLOCK_PATTERN = /^(?:(?:(\\d+):)?(\\d+):)?(\\d+)(?:\\.(\\d+))?$/\n\n// `ms` has to be tried before `m`, so the longer unit wins.\nconst OFFSET_PATTERN = /^(\\d+(?:\\.\\d+)?)(ms|h|m|s)$/iu\n\n/**\n * Reads a clock value, where the fraction is padded or truncated to millisecond precision.\n *\n * `14.514` is fourteen seconds, not fourteen minutes: a colon, not a dot, introduces the larger units.\n */\nconst parseClock = (value: string): number | undefined => {\n // A dot alone is enough to make a number a clock reading, which is what keeps `500` out.\n if (!value.includes(':') && !value.includes('.')) {\n return undefined\n }\n\n const match = CLOCK_PATTERN.exec(value)\n if (!match) {\n return undefined\n }\n\n const hour = Number(match[1] ?? 0)\n const minute = Number(match[2] ?? 0)\n const second = Number(match[3] ?? 0)\n const millisecond = Number((match[4] ?? '').padEnd(3, '0').slice(0, 3))\n\n return ((hour * 60 + minute) * 60 + second) * 1000 + millisecond\n}\n\n/**\n * Reads an offset such as `1.5s`, `2m`, `500ms`, or `1h`.\n */\nconst parseOffset = (value: string): number | undefined => {\n const match = OFFSET_PATTERN.exec(value)\n if (!match) {\n return undefined\n }\n\n const amount = Number(match[1])\n if (!Number.isFinite(amount)) {\n return undefined\n }\n\n switch ((match[2] ?? '').toLowerCase()) {\n case 'h':\n return Math.round(amount * 3600000)\n case 'm':\n return Math.round(amount * 60000)\n case 'ms':\n return Math.round(amount)\n default:\n return Math.round(amount * 1000)\n }\n}\n\n/**\n * Reports whether a value reads as a time.\n */\nexport const isTime = (body: string) => {\n return parseTime(body) !== undefined\n}\n\n/**\n * Reads a time value into milliseconds.\n *\n * A clock reading accepts `ss.fraction`, `mm:ss.fraction`, and `hh:mm:ss.fraction`.\n * An offset accepts a number with an `h`, `m`, `s`, or `ms` suffix.\n * A bare number returns `undefined`, and so does anything else.\n */\nexport const parseTime = (body: string): number | undefined => {\n const trimmed = body.trim()\n if (trimmed === '') {\n return undefined\n }\n\n return parseOffset(trimmed) ?? parseClock(trimmed)\n}\n\n/**\n * Tokens `h`, `m`, `s`, and `S` select hours, minutes, seconds, and fractional seconds.\n * Repeated unit tokens set minimum width; `S` tokens select up to three fractional digits.\n *\n * Omitting hours carries them into minutes; negative or non-finite input writes zero fields.\n */\nexport const formatTime = (time: number, format = 'mm:ss.SSS') => {\n if (!Number.isFinite(time) || time < 0) {\n return format.replace(/h+|m+|s+|S+/g, (run) => '0'.repeat(run.length))\n }\n\n const total = Math.floor(time)\n const totalSeconds = Math.floor(total / 1000)\n const totalMinutes = Math.floor(totalSeconds / 60)\n const millisecond = String(total % 1000).padStart(3, '0')\n\n const fields: Record<string, string> = {\n h: String(Math.floor(totalMinutes / 60)),\n m: String(format.includes('h') ? totalMinutes % 60 : totalMinutes),\n s: String(totalSeconds % 60),\n S: millisecond,\n }\n\n return format.replace(/h+|m+|s+|S+/g, (run) => {\n const field = fields[run[0] as string] as string\n\n if (run[0] === 'S') {\n return field.slice(0, run.length)\n }\n\n return field.padStart(run.length, '0')\n })\n}\n","export const XmlNodeType = {\n element: 1,\n text: 2,\n cdata: 3,\n} as const\n\nexport interface XmlAttribute {\n /** Name exactly as written, namespace prefix included, such as `ttm:agent`. */\n qualifiedName: string\n /** Decoded value, with entity references already resolved. */\n value: string\n /** Namespace prefix such as `ttm`, empty when the name carries none. */\n namespacePrefix: string\n /** Name without its prefix, such as `agent`, which is what format lookups match. */\n localName: string\n}\n\nexport interface XmlElement {\n /** Discriminant that tells this node apart from text and CDATA. */\n nodeType: typeof XmlNodeType.element\n /** Name exactly as written, namespace prefix included, such as `ttm:name`. */\n qualifiedName: string\n /** Namespace prefix such as `ttm`, empty when the name carries none. */\n namespacePrefix: string\n /** Name without its prefix, such as `name`, which is what format lookups match. */\n localName: string\n /** Attributes in document order, which keeps a source's own ordering readable. */\n attributes: XmlAttribute[]\n /** Child nodes in document order, text and CDATA included. */\n children: XmlNode[]\n}\n\nexport interface XmlText {\n /** Discriminant that tells this node apart from elements and CDATA. */\n nodeType: typeof XmlNodeType.text\n /** Decoded text, with entity references already resolved. */\n text: string\n}\n\nexport interface XmlCdata {\n /** Discriminant that tells this node apart from elements and text. */\n nodeType: typeof XmlNodeType.cdata\n /** Raw text between the CDATA markers, which is never decoded. */\n text: string\n}\n\nexport type XmlNode = XmlElement | XmlText | XmlCdata\n\n/**\n * Only prefixed names need their split cached, since an unprefixed one keeps its name as the local part.\n * The cache is bounded, which keeps an adversarial document from growing it without limit.\n */\nconst prefixedNames = new Map<string, { namespacePrefix: string; localName: string }>()\n\n/**\n * Splits a qualified name into its namespace prefix and local name.\n */\nconst splitXmlName = (name: string) => {\n const cached = prefixedNames.get(name)\n if (cached) {\n return cached\n }\n\n const colon = name.indexOf(':')\n const split = colon === -1 ? { namespacePrefix: '', localName: name } : { namespacePrefix: name.slice(0, colon), localName: name.slice(colon + 1) }\n if (split.namespacePrefix && prefixedNames.size < 1024) {\n prefixedNames.set(name, split)\n }\n\n return split\n}\n\n/**\n * Writes the prefix and local part onto a node that already carries the full name.\n */\nexport const applyXmlNameParts = (name: string, target: { namespacePrefix: string; localName: string }) => {\n if (name.indexOf(':') === -1) {\n target.namespacePrefix = ''\n target.localName = name\n return\n }\n\n const split = splitXmlName(name)\n target.namespacePrefix = split.namespacePrefix\n target.localName = split.localName\n}\n\n/**\n * Creates an attribute from its full name and value.\n */\nexport const createXmlAttribute = (qualifiedName: string, value: string): XmlAttribute => {\n const attribute: XmlAttribute = { qualifiedName, value, namespacePrefix: '', localName: qualifiedName }\n applyXmlNameParts(qualifiedName, attribute)\n\n return attribute\n}\n\n/**\n * Creates an element from its full name, with attributes and children in the order given.\n */\nexport const createXmlElement = (\n qualifiedName: string,\n attributes: readonly (readonly [string, string])[] = [],\n children: readonly XmlNode[] = [],\n): XmlElement => {\n const element: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName,\n namespacePrefix: '',\n localName: qualifiedName,\n attributes: attributes.map(([name, value]) => {\n return createXmlAttribute(name, value)\n }),\n children: [...children],\n }\n applyXmlNameParts(qualifiedName, element)\n\n return element\n}\n\n/**\n * Creates a text node, whose value the writer escapes.\n */\nexport const createXmlText = (text: string): XmlText => {\n return { nodeType: XmlNodeType.text, text }\n}\n\n/**\n * Creates a CDATA node, whose value the writer emits verbatim.\n */\nexport const createXmlCdata = (text: string): XmlCdata => {\n return { nodeType: XmlNodeType.cdata, text }\n}\n\n/**\n * Returns the value of one attribute, matched by its local name so the prefix never has to be known.\n */\nexport const getXmlAttribute = (element: XmlElement, localName: string): string | undefined => {\n const attributes = element.attributes\n for (let index = 0; index < attributes.length; index += 1) {\n const attribute = attributes[index]\n if (attribute && attribute.localName === localName) {\n return attribute.value\n }\n }\n\n return undefined\n}\n\n/**\n * Returns the value of one attribute, matched by its full name including the prefix.\n */\nexport const getXmlQualifiedAttribute = (element: XmlElement, qualifiedName: string): string | undefined => {\n const attributes = element.attributes\n for (let index = 0; index < attributes.length; index += 1) {\n const attribute = attributes[index]\n if (attribute && attribute.qualifiedName === qualifiedName) {\n return attribute.value\n }\n }\n\n return undefined\n}\n\n/**\n * Returns the direct element children carrying one local name.\n */\nexport const getXmlChildElements = (element: XmlElement, localName: string): XmlElement[] => {\n const result: XmlElement[] = []\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child && child.nodeType === XmlNodeType.element && child.localName === localName) {\n result.push(child)\n }\n }\n\n return result\n}\n\n/**\n * Reports whether the element has a direct child with one local name.\n */\nexport const hasXmlChildElement = (element: XmlElement, localName: string): boolean => {\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child && child.nodeType === XmlNodeType.element && child.localName === localName) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Returns the first element carrying one local name, the element itself included, in document order.\n */\nexport const findXmlElement = (element: XmlElement, localName: string): XmlElement | undefined => {\n const stack: XmlNode[] = [element]\n\n while (stack.length) {\n const node = stack.pop()\n if (!node || node.nodeType !== XmlNodeType.element) {\n continue\n }\n if (node.localName === localName) {\n return node\n }\n // Pushing in reverse makes the stack pop children in document order.\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child) {\n stack.push(child)\n }\n }\n }\n\n return undefined\n}\n\n/**\n * Returns every element carrying one local name, the element itself included, in document order.\n */\nexport const findXmlElements = (element: XmlElement, localName: string): XmlElement[] => {\n const result: XmlElement[] = []\n const stack: XmlNode[] = [element]\n\n while (stack.length) {\n const node = stack.pop()\n if (!node || node.nodeType !== XmlNodeType.element) {\n continue\n }\n if (node.localName === localName) {\n result.push(node)\n }\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child) {\n stack.push(child)\n }\n }\n }\n\n return result\n}\n\n/**\n * Groups every element carrying one of the given local names, in document order.\n */\nexport const groupXmlElements = (element: XmlElement, localNames: readonly string[]): Map<string, XmlElement[]> => {\n const wanted = new Set(localNames)\n const result = new Map<string, XmlElement[]>()\n const stack: XmlNode[] = [element]\n\n while (stack.length) {\n const node = stack.pop()\n if (!node || node.nodeType !== XmlNodeType.element) {\n continue\n }\n\n if (wanted.has(node.localName)) {\n const group = result.get(node.localName)\n if (!group) {\n result.set(node.localName, [node])\n } else {\n group.push(node)\n }\n }\n\n for (let index = node.children.length - 1; index >= 0; index -= 1) {\n const child = node.children[index]\n if (child) {\n stack.push(child)\n }\n }\n }\n\n return result\n}\n\n/**\n * Joins the text and CDATA content of a node and its descendants, in document order.\n */\nexport const getXmlTextContent = (node: XmlNode): string => {\n if (node.nodeType !== XmlNodeType.element) {\n return node.text\n }\n\n if (!node.children.length) {\n return ''\n }\n const child = node.children[0]\n if (node.children.length === 1 && child && child.nodeType !== XmlNodeType.element) {\n return child.text\n }\n\n const parts: string[] = []\n const stack: XmlNode[] = [node]\n\n while (stack.length) {\n const current = stack.pop()\n if (!current) {\n continue\n }\n if (current.nodeType === XmlNodeType.element) {\n for (let index = current.children.length - 1; index >= 0; index -= 1) {\n const child = current.children[index]\n if (child) {\n stack.push(child)\n }\n }\n continue\n }\n parts.push(current.text)\n }\n\n return parts.join('')\n}\n","import type { XmlAttribute, XmlElement } from './utils'\n\nimport { XmlNodeType, applyXmlNameParts, createXmlAttribute } from './utils'\n\nconst LESS_THAN = 0x3c\nconst GREATER_THAN = 0x3e\nconst SLASH = 0x2f\nconst EQUALS = 0x3d\nconst DOUBLE_QUOTE = 0x22\nconst SINGLE_QUOTE = 0x27\nconst EXCLAMATION = 0x21\nconst QUESTION = 0x3f\nconst AMPERSAND = 0x26\nconst HASH = 0x23\nconst HYPHEN = 0x2d\nconst LOWER_X = 0x78\nconst UPPER_X = 0x58\nconst BYTE_ORDER_MARK = 0xfeff\n\nconst ROOT_NAME = '#document'\n\nconst DECIMAL_DIGITS = /^\\d+$/\nconst HEX_DIGITS = /^[0-9a-fA-F]+$/\n\n/**\n * Resolves one entity reference body, leaving anything unrecognized as written.\n */\nconst decodeReference = (body: string): string => {\n switch (body) {\n case 'lt':\n return '<'\n case 'gt':\n return '>'\n case 'amp':\n return '&'\n case 'quot':\n return '\"'\n case 'apos':\n return \"'\"\n }\n\n if (body.charCodeAt(0) !== HASH) {\n return `&${body};`\n }\n\n const hexadecimal = body.charCodeAt(1) === LOWER_X || body.charCodeAt(1) === UPPER_X\n const digits = hexadecimal ? body.slice(2) : body.slice(1)\n if (!(hexadecimal ? HEX_DIGITS : DECIMAL_DIGITS).test(digits)) {\n return `&${body};`\n }\n\n const code = Number.parseInt(digits, hexadecimal ? 16 : 10)\n // Anything outside the Unicode range cannot be written back, so the reference stays literal.\n if (!Number.isFinite(code) || code > 0x10ffff) {\n return `&${body};`\n }\n\n return String.fromCodePoint(code)\n}\n\n/**\n * Replaces entity references in one run of text, leaving bare ampersands alone.\n */\nconst decodeText = (text: string): string => {\n const parts: string[] = []\n const length = text.length\n let start = 0\n let cursor = 0\n\n while (cursor < length) {\n if (text.charCodeAt(cursor) !== AMPERSAND) {\n cursor += 1\n continue\n }\n\n const end = text.indexOf(';', cursor + 1)\n if (end === -1) {\n cursor += 1\n continue\n }\n\n parts.push(text.slice(start, cursor), decodeReference(text.slice(cursor + 1, end)))\n cursor = end + 1\n start = cursor\n }\n\n if (!parts.length) {\n return text\n }\n\n parts.push(text.slice(start))\n return parts.join('')\n}\n\n/**\n * Reads a document into a tree, or returns `null` when it is not well formed.\n */\nexport const parseXml = (source: string): XmlElement | null => {\n const length = source.length\n let position = length && source.charCodeAt(0) === BYTE_ORDER_MARK ? 1 : 0\n let valid = true\n const stack: XmlElement[] = []\n\n const root: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName: ROOT_NAME,\n namespacePrefix: '',\n localName: ROOT_NAME,\n attributes: [],\n children: [],\n }\n stack.push(root)\n\n /**\n * Appends a text node to the element being read.\n */\n const readTextNode = (end: number) => {\n const start = position\n position = end\n if (start === end) {\n return\n }\n\n const parent = stack[stack.length - 1]\n if (!parent) {\n valid = false\n return\n }\n\n const raw = source.slice(start, end)\n parent.children.push({ nodeType: XmlNodeType.text, text: raw.indexOf('&') === -1 ? raw : decodeText(raw) })\n }\n\n /**\n * Reads one quoted value, starting at `position`, and leaves `position` after the closing quote.\n */\n const readQuotedValue = (): string => {\n const quote = source.charCodeAt(position)\n if (quote !== DOUBLE_QUOTE && quote !== SINGLE_QUOTE) {\n // XML requires a quoted value.\n valid = false\n return ''\n }\n\n position += 1\n const end = source.indexOf(quote === DOUBLE_QUOTE ? '\"' : \"'\", position)\n if (end === -1) {\n valid = false\n return ''\n }\n\n const raw = source.slice(position, end)\n position = end + 1\n return raw.indexOf('&') === -1 ? raw : decodeText(raw)\n }\n\n /**\n * Reads a start tag with its attributes, and opens the element unless it closes itself.\n */\n const readStartTag = () => {\n let cursor = position + 1\n const nameStart = cursor\n\n while (cursor < length) {\n const code = source.charCodeAt(cursor)\n if (code <= 32 || code === GREATER_THAN || code === SLASH || code === EQUALS) {\n break\n }\n cursor += 1\n }\n\n if (cursor === nameStart) {\n valid = false\n return\n }\n\n const qualifiedName = source.slice(nameStart, cursor)\n const attributes: XmlAttribute[] = []\n const element: XmlElement = {\n nodeType: XmlNodeType.element,\n qualifiedName,\n namespacePrefix: '',\n localName: qualifiedName,\n attributes,\n children: [],\n }\n applyXmlNameParts(qualifiedName, element)\n\n let closed = false\n let selfClosing = false\n\n while (cursor < length) {\n let code = source.charCodeAt(cursor)\n while (code <= 32) {\n cursor += 1\n if (cursor >= length) {\n break\n }\n code = source.charCodeAt(cursor)\n }\n if (cursor >= length) {\n break\n }\n\n if (code === GREATER_THAN) {\n cursor += 1\n closed = true\n break\n }\n if (code === SLASH) {\n cursor += 1\n if (cursor < length && source.charCodeAt(cursor) === GREATER_THAN) {\n cursor += 1\n closed = true\n selfClosing = true\n break\n }\n valid = false\n return\n }\n\n const attributeStart = cursor\n do {\n cursor += 1\n if (cursor >= length) {\n break\n }\n code = source.charCodeAt(cursor)\n } while (code > 32 && code !== GREATER_THAN && code !== SLASH && code !== EQUALS)\n if (cursor === attributeStart) {\n valid = false\n return\n }\n\n const attributeName = source.slice(attributeStart, cursor)\n\n while (cursor < length && source.charCodeAt(cursor) <= 32) {\n cursor += 1\n }\n if (cursor >= length || source.charCodeAt(cursor) !== EQUALS) {\n // XML requires every attribute to carry a quoted value.\n valid = false\n return\n }\n cursor += 1\n while (cursor < length && source.charCodeAt(cursor) <= 32) {\n cursor += 1\n }\n\n position = cursor\n const value = readQuotedValue()\n if (!valid) {\n return\n }\n cursor = position\n\n for (let index = 0; index < attributes.length; index += 1) {\n if (attributes[index]?.qualifiedName === attributeName) {\n // A repeated attribute name is not well formed.\n valid = false\n return\n }\n }\n\n attributes.push(createXmlAttribute(attributeName, value))\n }\n\n if (!closed) {\n valid = false\n return\n }\n\n position = cursor\n\n const parent = stack[stack.length - 1]\n if (!parent) {\n valid = false\n return\n }\n parent.children.push(element)\n\n // A self-closing tag is complete as written.\n if (!selfClosing) {\n stack.push(element)\n }\n }\n\n /**\n * Closes the innermost element, which has to be the one the tag names.\n */\n const readEndTag = () => {\n let cursor = position + 2\n const nameStart = cursor\n\n while (cursor < length) {\n const code = source.charCodeAt(cursor)\n if (code <= 32 || code === GREATER_THAN) {\n break\n }\n cursor += 1\n }\n\n const name = source.slice(nameStart, cursor)\n const end = source.indexOf('>', cursor)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 1\n\n // The root never closes, so a close tag here has no open element to match.\n if (stack.length <= 1) {\n valid = false\n return\n }\n\n const top = stack[stack.length - 1]\n if (!top || top.qualifiedName !== name) {\n valid = false\n return\n }\n\n stack.pop()\n }\n\n /**\n * Skips a comment, CDATA section, or any other declaration such as a DOCTYPE.\n */\n const readMarkupDeclaration = () => {\n if (source.charCodeAt(position + 2) === HYPHEN && source.charCodeAt(position + 3) === HYPHEN) {\n const end = source.indexOf('-->', position + 4)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 3\n return\n }\n\n if (source.startsWith('[CDATA[', position + 2)) {\n const start = position + 9\n const end = source.indexOf(']]>', start)\n if (end === -1) {\n valid = false\n return\n }\n\n const parent = stack[stack.length - 1]\n if (!parent) {\n valid = false\n return\n }\n\n parent.children.push({ nodeType: XmlNodeType.cdata, text: source.slice(start, end) })\n position = end + 3\n return\n }\n\n // Any other declaration, a DOCTYPE with an internal subset included, runs to its closing bracket.\n let cursor = position + 2\n let depth = 1\n while (cursor < length && depth > 0) {\n const code = source.charCodeAt(cursor)\n if (code === LESS_THAN) {\n depth += 1\n } else if (code === GREATER_THAN) {\n depth -= 1\n }\n cursor += 1\n }\n\n if (depth > 0) {\n valid = false\n return\n }\n\n position = cursor\n }\n\n /**\n * Skips a processing instruction, which carries nothing the kit reads.\n */\n const readProcessingInstruction = () => {\n const end = source.indexOf('?>', position + 2)\n if (end === -1) {\n valid = false\n return\n }\n position = end + 2\n }\n\n /**\n * Reads content until the end of input or the end tag of the innermost element.\n */\n const readNodes = () => {\n while (position < length) {\n const open = source.indexOf('<', position)\n if (open === -1) {\n readTextNode(length)\n return\n }\n if (open > position) {\n readTextNode(open)\n if (!valid) {\n return\n }\n }\n\n position = open\n const next = source.charCodeAt(open + 1)\n\n if (next === SLASH) {\n readEndTag()\n } else if (next === EXCLAMATION) {\n readMarkupDeclaration()\n } else if (next === QUESTION) {\n readProcessingInstruction()\n } else {\n readStartTag()\n }\n\n if (!valid) {\n return\n }\n }\n }\n\n readNodes()\n\n // An unclosed element leaves more than the root on the stack.\n if (!valid || stack.length !== 1) {\n return null\n }\n\n for (let index = 0; index < root.children.length; index += 1) {\n if (root.children[index]?.nodeType === XmlNodeType.element) {\n return root\n }\n }\n\n return null\n}\n","import type { XmlElement, XmlNode } from './utils'\n\nimport { XmlNodeType } from './utils'\n\nconst AMPERSAND = 0x26\nconst LESS_THAN = 0x3c\nconst GREATER_THAN = 0x3e\nconst DOUBLE_QUOTE = 0x22\nconst TAB = 0x09\nconst LINE_FEED = 0x0a\nconst CARRIAGE_RETURN = 0x0d\n\nconst ROOT_NAME = '#document'\n\nconst REPLACEMENT_CHARACTER = '�'\n\nconst XML_DECLARATION = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'\n\nconst DEFAULT_INDENT = ' '\n\nexport interface XmlWriteOptions {\n /** Emit the XML declaration; defaults to `true`. */\n declaration?: boolean\n /**\n * Indent elements by nesting depth; defaults to `false`.\n *\n * The inserted whitespace becomes text when the output is parsed again.\n * Turn this on only for output no one reads back as lyrics.\n */\n indent?: boolean\n /** One indentation level; defaults to two spaces. */\n indentText?: string\n}\n\n/**\n * Reports whether a code point may appear in an XML 1.0 document.\n */\nconst isAllowedCodePoint = (code: number): boolean => {\n return (\n code === TAB ||\n code === LINE_FEED ||\n code === CARRIAGE_RETURN ||\n (code >= 0x20 && code <= 0xd7ff) ||\n (code >= 0xe000 && code <= 0xfffd) ||\n (code >= 0x10000 && code <= 0x10ffff)\n )\n}\n\n/**\n * Escapes text content, replacing characters XML cannot carry so corruption stays visible.\n */\nconst escapeXmlText = (text: string, chunks: string[]): void => {\n const length = text.length\n let start = 0\n\n for (let index = 0; index < length; index += 1) {\n const code = text.charCodeAt(index)\n let escaped = ''\n\n if (code === AMPERSAND) {\n escaped = '&amp;'\n } else if (code === LESS_THAN) {\n escaped = '&lt;'\n } else if (code === GREATER_THAN) {\n escaped = '&gt;'\n } else if (code === CARRIAGE_RETURN) {\n // A parser folds a bare carriage return into a line feed, so the reference is the only way to keep it.\n escaped = '&#13;'\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const low = index + 1 < length ? text.charCodeAt(index + 1) : 0\n if (low < 0xdc00 || low > 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else {\n // A paired surrogate is one code point, which the loop advances over next.\n index += 1\n continue\n }\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else if (!isAllowedCodePoint(code)) {\n escaped = REPLACEMENT_CHARACTER\n }\n\n if (!escaped) {\n continue\n }\n\n if (start < index) {\n chunks.push(text.slice(start, index))\n }\n chunks.push(escaped)\n start = index + 1\n }\n\n if (start === 0) {\n chunks.push(text)\n return\n }\n if (start < length) {\n chunks.push(text.slice(start))\n }\n}\n\n/**\n * Escapes an attribute value, where whitespace also has to survive normalization.\n */\nconst escapeXmlAttribute = (value: string, chunks: string[]): void => {\n const length = value.length\n let start = 0\n\n for (let index = 0; index < length; index += 1) {\n const code = value.charCodeAt(index)\n let escaped = ''\n\n if (code === AMPERSAND) {\n escaped = '&amp;'\n } else if (code === LESS_THAN) {\n escaped = '&lt;'\n } else if (code === GREATER_THAN) {\n escaped = '&gt;'\n } else if (code === DOUBLE_QUOTE) {\n escaped = '&quot;'\n } else if (code === TAB) {\n escaped = '&#9;'\n } else if (code === LINE_FEED) {\n escaped = '&#10;'\n } else if (code === CARRIAGE_RETURN) {\n escaped = '&#13;'\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const low = index + 1 < length ? value.charCodeAt(index + 1) : 0\n if (low < 0xdc00 || low > 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else {\n index += 1\n continue\n }\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n escaped = REPLACEMENT_CHARACTER\n } else if (!isAllowedCodePoint(code)) {\n escaped = REPLACEMENT_CHARACTER\n }\n\n if (!escaped) {\n continue\n }\n\n if (start < index) {\n chunks.push(value.slice(start, index))\n }\n chunks.push(escaped)\n start = index + 1\n }\n\n if (start === 0) {\n chunks.push(value)\n return\n }\n if (start < length) {\n chunks.push(value.slice(start))\n }\n}\n\n/**\n * Reports whether every child is an element, which is the only case indentation can add whitespace to.\n *\n * An element holding any character data is mixed content, where the inserted whitespace would join the text.\n */\nconst hasOnlyElements = (element: XmlElement): boolean => {\n const children = element.children\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child && child.nodeType !== XmlNodeType.element) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Serializes one node, appending its pieces to `chunks`.\n */\nconst writeXmlNode = (node: XmlNode, chunks: string[], depth: number, indent: string | undefined) => {\n if (node.nodeType === XmlNodeType.text) {\n escapeXmlText(node.text, chunks)\n return\n }\n\n if (node.nodeType === XmlNodeType.cdata) {\n // A `]]>` inside the data would close the section early, so it is split across two sections.\n chunks.push('<![CDATA[', node.text.replaceAll(']]>', ']]]]><![CDATA[>'), ']]>')\n return\n }\n\n if (indent !== undefined && depth > 0) {\n chunks.push('\\n', indent.repeat(depth))\n }\n\n chunks.push('<', node.qualifiedName)\n for (let index = 0; index < node.attributes.length; index += 1) {\n const attribute = node.attributes[index]\n if (!attribute) {\n continue\n }\n chunks.push(' ', attribute.qualifiedName, '=\"')\n escapeXmlAttribute(attribute.value, chunks)\n chunks.push('\"')\n }\n\n const children = node.children\n if (!children.length) {\n chunks.push('/>')\n return\n }\n\n chunks.push('>')\n // Mixed content keeps its children flush, since any whitespace here would join the text.\n const childIndent = indent !== undefined && hasOnlyElements(node) ? indent : undefined\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index]\n if (child) {\n writeXmlNode(child, chunks, depth + 1, childIndent)\n }\n }\n\n if (childIndent !== undefined) {\n chunks.push('\\n', childIndent.repeat(depth))\n }\n chunks.push('</', node.qualifiedName, '>')\n}\n\n/**\n * Writes a tree back to text.\n *\n * A `#document` root, as `parseXml` returns, writes its children; any other root writes itself.\n */\nexport const serializeXml = (root: XmlElement, options: XmlWriteOptions = {}): string => {\n const chunks: string[] = []\n\n if (options.declaration ?? true) {\n chunks.push(XML_DECLARATION)\n }\n\n const indent = options.indent ? (options.indentText ?? DEFAULT_INDENT) : undefined\n if (indent !== undefined) {\n chunks.push('\\n')\n }\n\n if (root.qualifiedName === ROOT_NAME) {\n for (let index = 0; index < root.children.length; index += 1) {\n const child = root.children[index]\n if (child) {\n writeXmlNode(child, chunks, 0, indent)\n }\n }\n } else {\n writeXmlNode(root, chunks, 0, indent)\n }\n\n return chunks.join('')\n}\n","import type { XmlElement } from '@root/utils'\n\nimport { XmlNodeType, getXmlAttribute, parseXml } from '@root/utils'\n\nexport const FORMAT = 'qrc'\nexport const LINE_PATTERN = /^\\[(\\d+),(\\d+)\\]/\n\nexport interface QrcContent {\n original: string\n translations?: string\n romans?: string\n}\n\nconst XML_ROOT_NAMES = ['QrcInfos', 'LyricInfo', 'Lyric_1']\nconst XML_PATTERN = /^\\s*</\nconst TIMED_LINE_PATTERN = /(?:^|[\\r\\n])[^\\S\\r\\n]*\\[\\d+,\\d+\\]/\n\n/**\n * Unwraps supported QRC XML while keeping plaintext literal.\n *\n * XML entities are decoded once by the XML reader.\n *\n * @returns The payload, or null when XML is malformed or has no supported lyric content.\n */\nexport const readText = (source: string): string | null => {\n if (!XML_PATTERN.test(source)) {\n return source\n }\n // Reject unrelated XML before building a document tree.\n if (!XML_ROOT_NAMES.some((name) => source.includes(name))) {\n return null\n }\n\n const document = parseXml(source)\n if (!document) {\n return null\n }\n const root = document.children.find((node): node is XmlElement => node.nodeType === XmlNodeType.element)\n if (!root || !XML_ROOT_NAMES.includes(root.localName)) {\n return null\n }\n\n const pending = [root]\n while (pending.length) {\n const element = pending.pop()!\n const content = getXmlAttribute(element, 'LyricContent')\n if (content !== undefined) {\n return content\n }\n for (let index = element.children.length - 1; index >= 0; index -= 1) {\n const child = element.children[index]!\n if (child.nodeType === XmlNodeType.element) {\n pending.push(child)\n }\n }\n }\n return null\n}\n\n/**\n * Validates the original payload and keeps auxiliary tracks separate so each can use its own format.\n *\n * @returns Normalized input, or null when the original content cannot be read.\n */\nexport const readContent = (input: unknown): QrcContent | null => {\n const value = typeof input === 'string' ? { original: input } : input\n if (!value || typeof value !== 'object') {\n return null\n }\n const source = value as Partial<QrcContent>\n if (typeof source.original !== 'string') {\n return null\n }\n const original = readText(source.original)\n if (original === null) {\n return null\n }\n return {\n original,\n translations: typeof source.translations === 'string' ? source.translations : undefined,\n romans: typeof source.romans === 'string' ? source.romans : undefined,\n }\n}\n\n/**\n * Requires a timed QRC row so metadata alone cannot select the format.\n */\nexport const hasTimedLines = (text: string): boolean => {\n return TIMED_LINE_PATTERN.test(text)\n}\n","import { hasTimedLines, readContent } from './common'\n\n/**\n * Detects QRC from the original track so annotations cannot change format selection.\n *\n * @returns Whether plaintext or a supported XML payload contains a timed QRC row.\n */\nexport const detectQrc = (input: unknown): boolean => {\n const content = readContent(input)\n return !!content && hasTimedLines(content.original)\n}\n","export const FORMAT = 'lrc'\n\nexport interface LrcContent {\n original: string\n translations?: string\n romans?: string\n}\n\n/**\n * Accepts plain lyrics or separate tracks while rejecting an unreadable original payload.\n */\nexport const readLrcContent = (input: unknown): LrcContent | null => {\n if (typeof input === 'string') {\n return { original: input }\n }\n if (!input || typeof input !== 'object') {\n return null\n }\n\n const source = input as Partial<LrcContent>\n if (typeof source.original !== 'string') {\n return null\n }\n\n return {\n original: source.original,\n translations: typeof source.translations === 'string' ? source.translations : undefined,\n romans: typeof source.romans === 'string' ? source.romans : undefined,\n }\n}\n","import { isTime, parseTime } from '@root/utils'\n\nconst WORD_OFFSET_PATTERN = /^(\\d+)(?:,(\\d+))?$/\n\nconst WORD_CLOCK_DURATION_PATTERN = /^([^,]+),(\\d+)$/\n\nconst WORD_TAG_PATTERN = /<([^>]*)>/g\n\nexport const TAG_PATTERN = /\\[([^\\]]*)\\]/g\n\nexport const META_PATTERN = /^([A-Za-z0-9_-]+)\\s*:\\s*([\\s\\S]*)$/\n\n/**\n * Integer tags use `offset[,duration]` in milliseconds relative to the line start.\n * Clock tags are absolute and may append a duration in milliseconds, as in `<00:01.50,500>`.\n * A missing or zero duration leaves the word end unspecified.\n */\nexport const parseWordTime = (body: string, lineStart: number) => {\n if (isTime(body)) {\n const start = parseTime(body)\n\n return start === undefined ? undefined : { start, end: undefined }\n }\n\n const match = WORD_OFFSET_PATTERN.exec(body.trim())\n if (match) {\n const start = lineStart + Number(match[1])\n const duration = Number(match[2] ?? 0)\n\n return { start, end: duration > 0 ? start + duration : undefined }\n }\n\n const clock = WORD_CLOCK_DURATION_PATTERN.exec(body.trim())\n if (clock && isTime(clock[1] ?? '')) {\n const start = parseTime(clock[1] ?? '')\n const duration = Number(clock[2] ?? 0)\n\n return start === undefined ? undefined : { start, end: duration > 0 ? start + duration : undefined }\n }\n\n return undefined\n}\n\n/**\n * A recognized tag precedes its text; a missing tag identifies the literal prefix.\n */\nexport interface WordPiece {\n text: string\n tag?: string\n}\n\n/**\n * Splits recognized tags from their following text while preserving literal content and empty tagged segments.\n *\n * @param pattern A global pattern whose first capture is the tag body.\n * @param accepts Optional format-specific tag validation.\n *\n * @returns Source pieces in their original order, including an untagged prefix when present.\n */\nexport const scanWordTags = (content: string, pattern: RegExp, accepts?: (tag: string) => boolean): WordPiece[] => {\n const pieces: WordPiece[] = []\n let tag: string | undefined\n let cursor = 0\n\n for (const match of content.matchAll(pattern)) {\n const nextTag = match[1] ?? ''\n if (accepts && !accepts(nextTag)) {\n continue\n }\n const before = content.slice(cursor, match.index)\n if (before || tag !== undefined) {\n pieces.push({ text: before, tag })\n }\n tag = nextTag\n cursor = match.index + match[0].length\n }\n\n const tail = content.slice(cursor)\n if (tail || tag !== undefined) {\n pieces.push({ text: tail, tag })\n }\n return pieces\n}\n\n/**\n * Untagged leading text is preserved; empty timed pieces retain explicit segment boundaries.\n * Only recognized time tags split content; other angle-bracket text remains literal.\n */\nexport const splitWordTags = (content: string) => {\n return scanWordTags(content, WORD_TAG_PATTERN, (tag) => !!parseWordTime(tag, 0))\n}\n","import { isTime } from '@root/utils'\n\nimport { readLrcContent } from './common'\nimport { TAG_PATTERN } from './utils'\n\n/**\n * A single readable time tag is enough for recognition; metadata alone is not.\n * This is a format probe, not a validity check, so an input of another shape is simply not LRC.\n */\nexport const detectLrc = (input: unknown) => {\n const content = readLrcContent(input)\n if (!content) {\n return false\n }\n\n const lines = content.original.replace(/\\r\\n?/g, '\\n').split('\\n')\n return lines.some((line) => [...line.matchAll(TAG_PATTERN)].some((match) => isTime(match[1] ?? '')))\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { LrcContent } from './common'\n\nimport { LineType, WordType, getAnnotationItemText, getContentText, resolveAnnotationTokenTime } from '@gondola-lyrics/model/runtime'\n\nimport { formatTime, getLineRomans, lowerTag } from '@root/utils'\n\nexport type LrcGenerateResult = LrcContent\n\nexport interface LrcGenerateOptions {\n /**\n * Word-level timestamp style; defaults to `angle`.\n *\n * `angle` is the enhanced LRC form and round-trips through this parser.\n *\n * `bracket` matches line timestamps, so this parser reads it as new lines rather than words.\n */\n wordTiming?: 'angle' | 'bracket' | 'none'\n /** Clock format for every timestamp; defaults to `mm:ss.SSS`. */\n timeFormat?: string\n /** Emit the metadata header; defaults to `true`. */\n includeMeta?: boolean\n /** Append the word duration to its tag, as in `<00:01.00,500>`. */\n includeWordEnd?: boolean\n /** Emit instrumental lines as a timestamp with no text; defaults to `true`. */\n includeInstrumental?: boolean\n}\n\ntype LrcGenerateOptionsRequired = Required<LrcGenerateOptions>\n\nconst resolveOptions = (options: LrcGenerateOptions = {}): LrcGenerateOptionsRequired => {\n return {\n wordTiming: options.wordTiming ?? 'angle',\n timeFormat: options.timeFormat ?? 'mm:ss.SSS',\n includeMeta: options.includeMeta ?? true,\n includeWordEnd: options.includeWordEnd ?? false,\n includeInstrumental: options.includeInstrumental ?? true,\n }\n}\n\nconst renderTimeTag = (time: number, options: LrcGenerateOptionsRequired) => {\n return `[${formatTime(time, options.timeFormat)}]`\n}\n\nconst renderWordTag = (start: number, end: number | undefined, options: LrcGenerateOptionsRequired) => {\n if (options.wordTiming === 'none') {\n return ''\n }\n\n const open = options.wordTiming === 'bracket' ? '[' : '<'\n const close = options.wordTiming === 'bracket' ? ']' : '>'\n const duration = options.includeWordEnd && end !== undefined ? `,${Math.max(0, end - start)}` : ''\n\n return `${open}${formatTime(start, options.timeFormat)}${duration}${close}`\n}\n\n/**\n * Word-level lines interleave tags with their text; untimed words stay untagged.\n */\nconst renderSyllableText = (line: runtime.Line, options: LrcGenerateOptionsRequired) => {\n const content = line.content\n if (!content?.words.length) {\n return getContentText(content)\n }\n\n return content.words\n .map((word) => {\n if (word.type === WordType.SPACE) {\n return word.text\n }\n const start = word.time?.start\n if (start === undefined) {\n return word.text\n }\n const end = word.time?.end\n // Zero duration is open in LRC, so a closing boundary preserves a known zero range.\n const closing = options.wordTiming === 'angle' && options.includeWordEnd && end === start ? renderWordTag(end, undefined, options) : ''\n return `${renderWordTag(start, end, options)}${word.text}${closing}`\n })\n .join('')\n}\n\nconst renderWordRomans = (line: runtime.Line, language: string | undefined, options: LrcGenerateOptionsRequired): string => {\n const pieces: { text: string; time: runtime.TimeRange | undefined }[] = []\n let spaced = false\n for (const word of line.content?.words ?? []) {\n if (word.type === WordType.SPACE) {\n spaced = true\n continue\n }\n const roman = word.annotation?.romans.find((item) => lowerTag(item.language) === language)\n if (!roman || !getAnnotationItemText(roman)) {\n continue\n }\n let prefix = pieces.length && spaced ? ' ' : ''\n spaced = false\n for (const token of roman.tokens) {\n if (!token.text) {\n continue\n }\n pieces.push({ text: prefix + token.text, time: resolveAnnotationTokenTime(token, roman, word) })\n prefix = ''\n }\n }\n\n return pieces\n .map((piece, index) => {\n const start = piece.time?.start\n if (start === undefined) {\n return piece.text\n }\n const end = piece.time?.end\n const nextStart = pieces[index + 1]?.time?.start\n const needsClosing = end !== undefined && end !== nextStart && (!options.includeWordEnd || end === start)\n // Otherwise an open token could extend across words omitted from this romanization track.\n const closing = needsClosing ? renderWordTag(end, undefined, options) : ''\n return `${renderWordTag(start, end, options)}${piece.text}${closing}`\n })\n .join('')\n}\n\nconst renderMetaRows = (meta: runtime.Meta, options: LrcGenerateOptionsRequired) => {\n const rows: string[] = []\n\n for (const title of meta.titles) {\n rows.push(`[ti:${title.text}]`)\n }\n for (const artist of meta.artists) {\n rows.push(`[ar:${artist.text}]`)\n }\n for (const album of meta.albums) {\n rows.push(`[al:${album.text}]`)\n }\n for (const author of meta.authors) {\n rows.push(`[by:${author.text}]`)\n }\n if (meta.offset) {\n rows.push(`[offset:${meta.offset}]`)\n }\n if (meta.duration !== undefined) {\n rows.push(`[length:${formatTime(meta.duration, options.timeFormat)}]`)\n }\n for (const isrc of meta.isrcs) {\n rows.push(`[isrc:${isrc}]`)\n }\n for (const unknown of meta.unknowns) {\n rows.push(`[${unknown.key}:${unknown.value}]`)\n }\n\n return rows\n}\n\n/**\n * Returns `undefined` for a line the options leave out, so callers can drop it rather than emit a blank row.\n */\nconst renderLineRow = (line: runtime.Line, options: LrcGenerateOptionsRequired, wordLevel: boolean) => {\n if (line.type === LineType.INSTRUMENTAL && !options.includeInstrumental) {\n return undefined\n }\n\n // An untimed lyric still needs a stamp, so it starts at zero like any other line.\n const time = renderTimeTag(line.time?.start ?? 0, options)\n\n // An instrumental line carries no content, so its timestamp alone marks the gap.\n if (line.type === LineType.INSTRUMENTAL) {\n return time\n }\n\n const text = wordLevel && line.content?.words.length ? renderSyllableText(line, options) : getContentText(line.content)\n return `${time}${text}`\n}\n\nconst renderAnnotationRows = (lines: runtime.Line[], options: LrcGenerateOptionsRequired, pick: (line: runtime.Line) => { text: string }[]) => {\n const rows: string[] = []\n\n for (const line of lines) {\n const start = line.time?.start\n if (start === undefined) {\n continue\n }\n for (const item of pick(line)) {\n rows.push(`${renderTimeTag(start, options)}${item.text}`)\n }\n }\n\n return rows\n}\n\nconst renderRomanRows = (lines: runtime.Line[], options: LrcGenerateOptionsRequired): string[] => {\n const rows: string[] = []\n for (const line of lines) {\n const start = line.time?.start\n if (start === undefined) {\n continue\n }\n const explicit = new Set((line.annotation?.romans ?? []).map((item) => lowerTag(item.language)))\n for (const item of getLineRomans(line)) {\n const language = lowerTag(item.language)\n const text = options.wordTiming === 'none' || explicit.has(language) ? item.text : renderWordRomans(line, language, options)\n rows.push(`${renderTimeTag(start, options)}${text}`)\n }\n }\n return rows\n}\n\nconst joinBlocks = (header: string[], body: string[]) => {\n const blocks: string[] = []\n if (header.length) {\n blocks.push(header.join('\\n'))\n }\n if (body.length) {\n blocks.push(body.join('\\n'))\n }\n\n return blocks.join('\\n\\n')\n}\n\n/**\n * Generates the LRC text plus the annotations a single file cannot hold.\n *\n * Word tags appear only for a word-timed lyric when `wordTiming` is not `none`; otherwise every line stays whole.\n * Word romanizations retain token boundaries; explicit line romanizations take precedence for the same language.\n */\nexport const generateLrc = (lyric: runtime.Lyric, options: LrcGenerateOptions = {}): LrcGenerateResult => {\n const resolved = resolveOptions(options)\n const header = resolved.includeMeta && lyric.meta ? renderMetaRows(lyric.meta, resolved) : []\n\n const hasWords = lyric.lines.some((line) => !!line.content?.words.length)\n const wordLevel = hasWords && resolved.wordTiming !== 'none'\n\n const body = lyric.lines\n .map((line) => {\n return renderLineRow(line, resolved, wordLevel)\n })\n .filter((row) => row !== undefined)\n\n const result: LrcGenerateResult = {\n original: joinBlocks(header, body),\n }\n\n const translations = renderAnnotationRows(lyric.lines, resolved, (line) => line.annotation?.translations ?? [])\n if (translations.length) {\n result.translations = joinBlocks(header, translations)\n }\n\n const romans = renderRomanRows(lyric.lines, resolved)\n if (romans.length) {\n result.romans = joinBlocks(header, romans)\n }\n\n return result\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { ParseResult } from '../result'\nimport type { LrcContent } from './common'\nimport type { WordPiece } from './utils'\n\nimport {\n LyricStatus,\n Timing,\n deriveLanguageUsages,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeMeta,\n makeText,\n makeTimeRange,\n makeUnknownEntry,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport { attachAnnotations, isTime, parseTime } from '@root/utils'\n\nimport { finalizeLyric } from '../result'\nimport { FORMAT, readLrcContent } from './common'\nimport { META_PATTERN, TAG_PATTERN, parseWordTime, splitWordTags } from './utils'\n\ninterface TimedLine {\n text: string\n start: number\n tag: string\n row: number\n}\n\nexport interface LrcMetaTag {\n key: string\n value: string\n}\n\nexport interface LrcReadResult {\n lines: runtime.Line[]\n metaTags: LrcMetaTag[]\n}\n\nexport interface LrcLineTiming {\n /**\n * Clock timestamp precision in milliseconds; unit-suffixed timestamps use 1ms.\n */\n precision: number\n}\n\nexport interface LrcReadOptions {\n /**\n * Reports each line with its source precision and zero-based physical row before normalization changes its identity or order.\n */\n onLine?: (line: runtime.Line, timing: LrcLineTiming, row: number) => void\n /**\n * Reports metadata with its zero-based physical row so container fields can preserve their relative order.\n */\n onMeta?: (tag: LrcMetaTag, row: number) => void\n}\n\nexport interface LrcParseOptions {\n /**\n * How far an annotation's timestamp may sit from a line's start, in milliseconds.\n * Defaults to `0`, which requires an exact match.\n */\n annotationTolerance?: number\n /**\n * Maximum roman token drift outside a matched word, in milliseconds; matched boundaries are adjusted to that word.\n * Original word timing is preserved, and incomplete word matches retain the source line romanization.\n *\n * @default 0\n */\n wordAnnotationTolerance?: number\n /**\n * Recovers unmatched roman fragments from unique two-kana combination starts or equal-sized gaps between timing anchors.\n * Only a base kana followed by its small kana combines; doubled consonants and long vowels retain the whole line romanization.\n * Recovered token times are clipped to their original word; untimed fragments inherit its range.\n *\n * @default false\n */\n wordAnnotationFallback?: boolean\n}\n\nexport type LrcParseInput = LrcContent\n\nconst CLOCK_PATTERN = /^(?:\\d+:){0,2}\\d+(?:\\.(\\d+))?$/\n\nconst readLineTiming = (tag: string): LrcLineTiming => {\n const clock = CLOCK_PATTERN.exec(tag.trim())\n return { precision: clock ? 10 ** Math.max(0, 3 - (clock[1]?.length ?? 0)) : 1 }\n}\n\nconst readMeta = (body: string) => {\n const match = META_PATTERN.exec(body)\n if (!match) {\n return undefined\n }\n\n return { key: (match[1] ?? '').toLowerCase(), value: (match[2] ?? '').trim() }\n}\n\nconst readGroup = (tags: string[], text: string, row: number, timed: TimedLine[], meta: LrcMetaTag[], options: LrcReadOptions) => {\n for (const tag of tags) {\n const start = isTime(tag) ? parseTime(tag) : undefined\n if (start !== undefined) {\n timed.push({ text, start, tag, row })\n continue\n }\n\n const pair = readMeta(tag)\n if (pair) {\n meta.push(pair)\n options.onMeta?.(pair, row)\n }\n }\n}\n\n/**\n * Stacked timestamps share the following text, as in `[00:10][00:20]twice`.\n * Text before the first tag is discarded because it has no timing association.\n */\nconst readTimedLines = (text: string, options: LrcReadOptions) => {\n const timed: TimedLine[] = []\n const meta: LrcMetaTag[] = []\n\n for (const [row, raw] of text.replace(/\\r\\n?/g, '\\n').split('\\n').entries()) {\n const line = raw.trim()\n if (!line) {\n continue\n }\n\n const matches = [...line.matchAll(TAG_PATTERN)]\n let group: string[] = []\n\n for (const [index, match] of matches.entries()) {\n const at = match.index + match[0].length\n const next = matches[index + 1]?.index ?? line.length\n const shared = line.slice(at, next)\n\n group.push(match[1] ?? '')\n\n if (!shared.trim()) {\n continue\n }\n\n readGroup(group, shared, row, timed, meta, options)\n group = []\n }\n\n // Trailing timestamps still represent empty timed lines.\n readGroup(group, '', row, timed, meta, options)\n }\n\n return { timed, meta }\n}\n\n/**\n * Whitespace becomes a space word preserving the source run, as in `lo World`.\n * A tag opens a segment; untagged words continue from the previous end so the timeline has no holes.\n * Explicit word ends are kept as written, so duration tags survive unchanged.\n */\nconst readWords = (pieces: WordPiece[], lineStart: number) => {\n const drafts: { text: string; start?: number; end?: number; space?: boolean }[] = []\n const open = new Set<{ start?: number; end?: number }>()\n\n const closeSegment = (boundary: number | undefined) => {\n if (boundary === undefined) {\n return\n }\n for (const draft of open) {\n if (draft.start !== undefined && draft.end === undefined && boundary >= draft.start) {\n draft.end = boundary\n }\n }\n open.clear()\n }\n\n let segmentStart: number | undefined = lineStart\n let cursor: number | undefined = lineStart\n\n for (const piece of pieces) {\n const time = piece.tag ? parseWordTime(piece.tag, lineStart) : undefined\n\n // A tag, even without following text, closes the segment it opens.\n if (time) {\n closeSegment(time.start)\n segmentStart = time.start\n cursor = time.start\n }\n\n if (!piece.text) {\n continue\n }\n\n let applied = false\n\n for (const run of piece.text.split(/(\\s+)/)) {\n if (!run) {\n continue\n }\n\n // A separator keeps its own text and never carries a tag.\n if (!run.trim()) {\n if (drafts.length) {\n drafts.push({ text: run, space: true })\n }\n continue\n }\n\n const tagged = !applied && !!time\n applied = true\n\n const start = tagged ? segmentStart : cursor\n const end = tagged ? time?.end : undefined\n const draft = { text: run, start, end }\n\n drafts.push(draft)\n if (end !== undefined) {\n cursor = end\n } else {\n open.add(draft)\n }\n }\n }\n\n return { drafts, closeSegment }\n}\n\n/**\n * Explicit word ranges can extend past the next line's start, so the inferred end covers both.\n * A trailing open segment uses that end when it is known.\n */\nconst readLine = (text: string, start: number, nextStart: number | undefined) => {\n const trimmed = text.trim()\n let end = nextStart !== undefined && nextStart >= start ? nextStart : undefined\n if (!trimmed) {\n return makeLineInstrumental({ time: makeTimeRange({ start, end }) })\n }\n\n const pieces = splitWordTags(text)\n const wordTimed = pieces.some((piece) => !!piece.tag)\n const { drafts, closeSegment } = wordTimed ? readWords(pieces, start) : { drafts: [], closeSegment: () => {} }\n\n // Without a later line, a final word carrying its own end bounds the line; otherwise it stays open.\n if (end === undefined) {\n const last = [...drafts].reverse().find((draft) => !draft.space && draft.start !== undefined)\n end = last?.end\n }\n\n if (end !== undefined) {\n for (const draft of drafts) {\n if (draft.end !== undefined) {\n end = Math.max(end, draft.end)\n }\n }\n }\n\n // Earlier segments were closed by their next tag, so this only closes the final one.\n closeSegment(end)\n\n const words = drafts.map((draft) => {\n if (draft.space) {\n return makeWordSpace({ text: draft.text })\n }\n // A missing start omits the range instead of inventing a word timestamp.\n const time = draft.start === undefined ? undefined : makeTimeRange({ start: draft.start, end: draft.end })\n return makeWordNormal({ text: draft.text, time })\n })\n\n const time = makeTimeRange({ start, end })\n const content = wordTimed ? makeLineContentWords(words) : makeLineContentText(trimmed)\n\n return makeLineNormal({ time, content })\n}\n\n/**\n * Builds one line per timed row, so an annotation track reuses the original text's reading unchanged.\n * Empty timed rows become instrumental lines bounded by the next timestamp when one is usable.\n */\nconst readLines = (timed: TimedLine[], options: LrcReadOptions): runtime.Line[] => {\n const lines: runtime.Line[] = []\n\n for (const [index, item] of timed.entries()) {\n const next = timed[index + 1]?.start\n // LRC has no line ends; only a nondecreasing next timestamp can supply one.\n const line = readLine(item.text, item.start, next)\n lines.push(line)\n options.onLine?.(line, readLineTiming(item.tag), item.row)\n }\n\n return lines\n}\n\n/**\n * Reads one LRC track in source order and performs no other operation: no metadata mapping, annotation attachment, sorting, or normalization.\n *\n * @param text Original lyrics or one auxiliary track in LRC syntax.\n * @param options Optional observer for source timestamp information.\n *\n * @returns Model lines in input order and metadata tags with lowercase keys and trimmed values.\n */\nexport const readLrc = (text: string, options: LrcReadOptions = {}): LrcReadResult => {\n const { timed, meta } = readTimedLines(text, options)\n return { lines: readLines(timed, options), metaTags: meta }\n}\n\nconst isBareNumber = (value: string) => {\n return /^\\d+$/.test(value.trim())\n}\n\n/**\n * Maps standard lyric metadata while preserving unmapped tags and unparseable durations in unknowns.\n *\n * @param tags Reader tags with lowercase keys and trimmed values.\n *\n * @returns Model metadata without interpreting platform-specific embedded annotations.\n */\nexport const readLrcMetaTags = (tags: LrcMetaTag[]) => {\n const meta = makeMeta()\n\n for (const tag of tags) {\n switch (tag.key) {\n case 'length':\n case 'duration': {\n // Duration tags accept both clock notation and integer milliseconds.\n const duration = parseTime(tag.value) ?? (isBareNumber(tag.value) ? Number(tag.value) : Number.NaN)\n if (Number.isFinite(duration)) {\n meta.duration = Math.trunc(duration)\n } else {\n meta.unknowns.push(makeUnknownEntry({ key: tag.key, value: tag.value }))\n }\n break\n }\n case 'offset':\n meta.offset = Math.trunc(Number(tag.value)) || 0\n break\n case 'ti':\n case 'title':\n meta.titles.push(makeText({ text: tag.value }))\n break\n case 'ar':\n case 'artist':\n meta.artists.push(makeText({ text: tag.value }))\n break\n case 'al':\n case 'album':\n meta.albums.push(makeText({ text: tag.value }))\n break\n case 'by':\n case 'author':\n meta.authors.push(makeText({ text: tag.value }))\n break\n case 'isrc':\n meta.isrcs.push(tag.value)\n break\n default:\n meta.unknowns.push(makeUnknownEntry({ key: tag.key, value: tag.value }))\n break\n }\n }\n\n return meta\n}\n\nconst parseLrcText = (text: string): runtime.Lyric => {\n const { lines, metaTags } = readLrc(text)\n const meta = readLrcMetaTags(metaTags)\n\n if (!lines.length) {\n return makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta })\n }\n\n const wordTimed = lines.some((line) => (line.content?.words.length ?? 0) > 0)\n\n return makeLyric({\n format: FORMAT,\n status: LyricStatus.VALID,\n timing: wordTimed ? Timing.WORD : Timing.LINE,\n meta,\n languages: deriveLanguageUsages(lines),\n lines,\n })\n}\n\n/**\n * Empty timed rows become instrumental lines; source order and missing word times remain for model validation.\n *\n * Annotation tracks are read as lines too and attached by timestamp, and rows that match no line are dropped.\n * Complete roman tracks attach to words by timing and optional local recovery; other tracks retain their source line text.\n *\n * `INVALID` means no readable timed lines; the returned diagnostics carry whatever the canonical tree breaks.\n */\nexport const parseLrc = (input: string | LrcParseInput, options: LrcParseOptions = {}): ParseResult => {\n const source = readLrcContent(input) ?? { original: '' }\n const lyric = parseLrcText(source.original)\n\n if (lyric.status === LyricStatus.INVALID) {\n return finalizeLyric(lyric)\n }\n\n const translations = source.translations ? readLrc(source.translations).lines : []\n const romans = source.romans ? readLrc(source.romans).lines : []\n if (!translations.length && !romans.length) {\n return finalizeLyric(lyric)\n }\n\n const lines = attachAnnotations(\n lyric.lines,\n { translations, romans },\n {\n tolerance: options.annotationTolerance,\n wordTolerance: options.wordAnnotationTolerance,\n wordFallback: options.wordAnnotationFallback,\n },\n )\n\n return finalizeLyric({ ...lyric, lines })\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { AnnotationTiming } from '@root/utils'\nimport type { ParseResult } from '../result'\nimport type { QrcContent } from './common'\n\nimport {\n LineType,\n LyricStatus,\n Timing,\n WordType,\n deriveLanguageUsages,\n getContentText,\n getWordsText,\n isWordLevelLine,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeMeta,\n makeText,\n makeTimeRange,\n makeUnknownEntry,\n makeWordAnnotation,\n makeWordAnnotationRuby,\n makeWordAnnotationToken,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport { attachAnnotations, isTime, mapShared, parseTime } from '@root/utils'\n\nimport { readLrc } from '../lrc'\nimport { finalizeLyric } from '../result'\nimport { FORMAT, LINE_PATTERN, readContent, readText } from './common'\n\nexport interface QrcParseOptions {\n /**\n * Extra tolerance in milliseconds for line annotations left after exact time and row order matching.\n *\n * @default 0\n */\n annotationTolerance?: number\n /**\n * Extra word-boundary tolerance in milliseconds; native QRC tracks allow at least 1ms for rounding.\n * LRC auxiliary tracks use exact word boundaries by default, and incomplete matches retain the whole line romanization.\n *\n * @default 0\n */\n wordAnnotationTolerance?: number\n /**\n * Recovers unmatched roman fragments from unique two-kana combination starts or equal-sized gaps between timing anchors.\n * Only a base kana followed by its small kana combines; doubled consonants and long vowels retain the whole line romanization.\n * Recovered token times are clipped to their original word; untimed fragments inherit its range.\n *\n * @default false\n */\n wordAnnotationFallback?: boolean\n}\n\nexport type QrcParseInput = QrcContent\n\n/**\n * One reading and the length of the source word it covers, in Unicode code points.\n */\nexport interface RubySource {\n length: number\n ruby: runtime.WordAnnotationRuby\n}\n\ninterface RubyWord {\n word: runtime.Word\n length: number\n byOrder: boolean\n}\n\nconst WORD_PATTERN = /\\((\\d+),(\\d+)\\)/g\nconst META_PATTERN = /^([A-Za-z0-9_-]+)\\s*:\\s*([\\s\\S]*)$/\nconst META_TAG_PATTERN = /\\[([^\\]]*)\\]/g\nconst RUBY_PATTERN = /\\((\\d+),(\\d+)\\)|(\\d+)|([^0-9()]+)/gy\nconst RUBY_WORD_PATTERN = /[\\p{Script=Han}\\p{Number}]/u\nconst SEPARATORS = /^\\p{White_Space}+$/u\nconst NATIVE_ANNOTATION_TIMING: AnnotationTiming = { precision: 1, rounding: 1 }\n\n/**\n * Reads coverage markers and optional absolute token times without interpreting timing digits as coverage.\n *\n * @returns Complete ruby sources, or undefined when any source cannot be read.\n */\nexport const readRubyEntries = (value: string): RubySource[] | undefined => {\n const entries: RubySource[] = []\n let length = 0\n let tokens: runtime.WordAnnotationToken[] = []\n let text = ''\n let cursor = 0\n const finish = (): boolean => {\n if (text.trim()) {\n tokens.push(makeWordAnnotationToken({ text }))\n }\n if (!length || !tokens.length) {\n return false\n }\n entries.push({ length, ruby: makeWordAnnotationRuby({ tokens }) })\n tokens = []\n text = ''\n return true\n }\n\n // Consume timing parentheses as one token so their digits cannot become coverage markers.\n for (const match of value.matchAll(RUBY_PATTERN)) {\n cursor = match.index + match[0].length\n if (match[3]) {\n if (length && !finish()) {\n return undefined\n }\n length = Number(match[3])\n if (!Number.isSafeInteger(length) || length <= 0) {\n return undefined\n }\n } else if (match[1]) {\n const start = Number(match[1])\n const end = start + Number(match[2])\n if (!length || !text.trim() || !Number.isSafeInteger(start) || !Number.isSafeInteger(end)) {\n return undefined\n }\n tokens.push(makeWordAnnotationToken({ text, time: { start, end } }))\n text = ''\n } else {\n if (!length) {\n return undefined\n }\n text += match[4]!\n }\n }\n return cursor === value.length && finish() ? entries : undefined\n}\n\n// QRC consumes every kana tag, damaged or unmatched included; only the first valid reading is used.\nconst readRubies = (meta: runtime.Meta): RubySource[] | undefined => {\n let entries: RubySource[] | undefined\n const unknowns: runtime.UnknownEntry[] = []\n for (const entry of meta.unknowns) {\n if (entry.key === 'kana') {\n entries ??= readRubyEntries(entry.value)\n } else {\n unknowns.push(entry)\n }\n }\n meta.unknowns = unknowns\n return entries\n}\n\nconst matchRubies = (words: (RubyWord | undefined)[], sources: RubySource[]): Map<number, number> => {\n const starts = new Map<number, number[]>()\n for (const [index, candidate] of words.entries()) {\n const start = candidate?.word.time?.start\n if (start !== undefined && Number.isSafeInteger(start) && start >= 0) {\n const queue = starts.get(start) ?? []\n queue.push(index)\n starts.set(start, queue)\n }\n }\n const timed = new Set<number>()\n const claims = new Map<number, number[]>()\n for (const [index, source] of sources.entries()) {\n const times = source.ruby.tokens.flatMap((token) => (token.time ? [token.time] : []))\n if (!times.length) {\n continue\n }\n timed.add(index)\n const start = times[0]!.start\n const end = times.at(-1)!.end\n if (start === undefined) {\n continue\n }\n let candidates = (starts.get(start) ?? []).filter((target) => {\n const candidate = words[target]!\n const finish = candidate.word.time?.end\n return (\n candidate.length === source.length &&\n finish !== undefined &&\n Number.isSafeInteger(finish) &&\n times.every((time) => {\n return time.start !== undefined && time.end !== undefined && time.start >= start && time.end >= time.start && time.end <= finish\n })\n )\n })\n if (times.length === source.ruby.tokens.length) {\n const exact = candidates.filter((target) => words[target]!.word.time!.end === end)\n if (exact.length) {\n candidates = exact\n }\n }\n if (candidates.length !== 1) {\n continue\n }\n const target = candidates[0]!\n const queue = claims.get(target) ?? []\n queue.push(index)\n claims.set(target, queue)\n }\n const matched = new Map<number, number>()\n for (const [target, queue] of claims) {\n if (queue.length === 1) {\n matched.set(queue[0]!, target)\n }\n }\n\n const anchors: [number, number][] = [[-1, -1], ...[...matched].sort((first, second) => first[0] - second[0]), [sources.length, words.length]]\n for (let index = 1; index < anchors.length; index += 1) {\n if (anchors[index]![1] <= anchors[index - 1]![1]) {\n return matched\n }\n }\n for (let index = 1; index < anchors.length; index += 1) {\n const [firstSource, firstWord] = anchors[index - 1]!\n const [lastSource, lastWord] = anchors[index]!\n const pending: number[] = []\n let compatible = true\n for (let source = firstSource + 1; source < lastSource; source += 1) {\n if (timed.has(source)) {\n compatible = false\n break\n }\n pending.push(source)\n }\n if (!compatible || !pending.length) {\n continue\n }\n const candidates: number[] = []\n for (let target = firstWord + 1; target < lastWord; target += 1) {\n const candidate = words[target]\n if (!candidate) {\n compatible = false\n break\n }\n if (candidate.byOrder) {\n candidates.push(target)\n }\n }\n // An incomplete interval cannot tell which reading or word is missing.\n if (\n !compatible ||\n candidates.length !== pending.length ||\n pending.some((source, position) => sources[source]!.length !== words[candidates[position]!]!.length)\n ) {\n continue\n }\n for (const [position, source] of pending.entries()) {\n matched.set(source, candidates[position]!)\n }\n }\n return matched\n}\n\n/**\n * Attaches whole-word ruby without changing the source text, segmentation, or timing.\n *\n * @param lines Original timed rows before filtering or sorting.\n * @param sources Readings with source coverage lengths and optional token times.\n *\n * @returns Annotated rows and matched source indices, preserving unchanged nodes.\n */\nexport const attachRubies = (lines: runtime.Line[], sources: RubySource[]): { lines: runtime.Line[]; matched: Set<number> } => {\n if (!sources.length) {\n return { lines, matched: new Set<number>() }\n }\n const words: (RubyWord | undefined)[] = []\n for (const line of lines) {\n if (line.type !== LineType.NORMAL) {\n continue\n }\n if (line.content?.text && RUBY_WORD_PATTERN.test(line.content.text)) {\n // Text-only rows must still block readings from shifting onto later words.\n words.push(undefined)\n continue\n }\n for (const word of line.content?.words ?? []) {\n if (word.type === WordType.NORMAL) {\n words.push({ word, length: [...word.text].length, byOrder: RUBY_WORD_PATTERN.test(word.text) })\n }\n }\n }\n const matched = matchRubies(words, sources)\n if (!matched.size) {\n return { lines, matched: new Set<number>() }\n }\n const annotations = new Map([...matched].map(([source, target]) => [words[target]!.word, sources[source]!.ruby]))\n const annotated = mapShared(lines, (line) => {\n const content = line.content\n if (!content) {\n return line\n }\n const words = mapShared(content.words, (word) => {\n const ruby = annotations.get(word)\n if (!ruby) {\n return word\n }\n return { ...word, annotation: makeWordAnnotation({ ...word.annotation, rubies: [...(word.annotation?.rubies ?? []), ruby] }) }\n })\n return words === content.words ? line : { ...line, content: { ...content, words } }\n })\n return { lines: annotated, matched: new Set(matched.keys()) }\n}\n\nconst readMeta = (body: string, meta: runtime.Meta) => {\n const match = META_PATTERN.exec(body)\n if (!match) {\n return\n }\n const key = match[1]!.toLowerCase()\n const value = match[2]!.trim()\n switch (key) {\n case 'length':\n case 'duration': {\n const duration = parseTime(value) ?? (/^\\d+$/.test(value) ? Number(value) : Number.NaN)\n if (Number.isFinite(duration)) {\n meta.duration = Math.trunc(duration)\n } else {\n meta.unknowns.push(makeUnknownEntry({ key, value }))\n }\n break\n }\n case 'offset':\n meta.offset = Math.trunc(Number(value)) || 0\n break\n case 'ti':\n case 'title':\n meta.titles.push(makeText({ text: value }))\n break\n case 'ar':\n case 'artist':\n meta.artists.push(makeText({ text: value }))\n break\n case 'al':\n case 'album':\n meta.albums.push(makeText({ text: value }))\n break\n case 'by':\n case 'author':\n meta.authors.push(makeText({ text: value }))\n break\n case 'isrc':\n meta.isrcs.push(value)\n break\n default:\n meta.unknowns.push(makeUnknownEntry({ key, value }))\n break\n }\n}\n\nconst readTimeRange = (startText: string, durationText: string): NonNullable<runtime.Word['time']> => {\n const start = Number(startText)\n return makeTimeRange({ start, end: start + Number(durationText) })\n}\n\nconst appendWords = (words: runtime.Word[], text: string, time?: runtime.Word['time']) => {\n for (const fragment of text.split(/(\\p{White_Space}+)/u)) {\n if (!fragment) {\n continue\n }\n if (SEPARATORS.test(fragment)) {\n words.push(makeWordSpace({ text: fragment }))\n } else {\n // QRC gives the fragment one range, so whitespace splitting cannot invent finer timing.\n words.push(makeWordNormal({ text: fragment, time }))\n }\n }\n}\n\nconst readWords = (text: string): runtime.Word[] | undefined => {\n const words: runtime.Word[] = []\n let cursor = 0\n let tagged = false\n for (const match of text.matchAll(WORD_PATTERN)) {\n tagged = true\n appendWords(words, text.slice(cursor, match.index), readTimeRange(match[1]!, match[2]!))\n cursor = match.index + match[0].length\n }\n if (!tagged) {\n return undefined\n }\n appendWords(words, text.slice(cursor))\n return words\n}\n\n/**\n * Kugou writes `//` where it holds no translation, in QRC source rows and in its language payload alike.\n *\n * @returns Whether the trimmed text is that sentinel instead of real content.\n */\nexport const isPlaceholderText = (text: string): boolean => {\n return text.trim() === '//'\n}\n\nconst readLines = (text: string): { lines: runtime.Line[]; meta: runtime.Meta; placeholders: Set<number> } => {\n const lines: runtime.Line[] = []\n const meta = makeMeta()\n const placeholders = new Set<number>()\n for (const raw of text.split(/\\r\\n?|\\n/)) {\n const line = raw.trimStart()\n const match = LINE_PATTERN.exec(line)\n if (match) {\n const time = readTimeRange(match[1]!, match[2]!)\n const text = line.slice(match[0].length)\n const words = readWords(text)\n const contentText = (words ? getWordsText(words) : text).trim()\n const placeholder = isPlaceholderText(contentText)\n if (placeholder) {\n placeholders.add(lines.length)\n }\n if (!contentText || placeholder) {\n lines.push(makeLineInstrumental({ time }))\n } else {\n const content = words ? makeLineContentWords(words) : makeLineContentText(text)\n lines.push(makeLineNormal({ time, content }))\n }\n continue\n }\n if (!line.startsWith('[')) {\n continue\n }\n for (const tag of line.matchAll(META_TAG_PATTERN)) {\n const body = tag[1]!\n if (isTime(body)) {\n continue\n }\n readMeta(body, meta)\n }\n }\n return { lines, meta, placeholders }\n}\n\nconst readAnnotations = (text: string | null | undefined, timings: WeakMap<runtime.Line, AnnotationTiming>): runtime.Line[] => {\n if (!text) {\n return []\n }\n\n const { lines } = readLines(text)\n if (lines.length) {\n for (const line of lines) {\n timings.set(line, NATIVE_ANNOTATION_TIMING)\n }\n return lines\n }\n\n readLrc(text, {\n onLine: (line, timing) => {\n // QRC placeholders must keep both their timing slot and source precision after conversion.\n const annotation = isPlaceholderText(getContentText(line.content)) ? makeLineInstrumental({ time: line.time }) : line\n timings.set(annotation, timing)\n lines.push(annotation)\n },\n })\n\n return lines\n}\n\n/**\n * Parses plaintext or XML QRC, retaining explicit timing, word romanization, and ruby from kana metadata.\n * Original-track kana supplies ruby and is removed from the returned metadata.\n *\n * @param input Original lyrics with optional translation and romanization tracks.\n * @param options Independent line and word tolerances, with optional local roman recovery.\n *\n * @returns Canonical lyrics and source diagnostics; an empty result has INVALID status.\n */\nexport const parseQrc = (input: string | QrcParseInput, options: QrcParseOptions = {}): ParseResult => {\n const source = readContent(input)\n if (!source) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID }))\n }\n\n const parsed = readLines(source.original)\n const meta = parsed.meta\n const rubies = readRubies(meta)\n if (!parsed.lines.length) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta }))\n }\n\n const timings = new WeakMap<runtime.Line, AnnotationTiming>()\n\n const translationText = source.translations && readText(source.translations)\n const translationLines = readAnnotations(translationText, timings)\n\n const romanText = source.romans && readText(source.romans)\n const romanLines = readAnnotations(romanText, timings)\n\n // Each track uses one syntax, so native word boundaries share its timestamp rounding allowance.\n const rounding = romanLines.some((line) => timings.get(line)?.rounding === 1) ? 1 : 0\n const wordTolerance = Number.isFinite(options.wordAnnotationTolerance) ? (options.wordAnnotationTolerance ?? 0) : 0\n\n const annotated = attachAnnotations(\n !rubies ? parsed.lines : attachRubies(parsed.lines, rubies).lines,\n { translations: translationLines, romans: romanLines },\n {\n matchByOrder: true,\n preservePlaceholders: true,\n tolerance: options.annotationTolerance,\n wordTolerance: Math.max(wordTolerance, rounding),\n wordFallback: options.wordAnnotationFallback,\n getTiming: (line) => timings.get(line),\n },\n )\n\n // Removing placeholders before alignment would shift annotations at duplicate timestamps.\n const lines = parsed.placeholders.size ? annotated.filter((_, index) => !parsed.placeholders.has(index)) : annotated\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: lines.length ? LyricStatus.VALID : LyricStatus.INVALID,\n timing: lines.some(isWordLevelLine) ? Timing.WORD : Timing.LINE,\n meta,\n lines,\n languages: deriveLanguageUsages(lines),\n }),\n )\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { LrcMetaTag } from '../lrc'\nimport type { ParseResult } from '../result'\nimport type { KrcContent } from './common'\n\nimport {\n LineType,\n LyricStatus,\n Timing,\n deriveLanguageUsages,\n getWordsText,\n isWordLevelLine,\n makeLineAnnotation,\n makeLineAnnotationRoman,\n makeLineAnnotationTranslation,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeTimeRange,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport { finalizeLyric } from '../result'\nimport { attachRubies, isPlaceholderText, readRubyEntries } from '../qrc'\nimport { decodeBase64 } from '@root/utils'\n\nimport { META_PATTERN, TAG_PATTERN, readLrc, readLrcMetaTags, scanWordTags } from '../lrc'\nimport { FORMAT, LINE_PATTERN, WORD_PATTERN, readKrcContent } from './common'\n\nexport type KrcParseInput = KrcContent\n\nexport interface KrcReadResult {\n lines: runtime.Line[]\n metaTags: LrcMetaTag[]\n}\n\nconst SEPARATORS = /^\\p{White_Space}+$/u\n\nconst appendWords = (words: runtime.Word[], text: string, time?: runtime.TimeRange): void => {\n for (const fragment of text.split(/(\\p{White_Space}+)/u)) {\n if (!fragment) {\n continue\n }\n words.push(SEPARATORS.test(fragment) ? makeWordSpace({ text: fragment }) : makeWordNormal({ text: fragment, time }))\n }\n}\n\nconst readLine = (body: string, start: number, duration: number): runtime.Line => {\n const time = makeTimeRange({ start, end: start + duration })\n const pieces = scanWordTags(body, WORD_PATTERN)\n const tagged = pieces.some((piece) => piece.tag !== undefined)\n if (!tagged) {\n return body.trim() ? makeLineNormal({ time, content: makeLineContentText(body) }) : makeLineInstrumental({ time })\n }\n\n const words: runtime.Word[] = []\n for (const piece of pieces) {\n if (piece.tag === undefined) {\n appendWords(words, piece.text)\n continue\n }\n // Only offset and duration are used; the third field has no verified meaning.\n const [offset, wordDuration] = piece.tag.split(',').map(Number)\n const wordStart = start + offset!\n appendWords(words, piece.text, makeTimeRange({ start: wordStart, end: wordStart + wordDuration! }))\n }\n return getWordsText(words).trim() ? makeLineNormal({ time, content: makeLineContentWords(words) }) : makeLineInstrumental({ time })\n}\n\n/**\n * Reads native KRC rows in source order and performs no other operation: no metadata mapping, annotation attachment, sorting, or normalization.\n *\n * Explicit line and word durations survive unchanged; whitespace splitting never reallocates segment time.\n *\n * @returns Original-order model lines and metadata tags awaiting interpretation.\n */\nexport const readKrc = (text: string): KrcReadResult => {\n const lines: runtime.Line[] = []\n const metaTags: LrcMetaTag[] = []\n for (const raw of text.replace(/^\\uFEFF/, '').split(/\\r\\n?|\\n/)) {\n const line = raw.trimStart()\n const header = LINE_PATTERN.exec(line)\n if (header) {\n lines.push(readLine(line.slice(header[0].length), Number(header[1]), Number(header[2])))\n continue\n }\n if (!line.startsWith('[')) {\n continue\n }\n for (const tag of line.matchAll(TAG_PATTERN)) {\n const meta = META_PATTERN.exec(tag[1]!)\n if (meta) {\n metaTags.push({ key: meta[1]!.toLowerCase(), value: meta[2]!.trim() })\n }\n }\n }\n return { lines, metaTags }\n}\n\n// Only a fully matched kana field is consumed; partial matches keep both the attachment and the source value.\nconst attachKana = (lines: runtime.Line[], meta: runtime.Meta): runtime.Line[] => {\n for (const entry of meta.unknowns) {\n if (entry.key !== 'kana') {\n continue\n }\n const sources = readRubyEntries(entry.value)\n if (!sources) {\n continue\n }\n const attached = attachRubies(lines, sources)\n if (attached.matched.size === sources.length) {\n meta.unknowns = meta.unknowns.filter((item) => item !== entry)\n }\n return attached.lines\n }\n return lines\n}\n\ninterface LanguageTrack {\n type: 0 | 1\n language: number\n lyricContent: string[][]\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> => {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\n// Payload recognition stays strict: plain tags and coincidental base64 must never pass as Kugou data.\nconst readPayload = (value: string): Record<string, unknown> | undefined => {\n const bytes = decodeBase64(value)\n if (!bytes) {\n return undefined\n }\n try {\n const payload: unknown = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n return isObject(payload) && payload.version === 1 && Array.isArray(payload.content) ? payload : undefined\n } catch {\n return undefined\n }\n}\n\nconst readTrack = (value: unknown): LanguageTrack | undefined => {\n if (\n !isObject(value) ||\n (value.type !== 0 && value.type !== 1) ||\n typeof value.language !== 'number' ||\n !Number.isSafeInteger(value.language) ||\n value.language < 0 ||\n !Array.isArray(value.lyricContent) ||\n !value.lyricContent.every((row) => Array.isArray(row) && row.every((cell) => typeof cell === 'string'))\n ) {\n return undefined\n }\n return value as unknown as LanguageTrack\n}\n\nconst attachTrack = (lines: runtime.Line[], track: LanguageTrack): { lines: runtime.Line[]; complete: boolean } => {\n let result = lines\n let complete = true\n for (const [index, cells] of track.lyricContent.entries()) {\n const text = cells.join('')\n // Multiple cells can be displayed losslessly as text, but their boundaries still need the original payload.\n if (cells.length > 1) {\n complete = false\n }\n // A slot Kugou left without a translation carries nothing to attach.\n if (!text.trim() || isPlaceholderText(text)) {\n continue\n }\n const line = result[index]!\n if (line.type === LineType.INSTRUMENTAL) {\n complete = false\n continue\n }\n const kind = track.type === 1 ? 'translations' : 'romans'\n const existing = line.annotation?.[kind] ?? []\n const occupied = existing.find((item) => !item.language)\n if (occupied) {\n complete = complete && occupied.text === text\n continue\n }\n const create = track.type === 1 ? makeLineAnnotationTranslation : makeLineAnnotationRoman\n const annotated = {\n ...line,\n annotation: makeLineAnnotation({ ...line.annotation, [kind]: [...existing, create({ text })] }),\n }\n if (result === lines) {\n result = lines.slice()\n }\n result[index] = annotated\n }\n return { lines: result, complete }\n}\n\n/**\n * Attaches strictly recognized Kugou language tracks by original timed slot before sorting or filtering.\n *\n * Existing annotations take precedence; incomplete or ambiguous payloads remain in metadata.\n * Numeric language codes other than the verified default are retained without inventing BCP 47 tags.\n *\n * @returns Annotated lines, reusing the original array when no visible content changes.\n */\nconst attachKugouLanguage = (lines: runtime.Line[], meta: runtime.Meta): runtime.Line[] => {\n if (!lines.length) {\n return lines\n }\n let result = lines\n const unknowns: runtime.UnknownEntry[] = []\n const selected = new Map<number, string[][]>()\n for (const entry of meta.unknowns) {\n const payload = entry.key === 'language' ? readPayload(entry.value) : undefined\n if (!payload) {\n unknowns.push(entry)\n continue\n }\n let complete = Object.keys(payload).every((key) => key === 'version' || key === 'content' || key === 'contentV2')\n if ('contentV2' in payload && (!Array.isArray(payload.contentV2) || payload.contentV2.length !== 0)) {\n complete = false\n }\n for (const value of payload.content as unknown[]) {\n const track = readTrack(value)\n if (!track || track.language !== 0 || track.lyricContent.length !== lines.length) {\n complete = false\n continue\n }\n if (Object.keys(value as object).some((key) => key !== 'type' && key !== 'language' && key !== 'lyricContent')) {\n complete = false\n }\n const previous = selected.get(track.type)\n if (previous) {\n complete = complete && JSON.stringify(previous) === JSON.stringify(track.lyricContent)\n continue\n }\n selected.set(track.type, track.lyricContent)\n const attached = attachTrack(result, track)\n result = attached.lines\n complete = complete && attached.complete\n }\n if (!complete) {\n unknowns.push(entry)\n }\n }\n meta.unknowns = unknowns\n return result\n}\n\n/**\n * Parses decrypted Kugou lyrics, retaining explicit durations and attaching embedded annotations by source slot.\n *\n * A source carrying no KRC row is read as LRC, so a platform fallback keeps its container annotations.\n * Placeholder slots carry no annotation, so they never keep a credit line in the stream.\n * Kana supplies whole-word ruby; type 0 language tracks retain complete line romanization.\n * Incomplete metadata remains available in unknowns, and source timing violations remain visible in diagnostics.\n *\n * @param input Decrypted plaintext or an object containing its original text.\n *\n * @returns Canonical lyrics and model diagnostics; no readable timed rows yields INVALID status.\n */\nexport const parseKrc = (input: string | KrcParseInput): ParseResult => {\n const source = readKrcContent(input)\n if (!source) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID }))\n }\n\n const native = readKrc(source.original)\n const parsed = native.lines.length ? native : readLrc(source.original)\n\n const meta = readLrcMetaTags(parsed.metaTags)\n const lines = attachKugouLanguage(attachKana(parsed.lines, meta), meta)\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: lines.length ? LyricStatus.VALID : LyricStatus.INVALID,\n timing: lines.some(isWordLevelLine) ? Timing.WORD : Timing.LINE,\n meta,\n lines,\n languages: deriveLanguageUsages(lines),\n }),\n )\n}\n","import type { LrcMetaTag } from '../lrc'\n\nimport { parseTime } from '@root/utils'\n\nimport { META_PATTERN } from '../lrc'\n\nexport const FORMAT = 'kwrc'\nexport const LINE_PATTERN = /^\\[([^\\]]*)\\]/\nexport const WORD_PATTERN = /<(-?\\d+,-?\\d+(?:,-?\\d+)?)>/g\nexport const VISIBLE_TEXT = /[^\\p{White_Space}]/u\n\nexport interface KwrcContent {\n original: string\n}\n\nexport interface SourceLine {\n row: number\n start: number\n text: string\n clock: boolean\n}\n\ninterface SourceTrack {\n lines: SourceLine[]\n metaTags: LrcMetaTag[]\n}\n\nexport interface WordScales {\n start: number\n duration: number\n}\n\n/**\n * Removes only complete encoded tags so literal angle-bracket text survives.\n */\nexport const readText = (text: string): string => {\n return text.replace(WORD_PATTERN, '')\n}\n\n/**\n * Accepts decoded plaintext without unwrapping XML or auxiliary tracks.\n */\nexport const readKwrcContent = (input: unknown): KwrcContent | null => {\n const source = typeof input === 'string' ? { original: input } : input\n if (!source || typeof source !== 'object' || Array.isArray(source)) {\n return null\n }\n\n const original = (source as Partial<KwrcContent>).original\n if (typeof original !== 'string' || /^\\s*</.test(original)) {\n return null\n }\n\n return { original }\n}\n\n/**\n * Retains source slots and literal bodies before word timing or bilingual boundaries are interpreted.\n */\nexport const readKwrcSource = (text: string): SourceTrack => {\n const lines: SourceLine[] = []\n const metaTags: LrcMetaTag[] = []\n\n const rows = text.replace(/^\\uFEFF/, '').split(/\\r\\n?|\\n/)\n for (const [row, raw] of rows.entries()) {\n const times: { start: number; clock: boolean }[] = []\n\n let body = raw.trimStart()\n let header: RegExpExecArray | null\n\n while ((header = LINE_PATTERN.exec(body))) {\n const tag = header[1]!.trim()\n const start = parseTime(tag)\n if (start !== undefined) {\n times.push({ start, clock: /^[\\d:.]+$/.test(tag) })\n } else {\n const meta = META_PATTERN.exec(tag)\n if (!meta || times.length) {\n break\n }\n metaTags.push({ key: meta[1]!.toLowerCase(), value: meta[2]!.trim() })\n }\n\n body = body.slice(header[0].length)\n if (!times.length) {\n body = body.trimStart()\n }\n }\n\n for (const time of times) {\n lines.push({ row, ...time, text: body })\n }\n }\n\n return { lines, metaTags }\n}\n\n/**\n * Requires complete octal values and agreement across all parameter tags, without selecting a default scale.\n */\nexport const readKwrcScales = (tags: LrcMetaTag[]): WordScales | undefined => {\n let value: number | undefined\n for (const tag of tags) {\n if (tag.key !== 'kuwo') {\n continue\n }\n if (!/^[0-7]+$/.test(tag.value)) {\n return undefined\n }\n const next = Number.parseInt(tag.value, 8)\n if (!Number.isSafeInteger(next) || (value !== undefined && value !== next)) {\n return undefined\n }\n value = next\n }\n\n if (value === undefined) {\n return undefined\n }\n\n const start = Math.trunc(value / 10)\n const duration = value % 10\n return start > 0 && duration > 0 ? { start, duration } : undefined\n}\n\n/**\n * A repeated timestamp opens the previous original's translation slot before the next original.\n * The entire sequence must agree so one missing slot cannot shift all later translations.\n */\nexport const hasKwrcTranslations = ({ lines, metaTags }: SourceTrack): boolean => {\n const markers = metaTags.filter((tag) => tag.key === 'ml')\n if (!markers.length || markers.some((tag) => tag.value !== '1.0') || lines.length < 3 || lines.length % 2 !== 1) {\n return false\n }\n\n const has = lines.every((line, index) => {\n return line.clock && Number.isSafeInteger(line.start) && line.row !== lines[index - 1]?.row\n })\n if (!has) {\n return false\n }\n\n let previous = lines[0]!\n for (let index = 1; index < lines.length; index += 2) {\n const translation = lines[index]!\n const original = lines[index + 1]!\n if (translation.start <= previous.start || translation.start !== original.start) {\n return false\n }\n // An instrumental slot cannot carry a nonempty translation in the output model.\n if (!VISIBLE_TEXT.test(readText(previous.text)) && VISIBLE_TEXT.test(readText(translation.text))) {\n return false\n }\n previous = original\n }\n\n return true\n}\n","import { WORD_PATTERN, hasKwrcTranslations, readKwrcContent, readKwrcScales, readKwrcSource } from './common'\n\n/**\n * Recognizes octal parameters with encoded clock rows, or a complete marked bilingual sequence.\n */\nexport const detectKwrc = (input: unknown): boolean => {\n const source = readKwrcContent(input)\n if (!source) {\n return false\n }\n\n const track = readKwrcSource(source.original)\n if (readKwrcScales(track.metaTags)) {\n for (const line of track.lines) {\n if (line.clock && Number.isSafeInteger(line.start) && line.text.search(WORD_PATTERN) !== -1) {\n return true\n }\n }\n }\n\n return hasKwrcTranslations(track)\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { ParseResult } from '../result'\nimport type { KwrcContent, SourceLine, WordScales } from './common'\n\nimport {\n LineType,\n LyricStatus,\n Timing,\n deriveLanguageUsages,\n isWordLevelLine,\n makeLineAnnotation,\n makeLineAnnotationTranslation,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeTimeRange,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport { readLrc, readLrcMetaTags, scanWordTags, splitWordTags } from '../lrc'\nimport { finalizeLyric } from '../result'\nimport { FORMAT, VISIBLE_TEXT, WORD_PATTERN, hasKwrcTranslations, readKwrcContent, readKwrcScales, readKwrcSource, readText } from './common'\n\nexport type { KwrcContent as KwrcParseInput } from './common'\n\nconst SEPARATORS = /^\\p{White_Space}+$/u\n\nconst readWordTime = (tag: string, lineStart: number, scales: WordScales): runtime.TimeRange | undefined => {\n const values = tag.split(',').map(Number)\n if (!Number.isSafeInteger(lineStart) || !values.every(Number.isSafeInteger)) {\n return undefined\n }\n\n // The optional third field has no verified timing meaning.\n const [x, y] = values as [number, number]\n const sum = x + y\n const difference = x - y\n if (!Number.isSafeInteger(sum) || !Number.isSafeInteger(difference) || sum % (2 * scales.start) !== 0 || difference % (2 * scales.duration) !== 0) {\n return undefined\n }\n\n const relativeStart = Math.abs(sum / (2 * scales.start))\n const duration = Math.abs(difference / (2 * scales.duration))\n const start = lineStart + relativeStart\n const end = start + duration\n if (![relativeStart, duration, start, end].every(Number.isSafeInteger)) {\n return undefined\n }\n\n return makeTimeRange({ start, end })\n}\n\nconst readLine = ({ text, start }: SourceLine, nextStart: number | undefined, scales: WordScales | undefined): runtime.Line => {\n const boundary = nextStart !== undefined && nextStart >= start ? nextStart : undefined\n let end = boundary\n const pieces = scanWordTags(text, WORD_PATTERN)\n if (!pieces.some((piece) => piece.tag !== undefined)) {\n if (Number.isSafeInteger(start) && splitWordTags(text).some((piece) => piece.tag !== undefined)) {\n const suffix = end === undefined ? '' : `\\n[${end}ms]`\n return readLrc(`[${start}ms]${text}${suffix}`).lines[0]!\n }\n const time = makeTimeRange({ start, end })\n return VISIBLE_TEXT.test(text) ? makeLineNormal({ time, content: makeLineContentText(text) }) : makeLineInstrumental({ time })\n }\n\n const words: runtime.Word[] = []\n for (const piece of pieces) {\n const time = piece.tag !== undefined && scales ? readWordTime(piece.tag, start, scales) : undefined\n if (piece.tag !== undefined && !time) {\n // Retaining the whole encoded row avoids presenting partially decoded or rounded timing as reliable.\n return makeLineNormal({\n time: makeTimeRange({ start, end: boundary }),\n content: makeLineContentText(text),\n })\n }\n if (time?.end !== undefined) {\n end = Math.max(end ?? start, time.end)\n }\n for (const fragment of piece.text.split(/(\\p{White_Space}+)/u)) {\n if (fragment) {\n words.push(SEPARATORS.test(fragment) ? makeWordSpace({ text: fragment }) : makeWordNormal({ text: fragment, time }))\n }\n }\n }\n\n const time = makeTimeRange({ start, end })\n return VISIBLE_TEXT.test(readText(text)) ? makeLineNormal({ time, content: makeLineContentWords(words) }) : makeLineInstrumental({ time })\n}\n\n/**\n * Parses decoded KWRC with explicit word durations and structurally verified embedded translations.\n *\n * Missing or conflicting parameters and unsafe word calculations retain the complete row as line-level text.\n * Plain LRC remains readable; offset is stored as metadata without changing source timestamps.\n *\n * @param input Decoded plaintext or an object containing its original text.\n *\n * @returns Canonical lyrics and model diagnostics; no readable timed rows yields INVALID status.\n */\nexport const parseKwrc = (input: string | KwrcContent): ParseResult => {\n const source = readKwrcContent(input)\n if (!source) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID }))\n }\n\n const track = readKwrcSource(source.original)\n const bilingual = hasKwrcTranslations(track)\n const encoded = track.lines.some((line) => !!line.text.match(WORD_PATTERN))\n\n let lines: runtime.Line[]\n let tags = track.metaTags\n if (!encoded && !bilingual) {\n const fallback = readLrc(source.original)\n lines = fallback.lines\n tags = fallback.metaTags\n } else {\n const scales = readKwrcScales(tags)\n const originals = bilingual ? track.lines.filter((_, index) => index % 2 === 0) : track.lines\n lines = originals.map((original, index) => {\n const line = readLine(original, originals[index + 1]?.start, scales)\n const translation = bilingual ? readText(track.lines[index * 2 + 1]?.text ?? '') : ''\n if (VISIBLE_TEXT.test(translation)) {\n line.annotation = makeLineAnnotation({ translations: [makeLineAnnotationTranslation({ text: translation })] })\n }\n return line\n })\n }\n\n // A final empty slot already supplied the preceding line's boundary.\n const last = lines.at(-1)\n if (last?.type === LineType.INSTRUMENTAL && (last.time?.end === undefined || last.time.end === last.time.start)) {\n lines.pop()\n }\n\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: lines.length ? LyricStatus.VALID : LyricStatus.INVALID,\n timing: lines.some(isWordLevelLine) ? Timing.WORD : Timing.LINE,\n meta: readLrcMetaTags(tags),\n lines,\n languages: deriveLanguageUsages(lines),\n }),\n )\n}\n","export const FORMAT = 'ttml'\n\nexport type TtmlProfile = 'amll' | 'itunes'\n\nexport const AMLL_HINT_PATTERN = /xmlns:amll|amll:meta/iu\n\nexport const ITUNES_HINT_PATTERN = /xmlns:itunes|iTunesMetadata|itunes:timing=/iu\n\n/**\n * Accepts the text input shared by TTML detection and parsing.\n */\nexport const readTtmlContent = (input: unknown): string | null => {\n if (typeof input !== 'string') {\n return null\n }\n return input\n}\n","import { XmlNodeType, parseXml } from '@root/utils'\n\nimport { AMLL_HINT_PATTERN, ITUNES_HINT_PATTERN, readTtmlContent } from './common'\n\n/**\n * Recognition needs a profile hint, since plain TTML says nothing about which profile wrote it.\n *\n * A bare `tt` root also counts, which is what a hand-written document has.\n * This is a format probe, not a validity check, so an input of another shape is simply not TTML.\n */\nexport const detectTtml = (input: unknown) => {\n const content = readTtmlContent(input)\n if (!content) {\n return false\n }\n\n if (AMLL_HINT_PATTERN.test(content) || ITUNES_HINT_PATTERN.test(content)) {\n return true\n }\n\n // A document without a hint still counts when its root is a tt element.\n const root = parseXml(content)\n if (!root) {\n return false\n }\n\n for (const child of root.children) {\n if (child.nodeType === XmlNodeType.element && child.localName === 'tt') {\n return true\n }\n }\n\n return false\n}\n","export const ROLE_BACKGROUND = 'x-bg'\nexport const ROLE_TRANSLATION = 'x-translation'\nexport const ROLE_ROMAN = 'x-roman'\n\nexport const RUBY_CONTAINER = 'container'\nexport const RUBY_BASE = 'base'\nexport const RUBY_TEXT_CONTAINER = 'textContainer'\nexport const RUBY_TEXT = 'text'\n\nexport const TIMING_WORD = 'Word'\nexport const TIMING_LINE = 'Line'\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { XmlElement, XmlNode } from '@root/utils'\nimport type { TtmlProfile } from './common'\n\nimport {\n AgentType,\n CreditRole,\n LineType,\n Timing,\n WordType,\n removeOffset,\n resolveAnnotationItemTime,\n resolveAnnotationTokenTime,\n} from '@gondola-lyrics/model/runtime'\n\nimport { createXmlElement, createXmlText, getLineRomans, serializeXml } from '@root/utils'\n\nimport { FORMAT } from './common'\nimport {\n ROLE_BACKGROUND,\n ROLE_ROMAN,\n ROLE_TRANSLATION,\n RUBY_BASE,\n RUBY_CONTAINER,\n RUBY_TEXT,\n RUBY_TEXT_CONTAINER,\n TIMING_LINE,\n TIMING_WORD,\n} from './utils'\n\nexport type TtmlGenerateResult = string\n\nexport interface TtmlGenerateOptions {\n /**\n * Defaults to the source TTML profile, or `amll` when the lyric came from another format.\n */\n profile?: TtmlProfile\n /**\n * Indent document structure; defaults to `false`.\n * Lyric content stays flush to keep formatting whitespace out of the words.\n */\n indent?: boolean\n /**\n * Emit song metadata; defaults to `true`.\n * Agents and annotation tracks are retained because the body references them.\n */\n includeMeta?: boolean\n}\n\ntype SungLine = runtime.Line | runtime.LineBackground\n\ntype Attributes = [string, string][]\n\ntype AnnotationKind = 'translations' | 'romans'\n\ntype AnnotationTracks = Map<string | undefined, Map<runtime.Line, XmlNode[]>>\n\ntype ResolvedTtmlGenerateOptions = Required<TtmlGenerateOptions>\n\ninterface RenderContext {\n profile: TtmlProfile\n offset: number\n keys: Map<SungLine, string>\n agents: Map<string, string>\n}\n\nconst NAMESPACE_TTML = 'http://www.w3.org/ns/ttml'\nconst NAMESPACE_TTML_METADATA = 'http://www.w3.org/ns/ttml#metadata'\nconst NAMESPACE_TTML_STYLING = 'http://www.w3.org/ns/ttml#styling'\nconst NAMESPACE_ITUNES = 'http://itunes.apple.com/lyric-ttml-extensions'\nconst NAMESPACE_ITUNES_METADATA = 'http://music.apple.com/lyric-ttml-internal'\nconst NAMESPACE_AMLL = 'http://www.example.com/ns/amll'\n\nconst ANNOTATION_KINDS = ['translations', 'romans'] as const\n\nconst XML_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_.-]*$/\n\nconst resolveOptions = (lyric: runtime.Lyric, options: TtmlGenerateOptions): ResolvedTtmlGenerateOptions => {\n const profile = options.profile ?? (lyric.format === FORMAT && lyric.extra.profile === 'itunes' ? 'itunes' : 'amll')\n if (profile !== 'amll' && profile !== 'itunes') {\n throw new Error('Unsupported TTML profile')\n }\n\n return { profile, includeMeta: options.includeMeta ?? true, indent: options.indent ?? false }\n}\n\n/**\n * Reserves source ids before allocating keys, so unnamed entries cannot take later source ids.\n */\nconst makeIdAllocator = (ids: string[]) => {\n const reserved = new Set(\n ids.filter((id) => {\n return XML_ID_PATTERN.test(id)\n }),\n )\n const used = new Set<string>()\n const counters = new Map<string, number>()\n\n return (preferred: string, prefix: string) => {\n if (XML_ID_PATTERN.test(preferred) && !used.has(preferred)) {\n used.add(preferred)\n return preferred\n }\n\n let count = counters.get(prefix) ?? 0\n let id: string\n do {\n count += 1\n id = `${prefix}${count}`\n } while (reserved.has(id) || used.has(id))\n\n counters.set(prefix, count)\n used.add(id)\n return id\n }\n}\n\n/**\n * Shares one mapping between declarations, body lines, and annotation references.\n */\nconst makeContext = (lyric: runtime.Lyric, lines: runtime.Line[], profile: TtmlProfile): RenderContext => {\n const ids = lyric.agents.map((agent) => {\n return agent.id\n })\n for (const line of lines) {\n ids.push(line.id)\n for (const background of line.backgrounds) {\n ids.push(background.id)\n }\n }\n\n const allocate = makeIdAllocator(ids)\n const agents = new Map<string, string>()\n const keys = new Map<SungLine, string>()\n\n for (const agent of lyric.agents) {\n if (agents.has(agent.id)) {\n throw new Error('TTML agent declarations require unique ids')\n }\n agents.set(agent.id, allocate(agent.id, 'v'))\n }\n for (const line of lines) {\n keys.set(line, allocate(line.id, 'L'))\n for (const background of line.backgrounds) {\n keys.set(background, allocate(background.id, 'B'))\n }\n }\n\n return { profile, offset: lyric.meta?.offset ?? 0, keys, agents }\n}\n\n/**\n * Bakes the playback offset into TTML timestamps without clamping negative results.\n */\nconst renderTime = (time: number, offset: number) => {\n const shifted = removeOffset(time, offset)\n if (!Number.isInteger(shifted) || shifted < 0) {\n throw new RangeError('TTML timestamps must be non-negative integer milliseconds after applying the offset')\n }\n\n const seconds = Math.floor(shifted / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = String(Math.floor(minutes / 60)).padStart(2, '0')\n const milliseconds = String(shifted % 1000).padStart(3, '0')\n\n return `${hours}:${String(minutes % 60).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}.${milliseconds}`\n}\n\n/**\n * Writes known bounds without inventing an end.\n */\nconst renderTimeAttributes = (time: runtime.TimeRange | undefined, offset: number): Attributes => {\n if (!time) {\n throw new Error('TTML sung lines, words, and ruby tokens require a time range')\n }\n\n const attributes: Attributes = [['begin', renderTime(time.start, offset)]]\n if (time.end !== undefined) {\n attributes.push(['end', renderTime(time.end, offset)])\n }\n return attributes\n}\n\n/**\n * Clears inherited language when the model leaves an item's language unspecified.\n */\nconst renderLanguage = (language: string | undefined, inherited?: string): Attributes => {\n if (language !== undefined) {\n return [['xml:lang', language]]\n }\n\n return inherited === undefined ? [] : [['xml:lang', '']]\n}\n\nconst getLineLanguage = (line: SungLine): string | undefined => {\n return line.languages.length === 1 ? line.languages[0] : undefined\n}\n\n/**\n * Writes separators as text and resolves inherited ruby timing through the model.\n */\nconst renderWord = (word: runtime.Word, context: RenderContext, language?: string): XmlNode => {\n if (word.type === WordType.SPACE) {\n return createXmlText(word.text)\n }\n\n const attributes = [...renderTimeAttributes(word.time, context.offset), ...renderLanguage(word.language, language)]\n const ruby = context.profile === 'amll' ? word.annotation?.rubies[0] : undefined\n if (!ruby) {\n return createXmlElement('span', attributes, [createXmlText(word.text)])\n }\n\n const tokens = ruby.tokens.map((token) => {\n return createXmlElement(\n 'span',\n [['tts:ruby', RUBY_TEXT], ...renderTimeAttributes(resolveAnnotationTokenTime(token, ruby, word), context.offset)],\n [createXmlText(token.text)],\n )\n })\n\n return createXmlElement(\n 'span',\n [['tts:ruby', RUBY_CONTAINER], ...attributes],\n [\n createXmlElement('span', [['tts:ruby', RUBY_BASE]], [createXmlText(word.text)]),\n createXmlElement(\n 'span',\n [\n ['tts:ruby', RUBY_TEXT_CONTAINER],\n ...renderTimeAttributes(resolveAnnotationItemTime(ruby, word), context.offset),\n ...renderLanguage(ruby.language, word.language),\n ],\n tokens,\n ),\n ],\n )\n}\n\n/**\n * Retains the model's choice between whole text and timed words.\n */\nconst renderContent = (line: SungLine, context: RenderContext): XmlNode[] => {\n const content = line.content\n if (!content) {\n throw new Error('TTML sung lines require content')\n }\n if (content.text !== undefined) {\n return [createXmlText(content.text)]\n }\n\n return content.words.map((word) => {\n return renderWord(word, context, getLineLanguage(line))\n })\n}\n\n/**\n * Keeps annotations outside the sung word stream.\n */\nconst renderInlineAnnotations = (line: SungLine, language?: string): XmlElement[] => {\n const nodes: XmlElement[] = []\n for (const item of line.annotation?.translations ?? []) {\n nodes.push(createXmlElement('span', [['ttm:role', ROLE_TRANSLATION], ...renderLanguage(item.language, language)], [createXmlText(item.text)]))\n }\n for (const item of getLineRomans(line)) {\n nodes.push(createXmlElement('span', [['ttm:role', ROLE_ROMAN], ...renderLanguage(item.language, language)], [createXmlText(item.text)]))\n }\n return nodes\n}\n\n/**\n * Uses the same allocated keys and agent ids as the document's declarations.\n */\nconst renderLineAttributes = (line: SungLine, context: RenderContext): Attributes => {\n const attributes: Attributes = [\n ...renderTimeAttributes(line.time, context.offset),\n ['itunes:key', context.keys.get(line)!],\n ['xml:space', 'preserve'],\n ['xml:lang', getLineLanguage(line) ?? ''],\n ]\n const lead = line.agents[0]\n if (lead !== undefined) {\n const id = context.agents.get(lead)\n if (!id) {\n throw new Error('TTML performing agents must have a declaration')\n }\n attributes.push(['ttm:agent', id])\n }\n return attributes\n}\n\n/**\n * An empty text node keeps the XML writer's indentation outside lyric content.\n */\nconst createLyricElement = (name: string, attributes: Attributes, children: XmlNode[]) => {\n return createXmlElement(name, attributes, [createXmlText(''), ...children])\n}\n\nconst renderBackground = (line: runtime.LineBackground, context: RenderContext) => {\n const children = renderContent(line, context)\n if (context.profile === 'amll') {\n children.push(...renderInlineAnnotations(line, getLineLanguage(line)))\n }\n\n return createXmlElement('span', [['ttm:role', ROLE_BACKGROUND], ...renderLineAttributes(line, context)], children)\n}\n\nconst renderLine = (line: runtime.Line, context: RenderContext) => {\n const before: XmlNode[] = []\n const after: XmlNode[] = []\n for (const background of line.backgrounds) {\n const node = renderBackground(background, context)\n if (background.time && line.time && background.time.start < line.time.start) {\n before.push(node)\n } else {\n after.push(node)\n }\n }\n\n const children = [...before, ...renderContent(line, context), ...after]\n if (context.profile === 'amll') {\n children.push(...renderInlineAnnotations(line, getLineLanguage(line)))\n }\n return createLyricElement('p', renderLineAttributes(line, context), children)\n}\n\nconst renderAgents = (lyric: runtime.Lyric, context: RenderContext) => {\n return lyric.agents.map((agent) => {\n const type = agent.type === AgentType.PERSON ? 'person' : agent.type === AgentType.GROUP ? 'group' : (agent.raw ?? 'other')\n const names = agent.names.map((name) => {\n return createXmlElement('ttm:name', [['type', 'full'], ...renderLanguage(name.language)], [createXmlText(name.text)])\n })\n\n return createXmlElement(\n 'ttm:agent',\n [\n ['type', type],\n ['xml:id', context.agents.get(agent.id)!],\n ],\n names,\n )\n })\n}\n\nconst renderAmllMeta = (meta: runtime.Meta): XmlElement[] => {\n const nodes: XmlElement[] = []\n const groups: [string, runtime.Text[]][] = [\n ['musicName', meta.titles],\n ['artists', meta.artists],\n ['album', meta.albums],\n ['ttmlAuthorGithubLogin', meta.authors],\n ]\n for (const [key, items] of groups) {\n for (const item of items) {\n nodes.push(createXmlElement('amll:meta', [['key', key], ['value', item.text], ...renderLanguage(item.language)]))\n }\n }\n for (const value of meta.isrcs) {\n nodes.push(\n createXmlElement('amll:meta', [\n ['key', 'isrc'],\n ['value', value],\n ]),\n )\n }\n for (const item of meta.unknowns) {\n nodes.push(\n createXmlElement('amll:meta', [\n ['key', item.key],\n ['value', item.value],\n ]),\n )\n }\n return nodes\n}\n\nconst renderSongwriters = (meta: runtime.Meta): XmlElement[] => {\n const names: XmlElement[] = []\n for (const credit of meta.credits) {\n if (credit.role !== CreditRole.LYRICIST) {\n continue\n }\n for (const name of credit.names) {\n names.push(createXmlElement('songwriter', renderLanguage(name.language), [createXmlText(name.text)]))\n }\n }\n return names.length ? [createXmlElement('songwriters', [], names)] : []\n}\n\nconst renderAnnotationTracks = (tracks: AnnotationTracks, kind: AnnotationKind, context: RenderContext): XmlElement[] => {\n if (!tracks.size) {\n return []\n }\n\n const translated = kind === 'translations'\n const blocks = Array.from(tracks, ([language, track]) => {\n const attributes: Attributes = translated ? [['type', 'subtitle']] : []\n attributes.push(...renderLanguage(language))\n const texts = Array.from(track, ([line, children]) => {\n return createLyricElement(\n 'text',\n [\n ['for', context.keys.get(line)!],\n ['xml:space', 'preserve'],\n ],\n children,\n )\n })\n return createXmlElement(translated ? 'translation' : 'transliteration', attributes, texts)\n })\n\n return [createXmlElement(translated ? 'translations' : 'transliterations', [], blocks)]\n}\n\n/**\n * A background-only annotation still references its parent paragraph, with a second reference naming the background.\n */\nconst renderHeadAnnotations = (lines: runtime.Line[], context: RenderContext): XmlElement[] => {\n const tracks: Record<AnnotationKind, AnnotationTracks> = { translations: new Map(), romans: new Map() }\n const append = (source: SungLine, line: runtime.Line, background?: runtime.LineBackground) => {\n const annotation = { translations: source.annotation?.translations ?? [], romans: getLineRomans(source) }\n for (const kind of ANNOTATION_KINDS) {\n for (const item of annotation[kind]) {\n const language = item.language?.toLowerCase()\n let track = tracks[kind].get(language)\n if (!track) {\n track = new Map()\n tracks[kind].set(language, track)\n }\n let nodes = track.get(line)\n if (!nodes) {\n nodes = []\n track.set(line, nodes)\n }\n\n nodes.push(\n !background\n ? createXmlText(item.text)\n : createXmlElement(\n 'span',\n [\n ['ttm:role', ROLE_BACKGROUND],\n ['for', context.keys.get(background)!],\n ],\n [createXmlText(item.text)],\n ),\n )\n }\n }\n }\n\n for (const line of lines) {\n append(line, line)\n for (const background of line.backgrounds) {\n append(background, line, background)\n }\n }\n\n return ANNOTATION_KINDS.flatMap((kind) => {\n return renderAnnotationTracks(tracks[kind], kind, context)\n })\n}\n\nconst renderMetadata = (lyric: runtime.Lyric, lines: runtime.Line[], context: RenderContext, includeMeta: boolean): XmlElement => {\n const metadata = renderAgents(lyric, context)\n const itunes: XmlElement[] = []\n if (includeMeta && lyric.meta) {\n if (context.profile === 'amll') {\n metadata.push(...renderAmllMeta(lyric.meta))\n }\n itunes.push(...renderSongwriters(lyric.meta))\n }\n if (context.profile === 'itunes') {\n itunes.push(...renderHeadAnnotations(lines, context))\n }\n if (itunes.length) {\n metadata.push(createXmlElement('iTunesMetadata', [['xmlns', NAMESPACE_ITUNES_METADATA]], itunes))\n }\n\n return createXmlElement('metadata', renderLanguage(undefined, lyric.meta?.language), metadata)\n}\n\nconst renderRootAttributes = (lyric: runtime.Lyric, profile: TtmlProfile): Attributes => {\n const attributes: Attributes = [\n ['xmlns', NAMESPACE_TTML],\n ['xmlns:ttm', NAMESPACE_TTML_METADATA],\n ['xmlns:tts', NAMESPACE_TTML_STYLING],\n ['xmlns:itunes', NAMESPACE_ITUNES],\n ]\n if (profile === 'amll') {\n attributes.push(['xmlns:amll', NAMESPACE_AMLL])\n }\n attributes.push(...renderLanguage(lyric.meta?.language), ['itunes:timing', lyric.timing === Timing.WORD ? TIMING_WORD : TIMING_LINE])\n\n return attributes\n}\n\n/**\n * Generates one TTML document, retaining the source profile unless explicitly overridden.\n *\n * Offsets are baked into timestamps; a negative result or a missing required time throws.\n * Profile mappings retain the lead agent and first AMLL ruby, omitting unsupported fields and instrumental nodes.\n * Word romanizations are emitted as line text without their token timing.\n */\nexport const generateTtml = (lyric: runtime.Lyric, options: TtmlGenerateOptions = {}): TtmlGenerateResult => {\n if (lyric.timing !== Timing.LINE && lyric.timing !== Timing.WORD) {\n throw new Error('TTML generation requires line or word timing')\n }\n\n const resolved = resolveOptions(lyric, options)\n const lines = lyric.lines.filter((line) => {\n return line.type !== LineType.INSTRUMENTAL\n })\n const context = makeContext(lyric, lines, resolved.profile)\n const metadata = renderMetadata(lyric, lines, context, resolved.includeMeta)\n const paragraphs = lines.map((line) => {\n return renderLine(line, context)\n })\n\n const root = createXmlElement('tt', renderRootAttributes(lyric, resolved.profile), [\n createXmlElement('head', [], [metadata]),\n createXmlElement('body', [], [createXmlElement('div', [], paragraphs)]),\n ])\n\n return serializeXml(root, { indent: resolved.indent })\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { XmlElement } from '@root/utils'\nimport type { ParseResult } from '../result'\nimport type { TtmlProfile } from './common'\n\nimport {\n AgentType,\n CreditRole,\n LyricStatus,\n Timing,\n deriveLanguageUsages,\n makeAgent,\n makeLineAnnotation,\n makeLineAnnotationRoman,\n makeLineAnnotationTranslation,\n makeLineBackground,\n makeLineContentText,\n makeLineContentWords,\n makeLineNormal,\n makeLyric,\n makeMeta,\n makeMetaCredit,\n makeText,\n makeTimeRange,\n makeUnknownEntry,\n makeWordAnnotation,\n makeWordAnnotationRuby,\n makeWordAnnotationToken,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport {\n XmlNodeType,\n findXmlElement,\n getXmlAttribute,\n getXmlChildElements,\n getXmlQualifiedAttribute,\n getXmlTextContent,\n hasXmlChildElement,\n lowerTag,\n parseTime,\n parseXml,\n} from '@root/utils'\n\nimport { finalizeLyric } from '../result'\nimport { FORMAT, AMLL_HINT_PATTERN, readTtmlContent } from './common'\nimport {\n ROLE_BACKGROUND,\n ROLE_ROMAN,\n ROLE_TRANSLATION,\n RUBY_BASE,\n RUBY_CONTAINER,\n RUBY_TEXT,\n RUBY_TEXT_CONTAINER,\n TIMING_LINE,\n TIMING_WORD,\n} from './utils'\n\ninterface TokenDraft {\n start?: number\n end?: number\n text: string\n}\n\ninterface RubyDraft {\n start?: number\n end?: number\n language?: string\n tokens: TokenDraft[]\n}\n\ninterface WordDraft {\n text: string\n space: boolean\n start?: number\n end?: number\n language?: string\n rubies: RubyDraft[]\n}\n\ninterface AnnotationDraft {\n language: string | undefined\n text: string\n}\n\ninterface LineDraft {\n start: number\n end: number | undefined\n agentId: string | undefined\n key: string | undefined\n words: WordDraft[]\n translations: AnnotationDraft[]\n romans: AnnotationDraft[]\n backgrounds: LineDraft[]\n wordLevel: boolean\n preserveSpace: boolean\n language: string | undefined\n}\n\ninterface ElementContext {\n element: XmlElement\n preserveSpace: boolean\n language: string | undefined\n}\n\nexport type TtmlParseInput = string\n\nexport interface TtmlParseOptions {\n /** Language tag the lyric declares; the document's own `xml:lang` wins when it states one. */\n language?: string\n}\n\nconst METADATA_NAMES = ['agent', 'songwriter', 'meta', 'translation', 'transliteration'] as const\n\nconst WORD_SEPARATOR_PATTERN = /\\p{White_Space}/u\n\nconst readTtmlProfile = (source: string): TtmlProfile => {\n return AMLL_HINT_PATTERN.test(source) ? 'amll' : 'itunes'\n}\n\nconst readSpanTime = (element: XmlElement) => {\n const begin = getXmlAttribute(element, 'begin')\n if (!begin) {\n return undefined\n }\n\n const start = parseTime(begin)\n if (start === undefined) {\n return undefined\n }\n\n const end = getXmlAttribute(element, 'end')\n\n return { start, end: end ? parseTime(end) : undefined }\n}\n\nconst readLineTime = (element: XmlElement) => {\n return readSpanTime(element)\n}\n\nconst readAgentType = (raw: string | undefined): { type: AgentType; raw: string | undefined } => {\n switch (raw) {\n case 'person':\n return { type: AgentType.PERSON, raw: undefined }\n case 'group':\n return { type: AgentType.GROUP, raw: undefined }\n default:\n return { type: AgentType.OTHER, raw: raw ?? 'other' }\n }\n}\n\nconst readDeclaredTiming = (root: XmlElement): Timing | undefined => {\n switch (getXmlQualifiedAttribute(root, 'itunes:timing')) {\n case TIMING_WORD:\n return Timing.WORD\n case TIMING_LINE:\n return Timing.LINE\n default:\n return undefined\n }\n}\n\nconst readPreserveSpace = (element: XmlElement, inherited: boolean): boolean => {\n switch (getXmlQualifiedAttribute(element, 'xml:space')) {\n case 'preserve':\n return true\n case 'default':\n return false\n default:\n return inherited\n }\n}\n\nconst readLanguage = (element: XmlElement, inherited?: string): string | undefined => {\n const language = getXmlQualifiedAttribute(element, 'xml:lang') ?? getXmlAttribute(element, 'lang')\n return language === undefined ? inherited : lowerTag(language)\n}\n\nconst readText = (element: XmlElement, inherited: boolean): string => {\n const text = getXmlTextContent(element)\n return readPreserveSpace(element, inherited) ? text : text.trim()\n}\n\n/**\n * Preserves the parser's whitespace segmentation when turning text into word drafts.\n */\nconst splitWords = (text: string, language?: string): WordDraft[] => {\n if (!text) {\n return []\n }\n if (!WORD_SEPARATOR_PATTERN.test(text)) {\n return [{ text, space: false, language, rubies: [] }]\n }\n\n const words: WordDraft[] = []\n\n for (const run of text.split(/(\\p{White_Space}+)/u)) {\n if (run) {\n const space = /^\\p{White_Space}+$/u.test(run)\n words.push({ text: run, space, language: space ? undefined : language, rubies: [] })\n }\n }\n\n return words\n}\n\n/**\n * Distinguishes indentation runs from separators using the parser's existing rule.\n */\nconst isFormattingWhitespace = (text: string) => {\n return !text.trim() && text.includes('\\n')\n}\n\n/**\n * Builds words from source drafts without deriving missing timestamps.\n */\nconst buildWords = (draft: LineDraft): runtime.Word[] => {\n const words: runtime.Word[] = []\n\n for (const word of draft.words) {\n if (word.space) {\n words.push(makeWordSpace({ text: word.text }))\n continue\n }\n\n const time = word.start === undefined ? undefined : makeTimeRange({ start: word.start, end: word.end })\n if (!word.rubies.length) {\n words.push(makeWordNormal({ text: word.text, time, language: word.language }))\n continue\n }\n\n const rubies = word.rubies.map((ruby) => {\n return makeWordAnnotationRuby({\n time: ruby.start === undefined ? undefined : makeTimeRange({ start: ruby.start, end: ruby.end }),\n language: ruby.language,\n tokens: ruby.tokens.map((token) => {\n return makeWordAnnotationToken({\n text: token.text,\n time: token.start === undefined ? undefined : makeTimeRange({ start: token.start, end: token.end }),\n })\n }),\n })\n })\n\n words.push(makeWordNormal({ text: word.text, time, language: word.language, annotation: makeWordAnnotation({ rubies }) }))\n }\n\n return words\n}\n\n/**\n * Builds only annotations explicitly present in the source drafts.\n */\nconst buildLineAnnotation = (draft: LineDraft): runtime.LineAnnotation | undefined => {\n if (!draft.translations.length && !draft.romans.length) {\n return undefined\n }\n\n return makeLineAnnotation({\n translations: draft.translations.map((item) => {\n return makeLineAnnotationTranslation({ text: item.text, language: item.language })\n }),\n romans: draft.romans.map((item) => {\n return makeLineAnnotationRoman({ text: item.text, language: item.language })\n }),\n })\n}\n\n/**\n * Separates head annotation text from its background references.\n */\nconst splitBackgroundText = (element: XmlElement, preserveSpace: boolean, language?: string) => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n let main = ''\n const backgrounds: { text: string; key: string | undefined; language: string | undefined }[] = []\n\n for (const child of element.children) {\n if (child.nodeType === XmlNodeType.element && child.localName === 'span' && getXmlAttribute(child, 'role') === ROLE_BACKGROUND) {\n backgrounds.push({ text: readText(child, preserveSpace), key: getXmlAttribute(child, 'for'), language: readLanguage(child, language) })\n continue\n }\n main += getXmlTextContent(child)\n }\n\n return { main: preserveSpace ? main : main.trim(), backgrounds }\n}\n\n/**\n * Carries language and whitespace declarations through wrappers to the elements they govern.\n */\nconst groupElements = (\n root: XmlElement,\n names: readonly string[],\n preserveSpace: boolean,\n stopAtMatch = false,\n language?: string,\n): Map<string, ElementContext[]> => {\n const wanted = new Set(names)\n const result = new Map<string, ElementContext[]>()\n const stack: ElementContext[] = [{ element: root, preserveSpace, language }]\n\n while (stack.length) {\n const entry = stack.pop()\n if (!entry) {\n continue\n }\n const element = entry.element\n const currentSpace = readPreserveSpace(element, entry.preserveSpace)\n const currentLanguage = readLanguage(element, entry.language)\n if (wanted.has(element.localName)) {\n const group = result.get(element.localName)\n const context = { element, preserveSpace: currentSpace, language: currentLanguage }\n if (!group) {\n result.set(element.localName, [context])\n } else {\n group.push(context)\n }\n if (stopAtMatch) {\n continue\n }\n }\n\n const children = element.children\n for (let index = children.length - 1; index >= 0; index -= 1) {\n const child = children[index]\n if (child && child.nodeType === XmlNodeType.element) {\n stack.push({ element: child, preserveSpace: currentSpace, language: currentLanguage })\n }\n }\n }\n\n return result\n}\n\nconst findElements = (root: XmlElement, name: string, preserveSpace: boolean, stopAtMatch = false, language?: string): ElementContext[] => {\n return groupElements(root, [name], preserveSpace, stopAtMatch, language).get(name) ?? []\n}\n\n/**\n * Reads an AMLL ruby container into one word plus its per-syllable annotation.\n */\nconst readRuby = (container: XmlElement, preserveSpace: boolean, language?: string): WordDraft | undefined => {\n preserveSpace = readPreserveSpace(container, preserveSpace)\n language = readLanguage(container, language)\n let base = ''\n let baseLanguage = language\n let rubyTime: ReturnType<typeof readSpanTime>\n let rubyLanguage = language\n const tokens: TokenDraft[] = []\n\n for (const child of getXmlChildElements(container, 'span')) {\n const kind = getXmlAttribute(child, 'ruby')\n if (kind === RUBY_BASE) {\n base = readText(child, preserveSpace)\n baseLanguage = readLanguage(child, language)\n continue\n }\n if (kind !== RUBY_TEXT_CONTAINER) {\n continue\n }\n\n rubyTime ??= readSpanTime(child)\n rubyLanguage = readLanguage(child, language)\n const rubySpace = readPreserveSpace(child, preserveSpace)\n for (const text of getXmlChildElements(child, 'span')) {\n if (getXmlAttribute(text, 'ruby') !== RUBY_TEXT) {\n continue\n }\n const time = readSpanTime(text)\n const content = readText(text, rubySpace)\n if (!content) {\n continue\n }\n tokens.push({ start: time?.start, end: time?.end, text: content })\n }\n }\n\n if (!base) {\n return undefined\n }\n\n const first = tokens.find((token) => {\n return token.start !== undefined\n })\n const last = tokens.findLast((token) => {\n return token.start !== undefined\n })\n // Older AMLL containers state timing only on their annotation tokens.\n const time = readSpanTime(container) ?? rubyTime ?? (first ? { start: first.start, end: last?.end } : undefined)\n\n return {\n text: base,\n space: false,\n start: time?.start,\n end: time?.end,\n language: baseLanguage,\n rubies: tokens.length ? [{ start: rubyTime?.start, end: rubyTime?.end, language: rubyLanguage, tokens }] : [],\n }\n}\n\n/**\n * Collects the words of one span-bearing element.\n *\n * Text between spans carries the separators, and a span without a readable begin contributes its text untimed.\n * A span carrying a role is annotation rather than a word, so it is skipped here.\n * Whitespace inside a span remains a separator; indentation is dropped only without a preserve declaration.\n */\nconst readWords = (element: XmlElement, preserveSpace: boolean, language?: string): { words: WordDraft[]; wordLevel: boolean } => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const words: WordDraft[] = []\n let wordLevel = false\n\n for (const child of element.children) {\n if (child.nodeType !== XmlNodeType.element) {\n if (preserveSpace || !isFormattingWhitespace(child.text)) {\n words.push(...splitWords(child.text, language))\n }\n continue\n }\n if (child.localName !== 'span') {\n continue\n }\n\n const role = getXmlAttribute(child, 'role')\n if (role !== undefined) {\n continue\n }\n\n if (getXmlAttribute(child, 'ruby') === RUBY_CONTAINER) {\n const ruby = readRuby(child, preserveSpace, language)\n if (ruby) {\n for (const part of splitWords(ruby.text)) {\n words.push(part.space ? part : { ...ruby, text: part.text })\n }\n wordLevel ||= ruby.start !== undefined\n }\n continue\n }\n\n const text = getXmlTextContent(child)\n const childSpace = readPreserveSpace(child, preserveSpace)\n if (!text || (!childSpace && isFormattingWhitespace(text))) {\n continue\n }\n\n const time = readSpanTime(child)\n for (const part of splitWords(text, readLanguage(child, language))) {\n if (!part.space && time) {\n part.start = time.start\n part.end = time.end\n wordLevel = true\n }\n words.push(part)\n }\n }\n\n return { words, wordLevel }\n}\n\nconst readInlineAnnotations = (element: XmlElement, preserveSpace: boolean, language?: string): Pick<LineDraft, 'translations' | 'romans'> => {\n const translations: AnnotationDraft[] = []\n const romans: AnnotationDraft[] = []\n\n for (const span of getXmlChildElements(element, 'span')) {\n const role = getXmlAttribute(span, 'role')\n if (role !== ROLE_TRANSLATION && role !== ROLE_ROMAN) {\n continue\n }\n const text = readText(span, preserveSpace)\n if (!text) {\n continue\n }\n\n const item = { language: readLanguage(span, language), text }\n if (role === ROLE_TRANSLATION) {\n translations.push(item)\n } else {\n romans.push(item)\n }\n }\n\n return { translations, romans }\n}\n\n/**\n * Reads one paragraph, pulling its inline annotations and background lines out of the word stream.\n */\nconst readLine = (element: XmlElement, preserveSpace: boolean, language?: string): LineDraft | undefined => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const time = readLineTime(element)\n if (!time) {\n return undefined\n }\n\n const draft: LineDraft = {\n start: time.start,\n end: time.end,\n agentId: getXmlAttribute(element, 'agent'),\n key: getXmlAttribute(element, 'key'),\n words: [],\n translations: [],\n romans: [],\n backgrounds: [],\n wordLevel: false,\n preserveSpace,\n language,\n }\n\n if (!hasXmlChildElement(element, 'span')) {\n const plain = readText(element, preserveSpace)\n if (!plain) {\n return undefined\n }\n\n draft.words = splitWords(plain, language)\n return draft\n }\n\n const read = readWords(element, preserveSpace, language)\n draft.words = read.words\n draft.wordLevel = read.wordLevel\n const annotations = readInlineAnnotations(element, preserveSpace, language)\n draft.translations = annotations.translations\n draft.romans = annotations.romans\n\n for (const span of getXmlChildElements(element, 'span')) {\n const role = getXmlAttribute(span, 'role')\n if (role === ROLE_BACKGROUND) {\n const background = readBackground(span, preserveSpace, language)\n if (background) {\n draft.backgrounds.push(background)\n }\n }\n }\n\n return draft\n}\n\n/**\n * Reads a background line, whose end may stay open because its parent's end covers it.\n *\n * A background line states no time of its own in AMLL files, so its range comes from its words.\n */\nconst readBackground = (element: XmlElement, preserveSpace: boolean, language?: string): LineDraft | undefined => {\n preserveSpace = readPreserveSpace(element, preserveSpace)\n language = readLanguage(element, language)\n const read = readWords(element, preserveSpace, language)\n if (!read.words.length) {\n return undefined\n }\n\n const begin = getXmlAttribute(element, 'begin')\n const end = getXmlAttribute(element, 'end')\n const first = read.words.find((word) => {\n return !word.space && word.start !== undefined\n })\n const last = read.words.findLast((word) => {\n return !word.space && word.start !== undefined\n })\n\n const start = begin === undefined ? (first?.start ?? 0) : parseTime(begin)\n if (start === undefined) {\n return undefined\n }\n\n const finish = end === undefined ? last?.end : parseTime(end)\n\n return {\n start,\n end: finish,\n agentId: getXmlAttribute(element, 'agent'),\n key: getXmlAttribute(element, 'key'),\n words: read.words,\n ...readInlineAnnotations(element, preserveSpace, language),\n backgrounds: [],\n wordLevel: read.wordLevel,\n preserveSpace,\n language,\n }\n}\n\nconst buildContent = (draft: LineDraft): runtime.LineContent => {\n if (draft.wordLevel) {\n return makeLineContentWords(buildWords(draft))\n }\n\n const text = draft.words\n .map((word) => {\n return word.text\n })\n .join('')\n return makeLineContentText(draft.preserveSpace ? text : text.trim())\n}\n\n/**\n * Builds one background line.\n */\nconst buildBackground = (draft: LineDraft): runtime.LineBackground => {\n return makeLineBackground({\n id: draft.key,\n time: makeTimeRange({ start: draft.start, end: draft.end }),\n agents: draft.agentId === undefined ? [] : [draft.agentId],\n languages: draft.language ? [draft.language] : [],\n content: buildContent(draft),\n annotation: buildLineAnnotation(draft),\n })\n}\n\n/**\n * Builds one normal line, keeping plain text whole unless the source timed its words.\n */\nconst buildLine = (draft: LineDraft): runtime.Line => {\n return makeLineNormal({\n id: draft.key,\n time: makeTimeRange({ start: draft.start, end: draft.end }),\n agents: draft.agentId === undefined ? [] : [draft.agentId],\n languages: draft.language ? [draft.language] : [],\n content: buildContent(draft),\n annotation: buildLineAnnotation(draft),\n backgrounds: draft.backgrounds.map(buildBackground),\n })\n}\n\n/**\n * Reads the head's agents, which lines reference by id.\n */\nconst readAgents = (elements: ElementContext[]): runtime.Agent[] => {\n const agents: runtime.Agent[] = []\n for (const { element, preserveSpace, language } of elements) {\n const id = getXmlQualifiedAttribute(element, 'xml:id') ?? getXmlAttribute(element, 'id')\n if (!id) {\n continue\n }\n\n const names = getXmlChildElements(element, 'name')\n .map((name) => {\n return makeText({ text: readText(name, preserveSpace), language: readLanguage(name, language) })\n })\n .filter((name) => {\n return !!name.text\n })\n\n const kind = readAgentType(getXmlAttribute(element, 'type'))\n agents.push(\n makeAgent({\n id,\n type: kind.type,\n raw: kind.raw,\n names,\n }),\n )\n }\n\n return agents\n}\n\n/**\n * Reads the head's songwriters as one lyricist credit, since TTML does not split the role further.\n *\n * AMLL wraps these in `iTunesMetadata`, so the whole head is searched rather than its direct children.\n */\nconst readCredits = (elements: ElementContext[], meta: runtime.Meta) => {\n const names = elements\n .map(({ element, preserveSpace, language }) => {\n return makeText({ text: readText(element, preserveSpace), language })\n })\n .filter((name) => {\n return !!name.text\n })\n\n if (!names.length) {\n return\n }\n\n meta.credits.push(\n makeMetaCredit({\n role: CreditRole.LYRICIST,\n names,\n }),\n )\n}\n\n/**\n * Reads one `amll:meta` entry, keeping an unknown key as written so a round trip loses nothing.\n */\nconst applyAmllMeta = (meta: runtime.Meta, element: XmlElement, language?: string) => {\n const key = getXmlAttribute(element, 'key')\n const value = getXmlAttribute(element, 'value')?.trim()\n if (!key || !value) {\n return\n }\n\n language = readLanguage(element, language)\n switch (key) {\n case 'musicName':\n meta.titles.push(makeText({ text: value, language }))\n return\n case 'artists':\n meta.artists.push(makeText({ text: value, language }))\n return\n case 'album':\n meta.albums.push(makeText({ text: value, language }))\n return\n case 'isrc':\n meta.isrcs.push(value)\n return\n case 'ttmlAuthorGithubLogin':\n meta.authors.push(makeText({ text: value, language }))\n return\n default:\n meta.unknowns.push(makeUnknownEntry({ key, value }))\n }\n}\n\n/**\n * Attaches head translations and transliterations to the lines they name by `itunes:key`.\n *\n * A replacement translation rewrites the line's text, which is how a source swaps one script for another.\n */\nconst attachHeadAnnotations = (metadata: Map<string, ElementContext[]>, lineMap: Map<string, LineDraft>, backgroundMap: Map<string, LineDraft>) => {\n if (!lineMap.size) {\n return\n }\n\n const attach = (blocks: ElementContext[], kind: 'translation' | 'roman') => {\n for (const { element: block, preserveSpace, language } of blocks) {\n const type = getXmlQualifiedAttribute(block, 'type') ?? getXmlAttribute(block, 'type')\n\n for (const text of getXmlChildElements(block, 'text')) {\n const key = getXmlAttribute(text, 'for')\n const line = key ? lineMap.get(key) : undefined\n if (!line) {\n continue\n }\n\n const textLanguage = readLanguage(text, language)\n const { main, backgrounds } = splitBackgroundText(text, preserveSpace, textLanguage)\n if (kind === 'translation' && type === 'replacement') {\n if (main) {\n line.words = splitWords(main, textLanguage)\n line.wordLevel = false\n line.preserveSpace = readPreserveSpace(text, preserveSpace)\n line.language = textLanguage\n }\n continue\n }\n\n if (main) {\n const item = { language: textLanguage, text: main }\n if (kind === 'translation') {\n line.translations.push(item)\n } else {\n line.romans.push(item)\n }\n }\n\n for (const background of backgrounds) {\n if (!background.text) {\n continue\n }\n const target = background.key ? backgroundMap.get(background.key) : undefined\n if (!target) {\n continue\n }\n const item = { language: background.language, text: background.text }\n if (kind === 'translation') {\n target.translations.push(item)\n } else {\n target.romans.push(item)\n }\n }\n }\n }\n }\n\n attach(metadata.get('translation') ?? [], 'translation')\n attach(metadata.get('transliteration') ?? [], 'roman')\n}\n\n/**\n * Reads a TTML document into the model.\n *\n * The profile only changes where metadata comes from, so one reader serves both.\n * A document that parses but holds no timed paragraph is `INVALID` rather than an error.\n */\nexport const parseTtml = (input: TtmlParseInput, options: TtmlParseOptions = {}): ParseResult => {\n const content = readTtmlContent(input)\n if (!content) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta: makeMeta() }))\n }\n\n const extra = {\n profile: readTtmlProfile(content),\n }\n\n const document = parseXml(content)\n const root = document ? findXmlElement(document, 'tt') : undefined\n if (!root) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta: makeMeta(), extra }))\n }\n\n const language = readLanguage(root, lowerTag(options.language))\n const body = findElements(root, 'body', false, true, language)[0]\n const metadata = findElements(root, 'metadata', false, true, language)[0]\n const metadataElements = metadata\n ? groupElements(metadata.element, METADATA_NAMES, metadata.preserveSpace, false, metadata.language)\n : new Map<string, ElementContext[]>()\n const meta = makeMeta()\n\n if (language) {\n meta.language = language\n }\n\n readCredits(metadataElements.get('songwriter') ?? [], meta)\n for (const { element, language: itemLanguage } of metadataElements.get('meta') ?? []) {\n applyAmllMeta(meta, element, itemLanguage)\n }\n\n const drafts: LineDraft[] = []\n const lineMap = new Map<string, LineDraft>()\n const backgroundMap = new Map<string, LineDraft>()\n\n for (const { element, preserveSpace, language: lineLanguage } of body\n ? findElements(body.element, 'p', body.preserveSpace, true, body.language)\n : []) {\n const draft = readLine(element, preserveSpace, lineLanguage)\n if (!draft) {\n continue\n }\n\n drafts.push(draft)\n if (draft.key) {\n lineMap.set(draft.key, draft)\n }\n for (const background of draft.backgrounds) {\n if (background.key) {\n backgroundMap.set(background.key, background)\n }\n }\n }\n\n attachHeadAnnotations(metadataElements, lineMap, backgroundMap)\n\n if (!drafts.length) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID, meta, extra }))\n }\n\n const lines = drafts.map(buildLine)\n const wordLevel = drafts.some((draft) => {\n return (\n draft.wordLevel ||\n draft.backgrounds.some((background) => {\n return background.wordLevel\n })\n )\n })\n\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: LyricStatus.VALID,\n timing: readDeclaredTiming(root) ?? (wordLevel ? Timing.WORD : Timing.LINE),\n meta,\n extra,\n agents: readAgents(metadataElements.get('agent') ?? []),\n languages: deriveLanguageUsages(lines),\n lines,\n }),\n )\n}\n","export const FORMAT = 'yrc'\nexport const LINE_PATTERN = /^\\[(\\d+),(\\d+)\\]/\nexport const WORD_PATTERN = /\\((\\d+,\\d+,\\d+)\\)/g\n\nexport interface YrcContent {\n original: string\n translations?: string\n romans?: string\n}\n\n/**\n * Accepts plaintext tracks on one timeline without interpreting an API response or an XML container.\n *\n * @returns Original and optional auxiliary text, or null when the original payload is unreadable.\n */\nexport const readYrcContent = (input: unknown): YrcContent | null => {\n const value = typeof input === 'string' ? { original: input } : input\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null\n }\n const source = value as Partial<YrcContent>\n if (typeof source.original !== 'string' || /^\\s*</.test(source.original)) {\n return null\n }\n return {\n original: source.original,\n translations: typeof source.translations === 'string' ? source.translations : undefined,\n romans: typeof source.romans === 'string' ? source.romans : undefined,\n }\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { AnnotationTiming } from '@root/utils'\nimport type { LrcMetaTag } from '../lrc'\nimport type { ParseResult } from '../result'\nimport type { YrcContent } from './common'\n\nimport {\n LyricStatus,\n Timing,\n WordType,\n deriveLanguageUsages,\n isWordLevelLine,\n makeLineContentText,\n makeLineContentWords,\n makeLineInstrumental,\n makeLineNormal,\n makeLyric,\n makeTimeRange,\n makeUnknownEntry,\n makeWordNormal,\n makeWordSpace,\n} from '@gondola-lyrics/model/runtime'\n\nimport { attachAnnotations, trimRuleWhitespace } from '@root/utils'\n\nimport { readLrc, readLrcMetaTags, scanWordTags } from '../lrc'\nimport { finalizeLyric } from '../result'\nimport { FORMAT, LINE_PATTERN, WORD_PATTERN, readYrcContent } from './common'\n\nexport type YrcParseInput = YrcContent\n\nexport interface YrcParseOptions {\n /**\n * Extra timestamp drift allowed after exact and source-precision matching, in milliseconds.\n * Tracks must share the original timeline; equal row counts never enable order matching.\n *\n * @default 0\n */\n annotationTolerance?: number\n /**\n * Maximum roman token drift outside a matched word, in milliseconds; matched boundaries are adjusted to that word.\n * Original word timing is preserved, and incomplete matches retain the whole line romanization.\n *\n * @default 0\n */\n wordAnnotationTolerance?: number\n /**\n * Recovers roman fragments from unique two-kana combination starts or equal-sized gaps between timing anchors.\n * Recovered token times are clipped to their original word; untimed fragments inherit its range.\n *\n * @default false\n */\n wordAnnotationFallback?: boolean\n}\n\ninterface JsonLine {\n start: number\n text: string\n complete: boolean\n credit?: {\n raw: string\n names: string[]\n }\n}\n\ninterface SourceLine {\n row: number\n line: runtime.Line\n display?: boolean\n credit?: boolean\n}\n\nconst SEPARATORS = /^\\p{White_Space}+$/u\nconst CREDIT_LABEL_PATTERN = /[::]$/u\n\nconst isObject = (value: unknown): value is Record<string, unknown> => {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nconst readCredit = (fragments: string[]): JsonLine['credit'] => {\n const label = trimRuleWhitespace(fragments[0] ?? '')\n const raw = trimRuleWhitespace(label.replace(CREDIT_LABEL_PATTERN, ''))\n if (!raw) {\n return undefined\n }\n\n const names = fragments.slice(1).join('').split('/').map(trimRuleWhitespace).filter(Boolean)\n return names.length ? { raw, names } : undefined\n}\n\n/**\n * Reads JSON display text and splits the joined credit content at slash separators.\n *\n * @returns A readable display line and whether all source fields are represented, or null for other JSON.\n */\nexport const readJsonLine = (text: string): JsonLine | null => {\n try {\n const value: unknown = JSON.parse(text)\n if (!isObject(value) || typeof value.t !== 'number' || !Number.isSafeInteger(value.t) || value.t < 0 || !Array.isArray(value.c)) {\n return null\n }\n\n const fragments: string[] = []\n let complete = Object.keys(value).every((key) => key === 't' || key === 'c')\n for (const fragment of value.c) {\n if (!isObject(fragment) || typeof fragment.tx !== 'string') {\n return null\n }\n fragments.push(fragment.tx)\n complete = complete && Object.keys(fragment).every((key) => key === 'tx')\n }\n\n const content = fragments.join('')\n return /[^\\p{White_Space}]/u.test(content) ? { start: value.t, text: content, complete, credit: readCredit(fragments) } : null\n } catch {\n return null\n }\n}\n\nconst appendWords = (words: runtime.Word[], text: string, time?: runtime.TimeRange): void => {\n for (const fragment of text.split(/(\\p{White_Space}+)/u)) {\n if (fragment) {\n words.push(SEPARATORS.test(fragment) ? makeWordSpace({ text: fragment }) : makeWordNormal({ text: fragment, time }))\n }\n }\n}\n\nconst readLine = (body: string, start: number, duration: number): runtime.Line => {\n const time = makeTimeRange({ start, end: start + duration })\n const pieces = scanWordTags(body, WORD_PATTERN)\n if (!pieces.some((piece) => piece.tag !== undefined)) {\n return /[^\\p{White_Space}]/u.test(body) ? makeLineNormal({ time, content: makeLineContentText(body) }) : makeLineInstrumental({ time })\n }\n\n const words: runtime.Word[] = []\n for (const piece of pieces) {\n if (piece.tag === undefined) {\n appendWords(words, piece.text)\n continue\n }\n // YRC starts are absolute; the third field has no verified meaning.\n const [wordStart, wordDuration] = piece.tag.split(',').map(Number)\n appendWords(words, piece.text, makeTimeRange({ start: wordStart!, end: wordStart! + wordDuration! }))\n }\n\n return words.some((word) => word.type === WordType.NORMAL)\n ? makeLineNormal({ time, content: makeLineContentWords(words) })\n : makeLineInstrumental({ time })\n}\n\nconst readTrack = (text: string, timings?: WeakMap<runtime.Line, AnnotationTiming>) => {\n const tags: { row: number; tag: LrcMetaTag; unknown?: boolean }[] = []\n\n const native: SourceLine[] = []\n const fallback: string[] = []\n\n const displays: SourceLine[] = []\n\n const rows = /^\\s*</.test(text) ? [] : text.replace(/^\\uFEFF/, '').split(/\\r\\n?|\\n/)\n\n for (const [row, raw] of rows.entries()) {\n const line = raw.trimStart()\n const header = LINE_PATTERN.exec(line)\n if (header) {\n native.push({ row, line: readLine(line.slice(header[0].length), Number(header[1]), Number(header[2])) })\n fallback.push('')\n } else if (line.startsWith('{')) {\n const display = readJsonLine(line)\n if (display) {\n displays.push({\n row,\n display: true,\n credit: !!display.credit,\n line: makeLineNormal({ time: makeTimeRange({ start: display.start }), content: makeLineContentText(display.text) }),\n })\n if (display.credit) {\n const { raw, names } = display.credit\n for (const value of names) {\n tags.push({ row, unknown: true, tag: { key: raw, value } })\n }\n }\n }\n if (!display?.complete) {\n tags.push({ row, unknown: true, tag: { key: 'yrc:json', value: raw } })\n }\n fallback.push(display ? `[${display.start}ms]` : '')\n } else {\n fallback.push(raw)\n }\n }\n\n const clock: SourceLine[] = []\n const displayRows = new Set(displays.map((entry) => entry.row))\n readLrc(fallback.join('\\n'), {\n onLine: (line, timing, row) => {\n // Display timestamps close preceding LRC segments, but their text never passes through the LRC grammar.\n if (displayRows.has(row)) {\n return\n }\n clock.push({ row, line })\n timings?.set(line, timing)\n },\n onMeta: (tag, row) => {\n tags.push({ row, tag })\n },\n })\n\n const entries = [...displays, ...(native.length ? native : clock)].sort((first, second) => first.row - second.row)\n for (const [index, entry] of entries.entries()) {\n if (!entry.display) {\n continue\n }\n // Only display rows lack an explicit end; a nondecreasing source successor can bound them.\n const next = entries[index + 1]?.line.time?.start\n if (next !== undefined && next >= entry.line.time!.start) {\n entry.line.time!.end = next\n }\n }\n\n const metaTags = tags.sort((first, second) => first.row - second.row)\n // Credit timestamps still bound preceding rows before their display content leaves the lyric stream.\n return { entries: entries.filter((entry) => !entry.credit), metaTags }\n}\n\nconst readAnnotations = (text: string | undefined, timings: WeakMap<runtime.Line, AnnotationTiming>): runtime.Line[] => {\n return text\n ? readTrack(text, timings)\n .entries.filter((entry) => !entry.display)\n .map((entry) => entry.line)\n : []\n}\n\n/**\n * Parses native YRC or LRC fallback, keeping JSON display rows separate from annotation matching.\n * Explicit line and word durations remain unchanged, including zero durations and source timing violations.\n * JSON credit content becomes separate plain-text unknown entries sharing the source label and is omitted from lyric lines.\n *\n * @param input Plaintext tracks on the same timeline: yrc with ytlrc/yromalrc, or lrc with tlyric/romalrc.\n * @param options Independent line and word tolerances, with optional local roman recovery.\n *\n * @returns Canonical lyrics and model diagnostics; no readable timed rows yields INVALID status.\n */\nexport const parseYrc = (input: string | YrcParseInput, options: YrcParseOptions = {}): ParseResult => {\n const source = readYrcContent(input)\n if (!source) {\n return finalizeLyric(makeLyric({ format: FORMAT, status: LyricStatus.INVALID }))\n }\n\n const parsed = readTrack(source.original)\n const meta = readLrcMetaTags(parsed.metaTags.filter((entry) => !entry.unknown).map((entry) => entry.tag))\n let unknownIndex = 0\n // Standard mapping retains unknown tag order; merge literal JSON fields without interpreting reserved metadata keys.\n meta.unknowns = parsed.metaTags.flatMap(({ tag, unknown }) => {\n if (unknown) {\n return [makeUnknownEntry(tag)]\n }\n const entry = meta.unknowns[unknownIndex]\n if (entry?.key === tag.key && entry.value === tag.value) {\n unknownIndex += 1\n return [entry]\n }\n return []\n })\n\n const body = parsed.entries.filter((entry) => !entry.display).map((entry) => entry.line)\n const timings = new WeakMap<runtime.Line, AnnotationTiming>()\n const annotated = attachAnnotations(\n body,\n { translations: readAnnotations(source.translations, timings), romans: readAnnotations(source.romans, timings) },\n {\n preservePlaceholders: true,\n tolerance: options.annotationTolerance,\n wordTolerance: options.wordAnnotationTolerance,\n wordFallback: options.wordAnnotationFallback,\n getTiming: (line) => timings.get(line),\n },\n )\n\n let index = 0\n const lines = parsed.entries.map((entry) => {\n return entry.display ? entry.line : annotated[index++]!\n })\n\n return finalizeLyric(\n makeLyric({\n format: FORMAT,\n status: lines.length ? LyricStatus.VALID : LyricStatus.INVALID,\n timing: lines.some(isWordLevelLine) ? Timing.WORD : Timing.LINE,\n meta,\n lines,\n languages: deriveLanguageUsages(lines),\n }),\n )\n}\n","import { detectLrc } from '../lrc'\nimport { LINE_PATTERN, WORD_PATTERN, readYrcContent } from './common'\nimport { readJsonLine } from './parser'\n\n/**\n * Recognizes native word tags or a JSON display line accompanied by LRC content in the original track.\n *\n * @returns Whether the original plaintext carries a YRC signal stronger than its shared QRC line header.\n */\nexport const detectYrc = (input: unknown): boolean => {\n const source = readYrcContent(input)\n if (!source) {\n return false\n }\n let display = false\n const fallback: string[] = []\n for (const raw of source.original.split(/\\r\\n?|\\n/)) {\n const line = raw.trimStart()\n const header = LINE_PATTERN.exec(line)\n if (header && line.slice(header[0].length).match(WORD_PATTERN)) {\n return true\n }\n if (line.startsWith('{')) {\n display = display || !!readJsonLine(line)\n } else {\n fallback.push(raw)\n }\n }\n return display && detectLrc(fallback.join('\\n'))\n}\n","import type { runtime } from '@gondola-lyrics/model'\nimport type { LyricFormat } from './format'\nimport type { KrcParseInput } from './krc'\nimport type { KwrcParseInput } from './kwrc'\nimport type { LrcGenerateOptions, LrcGenerateResult, LrcParseInput, LrcParseOptions } from './lrc'\nimport type { QrcParseInput, QrcParseOptions } from './qrc'\nimport type { ParseResult } from './result'\nimport type { TtmlGenerateOptions, TtmlGenerateResult, TtmlParseOptions } from './ttml'\nimport type { YrcParseInput, YrcParseOptions } from './yrc'\n\nimport { detectKrc, parseKrc } from './krc'\nimport { detectKwrc, parseKwrc } from './kwrc'\nimport { detectLrc, generateLrc, parseLrc } from './lrc'\nimport { detectQrc, parseQrc } from './qrc'\nimport { detectTtml, generateTtml, parseTtml } from './ttml'\nimport { detectYrc, parseYrc } from './yrc'\n\n/**\n * Recognition reads only the original text; the annotation tracks never decide the format.\n *\n * Unrecognized text returns `undefined`.\n */\nexport const detectFormat = (input: unknown): LyricFormat | undefined => {\n if (detectKrc(input)) {\n return 'krc'\n }\n if (detectYrc(input)) {\n return 'yrc'\n }\n if (detectQrc(input)) {\n return 'qrc'\n }\n if (detectKwrc(input)) {\n return 'kwrc'\n }\n if (detectLrc(input)) {\n return 'lrc'\n }\n if (detectTtml(input)) {\n return 'ttml'\n }\n\n return undefined\n}\n\n/**\n * Unrecognized text returns `null`; a recognized format returns its canonical lyric and diagnostics.\n * Annotation tracks travel with the source and are attached by the format's parser.\n */\nexport const parse = (input: unknown, options: LrcParseOptions & QrcParseOptions & TtmlParseOptions & YrcParseOptions = {}): ParseResult | null => {\n const format = detectFormat(input)\n if (!format) {\n return null\n }\n\n switch (format) {\n case 'krc':\n return parseKrc(input as string | KrcParseInput)\n case 'kwrc':\n return parseKwrc(input as string | KwrcParseInput)\n case 'lrc':\n return parseLrc(input as string | LrcParseInput, options)\n case 'qrc':\n return parseQrc(input as string | QrcParseInput, options)\n case 'ttml':\n return parseTtml(input as string, options)\n case 'yrc':\n return parseYrc(input as string | YrcParseInput, options)\n }\n}\n\ninterface GenerateOptions {\n lrc: LrcGenerateOptions\n ttml: TtmlGenerateOptions\n}\n\ninterface GenerateResults {\n lrc: LrcGenerateResult\n ttml: TtmlGenerateResult\n}\n\nexport type GenerateFormat = keyof GenerateOptions\n\nconst GENERATORS: {\n [Target in GenerateFormat]: (lyric: runtime.Lyric, options: GenerateOptions[Target]) => GenerateResults[Target]\n} = {\n lrc: generateLrc,\n ttml: generateTtml,\n}\n\n/**\n * Generates text in the requested format, which need not match `lyric.format`.\n *\n * The writer map pairs options with results only for formats that have an implemented writer.\n * An unknown target returns `null`.\n */\nexport const generate = <Target extends GenerateFormat>(\n lyric: runtime.Lyric,\n target: Target,\n options: GenerateOptions[Target] = {},\n): GenerateResults[Target] | null => {\n if (!Object.hasOwn(GENERATORS, target)) {\n return null\n }\n\n return GENERATORS[target](lyric, options)\n}\n\nexport type { ParseResult } from './result'\n\nexport type { LyricFormat } from './format'\n\nexport * from './krc'\nexport * from './kwrc'\nexport * from './lrc'\nexport * from './qrc'\nexport * from './ttml'\nexport * from './yrc'\n"],"mappings":"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"}