pptx-previewer 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 ADDED
@@ -0,0 +1,87 @@
1
+ # pptx-previewer
2
+
3
+ `pptx-previewer` is a React component for rendering PPTX-like slide JSON in the browser.
4
+
5
+ It is designed to work with JSON produced by PPTX parsers (for example the `pptx2json` output used in this repository) and supports common slide elements:
6
+
7
+ - `shape`
8
+ - `line`
9
+ - `text`
10
+ - `image`
11
+ - `table`
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pnpm add pptx-previewer
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```tsx
22
+ import { PPTXPreviewer, type Slide } from 'pptx-previewer';
23
+
24
+ const slide: Slide = {
25
+ background: { color: '#ffffff' },
26
+ elements: [
27
+ {
28
+ type: 'text',
29
+ left: 40,
30
+ top: 32,
31
+ width: 300,
32
+ height: 60,
33
+ content: '<p>Hello PPTX Preview</p>',
34
+ defaultColor: '#111827',
35
+ defaultFontName: 'Arial'
36
+ }
37
+ ]
38
+ };
39
+
40
+ export function App() {
41
+ return (
42
+ <div style={{ width: 960, height: 540 }}>
43
+ <PPTXPreviewer slide={slide} />
44
+ </div>
45
+ );
46
+ }
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### `PPTXPreviewer`
52
+
53
+ Props:
54
+
55
+ - `slide: Slide` (required)
56
+ - `className?: string`
57
+
58
+ The component fills the size of its parent container. Set width/height on the parent element.
59
+
60
+ ## Types
61
+
62
+ The package exports:
63
+
64
+ - `Slide`
65
+ - `SlideElement`
66
+ - `PPTXPreviewerProps`
67
+
68
+ ## Development
69
+
70
+ ```bash
71
+ cd src/lib/pptx-previewer
72
+ pnpm install
73
+ pnpm run typecheck
74
+ pnpm run build
75
+ ```
76
+
77
+ Build output is generated in `dist/`:
78
+
79
+ - `dist/index.mjs`
80
+ - `dist/index.js`
81
+ - `dist/index.d.ts`
82
+
83
+ ## Notes
84
+
85
+ - This package is `react` peer-dependent (`>=18`).
86
+ - Element coordinates, sizes, and style semantics follow the input JSON schema.
87
+ - Text content is rendered via `dangerouslySetInnerHTML`; sanitize external/untrusted HTML before rendering.
@@ -0,0 +1,103 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type SlideElement = {
4
+ type: string;
5
+ id?: string;
6
+ groupId?: string;
7
+ left?: number;
8
+ top?: number;
9
+ width?: number;
10
+ height?: number;
11
+ rotate?: number;
12
+ fill?: string;
13
+ pattern?: string;
14
+ path?: string;
15
+ viewBox?: [number, number];
16
+ pathFormula?: string;
17
+ keypoints?: number[];
18
+ special?: boolean;
19
+ opacity?: number;
20
+ fixedRatio?: boolean;
21
+ outline?: {
22
+ width?: number;
23
+ color?: string;
24
+ style?: string;
25
+ };
26
+ shadow?: {
27
+ h?: number;
28
+ v?: number;
29
+ blur?: number;
30
+ color?: string;
31
+ };
32
+ content?: string;
33
+ defaultColor?: string;
34
+ defaultFontName?: string;
35
+ wordSpace?: number;
36
+ lineHeight?: number;
37
+ paragraphSpace?: number;
38
+ vertical?: boolean;
39
+ src?: string;
40
+ imageType?: string;
41
+ flipH?: boolean;
42
+ flipV?: boolean;
43
+ start?: [number, number];
44
+ end?: [number, number];
45
+ broken?: [number, number];
46
+ broken2?: [number, number];
47
+ curve?: [number, number];
48
+ cubic?: [[number, number], [number, number]];
49
+ color?: string;
50
+ points?: string[];
51
+ style?: string;
52
+ radius?: number;
53
+ clip?: {
54
+ shape?: string;
55
+ range?: [[number, number], [number, number]];
56
+ };
57
+ filters?: {
58
+ grayscale?: string;
59
+ opacity?: string;
60
+ blur?: string;
61
+ };
62
+ colWidths?: number[];
63
+ data?: Array<Array<{
64
+ id?: string;
65
+ colspan?: number;
66
+ rowspan?: number;
67
+ text?: string;
68
+ style?: {
69
+ fontname?: string;
70
+ color?: string;
71
+ align?: string;
72
+ fontsize?: string;
73
+ backcolor?: string;
74
+ };
75
+ }>>;
76
+ cellMinHeight?: number;
77
+ text?: {
78
+ content: string;
79
+ defaultColor?: string;
80
+ defaultFontName?: string;
81
+ align?: string;
82
+ lineHeight?: number;
83
+ };
84
+ };
85
+ type Slide = {
86
+ id?: string;
87
+ elements?: SlideElement[];
88
+ remark?: string;
89
+ background?: {
90
+ type?: string;
91
+ color?: string;
92
+ src?: string;
93
+ };
94
+ type?: string;
95
+ };
96
+ type PPTXPreviewerProps = {
97
+ slide: Slide;
98
+ className?: string;
99
+ };
100
+
101
+ declare function PPTXPreviewer({ slide, className }: PPTXPreviewerProps): react_jsx_runtime.JSX.Element;
102
+
103
+ export { PPTXPreviewer, type PPTXPreviewerProps, type Slide, type SlideElement };
@@ -0,0 +1,103 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type SlideElement = {
4
+ type: string;
5
+ id?: string;
6
+ groupId?: string;
7
+ left?: number;
8
+ top?: number;
9
+ width?: number;
10
+ height?: number;
11
+ rotate?: number;
12
+ fill?: string;
13
+ pattern?: string;
14
+ path?: string;
15
+ viewBox?: [number, number];
16
+ pathFormula?: string;
17
+ keypoints?: number[];
18
+ special?: boolean;
19
+ opacity?: number;
20
+ fixedRatio?: boolean;
21
+ outline?: {
22
+ width?: number;
23
+ color?: string;
24
+ style?: string;
25
+ };
26
+ shadow?: {
27
+ h?: number;
28
+ v?: number;
29
+ blur?: number;
30
+ color?: string;
31
+ };
32
+ content?: string;
33
+ defaultColor?: string;
34
+ defaultFontName?: string;
35
+ wordSpace?: number;
36
+ lineHeight?: number;
37
+ paragraphSpace?: number;
38
+ vertical?: boolean;
39
+ src?: string;
40
+ imageType?: string;
41
+ flipH?: boolean;
42
+ flipV?: boolean;
43
+ start?: [number, number];
44
+ end?: [number, number];
45
+ broken?: [number, number];
46
+ broken2?: [number, number];
47
+ curve?: [number, number];
48
+ cubic?: [[number, number], [number, number]];
49
+ color?: string;
50
+ points?: string[];
51
+ style?: string;
52
+ radius?: number;
53
+ clip?: {
54
+ shape?: string;
55
+ range?: [[number, number], [number, number]];
56
+ };
57
+ filters?: {
58
+ grayscale?: string;
59
+ opacity?: string;
60
+ blur?: string;
61
+ };
62
+ colWidths?: number[];
63
+ data?: Array<Array<{
64
+ id?: string;
65
+ colspan?: number;
66
+ rowspan?: number;
67
+ text?: string;
68
+ style?: {
69
+ fontname?: string;
70
+ color?: string;
71
+ align?: string;
72
+ fontsize?: string;
73
+ backcolor?: string;
74
+ };
75
+ }>>;
76
+ cellMinHeight?: number;
77
+ text?: {
78
+ content: string;
79
+ defaultColor?: string;
80
+ defaultFontName?: string;
81
+ align?: string;
82
+ lineHeight?: number;
83
+ };
84
+ };
85
+ type Slide = {
86
+ id?: string;
87
+ elements?: SlideElement[];
88
+ remark?: string;
89
+ background?: {
90
+ type?: string;
91
+ color?: string;
92
+ src?: string;
93
+ };
94
+ type?: string;
95
+ };
96
+ type PPTXPreviewerProps = {
97
+ slide: Slide;
98
+ className?: string;
99
+ };
100
+
101
+ declare function PPTXPreviewer({ slide, className }: PPTXPreviewerProps): react_jsx_runtime.JSX.Element;
102
+
103
+ export { PPTXPreviewer, type PPTXPreviewerProps, type Slide, type SlideElement };
package/dist/index.js ADDED
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ PPTXPreviewer: () => PPTXPreviewer
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/renderers/image.tsx
28
+ var import_jsx_runtime = require("react/jsx-runtime");
29
+ function renderImage(element) {
30
+ const filterStr = [
31
+ element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : "",
32
+ element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
33
+ element.filters?.blur ? `blur(${element.filters.blur})` : ""
34
+ ].filter(Boolean).join(" ");
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
36
+ "div",
37
+ {
38
+ style: {
39
+ width: "100%",
40
+ height: "100%",
41
+ overflow: "hidden",
42
+ borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
43
+ filter: filterStr || void 0
44
+ },
45
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
46
+ }
47
+ );
48
+ }
49
+
50
+ // src/constants.ts
51
+ var MIN_LINE_SIZE = 24;
52
+
53
+ // src/renderers/line.tsx
54
+ var import_jsx_runtime2 = require("react/jsx-runtime");
55
+ var getLineDashArray = (width, style) => {
56
+ if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
57
+ if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
58
+ return "0 0";
59
+ };
60
+ var getLinePath = (element) => {
61
+ const start = element.start.join(",");
62
+ const end = element.end.join(",");
63
+ if (element.broken) return `M${start} L${element.broken.join(",")} L${end}`;
64
+ if (element.broken2) {
65
+ const width = Math.abs(element.end[0] - element.start[0]);
66
+ const height = Math.abs(element.end[1] - element.start[1]);
67
+ if (width >= height) {
68
+ return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;
69
+ }
70
+ return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;
71
+ }
72
+ if (element.curve) return `M${start} Q${element.curve.join(",")} ${end}`;
73
+ if (element.cubic) {
74
+ const [c1, c2] = element.cubic;
75
+ return `M${start} C${c1.join(",")} ${c2.join(",")} ${end}`;
76
+ }
77
+ return `M${start} L${end}`;
78
+ };
79
+ function renderLineMarker(props) {
80
+ const pathMap = {
81
+ dot: "m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",
82
+ arrow: "M0,0 L10,5 0,10 Z"
83
+ };
84
+ const rotateMap = {
85
+ "arrow-start": 180,
86
+ "arrow-end": 0
87
+ };
88
+ const size = props.baseSize < 2 ? 2 : props.baseSize;
89
+ const rotate = rotateMap[`${props.type}-${props.position}`] || 0;
90
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
91
+ "marker",
92
+ {
93
+ id: `${props.id}-${props.type}-${props.position}`,
94
+ markerUnits: "userSpaceOnUse",
95
+ orient: "auto",
96
+ markerWidth: size * 3,
97
+ markerHeight: size * 3,
98
+ refX: size * 1.5,
99
+ refY: size * 1.5,
100
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: pathMap[props.type], fill: props.color, transform: `scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)` })
101
+ }
102
+ );
103
+ }
104
+ function renderLine(element, markerId) {
105
+ if (!element.start || !element.end) return null;
106
+ const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);
107
+ const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);
108
+ const lineWidth = element.width ?? 1;
109
+ const dashArray = getLineDashArray(lineWidth, element.style);
110
+ const path = getLinePath(element);
111
+ const points = element.points;
112
+ const startMarker = points?.[0] ? points[0] : void 0;
113
+ const endMarker = points?.[1] ? points[1] : void 0;
114
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { overflow: "visible", width, height, children: [
115
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("defs", { children: [
116
+ startMarker && renderLineMarker({ id: markerId, position: "start", type: startMarker, color: element.color, baseSize: lineWidth }),
117
+ endMarker && renderLineMarker({ id: markerId, position: "end", type: endMarker, color: element.color, baseSize: lineWidth })
118
+ ] }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
120
+ "path",
121
+ {
122
+ d: path,
123
+ stroke: element.color ?? "#000",
124
+ strokeWidth: lineWidth,
125
+ strokeDasharray: dashArray,
126
+ fill: "none",
127
+ markerStart: startMarker ? `url(#${markerId}-${startMarker}-start)` : void 0,
128
+ markerEnd: endMarker ? `url(#${markerId}-${endMarker}-end)` : void 0
129
+ }
130
+ )
131
+ ] });
132
+ }
133
+
134
+ // src/renderers/shape.tsx
135
+ var import_jsx_runtime3 = require("react/jsx-runtime");
136
+ var getOutlineDashArray = (outline) => {
137
+ const style = outline?.style;
138
+ const width = outline?.width ?? 1;
139
+ if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
140
+ if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
141
+ return void 0;
142
+ };
143
+ function renderShape(element, patternId) {
144
+ const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
145
+ const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
146
+ const outlineDashArray = getOutlineDashArray(element.outline);
147
+ const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
148
+ const text = element.text;
149
+ const verticalAlign = text?.align ?? "middle";
150
+ const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
151
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
152
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
153
+ element.pattern && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
154
+ "pattern",
155
+ {
156
+ id: patternId,
157
+ patternUnits: "userSpaceOnUse",
158
+ patternContentUnits: "userSpaceOnUse",
159
+ width: viewWidth,
160
+ height: viewHeight,
161
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
162
+ }
163
+ ) }),
164
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { transform: `scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
165
+ "path",
166
+ {
167
+ vectorEffect: "non-scaling-stroke",
168
+ strokeLinecap: "butt",
169
+ strokeMiterlimit: 8,
170
+ d: element.path || "",
171
+ fill,
172
+ stroke: element.outline?.color,
173
+ strokeWidth: element.outline?.width,
174
+ strokeDasharray: outlineDashArray
175
+ }
176
+ ) })
177
+ ] }),
178
+ text?.content && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
179
+ "div",
180
+ {
181
+ style: {
182
+ position: "absolute",
183
+ inset: 0,
184
+ display: "flex",
185
+ flexDirection: "column",
186
+ justifyContent,
187
+ alignItems: "stretch",
188
+ color: text.defaultColor,
189
+ fontFamily: text.defaultFontName || void 0,
190
+ lineHeight: text.lineHeight,
191
+ pointerEvents: "none"
192
+ },
193
+ dangerouslySetInnerHTML: { __html: text.content }
194
+ }
195
+ )
196
+ ] });
197
+ }
198
+
199
+ // src/renderers/table.tsx
200
+ var import_jsx_runtime4 = require("react/jsx-runtime");
201
+ var parseFontSize = (value) => {
202
+ if (!value) return void 0;
203
+ const size = Number.parseFloat(value);
204
+ return Number.isFinite(size) ? `${size}px` : void 0;
205
+ };
206
+ var normalizeFontName = (value) => {
207
+ if (!value) return void 0;
208
+ return value.replace(/^"+|"+$/g, "");
209
+ };
210
+ var tableColor = (value) => {
211
+ if (!value) return void 0;
212
+ return value.startsWith("rgb") || value.startsWith("#") ? value : void 0;
213
+ };
214
+ var isPlaceholderCell = (cell) => {
215
+ if (!cell) return false;
216
+ const colspan = cell.colspan ?? 1;
217
+ const rowspan = cell.rowspan ?? 1;
218
+ if (colspan !== 1 || rowspan !== 1) return false;
219
+ const style = cell.style;
220
+ const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);
221
+ return (cell.text ?? "").trim() === "" && !hasStyle;
222
+ };
223
+ var buildTableRows = (element) => {
224
+ const rows = element.data ?? [];
225
+ const colCount = element.colWidths?.length ?? 0;
226
+ const rowCells = [];
227
+ const skip = new Array(colCount).fill(0);
228
+ rows.forEach((row, rowIndex) => {
229
+ const cells = [];
230
+ let colIndex = 0;
231
+ let cellIndex = 0;
232
+ while (colIndex < colCount) {
233
+ if (skip[colIndex] > 0) {
234
+ skip[colIndex] -= 1;
235
+ if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
236
+ colIndex += 1;
237
+ continue;
238
+ }
239
+ const cell = row[cellIndex];
240
+ if (!cell) break;
241
+ cellIndex += 1;
242
+ const colSpan = cell.colspan ?? 1;
243
+ const rowSpan = cell.rowspan ?? 1;
244
+ if (rowSpan > 1) {
245
+ for (let i = 0; i < colSpan; i += 1) {
246
+ skip[colIndex + i] = rowSpan - 1;
247
+ }
248
+ }
249
+ if (colSpan > 1) {
250
+ for (let i = 0; i < colSpan - 1; i += 1) {
251
+ if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
252
+ }
253
+ }
254
+ cells.push({
255
+ key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,
256
+ colSpan,
257
+ rowSpan,
258
+ text: cell.text ?? "",
259
+ style: cell.style
260
+ });
261
+ colIndex += colSpan;
262
+ }
263
+ rowCells.push(cells);
264
+ });
265
+ return rowCells;
266
+ };
267
+ function renderTable(element) {
268
+ const colWidths = element.colWidths ?? [];
269
+ const rows = buildTableRows(element);
270
+ const rowCount = rows.length || 1;
271
+ const baseRowHeight = (element.height ?? 0) / rowCount;
272
+ const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;
273
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
274
+ "table",
275
+ {
276
+ style: {
277
+ width: "100%",
278
+ height: "100%",
279
+ tableLayout: "fixed",
280
+ borderCollapse: "collapse",
281
+ border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : void 0
282
+ },
283
+ children: [
284
+ colWidths.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("colgroup", { children: colWidths.map((width, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("col", { style: { width: `${width * 100}%` } }, `col-${index}`)) }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tbody", { children: rows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { style: { height: rowHeight }, children: row.map((cell) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
286
+ "td",
287
+ {
288
+ colSpan: cell.colSpan,
289
+ rowSpan: cell.rowSpan,
290
+ style: {
291
+ border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : "1px solid #ddd",
292
+ background: tableColor(cell.style?.backcolor),
293
+ padding: "6px 8px",
294
+ textAlign: cell.style?.align ?? "left",
295
+ color: tableColor(cell.style?.color),
296
+ fontFamily: normalizeFontName(cell.style?.fontname),
297
+ fontSize: parseFontSize(cell.style?.fontsize),
298
+ verticalAlign: "middle"
299
+ },
300
+ children: cell.text
301
+ },
302
+ cell.key
303
+ )) }, `row-${rowIndex}`)) })
304
+ ]
305
+ }
306
+ ) });
307
+ }
308
+
309
+ // src/renderers/text.tsx
310
+ var import_jsx_runtime5 = require("react/jsx-runtime");
311
+ function renderText(element) {
312
+ const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
313
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
314
+ "div",
315
+ {
316
+ style: {
317
+ width: "100%",
318
+ height: "100%",
319
+ padding: 10,
320
+ lineHeight: element.lineHeight ?? 1.5,
321
+ letterSpacing: `${element.wordSpace ?? 0}px`,
322
+ wordBreak: "break-word",
323
+ fontFamily: element.defaultFontName || "sans-serif",
324
+ color: element.defaultColor,
325
+ writingMode: element.vertical ? "vertical-rl" : void 0,
326
+ ...paragraphStyle
327
+ },
328
+ dangerouslySetInnerHTML: { __html: element.content || "" }
329
+ }
330
+ );
331
+ }
332
+
333
+ // src/renderers/index.tsx
334
+ function renderElement(element, markerId) {
335
+ if (element.type === "shape") return renderShape(element, `shape-${markerId}`);
336
+ if (element.type === "line") return renderLine(element, markerId);
337
+ if (element.type === "text") return renderText(element);
338
+ if (element.type === "image") return renderImage(element);
339
+ if (element.type === "table") return renderTable(element);
340
+ return null;
341
+ }
342
+
343
+ // src/utils/elementSize.ts
344
+ function getElementSize(element) {
345
+ if (element.type === "line" && element.start && element.end) {
346
+ return {
347
+ width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),
348
+ height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)
349
+ };
350
+ }
351
+ return {
352
+ width: element.width ?? 0,
353
+ height: element.height ?? 0
354
+ };
355
+ }
356
+
357
+ // src/utils/elementStyle.ts
358
+ var getShadowFilter = (shadow) => {
359
+ if (!shadow) return void 0;
360
+ const h = shadow.h ?? 0;
361
+ const v = shadow.v ?? 0;
362
+ const blur = shadow.blur ?? 0;
363
+ const color = shadow.color ?? "#000";
364
+ return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;
365
+ };
366
+ var getFlipTransform = (flipH, flipV) => {
367
+ const transforms = [flipH ? "scaleX(-1)" : "", flipV ? "scaleY(-1)" : ""].filter(Boolean).join(" ");
368
+ return transforms || void 0;
369
+ };
370
+
371
+ // src/PPTXPreviewer.tsx
372
+ var import_jsx_runtime6 = require("react/jsx-runtime");
373
+ function PPTXPreviewer({ slide, className }) {
374
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
375
+ "div",
376
+ {
377
+ className,
378
+ style: {
379
+ position: "relative",
380
+ width: "100%",
381
+ height: "100%",
382
+ overflow: "hidden",
383
+ fontSize: 16,
384
+ lineHeight: "normal"
385
+ },
386
+ children: [
387
+ slide.background?.color ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
388
+ "div",
389
+ {
390
+ style: {
391
+ position: "absolute",
392
+ inset: 0,
393
+ backgroundColor: slide.background.color
394
+ }
395
+ }
396
+ ) : null,
397
+ (slide.elements ?? []).map((element, elementIndex) => {
398
+ const size = getElementSize(element);
399
+ const markerId = element.id ?? `line-${elementIndex}`;
400
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
401
+ "div",
402
+ {
403
+ style: {
404
+ position: "absolute",
405
+ left: element.left ?? 0,
406
+ top: element.top ?? 0,
407
+ width: size.width,
408
+ height: size.height
409
+ },
410
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
411
+ "div",
412
+ {
413
+ style: {
414
+ width: "100%",
415
+ height: "100%",
416
+ transform: element.rotate ? `rotate(${element.rotate}deg)` : void 0
417
+ },
418
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
419
+ "div",
420
+ {
421
+ style: {
422
+ position: "relative",
423
+ width: "100%",
424
+ height: "100%",
425
+ opacity: element.opacity ?? 1,
426
+ filter: getShadowFilter(element.shadow),
427
+ transform: getFlipTransform(element.flipH, element.flipV),
428
+ transformOrigin: "center",
429
+ color: element.defaultColor,
430
+ fontFamily: element.defaultFontName
431
+ },
432
+ children: renderElement(element, markerId)
433
+ }
434
+ )
435
+ }
436
+ )
437
+ },
438
+ element.id ?? elementIndex
439
+ );
440
+ })
441
+ ]
442
+ }
443
+ );
444
+ }
445
+ // Annotate the CommonJS export names for ESM import in node:
446
+ 0 && (module.exports = {
447
+ PPTXPreviewer
448
+ });
449
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts","../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts","../src/PPTXPreviewer.tsx"],"sourcesContent":["export { PPTXPreviewer } from './src/PPTXPreviewer';\nexport type { PPTXPreviewerProps, Slide, SlideElement } from './src/types';\n","import type { SlideElement } from '../types';\n\nexport function renderImage(element: SlideElement) {\n const filterStr = [\n element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : '',\n element.filters?.opacity ? `opacity(${element.filters.opacity})` : '',\n element.filters?.blur ? `blur(${element.filters.blur})` : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: element.clip?.shape === 'ellipse' ? '50%' : element.radius ? `${element.radius}px` : undefined,\n filter: filterStr || undefined\n }}\n >\n <img src={element.src || ''} alt='' style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n </div>\n );\n}\n","export const MIN_LINE_SIZE = 24;\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\ntype LineElement = SlideElement & { start: [number, number]; end: [number, number] };\ntype LinePointType = '' | 'arrow' | 'dot';\n\nconst getLineDashArray = (width: number, style?: string) => {\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return '0 0';\n};\n\nconst getLinePath = (element: LineElement) => {\n const start = element.start.join(',');\n const end = element.end.join(',');\n\n if (element.broken) return `M${start} L${element.broken.join(',')} L${end}`;\n\n if (element.broken2) {\n const width = Math.abs(element.end[0] - element.start[0]);\n const height = Math.abs(element.end[1] - element.start[1]);\n if (width >= height) {\n return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;\n }\n return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;\n }\n\n if (element.curve) return `M${start} Q${element.curve.join(',')} ${end}`;\n\n if (element.cubic) {\n const [c1, c2] = element.cubic;\n return `M${start} C${c1.join(',')} ${c2.join(',')} ${end}`;\n }\n\n return `M${start} L${end}`;\n};\n\nfunction renderLineMarker(props: {\n id: string;\n position: 'start' | 'end';\n type: 'arrow' | 'dot';\n baseSize: number;\n color?: string;\n}) {\n const pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z'\n };\n const rotateMap: Record<string, number> = {\n 'arrow-start': 180,\n 'arrow-end': 0\n };\n const size = props.baseSize < 2 ? 2 : props.baseSize;\n const rotate = rotateMap[`${props.type}-${props.position}`] || 0;\n\n return (\n <marker\n id={`${props.id}-${props.type}-${props.position}`}\n markerUnits='userSpaceOnUse'\n orient='auto'\n markerWidth={size * 3}\n markerHeight={size * 3}\n refX={size * 1.5}\n refY={size * 1.5}\n >\n <path d={pathMap[props.type]} fill={props.color} transform={`scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)`} />\n </marker>\n );\n}\n\nexport function renderLine(element: SlideElement, markerId: string) {\n if (!element.start || !element.end) return null;\n\n const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);\n const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);\n const lineWidth = element.width ?? 1;\n const dashArray = getLineDashArray(lineWidth, element.style);\n const path = getLinePath(element as LineElement);\n\n const points = element.points as [LinePointType, LinePointType] | undefined;\n const startMarker = points?.[0] ? points[0] : undefined;\n const endMarker = points?.[1] ? points[1] : undefined;\n\n return (\n <svg overflow='visible' width={width} height={height}>\n <defs>\n {startMarker && renderLineMarker({ id: markerId, position: 'start', type: startMarker, color: element.color, baseSize: lineWidth })}\n {endMarker && renderLineMarker({ id: markerId, position: 'end', type: endMarker, color: element.color, baseSize: lineWidth })}\n </defs>\n <path\n d={path}\n stroke={element.color ?? '#000'}\n strokeWidth={lineWidth}\n strokeDasharray={dashArray}\n fill='none'\n markerStart={startMarker ? `url(#${markerId}-${startMarker}-start)` : undefined}\n markerEnd={endMarker ? `url(#${markerId}-${endMarker}-end)` : undefined}\n />\n </svg>\n );\n}\n","import type { SlideElement } from '../types';\n\nconst getOutlineDashArray = (outline?: SlideElement['outline']) => {\n const style = outline?.style;\n const width = outline?.width ?? 1;\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return undefined;\n};\n\nexport function renderShape(element: SlideElement, patternId: string) {\n const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;\n const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;\n const outlineDashArray = getOutlineDashArray(element.outline);\n const fill = element.pattern ? `url(#${patternId})` : element.fill || 'transparent';\n\n const text = element.text;\n const verticalAlign = text?.align ?? 'middle';\n const justifyContent = verticalAlign === 'top' ? 'flex-start' : verticalAlign === 'bottom' ? 'flex-end' : 'center';\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <svg style={{ position: 'absolute', inset: 0 }} overflow='visible' width={element.width} height={element.height}>\n {element.pattern && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image href={element.pattern} width={viewWidth} height={viewHeight} preserveAspectRatio='xMidYMid slice' />\n </pattern>\n </defs>\n )}\n <g transform={`scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`}>\n <path\n vectorEffect='non-scaling-stroke'\n strokeLinecap='butt'\n strokeMiterlimit={8}\n d={element.path || ''}\n fill={fill}\n stroke={element.outline?.color}\n strokeWidth={element.outline?.width}\n strokeDasharray={outlineDashArray}\n />\n </g>\n </svg>\n\n {text?.content && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n justifyContent,\n alignItems: 'stretch',\n color: text.defaultColor,\n fontFamily: text.defaultFontName || undefined,\n lineHeight: text.lineHeight,\n pointerEvents: 'none'\n }}\n dangerouslySetInnerHTML={{ __html: text.content }}\n />\n )}\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\ntype TableCellData = NonNullable<NonNullable<SlideElement['data']>[number][number]>;\ntype TableCell = {\n key: string;\n colSpan: number;\n rowSpan: number;\n text: string;\n style: TableCellData['style'];\n};\n\nconst parseFontSize = (value?: string) => {\n if (!value) return undefined;\n const size = Number.parseFloat(value);\n return Number.isFinite(size) ? `${size}px` : undefined;\n};\n\nconst normalizeFontName = (value?: string) => {\n if (!value) return undefined;\n return value.replace(/^\"+|\"+$/g, '');\n};\n\nconst tableColor = (value?: string) => {\n if (!value) return undefined;\n return value.startsWith('rgb') || value.startsWith('#') ? value : undefined;\n};\n\nconst isPlaceholderCell = (cell: TableCellData | undefined) => {\n if (!cell) return false;\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n if (colspan !== 1 || rowspan !== 1) return false;\n\n const style = cell.style;\n const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);\n return (cell.text ?? '').trim() === '' && !hasStyle;\n};\n\nconst buildTableRows = (element: SlideElement) => {\n const rows = element.data ?? [];\n const colCount = element.colWidths?.length ?? 0;\n const rowCells: TableCell[][] = [];\n const skip = new Array(colCount).fill(0);\n\n rows.forEach((row, rowIndex) => {\n const cells: TableCell[] = [];\n let colIndex = 0;\n let cellIndex = 0;\n\n while (colIndex < colCount) {\n if (skip[colIndex] > 0) {\n skip[colIndex] -= 1;\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n colIndex += 1;\n continue;\n }\n\n const cell = row[cellIndex];\n if (!cell) break;\n cellIndex += 1;\n\n const colSpan = cell.colspan ?? 1;\n const rowSpan = cell.rowspan ?? 1;\n\n if (rowSpan > 1) {\n for (let i = 0; i < colSpan; i += 1) {\n skip[colIndex + i] = rowSpan - 1;\n }\n }\n\n if (colSpan > 1) {\n for (let i = 0; i < colSpan - 1; i += 1) {\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n }\n }\n\n cells.push({\n key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,\n colSpan,\n rowSpan,\n text: cell.text ?? '',\n style: cell.style\n });\n\n colIndex += colSpan;\n }\n\n rowCells.push(cells);\n });\n\n return rowCells;\n};\n\nexport function renderTable(element: SlideElement) {\n const colWidths = element.colWidths ?? [];\n const rows = buildTableRows(element);\n const rowCount = rows.length || 1;\n const baseRowHeight = (element.height ?? 0) / rowCount;\n const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;\n\n return (\n <div style={{ width: '100%', height: '100%' }}>\n <table\n style={{\n width: '100%',\n height: '100%',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : undefined\n }}\n >\n {colWidths.length > 0 && (\n <colgroup>\n {colWidths.map((width, index) => (\n <col key={`col-${index}`} style={{ width: `${width * 100}%` }} />\n ))}\n </colgroup>\n )}\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={`row-${rowIndex}`} style={{ height: rowHeight }}>\n {row.map((cell) => (\n <td\n key={cell.key}\n colSpan={cell.colSpan}\n rowSpan={cell.rowSpan}\n style={{\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : '1px solid #ddd',\n background: tableColor(cell.style?.backcolor),\n padding: '6px 8px',\n textAlign: (cell.style?.align as CSSProperties['textAlign']) ?? 'left',\n color: tableColor(cell.style?.color),\n fontFamily: normalizeFontName(cell.style?.fontname),\n fontSize: parseFontSize(cell.style?.fontsize),\n verticalAlign: 'middle'\n }}\n >\n {cell.text}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\nexport function renderText(element: SlideElement) {\n const paragraphStyle =\n element.paragraphSpace !== undefined\n ? ({ ['--paragraphSpace' as string]: `${element.paragraphSpace}px` } as CSSProperties)\n : undefined;\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n padding: 10,\n lineHeight: element.lineHeight ?? 1.5,\n letterSpacing: `${element.wordSpace ?? 0}px`,\n wordBreak: 'break-word',\n fontFamily: element.defaultFontName || 'sans-serif',\n color: element.defaultColor,\n writingMode: element.vertical ? 'vertical-rl' : undefined,\n ...paragraphStyle\n }}\n dangerouslySetInnerHTML={{ __html: element.content || '' }}\n />\n );\n}\n","import type { SlideElement } from '../types';\nimport { renderImage } from './image';\nimport { renderLine } from './line';\nimport { renderShape } from './shape';\nimport { renderTable } from './table';\nimport { renderText } from './text';\n\nexport function renderElement(element: SlideElement, markerId: string) {\n if (element.type === 'shape') return renderShape(element, `shape-${markerId}`);\n if (element.type === 'line') return renderLine(element, markerId);\n if (element.type === 'text') return renderText(element);\n if (element.type === 'image') return renderImage(element);\n if (element.type === 'table') return renderTable(element);\n return null;\n}\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\nexport function getElementSize(element: SlideElement): { width: number; height: number } {\n if (element.type === 'line' && element.start && element.end) {\n return {\n width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),\n height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)\n };\n }\n\n return {\n width: element.width ?? 0,\n height: element.height ?? 0\n };\n}\n","import type { SlideElement } from '../types';\n\nexport const getShadowFilter = (shadow?: SlideElement['shadow']) => {\n if (!shadow) return undefined;\n const h = shadow.h ?? 0;\n const v = shadow.v ?? 0;\n const blur = shadow.blur ?? 0;\n const color = shadow.color ?? '#000';\n return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;\n};\n\nexport const getFlipTransform = (flipH?: boolean, flipV?: boolean) => {\n const transforms = [flipH ? 'scaleX(-1)' : '', flipV ? 'scaleY(-1)' : '']\n .filter(Boolean)\n .join(' ');\n return transforms || undefined;\n};\n","import { renderElement } from './renderers';\nimport type { PPTXPreviewerProps } from './types';\nimport { getElementSize } from './utils/elementSize';\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle';\n\nexport function PPTXPreviewer({ slide, className }: PPTXPreviewerProps) {\n return (\n <div\n className={className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n fontSize: 16,\n lineHeight: 'normal'\n }}\n >\n {slide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: slide.background.color\n }}\n />\n ) : null}\n\n {(slide.elements ?? []).map((element, elementIndex) => {\n const size = getElementSize(element);\n const markerId = element.id ?? `line-${elementIndex}`;\n\n return (\n <div\n key={element.id ?? elementIndex}\n style={{\n position: 'absolute',\n left: element.left ?? 0,\n top: element.top ?? 0,\n width: size.width,\n height: size.height\n }}\n >\n <div\n style={{\n width: '100%',\n height: '100%',\n transform: element.rotate ? `rotate(${element.rotate}deg)` : undefined\n }}\n >\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n opacity: element.opacity ?? 1,\n filter: getShadowFilter(element.shadow),\n transform: getFlipTransform(element.flipH, element.flipV),\n transformOrigin: 'center',\n color: element.defaultColor,\n fontFamily: element.defaultFontName\n }}\n >\n {renderElement(element, markerId)}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,422 @@
1
+ // src/renderers/image.tsx
2
+ import { jsx } from "react/jsx-runtime";
3
+ function renderImage(element) {
4
+ const filterStr = [
5
+ element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : "",
6
+ element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
7
+ element.filters?.blur ? `blur(${element.filters.blur})` : ""
8
+ ].filter(Boolean).join(" ");
9
+ return /* @__PURE__ */ jsx(
10
+ "div",
11
+ {
12
+ style: {
13
+ width: "100%",
14
+ height: "100%",
15
+ overflow: "hidden",
16
+ borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
17
+ filter: filterStr || void 0
18
+ },
19
+ children: /* @__PURE__ */ jsx("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
20
+ }
21
+ );
22
+ }
23
+
24
+ // src/constants.ts
25
+ var MIN_LINE_SIZE = 24;
26
+
27
+ // src/renderers/line.tsx
28
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
29
+ var getLineDashArray = (width, style) => {
30
+ if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
31
+ if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
32
+ return "0 0";
33
+ };
34
+ var getLinePath = (element) => {
35
+ const start = element.start.join(",");
36
+ const end = element.end.join(",");
37
+ if (element.broken) return `M${start} L${element.broken.join(",")} L${end}`;
38
+ if (element.broken2) {
39
+ const width = Math.abs(element.end[0] - element.start[0]);
40
+ const height = Math.abs(element.end[1] - element.start[1]);
41
+ if (width >= height) {
42
+ return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;
43
+ }
44
+ return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;
45
+ }
46
+ if (element.curve) return `M${start} Q${element.curve.join(",")} ${end}`;
47
+ if (element.cubic) {
48
+ const [c1, c2] = element.cubic;
49
+ return `M${start} C${c1.join(",")} ${c2.join(",")} ${end}`;
50
+ }
51
+ return `M${start} L${end}`;
52
+ };
53
+ function renderLineMarker(props) {
54
+ const pathMap = {
55
+ dot: "m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",
56
+ arrow: "M0,0 L10,5 0,10 Z"
57
+ };
58
+ const rotateMap = {
59
+ "arrow-start": 180,
60
+ "arrow-end": 0
61
+ };
62
+ const size = props.baseSize < 2 ? 2 : props.baseSize;
63
+ const rotate = rotateMap[`${props.type}-${props.position}`] || 0;
64
+ return /* @__PURE__ */ jsx2(
65
+ "marker",
66
+ {
67
+ id: `${props.id}-${props.type}-${props.position}`,
68
+ markerUnits: "userSpaceOnUse",
69
+ orient: "auto",
70
+ markerWidth: size * 3,
71
+ markerHeight: size * 3,
72
+ refX: size * 1.5,
73
+ refY: size * 1.5,
74
+ children: /* @__PURE__ */ jsx2("path", { d: pathMap[props.type], fill: props.color, transform: `scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)` })
75
+ }
76
+ );
77
+ }
78
+ function renderLine(element, markerId) {
79
+ if (!element.start || !element.end) return null;
80
+ const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);
81
+ const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);
82
+ const lineWidth = element.width ?? 1;
83
+ const dashArray = getLineDashArray(lineWidth, element.style);
84
+ const path = getLinePath(element);
85
+ const points = element.points;
86
+ const startMarker = points?.[0] ? points[0] : void 0;
87
+ const endMarker = points?.[1] ? points[1] : void 0;
88
+ return /* @__PURE__ */ jsxs("svg", { overflow: "visible", width, height, children: [
89
+ /* @__PURE__ */ jsxs("defs", { children: [
90
+ startMarker && renderLineMarker({ id: markerId, position: "start", type: startMarker, color: element.color, baseSize: lineWidth }),
91
+ endMarker && renderLineMarker({ id: markerId, position: "end", type: endMarker, color: element.color, baseSize: lineWidth })
92
+ ] }),
93
+ /* @__PURE__ */ jsx2(
94
+ "path",
95
+ {
96
+ d: path,
97
+ stroke: element.color ?? "#000",
98
+ strokeWidth: lineWidth,
99
+ strokeDasharray: dashArray,
100
+ fill: "none",
101
+ markerStart: startMarker ? `url(#${markerId}-${startMarker}-start)` : void 0,
102
+ markerEnd: endMarker ? `url(#${markerId}-${endMarker}-end)` : void 0
103
+ }
104
+ )
105
+ ] });
106
+ }
107
+
108
+ // src/renderers/shape.tsx
109
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
110
+ var getOutlineDashArray = (outline) => {
111
+ const style = outline?.style;
112
+ const width = outline?.width ?? 1;
113
+ if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
114
+ if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
115
+ return void 0;
116
+ };
117
+ function renderShape(element, patternId) {
118
+ const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
119
+ const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
120
+ const outlineDashArray = getOutlineDashArray(element.outline);
121
+ const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
122
+ const text = element.text;
123
+ const verticalAlign = text?.align ?? "middle";
124
+ const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
125
+ return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
126
+ /* @__PURE__ */ jsxs2("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
127
+ element.pattern && /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsx3(
128
+ "pattern",
129
+ {
130
+ id: patternId,
131
+ patternUnits: "userSpaceOnUse",
132
+ patternContentUnits: "userSpaceOnUse",
133
+ width: viewWidth,
134
+ height: viewHeight,
135
+ children: /* @__PURE__ */ jsx3("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
136
+ }
137
+ ) }),
138
+ /* @__PURE__ */ jsx3("g", { transform: `scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`, children: /* @__PURE__ */ jsx3(
139
+ "path",
140
+ {
141
+ vectorEffect: "non-scaling-stroke",
142
+ strokeLinecap: "butt",
143
+ strokeMiterlimit: 8,
144
+ d: element.path || "",
145
+ fill,
146
+ stroke: element.outline?.color,
147
+ strokeWidth: element.outline?.width,
148
+ strokeDasharray: outlineDashArray
149
+ }
150
+ ) })
151
+ ] }),
152
+ text?.content && /* @__PURE__ */ jsx3(
153
+ "div",
154
+ {
155
+ style: {
156
+ position: "absolute",
157
+ inset: 0,
158
+ display: "flex",
159
+ flexDirection: "column",
160
+ justifyContent,
161
+ alignItems: "stretch",
162
+ color: text.defaultColor,
163
+ fontFamily: text.defaultFontName || void 0,
164
+ lineHeight: text.lineHeight,
165
+ pointerEvents: "none"
166
+ },
167
+ dangerouslySetInnerHTML: { __html: text.content }
168
+ }
169
+ )
170
+ ] });
171
+ }
172
+
173
+ // src/renderers/table.tsx
174
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
175
+ var parseFontSize = (value) => {
176
+ if (!value) return void 0;
177
+ const size = Number.parseFloat(value);
178
+ return Number.isFinite(size) ? `${size}px` : void 0;
179
+ };
180
+ var normalizeFontName = (value) => {
181
+ if (!value) return void 0;
182
+ return value.replace(/^"+|"+$/g, "");
183
+ };
184
+ var tableColor = (value) => {
185
+ if (!value) return void 0;
186
+ return value.startsWith("rgb") || value.startsWith("#") ? value : void 0;
187
+ };
188
+ var isPlaceholderCell = (cell) => {
189
+ if (!cell) return false;
190
+ const colspan = cell.colspan ?? 1;
191
+ const rowspan = cell.rowspan ?? 1;
192
+ if (colspan !== 1 || rowspan !== 1) return false;
193
+ const style = cell.style;
194
+ const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);
195
+ return (cell.text ?? "").trim() === "" && !hasStyle;
196
+ };
197
+ var buildTableRows = (element) => {
198
+ const rows = element.data ?? [];
199
+ const colCount = element.colWidths?.length ?? 0;
200
+ const rowCells = [];
201
+ const skip = new Array(colCount).fill(0);
202
+ rows.forEach((row, rowIndex) => {
203
+ const cells = [];
204
+ let colIndex = 0;
205
+ let cellIndex = 0;
206
+ while (colIndex < colCount) {
207
+ if (skip[colIndex] > 0) {
208
+ skip[colIndex] -= 1;
209
+ if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
210
+ colIndex += 1;
211
+ continue;
212
+ }
213
+ const cell = row[cellIndex];
214
+ if (!cell) break;
215
+ cellIndex += 1;
216
+ const colSpan = cell.colspan ?? 1;
217
+ const rowSpan = cell.rowspan ?? 1;
218
+ if (rowSpan > 1) {
219
+ for (let i = 0; i < colSpan; i += 1) {
220
+ skip[colIndex + i] = rowSpan - 1;
221
+ }
222
+ }
223
+ if (colSpan > 1) {
224
+ for (let i = 0; i < colSpan - 1; i += 1) {
225
+ if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
226
+ }
227
+ }
228
+ cells.push({
229
+ key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,
230
+ colSpan,
231
+ rowSpan,
232
+ text: cell.text ?? "",
233
+ style: cell.style
234
+ });
235
+ colIndex += colSpan;
236
+ }
237
+ rowCells.push(cells);
238
+ });
239
+ return rowCells;
240
+ };
241
+ function renderTable(element) {
242
+ const colWidths = element.colWidths ?? [];
243
+ const rows = buildTableRows(element);
244
+ const rowCount = rows.length || 1;
245
+ const baseRowHeight = (element.height ?? 0) / rowCount;
246
+ const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;
247
+ return /* @__PURE__ */ jsx4("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxs3(
248
+ "table",
249
+ {
250
+ style: {
251
+ width: "100%",
252
+ height: "100%",
253
+ tableLayout: "fixed",
254
+ borderCollapse: "collapse",
255
+ border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : void 0
256
+ },
257
+ children: [
258
+ colWidths.length > 0 && /* @__PURE__ */ jsx4("colgroup", { children: colWidths.map((width, index) => /* @__PURE__ */ jsx4("col", { style: { width: `${width * 100}%` } }, `col-${index}`)) }),
259
+ /* @__PURE__ */ jsx4("tbody", { children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx4("tr", { style: { height: rowHeight }, children: row.map((cell) => /* @__PURE__ */ jsx4(
260
+ "td",
261
+ {
262
+ colSpan: cell.colSpan,
263
+ rowSpan: cell.rowSpan,
264
+ style: {
265
+ border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : "1px solid #ddd",
266
+ background: tableColor(cell.style?.backcolor),
267
+ padding: "6px 8px",
268
+ textAlign: cell.style?.align ?? "left",
269
+ color: tableColor(cell.style?.color),
270
+ fontFamily: normalizeFontName(cell.style?.fontname),
271
+ fontSize: parseFontSize(cell.style?.fontsize),
272
+ verticalAlign: "middle"
273
+ },
274
+ children: cell.text
275
+ },
276
+ cell.key
277
+ )) }, `row-${rowIndex}`)) })
278
+ ]
279
+ }
280
+ ) });
281
+ }
282
+
283
+ // src/renderers/text.tsx
284
+ import { jsx as jsx5 } from "react/jsx-runtime";
285
+ function renderText(element) {
286
+ const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
287
+ return /* @__PURE__ */ jsx5(
288
+ "div",
289
+ {
290
+ style: {
291
+ width: "100%",
292
+ height: "100%",
293
+ padding: 10,
294
+ lineHeight: element.lineHeight ?? 1.5,
295
+ letterSpacing: `${element.wordSpace ?? 0}px`,
296
+ wordBreak: "break-word",
297
+ fontFamily: element.defaultFontName || "sans-serif",
298
+ color: element.defaultColor,
299
+ writingMode: element.vertical ? "vertical-rl" : void 0,
300
+ ...paragraphStyle
301
+ },
302
+ dangerouslySetInnerHTML: { __html: element.content || "" }
303
+ }
304
+ );
305
+ }
306
+
307
+ // src/renderers/index.tsx
308
+ function renderElement(element, markerId) {
309
+ if (element.type === "shape") return renderShape(element, `shape-${markerId}`);
310
+ if (element.type === "line") return renderLine(element, markerId);
311
+ if (element.type === "text") return renderText(element);
312
+ if (element.type === "image") return renderImage(element);
313
+ if (element.type === "table") return renderTable(element);
314
+ return null;
315
+ }
316
+
317
+ // src/utils/elementSize.ts
318
+ function getElementSize(element) {
319
+ if (element.type === "line" && element.start && element.end) {
320
+ return {
321
+ width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),
322
+ height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)
323
+ };
324
+ }
325
+ return {
326
+ width: element.width ?? 0,
327
+ height: element.height ?? 0
328
+ };
329
+ }
330
+
331
+ // src/utils/elementStyle.ts
332
+ var getShadowFilter = (shadow) => {
333
+ if (!shadow) return void 0;
334
+ const h = shadow.h ?? 0;
335
+ const v = shadow.v ?? 0;
336
+ const blur = shadow.blur ?? 0;
337
+ const color = shadow.color ?? "#000";
338
+ return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;
339
+ };
340
+ var getFlipTransform = (flipH, flipV) => {
341
+ const transforms = [flipH ? "scaleX(-1)" : "", flipV ? "scaleY(-1)" : ""].filter(Boolean).join(" ");
342
+ return transforms || void 0;
343
+ };
344
+
345
+ // src/PPTXPreviewer.tsx
346
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
347
+ function PPTXPreviewer({ slide, className }) {
348
+ return /* @__PURE__ */ jsxs4(
349
+ "div",
350
+ {
351
+ className,
352
+ style: {
353
+ position: "relative",
354
+ width: "100%",
355
+ height: "100%",
356
+ overflow: "hidden",
357
+ fontSize: 16,
358
+ lineHeight: "normal"
359
+ },
360
+ children: [
361
+ slide.background?.color ? /* @__PURE__ */ jsx6(
362
+ "div",
363
+ {
364
+ style: {
365
+ position: "absolute",
366
+ inset: 0,
367
+ backgroundColor: slide.background.color
368
+ }
369
+ }
370
+ ) : null,
371
+ (slide.elements ?? []).map((element, elementIndex) => {
372
+ const size = getElementSize(element);
373
+ const markerId = element.id ?? `line-${elementIndex}`;
374
+ return /* @__PURE__ */ jsx6(
375
+ "div",
376
+ {
377
+ style: {
378
+ position: "absolute",
379
+ left: element.left ?? 0,
380
+ top: element.top ?? 0,
381
+ width: size.width,
382
+ height: size.height
383
+ },
384
+ children: /* @__PURE__ */ jsx6(
385
+ "div",
386
+ {
387
+ style: {
388
+ width: "100%",
389
+ height: "100%",
390
+ transform: element.rotate ? `rotate(${element.rotate}deg)` : void 0
391
+ },
392
+ children: /* @__PURE__ */ jsx6(
393
+ "div",
394
+ {
395
+ style: {
396
+ position: "relative",
397
+ width: "100%",
398
+ height: "100%",
399
+ opacity: element.opacity ?? 1,
400
+ filter: getShadowFilter(element.shadow),
401
+ transform: getFlipTransform(element.flipH, element.flipV),
402
+ transformOrigin: "center",
403
+ color: element.defaultColor,
404
+ fontFamily: element.defaultFontName
405
+ },
406
+ children: renderElement(element, markerId)
407
+ }
408
+ )
409
+ }
410
+ )
411
+ },
412
+ element.id ?? elementIndex
413
+ );
414
+ })
415
+ ]
416
+ }
417
+ );
418
+ }
419
+ export {
420
+ PPTXPreviewer
421
+ };
422
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts","../src/PPTXPreviewer.tsx"],"sourcesContent":["import type { SlideElement } from '../types';\n\nexport function renderImage(element: SlideElement) {\n const filterStr = [\n element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : '',\n element.filters?.opacity ? `opacity(${element.filters.opacity})` : '',\n element.filters?.blur ? `blur(${element.filters.blur})` : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: element.clip?.shape === 'ellipse' ? '50%' : element.radius ? `${element.radius}px` : undefined,\n filter: filterStr || undefined\n }}\n >\n <img src={element.src || ''} alt='' style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n </div>\n );\n}\n","export const MIN_LINE_SIZE = 24;\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\ntype LineElement = SlideElement & { start: [number, number]; end: [number, number] };\ntype LinePointType = '' | 'arrow' | 'dot';\n\nconst getLineDashArray = (width: number, style?: string) => {\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return '0 0';\n};\n\nconst getLinePath = (element: LineElement) => {\n const start = element.start.join(',');\n const end = element.end.join(',');\n\n if (element.broken) return `M${start} L${element.broken.join(',')} L${end}`;\n\n if (element.broken2) {\n const width = Math.abs(element.end[0] - element.start[0]);\n const height = Math.abs(element.end[1] - element.start[1]);\n if (width >= height) {\n return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;\n }\n return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;\n }\n\n if (element.curve) return `M${start} Q${element.curve.join(',')} ${end}`;\n\n if (element.cubic) {\n const [c1, c2] = element.cubic;\n return `M${start} C${c1.join(',')} ${c2.join(',')} ${end}`;\n }\n\n return `M${start} L${end}`;\n};\n\nfunction renderLineMarker(props: {\n id: string;\n position: 'start' | 'end';\n type: 'arrow' | 'dot';\n baseSize: number;\n color?: string;\n}) {\n const pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z'\n };\n const rotateMap: Record<string, number> = {\n 'arrow-start': 180,\n 'arrow-end': 0\n };\n const size = props.baseSize < 2 ? 2 : props.baseSize;\n const rotate = rotateMap[`${props.type}-${props.position}`] || 0;\n\n return (\n <marker\n id={`${props.id}-${props.type}-${props.position}`}\n markerUnits='userSpaceOnUse'\n orient='auto'\n markerWidth={size * 3}\n markerHeight={size * 3}\n refX={size * 1.5}\n refY={size * 1.5}\n >\n <path d={pathMap[props.type]} fill={props.color} transform={`scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)`} />\n </marker>\n );\n}\n\nexport function renderLine(element: SlideElement, markerId: string) {\n if (!element.start || !element.end) return null;\n\n const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);\n const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);\n const lineWidth = element.width ?? 1;\n const dashArray = getLineDashArray(lineWidth, element.style);\n const path = getLinePath(element as LineElement);\n\n const points = element.points as [LinePointType, LinePointType] | undefined;\n const startMarker = points?.[0] ? points[0] : undefined;\n const endMarker = points?.[1] ? points[1] : undefined;\n\n return (\n <svg overflow='visible' width={width} height={height}>\n <defs>\n {startMarker && renderLineMarker({ id: markerId, position: 'start', type: startMarker, color: element.color, baseSize: lineWidth })}\n {endMarker && renderLineMarker({ id: markerId, position: 'end', type: endMarker, color: element.color, baseSize: lineWidth })}\n </defs>\n <path\n d={path}\n stroke={element.color ?? '#000'}\n strokeWidth={lineWidth}\n strokeDasharray={dashArray}\n fill='none'\n markerStart={startMarker ? `url(#${markerId}-${startMarker}-start)` : undefined}\n markerEnd={endMarker ? `url(#${markerId}-${endMarker}-end)` : undefined}\n />\n </svg>\n );\n}\n","import type { SlideElement } from '../types';\n\nconst getOutlineDashArray = (outline?: SlideElement['outline']) => {\n const style = outline?.style;\n const width = outline?.width ?? 1;\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return undefined;\n};\n\nexport function renderShape(element: SlideElement, patternId: string) {\n const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;\n const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;\n const outlineDashArray = getOutlineDashArray(element.outline);\n const fill = element.pattern ? `url(#${patternId})` : element.fill || 'transparent';\n\n const text = element.text;\n const verticalAlign = text?.align ?? 'middle';\n const justifyContent = verticalAlign === 'top' ? 'flex-start' : verticalAlign === 'bottom' ? 'flex-end' : 'center';\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <svg style={{ position: 'absolute', inset: 0 }} overflow='visible' width={element.width} height={element.height}>\n {element.pattern && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image href={element.pattern} width={viewWidth} height={viewHeight} preserveAspectRatio='xMidYMid slice' />\n </pattern>\n </defs>\n )}\n <g transform={`scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`}>\n <path\n vectorEffect='non-scaling-stroke'\n strokeLinecap='butt'\n strokeMiterlimit={8}\n d={element.path || ''}\n fill={fill}\n stroke={element.outline?.color}\n strokeWidth={element.outline?.width}\n strokeDasharray={outlineDashArray}\n />\n </g>\n </svg>\n\n {text?.content && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n justifyContent,\n alignItems: 'stretch',\n color: text.defaultColor,\n fontFamily: text.defaultFontName || undefined,\n lineHeight: text.lineHeight,\n pointerEvents: 'none'\n }}\n dangerouslySetInnerHTML={{ __html: text.content }}\n />\n )}\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\ntype TableCellData = NonNullable<NonNullable<SlideElement['data']>[number][number]>;\ntype TableCell = {\n key: string;\n colSpan: number;\n rowSpan: number;\n text: string;\n style: TableCellData['style'];\n};\n\nconst parseFontSize = (value?: string) => {\n if (!value) return undefined;\n const size = Number.parseFloat(value);\n return Number.isFinite(size) ? `${size}px` : undefined;\n};\n\nconst normalizeFontName = (value?: string) => {\n if (!value) return undefined;\n return value.replace(/^\"+|\"+$/g, '');\n};\n\nconst tableColor = (value?: string) => {\n if (!value) return undefined;\n return value.startsWith('rgb') || value.startsWith('#') ? value : undefined;\n};\n\nconst isPlaceholderCell = (cell: TableCellData | undefined) => {\n if (!cell) return false;\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n if (colspan !== 1 || rowspan !== 1) return false;\n\n const style = cell.style;\n const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);\n return (cell.text ?? '').trim() === '' && !hasStyle;\n};\n\nconst buildTableRows = (element: SlideElement) => {\n const rows = element.data ?? [];\n const colCount = element.colWidths?.length ?? 0;\n const rowCells: TableCell[][] = [];\n const skip = new Array(colCount).fill(0);\n\n rows.forEach((row, rowIndex) => {\n const cells: TableCell[] = [];\n let colIndex = 0;\n let cellIndex = 0;\n\n while (colIndex < colCount) {\n if (skip[colIndex] > 0) {\n skip[colIndex] -= 1;\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n colIndex += 1;\n continue;\n }\n\n const cell = row[cellIndex];\n if (!cell) break;\n cellIndex += 1;\n\n const colSpan = cell.colspan ?? 1;\n const rowSpan = cell.rowspan ?? 1;\n\n if (rowSpan > 1) {\n for (let i = 0; i < colSpan; i += 1) {\n skip[colIndex + i] = rowSpan - 1;\n }\n }\n\n if (colSpan > 1) {\n for (let i = 0; i < colSpan - 1; i += 1) {\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n }\n }\n\n cells.push({\n key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,\n colSpan,\n rowSpan,\n text: cell.text ?? '',\n style: cell.style\n });\n\n colIndex += colSpan;\n }\n\n rowCells.push(cells);\n });\n\n return rowCells;\n};\n\nexport function renderTable(element: SlideElement) {\n const colWidths = element.colWidths ?? [];\n const rows = buildTableRows(element);\n const rowCount = rows.length || 1;\n const baseRowHeight = (element.height ?? 0) / rowCount;\n const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;\n\n return (\n <div style={{ width: '100%', height: '100%' }}>\n <table\n style={{\n width: '100%',\n height: '100%',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : undefined\n }}\n >\n {colWidths.length > 0 && (\n <colgroup>\n {colWidths.map((width, index) => (\n <col key={`col-${index}`} style={{ width: `${width * 100}%` }} />\n ))}\n </colgroup>\n )}\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={`row-${rowIndex}`} style={{ height: rowHeight }}>\n {row.map((cell) => (\n <td\n key={cell.key}\n colSpan={cell.colSpan}\n rowSpan={cell.rowSpan}\n style={{\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : '1px solid #ddd',\n background: tableColor(cell.style?.backcolor),\n padding: '6px 8px',\n textAlign: (cell.style?.align as CSSProperties['textAlign']) ?? 'left',\n color: tableColor(cell.style?.color),\n fontFamily: normalizeFontName(cell.style?.fontname),\n fontSize: parseFontSize(cell.style?.fontsize),\n verticalAlign: 'middle'\n }}\n >\n {cell.text}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\nexport function renderText(element: SlideElement) {\n const paragraphStyle =\n element.paragraphSpace !== undefined\n ? ({ ['--paragraphSpace' as string]: `${element.paragraphSpace}px` } as CSSProperties)\n : undefined;\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n padding: 10,\n lineHeight: element.lineHeight ?? 1.5,\n letterSpacing: `${element.wordSpace ?? 0}px`,\n wordBreak: 'break-word',\n fontFamily: element.defaultFontName || 'sans-serif',\n color: element.defaultColor,\n writingMode: element.vertical ? 'vertical-rl' : undefined,\n ...paragraphStyle\n }}\n dangerouslySetInnerHTML={{ __html: element.content || '' }}\n />\n );\n}\n","import type { SlideElement } from '../types';\nimport { renderImage } from './image';\nimport { renderLine } from './line';\nimport { renderShape } from './shape';\nimport { renderTable } from './table';\nimport { renderText } from './text';\n\nexport function renderElement(element: SlideElement, markerId: string) {\n if (element.type === 'shape') return renderShape(element, `shape-${markerId}`);\n if (element.type === 'line') return renderLine(element, markerId);\n if (element.type === 'text') return renderText(element);\n if (element.type === 'image') return renderImage(element);\n if (element.type === 'table') return renderTable(element);\n return null;\n}\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\nexport function getElementSize(element: SlideElement): { width: number; height: number } {\n if (element.type === 'line' && element.start && element.end) {\n return {\n width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),\n height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)\n };\n }\n\n return {\n width: element.width ?? 0,\n height: element.height ?? 0\n };\n}\n","import type { SlideElement } from '../types';\n\nexport const getShadowFilter = (shadow?: SlideElement['shadow']) => {\n if (!shadow) return undefined;\n const h = shadow.h ?? 0;\n const v = shadow.v ?? 0;\n const blur = shadow.blur ?? 0;\n const color = shadow.color ?? '#000';\n return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;\n};\n\nexport const getFlipTransform = (flipH?: boolean, flipV?: boolean) => {\n const transforms = [flipH ? 'scaleX(-1)' : '', flipV ? 'scaleY(-1)' : '']\n .filter(Boolean)\n .join(' ');\n return transforms || undefined;\n};\n","import { renderElement } from './renderers';\nimport type { PPTXPreviewerProps } from './types';\nimport { getElementSize } from './utils/elementSize';\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle';\n\nexport function PPTXPreviewer({ slide, className }: PPTXPreviewerProps) {\n return (\n <div\n className={className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n fontSize: 16,\n lineHeight: 'normal'\n }}\n >\n {slide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: slide.background.color\n }}\n />\n ) : null}\n\n {(slide.elements ?? []).map((element, elementIndex) => {\n const size = getElementSize(element);\n const markerId = element.id ?? `line-${elementIndex}`;\n\n return (\n <div\n key={element.id ?? elementIndex}\n style={{\n position: 'absolute',\n left: element.left ?? 0,\n top: element.top ?? 0,\n width: size.width,\n height: size.height\n }}\n >\n <div\n style={{\n width: '100%',\n height: '100%',\n transform: element.rotate ? `rotate(${element.rotate}deg)` : undefined\n }}\n >\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n opacity: element.opacity ?? 1,\n filter: getShadowFilter(element.shadow),\n transform: getFlipTransform(element.flipH, element.flipV),\n transformOrigin: 'center',\n color: element.defaultColor,\n fontFamily: element.defaultFontName\n }}\n >\n {renderElement(element, markerId)}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "pptx-previewer",
3
+ "version": "0.1.0",
4
+ "description": "A React component to preview PPTX JSON slides in the browser.",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "homepage": "https://json2pptx.henryge.com/",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/gezhiheng/json2ppt-editor/"
13
+ },
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
+ "scripts": {
35
+ "build": "tsup",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit",
37
+ "prepublishOnly": "pnpm run build"
38
+ },
39
+ "peerDependencies": {
40
+ "react": ">=18"
41
+ },
42
+ "devDependencies": {
43
+ "@types/react": "^18.3.3",
44
+ "tsup": "^8.0.1",
45
+ "typescript": "^5.3.3"
46
+ }
47
+ }