pptx-kit-preview 0.3.0 → 0.3.2
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/dist/index.js +129 -127
- package/dist/index.js.map +1 -1
- package/dist/node.js +129 -127
- package/dist/node.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getSlideSize, getPresentationTheme, getEffectiveColorMap, getSlideBackground, getSlideLayout, getSlideLayoutBackground, getSlideMasterBackground, getSlideBackgroundGradientFill, getSlideLayoutBackgroundGradientFill, getSlideMasterBackgroundGradientFill, getSlideBackgroundPatternFill, getSlideLayoutBackgroundPatternFill, getSlideMasterBackgroundPatternFill, getSlideBackgroundImageBytes, getSlideLayoutBackgroundImageBytes, getSlideMasterBackgroundImageBytes, getSlideMasterShapes, getSlideLayoutShapes, getSlideShapes, getShapeBoundsResolved, getShapeKind, getShapeFillEffective, getShapeStrokeEffective, getShapeRotation, getShapeFlip, getShapePlaceholderType, getShapeImageFormat, getShapeImageBytes, getShapeImageFillBytes, getShapePreset, getGroupTransform, getGroupChildren, isChartShape, isTableShape, getTableDimensions, getShapeCustomGeometry, getShapeXmlString, getShapeAdjustValues, getShapeHyperlink, getShapeHyperlinkTooltip, getShapeName, getShapeAltTitle, getShapeDescription, getShapeClickAction, getSlideIndex, getShapeParagraphCount, getPresentationFonts, getShapeBodyPrEffective, getShapeTextMargins, getShapeTextDirection, getShapeTextAnchor, isShapePlaceholder, isShapeTextBox, getParagraphPropertiesEffective, getParagraphLevel, getParagraphAlignment, getParagraphBullet, getParagraphBulletStyle, isParagraphBulletPicture, getParagraphBulletImageBytes, getParagraphSpacing, getParagraphIndent, getShapeParagraphElements, getShapeRunFormatEffective, getShapeRunFormat, getShapeRunHyperlink, getShapeRunClickAction, getShapeRunHyperlinkTooltip, getShapeTextAutoFitParams, getShapeTextColumns, getShapeTextBodyRotationDeg, getShapeImagePartName, getShapeImageCrop, getShapeImageBrightness, getShapeImageContrast, getShapeImageOpacity, isShapeImageGrayscale, getShapeImageBiLevelThreshold, getShapeImageDuotone, getShapeImageLinkUrl, getShapeFillColorResolved, getShapeGradientFillEffective, getShapeGradientFill, getShapePatternFill, getShapeStrokeColorResolved, getShapeStrokeDash, getShapeStrokeCap, getShapeStrokeJoin, getShapeStrokeCompound, getShapeStrokeArrow, getShapeChartSpec, getTableColumnWidths, getTableRowHeights, getTableCells, getTableStyleFlags, getTableCellSpan, getTableCellFill, getTableCellBorders, getTableCellParagraphs, getTableCellAnchor, getTableCellMargins, getShapeEffectsEffective } from 'pptx-kit';
|
|
1
|
+
import { getSlideSize, getPresentationTheme, getEffectiveColorMap, resolveDeckBodyTextColor, getSlideBackground, getSlideLayout, getSlideLayoutBackground, getSlideMasterBackground, getSlideBackgroundGradientFill, getSlideLayoutBackgroundGradientFill, getSlideMasterBackgroundGradientFill, getSlideBackgroundPatternFill, getSlideLayoutBackgroundPatternFill, getSlideMasterBackgroundPatternFill, getSlideBackgroundImageBytes, getSlideLayoutBackgroundImageBytes, getSlideMasterBackgroundImageBytes, getSlideMasterShapes, getSlideLayoutShapes, getSlideShapes, getShapeBoundsResolved, getShapeKind, getShapeFillEffective, getShapeStrokeEffective, getShapeRotation, getShapeFlip, getShapePlaceholderType, getShapeImageFormat, getShapeImageBytes, getShapeImageFillBytes, getShapePreset, getGroupTransform, getGroupChildren, isChartShape, isTableShape, getTableDimensions, getShapeCustomGeometry, getShapeXmlString, getShapeAdjustValues, getShapeHyperlink, getShapeHyperlinkTooltip, getShapeName, getShapeAltTitle, getShapeDescription, getShapeClickAction, getSlideIndex, getShapeParagraphCount, getPresentationFonts, getShapeBodyPrEffective, getShapeTextMargins, getShapeTextDirection, getShapeTextAnchor, isShapePlaceholder, isShapeTextBox, getParagraphPropertiesEffective, getParagraphLevel, getParagraphAlignment, getParagraphBullet, getParagraphBulletStyle, isParagraphBulletPicture, getParagraphBulletImageBytes, getParagraphSpacing, getParagraphIndent, getShapeParagraphElements, getShapeRunFormatEffective, getShapeRunFormat, getShapeRunHyperlink, getShapeRunClickAction, getShapeRunHyperlinkTooltip, getShapeTextAutoFitParams, getShapeTextColumns, getShapeTextBodyRotationDeg, getShapeImagePartName, getShapeImageCrop, getShapeImageBrightness, getShapeImageContrast, getShapeImageOpacity, isShapeImageGrayscale, getShapeImageBiLevelThreshold, getShapeImageDuotone, getShapeImageLinkUrl, getShapeFillColorResolved, getShapeGradientFillEffective, getShapeGradientFill, getShapePatternFill, getShapeStrokeColorResolved, getShapeStrokeDash, getShapeStrokeCap, getShapeStrokeJoin, getShapeStrokeCompound, getShapeStrokeArrow, getShapeChartSpec, getTableColumnWidths, getTableRowHeights, getTableCells, getTableStyleFlags, getTableCellSpan, getTableCellFill, getTableCellBorders, getTableCellParagraphs, getTableCellAnchor, getTableCellMargins, getShapeEffectsEffective } from 'pptx-kit';
|
|
2
2
|
|
|
3
3
|
// src/render-slide.ts
|
|
4
4
|
|
|
@@ -560,6 +560,7 @@ var resolveColor = (c, theme, fallback = "#1F2937") => {
|
|
|
560
560
|
var nextDefId = 0;
|
|
561
561
|
var mintId = () => `pkdef-${(nextDefId++).toString(36)}`;
|
|
562
562
|
var activeColorMap = null;
|
|
563
|
+
var activeDeckTextColor = "#000000";
|
|
563
564
|
var gradientDef = (grad, theme) => {
|
|
564
565
|
const id = mintId();
|
|
565
566
|
const stops = grad.stops.map(
|
|
@@ -602,27 +603,23 @@ var patternDef = (pat) => {
|
|
|
602
603
|
return `<path d="M0 0L${W} ${H}" stroke="${fg}" stroke-width="${width}"/>`;
|
|
603
604
|
return `<path d="M${W} 0L0 ${H}" stroke="${fg}" stroke-width="${width}"/>`;
|
|
604
605
|
};
|
|
605
|
-
const
|
|
606
|
-
|
|
606
|
+
const BAYER4 = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
|
|
607
|
+
const screen = (density) => {
|
|
608
|
+
const threshold = density * 16;
|
|
607
609
|
const out = [];
|
|
608
|
-
|
|
609
|
-
[
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
[2, 6],
|
|
615
|
-
[6, 6]
|
|
616
|
-
];
|
|
617
|
-
for (const [x, y] of grid.slice(0, count)) {
|
|
618
|
-
out.push(`<circle cx="${x}" cy="${y}" r="0.7" fill="${fg}"/>`);
|
|
610
|
+
for (let i = 0; i < 16; i++) {
|
|
611
|
+
if (BAYER4[i] < threshold) {
|
|
612
|
+
const cx = i % 4 * 2;
|
|
613
|
+
const cy = Math.floor(i / 4) * 2;
|
|
614
|
+
out.push(`<rect x="${cx}" y="${cy}" width="2" height="2" fill="${fg}"/>`);
|
|
615
|
+
}
|
|
619
616
|
}
|
|
620
617
|
return out.join("");
|
|
621
618
|
};
|
|
622
619
|
const pctMatch = /^pct(\d+)$/.exec(preset);
|
|
623
620
|
if (pctMatch) {
|
|
624
|
-
const pct = Math.min(100, Math.max(
|
|
625
|
-
body =
|
|
621
|
+
const pct = Math.min(100, Math.max(0, Number.parseInt(pctMatch[1], 10)));
|
|
622
|
+
body = screen(pct / 100);
|
|
626
623
|
} else if (preset === "horzBrick" || preset === "ltHorizontal" || preset === "narHorz") {
|
|
627
624
|
body = stripe("h", 0.8);
|
|
628
625
|
} else if (preset === "dkHorizontal") {
|
|
@@ -656,7 +653,7 @@ var patternDef = (pat) => {
|
|
|
656
653
|
} else if (preset === "solidDmnd" || preset === "openDmnd") {
|
|
657
654
|
body = `<path d="M4 1L7 4 4 7 1 4Z" fill="${preset === "solidDmnd" ? fg : "none"}" stroke="${fg}" stroke-width="0.6"/>`;
|
|
658
655
|
} else {
|
|
659
|
-
body =
|
|
656
|
+
body = screen(0.5);
|
|
660
657
|
}
|
|
661
658
|
const defs = `<defs><pattern id="${id}" patternUnits="userSpaceOnUse" width="${W}" height="${H}"><rect width="${W}" height="${H}" fill="${bg}"/>${body}</pattern></defs>`;
|
|
662
659
|
return { defs, fillAttr: `url(#${id})` };
|
|
@@ -2321,7 +2318,7 @@ var renderTextBody = (pres, shape, bounds, theme, phType, ctx) => {
|
|
|
2321
2318
|
);
|
|
2322
2319
|
}
|
|
2323
2320
|
const justify = ANCHOR_TO_CSS[anchor] ?? "flex-start";
|
|
2324
|
-
const defaultColor =
|
|
2321
|
+
const defaultColor = activeDeckTextColor;
|
|
2325
2322
|
if (ctx.mode === "svg") {
|
|
2326
2323
|
const svgScale = authoredAutofit?.fontScale ?? 1;
|
|
2327
2324
|
const svgLineScale = 1 - (authoredAutofit?.lnSpcReduction ?? 0);
|
|
@@ -2515,6 +2512,9 @@ var DISPLAY_UNIT_LABEL = {
|
|
|
2515
2512
|
billions: "Billions",
|
|
2516
2513
|
trillions: "Trillions"
|
|
2517
2514
|
};
|
|
2515
|
+
var DEFAULT_AXIS_COLOR = "#000000";
|
|
2516
|
+
var DEFAULT_GRID_COLOR = "#D9D9D9";
|
|
2517
|
+
var AXIS_TICK_LEN = 5;
|
|
2518
2518
|
var axisTickAttrs = (style) => {
|
|
2519
2519
|
const sz = style?.sizePt ?? 10;
|
|
2520
2520
|
const fill = style?.color ?? "#6B7280";
|
|
@@ -2531,10 +2531,15 @@ var renderValueAxis = (f, axis) => {
|
|
|
2531
2531
|
})() : niceTicks(axis.min, axis.max);
|
|
2532
2532
|
const out = [];
|
|
2533
2533
|
const range = axis.max - axis.min || 1;
|
|
2534
|
-
const
|
|
2535
|
-
|
|
2534
|
+
const fmtTick = (t) => axis.percent ? `${Math.round(t * 100)}%` : formatAxisLabel(
|
|
2535
|
+
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2536
|
+
axis.numberFormat
|
|
2537
|
+
);
|
|
2538
|
+
const showGrid = axis.majorGridlines ?? false;
|
|
2539
|
+
const gridStroke = axis.majorGridlineColor ?? DEFAULT_GRID_COLOR;
|
|
2540
|
+
const axisColor = axis.lineColor ?? DEFAULT_AXIS_COLOR;
|
|
2536
2541
|
const tickMark = axis.majorTickMark ?? "out";
|
|
2537
|
-
const tickLen =
|
|
2542
|
+
const tickLen = AXIS_TICK_LEN;
|
|
2538
2543
|
for (const t of ticks) {
|
|
2539
2544
|
if (axis.orientation === "vertical") {
|
|
2540
2545
|
const yp = f.plotY + f.plotH - (t - axis.min) / range * f.plotH;
|
|
@@ -2547,19 +2552,14 @@ var renderValueAxis = (f, axis) => {
|
|
|
2547
2552
|
const tx1 = tickMark === "in" ? f.plotX : f.plotX - tickLen;
|
|
2548
2553
|
const tx2 = tickMark === "out" ? f.plotX : tickMark === "cross" ? f.plotX + tickLen : f.plotX + tickLen;
|
|
2549
2554
|
out.push(
|
|
2550
|
-
`<line x1="${px(tx1)}" y1="${px(yp)}" x2="${px(tx2)}" y2="${px(yp)}" stroke="
|
|
2555
|
+
`<line x1="${px(tx1)}" y1="${px(yp)}" x2="${px(tx2)}" y2="${px(yp)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2551
2556
|
);
|
|
2552
2557
|
}
|
|
2553
2558
|
const labelX = f.plotX - 4;
|
|
2554
2559
|
const rot = axis.labelRotationDeg ?? 0;
|
|
2555
2560
|
const transform = rot ? ` transform="rotate(${rot} ${px(labelX)} ${px(yp)})"` : "";
|
|
2556
2561
|
out.push(
|
|
2557
|
-
`<text x="${px(labelX)}" y="${px(yp)}" text-anchor="end" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transform}>${escapeXml2(
|
|
2558
|
-
formatAxisLabel(
|
|
2559
|
-
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2560
|
-
axis.numberFormat
|
|
2561
|
-
)
|
|
2562
|
-
)}</text>`
|
|
2562
|
+
`<text x="${px(labelX)}" y="${px(yp)}" text-anchor="end" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transform}>${escapeXml2(fmtTick(t))}</text>`
|
|
2563
2563
|
);
|
|
2564
2564
|
} else {
|
|
2565
2565
|
const xp = f.plotX + (t - axis.min) / range * f.plotW;
|
|
@@ -2573,19 +2573,14 @@ var renderValueAxis = (f, axis) => {
|
|
|
2573
2573
|
const ty1 = tickMark === "in" ? baseY : baseY + tickLen;
|
|
2574
2574
|
const ty2 = tickMark === "out" ? baseY : tickMark === "cross" ? baseY - tickLen : baseY - tickLen;
|
|
2575
2575
|
out.push(
|
|
2576
|
-
`<line x1="${px(xp)}" y1="${px(ty1)}" x2="${px(xp)}" y2="${px(ty2)}" stroke="
|
|
2576
|
+
`<line x1="${px(xp)}" y1="${px(ty1)}" x2="${px(xp)}" y2="${px(ty2)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2577
2577
|
);
|
|
2578
2578
|
}
|
|
2579
2579
|
const horizLabelY = f.plotY + f.plotH + 12;
|
|
2580
2580
|
const rotH = axis.labelRotationDeg ?? 0;
|
|
2581
2581
|
const transformH = rotH ? ` transform="rotate(${rotH} ${px(xp)} ${px(horizLabelY)})"` : "";
|
|
2582
2582
|
out.push(
|
|
2583
|
-
`<text x="${px(xp)}" y="${px(horizLabelY)}" text-anchor="middle" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transformH}>${escapeXml2(
|
|
2584
|
-
formatAxisLabel(
|
|
2585
|
-
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2586
|
-
axis.numberFormat
|
|
2587
|
-
)
|
|
2588
|
-
)}</text>`
|
|
2583
|
+
`<text x="${px(xp)}" y="${px(horizLabelY)}" text-anchor="middle" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transformH}>${escapeXml2(fmtTick(t))}</text>`
|
|
2589
2584
|
);
|
|
2590
2585
|
}
|
|
2591
2586
|
}
|
|
@@ -2603,16 +2598,16 @@ var renderValueAxis = (f, axis) => {
|
|
|
2603
2598
|
);
|
|
2604
2599
|
}
|
|
2605
2600
|
}
|
|
2606
|
-
if (axis.
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
)
|
|
2615
|
-
|
|
2601
|
+
if (axis.orientation === "vertical") {
|
|
2602
|
+
out.push(
|
|
2603
|
+
`<line x1="${px(f.plotX)}" y1="${px(f.plotY)}" x2="${px(f.plotX)}" y2="${px(f.plotY + f.plotH)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2604
|
+
);
|
|
2605
|
+
} else {
|
|
2606
|
+
const zeroY = f.plotY + f.plotH - (0 - axis.min) / range * f.plotH;
|
|
2607
|
+
const spineY = axis.min <= 0 && axis.max >= 0 ? zeroY : f.plotY + f.plotH;
|
|
2608
|
+
out.push(
|
|
2609
|
+
`<line x1="${px(f.plotX)}" y1="${px(spineY)}" x2="${px(f.plotX + f.plotW)}" y2="${px(spineY)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2610
|
+
);
|
|
2616
2611
|
}
|
|
2617
2612
|
return out.join("");
|
|
2618
2613
|
};
|
|
@@ -2641,7 +2636,7 @@ var renderCategoryAxis = (f, orientation, cats, pointCount2, skip = 1, labelStyl
|
|
|
2641
2636
|
const truncLen = labelRotationDeg && Math.abs(labelRotationDeg) >= 30 ? 28 : 14;
|
|
2642
2637
|
for (let i = 0; i < pointCount2; i++) {
|
|
2643
2638
|
if (skip > 1 && i % skip !== 0) continue;
|
|
2644
|
-
const cy = f.plotY + (i + 0.5) * step;
|
|
2639
|
+
const cy = f.plotY + (pointCount2 - 1 - i + 0.5) * step;
|
|
2645
2640
|
const lx = f.plotX - 4;
|
|
2646
2641
|
const truncated = labels[i] !== void 0 && labels[i].length > truncLen ? `${labels[i].slice(0, truncLen - 2)}\u2026` : labels[i] ?? "";
|
|
2647
2642
|
const transform = labelRotationDeg && labelRotationDeg !== 0 ? ` transform="rotate(${labelRotationDeg} ${px(lx)} ${px(cy)})"` : "";
|
|
@@ -2650,27 +2645,63 @@ var renderCategoryAxis = (f, orientation, cats, pointCount2, skip = 1, labelStyl
|
|
|
2650
2645
|
);
|
|
2651
2646
|
}
|
|
2652
2647
|
}
|
|
2653
|
-
|
|
2654
|
-
|
|
2648
|
+
const axisColor = lineColor ?? DEFAULT_AXIS_COLOR;
|
|
2649
|
+
if (orientation === "horizontal") {
|
|
2650
|
+
const baseY = f.plotY + f.plotH;
|
|
2651
|
+
out.push(
|
|
2652
|
+
`<line x1="${px(f.plotX)}" y1="${px(baseY)}" x2="${px(f.plotX + f.plotW)}" y2="${px(baseY)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2653
|
+
);
|
|
2654
|
+
const stepB = pointCount2 > 0 ? f.plotW / pointCount2 : 0;
|
|
2655
|
+
for (let i = 0; i <= pointCount2; i++) {
|
|
2656
|
+
const bx = f.plotX + i * stepB;
|
|
2655
2657
|
out.push(
|
|
2656
|
-
`<line x1="${px(
|
|
2658
|
+
`<line x1="${px(bx)}" y1="${px(baseY)}" x2="${px(bx)}" y2="${px(baseY + AXIS_TICK_LEN)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2657
2659
|
);
|
|
2658
|
-
}
|
|
2660
|
+
}
|
|
2661
|
+
} else {
|
|
2662
|
+
out.push(
|
|
2663
|
+
`<line x1="${px(f.plotX)}" y1="${px(f.plotY)}" x2="${px(f.plotX)}" y2="${px(f.plotY + f.plotH)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2664
|
+
);
|
|
2665
|
+
const stepB = pointCount2 > 0 ? f.plotH / pointCount2 : 0;
|
|
2666
|
+
for (let i = 0; i <= pointCount2; i++) {
|
|
2667
|
+
const by = f.plotY + i * stepB;
|
|
2659
2668
|
out.push(
|
|
2660
|
-
`<line x1="${px(f.plotX)}" y1="${px(
|
|
2669
|
+
`<line x1="${px(f.plotX - AXIS_TICK_LEN)}" y1="${px(by)}" x2="${px(f.plotX)}" y2="${px(by)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2661
2670
|
);
|
|
2662
2671
|
}
|
|
2663
2672
|
}
|
|
2664
2673
|
return out.join("");
|
|
2665
2674
|
};
|
|
2666
2675
|
var seriesMinMax = (spec) => {
|
|
2676
|
+
const isStacked = spec.grouping === "stacked" || spec.grouping === "percentStacked";
|
|
2677
|
+
const isPercent = spec.grouping === "percentStacked";
|
|
2667
2678
|
let min = Infinity;
|
|
2668
2679
|
let max = -Infinity;
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2680
|
+
if (isPercent) {
|
|
2681
|
+
min = 0;
|
|
2682
|
+
max = 1;
|
|
2683
|
+
} else if (isStacked) {
|
|
2684
|
+
const N = spec.series.reduce((n, s) => Math.max(n, s.values.length), 0);
|
|
2685
|
+
for (let c = 0; c < N; c++) {
|
|
2686
|
+
let pos = 0;
|
|
2687
|
+
let neg = 0;
|
|
2688
|
+
for (const s of spec.series) {
|
|
2689
|
+
const v = s.values[c];
|
|
2690
|
+
if (v !== null && v !== void 0 && Number.isFinite(v)) {
|
|
2691
|
+
if (v >= 0) pos += v;
|
|
2692
|
+
else neg += v;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
if (pos > max) max = pos;
|
|
2696
|
+
if (neg < min) min = neg;
|
|
2697
|
+
}
|
|
2698
|
+
} else {
|
|
2699
|
+
for (const s of spec.series) {
|
|
2700
|
+
for (const v of s.values) {
|
|
2701
|
+
if (v !== null && Number.isFinite(v)) {
|
|
2702
|
+
if (v < min) min = v;
|
|
2703
|
+
if (v > max) max = v;
|
|
2704
|
+
}
|
|
2674
2705
|
}
|
|
2675
2706
|
}
|
|
2676
2707
|
}
|
|
@@ -2678,6 +2709,9 @@ var seriesMinMax = (spec) => {
|
|
|
2678
2709
|
if (!Number.isFinite(max)) max = 1;
|
|
2679
2710
|
if (max === min) max = min + 1;
|
|
2680
2711
|
if (min > 0) min = 0;
|
|
2712
|
+
if (isPercent) {
|
|
2713
|
+
return { min: 0, max: 1, step: 0.2 };
|
|
2714
|
+
}
|
|
2681
2715
|
const step = niceStep(max - min);
|
|
2682
2716
|
max = (Math.floor(max / step) + 1) * step;
|
|
2683
2717
|
if (spec.valueAxis?.min !== void 0) min = spec.valueAxis.min;
|
|
@@ -2703,9 +2737,9 @@ var renderChartLegend = (f, names, colors, position = "b", textStyle, markerSymb
|
|
|
2703
2737
|
const swatch = (i, swatchX, swatchY) => {
|
|
2704
2738
|
const color = colors[i % colors.length];
|
|
2705
2739
|
const sym = markerSymbols?.[i];
|
|
2706
|
-
if (
|
|
2740
|
+
if (markerSymbols !== void 0 && sym !== "none") {
|
|
2707
2741
|
const r = 4.5;
|
|
2708
|
-
return seriesMarker(sym, swatchX + r, swatchY + r, r, color);
|
|
2742
|
+
return seriesMarker(autoMarkerSymbol(sym, i), swatchX + r, swatchY + r, r, color);
|
|
2709
2743
|
}
|
|
2710
2744
|
return `<rect x="${px(swatchX)}" y="${px(swatchY)}" width="9" height="9" fill="${color}"/>`;
|
|
2711
2745
|
};
|
|
@@ -2768,24 +2802,7 @@ var renderColumnChart = (f, spec, colors) => {
|
|
|
2768
2802
|
const grouping = spec.grouping ?? "clustered";
|
|
2769
2803
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
2770
2804
|
const isPercent = grouping === "percentStacked";
|
|
2771
|
-
|
|
2772
|
-
if (isStacked) {
|
|
2773
|
-
let sumMin = Infinity;
|
|
2774
|
-
let sumMax = -Infinity;
|
|
2775
|
-
for (let c = 0; c < N; c++) {
|
|
2776
|
-
let pos = 0;
|
|
2777
|
-
let neg = 0;
|
|
2778
|
-
for (const s of spec.series) {
|
|
2779
|
-
const v = s.values[c] ?? 0;
|
|
2780
|
-
if (v >= 0) pos += v;
|
|
2781
|
-
else neg += v;
|
|
2782
|
-
}
|
|
2783
|
-
if (neg < sumMin) sumMin = neg;
|
|
2784
|
-
if (pos > sumMax) sumMax = pos;
|
|
2785
|
-
}
|
|
2786
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
2787
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
2788
|
-
}
|
|
2805
|
+
const { min, max } = seriesMinMax(spec);
|
|
2789
2806
|
const range = max - min || 1;
|
|
2790
2807
|
const groupW = f.plotW / N;
|
|
2791
2808
|
const gapPctC = (spec.gapWidthPct ?? 150) / 100;
|
|
@@ -2818,7 +2835,7 @@ var renderColumnChart = (f, spec, colors) => {
|
|
|
2818
2835
|
const y1 = f.plotY + f.plotH - (Math.min(stackedTop, stackedBase) - min) / range * f.plotH;
|
|
2819
2836
|
const h = Math.abs(y1 - y0);
|
|
2820
2837
|
out.push(
|
|
2821
|
-
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(barW)}" height="${px(h)}" fill="${colors[s % colors.length]}"/>`
|
|
2838
|
+
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(barW)}" height="${px(h)}" fill="${spec.series[s]?.color ?? colors[s % colors.length]}"/>`
|
|
2822
2839
|
);
|
|
2823
2840
|
if (showLabelFor(s) && Math.abs(v) > 0) {
|
|
2824
2841
|
const labelY = (y0 + y1) / 2 + 3;
|
|
@@ -2992,6 +3009,17 @@ var smoothPath = (pts) => {
|
|
|
2992
3009
|
}
|
|
2993
3010
|
return parts.join(" ");
|
|
2994
3011
|
};
|
|
3012
|
+
var AUTO_MARKER_SYMBOLS = [
|
|
3013
|
+
"diamond",
|
|
3014
|
+
"square",
|
|
3015
|
+
"triangle",
|
|
3016
|
+
"x",
|
|
3017
|
+
"star",
|
|
3018
|
+
"dot",
|
|
3019
|
+
"plus",
|
|
3020
|
+
"dash"
|
|
3021
|
+
];
|
|
3022
|
+
var autoMarkerSymbol = (symbol, seriesIdx) => symbol !== void 0 && symbol !== "auto" ? symbol : AUTO_MARKER_SYMBOLS[seriesIdx % AUTO_MARKER_SYMBOLS.length];
|
|
2995
3023
|
var seriesMarker = (symbol, cx, cy, r, color) => {
|
|
2996
3024
|
switch (symbol) {
|
|
2997
3025
|
case "square":
|
|
@@ -3053,24 +3081,7 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3053
3081
|
const grouping = spec.grouping ?? "clustered";
|
|
3054
3082
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
3055
3083
|
const isPercent = grouping === "percentStacked";
|
|
3056
|
-
|
|
3057
|
-
if (isStacked) {
|
|
3058
|
-
let sumMin = Infinity;
|
|
3059
|
-
let sumMax = -Infinity;
|
|
3060
|
-
for (let c = 0; c < N; c++) {
|
|
3061
|
-
let pos = 0;
|
|
3062
|
-
let neg = 0;
|
|
3063
|
-
for (const s of spec.series) {
|
|
3064
|
-
const v = s.values[c] ?? 0;
|
|
3065
|
-
if (v >= 0) pos += v;
|
|
3066
|
-
else neg += v;
|
|
3067
|
-
}
|
|
3068
|
-
if (neg < sumMin) sumMin = neg;
|
|
3069
|
-
if (pos > sumMax) sumMax = pos;
|
|
3070
|
-
}
|
|
3071
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
3072
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
3073
|
-
}
|
|
3084
|
+
const { min, max } = seriesMinMax(spec);
|
|
3074
3085
|
const range = max - min || 1;
|
|
3075
3086
|
const groupH = f.plotH / N;
|
|
3076
3087
|
const gapPctB = (spec.gapWidthPct ?? 150) / 100;
|
|
@@ -3095,12 +3106,12 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3095
3106
|
}
|
|
3096
3107
|
const base = v >= 0 ? posAcc : negAcc;
|
|
3097
3108
|
const stackedTop = base + v;
|
|
3098
|
-
const y0 = f.plotY + c * groupH + (groupH - barH) / 2;
|
|
3109
|
+
const y0 = f.plotY + (N - 1 - c) * groupH + (groupH - barH) / 2;
|
|
3099
3110
|
const x0 = f.plotX + (Math.min(base, stackedTop) - min) / range * f.plotW;
|
|
3100
3111
|
const x1 = f.plotX + (Math.max(base, stackedTop) - min) / range * f.plotW;
|
|
3101
3112
|
const w = Math.abs(x1 - x0);
|
|
3102
3113
|
out.push(
|
|
3103
|
-
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(w)}" height="${px(barH)}" fill="${colors[s % colors.length]}"/>`
|
|
3114
|
+
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(w)}" height="${px(barH)}" fill="${spec.series[s]?.color ?? colors[s % colors.length]}"/>`
|
|
3104
3115
|
);
|
|
3105
3116
|
if (showLabelForBar(s) && Math.abs(v) > 0) {
|
|
3106
3117
|
const labelX = (x0 + x1) / 2;
|
|
@@ -3114,11 +3125,11 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3114
3125
|
}
|
|
3115
3126
|
} else {
|
|
3116
3127
|
const clusterH = barH * clusterUnitsB;
|
|
3117
|
-
const clusterStartY = f.plotY + c * groupH + (groupH - clusterH) / 2;
|
|
3128
|
+
const clusterStartY = f.plotY + (N - 1 - c) * groupH + (groupH - clusterH) / 2;
|
|
3118
3129
|
const strideB = barH * (1 - overlapPctB);
|
|
3119
3130
|
for (let s = 0; s < spec.series.length; s++) {
|
|
3120
3131
|
const v = spec.series[s]?.values[c] ?? 0;
|
|
3121
|
-
const y0 = clusterStartY + s * strideB;
|
|
3132
|
+
const y0 = clusterStartY + (Sb - 1 - s) * strideB;
|
|
3122
3133
|
const tip = f.plotX + (v - min) / range * f.plotW;
|
|
3123
3134
|
const x0 = Math.min(tip, baseX);
|
|
3124
3135
|
const w = Math.abs(tip - baseX);
|
|
@@ -3166,24 +3177,7 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3166
3177
|
const grouping = spec.grouping ?? "clustered";
|
|
3167
3178
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
3168
3179
|
const isPercent = grouping === "percentStacked";
|
|
3169
|
-
|
|
3170
|
-
if (isStacked) {
|
|
3171
|
-
let sumMin = Infinity;
|
|
3172
|
-
let sumMax = -Infinity;
|
|
3173
|
-
for (let c = 0; c < N; c++) {
|
|
3174
|
-
let pos = 0;
|
|
3175
|
-
let neg = 0;
|
|
3176
|
-
for (const s of spec.series) {
|
|
3177
|
-
const v = s.values[c] ?? 0;
|
|
3178
|
-
if (v >= 0) pos += v;
|
|
3179
|
-
else neg += v;
|
|
3180
|
-
}
|
|
3181
|
-
if (neg < sumMin) sumMin = neg;
|
|
3182
|
-
if (pos > sumMax) sumMax = pos;
|
|
3183
|
-
}
|
|
3184
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
3185
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
3186
|
-
}
|
|
3180
|
+
const { min, max } = seriesMinMax(spec);
|
|
3187
3181
|
const range = max - min || 1;
|
|
3188
3182
|
const step = N > 1 ? f.plotW / (N - 1) : 0;
|
|
3189
3183
|
const baseY = f.plotY + f.plotH - (0 - min) / range * f.plotH;
|
|
@@ -3244,7 +3238,7 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3244
3238
|
})();
|
|
3245
3239
|
if (fill) {
|
|
3246
3240
|
const back = basePts.slice().reverse().map(([xp, yp]) => `L${px(xp)},${px(yp)}`).join(" ");
|
|
3247
|
-
out.push(`<path d="${dPath} ${back} Z" fill="${color}"
|
|
3241
|
+
out.push(`<path d="${dPath} ${back} Z" fill="${color}" stroke="none"/>`);
|
|
3248
3242
|
}
|
|
3249
3243
|
const lineWPx = series.lineWidthEmu ? Math.max(0.3, series.lineWidthEmu / EMU_PER_PX) : 1.5;
|
|
3250
3244
|
const dashAttr = series.lineDash ? (() => {
|
|
@@ -3258,8 +3252,9 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3258
3252
|
`<path d="${dPath}" fill="none" stroke="${color}" stroke-width="${lineWPx.toFixed(2)}" stroke-linejoin="round" stroke-linecap="round"${dashAttr}/>`
|
|
3259
3253
|
);
|
|
3260
3254
|
if (!isStacked) {
|
|
3261
|
-
const
|
|
3262
|
-
if (
|
|
3255
|
+
const explicitSymbol = series.markerSymbol !== void 0 && series.markerSymbol !== "auto" && series.markerSymbol !== "none";
|
|
3256
|
+
if (series.markerSymbol !== "none" && !fill && (spec.lineMarkers === true || explicitSymbol)) {
|
|
3257
|
+
const symbol = autoMarkerSymbol(series.markerSymbol, s);
|
|
3263
3258
|
const size = series.markerSizePt ?? 5;
|
|
3264
3259
|
const r = Math.max(1, size * 0.5);
|
|
3265
3260
|
for (const [xp, yp] of pts) {
|
|
@@ -3501,7 +3496,7 @@ var renderScatterChart = (f, spec, colors) => {
|
|
|
3501
3496
|
const drawMarker = sym === "none" ? false : showMarker || sym !== void 0 && sym !== "auto";
|
|
3502
3497
|
if (drawMarker) {
|
|
3503
3498
|
const r = Math.max(1.5, (series.markerSizePt ?? 5) * 0.5);
|
|
3504
|
-
const glyph = sym
|
|
3499
|
+
const glyph = autoMarkerSymbol(sym, s);
|
|
3505
3500
|
for (const [xp, yp] of proj) out.push(seriesMarker(glyph, xp, yp, r, color));
|
|
3506
3501
|
}
|
|
3507
3502
|
}
|
|
@@ -3624,7 +3619,7 @@ var renderRadarChart = (f, spec, colors) => {
|
|
|
3624
3619
|
);
|
|
3625
3620
|
if (showMarker) {
|
|
3626
3621
|
const r = Math.max(1.5, (series.markerSizePt ?? 5) * 0.5);
|
|
3627
|
-
const glyph = series.markerSymbol
|
|
3622
|
+
const glyph = autoMarkerSymbol(series.markerSymbol, s);
|
|
3628
3623
|
for (const [xp, yp] of proj) out.push(seriesMarker(glyph, xp, yp, r, color));
|
|
3629
3624
|
}
|
|
3630
3625
|
}
|
|
@@ -3660,7 +3655,9 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3660
3655
|
const hiddenSet = new Set(spec.legend?.hiddenIndices ?? []);
|
|
3661
3656
|
const seriesNamesForLegend = allNamesForLegend.filter((_, i) => !hiddenSet.has(i));
|
|
3662
3657
|
const seriesColorsForLegend = allColorsForLegend.filter((_, i) => !hiddenSet.has(i));
|
|
3663
|
-
const
|
|
3658
|
+
const explicitMarker = (sym) => sym !== void 0 && sym !== "auto" && sym !== "none";
|
|
3659
|
+
const showsMarkers = spec.kind === "line" && (spec.lineMarkers === true || spec.series.some((s) => explicitMarker(s.markerSymbol)));
|
|
3660
|
+
const markerSymbolsForLegend = showsMarkers ? spec.series.map((s) => s.markerSymbol).filter((_, i) => !hiddenSet.has(i)) : void 0;
|
|
3664
3661
|
let finiteCount = 0;
|
|
3665
3662
|
for (const s of spec.series) {
|
|
3666
3663
|
for (const v of s.values) if (v !== null && Number.isFinite(v)) finiteCount++;
|
|
@@ -3683,7 +3680,8 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3683
3680
|
...spec.valueAxisLabelRotationDeg !== void 0 ? { labelRotationDeg: spec.valueAxisLabelRotationDeg } : {},
|
|
3684
3681
|
...spec.valueAxis?.displayUnits !== void 0 ? { displayUnits: spec.valueAxis.displayUnits } : {}
|
|
3685
3682
|
};
|
|
3686
|
-
const
|
|
3683
|
+
const isPercentStacked = spec.grouping === "percentStacked";
|
|
3684
|
+
const valueAxis = spec.kind === "bar" ? { orientation: "horizontal", min, max, percent: isPercentStacked, ...axisExtras } : { orientation: "vertical", min, max, percent: isPercentStacked, ...axisExtras };
|
|
3687
3685
|
if (!spec.valueAxisHidden) axes = renderValueAxis(f, valueAxis);
|
|
3688
3686
|
const labelsHidden = spec.categoryAxisHidden || spec.categoryAxisTickLabelPos === "none";
|
|
3689
3687
|
if (N > 0 && !labelsHidden) {
|
|
@@ -3748,8 +3746,11 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3748
3746
|
`<g${transform}>`,
|
|
3749
3747
|
// Chart-area backdrop honors <c:chartSpace><c:spPr><a:solidFill> /
|
|
3750
3748
|
// <a:ln>. plot-area gets its own tinted rect + border when
|
|
3751
|
-
// <c:plotArea><c:spPr> authors them.
|
|
3752
|
-
|
|
3749
|
+
// <c:plotArea><c:spPr> authors them. PowerPoint draws no chart-area
|
|
3750
|
+
// border unless the chartSpace authors an <a:ln>, so the default is
|
|
3751
|
+
// `none` — an invented light-gray frame is the most visible single
|
|
3752
|
+
// divergence from PowerPoint's actual rendering.
|
|
3753
|
+
`<rect x="${px(f.x)}" y="${px(f.y)}" width="${px(f.w)}" height="${px(f.h)}" fill="${spec.chartAreaFill ?? "#FFFFFF"}" stroke="${spec.chartAreaStrokeColor ?? "none"}" stroke-width="0.6"${spec.roundedCorners ? ' rx="6" ry="6"' : ""}/>`,
|
|
3753
3754
|
spec.plotAreaFill || spec.plotAreaStrokeColor ? `<rect x="${px(f.plotX)}" y="${px(f.plotY)}" width="${px(f.plotW)}" height="${px(f.plotH)}" fill="${spec.plotAreaFill ?? "none"}" stroke="${spec.plotAreaStrokeColor ?? "none"}" stroke-width="0.6"/>` : "",
|
|
3754
3755
|
renderChartTitle(f, spec.title ?? "", spec.titleStyle),
|
|
3755
3756
|
axes,
|
|
@@ -3879,7 +3880,7 @@ var renderTable = (shape, pres, x, y, w, h, transform, theme, ctx) => {
|
|
|
3879
3880
|
const accent = theme ? normalizeHex(theme.accent1) : "#4472C4";
|
|
3880
3881
|
const headerFill = accent;
|
|
3881
3882
|
const bandFill = mixHex(accent, "#FFFFFF", 0.92);
|
|
3882
|
-
const textColor =
|
|
3883
|
+
const textColor = activeDeckTextColor;
|
|
3883
3884
|
const tableThemeFace = getPresentationFonts(pres)?.minorLatin ?? null;
|
|
3884
3885
|
const out = [];
|
|
3885
3886
|
out.push(`<g${transform}>`);
|
|
@@ -4459,6 +4460,7 @@ var renderSlideSvg = (pres, slide, opts = {}) => {
|
|
|
4459
4460
|
const H = size.height;
|
|
4460
4461
|
const theme = getPresentationTheme(pres);
|
|
4461
4462
|
activeColorMap = getEffectiveColorMap(slide);
|
|
4463
|
+
activeDeckTextColor = resolveDeckBodyTextColor(slide) ?? "#000000";
|
|
4462
4464
|
const ctx = {
|
|
4463
4465
|
mode: opts.textLayout ?? "foreignObject",
|
|
4464
4466
|
measure: opts.measureText ?? defaultMeasurer
|