@4399ywkf/editor 0.8.1 → 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.
Files changed (43) hide show
  1. package/README.md +45 -27
  2. package/dist/SheetView-YFK7BUS5.js +3 -0
  3. package/dist/{SheetView-SDBRSTVS.js.map → SheetView-YFK7BUS5.js.map} +1 -1
  4. package/dist/{chunk-KRP5V7VF.js → chunk-2DI4FJPC.js} +10 -3
  5. package/dist/chunk-2DI4FJPC.js.map +1 -0
  6. package/dist/{chunk-DGUNVCOM.js → chunk-3QTRZBIK.js} +111 -26
  7. package/dist/chunk-3QTRZBIK.js.map +1 -0
  8. package/dist/chunk-JWHQF2CZ.js +257 -0
  9. package/dist/chunk-JWHQF2CZ.js.map +1 -0
  10. package/dist/{chunk-WF7PIIFR.js → chunk-JZ67Q3QI.js} +4 -4
  11. package/dist/chunk-JZ67Q3QI.js.map +1 -0
  12. package/dist/{chunk-SBTKDJAL.js → chunk-SDVGDHC4.js} +45 -3
  13. package/dist/chunk-SDVGDHC4.js.map +1 -0
  14. package/dist/{chunk-HPSPOM2O.js → chunk-XB6FEC4I.js} +3 -3
  15. package/dist/chunk-XB6FEC4I.js.map +1 -0
  16. package/dist/{csv-parse-D0zTBvDB.d.ts → csv-parse-DXlwzoZ6.d.ts} +28 -1
  17. package/dist/csv.d.ts +2 -2
  18. package/dist/csv.js +4 -4
  19. package/dist/import-O7RUERND.js +6 -0
  20. package/dist/{import-GVZDLWA2.js.map → import-O7RUERND.js.map} +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +1 -1
  23. package/dist/pdf.d.ts +1 -1
  24. package/dist/pptx.d.ts +1 -1
  25. package/dist/{registry-CYKivRDh.d.ts → registry-BQ5T1Yko.d.ts} +9 -16
  26. package/dist/sheet-runtime.d.ts +10 -8
  27. package/dist/sheet-runtime.js +6 -14
  28. package/dist/sheet-runtime.js.map +1 -1
  29. package/dist/sheet.d.ts +4 -3
  30. package/dist/sheet.js +1 -1
  31. package/dist/xlsx.d.ts +12 -11
  32. package/dist/xlsx.js +121 -32
  33. package/dist/xlsx.js.map +1 -1
  34. package/package.json +46 -2
  35. package/dist/SheetView-SDBRSTVS.js +0 -3
  36. package/dist/chunk-DGUNVCOM.js.map +0 -1
  37. package/dist/chunk-HPSPOM2O.js.map +0 -1
  38. package/dist/chunk-KRP5V7VF.js.map +0 -1
  39. package/dist/chunk-SBTKDJAL.js.map +0 -1
  40. package/dist/chunk-SYCK6Y5F.js +0 -89
  41. package/dist/chunk-SYCK6Y5F.js.map +0 -1
  42. package/dist/chunk-WF7PIIFR.js.map +0 -1
  43. package/dist/import-GVZDLWA2.js +0 -6
package/README.md CHANGED
@@ -18,7 +18,7 @@ import "@4399ywkf/editor/styles"
18
18
  | 格式 | 引擎 | 编辑 | AI 可操作 | 协同 | 依赖 |
19
19
  |---|---|---|---|---|---|
20
20
  | **doc**(含云文档) | tiptap | ✅ | ✅ | ✅ | 内置 |
