@4399ywkf/editor 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/README.md +58 -27
- package/dist/SheetView-YFK7BUS5.js +3 -0
- package/dist/{SheetView-SDBRSTVS.js.map → SheetView-YFK7BUS5.js.map} +1 -1
- package/dist/{chunk-KRP5V7VF.js → chunk-2DI4FJPC.js} +10 -3
- package/dist/chunk-2DI4FJPC.js.map +1 -0
- package/dist/{chunk-DGUNVCOM.js → chunk-3QTRZBIK.js} +111 -26
- package/dist/chunk-3QTRZBIK.js.map +1 -0
- package/dist/chunk-JWHQF2CZ.js +257 -0
- package/dist/chunk-JWHQF2CZ.js.map +1 -0
- package/dist/{chunk-WF7PIIFR.js → chunk-JZ67Q3QI.js} +4 -4
- package/dist/chunk-JZ67Q3QI.js.map +1 -0
- package/dist/{chunk-SBTKDJAL.js → chunk-SDVGDHC4.js} +45 -3
- package/dist/chunk-SDVGDHC4.js.map +1 -0
- package/dist/{chunk-HPSPOM2O.js → chunk-XB6FEC4I.js} +3 -3
- package/dist/chunk-XB6FEC4I.js.map +1 -0
- package/dist/{csv-parse-D0zTBvDB.d.ts → csv-parse-DXlwzoZ6.d.ts} +28 -1
- package/dist/csv.d.ts +2 -2
- package/dist/csv.js +4 -4
- package/dist/import-O7RUERND.js +6 -0
- package/dist/{import-GVZDLWA2.js.map → import-O7RUERND.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/pdf.d.ts +1 -1
- package/dist/pptx.d.ts +1 -1
- package/dist/{registry-CYKivRDh.d.ts → registry-BQ5T1Yko.d.ts} +9 -16
- package/dist/sheet-runtime.d.ts +10 -8
- package/dist/sheet-runtime.js +6 -14
- package/dist/sheet-runtime.js.map +1 -1
- package/dist/sheet.d.ts +4 -3
- package/dist/sheet.js +1 -1
- package/dist/xlsx.d.ts +12 -11
- package/dist/xlsx.js +121 -32
- package/dist/xlsx.js.map +1 -1
- package/package.json +71 -27
- package/dist/SheetView-SDBRSTVS.js +0 -3
- package/dist/chunk-DGUNVCOM.js.map +0 -1
- package/dist/chunk-HPSPOM2O.js.map +0 -1
- package/dist/chunk-KRP5V7VF.js.map +0 -1
- package/dist/chunk-SBTKDJAL.js.map +0 -1
- package/dist/chunk-SYCK6Y5F.js +0 -89
- package/dist/chunk-SYCK6Y5F.js.map +0 -1
- package/dist/chunk-WF7PIIFR.js.map +0 -1
- 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
|
|
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` / `
|
|
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`
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
246
|
+
**能保住的**:多工作表(顺序 / 隐藏 / 深度隐藏)、值与类型、
|
|
247
|
+
公式(普通 / 共享 / 数组 / 动态数组)、1904 日期系统、数字格式(含内建表)、
|
|
248
|
+
字体 / 颜色 / 填充 / 边框 / 对齐 / 换行 / 旋转 / 缩小字体填充、会计用下划线、合并单元格、
|
|
249
|
+
行高列宽、隐藏行列、冻结窗格、网格线、标签颜色、工作表背景图(png / jpg / gif / bmp)、
|
|
250
|
+
`quotePrefix`(强制文本)。
|
|
251
|
+
|
|
252
|
+
1904 日期系统只在工作簿上标 `dateSystem`、不改数值 —— Univer 的显示、日期编辑和公式
|
|
253
|
+
都按它解释序列号。
|
|
237
254
|
|
|
238
255
|
**保不住的逐个点名**(进 `warnings`):图片 / 图表、透视表、条件格式、数据校验、
|
|
239
|
-
|
|
256
|
+
筛选、超链接、批注、宏、主题色、模拟运算表的定义(只留计算结果)。编辑器能新建这些
|
|
257
|
+
(图表和透视表除外),但 xlsx 里原有的不会进快照。和导出侧一样 ——
|
|
240
258
|
**打开文件才发现少了东西,远比导入时被告知糟糕**。
|
|
241
259
|
|
|
242
260
|
`.xls` 是老的二进制复合文档,明确不解析:报错会直接告诉用户「另存为 .xlsx」,
|
|
@@ -417,6 +435,19 @@ import "@4399ywkf/editor/styles" // dist/style.css,168KB
|
|
|
417
435
|
包内 55 个 scss 在构建期编译并拼成单文件,JS 产物里**不残留任何 scss 导入** ——
|
|
418
436
|
消费方无需配置 sass loader,SSR 也不会因为 `import "x.scss"` 报错。
|
|
419
437
|
|
|
438
|
+
## 依赖版本:`@tiptap/*` 必须同版本
|
|
439
|
+
|
|
440
|
+
Tiptap 各包之间用**精确版本**的 peerDependencies 互相钉死,本包把全部 `@tiptap/*`
|
|
441
|
+
统一声明为同一个范围(当前 `^3.30.0`,由 `src/tiptap-versions.test.ts` 守着)。
|
|
442
|
+
业务仓库自己也引了 `@tiptap/core` / `@tiptap/react` 时,版本必须落在同一个范围里,
|
|
443
|
+
否则 pnpm 会把一部分去重到你锁文件里的旧版本、给另一部分另拉新版本,构建时报
|
|
444
|
+
`Export attrsEqual doesn't exist in target module` 这类错。升级本包后在业务仓库跑:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
pnpm update -r "@tiptap/*" # 整个 tiptap 家族对齐到一个版本
|
|
448
|
+
pnpm ls -r "@tiptap/core" # 只应出现一个版本
|
|
449
|
+
```
|
|
450
|
+
|
|
420
451
|
## 协同
|
|
421
452
|
|
|
422
453
|
`doc` 走 yjs。注入扩展时注意:**所有客户端必须注入同一组扩展**,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"SheetView-
|
|
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-
|
|
130
|
-
//# sourceMappingURL=chunk-
|
|
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-
|
|
2
|
-
import { H_ALIGN, V_ALIGN, CELL_TYPE, csvToSnapshot, WRAP } from './chunk-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
315
|
-
const
|
|
316
|
-
|
|
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
|
|
329
|
-
|
|
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
|
-
|
|
351
|
-
|
|
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-
|
|
711
|
-
//# sourceMappingURL=chunk-
|
|
795
|
+
//# sourceMappingURL=chunk-3QTRZBIK.js.map
|
|
796
|
+
//# sourceMappingURL=chunk-3QTRZBIK.js.map
|