@file-viewer/renderer-iwork 0.0.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -158
- package/README.en.md +2 -15
- package/README.md +2 -15
- package/THIRD_PARTY_NOTICES.md +6 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +7 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +17 -72
- package/dist/iwork.d.ts +2 -0
- package/dist/iwork.js +368 -0
- package/dist/iwork.parser.d.ts +1 -0
- package/dist/iwork.parser.js +100 -0
- package/dist/iwork.worker.d.ts +1 -0
- package/dist/iwork.worker.js +100 -0
- package/dist/limits.d.ts +2 -0
- package/dist/limits.js +7 -0
- package/dist/model.d.ts +122 -0
- package/dist/model.js +1 -0
- package/dist/parser.d.ts +17 -2
- package/dist/parser.js +1387 -1
- package/dist/snappy.d.ts +2 -0
- package/dist/snappy.js +109 -0
- package/dist/workerClient.d.ts +3 -0
- package/dist/workerClient.js +60 -0
- package/package.json +37 -22
package/dist/iwork.js
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { registerFileViewerZoomProvider, resolveFileViewerFitScale, unregisterFileViewerZoomProvider, } from '@file-viewer/core';
|
|
2
|
+
import { parseIworkWithWorker } from './workerClient.js';
|
|
3
|
+
const MIN_SCALE = 0.25;
|
|
4
|
+
const MAX_SCALE = 4;
|
|
5
|
+
const ZOOM_STEP = 0.1;
|
|
6
|
+
const styleText = `
|
|
7
|
+
.iwork-viewer{width:100%;height:100%;display:grid;grid-template-columns:minmax(190px,250px) minmax(0,1fr);overflow:hidden;background:var(--file-viewer-render-surface-background,#e8edf2);color:#172033;font-family:Aptos,'Helvetica Neue','PingFang SC',sans-serif}.iwork-nav{min-height:0;overflow:auto;padding:14px 10px;border-right:1px solid rgba(15,23,42,.1);background:rgba(255,255,255,.96)}.iwork-nav button{display:block;width:100%;margin:0 0 5px;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:#475569;text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.iwork-nav button.active,.iwork-nav button:hover{background:#e8f4ff;color:#0369a1}.iwork-stage{min-width:0;min-height:0;overflow:auto;padding:24px;box-sizing:border-box}.iwork-scene-wrap{position:relative;margin:0 auto 24px}.iwork-scene{position:absolute;top:0;left:0;overflow:hidden;background:#fff;box-shadow:0 18px 48px rgba(15,23,42,.15);transform-origin:top left;color:#172033}.iwork-preview{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#fff}.iwork-object{position:absolute;box-sizing:border-box}.iwork-object-shape{border-radius:14px;background:#111827;color:#fff;display:grid;place-items:center}.iwork-object-chart{overflow:visible}.iwork-object-image{object-fit:fill}.iwork-text-layer{position:absolute;inset:0;pointer-events:none}.iwork-text{position:absolute;overflow:hidden;white-space:pre-wrap;word-break:break-word;line-height:1.15;box-sizing:border-box;pointer-events:auto}.iwork-table{position:absolute;border-collapse:collapse;table-layout:fixed;background:#fff;font-size:14px}.iwork-table td{min-width:0;padding:0 6px;border:1px solid #aaa;overflow:hidden;white-space:pre-wrap;vertical-align:middle}.iwork-table .iwork-table-header-row{font-weight:700;border-bottom-color:#333}.iwork-table .iwork-table-header-column{font-weight:700;border-right-color:#333}.iwork-table .iwork-table-number{text-align:right}.iwork-notes{position:absolute;z-index:1000000;left:40px;right:40px;bottom:20px;padding:10px 14px;border-radius:7px;background:rgba(248,250,252,.95);color:#475569;font-size:12px}.iwork-empty{padding:48px;color:#64748b;text-align:center}
|
|
8
|
+
[data-viewer-theme='dark'] .iwork-viewer{background:var(--file-viewer-render-surface-background,#0d1117)}[data-viewer-theme='dark'] .iwork-nav{background:#161b22;border-color:#30363d;color:#e6edf3}.iwork-scene{color-scheme:light}
|
|
9
|
+
@media(max-width:720px){.iwork-viewer{grid-template-columns:1fr}.iwork-nav{display:flex;min-height:auto;max-height:96px;overflow:auto;border-right:0;border-bottom:1px solid #d8dee6}.iwork-nav button{flex:0 0 auto;width:auto}.iwork-stage{padding:10px}}
|
|
10
|
+
@media print{.iwork-nav{display:none}.iwork-viewer{display:block;height:auto}.iwork-stage{overflow:visible;padding:0}.iwork-scene-wrap{break-after:page;margin:0}.iwork-scene{box-shadow:none}}
|
|
11
|
+
`;
|
|
12
|
+
const clamp = (value) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, Math.round(value * 100) / 100));
|
|
13
|
+
const createPreviewUrl = (model) => model.preview
|
|
14
|
+
? URL.createObjectURL(new Blob([Uint8Array.from(model.preview.bytes)], { type: model.preview.mimeType }))
|
|
15
|
+
: '';
|
|
16
|
+
const bytesToDataUrl = ({ bytes, mimeType }) => {
|
|
17
|
+
let binary = '';
|
|
18
|
+
for (let offset = 0; offset < bytes.length; offset += 0x8000) {
|
|
19
|
+
binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));
|
|
20
|
+
}
|
|
21
|
+
return `data:${mimeType};base64,${btoa(binary)}`;
|
|
22
|
+
};
|
|
23
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
24
|
+
const appendSvg = (parent, tag, attributes) => {
|
|
25
|
+
const element = document.createElementNS(SVG_NS, tag);
|
|
26
|
+
Object.entries(attributes).forEach(([name, value]) => element.setAttribute(name, String(value)));
|
|
27
|
+
parent.appendChild(element);
|
|
28
|
+
return element;
|
|
29
|
+
};
|
|
30
|
+
const renderChart = (object, kind) => {
|
|
31
|
+
var _a;
|
|
32
|
+
const svg = document.createElementNS(SVG_NS, 'svg');
|
|
33
|
+
svg.setAttribute('viewBox', `0 0 ${object.width} ${object.height}`);
|
|
34
|
+
svg.setAttribute('role', 'img');
|
|
35
|
+
svg.setAttribute('aria-label', object.chart ? 'Static Apple chart' : 'Chart preview unavailable');
|
|
36
|
+
if (!((_a = object.chart) === null || _a === void 0 ? void 0 : _a.series.length) || !object.chart.categories.length)
|
|
37
|
+
return svg;
|
|
38
|
+
const values = object.chart.series.flatMap(series => series.values).filter(Number.isFinite);
|
|
39
|
+
const maximum = Math.max(25, Math.ceil(Math.max(...values, 0) / 25) * 25);
|
|
40
|
+
const plotHeight = object.height;
|
|
41
|
+
const colors = ['#0b9fe8', '#58d52f', '#f5a623', '#9b59b6', '#ef4444', '#14b8a6'];
|
|
42
|
+
for (let tick = 0; tick <= 4; tick += 1) {
|
|
43
|
+
const y = plotHeight - plotHeight * tick / 4;
|
|
44
|
+
appendSvg(svg, 'line', { x1: 0, y1: y, x2: object.width, y2: y, stroke: tick === 0 ? '#111' : '#b7b7b7', 'stroke-width': tick === 0 ? 1.2 : 0.6 });
|
|
45
|
+
const label = appendSvg(svg, 'text', { x: -12, y: y + 4, fill: '#111', 'font-size': 10, 'text-anchor': 'end', 'font-family': 'Helvetica Neue, sans-serif' });
|
|
46
|
+
label.textContent = String(Math.round(maximum * tick / 4));
|
|
47
|
+
}
|
|
48
|
+
const groupWidth = object.width / object.chart.categories.length;
|
|
49
|
+
const usableWidth = groupWidth * 0.82;
|
|
50
|
+
const barWidth = usableWidth / object.chart.series.length;
|
|
51
|
+
object.chart.categories.forEach((category, categoryIndex) => {
|
|
52
|
+
if (object.chart.type === 'bar') {
|
|
53
|
+
object.chart.series.forEach((series, seriesIndex) => {
|
|
54
|
+
const value = Number(series.values[categoryIndex] || 0);
|
|
55
|
+
const height = Math.max(0, Math.min(plotHeight, value / maximum * plotHeight));
|
|
56
|
+
appendSvg(svg, 'rect', {
|
|
57
|
+
x: categoryIndex * groupWidth + (groupWidth - usableWidth) / 2 + seriesIndex * barWidth,
|
|
58
|
+
y: plotHeight - height,
|
|
59
|
+
width: Math.max(1, barWidth - 2),
|
|
60
|
+
height,
|
|
61
|
+
fill: colors[seriesIndex % colors.length],
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (object.chart.type === 'line') {
|
|
66
|
+
const label = appendSvg(svg, 'text', { x: categoryIndex * groupWidth + groupWidth / 2, y: plotHeight + 22, fill: '#111', 'font-size': 10, 'text-anchor': 'middle', 'font-family': 'Helvetica Neue, sans-serif' });
|
|
67
|
+
label.textContent = category;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (object.chart.type === 'line') {
|
|
71
|
+
object.chart.series.forEach((series, seriesIndex) => {
|
|
72
|
+
const points = series.values.map((value, index) => `${index * groupWidth + groupWidth / 2},${plotHeight - Math.max(0, Math.min(plotHeight, Number(value || 0) / maximum * plotHeight))}`).join(' ');
|
|
73
|
+
appendSvg(svg, 'polyline', { points, fill: 'none', stroke: colors[seriesIndex % colors.length], 'stroke-width': 3 });
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (kind === 'pages') {
|
|
77
|
+
const legendY = -39;
|
|
78
|
+
object.chart.series.forEach((series, index) => {
|
|
79
|
+
const x = object.width / 2 - 100 + index * 130;
|
|
80
|
+
appendSvg(svg, 'line', { x1: x, y1: legendY, x2: x + 12, y2: legendY, stroke: colors[index % colors.length], 'stroke-width': 2 });
|
|
81
|
+
const label = appendSvg(svg, 'text', { x: x + 20, y: legendY + 4, fill: '#111', 'font-size': 10, 'font-family': 'Helvetica Neue, sans-serif' });
|
|
82
|
+
label.textContent = series.name;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return svg;
|
|
86
|
+
};
|
|
87
|
+
const renderScene = (scene, model, scale, previewUrl, showPreview, objectUrls) => {
|
|
88
|
+
const wrap = document.createElement('section');
|
|
89
|
+
wrap.className = 'iwork-scene-wrap';
|
|
90
|
+
wrap.dataset.viewerAnchorId = scene.id;
|
|
91
|
+
wrap.dataset.sceneId = scene.id;
|
|
92
|
+
Object.assign(wrap.style, { width: `${scene.width * scale}px`, height: `${scene.height * scale}px` });
|
|
93
|
+
const surface = document.createElement('article');
|
|
94
|
+
surface.className = 'iwork-scene';
|
|
95
|
+
surface.dataset.pageIndex = scene.id.replace(/\D+/g, '') || '0';
|
|
96
|
+
Object.assign(surface.style, { width: `${scene.width}px`, height: `${scene.height}px`, transform: `scale(${scale})` });
|
|
97
|
+
if (showPreview && previewUrl) {
|
|
98
|
+
const image = document.createElement('img');
|
|
99
|
+
image.className = 'iwork-preview';
|
|
100
|
+
image.src = previewUrl;
|
|
101
|
+
image.alt = `${scene.name} embedded preview`;
|
|
102
|
+
surface.appendChild(image);
|
|
103
|
+
}
|
|
104
|
+
scene.objects.filter(object => object.kind !== 'table').forEach(object => {
|
|
105
|
+
var _a;
|
|
106
|
+
const element = object.kind === 'image' && object.bytes && object.mimeType
|
|
107
|
+
? document.createElement('img')
|
|
108
|
+
: object.kind === 'chart'
|
|
109
|
+
? renderChart(object, model.kind)
|
|
110
|
+
: document.createElement('div');
|
|
111
|
+
element.setAttribute('class', `iwork-object iwork-object-${object.kind}`);
|
|
112
|
+
Object.assign(element.style, { left: `${object.x}px`, top: `${object.y}px`, width: `${object.width}px`, height: `${object.height}px`, transform: object.angle ? `rotate(${object.angle}rad)` : '', zIndex: String((_a = object.zIndex) !== null && _a !== void 0 ? _a : 1) });
|
|
113
|
+
if (element instanceof HTMLImageElement) {
|
|
114
|
+
const objectUrl = URL.createObjectURL(new Blob([Uint8Array.from(object.bytes)], { type: object.mimeType }));
|
|
115
|
+
objectUrls.set(objectUrl, { bytes: object.bytes, mimeType: object.mimeType });
|
|
116
|
+
element.src = objectUrl;
|
|
117
|
+
element.alt = object.text || 'Embedded Keynote image';
|
|
118
|
+
}
|
|
119
|
+
else if (object.text)
|
|
120
|
+
element.textContent = object.text;
|
|
121
|
+
surface.appendChild(element);
|
|
122
|
+
});
|
|
123
|
+
const textLayer = document.createElement('div');
|
|
124
|
+
textLayer.className = 'iwork-text-layer';
|
|
125
|
+
scene.blocks.forEach(block => {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
const element = document.createElement('div');
|
|
128
|
+
element.className = 'iwork-text';
|
|
129
|
+
Object.assign(element.style, {
|
|
130
|
+
left: `${block.x}px`, top: `${block.y}px`, width: `${block.width}px`, height: `${block.height}px`,
|
|
131
|
+
fontSize: `${block.fontSize || 16}px`, fontFamily: block.fontFamily || 'inherit', color: block.color || 'inherit',
|
|
132
|
+
fontWeight: block.bold ? '700' : '400', fontStyle: block.italic ? 'italic' : 'normal', textAlign: block.align || 'left',
|
|
133
|
+
letterSpacing: block.letterSpacing == null ? 'normal' : `${block.letterSpacing}em`,
|
|
134
|
+
lineHeight: block.lineHeight == null ? '1.15' : String(block.lineHeight),
|
|
135
|
+
display: block.verticalAlign ? 'flex' : 'block',
|
|
136
|
+
flexDirection: block.verticalAlign ? 'column' : '',
|
|
137
|
+
justifyContent: block.verticalAlign === 'middle' ? 'center' : block.verticalAlign === 'bottom' ? 'flex-end' : 'flex-start',
|
|
138
|
+
padding: block.padding ? `${block.padding.top}px ${block.padding.right}px ${block.padding.bottom}px ${block.padding.left}px` : '0',
|
|
139
|
+
zIndex: String((_a = block.zIndex) !== null && _a !== void 0 ? _a : 2),
|
|
140
|
+
});
|
|
141
|
+
if ((_b = block.paragraphs) === null || _b === void 0 ? void 0 : _b.length) {
|
|
142
|
+
block.paragraphs.forEach(paragraph => {
|
|
143
|
+
const paragraphElement = document.createElement('div');
|
|
144
|
+
Object.assign(paragraphElement.style, {
|
|
145
|
+
display: paragraph.bullet ? 'grid' : 'block',
|
|
146
|
+
gridTemplateColumns: paragraph.bullet ? '42px minmax(0, 1fr)' : '',
|
|
147
|
+
marginTop: `${paragraph.spaceBefore || 0}px`,
|
|
148
|
+
marginBottom: `${paragraph.spaceAfter || 0}px`,
|
|
149
|
+
color: paragraph.color || 'inherit',
|
|
150
|
+
fontWeight: paragraph.bold ? '700' : 'inherit',
|
|
151
|
+
fontStyle: paragraph.italic ? 'italic' : 'inherit',
|
|
152
|
+
});
|
|
153
|
+
if (paragraph.bullet) {
|
|
154
|
+
const bullet = document.createElement('span');
|
|
155
|
+
bullet.textContent = '•';
|
|
156
|
+
paragraphElement.appendChild(bullet);
|
|
157
|
+
}
|
|
158
|
+
const content = document.createElement('span');
|
|
159
|
+
paragraph.runs.forEach(run => {
|
|
160
|
+
const span = document.createElement('span');
|
|
161
|
+
span.textContent = run.text;
|
|
162
|
+
if (run.color)
|
|
163
|
+
span.style.color = run.color;
|
|
164
|
+
if (run.bold)
|
|
165
|
+
span.style.fontWeight = '700';
|
|
166
|
+
if (run.italic)
|
|
167
|
+
span.style.fontStyle = 'italic';
|
|
168
|
+
content.appendChild(span);
|
|
169
|
+
});
|
|
170
|
+
paragraphElement.appendChild(content);
|
|
171
|
+
element.appendChild(paragraphElement);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
element.textContent = block.text;
|
|
176
|
+
}
|
|
177
|
+
textLayer.appendChild(element);
|
|
178
|
+
});
|
|
179
|
+
surface.appendChild(textLayer);
|
|
180
|
+
scene.tables.forEach(table => {
|
|
181
|
+
var _a, _b;
|
|
182
|
+
const element = document.createElement('table');
|
|
183
|
+
element.className = 'iwork-table';
|
|
184
|
+
Object.assign(element.style, { left: `${table.x}px`, top: `${table.y}px`, width: table.width ? `${table.width}px` : '', height: table.height ? `${table.height}px` : '', zIndex: String((_a = table.zIndex) !== null && _a !== void 0 ? _a : 3) });
|
|
185
|
+
if (table.fontSize)
|
|
186
|
+
element.style.fontSize = `${table.fontSize}px`;
|
|
187
|
+
if (table.fontFamily)
|
|
188
|
+
element.style.fontFamily = table.fontFamily;
|
|
189
|
+
if ((_b = table.columnWidths) === null || _b === void 0 ? void 0 : _b.length) {
|
|
190
|
+
const columns = document.createElement('colgroup');
|
|
191
|
+
table.columnWidths.forEach(width => {
|
|
192
|
+
const column = document.createElement('col');
|
|
193
|
+
column.style.width = `${width}px`;
|
|
194
|
+
columns.appendChild(column);
|
|
195
|
+
});
|
|
196
|
+
element.appendChild(columns);
|
|
197
|
+
}
|
|
198
|
+
const mergeOrigins = new Map((table.merges || []).map(merge => [`${merge.row}:${merge.col}`, merge]));
|
|
199
|
+
const covered = new Set();
|
|
200
|
+
for (const merge of table.merges || []) {
|
|
201
|
+
for (let row = merge.row; row < merge.row + merge.rowspan; row += 1) {
|
|
202
|
+
for (let col = merge.col; col < merge.col + merge.colspan; col += 1) {
|
|
203
|
+
if (row !== merge.row || col !== merge.col)
|
|
204
|
+
covered.add(`${row}:${col}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
table.rows.forEach((row, rowIndex) => {
|
|
209
|
+
var _a;
|
|
210
|
+
const tr = document.createElement('tr');
|
|
211
|
+
if ((_a = table.rowHeights) === null || _a === void 0 ? void 0 : _a[rowIndex])
|
|
212
|
+
tr.style.height = `${table.rowHeights[rowIndex]}px`;
|
|
213
|
+
row.forEach((value, colIndex) => {
|
|
214
|
+
if (covered.has(`${rowIndex}:${colIndex}`))
|
|
215
|
+
return;
|
|
216
|
+
const cell = document.createElement('td');
|
|
217
|
+
cell.textContent = value;
|
|
218
|
+
if (table.borderColor)
|
|
219
|
+
cell.style.borderColor = table.borderColor;
|
|
220
|
+
if (rowIndex < (table.headerRows || 0)) {
|
|
221
|
+
cell.classList.add('iwork-table-header-row');
|
|
222
|
+
if (table.headerRowBackground)
|
|
223
|
+
cell.style.background = table.headerRowBackground;
|
|
224
|
+
}
|
|
225
|
+
if (colIndex < (table.headerColumns || 0) && rowIndex >= (table.headerRows || 0)) {
|
|
226
|
+
cell.classList.add('iwork-table-header-column');
|
|
227
|
+
if (table.headerColumnBackground)
|
|
228
|
+
cell.style.background = table.headerColumnBackground;
|
|
229
|
+
}
|
|
230
|
+
if (value !== '' && Number.isFinite(Number(value)) && rowIndex >= (table.headerRows || 0))
|
|
231
|
+
cell.classList.add('iwork-table-number');
|
|
232
|
+
const merge = mergeOrigins.get(`${rowIndex}:${colIndex}`);
|
|
233
|
+
if (merge) {
|
|
234
|
+
cell.rowSpan = merge.rowspan;
|
|
235
|
+
cell.colSpan = merge.colspan;
|
|
236
|
+
}
|
|
237
|
+
tr.appendChild(cell);
|
|
238
|
+
});
|
|
239
|
+
element.appendChild(tr);
|
|
240
|
+
});
|
|
241
|
+
surface.appendChild(element);
|
|
242
|
+
});
|
|
243
|
+
if (scene.notes.length) {
|
|
244
|
+
const notes = document.createElement('aside');
|
|
245
|
+
notes.className = 'iwork-notes';
|
|
246
|
+
notes.textContent = scene.notes.join('\n');
|
|
247
|
+
surface.appendChild(notes);
|
|
248
|
+
}
|
|
249
|
+
wrap.appendChild(surface);
|
|
250
|
+
return wrap;
|
|
251
|
+
};
|
|
252
|
+
export default async function renderIwork(buffer, target, type, context) {
|
|
253
|
+
var _a, _b, _c, _d, _e, _f;
|
|
254
|
+
const model = await parseIworkWithWorker(buffer.slice(0), type, (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.iwork, context === null || context === void 0 ? void 0 : context.signal);
|
|
255
|
+
let scale = 1;
|
|
256
|
+
let activeScene = ((_b = model.scenes[0]) === null || _b === void 0 ? void 0 : _b.id) || '';
|
|
257
|
+
const previewUrl = createPreviewUrl(model);
|
|
258
|
+
const showEmbeddedPreview = ((_d = (_c = context === null || context === void 0 ? void 0 : context.options) === null || _c === void 0 ? void 0 : _c.iwork) === null || _d === void 0 ? void 0 : _d.embeddedPreview) === 'fallback' && model.limitedPreview;
|
|
259
|
+
const style = document.createElement('style');
|
|
260
|
+
style.textContent = styleText;
|
|
261
|
+
const root = document.createElement('div');
|
|
262
|
+
root.className = 'iwork-viewer';
|
|
263
|
+
const nav = document.createElement('nav');
|
|
264
|
+
nav.className = 'iwork-nav';
|
|
265
|
+
const stage = document.createElement('main');
|
|
266
|
+
stage.className = 'iwork-stage';
|
|
267
|
+
let objectUrls = new Map();
|
|
268
|
+
const render = () => {
|
|
269
|
+
const showAll = model.kind === 'pages';
|
|
270
|
+
const scenes = showAll ? model.scenes : model.scenes.filter(scene => scene.id === activeScene);
|
|
271
|
+
const nextObjectUrls = new Map();
|
|
272
|
+
const nextScenes = scenes.map(scene => renderScene(scene, model, scale, previewUrl, showEmbeddedPreview, nextObjectUrls));
|
|
273
|
+
stage.replaceChildren(...nextScenes);
|
|
274
|
+
objectUrls.forEach((_asset, url) => URL.revokeObjectURL(url));
|
|
275
|
+
objectUrls = nextObjectUrls;
|
|
276
|
+
nav.querySelectorAll('button').forEach(button => button.classList.toggle('active', button.dataset.sceneId === activeScene));
|
|
277
|
+
};
|
|
278
|
+
model.scenes.forEach(scene => {
|
|
279
|
+
const button = document.createElement('button');
|
|
280
|
+
button.type = 'button';
|
|
281
|
+
button.dataset.sceneId = scene.id;
|
|
282
|
+
button.textContent = scene.name;
|
|
283
|
+
button.addEventListener('click', () => {
|
|
284
|
+
var _a;
|
|
285
|
+
activeScene = scene.id;
|
|
286
|
+
if (model.kind === 'pages')
|
|
287
|
+
(_a = stage.querySelector(`[data-scene-id="${CSS.escape(scene.id)}"]`)) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'start' });
|
|
288
|
+
else
|
|
289
|
+
render();
|
|
290
|
+
});
|
|
291
|
+
nav.appendChild(button);
|
|
292
|
+
});
|
|
293
|
+
root.append(nav, stage);
|
|
294
|
+
target.replaceChildren(style, root);
|
|
295
|
+
render();
|
|
296
|
+
const getState = () => ({
|
|
297
|
+
scale,
|
|
298
|
+
label: `${Math.round(scale * 100)}%`,
|
|
299
|
+
canZoomIn: scale < MAX_SCALE,
|
|
300
|
+
canZoomOut: scale > MIN_SCALE,
|
|
301
|
+
canReset: scale !== 1,
|
|
302
|
+
minScale: MIN_SCALE,
|
|
303
|
+
maxScale: MAX_SCALE,
|
|
304
|
+
});
|
|
305
|
+
const setScale = (value) => { scale = clamp(value); render(); return getState(); };
|
|
306
|
+
const fit = (request) => {
|
|
307
|
+
const scene = model.scenes.find(item => item.id === activeScene) || model.scenes[0];
|
|
308
|
+
if (!scene)
|
|
309
|
+
return { applied: false, mode: request.mode, resize: request.resize, source: request.source, reason: 'unmeasurable', provider: 'zoom' };
|
|
310
|
+
const next = resolveFileViewerFitScale({
|
|
311
|
+
mode: request.mode === 'auto' ? 'width' : request.mode,
|
|
312
|
+
viewportWidth: request.viewportWidth || stage.clientWidth,
|
|
313
|
+
viewportHeight: request.viewportHeight || stage.clientHeight,
|
|
314
|
+
contentWidth: scene.width,
|
|
315
|
+
contentHeight: scene.height,
|
|
316
|
+
currentScale: scale,
|
|
317
|
+
minScale: MIN_SCALE,
|
|
318
|
+
maxScale: MAX_SCALE,
|
|
319
|
+
});
|
|
320
|
+
if (!next)
|
|
321
|
+
return { applied: false, mode: request.mode, resize: request.resize, source: request.source, reason: 'unmeasurable', provider: 'zoom' };
|
|
322
|
+
setScale(next);
|
|
323
|
+
return { applied: true, mode: request.mode, resize: request.resize, source: request.source, scale, provider: 'zoom' };
|
|
324
|
+
};
|
|
325
|
+
registerFileViewerZoomProvider(target, {
|
|
326
|
+
zoomIn: () => setScale(scale + ZOOM_STEP),
|
|
327
|
+
zoomOut: () => setScale(scale - ZOOM_STEP),
|
|
328
|
+
resetZoom: () => setScale(1),
|
|
329
|
+
setZoom: setScale,
|
|
330
|
+
fit,
|
|
331
|
+
getState,
|
|
332
|
+
});
|
|
333
|
+
(_e = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _e === void 0 ? void 0 : _e.call(context, {
|
|
334
|
+
includeDocumentStyles: false,
|
|
335
|
+
getPrintMaskPages: () => Array.from(stage.querySelectorAll('.iwork-scene')),
|
|
336
|
+
printStyle: styleText,
|
|
337
|
+
toHtml: () => {
|
|
338
|
+
const clone = root.cloneNode(true);
|
|
339
|
+
clone.querySelectorAll('img').forEach(image => {
|
|
340
|
+
const asset = objectUrls.get(image.src)
|
|
341
|
+
|| (image.src === previewUrl && model.preview
|
|
342
|
+
? { bytes: model.preview.bytes, mimeType: model.preview.mimeType }
|
|
343
|
+
: undefined);
|
|
344
|
+
if (asset)
|
|
345
|
+
image.src = bytesToDataUrl(asset);
|
|
346
|
+
});
|
|
347
|
+
return clone.outerHTML;
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
(_f = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _f === void 0 ? void 0 : _f.call(context, {
|
|
351
|
+
captureSource: showEmbeddedPreview ? 'embedded' : 'rendered',
|
|
352
|
+
capture: showEmbeddedPreview && model.preview ? () => new Blob([Uint8Array.from(model.preview.bytes)], { type: model.preview.mimeType }) : undefined,
|
|
353
|
+
getTarget: () => stage.querySelector('.iwork-scene') || stage,
|
|
354
|
+
});
|
|
355
|
+
return {
|
|
356
|
+
$el: target,
|
|
357
|
+
unmount() {
|
|
358
|
+
var _a, _b;
|
|
359
|
+
unregisterFileViewerZoomProvider(target);
|
|
360
|
+
(_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
|
|
361
|
+
(_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, null);
|
|
362
|
+
if (previewUrl)
|
|
363
|
+
URL.revokeObjectURL(previewUrl);
|
|
364
|
+
objectUrls.forEach((_asset, url) => URL.revokeObjectURL(url));
|
|
365
|
+
target.replaceChildren();
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { inspectIworkContainer, parseIworkDocument, } from './parser.js';
|