pptx-viewer-mcp 2.2.0 → 2.4.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/CHANGELOG.md +12 -0
- package/README.md +20 -19
- package/dist/index.d.ts +237 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +486 -172
- package/dist/index.mjs +479 -174
- package/dist/mcp/index.js +1044 -281
- package/dist/mcp/index.mjs +1045 -282
- package/dist/schemas/index.d.ts +604 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +338 -2
- package/dist/schemas/index.mjs +325 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -22,11 +22,17 @@ async function loadPresentation(filePath, execCtx) {
|
|
|
22
22
|
const pptxData = await handler.load(rawBytes.buffer);
|
|
23
23
|
return { pptxData, rawBytes };
|
|
24
24
|
}
|
|
25
|
-
async function savePresentation(filePath, pptxData, rawBytes, execCtx) {
|
|
25
|
+
async function savePresentation(filePath, pptxData, rawBytes, execCtx, tableStyleSaveOptions) {
|
|
26
26
|
const handler = new pptxViewerCore.PptxHandler();
|
|
27
27
|
await handler.load(rawBytes.buffer);
|
|
28
28
|
const outputBytes = await handler.save(pptxData.slides, {
|
|
29
|
-
headerFooter: pptxData.headerFooter
|
|
29
|
+
headerFooter: pptxData.headerFooter,
|
|
30
|
+
// `pptxData.tableStyleMap` carries any in-memory table-style edits a
|
|
31
|
+
// tool made (e.g. `set_table_style_section`, `create_table_style`);
|
|
32
|
+
// without forwarding it here those edits were silently dropped on
|
|
33
|
+
// save even though the core save pipeline already supports them.
|
|
34
|
+
tableStyles: pptxData.tableStyleMap,
|
|
35
|
+
...tableStyleSaveOptions
|
|
30
36
|
});
|
|
31
37
|
if (execCtx.collaboration) {
|
|
32
38
|
const room = execCtx.collaboration.getRoom(filePath);
|
|
@@ -58,7 +64,13 @@ async function executeToolWithContext(filePath, execCtx, toolFn) {
|
|
|
58
64
|
const { pptxData, rawBytes } = await loadPresentation(filePath, execCtx);
|
|
59
65
|
const toolResult = await toolFn({ pptxData });
|
|
60
66
|
if (toolResult.dirty) {
|
|
61
|
-
const saveResult = await savePresentation(
|
|
67
|
+
const saveResult = await savePresentation(
|
|
68
|
+
filePath,
|
|
69
|
+
toolResult.pptxData,
|
|
70
|
+
rawBytes,
|
|
71
|
+
execCtx,
|
|
72
|
+
toolResult.saveOptions
|
|
73
|
+
);
|
|
62
74
|
return { ...toolResult.result, ...saveResult };
|
|
63
75
|
}
|
|
64
76
|
return toolResult.result;
|
|
@@ -383,6 +395,240 @@ function setCanvasSize(ctx, params) {
|
|
|
383
395
|
result: { canvasWidth: params.width, canvasHeight: params.height }
|
|
384
396
|
};
|
|
385
397
|
}
|
|
398
|
+
var ALT_TEXT_ELEMENT_TYPES = /* @__PURE__ */ new Set(["image", "picture", "table", "chart", "smartArt", "ole", "media", "text", "shape", "connector"]);
|
|
399
|
+
var TITLE_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
400
|
+
"table",
|
|
401
|
+
"chart",
|
|
402
|
+
"smartArt",
|
|
403
|
+
"ole",
|
|
404
|
+
"media",
|
|
405
|
+
"text",
|
|
406
|
+
"shape",
|
|
407
|
+
"connector"
|
|
408
|
+
]);
|
|
409
|
+
function applyElementAltText(el, altText) {
|
|
410
|
+
if (!ALT_TEXT_ELEMENT_TYPES.has(el.type)) {
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Element '${el.id}' (${el.type}) does not support altText; only ${[...ALT_TEXT_ELEMENT_TYPES].join(", ")} elements do.`
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
el.altText = altText;
|
|
416
|
+
}
|
|
417
|
+
function applyElementTitle(el, title) {
|
|
418
|
+
if (!TITLE_ELEMENT_TYPES.has(el.type)) {
|
|
419
|
+
throw new Error(
|
|
420
|
+
`Element '${el.id}' (${el.type}) does not support title; only ${[...TITLE_ELEMENT_TYPES].join(", ")} elements do.`
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
el.title = title;
|
|
424
|
+
}
|
|
425
|
+
function updateElementStyle(ctx, params) {
|
|
426
|
+
const err = validateSlideIndex(params.slideIndex, ctx.pptxData.slides.length);
|
|
427
|
+
if (err) {
|
|
428
|
+
throw new Error(err);
|
|
429
|
+
}
|
|
430
|
+
const slide = ctx.pptxData.slides[params.slideIndex];
|
|
431
|
+
const el = slide.elements.find((e) => e.id === params.elementId);
|
|
432
|
+
if (!el) {
|
|
433
|
+
throw new Error(`Element '${params.elementId}' not found on slide ${params.slideIndex}.`);
|
|
434
|
+
}
|
|
435
|
+
if ("shapeStyle" in el) {
|
|
436
|
+
if (!el.shapeStyle) {
|
|
437
|
+
el.shapeStyle = {};
|
|
438
|
+
}
|
|
439
|
+
const ss = el.shapeStyle;
|
|
440
|
+
if (params.fillThemeColor !== void 0) {
|
|
441
|
+
ss.fillColorRef = params.fillThemeColor;
|
|
442
|
+
const resolved = pptxViewerCore.resolveThemeColorRef(params.fillThemeColor, ctx.pptxData.themeColorMap);
|
|
443
|
+
if (params.fillColor !== void 0) {
|
|
444
|
+
ss.fillColor = params.fillColor;
|
|
445
|
+
} else if (resolved) {
|
|
446
|
+
ss.fillColor = resolved;
|
|
447
|
+
}
|
|
448
|
+
} else if (params.fillColor !== void 0) {
|
|
449
|
+
ss.fillColor = params.fillColor;
|
|
450
|
+
ss.fillColorRef = void 0;
|
|
451
|
+
}
|
|
452
|
+
if (params.fillMode !== void 0) {
|
|
453
|
+
ss.fillMode = params.fillMode;
|
|
454
|
+
}
|
|
455
|
+
if (params.fillGradientStops !== void 0) {
|
|
456
|
+
ss.fillGradientStops = params.fillGradientStops;
|
|
457
|
+
}
|
|
458
|
+
if (params.fillGradientAngle !== void 0) {
|
|
459
|
+
ss.fillGradientAngle = params.fillGradientAngle;
|
|
460
|
+
}
|
|
461
|
+
if (params.fillGradientType !== void 0) {
|
|
462
|
+
ss.fillGradientType = params.fillGradientType;
|
|
463
|
+
}
|
|
464
|
+
if (params.fillOpacity !== void 0) {
|
|
465
|
+
ss.fillOpacity = params.fillOpacity;
|
|
466
|
+
}
|
|
467
|
+
if (params.strokeThemeColor !== void 0) {
|
|
468
|
+
ss.strokeColorRef = params.strokeThemeColor;
|
|
469
|
+
const resolved = pptxViewerCore.resolveThemeColorRef(params.strokeThemeColor, ctx.pptxData.themeColorMap);
|
|
470
|
+
if (params.strokeColor !== void 0) {
|
|
471
|
+
ss.strokeColor = params.strokeColor;
|
|
472
|
+
} else if (resolved) {
|
|
473
|
+
ss.strokeColor = resolved;
|
|
474
|
+
}
|
|
475
|
+
} else if (params.strokeColor !== void 0) {
|
|
476
|
+
ss.strokeColor = params.strokeColor;
|
|
477
|
+
ss.strokeColorRef = void 0;
|
|
478
|
+
}
|
|
479
|
+
if (params.strokeWidth !== void 0) {
|
|
480
|
+
ss.strokeWidth = params.strokeWidth;
|
|
481
|
+
}
|
|
482
|
+
if (params.strokeDash !== void 0) {
|
|
483
|
+
ss.strokeDash = params.strokeDash;
|
|
484
|
+
}
|
|
485
|
+
if (params.strokeOpacity !== void 0) {
|
|
486
|
+
ss.strokeOpacity = params.strokeOpacity;
|
|
487
|
+
}
|
|
488
|
+
if (params.shadowColor !== void 0) {
|
|
489
|
+
ss.shadowColor = params.shadowColor;
|
|
490
|
+
}
|
|
491
|
+
if (params.shadowBlur !== void 0) {
|
|
492
|
+
ss.shadowBlur = params.shadowBlur;
|
|
493
|
+
}
|
|
494
|
+
if (params.shadowOffsetX !== void 0) {
|
|
495
|
+
ss.shadowOffsetX = params.shadowOffsetX;
|
|
496
|
+
}
|
|
497
|
+
if (params.shadowOffsetY !== void 0) {
|
|
498
|
+
ss.shadowOffsetY = params.shadowOffsetY;
|
|
499
|
+
}
|
|
500
|
+
if (params.shadowOpacity !== void 0) {
|
|
501
|
+
ss.shadowOpacity = params.shadowOpacity;
|
|
502
|
+
}
|
|
503
|
+
if (params.glowColor !== void 0) {
|
|
504
|
+
ss.glowColor = params.glowColor;
|
|
505
|
+
}
|
|
506
|
+
if (params.glowRadius !== void 0) {
|
|
507
|
+
ss.glowRadius = params.glowRadius;
|
|
508
|
+
}
|
|
509
|
+
if (params.glowOpacity !== void 0) {
|
|
510
|
+
ss.glowOpacity = params.glowOpacity;
|
|
511
|
+
}
|
|
512
|
+
if (params.softEdgeRadius !== void 0) {
|
|
513
|
+
ss.softEdgeRadius = params.softEdgeRadius;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (params.altText !== void 0) {
|
|
517
|
+
applyElementAltText(el, params.altText);
|
|
518
|
+
}
|
|
519
|
+
if (params.title !== void 0) {
|
|
520
|
+
applyElementTitle(el, params.title);
|
|
521
|
+
}
|
|
522
|
+
if (el.type === "image" || el.type === "picture") {
|
|
523
|
+
const img = el;
|
|
524
|
+
if (params.cropLeft !== void 0) {
|
|
525
|
+
img.cropLeft = params.cropLeft;
|
|
526
|
+
}
|
|
527
|
+
if (params.cropTop !== void 0) {
|
|
528
|
+
img.cropTop = params.cropTop;
|
|
529
|
+
}
|
|
530
|
+
if (params.cropRight !== void 0) {
|
|
531
|
+
img.cropRight = params.cropRight;
|
|
532
|
+
}
|
|
533
|
+
if (params.cropBottom !== void 0) {
|
|
534
|
+
img.cropBottom = params.cropBottom;
|
|
535
|
+
}
|
|
536
|
+
if (params.brightness !== void 0 || params.contrast !== void 0 || params.grayscale !== void 0) {
|
|
537
|
+
if (!img.imageEffects) {
|
|
538
|
+
img.imageEffects = {};
|
|
539
|
+
}
|
|
540
|
+
if (params.brightness !== void 0) {
|
|
541
|
+
img.imageEffects.brightness = params.brightness;
|
|
542
|
+
}
|
|
543
|
+
if (params.contrast !== void 0) {
|
|
544
|
+
img.imageEffects.contrast = params.contrast;
|
|
545
|
+
}
|
|
546
|
+
if (params.grayscale !== void 0) {
|
|
547
|
+
img.imageEffects.grayscale = params.grayscale;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
pptxData: ctx.pptxData,
|
|
553
|
+
dirty: true,
|
|
554
|
+
result: { elementId: params.elementId }
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function runAccessibilityCheck(ctx) {
|
|
558
|
+
const issues = [];
|
|
559
|
+
for (let si = 0; si < ctx.pptxData.slides.length; si++) {
|
|
560
|
+
const slide = ctx.pptxData.slides[si];
|
|
561
|
+
let slideHasText = false;
|
|
562
|
+
for (const el of slide.elements) {
|
|
563
|
+
if (el.type === "image" || el.type === "picture") {
|
|
564
|
+
const img = el;
|
|
565
|
+
if (!img.altText) {
|
|
566
|
+
issues.push({
|
|
567
|
+
slideIndex: si,
|
|
568
|
+
elementId: el.id,
|
|
569
|
+
severity: "error",
|
|
570
|
+
message: `Image element '${el.id}' has no alt text.`
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
if (pptxViewerCore.hasTextProperties(el)) {
|
|
575
|
+
const textEl = el;
|
|
576
|
+
slideHasText = true;
|
|
577
|
+
if (!textEl.text || textEl.text.trim() === "") {
|
|
578
|
+
issues.push({
|
|
579
|
+
slideIndex: si,
|
|
580
|
+
elementId: el.id,
|
|
581
|
+
severity: "info",
|
|
582
|
+
message: `Text element '${el.id}' is empty.`
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
const fs = textEl.textStyle?.fontSize;
|
|
586
|
+
if (fs !== void 0 && fs < 10) {
|
|
587
|
+
issues.push({
|
|
588
|
+
slideIndex: si,
|
|
589
|
+
elementId: el.id,
|
|
590
|
+
severity: "warning",
|
|
591
|
+
message: `Text element '${el.id}' has very small font size (${fs}pt < 10pt).`
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
const textColor = textEl.textStyle?.color?.toLowerCase();
|
|
595
|
+
const bgColor = slide.backgroundColor?.toLowerCase();
|
|
596
|
+
if (textColor && bgColor && textColor === bgColor) {
|
|
597
|
+
issues.push({
|
|
598
|
+
slideIndex: si,
|
|
599
|
+
elementId: el.id,
|
|
600
|
+
severity: "error",
|
|
601
|
+
message: `Text element '${el.id}' has same color as slide background (${textColor}).`
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (!slideHasText) {
|
|
607
|
+
issues.push({
|
|
608
|
+
slideIndex: si,
|
|
609
|
+
severity: "warning",
|
|
610
|
+
message: `Slide ${si + 1} contains no text elements.`
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
615
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
616
|
+
const infoCount = issues.filter((i) => i.severity === "info").length;
|
|
617
|
+
return {
|
|
618
|
+
pptxData: ctx.pptxData,
|
|
619
|
+
dirty: false,
|
|
620
|
+
result: {
|
|
621
|
+
slideCount: ctx.pptxData.slides.length,
|
|
622
|
+
totalIssues: issues.length,
|
|
623
|
+
errorCount,
|
|
624
|
+
warningCount,
|
|
625
|
+
infoCount,
|
|
626
|
+
issues
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// src/tools/element-tools.ts
|
|
386
632
|
function addElement(ctx, params) {
|
|
387
633
|
const err = validateSlideIndex(params.slideIndex, ctx.pptxData.slides.length);
|
|
388
634
|
if (err) {
|
|
@@ -562,6 +808,12 @@ function updateElement(ctx, params) {
|
|
|
562
808
|
if (params.flipV !== void 0) {
|
|
563
809
|
el.flipVertical = params.flipV;
|
|
564
810
|
}
|
|
811
|
+
if (params.altText !== void 0) {
|
|
812
|
+
applyElementAltText(el, params.altText);
|
|
813
|
+
}
|
|
814
|
+
if (params.title !== void 0) {
|
|
815
|
+
applyElementTitle(el, params.title);
|
|
816
|
+
}
|
|
565
817
|
if (pptxViewerCore.hasTextProperties(el)) {
|
|
566
818
|
const textEl = el;
|
|
567
819
|
if (params.text !== void 0) {
|
|
@@ -581,8 +833,17 @@ function updateElement(ctx, params) {
|
|
|
581
833
|
if (params.fontFamily !== void 0) {
|
|
582
834
|
textEl.textStyle.fontFamily = params.fontFamily;
|
|
583
835
|
}
|
|
584
|
-
if (params.
|
|
836
|
+
if (params.fontThemeColor !== void 0) {
|
|
837
|
+
textEl.textStyle.colorRef = params.fontThemeColor;
|
|
838
|
+
const resolved = pptxViewerCore.resolveThemeColorRef(params.fontThemeColor, ctx.pptxData.themeColorMap);
|
|
839
|
+
if (params.fontColor !== void 0) {
|
|
840
|
+
textEl.textStyle.color = params.fontColor;
|
|
841
|
+
} else if (resolved) {
|
|
842
|
+
textEl.textStyle.color = resolved;
|
|
843
|
+
}
|
|
844
|
+
} else if (params.fontColor !== void 0) {
|
|
585
845
|
textEl.textStyle.color = params.fontColor;
|
|
846
|
+
textEl.textStyle.colorRef = void 0;
|
|
586
847
|
}
|
|
587
848
|
if (params.bold !== void 0) {
|
|
588
849
|
textEl.textStyle.bold = params.bold;
|
|
@@ -1073,188 +1334,140 @@ function manageTableStructure(ctx, params) {
|
|
|
1073
1334
|
}
|
|
1074
1335
|
};
|
|
1075
1336
|
}
|
|
1076
|
-
function
|
|
1077
|
-
const err = validateSlideIndex(
|
|
1337
|
+
function findTableElement(ctx, slideIndex, elementId) {
|
|
1338
|
+
const err = validateSlideIndex(slideIndex, ctx.pptxData.slides.length);
|
|
1078
1339
|
if (err) {
|
|
1079
1340
|
throw new Error(err);
|
|
1080
1341
|
}
|
|
1081
|
-
const slide = ctx.pptxData.slides[
|
|
1082
|
-
const el = slide.elements.find((e) => e.id ===
|
|
1342
|
+
const slide = ctx.pptxData.slides[slideIndex];
|
|
1343
|
+
const el = slide.elements.find((e) => e.id === elementId);
|
|
1083
1344
|
if (!el) {
|
|
1084
|
-
throw new Error(`Element '${
|
|
1345
|
+
throw new Error(`Element '${elementId}' not found on slide ${slideIndex}.`);
|
|
1085
1346
|
}
|
|
1086
|
-
if ("
|
|
1087
|
-
|
|
1088
|
-
el.shapeStyle = {};
|
|
1089
|
-
}
|
|
1090
|
-
const ss = el.shapeStyle;
|
|
1091
|
-
if (params.fillColor !== void 0) {
|
|
1092
|
-
ss.fillColor = params.fillColor;
|
|
1093
|
-
}
|
|
1094
|
-
if (params.fillMode !== void 0) {
|
|
1095
|
-
ss.fillMode = params.fillMode;
|
|
1096
|
-
}
|
|
1097
|
-
if (params.fillGradientStops !== void 0) {
|
|
1098
|
-
ss.fillGradientStops = params.fillGradientStops;
|
|
1099
|
-
}
|
|
1100
|
-
if (params.fillGradientAngle !== void 0) {
|
|
1101
|
-
ss.fillGradientAngle = params.fillGradientAngle;
|
|
1102
|
-
}
|
|
1103
|
-
if (params.fillGradientType !== void 0) {
|
|
1104
|
-
ss.fillGradientType = params.fillGradientType;
|
|
1105
|
-
}
|
|
1106
|
-
if (params.fillOpacity !== void 0) {
|
|
1107
|
-
ss.fillOpacity = params.fillOpacity;
|
|
1108
|
-
}
|
|
1109
|
-
if (params.strokeColor !== void 0) {
|
|
1110
|
-
ss.strokeColor = params.strokeColor;
|
|
1111
|
-
}
|
|
1112
|
-
if (params.strokeWidth !== void 0) {
|
|
1113
|
-
ss.strokeWidth = params.strokeWidth;
|
|
1114
|
-
}
|
|
1115
|
-
if (params.strokeDash !== void 0) {
|
|
1116
|
-
ss.strokeDash = params.strokeDash;
|
|
1117
|
-
}
|
|
1118
|
-
if (params.strokeOpacity !== void 0) {
|
|
1119
|
-
ss.strokeOpacity = params.strokeOpacity;
|
|
1120
|
-
}
|
|
1121
|
-
if (params.shadowColor !== void 0) {
|
|
1122
|
-
ss.shadowColor = params.shadowColor;
|
|
1123
|
-
}
|
|
1124
|
-
if (params.shadowBlur !== void 0) {
|
|
1125
|
-
ss.shadowBlur = params.shadowBlur;
|
|
1126
|
-
}
|
|
1127
|
-
if (params.shadowOffsetX !== void 0) {
|
|
1128
|
-
ss.shadowOffsetX = params.shadowOffsetX;
|
|
1129
|
-
}
|
|
1130
|
-
if (params.shadowOffsetY !== void 0) {
|
|
1131
|
-
ss.shadowOffsetY = params.shadowOffsetY;
|
|
1132
|
-
}
|
|
1133
|
-
if (params.shadowOpacity !== void 0) {
|
|
1134
|
-
ss.shadowOpacity = params.shadowOpacity;
|
|
1135
|
-
}
|
|
1136
|
-
if (params.glowColor !== void 0) {
|
|
1137
|
-
ss.glowColor = params.glowColor;
|
|
1138
|
-
}
|
|
1139
|
-
if (params.glowRadius !== void 0) {
|
|
1140
|
-
ss.glowRadius = params.glowRadius;
|
|
1141
|
-
}
|
|
1142
|
-
if (params.glowOpacity !== void 0) {
|
|
1143
|
-
ss.glowOpacity = params.glowOpacity;
|
|
1144
|
-
}
|
|
1145
|
-
if (params.softEdgeRadius !== void 0) {
|
|
1146
|
-
ss.softEdgeRadius = params.softEdgeRadius;
|
|
1147
|
-
}
|
|
1347
|
+
if (el.type !== "table") {
|
|
1348
|
+
throw new Error(`Element '${elementId}' is not a table.`);
|
|
1148
1349
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
if (params.cropTop !== void 0) {
|
|
1158
|
-
img.cropTop = params.cropTop;
|
|
1159
|
-
}
|
|
1160
|
-
if (params.cropRight !== void 0) {
|
|
1161
|
-
img.cropRight = params.cropRight;
|
|
1162
|
-
}
|
|
1163
|
-
if (params.cropBottom !== void 0) {
|
|
1164
|
-
img.cropBottom = params.cropBottom;
|
|
1165
|
-
}
|
|
1166
|
-
if (params.brightness !== void 0 || params.contrast !== void 0 || params.grayscale !== void 0) {
|
|
1167
|
-
if (!img.imageEffects) {
|
|
1168
|
-
img.imageEffects = {};
|
|
1169
|
-
}
|
|
1170
|
-
if (params.brightness !== void 0) {
|
|
1171
|
-
img.imageEffects.brightness = params.brightness;
|
|
1172
|
-
}
|
|
1173
|
-
if (params.contrast !== void 0) {
|
|
1174
|
-
img.imageEffects.contrast = params.contrast;
|
|
1175
|
-
}
|
|
1176
|
-
if (params.grayscale !== void 0) {
|
|
1177
|
-
img.imageEffects.grayscale = params.grayscale;
|
|
1350
|
+
return el;
|
|
1351
|
+
}
|
|
1352
|
+
function tableStyleIdsInUse(ctx) {
|
|
1353
|
+
const used = /* @__PURE__ */ new Set();
|
|
1354
|
+
for (const slide of ctx.pptxData.slides) {
|
|
1355
|
+
for (const el of slide.elements) {
|
|
1356
|
+
if (el.type === "table" && el.tableData?.tableStyleId) {
|
|
1357
|
+
used.add(pptxViewerCore.normalizeTableStyleGuid(el.tableData.tableStyleId));
|
|
1178
1358
|
}
|
|
1179
1359
|
}
|
|
1180
1360
|
}
|
|
1361
|
+
return used;
|
|
1362
|
+
}
|
|
1363
|
+
function setTableStyleSection(ctx, params) {
|
|
1364
|
+
if (!pptxViewerCore.TABLE_STYLE_PART_SEQUENCE.includes(params.section)) {
|
|
1365
|
+
throw new Error(
|
|
1366
|
+
`Unknown table style section '${params.section}'. Valid sections: ${pptxViewerCore.TABLE_STYLE_PART_SEQUENCE.join(", ")}.`
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
const map = ctx.pptxData.tableStyleMap ?? {};
|
|
1370
|
+
ctx.pptxData.tableStyleMap = map;
|
|
1371
|
+
const normalizedId = pptxViewerCore.normalizeTableStyleGuid(params.styleId);
|
|
1372
|
+
const entry = map[normalizedId];
|
|
1373
|
+
if (!entry) {
|
|
1374
|
+
throw new Error(
|
|
1375
|
+
`Table style '${params.styleId}' is not loaded in this presentation. Use create_table_style to add a new one.`
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
if (params.styleName !== void 0) {
|
|
1379
|
+
entry.styleName = params.styleName;
|
|
1380
|
+
}
|
|
1381
|
+
const mutableEntry = entry;
|
|
1382
|
+
if (params.fill !== void 0) {
|
|
1383
|
+
mutableEntry[`${params.section}Fill`] = params.fill;
|
|
1384
|
+
}
|
|
1385
|
+
if (params.text !== void 0) {
|
|
1386
|
+
mutableEntry[`${params.section}Text`] = params.text;
|
|
1387
|
+
}
|
|
1388
|
+
if (params.borders !== void 0) {
|
|
1389
|
+
mutableEntry[`${params.section}Borders`] = params.borders;
|
|
1390
|
+
}
|
|
1391
|
+
if (params.cell3D !== void 0) {
|
|
1392
|
+
mutableEntry[`${params.section}Cell3D`] = params.cell3D;
|
|
1393
|
+
}
|
|
1181
1394
|
return {
|
|
1182
1395
|
pptxData: ctx.pptxData,
|
|
1183
1396
|
dirty: true,
|
|
1184
|
-
result: {
|
|
1397
|
+
result: { styleId: normalizedId, section: params.section }
|
|
1185
1398
|
};
|
|
1186
1399
|
}
|
|
1187
|
-
function
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (el.type === "image" || el.type === "picture") {
|
|
1194
|
-
const img = el;
|
|
1195
|
-
if (!img.altText) {
|
|
1196
|
-
issues.push({
|
|
1197
|
-
slideIndex: si,
|
|
1198
|
-
elementId: el.id,
|
|
1199
|
-
severity: "error",
|
|
1200
|
-
message: `Image element '${el.id}' has no alt text.`
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
if (pptxViewerCore.hasTextProperties(el)) {
|
|
1205
|
-
const textEl = el;
|
|
1206
|
-
slideHasText = true;
|
|
1207
|
-
if (!textEl.text || textEl.text.trim() === "") {
|
|
1208
|
-
issues.push({
|
|
1209
|
-
slideIndex: si,
|
|
1210
|
-
elementId: el.id,
|
|
1211
|
-
severity: "info",
|
|
1212
|
-
message: `Text element '${el.id}' is empty.`
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1215
|
-
const fs = textEl.textStyle?.fontSize;
|
|
1216
|
-
if (fs !== void 0 && fs < 10) {
|
|
1217
|
-
issues.push({
|
|
1218
|
-
slideIndex: si,
|
|
1219
|
-
elementId: el.id,
|
|
1220
|
-
severity: "warning",
|
|
1221
|
-
message: `Text element '${el.id}' has very small font size (${fs}pt < 10pt).`
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
const textColor = textEl.textStyle?.color?.toLowerCase();
|
|
1225
|
-
const bgColor = slide.backgroundColor?.toLowerCase();
|
|
1226
|
-
if (textColor && bgColor && textColor === bgColor) {
|
|
1227
|
-
issues.push({
|
|
1228
|
-
slideIndex: si,
|
|
1229
|
-
elementId: el.id,
|
|
1230
|
-
severity: "error",
|
|
1231
|
-
message: `Text element '${el.id}' has same color as slide background (${textColor}).`
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
if (!slideHasText) {
|
|
1237
|
-
issues.push({
|
|
1238
|
-
slideIndex: si,
|
|
1239
|
-
severity: "warning",
|
|
1240
|
-
message: `Slide ${si + 1} contains no text elements.`
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1400
|
+
function createTableStyle(ctx, params) {
|
|
1401
|
+
const map = ctx.pptxData.tableStyleMap ?? {};
|
|
1402
|
+
ctx.pptxData.tableStyleMap = map;
|
|
1403
|
+
const basedOn = params.basedOnStyleId ? map[pptxViewerCore.normalizeTableStyleGuid(params.basedOnStyleId)] : void 0;
|
|
1404
|
+
if (params.basedOnStyleId && !basedOn) {
|
|
1405
|
+
throw new Error(`basedOnStyleId '${params.basedOnStyleId}' is not a loaded table style.`);
|
|
1243
1406
|
}
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
const infoCount = issues.filter((i) => i.severity === "info").length;
|
|
1407
|
+
const entry = pptxViewerCore.createTableStyleEntry(map, { styleName: params.styleName, basedOn });
|
|
1408
|
+
pptxViewerCore.addTableStyleToMap(map, entry);
|
|
1247
1409
|
return {
|
|
1248
1410
|
pptxData: ctx.pptxData,
|
|
1249
|
-
dirty:
|
|
1250
|
-
result: {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1411
|
+
dirty: true,
|
|
1412
|
+
result: { styleId: entry.styleId },
|
|
1413
|
+
...params.setAsDefault ? { saveOptions: { tableStylesDefaultId: entry.styleId } } : {}
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
function deleteTableStyle(ctx, params) {
|
|
1417
|
+
const normalizedId = pptxViewerCore.normalizeTableStyleGuid(params.styleId);
|
|
1418
|
+
if (!params.force) {
|
|
1419
|
+
const used = tableStyleIdsInUse(ctx);
|
|
1420
|
+
if (used.has(normalizedId)) {
|
|
1421
|
+
throw new Error(
|
|
1422
|
+
`Table style '${params.styleId}' is assigned to at least one table on this deck. Reassign those tables first, or pass force: true.`
|
|
1423
|
+
);
|
|
1257
1424
|
}
|
|
1425
|
+
}
|
|
1426
|
+
const map = ctx.pptxData.tableStyleMap ?? {};
|
|
1427
|
+
ctx.pptxData.tableStyleMap = map;
|
|
1428
|
+
pptxViewerCore.deleteTableStyleFromMap(map, normalizedId);
|
|
1429
|
+
return {
|
|
1430
|
+
pptxData: ctx.pptxData,
|
|
1431
|
+
dirty: true,
|
|
1432
|
+
result: { deleted: true },
|
|
1433
|
+
saveOptions: { tableStylesToDelete: [normalizedId] }
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function assignTableStyle(ctx, params) {
|
|
1437
|
+
const el = findTableElement(ctx, params.slideIndex, params.elementId);
|
|
1438
|
+
if (!el.tableData) {
|
|
1439
|
+
throw new Error(`Table '${params.elementId}' has no tableData.`);
|
|
1440
|
+
}
|
|
1441
|
+
const styleId = params.styleId ?? ctx.pptxData.tableStylesDefaultId;
|
|
1442
|
+
if (!styleId) {
|
|
1443
|
+
throw new Error(
|
|
1444
|
+
"styleId was not provided and this presentation has no tableStylesDefaultId to fall back to."
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
const normalizedId = pptxViewerCore.normalizeTableStyleGuid(styleId);
|
|
1448
|
+
el.tableData.tableStyleId = normalizedId;
|
|
1449
|
+
if (params.bandedRows !== void 0) {
|
|
1450
|
+
el.tableData.bandedRows = params.bandedRows;
|
|
1451
|
+
}
|
|
1452
|
+
if (params.bandedColumns !== void 0) {
|
|
1453
|
+
el.tableData.bandedColumns = params.bandedColumns;
|
|
1454
|
+
}
|
|
1455
|
+
if (params.firstRowHeader !== void 0) {
|
|
1456
|
+
el.tableData.firstRowHeader = params.firstRowHeader;
|
|
1457
|
+
}
|
|
1458
|
+
if (params.lastRow !== void 0) {
|
|
1459
|
+
el.tableData.lastRow = params.lastRow;
|
|
1460
|
+
}
|
|
1461
|
+
if (params.firstCol !== void 0) {
|
|
1462
|
+
el.tableData.firstCol = params.firstCol;
|
|
1463
|
+
}
|
|
1464
|
+
if (params.lastCol !== void 0) {
|
|
1465
|
+
el.tableData.lastCol = params.lastCol;
|
|
1466
|
+
}
|
|
1467
|
+
return {
|
|
1468
|
+
pptxData: ctx.pptxData,
|
|
1469
|
+
dirty: true,
|
|
1470
|
+
result: { elementId: params.elementId, styleId: normalizedId }
|
|
1258
1471
|
};
|
|
1259
1472
|
}
|
|
1260
1473
|
var MAX_REGEX_LEN = 200;
|
|
@@ -1863,6 +2076,98 @@ function findChartElement(ctx, slideIndex, elementId) {
|
|
|
1863
2076
|
}
|
|
1864
2077
|
return el;
|
|
1865
2078
|
}
|
|
2079
|
+
function formatChartDataPoint(ctx, params) {
|
|
2080
|
+
const chart = findChartElement(ctx, params.slideIndex, params.elementId);
|
|
2081
|
+
if (params.clearStyle) {
|
|
2082
|
+
pptxViewerCore.setChartDataPointStyle(chart, params.seriesIndex, params.pointIndex, null);
|
|
2083
|
+
} else if (params.fillColor !== void 0 || params.strokeColor !== void 0 || params.strokeWidth !== void 0 || params.strokeDashStyle !== void 0) {
|
|
2084
|
+
pptxViewerCore.setChartDataPointStyle(chart, params.seriesIndex, params.pointIndex, {
|
|
2085
|
+
...params.fillColor !== void 0 ? { fillColor: params.fillColor } : {},
|
|
2086
|
+
...params.strokeColor !== void 0 ? { strokeColor: params.strokeColor } : {},
|
|
2087
|
+
...params.strokeWidth !== void 0 ? { strokeWidth: params.strokeWidth } : {},
|
|
2088
|
+
...params.strokeDashStyle !== void 0 ? { strokeDashStyle: params.strokeDashStyle } : {}
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
if (params.explosion !== void 0) {
|
|
2092
|
+
pptxViewerCore.setChartDataPointExplosion(chart, params.seriesIndex, params.pointIndex, params.explosion);
|
|
2093
|
+
}
|
|
2094
|
+
if (params.marker !== void 0) {
|
|
2095
|
+
pptxViewerCore.setChartDataPointMarker(chart, params.seriesIndex, params.pointIndex, params.marker);
|
|
2096
|
+
}
|
|
2097
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2098
|
+
}
|
|
2099
|
+
function formatChartDataLabel(ctx, params) {
|
|
2100
|
+
const chart = findChartElement(ctx, params.slideIndex, params.elementId);
|
|
2101
|
+
if (params.remove) {
|
|
2102
|
+
pptxViewerCore.setChartDataPointLabel(chart, params.seriesIndex, params.pointIndex, null);
|
|
2103
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2104
|
+
}
|
|
2105
|
+
pptxViewerCore.setChartDataPointLabel(chart, params.seriesIndex, params.pointIndex, {
|
|
2106
|
+
...params.showValue !== void 0 ? { showValue: params.showValue } : {},
|
|
2107
|
+
...params.showCategory !== void 0 ? { showCategory: params.showCategory } : {},
|
|
2108
|
+
...params.showSeriesName !== void 0 ? { showSeriesName: params.showSeriesName } : {},
|
|
2109
|
+
...params.showPercent !== void 0 ? { showPercent: params.showPercent } : {},
|
|
2110
|
+
...params.showLegendKey !== void 0 ? { showLegendKey: params.showLegendKey } : {},
|
|
2111
|
+
...params.position !== void 0 ? { position: params.position } : {},
|
|
2112
|
+
...params.text !== void 0 ? { text: params.text } : {},
|
|
2113
|
+
...params.spPr !== void 0 ? { spPr: params.spPr } : {},
|
|
2114
|
+
...params.txPr !== void 0 ? { txPr: params.txPr } : {}
|
|
2115
|
+
});
|
|
2116
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2117
|
+
}
|
|
2118
|
+
function formatChartSeries(ctx, params) {
|
|
2119
|
+
const chart = findChartElement(ctx, params.slideIndex, params.elementId);
|
|
2120
|
+
if (params.marker !== void 0) {
|
|
2121
|
+
if (params.marker === null) {
|
|
2122
|
+
pptxViewerCore.setChartSeriesMarker(chart, params.seriesIndex, null);
|
|
2123
|
+
} else if (params.marker.strokeColor !== void 0 || params.marker.strokeWidth !== void 0 || params.marker.strokeDashStyle !== void 0) {
|
|
2124
|
+
pptxViewerCore.setChartSeriesMarker(chart, params.seriesIndex, {
|
|
2125
|
+
symbol: params.marker.symbol ?? "circle",
|
|
2126
|
+
...params.marker.size !== void 0 ? { size: params.marker.size } : {},
|
|
2127
|
+
spPr: {
|
|
2128
|
+
...params.marker.fillColor !== void 0 ? { fillColor: params.marker.fillColor } : {},
|
|
2129
|
+
...params.marker.strokeColor !== void 0 ? { strokeColor: params.marker.strokeColor } : {},
|
|
2130
|
+
...params.marker.strokeWidth !== void 0 ? { strokeWidth: params.marker.strokeWidth } : {},
|
|
2131
|
+
...params.marker.strokeDashStyle !== void 0 ? { strokeDashStyle: params.marker.strokeDashStyle } : {}
|
|
2132
|
+
}
|
|
2133
|
+
});
|
|
2134
|
+
} else {
|
|
2135
|
+
pptxViewerCore.setChartSeriesMarker(chart, params.seriesIndex, params.marker);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
if (params.trendline !== void 0) {
|
|
2139
|
+
pptxViewerCore.setChartSeriesTrendline(chart, params.seriesIndex, params.trendline);
|
|
2140
|
+
}
|
|
2141
|
+
if (params.errorBars !== void 0) {
|
|
2142
|
+
pptxViewerCore.setChartSeriesErrorBars(chart, params.seriesIndex, params.errorBars);
|
|
2143
|
+
}
|
|
2144
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2145
|
+
}
|
|
2146
|
+
function setChartHelperLineT(ctx, params) {
|
|
2147
|
+
const chart = findChartElement(ctx, params.slideIndex, params.elementId);
|
|
2148
|
+
pptxViewerCore.setChartHelperLine(chart, params.line, params.style);
|
|
2149
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2150
|
+
}
|
|
2151
|
+
function setChartColorMapOverrideT(ctx, params) {
|
|
2152
|
+
const chart = findChartElement(ctx, params.slideIndex, params.elementId);
|
|
2153
|
+
pptxViewerCore.setChartColorMapOverride(chart, params.overrides);
|
|
2154
|
+
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
2155
|
+
}
|
|
2156
|
+
function findChartElement2(ctx, slideIndex, elementId) {
|
|
2157
|
+
const err = validateSlideIndex(slideIndex, ctx.pptxData.slides.length);
|
|
2158
|
+
if (err) {
|
|
2159
|
+
throw new Error(err);
|
|
2160
|
+
}
|
|
2161
|
+
const slide = ctx.pptxData.slides[slideIndex];
|
|
2162
|
+
const el = slide.elements.find((e) => e.id === elementId);
|
|
2163
|
+
if (!el) {
|
|
2164
|
+
throw new Error(`Element '${elementId}' not found on slide ${slideIndex}.`);
|
|
2165
|
+
}
|
|
2166
|
+
if (el.type !== "chart") {
|
|
2167
|
+
throw new Error(`Element '${elementId}' is not a chart.`);
|
|
2168
|
+
}
|
|
2169
|
+
return el;
|
|
2170
|
+
}
|
|
1866
2171
|
function buildShape(input) {
|
|
1867
2172
|
return {
|
|
1868
2173
|
kind: input.kind ?? "sp",
|
|
@@ -1878,17 +2183,17 @@ function buildShape(input) {
|
|
|
1878
2183
|
};
|
|
1879
2184
|
}
|
|
1880
2185
|
function listChartUserShapesT(ctx, params) {
|
|
1881
|
-
const chart =
|
|
2186
|
+
const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
|
|
1882
2187
|
return { pptxData: ctx.pptxData, dirty: false, result: { shapes: pptxViewerCore.listChartUserShapes(chart) } };
|
|
1883
2188
|
}
|
|
1884
2189
|
function addChartUserShapeT(ctx, params) {
|
|
1885
|
-
const chart =
|
|
2190
|
+
const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
|
|
1886
2191
|
pptxViewerCore.addChartUserShape(chart, buildShape(params.shape));
|
|
1887
2192
|
const index = (chart.chartData?.userShapes?.length ?? 1) - 1;
|
|
1888
2193
|
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId, index } };
|
|
1889
2194
|
}
|
|
1890
2195
|
function updateChartUserShapeT(ctx, params) {
|
|
1891
|
-
const chart =
|
|
2196
|
+
const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
|
|
1892
2197
|
const patch = {
|
|
1893
2198
|
...params.patch.kind ? { kind: params.patch.kind } : {},
|
|
1894
2199
|
...params.patch.anchor ? { anchor: params.patch.anchor } : {},
|
|
@@ -1905,7 +2210,7 @@ function updateChartUserShapeT(ctx, params) {
|
|
|
1905
2210
|
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
1906
2211
|
}
|
|
1907
2212
|
function removeChartUserShapeT(ctx, params) {
|
|
1908
|
-
const chart =
|
|
2213
|
+
const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
|
|
1909
2214
|
pptxViewerCore.removeChartUserShape(chart, params.index);
|
|
1910
2215
|
return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
|
|
1911
2216
|
}
|
|
@@ -2661,12 +2966,15 @@ exports.applyLayout = applyLayout;
|
|
|
2661
2966
|
exports.applyTemplateT = applyTemplateT;
|
|
2662
2967
|
exports.applyThemePreset = applyThemePreset;
|
|
2663
2968
|
exports.arrangeElements = arrangeElements;
|
|
2969
|
+
exports.assignTableStyle = assignTableStyle;
|
|
2664
2970
|
exports.batchUpdateElements = batchUpdateElements;
|
|
2665
2971
|
exports.cloneElement = cloneElement;
|
|
2666
2972
|
exports.convertToMarkdown = convertToMarkdown;
|
|
2667
2973
|
exports.createChart = createChart;
|
|
2974
|
+
exports.createTableStyle = createTableStyle;
|
|
2668
2975
|
exports.deleteElements = deleteElements;
|
|
2669
2976
|
exports.deleteSlides = deleteSlides;
|
|
2977
|
+
exports.deleteTableStyle = deleteTableStyle;
|
|
2670
2978
|
exports.describeElement = describeElement;
|
|
2671
2979
|
exports.diffPresentationsT = diffPresentationsT;
|
|
2672
2980
|
exports.duplicateSlide = duplicateSlide;
|
|
@@ -2677,6 +2985,9 @@ exports.exportToSvg = exportToSvg;
|
|
|
2677
2985
|
exports.extractSlideText = extractSlideText;
|
|
2678
2986
|
exports.findPlaceholdersT = findPlaceholdersT;
|
|
2679
2987
|
exports.findText = findText;
|
|
2988
|
+
exports.formatChartDataLabel = formatChartDataLabel;
|
|
2989
|
+
exports.formatChartDataPoint = formatChartDataPoint;
|
|
2990
|
+
exports.formatChartSeries = formatChartSeries;
|
|
2680
2991
|
exports.generateElementId = generateElementId;
|
|
2681
2992
|
exports.generateSlideId = generateSlideId;
|
|
2682
2993
|
exports.getLayouts = getLayouts;
|
|
@@ -2704,9 +3015,12 @@ exports.replaceText = replaceText;
|
|
|
2704
3015
|
exports.runAccessibilityCheck = runAccessibilityCheck;
|
|
2705
3016
|
exports.savePresentation = savePresentation;
|
|
2706
3017
|
exports.setCanvasSize = setCanvasSize;
|
|
3018
|
+
exports.setChartColorMapOverrideT = setChartColorMapOverrideT;
|
|
3019
|
+
exports.setChartHelperLineT = setChartHelperLineT;
|
|
2707
3020
|
exports.setElementAnimation = setElementAnimation;
|
|
2708
3021
|
exports.setElementLockT = setElementLockT;
|
|
2709
3022
|
exports.setSlideTransition = setSlideTransition;
|
|
3023
|
+
exports.setTableStyleSection = setTableStyleSection;
|
|
2710
3024
|
exports.ungroupElements = ungroupElements;
|
|
2711
3025
|
exports.updateChart = updateChart;
|
|
2712
3026
|
exports.updateChartSeriesData = updateChartSeriesData;
|