21
- | **sheet** | Univer OSS 核心 | ✅ | ✅ | ✕ | 可选 peer `@univerjs/presets` |
21
+ | **sheet** | Univer 1.x OSS 核心 | ✅ | ✅ | ✕ | 可选 peer,见[表格通道配置](#表格通道配置) |
22
22
  | **pdf** | pdf.js | ✕ 只读 | ✕ | ✕ | 可选 peer `pdfjs-dist` |
23
23
  | **pptx** | pptx-preview | ✕ 只读 | ✕ | ✕ | 可选 peer `pptx-preview` |
24
24
 
@@ -97,6 +97,20 @@ const { bytes, removed } = repairPptx(new Uint8Array(await file.arrayBuffer()))
97
97
 
98
98
  ## 表格通道配置
99
99
 
100
+ ```bash
101
+ # 版本必须一致(Univer 要求所有 @univerjs/* 同版本,混装会出两份 core)
102
+ pnpm add @univerjs/presets @univerjs/preset-sheets-core @univerjs/preset-sheets-find-replace \
103
+ @univerjs/preset-sheets-filter @univerjs/preset-sheets-sort \
104
+ @univerjs/preset-sheets-data-validation @univerjs/preset-sheets-conditional-formatting \
105
+ @univerjs/preset-sheets-hyper-link @univerjs/preset-sheets-note \
106
+ @univerjs/preset-sheets-thread-comment @univerjs/preset-sheets-table \
107
+ @univerjs/preset-sheets-drawing
108
+ ```
109
+
110
+ 只要用到表格通道(`DocumentView` 主入口或 `./sheet`),这些包就都得装 ——
111
+ 引擎是动态 import 的,但打包器在构建期就要解析它,解析不到直接构建失败。
112
+ 样式随表格视图一起加载;宿主自己再 `import` 一次同一份 CSS 也不会冲突。
113
+
100
114
  Univer 的 UI 是 `univer-` 前缀的原子类,没有稳定选择器 —— **别用 CSS 硬藏工具栏**。
101
115
  开关走 `sheet` 这个 prop,直接透传到 Univer preset:
102
116
 
@@ -112,26 +126,18 @@ Univer 的 UI 是 `univer-` 前缀的原子类,没有稳定选择器 —— **
112
126
  />
113
127
  ```
114
128
 
115
- `ui` 可用:`header` / `toolbar` / `ribbonType` / `footer` / `formulaBar` / `contextMenu` /
116
- `statusBarStatistic` / `menu`。
129
+ `ui` 可用:`header` / `toolbar` / `ribbonType`(`collapsed` / `simple` / `classic` / `grid`)/
130
+ `footer` / `formulaBar` / `contextMenu` / `statusBarStatistic` / `menu`。
117
131
 
118
132
  - **`readOnly` 时 `toolbar` 默认为 `false`** —— 整条 ribbon 在只读预览里全是死按钮,
119
133
  窄面板里还挤。要它回来就显式传 `ui: { toolbar: true }`。
120
134
  - `footer` 别随手关:多工作表时它是唯一的切表入口,关掉用户就只看得见第一张表。
121
- - `findReplace` 不需要额外装包:`preset-sheets-find-replace` 是 `@univerjs/presets`
122
- 自己的 dependency,走子路径动态 import,没开就完全不下载。
123
-
124
- 其它能力(筛选、排序、条件格式、图片……)自己 import preset 传进来。
125
- `createUniver` **不会**自动收集 preset 自带的 locales,得配套传 `locales`,
126
- 否则菜单会显示成原始 i18n key:
127
-
128
- ```tsx
129
- import { UniverSheetsFilterPreset } from "@univerjs/presets/preset-sheets-filter"
130
- import zhCN from "@univerjs/presets/preset-sheets-filter/locales/zh-CN"
131
-
132
- <DocumentView format="sheet" content={snapshot}
133
- sheet={{ presets: [UniverSheetsFilterPreset()], locales: [zhCN] }} />
134
- ```
135
+ - `findReplace` 没开就完全不下载(但包还是要装,见上)。
136
+ - 筛选、排序、数据校验、条件格式、超链接、批注、评论、表格(Excel Table)和浮动图片默认就在。
137
+ 工作表背景图走的也是这套图片能力。图表、透视表不在其中。
138
+ - `sheet.presets` 用来追加别的 preset。上面这些再传一次时,同名插件以宿主那份为准。
139
+ 自带的 locale 已经合并进 zh-CN;额外 preset 仍要自己把 locale 放进 `sheet.locales`,
140
+ 否则菜单会显示成原始 i18n key。
135
141
 
136
142
  `sheet` 里的配置**只在引擎创建时读一次**,挂载后改不生效也不会重建
137
143
  (重建 = 重下引擎 + 丢掉选区和滚动位置,而宿主几乎总是传内联字面量)。要换配置请换 `key`。
@@ -164,15 +170,20 @@ const { bytes, warnings, stats } = xlsxFromSnapshot(snapshot)
164
170
  |---|---|
165
171
  | 值与类型、共享字符串、强制文本(`quotePrefix`) | ✅ |
166
172
  | 公式 + 缓存值,填充公式还原成 xlsx 的共享公式 | ✅ |
167
- | 数字格式、字体、颜色、填充、边框、对齐、换行、旋转 | ✅ |
173
+ | 数组公式、动态数组(Excel 365 的溢出公式) | ✅ 区域里另有公式或碰到合并单元格时降级并点名 |
174
+ | 1904 日期系统 | ✅ |
175
+ | 数字格式、字体、颜色、填充、边框、对齐、换行、旋转、缩小字体填充、会计用下划线 | ✅ |
168
176
  | 合并单元格、行高列宽、隐藏行列、冻结窗格 | ✅ |
169
- | 多工作表、工作表隐藏、标签颜色、网格线开关 | ✅ |
177
+ | 多工作表、工作表隐藏与深度隐藏、标签颜色、网格线开关 | ✅ |
178
+ | 工作表背景图 | ✅ data URL 形式的;外链 / 图床地址不联网取图,点名跳过 |
170
179
  | 富文本单元格 | ~ 压平成纯文本 |
180
+ | 模拟运算表 | ~ 只有计算结果,按值写出 |
171
181
  | 图片、图表、透视表、条件格式、数据校验、筛选、批注、超链接 | ✕ |
172
182
 
173
- 最后一行是 Univer 社区版的结构性限制:这些数据不在 `cellData` 里,而是各插件自己
174
- 序列化进 `resources` 的私有结构。**所以 `warnings` 必须展示给用户** —— 导出时它会
175
- 逐条点名丢了什么(「条件格式未随 xlsx 导出」),打开文件才发现要糟得多。
183
+ 编辑器里可以直接用筛选、排序、数据校验、条件格式、超链接、批注、评论、表格和浮动图片。
184
+ 写进 xlsx 时它们仍在各插件自己的 `resources` 里,不在 `cellData` 中,所以上面最后一行照样进
185
+ `warnings`。**要展示给用户** —— 导出时会逐条点名丢了什么(「条件格式未随 xlsx 导出」),
186
+ 打开文件才发现要糟得多。
176
187
 
177
188
  `cachedFormulaValues`(默认 true)决定公式格写不写 Univer 算好的值。关掉则只留公式、
178
189
  由 Excel 打开时重算 —— 这时会自动加上 `fullCalcOnLoad`,否则不重算的消费方
@@ -203,7 +214,8 @@ if (warnings.length) toast(warnings.join("\n"))
203
214
  其余降级同样会点名:合并单元格被拆开、富文本压平、公式写成算好的值
204
215
  (`formulas: "formula"` 可改成写公式原文)。**日期不做转换** —— 它在 Univer 里是
205
216
  「序列号 + 数字格式」,csv 里会写成 `45678`。格式码有转义、区域前缀、还有和 `mm`
206
- 同形的分钟,猜错日期比原样给出序列号更糟,所以只警告不转换。
217
+ 同形的分钟,猜错日期比原样给出序列号更糟,所以只警告不转换。1904 日期系统的工作簿会在
218
+ 警告里额外说明序列号的起算日。
207
219
 
208
220
  ## xlsx / csv / tsv 导入
209
221
 
@@ -231,12 +243,18 @@ univerAPI.createWorkbook(workbook)
231
243
  Node 侧没有全局 `DOMParser`,把 `@xmldom/xmldom` 的传进去即可
232
244
  (`importXlsx(bytes, { DOMParser })`)—— 解析层是纯函数,整条链路不碰 DOM。
233
245
 
234
- **能保住的**:多工作表(顺序 / 隐藏)、值与类型、公式(普通 / 共享 / 数组)、
235
- 数字格式(含内建表)、字体 / 颜色 / 填充 / 边框 / 对齐 / 换行 / 旋转、合并单元格、
236
- 行高列宽、隐藏行列、冻结窗格、网格线、标签颜色、`quotePrefix`(强制文本)。
246
+ **能保住的**:多工作表(顺序 / 隐藏 / 深度隐藏)、值与类型、
247
+ 公式(普通 / 共享 / 数组 / 动态数组)、1904 日期系统、数字格式(含内建表)、
248
+ 字体 / 颜色 / 填充 / 边框 / 对齐 / 换行 / 旋转 / 缩小字体填充、会计用下划线、合并单元格、
249
+ 行高列宽、隐藏行列、冻结窗格、网格线、标签颜色、工作表背景图(png / jpg / gif / bmp)、
250
+ `quotePrefix`(强制文本)。
251
+
252
+ 1904 日期系统只在工作簿上标 `dateSystem`、不改数值 —— Univer 的显示、日期编辑和公式
253
+ 都按它解释序列号。
237
254
 
238
255
  **保不住的逐个点名**(进 `warnings`):图片 / 图表、透视表、条件格式、数据校验、
239
- 筛选、超链接、批注、宏、主题色、1904 日期系统。和导出侧一样 ——
256
+ 筛选、超链接、批注、宏、主题色、模拟运算表的定义(只留计算结果)。编辑器能新建这些
257
+ (图表和透视表除外),但 xlsx 里原有的不会进快照。和导出侧一样 ——
240
258
  **打开文件才发现少了东西,远比导入时被告知糟糕**。
241
259
 
242
260
  `.xls` 是老的二进制复合文档,明确不解析:报错会直接告诉用户「另存为 .xlsx」,
@@ -0,0 +1,3 @@
1
+ export { SheetView as default } from './chunk-JWHQF2CZ.js';
2
+ //# sourceMappingURL=SheetView-YFK7BUS5.js.map
3
+ //# sourceMappingURL=SheetView-YFK7BUS5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"SheetView-SDBRSTVS.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"SheetView-YFK7BUS5.js"}
@@ -18,6 +18,13 @@ var H_ALIGN = {
18
18
  };
19
19
  var V_ALIGN = { TOP: 1, MIDDLE: 2, BOTTOM: 3 };
20
20
  var WRAP = { UNSPECIFIED: 0, OVERFLOW: 1, CLIP: 2, WRAP: 3 };
21
+ var UNDERLINE = {
22
+ DOUBLE: 10,
23
+ SINGLE: 12,
24
+ SINGLE_ACCOUNTING: 18,
25
+ DOUBLE_ACCOUNTING: 19
26
+ };
27
+ var FORMULA_TYPE = { NORMAL: 0, SHARED: 1, ARRAY: 2, DATA_TABLE: 3 };
21
28
 
22
29
  // src/xlsx/csv-parse.ts
23
30
  function parseCsv(text, delimiter = ",") {
@@ -125,6 +132,6 @@ function csvToSnapshot(text, options = {}) {
125
132
  };
126
133
  }
127
134
 
128
- export { CELL_TYPE, H_ALIGN, V_ALIGN, WRAP, csvToSnapshot, parseCsv };
129
- //# sourceMappingURL=chunk-KRP5V7VF.js.map
130
- //# sourceMappingURL=chunk-KRP5V7VF.js.map
135
+ export { CELL_TYPE, FORMULA_TYPE, H_ALIGN, UNDERLINE, V_ALIGN, WRAP, csvToSnapshot, parseCsv };
136
+ //# sourceMappingURL=chunk-2DI4FJPC.js.map
137
+ //# sourceMappingURL=chunk-2DI4FJPC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/xlsx/types.ts","../src/xlsx/csv-parse.ts"],"names":[],"mappings":"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","file":"chunk-2DI4FJPC.js","sourcesContent":["/**\n * Univer 快照的结构化镜像。\n *\n * 为什么不直接 `import type { IWorkbookData } from \"@univerjs/core\"`:\n * 那是**可选 peer**。没装 `@univerjs/presets` 的项目一解析不到这个模块,\n * 整个包的 typecheck 就红了 —— 而「拿快照出 xlsx」恰恰是最不该逼人装 871KB\n * 渲染引擎的场景(服务端定时导出、Node 里跑批都只有 JSON)。\n *\n * 所以这里只声明导出真正读到的字段,字段名与取值语义和 `@univerjs/core`\n * 逐一对齐。Univer 加字段不会影响这里;改字段含义会 —— 那种时候本文件是\n * 唯一需要改的地方。\n */\n\nexport type CellValue = string | number | boolean\n\n/** 对齐 `CellValueType` */\nexport const CELL_TYPE = {\n STRING: 1,\n NUMBER: 2,\n BOOLEAN: 3,\n /** 强制文本:用户输入 `'0123` 这类本该被当数字的内容 */\n FORCE_STRING: 4,\n} as const\n\n/** 对齐 `HorizontalAlign` */\nexport const H_ALIGN = {\n LEFT: 1,\n CENTER: 2,\n RIGHT: 3,\n JUSTIFIED: 4,\n BOTH: 5,\n DISTRIBUTED: 6,\n} as const\n\n/** 对齐 `VerticalAlign` */\nexport const V_ALIGN = { TOP: 1, MIDDLE: 2, BOTTOM: 3 } as const\n\n/** 对齐 `WrapStrategy` */\nexport const WRAP = { UNSPECIFIED: 0, OVERFLOW: 1, CLIP: 2, WRAP: 3 } as const\n\n/** 对齐 `TextDecoration` 里下划线会用到的几种。`ul.t` 缺省即单下划线 */\nexport const UNDERLINE = {\n DOUBLE: 10,\n SINGLE: 12,\n SINGLE_ACCOUNTING: 18,\n DOUBLE_ACCOUNTING: 19,\n} as const\n\n/** 对齐 `FormulaType`(`CellData.ft`),即 OOXML 的 `f@t` */\nexport const FORMULA_TYPE = { NORMAL: 0, SHARED: 1, ARRAY: 2, DATA_TABLE: 3 } as const\n\n/** 对齐 `DateSystem`:日期序列号从哪天起算 */\nexport type DateSystem = \"date1900\" | \"date1904\"\n\nexport interface ColorStyle {\n /** `#RRGGBB` / `rgb(r,g,b)` / `rgba(r,g,b,a)` */\n rgb?: string | null\n /** 主题色 token。xlsx 侧解析不了,直接忽略 */\n th?: number\n}\n\n/** 下划线 / 删除线 / 上划线 */\nexport interface TextDecorationData {\n /** 0 关 1 开 */\n s?: number\n cl?: ColorStyle | null\n /** 线型,对齐 `TextDecoration`,下划线见 `UNDERLINE` */\n t?: number\n}\n\nexport interface BorderStyleData {\n /** 对齐 `BorderStyleTypes` */\n s?: number\n cl?: ColorStyle | null\n}\n\nexport interface BorderData {\n t?: BorderStyleData | null\n r?: BorderStyleData | null\n b?: BorderStyleData | null\n l?: BorderStyleData | null\n}\n\nexport interface TextRotation {\n /** 角度,-90 ~ 90,正数逆时针 */\n a?: number\n /** 1 = 竖排 */\n v?: number\n}\n\nexport interface StyleData {\n /** fontFamily */\n ff?: string | null\n /** 东亚字体,中日韩字符优先用它渲染。xlsx 的字体只有一个名字,导出时仅在没有 `ff` 时顶上 */\n eastAsiaFontFamily?: string | null\n /** fontSize,pt */\n fs?: number\n /** italic */\n it?: number\n /** bold */\n bl?: number\n /** underline */\n ul?: TextDecorationData | null\n /** strikethrough */\n st?: TextDecorationData | null\n /** overline —— xlsx 没有对应表达 */\n ol?: TextDecorationData | null\n /** background */\n bg?: ColorStyle | null\n /** border */\n bd?: BorderData | null\n /** font color */\n cl?: ColorStyle | null\n /** 上下标 */\n va?: number | null\n /** 数字格式 */\n n?: { pattern?: string } | null\n /** shrinkToFit:缩小字体填充,1 开 */\n stf?: number\n /** textRotation */\n tr?: TextRotation | null\n /** horizontalAlign */\n ht?: number | null\n /** verticalAlign */\n vt?: number | null\n /** wrapStrategy */\n tb?: number | null\n}\n\n/** 富文本单元格。导出只取纯文本 —— xlsx 的富文本要拆成 `<si><r>` 段,收益不抵复杂度 */\nexport interface RichTextData {\n body?: { dataStream?: string } | null\n}\n\nexport interface CellData {\n v?: CellValue | null\n /** 对齐 `CellValueType` */\n t?: number | null\n /** 原始公式,含前导 `=` */\n f?: string | null\n /**\n * 公式类型,见 `FORMULA_TYPE`。Univer 只保存不参与计算,用户改了公式就清空 ——\n * 它存在的意义就是让导入的数组公式 / 模拟运算表在导出时能还原\n */\n ft?: number | null\n /** 1 = 动态数组公式(Excel 365 的溢出公式),来自 metadata.xml 的 `dynamicArrayProperties@fDynamic` */\n fd?: number | null\n /** 共享公式组 id。同组里只有一个单元格带 `f` */\n si?: string | null\n /** 数组公式的引用范围 */\n ref?: string | null\n /** 样式 id 或内联样式 */\n s?: StyleData | string | null\n /** 富文本 */\n p?: RichTextData | null\n}\n\nexport interface RowData {\n /** 高度 px */\n h?: number\n /** 自适应高度 px,`ia` 为 1 时用它 */\n ah?: number\n /** 是否自适应 */\n ia?: number\n /** 隐藏 */\n hd?: number\n s?: StyleData | string | null\n}\n\nexport interface ColumnData {\n /** 宽度 px */\n w?: number\n hd?: number\n s?: StyleData | string | null\n}\n\nexport interface CellRange {\n startRow: number\n startColumn: number\n endRow: number\n endColumn: number\n}\n\nexport interface FreezeData {\n /** 冻结列数 */\n xSplit: number\n /** 冻结行数 */\n ySplit: number\n startRow: number\n startColumn: number\n}\n\n/** 对齐 `IWorksheetBackgroundImage`:平铺在单元格下面的工作表背景图 */\nexport interface WorksheetBackgroundImage {\n /** `BASE64` 时必须是完整的 data URL —— Univer 直接把它塞给 `img.src` */\n source: string\n /** 对齐 `ImageSourceType` */\n imageSourceType: \"URL\" | \"UUID\" | \"BASE64\"\n scaleX?: number\n scaleY?: number\n}\n\n/** `IObjectMatrixPrimitiveType<T>`:行号 → 列号 → 值,两层都是稀疏对象 */\nexport type Matrix<T> = Record<number, Record<number, T> | undefined>\n\nexport interface WorksheetData {\n id?: string\n name?: string\n /** `#RRGGBB` */\n tabColor?: string\n /** 对齐 `WorksheetHiddenState`:1 = 隐藏,2 = 深度隐藏(xlsx 的 veryHidden,「取消隐藏」里不列出) */\n hidden?: number\n freeze?: FreezeData\n rowCount?: number\n columnCount?: number\n /** px */\n defaultColumnWidth?: number\n /** px */\n defaultRowHeight?: number\n mergeData?: CellRange[]\n cellData?: Matrix<CellData>\n rowData?: Record<number, RowData | undefined>\n columnData?: Record<number, ColumnData | undefined>\n /** 0 = 不显示网格线 */\n showGridlines?: number\n /** 1 = 从右向左 */\n rightToLeft?: number\n defaultStyle?: StyleData | string | null\n /** 渲染随表格通道内置的 drawing preset 一起加载;没装该包时快照里仍会原样保留 */\n backgroundImage?: WorksheetBackgroundImage\n}\n\nexport interface WorkbookData {\n id?: string\n name?: string\n /** 工作表顺序。缺省时按 `sheets` 的键序 */\n sheetOrder?: string[]\n sheets?: Record<string, WorksheetData | undefined>\n /** 样式表:`CellData.s` 为字符串时查这里 */\n styles?: Record<string, StyleData | null | undefined>\n defaultStyle?: StyleData | string | null\n /** 缺省是 1900 体系。Univer 的格式化、日期编辑和公式都按它解释序列号 */\n dateSystem?: DateSystem\n /**\n * 各插件自己序列化的数据(图片、条件格式、数据校验、筛选……)。\n * 导出读不了它们的私有结构,但**能据此如实报告丢了什么** —— 见 `warnings`。\n */\n resources?: Array<{ id?: string; name: string; data: string }>\n}\n","/**\n * CSV → Univer 快照。`csv.ts`(导出侧)的逆。\n *\n * 解析按 RFC 4180:引号字段、内部引号翻倍、字段内换行都认;\n * 行分隔 `\\r\\n` / `\\n` / `\\r` 混用也收 —— 真实世界的 csv 三种都有。\n *\n * **类型推断是有立场的**:看起来是数字就转数字、TRUE/FALSE 转布尔,\n * 但「会失真的数字」除外 —— 前导零(\"0123\")和超过 15 位有效数字的\n * (超出 IEEE 754 精度,转了就变值)保留为强制文本,宁可让用户看到\n * 原文也不悄悄改数据。不想要推断就 `inferTypes: false`,全部按文本进。\n */\n\nimport { matrixRow } from \"./cell.ts\"\nimport { CELL_TYPE, type CellData, type Matrix, type WorkbookData } from \"./types.ts\"\n\nexport interface CsvParseOptions {\n /** 分隔符,默认 `,`。tsv 传 `\\t` */\n delimiter?: string\n /** 是否推断数字/布尔类型,默认 true */\n inferTypes?: boolean\n /** 工作表名,默认 \"Sheet1\" */\n sheetName?: string\n /** 工作簿名 */\n name?: string\n}\n\nexport interface CsvToSnapshotResult {\n workbook: WorkbookData\n warnings: string[]\n stats: { rows: number; columns: number; cells: number }\n}\n\n/**\n * RFC 4180 状态机。比 split 系写法多出的能力:引号字段里的\n * 分隔符/换行/翻倍引号。输入带 BOM 时自动剥掉。\n */\nexport function parseCsv(text: string, delimiter = \",\"): string[][] {\n const src = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text\n const rows: string[][] = []\n let row: string[] = []\n let field = \"\"\n let inQuotes = false\n\n for (let i = 0; i < src.length; i++) {\n const ch = src[i] as string\n\n if (inQuotes) {\n if (ch === '\"') {\n if (src[i + 1] === '\"') {\n field += '\"'\n i++\n } else {\n inQuotes = false\n }\n } else {\n field += ch\n }\n continue\n }\n\n if (ch === '\"' && field === \"\") {\n inQuotes = true\n } else if (ch === delimiter) {\n row.push(field)\n field = \"\"\n } else if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && src[i + 1] === \"\\n\") i++\n row.push(field)\n rows.push(row)\n row = []\n field = \"\"\n } else {\n field += ch\n }\n }\n // 最后一行可以没有行尾符\n if (field !== \"\" || row.length) {\n row.push(field)\n rows.push(row)\n }\n return rows\n}\n\n/** 数字外观:可选正负号、整数/小数/科学计数法 */\nconst NUMERIC = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/\n\n/** 转成 number 会失真的「数字」:前导零编号、超过 15 位有效数字(IEEE 754 上限) */\nfunction losesPrecision(text: string): boolean {\n if (/^[+-]?0\\d/.test(text)) return true\n const digits = text.replace(/[^0-9]/g, \"\")\n return digits.replace(/^0+/, \"\").length > 15\n}\n\n/** 一个字段 → CellData。空字段返回 undefined(稀疏矩阵不落空格) */\nfunction fieldToCell(text: string, inferTypes: boolean): CellData | undefined {\n if (text === \"\") return undefined\n if (!inferTypes) return { v: text, t: CELL_TYPE.STRING }\n\n if (text === \"TRUE\" || text === \"true\") return { v: true, t: CELL_TYPE.BOOLEAN }\n if (text === \"FALSE\" || text === \"false\") return { v: false, t: CELL_TYPE.BOOLEAN }\n\n if (NUMERIC.test(text)) {\n if (losesPrecision(text)) return { v: text, t: CELL_TYPE.FORCE_STRING }\n const n = Number.parseFloat(text)\n if (Number.isFinite(n)) return { v: n, t: CELL_TYPE.NUMBER }\n }\n return { v: text, t: CELL_TYPE.STRING }\n}\n\nexport function csvToSnapshot(text: string, options: CsvParseOptions = {}): CsvToSnapshotResult {\n const { delimiter = \",\", inferTypes = true, sheetName = \"Sheet1\" } = options\n\n const rows = parseCsv(text, delimiter)\n const warnings: string[] = []\n\n const cellData: Matrix<CellData> = {}\n let cells = 0\n let maxCol = -1\n let forcedText = 0\n\n rows.forEach((fields, r) => {\n fields.forEach((field, c) => {\n const cell = fieldToCell(field, inferTypes)\n if (!cell) return\n if (cell.t === CELL_TYPE.FORCE_STRING) forcedText++\n matrixRow(cellData, r)[c] = cell\n cells++\n if (c > maxCol) maxCol = c\n })\n })\n\n if (forcedText) {\n warnings.push(\n `${forcedText} 个看似数字的值转成 number 会失真(前导零或超过 15 位),已按文本保留原文`,\n )\n }\n\n const sheetId = \"sheet-1\"\n const workbook: WorkbookData = {\n id: `import-${Date.now().toString(36)}`,\n name: options.name ?? sheetName,\n sheetOrder: [sheetId],\n sheets: {\n [sheetId]: {\n id: sheetId,\n name: sheetName,\n cellData,\n rowCount: Math.max(1000, rows.length),\n columnCount: Math.max(20, maxCol + 1),\n },\n },\n }\n\n return {\n workbook,\n warnings,\n stats: { rows: rows.length, columns: maxCol + 1, cells },\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { pointsToPx, columnWidthToPx, parseRange, parseCellRef, argbToCss } from './chunk-SBTKDJAL.js';
2
- import { H_ALIGN, V_ALIGN, CELL_TYPE, csvToSnapshot, WRAP } from './chunk-KRP5V7VF.js';
1
+ import { pointsToPx, columnWidthToPx, parseRange, parseCellRef, imageMimeOf, bytesToDataUrl, argbToCss } from './chunk-SDVGDHC4.js';
2
+ import { H_ALIGN, V_ALIGN, UNDERLINE, FORMULA_TYPE, CELL_TYPE, csvToSnapshot, WRAP } from './chunk-2DI4FJPC.js';
3
3
  import { matrixRow } from './chunk-5HMKRNIH.js';
4
4
  import { unzipSync } from 'fflate';
5
5
 
@@ -74,6 +74,11 @@ var V_ALIGN_INDEX = {
74
74
  center: V_ALIGN.MIDDLE,
75
75
  bottom: V_ALIGN.BOTTOM
76
76
  };
77
+ var UNDERLINE_INDEX = {
78
+ double: UNDERLINE.DOUBLE,
79
+ singleAccounting: UNDERLINE.SINGLE_ACCOUNTING,
80
+ doubleAccounting: UNDERLINE.DOUBLE_ACCOUNTING
81
+ };
77
82
  var BUILTIN_NUMFMT = {
78
83
  1: "0",
79
84
  2: "0.00",
@@ -196,7 +201,11 @@ function parseStylesXml(dom) {
196
201
  if (childOf(el, "i")) s.it = 1;
197
202
  if (childOf(el, "strike")) s.st = { s: 1 };
198
203
  const u = childOf(el, "u");
199
- if (u && u.getAttribute("val") !== "none") s.ul = { s: 1 };
204
+ const underline = u?.getAttribute("val") || "single";
205
+ if (u && underline !== "none") {
206
+ const t = UNDERLINE_INDEX[underline];
207
+ s.ul = t ? { s: 1, t } : { s: 1 };
208
+ }
200
209
  const va = childOf(el, "vertAlign")?.getAttribute("val");
201
210
  if (va === "superscript") s.va = 1;
202
211
  else if (va === "subscript") s.va = 2;
@@ -244,6 +253,7 @@ function parseStylesXml(dom) {
244
253
  const vt = V_ALIGN_INDEX[align.getAttribute("vertical") ?? ""];
245
254
  if (vt) s.vt = vt;
246
255
  if (boolAttr(align, "wrapText")) s.tb = WRAP.WRAP;
256
+ if (boolAttr(align, "shrinkToFit")) s.stf = 1;
247
257
  const rotation = intAttr(align, "textRotation");
248
258
  if (rotation === 255) s.tr = { v: 1 };
249
259
  else if (rotation !== void 0 && rotation !== 0) {
@@ -294,9 +304,7 @@ function parseXlsx(entries, options) {
294
304
  if (!workbookRoot) {
295
305
  throw new Error("不是有效的 xlsx:包内找不到 xl/workbook.xml(.xls 老格式请先另存为 .xlsx)");
296
306
  }
297
- if (boolAttr(childOf(workbookRoot, "workbookPr"), "date1904")) {
298
- warnings.push("此文件使用 1904 日期系统,日期单元格会整体偏差约 4 年,请核对后手动调整");
299
- }
307
+ const date1904 = boolAttr(childOf(workbookRoot, "workbookPr"), "date1904");
300
308
  const parsedStyles = parseStylesXml(parseEntry("xl/styles.xml"));
301
309
  const styleMap = {};
302
310
  const styleIdOf = (xfIndex) => {
@@ -311,30 +319,23 @@ function parseXlsx(entries, options) {
311
319
  return id;
312
320
  };
313
321
  const sharedStrings = parseSharedStrings(parseEntry("xl/sharedStrings.xml"));
314
- const relTargets = /* @__PURE__ */ new Map();
315
- const relsDom = parseEntry("xl/_rels/workbook.xml.rels");
316
- for (const rel of childrenOf(relsDom?.documentElement, "Relationship")) {
317
- const id = rel.getAttribute("Id");
318
- const target = rel.getAttribute("Target");
319
- if (!id || !target) continue;
320
- relTargets.set(id, target.startsWith("/") ? target.slice(1) : `xl/${target}`);
321
- }
322
+ const workbookRels = readRels(parseEntry, "xl/workbook.xml");
323
+ const metadataPath = [...workbookRels.values()].find((rel) => rel.type.endsWith("/sheetMetadata"))?.path ?? "xl/metadata.xml";
324
+ const dynamicArrayCm = parseDynamicArrayCm(parseEntry(metadataPath));
322
325
  const sheets = {};
323
326
  const sheetOrder = [];
324
327
  const droppedBySheet = /* @__PURE__ */ new Map();
325
328
  const sheetEls = childrenOf(childOf(workbookRoot, "sheets"), "sheet");
326
329
  sheetEls.forEach((el, index) => {
327
330
  const name = el.getAttribute("name") ?? `Sheet${index + 1}`;
328
- const rId = el.getAttribute("r:id") ?? el.getAttributeNS?.(
329
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
330
- "id"
331
- );
332
- const path = rId && relTargets.get(rId) || `xl/worksheets/sheet${index + 1}.xml`;
331
+ const rId = relIdOf(el);
332
+ const path = rId && workbookRels.get(rId)?.path || `xl/worksheets/sheet${index + 1}.xml`;
333
333
  const dom = parseEntry(path);
334
334
  if (!dom?.documentElement) {
335
335
  warnings.push(`工作表「${name}」的数据部件缺失(${path}),已跳过`);
336
336
  return;
337
337
  }
338
+ const sheetRels = readRels(parseEntry, path);
338
339
  const id = `sheet-${index + 1}`;
339
340
  const { sheet, dropped } = parseSheetXml(dom.documentElement, {
340
341
  sharedStrings,
@@ -343,13 +344,20 @@ function parseXlsx(entries, options) {
343
344
  sheetKey: id,
344
345
  stats,
345
346
  warnings,
346
- sheetName: name
347
+ sheetName: name,
348
+ dynamicArrayCm,
349
+ imageOf: (imageRelId) => {
350
+ const target = sheetRels.get(imageRelId)?.path;
351
+ const mime = target ? imageMimeOf(target) : void 0;
352
+ const bytes = target && mime ? entries.read(target) : null;
353
+ return bytes && mime ? bytesToDataUrl(bytes, mime) : void 0;
354
+ }
347
355
  });
348
356
  sheet.id = id;
349
357
  sheet.name = name;
350
- if (el.getAttribute("state") === "hidden" || el.getAttribute("state") === "veryHidden") {
351
- sheet.hidden = 1;
352
- }
358
+ const state = el.getAttribute("state");
359
+ if (state === "hidden") sheet.hidden = 1;
360
+ else if (state === "veryHidden") sheet.hidden = 2;
353
361
  sheets[id] = sheet;
354
362
  sheetOrder.push(id);
355
363
  stats.sheets++;
@@ -375,13 +383,19 @@ function parseXlsx(entries, options) {
375
383
  );
376
384
  stats.themeColors = parsedStyles.themeColorCount;
377
385
  }
386
+ if (stats.dataTables) {
387
+ warnings.push(
388
+ `${stats.dataTables} 处模拟运算表(数据表)只保留了计算结果:Univer 不计算模拟运算表,引用的输入单元格等定义没有导入,改了源数据结果不会跟着变`
389
+ );
390
+ }
378
391
  const title = textOf(childOf(parseEntry("docProps/core.xml")?.documentElement, "title"));
379
392
  const workbook = {
380
393
  id: `import-${Date.now().toString(36)}`,
381
394
  name: options.name ?? (title || "导入的工作簿"),
382
395
  sheetOrder,
383
396
  sheets,
384
- styles: styleMap
397
+ styles: styleMap,
398
+ ...date1904 ? { dateSystem: "date1904" } : {}
385
399
  };
386
400
  return { workbook, warnings, stats };
387
401
  }
@@ -399,6 +413,53 @@ function parseSharedStrings(dom) {
399
413
  }
400
414
  return out;
401
415
  }
416
+ var REL_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
417
+ function relIdOf(el) {
418
+ return el.getAttribute("r:id") ?? el.getAttributeNS?.(REL_NS, "id") ?? null;
419
+ }
420
+ function readRels(parseEntry, partPath) {
421
+ const slash = partPath.lastIndexOf("/");
422
+ const dir = slash < 0 ? "" : partPath.slice(0, slash);
423
+ const out = /* @__PURE__ */ new Map();
424
+ const dom = parseEntry(`${dir ? `${dir}/` : ""}_rels/${partPath.slice(slash + 1)}.rels`);
425
+ for (const rel of childrenOf(dom?.documentElement, "Relationship")) {
426
+ const id = rel.getAttribute("Id");
427
+ const target = rel.getAttribute("Target");
428
+ if (!id || !target || rel.getAttribute("TargetMode") === "External") continue;
429
+ const segments = target.startsWith("/") ? [] : dir.split("/").filter(Boolean);
430
+ for (const part of target.split("/")) {
431
+ if (part === "..") segments.pop();
432
+ else if (part && part !== ".") segments.push(part);
433
+ }
434
+ out.set(id, { type: rel.getAttribute("Type") ?? "", path: segments.join("/") });
435
+ }
436
+ return out;
437
+ }
438
+ function parseDynamicArrayCm(dom) {
439
+ const out = /* @__PURE__ */ new Set();
440
+ const root = dom?.documentElement;
441
+ if (!root) return out;
442
+ const typeNames = childrenOf(childOf(root, "metadataTypes"), "metadataType").map(
443
+ (el) => el.getAttribute("name")
444
+ );
445
+ const future = childrenOf(root, "futureMetadata").find(
446
+ (el) => el.getAttribute("name") === "XLDAPR"
447
+ );
448
+ const dynamic = childrenOf(future, "bk").map(
449
+ (bk) => childrenOf(childOf(bk, "extLst"), "ext").some(
450
+ (ext) => boolAttr(childOf(ext, "dynamicArrayProperties"), "fDynamic")
451
+ )
452
+ );
453
+ childrenOf(childOf(root, "cellMetadata"), "bk").forEach((bk, index) => {
454
+ const rc = childOf(bk, "rc");
455
+ const t = intAttr(rc, "t");
456
+ const v = intAttr(rc, "v");
457
+ if (t !== void 0 && v !== void 0 && typeNames[t - 1] === "XLDAPR" && dynamic[v]) {
458
+ out.add(index + 1);
459
+ }
460
+ });
461
+ return out;
462
+ }
402
463
  function parseSheetXml(root, ctx) {
403
464
  const sheet = {};
404
465
  parseSheetProperties(root, sheet);
@@ -406,6 +467,7 @@ function parseSheetXml(root, ctx) {
406
467
  parseColumns(root, sheet, ctx);
407
468
  const { maxRow, maxCol } = parseSheetData(root, sheet, ctx);
408
469
  parseMerges(root, sheet, ctx);
470
+ parseBackgroundPicture(root, sheet, ctx);
409
471
  sheet.rowCount = Math.max(1e3, maxRow + 1);
410
472
  sheet.columnCount = Math.max(20, maxCol + 1);
411
473
  const dropped = Object.entries(SHEET_DROPPED_ELEMENTS).filter(([tag]) => root.getElementsByTagName(tag).length > 0).map(([, label]) => label);
@@ -475,6 +537,20 @@ function parseMerges(root, sheet, ctx) {
475
537
  ctx.stats.merges += merges.length;
476
538
  }
477
539
  }
540
+ function parseBackgroundPicture(root, sheet, ctx) {
541
+ const picture = childOf(root, "picture");
542
+ if (!picture) return;
543
+ const relId = relIdOf(picture);
544
+ const source = relId ? ctx.imageOf(relId) : void 0;
545
+ if (source) {
546
+ sheet.backgroundImage = { source, imageSourceType: "BASE64" };
547
+ ctx.stats.backgroundImages = (ctx.stats.backgroundImages ?? 0) + 1;
548
+ } else {
549
+ ctx.warnings.push(
550
+ `工作表「${ctx.sheetName}」的背景图读不到或格式不支持(只认 png / jpg / gif / bmp),已跳过`
551
+ );
552
+ }
553
+ }
478
554
  function parseSheetData(root, sheet, ctx) {
479
555
  const cellData = {};
480
556
  const rowData = {};
@@ -540,8 +616,17 @@ function parseCellFormula(el, cell, ctx) {
540
616
  ctx.stats.sharedFormulas++;
541
617
  }
542
618
  } else if (type === "array") {
619
+ cell.ft = FORMULA_TYPE.ARRAY;
543
620
  const ref = f.getAttribute("ref");
544
621
  if (ref) cell.ref = ref;
622
+ const cm = intAttr(el, "cm");
623
+ if (cm !== void 0 && ctx.dynamicArrayCm.has(cm)) {
624
+ cell.fd = 1;
625
+ ctx.stats.dynamicArrays = (ctx.stats.dynamicArrays ?? 0) + 1;
626
+ }
627
+ } else if (type === "dataTable") {
628
+ cell.ft = FORMULA_TYPE.DATA_TABLE;
629
+ ctx.stats.dataTables = (ctx.stats.dataTables ?? 0) + 1;
545
630
  }
546
631
  }
547
632
  function parseCellValue(el, cell, ctx, xfIndex) {
@@ -707,5 +792,5 @@ function stripExtension(name) {
707
792
  }
708
793
 
709
794
  export { importCsv, importSheetSource, importXlsx, parseXlsx };
710
- //# sourceMappingURL=chunk-DGUNVCOM.js.map
711
- //# sourceMappingURL=chunk-DGUNVCOM.js.map
795
+ //# sourceMappingURL=chunk-3QTRZBIK.js.map
796
+ //# sourceMappingURL=chunk-3QTRZBIK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/xlsx/dom.ts","../src/xlsx/parse-styles.ts","../src/xlsx/parse.ts","../src/xlsx/import.ts"],"names":["result"],"mappings":"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","file":"chunk-3QTRZBIK.js","sourcesContent":["/**\n * 解析 OOXML 用的 DOM 小工具。\n *\n * 只用 DOM Level 2 的接口(firstChild / nextSibling / getAttribute),\n * 浏览器原生 DOMParser 和 @xmldom/xmldom 的产物都吃 —— 不用 querySelector\n * 是因为 xmldom 没有它,且命名空间前缀会让选择器在两边行为不一致。\n */\n\n/** 注入式 DOMParser 的最小面:浏览器传原生的,Node 传 @xmldom/xmldom 的 */\nexport interface DomParserLike {\n new (): { parseFromString(source: string, mimeType: string): Document }\n}\n\n/** 第一个指定标签名的**直接**子元素。按 localName 匹配,无视命名空间前缀 */\nexport function childOf(parent: Element | undefined, tag: string): Element | undefined {\n for (let n = parent?.firstChild; n; n = n.nextSibling) {\n if (n.nodeType === 1 && (n as Element).localName === tag) return n as Element\n }\n return undefined\n}\n\n/** 全部指定标签名的**直接**子元素 */\nexport function childrenOf(parent: Element | undefined, tag: string): Element[] {\n if (!parent) return []\n const out: Element[] = []\n for (let n = parent.firstChild; n; n = n.nextSibling) {\n if (n.nodeType === 1 && (n as Element).localName === tag) out.push(n as Element)\n }\n return out\n}\n\n/** 元素的直接文本内容(含子元素的文本,按文档序拼接) */\nexport function textOf(el: Element | undefined): string {\n if (!el) return \"\"\n let out = \"\"\n for (let n = el.firstChild; n; n = n.nextSibling) {\n if (n.nodeType === 3 || n.nodeType === 4) out += n.nodeValue ?? \"\"\n else if (n.nodeType === 1) out += textOf(n as Element)\n }\n return out\n}\n\n/** 属性转整数。缺失或非法返回 undefined */\nexport function intAttr(el: Element | undefined, name: string): number | undefined {\n const raw = el?.getAttribute(name)\n if (raw === null || raw === undefined || raw === \"\") return undefined\n const n = Number.parseInt(raw, 10)\n return Number.isInteger(n) ? n : undefined\n}\n\n/** 属性转浮点数。缺失或非法返回 undefined */\nexport function floatAttr(el: Element | undefined, name: string): number | undefined {\n const raw = el?.getAttribute(name)\n if (raw === null || raw === undefined || raw === \"\") return undefined\n const n = Number.parseFloat(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\n/** xml 的布尔属性:\"1\" / \"true\" 为真 */\nexport function boolAttr(el: Element | undefined, name: string): boolean {\n const raw = el?.getAttribute(name)\n return raw === \"1\" || raw === \"true\"\n}\n","/**\n * xl/styles.xml 的解析 —— `styles.ts`(构建侧)的逆。\n *\n * xlsx 的样式是分表索引的:字体、填充、边框、数字格式各自成表,`cellXfs`\n * 把四张表的下标组合起来,单元格引用 `cellXfs` 的下标。这里把每条 xf\n * 摊平成一份 Univer `StyleData`,调用方按 xf 下标取用。\n *\n * **颜色的三种写法**:`rgb`(直接收)、`indexed`(查 legacy 调色板,是死表)、\n * `theme`(要解析 theme1.xml 并做 tint 变换 —— 本实现不做,跳过并计数,\n * 由 `parse.ts` 汇总成一条 warning。猜一个颜色写进去比不写更糟)。\n */\n\nimport { boolAttr, childOf, childrenOf, floatAttr, intAttr } from \"./dom.ts\"\nimport { type BorderStyleData, H_ALIGN, type StyleData, UNDERLINE, V_ALIGN, WRAP } from \"./types.ts\"\nimport { argbToCss } from \"./xml.ts\"\n\n/** 对齐导出侧 `BORDER_STYLE`:Excel `ST_BorderStyle` → Univer `BorderStyleTypes` 下标 */\nconst BORDER_STYLE_INDEX: Record<string, number> = {\n none: 0,\n thin: 1,\n hair: 2,\n dotted: 3,\n dashed: 4,\n dashDot: 5,\n dashDotDot: 6,\n double: 7,\n medium: 8,\n mediumDashed: 9,\n mediumDashDot: 10,\n mediumDashDotDot: 11,\n slantDashDot: 12,\n thick: 13,\n}\n\n/** 导出侧 `H_ALIGN_NAME` 的逆 */\nconst H_ALIGN_INDEX: Record<string, number> = {\n left: H_ALIGN.LEFT,\n center: H_ALIGN.CENTER,\n centerContinuous: H_ALIGN.CENTER,\n right: H_ALIGN.RIGHT,\n justify: H_ALIGN.JUSTIFIED,\n distributed: H_ALIGN.DISTRIBUTED,\n}\n\n/** 导出侧 `V_ALIGN_NAME` 的逆 */\nconst V_ALIGN_INDEX: Record<string, number> = {\n top: V_ALIGN.TOP,\n center: V_ALIGN.MIDDLE,\n bottom: V_ALIGN.BOTTOM,\n}\n\n/** 导出侧 `UNDERLINE_NAME` 的逆。single 是缺省,不写 `t` */\nconst UNDERLINE_INDEX: Record<string, number> = {\n double: UNDERLINE.DOUBLE,\n singleAccounting: UNDERLINE.SINGLE_ACCOUNTING,\n doubleAccounting: UNDERLINE.DOUBLE_ACCOUNTING,\n}\n\n/**\n * ECMA-376 §18.8.30 的内建数字格式。0-163 保留,文件里不写定义 ——\n * 不带上这张表,内建的日期/百分比格式一导入就全变回 General。\n * (区域相关的 5-8、23-26、41-44 各家实现不一,只列跨区域稳定的那些)\n */\nconst BUILTIN_NUMFMT: Record<number, string> = {\n 1: \"0\",\n 2: \"0.00\",\n 3: \"#,##0\",\n 4: \"#,##0.00\",\n 9: \"0%\",\n 10: \"0.00%\",\n 11: \"0.00E+00\",\n 12: \"# ?/?\",\n 13: \"# ??/??\",\n 14: \"m/d/yyyy\",\n 15: \"d-mmm-yy\",\n 16: \"d-mmm\",\n 17: \"mmm-yy\",\n 18: \"h:mm AM/PM\",\n 19: \"h:mm:ss AM/PM\",\n 20: \"h:mm\",\n 21: \"h:mm:ss\",\n 22: \"m/d/yyyy h:mm\",\n 37: \"#,##0;(#,##0)\",\n 38: \"#,##0;[Red](#,##0)\",\n 39: \"#,##0.00;(#,##0.00)\",\n 40: \"#,##0.00;[Red](#,##0.00)\",\n 45: \"mm:ss\",\n 46: \"[h]:mm:ss\",\n 47: \"mm:ss.0\",\n 48: \"##0.0E+0\",\n 49: \"@\",\n}\n\n/**\n * legacy `indexed` 调色板(ECMA-376 §18.8.27 的默认 64 色)。\n * 老文件和部分生成器还在用;这是规范里的死表,不是猜。\n */\nconst INDEXED_PALETTE = [\n \"FF000000\",\n \"FFFFFFFF\",\n \"FFFF0000\",\n \"FF00FF00\",\n \"FF0000FF\",\n \"FFFFFF00\",\n \"FFFF00FF\",\n \"FF00FFFF\",\n \"FF000000\",\n \"FFFFFFFF\",\n \"FFFF0000\",\n \"FF00FF00\",\n \"FF0000FF\",\n \"FFFFFF00\",\n \"FFFF00FF\",\n \"FF00FFFF\",\n \"FF800000\",\n \"FF008000\",\n \"FF000080\",\n \"FF808000\",\n \"FF800080\",\n \"FF008080\",\n \"FFC0C0C0\",\n \"FF808080\",\n \"FF9999FF\",\n \"FF993366\",\n \"FFFFFFCC\",\n \"FFCCFFFF\",\n \"FF660066\",\n \"FFFF8080\",\n \"FF0066CC\",\n \"FFCCCCFF\",\n \"FF000080\",\n \"FFFF00FF\",\n \"FFFFFF00\",\n \"FF00FFFF\",\n \"FF800080\",\n \"FF800000\",\n \"FF008080\",\n \"FF0000FF\",\n \"FF00CCFF\",\n \"FFCCFFFF\",\n \"FFCCFFCC\",\n \"FFFFFF99\",\n \"FF99CCFF\",\n \"FFFF99CC\",\n \"FFCC99FF\",\n \"FFFFCC99\",\n \"FF3366FF\",\n \"FF33CCCC\",\n \"FF99CC00\",\n \"FFFFCC00\",\n \"FFFF9900\",\n \"FFFF6600\",\n \"FF666699\",\n \"FF969696\",\n \"FF003366\",\n \"FF339966\",\n \"FF003300\",\n \"FF333300\",\n \"FF993300\",\n \"FF993366\",\n \"FF333399\",\n \"FF333333\",\n] as const\n\nexport interface ParsedStyles {\n /** 按 `cellXfs` 下标取样式。空样式(全默认)为 undefined */\n xfs: (StyleData | undefined)[]\n /** 对应下标的 xf 是否带 quotePrefix(↔ Univer 的 FORCE_STRING) */\n quotePrefix: boolean[]\n /** 遇到多少个解析不了的主题色(theme 引用) */\n themeColorCount: number\n}\n\ntype Dom = Document\n\nexport function parseStylesXml(dom: Dom | null): ParsedStyles {\n const empty: ParsedStyles = { xfs: [], quotePrefix: [], themeColorCount: 0 }\n const root = dom?.documentElement\n if (!root) return empty\n\n let themeColorCount = 0\n\n /** `<color rgb|indexed|theme/>` → CSS 颜色。主题色解析不了,计数后跳过 */\n const colorOf = (el: Element | undefined): string | undefined => {\n if (!el) return undefined\n const rgb = el.getAttribute(\"rgb\")\n if (rgb) return argbToCss(rgb)\n const indexed = el.getAttribute(\"indexed\")\n if (indexed) return argbToCss(INDEXED_PALETTE[Number.parseInt(indexed, 10)])\n if (el.getAttribute(\"theme\") !== null) themeColorCount++\n return undefined\n }\n\n /* ------------------------------ 数字格式 ------------------------------ */\n\n const numFmts = new Map<number, string>()\n for (const el of childrenOf(childOf(root, \"numFmts\"), \"numFmt\")) {\n const id = intAttr(el, \"numFmtId\")\n const code = el.getAttribute(\"formatCode\")\n if (id !== undefined && code) numFmts.set(id, code)\n }\n const numFmtPattern = (id: number): string | undefined => numFmts.get(id) ?? BUILTIN_NUMFMT[id]\n\n /* -------------------------------- 字体 -------------------------------- */\n\n const fonts: StyleData[] = childrenOf(childOf(root, \"fonts\"), \"font\").map((el) => {\n const s: StyleData = {}\n if (childOf(el, \"b\")) s.bl = 1\n if (childOf(el, \"i\")) s.it = 1\n if (childOf(el, \"strike\")) s.st = { s: 1 }\n const u = childOf(el, \"u\")\n // <u/> 不带 val 就是单下划线\n const underline = u?.getAttribute(\"val\") || \"single\"\n if (u && underline !== \"none\") {\n const t = UNDERLINE_INDEX[underline]\n s.ul = t ? { s: 1, t } : { s: 1 }\n }\n const va = childOf(el, \"vertAlign\")?.getAttribute(\"val\")\n if (va === \"superscript\") s.va = 1\n else if (va === \"subscript\") s.va = 2\n const sz = floatAttr(childOf(el, \"sz\"), \"val\")\n if (sz !== undefined) s.fs = sz\n const cl = colorOf(childOf(el, \"color\"))\n if (cl) s.cl = { rgb: cl }\n const name = childOf(el, \"name\")?.getAttribute(\"val\")\n if (name) s.ff = name\n return s\n })\n\n /* -------------------------------- 填充 -------------------------------- */\n\n // solid 只认 fgColor;其它花纹(gray125 等)没有 Univer 对应,按无填充处理\n const fills: (string | undefined)[] = childrenOf(childOf(root, \"fills\"), \"fill\").map((el) => {\n const pattern = childOf(el, \"patternFill\")\n if (!pattern || pattern.getAttribute(\"patternType\") !== \"solid\") return undefined\n return colorOf(childOf(pattern, \"fgColor\"))\n })\n\n /* -------------------------------- 边框 -------------------------------- */\n\n const borders = childrenOf(childOf(root, \"borders\"), \"border\").map((el) => {\n const side = (tag: string): BorderStyleData | undefined => {\n const s = childOf(el, tag)\n const style = s?.getAttribute(\"style\")\n const index = style ? BORDER_STYLE_INDEX[style] : undefined\n if (!index) return undefined\n const cl = colorOf(childOf(s as Element, \"color\"))\n return cl ? { s: index, cl: { rgb: cl } } : { s: index }\n }\n const bd = { l: side(\"left\"), r: side(\"right\"), t: side(\"top\"), b: side(\"bottom\") }\n return bd.l || bd.r || bd.t || bd.b ? bd : undefined\n })\n\n /* ------------------------------- cellXfs ------------------------------- */\n\n const xfs: (StyleData | undefined)[] = []\n const quotePrefix: boolean[] = []\n\n for (const el of childrenOf(childOf(root, \"cellXfs\"), \"xf\")) {\n const s: StyleData = {}\n\n const font = fonts[intAttr(el, \"fontId\") ?? -1]\n if (font) Object.assign(s, font)\n\n const fill = fills[intAttr(el, \"fillId\") ?? -1]\n if (fill) s.bg = { rgb: fill }\n\n const border = borders[intAttr(el, \"borderId\") ?? -1]\n if (border) s.bd = border\n\n const pattern = numFmtPattern(intAttr(el, \"numFmtId\") ?? 0)\n if (pattern && pattern.toLowerCase() !== \"general\") s.n = { pattern }\n\n const align = childOf(el, \"alignment\")\n if (align) {\n const ht = H_ALIGN_INDEX[align.getAttribute(\"horizontal\") ?? \"\"]\n if (ht) s.ht = ht\n const vt = V_ALIGN_INDEX[align.getAttribute(\"vertical\") ?? \"\"]\n if (vt) s.vt = vt\n if (boolAttr(align, \"wrapText\")) s.tb = WRAP.WRAP\n if (boolAttr(align, \"shrinkToFit\")) s.stf = 1\n const rotation = intAttr(align, \"textRotation\")\n if (rotation === 255) s.tr = { v: 1 }\n else if (rotation !== undefined && rotation !== 0) {\n // Excel 编码:0-90 是逆时针角度,91-180 是顺时针 (值 - 90) 度\n s.tr = { a: rotation <= 90 ? rotation : 90 - rotation }\n }\n }\n\n xfs.push(Object.keys(s).length ? s : undefined)\n quotePrefix.push(boolAttr(el, \"quotePrefix\"))\n }\n\n return { xfs, quotePrefix, themeColorCount }\n}\n","/**\n * xlsx 的各个 XML 部件 → Univer 快照。`serialize.ts`(导出侧)的逆。\n *\n * 同构:解压和 XML 解析都由调用方注入(见 `import.ts`),浏览器\n * (fflate + 原生 DOMParser)和 Node(任意 zip 库 + @xmldom/xmldom)\n * 共用这一份实现,不存在两份真相 —— 和 `docx/parse.ts` 同一套约定。\n *\n * **能保住的**:多工作表(含顺序、隐藏与深度隐藏)、值与类型、\n * 公式(普通/共享/数组/动态数组)、1904 日期系统、数字格式、\n * 字体/颜色/填充/边框/对齐/换行/旋转/缩小字体填充、会计用下划线、合并单元格、\n * 行高列宽、隐藏行列、冻结窗格、网格线开关、标签颜色、工作表背景图、quotePrefix(强制文本)。\n *\n * **保不住的**:图片、图表、透视表、条件格式、数据校验、筛选、批注、\n * 超链接、主题色、模拟运算表的定义(只留结果)。它们要么住在独立部件里(drawing / pivot / comments),\n * 要么需要把 Excel 的主题模型抄一遍(theme + tint)。这里不假装支持,\n * 而是逐个探测、**如实报告丢了什么**(见 `warnings`)—— 让宿主能把话\n * 原样告诉用户,而不是打开表格才发现少了东西。\n */\n\nimport { matrixRow } from \"./cell.ts\"\nimport {\n boolAttr,\n childOf,\n childrenOf,\n type DomParserLike,\n floatAttr,\n intAttr,\n textOf,\n} from \"./dom.ts\"\nimport { bytesToDataUrl, imageMimeOf } from \"./media.ts\"\nimport { parseStylesXml } from \"./parse-styles.ts\"\nimport {\n CELL_TYPE,\n type CellData,\n type CellRange,\n FORMULA_TYPE,\n type Matrix,\n type StyleData,\n type WorkbookData,\n type WorksheetData,\n} from \"./types.ts\"\nimport { columnWidthToPx, parseCellRef, parseRange, pointsToPx } from \"./xml.ts\"\n\nexport interface XlsxEntries {\n /** 读取包内某个条目;不存在返回 null */\n read(entryPath: string): Uint8Array | null\n /** 包内全部条目路径。用于探测图片/批注等「导入保不住」的部件 */\n list(): string[]\n}\n\nexport interface ParseXlsxOptions {\n /** 浏览器传原生 DOMParser,Node 传 @xmldom/xmldom 的 */\n DOMParser: DomParserLike\n /** 快照里的工作簿名。不传则用 docProps 里的标题,再没有就空着 */\n name?: string\n}\n\nexport interface ParseXlsxResult {\n workbook: WorkbookData\n /** 导入时丢掉/降级了什么。**要展示给用户**,别吞 */\n warnings: string[]\n /** 计数,用于量化保真度 */\n stats: Record<string, number>\n}\n\n/** 工作表 XML 里出现即意味着有内容会丢的元素 → 人话 */\nconst SHEET_DROPPED_ELEMENTS: Record<string, string> = {\n autoFilter: \"筛选\",\n conditionalFormatting: \"条件格式\",\n dataValidations: \"数据校验\",\n hyperlinks: \"超链接\",\n drawing: \"图片或图表\",\n oleObjects: \"嵌入对象\",\n controls: \"表单控件\",\n}\n\n/** 包内条目路径特征 → 人话。工作表 XML 探测不到的部件走这里 */\nconst ENTRY_DROPPED_PARTS: Array<{ pattern: RegExp; label: string }> = [\n { pattern: /^xl\\/pivotTables\\//, label: \"透视表\" },\n { pattern: /^xl\\/comments/, label: \"批注\" },\n { pattern: /^xl\\/tables\\//, label: \"表格样式(Table)\" },\n { pattern: /^xl\\/vbaProject\\.bin$/, label: \"宏(VBA)\" },\n]\n\nexport function parseXlsx(entries: XlsxEntries, options: ParseXlsxOptions): ParseXlsxResult {\n const { DOMParser } = options\n const decoder = new TextDecoder()\n const parseEntry = (path: string): Document | null => {\n const bytes = entries.read(path)\n if (!bytes) return null\n return new DOMParser().parseFromString(decoder.decode(bytes), \"text/xml\")\n }\n\n const warnings: string[] = []\n const stats: Record<string, number> = {\n sheets: 0,\n cells: 0,\n formulas: 0,\n sharedFormulas: 0,\n merges: 0,\n styles: 0,\n }\n\n const workbookDom = parseEntry(\"xl/workbook.xml\")\n const workbookRoot = workbookDom?.documentElement\n if (!workbookRoot) {\n throw new Error(\"不是有效的 xlsx:包内找不到 xl/workbook.xml(.xls 老格式请先另存为 .xlsx)\")\n }\n\n // 1904 日期系统:Mac 老 Excel 的遗产,同一个序列号比 1900 体系晚 1462 天。\n // 只标在工作簿上、不换算数值 —— Univer 的格式化、日期编辑和公式都按 dateSystem 解释序列号\n const date1904 = boolAttr(childOf(workbookRoot, \"workbookPr\"), \"date1904\")\n\n /* ------------------------------ 样式表 ------------------------------ */\n\n const parsedStyles = parseStylesXml(parseEntry(\"xl/styles.xml\"))\n // 快照的 styles 表按 xf 下标登记,单元格用字符串 id 引用 —— 天然去重\n const styleMap: Record<string, StyleData> = {}\n const styleIdOf = (xfIndex: number | undefined): string | undefined => {\n if (xfIndex === undefined) return undefined\n const style = parsedStyles.xfs[xfIndex]\n if (!style) return undefined\n const id = `xf${xfIndex}`\n if (!styleMap[id]) {\n styleMap[id] = style\n stats.styles++\n }\n return id\n }\n\n /* ---------------------------- 共享字符串 ---------------------------- */\n\n const sharedStrings = parseSharedStrings(parseEntry(\"xl/sharedStrings.xml\"))\n\n /* ------------------------------ 工作表 ------------------------------ */\n\n const workbookRels = readRels(parseEntry, \"xl/workbook.xml\")\n\n const metadataPath =\n [...workbookRels.values()].find((rel) => rel.type.endsWith(\"/sheetMetadata\"))?.path ??\n \"xl/metadata.xml\"\n const dynamicArrayCm = parseDynamicArrayCm(parseEntry(metadataPath))\n\n const sheets: Record<string, WorksheetData> = {}\n const sheetOrder: string[] = []\n const droppedBySheet = new Map<string, string[]>()\n\n const sheetEls = childrenOf(childOf(workbookRoot, \"sheets\"), \"sheet\")\n sheetEls.forEach((el, index) => {\n const name = el.getAttribute(\"name\") ?? `Sheet${index + 1}`\n const rId = relIdOf(el)\n // 找不到关系就按约定路径猜一次 —— 部分生成器的 rels 写得不规范\n const path = (rId && workbookRels.get(rId)?.path) || `xl/worksheets/sheet${index + 1}.xml`\n const dom = parseEntry(path)\n if (!dom?.documentElement) {\n warnings.push(`工作表「${name}」的数据部件缺失(${path}),已跳过`)\n return\n }\n\n const sheetRels = readRels(parseEntry, path)\n const id = `sheet-${index + 1}`\n const { sheet, dropped } = parseSheetXml(dom.documentElement, {\n sharedStrings,\n styleIdOf,\n quotePrefix: parsedStyles.quotePrefix,\n sheetKey: id,\n stats,\n warnings,\n sheetName: name,\n dynamicArrayCm,\n imageOf: (imageRelId) => {\n const target = sheetRels.get(imageRelId)?.path\n const mime = target ? imageMimeOf(target) : undefined\n const bytes = target && mime ? entries.read(target) : null\n return bytes && mime ? bytesToDataUrl(bytes, mime) : undefined\n },\n })\n sheet.id = id\n sheet.name = name\n const state = el.getAttribute(\"state\")\n if (state === \"hidden\") sheet.hidden = 1\n else if (state === \"veryHidden\") sheet.hidden = 2\n sheets[id] = sheet\n sheetOrder.push(id)\n stats.sheets++\n if (dropped.length) droppedBySheet.set(name, dropped)\n })\n\n if (!sheetOrder.length) {\n throw new Error(\"xlsx 里没有可读的工作表\")\n }\n\n /* --------------------- 如实报告丢了什么 --------------------- */\n\n for (const [name, dropped] of droppedBySheet) {\n warnings.push(`工作表「${name}」的${dropped.join(\"、\")}未随导入保留(本实现不解析这些部件)`)\n for (const label of dropped) stats[`dropped:${label}`] = (stats[`dropped:${label}`] ?? 0) + 1\n }\n\n const entryPaths = entries.list()\n for (const { pattern, label } of ENTRY_DROPPED_PARTS) {\n if (entryPaths.some((p) => pattern.test(p))) {\n warnings.push(`${label}未随导入保留(本实现不解析这些部件)`)\n stats[`dropped:${label}`] = (stats[`dropped:${label}`] ?? 0) + 1\n }\n }\n if (parsedStyles.themeColorCount) {\n warnings.push(\n `${parsedStyles.themeColorCount} 处颜色引用了文档主题(theme),已按默认色显示 —— ` +\n \"主题色需要解析 theme1.xml 并做 tint 变换,本实现不做,猜一个颜色比不给更糟\",\n )\n stats.themeColors = parsedStyles.themeColorCount\n }\n if (stats.dataTables) {\n warnings.push(\n `${stats.dataTables} 处模拟运算表(数据表)只保留了计算结果:Univer 不计算模拟运算表,` +\n \"引用的输入单元格等定义没有导入,改了源数据结果不会跟着变\",\n )\n }\n\n /* ------------------------------ 工作簿 ------------------------------ */\n\n const title = textOf(childOf(parseEntry(\"docProps/core.xml\")?.documentElement, \"title\"))\n const workbook: WorkbookData = {\n id: `import-${Date.now().toString(36)}`,\n name: options.name ?? (title || \"导入的工作簿\"),\n sheetOrder,\n sheets,\n styles: styleMap,\n ...(date1904 ? { dateSystem: \"date1904\" as const } : {}),\n }\n\n return { workbook, warnings, stats }\n}\n\n/* ============================ 共享字符串 ============================ */\n\n/**\n * `<si>` 的取文本:纯 `<t>` 或富文本 `<r><t>` 都收,注音 `<rPh>` 要排除 ——\n * 它是给日文假名标注用的,混进正文就成了重复文字。\n */\nfunction parseSharedStrings(dom: Document | null): string[] {\n const out: string[] = []\n for (const si of childrenOf(dom?.documentElement, \"si\")) {\n const direct = childOf(si, \"t\")\n if (direct) {\n out.push(textOf(direct))\n continue\n }\n let text = \"\"\n for (const run of childrenOf(si, \"r\")) text += textOf(childOf(run, \"t\"))\n out.push(text)\n }\n return out\n}\n\n/* ========================== 关系表与元数据 ========================== */\n\nconst REL_NS = \"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"\n\nfunction relIdOf(el: Element): string | null {\n return el.getAttribute(\"r:id\") ?? el.getAttributeNS?.(REL_NS, \"id\") ?? null\n}\n\n/**\n * 某个部件的关系表:rId → { 类型, 包内路径 }。\n * Target 相对部件所在目录(可以带 `../`),也可能是从包根起的 `/xl/...`。\n */\nfunction readRels(\n parseEntry: (path: string) => Document | null,\n partPath: string,\n): Map<string, { type: string; path: string }> {\n const slash = partPath.lastIndexOf(\"/\")\n const dir = slash < 0 ? \"\" : partPath.slice(0, slash)\n const out = new Map<string, { type: string; path: string }>()\n const dom = parseEntry(`${dir ? `${dir}/` : \"\"}_rels/${partPath.slice(slash + 1)}.rels`)\n for (const rel of childrenOf(dom?.documentElement, \"Relationship\")) {\n const id = rel.getAttribute(\"Id\")\n const target = rel.getAttribute(\"Target\")\n if (!id || !target || rel.getAttribute(\"TargetMode\") === \"External\") continue\n const segments = target.startsWith(\"/\") ? [] : dir.split(\"/\").filter(Boolean)\n for (const part of target.split(\"/\")) {\n if (part === \"..\") segments.pop()\n else if (part && part !== \".\") segments.push(part)\n }\n out.set(id, { type: rel.getAttribute(\"Type\") ?? \"\", path: segments.join(\"/\") })\n }\n return out\n}\n\n/**\n * metadata.xml → 代表动态数组的 `cm` 下标(从 1 起)。\n *\n * 链路:cellMetadata 第 cm 个 bk 的 `<rc t v>` → metadataTypes 第 t 个(从 1 起)须是 XLDAPR\n * → futureMetadata[XLDAPR] 第 v 个 bk(从 0 起)里 `dynamicArrayProperties@fDynamic` 为 1。\n */\nfunction parseDynamicArrayCm(dom: Document | null): Set<number> {\n const out = new Set<number>()\n const root = dom?.documentElement\n if (!root) return out\n const typeNames = childrenOf(childOf(root, \"metadataTypes\"), \"metadataType\").map((el) =>\n el.getAttribute(\"name\"),\n )\n const future = childrenOf(root, \"futureMetadata\").find(\n (el) => el.getAttribute(\"name\") === \"XLDAPR\",\n )\n const dynamic = childrenOf(future, \"bk\").map((bk) =>\n childrenOf(childOf(bk, \"extLst\"), \"ext\").some((ext) =>\n boolAttr(childOf(ext, \"dynamicArrayProperties\"), \"fDynamic\"),\n ),\n )\n childrenOf(childOf(root, \"cellMetadata\"), \"bk\").forEach((bk, index) => {\n const rc = childOf(bk, \"rc\")\n const t = intAttr(rc, \"t\")\n const v = intAttr(rc, \"v\")\n if (t !== undefined && v !== undefined && typeNames[t - 1] === \"XLDAPR\" && dynamic[v]) {\n out.add(index + 1)\n }\n })\n return out\n}\n\n/* ============================== 工作表 ============================== */\n\ninterface SheetParseContext {\n sharedStrings: string[]\n styleIdOf: (xfIndex: number | undefined) => string | undefined\n quotePrefix: boolean[]\n /** 共享公式 si 的命名空间:xlsx 的 si 只在表内唯一,快照是工作簿级的 */\n sheetKey: string\n stats: Record<string, number>\n warnings: string[]\n sheetName: string\n /** 代表动态数组的单元格 `cm` 下标,见 `parseDynamicArrayCm` */\n dynamicArrayCm: Set<number>\n /** 本表关系里的图片 → data URL。读不到或浏览器画不出来的格式返回 undefined */\n imageOf: (relId: string) => string | undefined\n}\n\nfunction parseSheetXml(\n root: Element,\n ctx: SheetParseContext,\n): { sheet: WorksheetData; dropped: string[] } {\n const sheet: WorksheetData = {}\n\n parseSheetProperties(root, sheet)\n parseSheetViews(root, sheet)\n parseColumns(root, sheet, ctx)\n const { maxRow, maxCol } = parseSheetData(root, sheet, ctx)\n parseMerges(root, sheet, ctx)\n parseBackgroundPicture(root, sheet, ctx)\n\n // Univer 的网格尺寸下限(默认 1000×20),数据更大就放大到装得下\n sheet.rowCount = Math.max(1000, maxRow + 1)\n sheet.columnCount = Math.max(20, maxCol + 1)\n\n const dropped = Object.entries(SHEET_DROPPED_ELEMENTS)\n .filter(([tag]) => root.getElementsByTagName(tag).length > 0)\n .map(([, label]) => label)\n\n return { sheet, dropped }\n}\n\n/** sheetPr(标签颜色)与 sheetFormatPr(默认行高列宽) */\nfunction parseSheetProperties(root: Element, sheet: WorksheetData): void {\n const tabColor = childOf(childOf(root, \"sheetPr\"), \"tabColor\")?.getAttribute(\"rgb\")\n if (tabColor && /^[0-9a-fA-F]{8}$/.test(tabColor)) sheet.tabColor = `#${tabColor.slice(2)}`\n\n const formatPr = childOf(root, \"sheetFormatPr\")\n const rowHeight = floatAttr(formatPr, \"defaultRowHeight\")\n if (rowHeight !== undefined) sheet.defaultRowHeight = pointsToPx(rowHeight)\n const colWidth = floatAttr(formatPr, \"defaultColWidth\")\n if (colWidth !== undefined) sheet.defaultColumnWidth = columnWidthToPx(colWidth)\n}\n\n/** sheetViews:冻结窗格、网格线开关、从右向左 */\nfunction parseSheetViews(root: Element, sheet: WorksheetData): void {\n const view = childOf(childOf(root, \"sheetViews\"), \"sheetView\")\n if (!view) return\n if (view.getAttribute(\"showGridLines\") === \"0\") sheet.showGridlines = 0\n if (boolAttr(view, \"rightToLeft\")) sheet.rightToLeft = 1\n\n const pane = childOf(view, \"pane\")\n if (pane && pane.getAttribute(\"state\") === \"frozen\") {\n const xSplit = intAttr(pane, \"xSplit\") ?? 0\n const ySplit = intAttr(pane, \"ySplit\") ?? 0\n if (xSplit > 0 || ySplit > 0) {\n sheet.freeze = { xSplit, ySplit, startRow: ySplit, startColumn: xSplit }\n }\n }\n}\n\n/**\n * cols:`<col min max .../>` 是区间定义,快照的 columnData 是逐列的。\n * 铺满整表的区间(min=1 且 max≥16384)其实是「默认列宽」,落到\n * defaultColumnWidth 而不是展开 16384 个条目。\n */\nfunction parseColumns(root: Element, sheet: WorksheetData, ctx: SheetParseContext): void {\n const MAX_EXCEL_COLUMNS = 16384\n const columnData: Record<number, NonNullable<WorksheetData[\"columnData\"]>[number]> = {}\n\n for (const col of childrenOf(childOf(root, \"cols\"), \"col\")) {\n const min = intAttr(col, \"min\")\n const max = intAttr(col, \"max\")\n if (min === undefined || max === undefined || max < min) continue\n\n const width = floatAttr(col, \"width\")\n const hidden = boolAttr(col, \"hidden\")\n const styleId = ctx.styleIdOf(intAttr(col, \"style\"))\n\n if (min === 1 && max >= MAX_EXCEL_COLUMNS) {\n if (width !== undefined) sheet.defaultColumnWidth = columnWidthToPx(width)\n continue\n }\n // 防御异常文件:单个区间超过 2000 列还带样式的,展开会把快照撑爆\n const end = Math.min(max, min + 2000)\n if (end < max) {\n ctx.warnings.push(\n `工作表「${ctx.sheetName}」有跨 ${max - min + 1} 列的列定义,仅保留前 ${end - min + 1} 列的宽度/样式`,\n )\n }\n for (let i = min - 1; i < end; i++) {\n const entry: NonNullable<WorksheetData[\"columnData\"]>[number] = {}\n if (width !== undefined) entry.w = columnWidthToPx(width)\n if (hidden) entry.hd = 1\n if (styleId) entry.s = styleId\n if (Object.keys(entry).length) columnData[i] = entry\n }\n }\n\n if (Object.keys(columnData).length) sheet.columnData = columnData\n}\n\n/** mergeCells → mergeData */\nfunction parseMerges(root: Element, sheet: WorksheetData, ctx: SheetParseContext): void {\n const merges: CellRange[] = []\n for (const el of childrenOf(childOf(root, \"mergeCells\"), \"mergeCell\")) {\n const range = parseRange(el.getAttribute(\"ref\") ?? \"\")\n if (range) merges.push(range)\n }\n if (merges.length) {\n sheet.mergeData = merges\n ctx.stats.merges += merges.length\n }\n}\n\n/** `<picture r:id>`:平铺的工作表背景图,存成 data URL 跟着快照走 */\nfunction parseBackgroundPicture(root: Element, sheet: WorksheetData, ctx: SheetParseContext): void {\n const picture = childOf(root, \"picture\")\n if (!picture) return\n const relId = relIdOf(picture)\n const source = relId ? ctx.imageOf(relId) : undefined\n if (source) {\n sheet.backgroundImage = { source, imageSourceType: \"BASE64\" }\n ctx.stats.backgroundImages = (ctx.stats.backgroundImages ?? 0) + 1\n } else {\n ctx.warnings.push(\n `工作表「${ctx.sheetName}」的背景图读不到或格式不支持(只认 png / jpg / gif / bmp),已跳过`,\n )\n }\n}\n\n/** sheetData:行属性 + 单元格。返回数据范围,供 rowCount/columnCount 兜底 */\nfunction parseSheetData(\n root: Element,\n sheet: WorksheetData,\n ctx: SheetParseContext,\n): { maxRow: number; maxCol: number } {\n const cellData: Matrix<CellData> = {}\n const rowData: Record<number, NonNullable<WorksheetData[\"rowData\"]>[number]> = {}\n let maxRow = -1\n let maxCol = -1\n\n let cursorRow = -1\n for (const rowEl of childrenOf(childOf(root, \"sheetData\"), \"row\")) {\n // r 属性可省略(省略时接在上一行后面)\n const r = (intAttr(rowEl, \"r\") ?? cursorRow + 2) - 1\n cursorRow = r\n if (r < 0) continue\n\n const meta: NonNullable<WorksheetData[\"rowData\"]>[number] = {}\n const height = floatAttr(rowEl, \"ht\")\n if (height !== undefined && boolAttr(rowEl, \"customHeight\")) meta.h = pointsToPx(height)\n if (boolAttr(rowEl, \"hidden\")) meta.hd = 1\n if (boolAttr(rowEl, \"customFormat\")) {\n const styleId = ctx.styleIdOf(intAttr(rowEl, \"s\"))\n if (styleId) meta.s = styleId\n }\n if (Object.keys(meta).length) {\n rowData[r] = meta\n if (r > maxRow) maxRow = r\n }\n\n let cursorCol = -1\n for (const cellEl of childrenOf(rowEl, \"c\")) {\n const ref = cellEl.getAttribute(\"r\")\n const parsed = ref ? parseCellRef(ref) : undefined\n const c = parsed ? parsed.column : cursorCol + 1\n cursorCol = c\n\n const cell = parseCell(cellEl, ctx)\n if (!cell) continue\n matrixRow(cellData, r)[c] = cell\n ctx.stats.cells++\n if (r > maxRow) maxRow = r\n if (c > maxCol) maxCol = c\n }\n }\n\n if (Object.keys(cellData).length) sheet.cellData = cellData\n if (Object.keys(rowData).length) sheet.rowData = rowData\n return { maxRow, maxCol }\n}\n\n/** 一个 `<c>` → CellData。空格(没值没公式没样式)返回 undefined */\nfunction parseCell(el: Element, ctx: SheetParseContext): CellData | undefined {\n const cell: CellData = {}\n\n const xfIndex = intAttr(el, \"s\")\n const styleId = ctx.styleIdOf(xfIndex)\n if (styleId) cell.s = styleId\n\n parseCellFormula(el, cell, ctx)\n parseCellValue(el, cell, ctx, xfIndex)\n\n return Object.keys(cell).length ? cell : undefined\n}\n\n/**\n * `<f>`:普通 / 共享(t=\"shared\")/ 数组(t=\"array\")/ 模拟运算表(t=\"dataTable\")。\n *\n * 数组和模拟运算表记进 `ft`,导出时据此还原;共享公式靠 `si` 分组就够了,不另标。\n * 动态数组在文件里也是 t=\"array\",区别在单元格的 `cm` 指向 XLDAPR 元数据。\n */\nfunction parseCellFormula(el: Element, cell: CellData, ctx: SheetParseContext): void {\n const f = childOf(el, \"f\")\n if (!f) return\n\n const text = textOf(f)\n if (text) {\n cell.f = `=${text}`\n ctx.stats.formulas++\n }\n\n const type = f.getAttribute(\"t\")\n if (type === \"shared\") {\n const si = f.getAttribute(\"si\")\n // xlsx 的 si 只在本表内唯一,快照是工作簿级的 —— 加表前缀隔离\n if (si !== null) {\n cell.si = `${ctx.sheetKey}-${si}`\n ctx.stats.sharedFormulas++\n }\n } else if (type === \"array\") {\n cell.ft = FORMULA_TYPE.ARRAY\n const ref = f.getAttribute(\"ref\")\n if (ref) cell.ref = ref\n const cm = intAttr(el, \"cm\")\n if (cm !== undefined && ctx.dynamicArrayCm.has(cm)) {\n cell.fd = 1\n ctx.stats.dynamicArrays = (ctx.stats.dynamicArrays ?? 0) + 1\n }\n } else if (type === \"dataTable\") {\n cell.ft = FORMULA_TYPE.DATA_TABLE\n ctx.stats.dataTables = (ctx.stats.dataTables ?? 0) + 1\n }\n}\n\n/** 值与类型。t 缺省是 \"n\"(数字) */\nfunction parseCellValue(\n el: Element,\n cell: CellData,\n ctx: SheetParseContext,\n xfIndex: number | undefined,\n): void {\n const type = el.getAttribute(\"t\") ?? \"n\"\n\n if (type === \"inlineStr\") {\n const is = childOf(el, \"is\")\n const direct = childOf(is, \"t\")\n let text = direct ? textOf(direct) : \"\"\n if (!direct) for (const run of childrenOf(is, \"r\")) text += textOf(childOf(run, \"t\"))\n cell.v = text\n cell.t = CELL_TYPE.STRING\n return\n }\n\n const v = childOf(el, \"v\")\n if (!v) return\n const raw = textOf(v)\n\n switch (type) {\n case \"s\": {\n const text = ctx.sharedStrings[Number.parseInt(raw, 10)]\n if (text === undefined) {\n ctx.warnings.push(\n `工作表「${ctx.sheetName}」有单元格引用了不存在的共享字符串 #${raw},已置空`,\n )\n return\n }\n cell.v = text\n cell.t = forceString(ctx, xfIndex) ? CELL_TYPE.FORCE_STRING : CELL_TYPE.STRING\n return\n }\n case \"str\":\n cell.v = raw\n cell.t = CELL_TYPE.STRING\n return\n case \"b\":\n cell.v = raw === \"1\" || raw === \"true\"\n cell.t = CELL_TYPE.BOOLEAN\n return\n case \"e\":\n // 公式错误值(#DIV/0! 等)。保留文本,Univer 重算公式时会自己得出新结果\n cell.v = raw\n cell.t = CELL_TYPE.STRING\n return\n default: {\n const n = Number.parseFloat(raw)\n if (Number.isFinite(n)) {\n cell.v = n\n cell.t = CELL_TYPE.NUMBER\n } else if (raw) {\n cell.v = raw\n cell.t = CELL_TYPE.STRING\n }\n }\n }\n}\n\n/** 该 xf 是否带 quotePrefix(Excel 的「以文本形式存储」,↔ FORCE_STRING) */\nfunction forceString(ctx: SheetParseContext, xfIndex: number | undefined): boolean {\n return xfIndex !== undefined && ctx.quotePrefix[xfIndex] === true\n}\n","/**\n * xlsx / csv 导入的入口 —— 把「拿到手的东西」变成 Univer 快照。\n *\n * 分层和导出侧对称:`parse.ts` / `csv-parse.ts` 是纯函数(解压、XML 解析\n * 都注入),本文件负责脏活 —— 解 zip(fflate)、缺省 DOMParser(浏览器原生)、\n * 解码文本(UTF-8 优先,失败退 GBK)、从 URL 拉字节、按扩展名和魔数嗅探格式。\n *\n * ```ts\n * import { importSheetSource } from \"@4399ywkf/editor/xlsx\"\n *\n * const { workbook, warnings } = await importSheetSource(file)\n * univerAPI.createWorkbook(workbook)\n * if (warnings.length) toast(warnings.join(\"\\n\")) // ← 如实报告丢了什么\n * ```\n *\n * Node 侧没有全局 DOMParser,`importXlsx` 显式传 `@xmldom/xmldom` 的即可。\n */\n\nimport { unzipSync } from \"fflate\"\n\nimport { type CsvParseOptions, csvToSnapshot } from \"./csv-parse.ts\"\nimport type { DomParserLike } from \"./dom.ts\"\nimport { type ParseXlsxResult, parseXlsx, type XlsxEntries } from \"./parse.ts\"\nimport type { WorkbookData } from \"./types.ts\"\n\nexport interface ImportSheetResult {\n workbook: WorkbookData\n /** 导入时丢掉/降级了什么。**要展示给用户**,别吞 */\n warnings: string[]\n stats: Record<string, number>\n}\n\nexport interface ImportXlsxOptions {\n /** 不传则用浏览器原生 DOMParser;Node 里传 @xmldom/xmldom 的 */\n DOMParser?: DomParserLike\n /** 快照里的工作簿名。不传则用 File 名或文档属性里的标题 */\n name?: string\n}\n\ntype BinarySource = File | Blob | ArrayBuffer | Uint8Array\n\n/** zip 的魔数 \"PK\\x03\\x04\" —— xlsx 本质是个 zip 包 */\nfunction isZip(bytes: Uint8Array): boolean {\n return bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04\n}\n\nasync function toBytes(source: BinarySource): Promise<Uint8Array> {\n if (source instanceof Uint8Array) return source\n if (source instanceof ArrayBuffer) return new Uint8Array(source)\n return new Uint8Array(await source.arrayBuffer())\n}\n\n/**\n * 字节 → 文本。UTF-8 严格解码优先,失败退 GBK ——\n * 简中环境的 csv 相当一部分是 Excel 直接另存的,编码就是 GBK。\n */\nfunction decodeText(bytes: Uint8Array, warnings: string[]): string {\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes)\n } catch {\n try {\n const text = new TextDecoder(\"gbk\").decode(bytes)\n warnings.push(\"文件不是 UTF-8 编码,已按 GBK 解码 —— 如出现乱码请转成 UTF-8 后重新导入\")\n return text\n } catch {\n // 连 GBK 解码器都没有(部分 Node 构建),退回宽松 UTF-8,坏字符变 �\n return new TextDecoder(\"utf-8\").decode(bytes)\n }\n }\n}\n\nfunction defaultDomParser(): DomParserLike {\n const DP = (globalThis as { DOMParser?: DomParserLike }).DOMParser\n if (!DP) {\n throw new Error(\n \"当前环境没有 DOMParser:浏览器外使用请在 options 里注入(如 @xmldom/xmldom 的 DOMParser)\",\n )\n }\n return DP\n}\n\n/** File 才有名字;Blob/字节没有 */\nfunction nameOf(source: BinarySource | string): string | undefined {\n if (typeof source === \"string\") {\n const last = source.split(/[?#]/)[0]?.split(\"/\").pop()\n return last ? decodeURIComponent(last) : undefined\n }\n return typeof File !== \"undefined\" && source instanceof File ? source.name : undefined\n}\n\n/* ------------------------------- xlsx ------------------------------- */\n\n/** .xlsx 字节 → Univer 快照。纯本地解析,文档不出内网 */\nexport async function importXlsx(\n source: BinarySource,\n options: ImportXlsxOptions = {},\n): Promise<ImportSheetResult> {\n const bytes = await toBytes(source)\n if (!isZip(bytes)) {\n throw new Error(\"这不是 xlsx 文件(缺少 zip 魔数)。.xls 老格式请先在 Excel/WPS 里另存为 .xlsx\")\n }\n\n let files: Record<string, Uint8Array>\n try {\n files = unzipSync(bytes)\n } catch (e) {\n throw new Error(`xlsx 解压失败:${e instanceof Error ? e.message : String(e)}`)\n }\n\n const entries: XlsxEntries = {\n read: (path) => files[path] ?? null,\n list: () => Object.keys(files),\n }\n const result: ParseXlsxResult = parseXlsx(entries, {\n DOMParser: options.DOMParser ?? defaultDomParser(),\n name: options.name ?? stripExtension(nameOf(source)),\n })\n return result\n}\n\n/* -------------------------------- csv -------------------------------- */\n\nexport interface ImportCsvOptions extends CsvParseOptions {}\n\n/** csv/tsv 文本或字节 → Univer 快照 */\nexport async function importCsv(\n source: BinarySource | string,\n options: ImportCsvOptions = {},\n): Promise<ImportSheetResult> {\n const warnings: string[] = []\n const text = typeof source === \"string\" ? source : decodeText(await toBytes(source), warnings)\n const name = typeof source === \"string\" ? undefined : stripExtension(nameOf(source))\n const result = csvToSnapshot(text, { name, ...options })\n return {\n workbook: result.workbook,\n warnings: [...warnings, ...result.warnings],\n stats: result.stats as unknown as Record<string, number>,\n }\n}\n\n/* --------------------------- 统一入口(嗅探) --------------------------- */\n\nexport interface ImportSheetSourceResult extends ImportSheetResult {\n /** 实际按哪种格式解析的 */\n format: \"xlsx\" | \"csv\" | \"tsv\"\n}\n\n/**\n * `DocumentView` 的 `source` → Univer 快照:URL / File / Blob 都收。\n *\n * 判定顺序:扩展名(.csv/.tsv 显式声明就信)→ zip 魔数(xlsx 本质是 zip)\n * → 都不是则按 csv 试 —— 文本表格没有魔数,这是唯一诚实的兜底。\n */\nexport async function importSheetSource(\n source: string | Blob | File,\n options: ImportXlsxOptions & ImportCsvOptions = {},\n): Promise<ImportSheetSourceResult> {\n const name = nameOf(source)\n const bytes = typeof source === \"string\" ? await fetchBytes(source) : await toBytes(source)\n\n const ext = /\\.([a-z0-9]+)$/i.exec(name ?? \"\")?.[1]?.toLowerCase()\n if (ext === \"csv\" || ext === \"tsv\") {\n const delimiter = options.delimiter ?? (ext === \"tsv\" ? \"\\t\" : \",\")\n const result = await importCsv(bytes, {\n ...options,\n delimiter,\n name: options.name ?? stripExtension(name),\n })\n return { ...result, format: ext }\n }\n\n if (isZip(bytes)) {\n const result = await importXlsx(bytes, {\n ...options,\n name: options.name ?? stripExtension(name),\n })\n return { ...result, format: \"xlsx\" }\n }\n\n if (ext === \"xlsx\" || ext === \"xls\") {\n throw new Error(\n ext === \"xls\"\n ? \".xls 是二进制老格式,本实现不解析 —— 请先在 Excel/WPS 里另存为 .xlsx\"\n : \"文件扩展名是 .xlsx 但内容不是 zip 包,文件可能已损坏\",\n )\n }\n\n const result = await importCsv(bytes, { ...options, name: options.name ?? stripExtension(name) })\n return { ...result, format: \"csv\" }\n}\n\nasync function fetchBytes(url: string): Promise<Uint8Array> {\n const res = await fetch(url)\n if (!res.ok) throw new Error(`拉取表格失败:HTTP ${res.status}(${url})`)\n return new Uint8Array(await res.arrayBuffer())\n}\n\nfunction stripExtension(name: string | undefined): string | undefined {\n return name?.replace(/\\.[a-z0-9]+$/i, \"\") || undefined\n}\n"]}