@dou-ui/sheet-xlsx 0.0.0-stage → 0.1.0-alpha.1
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.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.js +94 -0
- package/dist/messages.js.map +1 -0
- package/dist/read-styles.js +301 -0
- package/dist/read-styles.js.map +1 -0
- package/dist/read.js +1099 -0
- package/dist/read.js.map +1 -0
- package/dist/styles.js +124 -0
- package/dist/styles.js.map +1 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/messages.d.ts +20 -0
- package/dist/types/read-styles.d.ts +28 -0
- package/dist/types/read.d.ts +36 -0
- package/dist/types/styles.d.ts +33 -0
- package/dist/types/write.d.ts +13 -0
- package/dist/types/xml-read.d.ts +45 -0
- package/dist/types/xml.d.ts +8 -0
- package/dist/types/zip.d.ts +32 -0
- package/dist/write.js +799 -0
- package/dist/write.js.map +1 -0
- package/dist/xml-read.js +166 -0
- package/dist/xml-read.js.map +1 -0
- package/dist/xml.js +20 -0
- package/dist/xml.js.map +1 -0
- package/dist/zip.js +168 -0
- package/dist/zip.js.map +1 -0
- package/package.json +44 -4
package/dist/read.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","names":[],"sources":["../src/read.ts"],"sourcesContent":["import {\n boundsOf,\n columnName,\n linkTarget,\n parseCell,\n parseRange,\n SheetFileError,\n shiftFormula,\n type SheetCell,\n type SheetCondition,\n type SheetConditionalFormat,\n type SheetData,\n type SheetFilterRule,\n type SheetImportResult,\n type SheetImportWarning,\n type SheetProtection,\n type SheetRuleRange,\n type SheetStyle,\n type SheetValidation,\n type SheetValue,\n type SheetWorkbook,\n} from '@dou-ui/sheet/core'\nimport { dateText } from '@dou-ui/sheet/formula'\nimport {\n mergeXlsxMessages,\n sheetXlsxMessagesFor,\n type SheetXlsxMessages,\n type SheetXlsxMessagesInput,\n type SheetXlsxWarningCode,\n} from './messages'\nimport { colorOf, readStyles, themeColors, type CellLookIn } from './read-styles'\nimport {\n attrsOf,\n childOf,\n childrenOf,\n isNotOff,\n isOff,\n isOn,\n parseXml,\n XmlReader,\n type XmlNode,\n} from './xml-read'\nimport { pause, SLICE, zipFiles, type ZipFile, type ZipPacing } from './zip'\n\n/** Options of reading an .xlsx file. */\nexport interface SheetXlsxImportOptions {\n /**\n * Reads formulas; `false` reads only what they came to when the file was\n * saved, e.g. for formulas with functions this sheet doesn't have. `true`\n * by default.\n */\n formulas?: boolean\n /** Texts of the warnings and of why a file couldn't be read, in part: such as `{ warnings: { border: '框线' } }`. */\n messages?: SheetXlsxMessagesInput\n}\n\n/** What `readXlsx` takes besides the file. */\nexport interface SheetXlsxReadOptions extends SheetXlsxImportOptions {\n /** The language of the warnings and of why a file couldn't be read. */\n locale?: string\n signal?: AbortSignal\n}\n\n/** Something a file had that the sheet can't hold, as `readXlsx` lists it. */\nexport interface SheetXlsxWarning extends SheetImportWarning {\n code: SheetXlsxWarningCode\n}\n\n/** Why `readXlsx` couldn't read a file, as the `code` of its `SheetFileError`. */\nexport type SheetXlsxErrorCode = 'notXlsx' | 'damaged' | 'locked'\n\n/** What `readXlsx` gives back. */\nexport interface SheetXlsxImportResult extends SheetImportResult {\n warnings: SheetXlsxWarning[]\n}\n\nconst ERRORS: Record<SheetXlsxErrorCode, string> = {\n notXlsx: \"[@dou-ui/sheet-xlsx] The file isn't an .xlsx file.\",\n damaged: '[@dou-ui/sheet-xlsx] The file is damaged and could not be read.',\n locked: '[@dou-ui/sheet-xlsx] The file is encrypted with a password.',\n}\n\nconst decoder = new TextDecoder()\n\n/** Column widths: the characters the file counts in to px, as the file format works it out (padding included). */\nconst pxOfWidth = (width: number) => Math.trunc(((256 * width + Math.trunc(128 / 7)) / 256) * 7)\n/** Row heights: points to px. */\nconst pxOfHeight = (points: number) => Math.round(points / 0.75)\n\n/** A path a relationship points to, from the part it is in. */\nfunction resolvePath(from: string, target: string) {\n if (target.startsWith('/')) return target.slice(1)\n const parts = from.split('/').slice(0, -1)\n for (const piece of target.split('/')) {\n if (piece === '..') parts.pop()\n else if (piece !== '.') parts.push(piece)\n }\n return parts.join('/')\n}\n\n/** Where a part's relationships are: `xl/workbook.xml` keeps them in `xl/_rels/workbook.xml.rels`. */\nconst relsPath = (part: string) => {\n const slash = part.lastIndexOf('/')\n return `${part.slice(0, slash + 1)}_rels/${part.slice(slash + 1)}.rels`\n}\n\n/** Text of a run of text: `<t>`, or the `<t>` of each `<r>`. Phonetic guides are left out. */\nfunction textOf(node: XmlNode): string {\n let out = ''\n for (const child of node.children)\n if (child.name === 't') out += child.text\n else if (child.name === 'r') out += textOf(child)\n return out\n}\n\n/** Text the file escapes as `_x000D_`, back to its characters. */\nconst unescapeX = (text: string) =>\n text.includes('_x')\n ? text.replace(/_x([0-9a-f]{4})_/gi, (_, hex: string) => String.fromCharCode(parseInt(hex, 16)))\n : text\n\n/** A formula as the sheet writes it: with `=`, without the prefixes of newer functions. */\nconst formulaOf = (text: string) => `=${text.replace(/_xl(?:fn|ws)\\./g, '')}`\n\n/** A value written in a rule's formula: a number, text in quotes, `TRUE` or `FALSE`; `undefined` otherwise. */\nfunction literalOf(formula: string | undefined): SheetValue | undefined {\n if (formula == null) return undefined\n const text = formula.trim()\n if (/^-?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i.test(text)) return Number(text)\n if (/^\"(?:[^\"]|\"\")*\"$/.test(text)) return text.slice(1, -1).replaceAll('\"\"', '\"')\n if (/^true$/i.test(text)) return true\n if (/^false$/i.test(text)) return false\n return undefined\n}\n\n/** A rule's cells as the sheet writes them: one range, or several. */\nfunction rangesOf(sqref: string | undefined): SheetRuleRange | null {\n const list = (sqref ?? '').trim().split(/\\s+/).filter(Boolean)\n if (!list.length) return null\n return list.length === 1 ? list[0]! : list\n}\n\n/** The top left cell of a rule's first range, which its formula is written for. */\nfunction anchorOf(range: SheetRuleRange) {\n const first = (Array.isArray(range) ? range[0]! : range).split(':')[0]!\n return first.replaceAll('$', '')\n}\n\nconst CELL_IS: Record<string, SheetCondition['op']> = {\n equal: 'eq',\n notEqual: 'ne',\n greaterThan: 'gt',\n greaterThanOrEqual: 'ge',\n lessThan: 'lt',\n lessThanOrEqual: 'le',\n between: 'between',\n notBetween: 'notBetween',\n}\nconst COMPARE: Partial<Record<SheetCondition['op'], string>> = {\n eq: '=',\n ne: '<>',\n gt: '>',\n ge: '>=',\n lt: '<',\n le: '<=',\n}\n\n/** Where the first relationship of a kind points. */\n/** Days from 1900's day 0 to 1904's, as the two ways of counting dates differ. */\nconst DAYS_1904 = 1462\n\n/** Whether an older-style container holds an encrypted workbook, by its `EncryptionInfo` stream's name. */\nfunction hasEncryptionInfo(bytes: Uint8Array) {\n const name = [...'EncryptionInfo'].flatMap((ch) => [ch.charCodeAt(0), 0])\n for (let i = bytes.indexOf(name[0]!); i !== -1; i = bytes.indexOf(name[0]!, i + 1)) {\n let j = 1\n while (j < name.length && bytes[i + j] === name[j]) j++\n if (j === name.length) return true\n }\n return false\n}\n\n/** What sets a run of text apart from another, leaving out its typeface. */\nfunction runLook(run: XmlNode) {\n const props = childOf(run, 'rPr')\n if (!props) return ''\n return ['b', 'i', 'u', 'strike', 'color', 'sz']\n .map((part) => {\n const node = childOf(props, part)\n return node ? `${part}${JSON.stringify(node.attrs)}` : ''\n })\n .join('')\n}\n\n/** Whether a string's runs differ in more than their typeface, as text mixing scripts is split by font. */\nfunction hasRichRuns(si: XmlNode) {\n const runs = childrenOf(si, 'r')\n return runs.length > 1 && new Set(runs.map(runLook)).size > 1\n}\n\nconst ofType = (rels: Map<string, { path: string; type: string }>, type: string) =>\n [...rels.values()].find((rel) => rel.type.endsWith(`/${type}`))?.path\n\n/** Reads the file's warnings up, by what was lost and on which sheet. */\nclass Warnings {\n private list = new Map<string, SheetXlsxWarning>()\n constructor(private readonly messages: SheetXlsxMessages) {}\n add(code: SheetXlsxWarningCode, sheet?: string, count = 1) {\n if (count <= 0) return\n const key = `${code}\\u0000${sheet ?? ''}`\n const warning = this.list.get(key)\n if (warning) warning.count = (warning.count ?? 1) + count\n else\n this.list.set(key, {\n code,\n message: this.messages.warnings[code],\n count,\n ...(sheet == null ? {} : { sheet }),\n })\n }\n get all() {\n return [...this.list.values()]\n }\n}\n\n/**\n * Reads an .xlsx file as a workbook: values, formulas, number formats,\n * styles, merges, frozen panes, sizes, hidden rows and columns, groups,\n * notes, data validations, conditional formats and filters. What it can't\n * bring over, such as borders or charts, is listed in `warnings`.\n */\nexport async function readXlsx(\n file: Blob | ArrayBuffer | Uint8Array,\n options: SheetXlsxReadOptions = {},\n): Promise<SheetXlsxImportResult> {\n const messages = mergeXlsxMessages(sheetXlsxMessagesFor(options.locale), options.messages)\n /** Why the file can't be read: for developers in `message`, for people in `reason`. */\n const failed = (code: SheetXlsxErrorCode, cause?: unknown) =>\n new SheetFileError(ERRORS[code], code, messages[code], cause ? { cause } : undefined)\n const { signal } = options\n const bytes =\n file instanceof Uint8Array\n ? file\n : new Uint8Array(file instanceof ArrayBuffer ? file : await file.arrayBuffer())\n signal?.throwIfAborted()\n // a file with a password is kept in another kind of container, as are older .xls files\n if (bytes[0] === 0xd0 && bytes[1] === 0xcf && bytes[2] === 0x11 && bytes[3] === 0xe0)\n throw failed(hasEncryptionInfo(bytes) ? 'locked' : 'notXlsx')\n if (bytes[0] !== 0x50 || bytes[1] !== 0x4b) throw failed('notXlsx')\n let files: Map<string, ZipFile>\n try {\n files = zipFiles(bytes)\n } catch (error) {\n throw failed('damaged', error)\n }\n const pacing: ZipPacing = { signal, lastPause: { at: performance.now() } }\n const readText = async (path: string) => {\n const entry = files.get(path)\n if (!entry) return undefined\n try {\n return decoder.decode(await entry.read(pacing))\n } catch (error) {\n if (signal?.aborted || String(error).includes('CompressionStream')) throw error\n throw failed('damaged', error)\n }\n }\n const readNode = async (path: string | undefined) => {\n const text = path ? await readText(path) : undefined\n return text == null ? undefined : parseXml(text)\n }\n /** A part's relationships by id: where each points and what kind it is. */\n const relsOf = async (part: string) => {\n const out = new Map<string, { path: string; type: string; external: boolean }>()\n const rels = await readNode(relsPath(part))\n for (const rel of childrenOf(rels, 'Relationship')) {\n const external = rel.attrs.TargetMode === 'External'\n out.set(rel.attrs.Id ?? '', {\n path: external ? (rel.attrs.Target ?? '') : resolvePath(part, rel.attrs.Target ?? ''),\n type: rel.attrs.Type ?? '',\n external,\n })\n }\n return out\n }\n\n const root = await relsOf('')\n const workbookPath =\n [...root.values()].find((rel) => rel.type.endsWith('/officeDocument'))?.path ??\n 'xl/workbook.xml'\n const workbook = await readNode(workbookPath)\n if (!workbook || workbook.name !== 'workbook') throw failed('notXlsx')\n const workbookRels = await relsOf(workbookPath)\n const warnings = new Warnings(messages)\n\n const theme = themeColors(await readNode(ofType(workbookRels, 'theme')))\n const { looks, differentials } = readStyles(await readNode(ofType(workbookRels, 'styles')), theme)\n\n // shared strings, and whether any had formatting in parts\n const strings: string[] = []\n const stringsXML = await readNode(ofType(workbookRels, 'sharedStrings'))\n const richText = new Set<number>()\n for (const [i, si] of childrenOf(stringsXML, 'si').entries()) {\n strings.push(unescapeX(textOf(si)))\n if (hasRichRuns(si)) richText.add(i)\n }\n\n // whole-workbook things the sheet doesn't have\n for (const path of files.keys()) {\n if (/^xl\\/vbaProject\\.bin$/i.test(path)) warnings.add('macro')\n if (/^xl\\/pivotTables\\/[^/]+\\.xml$/i.test(path)) warnings.add('pivot')\n }\n for (const name of childrenOf(childOf(workbook, 'definedNames'), 'definedName'))\n if (!name.attrs.name?.startsWith('_xlnm.')) warnings.add('name')\n // dates counted from 1904 rather than 1900, as files from some computers are\n const date1904 = isOn(childOf(workbook, 'workbookPr')?.attrs.date1904)\n // tables' names, so formulas that refer to them by name can be told apart\n const tableNames: string[] = []\n for (const path of files.keys()) {\n if (!/^xl\\/tables\\/[^/]+\\.xml$/i.test(path)) continue\n const table = await readNode(path)\n for (const key of ['name', 'displayName'] as const) {\n const tableName = table?.attrs[key]\n if (tableName && !tableNames.includes(tableName)) tableNames.push(tableName)\n }\n }\n const tableRef = tableNames.length\n ? new RegExp(\n `(?:^|[^\\\\w.])(?:${tableNames.map((n) => n.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})\\\\[`,\n 'i',\n )\n : null\n\n // named styles, one for each different look the cells use\n const styleNames = new Map<string, string>()\n const styles: Record<string, SheetStyle> = {}\n const styleName = (look: CellLookIn) => {\n if (!look.key) return undefined\n let name = styleNames.get(look.key)\n if (!name) {\n name = `style${styleNames.size + 1}`\n styleNames.set(look.key, name)\n styles[name] = look.style!\n }\n return name\n }\n\n const sheets: SheetData[] = []\n const keepFormulas = options.formulas !== false\n for (const sheetNode of childrenOf(childOf(workbook, 'sheets'), 'sheet')) {\n signal?.throwIfAborted()\n const name = sheetNode.attrs.name ?? `Sheet${sheets.length + 1}`\n const rel = workbookRels.get(sheetNode.attrs.id ?? '')\n if (!rel || !rel.type.endsWith('/worksheet')) {\n // a sheet that is only a chart\n if (rel?.type.endsWith('/chartsheet')) warnings.add('chart', name)\n continue\n }\n if (sheetNode.attrs.state === 'hidden' || sheetNode.attrs.state === 'veryHidden')\n warnings.add('hiddenSheet', name)\n const xml = await readText(rel.path)\n if (xml == null) throw failed('damaged')\n const sheetRels = await relsOf(rel.path)\n const { data, links, passwords } = await readSheet(xml, name, {\n strings,\n richText,\n looks,\n differentials,\n styleName,\n keepFormulas,\n warnings,\n pacing,\n date1904,\n tableRef,\n })\n warnings.add('hyperlink', name, addLinks(data, links, sheetRels))\n warnings.add('password', name, passwords)\n // notes, kept in another part\n const comments = await readNode(ofType(sheetRels, 'comments'))\n if (comments) addNotes(data, comments)\n for (const { type, path } of sheetRels.values()) {\n if (type.endsWith('/drawing')) {\n const drawing = await relsOf(path)\n for (const { type: kind } of drawing.values())\n if (kind.endsWith('/chart')) warnings.add('chart', name)\n else if (kind.endsWith('/image')) warnings.add('image', name)\n }\n if (type.endsWith('/pivotTable')) warnings.add('pivot', name)\n if (type.endsWith('/table')) warnings.add('table', name)\n }\n sheets.push(data)\n }\n if (!sheets.length) sheets.push({ name: 'Sheet1', cells: [] })\n const book: SheetWorkbook = { version: 1, sheets }\n if (styleNames.size) book.styles = styles\n const lock = childOf(workbook, 'workbookProtection')\n if (lock && isOn(lock.attrs.lockStructure)) {\n book.protect = true\n const a = lock.attrs\n if (a.workbookPassword || a.workbookHashValue) warnings.add('password')\n }\n signal?.throwIfAborted()\n return { book, warnings: warnings.all }\n}\n\ninterface SheetContext {\n strings: string[]\n richText: Set<number>\n looks: CellLookIn[]\n differentials: SheetStyle[]\n styleName: (look: CellLookIn) => string | undefined\n keepFormulas: boolean\n warnings: Warnings\n pacing: ZipPacing\n /** Dates counted from 1904. */\n date1904: boolean\n /** Matches formulas that refer to a table by name; `null` when the file has none. */\n tableRef: RegExp | null\n}\n\n/** One sheet's part, read a piece at a time. */\nasync function readSheet(\n xml: string,\n name: string,\n context: SheetContext,\n): Promise<{ data: SheetData; links: Record<string, string>[]; passwords: number }> {\n const { strings, richText, looks, differentials, styleName, keepFormulas, warnings, pacing } =\n context\n const { date1904, tableRef } = context\n const dateOf = (serial: number) => dateText(date1904 ? serial + DAYS_1904 : serial)\n const data: SheetData = { name, cells: [] }\n const cells = data.cells\n const rowSizes: Record<number, number> = {}\n const hiddenRows = new Set<number>()\n const rowLevels = new Map<number, number>()\n const colSizes: Record<number, number> = {}\n const hiddenCols = new Set<number>()\n const colLevels = new Map<number, number>()\n const merges: string[] = []\n let summaryAfter = true\n let borders = 0\n let fonts = 0\n let rich = 0\n let external = 0\n let tableFormulas = 0\n const links: Record<string, string>[] = []\n let passwords = 0\n const dates = new Map<number, string>()\n const times = new Map<number, string>()\n // shared formulas by number: their text and the cell they were written for\n const sharedFormulas = new Map<string, { formula: string; row: number; col: number }>()\n\n // the cell being read\n let row = -1\n let col = -1\n let kind = ''\n let look: CellLookIn | undefined\n let value = ''\n let inlineText = ''\n let formula: string | null = null\n let formulaAttrs: Record<string, string> | null = null\n let reading: 'v' | 'f' | 't' | null = null\n let inInline = false\n let inPhonetic = false\n // where we are outside the cells\n let skip = 0\n type FilterState = { range: string; left: number; columns: Record<number, SheetFilterRule> }\n // set while reading, out of the type checker's sight\n let filter = null as FilterState | null\n let filterCol: {\n id: number\n values: string[]\n blank: boolean\n custom: { op?: string; val: string }[]\n and: boolean\n other: boolean\n } | null = null\n const conditional: { priority: number; rule: SheetConditionalFormat }[] = []\n let cfRange: SheetRuleRange | null = null\n let cfRule: {\n attrs: Record<string, string>\n formulas: string[]\n colors: (string | undefined)[]\n } | null = null\n const validations: SheetValidation[] = []\n let validation: { attrs: Record<string, string>; formula1?: string; formula2?: string } | null =\n null\n let text = ''\n\n const finishCell = () => {\n let content: SheetValue = null\n if (kind === 's') {\n const index = +value\n content = strings[index] ?? ''\n if (richText.has(index)) rich++\n } else if (kind === 'inlineStr') content = unescapeX(inlineText)\n else if (kind === 'str') content = unescapeX(value)\n else if (kind === 'b') content = isOn(value)\n else if (kind === 'e') content = value\n else if (kind === 'd') {\n const date = /^(\\d{4}-\\d{2}-\\d{2})(?:T(\\d{2}:\\d{2}(?::\\d{2})?))?/.exec(value)\n content = date\n ? date[2] && date[2] !== '00:00:00'\n ? `${date[1]} ${date[2].replace(/:00$/, '')}`\n : date[1]!\n : value\n } else if (value !== '') {\n const number = Number(value)\n content = Number.isFinite(number) ? number : value\n }\n\n // text that reads as a formula stays text\n if (typeof content === 'string' && content.startsWith('=') && !formula) content = `'${content}`\n let format = look?.format\n if (typeof content === 'number' && look && look.kind !== 'number') {\n const serial = content\n const time = look.kind === 'time' && serial < 1\n // dates repeat a lot in a column: each one's text worked out once\n let shown = (time ? times : dates).get(serial)\n if (shown == null) {\n shown = time ? timeText(serial) : dateOf(serial)\n if (dates.size + times.size < 100_000) (time ? times : dates).set(serial, shown)\n }\n content = shown\n // the format the sheet gives such a date anyway isn't kept\n if (format && sameAsPlain(format, content)) format = undefined\n }\n // some programs write TRUE and FALSE as the functions that give them\n if (kind === 'b' && formula != null && /^(TRUE|FALSE)\\(\\)$/i.test(formula)) formula = null\n if (formula != null && keepFormulas) {\n if (/\\[\\d+\\]/.test(formula)) external++\n // the sheet has no tables to look into: the result the file kept stays\n else if (tableRef?.test(formula)) tableFormulas++\n else content = formulaOf(formula)\n }\n if (look?.border) borders++\n if (look?.font) fonts++\n const style = look ? styleName(look) : undefined\n if (content === null && !style && !format) return\n const line = (cells[row] ??= [])\n line[col] = style || format ? compact({ value: content, style, format }) : content\n }\n\n const handler = {\n open(tag: string, raw: string, empty: boolean) {\n if (skip) {\n if (!empty) skip++\n return\n }\n switch (tag) {\n case 'extLst':\n if (!empty) skip = 1\n return\n case 'row': {\n const a = attrsOf(raw)\n row = a.r ? +a.r - 1 : row + 1\n col = -1\n if (isOn(a.customHeight) && a.ht) rowSizes[row] = pxOfHeight(+a.ht)\n if (isOn(a.hidden)) hiddenRows.add(row)\n if (a.outlineLevel && +a.outlineLevel > 0) rowLevels.set(row, +a.outlineLevel)\n break\n }\n case 'c': {\n const a = attrsOf(raw)\n if (a.r) {\n const point = parseCell(a.r)\n if (point) {\n row = point.row\n col = point.col\n } else col++\n } else col++\n kind = a.t ?? 'n'\n look = a.s ? looks[+a.s] : looks[0]\n if (look && !look.style && !look.format && !look.border && !look.font && !look.quote)\n look = undefined\n value = ''\n inlineText = ''\n formula = null\n formulaAttrs = null\n if (empty) finishCell()\n break\n }\n case 'v':\n reading = 'v'\n value = ''\n break\n case 'f':\n formulaAttrs = attrsOf(raw)\n reading = 'f'\n formula = ''\n if (empty) closeFormula()\n break\n case 'is':\n inInline = true\n break\n case 'rPh':\n inPhonetic = true\n break\n case 't':\n if (inInline && !inPhonetic) reading = 't'\n else text = ''\n break\n case 'outlinePr': {\n const a = attrsOf(raw)\n summaryAfter = isNotOff(a.summaryBelow)\n break\n }\n case 'pane': {\n const a = attrsOf(raw)\n if (a.state === 'frozen' || a.state === 'frozenSplit') {\n const rows = Math.round(+(a.ySplit ?? 0))\n const cols = Math.round(+(a.xSplit ?? 0))\n if (rows || cols) data.freeze = { ...(rows ? { rows } : {}), ...(cols ? { cols } : {}) }\n }\n break\n }\n case 'col': {\n const a = attrsOf(raw)\n const min = +(a.min ?? 1) - 1\n const max = Math.min(+(a.max ?? a.min ?? 1) - 1, 16_383)\n const hidden = isOn(a.hidden)\n const level = a.outlineLevel ? +a.outlineLevel : 0\n // a width for all the columns at once is the sheet's, not theirs\n const sized = isOn(a.customWidth) && a.width != null && max - min < 256\n for (let c = min; c <= max; c++) {\n if (sized) colSizes[c] = pxOfWidth(+a.width!)\n if (hidden) hiddenCols.add(c)\n if (level > 0) colLevels.set(c, level)\n }\n break\n }\n case 'mergeCell': {\n const ref = attrsOf(raw).ref\n if (ref) merges.push(ref)\n break\n }\n case 'autoFilter': {\n const ref = attrsOf(raw).ref\n if (ref) {\n const start = parseCell(ref.split(':')[0]!)\n filter = { range: ref, left: start?.col ?? 0, columns: {} }\n }\n break\n }\n case 'filterColumn':\n filterCol = {\n id: +(attrsOf(raw).colId ?? 0),\n values: [],\n blank: false,\n custom: [],\n and: false,\n other: false,\n }\n break\n case 'filters':\n if (filterCol) filterCol.blank = isOn(attrsOf(raw).blank)\n break\n case 'filter':\n filterCol?.values.push(attrsOf(raw).val ?? '')\n break\n case 'customFilters':\n if (filterCol) filterCol.and = isOn(attrsOf(raw).and)\n break\n case 'customFilter': {\n const a = attrsOf(raw)\n filterCol?.custom.push({ op: a.operator, val: a.val ?? '' })\n break\n }\n case 'top10':\n case 'dynamicFilter':\n case 'colorFilter':\n case 'iconFilter':\n case 'dateGroupItem':\n if (filterCol) filterCol.other = true\n break\n case 'conditionalFormatting':\n cfRange = rangesOf(attrsOf(raw).sqref)\n break\n case 'cfRule':\n cfRule = { attrs: attrsOf(raw), formulas: [], colors: [] }\n if (empty) closeRule()\n break\n case 'formula':\n case 'formula1':\n case 'formula2':\n text = ''\n break\n case 'color':\n if (cfRule)\n cfRule.colors.push(\n colorOf({ name: 'color', attrs: attrsOf(raw), children: [], text: '' }, []),\n )\n break\n case 'dataValidation':\n validation = { attrs: attrsOf(raw) }\n if (empty) closeValidation()\n break\n case 'hyperlink':\n links.push(attrsOf(raw))\n break\n case 'sheetProtection': {\n const a = attrsOf(raw)\n if (!isOn(a.sheet)) break\n // in the file each part says what is kept from people, so `0` allows it\n const allow: SheetProtection = {}\n for (const [key, part] of PROTECTION_PARTS) if (isOff(a[key])) allow[part] = true\n data.protect = Object.keys(allow).length ? allow : true\n if (a.password || a.hashValue) passwords++\n break\n }\n }\n },\n close(tag: string) {\n if (skip) {\n skip--\n return\n }\n switch (tag) {\n case 'c':\n finishCell()\n break\n case 'v':\n case 't':\n if (reading === 'v' || reading === 't') reading = null\n break\n case 'f':\n closeFormula()\n break\n case 'is':\n inInline = false\n break\n case 'rPh':\n inPhonetic = false\n break\n case 'formula':\n cfRule?.formulas.push(text)\n break\n case 'formula1':\n if (validation) validation.formula1 = text\n break\n case 'formula2':\n if (validation) validation.formula2 = text\n break\n case 'filterColumn':\n closeFilterColumn()\n break\n case 'cfRule':\n closeRule()\n break\n case 'dataValidation':\n closeValidation()\n break\n }\n },\n text(chunk: string) {\n if (skip) return\n if (reading === 'v') value += chunk\n else if (reading === 'f') formula += chunk\n else if (reading === 't') inlineText += chunk\n else text += chunk\n },\n }\n\n function closeFormula() {\n reading = null\n const a = formulaAttrs ?? {}\n let written = formula ?? ''\n if (a.t === 'shared' && a.si != null) {\n const master = sharedFormulas.get(a.si)\n if (written) sharedFormulas.set(a.si, { formula: written, row, col })\n else if (master)\n written = shiftFormula(`=${master.formula}`, row - master.row, col - master.col).slice(1)\n }\n // a table of what-ifs: only its results come over\n formula = written && a.t !== 'dataTable' ? written : null\n }\n\n function closeFilterColumn() {\n const column = filterCol\n filterCol = null\n if (!filter || !column) return\n const at = filter.left + column.id\n if (column.other) {\n warnings.add('filter', name)\n return\n }\n if (column.values.length || column.blank) {\n filter.columns[at] = { values: [...column.values, ...(column.blank ? [''] : [])] }\n return\n }\n const condition = filterCondition(column.custom, column.and)\n if (condition) filter.columns[at] = { condition }\n else if (column.custom.length) warnings.add('filter', name)\n }\n\n function closeRule() {\n const rule = cfRule\n cfRule = null\n if (!rule || !cfRange) return\n const made = conditionalOf(rule, cfRange, differentials)\n if (made) conditional.push({ priority: +(rule.attrs.priority ?? 0), rule: made })\n else warnings.add('conditional', name)\n }\n\n function closeValidation() {\n const rule = validation\n validation = null\n if (!rule) return\n const made = validationOf(rule, dateOf)\n if (made) validations.push(made)\n else if (rule.attrs.type && rule.attrs.type !== 'none') warnings.add('validation', name)\n }\n\n const reader = new XmlReader(xml, handler)\n while (reader.step(20_000)) {\n if (performance.now() - pacing.lastPause.at > SLICE) {\n await pause()\n pacing.signal?.throwIfAborted()\n pacing.lastPause.at = performance.now()\n }\n }\n\n // rows a filter hides aren't hidden for good: the filter hides them again\n const filtered = filter && Object.keys(filter.columns).length ? filter : null\n const filterRows = filtered ? rowSpan(filtered.range) : null\n const rowGroups = groupsOf(rowLevels, hiddenRows, (a, b) => `${a + 1}:${b + 1}`)\n const colGroups = groupsOf(colLevels, hiddenCols, (a, b) => `${columnName(a)}:${columnName(b)}`)\n for (const r of hiddenRows) {\n if (rowGroups.folded.has(r)) continue\n if (filterRows && r > filterRows[0] && r <= filterRows[1]) continue\n rowSizes[r] = 0\n }\n for (const c of hiddenCols) if (!colGroups.folded.has(c)) colSizes[c] = 0\n\n if (Object.keys(rowSizes).length) data.rowSizes = rowSizes\n if (Object.keys(colSizes).length) data.colSizes = colSizes\n if (merges.length) data.merges = merges\n const groups = [...rowGroups.groups, ...colGroups.groups]\n if (groups.length) {\n data.groups = groups\n if (!summaryAfter) data.groupSummary = 'before'\n else data.groupSummary = 'after'\n }\n if (filter)\n data.filter = Object.keys(filter.columns).length\n ? { range: filter.range, columns: filter.columns }\n : { range: filter.range }\n if (conditional.length)\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts the list built here\n data.conditionalFormats = conditional.sort((a, b) => a.priority - b.priority).map((c) => c.rule)\n if (validations.length) data.validations = validations\n warnings.add('border', name, borders)\n warnings.add('font', name, fonts)\n warnings.add('richText', name, rich)\n warnings.add('external', name, external)\n warnings.add('table', name, tableFormulas)\n return { data, links, passwords }\n}\n\n/** The parts of a sheet's protection in the file, with the names the sheet gives them. */\nconst PROTECTION_PARTS: [string, keyof SheetProtection][] = [\n ['formatCells', 'formatCells'],\n ['formatColumns', 'formatColumns'],\n ['formatRows', 'formatRows'],\n ['insertColumns', 'insertColumns'],\n ['insertRows', 'insertRows'],\n ['deleteColumns', 'deleteColumns'],\n ['deleteRows', 'deleteRows'],\n ['autoFilter', 'filter'],\n]\n\n/**\n * Puts a sheet's links on their cells: a web address from the sheet's\n * relationships, a place in the workbook as `#` and its reference. Gives\n * how many couldn't be kept, such as links to other files.\n */\nfunction addLinks(\n data: SheetData,\n links: Record<string, string>[],\n rels: Map<string, { path: string; external: boolean }>,\n) {\n let dropped = 0\n for (const a of links) {\n const rel = a.id ? rels.get(a.id) : undefined\n const place = a.location ? `#${a.location}` : ''\n const link = rel ? (rel.external ? rel.path + place : '') : place\n const range = a.ref ? parseRange(a.ref) : null\n if (!range || !link || !linkTarget(link)) {\n dropped++\n continue\n }\n const b = boundsOf(range)\n // a link over many cells is each one's; a whole column's stays with its first cells\n const bottom = Math.min(b.bottom, b.top + 999)\n for (let r = b.top; r <= bottom; r++)\n for (let c = b.left; c <= b.right && c <= b.left + 99; c++) {\n const line = (data.cells[r] ??= [])\n const cell = line[c]\n line[c] =\n cell != null && typeof cell === 'object'\n ? { ...cell, link }\n : cell == null || cell === ''\n ? { link }\n : { value: cell, link }\n }\n }\n return dropped\n}\n\n/** A cell with only what it has. */\nfunction compact(cell: SheetCell): SheetCell {\n const out: SheetCell = {}\n if (cell.value != null) out.value = cell.value\n if (cell.style) out.style = cell.style\n if (cell.format) out.format = cell.format\n return out\n}\n\n/** Whether a date's format is the one the sheet would show it with anyway. */\nfunction sameAsPlain(format: string, text: string) {\n const plain =\n text.length === 10\n ? 'yyyy-mm-dd'\n : text.length === 5\n ? 'hh:mm'\n : text.length === 8\n ? 'hh:mm:ss'\n : text.length === 16\n ? 'yyyy-mm-dd hh:mm'\n : 'yyyy-mm-dd hh:mm:ss'\n return format.toLowerCase() === plain\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0')\n\n/** A part of a day as `hh:mm`, or `hh:mm:ss` with seconds. */\nfunction timeText(fraction: number) {\n const seconds = Math.round(fraction * 86_400) % 86_400\n const time = `${pad(Math.floor(seconds / 3600))}:${pad(Math.floor((seconds % 3600) / 60))}`\n return seconds % 60 ? `${time}:${pad(seconds % 60)}` : time\n}\n\n/** The first and last row of a range such as `A1:E40`. */\nfunction rowSpan(range: string): [number, number] | null {\n const [from, to] = range.split(':')\n const start = from ? parseCell(from) : null\n const end = to ? parseCell(to) : start\n return start && end ? [start.row, end.row] : null\n}\n\n/**\n * The groups of lines with outline levels: each run of lines at a level or\n * deeper is a group. A group whose lines are all hidden is folded.\n */\nfunction groupsOf(\n levels: Map<number, number>,\n hidden: Set<number>,\n rangeOf: (start: number, end: number) => string,\n) {\n const groups: { range: string; collapsed?: boolean }[] = []\n const folded = new Set<number>()\n if (!levels.size) return { groups, folded }\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts the list built here\n const lines = [...levels.keys()].sort((a, b) => a - b)\n let deepest = 0\n for (const level of levels.values()) if (level > deepest) deepest = level\n for (let level = 1; level <= deepest; level++) {\n let start = -1\n let prev = -2\n const close = () => {\n if (start < 0) return\n let all = true\n for (let i = start; i <= prev; i++) if (!hidden.has(i)) all = false\n if (all) for (let i = start; i <= prev; i++) folded.add(i)\n groups.push(\n all ? { range: rangeOf(start, prev), collapsed: true } : { range: rangeOf(start, prev) },\n )\n }\n for (const line of lines) {\n if (levels.get(line)! < level) continue\n if (line !== prev + 1) {\n close()\n start = line\n }\n prev = line\n }\n close()\n }\n return { groups, folded }\n}\n\n/** A value typed in a filter or a list: a number when it reads as one. */\nconst typedValue = (val: string): SheetValue =>\n /^-?(\\d+\\.?\\d*|\\.\\d+)$/.test(val.trim()) ? Number(val) : val\n\n/** A filter's custom conditions as one condition, `null` when the sheet has none like them. */\nfunction filterCondition(\n custom: { op?: string; val: string }[],\n and: boolean,\n): SheetCondition | null {\n if (custom.length === 1) {\n const { op = 'equal', val } = custom[0]!\n const wild = /^\\*(.*)\\*$/.exec(val)\n if (op === 'equal' || op === 'notEqual') {\n const not = op === 'notEqual'\n if (not && val === ' ') return { op: 'notBlank' }\n if (wild && !wild[1]!.includes('*'))\n return { op: not ? 'notContains' : 'contains', value: wild[1]! }\n if (!not && /^[^*]+\\*$/.test(val)) return { op: 'begins', value: val.slice(0, -1) }\n if (!not && /^\\*[^*]+$/.test(val)) return { op: 'ends', value: val.slice(1) }\n if (val.includes('*') || val.includes('?')) return null\n return { op: not ? 'ne' : 'eq', value: typedValue(val) }\n }\n const ops: Record<string, SheetCondition['op']> = {\n greaterThan: 'gt',\n greaterThanOrEqual: 'ge',\n lessThan: 'lt',\n lessThanOrEqual: 'le',\n }\n return ops[op] ? { op: ops[op], value: typedValue(val) } : null\n }\n if (custom.length === 2) {\n const [a, b] = custom as [{ op?: string; val: string }, { op?: string; val: string }]\n if (and && a.op === 'greaterThanOrEqual' && b.op === 'lessThanOrEqual')\n return { op: 'between', value: typedValue(a.val), to: typedValue(b.val) }\n if (!and && a.op === 'lessThan' && b.op === 'greaterThan')\n return { op: 'notBetween', value: typedValue(a.val), to: typedValue(b.val) }\n }\n return null\n}\n\n/** A conditional format's rule as the sheet's, `null` for one it has none like. */\nfunction conditionalOf(\n rule: { attrs: Record<string, string>; formulas: string[]; colors: (string | undefined)[] },\n range: SheetRuleRange,\n differentials: SheetStyle[],\n): SheetConditionalFormat | null {\n const { attrs, formulas } = rule\n const style = differentials[+(attrs.dxfId ?? -1)] ?? {}\n const anchor = anchorOf(range)\n switch (attrs.type) {\n case 'cellIs': {\n const op = CELL_IS[attrs.operator ?? 'between']\n if (!op) return null\n const value = literalOf(formulas[0])\n const to = literalOf(formulas[1])\n const two = op === 'between' || op === 'notBetween'\n if (value !== undefined && (!two || to !== undefined))\n return { range, when: two ? { op, value, to } : { op, value }, style }\n // compared with other cells: as a formula on the top left cell\n if (!formulas[0]) return null\n if (two) {\n if (!formulas[1]) return null\n const inside = `AND(${anchor}>=${formulas[0]},${anchor}<=${formulas[1]})`\n return { range, formula: `=${op === 'between' ? inside : `NOT(${inside})`}`, style }\n }\n return { range, formula: `=${anchor}${COMPARE[op]}${formulas[0]}`, style }\n }\n case 'containsText':\n case 'notContainsText':\n case 'beginsWith':\n case 'endsWith': {\n const ops = {\n containsText: 'contains',\n notContainsText: 'notContains',\n beginsWith: 'begins',\n endsWith: 'ends',\n } as const\n if (attrs.text == null) break\n return { range, when: { op: ops[attrs.type], value: attrs.text }, style }\n }\n case 'containsBlanks':\n return { range, when: { op: 'blank' }, style }\n case 'notContainsBlanks':\n return { range, when: { op: 'notBlank' }, style }\n case 'expression':\n return formulas[0] ? { range, formula: formulaOf(formulas[0]), style } : null\n case 'top10': {\n const rank = +(attrs.rank ?? 10)\n const percent = isOn(attrs.percent) ? { percent: true } : {}\n return isOn(attrs.bottom)\n ? { range, bottom: rank, ...percent, style }\n : { range, top: rank, ...percent, style }\n }\n case 'aboveAverage':\n if (attrs.stdDev != null) return null\n return { range, average: !isNotOff(attrs.aboveAverage) ? 'below' : 'above', style }\n case 'duplicateValues':\n return { range, duplicates: true, style }\n case 'uniqueValues':\n return { range, unique: true, style }\n case 'colorScale': {\n const colors = rule.colors.map((c) => c ?? '#ffffff')\n if (colors.length === 2) return { range, scale: [colors[0]!, colors[1]!] }\n if (colors.length === 3) return { range, scale: [colors[0]!, colors[1]!, colors[2]!] }\n return null\n }\n case 'dataBar':\n return { range, bar: rule.colors[0] ?? true }\n }\n // others with a formula, such as cells with errors, keep it\n return formulas[0] ? { range, formula: formulaOf(formulas[0]), style } : null\n}\n\n/** A data validation as the sheet's, `null` for one it has none like. */\nfunction validationOf(\n rule: {\n attrs: Record<string, string>\n formula1?: string\n formula2?: string\n },\n dateOf: (serial: number) => string,\n): SheetValidation | null {\n const { attrs, formula1, formula2 } = rule\n const range = rangesOf(attrs.sqref)\n if (!range || formula1 == null) return null\n const common = {\n range,\n ...(attrs.errorStyle === 'warning' || attrs.errorStyle === 'information'\n ? { strict: false }\n : {}),\n ...(attrs.error ? { message: attrs.error } : {}),\n ...(attrs.prompt ? { prompt: attrs.prompt } : {}),\n }\n switch (attrs.type) {\n case 'list': {\n const inline = /^\"(.*)\"$/s.exec(formula1.trim())\n if (!inline) return { ...common, list: formulaOf(formula1) }\n const list = inline[1]!.split(',').map(typedValue)\n return { ...common, list }\n }\n case 'custom':\n return { ...common, formula: formulaOf(formula1) }\n case 'whole':\n case 'decimal':\n case 'date':\n case 'time': {\n const op = CELL_IS[attrs.operator ?? 'between']\n const date = attrs.type === 'date' || attrs.type === 'time'\n const valueOf = (formula: string | undefined) => {\n const value = literalOf(formula)\n if (typeof value !== 'number') return undefined\n return date ? (attrs.type === 'time' ? timeText(value) : dateOf(value)) : value\n }\n const value = valueOf(formula1)\n const to = valueOf(formula2)\n if (!op || value === undefined) return null\n if (op === 'between' || op === 'notBetween') {\n if (to === undefined) return null\n return {\n ...common,\n when: { op, value, to },\n ...(attrs.type === 'whole' ? { integer: true } : {}),\n }\n }\n return {\n ...common,\n when: { op, value },\n ...(attrs.type === 'whole' ? { integer: true } : {}),\n }\n }\n }\n return null\n}\n\n/** Adds a sheet's notes to its cells. */\nfunction addNotes(data: SheetData, comments: XmlNode) {\n const authors = childrenOf(childOf(comments, 'authors'), 'author').map((a) => a.text)\n for (const comment of childrenOf(childOf(comments, 'commentList'), 'comment')) {\n const point = parseCell(comment.attrs.ref ?? '')\n const body = childOf(comment, 'text')\n if (!point || !body) continue\n let note = unescapeX(textOf(body))\n // other programs put the author's name first, on a line of its own\n const author = authors[+(comment.attrs.authorId ?? -1)]\n if (author && note.startsWith(`${author}:`))\n note = note.slice(author.length + 1).replace(/^\\r?\\n/, '')\n if (!note) continue\n const line = (data.cells[point.row] ??= [])\n const input = line[point.col]\n line[point.col] =\n input != null && typeof input === 'object'\n ? { ...input, note }\n : { ...(input == null ? {} : { value: input }), note }\n }\n}\n"],"mappings":";;;;;;;AA4EA,IAAM,SAA6C;CACjD,SAAS;CACT,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,UAAU,IAAI,YAAY;;AAGhC,IAAM,aAAa,UAAkB,KAAK,OAAQ,MAAM,QAAQ,KAAK,MAAM,MAAM,CAAC,KAAK,MAAO,CAAC;;AAE/F,IAAM,cAAc,WAAmB,KAAK,MAAM,SAAS,GAAI;;AAG/D,SAAS,YAAY,MAAc,QAAgB;CACjD,IAAI,OAAO,WAAW,GAAG,GAAG,OAAO,OAAO,MAAM,CAAC;CACjD,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE;CACzC,KAAK,MAAM,SAAS,OAAO,MAAM,GAAG,GAClC,IAAI,UAAU,MAAM,MAAM,IAAI;MACzB,IAAI,UAAU,KAAK,MAAM,KAAK,KAAK;CAE1C,OAAO,MAAM,KAAK,GAAG;AACvB;;AAGA,IAAM,YAAY,SAAiB;CACjC,MAAM,QAAQ,KAAK,YAAY,GAAG;CAClC,OAAO,GAAG,KAAK,MAAM,GAAG,QAAQ,CAAC,EAAE,QAAQ,KAAK,MAAM,QAAQ,CAAC,EAAE;AACnE;;AAGA,SAAS,OAAO,MAAuB;CACrC,IAAI,MAAM;CACV,KAAK,MAAM,SAAS,KAAK,UACvB,IAAI,MAAM,SAAS,KAAK,OAAO,MAAM;MAChC,IAAI,MAAM,SAAS,KAAK,OAAO,OAAO,KAAK;CAClD,OAAO;AACT;;AAGA,IAAM,aAAa,SACjB,KAAK,SAAS,IAAI,IACd,KAAK,QAAQ,uBAAuB,GAAG,QAAgB,OAAO,aAAa,SAAS,KAAK,EAAE,CAAC,CAAC,IAC7F;;AAGN,IAAM,aAAa,SAAiB,IAAI,KAAK,QAAQ,mBAAmB,EAAE;;AAG1E,SAAS,UAAU,SAAqD;CACtE,IAAI,WAAW,MAAM,OAAO,KAAA;CAC5B,MAAM,OAAO,QAAQ,KAAK;CAC1B,IAAI,qCAAqC,KAAK,IAAI,GAAG,OAAO,OAAO,IAAI;CACvE,IAAI,mBAAmB,KAAK,IAAI,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,WAAW,QAAM,IAAG;CAChF,IAAI,UAAU,KAAK,IAAI,GAAG,OAAO;CACjC,IAAI,WAAW,KAAK,IAAI,GAAG,OAAO;AAEpC;;AAGA,SAAS,SAAS,OAAkD;CAClE,MAAM,QAAQ,SAAS,GAAA,CAAI,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC7D,IAAI,CAAC,KAAK,QAAQ,OAAO;CACzB,OAAO,KAAK,WAAW,IAAI,KAAK,KAAM;AACxC;;AAGA,SAAS,SAAS,OAAuB;CAEvC,QADe,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAM,MAAA,CAAO,MAAM,GAAG,CAAC,CAAC,EAC7D,CAAM,WAAW,KAAK,EAAE;AACjC;AAEA,IAAM,UAAgD;CACpD,OAAO;CACP,UAAU;CACV,aAAa;CACb,oBAAoB;CACpB,UAAU;CACV,iBAAiB;CACjB,SAAS;CACT,YAAY;AACd;AACA,IAAM,UAAyD;CAC7D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;AAIA,IAAM,YAAY;;AAGlB,SAAS,kBAAkB,OAAmB;CAC5C,MAAM,OAAO,CAAC,GAAG,gBAAgB,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;CACxE,KAAK,IAAI,IAAI,MAAM,QAAQ,KAAK,EAAG,GAAG,MAAM,IAAI,IAAI,MAAM,QAAQ,KAAK,IAAK,IAAI,CAAC,GAAG;EAClF,IAAI,IAAI;EACR,OAAO,IAAI,KAAK,UAAU,MAAM,IAAI,OAAO,KAAK,IAAI;EACpD,IAAI,MAAM,KAAK,QAAQ,OAAO;CAChC;CACA,OAAO;AACT;;AAGA,SAAS,QAAQ,KAAc;CAC7B,MAAM,QAAQ,QAAQ,KAAK,KAAK;CAChC,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO;EAAC;EAAK;EAAK;EAAK;EAAU;EAAS;CAAI,CAAC,CAC5C,KAAK,SAAS;EACb,MAAM,OAAO,QAAQ,OAAO,IAAI;EAChC,OAAO,OAAO,GAAG,OAAO,KAAK,UAAU,KAAK,KAAK,MAAM;CACzD,CAAC,CAAC,CACD,KAAK,EAAE;AACZ;;AAGA,SAAS,YAAY,IAAa;CAChC,MAAM,OAAO,WAAW,IAAI,GAAG;CAC/B,OAAO,KAAK,SAAS,KAAK,IAAI,IAAI,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO;AAC9D;AAEA,IAAM,UAAU,MAAmD,SACjE,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,QAAQ,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,EAAE;;AAGnE,IAAM,WAAN,MAAe;CAEgB;CAD7B,uBAAe,IAAI,IAA8B;CACjD,YAAY,UAA8C;EAA7B,KAAA,WAAA;CAA8B;CAC3D,IAAI,MAA4B,OAAgB,QAAQ,GAAG;EACzD,IAAI,SAAS,GAAG;EAChB,MAAM,MAAM,GAAG,KAAK,QAAQ,SAAS;EACrC,MAAM,UAAU,KAAK,KAAK,IAAI,GAAG;EACjC,IAAI,SAAS,QAAQ,SAAS,QAAQ,SAAS,KAAK;OAElD,KAAK,KAAK,IAAI,KAAK;GACjB;GACA,SAAS,KAAK,SAAS,SAAS;GAChC;GACA,GAAI,SAAS,OAAO,CAAC,IAAI,EAAE,MAAM;EACnC,CAAC;CACL;CACA,IAAI,MAAM;EACR,OAAO,CAAC,GAAG,KAAK,KAAK,OAAO,CAAC;CAC/B;AACF;;;;;;;AAQA,eAAsB,SACpB,MACA,UAAgC,CAAC,GACD;CAChC,MAAM,WAAW,kBAAkB,qBAAqB,QAAQ,MAAM,GAAG,QAAQ,QAAQ;;CAEzF,MAAM,UAAU,MAA0B,UACxC,IAAI,eAAe,OAAO,OAAO,MAAM,SAAS,OAAO,QAAQ,EAAE,MAAM,IAAI,KAAA,CAAS;CACtF,MAAM,EAAE,WAAW;CACnB,MAAM,QACJ,gBAAgB,aACZ,OACA,IAAI,WAAW,gBAAgB,cAAc,OAAO,MAAM,KAAK,YAAY,CAAC;CAClF,QAAQ,eAAe;CAEvB,IAAI,MAAM,OAAO,OAAQ,MAAM,OAAO,OAAQ,MAAM,OAAO,MAAQ,MAAM,OAAO,KAC9E,MAAM,OAAO,kBAAkB,KAAK,IAAI,WAAW,SAAS;CAC9D,IAAI,MAAM,OAAO,MAAQ,MAAM,OAAO,IAAM,MAAM,OAAO,SAAS;CAClE,IAAI;CACJ,IAAI;EACF,QAAQ,SAAS,KAAK;CACxB,SAAS,OAAO;EACd,MAAM,OAAO,WAAW,KAAK;CAC/B;CACA,MAAM,SAAoB;EAAE;EAAQ,WAAW,EAAE,IAAI,YAAY,IAAI,EAAE;CAAE;CACzE,MAAM,WAAW,OAAO,SAAiB;EACvC,MAAM,QAAQ,MAAM,IAAI,IAAI;EAC5B,IAAI,CAAC,OAAO,OAAO,KAAA;EACnB,IAAI;GACF,OAAO,QAAQ,OAAO,MAAM,MAAM,KAAK,MAAM,CAAC;EAChD,SAAS,OAAO;GACd,IAAI,QAAQ,WAAW,OAAO,KAAK,CAAC,CAAC,SAAS,mBAAmB,GAAG,MAAM;GAC1E,MAAM,OAAO,WAAW,KAAK;EAC/B;CACF;CACA,MAAM,WAAW,OAAO,SAA6B;EACnD,MAAM,OAAO,OAAO,MAAM,SAAS,IAAI,IAAI,KAAA;EAC3C,OAAO,QAAQ,OAAO,KAAA,IAAY,SAAS,IAAI;CACjD;;CAEA,MAAM,SAAS,OAAO,SAAiB;EACrC,MAAM,sBAAM,IAAI,IAA+D;EAC/E,MAAM,OAAO,MAAM,SAAS,SAAS,IAAI,CAAC;EAC1C,KAAK,MAAM,OAAO,WAAW,MAAM,cAAc,GAAG;GAClD,MAAM,WAAW,IAAI,MAAM,eAAe;GAC1C,IAAI,IAAI,IAAI,MAAM,MAAM,IAAI;IAC1B,MAAM,WAAY,IAAI,MAAM,UAAU,KAAM,YAAY,MAAM,IAAI,MAAM,UAAU,EAAE;IACpF,MAAM,IAAI,MAAM,QAAQ;IACxB;GACF,CAAC;EACH;EACA,OAAO;CACT;CAGA,MAAM,eACJ,CAAC,IAAG,MAFa,OAAO,EAAE,EAAA,CAEjB,OAAO,CAAC,CAAC,CAAC,MAAM,QAAQ,IAAI,KAAK,SAAS,iBAAiB,CAAC,CAAC,EAAE,QACxE;CACF,MAAM,WAAW,MAAM,SAAS,YAAY;CAC5C,IAAI,CAAC,YAAY,SAAS,SAAS,YAAY,MAAM,OAAO,SAAS;CACrE,MAAM,eAAe,MAAM,OAAO,YAAY;CAC9C,MAAM,WAAW,IAAI,SAAS,QAAQ;CAEtC,MAAM,QAAQ,YAAY,MAAM,SAAS,OAAO,cAAc,OAAO,CAAC,CAAC;CACvE,MAAM,EAAE,OAAO,kBAAkB,WAAW,MAAM,SAAS,OAAO,cAAc,QAAQ,CAAC,GAAG,KAAK;CAGjG,MAAM,UAAoB,CAAC;CAC3B,MAAM,aAAa,MAAM,SAAS,OAAO,cAAc,eAAe,CAAC;CACvE,MAAM,2BAAW,IAAI,IAAY;CACjC,KAAK,MAAM,CAAC,GAAG,OAAO,WAAW,YAAY,IAAI,CAAC,CAAC,QAAQ,GAAG;EAC5D,QAAQ,KAAK,UAAU,OAAO,EAAE,CAAC,CAAC;EAClC,IAAI,YAAY,EAAE,GAAG,SAAS,IAAI,CAAC;CACrC;CAGA,KAAK,MAAM,QAAQ,MAAM,KAAK,GAAG;EAC/B,IAAI,yBAAyB,KAAK,IAAI,GAAG,SAAS,IAAI,OAAO;EAC7D,IAAI,iCAAiC,KAAK,IAAI,GAAG,SAAS,IAAI,OAAO;CACvE;CACA,KAAK,MAAM,QAAQ,WAAW,QAAQ,UAAU,cAAc,GAAG,aAAa,GAC5E,IAAI,CAAC,KAAK,MAAM,MAAM,WAAW,QAAQ,GAAG,SAAS,IAAI,MAAM;CAEjE,MAAM,WAAW,KAAK,QAAQ,UAAU,YAAY,CAAC,EAAE,MAAM,QAAQ;CAErE,MAAM,aAAuB,CAAC;CAC9B,KAAK,MAAM,QAAQ,MAAM,KAAK,GAAG;EAC/B,IAAI,CAAC,4BAA4B,KAAK,IAAI,GAAG;EAC7C,MAAM,QAAQ,MAAM,SAAS,IAAI;EACjC,KAAK,MAAM,OAAO,CAAC,QAAQ,aAAa,GAAY;GAClD,MAAM,YAAY,OAAO,MAAM;GAC/B,IAAI,aAAa,CAAC,WAAW,SAAS,SAAS,GAAG,WAAW,KAAK,SAAS;EAC7E;CACF;CACA,MAAM,WAAW,WAAW,SACxB,IAAI,OACF,mBAAmB,WAAW,KAAK,MAAM,EAAE,QAAQ,uBAAuB,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAC7F,GACF,IACA;CAGJ,MAAM,6BAAa,IAAI,IAAoB;CAC3C,MAAM,SAAqC,CAAC;CAC5C,MAAM,aAAa,SAAqB;EACtC,IAAI,CAAC,KAAK,KAAK,OAAO,KAAA;EACtB,IAAI,OAAO,WAAW,IAAI,KAAK,GAAG;EAClC,IAAI,CAAC,MAAM;GACT,OAAO,QAAQ,WAAW,OAAO;GACjC,WAAW,IAAI,KAAK,KAAK,IAAI;GAC7B,OAAO,QAAQ,KAAK;EACtB;EACA,OAAO;CACT;CAEA,MAAM,SAAsB,CAAC;CAC7B,MAAM,eAAe,QAAQ,aAAa;CAC1C,KAAK,MAAM,aAAa,WAAW,QAAQ,UAAU,QAAQ,GAAG,OAAO,GAAG;EACxE,QAAQ,eAAe;EACvB,MAAM,OAAO,UAAU,MAAM,QAAQ,QAAQ,OAAO,SAAS;EAC7D,MAAM,MAAM,aAAa,IAAI,UAAU,MAAM,MAAM,EAAE;EACrD,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,YAAY,GAAG;GAE5C,IAAI,KAAK,KAAK,SAAS,aAAa,GAAG,SAAS,IAAI,SAAS,IAAI;GACjE;EACF;EACA,IAAI,UAAU,MAAM,UAAU,YAAY,UAAU,MAAM,UAAU,cAClE,SAAS,IAAI,eAAe,IAAI;EAClC,MAAM,MAAM,MAAM,SAAS,IAAI,IAAI;EACnC,IAAI,OAAO,MAAM,MAAM,OAAO,SAAS;EACvC,MAAM,YAAY,MAAM,OAAO,IAAI,IAAI;EACvC,MAAM,EAAE,MAAM,OAAO,cAAc,MAAM,UAAU,KAAK,MAAM;GAC5D;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;EACD,SAAS,IAAI,aAAa,MAAM,SAAS,MAAM,OAAO,SAAS,CAAC;EAChE,SAAS,IAAI,YAAY,MAAM,SAAS;EAExC,MAAM,WAAW,MAAM,SAAS,OAAO,WAAW,UAAU,CAAC;EAC7D,IAAI,UAAU,SAAS,MAAM,QAAQ;EACrC,KAAK,MAAM,EAAE,MAAM,UAAU,UAAU,OAAO,GAAG;GAC/C,IAAI,KAAK,SAAS,UAAU,GAAG;IAC7B,MAAM,UAAU,MAAM,OAAO,IAAI;IACjC,KAAK,MAAM,EAAE,MAAM,UAAU,QAAQ,OAAO,GAC1C,IAAI,KAAK,SAAS,QAAQ,GAAG,SAAS,IAAI,SAAS,IAAI;SAClD,IAAI,KAAK,SAAS,QAAQ,GAAG,SAAS,IAAI,SAAS,IAAI;GAChE;GACA,IAAI,KAAK,SAAS,aAAa,GAAG,SAAS,IAAI,SAAS,IAAI;GAC5D,IAAI,KAAK,SAAS,QAAQ,GAAG,SAAS,IAAI,SAAS,IAAI;EACzD;EACA,OAAO,KAAK,IAAI;CAClB;CACA,IAAI,CAAC,OAAO,QAAQ,OAAO,KAAK;EAAE,MAAM;EAAU,OAAO,CAAC;CAAE,CAAC;CAC7D,MAAM,OAAsB;EAAE,SAAS;EAAG;CAAO;CACjD,IAAI,WAAW,MAAM,KAAK,SAAS;CACnC,MAAM,OAAO,QAAQ,UAAU,oBAAoB;CACnD,IAAI,QAAQ,KAAK,KAAK,MAAM,aAAa,GAAG;EAC1C,KAAK,UAAU;EACf,MAAM,IAAI,KAAK;EACf,IAAI,EAAE,oBAAoB,EAAE,mBAAmB,SAAS,IAAI,UAAU;CACxE;CACA,QAAQ,eAAe;CACvB,OAAO;EAAE;EAAM,UAAU,SAAS;CAAI;AACxC;;AAkBA,eAAe,UACb,KACA,MACA,SACkF;CAClF,MAAM,EAAE,SAAS,UAAU,OAAO,eAAe,WAAW,cAAc,UAAU,WAClF;CACF,MAAM,EAAE,UAAU,aAAa;CAC/B,MAAM,UAAU,WAAmB,SAAS,WAAW,SAAS,YAAY,MAAM;CAClF,MAAM,OAAkB;EAAE;EAAM,OAAO,CAAC;CAAE;CAC1C,MAAM,QAAQ,KAAK;CACnB,MAAM,WAAmC,CAAC;CAC1C,MAAM,6BAAa,IAAI,IAAY;CACnC,MAAM,4BAAY,IAAI,IAAoB;CAC1C,MAAM,WAAmC,CAAC;CAC1C,MAAM,6BAAa,IAAI,IAAY;CACnC,MAAM,4BAAY,IAAI,IAAoB;CAC1C,MAAM,SAAmB,CAAC;CAC1B,IAAI,eAAe;CACnB,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,IAAI,OAAO;CACX,IAAI,WAAW;CACf,IAAI,gBAAgB;CACpB,MAAM,QAAkC,CAAC;CACzC,IAAI,YAAY;CAChB,MAAM,wBAAQ,IAAI,IAAoB;CACtC,MAAM,wBAAQ,IAAI,IAAoB;CAEtC,MAAM,iCAAiB,IAAI,IAA2D;CAGtF,IAAI,MAAM;CACV,IAAI,MAAM;CACV,IAAI,OAAO;CACX,IAAI;CACJ,IAAI,QAAQ;CACZ,IAAI,aAAa;CACjB,IAAI,UAAyB;CAC7B,IAAI,eAA8C;CAClD,IAAI,UAAkC;CACtC,IAAI,WAAW;CACf,IAAI,aAAa;CAEjB,IAAI,OAAO;CAGX,IAAI,SAAS;CACb,IAAI,YAOO;CACX,MAAM,cAAoE,CAAC;CAC3E,IAAI,UAAiC;CACrC,IAAI,SAIO;CACX,MAAM,cAAiC,CAAC;CACxC,IAAI,aACF;CACF,IAAI,OAAO;CAEX,MAAM,mBAAmB;EACvB,IAAI,UAAsB;EAC1B,IAAI,SAAS,KAAK;GAChB,MAAM,QAAQ,CAAC;GACf,UAAU,QAAQ,UAAU;GAC5B,IAAI,SAAS,IAAI,KAAK,GAAG;EAC3B,OAAO,IAAI,SAAS,aAAa,UAAU,UAAU,UAAU;OAC1D,IAAI,SAAS,OAAO,UAAU,UAAU,KAAK;OAC7C,IAAI,SAAS,KAAK,UAAU,KAAK,KAAK;OACtC,IAAI,SAAS,KAAK,UAAU;OAC5B,IAAI,SAAS,KAAK;GACrB,MAAM,OAAO,qDAAqD,KAAK,KAAK;GAC5E,UAAU,OACN,KAAK,MAAM,KAAK,OAAO,aACrB,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC,QAAQ,QAAQ,EAAE,MACxC,KAAK,KACP;EACN,OAAO,IAAI,UAAU,IAAI;GACvB,MAAM,SAAS,OAAO,KAAK;GAC3B,UAAU,OAAO,SAAS,MAAM,IAAI,SAAS;EAC/C;EAGA,IAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG,KAAK,CAAC,SAAS,UAAU,IAAI;EACtF,IAAI,SAAS,MAAM;EACnB,IAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,SAAS,UAAU;GACjE,MAAM,SAAS;GACf,MAAM,OAAO,KAAK,SAAS,UAAU,SAAS;GAE9C,IAAI,SAAS,OAAO,QAAQ,MAAA,CAAO,IAAI,MAAM;GAC7C,IAAI,SAAS,MAAM;IACjB,QAAQ,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM;IAC/C,IAAI,MAAM,OAAO,MAAM,OAAO,KAAS,CAAC,OAAO,QAAQ,MAAA,CAAO,IAAI,QAAQ,KAAK;GACjF;GACA,UAAU;GAEV,IAAI,UAAU,YAAY,QAAQ,OAAO,GAAG,SAAS,KAAA;EACvD;EAEA,IAAI,SAAS,OAAO,WAAW,QAAQ,sBAAsB,KAAK,OAAO,GAAG,UAAU;EACtF,IAAI,WAAW,QAAQ,cAAc;GACnC,IAAI,UAAU,KAAK,OAAO,GAAG;QAExB,IAAI,UAAU,KAAK,OAAO,GAAG;QAC7B,UAAU,UAAU,OAAO;EAClC;EACA,IAAI,MAAM,QAAQ;EAClB,IAAI,MAAM,MAAM;EAChB,MAAM,QAAQ,OAAO,UAAU,IAAI,IAAI,KAAA;EACvC,IAAI,YAAY,QAAQ,CAAC,SAAS,CAAC,QAAQ;EAC3C,MAAM,OAAQ,MAAM,SAAS,CAAC;EAC9B,KAAK,OAAO,SAAS,SAAS,QAAQ;GAAE,OAAO;GAAS;GAAO;EAAO,CAAC,IAAI;CAC7E;CAEA,MAAM,UAAU;EACd,KAAK,KAAa,KAAa,OAAgB;GAC7C,IAAI,MAAM;IACR,IAAI,CAAC,OAAO;IACZ;GACF;GACA,QAAQ,KAAR;IACE,KAAK;KACH,IAAI,CAAC,OAAO,OAAO;KACnB;IACF,KAAK,OAAO;KACV,MAAM,IAAI,QAAQ,GAAG;KACrB,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,MAAM;KAC7B,MAAM;KACN,IAAI,KAAK,EAAE,YAAY,KAAK,EAAE,IAAI,SAAS,OAAO,WAAW,CAAC,EAAE,EAAE;KAClE,IAAI,KAAK,EAAE,MAAM,GAAG,WAAW,IAAI,GAAG;KACtC,IAAI,EAAE,gBAAgB,CAAC,EAAE,eAAe,GAAG,UAAU,IAAI,KAAK,CAAC,EAAE,YAAY;KAC7E;IACF;IACA,KAAK,KAAK;KACR,MAAM,IAAI,QAAQ,GAAG;KACrB,IAAI,EAAE,GAAG;MACP,MAAM,QAAQ,UAAU,EAAE,CAAC;MAC3B,IAAI,OAAO;OACT,MAAM,MAAM;OACZ,MAAM,MAAM;MACd,OAAO;KACT,OAAO;KACP,OAAO,EAAE,KAAK;KACd,OAAO,EAAE,IAAI,MAAM,CAAC,EAAE,KAAK,MAAM;KACjC,IAAI,QAAQ,CAAC,KAAK,SAAS,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU,CAAC,KAAK,QAAQ,CAAC,KAAK,OAC7E,OAAO,KAAA;KACT,QAAQ;KACR,aAAa;KACb,UAAU;KACV,eAAe;KACf,IAAI,OAAO,WAAW;KACtB;IACF;IACA,KAAK;KACH,UAAU;KACV,QAAQ;KACR;IACF,KAAK;KACH,eAAe,QAAQ,GAAG;KAC1B,UAAU;KACV,UAAU;KACV,IAAI,OAAO,aAAa;KACxB;IACF,KAAK;KACH,WAAW;KACX;IACF,KAAK;KACH,aAAa;KACb;IACF,KAAK;KACH,IAAI,YAAY,CAAC,YAAY,UAAU;UAClC,OAAO;KACZ;IACF,KAAK,aAAa;KAChB,MAAM,IAAI,QAAQ,GAAG;KACrB,eAAe,SAAS,EAAE,YAAY;KACtC;IACF;IACA,KAAK,QAAQ;KACX,MAAM,IAAI,QAAQ,GAAG;KACrB,IAAI,EAAE,UAAU,YAAY,EAAE,UAAU,eAAe;MACrD,MAAM,OAAO,KAAK,MAAM,EAAE,EAAE,UAAU,EAAE;MACxC,MAAM,OAAO,KAAK,MAAM,EAAE,EAAE,UAAU,EAAE;MACxC,IAAI,QAAQ,MAAM,KAAK,SAAS;OAAE,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;OAAI,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;MAAG;KACzF;KACA;IACF;IACA,KAAK,OAAO;KACV,MAAM,IAAI,QAAQ,GAAG;KACrB,MAAM,MAAM,EAAE,EAAE,OAAO,KAAK;KAC5B,MAAM,MAAM,KAAK,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,GAAG,KAAM;KACvD,MAAM,SAAS,KAAK,EAAE,MAAM;KAC5B,MAAM,QAAQ,EAAE,eAAe,CAAC,EAAE,eAAe;KAEjD,MAAM,QAAQ,KAAK,EAAE,WAAW,KAAK,EAAE,SAAS,QAAQ,MAAM,MAAM;KACpE,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK;MAC/B,IAAI,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,KAAM;MAC5C,IAAI,QAAQ,WAAW,IAAI,CAAC;MAC5B,IAAI,QAAQ,GAAG,UAAU,IAAI,GAAG,KAAK;KACvC;KACA;IACF;IACA,KAAK,aAAa;KAChB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC;KACzB,IAAI,KAAK,OAAO,KAAK,GAAG;KACxB;IACF;IACA,KAAK,cAAc;KACjB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC;KACzB,IAAI,KAEF,SAAS;MAAE,OAAO;MAAK,MADT,UAAU,IAAI,MAAM,GAAG,CAAC,CAAC,EACV,CAAA,EAAO,OAAO;MAAG,SAAS,CAAC;KAAE;KAE5D;IACF;IACA,KAAK;KACH,YAAY;MACV,IAAI,EAAE,QAAQ,GAAG,CAAC,CAAC,SAAS;MAC5B,QAAQ,CAAC;MACT,OAAO;MACP,QAAQ,CAAC;MACT,KAAK;MACL,OAAO;KACT;KACA;IACF,KAAK;KACH,IAAI,WAAW,UAAU,QAAQ,KAAK,QAAQ,GAAG,CAAC,CAAC,KAAK;KACxD;IACF,KAAK;KACH,WAAW,OAAO,KAAK,QAAQ,GAAG,CAAC,CAAC,OAAO,EAAE;KAC7C;IACF,KAAK;KACH,IAAI,WAAW,UAAU,MAAM,KAAK,QAAQ,GAAG,CAAC,CAAC,GAAG;KACpD;IACF,KAAK,gBAAgB;KACnB,MAAM,IAAI,QAAQ,GAAG;KACrB,WAAW,OAAO,KAAK;MAAE,IAAI,EAAE;MAAU,KAAK,EAAE,OAAO;KAAG,CAAC;KAC3D;IACF;IACA,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;KACH,IAAI,WAAW,UAAU,QAAQ;KACjC;IACF,KAAK;KACH,UAAU,SAAS,QAAQ,GAAG,CAAC,CAAC,KAAK;KACrC;IACF,KAAK;KACH,SAAS;MAAE,OAAO,QAAQ,GAAG;MAAG,UAAU,CAAC;MAAG,QAAQ,CAAC;KAAE;KACzD,IAAI,OAAO,UAAU;KACrB;IACF,KAAK;IACL,KAAK;IACL,KAAK;KACH,OAAO;KACP;IACF,KAAK;KACH,IAAI,QACF,OAAO,OAAO,KACZ,QAAQ;MAAE,MAAM;MAAS,OAAO,QAAQ,GAAG;MAAG,UAAU,CAAC;MAAG,MAAM;KAAG,GAAG,CAAC,CAAC,CAC5E;KACF;IACF,KAAK;KACH,aAAa,EAAE,OAAO,QAAQ,GAAG,EAAE;KACnC,IAAI,OAAO,gBAAgB;KAC3B;IACF,KAAK;KACH,MAAM,KAAK,QAAQ,GAAG,CAAC;KACvB;IACF,KAAK,mBAAmB;KACtB,MAAM,IAAI,QAAQ,GAAG;KACrB,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG;KAEpB,MAAM,QAAyB,CAAC;KAChC,KAAK,MAAM,CAAC,KAAK,SAAS,kBAAkB,IAAI,MAAM,EAAE,IAAI,GAAG,MAAM,QAAQ;KAC7E,KAAK,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,QAAQ;KACnD,IAAI,EAAE,YAAY,EAAE,WAAW;KAC/B;IACF;GACF;EACF;EACA,MAAM,KAAa;GACjB,IAAI,MAAM;IACR;IACA;GACF;GACA,QAAQ,KAAR;IACE,KAAK;KACH,WAAW;KACX;IACF,KAAK;IACL,KAAK;KACH,IAAI,YAAY,OAAO,YAAY,KAAK,UAAU;KAClD;IACF,KAAK;KACH,aAAa;KACb;IACF,KAAK;KACH,WAAW;KACX;IACF,KAAK;KACH,aAAa;KACb;IACF,KAAK;KACH,QAAQ,SAAS,KAAK,IAAI;KAC1B;IACF,KAAK;KACH,IAAI,YAAY,WAAW,WAAW;KACtC;IACF,KAAK;KACH,IAAI,YAAY,WAAW,WAAW;KACtC;IACF,KAAK;KACH,kBAAkB;KAClB;IACF,KAAK;KACH,UAAU;KACV;IACF,KAAK,kBACH,gBAAgB;GAEpB;EACF;EACA,KAAK,OAAe;GAClB,IAAI,MAAM;GACV,IAAI,YAAY,KAAK,SAAS;QACzB,IAAI,YAAY,KAAK,WAAW;QAChC,IAAI,YAAY,KAAK,cAAc;QACnC,QAAQ;EACf;CACF;CAEA,SAAS,eAAe;EACtB,UAAU;EACV,MAAM,IAAI,gBAAgB,CAAC;EAC3B,IAAI,UAAU,WAAW;EACzB,IAAI,EAAE,MAAM,YAAY,EAAE,MAAM,MAAM;GACpC,MAAM,SAAS,eAAe,IAAI,EAAE,EAAE;GACtC,IAAI,SAAS,eAAe,IAAI,EAAE,IAAI;IAAE,SAAS;IAAS;IAAK;GAAI,CAAC;QAC/D,IAAI,QACP,UAAU,aAAa,IAAI,OAAO,WAAW,MAAM,OAAO,KAAK,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;EAC5F;EAEA,UAAU,WAAW,EAAE,MAAM,cAAc,UAAU;CACvD;CAEA,SAAS,oBAAoB;EAC3B,MAAM,SAAS;EACf,YAAY;EACZ,IAAI,CAAC,UAAU,CAAC,QAAQ;EACxB,MAAM,KAAK,OAAO,OAAO,OAAO;EAChC,IAAI,OAAO,OAAO;GAChB,SAAS,IAAI,UAAU,IAAI;GAC3B;EACF;EACA,IAAI,OAAO,OAAO,UAAU,OAAO,OAAO;GACxC,OAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,GAAG,OAAO,QAAQ,GAAI,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAE,EAAE;GACjF;EACF;EACA,MAAM,YAAY,gBAAgB,OAAO,QAAQ,OAAO,GAAG;EAC3D,IAAI,WAAW,OAAO,QAAQ,MAAM,EAAE,UAAU;OAC3C,IAAI,OAAO,OAAO,QAAQ,SAAS,IAAI,UAAU,IAAI;CAC5D;CAEA,SAAS,YAAY;EACnB,MAAM,OAAO;EACb,SAAS;EACT,IAAI,CAAC,QAAQ,CAAC,SAAS;EACvB,MAAM,OAAO,cAAc,MAAM,SAAS,aAAa;EACvD,IAAI,MAAM,YAAY,KAAK;GAAE,UAAU,EAAE,KAAK,MAAM,YAAY;GAAI,MAAM;EAAK,CAAC;OAC3E,SAAS,IAAI,eAAe,IAAI;CACvC;CAEA,SAAS,kBAAkB;EACzB,MAAM,OAAO;EACb,aAAa;EACb,IAAI,CAAC,MAAM;EACX,MAAM,OAAO,aAAa,MAAM,MAAM;EACtC,IAAI,MAAM,YAAY,KAAK,IAAI;OAC1B,IAAI,KAAK,MAAM,QAAQ,KAAK,MAAM,SAAS,QAAQ,SAAS,IAAI,cAAc,IAAI;CACzF;CAEA,MAAM,SAAS,IAAI,UAAU,KAAK,OAAO;CACzC,OAAO,OAAO,KAAK,GAAM,GACvB,IAAI,YAAY,IAAI,IAAI,OAAO,UAAU,KAAA,IAAY;EACnD,MAAM,MAAM;EACZ,OAAO,QAAQ,eAAe;EAC9B,OAAO,UAAU,KAAK,YAAY,IAAI;CACxC;CAIF,MAAM,WAAW,UAAU,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC,SAAS,SAAS;CACzE,MAAM,aAAa,WAAW,QAAQ,SAAS,KAAK,IAAI;CACxD,MAAM,YAAY,SAAS,WAAW,aAAa,GAAG,MAAM,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG;CAC/E,MAAM,YAAY,SAAS,WAAW,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC,EAAE,GAAG,WAAW,CAAC,GAAG;CAC/F,KAAK,MAAM,KAAK,YAAY;EAC1B,IAAI,UAAU,OAAO,IAAI,CAAC,GAAG;EAC7B,IAAI,cAAc,IAAI,WAAW,MAAM,KAAK,WAAW,IAAI;EAC3D,SAAS,KAAK;CAChB;CACA,KAAK,MAAM,KAAK,YAAY,IAAI,CAAC,UAAU,OAAO,IAAI,CAAC,GAAG,SAAS,KAAK;CAExE,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,QAAQ,KAAK,WAAW;CAClD,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,QAAQ,KAAK,WAAW;CAClD,IAAI,OAAO,QAAQ,KAAK,SAAS;CACjC,MAAM,SAAS,CAAC,GAAG,UAAU,QAAQ,GAAG,UAAU,MAAM;CACxD,IAAI,OAAO,QAAQ;EACjB,KAAK,SAAS;EACd,IAAI,CAAC,cAAc,KAAK,eAAe;OAClC,KAAK,eAAe;CAC3B;CACA,IAAI,QACF,KAAK,SAAS,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC,SACtC;EAAE,OAAO,OAAO;EAAO,SAAS,OAAO;CAAQ,IAC/C,EAAE,OAAO,OAAO,MAAM;CAC5B,IAAI,YAAY,QAEd,KAAK,qBAAqB,YAAY,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;CACjG,IAAI,YAAY,QAAQ,KAAK,cAAc;CAC3C,SAAS,IAAI,UAAU,MAAM,OAAO;CACpC,SAAS,IAAI,QAAQ,MAAM,KAAK;CAChC,SAAS,IAAI,YAAY,MAAM,IAAI;CACnC,SAAS,IAAI,YAAY,MAAM,QAAQ;CACvC,SAAS,IAAI,SAAS,MAAM,aAAa;CACzC,OAAO;EAAE;EAAM;EAAO;CAAU;AAClC;;AAGA,IAAM,mBAAsD;CAC1D,CAAC,eAAe,aAAa;CAC7B,CAAC,iBAAiB,eAAe;CACjC,CAAC,cAAc,YAAY;CAC3B,CAAC,iBAAiB,eAAe;CACjC,CAAC,cAAc,YAAY;CAC3B,CAAC,iBAAiB,eAAe;CACjC,CAAC,cAAc,YAAY;CAC3B,CAAC,cAAc,QAAQ;AACzB;;;;;;AAOA,SAAS,SACP,MACA,OACA,MACA;CACA,IAAI,UAAU;CACd,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,MAAM,EAAE,KAAK,KAAK,IAAI,EAAE,EAAE,IAAI,KAAA;EACpC,MAAM,QAAQ,EAAE,WAAW,IAAI,EAAE,aAAa;EAC9C,MAAM,OAAO,MAAO,IAAI,WAAW,IAAI,OAAO,QAAQ,KAAM;EAC5D,MAAM,QAAQ,EAAE,MAAM,WAAW,EAAE,GAAG,IAAI;EAC1C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,IAAI,GAAG;GACxC;GACA;EACF;EACA,MAAM,IAAI,SAAS,KAAK;EAExB,MAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG;EAC7C,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,QAAQ,KAC/B,KAAK,IAAI,IAAI,EAAE,MAAM,KAAK,EAAE,SAAS,KAAK,EAAE,OAAO,IAAI,KAAK;GAC1D,MAAM,OAAQ,KAAK,MAAM,OAAO,CAAC;GACjC,MAAM,OAAO,KAAK;GAClB,KAAK,KACH,QAAQ,QAAQ,OAAO,SAAS,WAC5B;IAAE,GAAG;IAAM;GAAK,IAChB,QAAQ,QAAQ,SAAS,KACvB,EAAE,KAAK,IACP;IAAE,OAAO;IAAM;GAAK;EAC9B;CACJ;CACA,OAAO;AACT;;AAGA,SAAS,QAAQ,MAA4B;CAC3C,MAAM,MAAiB,CAAC;CACxB,IAAI,KAAK,SAAS,MAAM,IAAI,QAAQ,KAAK;CACzC,IAAI,KAAK,OAAO,IAAI,QAAQ,KAAK;CACjC,IAAI,KAAK,QAAQ,IAAI,SAAS,KAAK;CACnC,OAAO;AACT;;AAGA,SAAS,YAAY,QAAgB,MAAc;CACjD,MAAM,QACJ,KAAK,WAAW,KACZ,eACA,KAAK,WAAW,IACd,UACA,KAAK,WAAW,IACd,aACA,KAAK,WAAW,KACd,qBACA;CACZ,OAAO,OAAO,YAAY,MAAM;AAClC;AAEA,IAAM,OAAO,MAAc,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;;AAGpD,SAAS,SAAS,UAAkB;CAClC,MAAM,UAAU,KAAK,MAAM,WAAW,KAAM,IAAI;CAChD,MAAM,OAAO,GAAG,IAAI,KAAK,MAAM,UAAU,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,MAAO,UAAU,OAAQ,EAAE,CAAC;CACxF,OAAO,UAAU,KAAK,GAAG,KAAK,GAAG,IAAI,UAAU,EAAE,MAAM;AACzD;;AAGA,SAAS,QAAQ,OAAwC;CACvD,MAAM,CAAC,MAAM,MAAM,MAAM,MAAM,GAAG;CAClC,MAAM,QAAQ,OAAO,UAAU,IAAI,IAAI;CACvC,MAAM,MAAM,KAAK,UAAU,EAAE,IAAI;CACjC,OAAO,SAAS,MAAM,CAAC,MAAM,KAAK,IAAI,GAAG,IAAI;AAC/C;;;;;AAMA,SAAS,SACP,QACA,QACA,SACA;CACA,MAAM,SAAmD,CAAC;CAC1D,MAAM,yBAAS,IAAI,IAAY;CAC/B,IAAI,CAAC,OAAO,MAAM,OAAO;EAAE;EAAQ;CAAO;CAE1C,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CACrD,IAAI,UAAU;CACd,KAAK,MAAM,SAAS,OAAO,OAAO,GAAG,IAAI,QAAQ,SAAS,UAAU;CACpE,KAAK,IAAI,QAAQ,GAAG,SAAS,SAAS,SAAS;EAC7C,IAAI,QAAQ;EACZ,IAAI,OAAO;EACX,MAAM,cAAc;GAClB,IAAI,QAAQ,GAAG;GACf,IAAI,MAAM;GACV,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,MAAM;GAC9D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,CAAC;GACzD,OAAO,KACL,MAAM;IAAE,OAAO,QAAQ,OAAO,IAAI;IAAG,WAAW;GAAK,IAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,EAAE,CACzF;EACF;EACA,KAAK,MAAM,QAAQ,OAAO;GACxB,IAAI,OAAO,IAAI,IAAI,IAAK,OAAO;GAC/B,IAAI,SAAS,OAAO,GAAG;IACrB,MAAM;IACN,QAAQ;GACV;GACA,OAAO;EACT;EACA,MAAM;CACR;CACA,OAAO;EAAE;EAAQ;CAAO;AAC1B;;AAGA,IAAM,cAAc,QAClB,wBAAwB,KAAK,IAAI,KAAK,CAAC,IAAI,OAAO,GAAG,IAAI;;AAG3D,SAAS,gBACP,QACA,KACuB;CACvB,IAAI,OAAO,WAAW,GAAG;EACvB,MAAM,EAAE,KAAK,SAAS,QAAQ,OAAO;EACrC,MAAM,OAAO,aAAa,KAAK,GAAG;EAClC,IAAI,OAAO,WAAW,OAAO,YAAY;GACvC,MAAM,MAAM,OAAO;GACnB,IAAI,OAAO,QAAQ,KAAK,OAAO,EAAE,IAAI,WAAW;GAChD,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAE,SAAS,GAAG,GAChC,OAAO;IAAE,IAAI,MAAM,gBAAgB;IAAY,OAAO,KAAK;GAAI;GACjE,IAAI,CAAC,OAAO,YAAY,KAAK,GAAG,GAAG,OAAO;IAAE,IAAI;IAAU,OAAO,IAAI,MAAM,GAAG,EAAE;GAAE;GAClF,IAAI,CAAC,OAAO,YAAY,KAAK,GAAG,GAAG,OAAO;IAAE,IAAI;IAAQ,OAAO,IAAI,MAAM,CAAC;GAAE;GAC5E,IAAI,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG,OAAO;GACnD,OAAO;IAAE,IAAI,MAAM,OAAO;IAAM,OAAO,WAAW,GAAG;GAAE;EACzD;EACA,MAAM,MAA4C;GAChD,aAAa;GACb,oBAAoB;GACpB,UAAU;GACV,iBAAiB;EACnB;EACA,OAAO,IAAI,MAAM;GAAE,IAAI,IAAI;GAAK,OAAO,WAAW,GAAG;EAAE,IAAI;CAC7D;CACA,IAAI,OAAO,WAAW,GAAG;EACvB,MAAM,CAAC,GAAG,KAAK;EACf,IAAI,OAAO,EAAE,OAAO,wBAAwB,EAAE,OAAO,mBACnD,OAAO;GAAE,IAAI;GAAW,OAAO,WAAW,EAAE,GAAG;GAAG,IAAI,WAAW,EAAE,GAAG;EAAE;EAC1E,IAAI,CAAC,OAAO,EAAE,OAAO,cAAc,EAAE,OAAO,eAC1C,OAAO;GAAE,IAAI;GAAc,OAAO,WAAW,EAAE,GAAG;GAAG,IAAI,WAAW,EAAE,GAAG;EAAE;CAC/E;CACA,OAAO;AACT;;AAGA,SAAS,cACP,MACA,OACA,eAC+B;CAC/B,MAAM,EAAE,OAAO,aAAa;CAC5B,MAAM,QAAQ,cAAc,EAAE,MAAM,SAAS,QAAQ,CAAC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,QAAQ,MAAM,MAAd;EACE,KAAK,UAAU;GACb,MAAM,KAAK,QAAQ,MAAM,YAAY;GACrC,IAAI,CAAC,IAAI,OAAO;GAChB,MAAM,QAAQ,UAAU,SAAS,EAAE;GACnC,MAAM,KAAK,UAAU,SAAS,EAAE;GAChC,MAAM,MAAM,OAAO,aAAa,OAAO;GACvC,IAAI,UAAU,KAAA,MAAc,CAAC,OAAO,OAAO,KAAA,IACzC,OAAO;IAAE;IAAO,MAAM,MAAM;KAAE;KAAI;KAAO;IAAG,IAAI;KAAE;KAAI;IAAM;IAAG;GAAM;GAEvE,IAAI,CAAC,SAAS,IAAI,OAAO;GACzB,IAAI,KAAK;IACP,IAAI,CAAC,SAAS,IAAI,OAAO;IACzB,MAAM,SAAS,OAAO,OAAO,IAAI,SAAS,GAAG,GAAG,OAAO,IAAI,SAAS,GAAG;IACvE,OAAO;KAAE;KAAO,SAAS,IAAI,OAAO,YAAY,SAAS,OAAO,OAAO;KAAM;IAAM;GACrF;GACA,OAAO;IAAE;IAAO,SAAS,IAAI,SAAS,QAAQ,MAAM,SAAS;IAAM;GAAM;EAC3E;EACA,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YAAY;GACf,MAAM,MAAM;IACV,cAAc;IACd,iBAAiB;IACjB,YAAY;IACZ,UAAU;GACZ;GACA,IAAI,MAAM,QAAQ,MAAM;GACxB,OAAO;IAAE;IAAO,MAAM;KAAE,IAAI,IAAI,MAAM;KAAO,OAAO,MAAM;IAAK;IAAG;GAAM;EAC1E;EACA,KAAK,kBACH,OAAO;GAAE;GAAO,MAAM,EAAE,IAAI,QAAQ;GAAG;EAAM;EAC/C,KAAK,qBACH,OAAO;GAAE;GAAO,MAAM,EAAE,IAAI,WAAW;GAAG;EAAM;EAClD,KAAK,cACH,OAAO,SAAS,KAAK;GAAE;GAAO,SAAS,UAAU,SAAS,EAAE;GAAG;EAAM,IAAI;EAC3E,KAAK,SAAS;GACZ,MAAM,OAAO,EAAE,MAAM,QAAQ;GAC7B,MAAM,UAAU,KAAK,MAAM,OAAO,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;GAC3D,OAAO,KAAK,MAAM,MAAM,IACpB;IAAE;IAAO,QAAQ;IAAM,GAAG;IAAS;GAAM,IACzC;IAAE;IAAO,KAAK;IAAM,GAAG;IAAS;GAAM;EAC5C;EACA,KAAK;GACH,IAAI,MAAM,UAAU,MAAM,OAAO;GACjC,OAAO;IAAE;IAAO,SAAS,CAAC,SAAS,MAAM,YAAY,IAAI,UAAU;IAAS;GAAM;EACpF,KAAK,mBACH,OAAO;GAAE;GAAO,YAAY;GAAM;EAAM;EAC1C,KAAK,gBACH,OAAO;GAAE;GAAO,QAAQ;GAAM;EAAM;EACtC,KAAK,cAAc;GACjB,MAAM,SAAS,KAAK,OAAO,KAAK,MAAM,KAAK,SAAS;GACpD,IAAI,OAAO,WAAW,GAAG,OAAO;IAAE;IAAO,OAAO,CAAC,OAAO,IAAK,OAAO,EAAG;GAAE;GACzE,IAAI,OAAO,WAAW,GAAG,OAAO;IAAE;IAAO,OAAO;KAAC,OAAO;KAAK,OAAO;KAAK,OAAO;IAAG;GAAE;GACrF,OAAO;EACT;EACA,KAAK,WACH,OAAO;GAAE;GAAO,KAAK,KAAK,OAAO,MAAM;EAAK;CAChD;CAEA,OAAO,SAAS,KAAK;EAAE;EAAO,SAAS,UAAU,SAAS,EAAE;EAAG;CAAM,IAAI;AAC3E;;AAGA,SAAS,aACP,MAKA,QACwB;CACxB,MAAM,EAAE,OAAO,UAAU,aAAa;CACtC,MAAM,QAAQ,SAAS,MAAM,KAAK;CAClC,IAAI,CAAC,SAAS,YAAY,MAAM,OAAO;CACvC,MAAM,SAAS;EACb;EACA,GAAI,MAAM,eAAe,aAAa,MAAM,eAAe,gBACvD,EAAE,QAAQ,MAAM,IAChB,CAAC;EACL,GAAI,MAAM,QAAQ,EAAE,SAAS,MAAM,MAAM,IAAI,CAAC;EAC9C,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;CACjD;CACA,QAAQ,MAAM,MAAd;EACE,KAAK,QAAQ;GACX,MAAM,SAAS,YAAY,KAAK,SAAS,KAAK,CAAC;GAC/C,IAAI,CAAC,QAAQ,OAAO;IAAE,GAAG;IAAQ,MAAM,UAAU,QAAQ;GAAE;GAC3D,MAAM,OAAO,OAAO,EAAE,CAAE,MAAM,GAAG,CAAC,CAAC,IAAI,UAAU;GACjD,OAAO;IAAE,GAAG;IAAQ;GAAK;EAC3B;EACA,KAAK,UACH,OAAO;GAAE,GAAG;GAAQ,SAAS,UAAU,QAAQ;EAAE;EACnD,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,QAAQ;GACX,MAAM,KAAK,QAAQ,MAAM,YAAY;GACrC,MAAM,OAAO,MAAM,SAAS,UAAU,MAAM,SAAS;GACrD,MAAM,WAAW,YAAgC;IAC/C,MAAM,QAAQ,UAAU,OAAO;IAC/B,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;IACtC,OAAO,OAAQ,MAAM,SAAS,SAAS,SAAS,KAAK,IAAI,OAAO,KAAK,IAAK;GAC5E;GACA,MAAM,QAAQ,QAAQ,QAAQ;GAC9B,MAAM,KAAK,QAAQ,QAAQ;GAC3B,IAAI,CAAC,MAAM,UAAU,KAAA,GAAW,OAAO;GACvC,IAAI,OAAO,aAAa,OAAO,cAAc;IAC3C,IAAI,OAAO,KAAA,GAAW,OAAO;IAC7B,OAAO;KACL,GAAG;KACH,MAAM;MAAE;MAAI;MAAO;KAAG;KACtB,GAAI,MAAM,SAAS,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;IACpD;GACF;GACA,OAAO;IACL,GAAG;IACH,MAAM;KAAE;KAAI;IAAM;IAClB,GAAI,MAAM,SAAS,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;GACpD;EACF;CACF;CACA,OAAO;AACT;;AAGA,SAAS,SAAS,MAAiB,UAAmB;CACpD,MAAM,UAAU,WAAW,QAAQ,UAAU,SAAS,GAAG,QAAQ,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;CACpF,KAAK,MAAM,WAAW,WAAW,QAAQ,UAAU,aAAa,GAAG,SAAS,GAAG;EAC7E,MAAM,QAAQ,UAAU,QAAQ,MAAM,OAAO,EAAE;EAC/C,MAAM,OAAO,QAAQ,SAAS,MAAM;EACpC,IAAI,CAAC,SAAS,CAAC,MAAM;EACrB,IAAI,OAAO,UAAU,OAAO,IAAI,CAAC;EAEjC,MAAM,SAAS,QAAQ,EAAE,QAAQ,MAAM,YAAY;EACnD,IAAI,UAAU,KAAK,WAAW,GAAG,OAAO,EAAE,GACxC,OAAO,KAAK,MAAM,OAAO,SAAS,CAAC,CAAC,CAAC,QAAQ,UAAU,EAAE;EAC3D,IAAI,CAAC,MAAM;EACX,MAAM,OAAQ,KAAK,MAAM,MAAM,SAAS,CAAC;EACzC,MAAM,QAAQ,KAAK,MAAM;EACzB,KAAK,MAAM,OACT,SAAS,QAAQ,OAAO,UAAU,WAC9B;GAAE,GAAG;GAAO;EAAK,IACjB;GAAE,GAAI,SAAS,OAAO,CAAC,IAAI,EAAE,OAAO,MAAM;GAAI;EAAK;CAC3D;AACF"}
|
package/dist/styles.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { HEAD, NS, attrs, esc } from "./xml.js";
|
|
2
|
+
// src/styles.ts
|
|
3
|
+
/** A color as the file writes it, `FFRRGGBB`; `undefined` for colors it can't write. */
|
|
4
|
+
function argb(color) {
|
|
5
|
+
if (!color) return void 0;
|
|
6
|
+
let hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color.trim())?.[1];
|
|
7
|
+
if (!hex) return void 0;
|
|
8
|
+
if (hex.length === 3) hex = [...hex].map((d) => d + d).join("");
|
|
9
|
+
return `FF${hex.toUpperCase()}`;
|
|
10
|
+
}
|
|
11
|
+
var BUILTIN_FORMATS = {
|
|
12
|
+
General: 0,
|
|
13
|
+
"0": 1,
|
|
14
|
+
"0.00": 2,
|
|
15
|
+
"#,##0": 3,
|
|
16
|
+
"#,##0.00": 4,
|
|
17
|
+
"0%": 9,
|
|
18
|
+
"0.00%": 10,
|
|
19
|
+
"0.00E+00": 11,
|
|
20
|
+
"@": 49
|
|
21
|
+
};
|
|
22
|
+
/** A list element with its count, `''` when empty. */
|
|
23
|
+
var list = (tag, items) => items.length ? `<${tag} count="${items.length}">${items.join("")}</${tag}>` : "";
|
|
24
|
+
/**
|
|
25
|
+
* The file's style sheet, built up as cells ask for looks: each different
|
|
26
|
+
* look is written once and cells refer to it by number.
|
|
27
|
+
*/
|
|
28
|
+
var StyleSheet = class {
|
|
29
|
+
formats = /* @__PURE__ */ new Map();
|
|
30
|
+
fonts = ["<font><sz val=\"11\"/><name val=\"Calibri\"/><family val=\"2\"/></font>"];
|
|
31
|
+
fontIds = /* @__PURE__ */ new Map([[this.fonts[0], 0]]);
|
|
32
|
+
fills = ["<fill><patternFill patternType=\"none\"/></fill>", "<fill><patternFill patternType=\"gray125\"/></fill>"];
|
|
33
|
+
fillIds = /* @__PURE__ */ new Map();
|
|
34
|
+
xfs = ["<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>"];
|
|
35
|
+
xfIds = /* @__PURE__ */ new Map([[this.xfs[0], 0]]);
|
|
36
|
+
dxfs = [];
|
|
37
|
+
dxfIds = /* @__PURE__ */ new Map();
|
|
38
|
+
/** The number of a look, `0` for the plain one. */
|
|
39
|
+
look({ style, format, quote }) {
|
|
40
|
+
const numFmtId = format ? this.format(format) : 0;
|
|
41
|
+
const fontId = style ? this.font(style) : 0;
|
|
42
|
+
const fillId = style ? this.fill(argb(style.background)) : 0;
|
|
43
|
+
const align = style && (style.align || style.valign || style.wrap) ? `<alignment${attrs({
|
|
44
|
+
horizontal: style.align,
|
|
45
|
+
vertical: style.valign === "middle" ? "center" : style.valign,
|
|
46
|
+
wrapText: style.wrap
|
|
47
|
+
})}/>` : "";
|
|
48
|
+
const open = style?.locked === false ? "<protection locked=\"0\"/>" : "";
|
|
49
|
+
const inner = align + open;
|
|
50
|
+
const xf = `<xf${attrs({
|
|
51
|
+
numFmtId,
|
|
52
|
+
fontId,
|
|
53
|
+
fillId,
|
|
54
|
+
borderId: 0,
|
|
55
|
+
xfId: 0,
|
|
56
|
+
applyNumberFormat: numFmtId ? 1 : void 0,
|
|
57
|
+
applyFont: fontId ? 1 : void 0,
|
|
58
|
+
applyFill: fillId ? 1 : void 0,
|
|
59
|
+
applyAlignment: align ? 1 : void 0,
|
|
60
|
+
applyProtection: open ? 1 : void 0,
|
|
61
|
+
quotePrefix: quote
|
|
62
|
+
})}${inner ? `>${inner}</xf>` : "/>"}`;
|
|
63
|
+
let id = this.xfIds.get(xf);
|
|
64
|
+
if (id == null) {
|
|
65
|
+
id = this.xfs.push(xf) - 1;
|
|
66
|
+
this.xfIds.set(xf, id);
|
|
67
|
+
}
|
|
68
|
+
return id;
|
|
69
|
+
}
|
|
70
|
+
/** The number of a conditional format's look. */
|
|
71
|
+
differential(style) {
|
|
72
|
+
const font = fontParts(style);
|
|
73
|
+
const fill = argb(style.background);
|
|
74
|
+
const dxf = `<dxf>${font ? `<font>${font}</font>` : ""}${fill ? `<fill><patternFill patternType="solid"><bgColor rgb="${fill}"/></patternFill></fill>` : ""}</dxf>`;
|
|
75
|
+
let id = this.dxfIds.get(dxf);
|
|
76
|
+
if (id == null) {
|
|
77
|
+
id = this.dxfs.push(dxf) - 1;
|
|
78
|
+
this.dxfIds.set(dxf, id);
|
|
79
|
+
}
|
|
80
|
+
return id;
|
|
81
|
+
}
|
|
82
|
+
format(code) {
|
|
83
|
+
const builtin = BUILTIN_FORMATS[code];
|
|
84
|
+
if (builtin != null) return builtin;
|
|
85
|
+
let id = this.formats.get(code);
|
|
86
|
+
if (id == null) {
|
|
87
|
+
id = 164 + this.formats.size;
|
|
88
|
+
this.formats.set(code, id);
|
|
89
|
+
}
|
|
90
|
+
return id;
|
|
91
|
+
}
|
|
92
|
+
font(style) {
|
|
93
|
+
const parts = fontParts(style);
|
|
94
|
+
if (!parts) return 0;
|
|
95
|
+
const font = `<font>${parts}<sz val="11"/><name val="Calibri"/><family val="2"/></font>`;
|
|
96
|
+
let id = this.fontIds.get(font);
|
|
97
|
+
if (id == null) {
|
|
98
|
+
id = this.fonts.push(font) - 1;
|
|
99
|
+
this.fontIds.set(font, id);
|
|
100
|
+
}
|
|
101
|
+
return id;
|
|
102
|
+
}
|
|
103
|
+
fill(color) {
|
|
104
|
+
if (!color) return 0;
|
|
105
|
+
let id = this.fillIds.get(color);
|
|
106
|
+
if (id == null) {
|
|
107
|
+
id = this.fills.push(`<fill><patternFill patternType="solid"><fgColor rgb="${color}"/><bgColor indexed="64"/></patternFill></fill>`) - 1;
|
|
108
|
+
this.fillIds.set(color, id);
|
|
109
|
+
}
|
|
110
|
+
return id;
|
|
111
|
+
}
|
|
112
|
+
toXML() {
|
|
113
|
+
const formats = [...this.formats].map(([code, id]) => `<numFmt numFmtId="${id}" formatCode="${esc(code)}"/>`);
|
|
114
|
+
return `${HEAD}<styleSheet xmlns="${NS}">` + list("numFmts", formats) + list("fonts", this.fonts) + list("fills", this.fills) + "<borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>" + list("cellXfs", this.xfs) + `<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles><dxfs count="${this.dxfs.length}">${this.dxfs.join("")}</dxfs></styleSheet>`;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
/** A style's font parts, in the order the file keeps them; `''` for none. */
|
|
118
|
+
function fontParts(style) {
|
|
119
|
+
const color = argb(style.color);
|
|
120
|
+
return (style.bold ? "<b/>" : "") + (style.italic ? "<i/>" : "") + (style.strike ? "<strike/>" : "") + (color ? `<color rgb="${color}"/>` : "") + (style.underline ? "<u/>" : "");
|
|
121
|
+
}
|
|
122
|
+
export { StyleSheet, argb };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","names":[],"sources":["../src/styles.ts"],"sourcesContent":["import type { SheetStyle } from '@dou-ui/sheet/core'\nimport { attrs, esc, HEAD, NS } from './xml'\n\n/** A color as the file writes it, `FFRRGGBB`; `undefined` for colors it can't write. */\nexport function argb(color: string | undefined) {\n if (!color) return undefined\n let hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color.trim())?.[1]\n if (!hex) return undefined\n if (hex.length === 3) hex = [...hex].map((d) => d + d).join('')\n return `FF${hex.toUpperCase()}`\n}\n\nconst BUILTIN_FORMATS: Record<string, number> = {\n General: 0,\n '0': 1,\n '0.00': 2,\n '#,##0': 3,\n '#,##0.00': 4,\n '0%': 9,\n '0.00%': 10,\n '0.00E+00': 11,\n '@': 49,\n}\n\n/** A look as the file keeps it: a style in plain colors and a number format. */\nexport interface CellLook {\n style?: SheetStyle\n format?: string\n /** Text that reads as a formula, kept as text when edited in other programs. */\n quote?: boolean\n}\n\n/** A list element with its count, `''` when empty. */\nconst list = (tag: string, items: string[]) =>\n items.length ? `<${tag} count=\"${items.length}\">${items.join('')}</${tag}>` : ''\n\n/**\n * The file's style sheet, built up as cells ask for looks: each different\n * look is written once and cells refer to it by number.\n */\nexport class StyleSheet {\n private formats = new Map<string, number>()\n private fonts = ['<font><sz val=\"11\"/><name val=\"Calibri\"/><family val=\"2\"/></font>']\n private fontIds = new Map<string, number>([[this.fonts[0]!, 0]])\n private fills = [\n '<fill><patternFill patternType=\"none\"/></fill>',\n '<fill><patternFill patternType=\"gray125\"/></fill>',\n ]\n private fillIds = new Map<string, number>()\n private xfs = ['<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>']\n private xfIds = new Map<string, number>([[this.xfs[0]!, 0]])\n private dxfs: string[] = []\n private dxfIds = new Map<string, number>()\n\n /** The number of a look, `0` for the plain one. */\n look({ style, format, quote }: CellLook) {\n const numFmtId = format ? this.format(format) : 0\n const fontId = style ? this.font(style) : 0\n const fillId = style ? this.fill(argb(style.background)) : 0\n const align =\n style && (style.align || style.valign || style.wrap)\n ? `<alignment${attrs({\n horizontal: style.align,\n vertical: style.valign === 'middle' ? 'center' : style.valign,\n wrapText: style.wrap,\n })}/>`\n : ''\n // cells are locked unless their style says otherwise\n const open = style?.locked === false ? '<protection locked=\"0\"/>' : ''\n const inner = align + open\n const xf = `<xf${attrs({\n numFmtId,\n fontId,\n fillId,\n borderId: 0,\n xfId: 0,\n applyNumberFormat: numFmtId ? 1 : undefined,\n applyFont: fontId ? 1 : undefined,\n applyFill: fillId ? 1 : undefined,\n applyAlignment: align ? 1 : undefined,\n applyProtection: open ? 1 : undefined,\n quotePrefix: quote,\n })}${inner ? `>${inner}</xf>` : '/>'}`\n let id = this.xfIds.get(xf)\n if (id == null) {\n id = this.xfs.push(xf) - 1\n this.xfIds.set(xf, id)\n }\n return id\n }\n\n /** The number of a conditional format's look. */\n differential(style: SheetStyle) {\n const font = fontParts(style)\n const fill = argb(style.background)\n const dxf = `<dxf>${font ? `<font>${font}</font>` : ''}${\n fill\n ? `<fill><patternFill patternType=\"solid\"><bgColor rgb=\"${fill}\"/></patternFill></fill>`\n : ''\n }</dxf>`\n let id = this.dxfIds.get(dxf)\n if (id == null) {\n id = this.dxfs.push(dxf) - 1\n this.dxfIds.set(dxf, id)\n }\n return id\n }\n\n private format(code: string) {\n const builtin = BUILTIN_FORMATS[code]\n if (builtin != null) return builtin\n let id = this.formats.get(code)\n if (id == null) {\n id = 164 + this.formats.size\n this.formats.set(code, id)\n }\n return id\n }\n\n private font(style: SheetStyle) {\n const parts = fontParts(style)\n if (!parts) return 0\n const font = `<font>${parts}<sz val=\"11\"/><name val=\"Calibri\"/><family val=\"2\"/></font>`\n let id = this.fontIds.get(font)\n if (id == null) {\n id = this.fonts.push(font) - 1\n this.fontIds.set(font, id)\n }\n return id\n }\n\n private fill(color: string | undefined) {\n if (!color) return 0\n let id = this.fillIds.get(color)\n if (id == null) {\n id =\n this.fills.push(\n `<fill><patternFill patternType=\"solid\"><fgColor rgb=\"${color}\"/><bgColor indexed=\"64\"/></patternFill></fill>`,\n ) - 1\n this.fillIds.set(color, id)\n }\n return id\n }\n\n toXML() {\n const formats = [...this.formats].map(\n ([code, id]) => `<numFmt numFmtId=\"${id}\" formatCode=\"${esc(code)}\"/>`,\n )\n return (\n `${HEAD}<styleSheet xmlns=\"${NS}\">` +\n list('numFmts', formats) +\n list('fonts', this.fonts) +\n list('fills', this.fills) +\n '<borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>' +\n '<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>' +\n list('cellXfs', this.xfs) +\n '<cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles>' +\n `<dxfs count=\"${this.dxfs.length}\">${this.dxfs.join('')}</dxfs>` +\n '</styleSheet>'\n )\n }\n}\n\n/** A style's font parts, in the order the file keeps them; `''` for none. */\nfunction fontParts(style: SheetStyle) {\n const color = argb(style.color)\n return (\n (style.bold ? '<b/>' : '') +\n (style.italic ? '<i/>' : '') +\n (style.strike ? '<strike/>' : '') +\n (color ? `<color rgb=\"${color}\"/>` : '') +\n (style.underline ? '<u/>' : '')\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SheetExtension, SheetLabel } from '@dou-ui/sheet';
|
|
2
|
+
import { type SheetXlsxImportOptions, type SheetXlsxImportResult } from './read';
|
|
3
|
+
import { type SheetXlsxExportOptions } from './write';
|
|
4
|
+
export { writeXlsx, type SheetXlsxExportOptions } from './write';
|
|
5
|
+
export { readXlsx, type SheetXlsxErrorCode, type SheetXlsxImportOptions, type SheetXlsxImportResult, type SheetXlsxReadOptions, type SheetXlsxWarning, } from './read';
|
|
6
|
+
export { sheetXlsxLocales, sheetXlsxMessagesFor } from './messages';
|
|
7
|
+
export type { SheetXlsxMessages, SheetXlsxMessagesInput, SheetXlsxWarningCode } from './messages';
|
|
8
|
+
declare module '@dou-ui/sheet' {
|
|
9
|
+
interface SheetExporterOptions {
|
|
10
|
+
xlsx: SheetXlsxExportOptions;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Writes the workbook, one sheet or the selected cells as an .xlsx file. */
|
|
14
|
+
export declare const xlsxExporter: import("@dou-ui/sheet").SheetExporter<SheetXlsxExportOptions>;
|
|
15
|
+
/** Reads an .xlsx file as a workbook; what it can't bring over comes back in `warnings`. */
|
|
16
|
+
export declare const xlsxImporter: import("@dou-ui/sheet").SheetImporter<SheetXlsxImportOptions, SheetXlsxImportResult>;
|
|
17
|
+
export interface SheetXlsxOptions extends SheetXlsxExportOptions, SheetXlsxImportOptions {
|
|
18
|
+
/** The name in the toolbar's export menu, and of the files in the import hints. */
|
|
19
|
+
label?: SheetLabel;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The .xlsx extension: adds exporting and importing .xlsx files to the
|
|
23
|
+
* toolbar, to `exportFile('xlsx')` / `saveFile('xlsx')` and to `importFile`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function xlsx(options?: SheetXlsxOptions): SheetExtension;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** The texts of reading .xlsx files: what couldn't be brought over, and why a file couldn't be read. */
|
|
2
|
+
export interface SheetXlsxMessages {
|
|
3
|
+
/** What a file had that the sheet can't hold, by warning code: a short noun phrase each, to be listed. */
|
|
4
|
+
warnings: Record<SheetXlsxWarningCode, string>;
|
|
5
|
+
/** Why a file couldn't be read, shown in the sheet's hint. */
|
|
6
|
+
notXlsx: string;
|
|
7
|
+
damaged: string;
|
|
8
|
+
locked: string;
|
|
9
|
+
}
|
|
10
|
+
/** What `readXlsx` couldn't bring over, as the `code` of its warnings. */
|
|
11
|
+
export type SheetXlsxWarningCode = 'border' | 'font' | 'richText' | 'image' | 'chart' | 'pivot' | 'table' | 'macro' | 'hyperlink' | 'password' | 'hiddenSheet' | 'external' | 'name' | 'conditional' | 'validation' | 'filter';
|
|
12
|
+
export declare const sheetXlsxLocales: Record<string, SheetXlsxMessages>;
|
|
13
|
+
/** The texts for a language, such as `zh-CN`; Chinese or English by its first part, English otherwise. */
|
|
14
|
+
export declare function sheetXlsxMessagesFor(locale?: string): SheetXlsxMessages;
|
|
15
|
+
/** Texts to use instead, in part: any of them, and any of the warnings. */
|
|
16
|
+
export type SheetXlsxMessagesInput = Partial<Omit<SheetXlsxMessages, 'warnings'>> & {
|
|
17
|
+
warnings?: Partial<SheetXlsxMessages['warnings']>;
|
|
18
|
+
};
|
|
19
|
+
/** A language's texts with some of them given instead. */
|
|
20
|
+
export declare function mergeXlsxMessages(base: SheetXlsxMessages, own: SheetXlsxMessagesInput | undefined): SheetXlsxMessages;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SheetStyle } from '@dou-ui/sheet/core';
|
|
2
|
+
import { type XmlNode } from './xml-read';
|
|
3
|
+
/** The theme's colors in the order cells name them: light 1, dark 1, light 2, dark 2, accents, links. */
|
|
4
|
+
export declare function themeColors(theme: XmlNode | undefined): (string | undefined)[];
|
|
5
|
+
/** A color element as `#rrggbb`; `undefined` for the automatic color or one the file doesn't say. */
|
|
6
|
+
export declare function colorOf(node: XmlNode | undefined, theme: (string | undefined)[]): string | undefined;
|
|
7
|
+
/** What a number format makes of a number: a date, a time, or a number. */
|
|
8
|
+
export declare function formatKind(code: string | undefined): 'date' | 'time' | 'number';
|
|
9
|
+
/** A look a cell takes, by its style number. */
|
|
10
|
+
export interface CellLookIn {
|
|
11
|
+
/** The style, in plain colors; `undefined` for none. */
|
|
12
|
+
style?: SheetStyle;
|
|
13
|
+
/** Its key, the same for the same style. */
|
|
14
|
+
key?: string;
|
|
15
|
+
/** The number format, `undefined` for General. */
|
|
16
|
+
format?: string;
|
|
17
|
+
kind: 'date' | 'time' | 'number';
|
|
18
|
+
/** Text that is kept as text even when it reads as a formula. */
|
|
19
|
+
quote: boolean;
|
|
20
|
+
/** What it has that the sheet can't hold. */
|
|
21
|
+
border: boolean;
|
|
22
|
+
font: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** The looks of the file's cells and conditional formats, from its style sheet. */
|
|
25
|
+
export declare function readStyles(sheet: XmlNode | undefined, theme: (string | undefined)[]): {
|
|
26
|
+
looks: CellLookIn[];
|
|
27
|
+
differentials: SheetStyle[];
|
|
28
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type SheetImportResult, type SheetImportWarning } from '@dou-ui/sheet/core';
|
|
2
|
+
import { type SheetXlsxMessagesInput, type SheetXlsxWarningCode } from './messages';
|
|
3
|
+
/** Options of reading an .xlsx file. */
|
|
4
|
+
export interface SheetXlsxImportOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Reads formulas; `false` reads only what they came to when the file was
|
|
7
|
+
* saved, e.g. for formulas with functions this sheet doesn't have. `true`
|
|
8
|
+
* by default.
|
|
9
|
+
*/
|
|
10
|
+
formulas?: boolean;
|
|
11
|
+
/** Texts of the warnings and of why a file couldn't be read, in part: such as `{ warnings: { border: '框线' } }`. */
|
|
12
|
+
messages?: SheetXlsxMessagesInput;
|
|
13
|
+
}
|
|
14
|
+
/** What `readXlsx` takes besides the file. */
|
|
15
|
+
export interface SheetXlsxReadOptions extends SheetXlsxImportOptions {
|
|
16
|
+
/** The language of the warnings and of why a file couldn't be read. */
|
|
17
|
+
locale?: string;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}
|
|
20
|
+
/** Something a file had that the sheet can't hold, as `readXlsx` lists it. */
|
|
21
|
+
export interface SheetXlsxWarning extends SheetImportWarning {
|
|
22
|
+
code: SheetXlsxWarningCode;
|
|
23
|
+
}
|
|
24
|
+
/** Why `readXlsx` couldn't read a file, as the `code` of its `SheetFileError`. */
|
|
25
|
+
export type SheetXlsxErrorCode = 'notXlsx' | 'damaged' | 'locked';
|
|
26
|
+
/** What `readXlsx` gives back. */
|
|
27
|
+
export interface SheetXlsxImportResult extends SheetImportResult {
|
|
28
|
+
warnings: SheetXlsxWarning[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reads an .xlsx file as a workbook: values, formulas, number formats,
|
|
32
|
+
* styles, merges, frozen panes, sizes, hidden rows and columns, groups,
|
|
33
|
+
* notes, data validations, conditional formats and filters. What it can't
|
|
34
|
+
* bring over, such as borders or charts, is listed in `warnings`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readXlsx(file: Blob | ArrayBuffer | Uint8Array, options?: SheetXlsxReadOptions): Promise<SheetXlsxImportResult>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SheetStyle } from '@dou-ui/sheet/core';
|
|
2
|
+
/** A color as the file writes it, `FFRRGGBB`; `undefined` for colors it can't write. */
|
|
3
|
+
export declare function argb(color: string | undefined): string | undefined;
|
|
4
|
+
/** A look as the file keeps it: a style in plain colors and a number format. */
|
|
5
|
+
export interface CellLook {
|
|
6
|
+
style?: SheetStyle;
|
|
7
|
+
format?: string;
|
|
8
|
+
/** Text that reads as a formula, kept as text when edited in other programs. */
|
|
9
|
+
quote?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The file's style sheet, built up as cells ask for looks: each different
|
|
13
|
+
* look is written once and cells refer to it by number.
|
|
14
|
+
*/
|
|
15
|
+
export declare class StyleSheet {
|
|
16
|
+
private formats;
|
|
17
|
+
private fonts;
|
|
18
|
+
private fontIds;
|
|
19
|
+
private fills;
|
|
20
|
+
private fillIds;
|
|
21
|
+
private xfs;
|
|
22
|
+
private xfIds;
|
|
23
|
+
private dxfs;
|
|
24
|
+
private dxfIds;
|
|
25
|
+
/** The number of a look, `0` for the plain one. */
|
|
26
|
+
look({ style, format, quote }: CellLook): number;
|
|
27
|
+
/** The number of a conditional format's look. */
|
|
28
|
+
differential(style: SheetStyle): number;
|
|
29
|
+
private format;
|
|
30
|
+
private font;
|
|
31
|
+
private fill;
|
|
32
|
+
toXML(): string;
|
|
33
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type SheetFileSource } from '@dou-ui/sheet/core';
|
|
2
|
+
/** Options of the .xlsx exporter. */
|
|
3
|
+
export interface SheetXlsxExportOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Writes formulas, with what they came to so other programs show the
|
|
6
|
+
* results until they work them out again; `false` writes only the
|
|
7
|
+
* results, e.g. for formulas with functions only this grid has. `true`
|
|
8
|
+
* by default; exporting the selection always writes the results.
|
|
9
|
+
*/
|
|
10
|
+
formulas?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Writes the cells a source exports as an .xlsx file. */
|
|
13
|
+
export declare function writeXlsx(source: SheetFileSource, options?: SheetXlsxExportOptions): Promise<Uint8Array>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Text with its entities, such as `&` and `中`, turned back into characters. */
|
|
2
|
+
export declare function unescape(text: string): string;
|
|
3
|
+
/** An element's attributes by name, without their prefixes: `r:id` is `id`. */
|
|
4
|
+
export declare function attrsOf(raw: string): Record<string, string>;
|
|
5
|
+
/** A yes-or-no attribute, which files write as `1` or `true`. */
|
|
6
|
+
export declare const isOn: (value: string | undefined) => value is "1" | "true";
|
|
7
|
+
/** Whether a true-or-false attribute is off; one left out is neither. */
|
|
8
|
+
export declare const isOff: (value: string | undefined) => value is "0" | "false";
|
|
9
|
+
/** An attribute that is on unless it says `0` or `false`. */
|
|
10
|
+
export declare const isNotOff: (value: string | undefined) => boolean;
|
|
11
|
+
/** What a reader is told as it goes through the text. */
|
|
12
|
+
export interface XmlHandler {
|
|
13
|
+
/** An element starts; `empty` when it ends there too, as `<a/>`. Names are without prefixes. */
|
|
14
|
+
open(name: string, attrs: string, empty: boolean): void;
|
|
15
|
+
close?(name: string): void;
|
|
16
|
+
/** Text between elements, its entities already turned back. */
|
|
17
|
+
text?(text: string): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Goes through XML text, telling `handler` what it meets. `step` reads up
|
|
21
|
+
* to `budget` tags and says whether there is more, so a big part can be
|
|
22
|
+
* read in pieces with pauses between.
|
|
23
|
+
*/
|
|
24
|
+
export declare class XmlReader {
|
|
25
|
+
private readonly xml;
|
|
26
|
+
private readonly handler;
|
|
27
|
+
private at;
|
|
28
|
+
constructor(xml: string, handler: XmlHandler);
|
|
29
|
+
/** Reads on; `false` once the text is done. */
|
|
30
|
+
step(budget?: number): boolean;
|
|
31
|
+
}
|
|
32
|
+
/** An element of a small part, read whole. */
|
|
33
|
+
export interface XmlNode {
|
|
34
|
+
name: string;
|
|
35
|
+
attrs: Record<string, string>;
|
|
36
|
+
children: XmlNode[];
|
|
37
|
+
/** The text inside it, its children's included. */
|
|
38
|
+
text: string;
|
|
39
|
+
}
|
|
40
|
+
/** Reads a small part, such as the workbook or the styles, as a tree. */
|
|
41
|
+
export declare function parseXml(xml: string): XmlNode;
|
|
42
|
+
/** The children of a node with this name. */
|
|
43
|
+
export declare const childrenOf: (node: XmlNode | undefined, name: string) => XmlNode[];
|
|
44
|
+
/** The first child of a node with this name. */
|
|
45
|
+
export declare const childOf: (node: XmlNode | undefined, name: string) => XmlNode | undefined;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Text for an XML element's content or attribute. */
|
|
2
|
+
export declare const esc: (text: string) => string;
|
|
3
|
+
/** Attributes, leaving out the ones without a value. */
|
|
4
|
+
export declare function attrs(list: Record<string, string | number | boolean | undefined | null>): string;
|
|
5
|
+
export declare const HEAD = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
|
|
6
|
+
export declare const NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
|
7
|
+
export declare const NS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
8
|
+
export declare const NS_PKG = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Lets the page handle what is waiting, such as input, before going on. */
|
|
2
|
+
export declare const pause: () => Promise<void>;
|
|
3
|
+
/** How long work goes on before letting the page go on, in ms. */
|
|
4
|
+
export declare const SLICE = 50;
|
|
5
|
+
/** How `zip` goes on with a big file: when to let the page go on, and when to stop. */
|
|
6
|
+
export interface ZipPacing {
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
/** When work last let the page go on, from `performance.now()`; kept up to date. */
|
|
9
|
+
lastPause: {
|
|
10
|
+
at: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** A file to put in a zip: its path, and its text or bytes, whole or in pieces. */
|
|
14
|
+
export interface ZipEntry {
|
|
15
|
+
path: string;
|
|
16
|
+
data: string | Uint8Array | Uint8Array[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Packs files into a zip, compressed. The files' times are left at the
|
|
20
|
+
* zip format's first day, so the same files give the same bytes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function zip(entries: readonly ZipEntry[], pacing?: ZipPacing): Promise<Uint8Array>;
|
|
23
|
+
/** A file in a zip, as its directory lists it. */
|
|
24
|
+
export interface ZipFile {
|
|
25
|
+
path: string;
|
|
26
|
+
/** Read it: its bytes, unpacked. */
|
|
27
|
+
read(pacing?: ZipPacing): Promise<Uint8Array>;
|
|
28
|
+
}
|
|
29
|
+
/** The files of a zip, by path, each read when asked for. Only stored and deflated files, as .xlsx files have. */
|
|
30
|
+
export declare function zipFiles(bytes: Uint8Array): Map<string, ZipFile>;
|
|
31
|
+
/** Reads all the files of a zip, by path. */
|
|
32
|
+
export declare function unzip(bytes: Uint8Array): Promise<Map<string, Uint8Array>>;
|