@a3s-lab/office 0.28.0 → 0.29.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 +27 -1
- package/dist/0~1403.js +1 -1
- package/dist/0~4980.js +1 -1
- package/dist/0~5093.js +64 -5
- package/dist/0~7043.js +241 -241
- package/dist/0~7048.js +1 -1
- package/dist/0~7614.js +1 -1
- package/dist/0~document-editor.js +433 -10
- package/dist/0~presentation-editor.js +1 -1
- package/dist/0~spreadsheet-editor.js +1 -2
- package/dist/0~work-docx-export.js +141 -3
- package/dist/0~work-docx-import.js +5 -3
- package/dist/0~work-office-diagnostics.js +46 -3
- package/dist/0~work-pptx-export.js +1 -1
- package/dist/0~work-pptx-import.js +1 -1
- package/dist/0~work-presentation-charts.js +1 -1
- package/dist/1544.js +1 -1
- package/dist/4104.js +2 -2
- package/dist/4121.js +1510 -0
- package/dist/6282.js +59 -684
- package/dist/8715.js +1 -1
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +9 -0
- package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +5 -2
- package/dist/internal/features/work/editors/document-font-dialog-run-border-model.d.ts +24 -0
- package/dist/internal/features/work/editors/document-font-dialog-run-border-section.d.ts +10 -0
- package/dist/internal/features/work/work-document-character-formatting.d.ts +4 -0
- package/dist/internal/features/work/work-document-format-changes.d.ts +1 -0
- package/dist/internal/features/work/work-document-run-border.d.ts +11 -0
- package/dist/internal/features/work/work-document-word-line-metrics.d.ts +1 -0
- package/dist/internal/features/work/work-docx-run-border-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-run-border-export.d.ts +17 -0
- package/dist/internal/features/work/work-docx-run-border.d.ts +20 -0
- package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +2 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +31 -0
- package/docs/latest/en/browser-editor-architecture.md +22 -0
- package/package.json +4 -1
- package/dist/5184.js +0 -662
- package/dist/9424.js +0 -16
package/dist/5184.js
DELETED
|
@@ -1,662 +0,0 @@
|
|
|
1
|
-
import jszip from "jszip";
|
|
2
|
-
const WORK_TEMPLATES = [
|
|
3
|
-
{
|
|
4
|
-
id: 'blank-document',
|
|
5
|
-
kind: 'document',
|
|
6
|
-
name: '空白文字',
|
|
7
|
-
description: '从一张干净的 A4 页面开始',
|
|
8
|
-
accent: '#2f6fed'
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
id: 'project-brief',
|
|
12
|
-
kind: 'document',
|
|
13
|
-
name: '项目方案',
|
|
14
|
-
description: '目标、范围、里程碑与风险',
|
|
15
|
-
accent: '#536de2'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
id: 'text-effects',
|
|
19
|
-
kind: 'document',
|
|
20
|
-
name: '文字效果',
|
|
21
|
-
description: '空心、阴影、阳文与阴文',
|
|
22
|
-
accent: '#6b5bd2'
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'blank-markdown',
|
|
26
|
-
kind: 'markdown',
|
|
27
|
-
name: '空白 Markdown',
|
|
28
|
-
description: '用轻量标记编写结构化内容',
|
|
29
|
-
accent: '#586574'
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: 'blank-spreadsheet',
|
|
33
|
-
kind: 'spreadsheet',
|
|
34
|
-
name: '空白表格',
|
|
35
|
-
description: '公式、表格、筛选与多工作表',
|
|
36
|
-
accent: '#16a36a'
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: 'quarterly-plan',
|
|
40
|
-
kind: 'spreadsheet',
|
|
41
|
-
name: '季度计划',
|
|
42
|
-
description: '目标进度与预算跟踪',
|
|
43
|
-
accent: '#168f72'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: 'blank-presentation',
|
|
47
|
-
kind: 'presentation',
|
|
48
|
-
name: '空白演示',
|
|
49
|
-
description: '16:9 宽屏演示文稿',
|
|
50
|
-
accent: '#e16b3d'
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: 'strategy-deck',
|
|
54
|
-
kind: 'presentation',
|
|
55
|
-
name: '策略汇报',
|
|
56
|
-
description: '结论先行的三页汇报',
|
|
57
|
-
accent: '#c85637'
|
|
58
|
-
}
|
|
59
|
-
];
|
|
60
|
-
function createWorkArtifact(templateId) {
|
|
61
|
-
const template = WORK_TEMPLATES.find((item)=>item.id === templateId) ?? WORK_TEMPLATES[0];
|
|
62
|
-
const now = Date.now();
|
|
63
|
-
return {
|
|
64
|
-
id: createWorkId('artifact'),
|
|
65
|
-
kind: template.kind,
|
|
66
|
-
title: initialTitle(template.id, template.kind),
|
|
67
|
-
favorite: false,
|
|
68
|
-
createdAt: now,
|
|
69
|
-
updatedAt: now,
|
|
70
|
-
lastOpenedAt: now,
|
|
71
|
-
revision: 1,
|
|
72
|
-
content: contentForTemplate(template.id)
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function createWorkId(prefix) {
|
|
76
|
-
const random = "u" > typeof crypto && 'function' == typeof crypto.randomUUID ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
77
|
-
return `${prefix}-${random}`;
|
|
78
|
-
}
|
|
79
|
-
function initialTitle(templateId, kind) {
|
|
80
|
-
const titles = {
|
|
81
|
-
'project-brief': '新项目方案',
|
|
82
|
-
'text-effects': '文字效果示例',
|
|
83
|
-
'quarterly-plan': '季度执行计划',
|
|
84
|
-
'strategy-deck': '业务策略汇报'
|
|
85
|
-
};
|
|
86
|
-
if (titles[templateId]) return titles[templateId];
|
|
87
|
-
if ('document' === kind) return '无标题文字';
|
|
88
|
-
if ('markdown' === kind) return '无标题 Markdown';
|
|
89
|
-
if ('spreadsheet' === kind) return '无标题表格';
|
|
90
|
-
return '无标题演示';
|
|
91
|
-
}
|
|
92
|
-
function contentForTemplate(templateId) {
|
|
93
|
-
if ('project-brief' === templateId) return {
|
|
94
|
-
type: 'document',
|
|
95
|
-
pageSize: 'a4',
|
|
96
|
-
html: "<h1>新项目方案</h1><p><strong>负责人:</strong>项目团队 <strong>更新日期:</strong>今天</p><blockquote><p>用一句话说明这项工作的目标,以及完成后会带来什么变化。</p></blockquote><h2>背景与目标</h2><p>描述当前情况、核心问题和可衡量的成功标准。</p><h2>工作范围</h2><ul><li><p>需要完成的关键交付物</p></li><li><p>明确不在本期范围内的事项</p></li></ul><h2>里程碑</h2><ol><li><p>方案确认</p></li><li><p>执行与评审</p></li><li><p>交付与复盘</p></li></ol><h2>风险与决策</h2><p>记录尚未解决的问题、依赖和决策负责人。</p>"
|
|
97
|
-
};
|
|
98
|
-
if ('text-effects' === templateId) return {
|
|
99
|
-
type: 'document',
|
|
100
|
-
pageSize: 'a4',
|
|
101
|
-
html: '<h1>原生文字效果</h1><p>选择下面任一示例并打开字体高级设置,可以组合空心与阴影,或在互斥的阳文和阴文之间切换。</p><h2>可组合效果</h2><p><span data-office-legacy-text-outline="true" data-office-legacy-text-shadow="true">空心 + 阴影</span></p><p><span data-office-legacy-text-outline="true">空心</span></p><p><span data-office-legacy-text-shadow="true">阴影</span></p><h2>互斥效果</h2><p><span data-office-legacy-text-emboss="true">阳文</span></p><p><span data-office-legacy-text-imprint="true">阴文</span></p>'
|
|
102
|
-
};
|
|
103
|
-
if ('quarterly-plan' === templateId) return {
|
|
104
|
-
type: 'spreadsheet',
|
|
105
|
-
sheets: quarterlyPlanSheets()
|
|
106
|
-
};
|
|
107
|
-
if ('strategy-deck' === templateId) return strategyPresentation();
|
|
108
|
-
if ('blank-spreadsheet' === templateId) return {
|
|
109
|
-
type: 'spreadsheet',
|
|
110
|
-
sheets: [
|
|
111
|
-
blankSheet()
|
|
112
|
-
]
|
|
113
|
-
};
|
|
114
|
-
if ('blank-markdown' === templateId) return {
|
|
115
|
-
type: 'markdown',
|
|
116
|
-
markdown: ''
|
|
117
|
-
};
|
|
118
|
-
if ('blank-presentation' === templateId) return {
|
|
119
|
-
type: 'presentation',
|
|
120
|
-
slides: [
|
|
121
|
-
blankSlide()
|
|
122
|
-
]
|
|
123
|
-
};
|
|
124
|
-
return {
|
|
125
|
-
type: 'document',
|
|
126
|
-
pageSize: 'a4',
|
|
127
|
-
html: '<p></p>'
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function blankSheet() {
|
|
131
|
-
return {
|
|
132
|
-
id: createWorkId('sheet'),
|
|
133
|
-
name: '工作表1',
|
|
134
|
-
status: 1,
|
|
135
|
-
order: 0,
|
|
136
|
-
row: 60,
|
|
137
|
-
column: 26,
|
|
138
|
-
data: emptyMatrix(60, 26)
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function quarterlyPlanSheets() {
|
|
142
|
-
const data = emptyMatrix(40, 12);
|
|
143
|
-
data[0][0] = styledCell('季度执行计划', {
|
|
144
|
-
bl: 1,
|
|
145
|
-
fs: 16,
|
|
146
|
-
fc: '#ffffff',
|
|
147
|
-
bg: '#168f72'
|
|
148
|
-
});
|
|
149
|
-
data[2][0] = headerCell('目标');
|
|
150
|
-
data[2][1] = headerCell('负责人');
|
|
151
|
-
data[2][2] = headerCell('一月');
|
|
152
|
-
data[2][3] = headerCell('二月');
|
|
153
|
-
data[2][4] = headerCell('三月');
|
|
154
|
-
data[2][5] = headerCell('完成率');
|
|
155
|
-
data[2][6] = headerCell('状态');
|
|
156
|
-
const rows = [
|
|
157
|
-
[
|
|
158
|
-
'客户洞察报告',
|
|
159
|
-
'林岚',
|
|
160
|
-
1,
|
|
161
|
-
1,
|
|
162
|
-
0,
|
|
163
|
-
'=SUM(C4:E4)/3',
|
|
164
|
-
'进行中'
|
|
165
|
-
],
|
|
166
|
-
[
|
|
167
|
-
'新版发布',
|
|
168
|
-
'周启',
|
|
169
|
-
0.8,
|
|
170
|
-
0.6,
|
|
171
|
-
0,
|
|
172
|
-
'=AVERAGE(C5:E5)',
|
|
173
|
-
'有风险'
|
|
174
|
-
],
|
|
175
|
-
[
|
|
176
|
-
'渠道增长',
|
|
177
|
-
'陈一',
|
|
178
|
-
1,
|
|
179
|
-
0.9,
|
|
180
|
-
0.7,
|
|
181
|
-
'=AVERAGE(C6:E6)',
|
|
182
|
-
'正常'
|
|
183
|
-
],
|
|
184
|
-
[
|
|
185
|
-
'团队能力建设',
|
|
186
|
-
'项目组',
|
|
187
|
-
1,
|
|
188
|
-
1,
|
|
189
|
-
1,
|
|
190
|
-
'=AVERAGE(C7:E7)',
|
|
191
|
-
'已完成'
|
|
192
|
-
]
|
|
193
|
-
];
|
|
194
|
-
rows.forEach((row, rowIndex)=>{
|
|
195
|
-
row.forEach((value, columnIndex)=>{
|
|
196
|
-
data[rowIndex + 3][columnIndex] = styledCell(value, {
|
|
197
|
-
bg: rowIndex % 2 ? '#f7faf9' : '#ffffff',
|
|
198
|
-
...columnIndex >= 2 && columnIndex <= 5 ? {
|
|
199
|
-
ct: {
|
|
200
|
-
fa: '0%',
|
|
201
|
-
t: 'n'
|
|
202
|
-
},
|
|
203
|
-
...'number' == typeof value ? {
|
|
204
|
-
m: `${Math.round(100 * value)}%`
|
|
205
|
-
} : {}
|
|
206
|
-
} : {}
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
return [
|
|
211
|
-
{
|
|
212
|
-
id: createWorkId('sheet'),
|
|
213
|
-
name: '执行看板',
|
|
214
|
-
status: 1,
|
|
215
|
-
order: 0,
|
|
216
|
-
row: 40,
|
|
217
|
-
column: 12,
|
|
218
|
-
data,
|
|
219
|
-
config: {
|
|
220
|
-
columnlen: {
|
|
221
|
-
0: 180,
|
|
222
|
-
1: 96,
|
|
223
|
-
2: 76,
|
|
224
|
-
3: 76,
|
|
225
|
-
4: 76,
|
|
226
|
-
5: 96,
|
|
227
|
-
6: 96
|
|
228
|
-
},
|
|
229
|
-
rowlen: {
|
|
230
|
-
0: 34,
|
|
231
|
-
2: 28
|
|
232
|
-
},
|
|
233
|
-
merge: {
|
|
234
|
-
'0_0': {
|
|
235
|
-
r: 0,
|
|
236
|
-
c: 0,
|
|
237
|
-
rs: 1,
|
|
238
|
-
cs: 7
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
];
|
|
244
|
-
}
|
|
245
|
-
function emptyMatrix(rows, columns) {
|
|
246
|
-
return Array.from({
|
|
247
|
-
length: rows
|
|
248
|
-
}, ()=>Array(columns).fill(null));
|
|
249
|
-
}
|
|
250
|
-
function styledCell(value, style = {}) {
|
|
251
|
-
const formula = 'string' == typeof value && value.startsWith('=') ? value : void 0;
|
|
252
|
-
return {
|
|
253
|
-
v: formula ? void 0 : value,
|
|
254
|
-
m: formula ? '' : String(value),
|
|
255
|
-
f: formula,
|
|
256
|
-
...style
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
function headerCell(value) {
|
|
260
|
-
return styledCell(value, {
|
|
261
|
-
bl: 1,
|
|
262
|
-
fc: '#215446',
|
|
263
|
-
bg: '#dff3ec',
|
|
264
|
-
ht: 0,
|
|
265
|
-
vt: 0
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
function blankSlide() {
|
|
269
|
-
return {
|
|
270
|
-
id: createWorkId('slide'),
|
|
271
|
-
name: '标题幻灯片',
|
|
272
|
-
background: '#ffffff',
|
|
273
|
-
elements: [
|
|
274
|
-
{
|
|
275
|
-
id: createWorkId('element'),
|
|
276
|
-
type: 'text',
|
|
277
|
-
x: 12,
|
|
278
|
-
y: 25,
|
|
279
|
-
width: 76,
|
|
280
|
-
height: 18,
|
|
281
|
-
text: '',
|
|
282
|
-
fontSize: 34,
|
|
283
|
-
color: '#172033',
|
|
284
|
-
fill: 'transparent',
|
|
285
|
-
bold: true,
|
|
286
|
-
align: 'center',
|
|
287
|
-
placeholder: {
|
|
288
|
-
key: 'title',
|
|
289
|
-
type: 'title',
|
|
290
|
-
prompt: '单击添加标题'
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
id: createWorkId('element'),
|
|
295
|
-
type: 'text',
|
|
296
|
-
x: 18,
|
|
297
|
-
y: 49,
|
|
298
|
-
width: 64,
|
|
299
|
-
height: 10,
|
|
300
|
-
text: '',
|
|
301
|
-
fontSize: 17,
|
|
302
|
-
color: '#727b8f',
|
|
303
|
-
fill: 'transparent',
|
|
304
|
-
bold: false,
|
|
305
|
-
align: 'center',
|
|
306
|
-
placeholder: {
|
|
307
|
-
key: 'subtitle',
|
|
308
|
-
type: 'subtitle',
|
|
309
|
-
prompt: '添加副标题'
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
]
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
function strategyPresentation() {
|
|
316
|
-
const slides = [
|
|
317
|
-
{
|
|
318
|
-
id: createWorkId('slide'),
|
|
319
|
-
name: '封面',
|
|
320
|
-
background: '#16213d',
|
|
321
|
-
elements: [
|
|
322
|
-
{
|
|
323
|
-
id: createWorkId('element'),
|
|
324
|
-
type: 'shape',
|
|
325
|
-
x: 8,
|
|
326
|
-
y: 12,
|
|
327
|
-
width: 9,
|
|
328
|
-
height: 3,
|
|
329
|
-
text: '',
|
|
330
|
-
fontSize: 12,
|
|
331
|
-
color: '#ffffff',
|
|
332
|
-
fill: '#ffb15a',
|
|
333
|
-
bold: false,
|
|
334
|
-
align: 'left',
|
|
335
|
-
radius: 2
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
id: createWorkId('element'),
|
|
339
|
-
type: 'text',
|
|
340
|
-
x: 8,
|
|
341
|
-
y: 30,
|
|
342
|
-
width: 72,
|
|
343
|
-
height: 24,
|
|
344
|
-
text: '业务策略汇报',
|
|
345
|
-
fontSize: 38,
|
|
346
|
-
color: '#ffffff',
|
|
347
|
-
fill: 'transparent',
|
|
348
|
-
bold: true,
|
|
349
|
-
align: 'left'
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
id: createWorkId('element'),
|
|
353
|
-
type: 'text',
|
|
354
|
-
x: 8,
|
|
355
|
-
y: 58,
|
|
356
|
-
width: 62,
|
|
357
|
-
height: 10,
|
|
358
|
-
text: '把最重要的结论放在标题中',
|
|
359
|
-
fontSize: 17,
|
|
360
|
-
color: '#b8c4df',
|
|
361
|
-
fill: 'transparent',
|
|
362
|
-
bold: false,
|
|
363
|
-
align: 'left'
|
|
364
|
-
}
|
|
365
|
-
]
|
|
366
|
-
},
|
|
367
|
-
{
|
|
368
|
-
id: createWorkId('slide'),
|
|
369
|
-
name: '核心判断',
|
|
370
|
-
background: '#f7f4ee',
|
|
371
|
-
elements: [
|
|
372
|
-
{
|
|
373
|
-
id: createWorkId('element'),
|
|
374
|
-
type: 'text',
|
|
375
|
-
x: 8,
|
|
376
|
-
y: 10,
|
|
377
|
-
width: 84,
|
|
378
|
-
height: 11,
|
|
379
|
-
text: '01 核心判断',
|
|
380
|
-
fontSize: 15,
|
|
381
|
-
color: '#b44e34',
|
|
382
|
-
fill: 'transparent',
|
|
383
|
-
bold: true,
|
|
384
|
-
align: 'left'
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
id: createWorkId('element'),
|
|
388
|
-
type: 'text',
|
|
389
|
-
x: 8,
|
|
390
|
-
y: 27,
|
|
391
|
-
width: 76,
|
|
392
|
-
height: 22,
|
|
393
|
-
text: '用一句可以独立成立的话,说明我们看到了什么。',
|
|
394
|
-
fontSize: 31,
|
|
395
|
-
color: '#20273a',
|
|
396
|
-
fill: 'transparent',
|
|
397
|
-
bold: true,
|
|
398
|
-
align: 'left'
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
id: createWorkId('element'),
|
|
402
|
-
type: 'shape',
|
|
403
|
-
x: 8,
|
|
404
|
-
y: 60,
|
|
405
|
-
width: 84,
|
|
406
|
-
height: 22,
|
|
407
|
-
text: '关键证据或数据',
|
|
408
|
-
fontSize: 18,
|
|
409
|
-
color: '#ffffff',
|
|
410
|
-
fill: '#b44e34',
|
|
411
|
-
bold: true,
|
|
412
|
-
align: 'center',
|
|
413
|
-
radius: 3
|
|
414
|
-
}
|
|
415
|
-
]
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
id: createWorkId('slide'),
|
|
419
|
-
name: '下一步',
|
|
420
|
-
background: '#ffffff',
|
|
421
|
-
elements: [
|
|
422
|
-
{
|
|
423
|
-
id: createWorkId('element'),
|
|
424
|
-
type: 'text',
|
|
425
|
-
x: 8,
|
|
426
|
-
y: 10,
|
|
427
|
-
width: 84,
|
|
428
|
-
height: 12,
|
|
429
|
-
text: '02 下一步',
|
|
430
|
-
fontSize: 15,
|
|
431
|
-
color: '#b44e34',
|
|
432
|
-
fill: 'transparent',
|
|
433
|
-
bold: true,
|
|
434
|
-
align: 'left'
|
|
435
|
-
},
|
|
436
|
-
{
|
|
437
|
-
id: createWorkId('element'),
|
|
438
|
-
type: 'text',
|
|
439
|
-
x: 8,
|
|
440
|
-
y: 28,
|
|
441
|
-
width: 84,
|
|
442
|
-
height: 46,
|
|
443
|
-
text: '1 确认优先级\n2 指定负责人\n3 设定可验证的里程碑',
|
|
444
|
-
fontSize: 26,
|
|
445
|
-
color: '#20273a',
|
|
446
|
-
fill: '#f3f0ea',
|
|
447
|
-
bold: false,
|
|
448
|
-
align: 'left',
|
|
449
|
-
radius: 3
|
|
450
|
-
}
|
|
451
|
-
]
|
|
452
|
-
}
|
|
453
|
-
];
|
|
454
|
-
return {
|
|
455
|
-
type: 'presentation',
|
|
456
|
-
slides
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
function decodeXmlBytes(bytes, label) {
|
|
460
|
-
let encoding = 'utf-8';
|
|
461
|
-
let offset = 0;
|
|
462
|
-
if (0xef === bytes[0] && 0xbb === bytes[1] && 0xbf === bytes[2]) offset = 3;
|
|
463
|
-
else if (0xff === bytes[0] && 0xfe === bytes[1]) {
|
|
464
|
-
encoding = 'utf-16le';
|
|
465
|
-
offset = 2;
|
|
466
|
-
} else if (0xfe === bytes[0] && 0xff === bytes[1]) {
|
|
467
|
-
encoding = 'utf-16be';
|
|
468
|
-
offset = 2;
|
|
469
|
-
} else if (0x3c === bytes[0] && 0 === bytes[1] && 0x3f === bytes[2] && 0 === bytes[3]) encoding = 'utf-16le';
|
|
470
|
-
else if (0 === bytes[0] && 0x3c === bytes[1] && 0 === bytes[2] && 0x3f === bytes[3]) encoding = 'utf-16be';
|
|
471
|
-
try {
|
|
472
|
-
return new TextDecoder(encoding, {
|
|
473
|
-
fatal: true
|
|
474
|
-
}).decode(bytes.subarray(offset));
|
|
475
|
-
} catch {
|
|
476
|
-
throw new Error(`${label} uses an invalid ${encoding} XML encoding.`);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
function serializeUtf8Xml(document) {
|
|
480
|
-
const serialized = new XMLSerializer().serializeToString(document);
|
|
481
|
-
const body = serialized.replace(/^\s*<\?xml[^?]*\?>\s*/i, '');
|
|
482
|
-
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${body}`;
|
|
483
|
-
}
|
|
484
|
-
class OoxmlPackage {
|
|
485
|
-
zip;
|
|
486
|
-
textCache = new Map();
|
|
487
|
-
constructor(zip){
|
|
488
|
-
this.zip = zip;
|
|
489
|
-
}
|
|
490
|
-
static async load(buffer) {
|
|
491
|
-
return new OoxmlPackage(await jszip.loadAsync(buffer));
|
|
492
|
-
}
|
|
493
|
-
has(partPath) {
|
|
494
|
-
return Boolean(this.zip.file(partPath));
|
|
495
|
-
}
|
|
496
|
-
paths(prefix) {
|
|
497
|
-
return Object.keys(this.zip.files).filter((path)=>path.startsWith(prefix) && !this.zip.files[path]?.dir);
|
|
498
|
-
}
|
|
499
|
-
async text(partPath) {
|
|
500
|
-
const cached = this.textCache.get(partPath);
|
|
501
|
-
if (cached) return cached;
|
|
502
|
-
const entry = this.zip.file(partPath);
|
|
503
|
-
if (!entry) throw new Error(`Office package part is missing: ${partPath}`);
|
|
504
|
-
const pending = entry.async('uint8array').then((bytes)=>decodeXmlBytes(bytes, partPath));
|
|
505
|
-
this.textCache.set(partPath, pending);
|
|
506
|
-
try {
|
|
507
|
-
return await pending;
|
|
508
|
-
} catch (error) {
|
|
509
|
-
this.textCache.delete(partPath);
|
|
510
|
-
throw error;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
async xml(partPath) {
|
|
514
|
-
return parseXml(await this.text(partPath), partPath);
|
|
515
|
-
}
|
|
516
|
-
async bytes(partPath) {
|
|
517
|
-
const entry = this.zip.file(partPath);
|
|
518
|
-
if (!entry) throw new Error(`Office package part is missing: ${partPath}`);
|
|
519
|
-
return entry.async('uint8array');
|
|
520
|
-
}
|
|
521
|
-
async relationships(sourcePart) {
|
|
522
|
-
const partPath = relationshipsPartPath(sourcePart);
|
|
523
|
-
if (!this.has(partPath)) return new Map();
|
|
524
|
-
const document = await this.xml(partPath);
|
|
525
|
-
return new Map(descendants(document, 'Relationship').map((element)=>{
|
|
526
|
-
const relationship = {
|
|
527
|
-
id: attribute(element, 'Id') ?? '',
|
|
528
|
-
target: resolvePartTarget(sourcePart, attribute(element, 'Target') ?? ''),
|
|
529
|
-
type: attribute(element, 'Type') ?? '',
|
|
530
|
-
targetMode: attribute(element, 'TargetMode') ?? void 0
|
|
531
|
-
};
|
|
532
|
-
return [
|
|
533
|
-
relationship.id,
|
|
534
|
-
relationship
|
|
535
|
-
];
|
|
536
|
-
}));
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
function parseXml(source, label = 'Office XML') {
|
|
540
|
-
const document = new DOMParser().parseFromString(source, 'application/xml');
|
|
541
|
-
const error = descendants(document, 'parsererror')[0];
|
|
542
|
-
if (error) throw new Error(`${label} is not valid XML: ${error.textContent?.trim() || 'parse error'}`);
|
|
543
|
-
return document;
|
|
544
|
-
}
|
|
545
|
-
const xmlElementPatterns = new Map();
|
|
546
|
-
function xmlContainsAnyElement(source, localNames) {
|
|
547
|
-
if (!source || !localNames.length) return false;
|
|
548
|
-
const key = localNames.join('\u0000');
|
|
549
|
-
let pattern = xmlElementPatterns.get(key);
|
|
550
|
-
if (!pattern) {
|
|
551
|
-
const alternatives = localNames.map((name)=>name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
552
|
-
pattern = new RegExp(`<(?:[A-Za-z_][\\w.-]*:)?(?:${alternatives})(?=[\\s/>])`);
|
|
553
|
-
xmlElementPatterns.set(key, pattern);
|
|
554
|
-
}
|
|
555
|
-
return pattern.test(source);
|
|
556
|
-
}
|
|
557
|
-
function attribute(element, name) {
|
|
558
|
-
const direct = element.getAttribute(name);
|
|
559
|
-
if (null !== direct) return direct;
|
|
560
|
-
const localName = name.includes(':') ? name.slice(name.indexOf(':') + 1) : name;
|
|
561
|
-
return Array.from(element.attributes).find((item)=>{
|
|
562
|
-
const itemLocalName = item.localName.includes(':') ? item.localName.slice(item.localName.indexOf(':') + 1) : item.localName;
|
|
563
|
-
return itemLocalName === localName && (!name.includes(':') || item.name === name);
|
|
564
|
-
})?.value ?? null;
|
|
565
|
-
}
|
|
566
|
-
function xmlNamespacePrefix(element, namespace) {
|
|
567
|
-
if (!namespace) return element.prefix;
|
|
568
|
-
if ('function' == typeof element.lookupPrefix) {
|
|
569
|
-
const prefix = element.lookupPrefix(namespace);
|
|
570
|
-
if (prefix) return prefix;
|
|
571
|
-
}
|
|
572
|
-
let current = element;
|
|
573
|
-
while(current){
|
|
574
|
-
if (current.namespaceURI === namespace && current.prefix) return current.prefix;
|
|
575
|
-
const declaration = Array.from(current.attributes).find((item)=>item.value === namespace && ('xmlns' === item.name || item.name.startsWith('xmlns:')));
|
|
576
|
-
if (declaration?.name.startsWith('xmlns:')) return declaration.name.slice(6);
|
|
577
|
-
current = current.parentElement;
|
|
578
|
-
}
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
function directChildren(parent, localName) {
|
|
582
|
-
return Array.from(parent.children).filter((element)=>!localName || element.localName === localName);
|
|
583
|
-
}
|
|
584
|
-
function directChild(parent, localName) {
|
|
585
|
-
return directChildren(parent, localName)[0];
|
|
586
|
-
}
|
|
587
|
-
function descendants(parent, localName) {
|
|
588
|
-
return Array.from(parent.querySelectorAll('*')).filter((element)=>element.localName === localName);
|
|
589
|
-
}
|
|
590
|
-
function firstDescendant(parent, localName) {
|
|
591
|
-
if (!parent) return;
|
|
592
|
-
return descendants(parent, localName)[0];
|
|
593
|
-
}
|
|
594
|
-
function childPath(parent, ...localNames) {
|
|
595
|
-
let current = parent;
|
|
596
|
-
for (const name of localNames){
|
|
597
|
-
if (!current) return;
|
|
598
|
-
current = directChild(current, name);
|
|
599
|
-
}
|
|
600
|
-
return current instanceof Element ? current : void 0;
|
|
601
|
-
}
|
|
602
|
-
function resolvePartTarget(sourcePart, target) {
|
|
603
|
-
if (/^[a-z][a-z0-9+.-]*:/i.test(target)) return target;
|
|
604
|
-
const segments = target.startsWith('/') ? [] : sourcePart.split('/').slice(0, -1);
|
|
605
|
-
for (const segment of target.replace(/^\/+/, '').split('/'))if (segment && '.' !== segment) if ('..' === segment) segments.pop();
|
|
606
|
-
else segments.push(segment);
|
|
607
|
-
return segments.join('/');
|
|
608
|
-
}
|
|
609
|
-
function contentTypeForPart(partPath) {
|
|
610
|
-
const extension = partPath.split('.').pop()?.toLowerCase();
|
|
611
|
-
const types = {
|
|
612
|
-
apng: 'image/apng',
|
|
613
|
-
bmp: 'image/bmp',
|
|
614
|
-
emf: 'image/emf',
|
|
615
|
-
gif: 'image/gif',
|
|
616
|
-
jpeg: 'image/jpeg',
|
|
617
|
-
jpg: 'image/jpeg',
|
|
618
|
-
png: 'image/png',
|
|
619
|
-
svg: 'image/svg+xml',
|
|
620
|
-
tif: 'image/tiff',
|
|
621
|
-
tiff: 'image/tiff',
|
|
622
|
-
webp: 'image/webp',
|
|
623
|
-
wmf: 'image/wmf'
|
|
624
|
-
};
|
|
625
|
-
return types[extension ?? ''] ?? 'application/octet-stream';
|
|
626
|
-
}
|
|
627
|
-
function bytesToDataUrl(bytes, contentType) {
|
|
628
|
-
let binary = '';
|
|
629
|
-
const chunkSize = 32768;
|
|
630
|
-
for(let offset = 0; offset < bytes.length; offset += chunkSize)binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));
|
|
631
|
-
return `data:${contentType};base64,${btoa(binary)}`;
|
|
632
|
-
}
|
|
633
|
-
function relationshipsPartPath(sourcePart) {
|
|
634
|
-
const separator = sourcePart.lastIndexOf('/');
|
|
635
|
-
const directory = separator >= 0 ? sourcePart.slice(0, separator + 1) : '';
|
|
636
|
-
const fileName = separator >= 0 ? sourcePart.slice(separator + 1) : sourcePart;
|
|
637
|
-
return `${directory}_rels/${fileName}.rels`;
|
|
638
|
-
}
|
|
639
|
-
const OFFICE_KERNEL_SPREADSHEET_MAX_ROWS = 1048576;
|
|
640
|
-
const spreadsheetErrors = new Set([
|
|
641
|
-
'#BLOCKED!',
|
|
642
|
-
'#BUSY!',
|
|
643
|
-
'#CALC!',
|
|
644
|
-
'#CONNECT!',
|
|
645
|
-
'#DIV/0!',
|
|
646
|
-
'#FIELD!',
|
|
647
|
-
'#GETTING_DATA',
|
|
648
|
-
'#N/A',
|
|
649
|
-
'#NAME?',
|
|
650
|
-
'#NULL!',
|
|
651
|
-
'#NUM!',
|
|
652
|
-
'#PYTHON!',
|
|
653
|
-
'#REF!',
|
|
654
|
-
'#SPILL!',
|
|
655
|
-
'#UNKNOWN!',
|
|
656
|
-
'#VALUE!'
|
|
657
|
-
]);
|
|
658
|
-
new TextEncoder();
|
|
659
|
-
function isOfficeKernelSpreadsheetError(value) {
|
|
660
|
-
return 'string' == typeof value && spreadsheetErrors.has(value);
|
|
661
|
-
}
|
|
662
|
-
export { OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OoxmlPackage, WORK_TEMPLATES as officeTemplates, attribute, bytesToDataUrl, childPath, contentTypeForPart, createWorkArtifact as createArtifact, createWorkId as createOfficeId, decodeXmlBytes, descendants, directChild, directChildren, firstDescendant, isOfficeKernelSpreadsheetError, parseXml, resolvePartTarget, serializeUtf8Xml, xmlContainsAnyElement, xmlNamespacePrefix };
|
package/dist/9424.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
function normalizeCssColor(source) {
|
|
2
|
-
const value = source?.trim().toLowerCase();
|
|
3
|
-
if (!value) return null;
|
|
4
|
-
if ('transparent' === value) return 'transparent';
|
|
5
|
-
const shortHex = /^#([0-9a-f]{3})$/i.exec(value);
|
|
6
|
-
if (shortHex?.[1]) return `#${Array.from(shortHex[1]).map((channel)=>`${channel}${channel}`).join('')}`;
|
|
7
|
-
if (/^#[0-9a-f]{6}$/i.test(value)) return value;
|
|
8
|
-
const rgb = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*([\d.]+))?\s*\)$/i.exec(value);
|
|
9
|
-
if (!rgb) return null;
|
|
10
|
-
const channels = rgb.slice(1, 4).map(Number);
|
|
11
|
-
if (channels.some((channel)=>channel < 0 || channel > 255)) return null;
|
|
12
|
-
if (void 0 !== rgb[4] && 0 === Number(rgb[4])) return 'transparent';
|
|
13
|
-
if (void 0 !== rgb[4] && 1 !== Number(rgb[4])) return null;
|
|
14
|
-
return `#${channels.map((channel)=>channel.toString(16).padStart(2, '0')).join('')}`;
|
|
15
|
-
}
|
|
16
|
-
export { normalizeCssColor };
|