@office-kit/xlsx 0.8.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.
- package/LICENSE +21 -0
- package/README.md +319 -0
- package/THIRD_PARTY_NOTICES.md +56 -0
- package/dist/cell/cell.d.ts +234 -0
- package/dist/cell/index.d.ts +4 -0
- package/dist/cell/rich-text.d.ts +37 -0
- package/dist/cell-D9CaNKnU.mjs +320 -0
- package/dist/cell-D9CaNKnU.mjs.map +1 -0
- package/dist/cell-style-BEDjMX1y.mjs +1579 -0
- package/dist/cell-style-BEDjMX1y.mjs.map +1 -0
- package/dist/cell.mjs +2 -0
- package/dist/chart/chart-xml.d.ts +16 -0
- package/dist/chart/chart.d.ts +735 -0
- package/dist/chart/cx/chartex-xml.d.ts +6 -0
- package/dist/chart/cx/chartex.d.ts +279 -0
- package/dist/chart/index.d.ts +6 -0
- package/dist/chart/user-shapes-xml.d.ts +4 -0
- package/dist/chart/user-shapes.d.ts +61 -0
- package/dist/chart.mjs +232 -0
- package/dist/chart.mjs.map +1 -0
- package/dist/chartsheet/chartsheet-xml.d.ts +17 -0
- package/dist/chartsheet/chartsheet.d.ts +121 -0
- package/dist/chartsheet/index.d.ts +2 -0
- package/dist/chartsheet-C3-tqkPy.mjs +23 -0
- package/dist/chartsheet-C3-tqkPy.mjs.map +1 -0
- package/dist/chartsheet.mjs +2 -0
- package/dist/colors-ovWAwnZI.mjs +67 -0
- package/dist/colors-ovWAwnZI.mjs.map +1 -0
- package/dist/compat/numbers.d.ts +14 -0
- package/dist/coordinate-96Ecci4d.mjs +276 -0
- package/dist/coordinate-96Ecci4d.mjs.map +1 -0
- package/dist/datetime-B2ySVlXt.mjs +71 -0
- package/dist/datetime-B2ySVlXt.mjs.map +1 -0
- package/dist/defined-names-CviWmtQg.mjs +89 -0
- package/dist/defined-names-CviWmtQg.mjs.map +1 -0
- package/dist/differential-D4dg-qtZ.mjs +37 -0
- package/dist/differential-D4dg-qtZ.mjs.map +1 -0
- package/dist/drawing/anchor.d.ts +63 -0
- package/dist/drawing/dml/colors.d.ts +109 -0
- package/dist/drawing/dml/dml-xml.d.ts +35 -0
- package/dist/drawing/dml/effect.d.ts +92 -0
- package/dist/drawing/dml/fill.d.ts +115 -0
- package/dist/drawing/dml/geometry.d.ts +113 -0
- package/dist/drawing/dml/line.d.ts +41 -0
- package/dist/drawing/dml/shape-properties.d.ts +33 -0
- package/dist/drawing/dml/text.d.ts +218 -0
- package/dist/drawing/drawing-xml.d.ts +5 -0
- package/dist/drawing/drawing.d.ts +117 -0
- package/dist/drawing/image.d.ts +40 -0
- package/dist/drawing/index.d.ts +14 -0
- package/dist/drawing-BxzLuryn.mjs +415 -0
- package/dist/drawing-BxzLuryn.mjs.map +1 -0
- package/dist/drawing.mjs +119 -0
- package/dist/drawing.mjs.map +1 -0
- package/dist/escape-DFTE7ZJc.mjs +51 -0
- package/dist/escape-DFTE7ZJc.mjs.map +1 -0
- package/dist/exceptions-D-CFwxgm.mjs +37 -0
- package/dist/exceptions-D-CFwxgm.mjs.map +1 -0
- package/dist/formula/tokenizer.d.ts +61 -0
- package/dist/formula/translate.d.ts +67 -0
- package/dist/inference-B3ES3KEJ.mjs +42 -0
- package/dist/inference-B3ES3KEJ.mjs.map +1 -0
- package/dist/io/browser.d.ts +41 -0
- package/dist/io/index.d.ts +7 -0
- package/dist/io/load.d.ts +46 -0
- package/dist/io/node-fs.d.ts +62 -0
- package/dist/io/node-save.d.ts +3 -0
- package/dist/io/node.d.ts +17 -0
- package/dist/io/save.d.ts +14 -0
- package/dist/io/sink.d.ts +54 -0
- package/dist/io/source.d.ts +14 -0
- package/dist/io.mjs +212 -0
- package/dist/io.mjs.map +1 -0
- package/dist/load-D5cbhoGx.mjs +1069 -0
- package/dist/load-D5cbhoGx.mjs.map +1 -0
- package/dist/manifest-Dps1-OpP.mjs +801 -0
- package/dist/manifest-Dps1-OpP.mjs.map +1 -0
- package/dist/node.d.ts +3 -0
- package/dist/node.mjs +308 -0
- package/dist/node.mjs.map +1 -0
- package/dist/packaging/core.d.ts +45 -0
- package/dist/packaging/custom.d.ts +62 -0
- package/dist/packaging/extended.d.ts +45 -0
- package/dist/packaging/index.d.ts +10 -0
- package/dist/packaging/manifest.d.ts +24 -0
- package/dist/packaging/relationships.d.ts +30 -0
- package/dist/packaging.mjs +2 -0
- package/dist/parser-DuLejQy1.mjs +156 -0
- package/dist/parser-DuLejQy1.mjs.map +1 -0
- package/dist/reader-D1fNW9k1.mjs +534 -0
- package/dist/reader-D1fNW9k1.mjs.map +1 -0
- package/dist/save-RohQtgEZ.mjs +745 -0
- package/dist/save-RohQtgEZ.mjs.map +1 -0
- package/dist/schema/core.d.ts +133 -0
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/serialize.d.ts +6 -0
- package/dist/schema.mjs +2 -0
- package/dist/serialize-55EnT30e.mjs +254 -0
- package/dist/serialize-55EnT30e.mjs.map +1 -0
- package/dist/serializer-BwbgHYJV.mjs +116 -0
- package/dist/serializer-BwbgHYJV.mjs.map +1 -0
- package/dist/streaming/index.d.ts +2 -0
- package/dist/streaming/read-only.d.ts +38 -0
- package/dist/streaming/write-only.d.ts +47 -0
- package/dist/streaming.mjs +612 -0
- package/dist/streaming.mjs.map +1 -0
- package/dist/styles/alignment.d.ts +33 -0
- package/dist/styles/alignment.schema.d.ts +3 -0
- package/dist/styles/borders.d.ts +40 -0
- package/dist/styles/borders.schema.d.ts +4 -0
- package/dist/styles/cell-style.d.ts +270 -0
- package/dist/styles/colors.d.ts +128 -0
- package/dist/styles/colors.schema.d.ts +3 -0
- package/dist/styles/differential.d.ts +41 -0
- package/dist/styles/fills.d.ts +54 -0
- package/dist/styles/fills.schema.d.ts +6 -0
- package/dist/styles/fonts.d.ts +44 -0
- package/dist/styles/fonts.schema.d.ts +3 -0
- package/dist/styles/index.d.ts +21 -0
- package/dist/styles/named-styles.d.ts +52 -0
- package/dist/styles/numbers.d.ts +39 -0
- package/dist/styles/numbers.schema.d.ts +3 -0
- package/dist/styles/protection.d.ts +9 -0
- package/dist/styles/protection.schema.d.ts +3 -0
- package/dist/styles/stylesheet-reader.d.ts +7 -0
- package/dist/styles/stylesheet-writer.d.ts +3 -0
- package/dist/styles/stylesheet.d.ts +95 -0
- package/dist/styles.mjs +4 -0
- package/dist/stylesheet-writer-C2eRmn22.mjs +8624 -0
- package/dist/stylesheet-writer-C2eRmn22.mjs.map +1 -0
- package/dist/table-DkX6UniA.mjs +113 -0
- package/dist/table-DkX6UniA.mjs.map +1 -0
- package/dist/tree-Bbs1C8Rc.mjs +192 -0
- package/dist/tree-Bbs1C8Rc.mjs.map +1 -0
- package/dist/units-rOMQqXh2.mjs +41 -0
- package/dist/units-rOMQqXh2.mjs.map +1 -0
- package/dist/user-shapes-DfmCGKB0.mjs +252 -0
- package/dist/user-shapes-DfmCGKB0.mjs.map +1 -0
- package/dist/utf8-D91g1XTG.mjs +143 -0
- package/dist/utf8-D91g1XTG.mjs.map +1 -0
- package/dist/utils/coordinate.d.ts +103 -0
- package/dist/utils/css.d.ts +18 -0
- package/dist/utils/datetime.d.ts +38 -0
- package/dist/utils/escape.d.ts +34 -0
- package/dist/utils/exceptions.d.ts +34 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/inference.d.ts +24 -0
- package/dist/utils/stable-stringify.d.ts +7 -0
- package/dist/utils/units.d.ts +14 -0
- package/dist/utils/utf8.d.ts +1 -0
- package/dist/utils.mjs +39 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/workbook/calc-properties.d.ts +47 -0
- package/dist/workbook/defined-names.d.ts +121 -0
- package/dist/workbook/file-recovery.d.ts +11 -0
- package/dist/workbook/file-sharing.d.ts +14 -0
- package/dist/workbook/file-version.d.ts +13 -0
- package/dist/workbook/function-groups.d.ts +10 -0
- package/dist/workbook/index.d.ts +24 -0
- package/dist/workbook/protection.d.ts +35 -0
- package/dist/workbook/shared-strings.d.ts +57 -0
- package/dist/workbook/smart-tags.d.ts +13 -0
- package/dist/workbook/views.d.ts +89 -0
- package/dist/workbook/workbook-properties.d.ts +57 -0
- package/dist/workbook/workbook.d.ts +643 -0
- package/dist/workbook-HGYNRBlV.mjs +636 -0
- package/dist/workbook-HGYNRBlV.mjs.map +1 -0
- package/dist/workbook.mjs +58 -0
- package/dist/workbook.mjs.map +1 -0
- package/dist/worksheet/auto-filter.d.ts +34 -0
- package/dist/worksheet/cell-range.d.ts +121 -0
- package/dist/worksheet/comments-xml.d.ts +24 -0
- package/dist/worksheet/comments.d.ts +13 -0
- package/dist/worksheet/conditional-formatting.d.ts +150 -0
- package/dist/worksheet/custom-sheet-views.d.ts +43 -0
- package/dist/worksheet/data-consolidate.d.ts +29 -0
- package/dist/worksheet/data-validations.d.ts +72 -0
- package/dist/worksheet/dimensions.d.ts +40 -0
- package/dist/worksheet/errors.d.ts +40 -0
- package/dist/worksheet/hyperlinks.d.ts +42 -0
- package/dist/worksheet/index.d.ts +46 -0
- package/dist/worksheet/ole-objects.d.ts +37 -0
- package/dist/worksheet/page-setup.d.ts +173 -0
- package/dist/worksheet/phonetic.d.ts +11 -0
- package/dist/worksheet/properties.d.ts +34 -0
- package/dist/worksheet/protected-ranges.d.ts +19 -0
- package/dist/worksheet/protection.d.ts +44 -0
- package/dist/worksheet/reader.d.ts +38 -0
- package/dist/worksheet/scenarios.d.ts +36 -0
- package/dist/worksheet/smart-tags.d.ts +23 -0
- package/dist/worksheet/sort-state.d.ts +28 -0
- package/dist/worksheet/table-xml.d.ts +5 -0
- package/dist/worksheet/table.d.ts +80 -0
- package/dist/worksheet/views.d.ts +47 -0
- package/dist/worksheet/web-publish.d.ts +21 -0
- package/dist/worksheet/worksheet.d.ts +935 -0
- package/dist/worksheet/writer.d.ts +72 -0
- package/dist/worksheet-CmCNoIgD.mjs +1726 -0
- package/dist/worksheet-CmCNoIgD.mjs.map +1 -0
- package/dist/worksheet.mjs +247 -0
- package/dist/worksheet.mjs.map +1 -0
- package/dist/writer-DspzfkNA.mjs +221 -0
- package/dist/writer-DspzfkNA.mjs.map +1 -0
- package/dist/xml/index.d.ts +10 -0
- package/dist/xml/iterparse.d.ts +22 -0
- package/dist/xml/namespaces.d.ts +91 -0
- package/dist/xml/parser.d.ts +7 -0
- package/dist/xml/serializer.d.ts +14 -0
- package/dist/xml/stream-writer.d.ts +39 -0
- package/dist/xml/tree.d.ts +37 -0
- package/dist/xml.mjs +140 -0
- package/dist/xml.mjs.map +1 -0
- package/dist/zip/decompression-guard.d.ts +70 -0
- package/dist/zip/index.d.ts +6 -0
- package/dist/zip/random-access-reader.d.ts +16 -0
- package/dist/zip/reader.d.ts +45 -0
- package/dist/zip/writer.d.ts +65 -0
- package/dist/zip/zip64-patch.d.ts +12 -0
- package/dist/zip.mjs +3 -0
- package/package.json +147 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-RohQtgEZ.mjs","names":["serializeXmlNode"],"sources":["../src/io/save.ts"],"sourcesContent":["// Public `saveWorkbook` entry point.\n//\n// **Stage 1 minimum**: emits the bare set of parts a Workbook needs to\n// round-trip through `loadWorkbook`:\n//\n// [Content_Types].xml\n// _rels/.rels\n// xl/workbook.xml\n// xl/_rels/workbook.xml.rels\n// xl/worksheets/sheetN.xml ...\n// xl/styles.xml\n// xl/sharedStrings.xml (only when sst is non-empty)\n//\n// docProps / theme / VBA / drawings / charts are reserved for later iterations\n// — load tolerates their absence.\n\nimport { escapeXmlAttr, escapeXmlText } from '../utils/escape';\nimport { chartToBytes } from '../chart/chart-xml';\nimport { chartExToBytes } from '../chart/cx/chartex-xml';\nimport { userShapesToBytes } from '../chart/user-shapes-xml';\nimport { chartsheetToBytes } from '../chartsheet/chartsheet-xml';\nimport type { Drawing, DrawingItem } from '../drawing/drawing';\nimport { drawingToBytes } from '../drawing/drawing-xml';\nimport { IMAGE_FORMAT_EXTENSION, IMAGE_FORMAT_MIME, type XlsxImageFormat } from '../drawing/image';\nimport type { XlsxSink } from '../io/sink';\nimport { OpenXmlIoError, OpenXmlSchemaError } from '../utils/exceptions';\nimport { corePropsToBytes } from '../packaging/core';\nimport { customPropsToBytes } from '../packaging/custom';\nimport { extendedPropsToBytes } from '../packaging/extended';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest';\nimport { makeRelationships, type Relationships, relsToBytes } from '../packaging/relationships';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer';\nimport { makeSharedStrings, sharedStringsToBytes } from '../workbook/shared-strings';\nimport { type Workbook, validateSheetTitle } from '../workbook/workbook';\nimport type { LegacyComment } from '../worksheet/comments';\nimport { commentsToBytes, placeholderVmlDrawing } from '../worksheet/comments-xml';\nimport type { TableDefinition } from '../worksheet/table';\nimport { tableToBytes } from '../worksheet/table-xml';\nimport { worksheetToBytes } from '../worksheet/writer';\nimport { serializeXml as serializeXmlNode } from '../xml/serializer';\nimport {\n ARC_APP,\n ARC_CONTENT_TYPES,\n ARC_CORE,\n ARC_CUSTOM,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_THEME,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n CHARTEX_TYPE,\n CPROPS_TYPE,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n THEME_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces';\nimport { createZipWriter } from '../zip/writer';\n\nconst CORE_PROPS_TYPE = 'application/vnd.openxmlformats-package.core-properties+xml';\nconst EXT_PROPS_TYPE = 'application/vnd.openxmlformats-officedocument.extended-properties+xml';\nconst CORE_PROPS_REL = `${PKG_REL_NS}/metadata/core-properties`;\nconst EXT_PROPS_REL = `${REL_NS}/extended-properties`;\nconst CUSTOM_PROPS_REL = `${REL_NS}/custom-properties`;\nconst THEME_REL = `${REL_NS}/theme`;\nconst TABLE_REL = `${REL_NS}/table`;\nconst TABLE_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml';\nconst COMMENTS_REL = `${REL_NS}/comments`;\nconst VML_DRAWING_REL = `${REL_NS}/vmlDrawing`;\nconst COMMENTS_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml';\nconst VML_DRAWING_TYPE = 'application/vnd.openxmlformats-officedocument.vmlDrawing';\nconst DRAWING_REL = `${REL_NS}/drawing`;\nconst DRAWING_TYPE = 'application/vnd.openxmlformats-officedocument.drawing+xml';\nconst CHART_REL = `${REL_NS}/chart`;\nconst CHARTEX_REL = 'http://schemas.microsoft.com/office/2014/relationships/chartEx';\nconst CHART_TYPE = 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml';\nconst IMAGE_REL = `${REL_NS}/image`;\nconst CHARTSHEET_REL = `${REL_NS}/chartsheet`;\nconst CHARTSHEET_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml';\nconst CHART_USER_SHAPES_REL = `${REL_NS}/chartUserShapes`;\n\nexport interface SaveOptions {\n /** Reserved — passes through to the underlying ZIP writer when implemented. */\n compressionLevel?: number;\n}\n\n/** Convenience: serialise a Workbook to an in-memory `Uint8Array` xlsx.\n *\n * Browser-safe: this path uses an in-memory `Uint8Array` sink and never\n * touches Node's `Buffer` global, so it works unchanged in browser bundles.\n */\nexport async function workbookToBytes(wb: Workbook, opts: SaveOptions = {}): Promise<Uint8Array> {\n const sink = toUint8ArraySink();\n await saveWorkbook(wb, sink, opts);\n return sink.result();\n}\n\nconst toUint8ArraySink = (): XlsxSink & { result(): Uint8Array } => {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n let total = 0;\n for (const c of chunks) total += c.byteLength;\n const out = new Uint8Array(total);\n let off = 0;\n for (const c of chunks) {\n out.set(c, off);\n off += c.byteLength;\n }\n finalised = out;\n chunks.length = 0;\n return out;\n };\n return {\n toBytes() {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) {\n throw new OpenXmlIoError('workbookToBytes sink: write after finish');\n }\n if (!(chunk instanceof Uint8Array)) {\n throw new OpenXmlIoError('workbookToBytes sink: chunk is not a Uint8Array');\n }\n chunks.push(chunk);\n },\n async finish(): Promise<Uint8Array> {\n return finalise();\n },\n abort(): void {\n if (finalised !== undefined) return;\n finalised = new Uint8Array(0);\n chunks.length = 0;\n },\n };\n },\n result(): Uint8Array {\n return finalise();\n },\n };\n};\n\n/**\n * Validate every sheet title against Excel's character + length rules and\n * confirm titles are unique within the workbook. Catches bad state introduced\n * via direct mutation (`ws.title = ...`) that bypassed the public mutators.\n *\n * Without this gate, a workbook with an invalid sheet name would round-trip to\n * an xlsx Excel rejects with a generic \"file is corrupt\" dialog on open —\n * making it hard to diagnose. Raising at save time keeps the bad state\n * recoverable: callers can `renameSheet` and retry.\n */\nconst validateSheetTitles = (wb: Workbook): void => {\n const seen = new Map<string, number>();\n for (let i = 0; i < wb.sheets.length; i++) {\n const ref = wb.sheets[i];\n if (!ref) continue;\n const title = ref.sheet.title;\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlSchemaError(`saveWorkbook: sheet[${i}] title \"${title}\": ${reason}`);\n }\n const lower = title.toLowerCase();\n const prior = seen.get(lower);\n if (prior !== undefined) {\n throw new OpenXmlSchemaError(\n `saveWorkbook: sheet[${i}] title \"${title}\" collides with sheet[${prior}]` +\n ` (Excel treats sheet names case-insensitively for uniqueness).`,\n );\n }\n seen.set(lower, i);\n }\n};\n\n/** Save a workbook through the given sink. Returns once `finalize()` resolves. */\nexport async function saveWorkbook(wb: Workbook, sink: XlsxSink, _opts: SaveOptions = {}): Promise<void> {\n validateSheetTitles(wb);\n const writer = createZipWriter(sink);\n try {\n await saveWorkbookImpl(wb, writer);\n } catch (err) {\n // Release the sink so streaming destinations (`toFile` / `toWritable`)\n // don't leave a half-written file looking valid. abort() is idempotent so\n // a successful finalize() above is a no-op here.\n writer.abort(err);\n throw err;\n }\n}\n\nasync function saveWorkbookImpl(wb: Workbook, writer: ReturnType<typeof createZipWriter>): Promise<void> {\n // ---- 1. assemble the per-sheet rels + serialise each worksheet ----------\n const sst = makeSharedStrings();\n interface SheetEmit {\n id: string;\n target: string;\n bytes: Uint8Array;\n /** OOXML relationship type used in workbook.xml.rels. */\n relType: string;\n /** ZIP archive path the bytes are written to. */\n archivePath: string;\n /** Override content type for [Content_Types].xml. */\n contentType: string;\n /** Per-sheet rels — populated only if the sheet has hyperlinks / drawings / etc. */\n rels?: Relationships;\n }\n const sheetEmits: SheetEmit[] = [];\n // Workbook-global table counter so xl/tables/tableN.xml ids stay unique.\n const tableEmits: Array<{ id: number; bytes: Uint8Array }> = [];\n let nextTableId = 1;\n // Same counter pattern for comments parts. The comments part and the VML\n // drawing share their N because Excel always emits them paired.\n interface CommentEmit {\n id: number;\n commentsBytes: Uint8Array;\n vmlBytes: Uint8Array;\n }\n const commentEmits: CommentEmit[] = [];\n let nextCommentsId = 1;\n // Drawings: workbook-global drawingN counter for xl/drawings/drawingN.xml +\n // matching drawing-rels file (when chart items are present).\n interface DrawingEmit {\n id: number;\n bytes: Uint8Array;\n /** Drawing rels — when non-empty we also emit the rels file. */\n rels?: Relationships;\n }\n const drawingEmits: DrawingEmit[] = [];\n let nextDrawingId = 1;\n // Chart parts share a workbook-global counter so xl/charts/chartN.xml ids\n // stay unique.\n const chartEmits: Array<{\n id: number;\n bytes: Uint8Array;\n isCx: boolean;\n /** Per-chart rels file (only emitted when chart.userShapes is set). */\n rels?: Relationships;\n }> = [];\n let nextChartId = 1;\n // Workbook-global counter for chartDrawing parts. Each chart with userShapes\n // set produces one xl/drawings/chartDrawingN.xml entry.\n const userShapeEmits: Array<{ id: number; bytes: Uint8Array }> = [];\n let nextUserShapesId = 1;\n // Workbook-global counter for image media parts. Excel uses\n // xl/media/imageN.{ext} where N is shared across the package.\n interface ImageEmit {\n id: number;\n /** File extension (without the dot) — also drives the manifest Default. */\n ext: string;\n bytes: Uint8Array;\n }\n const imageEmits: ImageEmit[] = [];\n const imageExts = new Set<string>();\n let nextImageId = 1;\n // Track separate counters so worksheet / chartsheet IDs do not collide (Excel\n // uses xl/worksheets/sheetN.xml and xl/chartsheets/sheetM.xml independently\n // of one another).\n let nextWorksheetId = 1;\n let nextChartsheetId = 1;\n // Pre-claim every original rId so freshly allocated ones (sheets without a\n // captured rId, plus modeled non-sheet rels) avoid collision with captured\n // workbookRelsExtras and the modeled non-sheet original ids.\n const claimedRIds = new Set<string>();\n for (const ref of wb.sheets) {\n if (ref.rId !== undefined) claimedRIds.add(ref.rId);\n }\n if (wb.workbookRelOriginalIds) {\n for (const v of Object.values(wb.workbookRelOriginalIds)) {\n if (typeof v === 'string') claimedRIds.add(v);\n }\n }\n if (wb.workbookRelsExtras) {\n for (const e of wb.workbookRelsExtras) claimedRIds.add(e.id);\n }\n let nextRIdCursor = 1;\n const allocateRId = (): string => {\n let id = `rId${nextRIdCursor}`;\n while (claimedRIds.has(id)) {\n nextRIdCursor++;\n id = `rId${nextRIdCursor}`;\n }\n claimedRIds.add(id);\n nextRIdCursor++;\n return id;\n };\n wb.sheets.forEach((ref, _i) => {\n const isChartsheet = ref.kind === 'chartsheet';\n const target = isChartsheet ? `chartsheets/sheet${nextChartsheetId}.xml` : `worksheets/sheet${nextWorksheetId}.xml`;\n const archivePath = isChartsheet\n ? `xl/chartsheets/sheet${nextChartsheetId}.xml`\n : `xl/worksheets/sheet${nextWorksheetId}.xml`;\n if (isChartsheet) nextChartsheetId++;\n else nextWorksheetId++;\n const sheetRels = makeRelationships();\n // Pre-claim every captured relsExtras rId so freshly allocated modeled rels\n // never clash. The extras themselves are appended to sheetRels at the end\n // so any rId already used inside the worksheet body (drawing / hyperlink\n // refs) keeps pointing at our newly emitted rel.\n const sheetRelsClaimed = new Set<string>();\n const sheetRelsExtras = ref.kind === 'worksheet' ? (ref.sheet.relsExtras ?? []) : [];\n for (const e of sheetRelsExtras) sheetRelsClaimed.add(e.id);\n let sheetRIdCursor = 1;\n const allocateSheetRId = (): string => {\n let id = `rId${sheetRIdCursor}`;\n while (sheetRelsClaimed.has(id) || sheetRels.rels.some((r) => r.id === id)) {\n sheetRIdCursor++;\n id = `rId${sheetRIdCursor}`;\n }\n sheetRIdCursor++;\n return id;\n };\n const registerTable = (table: TableDefinition): { rId: string } => {\n const tableId = nextTableId++;\n const rId = allocateSheetRId();\n sheetRels.rels.push({\n id: rId,\n type: TABLE_REL,\n target: `../tables/table${tableId}.xml`,\n });\n // Emit the table part with its workbook-global id baked in.\n const xmlTable: TableDefinition = { ...table, id: tableId };\n tableEmits.push({ id: tableId, bytes: tableToBytes(xmlTable) });\n return { rId };\n };\n const registerComments = (comments: ReadonlyArray<LegacyComment>): { vmlRelId: string } => {\n const id = nextCommentsId++;\n const commentsRelId = allocateSheetRId();\n sheetRels.rels.push({\n id: commentsRelId,\n type: COMMENTS_REL,\n target: `../comments${id}.xml`,\n });\n const vmlRelId = allocateSheetRId();\n sheetRels.rels.push({\n id: vmlRelId,\n type: VML_DRAWING_REL,\n target: `../drawings/vmlDrawing${id}.vml`,\n });\n commentEmits.push({\n id,\n commentsBytes: commentsToBytes(comments),\n vmlBytes: placeholderVmlDrawing(comments),\n });\n return { vmlRelId };\n };\n const registerDrawing = (drawing: Drawing): { rId: string } => {\n const id = nextDrawingId++;\n const rId = allocateSheetRId();\n sheetRels.rels.push({\n id: rId,\n type: DRAWING_REL,\n target: `../drawings/drawing${id}.xml`,\n });\n // Walk drawing items: for each chart with a payload, allocate a\n // workbook-global chartN id and a per-drawing rId. Emit the chart part +\n // collect a drawing-rels entry so drawing.xml's <c:chart r:id> resolves.\n const drawingRels = makeRelationships();\n const itemsForXml: DrawingItem[] = [];\n for (const item of drawing.items) {\n if (item.content.kind === 'chart' && (item.content.chart.space || item.content.chart.cxSpace)) {\n const chartId = nextChartId++;\n const chartRId = `rId${drawingRels.rels.length + 1}`;\n // chartex parts use a different relationship Type than the legacy\n // ECMA-376 charts. Excel rejects the workbook when the drawing rels\n // claim a `relationships/chart` target that actually contains a\n // `cx:chartSpace` root.\n const isCxChart = item.content.chart.cxSpace !== undefined;\n drawingRels.rels.push({\n id: chartRId,\n type: isCxChart ? CHARTEX_REL : CHART_REL,\n target: `../charts/chart${chartId}.xml`,\n });\n if (item.content.chart.cxSpace) {\n chartEmits.push({\n id: chartId,\n bytes: chartExToBytes(item.content.chart.cxSpace),\n isCx: true,\n });\n } else if (item.content.chart.space) {\n const space = item.content.chart.space;\n // If the chart carries user shapes, allocate the chartDrawingN part\n // + a per-chart rels file referencing it, then bake the resulting\n // r:id into the chart's <c:userShapes> element.\n let userShapesRId: string | undefined;\n let chartRelsFile: Relationships | undefined;\n if (space.userShapes && space.userShapes.shapes.length > 0) {\n const userShapesId = nextUserShapesId++;\n userShapesRId = 'rId1';\n chartRelsFile = makeRelationships();\n chartRelsFile.rels.push({\n id: userShapesRId,\n type: CHART_USER_SHAPES_REL,\n target: `../drawings/chartDrawing${userShapesId}.xml`,\n });\n userShapeEmits.push({\n id: userShapesId,\n bytes: userShapesToBytes(space.userShapes),\n });\n }\n const chartEmit: typeof chartEmits[number] = {\n id: chartId,\n bytes: chartToBytes(space, userShapesRId !== undefined ? { userShapesRId } : {}),\n isCx: false,\n };\n if (chartRelsFile) chartEmit.rels = chartRelsFile;\n chartEmits.push(chartEmit);\n }\n itemsForXml.push({\n anchor: item.anchor,\n content: {\n kind: 'chart',\n chart: {\n rId: chartRId,\n ...(item.content.chart.cxSpace ? { isCx: true } : {}),\n },\n },\n });\n } else if (item.content.kind === 'picture' && item.content.picture.image) {\n const img = item.content.picture.image;\n const ext = IMAGE_FORMAT_EXTENSION[img.format];\n const imageId = nextImageId++;\n const picRId = `rId${drawingRels.rels.length + 1}`;\n drawingRels.rels.push({\n id: picRId,\n type: IMAGE_REL,\n target: `../media/image${imageId}.${ext}`,\n });\n imageEmits.push({ id: imageId, ext, bytes: img.bytes });\n imageExts.add(ext);\n itemsForXml.push({\n anchor: item.anchor,\n content: {\n kind: 'picture',\n picture: {\n rId: picRId,\n ...(item.content.picture.name !== undefined ? { name: item.content.picture.name } : {}),\n ...(item.content.picture.descr !== undefined ? { descr: item.content.picture.descr } : {}),\n ...(item.content.picture.hidden !== undefined ? { hidden: item.content.picture.hidden } : {}),\n ...(item.content.picture.spPr ? { spPr: item.content.picture.spPr } : {}),\n },\n },\n });\n } else {\n itemsForXml.push(item);\n }\n }\n const emit: DrawingEmit = { id, bytes: drawingToBytes({ items: itemsForXml }) };\n if (drawingRels.rels.length > 0) emit.rels = drawingRels;\n drawingEmits.push(emit);\n return { rId };\n };\n let bytes: Uint8Array;\n if (ref.kind === 'worksheet') {\n bytes = worksheetToBytes(ref.sheet, {\n sharedStrings: sst,\n date1904: wb.date1904,\n rels: sheetRels,\n registerTable,\n registerComments,\n registerDrawing,\n });\n } else {\n // Chartsheet: register the drawing (if any), then emit the chartsheet\n // part with the resulting r:id baked in.\n let drawingRId: string | undefined;\n if (ref.sheet.drawing) drawingRId = registerDrawing(ref.sheet.drawing).rId;\n bytes = chartsheetToBytes(ref.sheet, drawingRId !== undefined ? { drawingRId } : {});\n }\n // Append captured per-sheet rels passthrough (pivotTable / queryTable /\n // printerSettings / oleObject / customProperty / threadedComment …)\n // verbatim. Their original rIds were pre-claimed so the modeled allocations\n // above never collide with them.\n for (const e of sheetRelsExtras) {\n sheetRels.rels.push({ id: e.id, type: e.type, target: e.target });\n }\n const sheetRId = ref.rId ?? allocateRId();\n const emit: SheetEmit = {\n id: sheetRId,\n target,\n bytes,\n relType: isChartsheet ? CHARTSHEET_REL : `${REL_NS}/worksheet`,\n archivePath,\n contentType: isChartsheet ? CHARTSHEET_TYPE : WORKSHEET_TYPE,\n };\n if (sheetRels.rels.length > 0) emit.rels = sheetRels;\n sheetEmits.push(emit);\n });\n\n // ---- 2. workbook rels -- sheets first, then sst (if any), then styles, then\n // theme / vbaProject, then any captured workbookRelsExtras (e.g.\n // pivotCacheDefinition rels referenced by `<pivotCaches>`). Modeled non-sheet\n // rels prefer the rId captured at load time so any captured extras XML using\n // that Id still resolves after the round-trip.\n const wbRels = makeRelationships();\n wbRels.rels = sheetEmits.map((e) => ({\n id: e.id,\n type: e.relType,\n target: e.target,\n }));\n const orig = wb.workbookRelOriginalIds;\n if (sst.entries.length > 0) {\n wbRels.rels.push({\n id: orig?.sharedStrings ?? allocateRId(),\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: orig?.styles ?? allocateRId(),\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n if (wb.themeXml) {\n wbRels.rels.push({\n id: orig?.theme ?? allocateRId(),\n type: THEME_REL,\n target: 'theme/theme1.xml',\n });\n }\n if (wb.vbaProject) {\n wbRels.rels.push({\n id: orig?.vbaProject ?? allocateRId(),\n type: `${REL_NS}/vbaProject`,\n target: 'vbaProject.bin',\n });\n }\n if (wb.workbookRelsExtras) {\n for (const e of wb.workbookRelsExtras) {\n wbRels.rels.push({ id: e.id, type: e.type, target: e.target });\n }\n }\n\n // ---- 3. workbook.xml ----------------------------------------------------\n const workbookXml = serializeWorkbookXml(\n wb,\n sheetEmits.map((e) => e.id),\n );\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // ---- 4. each worksheet / chartsheet (and its rels file when present) --\n for (const e of sheetEmits) {\n await writer.addEntry(e.archivePath, e.bytes);\n if (e.rels) {\n // The rels file sits alongside its part: `xl/<dir>/_rels/<file>.rels`.\n const slash = e.archivePath.lastIndexOf('/');\n const dir = e.archivePath.slice(0, slash);\n const file = e.archivePath.slice(slash + 1);\n await writer.addEntry(`${dir}/_rels/${file}.rels`, relsToBytes(e.rels));\n }\n }\n\n // ---- 4b. table parts ----------------------------------------------------\n for (const t of tableEmits) {\n await writer.addEntry(`xl/tables/table${t.id}.xml`, t.bytes);\n }\n\n // ---- 4c. comments parts + matching VML drawings ------------------------\n for (const c of commentEmits) {\n await writer.addEntry(`xl/comments${c.id}.xml`, c.commentsBytes);\n await writer.addEntry(`xl/drawings/vmlDrawing${c.id}.vml`, c.vmlBytes);\n }\n\n // ---- 4d. drawings + their rels (when charts are embedded) -------------\n for (const d of drawingEmits) {\n await writer.addEntry(`xl/drawings/drawing${d.id}.xml`, d.bytes);\n if (d.rels) {\n await writer.addEntry(`xl/drawings/_rels/drawing${d.id}.xml.rels`, relsToBytes(d.rels));\n }\n }\n\n // ---- 4e. chart parts (and per-chart rels when user shapes attach) -----\n for (const c of chartEmits) {\n await writer.addEntry(`xl/charts/chart${c.id}.xml`, c.bytes);\n if (c.rels) {\n await writer.addEntry(`xl/charts/_rels/chart${c.id}.xml.rels`, relsToBytes(c.rels));\n }\n }\n\n // ---- 4f. user-shape drawings (xl/drawings/chartDrawingN.xml) ----------\n for (const us of userShapeEmits) {\n await writer.addEntry(`xl/drawings/chartDrawing${us.id}.xml`, us.bytes);\n }\n\n // ---- 4g. embedded images (xl/media/imageN.{ext}) ----------------------\n for (const img of imageEmits) {\n await writer.addEntry(`xl/media/image${img.id}.${img.ext}`, img.bytes);\n }\n\n // ---- 5. styles.xml + sharedStrings.xml (if any) -------------------------\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(wb.styles));\n if (sst.entries.length > 0) {\n await writer.addEntry(ARC_SHARED_STRINGS, sharedStringsToBytes(sst));\n }\n\n // ---- 5b. theme1.xml (passthrough) — only when wb carries one. The theme rel\n // was already added to wbRels above so workbook.xml.rels references it.\n if (wb.themeXml) await writer.addEntry(ARC_THEME, wb.themeXml);\n\n // ---- 5c. docProps/{core,app,custom}.xml (when present) ------------------\n if (wb.properties) await writer.addEntry(ARC_CORE, corePropsToBytes(wb.properties));\n if (wb.appProperties) await writer.addEntry(ARC_APP, extendedPropsToBytes(wb.appProperties));\n if (wb.customProperties) await writer.addEntry(ARC_CUSTOM, customPropsToBytes(wb.customProperties));\n\n // ---- 5d. VBA project + signature (when present) -------------------------\n if (wb.vbaProject) await writer.addEntry('xl/vbaProject.bin', wb.vbaProject);\n if (wb.vbaSignature) await writer.addEntry('xl/vbaProjectSignature.bin', wb.vbaSignature);\n\n // ---- 5e. Pass-through bytes (pivot / activeX / customXml / etc.) -------\n if (wb.passthrough) {\n for (const [path, bytes] of wb.passthrough) await writer.addEntry(path, bytes);\n }\n\n // ---- 6. root rels -------------------------------------------------------\n const rootRels: Relationships = { rels: [] };\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n if (wb.properties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: CORE_PROPS_REL,\n target: 'docProps/core.xml',\n });\n }\n if (wb.appProperties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: EXT_PROPS_REL,\n target: 'docProps/app.xml',\n });\n }\n if (wb.customProperties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: CUSTOM_PROPS_REL,\n target: 'docProps/custom.xml',\n });\n }\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n\n // ---- 7. [Content_Types].xml --------------------------------------------\n const manifest = makeManifest();\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n // VBA-bearing workbooks promote the workbook content type to xlsm.\n const workbookContentType = wb.vbaProject\n ? 'application/vnd.ms-excel.sheet.macroEnabled.main+xml'\n : XLSX_TYPE;\n addOverride(manifest, `/${ARC_WORKBOOK}`, workbookContentType);\n for (const e of sheetEmits) {\n addOverride(manifest, `/${e.archivePath}`, e.contentType);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (sst.entries.length > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n if (wb.themeXml) addOverride(manifest, `/${ARC_THEME}`, THEME_TYPE);\n for (const t of tableEmits) {\n addOverride(manifest, `/xl/tables/table${t.id}.xml`, TABLE_TYPE);\n }\n if (commentEmits.length > 0) {\n addDefault(manifest, 'vml', VML_DRAWING_TYPE);\n }\n for (const c of commentEmits) {\n addOverride(manifest, `/xl/comments${c.id}.xml`, COMMENTS_TYPE);\n }\n for (const d of drawingEmits) {\n addOverride(manifest, `/xl/drawings/drawing${d.id}.xml`, DRAWING_TYPE);\n }\n for (const c of chartEmits) {\n addOverride(manifest, `/xl/charts/chart${c.id}.xml`, c.isCx ? CHARTEX_TYPE : CHART_TYPE);\n }\n for (const us of userShapeEmits) {\n addOverride(manifest, `/xl/drawings/chartDrawing${us.id}.xml`, DRAWING_TYPE);\n }\n if (wb.vbaProject) {\n addDefault(manifest, 'bin', 'application/vnd.ms-office.vbaProject');\n }\n if (wb.passthrough) {\n for (const path of wb.passthrough.keys()) {\n const ct = wb.passthroughContentTypes?.get(path);\n if (ct !== undefined) addOverride(manifest, `/${path}`, ct);\n }\n }\n // Each unique image extension gets a Default entry (`<Default Extension=\"png\"\n // ContentType=\"image/png\"/>`).\n for (const ext of imageExts) {\n const fmt = (Object.entries(IMAGE_FORMAT_EXTENSION).find(([, e]) => e === ext) ?? [])[0] as\n | XlsxImageFormat\n | undefined;\n if (fmt) addDefault(manifest, ext, IMAGE_FORMAT_MIME[fmt]);\n }\n if (wb.properties) addOverride(manifest, `/${ARC_CORE}`, CORE_PROPS_TYPE);\n if (wb.appProperties) addOverride(manifest, `/${ARC_APP}`, EXT_PROPS_TYPE);\n if (wb.customProperties) addOverride(manifest, `/${ARC_CUSTOM}`, CPROPS_TYPE);\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n // ---- 8. close ----------------------------------------------------------\n await writer.finalize();\n}\n\n/** Serialise the minimum `<workbook><sheets/></workbook>` Excel needs to load a sheet list. */\nfunction serializeWorkbookXml(wb: Workbook, sheetRIds: ReadonlyArray<string>): string {\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`,\n ];\n if (wb.fileVersion) {\n const fv = serializeFileVersion(wb.fileVersion);\n if (fv) parts.push(fv);\n }\n if (wb.fileSharing) {\n const fs = serializeFileSharing(wb.fileSharing);\n if (fs) parts.push(fs);\n }\n if (wb.workbookXmlExtras?.beforeSheets) {\n for (const node of wb.workbookXmlExtras.beforeSheets) parts.push(serializeChildNode(node));\n }\n // Emit <workbookPr> from the typed model; fall back to a minimal {date1904:\n // true} synthesis so a fresh workbook (no load history) still round-trips\n // through Excel with the right epoch.\n const effectiveWp = effectiveWorkbookProperties(wb);\n if (effectiveWp) {\n const wp = serializeWorkbookProperties(effectiveWp);\n if (wp) parts.push(wp);\n }\n if (wb.workbookProtection) {\n const wp = serializeWorkbookProtection(wb.workbookProtection);\n if (wp) parts.push(wp);\n }\n if (wb.bookViews && wb.bookViews.length > 0) parts.push(serializeBookViews(wb.bookViews));\n parts.push('<sheets>');\n wb.sheets.forEach((ref, i) => {\n const stateAttr = ref.state === 'visible' ? '' : ` state=\"${ref.state}\"`;\n const rId = sheetRIds[i] ?? `rId${i + 1}`;\n parts.push(`<sheet name=\"${escapeAttr(ref.sheet.title)}\" sheetId=\"${ref.sheetId}\"${stateAttr} r:id=\"${rId}\"/>`);\n });\n parts.push('</sheets>');\n if (wb.definedNames.length > 0) {\n parts.push('<definedNames>');\n for (const dn of wb.definedNames) {\n let attrs = ` name=\"${escapeAttr(dn.name)}\"`;\n if (dn.scope !== undefined) attrs += ` localSheetId=\"${dn.scope}\"`;\n if (dn.hidden) attrs += ' hidden=\"1\"';\n if (dn.comment !== undefined) attrs += ` comment=\"${escapeAttr(dn.comment)}\"`;\n parts.push(`<definedName${attrs}>${escapeText(dn.value)}</definedName>`);\n }\n parts.push('</definedNames>');\n }\n if (wb.functionGroups) {\n const fg = serializeFunctionGroups(wb.functionGroups);\n if (fg) parts.push(fg);\n }\n if (wb.externalReferences && wb.externalReferences.length > 0) {\n const inner: string[] = ['<externalReferences>'];\n for (const er of wb.externalReferences) {\n inner.push(`<externalReference r:id=\"${escapeAttr(er.rId)}\"/>`);\n }\n inner.push('</externalReferences>');\n parts.push(inner.join(''));\n }\n if (wb.pivotCaches && wb.pivotCaches.length > 0) {\n const inner: string[] = ['<pivotCaches>'];\n for (const pc of wb.pivotCaches) {\n inner.push(`<pivotCache cacheId=\"${pc.cacheId}\" r:id=\"${escapeAttr(pc.rId)}\"/>`);\n }\n inner.push('</pivotCaches>');\n parts.push(inner.join(''));\n }\n if (wb.calcProperties) {\n const cp = serializeCalcProperties(wb.calcProperties);\n if (cp) parts.push(cp);\n }\n // No default `<calcPr>` — Excel handles its absence by inserting one on save.\n // Hand-rolled `calcId` values (especially the modern 191029) made Excel\n // reject workbooks whose future-function formulas (LET / LAMBDA / FILTER…)\n // couldn't be evaluated against the declared engine.\n if (wb.oleSize !== undefined) {\n parts.push(`<oleSize ref=\"${escapeAttr(wb.oleSize)}\"/>`);\n }\n if (wb.customWorkbookViews && wb.customWorkbookViews.length > 0) {\n parts.push(serializeCustomWorkbookViews(wb.customWorkbookViews));\n }\n if (wb.smartTagPr) {\n const stp = serializeSmartTagPr(wb.smartTagPr);\n if (stp) parts.push(stp);\n }\n if (wb.smartTagTypes && wb.smartTagTypes.length > 0) {\n parts.push(serializeSmartTagTypes(wb.smartTagTypes));\n }\n if (wb.workbookXmlExtras?.afterSheets) {\n for (const node of wb.workbookXmlExtras.afterSheets) parts.push(serializeChildNode(node));\n }\n if (wb.fileRecoveryPr) {\n const fp = serializeFileRecoveryPr(wb.fileRecoveryPr);\n if (fp) parts.push(fp);\n }\n parts.push('</workbook>');\n return parts.join('');\n}\n\nfunction serializeCalcProperties(\n cp: import('../workbook/calc-properties').CalcProperties,\n): string | undefined {\n let attrs = '';\n if (cp.calcId !== undefined) attrs += ` calcId=\"${cp.calcId}\"`;\n if (cp.calcMode !== undefined) attrs += ` calcMode=\"${cp.calcMode}\"`;\n if (cp.fullCalcOnLoad !== undefined) attrs += ` fullCalcOnLoad=\"${cp.fullCalcOnLoad ? '1' : '0'}\"`;\n if (cp.refMode !== undefined) attrs += ` refMode=\"${cp.refMode}\"`;\n if (cp.iterate !== undefined) attrs += ` iterate=\"${cp.iterate ? '1' : '0'}\"`;\n if (cp.iterateCount !== undefined) attrs += ` iterateCount=\"${cp.iterateCount}\"`;\n if (cp.iterateDelta !== undefined) attrs += ` iterateDelta=\"${cp.iterateDelta}\"`;\n if (cp.fullPrecision !== undefined) attrs += ` fullPrecision=\"${cp.fullPrecision ? '1' : '0'}\"`;\n if (cp.calcCompleted !== undefined) attrs += ` calcCompleted=\"${cp.calcCompleted ? '1' : '0'}\"`;\n if (cp.calcOnSave !== undefined) attrs += ` calcOnSave=\"${cp.calcOnSave ? '1' : '0'}\"`;\n if (cp.concurrentCalc !== undefined) attrs += ` concurrentCalc=\"${cp.concurrentCalc ? '1' : '0'}\"`;\n if (cp.concurrentManualCount !== undefined) attrs += ` concurrentManualCount=\"${cp.concurrentManualCount}\"`;\n if (cp.forceFullCalc !== undefined) attrs += ` forceFullCalc=\"${cp.forceFullCalc ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<calcPr${attrs}/>`;\n}\n\nfunction serializeFunctionGroups(\n fg: import('../workbook/function-groups').FunctionGroups,\n): string | undefined {\n let attrs = '';\n if (fg.builtInGroupCount !== undefined) attrs += ` builtInGroupCount=\"${fg.builtInGroupCount}\"`;\n if (fg.groups.length === 0 && attrs.length === 0) return undefined;\n if (fg.groups.length === 0) return `<functionGroups${attrs}/>`;\n const inner: string[] = [`<functionGroups${attrs}>`];\n for (const g of fg.groups) inner.push(`<functionGroup name=\"${escapeAttr(g.name)}\"/>`);\n inner.push('</functionGroups>');\n return inner.join('');\n}\n\nfunction serializeSmartTagPr(\n stp: import('../workbook/smart-tags').SmartTagProperties,\n): string | undefined {\n let attrs = '';\n if (stp.embed !== undefined) attrs += ` embed=\"${stp.embed ? '1' : '0'}\"`;\n if (stp.show !== undefined) attrs += ` show=\"${stp.show}\"`;\n if (attrs.length === 0) return undefined;\n return `<smartTagPr${attrs}/>`;\n}\n\nfunction serializeSmartTagTypes(\n tags: ReadonlyArray<import('../workbook/smart-tags').SmartTagType>,\n): string {\n const inner: string[] = ['<smartTagTypes>'];\n for (const t of tags) {\n let attrs = '';\n if (t.namespaceUri !== undefined) attrs += ` namespaceUri=\"${escapeAttr(t.namespaceUri)}\"`;\n if (t.name !== undefined) attrs += ` name=\"${escapeAttr(t.name)}\"`;\n if (t.url !== undefined) attrs += ` url=\"${escapeAttr(t.url)}\"`;\n inner.push(`<smartTagType${attrs}/>`);\n }\n inner.push('</smartTagTypes>');\n return inner.join('');\n}\n\nfunction serializeFileRecoveryPr(\n fp: import('../workbook/file-recovery').FileRecoveryProperties,\n): string | undefined {\n let attrs = '';\n if (fp.autoRecover !== undefined) attrs += ` autoRecover=\"${fp.autoRecover ? '1' : '0'}\"`;\n if (fp.crashSave !== undefined) attrs += ` crashSave=\"${fp.crashSave ? '1' : '0'}\"`;\n if (fp.dataExtractLoad !== undefined) attrs += ` dataExtractLoad=\"${fp.dataExtractLoad ? '1' : '0'}\"`;\n if (fp.repairLoad !== undefined) attrs += ` repairLoad=\"${fp.repairLoad ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileRecoveryPr${attrs}/>`;\n}\n\nfunction serializeFileSharing(\n fs: import('../workbook/file-sharing').FileSharing,\n): string | undefined {\n let attrs = '';\n if (fs.readOnlyRecommended !== undefined)\n attrs += ` readOnlyRecommended=\"${fs.readOnlyRecommended ? '1' : '0'}\"`;\n if (fs.userName !== undefined) attrs += ` userName=\"${escapeAttr(fs.userName)}\"`;\n if (fs.reservationPassword !== undefined)\n attrs += ` reservationPassword=\"${escapeAttr(fs.reservationPassword)}\"`;\n if (fs.algorithmName !== undefined) attrs += ` algorithmName=\"${escapeAttr(fs.algorithmName)}\"`;\n if (fs.hashValue !== undefined) attrs += ` hashValue=\"${escapeAttr(fs.hashValue)}\"`;\n if (fs.saltValue !== undefined) attrs += ` saltValue=\"${escapeAttr(fs.saltValue)}\"`;\n if (fs.spinCount !== undefined) attrs += ` spinCount=\"${fs.spinCount}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileSharing${attrs}/>`;\n}\n\nfunction serializeFileVersion(\n fv: import('../workbook/file-version').FileVersion,\n): string | undefined {\n let attrs = '';\n if (fv.appName !== undefined) attrs += ` appName=\"${escapeAttr(fv.appName)}\"`;\n if (fv.lastEdited !== undefined) attrs += ` lastEdited=\"${escapeAttr(fv.lastEdited)}\"`;\n if (fv.lowestEdited !== undefined) attrs += ` lowestEdited=\"${escapeAttr(fv.lowestEdited)}\"`;\n if (fv.rupBuild !== undefined) attrs += ` rupBuild=\"${escapeAttr(fv.rupBuild)}\"`;\n if (fv.codeName !== undefined) attrs += ` codeName=\"${escapeAttr(fv.codeName)}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileVersion${attrs}/>`;\n}\n\nfunction effectiveWorkbookProperties(\n wb: Workbook,\n): import('../workbook/workbook-properties').WorkbookProperties | undefined {\n const explicit = wb.workbookProperties;\n if (explicit) {\n // Mirror the canonical date1904 flag if the typed model omits it.\n if (wb.date1904 && explicit.date1904 === undefined) {\n return { ...explicit, date1904: true };\n }\n return explicit;\n }\n if (wb.date1904) return { date1904: true };\n return undefined;\n}\n\nfunction serializeWorkbookProperties(\n wp: import('../workbook/workbook-properties').WorkbookProperties,\n): string | undefined {\n let attrs = '';\n const boolKeys: ReadonlyArray<keyof import('../workbook/workbook-properties').WorkbookProperties> = [\n 'date1904',\n 'dateCompatibility',\n 'showBorderUnselectedTables',\n 'filterPrivacy',\n 'promptedSolutions',\n 'showInkAnnotation',\n 'backupFile',\n 'saveExternalLinkValues',\n 'hidePivotFieldList',\n 'showPivotChartFilter',\n 'allowRefreshQuery',\n 'publishItems',\n 'checkCompatibility',\n 'autoCompressPictures',\n 'refreshAllConnections',\n ];\n for (const k of boolKeys) {\n const v = wp[k];\n if (v !== undefined) attrs += ` ${k}=\"${v ? '1' : '0'}\"`;\n }\n if (wp.showObjects !== undefined) attrs += ` showObjects=\"${wp.showObjects}\"`;\n if (wp.updateLinks !== undefined) attrs += ` updateLinks=\"${wp.updateLinks}\"`;\n if (wp.codeName !== undefined) attrs += ` codeName=\"${escapeAttr(wp.codeName)}\"`;\n if (wp.defaultThemeVersion !== undefined) attrs += ` defaultThemeVersion=\"${wp.defaultThemeVersion}\"`;\n if (attrs.length === 0) return undefined;\n return `<workbookPr${attrs}/>`;\n}\n\nfunction serializeCustomWorkbookViews(\n views: ReadonlyArray<import('../workbook/views').CustomWorkbookView>,\n): string {\n const parts: string[] = ['<customWorkbookViews>'];\n for (const v of views) {\n let attrs = ` name=\"${escapeAttr(v.name)}\" guid=\"${escapeAttr(v.guid)}\"`;\n if (v.autoUpdate !== undefined) attrs += ` autoUpdate=\"${v.autoUpdate ? '1' : '0'}\"`;\n if (v.mergeInterval !== undefined) attrs += ` mergeInterval=\"${v.mergeInterval}\"`;\n if (v.changesSavedWin !== undefined) attrs += ` changesSavedWin=\"${v.changesSavedWin ? '1' : '0'}\"`;\n if (v.onlySync !== undefined) attrs += ` onlySync=\"${v.onlySync ? '1' : '0'}\"`;\n if (v.personalView !== undefined) attrs += ` personalView=\"${v.personalView ? '1' : '0'}\"`;\n if (v.includePrintSettings !== undefined)\n attrs += ` includePrintSettings=\"${v.includePrintSettings ? '1' : '0'}\"`;\n if (v.includeHiddenRowCol !== undefined)\n attrs += ` includeHiddenRowCol=\"${v.includeHiddenRowCol ? '1' : '0'}\"`;\n if (v.maximized !== undefined) attrs += ` maximized=\"${v.maximized ? '1' : '0'}\"`;\n if (v.minimized !== undefined) attrs += ` minimized=\"${v.minimized ? '1' : '0'}\"`;\n if (v.showHorizontalScroll !== undefined)\n attrs += ` showHorizontalScroll=\"${v.showHorizontalScroll ? '1' : '0'}\"`;\n if (v.showVerticalScroll !== undefined)\n attrs += ` showVerticalScroll=\"${v.showVerticalScroll ? '1' : '0'}\"`;\n if (v.showSheetTabs !== undefined) attrs += ` showSheetTabs=\"${v.showSheetTabs ? '1' : '0'}\"`;\n if (v.xWindow !== undefined) attrs += ` xWindow=\"${v.xWindow}\"`;\n if (v.yWindow !== undefined) attrs += ` yWindow=\"${v.yWindow}\"`;\n attrs += ` windowWidth=\"${v.windowWidth}\" windowHeight=\"${v.windowHeight}\"`;\n if (v.tabRatio !== undefined) attrs += ` tabRatio=\"${v.tabRatio}\"`;\n attrs += ` activeSheetId=\"${v.activeSheetId}\"`;\n if (v.showFormulaBar !== undefined) attrs += ` showFormulaBar=\"${v.showFormulaBar ? '1' : '0'}\"`;\n if (v.showStatusbar !== undefined) attrs += ` showStatusbar=\"${v.showStatusbar ? '1' : '0'}\"`;\n if (v.showComments !== undefined) attrs += ` showComments=\"${v.showComments}\"`;\n if (v.showObjects !== undefined) attrs += ` showObjects=\"${v.showObjects}\"`;\n parts.push(`<customWorkbookView${attrs}/>`);\n }\n parts.push('</customWorkbookViews>');\n return parts.join('');\n}\n\nfunction serializeBookViews(views: ReadonlyArray<import('../workbook/views').WorkbookView>): string {\n const parts: string[] = ['<bookViews>'];\n for (const v of views) {\n let attrs = '';\n if (v.visibility !== undefined) attrs += ` visibility=\"${v.visibility}\"`;\n if (v.minimized !== undefined) attrs += ` minimized=\"${v.minimized ? '1' : '0'}\"`;\n if (v.showHorizontalScroll !== undefined)\n attrs += ` showHorizontalScroll=\"${v.showHorizontalScroll ? '1' : '0'}\"`;\n if (v.showVerticalScroll !== undefined)\n attrs += ` showVerticalScroll=\"${v.showVerticalScroll ? '1' : '0'}\"`;\n if (v.showSheetTabs !== undefined) attrs += ` showSheetTabs=\"${v.showSheetTabs ? '1' : '0'}\"`;\n if (v.xWindow !== undefined) attrs += ` xWindow=\"${v.xWindow}\"`;\n if (v.yWindow !== undefined) attrs += ` yWindow=\"${v.yWindow}\"`;\n if (v.windowWidth !== undefined) attrs += ` windowWidth=\"${v.windowWidth}\"`;\n if (v.windowHeight !== undefined) attrs += ` windowHeight=\"${v.windowHeight}\"`;\n if (v.tabRatio !== undefined) attrs += ` tabRatio=\"${v.tabRatio}\"`;\n if (v.firstSheet !== undefined) attrs += ` firstSheet=\"${v.firstSheet}\"`;\n if (v.activeTab !== undefined) attrs += ` activeTab=\"${v.activeTab}\"`;\n if (v.autoFilterDateGrouping !== undefined)\n attrs += ` autoFilterDateGrouping=\"${v.autoFilterDateGrouping ? '1' : '0'}\"`;\n parts.push(`<workbookView${attrs}/>`);\n }\n parts.push('</bookViews>');\n return parts.join('');\n}\n\nfunction serializeWorkbookProtection(\n wp: import('../workbook/protection').WorkbookProtection,\n): string | undefined {\n let attrs = '';\n const strAttrs = [\n 'workbookPassword',\n 'workbookPasswordCharacterSet',\n 'workbookAlgorithmName',\n 'workbookHashValue',\n 'workbookSaltValue',\n 'revisionsPassword',\n 'revisionsPasswordCharacterSet',\n 'revisionsAlgorithmName',\n 'revisionsHashValue',\n 'revisionsSaltValue',\n ] as const;\n for (const k of strAttrs) {\n const v = wp[k];\n if (v !== undefined) attrs += ` ${k}=\"${escapeAttr(v)}\"`;\n }\n if (wp.workbookSpinCount !== undefined) attrs += ` workbookSpinCount=\"${wp.workbookSpinCount}\"`;\n if (wp.revisionsSpinCount !== undefined) attrs += ` revisionsSpinCount=\"${wp.revisionsSpinCount}\"`;\n if (wp.lockStructure !== undefined) attrs += ` lockStructure=\"${wp.lockStructure ? '1' : '0'}\"`;\n if (wp.lockWindows !== undefined) attrs += ` lockWindows=\"${wp.lockWindows ? '1' : '0'}\"`;\n if (wp.lockRevision !== undefined) attrs += ` lockRevision=\"${wp.lockRevision ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<workbookProtection${attrs}/>`;\n}\n\n// Local aliases keep the dense call sites below readable. Canonical\n// implementations live in utils/escape.ts so all three writers (this file,\n// xml/serializer, xml/stream-writer) agree on how `>` / whitespace are\n// handled.\nconst escapeText = escapeXmlText;\nconst escapeAttr = escapeXmlAttr;\n\n/**\n * Serialise an XmlNode child of `<workbook>` for inline injection back into the\n * workbook XML stream. Reuses serializeXml then strips the declaration.\n * Captured nodes carry Clark-notation names so namespace prefixes get\n * reallocated by serializeXml — Excel tolerates the extra `xmlns=\"…\"`\n * declarations on each captured root.\n */\nfunction serializeChildNode(node: import('../xml/tree').XmlNode): string {\n const bytes = serializeXmlNode(node, { xmlDeclaration: false });\n return new TextDecoder().decode(bytes);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** Primitive coercion kinds attribute values may declare. */
|
|
2
|
+
export type Primitive = 'string' | 'int' | 'float' | 'bool';
|
|
3
|
+
export interface AttrDef {
|
|
4
|
+
kind: Primitive | 'enum';
|
|
5
|
+
/** Allowed values when kind === 'enum'. */
|
|
6
|
+
values?: readonly string[];
|
|
7
|
+
/** Treat the attribute as optional; missing → undefined. */
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Default applied during fromTree when the attribute is absent. Never
|
|
11
|
+
* auto-stripped during toTree — round-trip equivalence is the primary
|
|
12
|
+
* concern; explicit emitters decide when to omit.
|
|
13
|
+
*/
|
|
14
|
+
default?: unknown;
|
|
15
|
+
/** Numeric range bounds for kind in {'int', 'float'}. */
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
/** XML attribute name when it differs from the property key on T. */
|
|
19
|
+
xmlName?: string;
|
|
20
|
+
/** Namespace URI for the XML attribute. Empty / undefined = no namespace. */
|
|
21
|
+
xmlNs?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Discriminated union of element shapes a schema can declare. Names are
|
|
25
|
+
* unprefixed (`xmlNs` carries the namespace); the serialiser pairs them into
|
|
26
|
+
* Clark names internally.
|
|
27
|
+
*/
|
|
28
|
+
export type ElementDef = {
|
|
29
|
+
kind: 'text';
|
|
30
|
+
/** Property key on T — the value lands at `T[key]`. */
|
|
31
|
+
key: string;
|
|
32
|
+
/** XML element local name. Defaults to `key` when omitted. */
|
|
33
|
+
name?: string;
|
|
34
|
+
xmlNs?: string;
|
|
35
|
+
primitive: Primitive;
|
|
36
|
+
optional?: boolean;
|
|
37
|
+
default?: unknown;
|
|
38
|
+
/**
|
|
39
|
+
* Fixed attributes always emitted on this element. Keys in Clark
|
|
40
|
+
* notation. On parse, attributes other than these are ignored; keep the
|
|
41
|
+
* schema strict only for the value (text content).
|
|
42
|
+
*
|
|
43
|
+
* Used for the `xsi:type="dcterms:W3CDTF"` marker that docProps/core.xml
|
|
44
|
+
* emits on its <dcterms:created> / <dcterms:modified> children, and
|
|
45
|
+
* similar fixed-marker patterns.
|
|
46
|
+
*/
|
|
47
|
+
attrs?: Record<string, string>;
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'object';
|
|
50
|
+
key: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
xmlNs?: string;
|
|
53
|
+
schema: () => Schema<any>;
|
|
54
|
+
optional?: boolean;
|
|
55
|
+
} | {
|
|
56
|
+
kind: 'sequence';
|
|
57
|
+
key: string;
|
|
58
|
+
/** Local name of the repeated child element. */
|
|
59
|
+
itemName: string;
|
|
60
|
+
itemNs?: string;
|
|
61
|
+
itemSchema: () => Schema<any>;
|
|
62
|
+
/** Optional wrapper element holding the items. */
|
|
63
|
+
container?: {
|
|
64
|
+
name: string;
|
|
65
|
+
xmlNs?: string;
|
|
66
|
+
count?: boolean;
|
|
67
|
+
};
|
|
68
|
+
} | {
|
|
69
|
+
/**
|
|
70
|
+
* Empty marker element — `<key/>` whose presence sets `T[key] = true`,
|
|
71
|
+
* absence leaves it `undefined`. Used by Font's `<b/>`, `<i/>`, etc.
|
|
72
|
+
*/
|
|
73
|
+
kind: 'empty';
|
|
74
|
+
key: string;
|
|
75
|
+
name?: string;
|
|
76
|
+
xmlNs?: string;
|
|
77
|
+
} | {
|
|
78
|
+
/**
|
|
79
|
+
* `<key val="value"/>` style child carrying a single primitive value via
|
|
80
|
+
* an attribute (default `val`). This is openpyxl's NestedString /
|
|
81
|
+
* NestedFloat / NestedInteger / NestedBool / NestedNoneSet pattern; it
|
|
82
|
+
* shows up across Font, NumberFormat children and several chart
|
|
83
|
+
* sub-elements.
|
|
84
|
+
*/
|
|
85
|
+
kind: 'nested';
|
|
86
|
+
key: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
xmlNs?: string;
|
|
89
|
+
primitive: Primitive | 'enum';
|
|
90
|
+
/** Allowed values when primitive === 'enum'. */
|
|
91
|
+
values?: readonly string[];
|
|
92
|
+
/** Attribute name carrying the value. Defaults to "val". */
|
|
93
|
+
valAttr?: string;
|
|
94
|
+
/** Numeric range bounds (int / float). */
|
|
95
|
+
min?: number;
|
|
96
|
+
max?: number;
|
|
97
|
+
optional?: boolean;
|
|
98
|
+
default?: unknown;
|
|
99
|
+
} | {
|
|
100
|
+
/**
|
|
101
|
+
* Opaque round-trip slot — fromTree stores the matched child as a raw
|
|
102
|
+
* `XmlNode`, toTree splices it back verbatim. Used for subtrees we don't
|
|
103
|
+
* want to model in detail (e.g. the vt:vector content under app.xml's
|
|
104
|
+
* HeadingPairs / TitlesOfParts) but still need to preserve byte-for-byte
|
|
105
|
+
* through edits.
|
|
106
|
+
*/
|
|
107
|
+
kind: 'raw';
|
|
108
|
+
key: string;
|
|
109
|
+
name?: string;
|
|
110
|
+
xmlNs?: string;
|
|
111
|
+
optional?: boolean;
|
|
112
|
+
};
|
|
113
|
+
export interface Schema<T> {
|
|
114
|
+
/** Local element name. */
|
|
115
|
+
tagname: string;
|
|
116
|
+
/** Namespace URI of this element. */
|
|
117
|
+
xmlNs?: string;
|
|
118
|
+
/** Attribute table keyed by property name on T. */
|
|
119
|
+
attrs: {
|
|
120
|
+
readonly [K in keyof T & string]?: AttrDef;
|
|
121
|
+
};
|
|
122
|
+
/** Child elements in declaration / emission order. */
|
|
123
|
+
elements: ReadonlyArray<ElementDef>;
|
|
124
|
+
/** Hook to normalise the parsed object (e.g., infer derived fields). */
|
|
125
|
+
postParse?: (value: T, node: import('../xml/tree').XmlNode) => T;
|
|
126
|
+
/** Hook to normalise the value before serialisation. */
|
|
127
|
+
preSerialize?: (value: T) => T;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Identity helper that pins inference to the supplied `T`. The runtime is just
|
|
131
|
+
* `s => s`; the value matters only for the call-site type.
|
|
132
|
+
*/
|
|
133
|
+
export declare function defineSchema<T>(s: Schema<T>): Schema<T>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type XmlNode } from '../xml/tree';
|
|
2
|
+
import type { Schema } from './core';
|
|
3
|
+
/** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */
|
|
4
|
+
export declare function toTree<T>(value: T, schema: Schema<T>): XmlNode;
|
|
5
|
+
/** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */
|
|
6
|
+
export declare function fromTree<T>(node: XmlNode, schema: Schema<T>): T;
|
package/dist/schema.mjs
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
|
+
import { jt as qname, n as el } from "./tree-Bbs1C8Rc.mjs";
|
|
3
|
+
//#region src/schema/core.ts
|
|
4
|
+
/**
|
|
5
|
+
* Identity helper that pins inference to the supplied `T`. The runtime is just
|
|
6
|
+
* `s => s`; the value matters only for the call-site type.
|
|
7
|
+
*/
|
|
8
|
+
function defineSchema(s) {
|
|
9
|
+
return s;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/schema/serialize.ts
|
|
13
|
+
const coerceFromString = (raw, kind, def) => {
|
|
14
|
+
switch (kind) {
|
|
15
|
+
case "string": return raw;
|
|
16
|
+
case "int": {
|
|
17
|
+
const n = Number.parseInt(raw, 10);
|
|
18
|
+
if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected an integer, got "${raw}"`);
|
|
19
|
+
if (def.min !== void 0 && n < def.min) throw new OpenXmlSchemaError(`int "${n}" is below min ${def.min}`);
|
|
20
|
+
if (def.max !== void 0 && n > def.max) throw new OpenXmlSchemaError(`int "${n}" is above max ${def.max}`);
|
|
21
|
+
return n;
|
|
22
|
+
}
|
|
23
|
+
case "float": {
|
|
24
|
+
const n = Number.parseFloat(raw);
|
|
25
|
+
if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected a number, got "${raw}"`);
|
|
26
|
+
if (def.min !== void 0 && n < def.min) throw new OpenXmlSchemaError(`float "${n}" is below min ${def.min}`);
|
|
27
|
+
if (def.max !== void 0 && n > def.max) throw new OpenXmlSchemaError(`float "${n}" is above max ${def.max}`);
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
case "bool": {
|
|
31
|
+
const v = raw.toLowerCase();
|
|
32
|
+
if (v === "true" || v === "t" || v === "1") return true;
|
|
33
|
+
if (v === "false" || v === "f" || v === "0") return false;
|
|
34
|
+
throw new OpenXmlSchemaError(`expected a boolean, got "${raw}"`);
|
|
35
|
+
}
|
|
36
|
+
case "enum":
|
|
37
|
+
if (!def.values?.includes(raw)) throw new OpenXmlSchemaError(`expected one of [${def.values?.join(", ") ?? ""}], got "${raw}"`);
|
|
38
|
+
return raw;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const coerceToString = (value, kind, def) => {
|
|
42
|
+
switch (kind) {
|
|
43
|
+
case "string":
|
|
44
|
+
if (typeof value !== "string") throw new OpenXmlSchemaError(`expected a string, got ${typeof value}`);
|
|
45
|
+
return value;
|
|
46
|
+
case "int":
|
|
47
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value)) throw new OpenXmlSchemaError(`expected an integer, got ${String(value)}`);
|
|
48
|
+
return String(value);
|
|
49
|
+
case "float":
|
|
50
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw new OpenXmlSchemaError(`expected a number, got ${String(value)}`);
|
|
51
|
+
return String(value);
|
|
52
|
+
case "bool":
|
|
53
|
+
if (typeof value !== "boolean") throw new OpenXmlSchemaError(`expected a boolean, got ${typeof value}`);
|
|
54
|
+
return value ? "1" : "0";
|
|
55
|
+
case "enum":
|
|
56
|
+
if (typeof value !== "string" || !def.values || !def.values.includes(value)) throw new OpenXmlSchemaError(`enum value out of range: ${String(value)}`);
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const attrXmlKey = (key, def) => qname(def.xmlNs ?? "", def.xmlName ?? key);
|
|
61
|
+
const elementXmlName = (def, fallbackNs) => {
|
|
62
|
+
const local = def.kind === "sequence" ? def.container?.name ?? def.itemName : def.name ?? def.key;
|
|
63
|
+
return qname((def.kind === "sequence" ? def.container?.xmlNs ?? def.itemNs ?? fallbackNs : def.xmlNs ?? fallbackNs) ?? "", local);
|
|
64
|
+
};
|
|
65
|
+
/** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */
|
|
66
|
+
function toTree(value, schema) {
|
|
67
|
+
const v = schema.preSerialize ? schema.preSerialize(value) : value;
|
|
68
|
+
const node = el(qname(schema.xmlNs ?? "", schema.tagname));
|
|
69
|
+
for (const [key, def] of Object.entries(schema.attrs)) {
|
|
70
|
+
if (def === void 0) continue;
|
|
71
|
+
const raw = v[key];
|
|
72
|
+
if (raw === void 0) {
|
|
73
|
+
if (def.optional) continue;
|
|
74
|
+
throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute "${key}" is missing`);
|
|
75
|
+
}
|
|
76
|
+
node.attrs[attrXmlKey(key, def)] = coerceToString(raw, def.kind, def);
|
|
77
|
+
}
|
|
78
|
+
for (const def of schema.elements) {
|
|
79
|
+
const raw = v[def.key];
|
|
80
|
+
if (raw === void 0) {
|
|
81
|
+
if ((def.kind === "text" || def.kind === "object" || def.kind === "raw") && !def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required element "${def.key}" is missing`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
switch (def.kind) {
|
|
85
|
+
case "text": {
|
|
86
|
+
const text = coerceToString(raw, def.primitive, { kind: def.primitive });
|
|
87
|
+
node.children.push(el(elementXmlName(def, schema.xmlNs), def.attrs ?? {}, [], text));
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case "empty":
|
|
91
|
+
if (raw === true) node.children.push(el(elementXmlName(def, schema.xmlNs), {}, []));
|
|
92
|
+
break;
|
|
93
|
+
case "nested": {
|
|
94
|
+
const valAttr = def.valAttr ?? "val";
|
|
95
|
+
const fakeAttrDef = {
|
|
96
|
+
kind: def.primitive,
|
|
97
|
+
...def.values !== void 0 ? { values: def.values } : {},
|
|
98
|
+
...def.min !== void 0 ? { min: def.min } : {},
|
|
99
|
+
...def.max !== void 0 ? { max: def.max } : {}
|
|
100
|
+
};
|
|
101
|
+
const text = coerceToString(raw, def.primitive, fakeAttrDef);
|
|
102
|
+
node.children.push(el(elementXmlName(def, schema.xmlNs), { [valAttr]: text }, []));
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case "object": {
|
|
106
|
+
const sub = toTree(raw, def.schema());
|
|
107
|
+
if (def.name !== void 0 && sub.name !== qname(def.xmlNs ?? schema.xmlNs ?? "", def.name)) sub.name = qname(def.xmlNs ?? schema.xmlNs ?? "", def.name);
|
|
108
|
+
else if (def.name === void 0 && def.key !== sub.name.replace(/^\{[^}]*\}/, "")) sub.name = qname(def.xmlNs ?? schema.xmlNs ?? "", def.key);
|
|
109
|
+
node.children.push(sub);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "raw": {
|
|
113
|
+
const sub = raw;
|
|
114
|
+
const expected = elementXmlName(def, schema.xmlNs);
|
|
115
|
+
if (sub.name !== expected) node.children.push({
|
|
116
|
+
...sub,
|
|
117
|
+
name: expected
|
|
118
|
+
});
|
|
119
|
+
else node.children.push(sub);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case "sequence": {
|
|
123
|
+
const items = raw;
|
|
124
|
+
const itemSchema = def.itemSchema();
|
|
125
|
+
const built = items.map((item) => {
|
|
126
|
+
const sub = toTree(item, itemSchema);
|
|
127
|
+
sub.name = qname(def.itemNs ?? itemSchema.xmlNs ?? "", def.itemName);
|
|
128
|
+
return sub;
|
|
129
|
+
});
|
|
130
|
+
if (def.container !== void 0) {
|
|
131
|
+
const containerAttrs = {};
|
|
132
|
+
if (def.container.count) containerAttrs["count"] = String(items.length);
|
|
133
|
+
node.children.push(el(elementXmlName(def, schema.xmlNs), containerAttrs, built));
|
|
134
|
+
} else for (const c of built) node.children.push(c);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return node;
|
|
140
|
+
}
|
|
141
|
+
const childByName = (node, fullName) => {
|
|
142
|
+
for (const c of node.children) if (c.name === fullName) return c;
|
|
143
|
+
};
|
|
144
|
+
const childrenByName = (node, fullName) => {
|
|
145
|
+
const out = [];
|
|
146
|
+
for (const c of node.children) if (c.name === fullName) out.push(c);
|
|
147
|
+
return out;
|
|
148
|
+
};
|
|
149
|
+
/** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */
|
|
150
|
+
function fromTree(node, schema) {
|
|
151
|
+
const out = {};
|
|
152
|
+
const expectedTag = qname(schema.xmlNs ?? "", schema.tagname);
|
|
153
|
+
if (node.name !== expectedTag) throw new OpenXmlSchemaError(`fromTree: expected <${schema.tagname}> (Clark "${expectedTag}"), got "${node.name}"`);
|
|
154
|
+
for (const [key, def] of Object.entries(schema.attrs)) {
|
|
155
|
+
if (def === void 0) continue;
|
|
156
|
+
const xmlKey = attrXmlKey(key, def);
|
|
157
|
+
const raw = node.attrs[xmlKey];
|
|
158
|
+
if (raw === void 0) {
|
|
159
|
+
if (def.default !== void 0) out[key] = def.default;
|
|
160
|
+
else if (!def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute "${key}" is missing`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
out[key] = coerceFromString(raw, def.kind, def);
|
|
164
|
+
}
|
|
165
|
+
for (const def of schema.elements) {
|
|
166
|
+
const fullName = elementXmlName(def, schema.xmlNs);
|
|
167
|
+
switch (def.kind) {
|
|
168
|
+
case "text": {
|
|
169
|
+
const child = childByName(node, fullName);
|
|
170
|
+
if (child === void 0) {
|
|
171
|
+
if (def.default !== void 0) out[def.key] = def.default;
|
|
172
|
+
else if (!def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required text element "${def.key}" is missing`);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
out[def.key] = coerceFromString(child.text ?? "", def.primitive, { kind: def.primitive });
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case "empty":
|
|
179
|
+
if (childByName(node, fullName) !== void 0) out[def.key] = true;
|
|
180
|
+
break;
|
|
181
|
+
case "nested": {
|
|
182
|
+
const child = childByName(node, fullName);
|
|
183
|
+
if (child === void 0) {
|
|
184
|
+
if (!def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required nested element "${def.key}" is missing`);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const valAttr = def.valAttr ?? "val";
|
|
188
|
+
const raw = child.attrs[valAttr];
|
|
189
|
+
if (raw === void 0) {
|
|
190
|
+
if (def.default !== void 0) {
|
|
191
|
+
out[def.key] = def.default;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
throw new OpenXmlSchemaError(`<${schema.tagname}>: nested element "${def.key}" missing attribute "${valAttr}"`);
|
|
195
|
+
}
|
|
196
|
+
out[def.key] = coerceFromString(raw, def.primitive, {
|
|
197
|
+
kind: def.primitive,
|
|
198
|
+
...def.values !== void 0 ? { values: def.values } : {},
|
|
199
|
+
...def.min !== void 0 ? { min: def.min } : {},
|
|
200
|
+
...def.max !== void 0 ? { max: def.max } : {}
|
|
201
|
+
});
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case "raw": {
|
|
205
|
+
const child = childByName(node, fullName);
|
|
206
|
+
if (child === void 0) {
|
|
207
|
+
if (!def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required raw element "${def.key}" is missing`);
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
out[def.key] = child;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "object": {
|
|
214
|
+
const child = childByName(node, fullName);
|
|
215
|
+
if (child === void 0) {
|
|
216
|
+
if (!def.optional) throw new OpenXmlSchemaError(`<${schema.tagname}>: required element "${def.key}" is missing`);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
const itemSchema = def.schema();
|
|
220
|
+
const renamed = child.name === qname(itemSchema.xmlNs ?? "", itemSchema.tagname) ? child : {
|
|
221
|
+
...child,
|
|
222
|
+
name: qname(itemSchema.xmlNs ?? "", itemSchema.tagname)
|
|
223
|
+
};
|
|
224
|
+
out[def.key] = fromTree(renamed, itemSchema);
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case "sequence": {
|
|
228
|
+
const itemSchema = def.itemSchema();
|
|
229
|
+
const itemFullName = qname(def.itemNs ?? itemSchema.xmlNs ?? "", def.itemName);
|
|
230
|
+
const itemSchemaName = qname(itemSchema.xmlNs ?? "", itemSchema.tagname);
|
|
231
|
+
const containerNode = def.container !== void 0 ? childByName(node, fullName) : node;
|
|
232
|
+
const items = [];
|
|
233
|
+
if (containerNode !== void 0) {
|
|
234
|
+
const matches = childrenByName(containerNode, itemFullName);
|
|
235
|
+
for (const m of matches) {
|
|
236
|
+
const renamed = m.name === itemSchemaName ? m : {
|
|
237
|
+
...m,
|
|
238
|
+
name: itemSchemaName
|
|
239
|
+
};
|
|
240
|
+
items.push(fromTree(renamed, itemSchema));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
out[def.key] = items;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const built = out;
|
|
249
|
+
return schema.postParse ? schema.postParse(built, node) : built;
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
252
|
+
export { toTree as n, defineSchema as r, fromTree as t };
|
|
253
|
+
|
|
254
|
+
//# sourceMappingURL=serialize-55EnT30e.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-55EnT30e.mjs","names":[],"sources":["../src/schema/core.ts","../src/schema/serialize.ts"],"sourcesContent":["// Schema layer types — pure data, zero classes.\n//\n// A Schema<T> describes how a plain `T` is mapped to and from an XmlNode. The\n// runtime serialiser (src/schema/serialize.ts) is a single switch-on-kind walk\n// that needs nothing beyond these tables; bundlers can drop schemas a build\n// path never imports because each lives in its own const.\n//\n// Lazy element schemas (`schema: () => SideSchema`) are how circular references\n// — Border has Sides, Side has its own Color, etc. — stay expressible without\n// hoisting hazards at module load.\n\n/** Primitive coercion kinds attribute values may declare. */\nexport type Primitive = 'string' | 'int' | 'float' | 'bool';\n\nexport interface AttrDef {\n kind: Primitive | 'enum';\n /** Allowed values when kind === 'enum'. */\n values?: readonly string[];\n /** Treat the attribute as optional; missing → undefined. */\n optional?: boolean;\n /**\n * Default applied during fromTree when the attribute is absent. Never\n * auto-stripped during toTree — round-trip equivalence is the primary\n * concern; explicit emitters decide when to omit.\n */\n default?: unknown;\n /** Numeric range bounds for kind in {'int', 'float'}. */\n min?: number;\n max?: number;\n /** XML attribute name when it differs from the property key on T. */\n xmlName?: string;\n /** Namespace URI for the XML attribute. Empty / undefined = no namespace. */\n xmlNs?: string;\n}\n\n/**\n * Discriminated union of element shapes a schema can declare. Names are\n * unprefixed (`xmlNs` carries the namespace); the serialiser pairs them into\n * Clark names internally.\n */\nexport type ElementDef =\n | {\n kind: 'text';\n /** Property key on T — the value lands at `T[key]`. */\n key: string;\n /** XML element local name. Defaults to `key` when omitted. */\n name?: string;\n xmlNs?: string;\n primitive: Primitive;\n optional?: boolean;\n default?: unknown;\n /**\n * Fixed attributes always emitted on this element. Keys in Clark\n * notation. On parse, attributes other than these are ignored; keep the\n * schema strict only for the value (text content).\n *\n * Used for the `xsi:type=\"dcterms:W3CDTF\"` marker that docProps/core.xml\n * emits on its <dcterms:created> / <dcterms:modified> children, and\n * similar fixed-marker patterns.\n */\n attrs?: Record<string, string>;\n }\n | {\n kind: 'object';\n key: string;\n name?: string;\n xmlNs?: string;\n // Schema is contravariant in T at the element boundary; named types\n // come back via T anyway. The `any` is intentional — `unknown` would\n // force a cast in every concrete schema definition with no extra safety.\n // oxlint-disable-next-line typescript/no-explicit-any\n schema: () => Schema<any>;\n optional?: boolean;\n }\n | {\n kind: 'sequence';\n key: string;\n /** Local name of the repeated child element. */\n itemName: string;\n itemNs?: string;\n // See ElementDef.kind === 'object' for why `any` survives here.\n // oxlint-disable-next-line typescript/no-explicit-any\n itemSchema: () => Schema<any>;\n /** Optional wrapper element holding the items. */\n container?: { name: string; xmlNs?: string; count?: boolean };\n }\n | {\n /**\n * Empty marker element — `<key/>` whose presence sets `T[key] = true`,\n * absence leaves it `undefined`. Used by Font's `<b/>`, `<i/>`, etc.\n */\n kind: 'empty';\n key: string;\n name?: string;\n xmlNs?: string;\n }\n | {\n /**\n * `<key val=\"value\"/>` style child carrying a single primitive value via\n * an attribute (default `val`). This is openpyxl's NestedString /\n * NestedFloat / NestedInteger / NestedBool / NestedNoneSet pattern; it\n * shows up across Font, NumberFormat children and several chart\n * sub-elements.\n */\n kind: 'nested';\n key: string;\n name?: string;\n xmlNs?: string;\n primitive: Primitive | 'enum';\n /** Allowed values when primitive === 'enum'. */\n values?: readonly string[];\n /** Attribute name carrying the value. Defaults to \"val\". */\n valAttr?: string;\n /** Numeric range bounds (int / float). */\n min?: number;\n max?: number;\n optional?: boolean;\n default?: unknown;\n }\n | {\n /**\n * Opaque round-trip slot — fromTree stores the matched child as a raw\n * `XmlNode`, toTree splices it back verbatim. Used for subtrees we don't\n * want to model in detail (e.g. the vt:vector content under app.xml's\n * HeadingPairs / TitlesOfParts) but still need to preserve byte-for-byte\n * through edits.\n */\n kind: 'raw';\n key: string;\n name?: string;\n xmlNs?: string;\n optional?: boolean;\n };\n\nexport interface Schema<T> {\n /** Local element name. */\n tagname: string;\n /** Namespace URI of this element. */\n xmlNs?: string;\n /** Attribute table keyed by property name on T. */\n attrs: { readonly [K in keyof T & string]?: AttrDef };\n /** Child elements in declaration / emission order. */\n elements: ReadonlyArray<ElementDef>;\n /** Hook to normalise the parsed object (e.g., infer derived fields). */\n postParse?: (value: T, node: import('../xml/tree').XmlNode) => T;\n /** Hook to normalise the value before serialisation. */\n preSerialize?: (value: T) => T;\n}\n\n/**\n * Identity helper that pins inference to the supplied `T`. The runtime is just\n * `s => s`; the value matters only for the call-site type.\n */\nexport function defineSchema<T>(s: Schema<T>): Schema<T> {\n return s;\n}\n","// Schema-driven (de)serialisation. One switch-on-kind walk in each direction;\n// the schema does the work, no class-based descriptors.\n//\n// `toTree` and `fromTree` are pure functions over plain data. They run the same\n// on the schema layer's own types and on user types in the styles / chart /\n// drawing modules.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport { qname } from '../xml/namespaces';\nimport { el, type XmlNode } from '../xml/tree';\nimport type { AttrDef, ElementDef, Primitive, Schema } from './core';\n\n// ---- coercion helpers -------------------------------------------------------\n\nconst coerceFromString = (raw: string, kind: Primitive | 'enum', def: AttrDef): unknown => {\n switch (kind) {\n case 'string':\n return raw;\n case 'int': {\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected an integer, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`int \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`int \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'float': {\n const n = Number.parseFloat(raw);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected a number, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`float \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`float \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'bool': {\n // openpyxl accepts 'true'/'t'/'1' or 'false'/'f'/'0' (case-insensitive).\n const v = raw.toLowerCase();\n if (v === 'true' || v === 't' || v === '1') return true;\n if (v === 'false' || v === 'f' || v === '0') return false;\n throw new OpenXmlSchemaError(`expected a boolean, got \"${raw}\"`);\n }\n case 'enum': {\n if (!def.values?.includes(raw)) {\n throw new OpenXmlSchemaError(`expected one of [${def.values?.join(', ') ?? ''}], got \"${raw}\"`);\n }\n return raw;\n }\n }\n};\n\nconst coerceToString = (value: unknown, kind: Primitive | 'enum', def: AttrDef): string => {\n switch (kind) {\n case 'string':\n if (typeof value !== 'string') throw new OpenXmlSchemaError(`expected a string, got ${typeof value}`);\n return value;\n case 'int': {\n if (typeof value !== 'number' || !Number.isFinite(value) || !Number.isInteger(value)) {\n throw new OpenXmlSchemaError(`expected an integer, got ${String(value)}`);\n }\n return String(value);\n }\n case 'float': {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new OpenXmlSchemaError(`expected a number, got ${String(value)}`);\n }\n return String(value);\n }\n case 'bool': {\n if (typeof value !== 'boolean') throw new OpenXmlSchemaError(`expected a boolean, got ${typeof value}`);\n // OOXML convention: '1' / '0'.\n return value ? '1' : '0';\n }\n case 'enum': {\n if (typeof value !== 'string' || !def.values || !def.values.includes(value)) {\n throw new OpenXmlSchemaError(`enum value out of range: ${String(value)}`);\n }\n return value;\n }\n }\n};\n\nconst attrXmlKey = (key: string, def: AttrDef): string => qname(def.xmlNs ?? '', def.xmlName ?? key);\nconst elementXmlName = (def: ElementDef, fallbackNs: string | undefined): string => {\n const local = def.kind === 'sequence' ? (def.container?.name ?? def.itemName) : (def.name ?? def.key);\n const ns = def.kind === 'sequence' ? (def.container?.xmlNs ?? def.itemNs ?? fallbackNs) : (def.xmlNs ?? fallbackNs);\n return qname(ns ?? '', local);\n};\n\n// ---- toTree -----------------------------------------------------------------\n\n/** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */\nexport function toTree<T>(value: T, schema: Schema<T>): XmlNode {\n const v = (schema.preSerialize ? schema.preSerialize(value) : value) as Record<string, unknown>;\n const node = el(qname(schema.xmlNs ?? '', schema.tagname));\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const raw = v[key];\n if (raw === undefined) {\n if (def.optional) continue;\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n node.attrs[attrXmlKey(key, def)] = coerceToString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const raw = v[def.key];\n if (raw === undefined) {\n // 'empty' has no `optional`; presence is binary on the value itself.\n // 'sequence' is implicitly optional (undefined / [] = no items). 'raw'\n // uses the same optional flag as text/object.\n if ((def.kind === 'text' || def.kind === 'object' || def.kind === 'raw') && !def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n continue;\n }\n switch (def.kind) {\n case 'text': {\n const text = coerceToString(raw, def.primitive, { kind: def.primitive });\n node.children.push(el(elementXmlName(def, schema.xmlNs), def.attrs ?? {}, [], text));\n break;\n }\n case 'empty': {\n if (raw === true) node.children.push(el(elementXmlName(def, schema.xmlNs), {}, []));\n break;\n }\n case 'nested': {\n const valAttr = def.valAttr ?? 'val';\n const fakeAttrDef: AttrDef = {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n };\n const text = coerceToString(raw, def.primitive, fakeAttrDef);\n node.children.push(el(elementXmlName(def, schema.xmlNs), { [valAttr]: text }, []));\n break;\n }\n case 'object': {\n const sub = toTree(raw as Record<string, unknown>, def.schema());\n // Allow the schema to declare its own tagname OR be addressed by the\n // parent under a different element name. We honour the schema's tagname\n // (it's the canonical identity for that type).\n if (def.name !== undefined && sub.name !== qname(def.xmlNs ?? schema.xmlNs ?? '', def.name)) {\n // Re-tag the produced element to the parent-defined name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.name);\n } else if (def.name === undefined && def.key !== sub.name.replace(/^\\{[^}]*\\}/, '')) {\n // No explicit `name` — use the property key as the local name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.key);\n }\n node.children.push(sub);\n break;\n }\n case 'raw': {\n // Splice the stored XmlNode back verbatim, but realign its name to the\n // schema-declared position so the output is well-formed even when the\n // caller mutates `name`.\n const sub = raw as XmlNode;\n const expected = elementXmlName(def, schema.xmlNs);\n if (sub.name !== expected) {\n node.children.push({ ...sub, name: expected });\n } else {\n node.children.push(sub);\n }\n break;\n }\n case 'sequence': {\n const items = raw as ReadonlyArray<Record<string, unknown>>;\n const itemSchema = def.itemSchema();\n const built = items.map((item) => {\n const sub = toTree(item, itemSchema);\n // Re-tag to the declared itemName / itemNs.\n sub.name = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n return sub;\n });\n if (def.container !== undefined) {\n const containerAttrs: Record<string, string> = {};\n if (def.container.count) containerAttrs['count'] = String(items.length);\n node.children.push(el(elementXmlName(def, schema.xmlNs), containerAttrs, built));\n } else {\n for (const c of built) node.children.push(c);\n }\n break;\n }\n }\n }\n\n return node;\n}\n\n// ---- fromTree ---------------------------------------------------------------\n\nconst childByName = (node: XmlNode, fullName: string): XmlNode | undefined => {\n for (const c of node.children) if (c.name === fullName) return c;\n return undefined;\n};\n\nconst childrenByName = (node: XmlNode, fullName: string): XmlNode[] => {\n const out: XmlNode[] = [];\n for (const c of node.children) if (c.name === fullName) out.push(c);\n return out;\n};\n\n/** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */\nexport function fromTree<T>(node: XmlNode, schema: Schema<T>): T {\n const out: Record<string, unknown> = {};\n const expectedTag = qname(schema.xmlNs ?? '', schema.tagname);\n if (node.name !== expectedTag) {\n throw new OpenXmlSchemaError(`fromTree: expected <${schema.tagname}> (Clark \"${expectedTag}\"), got \"${node.name}\"`);\n }\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const xmlKey = attrXmlKey(key, def);\n const raw = node.attrs[xmlKey];\n if (raw === undefined) {\n if (def.default !== undefined) out[key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n continue;\n }\n out[key] = coerceFromString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const fullName = elementXmlName(def, schema.xmlNs);\n switch (def.kind) {\n case 'text': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (def.default !== undefined) out[def.key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required text element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = coerceFromString(child.text ?? '', def.primitive, { kind: def.primitive });\n break;\n }\n case 'empty': {\n const child = childByName(node, fullName);\n if (child !== undefined) out[def.key] = true;\n // Absent → leave key unset so the value compares equal to the\n // round-trip-emitting input that omitted it.\n break;\n }\n case 'nested': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n // The element itself was omitted: leave the field unset for optional\n // nested elements, regardless of `default`. `default` here governs\n // the \"child present but @val omitted\" case (e.g. <u/> meaning\n // underline=single per ECMA-376 §18.4.13), not \"child entirely\n // absent\".\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required nested element \"${def.key}\" is missing`);\n }\n break;\n }\n const valAttr = def.valAttr ?? 'val';\n const raw = child.attrs[valAttr];\n if (raw === undefined) {\n if (def.default !== undefined) {\n out[def.key] = def.default;\n break;\n }\n throw new OpenXmlSchemaError(\n `<${schema.tagname}>: nested element \"${def.key}\" missing attribute \"${valAttr}\"`,\n );\n }\n out[def.key] = coerceFromString(raw, def.primitive, {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n });\n break;\n }\n case 'raw': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required raw element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = child;\n break;\n }\n case 'object': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n break;\n }\n const itemSchema = def.schema();\n // Address the child by the parent-declared name even if the child\n // schema names itself differently.\n const renamed: XmlNode =\n child.name === qname(itemSchema.xmlNs ?? '', itemSchema.tagname)\n ? child\n : { ...child, name: qname(itemSchema.xmlNs ?? '', itemSchema.tagname) };\n out[def.key] = fromTree(renamed, itemSchema);\n break;\n }\n case 'sequence': {\n const itemSchema = def.itemSchema();\n const itemFullName = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n const itemSchemaName = qname(itemSchema.xmlNs ?? '', itemSchema.tagname);\n const containerNode = def.container !== undefined ? childByName(node, fullName) : node;\n const items: unknown[] = [];\n if (containerNode !== undefined) {\n const matches = childrenByName(containerNode, itemFullName);\n for (const m of matches) {\n const renamed: XmlNode = m.name === itemSchemaName ? m : { ...m, name: itemSchemaName };\n items.push(fromTree(renamed, itemSchema));\n }\n }\n out[def.key] = items;\n break;\n }\n }\n }\n\n const built = out as unknown as T;\n return schema.postParse ? schema.postParse(built, node) : built;\n}\n"],"mappings":"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"}
|