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/node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Resvg } from '@resvg/resvg-js';
|
|
2
|
-
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';
|
|
2
|
+
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';
|
|
3
3
|
import * as fontkit from 'fontkit';
|
|
4
4
|
import { existsSync, readFileSync } from 'fs';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
@@ -564,6 +564,7 @@ var resolveColor = (c, theme, fallback = "#1F2937") => {
|
|
|
564
564
|
var nextDefId = 0;
|
|
565
565
|
var mintId = () => `pkdef-${(nextDefId++).toString(36)}`;
|
|
566
566
|
var activeColorMap = null;
|
|
567
|
+
var activeDeckTextColor = "#000000";
|
|
567
568
|
var gradientDef = (grad, theme) => {
|
|
568
569
|
const id = mintId();
|
|
569
570
|
const stops = grad.stops.map(
|
|
@@ -606,27 +607,23 @@ var patternDef = (pat) => {
|
|
|
606
607
|
return `<path d="M0 0L${W} ${H}" stroke="${fg}" stroke-width="${width}"/>`;
|
|
607
608
|
return `<path d="M${W} 0L0 ${H}" stroke="${fg}" stroke-width="${width}"/>`;
|
|
608
609
|
};
|
|
609
|
-
const
|
|
610
|
-
|
|
610
|
+
const BAYER4 = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
|
|
611
|
+
const screen = (density) => {
|
|
612
|
+
const threshold = density * 16;
|
|
611
613
|
const out = [];
|
|
612
|
-
|
|
613
|
-
[
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
[2, 6],
|
|
619
|
-
[6, 6]
|
|
620
|
-
];
|
|
621
|
-
for (const [x, y] of grid.slice(0, count)) {
|
|
622
|
-
out.push(`<circle cx="${x}" cy="${y}" r="0.7" fill="${fg}"/>`);
|
|
614
|
+
for (let i = 0; i < 16; i++) {
|
|
615
|
+
if (BAYER4[i] < threshold) {
|
|
616
|
+
const cx = i % 4 * 2;
|
|
617
|
+
const cy = Math.floor(i / 4) * 2;
|
|
618
|
+
out.push(`<rect x="${cx}" y="${cy}" width="2" height="2" fill="${fg}"/>`);
|
|
619
|
+
}
|
|
623
620
|
}
|
|
624
621
|
return out.join("");
|
|
625
622
|
};
|
|
626
623
|
const pctMatch = /^pct(\d+)$/.exec(preset);
|
|
627
624
|
if (pctMatch) {
|
|
628
|
-
const pct = Math.min(100, Math.max(
|
|
629
|
-
body =
|
|
625
|
+
const pct = Math.min(100, Math.max(0, Number.parseInt(pctMatch[1], 10)));
|
|
626
|
+
body = screen(pct / 100);
|
|
630
627
|
} else if (preset === "horzBrick" || preset === "ltHorizontal" || preset === "narHorz") {
|
|
631
628
|
body = stripe("h", 0.8);
|
|
632
629
|
} else if (preset === "dkHorizontal") {
|
|
@@ -660,7 +657,7 @@ var patternDef = (pat) => {
|
|
|
660
657
|
} else if (preset === "solidDmnd" || preset === "openDmnd") {
|
|
661
658
|
body = `<path d="M4 1L7 4 4 7 1 4Z" fill="${preset === "solidDmnd" ? fg : "none"}" stroke="${fg}" stroke-width="0.6"/>`;
|
|
662
659
|
} else {
|
|
663
|
-
body =
|
|
660
|
+
body = screen(0.5);
|
|
664
661
|
}
|
|
665
662
|
const defs = `<defs><pattern id="${id}" patternUnits="userSpaceOnUse" width="${W}" height="${H}"><rect width="${W}" height="${H}" fill="${bg}"/>${body}</pattern></defs>`;
|
|
666
663
|
return { defs, fillAttr: `url(#${id})` };
|
|
@@ -2325,7 +2322,7 @@ var renderTextBody = (pres, shape, bounds, theme, phType, ctx) => {
|
|
|
2325
2322
|
);
|
|
2326
2323
|
}
|
|
2327
2324
|
const justify = ANCHOR_TO_CSS[anchor] ?? "flex-start";
|
|
2328
|
-
const defaultColor =
|
|
2325
|
+
const defaultColor = activeDeckTextColor;
|
|
2329
2326
|
if (ctx.mode === "svg") {
|
|
2330
2327
|
const svgScale = authoredAutofit?.fontScale ?? 1;
|
|
2331
2328
|
const svgLineScale = 1 - (authoredAutofit?.lnSpcReduction ?? 0);
|
|
@@ -2519,6 +2516,9 @@ var DISPLAY_UNIT_LABEL = {
|
|
|
2519
2516
|
billions: "Billions",
|
|
2520
2517
|
trillions: "Trillions"
|
|
2521
2518
|
};
|
|
2519
|
+
var DEFAULT_AXIS_COLOR = "#000000";
|
|
2520
|
+
var DEFAULT_GRID_COLOR = "#D9D9D9";
|
|
2521
|
+
var AXIS_TICK_LEN = 5;
|
|
2522
2522
|
var axisTickAttrs = (style) => {
|
|
2523
2523
|
const sz = style?.sizePt ?? 10;
|
|
2524
2524
|
const fill = style?.color ?? "#6B7280";
|
|
@@ -2535,10 +2535,15 @@ var renderValueAxis = (f, axis) => {
|
|
|
2535
2535
|
})() : niceTicks(axis.min, axis.max);
|
|
2536
2536
|
const out = [];
|
|
2537
2537
|
const range = axis.max - axis.min || 1;
|
|
2538
|
-
const
|
|
2539
|
-
|
|
2538
|
+
const fmtTick = (t) => axis.percent ? `${Math.round(t * 100)}%` : formatAxisLabel(
|
|
2539
|
+
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2540
|
+
axis.numberFormat
|
|
2541
|
+
);
|
|
2542
|
+
const showGrid = axis.majorGridlines ?? false;
|
|
2543
|
+
const gridStroke = axis.majorGridlineColor ?? DEFAULT_GRID_COLOR;
|
|
2544
|
+
const axisColor = axis.lineColor ?? DEFAULT_AXIS_COLOR;
|
|
2540
2545
|
const tickMark = axis.majorTickMark ?? "out";
|
|
2541
|
-
const tickLen =
|
|
2546
|
+
const tickLen = AXIS_TICK_LEN;
|
|
2542
2547
|
for (const t of ticks) {
|
|
2543
2548
|
if (axis.orientation === "vertical") {
|
|
2544
2549
|
const yp = f.plotY + f.plotH - (t - axis.min) / range * f.plotH;
|
|
@@ -2551,19 +2556,14 @@ var renderValueAxis = (f, axis) => {
|
|
|
2551
2556
|
const tx1 = tickMark === "in" ? f.plotX : f.plotX - tickLen;
|
|
2552
2557
|
const tx2 = tickMark === "out" ? f.plotX : tickMark === "cross" ? f.plotX + tickLen : f.plotX + tickLen;
|
|
2553
2558
|
out.push(
|
|
2554
|
-
`<line x1="${px(tx1)}" y1="${px(yp)}" x2="${px(tx2)}" y2="${px(yp)}" stroke="
|
|
2559
|
+
`<line x1="${px(tx1)}" y1="${px(yp)}" x2="${px(tx2)}" y2="${px(yp)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2555
2560
|
);
|
|
2556
2561
|
}
|
|
2557
2562
|
const labelX = f.plotX - 4;
|
|
2558
2563
|
const rot = axis.labelRotationDeg ?? 0;
|
|
2559
2564
|
const transform = rot ? ` transform="rotate(${rot} ${px(labelX)} ${px(yp)})"` : "";
|
|
2560
2565
|
out.push(
|
|
2561
|
-
`<text x="${px(labelX)}" y="${px(yp)}" text-anchor="end" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transform}>${escapeXml2(
|
|
2562
|
-
formatAxisLabel(
|
|
2563
|
-
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2564
|
-
axis.numberFormat
|
|
2565
|
-
)
|
|
2566
|
-
)}</text>`
|
|
2566
|
+
`<text x="${px(labelX)}" y="${px(yp)}" text-anchor="end" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transform}>${escapeXml2(fmtTick(t))}</text>`
|
|
2567
2567
|
);
|
|
2568
2568
|
} else {
|
|
2569
2569
|
const xp = f.plotX + (t - axis.min) / range * f.plotW;
|
|
@@ -2577,19 +2577,14 @@ var renderValueAxis = (f, axis) => {
|
|
|
2577
2577
|
const ty1 = tickMark === "in" ? baseY : baseY + tickLen;
|
|
2578
2578
|
const ty2 = tickMark === "out" ? baseY : tickMark === "cross" ? baseY - tickLen : baseY - tickLen;
|
|
2579
2579
|
out.push(
|
|
2580
|
-
`<line x1="${px(xp)}" y1="${px(ty1)}" x2="${px(xp)}" y2="${px(ty2)}" stroke="
|
|
2580
|
+
`<line x1="${px(xp)}" y1="${px(ty1)}" x2="${px(xp)}" y2="${px(ty2)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2581
2581
|
);
|
|
2582
2582
|
}
|
|
2583
2583
|
const horizLabelY = f.plotY + f.plotH + 12;
|
|
2584
2584
|
const rotH = axis.labelRotationDeg ?? 0;
|
|
2585
2585
|
const transformH = rotH ? ` transform="rotate(${rotH} ${px(xp)} ${px(horizLabelY)})"` : "";
|
|
2586
2586
|
out.push(
|
|
2587
|
-
`<text x="${px(xp)}" y="${px(horizLabelY)}" text-anchor="middle" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transformH}>${escapeXml2(
|
|
2588
|
-
formatAxisLabel(
|
|
2589
|
-
axis.displayUnits ? t / DISPLAY_UNIT_DIVISOR[axis.displayUnits] : t,
|
|
2590
|
-
axis.numberFormat
|
|
2591
|
-
)
|
|
2592
|
-
)}</text>`
|
|
2587
|
+
`<text x="${px(xp)}" y="${px(horizLabelY)}" text-anchor="middle" dominant-baseline="middle" ${axisTickAttrs(axis.labelStyle)}${transformH}>${escapeXml2(fmtTick(t))}</text>`
|
|
2593
2588
|
);
|
|
2594
2589
|
}
|
|
2595
2590
|
}
|
|
@@ -2607,16 +2602,16 @@ var renderValueAxis = (f, axis) => {
|
|
|
2607
2602
|
);
|
|
2608
2603
|
}
|
|
2609
2604
|
}
|
|
2610
|
-
if (axis.
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
)
|
|
2619
|
-
|
|
2605
|
+
if (axis.orientation === "vertical") {
|
|
2606
|
+
out.push(
|
|
2607
|
+
`<line x1="${px(f.plotX)}" y1="${px(f.plotY)}" x2="${px(f.plotX)}" y2="${px(f.plotY + f.plotH)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2608
|
+
);
|
|
2609
|
+
} else {
|
|
2610
|
+
const zeroY = f.plotY + f.plotH - (0 - axis.min) / range * f.plotH;
|
|
2611
|
+
const spineY = axis.min <= 0 && axis.max >= 0 ? zeroY : f.plotY + f.plotH;
|
|
2612
|
+
out.push(
|
|
2613
|
+
`<line x1="${px(f.plotX)}" y1="${px(spineY)}" x2="${px(f.plotX + f.plotW)}" y2="${px(spineY)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2614
|
+
);
|
|
2620
2615
|
}
|
|
2621
2616
|
return out.join("");
|
|
2622
2617
|
};
|
|
@@ -2645,7 +2640,7 @@ var renderCategoryAxis = (f, orientation, cats, pointCount2, skip = 1, labelStyl
|
|
|
2645
2640
|
const truncLen = labelRotationDeg && Math.abs(labelRotationDeg) >= 30 ? 28 : 14;
|
|
2646
2641
|
for (let i = 0; i < pointCount2; i++) {
|
|
2647
2642
|
if (skip > 1 && i % skip !== 0) continue;
|
|
2648
|
-
const cy = f.plotY + (i + 0.5) * step;
|
|
2643
|
+
const cy = f.plotY + (pointCount2 - 1 - i + 0.5) * step;
|
|
2649
2644
|
const lx = f.plotX - 4;
|
|
2650
2645
|
const truncated = labels[i] !== void 0 && labels[i].length > truncLen ? `${labels[i].slice(0, truncLen - 2)}\u2026` : labels[i] ?? "";
|
|
2651
2646
|
const transform = labelRotationDeg && labelRotationDeg !== 0 ? ` transform="rotate(${labelRotationDeg} ${px(lx)} ${px(cy)})"` : "";
|
|
@@ -2654,27 +2649,63 @@ var renderCategoryAxis = (f, orientation, cats, pointCount2, skip = 1, labelStyl
|
|
|
2654
2649
|
);
|
|
2655
2650
|
}
|
|
2656
2651
|
}
|
|
2657
|
-
|
|
2658
|
-
|
|
2652
|
+
const axisColor = lineColor ?? DEFAULT_AXIS_COLOR;
|
|
2653
|
+
if (orientation === "horizontal") {
|
|
2654
|
+
const baseY = f.plotY + f.plotH;
|
|
2655
|
+
out.push(
|
|
2656
|
+
`<line x1="${px(f.plotX)}" y1="${px(baseY)}" x2="${px(f.plotX + f.plotW)}" y2="${px(baseY)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2657
|
+
);
|
|
2658
|
+
const stepB = pointCount2 > 0 ? f.plotW / pointCount2 : 0;
|
|
2659
|
+
for (let i = 0; i <= pointCount2; i++) {
|
|
2660
|
+
const bx = f.plotX + i * stepB;
|
|
2659
2661
|
out.push(
|
|
2660
|
-
`<line x1="${px(
|
|
2662
|
+
`<line x1="${px(bx)}" y1="${px(baseY)}" x2="${px(bx)}" y2="${px(baseY + AXIS_TICK_LEN)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2661
2663
|
);
|
|
2662
|
-
}
|
|
2664
|
+
}
|
|
2665
|
+
} else {
|
|
2666
|
+
out.push(
|
|
2667
|
+
`<line x1="${px(f.plotX)}" y1="${px(f.plotY)}" x2="${px(f.plotX)}" y2="${px(f.plotY + f.plotH)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2668
|
+
);
|
|
2669
|
+
const stepB = pointCount2 > 0 ? f.plotH / pointCount2 : 0;
|
|
2670
|
+
for (let i = 0; i <= pointCount2; i++) {
|
|
2671
|
+
const by = f.plotY + i * stepB;
|
|
2663
2672
|
out.push(
|
|
2664
|
-
`<line x1="${px(f.plotX)}" y1="${px(
|
|
2673
|
+
`<line x1="${px(f.plotX - AXIS_TICK_LEN)}" y1="${px(by)}" x2="${px(f.plotX)}" y2="${px(by)}" stroke="${axisColor}" stroke-width="1"/>`
|
|
2665
2674
|
);
|
|
2666
2675
|
}
|
|
2667
2676
|
}
|
|
2668
2677
|
return out.join("");
|
|
2669
2678
|
};
|
|
2670
2679
|
var seriesMinMax = (spec) => {
|
|
2680
|
+
const isStacked = spec.grouping === "stacked" || spec.grouping === "percentStacked";
|
|
2681
|
+
const isPercent = spec.grouping === "percentStacked";
|
|
2671
2682
|
let min = Infinity;
|
|
2672
2683
|
let max = -Infinity;
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2684
|
+
if (isPercent) {
|
|
2685
|
+
min = 0;
|
|
2686
|
+
max = 1;
|
|
2687
|
+
} else if (isStacked) {
|
|
2688
|
+
const N = spec.series.reduce((n, s) => Math.max(n, s.values.length), 0);
|
|
2689
|
+
for (let c = 0; c < N; c++) {
|
|
2690
|
+
let pos = 0;
|
|
2691
|
+
let neg = 0;
|
|
2692
|
+
for (const s of spec.series) {
|
|
2693
|
+
const v = s.values[c];
|
|
2694
|
+
if (v !== null && v !== void 0 && Number.isFinite(v)) {
|
|
2695
|
+
if (v >= 0) pos += v;
|
|
2696
|
+
else neg += v;
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
if (pos > max) max = pos;
|
|
2700
|
+
if (neg < min) min = neg;
|
|
2701
|
+
}
|
|
2702
|
+
} else {
|
|
2703
|
+
for (const s of spec.series) {
|
|
2704
|
+
for (const v of s.values) {
|
|
2705
|
+
if (v !== null && Number.isFinite(v)) {
|
|
2706
|
+
if (v < min) min = v;
|
|
2707
|
+
if (v > max) max = v;
|
|
2708
|
+
}
|
|
2678
2709
|
}
|
|
2679
2710
|
}
|
|
2680
2711
|
}
|
|
@@ -2682,6 +2713,9 @@ var seriesMinMax = (spec) => {
|
|
|
2682
2713
|
if (!Number.isFinite(max)) max = 1;
|
|
2683
2714
|
if (max === min) max = min + 1;
|
|
2684
2715
|
if (min > 0) min = 0;
|
|
2716
|
+
if (isPercent) {
|
|
2717
|
+
return { min: 0, max: 1, step: 0.2 };
|
|
2718
|
+
}
|
|
2685
2719
|
const step = niceStep(max - min);
|
|
2686
2720
|
max = (Math.floor(max / step) + 1) * step;
|
|
2687
2721
|
if (spec.valueAxis?.min !== void 0) min = spec.valueAxis.min;
|
|
@@ -2707,9 +2741,9 @@ var renderChartLegend = (f, names, colors, position = "b", textStyle, markerSymb
|
|
|
2707
2741
|
const swatch = (i, swatchX, swatchY) => {
|
|
2708
2742
|
const color = colors[i % colors.length];
|
|
2709
2743
|
const sym = markerSymbols?.[i];
|
|
2710
|
-
if (
|
|
2744
|
+
if (markerSymbols !== void 0 && sym !== "none") {
|
|
2711
2745
|
const r = 4.5;
|
|
2712
|
-
return seriesMarker(sym, swatchX + r, swatchY + r, r, color);
|
|
2746
|
+
return seriesMarker(autoMarkerSymbol(sym, i), swatchX + r, swatchY + r, r, color);
|
|
2713
2747
|
}
|
|
2714
2748
|
return `<rect x="${px(swatchX)}" y="${px(swatchY)}" width="9" height="9" fill="${color}"/>`;
|
|
2715
2749
|
};
|
|
@@ -2772,24 +2806,7 @@ var renderColumnChart = (f, spec, colors) => {
|
|
|
2772
2806
|
const grouping = spec.grouping ?? "clustered";
|
|
2773
2807
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
2774
2808
|
const isPercent = grouping === "percentStacked";
|
|
2775
|
-
|
|
2776
|
-
if (isStacked) {
|
|
2777
|
-
let sumMin = Infinity;
|
|
2778
|
-
let sumMax = -Infinity;
|
|
2779
|
-
for (let c = 0; c < N; c++) {
|
|
2780
|
-
let pos = 0;
|
|
2781
|
-
let neg = 0;
|
|
2782
|
-
for (const s of spec.series) {
|
|
2783
|
-
const v = s.values[c] ?? 0;
|
|
2784
|
-
if (v >= 0) pos += v;
|
|
2785
|
-
else neg += v;
|
|
2786
|
-
}
|
|
2787
|
-
if (neg < sumMin) sumMin = neg;
|
|
2788
|
-
if (pos > sumMax) sumMax = pos;
|
|
2789
|
-
}
|
|
2790
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
2791
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
2792
|
-
}
|
|
2809
|
+
const { min, max } = seriesMinMax(spec);
|
|
2793
2810
|
const range = max - min || 1;
|
|
2794
2811
|
const groupW = f.plotW / N;
|
|
2795
2812
|
const gapPctC = (spec.gapWidthPct ?? 150) / 100;
|
|
@@ -2822,7 +2839,7 @@ var renderColumnChart = (f, spec, colors) => {
|
|
|
2822
2839
|
const y1 = f.plotY + f.plotH - (Math.min(stackedTop, stackedBase) - min) / range * f.plotH;
|
|
2823
2840
|
const h = Math.abs(y1 - y0);
|
|
2824
2841
|
out.push(
|
|
2825
|
-
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(barW)}" height="${px(h)}" fill="${colors[s % colors.length]}"/>`
|
|
2842
|
+
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(barW)}" height="${px(h)}" fill="${spec.series[s]?.color ?? colors[s % colors.length]}"/>`
|
|
2826
2843
|
);
|
|
2827
2844
|
if (showLabelFor(s) && Math.abs(v) > 0) {
|
|
2828
2845
|
const labelY = (y0 + y1) / 2 + 3;
|
|
@@ -2996,6 +3013,17 @@ var smoothPath = (pts) => {
|
|
|
2996
3013
|
}
|
|
2997
3014
|
return parts.join(" ");
|
|
2998
3015
|
};
|
|
3016
|
+
var AUTO_MARKER_SYMBOLS = [
|
|
3017
|
+
"diamond",
|
|
3018
|
+
"square",
|
|
3019
|
+
"triangle",
|
|
3020
|
+
"x",
|
|
3021
|
+
"star",
|
|
3022
|
+
"dot",
|
|
3023
|
+
"plus",
|
|
3024
|
+
"dash"
|
|
3025
|
+
];
|
|
3026
|
+
var autoMarkerSymbol = (symbol, seriesIdx) => symbol !== void 0 && symbol !== "auto" ? symbol : AUTO_MARKER_SYMBOLS[seriesIdx % AUTO_MARKER_SYMBOLS.length];
|
|
2999
3027
|
var seriesMarker = (symbol, cx, cy, r, color) => {
|
|
3000
3028
|
switch (symbol) {
|
|
3001
3029
|
case "square":
|
|
@@ -3057,24 +3085,7 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3057
3085
|
const grouping = spec.grouping ?? "clustered";
|
|
3058
3086
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
3059
3087
|
const isPercent = grouping === "percentStacked";
|
|
3060
|
-
|
|
3061
|
-
if (isStacked) {
|
|
3062
|
-
let sumMin = Infinity;
|
|
3063
|
-
let sumMax = -Infinity;
|
|
3064
|
-
for (let c = 0; c < N; c++) {
|
|
3065
|
-
let pos = 0;
|
|
3066
|
-
let neg = 0;
|
|
3067
|
-
for (const s of spec.series) {
|
|
3068
|
-
const v = s.values[c] ?? 0;
|
|
3069
|
-
if (v >= 0) pos += v;
|
|
3070
|
-
else neg += v;
|
|
3071
|
-
}
|
|
3072
|
-
if (neg < sumMin) sumMin = neg;
|
|
3073
|
-
if (pos > sumMax) sumMax = pos;
|
|
3074
|
-
}
|
|
3075
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
3076
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
3077
|
-
}
|
|
3088
|
+
const { min, max } = seriesMinMax(spec);
|
|
3078
3089
|
const range = max - min || 1;
|
|
3079
3090
|
const groupH = f.plotH / N;
|
|
3080
3091
|
const gapPctB = (spec.gapWidthPct ?? 150) / 100;
|
|
@@ -3099,12 +3110,12 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3099
3110
|
}
|
|
3100
3111
|
const base = v >= 0 ? posAcc : negAcc;
|
|
3101
3112
|
const stackedTop = base + v;
|
|
3102
|
-
const y0 = f.plotY + c * groupH + (groupH - barH) / 2;
|
|
3113
|
+
const y0 = f.plotY + (N - 1 - c) * groupH + (groupH - barH) / 2;
|
|
3103
3114
|
const x0 = f.plotX + (Math.min(base, stackedTop) - min) / range * f.plotW;
|
|
3104
3115
|
const x1 = f.plotX + (Math.max(base, stackedTop) - min) / range * f.plotW;
|
|
3105
3116
|
const w = Math.abs(x1 - x0);
|
|
3106
3117
|
out.push(
|
|
3107
|
-
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(w)}" height="${px(barH)}" fill="${colors[s % colors.length]}"/>`
|
|
3118
|
+
`<rect x="${px(x0)}" y="${px(y0)}" width="${px(w)}" height="${px(barH)}" fill="${spec.series[s]?.color ?? colors[s % colors.length]}"/>`
|
|
3108
3119
|
);
|
|
3109
3120
|
if (showLabelForBar(s) && Math.abs(v) > 0) {
|
|
3110
3121
|
const labelX = (x0 + x1) / 2;
|
|
@@ -3118,11 +3129,11 @@ var renderBarChart = (f, spec, colors) => {
|
|
|
3118
3129
|
}
|
|
3119
3130
|
} else {
|
|
3120
3131
|
const clusterH = barH * clusterUnitsB;
|
|
3121
|
-
const clusterStartY = f.plotY + c * groupH + (groupH - clusterH) / 2;
|
|
3132
|
+
const clusterStartY = f.plotY + (N - 1 - c) * groupH + (groupH - clusterH) / 2;
|
|
3122
3133
|
const strideB = barH * (1 - overlapPctB);
|
|
3123
3134
|
for (let s = 0; s < spec.series.length; s++) {
|
|
3124
3135
|
const v = spec.series[s]?.values[c] ?? 0;
|
|
3125
|
-
const y0 = clusterStartY + s * strideB;
|
|
3136
|
+
const y0 = clusterStartY + (Sb - 1 - s) * strideB;
|
|
3126
3137
|
const tip = f.plotX + (v - min) / range * f.plotW;
|
|
3127
3138
|
const x0 = Math.min(tip, baseX);
|
|
3128
3139
|
const w = Math.abs(tip - baseX);
|
|
@@ -3170,24 +3181,7 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3170
3181
|
const grouping = spec.grouping ?? "clustered";
|
|
3171
3182
|
const isStacked = grouping === "stacked" || grouping === "percentStacked";
|
|
3172
3183
|
const isPercent = grouping === "percentStacked";
|
|
3173
|
-
|
|
3174
|
-
if (isStacked) {
|
|
3175
|
-
let sumMin = Infinity;
|
|
3176
|
-
let sumMax = -Infinity;
|
|
3177
|
-
for (let c = 0; c < N; c++) {
|
|
3178
|
-
let pos = 0;
|
|
3179
|
-
let neg = 0;
|
|
3180
|
-
for (const s of spec.series) {
|
|
3181
|
-
const v = s.values[c] ?? 0;
|
|
3182
|
-
if (v >= 0) pos += v;
|
|
3183
|
-
else neg += v;
|
|
3184
|
-
}
|
|
3185
|
-
if (neg < sumMin) sumMin = neg;
|
|
3186
|
-
if (pos > sumMax) sumMax = pos;
|
|
3187
|
-
}
|
|
3188
|
-
min = isPercent ? 0 : Math.min(0, sumMin);
|
|
3189
|
-
max = isPercent ? 1 : Math.max(1, sumMax);
|
|
3190
|
-
}
|
|
3184
|
+
const { min, max } = seriesMinMax(spec);
|
|
3191
3185
|
const range = max - min || 1;
|
|
3192
3186
|
const step = N > 1 ? f.plotW / (N - 1) : 0;
|
|
3193
3187
|
const baseY = f.plotY + f.plotH - (0 - min) / range * f.plotH;
|
|
@@ -3248,7 +3242,7 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3248
3242
|
})();
|
|
3249
3243
|
if (fill) {
|
|
3250
3244
|
const back = basePts.slice().reverse().map(([xp, yp]) => `L${px(xp)},${px(yp)}`).join(" ");
|
|
3251
|
-
out.push(`<path d="${dPath} ${back} Z" fill="${color}"
|
|
3245
|
+
out.push(`<path d="${dPath} ${back} Z" fill="${color}" stroke="none"/>`);
|
|
3252
3246
|
}
|
|
3253
3247
|
const lineWPx = series.lineWidthEmu ? Math.max(0.3, series.lineWidthEmu / EMU_PER_PX) : 1.5;
|
|
3254
3248
|
const dashAttr = series.lineDash ? (() => {
|
|
@@ -3262,8 +3256,9 @@ var renderLineChart = (f, spec, colors, fill) => {
|
|
|
3262
3256
|
`<path d="${dPath}" fill="none" stroke="${color}" stroke-width="${lineWPx.toFixed(2)}" stroke-linejoin="round" stroke-linecap="round"${dashAttr}/>`
|
|
3263
3257
|
);
|
|
3264
3258
|
if (!isStacked) {
|
|
3265
|
-
const
|
|
3266
|
-
if (
|
|
3259
|
+
const explicitSymbol = series.markerSymbol !== void 0 && series.markerSymbol !== "auto" && series.markerSymbol !== "none";
|
|
3260
|
+
if (series.markerSymbol !== "none" && !fill && (spec.lineMarkers === true || explicitSymbol)) {
|
|
3261
|
+
const symbol = autoMarkerSymbol(series.markerSymbol, s);
|
|
3267
3262
|
const size = series.markerSizePt ?? 5;
|
|
3268
3263
|
const r = Math.max(1, size * 0.5);
|
|
3269
3264
|
for (const [xp, yp] of pts) {
|
|
@@ -3505,7 +3500,7 @@ var renderScatterChart = (f, spec, colors) => {
|
|
|
3505
3500
|
const drawMarker = sym === "none" ? false : showMarker || sym !== void 0 && sym !== "auto";
|
|
3506
3501
|
if (drawMarker) {
|
|
3507
3502
|
const r = Math.max(1.5, (series.markerSizePt ?? 5) * 0.5);
|
|
3508
|
-
const glyph = sym
|
|
3503
|
+
const glyph = autoMarkerSymbol(sym, s);
|
|
3509
3504
|
for (const [xp, yp] of proj) out.push(seriesMarker(glyph, xp, yp, r, color));
|
|
3510
3505
|
}
|
|
3511
3506
|
}
|
|
@@ -3628,7 +3623,7 @@ var renderRadarChart = (f, spec, colors) => {
|
|
|
3628
3623
|
);
|
|
3629
3624
|
if (showMarker) {
|
|
3630
3625
|
const r = Math.max(1.5, (series.markerSizePt ?? 5) * 0.5);
|
|
3631
|
-
const glyph = series.markerSymbol
|
|
3626
|
+
const glyph = autoMarkerSymbol(series.markerSymbol, s);
|
|
3632
3627
|
for (const [xp, yp] of proj) out.push(seriesMarker(glyph, xp, yp, r, color));
|
|
3633
3628
|
}
|
|
3634
3629
|
}
|
|
@@ -3664,7 +3659,9 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3664
3659
|
const hiddenSet = new Set(spec.legend?.hiddenIndices ?? []);
|
|
3665
3660
|
const seriesNamesForLegend = allNamesForLegend.filter((_, i) => !hiddenSet.has(i));
|
|
3666
3661
|
const seriesColorsForLegend = allColorsForLegend.filter((_, i) => !hiddenSet.has(i));
|
|
3667
|
-
const
|
|
3662
|
+
const explicitMarker = (sym) => sym !== void 0 && sym !== "auto" && sym !== "none";
|
|
3663
|
+
const showsMarkers = spec.kind === "line" && (spec.lineMarkers === true || spec.series.some((s) => explicitMarker(s.markerSymbol)));
|
|
3664
|
+
const markerSymbolsForLegend = showsMarkers ? spec.series.map((s) => s.markerSymbol).filter((_, i) => !hiddenSet.has(i)) : void 0;
|
|
3668
3665
|
let finiteCount = 0;
|
|
3669
3666
|
for (const s of spec.series) {
|
|
3670
3667
|
for (const v of s.values) if (v !== null && Number.isFinite(v)) finiteCount++;
|
|
@@ -3687,7 +3684,8 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3687
3684
|
...spec.valueAxisLabelRotationDeg !== void 0 ? { labelRotationDeg: spec.valueAxisLabelRotationDeg } : {},
|
|
3688
3685
|
...spec.valueAxis?.displayUnits !== void 0 ? { displayUnits: spec.valueAxis.displayUnits } : {}
|
|
3689
3686
|
};
|
|
3690
|
-
const
|
|
3687
|
+
const isPercentStacked = spec.grouping === "percentStacked";
|
|
3688
|
+
const valueAxis = spec.kind === "bar" ? { orientation: "horizontal", min, max, percent: isPercentStacked, ...axisExtras } : { orientation: "vertical", min, max, percent: isPercentStacked, ...axisExtras };
|
|
3691
3689
|
if (!spec.valueAxisHidden) axes = renderValueAxis(f, valueAxis);
|
|
3692
3690
|
const labelsHidden = spec.categoryAxisHidden || spec.categoryAxisTickLabelPos === "none";
|
|
3693
3691
|
if (N > 0 && !labelsHidden) {
|
|
@@ -3752,8 +3750,11 @@ var renderChart = (shape, x, y, w, h, transform, theme) => {
|
|
|
3752
3750
|
`<g${transform}>`,
|
|
3753
3751
|
// Chart-area backdrop honors <c:chartSpace><c:spPr><a:solidFill> /
|
|
3754
3752
|
// <a:ln>. plot-area gets its own tinted rect + border when
|
|
3755
|
-
// <c:plotArea><c:spPr> authors them.
|
|
3756
|
-
|
|
3753
|
+
// <c:plotArea><c:spPr> authors them. PowerPoint draws no chart-area
|
|
3754
|
+
// border unless the chartSpace authors an <a:ln>, so the default is
|
|
3755
|
+
// `none` — an invented light-gray frame is the most visible single
|
|
3756
|
+
// divergence from PowerPoint's actual rendering.
|
|
3757
|
+
`<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"' : ""}/>`,
|
|
3757
3758
|
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"/>` : "",
|
|
3758
3759
|
renderChartTitle(f, spec.title ?? "", spec.titleStyle),
|
|
3759
3760
|
axes,
|
|
@@ -3883,7 +3884,7 @@ var renderTable = (shape, pres, x, y, w, h, transform, theme, ctx) => {
|
|
|
3883
3884
|
const accent = theme ? normalizeHex(theme.accent1) : "#4472C4";
|
|
3884
3885
|
const headerFill = accent;
|
|
3885
3886
|
const bandFill = mixHex(accent, "#FFFFFF", 0.92);
|
|
3886
|
-
const textColor =
|
|
3887
|
+
const textColor = activeDeckTextColor;
|
|
3887
3888
|
const tableThemeFace = getPresentationFonts(pres)?.minorLatin ?? null;
|
|
3888
3889
|
const out = [];
|
|
3889
3890
|
out.push(`<g${transform}>`);
|
|
@@ -4463,6 +4464,7 @@ var renderSlideSvg = (pres, slide, opts = {}) => {
|
|
|
4463
4464
|
const H = size.height;
|
|
4464
4465
|
const theme = getPresentationTheme(pres);
|
|
4465
4466
|
activeColorMap = getEffectiveColorMap(slide);
|
|
4467
|
+
activeDeckTextColor = resolveDeckBodyTextColor(slide) ?? "#000000";
|
|
4466
4468
|
const ctx = {
|
|
4467
4469
|
mode: opts.textLayout ?? "foreignObject",
|
|
4468
4470
|
measure: opts.measureText ?? defaultMeasurer
|