ppt2json 0.1.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 +23 -0
- package/dist/index.d.mts +122 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +569 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +538 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import JSZip from "jszip";
|
|
3
|
+
import {
|
|
4
|
+
ENABLE_DECK_JSON,
|
|
5
|
+
PPTX_JSON_PAYLOAD_PATH,
|
|
6
|
+
PPTX_JSON_PAYLOAD_VERSION
|
|
7
|
+
} from "json2pptx";
|
|
8
|
+
|
|
9
|
+
// parser/pptxtojson.ts
|
|
10
|
+
import { parse as parseWithPptxtojson } from "pptxtojson/dist/index.js";
|
|
11
|
+
async function parse(file) {
|
|
12
|
+
return parseWithPptxtojson(file);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// utils.ts
|
|
16
|
+
var PT_TO_PX = 96 / 72;
|
|
17
|
+
function toPx(value) {
|
|
18
|
+
if (value === void 0 || value === null) return void 0;
|
|
19
|
+
return value * PT_TO_PX;
|
|
20
|
+
}
|
|
21
|
+
function toPxPair(value) {
|
|
22
|
+
if (!value) return void 0;
|
|
23
|
+
return [toPx(value[0]) ?? 0, toPx(value[1]) ?? 0];
|
|
24
|
+
}
|
|
25
|
+
function mapColor(value) {
|
|
26
|
+
if (!value) return void 0;
|
|
27
|
+
const normalized = value.startsWith("#") ? value : `#${value}`;
|
|
28
|
+
return normalized.toUpperCase();
|
|
29
|
+
}
|
|
30
|
+
function mapFillColor(value) {
|
|
31
|
+
if (!value) return void 0;
|
|
32
|
+
return value.startsWith("#") ? value : `#${value}`;
|
|
33
|
+
}
|
|
34
|
+
function mapFill(fill) {
|
|
35
|
+
if (!fill) return {};
|
|
36
|
+
if (typeof fill === "string") return { fill: mapFillColor(fill) ?? void 0 };
|
|
37
|
+
if (typeof fill === "object") {
|
|
38
|
+
if (fill.type === "color" && typeof fill.value === "string") {
|
|
39
|
+
return { fill: mapFillColor(fill.value) ?? void 0 };
|
|
40
|
+
}
|
|
41
|
+
if (fill.type === "image" && fill.value?.picBase64) {
|
|
42
|
+
return { fill: "", pattern: fill.value.picBase64 };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
function convertFontSizeToPx(content) {
|
|
48
|
+
return content.replace(/font-size:\s*([0-9.]+)pt/gi, (_, size) => {
|
|
49
|
+
const px = Math.floor(Number.parseFloat(size) * PT_TO_PX);
|
|
50
|
+
return `font-size: ${px}px`;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function normalizeTextContent(content) {
|
|
54
|
+
return convertFontSizeToPx(content).replace(/ /g, " ");
|
|
55
|
+
}
|
|
56
|
+
function normalizeVAlign(value) {
|
|
57
|
+
if (!value) return void 0;
|
|
58
|
+
if (value === "mid") return "middle";
|
|
59
|
+
if (value === "up") return "top";
|
|
60
|
+
if (value === "down") return "bottom";
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function roundTo(value, digits = 2) {
|
|
64
|
+
if (value === void 0 || value === null) return void 0;
|
|
65
|
+
const factor = 10 ** digits;
|
|
66
|
+
return Math.round(value * factor) / factor;
|
|
67
|
+
}
|
|
68
|
+
function normalizeColor(value) {
|
|
69
|
+
if (!value) return void 0;
|
|
70
|
+
return value.startsWith("#") ? value.toUpperCase() : `#${value}`.toUpperCase();
|
|
71
|
+
}
|
|
72
|
+
function extractFirstFontSizePx(content) {
|
|
73
|
+
if (!content) return void 0;
|
|
74
|
+
const match = content.match(/font-size:\s*([0-9.]+)px/i);
|
|
75
|
+
if (!match) return void 0;
|
|
76
|
+
const size = Number.parseFloat(match[1]);
|
|
77
|
+
return Number.isFinite(size) ? size : void 0;
|
|
78
|
+
}
|
|
79
|
+
function normalizeTextHeight(height, content, lineHeight) {
|
|
80
|
+
if (height === void 0) return height;
|
|
81
|
+
const fontSize = extractFirstFontSizePx(content);
|
|
82
|
+
if (!fontSize) return height;
|
|
83
|
+
const lh = lineHeight ?? 1;
|
|
84
|
+
const base = fontSize * lh;
|
|
85
|
+
const padding = fontSize < 40 ? 21 : 20.5;
|
|
86
|
+
const target = Math.round((base + padding) * 2) / 2;
|
|
87
|
+
if (height > base * 2) return height;
|
|
88
|
+
return target;
|
|
89
|
+
}
|
|
90
|
+
function hasMultiLineText(content) {
|
|
91
|
+
if (!content) return false;
|
|
92
|
+
if (content.includes("<br")) return true;
|
|
93
|
+
const paragraphs = content.match(/<p\b/gi);
|
|
94
|
+
return (paragraphs?.length ?? 0) > 1;
|
|
95
|
+
}
|
|
96
|
+
function getPathBounds(path) {
|
|
97
|
+
if (!path) return void 0;
|
|
98
|
+
const nums = path.match(/-?\d+\.?\d*/g);
|
|
99
|
+
if (!nums || nums.length < 2) return void 0;
|
|
100
|
+
const values = nums.map((value) => Number.parseFloat(value)).filter(Number.isFinite);
|
|
101
|
+
if (!values.length) return void 0;
|
|
102
|
+
let maxX = 0;
|
|
103
|
+
let maxY = 0;
|
|
104
|
+
for (let index = 0; index < values.length; index += 2) {
|
|
105
|
+
const x = values[index];
|
|
106
|
+
const y = values[index + 1];
|
|
107
|
+
if (Number.isFinite(x)) maxX = Math.max(maxX, x);
|
|
108
|
+
if (Number.isFinite(y)) maxY = Math.max(maxY, y);
|
|
109
|
+
}
|
|
110
|
+
if (maxX === 0 && maxY === 0) return void 0;
|
|
111
|
+
return [maxX, maxY];
|
|
112
|
+
}
|
|
113
|
+
function buildEllipsePath() {
|
|
114
|
+
return "M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z";
|
|
115
|
+
}
|
|
116
|
+
function buildRoundRectPath(width, height, radius) {
|
|
117
|
+
const r = Math.max(0, Math.min(radius, Math.min(width, height)));
|
|
118
|
+
return `M ${r} 0 L ${width - r} 0 Q ${width} 0 ${width} ${r} L ${width} ${height - r} Q ${width} ${height} ${width - r} ${height} L ${r} ${height} Q 0 ${height} 0 ${height - r} L 0 ${r} Q 0 0 ${r} 0 Z`;
|
|
119
|
+
}
|
|
120
|
+
function buildRectPath() {
|
|
121
|
+
return "M 0 0 L 200 0 L 200 200 L 0 200 Z";
|
|
122
|
+
}
|
|
123
|
+
function buildCutRectDiagonalPath(width, height, adj) {
|
|
124
|
+
const cut = height * adj;
|
|
125
|
+
return `M 0 ${height - cut} L 0 0 L ${width - cut} 0 L ${width} ${cut} L ${width} ${height} L ${cut} ${height} Z`;
|
|
126
|
+
}
|
|
127
|
+
function mapPathFormula(shapeType) {
|
|
128
|
+
switch (shapeType) {
|
|
129
|
+
case "roundRect":
|
|
130
|
+
return "roundRect";
|
|
131
|
+
case "triangle":
|
|
132
|
+
return "triangle";
|
|
133
|
+
case "snip2DiagRect":
|
|
134
|
+
return "cutRectDiagonal";
|
|
135
|
+
default:
|
|
136
|
+
return void 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function parseKeypoints(raw) {
|
|
140
|
+
if (!raw) return void 0;
|
|
141
|
+
if (typeof raw === "string") {
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(raw);
|
|
144
|
+
} catch {
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return raw;
|
|
149
|
+
}
|
|
150
|
+
function mapKeypoints(pathFormula, raw) {
|
|
151
|
+
const keypoints = parseKeypoints(raw);
|
|
152
|
+
if (!keypoints) return void 0;
|
|
153
|
+
if (pathFormula === "roundRect") {
|
|
154
|
+
const adj = typeof keypoints.adj === "number" ? keypoints.adj : 0.5;
|
|
155
|
+
return [Math.min(0.5, Math.max(0, adj))];
|
|
156
|
+
}
|
|
157
|
+
if (pathFormula === "triangle") {
|
|
158
|
+
return [typeof keypoints.adj === "number" ? keypoints.adj : 0];
|
|
159
|
+
}
|
|
160
|
+
if (pathFormula === "cutRectDiagonal") {
|
|
161
|
+
const adj2 = typeof keypoints.adj2 === "number" ? keypoints.adj2 : 0.62602;
|
|
162
|
+
return [Number((adj2 / 2).toFixed(5))];
|
|
163
|
+
}
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// element-mapper.ts
|
|
168
|
+
function mapElement(raw) {
|
|
169
|
+
if (!raw || !raw.type) return null;
|
|
170
|
+
const base = mapBaseElement(raw);
|
|
171
|
+
if (raw.type === "text") {
|
|
172
|
+
const content = raw.content !== void 0 ? normalizeTextContent(raw.content) : raw.content;
|
|
173
|
+
const fallbackLineHeight = hasMultiLineText(content) ? 1.5 : 1;
|
|
174
|
+
const lineHeight = raw.lineHeight ?? fallbackLineHeight;
|
|
175
|
+
const normalizedHeight = normalizeTextHeight(base.height, content, lineHeight);
|
|
176
|
+
return {
|
|
177
|
+
...base,
|
|
178
|
+
height: normalizedHeight,
|
|
179
|
+
rotate: base.rotate ?? 0,
|
|
180
|
+
flipH: void 0,
|
|
181
|
+
flipV: void 0,
|
|
182
|
+
content,
|
|
183
|
+
defaultColor: normalizeColor(raw.defaultColor) ?? normalizeColor(raw.color) ?? "#333",
|
|
184
|
+
defaultFontName: raw.fontName ?? "",
|
|
185
|
+
wordSpace: raw.wordSpace,
|
|
186
|
+
lineHeight,
|
|
187
|
+
paragraphSpace: raw.paragraphSpace,
|
|
188
|
+
vertical: raw.isVertical,
|
|
189
|
+
fill: mapFill(raw.fill).fill ?? ""
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (raw.type === "image") {
|
|
193
|
+
const rect = raw.rect ?? {};
|
|
194
|
+
const clipRange = [
|
|
195
|
+
[rect.l ?? 0, rect.t ?? 0],
|
|
196
|
+
[rect.r ?? 100, rect.b ?? 100]
|
|
197
|
+
];
|
|
198
|
+
if (rect.r !== void 0 || rect.b !== void 0) {
|
|
199
|
+
clipRange[1][0] = 100 - (rect.r ?? 0);
|
|
200
|
+
clipRange[1][1] = 100 - (rect.b ?? 0);
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
...base,
|
|
204
|
+
rotate: base.rotate ?? 0,
|
|
205
|
+
fixedRatio: true,
|
|
206
|
+
src: raw.src,
|
|
207
|
+
clip: {
|
|
208
|
+
shape: raw.geom === "ellipse" ? "ellipse" : "rect",
|
|
209
|
+
range: clipRange
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
if (raw.type === "shape") {
|
|
214
|
+
const { fill, pattern } = mapFill(raw.fill);
|
|
215
|
+
const pathFormula = mapPathFormula(raw.shapType);
|
|
216
|
+
const keypoints = pathFormula ? mapKeypoints(pathFormula, raw.keypoints) : void 0;
|
|
217
|
+
const hasText = raw.content !== void 0;
|
|
218
|
+
let path = raw.path;
|
|
219
|
+
let viewBox = raw.viewBox ?? [raw.width ?? 0, raw.height ?? 0];
|
|
220
|
+
let special = false;
|
|
221
|
+
if (raw.shapType === "rect") {
|
|
222
|
+
path = buildRectPath();
|
|
223
|
+
viewBox = [200, 200];
|
|
224
|
+
}
|
|
225
|
+
if (pathFormula && base.width && base.height) {
|
|
226
|
+
if (pathFormula === "roundRect") {
|
|
227
|
+
const radius = (keypoints?.[0] ?? 0.5) * Math.min(base.width, base.height);
|
|
228
|
+
path = buildRoundRectPath(base.width, base.height, radius);
|
|
229
|
+
viewBox = [base.width, base.height];
|
|
230
|
+
} else if (pathFormula === "cutRectDiagonal") {
|
|
231
|
+
const adj = keypoints?.[0] ?? 0.31301;
|
|
232
|
+
path = buildCutRectDiagonalPath(base.width, base.height, adj);
|
|
233
|
+
viewBox = [base.width, base.height];
|
|
234
|
+
}
|
|
235
|
+
} else if (raw.shapType === "ellipse") {
|
|
236
|
+
path = buildEllipsePath();
|
|
237
|
+
viewBox = [200, 200];
|
|
238
|
+
} else if (raw.path) {
|
|
239
|
+
const bounds = getPathBounds(raw.path);
|
|
240
|
+
if (bounds) {
|
|
241
|
+
const rectPath = buildRectPath();
|
|
242
|
+
if (raw.path.trim() === rectPath) {
|
|
243
|
+
viewBox = [200, 200];
|
|
244
|
+
} else if (bounds[0] > viewBox[0] || bounds[1] > viewBox[1]) {
|
|
245
|
+
const ratio = base.width ? bounds[0] / base.width : void 0;
|
|
246
|
+
const nextHeight = ratio && base.height ? base.height * ratio : bounds[1];
|
|
247
|
+
viewBox = [bounds[0], nextHeight];
|
|
248
|
+
if (raw.shapType === "custom" && raw.path.length > 200) {
|
|
249
|
+
special = true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...base,
|
|
256
|
+
rotate: base.rotate ?? 0,
|
|
257
|
+
fixedRatio: false,
|
|
258
|
+
path,
|
|
259
|
+
viewBox,
|
|
260
|
+
pathFormula: pathFormula ?? void 0,
|
|
261
|
+
keypoints: keypoints ?? void 0,
|
|
262
|
+
pattern,
|
|
263
|
+
fill: fill ?? "",
|
|
264
|
+
...special ? { special: true } : {},
|
|
265
|
+
text: hasText ? {
|
|
266
|
+
content: normalizeTextContent(raw.content),
|
|
267
|
+
align: normalizeVAlign(raw.vAlign) ?? "middle",
|
|
268
|
+
defaultColor: normalizeColor(raw.defaultColor) ?? normalizeColor(raw.color) ?? "#333",
|
|
269
|
+
defaultFontName: raw.fontName ?? "",
|
|
270
|
+
lineHeight: raw.lineHeight ?? 1
|
|
271
|
+
} : void 0
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (raw.type === "line") {
|
|
275
|
+
return {
|
|
276
|
+
...base,
|
|
277
|
+
start: toPxPair(raw.start),
|
|
278
|
+
end: toPxPair(raw.end),
|
|
279
|
+
broken: toPxPair(raw.broken),
|
|
280
|
+
broken2: toPxPair(raw.broken2),
|
|
281
|
+
curve: toPxPair(raw.curve),
|
|
282
|
+
cubic: raw.cubic ? raw.cubic.map((point) => toPxPair(point)) : void 0,
|
|
283
|
+
color: mapColor(raw.color),
|
|
284
|
+
points: raw.points,
|
|
285
|
+
style: raw.style
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
...base,
|
|
290
|
+
content: raw.content,
|
|
291
|
+
path: raw.path,
|
|
292
|
+
viewBox: raw.viewBox,
|
|
293
|
+
text: raw.text
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function normalizeElement(element) {
|
|
297
|
+
if (element.type === "shape" && element.outline && (element.height === 0 && element.width || element.width === 0 && element.height)) {
|
|
298
|
+
const isVertical = element.width === 0;
|
|
299
|
+
return {
|
|
300
|
+
type: "line",
|
|
301
|
+
id: element.id,
|
|
302
|
+
groupId: element.groupId,
|
|
303
|
+
left: element.left,
|
|
304
|
+
top: element.top,
|
|
305
|
+
width: element.outline.width,
|
|
306
|
+
start: [0, 0],
|
|
307
|
+
end: isVertical ? [0, element.height ?? 0] : [element.width ?? 0, 0],
|
|
308
|
+
style: element.outline.style,
|
|
309
|
+
color: element.outline.color,
|
|
310
|
+
points: ["", ""]
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
if (element.type === "shape" && element.fill) {
|
|
314
|
+
element.fill = mapFillColor(element.fill) ?? element.fill;
|
|
315
|
+
}
|
|
316
|
+
if (element.type === "text" && element.content) {
|
|
317
|
+
element.content = normalizeTextContent(element.content);
|
|
318
|
+
}
|
|
319
|
+
if (element.type === "shape" && element.text?.content) {
|
|
320
|
+
element.text.content = normalizeTextContent(element.text.content);
|
|
321
|
+
}
|
|
322
|
+
if (element.type === "image") {
|
|
323
|
+
delete element.filters;
|
|
324
|
+
delete element.imageType;
|
|
325
|
+
delete element.outline;
|
|
326
|
+
}
|
|
327
|
+
return element;
|
|
328
|
+
}
|
|
329
|
+
function flattenElements(elements, offsetX = 0, offsetY = 0) {
|
|
330
|
+
const result = [];
|
|
331
|
+
for (const element of elements) {
|
|
332
|
+
if (element?.type === "group" && Array.isArray(element.elements)) {
|
|
333
|
+
const groupLeft = toPx(element.left) ?? 0;
|
|
334
|
+
const groupTop = toPx(element.top) ?? 0;
|
|
335
|
+
result.push(...flattenElements(element.elements, offsetX + groupLeft, offsetY + groupTop));
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
const mapped = mapElement(element);
|
|
339
|
+
if (!mapped) continue;
|
|
340
|
+
if (offsetX || offsetY) {
|
|
341
|
+
if (mapped.left !== void 0) mapped.left = mapped.left + offsetX;
|
|
342
|
+
if (mapped.top !== void 0) mapped.top = mapped.top + offsetY;
|
|
343
|
+
}
|
|
344
|
+
result.push(mapped);
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
function mapShadow(shadow) {
|
|
349
|
+
if (!shadow) return void 0;
|
|
350
|
+
return {
|
|
351
|
+
h: toPx(shadow.h),
|
|
352
|
+
v: toPx(shadow.v),
|
|
353
|
+
blur: toPx(shadow.blur),
|
|
354
|
+
color: mapColor(shadow.color) ?? shadow.color
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function mapOutline(raw) {
|
|
358
|
+
if (!raw) return void 0;
|
|
359
|
+
if (!raw.borderColor && !raw.borderWidth && !raw.borderType) return void 0;
|
|
360
|
+
return {
|
|
361
|
+
width: roundTo(toPx(raw.borderWidth)) ?? void 0,
|
|
362
|
+
color: normalizeColor(raw.borderColor),
|
|
363
|
+
style: raw.borderType
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function mapBaseElement(raw) {
|
|
367
|
+
const outline = mapOutline(raw);
|
|
368
|
+
const shadow = mapShadow(raw.shadow);
|
|
369
|
+
const { fill } = mapFill(raw.fill);
|
|
370
|
+
return {
|
|
371
|
+
type: raw.type,
|
|
372
|
+
id: raw.id,
|
|
373
|
+
groupId: raw.groupId,
|
|
374
|
+
left: toPx(raw.left),
|
|
375
|
+
top: toPx(raw.top),
|
|
376
|
+
width: toPx(raw.width),
|
|
377
|
+
height: toPx(raw.height),
|
|
378
|
+
rotate: raw.rotate,
|
|
379
|
+
fill: fill ?? void 0,
|
|
380
|
+
opacity: raw.opacity,
|
|
381
|
+
outline: outline ?? void 0,
|
|
382
|
+
shadow: shadow ?? void 0,
|
|
383
|
+
flipH: raw.isFlipH,
|
|
384
|
+
flipV: raw.isFlipV
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// slide-normalizer.ts
|
|
389
|
+
var ID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
|
|
390
|
+
function normalizeSlide(slide, index) {
|
|
391
|
+
const backgroundFill = mapFill(slide?.fill);
|
|
392
|
+
const rawElements = [
|
|
393
|
+
...Array.isArray(slide?.layoutElements) ? slide.layoutElements : [],
|
|
394
|
+
...Array.isArray(slide?.elements) ? slide.elements : []
|
|
395
|
+
];
|
|
396
|
+
const orderedElements = rawElements.slice().sort((a, b) => {
|
|
397
|
+
const orderA = typeof a?.order === "number" ? a.order : 0;
|
|
398
|
+
const orderB = typeof b?.order === "number" ? b.order : 0;
|
|
399
|
+
return orderA - orderB;
|
|
400
|
+
});
|
|
401
|
+
const elements = flattenElements(orderedElements).map((element, elementIndex) => {
|
|
402
|
+
if (!element.id) {
|
|
403
|
+
element.id = makeId(`slide-${index}-element-${elementIndex}-${element.type}`);
|
|
404
|
+
}
|
|
405
|
+
return normalizeElement(element);
|
|
406
|
+
});
|
|
407
|
+
return {
|
|
408
|
+
id: slide?.id ?? slide?.slideId ?? makeId(`slide-${index}`),
|
|
409
|
+
background: backgroundFill.fill ? { type: "solid", color: backgroundFill.fill } : backgroundFill.pattern ? { type: "image", src: backgroundFill.pattern } : void 0,
|
|
410
|
+
elements,
|
|
411
|
+
remark: slide?.remark ?? ""
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function makeId(seed) {
|
|
415
|
+
const next = hashSeed(seed);
|
|
416
|
+
let state = next();
|
|
417
|
+
let id = "";
|
|
418
|
+
for (let index = 0; index < 10; index += 1) {
|
|
419
|
+
state = Math.imul(state ^ state >>> 15, state | 1);
|
|
420
|
+
state ^= state + Math.imul(state ^ state >>> 7, state | 61);
|
|
421
|
+
const value = ((state ^ state >>> 14) >>> 0) / 4294967296;
|
|
422
|
+
id += ID_ALPHABET[Math.floor(value * ID_ALPHABET.length)];
|
|
423
|
+
}
|
|
424
|
+
return id;
|
|
425
|
+
}
|
|
426
|
+
function hashSeed(value) {
|
|
427
|
+
let hash = 1779033703 ^ value.length;
|
|
428
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
429
|
+
hash = Math.imul(hash ^ value.charCodeAt(index), 3432918353);
|
|
430
|
+
hash = hash << 13 | hash >>> 19;
|
|
431
|
+
}
|
|
432
|
+
return () => {
|
|
433
|
+
hash = Math.imul(hash ^ hash >>> 16, 2246822507);
|
|
434
|
+
hash = Math.imul(hash ^ hash >>> 13, 3266489909);
|
|
435
|
+
return (hash ^= hash >>> 16) >>> 0;
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// index.ts
|
|
440
|
+
var DEFAULT_DECK_TITLE = "\u672A\u547D\u540D\u6F14\u793A\u6587\u7A3F";
|
|
441
|
+
var DEFAULT_THEME = {
|
|
442
|
+
fontColor: "#333",
|
|
443
|
+
fontName: "",
|
|
444
|
+
backgroundColor: "#fff",
|
|
445
|
+
shadow: {
|
|
446
|
+
h: 3,
|
|
447
|
+
v: 3,
|
|
448
|
+
blur: 2,
|
|
449
|
+
color: "#808080"
|
|
450
|
+
},
|
|
451
|
+
outline: {
|
|
452
|
+
width: 2,
|
|
453
|
+
color: "#525252",
|
|
454
|
+
style: "solid"
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
async function parsePptxToJson(file) {
|
|
458
|
+
const fileBuffer = await file.arrayBuffer();
|
|
459
|
+
const zip = await JSZip.loadAsync(fileBuffer);
|
|
460
|
+
const embedded = ENABLE_DECK_JSON ? await resolveEmbeddedDeck(zip) : null;
|
|
461
|
+
if (embedded?.deck) {
|
|
462
|
+
return {
|
|
463
|
+
deck: embedded.deck,
|
|
464
|
+
warnings: embedded.warnings
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
deck: await buildDeckFromPptx(fileBuffer),
|
|
469
|
+
warnings: embedded?.warnings ?? []
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
async function resolveEmbeddedDeck(zip) {
|
|
473
|
+
const embeddedFile = zip.file(PPTX_JSON_PAYLOAD_PATH) ?? Object.values(zip.files).find(
|
|
474
|
+
(entry) => entry.name.endsWith(`/${PPTX_JSON_PAYLOAD_PATH}`)
|
|
475
|
+
) ?? null;
|
|
476
|
+
if (!embeddedFile) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const payloadText = await embeddedFile.async("string");
|
|
480
|
+
try {
|
|
481
|
+
const parsed = JSON.parse(payloadText);
|
|
482
|
+
if (isDeckEnvelope(parsed) && parsed.deck) {
|
|
483
|
+
return {
|
|
484
|
+
deck: parsed.deck,
|
|
485
|
+
warnings: parsed.version && parsed.version !== PPTX_JSON_PAYLOAD_VERSION ? [
|
|
486
|
+
`Embedded JSON payload version ${parsed.version} differs from ${PPTX_JSON_PAYLOAD_VERSION}.`
|
|
487
|
+
] : []
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
return {
|
|
491
|
+
deck: parsed,
|
|
492
|
+
warnings: []
|
|
493
|
+
};
|
|
494
|
+
} catch {
|
|
495
|
+
return {
|
|
496
|
+
warnings: ["Embedded JSON payload could not be parsed. Falling back to PPTX parsing."]
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function isDeckEnvelope(payload) {
|
|
501
|
+
return typeof payload === "object" && payload !== null && "deck" in payload;
|
|
502
|
+
}
|
|
503
|
+
async function buildDeckFromPptx(buffer) {
|
|
504
|
+
const pptxJson = await parse(buffer);
|
|
505
|
+
const width = toPx(pptxJson.size?.width);
|
|
506
|
+
const height = toPx(pptxJson.size?.height);
|
|
507
|
+
const themeColors = mapThemeColors(pptxJson);
|
|
508
|
+
const slides = (Array.isArray(pptxJson.slides) ? pptxJson.slides : []).map(
|
|
509
|
+
(slide, index) => normalizeSlide(slide, index)
|
|
510
|
+
);
|
|
511
|
+
return {
|
|
512
|
+
title: DEFAULT_DECK_TITLE,
|
|
513
|
+
width,
|
|
514
|
+
height,
|
|
515
|
+
theme: {
|
|
516
|
+
...DEFAULT_THEME,
|
|
517
|
+
themeColors
|
|
518
|
+
},
|
|
519
|
+
slides
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function mapThemeColors(pptxJson) {
|
|
523
|
+
if (!Array.isArray(pptxJson.themeColors)) {
|
|
524
|
+
return void 0;
|
|
525
|
+
}
|
|
526
|
+
return pptxJson.themeColors.map((color) => normalizeThemeColor(color));
|
|
527
|
+
}
|
|
528
|
+
function normalizeThemeColor(color) {
|
|
529
|
+
const mapped = mapColor(color);
|
|
530
|
+
if (!mapped) {
|
|
531
|
+
return color;
|
|
532
|
+
}
|
|
533
|
+
return /^#([0-9A-F]{6}|[0-9A-F]{8})$/.test(mapped) ? mapped : color;
|
|
534
|
+
}
|
|
535
|
+
export {
|
|
536
|
+
parsePptxToJson
|
|
537
|
+
};
|
|
538
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../index.ts","../parser/pptxtojson.ts","../utils.ts","../element-mapper.ts","../slide-normalizer.ts"],"sourcesContent":["import JSZip from 'jszip'\nimport {\n ENABLE_DECK_JSON,\n PPTX_JSON_PAYLOAD_PATH,\n PPTX_JSON_PAYLOAD_VERSION\n} from 'json2pptx'\nimport type { Deck } from './types'\nimport { parse } from './parser/pptxtojson'\nimport type { PptxParseResult } from './parser/pptxtojson'\nimport { normalizeSlide } from './slide-normalizer'\nimport { mapColor, toPx } from './utils'\n\nexport type ParsedResult = {\n deck: Deck\n warnings: string[]\n}\n\ntype EmbeddedDeckPayload =\n | Deck\n | {\n version?: number\n deck?: Deck\n }\n\ntype EmbeddedDeckResolution = {\n deck?: Deck\n warnings: string[]\n}\n\nconst DEFAULT_DECK_TITLE = '未命名演示文稿'\nconst DEFAULT_THEME = {\n fontColor: '#333',\n fontName: '',\n backgroundColor: '#fff',\n shadow: {\n h: 3,\n v: 3,\n blur: 2,\n color: '#808080'\n },\n outline: {\n width: 2,\n color: '#525252',\n style: 'solid'\n }\n} as const\n\nexport async function parsePptxToJson(file: File): Promise<ParsedResult> {\n const fileBuffer = await file.arrayBuffer()\n const zip = await JSZip.loadAsync(fileBuffer)\n\n const embedded = ENABLE_DECK_JSON ? await resolveEmbeddedDeck(zip) : null\n if (embedded?.deck) {\n return {\n deck: embedded.deck,\n warnings: embedded.warnings\n }\n }\n\n return {\n deck: await buildDeckFromPptx(fileBuffer),\n warnings: embedded?.warnings ?? []\n }\n}\n\nasync function resolveEmbeddedDeck(zip: JSZip): Promise<EmbeddedDeckResolution | null> {\n const embeddedFile =\n zip.file(PPTX_JSON_PAYLOAD_PATH) ??\n Object.values(zip.files).find((entry) =>\n entry.name.endsWith(`/${PPTX_JSON_PAYLOAD_PATH}`)\n ) ??\n null\n\n if (!embeddedFile) {\n return null\n }\n\n const payloadText = await embeddedFile.async('string')\n\n try {\n const parsed = JSON.parse(payloadText) as EmbeddedDeckPayload\n\n if (isDeckEnvelope(parsed) && parsed.deck) {\n return {\n deck: parsed.deck,\n warnings:\n parsed.version && parsed.version !== PPTX_JSON_PAYLOAD_VERSION\n ? [\n `Embedded JSON payload version ${parsed.version} differs from ${PPTX_JSON_PAYLOAD_VERSION}.`\n ]\n : []\n }\n }\n\n return {\n deck: parsed as Deck,\n warnings: []\n }\n } catch {\n return {\n warnings: ['Embedded JSON payload could not be parsed. Falling back to PPTX parsing.']\n }\n }\n}\n\nfunction isDeckEnvelope(payload: EmbeddedDeckPayload): payload is { version?: number; deck?: Deck } {\n return typeof payload === 'object' && payload !== null && 'deck' in payload\n}\n\nasync function buildDeckFromPptx(buffer: ArrayBuffer): Promise<Deck> {\n const pptxJson = await parse(buffer)\n const width = toPx(pptxJson.size?.width)\n const height = toPx(pptxJson.size?.height)\n const themeColors = mapThemeColors(pptxJson)\n const slides = (Array.isArray(pptxJson.slides) ? pptxJson.slides : []).map(\n (slide, index) => normalizeSlide(slide, index)\n )\n\n return {\n title: DEFAULT_DECK_TITLE,\n width,\n height,\n theme: {\n ...DEFAULT_THEME,\n themeColors\n },\n slides\n }\n}\n\nfunction mapThemeColors(pptxJson: PptxParseResult): string[] | undefined {\n if (!Array.isArray(pptxJson.themeColors)) {\n return undefined\n }\n\n return pptxJson.themeColors.map((color) => normalizeThemeColor(color))\n}\n\nfunction normalizeThemeColor(color: string): string {\n const mapped = mapColor(color)\n if (!mapped) {\n return color\n }\n\n return /^#([0-9A-F]{6}|[0-9A-F]{8})$/.test(mapped) ? mapped : color\n}\n\nexport type { Deck, Slide, SlideElement } from './types'\n","import { parse as parseWithPptxtojson } from 'pptxtojson/dist/index.js'\n\nexport type PptxParseResult = Awaited<ReturnType<typeof parseWithPptxtojson>>\n\nexport async function parse(file: ArrayBuffer): Promise<PptxParseResult> {\n return parseWithPptxtojson(file)\n}\n","const PT_TO_PX = 96 / 72;\n\ntype FillMapping = { fill?: string; pattern?: string };\n\nexport function toPx(value?: number | null): number | undefined {\n if (value === undefined || value === null) return undefined;\n return value * PT_TO_PX;\n}\n\nexport function toPxPair(value?: [number, number] | null): [number, number] | undefined {\n if (!value) return undefined;\n return [toPx(value[0]) ?? 0, toPx(value[1]) ?? 0];\n}\n\nexport function mapColor(value?: string | null): string | undefined {\n if (!value) return undefined;\n const normalized = value.startsWith(\"#\") ? value : `#${value}`;\n return normalized.toUpperCase();\n}\n\nexport function mapFillColor(value?: string | null): string | undefined {\n if (!value) return undefined;\n return value.startsWith(\"#\") ? value : `#${value}`;\n}\n\nexport function mapFill(fill: any): FillMapping {\n if (!fill) return {};\n if (typeof fill === \"string\") return { fill: mapFillColor(fill) ?? undefined };\n if (typeof fill === \"object\") {\n if (fill.type === \"color\" && typeof fill.value === \"string\") {\n return { fill: mapFillColor(fill.value) ?? undefined };\n }\n if (fill.type === \"image\" && fill.value?.picBase64) {\n return { fill: \"\", pattern: fill.value.picBase64 };\n }\n }\n return {};\n}\n\nfunction convertFontSizeToPx(content: string): string {\n return content.replace(/font-size:\\s*([0-9.]+)pt/gi, (_, size) => {\n const px = Math.floor(Number.parseFloat(size) * PT_TO_PX);\n return `font-size: ${px}px`;\n });\n}\n\nexport function normalizeTextContent(content: string): string {\n return convertFontSizeToPx(content).replace(/ /g, \" \");\n}\n\nexport function normalizeVAlign(value?: string): string | undefined {\n if (!value) return undefined;\n if (value === \"mid\") return \"middle\";\n if (value === \"up\") return \"top\";\n if (value === \"down\") return \"bottom\";\n return value;\n}\n\nexport function roundTo(value?: number | null, digits = 2): number | undefined {\n if (value === undefined || value === null) return undefined;\n const factor = 10 ** digits;\n return Math.round(value * factor) / factor;\n}\n\nexport function normalizeColor(value?: string | null): string | undefined {\n if (!value) return undefined;\n return value.startsWith(\"#\") ? value.toUpperCase() : `#${value}`.toUpperCase();\n}\n\nfunction extractFirstFontSizePx(content?: string): number | undefined {\n if (!content) return undefined;\n const match = content.match(/font-size:\\s*([0-9.]+)px/i);\n if (!match) return undefined;\n const size = Number.parseFloat(match[1]);\n return Number.isFinite(size) ? size : undefined;\n}\n\nexport function normalizeTextHeight(\n height?: number,\n content?: string,\n lineHeight?: number\n): number | undefined {\n if (height === undefined) return height;\n const fontSize = extractFirstFontSizePx(content);\n if (!fontSize) return height;\n const lh = lineHeight ?? 1;\n const base = fontSize * lh;\n const padding = fontSize < 40 ? 21 : 20.5;\n const target = Math.round((base + padding) * 2) / 2;\n if (height > base * 2) return height;\n return target;\n}\n\nexport function hasMultiLineText(content?: string): boolean {\n if (!content) return false;\n if (content.includes(\"<br\")) return true;\n const paragraphs = content.match(/<p\\b/gi);\n return (paragraphs?.length ?? 0) > 1;\n}\n\nexport function getPathBounds(path?: string): [number, number] | undefined {\n if (!path) return undefined;\n const nums = path.match(/-?\\d+\\.?\\d*/g);\n if (!nums || nums.length < 2) return undefined;\n const values = nums.map((value) => Number.parseFloat(value)).filter(Number.isFinite);\n if (!values.length) return undefined;\n let maxX = 0;\n let maxY = 0;\n for (let index = 0; index < values.length; index += 2) {\n const x = values[index];\n const y = values[index + 1];\n if (Number.isFinite(x)) maxX = Math.max(maxX, x);\n if (Number.isFinite(y)) maxY = Math.max(maxY, y);\n }\n if (maxX === 0 && maxY === 0) return undefined;\n return [maxX, maxY];\n}\n\nexport function buildEllipsePath(): string {\n return \"M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z\";\n}\n\nexport function buildRoundRectPath(width: number, height: number, radius: number): string {\n const r = Math.max(0, Math.min(radius, Math.min(width, height)));\n return `M ${r} 0 L ${width - r} 0 Q ${width} 0 ${width} ${r} ` +\n `L ${width} ${height - r} Q ${width} ${height} ${width - r} ${height} ` +\n `L ${r} ${height} Q 0 ${height} 0 ${height - r} ` +\n `L 0 ${r} Q 0 0 ${r} 0 Z`;\n}\n\nexport function buildRectPath(): string {\n return \"M 0 0 L 200 0 L 200 200 L 0 200 Z\";\n}\n\nexport function buildCutRectDiagonalPath(\n width: number,\n height: number,\n adj: number\n): string {\n const cut = height * adj;\n return `M 0 ${height - cut} L 0 0 L ${width - cut} 0 L ${width} ${cut} L ${width} ${height} L ${cut} ${height} Z`;\n}\n\nexport function mapPathFormula(\n shapeType?: string\n): \"roundRect\" | \"triangle\" | \"cutRectDiagonal\" | undefined {\n switch (shapeType) {\n case \"roundRect\":\n return \"roundRect\";\n case \"triangle\":\n return \"triangle\";\n case \"snip2DiagRect\":\n return \"cutRectDiagonal\";\n default:\n return undefined;\n }\n}\n\nfunction parseKeypoints(raw: any): any | undefined {\n if (!raw) return undefined;\n if (typeof raw === \"string\") {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n }\n return raw;\n}\n\nexport function mapKeypoints(pathFormula: string, raw: any): number[] | undefined {\n const keypoints = parseKeypoints(raw);\n if (!keypoints) return undefined;\n if (pathFormula === \"roundRect\") {\n const adj = typeof keypoints.adj === \"number\" ? keypoints.adj : 0.5;\n return [Math.min(0.5, Math.max(0, adj))];\n }\n if (pathFormula === \"triangle\") {\n return [typeof keypoints.adj === \"number\" ? keypoints.adj : 0];\n }\n if (pathFormula === \"cutRectDiagonal\") {\n const adj2 = typeof keypoints.adj2 === \"number\" ? keypoints.adj2 : 0.62602;\n return [Number((adj2 / 2).toFixed(5))];\n }\n return undefined;\n}\n","import type { SlideElement } from './types'\nimport {\n buildCutRectDiagonalPath,\n buildEllipsePath,\n buildRectPath,\n buildRoundRectPath,\n getPathBounds,\n hasMultiLineText,\n mapColor,\n mapFill,\n mapFillColor,\n mapKeypoints,\n mapPathFormula,\n normalizeColor,\n normalizeTextContent,\n normalizeTextHeight,\n normalizeVAlign,\n roundTo,\n toPx,\n toPxPair\n} from \"./utils\";\n\nexport function mapElement(raw: any): SlideElement | null {\n if (!raw || !raw.type) return null;\n const base = mapBaseElement(raw);\n\n if (raw.type === \"text\") {\n const content =\n raw.content !== undefined ? normalizeTextContent(raw.content) : raw.content;\n const fallbackLineHeight = hasMultiLineText(content) ? 1.5 : 1;\n const lineHeight = raw.lineHeight ?? fallbackLineHeight;\n const normalizedHeight = normalizeTextHeight(base.height, content, lineHeight);\n return {\n ...base,\n height: normalizedHeight,\n rotate: base.rotate ?? 0,\n flipH: undefined,\n flipV: undefined,\n content,\n defaultColor: normalizeColor(raw.defaultColor) ?? normalizeColor(raw.color) ?? \"#333\",\n defaultFontName: raw.fontName ?? \"\",\n wordSpace: raw.wordSpace,\n lineHeight,\n paragraphSpace: raw.paragraphSpace,\n vertical: raw.isVertical,\n fill: mapFill(raw.fill).fill ?? \"\"\n };\n }\n\n if (raw.type === \"image\") {\n const rect = raw.rect ?? {};\n const clipRange: [[number, number], [number, number]] = [\n [rect.l ?? 0, rect.t ?? 0],\n [rect.r ?? 100, rect.b ?? 100]\n ];\n if (rect.r !== undefined || rect.b !== undefined) {\n clipRange[1][0] = 100 - (rect.r ?? 0);\n clipRange[1][1] = 100 - (rect.b ?? 0);\n }\n return {\n ...base,\n rotate: base.rotate ?? 0,\n fixedRatio: true,\n src: raw.src,\n clip: {\n shape: raw.geom === \"ellipse\" ? \"ellipse\" : \"rect\",\n range: clipRange\n }\n };\n }\n\n if (raw.type === \"shape\") {\n const { fill, pattern } = mapFill(raw.fill);\n const pathFormula = mapPathFormula(raw.shapType);\n const keypoints = pathFormula ? mapKeypoints(pathFormula, raw.keypoints) : undefined;\n const hasText = raw.content !== undefined;\n let path = raw.path;\n let viewBox = raw.viewBox ?? [raw.width ?? 0, raw.height ?? 0];\n let special = false;\n\n if (raw.shapType === \"rect\") {\n path = buildRectPath();\n viewBox = [200, 200];\n }\n\n if (pathFormula && base.width && base.height) {\n if (pathFormula === \"roundRect\") {\n const radius = (keypoints?.[0] ?? 0.5) * Math.min(base.width, base.height);\n path = buildRoundRectPath(base.width, base.height, radius);\n viewBox = [base.width, base.height];\n } else if (pathFormula === \"cutRectDiagonal\") {\n const adj = keypoints?.[0] ?? 0.31301;\n path = buildCutRectDiagonalPath(base.width, base.height, adj);\n viewBox = [base.width, base.height];\n }\n } else if (raw.shapType === \"ellipse\") {\n path = buildEllipsePath();\n viewBox = [200, 200];\n } else if (raw.path) {\n const bounds = getPathBounds(raw.path);\n if (bounds) {\n const rectPath = buildRectPath();\n if (raw.path.trim() === rectPath) {\n viewBox = [200, 200];\n } else if (bounds[0] > viewBox[0] || bounds[1] > viewBox[1]) {\n const ratio = base.width ? bounds[0] / base.width : undefined;\n const nextHeight =\n ratio && base.height ? base.height * ratio : bounds[1];\n viewBox = [bounds[0], nextHeight];\n if (raw.shapType === \"custom\" && raw.path.length > 200) {\n special = true;\n }\n }\n }\n }\n\n return {\n ...base,\n rotate: base.rotate ?? 0,\n fixedRatio: false,\n path,\n viewBox,\n pathFormula: pathFormula ?? undefined,\n keypoints: keypoints ?? undefined,\n pattern,\n fill: fill ?? \"\",\n ...(special ? { special: true } : {}),\n text: hasText\n ? {\n content: normalizeTextContent(raw.content),\n align: normalizeVAlign(raw.vAlign) ?? \"middle\",\n defaultColor: normalizeColor(raw.defaultColor) ?? normalizeColor(raw.color) ?? \"#333\",\n defaultFontName: raw.fontName ?? \"\",\n lineHeight: raw.lineHeight ?? 1\n }\n : undefined\n };\n }\n\n if (raw.type === \"line\") {\n return {\n ...base,\n start: toPxPair(raw.start),\n end: toPxPair(raw.end),\n broken: toPxPair(raw.broken),\n broken2: toPxPair(raw.broken2),\n curve: toPxPair(raw.curve),\n cubic: raw.cubic\n ? (raw.cubic.map((point: [number, number]) => toPxPair(point)) as [\n [number, number],\n [number, number]\n ])\n : undefined,\n color: mapColor(raw.color),\n points: raw.points,\n style: raw.style\n };\n }\n\n return {\n ...base,\n content: raw.content,\n path: raw.path,\n viewBox: raw.viewBox,\n text: raw.text\n };\n}\n\nexport function normalizeElement(element: SlideElement): SlideElement {\n if (\n element.type === \"shape\" &&\n element.outline &&\n ((element.height === 0 && element.width) || (element.width === 0 && element.height))\n ) {\n const isVertical = element.width === 0;\n return {\n type: \"line\",\n id: element.id,\n groupId: element.groupId,\n left: element.left,\n top: element.top,\n width: element.outline.width,\n start: [0, 0],\n end: isVertical ? [0, element.height ?? 0] : [element.width ?? 0, 0],\n style: element.outline.style,\n color: element.outline.color,\n points: [\"\", \"\"]\n };\n }\n\n if (element.type === \"shape\" && element.fill) {\n element.fill = mapFillColor(element.fill) ?? element.fill;\n }\n\n if (element.type === \"text\" && element.content) {\n element.content = normalizeTextContent(element.content);\n }\n\n if (element.type === \"shape\" && element.text?.content) {\n element.text.content = normalizeTextContent(element.text.content);\n }\n\n if (element.type === \"image\") {\n delete element.filters;\n delete element.imageType;\n delete element.outline;\n }\n\n return element;\n}\n\nexport function flattenElements(\n elements: any[],\n offsetX = 0,\n offsetY = 0\n): SlideElement[] {\n const result: SlideElement[] = [];\n\n for (const element of elements) {\n if (element?.type === \"group\" && Array.isArray(element.elements)) {\n const groupLeft = toPx(element.left) ?? 0;\n const groupTop = toPx(element.top) ?? 0;\n result.push(...flattenElements(element.elements, offsetX + groupLeft, offsetY + groupTop));\n continue;\n }\n\n const mapped = mapElement(element);\n if (!mapped) continue;\n\n if (offsetX || offsetY) {\n if (mapped.left !== undefined) mapped.left = mapped.left + offsetX;\n if (mapped.top !== undefined) mapped.top = mapped.top + offsetY;\n }\n\n result.push(mapped);\n }\n\n return result;\n}\n\nfunction mapShadow(shadow: any): SlideElement[\"shadow\"] | undefined {\n if (!shadow) return undefined;\n return {\n h: toPx(shadow.h),\n v: toPx(shadow.v),\n blur: toPx(shadow.blur),\n color: mapColor(shadow.color) ?? shadow.color\n };\n}\n\nfunction mapOutline(raw: any): SlideElement[\"outline\"] | undefined {\n if (!raw) return undefined;\n if (!raw.borderColor && !raw.borderWidth && !raw.borderType) return undefined;\n return {\n width: roundTo(toPx(raw.borderWidth)) ?? undefined,\n color: normalizeColor(raw.borderColor),\n style: raw.borderType\n };\n}\n\nfunction mapBaseElement(raw: any): SlideElement {\n const outline = mapOutline(raw);\n const shadow = mapShadow(raw.shadow);\n const { fill } = mapFill(raw.fill);\n\n return {\n type: raw.type,\n id: raw.id,\n groupId: raw.groupId,\n left: toPx(raw.left),\n top: toPx(raw.top),\n width: toPx(raw.width),\n height: toPx(raw.height),\n rotate: raw.rotate,\n fill: fill ?? undefined,\n opacity: raw.opacity,\n outline: outline ?? undefined,\n shadow: shadow ?? undefined,\n flipH: raw.isFlipH,\n flipV: raw.isFlipV\n };\n}\n","import type { Slide } from './types'\nimport { flattenElements, normalizeElement } from './element-mapper'\nimport { mapFill } from './utils'\n\nconst ID_ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_\";\n\nexport function normalizeSlide(slide: any, index: number): Slide {\n const backgroundFill = mapFill(slide?.fill);\n const rawElements = [\n ...(Array.isArray(slide?.layoutElements) ? slide.layoutElements : []),\n ...(Array.isArray(slide?.elements) ? slide.elements : [])\n ];\n\n const orderedElements = rawElements.slice().sort((a, b) => {\n const orderA = typeof a?.order === \"number\" ? a.order : 0;\n const orderB = typeof b?.order === \"number\" ? b.order : 0;\n return orderA - orderB;\n });\n\n const elements = flattenElements(orderedElements).map((element, elementIndex) => {\n if (!element.id) {\n element.id = makeId(`slide-${index}-element-${elementIndex}-${element.type}`);\n }\n return normalizeElement(element);\n });\n\n return {\n id: slide?.id ?? slide?.slideId ?? makeId(`slide-${index}`),\n background: backgroundFill.fill\n ? { type: \"solid\", color: backgroundFill.fill }\n : backgroundFill.pattern\n ? { type: \"image\", src: backgroundFill.pattern }\n : undefined,\n elements,\n remark: slide?.remark ?? \"\"\n };\n}\n\nfunction makeId(seed: string): string {\n const next = hashSeed(seed);\n let state = next();\n let id = \"\";\n for (let index = 0; index < 10; index += 1) {\n state = Math.imul(state ^ (state >>> 15), state | 1);\n state ^= state + Math.imul(state ^ (state >>> 7), state | 61);\n const value = ((state ^ (state >>> 14)) >>> 0) / 4294967296;\n id += ID_ALPHABET[Math.floor(value * ID_ALPHABET.length)];\n }\n return id;\n}\n\nfunction hashSeed(value: string): () => number {\n let hash = 1779033703 ^ value.length;\n for (let index = 0; index < value.length; index += 1) {\n hash = Math.imul(hash ^ value.charCodeAt(index), 3432918353);\n hash = (hash << 13) | (hash >>> 19);\n }\n return () => {\n hash = Math.imul(hash ^ (hash >>> 16), 2246822507);\n hash = Math.imul(hash ^ (hash >>> 13), 3266489909);\n return (hash ^= hash >>> 16) >>> 0;\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ppt2json",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Convert PPTX files to json2pptx-compatible JSON decks.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://json2pptx.henryge.com/",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/gezhiheng/json2ppt-editor/"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"module": "dist/index.mjs",
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"require": "./dist/index.js",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"typesVersions": {
|
|
23
|
+
"*": {
|
|
24
|
+
"*": [
|
|
25
|
+
"dist/index.d.ts"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev:watch": "tsup --watch",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
41
|
+
"prepublishOnly": "pnpm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"jszip": "^3.10.1",
|
|
45
|
+
"json2pptx": "0.4.1",
|
|
46
|
+
"pptxtojson": "^1.12.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.10.2",
|
|
50
|
+
"tsup": "^8.5.1",
|
|
51
|
+
"typescript": "^5.6.3"
|
|
52
|
+
}
|
|
53
|
+
}
|