@office-kit/xlsx 0.8.0 → 0.9.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/dist/{cell-D9CaNKnU.mjs → cell-BucgGwl3.mjs} +2 -2
- package/dist/{cell-D9CaNKnU.mjs.map → cell-BucgGwl3.mjs.map} +1 -1
- package/dist/{cell-style-BEDjMX1y.mjs → cell-style-CN9JXOwm.mjs} +8 -6
- package/dist/cell-style-CN9JXOwm.mjs.map +1 -0
- package/dist/cell.mjs +1 -1
- package/dist/coordinate-96Ecci4d.mjs.map +1 -1
- package/dist/datetime-B2ySVlXt.mjs.map +1 -1
- package/dist/{differential-D4dg-qtZ.mjs → differential-YEjxNScf.mjs} +2 -2
- package/dist/{differential-D4dg-qtZ.mjs.map → differential-YEjxNScf.mjs.map} +1 -1
- package/dist/drawing-BxzLuryn.mjs.map +1 -1
- package/dist/escape-DFTE7ZJc.mjs.map +1 -1
- package/dist/{inference-B3ES3KEJ.mjs → inference-BrI9uIY4.mjs} +2 -2
- package/dist/{inference-B3ES3KEJ.mjs.map → inference-BrI9uIY4.mjs.map} +1 -1
- package/dist/io.mjs +4 -4
- package/dist/io.mjs.map +1 -1
- package/dist/{load-D5cbhoGx.mjs → load-BG5-CtPk.mjs} +10 -10
- package/dist/{load-D5cbhoGx.mjs.map → load-BG5-CtPk.mjs.map} +1 -1
- package/dist/{manifest-Dps1-OpP.mjs → manifest-CVL1_t0O.mjs} +7 -5
- package/dist/{manifest-Dps1-OpP.mjs.map → manifest-CVL1_t0O.mjs.map} +1 -1
- package/dist/node.mjs +3 -3
- package/dist/node.mjs.map +1 -1
- package/dist/packaging.mjs +1 -1
- package/dist/{parser-DuLejQy1.mjs → parser-nk0Lqmcb.mjs} +3 -2
- package/dist/{parser-DuLejQy1.mjs.map → parser-nk0Lqmcb.mjs.map} +1 -1
- package/dist/{reader-D1fNW9k1.mjs → reader-BNaUTVCy.mjs} +3 -2
- package/dist/{reader-D1fNW9k1.mjs.map → reader-BNaUTVCy.mjs.map} +1 -1
- package/dist/{save-RohQtgEZ.mjs → save-BcpDpE90.mjs} +7 -7
- package/dist/{save-RohQtgEZ.mjs.map → save-BcpDpE90.mjs.map} +1 -1
- package/dist/{serializer-BwbgHYJV.mjs → serializer-DQzTTNOS.mjs} +2 -2
- package/dist/{serializer-BwbgHYJV.mjs.map → serializer-DQzTTNOS.mjs.map} +1 -1
- package/dist/streaming.mjs +13 -11
- package/dist/streaming.mjs.map +1 -1
- package/dist/styles/borders.d.ts +1 -1
- package/dist/styles.mjs +3 -3
- package/dist/{stylesheet-writer-C2eRmn22.mjs → stylesheet-writer-P1Hxoqzm.mjs} +32 -26
- package/dist/{stylesheet-writer-C2eRmn22.mjs.map → stylesheet-writer-P1Hxoqzm.mjs.map} +1 -1
- package/dist/{table-DkX6UniA.mjs → table-BifavDVW.mjs} +2 -2
- package/dist/{table-DkX6UniA.mjs.map → table-BifavDVW.mjs.map} +1 -1
- package/dist/utf8-D91g1XTG.mjs.map +1 -1
- package/dist/utils.mjs +1 -1
- package/dist/utils.mjs.map +1 -1
- package/dist/{workbook-HGYNRBlV.mjs → workbook-T1Y3lstQ.mjs} +5 -5
- package/dist/{workbook-HGYNRBlV.mjs.map → workbook-T1Y3lstQ.mjs.map} +1 -1
- package/dist/workbook.mjs +1 -1
- package/dist/{worksheet-CmCNoIgD.mjs → worksheet-C6CWgvP5.mjs} +2 -2
- package/dist/{worksheet-CmCNoIgD.mjs.map → worksheet-C6CWgvP5.mjs.map} +1 -1
- package/dist/worksheet.mjs +2 -2
- package/dist/{writer-DspzfkNA.mjs → writer-IyFccCRJ.mjs} +3 -3
- package/dist/{writer-DspzfkNA.mjs.map → writer-IyFccCRJ.mjs.map} +1 -1
- package/dist/xml.mjs +2 -2
- package/dist/zip.mjs +2 -2
- package/package.json +23 -31
- package/dist/cell-style-BEDjMX1y.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime-B2ySVlXt.mjs","names":[],"sources":["../src/utils/datetime.ts"],"sourcesContent":["// Excel <-> JavaScript Date conversions. Mirrors\n// openpyxl/openpyxl/utils/datetime.py.\n//\n// Excel stores datetimes as fractional \"serial days\" since an epoch. Two epochs\n// are in use:\n// * Windows (\"1900 date system\", default): epoch 1899-12-30 with the\n// well-known 1900 leap-year bug — Excel treats 1900-02-29 as a\n// valid day even though it isn't. We collapse that phantom day\n// onto 1900-02-28 (the openpyxl approach), so date math past\n// March 1, 1900 stays consistent without leaking the bug.\n// * Mac (\"1904 date system\"): epoch 1904-01-01, no leap bug.\n//\n// Dates stay as numeric serials on the worksheet hot path; conversion to a JS\n// Date happens lazily only when callers ask. JS Dates are interpreted in UTC\n// throughout to avoid timezone drift between read and write.\n\nimport { OpenXmlSchemaError } from './exceptions';\n\n/** Excel epoch identifier. */\nexport type ExcelEpoch = 'windows' | 'mac';\n\n/** 1899-12-30 (UTC) — the Windows / 1900-system epoch in ms. */\nexport const WINDOWS_EPOCH_MS = Date.UTC(1899, 11, 30);\n/** 1904-01-01 (UTC) — the Mac / 1904-system epoch in ms. */\nexport const MAC_EPOCH_MS = Date.UTC(1904, 0, 1);\n\nconst MS_PER_DAY = 86_400_000;\n/** Serial day index of the phantom 1900-02-29; absorbed onto 1900-02-28. */\nconst LEAP_DUPLICATE_DAY = 60;\n\nconst epochMs = (e: ExcelEpoch | undefined): number => (e === 'mac' ? MAC_EPOCH_MS : WINDOWS_EPOCH_MS);\n\n/**\n * Convert an Excel serial date into a JS `Date` (UTC). The fractional part is\n * treated as a fraction of a day. For Windows 1900 the leap-bug compensation\n * kicks in for serials in [0, 60).\n */\nexport function excelToDate(serial: number, opts?: { epoch?: ExcelEpoch }): Date {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDate: serial \"${serial}\" is not finite`);\n }\n const epoch = epochMs(opts?.epoch);\n const day = Math.floor(serial);\n const fraction = serial - day;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n // Windows quirk: bump days [0, 60) by one so the day count lines up with\n // Excel's serial numbering through the phantom Feb 29 1900.\n const dayAdjusted = isWindows && serial >= 0 && serial < LEAP_DUPLICATE_DAY ? day + 1 : day;\n const ms = epoch + dayAdjusted * MS_PER_DAY + Math.round(fraction * MS_PER_DAY);\n return new Date(ms);\n}\n\n/**\n * Convert a JS `Date` into an Excel serial. The Date is read in UTC. On Windows\n * 1900, dates ≤ 1900-02-28 get a -1 day correction to account for Excel's\n * phantom leap day.\n */\nexport function dateToExcel(date: Date, opts?: { epoch?: ExcelEpoch }): number {\n const t = date.getTime();\n if (!Number.isFinite(t)) {\n throw new OpenXmlSchemaError('dateToExcel: invalid Date');\n }\n const epoch = epochMs(opts?.epoch);\n const dayStartMs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());\n const days = Math.round((dayStartMs - epoch) / MS_PER_DAY);\n const subDay = (t - dayStartMs) / MS_PER_DAY;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n const daysAdjusted = isWindows && days <= LEAP_DUPLICATE_DAY ? days - 1 : days;\n return daysAdjusted + subDay;\n}\n\n/** Excel duration serial (fraction of a day) → milliseconds. */\nexport function excelToDuration(serial: number): number {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDuration: serial \"${serial}\" is not finite`);\n }\n return Math.round(serial * MS_PER_DAY);\n}\n\n/** Milliseconds → Excel duration serial (fraction of a day). */\nexport function durationToExcel(ms: number): number {\n if (!Number.isFinite(ms)) {\n throw new OpenXmlSchemaError(`durationToExcel: ms \"${ms}\" is not finite`);\n }\n return ms / MS_PER_DAY;\n}\n\n// ---- ISO 8601 helpers ------------------------------------------------------\n\n/**\n * Parse an ISO-8601 / W3CDTF datetime string into a `Date`. Same grammar as\n * `new Date(string)`; the wrapper just adds typed error reporting and a\n * stricter \"must be a recognised ISO\" guard.\n */\nexport function fromIso8601(s: string): Date {\n if (typeof s !== 'string' || s.length === 0) {\n throw new OpenXmlSchemaError(`fromIso8601: empty input`);\n }\n const d = new Date(s);\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError(`fromIso8601: invalid datetime \"${s}\"`);\n }\n return d;\n}\n\n/**\n * Format a `Date` as ISO-8601 with second precision in UTC. Trims the\n * millisecond fragment that `Date.toISOString()` always produces, so the output\n * matches Excel / openpyxl's W3CDTF style.\n */\nexport function toIso8601(d: Date): string {\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError('toIso8601: invalid Date');\n }\n return d.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n"],"mappings":";;;AAsBA,MAAa,mBAAmB,KAAK,IAAI,MAAM,IAAI,EAAE;;AAErD,MAAa,eAAe,KAAK,IAAI,MAAM,GAAG,CAAC;AAE/C,MAAM,aAAa;;AAEnB,MAAM,qBAAqB;AAE3B,MAAM,WAAW,MAAuC,MAAM,QAAQ,eAAe;;;;;;AAOrF,SAAgB,YAAY,QAAgB,MAAqC;CAC/E,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,wBAAwB,OAAO,gBAAgB;CAE9E,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,MAAM,KAAK,MAAM,MAAM;CAC7B,MAAM,WAAW,SAAS;CAK1B,MAAM,KAAK,SAJO,UAAU,oBAGK,UAAU,KAAK,SAAS,qBAAqB,MAAM,IAAI,OACvD,aAAa,KAAK,MAAM,WAAW,UAAU;CAC9E,OAAO,IAAI,KAAK,EAAE;AACpB;;;;;;AAOA,SAAgB,YAAY,MAAY,MAAuC;CAC7E,MAAM,IAAI,KAAK,QAAQ;CACvB,IAAI,CAAC,OAAO,SAAS,CAAC,GACpB,MAAM,IAAI,mBAAmB,2BAA2B;CAE1D,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,aAAa,KAAK,IAAI,KAAK,eAAe,GAAG,KAAK,YAAY,GAAG,KAAK,WAAW,CAAC;CACxF,MAAM,OAAO,KAAK,OAAO,aAAa,SAAS,UAAU;CACzD,MAAM,UAAU,IAAI,cAAc;CAGlC,QAFkB,UAAU,oBACM,QAAQ,qBAAqB,OAAO,IAAI,QACpD;AACxB;;AAGA,SAAgB,gBAAgB,QAAwB;CACtD,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,4BAA4B,OAAO,gBAAgB;CAElF,OAAO,KAAK,MAAM,SAAS,UAAU;AACvC;;AAGA,SAAgB,gBAAgB,IAAoB;CAClD,IAAI,CAAC,OAAO,SAAS,EAAE,GACrB,MAAM,IAAI,mBAAmB,wBAAwB,GAAG,gBAAgB;CAE1E,OAAO,KAAK;AACd;;;;;;AASA,SAAgB,YAAY,GAAiB;CAC3C,IAAI,OAAO,MAAM,YAAY,EAAE,WAAW,GACxC,MAAM,IAAI,mBAAmB,0BAA0B;CAEzD,MAAM,IAAI,IAAI,KAAK,CAAC;CACpB,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,kCAAkC,EAAE,EAAE;CAErE,OAAO;AACT;;;;;;AAOA,SAAgB,UAAU,GAAiB;CACzC,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,yBAAyB;CAExD,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"datetime-B2ySVlXt.mjs","names":[],"sources":["../src/utils/datetime.ts"],"sourcesContent":["// Excel <-> JavaScript Date conversions. Mirrors\n// openpyxl/openpyxl/utils/datetime.py.\n//\n// Excel stores datetimes as fractional \"serial days\" since an epoch. Two epochs\n// are in use:\n// * Windows (\"1900 date system\", default): epoch 1899-12-30 with the\n// well-known 1900 leap-year bug — Excel treats 1900-02-29 as a\n// valid day even though it isn't. We collapse that phantom day\n// onto 1900-02-28 (the openpyxl approach), so date math past\n// March 1, 1900 stays consistent without leaking the bug.\n// * Mac (\"1904 date system\"): epoch 1904-01-01, no leap bug.\n//\n// Dates stay as numeric serials on the worksheet hot path; conversion to a JS\n// Date happens lazily only when callers ask. JS Dates are interpreted in UTC\n// throughout to avoid timezone drift between read and write.\n\nimport { OpenXmlSchemaError } from './exceptions';\n\n/** Excel epoch identifier. */\nexport type ExcelEpoch = 'windows' | 'mac';\n\n/** 1899-12-30 (UTC) — the Windows / 1900-system epoch in ms. */\nexport const WINDOWS_EPOCH_MS = Date.UTC(1899, 11, 30);\n/** 1904-01-01 (UTC) — the Mac / 1904-system epoch in ms. */\nexport const MAC_EPOCH_MS = Date.UTC(1904, 0, 1);\n\nconst MS_PER_DAY = 86_400_000;\n/** Serial day index of the phantom 1900-02-29; absorbed onto 1900-02-28. */\nconst LEAP_DUPLICATE_DAY = 60;\n\nconst epochMs = (e: ExcelEpoch | undefined): number => (e === 'mac' ? MAC_EPOCH_MS : WINDOWS_EPOCH_MS);\n\n/**\n * Convert an Excel serial date into a JS `Date` (UTC). The fractional part is\n * treated as a fraction of a day. For Windows 1900 the leap-bug compensation\n * kicks in for serials in [0, 60).\n */\nexport function excelToDate(serial: number, opts?: { epoch?: ExcelEpoch }): Date {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDate: serial \"${serial}\" is not finite`);\n }\n const epoch = epochMs(opts?.epoch);\n const day = Math.floor(serial);\n const fraction = serial - day;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n // Windows quirk: bump days [0, 60) by one so the day count lines up with\n // Excel's serial numbering through the phantom Feb 29 1900.\n const dayAdjusted = isWindows && serial >= 0 && serial < LEAP_DUPLICATE_DAY ? day + 1 : day;\n const ms = epoch + dayAdjusted * MS_PER_DAY + Math.round(fraction * MS_PER_DAY);\n return new Date(ms);\n}\n\n/**\n * Convert a JS `Date` into an Excel serial. The Date is read in UTC. On Windows\n * 1900, dates ≤ 1900-02-28 get a -1 day correction to account for Excel's\n * phantom leap day.\n */\nexport function dateToExcel(date: Date, opts?: { epoch?: ExcelEpoch }): number {\n const t = date.getTime();\n if (!Number.isFinite(t)) {\n throw new OpenXmlSchemaError('dateToExcel: invalid Date');\n }\n const epoch = epochMs(opts?.epoch);\n const dayStartMs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());\n const days = Math.round((dayStartMs - epoch) / MS_PER_DAY);\n const subDay = (t - dayStartMs) / MS_PER_DAY;\n const isWindows = epoch === WINDOWS_EPOCH_MS;\n const daysAdjusted = isWindows && days <= LEAP_DUPLICATE_DAY ? days - 1 : days;\n return daysAdjusted + subDay;\n}\n\n/** Excel duration serial (fraction of a day) → milliseconds. */\nexport function excelToDuration(serial: number): number {\n if (!Number.isFinite(serial)) {\n throw new OpenXmlSchemaError(`excelToDuration: serial \"${serial}\" is not finite`);\n }\n return Math.round(serial * MS_PER_DAY);\n}\n\n/** Milliseconds → Excel duration serial (fraction of a day). */\nexport function durationToExcel(ms: number): number {\n if (!Number.isFinite(ms)) {\n throw new OpenXmlSchemaError(`durationToExcel: ms \"${ms}\" is not finite`);\n }\n return ms / MS_PER_DAY;\n}\n\n// ---- ISO 8601 helpers ------------------------------------------------------\n\n/**\n * Parse an ISO-8601 / W3CDTF datetime string into a `Date`. Same grammar as\n * `new Date(string)`; the wrapper just adds typed error reporting and a\n * stricter \"must be a recognised ISO\" guard.\n */\nexport function fromIso8601(s: string): Date {\n if (typeof s !== 'string' || s.length === 0) {\n throw new OpenXmlSchemaError(`fromIso8601: empty input`);\n }\n const d = new Date(s);\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError(`fromIso8601: invalid datetime \"${s}\"`);\n }\n return d;\n}\n\n/**\n * Format a `Date` as ISO-8601 with second precision in UTC. Trims the\n * millisecond fragment that `Date.toISOString()` always produces, so the output\n * matches Excel / openpyxl's W3CDTF style.\n */\nexport function toIso8601(d: Date): string {\n if (Number.isNaN(d.getTime())) {\n throw new OpenXmlSchemaError('toIso8601: invalid Date');\n }\n return d.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n"],"mappings":";;;AAsBA,MAAa,mBAAmB,KAAK,IAAI,MAAM,IAAI,EAAE;;AAErD,MAAa,eAAe,KAAK,IAAI,MAAM,GAAG,CAAC;AAE/C,MAAM,aAAa;;AAEnB,MAAM,qBAAqB;AAE3B,MAAM,WAAW,MAAuC,MAAM,QAAQ,eAAe;;;;;;AAOrF,SAAgB,YAAY,QAAgB,MAAqC;CAC/E,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,wBAAwB,OAAO,gBAAgB;CAE9E,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,MAAM,KAAK,MAAM,MAAM;CAC7B,MAAM,WAAW,SAAS;CAK1B,MAAM,KAAK,SAJO,UAAU,oBAGK,UAAU,KAAK,SAAS,qBAAqB,MAAM,IAAI,OACvD,aAAa,KAAK,MAAM,WAAW,UAAU;CAC9E,OAAO,IAAI,KAAK,EAAE;AACpB;;;;;;AAOA,SAAgB,YAAY,MAAY,MAAuC;CAC7E,MAAM,IAAI,KAAK,QAAQ;CACvB,IAAI,CAAC,OAAO,SAAS,CAAC,GACpB,MAAM,IAAI,mBAAmB,2BAA2B;CAE1D,MAAM,QAAQ,QAAQ,MAAM,KAAK;CACjC,MAAM,aAAa,KAAK,IAAI,KAAK,eAAe,GAAG,KAAK,YAAY,GAAG,KAAK,WAAW,CAAC;CACxF,MAAM,OAAO,KAAK,OAAO,aAAa,SAAS,UAAU;CACzD,MAAM,UAAU,IAAI,cAAc;CAGlC,QAFkB,UAAU,oBACM,QAAQ,qBAAqB,OAAO,IAAI,QACpD;AACxB;;AAGA,SAAgB,gBAAgB,QAAwB;CACtD,IAAI,CAAC,OAAO,SAAS,MAAM,GACzB,MAAM,IAAI,mBAAmB,4BAA4B,OAAO,gBAAgB;CAElF,OAAO,KAAK,MAAM,SAAS,UAAU;AACvC;;AAGA,SAAgB,gBAAgB,IAAoB;CAClD,IAAI,CAAC,OAAO,SAAS,EAAE,GACrB,MAAM,IAAI,mBAAmB,wBAAwB,GAAG,gBAAgB;CAE1E,OAAO,KAAK;AACd;;;;;;AASA,SAAgB,YAAY,GAAiB;CAC3C,IAAI,OAAO,MAAM,YAAY,EAAE,WAAW,GACxC,MAAM,IAAI,mBAAmB,0BAA0B;CAEzD,MAAM,IAAI,IAAI,KAAK,CAAC;CACpB,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,kCAAkC,EAAE,EAAE;CAErE,OAAO;AACT;;;;;;AAOA,SAAgB,UAAU,GAAiB;CACzC,IAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAC1B,MAAM,IAAI,mBAAmB,yBAAyB;CAExD,OAAO,EAAE,YAAY,CAAC,CAAC,QAAQ,aAAa,GAAG;AACjD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Zt as stableStringify } from "./cell-style-
|
|
1
|
+
import { Zt as stableStringify } from "./cell-style-CN9JXOwm.mjs";
|
|
2
2
|
//#region src/styles/differential.ts
|
|
3
3
|
function makeDifferentialStyle(opts = {}) {
|
|
4
4
|
const out = {};
|
|
@@ -34,4 +34,4 @@ function getDxfs(ss) {
|
|
|
34
34
|
//#endregion
|
|
35
35
|
export { getDxfs as n, makeDifferentialStyle as r, addDxf as t };
|
|
36
36
|
|
|
37
|
-
//# sourceMappingURL=differential-
|
|
37
|
+
//# sourceMappingURL=differential-YEjxNScf.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"differential-
|
|
1
|
+
{"version":3,"file":"differential-YEjxNScf.mjs","names":[],"sources":["../src/styles/differential.ts"],"sourcesContent":["// DifferentialStyle (DXF) — partial style overlay used by conditional\n// formatting and Excel-table style elements. Mirrors\n// openpyxl/openpyxl/styles/differential.py.\n//\n// Where a NamedStyle / CellXf carries a *complete* style snapshot, a\n// DifferentialStyle carries only the components that override the base.\n// The Stylesheet keeps DXFs in their own pool (`dxfs`) and conditional-\n// formatting rules / table-style elements reference them by index.\n\nimport { stableStringify } from '../utils/stable-stringify';\nimport type { Alignment } from './alignment';\nimport type { Border } from './borders';\nimport type { Fill } from './fills';\nimport type { Font } from './fonts';\nimport type { NumberFormat } from './numbers';\nimport type { Protection } from './protection';\nimport type { Stylesheet } from './stylesheet';\n\n/**\n * Differential (\"partial\") style. Every component is optional; only\n * the set fields override the base style of whatever the DXF is\n * applied to.\n */\nexport interface DifferentialStyle {\n readonly font?: Font;\n readonly fill?: Fill;\n readonly border?: Border;\n readonly alignment?: Alignment;\n readonly protection?: Protection;\n /**\n * NumberFormat carries both the id and the format code so DXFs can\n * reference custom user-defined number formats without ambiguity.\n */\n readonly numFmt?: NumberFormat;\n}\n\nexport function makeDifferentialStyle(opts: Partial<DifferentialStyle> = {}): DifferentialStyle {\n const out: { -readonly [K in keyof DifferentialStyle]: DifferentialStyle[K] } = {};\n if (opts.font !== undefined) out.font = opts.font;\n if (opts.fill !== undefined) out.fill = opts.fill;\n if (opts.border !== undefined) out.border = opts.border;\n if (opts.alignment !== undefined) out.alignment = opts.alignment;\n if (opts.protection !== undefined) out.protection = opts.protection;\n if (opts.numFmt !== undefined) out.numFmt = opts.numFmt;\n return Object.freeze(out);\n}\n\n/**\n * Stylesheet pool extension. The DXF list is allocated lazily on first\n * use so empty stylesheets stay slim.\n */\nexport interface StylesheetWithDxfs extends Stylesheet {\n dxfs?: DifferentialStyle[];\n _dxfIdByKey?: Map<string, number>;\n}\n\n/**\n * Add a DifferentialStyle to the stylesheet's `dxfs` pool. Returns\n * the 0-based index. Idempotent on structural equality (via\n * stableStringify).\n */\nexport function addDxf(ss: Stylesheet, dxf: DifferentialStyle): number {\n const w = ss as StylesheetWithDxfs;\n if (w.dxfs === undefined) w.dxfs = [];\n if (w._dxfIdByKey === undefined) w._dxfIdByKey = new Map();\n const key = stableStringify(dxf);\n const cached = w._dxfIdByKey.get(key);\n if (cached !== undefined) return cached;\n const id = w.dxfs.length;\n w.dxfs.push(dxf);\n w._dxfIdByKey.set(key, id);\n return id;\n}\n\n/** Read-only access to the dxfs pool. Returns `[]` when none registered. */\nexport function getDxfs(ss: Stylesheet): ReadonlyArray<DifferentialStyle> {\n return (ss as StylesheetWithDxfs).dxfs ?? [];\n}\n"],"mappings":";;AAoCA,SAAgB,sBAAsB,OAAmC,CAAC,GAAsB;CAC9F,MAAM,MAA0E,CAAC;CACjF,IAAI,KAAK,SAAS,KAAA,GAAW,IAAI,OAAO,KAAK;CAC7C,IAAI,KAAK,SAAS,KAAA,GAAW,IAAI,OAAO,KAAK;CAC7C,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;CACjD,IAAI,KAAK,cAAc,KAAA,GAAW,IAAI,YAAY,KAAK;CACvD,IAAI,KAAK,eAAe,KAAA,GAAW,IAAI,aAAa,KAAK;CACzD,IAAI,KAAK,WAAW,KAAA,GAAW,IAAI,SAAS,KAAK;CACjD,OAAO,OAAO,OAAO,GAAG;AAC1B;;;;;;AAgBA,SAAgB,OAAO,IAAgB,KAAgC;CACrE,MAAM,IAAI;CACV,IAAI,EAAE,SAAS,KAAA,GAAW,EAAE,OAAO,CAAC;CACpC,IAAI,EAAE,gBAAgB,KAAA,GAAW,EAAE,8BAAc,IAAI,IAAI;CACzD,MAAM,MAAM,gBAAgB,GAAG;CAC/B,MAAM,SAAS,EAAE,YAAY,IAAI,GAAG;CACpC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,KAAK,EAAE,KAAK;CAClB,EAAE,KAAK,KAAK,GAAG;CACf,EAAE,YAAY,IAAI,KAAK,EAAE;CACzB,OAAO;AACT;;AAGA,SAAgB,QAAQ,IAAkD;CACxE,OAAQ,GAA0B,QAAQ,CAAC;AAC7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawing-BxzLuryn.mjs","names":[],"sources":["../src/drawing/image.ts","../src/drawing/anchor.ts","../src/drawing/drawing.ts"],"sourcesContent":["// Image embedding.\n//\n// `XlsxImage` is the workbook-level handle for any image referenced from a\n// worksheet drawing (or chart `<a:blipFill>`). Bytes are kept verbatim so\n// re-saving never re-encodes; format / width / height are detected from the\n// file header so callers don't have to specify them.\n\nimport { OpenXmlIoError } from '../utils/exceptions';\n\nexport type XlsxImageFormat = 'png' | 'jpeg' | 'gif' | 'bmp' | 'webp' | 'tiff' | 'svg' | 'emf' | 'wmf';\n\n/**\n * Map from image format to the Content-Types Default extension that Excel uses\n * in `[Content_Types].xml`. SVG / EMF / WMF use the same extension as the\n * format string; PNG/JPEG/GIF/BMP do too. WebP and TIFF use their canonical\n * short names.\n */\nexport const IMAGE_FORMAT_EXTENSION: Readonly<Record<XlsxImageFormat, string>> = {\n png: 'png',\n jpeg: 'jpeg',\n gif: 'gif',\n bmp: 'bmp',\n webp: 'webp',\n tiff: 'tiff',\n svg: 'svg',\n emf: 'emf',\n wmf: 'wmf',\n};\n\n/** Map from image format to its IANA `image/*` MIME type. */\nexport const IMAGE_FORMAT_MIME: Readonly<Record<XlsxImageFormat, string>> = {\n png: 'image/png',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n bmp: 'image/bmp',\n webp: 'image/webp',\n tiff: 'image/tiff',\n svg: 'image/svg+xml',\n emf: 'image/x-emf',\n wmf: 'image/x-wmf',\n};\n\nexport interface XlsxImage {\n bytes: Uint8Array;\n format: XlsxImageFormat;\n /** Pixel width. Zero when dimensions can't be determined for the format. */\n width: number;\n /** Pixel height. Zero when dimensions can't be determined for the format. */\n height: number;\n /** ZIP archive path, e.g. `xl/media/image3.png`. Set by the writer. */\n path?: string;\n /** rels-resolved id used by `<a:blip r:embed=\"...\">`. Set by the loader. */\n rId?: string;\n}\n\n// ---- Magic-byte format detection ------------------------------------------\n\nconst startsWith = (bytes: Uint8Array, sig: ReadonlyArray<number>, offset = 0): boolean => {\n if (bytes.length < offset + sig.length) return false;\n for (let i = 0; i < sig.length; i++) {\n if (bytes[offset + i] !== sig[i]) return false;\n }\n return true;\n};\n\nconst PNG_SIG = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\nconst JPEG_SIG = [0xff, 0xd8, 0xff];\nconst GIF87 = [0x47, 0x49, 0x46, 0x38, 0x37, 0x61];\nconst GIF89 = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];\nconst BMP_SIG = [0x42, 0x4d];\nconst RIFF_SIG = [0x52, 0x49, 0x46, 0x46];\nconst WEBP_TAG = [0x57, 0x45, 0x42, 0x50];\nconst TIFF_LE = [0x49, 0x49, 0x2a, 0x00];\nconst TIFF_BE = [0x4d, 0x4d, 0x00, 0x2a];\nconst EMF_SIG = [0x01, 0x00, 0x00, 0x00];\nconst EMF_TAG = [0x20, 0x45, 0x4d, 0x46]; // ' EMF' at offset 40\nconst WMF_SIG_PLACEABLE = [0xd7, 0xcd, 0xc6, 0x9a];\nconst WMF_SIG_BARE = [0x01, 0x00, 0x09, 0x00];\n\nconst isSvg = (bytes: Uint8Array): boolean => {\n // Inspect the first ~512 bytes for an `<svg` tag (with optional XML / DOCTYPE\n // preamble).\n const head = new TextDecoder('utf-8', { fatal: false }).decode(bytes.subarray(0, Math.min(bytes.length, 512)));\n return /<svg\\b/i.test(head);\n};\n\nexport function detectImageFormat(bytes: Uint8Array): XlsxImageFormat | undefined {\n if (startsWith(bytes, PNG_SIG)) return 'png';\n if (startsWith(bytes, JPEG_SIG)) return 'jpeg';\n if (startsWith(bytes, GIF87) || startsWith(bytes, GIF89)) return 'gif';\n if (startsWith(bytes, BMP_SIG)) return 'bmp';\n if (startsWith(bytes, RIFF_SIG) && startsWith(bytes, WEBP_TAG, 8)) return 'webp';\n if (startsWith(bytes, TIFF_LE) || startsWith(bytes, TIFF_BE)) return 'tiff';\n if (startsWith(bytes, EMF_SIG) && startsWith(bytes, EMF_TAG, 40)) return 'emf';\n if (startsWith(bytes, WMF_SIG_PLACEABLE) || startsWith(bytes, WMF_SIG_BARE)) return 'wmf';\n if (isSvg(bytes)) return 'svg';\n return undefined;\n}\n\n// ---- Per-format dimension extraction --------------------------------------\n\nconst readU32BE = (bytes: Uint8Array, offset: number): number =>\n ((bytes[offset] ?? 0) << 24) |\n ((bytes[offset + 1] ?? 0) << 16) |\n ((bytes[offset + 2] ?? 0) << 8) |\n (bytes[offset + 3] ?? 0);\n\nconst readU16LE = (bytes: Uint8Array, offset: number): number => (bytes[offset] ?? 0) | ((bytes[offset + 1] ?? 0) << 8);\n\nconst readU16BE = (bytes: Uint8Array, offset: number): number => ((bytes[offset] ?? 0) << 8) | (bytes[offset + 1] ?? 0);\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\nconst pngDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // PNG: 8-byte signature, 4-byte chunk-length, 4-byte type (\"IHDR\"), then\n // 4-byte width, 4-byte height (both big-endian).\n if (bytes.length < 24) return undefined;\n if (bytes[12] !== 0x49 || bytes[13] !== 0x48 || bytes[14] !== 0x44 || bytes[15] !== 0x52) {\n return undefined;\n }\n return { width: readU32BE(bytes, 16), height: readU32BE(bytes, 20) };\n};\n\nconst gifDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n if (bytes.length < 10) return undefined;\n return { width: readU16LE(bytes, 6), height: readU16LE(bytes, 8) };\n};\n\nconst bmpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n if (bytes.length < 26) return undefined;\n // BITMAPINFOHEADER: width (LE int32) at offset 18, height at offset 22.\n // Height can be negative for top-down bitmaps; we report absolute pixels.\n const w = (bytes[18] ?? 0) | ((bytes[19] ?? 0) << 8) | ((bytes[20] ?? 0) << 16) | ((bytes[21] ?? 0) << 24);\n const hRaw = (bytes[22] ?? 0) | ((bytes[23] ?? 0) << 8) | ((bytes[24] ?? 0) << 16) | ((bytes[25] ?? 0) << 24);\n // Treat width as signed; for height take absolute value (top-down bitmaps\n // store negative).\n const wSigned = (w | 0) >>> 0 > 0x7fffffff ? (w | 0) - 0x100000000 : w;\n const hSigned = (hRaw | 0) >>> 0 > 0x7fffffff ? (hRaw | 0) - 0x100000000 : hRaw;\n return { width: wSigned, height: Math.abs(hSigned) };\n};\n\nconst jpegDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // Walk the marker stream until an SOFn (FFC0..FFCF, excluding FFC4/C8/CC).\n let i = 2; // skip SOI (FFD8)\n while (i + 9 < bytes.length) {\n if (bytes[i] !== 0xff) return undefined;\n let marker = bytes[i + 1] ?? 0;\n while (marker === 0xff) {\n // Padding bytes. Advance to the next non-FF.\n i += 1;\n marker = bytes[i + 1] ?? 0;\n }\n i += 2;\n const isSof = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;\n const len = readU16BE(bytes, i);\n if (isSof) {\n // SOF segment: 2 bytes length, 1 byte precision, 2 bytes height, 2 bytes\n // width.\n if (i + 7 > bytes.length) return undefined;\n const height = readU16BE(bytes, i + 3);\n const width = readU16BE(bytes, i + 5);\n return { width, height };\n }\n i += len;\n }\n return undefined;\n};\n\nconst webpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // RIFF header is 12 bytes; chunk type is at offset 12.\n if (bytes.length < 30) return undefined;\n // VP8 (lossy): \"VP8 \" chunk; width / height at offset 26 / 28 (LE 14-bit each\n // + 2 unused bits).\n if (\n bytes[12] === 0x56 && // V\n bytes[13] === 0x50 && // P\n bytes[14] === 0x38 && // 8\n bytes[15] === 0x20 // space\n ) {\n const w = readU16LE(bytes, 26) & 0x3fff;\n const h = readU16LE(bytes, 28) & 0x3fff;\n return { width: w, height: h };\n }\n // VP8L (lossless): 14-bit width-1 / height-1 packed little-endian starting at\n // offset 21.\n if (\n bytes[12] === 0x56 &&\n bytes[13] === 0x50 &&\n bytes[14] === 0x38 &&\n bytes[15] === 0x4c // L\n ) {\n if (bytes.length < 25) return undefined;\n const b0 = bytes[21] ?? 0;\n const b1 = bytes[22] ?? 0;\n const b2 = bytes[23] ?? 0;\n const b3 = bytes[24] ?? 0;\n const w = (b0 | (b1 << 8)) & 0x3fff;\n const h = ((b1 >> 6) | (b2 << 2) | ((b3 & 0x0f) << 10)) & 0x3fff;\n return { width: w + 1, height: h + 1 };\n }\n // VP8X (extended): width-1 (24 bits) / height-1 (24 bits) at offset 24 / 27.\n if (\n bytes[12] === 0x56 &&\n bytes[13] === 0x50 &&\n bytes[14] === 0x38 &&\n bytes[15] === 0x58 // X\n ) {\n if (bytes.length < 30) return undefined;\n const w = (bytes[24] ?? 0) | ((bytes[25] ?? 0) << 8) | ((bytes[26] ?? 0) << 16);\n const h = (bytes[27] ?? 0) | ((bytes[28] ?? 0) << 8) | ((bytes[29] ?? 0) << 16);\n return { width: w + 1, height: h + 1 };\n }\n return undefined;\n};\n\nexport function detectImageDimensions(bytes: Uint8Array, format: XlsxImageFormat): Dimensions {\n let dims: Dimensions | undefined;\n switch (format) {\n case 'png':\n dims = pngDimensions(bytes);\n break;\n case 'jpeg':\n dims = jpegDimensions(bytes);\n break;\n case 'gif':\n dims = gifDimensions(bytes);\n break;\n case 'bmp':\n dims = bmpDimensions(bytes);\n break;\n case 'webp':\n dims = webpDimensions(bytes);\n break;\n default:\n // tiff / svg / emf / wmf — readers can fall back to 0 and Excel will\n // assign defaults.\n dims = undefined;\n }\n return dims ?? { width: 0, height: 0 };\n}\n\n// ---- Public factory --------------------------------------------------------\n\n/**\n * Build an `XlsxImage` from raw bytes. Detects the format and dimensions\n * automatically. Caller may pass an explicit `format` to override detection\n * (e.g. when bytes were read from a `data:` URL with a known MIME type) or\n * `width`/`height` to skip the parser.\n */\nexport function loadImage(\n bytes: Uint8Array,\n opts: { format?: XlsxImageFormat; width?: number; height?: number } = {},\n): XlsxImage {\n const format = opts.format ?? detectImageFormat(bytes);\n if (!format) {\n throw new OpenXmlIoError('loadImage: could not determine image format from bytes');\n }\n const dims =\n opts.width !== undefined && opts.height !== undefined\n ? { width: opts.width, height: opts.height }\n : detectImageDimensions(bytes, format);\n return { bytes, format, width: dims.width, height: dims.height };\n}\n","// DrawingML anchors.\n//\n// An anchor positions a drawing (chart / image / shape) inside a worksheet.\n// ECMA-376 §20.5.2 defines three kinds:\n//\n// absolute — fixed (x, y) and (cx, cy) in EMU; ignores cell layout. oneCell —\n// pinned at `from` cell, fixed extent. Resizes with the\n// cell only on its top-left corner.\n// twoCell — anchored to `from` and `to` cells. Resizes / moves with\n// both corners depending on `editAs`.\n//\n// Coordinates are EMU (English Metric Units). 1 inch = 914400 EMU, 1 cm =\n// 360000 EMU, 1 px = 9525 EMU at 96 dpi.\n\nimport { columnIndexFromLetter } from '../utils/coordinate';\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport { emuFromPx } from '../utils/units';\n\n/** EMU = English Metric Units. Drawing coordinates are stored in EMU on the wire. */\nexport interface Point2D {\n /** Horizontal offset in EMU. */\n x: number;\n /** Vertical offset in EMU. */\n y: number;\n}\n\nexport interface PositiveSize2D {\n cx: number;\n cy: number;\n}\n\n/**\n * `from` / `to` corners reference a cell by 0-based column + row index plus an\n * EMU offset within the cell. Excel's wire format is 0-based here even though\n * cell references in formulas / sheetData are 1-based.\n */\nexport interface AnchorMarker {\n col: number;\n colOff: number;\n row: number;\n rowOff: number;\n}\n\nexport type DrawingAnchor =\n | { kind: 'absolute'; pos: Point2D; ext: PositiveSize2D }\n | { kind: 'oneCell'; from: AnchorMarker; ext: PositiveSize2D }\n | { kind: 'twoCell'; from: AnchorMarker; to: AnchorMarker; editAs?: 'twoCell' | 'oneCell' | 'absolute' };\n\nconst A1_RE = /^([A-Za-z]{1,3})([1-9][0-9]*)$/;\n\n/**\n * Convert a cell ref (\"A1\", \"C5\") to a 0-based AnchorMarker with `colOff =\n * rowOff = 0`. Throws on malformed refs.\n */\nexport function anchorMarkerFromCellRef(ref: string): AnchorMarker {\n const m = A1_RE.exec(ref);\n if (!m || m[1] === undefined || m[2] === undefined) {\n throw new OpenXmlSchemaError(`anchorMarkerFromCellRef: invalid coordinate \"${ref}\"`);\n }\n const col = columnIndexFromLetter(m[1]) - 1; // 0-based\n const row = Number.parseInt(m[2], 10) - 1; // 0-based\n return { col, colOff: 0, row, rowOff: 0 };\n}\n\n/** Build an absolute anchor from an (x, y, cx, cy) EMU bundle. */\nexport function makeAbsoluteAnchor(opts: { x: number; y: number; cx: number; cy: number }): DrawingAnchor {\n return { kind: 'absolute', pos: { x: opts.x, y: opts.y }, ext: { cx: opts.cx, cy: opts.cy } };\n}\n\n/** Build a one-cell anchor pinned at `from` with an explicit pixel extent. */\nexport function makeOneCellAnchor(opts: {\n from: string | AnchorMarker;\n widthPx: number;\n heightPx: number;\n}): DrawingAnchor {\n const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n return {\n kind: 'oneCell',\n from,\n ext: { cx: emuFromPx(opts.widthPx), cy: emuFromPx(opts.heightPx) },\n };\n}\n\n/**\n * Build a two-cell anchor from cell-ref pairs (or pre-built markers). Defaults\n * to `editAs='twoCell'` — drag both corners with the cells.\n */\nexport function makeTwoCellAnchor(opts: {\n from: string | AnchorMarker;\n to: string | AnchorMarker;\n editAs?: 'twoCell' | 'oneCell' | 'absolute';\n}): DrawingAnchor {\n const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n const to = typeof opts.to === 'string' ? anchorMarkerFromCellRef(opts.to) : opts.to;\n return {\n kind: 'twoCell',\n from,\n to,\n ...(opts.editAs !== undefined ? { editAs: opts.editAs } : {}),\n };\n}\n","// Spreadsheet drawing data model.\n//\n// A `Drawing` is the per-worksheet `xl/drawings/drawingN.xml` part — a list of\n// anchor entries, each carrying a content variant (chart, picture, shape,\n// connector, group). Stage-1 implements the chart variant as a \"rels-only\"\n// reference (the full ChartML model lands in later iterations); picture / shape\n// / connector / group are reserved for later.\n\nimport type { ChartSpace } from '../chart/chart';\nimport type { CxChartSpace } from '../chart/cx/chartex';\nimport type { DrawingAnchor } from './anchor';\nimport type { ShapeProperties } from './dml/shape-properties';\nimport type { XlsxImage } from './image';\n\n/** Reference to a chart part — the chart's drawing-rels rId resolves to xl/charts/chartN.xml. */\nexport interface ChartReference {\n /** Drawing-rels rId pointing at the chart part. Populated on read; the writer assigns its own. */\n rId?: string;\n /**\n * Legacy ECMA-376 chart payload (`c:chartSpace`). Stage-1 supports BarChart\n * end-to-end; other chart kinds populate this field as their parsers /\n * writers land.\n */\n space?: ChartSpace;\n /**\n * Excel-2016 chartex payload (`cx:chartSpace`). Mutually exclusive with\n * {@link space} for any given drawing item; the parser sniffs the root\n * element and populates whichever is appropriate.\n */\n cxSpace?: CxChartSpace;\n /**\n * `true` when the resolved chart part is a chartex (`cx:`) chart. Set by the\n * package writer so the drawing emitter knows to use the chartex\n * `<a:graphicData uri>` instead of the legacy chart URI — Excel rejects the\n * workbook when the URI doesn't match the chart's actual root namespace.\n */\n isCx?: boolean;\n}\n\n/** Reference to an embedded picture inside a worksheet drawing. */\nexport interface PictureReference {\n /** Drawing-rels rId pointing at the embedded image. Populated on read; the writer assigns its own. */\n rId?: string;\n /** Resolved image bytes + metadata. Populated on read; the writer reads it back. */\n image?: XlsxImage;\n /** Picture display name (`<xdr:cNvPr name=\"...\">`). */\n name?: string;\n /** Optional alt-text description. */\n descr?: string;\n /** Hidden flag (`<xdr:cNvPr hidden=\"1\"/>`). */\n hidden?: boolean;\n /** Per-picture shape properties (extra fill / line / rotation). */\n spPr?: ShapeProperties;\n}\n\nexport interface DrawingItem {\n anchor: DrawingAnchor;\n content:\n | { kind: 'chart'; chart: ChartReference }\n | { kind: 'picture'; picture: PictureReference }\n | { kind: 'unsupported'; rawTag: string };\n}\n\nexport interface Drawing {\n items: DrawingItem[];\n}\n\nexport function makeDrawing(items: DrawingItem[] = []): Drawing {\n return { items };\n}\n\nexport function makeChartDrawingItem(anchor: DrawingAnchor, chart: ChartReference = {}): DrawingItem {\n return { anchor, content: { kind: 'chart', chart } };\n}\n\nexport function makePictureDrawingItem(anchor: DrawingAnchor, picture: PictureReference | XlsxImage): DrawingItem {\n // Distinguish raw image bytes from a full PictureReference by checking the\n // discriminator: XlsxImage carries `format`, PictureReference doesn't.\n const ref: PictureReference = 'format' in picture ? { image: picture as XlsxImage } : (picture as PictureReference);\n return { anchor, content: { kind: 'picture', picture: ref } };\n}\n\n// ---- Worksheet ergonomic helpers ----------------------------------------\n\nimport { loadImage } from './image';\nimport { makeOneCellAnchor } from './anchor';\nimport type { Worksheet } from '../worksheet/worksheet';\n\n/**\n * Drop an image onto a worksheet at a single-cell anchor. Lazy-allocates\n * `ws.drawing` (as `makeDrawing([])`) on first call and appends a picture\n * DrawingItem.\n *\n * `image` accepts either an `XlsxImage` (already loaded via `loadImage`) or raw\n * image bytes — in the bytes case, this helper sniffs the format with\n * `loadImage` itself.\n *\n * `at` is a cell ref like `\"C3\"`. Override `widthPx` / `heightPx` to scale;\n * otherwise the helper uses 96×96 defaults that look fine for typical icons.\n */\nexport const addImageAt = (\n ws: Worksheet,\n at: string,\n image: XlsxImage | Uint8Array,\n opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n const xlsxImage: XlsxImage = image instanceof Uint8Array ? loadImage(image) : image;\n const anchor = makeOneCellAnchor({\n from: at,\n widthPx: opts.widthPx ?? 96,\n heightPx: opts.heightPx ?? 96,\n });\n const item = makePictureDrawingItem(anchor, xlsxImage);\n if (!ws.drawing) ws.drawing = makeDrawing([]);\n ws.drawing.items.push(item);\n return item;\n};\n\n/**\n * Anchor a chart to a worksheet at a single-cell ref. Lazy-allocates\n * `ws.drawing`. `chart` is the same `ChartReference` shape `makeChart\n * DrawingItem` accepts (`{ space }` for legacy chart, `{ cxSpace }` for\n * chartex).\n */\nexport const addChartAt = (\n ws: Worksheet,\n at: string,\n chart: ChartReference,\n opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n const anchor = makeOneCellAnchor({\n from: at,\n widthPx: opts.widthPx ?? 480,\n heightPx: opts.heightPx ?? 320,\n });\n const item = makeChartDrawingItem(anchor, chart);\n if (!ws.drawing) ws.drawing = makeDrawing([]);\n ws.drawing.items.push(item);\n return item;\n};\n\n/**\n * Read-only snapshot of every picture DrawingItem on the sheet. Returns the\n * matching items (each with its anchor + picture reference). Empty array when\n * the sheet has no drawing or only non-picture items.\n */\nexport const listImagesOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n if (!ws.drawing) return [];\n return ws.drawing.items.filter((it) => it.content.kind === 'picture');\n};\n\n/**\n * Read-only snapshot of every chart DrawingItem on the sheet. Each item has its\n * anchor + chart reference.\n */\nexport const listChartsOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n if (!ws.drawing) return [];\n return ws.drawing.items.filter((it) => it.content.kind === 'chart');\n};\n\n/**\n * Drop every DrawingItem from the worksheet. Returns the count removed. The\n * `ws.drawing` field itself is left in place (empty) so subsequent `addImageAt`\n * / `addChartAt` calls don't have to re-allocate.\n */\nexport const removeAllDrawingItems = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const n = ws.drawing.items.length;\n ws.drawing.items = [];\n return n;\n};\n\n/**\n * Drop every picture DrawingItem from the worksheet, leaving charts and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllImages = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const before = ws.drawing.items.length;\n ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'picture');\n return before - ws.drawing.items.length;\n};\n\n/**\n * Drop every chart DrawingItem from the worksheet, leaving pictures and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllCharts = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const before = ws.drawing.items.length;\n ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'chart');\n return before - ws.drawing.items.length;\n};\n"],"mappings":";;;;;;;;;;AAiBA,MAAa,yBAAoE;CAC/E,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CACN,KAAK;CACL,KAAK;CACL,KAAK;AACP;;AAGA,MAAa,oBAA+D;CAC1E,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CACN,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAiBA,MAAM,cAAc,OAAmB,KAA4B,SAAS,MAAe;CACzF,IAAI,MAAM,SAAS,SAAS,IAAI,QAAQ,OAAO;CAC/C,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAC9B,IAAI,MAAM,SAAS,OAAO,IAAI,IAAI,OAAO;CAE3C,OAAO;AACT;AAEA,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;AAAI;AAC/D,MAAM,WAAW;CAAC;CAAM;CAAM;AAAI;AAClC,MAAM,QAAQ;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;AAAI;AACjD,MAAM,QAAQ;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;AAAI;AACjD,MAAM,UAAU,CAAC,IAAM,EAAI;AAC3B,MAAM,WAAW;CAAC;CAAM;CAAM;CAAM;AAAI;AACxC,MAAM,WAAW;CAAC;CAAM;CAAM;CAAM;AAAI;AACxC,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;AAAI;AACvC,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;AAAI;AACvC,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;AAAI;AACvC,MAAM,UAAU;CAAC;CAAM;CAAM;CAAM;AAAI;AACvC,MAAM,oBAAoB;CAAC;CAAM;CAAM;CAAM;AAAI;AACjD,MAAM,eAAe;CAAC;CAAM;CAAM;CAAM;AAAI;AAE5C,MAAM,SAAS,UAA+B;CAG5C,MAAM,OAAO,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,CAAC,EAAE,OAAO,MAAM,SAAS,GAAG,KAAK,IAAI,MAAM,QAAQ,GAAG,CAAC,CAAC;CAC7G,OAAO,UAAU,KAAK,IAAI;AAC5B;AAEA,SAAgB,kBAAkB,OAAgD;CAChF,IAAI,WAAW,OAAO,OAAO,GAAG,OAAO;CACvC,IAAI,WAAW,OAAO,QAAQ,GAAG,OAAO;CACxC,IAAI,WAAW,OAAO,KAAK,KAAK,WAAW,OAAO,KAAK,GAAG,OAAO;CACjE,IAAI,WAAW,OAAO,OAAO,GAAG,OAAO;CACvC,IAAI,WAAW,OAAO,QAAQ,KAAK,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO;CAC1E,IAAI,WAAW,OAAO,OAAO,KAAK,WAAW,OAAO,OAAO,GAAG,OAAO;CACrE,IAAI,WAAW,OAAO,OAAO,KAAK,WAAW,OAAO,SAAS,EAAE,GAAG,OAAO;CACzE,IAAI,WAAW,OAAO,iBAAiB,KAAK,WAAW,OAAO,YAAY,GAAG,OAAO;CACpF,IAAI,MAAM,KAAK,GAAG,OAAO;AAE3B;AAIA,MAAM,aAAa,OAAmB,YAClC,MAAM,WAAW,MAAM,MACvB,MAAM,SAAS,MAAM,MAAM,MAC3B,MAAM,SAAS,MAAM,MAAM,KAC5B,MAAM,SAAS,MAAM;AAExB,MAAM,aAAa,OAAmB,YAA4B,MAAM,WAAW,MAAO,MAAM,SAAS,MAAM,MAAM;AAErH,MAAM,aAAa,OAAmB,YAA6B,MAAM,WAAW,MAAM,KAAM,MAAM,SAAS,MAAM;AAOrH,MAAM,iBAAiB,UAA8C;CAGnE,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;CAC9B,IAAI,MAAM,QAAQ,MAAQ,MAAM,QAAQ,MAAQ,MAAM,QAAQ,MAAQ,MAAM,QAAQ,IAClF;CAEF,OAAO;EAAE,OAAO,UAAU,OAAO,EAAE;EAAG,QAAQ,UAAU,OAAO,EAAE;CAAE;AACrE;AAEA,MAAM,iBAAiB,UAA8C;CACnE,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;CAC9B,OAAO;EAAE,OAAO,UAAU,OAAO,CAAC;EAAG,QAAQ,UAAU,OAAO,CAAC;CAAE;AACnE;AAEA,MAAM,iBAAiB,UAA8C;CACnE,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;CAG9B,MAAM,KAAK,MAAM,OAAO,MAAO,MAAM,OAAO,MAAM,KAAO,MAAM,OAAO,MAAM,MAAQ,MAAM,OAAO,MAAM;CACvG,MAAM,QAAQ,MAAM,OAAO,MAAO,MAAM,OAAO,MAAM,KAAO,MAAM,OAAO,MAAM,MAAQ,MAAM,OAAO,MAAM;CAG1G,MAAM,WAAW,IAAI,OAAO,IAAI,cAAc,IAAI,KAAK,aAAc;CACrE,MAAM,WAAW,OAAO,OAAO,IAAI,cAAc,OAAO,KAAK,aAAc;CAC3E,OAAO;EAAE,OAAO;EAAS,QAAQ,KAAK,IAAI,OAAO;CAAE;AACrD;AAEA,MAAM,kBAAkB,UAA8C;CAEpE,IAAI,IAAI;CACR,OAAO,IAAI,IAAI,MAAM,QAAQ;EAC3B,IAAI,MAAM,OAAO,KAAM,OAAO,KAAA;EAC9B,IAAI,SAAS,MAAM,IAAI,MAAM;EAC7B,OAAO,WAAW,KAAM;GAEtB,KAAK;GACL,SAAS,MAAM,IAAI,MAAM;EAC3B;EACA,KAAK;EACL,MAAM,QAAQ,UAAU,OAAQ,UAAU,OAAQ,WAAW,OAAQ,WAAW,OAAQ,WAAW;EACnG,MAAM,MAAM,UAAU,OAAO,CAAC;EAC9B,IAAI,OAAO;GAGT,IAAI,IAAI,IAAI,MAAM,QAAQ,OAAO,KAAA;GACjC,MAAM,SAAS,UAAU,OAAO,IAAI,CAAC;GAErC,OAAO;IAAE,OADK,UAAU,OAAO,IAAI,CACtB;IAAG;GAAO;EACzB;EACA,KAAK;CACP;AAEF;AAEA,MAAM,kBAAkB,UAA8C;CAEpE,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;CAG9B,IACE,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,IAId,OAAO;EAAE,OAFC,UAAU,OAAO,EAAE,IAAI;EAEd,QADT,UAAU,OAAO,EAAE,IAAI;CACJ;CAI/B,IACE,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,IACd;EACA,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;EAC9B,MAAM,KAAK,MAAM,OAAO;EACxB,MAAM,KAAK,MAAM,OAAO;EACxB,MAAM,KAAK,MAAM,OAAO;EACxB,MAAM,KAAK,MAAM,OAAO;EACxB,MAAM,KAAK,KAAM,MAAM,KAAM;EAC7B,MAAM,KAAM,MAAM,IAAM,MAAM,KAAO,KAAK,OAAS,MAAO;EAC1D,OAAO;GAAE,OAAO,IAAI;GAAG,QAAQ,IAAI;EAAE;CACvC;CAEA,IACE,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,MACd,MAAM,QAAQ,IACd;EACA,IAAI,MAAM,SAAS,IAAI,OAAO,KAAA;EAC9B,MAAM,KAAK,MAAM,OAAO,MAAO,MAAM,OAAO,MAAM,KAAO,MAAM,OAAO,MAAM;EAC5E,MAAM,KAAK,MAAM,OAAO,MAAO,MAAM,OAAO,MAAM,KAAO,MAAM,OAAO,MAAM;EAC5E,OAAO;GAAE,OAAO,IAAI;GAAG,QAAQ,IAAI;EAAE;CACvC;AAEF;AAEA,SAAgB,sBAAsB,OAAmB,QAAqC;CAC5F,IAAI;CACJ,QAAQ,QAAR;EACE,KAAK;GACH,OAAO,cAAc,KAAK;GAC1B;EACF,KAAK;GACH,OAAO,eAAe,KAAK;GAC3B;EACF,KAAK;GACH,OAAO,cAAc,KAAK;GAC1B;EACF,KAAK;GACH,OAAO,cAAc,KAAK;GAC1B;EACF,KAAK;GACH,OAAO,eAAe,KAAK;GAC3B;EACF,SAGE,OAAO,KAAA;CACX;CACA,OAAO,QAAQ;EAAE,OAAO;EAAG,QAAQ;CAAE;AACvC;;;;;;;AAUA,SAAgB,UACd,OACA,OAAsE,CAAC,GAC5D;CACX,MAAM,SAAS,KAAK,UAAU,kBAAkB,KAAK;CACrD,IAAI,CAAC,QACH,MAAM,IAAI,eAAe,wDAAwD;CAEnF,MAAM,OACJ,KAAK,UAAU,KAAA,KAAa,KAAK,WAAW,KAAA,IACxC;EAAE,OAAO,KAAK;EAAO,QAAQ,KAAK;CAAO,IACzC,sBAAsB,OAAO,MAAM;CACzC,OAAO;EAAE;EAAO;EAAQ,OAAO,KAAK;EAAO,QAAQ,KAAK;CAAO;AACjE;;;ACzNA,MAAM,QAAQ;;;;;AAMd,SAAgB,wBAAwB,KAA2B;CACjE,MAAM,IAAI,MAAM,KAAK,GAAG;CACxB,IAAI,CAAC,KAAK,EAAE,OAAO,KAAA,KAAa,EAAE,OAAO,KAAA,GACvC,MAAM,IAAI,mBAAmB,gDAAgD,IAAI,EAAE;CAIrF,OAAO;EAAE,KAFG,sBAAsB,EAAE,EAAE,IAAI;EAE5B,QAAQ;EAAG,KADb,OAAO,SAAS,EAAE,IAAI,EAAE,IAAI;EACV,QAAQ;CAAE;AAC1C;;AAGA,SAAgB,mBAAmB,MAAuE;CACxG,OAAO;EAAE,MAAM;EAAY,KAAK;GAAE,GAAG,KAAK;GAAG,GAAG,KAAK;EAAE;EAAG,KAAK;GAAE,IAAI,KAAK;GAAI,IAAI,KAAK;EAAG;CAAE;AAC9F;;AAGA,SAAgB,kBAAkB,MAIhB;CAEhB,OAAO;EACL,MAAM;EACN,MAHW,OAAO,KAAK,SAAS,WAAW,wBAAwB,KAAK,IAAI,IAAI,KAAK;EAIrF,KAAK;GAAE,IAAI,UAAU,KAAK,OAAO;GAAG,IAAI,UAAU,KAAK,QAAQ;EAAE;CACnE;AACF;;;ACdA,SAAgB,YAAY,QAAuB,CAAC,GAAY;CAC9D,OAAO,EAAE,MAAM;AACjB;AAEA,SAAgB,qBAAqB,QAAuB,QAAwB,CAAC,GAAgB;CACnG,OAAO;EAAE;EAAQ,SAAS;GAAE,MAAM;GAAS;EAAM;CAAE;AACrD;AAEA,SAAgB,uBAAuB,QAAuB,SAAoD;CAIhH,OAAO;EAAE;EAAQ,SAAS;GAAE,MAAM;GAAW,SADf,YAAY,UAAU,EAAE,OAAO,QAAqB,IAAK;EAC7B;CAAE;AAC9D;;;;;;;;;;;;;AAoBA,MAAa,cACX,IACA,IACA,OACA,OAAgD,CAAC,MACjC;CAChB,MAAM,YAAuB,iBAAiB,aAAa,UAAU,KAAK,IAAI;CAM9E,MAAM,OAAO,uBALE,kBAAkB;EAC/B,MAAM;EACN,SAAS,KAAK,WAAW;EACzB,UAAU,KAAK,YAAY;CAC7B,CACyC,GAAG,SAAS;CACrD,IAAI,CAAC,GAAG,SAAS,GAAG,UAAU,YAAY,CAAC,CAAC;CAC5C,GAAG,QAAQ,MAAM,KAAK,IAAI;CAC1B,OAAO;AACT;;;;;;;AAQA,MAAa,cACX,IACA,IACA,OACA,OAAgD,CAAC,MACjC;CAMhB,MAAM,OAAO,qBALE,kBAAkB;EAC/B,MAAM;EACN,SAAS,KAAK,WAAW;EACzB,UAAU,KAAK,YAAY;CAC7B,CACuC,GAAG,KAAK;CAC/C,IAAI,CAAC,GAAG,SAAS,GAAG,UAAU,YAAY,CAAC,CAAC;CAC5C,GAAG,QAAQ,MAAM,KAAK,IAAI;CAC1B,OAAO;AACT;;;;;;AAOA,MAAa,qBAAqB,OAA8C;CAC9E,IAAI,CAAC,GAAG,SAAS,OAAO,CAAC;CACzB,OAAO,GAAG,QAAQ,MAAM,QAAQ,OAAO,GAAG,QAAQ,SAAS,SAAS;AACtE;;;;;AAMA,MAAa,qBAAqB,OAA8C;CAC9E,IAAI,CAAC,GAAG,SAAS,OAAO,CAAC;CACzB,OAAO,GAAG,QAAQ,MAAM,QAAQ,OAAO,GAAG,QAAQ,SAAS,OAAO;AACpE;;;;;;AAOA,MAAa,yBAAyB,OAA0B;CAC9D,IAAI,CAAC,GAAG,SAAS,OAAO;CACxB,MAAM,IAAI,GAAG,QAAQ,MAAM;CAC3B,GAAG,QAAQ,QAAQ,CAAC;CACpB,OAAO;AACT;;;;;AAMA,MAAa,mBAAmB,OAA0B;CACxD,IAAI,CAAC,GAAG,SAAS,OAAO;CACxB,MAAM,SAAS,GAAG,QAAQ,MAAM;CAChC,GAAG,QAAQ,QAAQ,GAAG,QAAQ,MAAM,QAAQ,OAAO,GAAG,QAAQ,SAAS,SAAS;CAChF,OAAO,SAAS,GAAG,QAAQ,MAAM;AACnC;;;;;AAMA,MAAa,mBAAmB,OAA0B;CACxD,IAAI,CAAC,GAAG,SAAS,OAAO;CACxB,MAAM,SAAS,GAAG,QAAQ,MAAM;CAChC,GAAG,QAAQ,QAAQ,GAAG,QAAQ,MAAM,QAAQ,OAAO,GAAG,QAAQ,SAAS,OAAO;CAC9E,OAAO,SAAS,GAAG,QAAQ,MAAM;AACnC"}
|
|
1
|
+
{"version":3,"file":"drawing-BxzLuryn.mjs","names":[],"sources":["../src/drawing/image.ts","../src/drawing/anchor.ts","../src/drawing/drawing.ts"],"sourcesContent":["// Image embedding.\n//\n// `XlsxImage` is the workbook-level handle for any image referenced from a\n// worksheet drawing (or chart `<a:blipFill>`). Bytes are kept verbatim so\n// re-saving never re-encodes; format / width / height are detected from the\n// file header so callers don't have to specify them.\n\nimport { OpenXmlIoError } from '../utils/exceptions';\n\nexport type XlsxImageFormat = 'png' | 'jpeg' | 'gif' | 'bmp' | 'webp' | 'tiff' | 'svg' | 'emf' | 'wmf';\n\n/**\n * Map from image format to the Content-Types Default extension that Excel uses\n * in `[Content_Types].xml`. SVG / EMF / WMF use the same extension as the\n * format string; PNG/JPEG/GIF/BMP do too. WebP and TIFF use their canonical\n * short names.\n */\nexport const IMAGE_FORMAT_EXTENSION: Readonly<Record<XlsxImageFormat, string>> = {\n png: 'png',\n jpeg: 'jpeg',\n gif: 'gif',\n bmp: 'bmp',\n webp: 'webp',\n tiff: 'tiff',\n svg: 'svg',\n emf: 'emf',\n wmf: 'wmf',\n};\n\n/** Map from image format to its IANA `image/*` MIME type. */\nexport const IMAGE_FORMAT_MIME: Readonly<Record<XlsxImageFormat, string>> = {\n png: 'image/png',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n bmp: 'image/bmp',\n webp: 'image/webp',\n tiff: 'image/tiff',\n svg: 'image/svg+xml',\n emf: 'image/x-emf',\n wmf: 'image/x-wmf',\n};\n\nexport interface XlsxImage {\n bytes: Uint8Array;\n format: XlsxImageFormat;\n /** Pixel width. Zero when dimensions can't be determined for the format. */\n width: number;\n /** Pixel height. Zero when dimensions can't be determined for the format. */\n height: number;\n /** ZIP archive path, e.g. `xl/media/image3.png`. Set by the writer. */\n path?: string;\n /** rels-resolved id used by `<a:blip r:embed=\"...\">`. Set by the loader. */\n rId?: string;\n}\n\n// ---- Magic-byte format detection ------------------------------------------\n\nconst startsWith = (bytes: Uint8Array, sig: ReadonlyArray<number>, offset = 0): boolean => {\n if (bytes.length < offset + sig.length) return false;\n for (let i = 0; i < sig.length; i++) {\n if (bytes[offset + i] !== sig[i]) return false;\n }\n return true;\n};\n\nconst PNG_SIG = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\nconst JPEG_SIG = [0xff, 0xd8, 0xff];\nconst GIF87 = [0x47, 0x49, 0x46, 0x38, 0x37, 0x61];\nconst GIF89 = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];\nconst BMP_SIG = [0x42, 0x4d];\nconst RIFF_SIG = [0x52, 0x49, 0x46, 0x46];\nconst WEBP_TAG = [0x57, 0x45, 0x42, 0x50];\nconst TIFF_LE = [0x49, 0x49, 0x2a, 0x00];\nconst TIFF_BE = [0x4d, 0x4d, 0x00, 0x2a];\nconst EMF_SIG = [0x01, 0x00, 0x00, 0x00];\nconst EMF_TAG = [0x20, 0x45, 0x4d, 0x46]; // ' EMF' at offset 40\nconst WMF_SIG_PLACEABLE = [0xd7, 0xcd, 0xc6, 0x9a];\nconst WMF_SIG_BARE = [0x01, 0x00, 0x09, 0x00];\n\nconst isSvg = (bytes: Uint8Array): boolean => {\n // Inspect the first ~512 bytes for an `<svg` tag (with optional XML / DOCTYPE\n // preamble).\n const head = new TextDecoder('utf-8', { fatal: false }).decode(bytes.subarray(0, Math.min(bytes.length, 512)));\n return /<svg\\b/i.test(head);\n};\n\nexport function detectImageFormat(bytes: Uint8Array): XlsxImageFormat | undefined {\n if (startsWith(bytes, PNG_SIG)) return 'png';\n if (startsWith(bytes, JPEG_SIG)) return 'jpeg';\n if (startsWith(bytes, GIF87) || startsWith(bytes, GIF89)) return 'gif';\n if (startsWith(bytes, BMP_SIG)) return 'bmp';\n if (startsWith(bytes, RIFF_SIG) && startsWith(bytes, WEBP_TAG, 8)) return 'webp';\n if (startsWith(bytes, TIFF_LE) || startsWith(bytes, TIFF_BE)) return 'tiff';\n if (startsWith(bytes, EMF_SIG) && startsWith(bytes, EMF_TAG, 40)) return 'emf';\n if (startsWith(bytes, WMF_SIG_PLACEABLE) || startsWith(bytes, WMF_SIG_BARE)) return 'wmf';\n if (isSvg(bytes)) return 'svg';\n return undefined;\n}\n\n// ---- Per-format dimension extraction --------------------------------------\n\nconst readU32BE = (bytes: Uint8Array, offset: number): number =>\n ((bytes[offset] ?? 0) << 24) |\n ((bytes[offset + 1] ?? 0) << 16) |\n ((bytes[offset + 2] ?? 0) << 8) |\n (bytes[offset + 3] ?? 0);\n\nconst readU16LE = (bytes: Uint8Array, offset: number): number => (bytes[offset] ?? 0) | ((bytes[offset + 1] ?? 0) << 8);\n\nconst readU16BE = (bytes: Uint8Array, offset: number): number => ((bytes[offset] ?? 0) << 8) | (bytes[offset + 1] ?? 0);\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\nconst pngDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // PNG: 8-byte signature, 4-byte chunk-length, 4-byte type (\"IHDR\"), then\n // 4-byte width, 4-byte height (both big-endian).\n if (bytes.length < 24) return undefined;\n if (bytes[12] !== 0x49 || bytes[13] !== 0x48 || bytes[14] !== 0x44 || bytes[15] !== 0x52) {\n return undefined;\n }\n return { width: readU32BE(bytes, 16), height: readU32BE(bytes, 20) };\n};\n\nconst gifDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n if (bytes.length < 10) return undefined;\n return { width: readU16LE(bytes, 6), height: readU16LE(bytes, 8) };\n};\n\nconst bmpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n if (bytes.length < 26) return undefined;\n // BITMAPINFOHEADER: width (LE int32) at offset 18, height at offset 22.\n // Height can be negative for top-down bitmaps; we report absolute pixels.\n const w = (bytes[18] ?? 0) | ((bytes[19] ?? 0) << 8) | ((bytes[20] ?? 0) << 16) | ((bytes[21] ?? 0) << 24);\n const hRaw = (bytes[22] ?? 0) | ((bytes[23] ?? 0) << 8) | ((bytes[24] ?? 0) << 16) | ((bytes[25] ?? 0) << 24);\n // Treat width as signed; for height take absolute value (top-down bitmaps\n // store negative).\n const wSigned = (w | 0) >>> 0 > 0x7fffffff ? (w | 0) - 0x100000000 : w;\n const hSigned = (hRaw | 0) >>> 0 > 0x7fffffff ? (hRaw | 0) - 0x100000000 : hRaw;\n return { width: wSigned, height: Math.abs(hSigned) };\n};\n\nconst jpegDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // Walk the marker stream until an SOFn (FFC0..FFCF, excluding FFC4/C8/CC).\n let i = 2; // skip SOI (FFD8)\n while (i + 9 < bytes.length) {\n if (bytes[i] !== 0xff) return undefined;\n let marker = bytes[i + 1] ?? 0;\n while (marker === 0xff) {\n // Padding bytes. Advance to the next non-FF.\n i += 1;\n marker = bytes[i + 1] ?? 0;\n }\n i += 2;\n const isSof = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;\n const len = readU16BE(bytes, i);\n if (isSof) {\n // SOF segment: 2 bytes length, 1 byte precision, 2 bytes height, 2 bytes\n // width.\n if (i + 7 > bytes.length) return undefined;\n const height = readU16BE(bytes, i + 3);\n const width = readU16BE(bytes, i + 5);\n return { width, height };\n }\n i += len;\n }\n return undefined;\n};\n\nconst webpDimensions = (bytes: Uint8Array): Dimensions | undefined => {\n // RIFF header is 12 bytes; chunk type is at offset 12.\n if (bytes.length < 30) return undefined;\n // VP8 (lossy): \"VP8 \" chunk; width / height at offset 26 / 28 (LE 14-bit each\n // + 2 unused bits).\n if (\n bytes[12] === 0x56 && // V\n bytes[13] === 0x50 && // P\n bytes[14] === 0x38 && // 8\n bytes[15] === 0x20 // space\n ) {\n const w = readU16LE(bytes, 26) & 0x3fff;\n const h = readU16LE(bytes, 28) & 0x3fff;\n return { width: w, height: h };\n }\n // VP8L (lossless): 14-bit width-1 / height-1 packed little-endian starting at\n // offset 21.\n if (\n bytes[12] === 0x56 &&\n bytes[13] === 0x50 &&\n bytes[14] === 0x38 &&\n bytes[15] === 0x4c // L\n ) {\n if (bytes.length < 25) return undefined;\n const b0 = bytes[21] ?? 0;\n const b1 = bytes[22] ?? 0;\n const b2 = bytes[23] ?? 0;\n const b3 = bytes[24] ?? 0;\n const w = (b0 | (b1 << 8)) & 0x3fff;\n const h = ((b1 >> 6) | (b2 << 2) | ((b3 & 0x0f) << 10)) & 0x3fff;\n return { width: w + 1, height: h + 1 };\n }\n // VP8X (extended): width-1 (24 bits) / height-1 (24 bits) at offset 24 / 27.\n if (\n bytes[12] === 0x56 &&\n bytes[13] === 0x50 &&\n bytes[14] === 0x38 &&\n bytes[15] === 0x58 // X\n ) {\n if (bytes.length < 30) return undefined;\n const w = (bytes[24] ?? 0) | ((bytes[25] ?? 0) << 8) | ((bytes[26] ?? 0) << 16);\n const h = (bytes[27] ?? 0) | ((bytes[28] ?? 0) << 8) | ((bytes[29] ?? 0) << 16);\n return { width: w + 1, height: h + 1 };\n }\n return undefined;\n};\n\nexport function detectImageDimensions(bytes: Uint8Array, format: XlsxImageFormat): Dimensions {\n let dims: Dimensions | undefined;\n switch (format) {\n case 'png':\n dims = pngDimensions(bytes);\n break;\n case 'jpeg':\n dims = jpegDimensions(bytes);\n break;\n case 'gif':\n dims = gifDimensions(bytes);\n break;\n case 'bmp':\n dims = bmpDimensions(bytes);\n break;\n case 'webp':\n dims = webpDimensions(bytes);\n break;\n default:\n // tiff / svg / emf / wmf — readers can fall back to 0 and Excel will\n // assign defaults.\n dims = undefined;\n }\n return dims ?? { width: 0, height: 0 };\n}\n\n// ---- Public factory --------------------------------------------------------\n\n/**\n * Build an `XlsxImage` from raw bytes. Detects the format and dimensions\n * automatically. Caller may pass an explicit `format` to override detection\n * (e.g. when bytes were read from a `data:` URL with a known MIME type) or\n * `width`/`height` to skip the parser.\n */\nexport function loadImage(\n bytes: Uint8Array,\n opts: { format?: XlsxImageFormat; width?: number; height?: number } = {},\n): XlsxImage {\n const format = opts.format ?? detectImageFormat(bytes);\n if (!format) {\n throw new OpenXmlIoError('loadImage: could not determine image format from bytes');\n }\n const dims =\n opts.width !== undefined && opts.height !== undefined\n ? { width: opts.width, height: opts.height }\n : detectImageDimensions(bytes, format);\n return { bytes, format, width: dims.width, height: dims.height };\n}\n","// DrawingML anchors.\n//\n// An anchor positions a drawing (chart / image / shape) inside a worksheet.\n// ECMA-376 §20.5.2 defines three kinds:\n//\n// absolute — fixed (x, y) and (cx, cy) in EMU; ignores cell layout. oneCell —\n// pinned at `from` cell, fixed extent. Resizes with the\n// cell only on its top-left corner.\n// twoCell — anchored to `from` and `to` cells. Resizes / moves with\n// both corners depending on `editAs`.\n//\n// Coordinates are EMU (English Metric Units). 1 inch = 914400 EMU, 1 cm =\n// 360000 EMU, 1 px = 9525 EMU at 96 dpi.\n\nimport { columnIndexFromLetter } from '../utils/coordinate';\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport { emuFromPx } from '../utils/units';\n\n/** EMU = English Metric Units. Drawing coordinates are stored in EMU on the wire. */\nexport interface Point2D {\n /** Horizontal offset in EMU. */\n x: number;\n /** Vertical offset in EMU. */\n y: number;\n}\n\nexport interface PositiveSize2D {\n cx: number;\n cy: number;\n}\n\n/**\n * `from` / `to` corners reference a cell by 0-based column + row index plus an\n * EMU offset within the cell. Excel's wire format is 0-based here even though\n * cell references in formulas / sheetData are 1-based.\n */\nexport interface AnchorMarker {\n col: number;\n colOff: number;\n row: number;\n rowOff: number;\n}\n\nexport type DrawingAnchor =\n | { kind: 'absolute'; pos: Point2D; ext: PositiveSize2D }\n | { kind: 'oneCell'; from: AnchorMarker; ext: PositiveSize2D }\n | { kind: 'twoCell'; from: AnchorMarker; to: AnchorMarker; editAs?: 'twoCell' | 'oneCell' | 'absolute' };\n\nconst A1_RE = /^([A-Za-z]{1,3})([1-9][0-9]*)$/;\n\n/**\n * Convert a cell ref (\"A1\", \"C5\") to a 0-based AnchorMarker with `colOff =\n * rowOff = 0`. Throws on malformed refs.\n */\nexport function anchorMarkerFromCellRef(ref: string): AnchorMarker {\n const m = A1_RE.exec(ref);\n if (!m || m[1] === undefined || m[2] === undefined) {\n throw new OpenXmlSchemaError(`anchorMarkerFromCellRef: invalid coordinate \"${ref}\"`);\n }\n const col = columnIndexFromLetter(m[1]) - 1; // 0-based\n const row = Number.parseInt(m[2], 10) - 1; // 0-based\n return { col, colOff: 0, row, rowOff: 0 };\n}\n\n/** Build an absolute anchor from an (x, y, cx, cy) EMU bundle. */\nexport function makeAbsoluteAnchor(opts: { x: number; y: number; cx: number; cy: number }): DrawingAnchor {\n return { kind: 'absolute', pos: { x: opts.x, y: opts.y }, ext: { cx: opts.cx, cy: opts.cy } };\n}\n\n/** Build a one-cell anchor pinned at `from` with an explicit pixel extent. */\nexport function makeOneCellAnchor(opts: {\n from: string | AnchorMarker;\n widthPx: number;\n heightPx: number;\n}): DrawingAnchor {\n const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n return {\n kind: 'oneCell',\n from,\n ext: { cx: emuFromPx(opts.widthPx), cy: emuFromPx(opts.heightPx) },\n };\n}\n\n/**\n * Build a two-cell anchor from cell-ref pairs (or pre-built markers). Defaults\n * to `editAs='twoCell'` — drag both corners with the cells.\n */\nexport function makeTwoCellAnchor(opts: {\n from: string | AnchorMarker;\n to: string | AnchorMarker;\n editAs?: 'twoCell' | 'oneCell' | 'absolute';\n}): DrawingAnchor {\n const from = typeof opts.from === 'string' ? anchorMarkerFromCellRef(opts.from) : opts.from;\n const to = typeof opts.to === 'string' ? anchorMarkerFromCellRef(opts.to) : opts.to;\n return {\n kind: 'twoCell',\n from,\n to,\n ...(opts.editAs !== undefined ? { editAs: opts.editAs } : {}),\n };\n}\n","// Spreadsheet drawing data model.\n//\n// A `Drawing` is the per-worksheet `xl/drawings/drawingN.xml` part — a list of\n// anchor entries, each carrying a content variant (chart, picture, shape,\n// connector, group). Stage-1 implements the chart variant as a \"rels-only\"\n// reference (the full ChartML model lands in later iterations); picture / shape\n// / connector / group are reserved for later.\n\nimport type { ChartSpace } from '../chart/chart';\nimport type { CxChartSpace } from '../chart/cx/chartex';\nimport type { DrawingAnchor } from './anchor';\nimport type { ShapeProperties } from './dml/shape-properties';\nimport type { XlsxImage } from './image';\n\n/** Reference to a chart part — the chart's drawing-rels rId resolves to xl/charts/chartN.xml. */\nexport interface ChartReference {\n /** Drawing-rels rId pointing at the chart part. Populated on read; the writer assigns its own. */\n rId?: string;\n /**\n * Legacy ECMA-376 chart payload (`c:chartSpace`). Stage-1 supports BarChart\n * end-to-end; other chart kinds populate this field as their parsers /\n * writers land.\n */\n space?: ChartSpace;\n /**\n * Excel-2016 chartex payload (`cx:chartSpace`). Mutually exclusive with\n * {@link space} for any given drawing item; the parser sniffs the root\n * element and populates whichever is appropriate.\n */\n cxSpace?: CxChartSpace;\n /**\n * `true` when the resolved chart part is a chartex (`cx:`) chart. Set by the\n * package writer so the drawing emitter knows to use the chartex\n * `<a:graphicData uri>` instead of the legacy chart URI — Excel rejects the\n * workbook when the URI doesn't match the chart's actual root namespace.\n */\n isCx?: boolean;\n}\n\n/** Reference to an embedded picture inside a worksheet drawing. */\nexport interface PictureReference {\n /** Drawing-rels rId pointing at the embedded image. Populated on read; the writer assigns its own. */\n rId?: string;\n /** Resolved image bytes + metadata. Populated on read; the writer reads it back. */\n image?: XlsxImage;\n /** Picture display name (`<xdr:cNvPr name=\"...\">`). */\n name?: string;\n /** Optional alt-text description. */\n descr?: string;\n /** Hidden flag (`<xdr:cNvPr hidden=\"1\"/>`). */\n hidden?: boolean;\n /** Per-picture shape properties (extra fill / line / rotation). */\n spPr?: ShapeProperties;\n}\n\nexport interface DrawingItem {\n anchor: DrawingAnchor;\n content:\n | { kind: 'chart'; chart: ChartReference }\n | { kind: 'picture'; picture: PictureReference }\n | { kind: 'unsupported'; rawTag: string };\n}\n\nexport interface Drawing {\n items: DrawingItem[];\n}\n\nexport function makeDrawing(items: DrawingItem[] = []): Drawing {\n return { items };\n}\n\nexport function makeChartDrawingItem(anchor: DrawingAnchor, chart: ChartReference = {}): DrawingItem {\n return { anchor, content: { kind: 'chart', chart } };\n}\n\nexport function makePictureDrawingItem(anchor: DrawingAnchor, picture: PictureReference | XlsxImage): DrawingItem {\n // Distinguish raw image bytes from a full PictureReference by checking the\n // discriminator: XlsxImage carries `format`, PictureReference doesn't.\n const ref: PictureReference = 'format' in picture ? { image: picture as XlsxImage } : (picture as PictureReference);\n return { anchor, content: { kind: 'picture', picture: ref } };\n}\n\n// ---- Worksheet ergonomic helpers ----------------------------------------\n\nimport { loadImage } from './image';\nimport { makeOneCellAnchor } from './anchor';\nimport type { Worksheet } from '../worksheet/worksheet';\n\n/**\n * Drop an image onto a worksheet at a single-cell anchor. Lazy-allocates\n * `ws.drawing` (as `makeDrawing([])`) on first call and appends a picture\n * DrawingItem.\n *\n * `image` accepts either an `XlsxImage` (already loaded via `loadImage`) or raw\n * image bytes — in the bytes case, this helper sniffs the format with\n * `loadImage` itself.\n *\n * `at` is a cell ref like `\"C3\"`. Override `widthPx` / `heightPx` to scale;\n * otherwise the helper uses 96×96 defaults that look fine for typical icons.\n */\nexport const addImageAt = (\n ws: Worksheet,\n at: string,\n image: XlsxImage | Uint8Array,\n opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n const xlsxImage: XlsxImage = image instanceof Uint8Array ? loadImage(image) : image;\n const anchor = makeOneCellAnchor({\n from: at,\n widthPx: opts.widthPx ?? 96,\n heightPx: opts.heightPx ?? 96,\n });\n const item = makePictureDrawingItem(anchor, xlsxImage);\n if (!ws.drawing) ws.drawing = makeDrawing([]);\n ws.drawing.items.push(item);\n return item;\n};\n\n/**\n * Anchor a chart to a worksheet at a single-cell ref. Lazy-allocates\n * `ws.drawing`. `chart` is the same `ChartReference` shape `makeChart\n * DrawingItem` accepts (`{ space }` for legacy chart, `{ cxSpace }` for\n * chartex).\n */\nexport const addChartAt = (\n ws: Worksheet,\n at: string,\n chart: ChartReference,\n opts: { widthPx?: number; heightPx?: number } = {},\n): DrawingItem => {\n const anchor = makeOneCellAnchor({\n from: at,\n widthPx: opts.widthPx ?? 480,\n heightPx: opts.heightPx ?? 320,\n });\n const item = makeChartDrawingItem(anchor, chart);\n if (!ws.drawing) ws.drawing = makeDrawing([]);\n ws.drawing.items.push(item);\n return item;\n};\n\n/**\n * Read-only snapshot of every picture DrawingItem on the sheet. Returns the\n * matching items (each with its anchor + picture reference). Empty array when\n * the sheet has no drawing or only non-picture items.\n */\nexport const listImagesOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n if (!ws.drawing) return [];\n return ws.drawing.items.filter((it) => it.content.kind === 'picture');\n};\n\n/**\n * Read-only snapshot of every chart DrawingItem on the sheet. Each item has its\n * anchor + chart reference.\n */\nexport const listChartsOnSheet = (ws: Worksheet): ReadonlyArray<DrawingItem> => {\n if (!ws.drawing) return [];\n return ws.drawing.items.filter((it) => it.content.kind === 'chart');\n};\n\n/**\n * Drop every DrawingItem from the worksheet. Returns the count removed. The\n * `ws.drawing` field itself is left in place (empty) so subsequent `addImageAt`\n * / `addChartAt` calls don't have to re-allocate.\n */\nexport const removeAllDrawingItems = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const n = ws.drawing.items.length;\n ws.drawing.items = [];\n return n;\n};\n\n/**\n * Drop every picture DrawingItem from the worksheet, leaving charts and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllImages = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const before = ws.drawing.items.length;\n ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'picture');\n return before - ws.drawing.items.length;\n};\n\n/**\n * Drop every chart DrawingItem from the worksheet, leaving pictures and any\n * other content kinds untouched. Returns the count removed.\n */\nexport const removeAllCharts = (ws: Worksheet): number => {\n if (!ws.drawing) return 0;\n const before = ws.drawing.items.length;\n ws.drawing.items = ws.drawing.items.filter((it) => it.content.kind !== 'chart');\n return before - ws.drawing.items.length;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"escape-DFTE7ZJc.mjs","names":[],"sources":["../src/utils/escape.ts"],"sourcesContent":["// XML 1.0 cell-string escaping. Mirrors openpyxl/openpyxl/utils/escape.py.\n//\n// Excel emits cell strings with control characters and other illegal\n// XML 1.0 codepoints encoded as `_xHHHH_` (uppercase hex). The\n// underscore itself is a literal in normal text but a sequence opener\n// in escape position; an existing `_xHHHH_` in the input is therefore\n// re-escaped to `_x005F_xHHHH_` so it round-trips losslessly.\n\n// Escape every C0 control character (U+0000 through U+001F) plus the\n// surrogate range U+D800–U+DFFF. NUL is invalid in XML 1.0 entirely.\n// This range deliberately covers `\\t` (U+0009), `\\n` (U+000A) and `\\r`\n// (U+000D) even though XML 1.0 considers them legal whitespace — XML\n// parsers normalise CRLF / lone CR to LF on read, so a cell string\n// containing `\\r` would silently lose its CR without the `_x000D_`\n// encoding. openpyxl escapes the same `\\x01-\\x19` range; we add NUL\n// to keep the writer well-formed when callers feed in binary data.\nconst ILLEGAL_RE =\n // biome-ignore lint/suspicious/noControlCharactersInRegex: by design — these are the codepoints we replace\n /[\\x00-\\x1F\\ud800-\\udfff]/g;\nconst ESCAPED_PATTERN_RE = /(_)(x[0-9A-Fa-f]{4}_)/g;\n\nconst toHex4 = (n: number): string => n.toString(16).toUpperCase().padStart(4, '0');\n\n/**\n * Escape a string for safe storage in an OOXML cell. Already-escaped\n * sequences (`_xHHHH_`) are protected by escaping their leading\n * underscore; illegal codepoints are replaced with their `_xHHHH_`\n * representation.\n */\nexport function escapeCellString(s: string): string {\n // Re-escape any existing `_xHHHH_` so it round-trips; the underscore\n // becomes `_x005F_` and the rest of the sequence is left as-is.\n const protectedString = s.replace(ESCAPED_PATTERN_RE, '_x005F_$2');\n return protectedString.replace(ILLEGAL_RE, (ch) => `_x${toHex4(ch.charCodeAt(0))}_`);\n}\n\nconst UNESCAPE_RE = /_x([0-9A-Fa-f]{4})_/g;\n\n/**\n * Inverse of {@link escapeCellString}. Looking from left to right\n * we replace any `_xHHHH_` sequence with the corresponding code unit;\n * the protected `_x005F_` becomes a literal underscore which the\n * subsequent replacements skip safely (replace's regex is non-overlapping).\n */\nexport function unescapeCellString(s: string): string {\n return s.replace(UNESCAPE_RE, (_full, hex: string) => String.fromCharCode(Number.parseInt(hex, 16)));\n}\n\n// ---- XML escape helpers ----------------------------------------------------\n//\n// One canonical implementation for text-node and attribute escaping. The\n// previous codebase carried three near-identical copies (one each in save.ts,\n// xml/serializer.ts, xml/stream-writer.ts); they disagreed about `>`-in-attribute\n// handling and would have drifted further apart over time. Keeping them in a\n// single place also makes future fixes (e.g. surrogate-pair scrubbing) land\n// once rather than three times.\n\n/**\n * Escape a string for safe placement in an XML text node. Replaces the three\n * codepoints that would otherwise terminate the text region or open a markup\n * sequence (`&`, `<`, `>`); `\"` and `'` are not legal markup terminators\n * inside text and stay verbatim.\n */\nexport function escapeXmlText(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n/**\n * Escape a string for safe placement inside a `\"`-quoted XML attribute.\n * Handles `&`, `<`, `>` and the `\"` that would otherwise close the value.\n *\n * Note: this deliberately does NOT escape `\\r` / `\\n` / `\\t` to numeric\n * character references. XML 1.0 attribute-value normalisation would\n * collapse them to spaces in theory, but the parser used on the read side\n * (fast-xml-parser) does not decode numeric character references, so a\n * write-then-read round-trip would surface the literal `	` instead of\n * recovering the original tab. Leaving the whitespace bytes literal keeps\n * the round-trip stable and matches what Excel itself emits.\n */\nexport function escapeXmlAttr(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n"],"mappings":";AAgBA,MAAM,aAEJ;AACF,MAAM,qBAAqB;AAE3B,MAAM,UAAU,MAAsB,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"escape-DFTE7ZJc.mjs","names":[],"sources":["../src/utils/escape.ts"],"sourcesContent":["// XML 1.0 cell-string escaping. Mirrors openpyxl/openpyxl/utils/escape.py.\n//\n// Excel emits cell strings with control characters and other illegal\n// XML 1.0 codepoints encoded as `_xHHHH_` (uppercase hex). The\n// underscore itself is a literal in normal text but a sequence opener\n// in escape position; an existing `_xHHHH_` in the input is therefore\n// re-escaped to `_x005F_xHHHH_` so it round-trips losslessly.\n\n// Escape every C0 control character (U+0000 through U+001F) plus the\n// surrogate range U+D800–U+DFFF. NUL is invalid in XML 1.0 entirely.\n// This range deliberately covers `\\t` (U+0009), `\\n` (U+000A) and `\\r`\n// (U+000D) even though XML 1.0 considers them legal whitespace — XML\n// parsers normalise CRLF / lone CR to LF on read, so a cell string\n// containing `\\r` would silently lose its CR without the `_x000D_`\n// encoding. openpyxl escapes the same `\\x01-\\x19` range; we add NUL\n// to keep the writer well-formed when callers feed in binary data.\nconst ILLEGAL_RE =\n // biome-ignore lint/suspicious/noControlCharactersInRegex: by design — these are the codepoints we replace\n /[\\x00-\\x1F\\ud800-\\udfff]/g;\nconst ESCAPED_PATTERN_RE = /(_)(x[0-9A-Fa-f]{4}_)/g;\n\nconst toHex4 = (n: number): string => n.toString(16).toUpperCase().padStart(4, '0');\n\n/**\n * Escape a string for safe storage in an OOXML cell. Already-escaped\n * sequences (`_xHHHH_`) are protected by escaping their leading\n * underscore; illegal codepoints are replaced with their `_xHHHH_`\n * representation.\n */\nexport function escapeCellString(s: string): string {\n // Re-escape any existing `_xHHHH_` so it round-trips; the underscore\n // becomes `_x005F_` and the rest of the sequence is left as-is.\n const protectedString = s.replace(ESCAPED_PATTERN_RE, '_x005F_$2');\n return protectedString.replace(ILLEGAL_RE, (ch) => `_x${toHex4(ch.charCodeAt(0))}_`);\n}\n\nconst UNESCAPE_RE = /_x([0-9A-Fa-f]{4})_/g;\n\n/**\n * Inverse of {@link escapeCellString}. Looking from left to right\n * we replace any `_xHHHH_` sequence with the corresponding code unit;\n * the protected `_x005F_` becomes a literal underscore which the\n * subsequent replacements skip safely (replace's regex is non-overlapping).\n */\nexport function unescapeCellString(s: string): string {\n return s.replace(UNESCAPE_RE, (_full, hex: string) => String.fromCharCode(Number.parseInt(hex, 16)));\n}\n\n// ---- XML escape helpers ----------------------------------------------------\n//\n// One canonical implementation for text-node and attribute escaping. The\n// previous codebase carried three near-identical copies (one each in save.ts,\n// xml/serializer.ts, xml/stream-writer.ts); they disagreed about `>`-in-attribute\n// handling and would have drifted further apart over time. Keeping them in a\n// single place also makes future fixes (e.g. surrogate-pair scrubbing) land\n// once rather than three times.\n\n/**\n * Escape a string for safe placement in an XML text node. Replaces the three\n * codepoints that would otherwise terminate the text region or open a markup\n * sequence (`&`, `<`, `>`); `\"` and `'` are not legal markup terminators\n * inside text and stay verbatim.\n */\nexport function escapeXmlText(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n/**\n * Escape a string for safe placement inside a `\"`-quoted XML attribute.\n * Handles `&`, `<`, `>` and the `\"` that would otherwise close the value.\n *\n * Note: this deliberately does NOT escape `\\r` / `\\n` / `\\t` to numeric\n * character references. XML 1.0 attribute-value normalisation would\n * collapse them to spaces in theory, but the parser used on the read side\n * (fast-xml-parser) does not decode numeric character references, so a\n * write-then-read round-trip would surface the literal `	` instead of\n * recovering the original tab. Leaving the whitespace bytes literal keeps\n * the round-trip stable and matches what Excel itself emits.\n */\nexport function escapeXmlAttr(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n"],"mappings":";AAgBA,MAAM,aAEJ;AACF,MAAM,qBAAqB;AAE3B,MAAM,UAAU,MAAsB,EAAE,SAAS,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,GAAG,GAAG;;;;;;;AAQlF,SAAgB,iBAAiB,GAAmB;CAIlD,OADwB,EAAE,QAAQ,oBAAoB,WACjC,CAAC,CAAC,QAAQ,aAAa,OAAO,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,EAAE,EAAE;AACrF;AAEA,MAAM,cAAc;;;;;;;AAQpB,SAAgB,mBAAmB,GAAmB;CACpD,OAAO,EAAE,QAAQ,cAAc,OAAO,QAAgB,OAAO,aAAa,OAAO,SAAS,KAAK,EAAE,CAAC,CAAC;AACrG;;;;;;;AAiBA,SAAgB,cAAc,GAAmB;CAC/C,OAAO,EAAE,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;AAC5E;;;;;;;;;;;;;AAcA,SAAgB,cAAc,GAAmB;CAC/C,OAAO,EACJ,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,QAAQ;AAC3B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/utils/inference.ts
|
|
2
2
|
/** Excel error tokens. Anything outside this set is treated as a string. */
|
|
3
|
-
const ERROR_CODES = new Set([
|
|
3
|
+
const ERROR_CODES = /* @__PURE__ */ new Set([
|
|
4
4
|
"#NULL!",
|
|
5
5
|
"#DIV/0!",
|
|
6
6
|
"#VALUE!",
|
|
@@ -39,4 +39,4 @@ function inferCellType(value) {
|
|
|
39
39
|
//#endregion
|
|
40
40
|
export { inferCellType as n, ERROR_CODES as t };
|
|
41
41
|
|
|
42
|
-
//# sourceMappingURL=inference-
|
|
42
|
+
//# sourceMappingURL=inference-BrI9uIY4.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inference-
|
|
1
|
+
{"version":3,"file":"inference-BrI9uIY4.mjs","names":[],"sources":["../src/utils/inference.ts"],"sourcesContent":["// Cell-value type inference. Maps a JS runtime value to the OOXML cell\n// `t` attribute value. Mirrors openpyxl's `Cell._bind_value` /\n// `_TYPES` / error-code path in openpyxl/openpyxl/cell/cell.py.\n\n/**\n * OOXML `t` attribute values. Note that 'inlineStr' is treated\n * separately — the writer chooses between 's' (shared string) and\n * 'inlineStr' based on workbook settings, not the value itself.\n */\nexport type CellDataType = 'n' | 's' | 'b' | 'd' | 'f' | 'e';\n\n/** Excel error tokens. Anything outside this set is treated as a string. */\nexport const ERROR_CODES: ReadonlySet<string> = new Set([\n '#NULL!',\n '#DIV/0!',\n '#VALUE!',\n '#REF!',\n '#NAME?',\n '#NUM!',\n '#N/A',\n '#GETTING_DATA',\n]);\n\n/**\n * Infer the cell `t` attribute for a runtime value.\n *\n * - `boolean` → 'b'\n * - `number` → 'n' (incl. integer numerics; date inference is left to\n * the caller because Excel decides on type via the cell's number\n * format, not the raw value)\n * - `Date` → 'd'\n * - string starting with `=` → 'f' (formula)\n * - string in {@link ERROR_CODES} → 'e'\n * - any other string → 's'\n * - `null` / `undefined` → 'n' (empty)\n *\n * Throws nothing — returns 'n' as the no-information fallback.\n */\nexport function inferCellType(value: unknown): CellDataType {\n if (typeof value === 'boolean') return 'b';\n if (typeof value === 'number') return 'n';\n if (value instanceof Date) return 'd';\n if (typeof value === 'string') {\n if (value.length > 0 && value.charCodeAt(0) === 61 /* '=' */) return 'f';\n if (ERROR_CODES.has(value)) return 'e';\n return 's';\n }\n return 'n';\n}\n"],"mappings":";;AAYA,MAAa,8BAAmC,IAAI,IAAI;CACtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;;;;;AAiBD,SAAgB,cAAc,OAA8B;CAC1D,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,iBAAiB,MAAM,OAAO;CAClC,IAAI,OAAO,UAAU,UAAU;EAC7B,IAAI,MAAM,SAAS,KAAK,MAAM,WAAW,CAAC,MAAM,IAAc,OAAO;EACrE,IAAI,YAAY,IAAI,KAAK,GAAG,OAAO;EACnC,OAAO;CACT;CACA,OAAO;AACT"}
|
package/dist/io.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as OpenXmlIoError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
|
-
import { t as loadWorkbook } from "./load-
|
|
3
|
-
import { n as workbookToBytes, t as saveWorkbook } from "./save-
|
|
2
|
+
import { t as loadWorkbook } from "./load-BG5-CtPk.mjs";
|
|
3
|
+
import { n as workbookToBytes, t as saveWorkbook } from "./save-BcpDpE90.mjs";
|
|
4
4
|
//#region src/io/browser.ts
|
|
5
5
|
/**
|
|
6
6
|
* Wrap a Blob (or File, since File extends Blob) as an XlsxSource. The
|
|
@@ -159,7 +159,7 @@ function toBlob(mime = "application/octet-stream") {
|
|
|
159
159
|
},
|
|
160
160
|
abort() {
|
|
161
161
|
if (finalised !== void 0) return;
|
|
162
|
-
finalised = new Uint8Array(0);
|
|
162
|
+
finalised = /* @__PURE__ */ new Uint8Array(0);
|
|
163
163
|
chunks.length = 0;
|
|
164
164
|
}
|
|
165
165
|
};
|
|
@@ -193,7 +193,7 @@ function toArrayBuffer() {
|
|
|
193
193
|
},
|
|
194
194
|
abort() {
|
|
195
195
|
if (finalised !== void 0) return;
|
|
196
|
-
finalised = new Uint8Array(0);
|
|
196
|
+
finalised = /* @__PURE__ */ new Uint8Array(0);
|
|
197
197
|
chunks.length = 0;
|
|
198
198
|
}
|
|
199
199
|
};
|
package/dist/io.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"io.mjs","names":[],"sources":["../src/io/browser.ts"],"sourcesContent":["// Browser-target I/O helpers. Phase-1 §1: synchronous in-memory paths.\n// Response / streaming-WritableStream bridges land alongside the\n// streaming ZIP work in §2.\n//\n// Node 18+ provides Blob / File / FormData / fetch / Web Streams natively,\n// so this module is also exercised by the Node-hosted vitest runner.\n\nimport { OpenXmlIoError } from '../utils/exceptions';\nimport type { BufferedSinkWriter, XlsxSink } from './sink';\nimport type { XlsxSource } from './source';\n\n/**\n * Wrap a Blob (or File, since File extends Blob) as an XlsxSource. The\n * source materialises bytes lazily on the first {@link XlsxSource.toBytes}\n * call.\n */\nexport function fromBlob(blob: Blob): XlsxSource {\n if (!(blob instanceof Blob)) {\n throw new OpenXmlIoError('fromBlob expects a Blob (or File)');\n }\n return {\n async toBytes() {\n try {\n const ab = await blob.arrayBuffer();\n return new Uint8Array(ab);\n } catch (cause) {\n throw new OpenXmlIoError('fromBlob: failed to read blob contents', { cause });\n }\n },\n toStream() {\n return blob.stream();\n },\n };\n}\n\n/**\n * Wrap a fetch {@link Response} as an XlsxSource. `toBytes` collects\n * the entire response body via `Response.arrayBuffer()`; `toStream`\n * returns `response.body` directly so the ZIP reader can pull chunks\n * lazily from the network. The Response can have been fetched with\n * any method and content-type; this helper does no validation.\n */\nexport function fromResponse(response: Response): XlsxSource {\n if (!(response instanceof Response)) {\n throw new OpenXmlIoError('fromResponse expects a fetch Response');\n }\n let bytes: Promise<Uint8Array> | undefined;\n return {\n async toBytes() {\n if (bytes) return bytes;\n bytes = (async () => {\n try {\n return new Uint8Array(await response.arrayBuffer());\n } catch (cause) {\n throw new OpenXmlIoError('fromResponse: failed to read response body', { cause });\n }\n })();\n return bytes;\n },\n toStream() {\n const body = response.body;\n if (!body) {\n // Bodyless responses (HEAD / 204 / 304) — return an empty stream.\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.close();\n },\n });\n }\n return body;\n },\n };\n}\n\n/**\n * Wrap a Web {@link ReadableStream} of bytes as an XlsxSource. `toStream`\n * returns the stream directly; `toBytes` drains it once and caches the\n * bytes. Streams can only be consumed once — calling `toBytes` after\n * `toStream` (or vice versa) on the same source throws.\n */\nexport function fromStream(stream: ReadableStream<Uint8Array>): XlsxSource {\n if (!(stream instanceof ReadableStream)) {\n throw new OpenXmlIoError('fromStream expects a ReadableStream<Uint8Array>');\n }\n let consumed = false;\n let bytes: Promise<Uint8Array> | undefined;\n return {\n async toBytes() {\n if (bytes) return bytes;\n if (consumed) {\n throw new OpenXmlIoError('fromStream: stream already consumed via toStream()');\n }\n consumed = true;\n bytes = (async () => {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\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 return out;\n })();\n return bytes;\n },\n toStream() {\n if (bytes) {\n throw new OpenXmlIoError('fromStream: bytes already consumed via toBytes()');\n }\n if (consumed) {\n throw new OpenXmlIoError('fromStream: stream already consumed');\n }\n consumed = true;\n return stream;\n },\n };\n}\n\n/**\n * Wrap an ArrayBuffer or Uint8Array. The bytes are referenced (Uint8Array\n * input) or wrapped without copy (ArrayBuffer input).\n */\nexport function fromArrayBuffer(buf: ArrayBuffer | Uint8Array): XlsxSource {\n let bytes: Uint8Array;\n if (buf instanceof Uint8Array) {\n bytes = buf;\n } else if (buf instanceof ArrayBuffer) {\n bytes = new Uint8Array(buf);\n } else {\n throw new OpenXmlIoError('fromArrayBuffer expects an ArrayBuffer or Uint8Array');\n }\n return {\n async toBytes() {\n return bytes;\n },\n toStream() {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(bytes);\n controller.close();\n },\n });\n },\n };\n}\n\nconst collectChunks = (chunks: Uint8Array[]): Uint8Array => {\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 return out;\n};\n\n/**\n * In-memory Blob sink. Convenience `result()` returns the accumulated\n * payload as a Blob with the supplied MIME type.\n */\nexport function toBlob(\n mime: string = 'application/octet-stream',\n): XlsxSink & { toBytes(): BufferedSinkWriter; result(): Blob } {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n finalised = collectChunks(chunks);\n chunks.length = 0;\n return finalised;\n };\n\n return {\n toBytes(): BufferedSinkWriter {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) throw new OpenXmlIoError('toBlob sink: write after finish');\n if (!(chunk instanceof Uint8Array)) throw new OpenXmlIoError('toBlob sink: chunk is not a Uint8Array');\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(): Blob {\n // Copy the bytes' typed-array view into a fresh Blob to detach from\n // the writer's internal buffer.\n const bytes = finalise();\n return new Blob([bytes.slice()], { type: mime });\n },\n };\n}\n\n/** In-memory ArrayBuffer sink. */\nexport function toArrayBuffer(): XlsxSink & { toBytes(): BufferedSinkWriter; result(): ArrayBuffer } {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n finalised = collectChunks(chunks);\n chunks.length = 0;\n return finalised;\n };\n\n return {\n toBytes(): BufferedSinkWriter {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) throw new OpenXmlIoError('toArrayBuffer sink: write after finish');\n if (!(chunk instanceof Uint8Array)) throw new OpenXmlIoError('toArrayBuffer sink: chunk is not a Uint8Array');\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(): ArrayBuffer {\n const bytes = finalise();\n // bytes' underlying buffer may be larger than its byteLength (slice\n // semantics on Uint8Array). Materialise an exactly-sized copy.\n const out = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(out).set(bytes);\n return out;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"io.mjs","names":[],"sources":["../src/io/browser.ts"],"sourcesContent":["// Browser-target I/O helpers. Phase-1 §1: synchronous in-memory paths.\n// Response / streaming-WritableStream bridges land alongside the\n// streaming ZIP work in §2.\n//\n// Node 18+ provides Blob / File / FormData / fetch / Web Streams natively,\n// so this module is also exercised by the Node-hosted vitest runner.\n\nimport { OpenXmlIoError } from '../utils/exceptions';\nimport type { BufferedSinkWriter, XlsxSink } from './sink';\nimport type { XlsxSource } from './source';\n\n/**\n * Wrap a Blob (or File, since File extends Blob) as an XlsxSource. The\n * source materialises bytes lazily on the first {@link XlsxSource.toBytes}\n * call.\n */\nexport function fromBlob(blob: Blob): XlsxSource {\n if (!(blob instanceof Blob)) {\n throw new OpenXmlIoError('fromBlob expects a Blob (or File)');\n }\n return {\n async toBytes() {\n try {\n const ab = await blob.arrayBuffer();\n return new Uint8Array(ab);\n } catch (cause) {\n throw new OpenXmlIoError('fromBlob: failed to read blob contents', { cause });\n }\n },\n toStream() {\n return blob.stream();\n },\n };\n}\n\n/**\n * Wrap a fetch {@link Response} as an XlsxSource. `toBytes` collects\n * the entire response body via `Response.arrayBuffer()`; `toStream`\n * returns `response.body` directly so the ZIP reader can pull chunks\n * lazily from the network. The Response can have been fetched with\n * any method and content-type; this helper does no validation.\n */\nexport function fromResponse(response: Response): XlsxSource {\n if (!(response instanceof Response)) {\n throw new OpenXmlIoError('fromResponse expects a fetch Response');\n }\n let bytes: Promise<Uint8Array> | undefined;\n return {\n async toBytes() {\n if (bytes) return bytes;\n bytes = (async () => {\n try {\n return new Uint8Array(await response.arrayBuffer());\n } catch (cause) {\n throw new OpenXmlIoError('fromResponse: failed to read response body', { cause });\n }\n })();\n return bytes;\n },\n toStream() {\n const body = response.body;\n if (!body) {\n // Bodyless responses (HEAD / 204 / 304) — return an empty stream.\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.close();\n },\n });\n }\n return body;\n },\n };\n}\n\n/**\n * Wrap a Web {@link ReadableStream} of bytes as an XlsxSource. `toStream`\n * returns the stream directly; `toBytes` drains it once and caches the\n * bytes. Streams can only be consumed once — calling `toBytes` after\n * `toStream` (or vice versa) on the same source throws.\n */\nexport function fromStream(stream: ReadableStream<Uint8Array>): XlsxSource {\n if (!(stream instanceof ReadableStream)) {\n throw new OpenXmlIoError('fromStream expects a ReadableStream<Uint8Array>');\n }\n let consumed = false;\n let bytes: Promise<Uint8Array> | undefined;\n return {\n async toBytes() {\n if (bytes) return bytes;\n if (consumed) {\n throw new OpenXmlIoError('fromStream: stream already consumed via toStream()');\n }\n consumed = true;\n bytes = (async () => {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\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 return out;\n })();\n return bytes;\n },\n toStream() {\n if (bytes) {\n throw new OpenXmlIoError('fromStream: bytes already consumed via toBytes()');\n }\n if (consumed) {\n throw new OpenXmlIoError('fromStream: stream already consumed');\n }\n consumed = true;\n return stream;\n },\n };\n}\n\n/**\n * Wrap an ArrayBuffer or Uint8Array. The bytes are referenced (Uint8Array\n * input) or wrapped without copy (ArrayBuffer input).\n */\nexport function fromArrayBuffer(buf: ArrayBuffer | Uint8Array): XlsxSource {\n let bytes: Uint8Array;\n if (buf instanceof Uint8Array) {\n bytes = buf;\n } else if (buf instanceof ArrayBuffer) {\n bytes = new Uint8Array(buf);\n } else {\n throw new OpenXmlIoError('fromArrayBuffer expects an ArrayBuffer or Uint8Array');\n }\n return {\n async toBytes() {\n return bytes;\n },\n toStream() {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(bytes);\n controller.close();\n },\n });\n },\n };\n}\n\nconst collectChunks = (chunks: Uint8Array[]): Uint8Array => {\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 return out;\n};\n\n/**\n * In-memory Blob sink. Convenience `result()` returns the accumulated\n * payload as a Blob with the supplied MIME type.\n */\nexport function toBlob(\n mime: string = 'application/octet-stream',\n): XlsxSink & { toBytes(): BufferedSinkWriter; result(): Blob } {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n finalised = collectChunks(chunks);\n chunks.length = 0;\n return finalised;\n };\n\n return {\n toBytes(): BufferedSinkWriter {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) throw new OpenXmlIoError('toBlob sink: write after finish');\n if (!(chunk instanceof Uint8Array)) throw new OpenXmlIoError('toBlob sink: chunk is not a Uint8Array');\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(): Blob {\n // Copy the bytes' typed-array view into a fresh Blob to detach from\n // the writer's internal buffer.\n const bytes = finalise();\n return new Blob([bytes.slice()], { type: mime });\n },\n };\n}\n\n/** In-memory ArrayBuffer sink. */\nexport function toArrayBuffer(): XlsxSink & { toBytes(): BufferedSinkWriter; result(): ArrayBuffer } {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n finalised = collectChunks(chunks);\n chunks.length = 0;\n return finalised;\n };\n\n return {\n toBytes(): BufferedSinkWriter {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) throw new OpenXmlIoError('toArrayBuffer sink: write after finish');\n if (!(chunk instanceof Uint8Array)) throw new OpenXmlIoError('toArrayBuffer sink: chunk is not a Uint8Array');\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(): ArrayBuffer {\n const bytes = finalise();\n // bytes' underlying buffer may be larger than its byteLength (slice\n // semantics on Uint8Array). Materialise an exactly-sized copy.\n const out = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(out).set(bytes);\n return out;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
2
|
import { h as loadImage } from "./drawing-BxzLuryn.mjs";
|
|
3
3
|
import { At as parseQName, a as findChildren, c as ARC_CONTENT_TYPES, f as ARC_ROOT_RELS, ft as SHEET_MAIN_NS, g as ARC_WORKBOOK, h as ARC_THEME, i as findChild, jt as qname, l as ARC_CORE, lt as REL_NS, m as ARC_STYLE, p as ARC_SHARED_STRINGS, s as ARC_APP, u as ARC_CUSTOM } from "./tree-Bbs1C8Rc.mjs";
|
|
4
|
-
import { C as isChartExBytes, D as parseChartXml, E as findUserShapesRId, a as parseCommentsXml, b as parseUserShapesXml, c as NumberFormatSchema, d as BorderSchema, f as AlignmentSchema, g as parseChartsheetXml, l as FontSchema, m as parseDrawingXml, n as parseTableXml, s as ProtectionSchema, u as fillFromTree, w as parseChartExXml, y as parseWorksheetXml } from "./stylesheet-writer-
|
|
5
|
-
import { t as parseXml } from "./parser-
|
|
4
|
+
import { C as isChartExBytes, D as parseChartXml, E as findUserShapesRId, a as parseCommentsXml, b as parseUserShapesXml, c as NumberFormatSchema, d as BorderSchema, f as AlignmentSchema, g as parseChartsheetXml, l as FontSchema, m as parseDrawingXml, n as parseTableXml, s as ProtectionSchema, u as fillFromTree, w as parseChartExXml, y as parseWorksheetXml } from "./stylesheet-writer-P1Hxoqzm.mjs";
|
|
5
|
+
import { t as parseXml } from "./parser-nk0Lqmcb.mjs";
|
|
6
6
|
import { t as fromTree } from "./serialize-55EnT30e.mjs";
|
|
7
|
-
import { B as corePropsFromBytes, Q as findById, _ as customPropsFromBytes, c as extendedPropsFromBytes, et as indexRelsById, nt as relsFromBytes, o as manifestFromBytes } from "./manifest-
|
|
8
|
-
import { D as parseSharedStringsXml, r as createWorkbook } from "./workbook-
|
|
9
|
-
import { Zt as stableStringify, ft as makeStylesheet } from "./cell-style-
|
|
7
|
+
import { B as corePropsFromBytes, Q as findById, _ as customPropsFromBytes, c as extendedPropsFromBytes, et as indexRelsById, nt as relsFromBytes, o as manifestFromBytes } from "./manifest-CVL1_t0O.mjs";
|
|
8
|
+
import { D as parseSharedStringsXml, r as createWorkbook } from "./workbook-T1Y3lstQ.mjs";
|
|
9
|
+
import { Zt as stableStringify, ft as makeStylesheet } from "./cell-style-CN9JXOwm.mjs";
|
|
10
10
|
import { a as makeDefinedName } from "./defined-names-CviWmtQg.mjs";
|
|
11
|
-
import { t as openZip } from "./reader-
|
|
11
|
+
import { t as openZip } from "./reader-BNaUTVCy.mjs";
|
|
12
12
|
//#region src/styles/stylesheet-reader.ts
|
|
13
13
|
const STYLESHEET_TAG = qname(SHEET_MAIN_NS, "styleSheet");
|
|
14
14
|
const FONTS_TAG = qname(SHEET_MAIN_NS, "fonts");
|
|
@@ -489,7 +489,7 @@ function loadWorkbookFromArchive(archive) {
|
|
|
489
489
|
capturePassthrough(archive, manifest, wb);
|
|
490
490
|
return wb;
|
|
491
491
|
}
|
|
492
|
-
const SHEET_MODELED_REL_TYPES = new Set([
|
|
492
|
+
const SHEET_MODELED_REL_TYPES = /* @__PURE__ */ new Set([
|
|
493
493
|
`${REL_NS}/hyperlink`,
|
|
494
494
|
`${REL_NS}/table`,
|
|
495
495
|
`${REL_NS}/comments`,
|
|
@@ -936,7 +936,7 @@ const parseWorkbookProtection = (node) => {
|
|
|
936
936
|
* allocated ones.
|
|
937
937
|
*/
|
|
938
938
|
function captureWorkbookRelsExtras(wbRels, wb) {
|
|
939
|
-
const SHEET_RELS = new Set([`${REL_NS}/worksheet`, `${REL_NS}/chartsheet`]);
|
|
939
|
+
const SHEET_RELS = /* @__PURE__ */ new Set([`${REL_NS}/worksheet`, `${REL_NS}/chartsheet`]);
|
|
940
940
|
const original = {};
|
|
941
941
|
const extras = [];
|
|
942
942
|
for (const rel of wbRels.rels) {
|
|
@@ -1017,7 +1017,7 @@ const containsCommentMarker = (bytes) => LATIN1_DECODER.decode(bytes).includes(C
|
|
|
1017
1017
|
* - `xl/metadata.xml` — Excel 365 dynamic-array cell metadata.
|
|
1018
1018
|
* - `xl/SheetMetadata.xml` — variant casing of the same.
|
|
1019
1019
|
*/
|
|
1020
|
-
const PASSTHROUGH_EXACT_PATHS = new Set([
|
|
1020
|
+
const PASSTHROUGH_EXACT_PATHS = /* @__PURE__ */ new Set([
|
|
1021
1021
|
"xl/calcChain.xml",
|
|
1022
1022
|
"xl/connections.xml",
|
|
1023
1023
|
"xl/metadata.xml",
|
|
@@ -1066,4 +1066,4 @@ function capturePassthrough(archive, manifest, wb) {
|
|
|
1066
1066
|
//#endregion
|
|
1067
1067
|
export { resolveRelTarget as n, parseStylesheetXml as r, loadWorkbook as t };
|
|
1068
1068
|
|
|
1069
|
-
//# sourceMappingURL=load-
|
|
1069
|
+
//# sourceMappingURL=load-BG5-CtPk.mjs.map
|