@hirokisakabe/pom 9.1.1 → 10.0.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/dist/buildContext.js +2 -6
- package/dist/buildContext.js.map +1 -1
- package/dist/buildPptx.d.ts +2 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +4 -9
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/registry/definitions/icon.js +1 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/renderPptx/nodes/chart.js +172 -47
- package/dist/renderPptx/nodes/chart.js.map +1 -1
- package/dist/renderPptx/nodes/flow.js +98 -90
- package/dist/renderPptx/nodes/flow.js.map +1 -1
- package/dist/renderPptx/nodes/icon.js +36 -24
- package/dist/renderPptx/nodes/icon.js.map +1 -1
- package/dist/renderPptx/nodes/image.js +5 -22
- package/dist/renderPptx/nodes/image.js.map +1 -1
- package/dist/renderPptx/nodes/list.js +94 -111
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/matrix.js +95 -70
- package/dist/renderPptx/nodes/matrix.js.map +1 -1
- package/dist/renderPptx/nodes/processArrow.js +74 -35
- package/dist/renderPptx/nodes/processArrow.js.map +1 -1
- package/dist/renderPptx/nodes/pyramid.js +37 -16
- package/dist/renderPptx/nodes/pyramid.js.map +1 -1
- package/dist/renderPptx/nodes/shape.js +66 -37
- package/dist/renderPptx/nodes/shape.js.map +1 -1
- package/dist/renderPptx/nodes/svg.js +2 -5
- package/dist/renderPptx/nodes/svg.js.map +1 -1
- package/dist/renderPptx/nodes/table.js +89 -59
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +1 -18
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/nodes/timeline.js +114 -74
- package/dist/renderPptx/nodes/timeline.js.map +1 -1
- package/dist/renderPptx/nodes/tree.js +81 -79
- package/dist/renderPptx/nodes/tree.js.map +1 -1
- package/dist/renderPptx/pptxAuthoring.js +381 -0
- package/dist/renderPptx/pptxAuthoring.js.map +1 -0
- package/dist/renderPptx/renderPptx.js +158 -128
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/textOptions.js +7 -8
- package/dist/renderPptx/textOptions.js.map +1 -1
- package/dist/renderPptx/units.js +3 -3
- package/dist/renderPptx/units.js.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.js +70 -48
- package/dist/renderPptx/utils/backgroundBorder.js.map +1 -1
- package/dist/renderPptx/utils/contentArea.js +1 -1
- package/dist/renderPptx/utils/contentArea.js.map +1 -1
- package/dist/renderPptx/utils/glimpsePicture.js +111 -0
- package/dist/renderPptx/utils/glimpsePicture.js.map +1 -0
- package/dist/renderPptx/utils/glimpseShape.js +71 -0
- package/dist/renderPptx/utils/glimpseShape.js.map +1 -0
- package/dist/renderPptx/utils/glimpseTextBox.js +107 -0
- package/dist/renderPptx/utils/glimpseTextBox.js.map +1 -0
- package/dist/renderPptx/utils/straightLine.js +33 -15
- package/dist/renderPptx/utils/straightLine.js.map +1 -1
- package/dist/renderPptx/utils/visualStyle.js +3 -56
- package/dist/renderPptx/utils/visualStyle.js.map +1 -1
- package/dist/renderPptx/writablePptx.d.ts +23 -0
- package/dist/renderPptx/writablePptx.d.ts.map +1 -0
- package/dist/renderPptx/writablePptx.js +74 -0
- package/dist/renderPptx/writablePptx.js.map +1 -0
- package/dist/shared/measureImage.js.map +1 -1
- package/package.json +4 -5
- package/dist/renderPptx/glimpseTextBoxes.js +0 -347
- package/dist/renderPptx/glimpseTextBoxes.js.map +0 -1
- package/dist/renderPptx/glowEffects.js +0 -157
- package/dist/renderPptx/glowEffects.js.map +0 -1
- package/dist/renderPptx/gradientFills.js +0 -154
- package/dist/renderPptx/gradientFills.js.map +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createGlimpseParagraphs } from "../utils/glimpseTextBox.js";
|
|
2
|
+
import { addGlimpseShape, createShapeBoundsInput, shapeOutline, solidShapeFill } from "../utils/glimpseShape.js";
|
|
3
|
+
import { addStraightLine } from "../utils/straightLine.js";
|
|
2
4
|
import { stripHash } from "../utils/visualStyle.js";
|
|
3
5
|
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
4
6
|
//#region src/renderPptx/nodes/tree.ts
|
|
@@ -86,37 +88,34 @@ function renderTreeNode(node, ctx) {
|
|
|
86
88
|
const childCenterX = ox + (child.x + child.width / 2) * sf;
|
|
87
89
|
const childTopY = oy + child.y * sf;
|
|
88
90
|
const midY = (parentBottomY + childTopY) / 2;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
91
|
+
addStraightLine(ctx, {
|
|
92
|
+
x1: parentCenterX,
|
|
93
|
+
y1: parentBottomY,
|
|
94
|
+
x2: parentCenterX,
|
|
95
|
+
y2: midY
|
|
96
|
+
}, {
|
|
97
|
+
color: lineColor,
|
|
98
|
+
lineWidth: lineWidth * sf
|
|
98
99
|
});
|
|
99
100
|
const minX = Math.min(parentCenterX, childCenterX);
|
|
100
101
|
const maxX = Math.max(parentCenterX, childCenterX);
|
|
101
|
-
if (maxX > minX)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
102
|
+
if (maxX > minX) addStraightLine(ctx, {
|
|
103
|
+
x1: minX,
|
|
104
|
+
y1: midY,
|
|
105
|
+
x2: maxX,
|
|
106
|
+
y2: midY
|
|
107
|
+
}, {
|
|
108
|
+
color: lineColor,
|
|
109
|
+
lineWidth: lineWidth * sf
|
|
110
110
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
111
|
+
addStraightLine(ctx, {
|
|
112
|
+
x1: childCenterX,
|
|
113
|
+
y1: midY,
|
|
114
|
+
x2: childCenterX,
|
|
115
|
+
y2: childTopY
|
|
116
|
+
}, {
|
|
117
|
+
color: lineColor,
|
|
118
|
+
lineWidth: lineWidth * sf
|
|
120
119
|
});
|
|
121
120
|
} else {
|
|
122
121
|
const parentRightX = ox + (parent.x + parent.width) * sf;
|
|
@@ -124,37 +123,34 @@ function renderTreeNode(node, ctx) {
|
|
|
124
123
|
const childLeftX = ox + child.x * sf;
|
|
125
124
|
const childCenterY = oy + (child.y + child.height / 2) * sf;
|
|
126
125
|
const midX = (parentRightX + childLeftX) / 2;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
126
|
+
addStraightLine(ctx, {
|
|
127
|
+
x1: parentRightX,
|
|
128
|
+
y1: parentCenterY,
|
|
129
|
+
x2: midX,
|
|
130
|
+
y2: parentCenterY
|
|
131
|
+
}, {
|
|
132
|
+
color: lineColor,
|
|
133
|
+
lineWidth: lineWidth * sf
|
|
136
134
|
});
|
|
137
135
|
const minY = Math.min(parentCenterY, childCenterY);
|
|
138
136
|
const maxY = Math.max(parentCenterY, childCenterY);
|
|
139
|
-
if (maxY > minY)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
137
|
+
if (maxY > minY) addStraightLine(ctx, {
|
|
138
|
+
x1: midX,
|
|
139
|
+
y1: minY,
|
|
140
|
+
x2: midX,
|
|
141
|
+
y2: maxY
|
|
142
|
+
}, {
|
|
143
|
+
color: lineColor,
|
|
144
|
+
lineWidth: lineWidth * sf
|
|
148
145
|
});
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
146
|
+
addStraightLine(ctx, {
|
|
147
|
+
x1: midX,
|
|
148
|
+
y1: childCenterY,
|
|
149
|
+
x2: childLeftX,
|
|
150
|
+
y2: childCenterY
|
|
151
|
+
}, {
|
|
152
|
+
color: lineColor,
|
|
153
|
+
lineWidth: lineWidth * sf
|
|
158
154
|
});
|
|
159
155
|
}
|
|
160
156
|
}
|
|
@@ -162,37 +158,43 @@ function renderTreeNode(node, ctx) {
|
|
|
162
158
|
const color = layoutNode.item.color ?? defaultNodeColor;
|
|
163
159
|
const shapeType = (() => {
|
|
164
160
|
switch (shape) {
|
|
165
|
-
case "rect": return
|
|
166
|
-
case "roundRect": return
|
|
167
|
-
case "ellipse": return
|
|
161
|
+
case "rect": return "rect";
|
|
162
|
+
case "roundRect": return "roundRect";
|
|
163
|
+
case "ellipse": return "ellipse";
|
|
168
164
|
}
|
|
169
165
|
})();
|
|
170
166
|
const drawX = ox + layoutNode.x * sf;
|
|
171
167
|
const drawY = oy + layoutNode.y * sf;
|
|
172
168
|
const drawW = layoutNode.width * sf;
|
|
173
169
|
const drawH = layoutNode.height * sf;
|
|
174
|
-
ctx
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
170
|
+
addGlimpseShape(ctx, {
|
|
171
|
+
geometry: {
|
|
172
|
+
kind: "preset",
|
|
173
|
+
preset: shapeType
|
|
174
|
+
},
|
|
175
|
+
...createShapeBoundsInput({
|
|
176
|
+
x: drawX,
|
|
177
|
+
y: drawY,
|
|
178
|
+
w: drawW,
|
|
179
|
+
h: drawH
|
|
180
|
+
}),
|
|
181
|
+
fill: solidShapeFill(color),
|
|
182
|
+
outline: shapeOutline({
|
|
181
183
|
color: "333333",
|
|
182
|
-
width:
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
});
|
|
184
|
+
width: 1 * sf
|
|
185
|
+
}),
|
|
186
|
+
body: { anchor: "middle" },
|
|
187
|
+
paragraphs: createGlimpseParagraphs(layoutNode.item.label, {
|
|
188
|
+
fontSize: 12 * sf,
|
|
189
|
+
fontFace: "Noto Sans JP",
|
|
190
|
+
color: stripHash(layoutNode.item.textColor) ?? defaultTextColor
|
|
191
|
+
}, { align: "center" })
|
|
192
|
+
}, {
|
|
193
|
+
x: drawX,
|
|
194
|
+
y: drawY,
|
|
195
|
+
w: drawW,
|
|
196
|
+
h: drawH
|
|
197
|
+
}, { fillColor: color });
|
|
196
198
|
}
|
|
197
199
|
function drawAllConnectors(layoutNode, sf, ox, oy) {
|
|
198
200
|
for (const child of layoutNode.children) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/renderPptx/nodes/tree.ts"],"sourcesContent":["import type {\n PositionedNode,\n TreeDataItem,\n TreeNodeShape,\n TreeConnectorStyle,\n} from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\n\ntype TreePositionedNode = Extract<PositionedNode, { type: \"tree\" }>;\n\ninterface LayoutNode {\n item: TreeDataItem;\n x: number;\n y: number;\n width: number;\n height: number;\n children: LayoutNode[];\n}\n\nexport function renderTreeNode(\n node: TreePositionedNode,\n ctx: RenderContext,\n): void {\n const layout = node.layout ?? \"vertical\";\n const nodeShape = node.nodeShape ?? \"rect\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 40;\n const levelGap = node.levelGap ?? 60;\n const siblingGap = node.siblingGap ?? 20;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n const defaultTextColor = stripHash(node.textColor) ?? \"FFFFFF\";\n\n // サブツリーの幅/高さを計算\n function calculateSubtreeSize(item: TreeDataItem): {\n width: number;\n height: number;\n } {\n if (!item.children || item.children.length === 0) {\n return { width: nodeWidth, height: nodeHeight };\n }\n\n const childSizes = item.children.map(calculateSubtreeSize);\n\n if (layout === \"vertical\") {\n const childrenWidth =\n childSizes.reduce((sum, s) => sum + s.width, 0) +\n siblingGap * (childSizes.length - 1);\n const childrenHeight = Math.max(...childSizes.map((s) => s.height));\n return {\n width: Math.max(nodeWidth, childrenWidth),\n height: nodeHeight + levelGap + childrenHeight,\n };\n } else {\n const childrenHeight =\n childSizes.reduce((sum, s) => sum + s.height, 0) +\n siblingGap * (childSizes.length - 1);\n const childrenWidth = Math.max(...childSizes.map((s) => s.width));\n return {\n width: nodeWidth + levelGap + childrenWidth,\n height: Math.max(nodeHeight, childrenHeight),\n };\n }\n }\n\n // ツリーレイアウトを計算(原点(0,0)からの相対座標)\n function calculateTreeLayout(\n item: TreeDataItem,\n x: number,\n y: number,\n ): LayoutNode {\n const subtreeSize = calculateSubtreeSize(item);\n const layoutNode: LayoutNode = {\n item,\n x: 0,\n y: 0,\n width: nodeWidth,\n height: nodeHeight,\n children: [],\n };\n\n if (layout === \"vertical\") {\n // ノードを中央上部に配置\n layoutNode.x = x + subtreeSize.width / 2 - nodeWidth / 2;\n layoutNode.y = y;\n\n // 子ノードを配置\n if (item.children && item.children.length > 0) {\n const childSizes = item.children.map(calculateSubtreeSize);\n const totalChildWidth =\n childSizes.reduce((sum, s) => sum + s.width, 0) +\n siblingGap * (childSizes.length - 1);\n let childX = x + subtreeSize.width / 2 - totalChildWidth / 2;\n const childY = y + nodeHeight + levelGap;\n\n for (let i = 0; i < item.children.length; i++) {\n const child = item.children[i];\n const childLayout = calculateTreeLayout(child, childX, childY);\n layoutNode.children.push(childLayout);\n childX += childSizes[i].width + siblingGap;\n }\n }\n } else {\n // horizontal: ノードを左中央に配置\n layoutNode.x = x;\n layoutNode.y = y + subtreeSize.height / 2 - nodeHeight / 2;\n\n // 子ノードを配置\n if (item.children && item.children.length > 0) {\n const childSizes = item.children.map(calculateSubtreeSize);\n const totalChildHeight =\n childSizes.reduce((sum, s) => sum + s.height, 0) +\n siblingGap * (childSizes.length - 1);\n const childX = x + nodeWidth + levelGap;\n let childY = y + subtreeSize.height / 2 - totalChildHeight / 2;\n\n for (let i = 0; i < item.children.length; i++) {\n const child = item.children[i];\n const childLayout = calculateTreeLayout(child, childX, childY);\n layoutNode.children.push(childLayout);\n childY += childSizes[i].height + siblingGap;\n }\n }\n }\n\n return layoutNode;\n }\n\n // 接続線を描画\n function drawConnector(\n parent: LayoutNode,\n child: LayoutNode,\n style: TreeConnectorStyle,\n sf: number,\n ox: number,\n oy: number,\n ) {\n const lineColor = style.color ?? \"333333\";\n const lineWidth = style.width ?? 2;\n\n if (layout === \"vertical\") {\n // 親の下端中央から子の上端中央へ\n const parentCenterX = ox + (parent.x + parent.width / 2) * sf;\n const parentBottomY = oy + (parent.y + parent.height) * sf;\n const childCenterX = ox + (child.x + child.width / 2) * sf;\n const childTopY = oy + child.y * sf;\n const midY = (parentBottomY + childTopY) / 2;\n\n // 垂直線(親から中間点まで)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(parentCenterX),\n y: pxToIn(parentBottomY),\n w: 0,\n h: pxToIn(midY - parentBottomY),\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n\n // 水平線(中間点で)\n const minX = Math.min(parentCenterX, childCenterX);\n const maxX = Math.max(parentCenterX, childCenterX);\n if (maxX > minX) {\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(minX),\n y: pxToIn(midY),\n w: pxToIn(maxX - minX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n }\n\n // 垂直線(中間点から子まで)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(childCenterX),\n y: pxToIn(midY),\n w: 0,\n h: pxToIn(childTopY - midY),\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n } else {\n // 親の右端中央から子の左端中央へ\n const parentRightX = ox + (parent.x + parent.width) * sf;\n const parentCenterY = oy + (parent.y + parent.height / 2) * sf;\n const childLeftX = ox + child.x * sf;\n const childCenterY = oy + (child.y + child.height / 2) * sf;\n const midX = (parentRightX + childLeftX) / 2;\n\n // 水平線(親から中間点まで)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(parentRightX),\n y: pxToIn(parentCenterY),\n w: pxToIn(midX - parentRightX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n\n // 垂直線(中間点で)\n const minY = Math.min(parentCenterY, childCenterY);\n const maxY = Math.max(parentCenterY, childCenterY);\n if (maxY > minY) {\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(minY),\n w: 0,\n h: pxToIn(maxY - minY),\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n }\n\n // 水平線(中間点から子まで)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(childCenterY),\n w: pxToIn(childLeftX - midX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth * sf) },\n });\n }\n }\n\n // ノードを描画\n function drawTreeNode(\n layoutNode: LayoutNode,\n shape: TreeNodeShape,\n defaultNodeColor: string,\n sf: number,\n ox: number,\n oy: number,\n ) {\n const color = layoutNode.item.color ?? defaultNodeColor;\n const shapeType = (() => {\n switch (shape) {\n case \"rect\":\n return ctx.pptx.ShapeType.rect;\n case \"roundRect\":\n return ctx.pptx.ShapeType.roundRect;\n case \"ellipse\":\n return ctx.pptx.ShapeType.ellipse;\n }\n })();\n\n const drawX = ox + layoutNode.x * sf;\n const drawY = oy + layoutNode.y * sf;\n const drawW = layoutNode.width * sf;\n const drawH = layoutNode.height * sf;\n\n // ノードの背景\n ctx.slide.addShape(shapeType, {\n x: pxToIn(drawX),\n y: pxToIn(drawY),\n w: pxToIn(drawW),\n h: pxToIn(drawH),\n fill: { color },\n line: { color: \"333333\", width: pxToPt(1 * sf) },\n });\n\n // ノードのラベル\n ctx.slide.addText(layoutNode.item.label, {\n x: pxToIn(drawX),\n y: pxToIn(drawY),\n w: pxToIn(drawW),\n h: pxToIn(drawH),\n fontSize: pxToPt(12 * sf),\n fontFace: \"Noto Sans JP\",\n color: stripHash(layoutNode.item.textColor) ?? defaultTextColor,\n align: \"center\",\n valign: \"middle\",\n });\n }\n\n // すべての接続線を再帰的に描画\n function drawAllConnectors(\n layoutNode: LayoutNode,\n sf: number,\n ox: number,\n oy: number,\n ) {\n for (const child of layoutNode.children) {\n drawConnector(layoutNode, child, connectorStyle, sf, ox, oy);\n drawAllConnectors(child, sf, ox, oy);\n }\n }\n\n // すべてのノードを再帰的に描画\n function drawAllNodes(\n layoutNode: LayoutNode,\n sf: number,\n ox: number,\n oy: number,\n ) {\n drawTreeNode(layoutNode, nodeShape, defaultColor, sf, ox, oy);\n for (const child of layoutNode.children) {\n drawAllNodes(child, sf, ox, oy);\n }\n }\n\n // ツリーのサイズを計算\n const treeSize = calculateSubtreeSize(node.data);\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n treeSize,\n ctx,\n );\n\n // スケール後のサイズで中央配置オフセットを計算\n const scaledW = treeSize.width * scaleFactor;\n const scaledH = treeSize.height * scaleFactor;\n const offsetX = content.x + (content.w - scaledW) / 2;\n const offsetY = content.y + (content.h - scaledH) / 2;\n\n // レイアウト計算(原点(0,0)からの相対座標)\n const rootLayout = calculateTreeLayout(node.data, 0, 0);\n\n // 描画(接続線を先に、ノードを後に描画)\n drawAllConnectors(rootLayout, scaleFactor, offsetX, offsetY);\n drawAllNodes(rootLayout, scaleFactor, offsetX, offsetY);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/renderPptx/nodes/tree.ts"],"sourcesContent":["import type {\n PositionedNode,\n TreeDataItem,\n TreeNodeShape,\n TreeConnectorStyle,\n} from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { addStraightLine } from \"../utils/straightLine.ts\";\nimport {\n addGlimpseShape,\n createShapeBoundsInput,\n shapeOutline,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\nimport { createGlimpseParagraphs } from \"../utils/glimpseTextBox.ts\";\n\ntype TreePositionedNode = Extract<PositionedNode, { type: \"tree\" }>;\n\ninterface LayoutNode {\n item: TreeDataItem;\n x: number;\n y: number;\n width: number;\n height: number;\n children: LayoutNode[];\n}\n\nexport function renderTreeNode(\n node: TreePositionedNode,\n ctx: RenderContext,\n): void {\n const layout = node.layout ?? \"vertical\";\n const nodeShape = node.nodeShape ?? \"rect\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 40;\n const levelGap = node.levelGap ?? 60;\n const siblingGap = node.siblingGap ?? 20;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n const defaultTextColor = stripHash(node.textColor) ?? \"FFFFFF\";\n\n // サブツリーの幅/高さを計算\n function calculateSubtreeSize(item: TreeDataItem): {\n width: number;\n height: number;\n } {\n if (!item.children || item.children.length === 0) {\n return { width: nodeWidth, height: nodeHeight };\n }\n\n const childSizes = item.children.map(calculateSubtreeSize);\n\n if (layout === \"vertical\") {\n const childrenWidth =\n childSizes.reduce((sum, s) => sum + s.width, 0) +\n siblingGap * (childSizes.length - 1);\n const childrenHeight = Math.max(...childSizes.map((s) => s.height));\n return {\n width: Math.max(nodeWidth, childrenWidth),\n height: nodeHeight + levelGap + childrenHeight,\n };\n } else {\n const childrenHeight =\n childSizes.reduce((sum, s) => sum + s.height, 0) +\n siblingGap * (childSizes.length - 1);\n const childrenWidth = Math.max(...childSizes.map((s) => s.width));\n return {\n width: nodeWidth + levelGap + childrenWidth,\n height: Math.max(nodeHeight, childrenHeight),\n };\n }\n }\n\n // ツリーレイアウトを計算(原点(0,0)からの相対座標)\n function calculateTreeLayout(\n item: TreeDataItem,\n x: number,\n y: number,\n ): LayoutNode {\n const subtreeSize = calculateSubtreeSize(item);\n const layoutNode: LayoutNode = {\n item,\n x: 0,\n y: 0,\n width: nodeWidth,\n height: nodeHeight,\n children: [],\n };\n\n if (layout === \"vertical\") {\n // ノードを中央上部に配置\n layoutNode.x = x + subtreeSize.width / 2 - nodeWidth / 2;\n layoutNode.y = y;\n\n // 子ノードを配置\n if (item.children && item.children.length > 0) {\n const childSizes = item.children.map(calculateSubtreeSize);\n const totalChildWidth =\n childSizes.reduce((sum, s) => sum + s.width, 0) +\n siblingGap * (childSizes.length - 1);\n let childX = x + subtreeSize.width / 2 - totalChildWidth / 2;\n const childY = y + nodeHeight + levelGap;\n\n for (let i = 0; i < item.children.length; i++) {\n const child = item.children[i];\n const childLayout = calculateTreeLayout(child, childX, childY);\n layoutNode.children.push(childLayout);\n childX += childSizes[i].width + siblingGap;\n }\n }\n } else {\n // horizontal: ノードを左中央に配置\n layoutNode.x = x;\n layoutNode.y = y + subtreeSize.height / 2 - nodeHeight / 2;\n\n // 子ノードを配置\n if (item.children && item.children.length > 0) {\n const childSizes = item.children.map(calculateSubtreeSize);\n const totalChildHeight =\n childSizes.reduce((sum, s) => sum + s.height, 0) +\n siblingGap * (childSizes.length - 1);\n const childX = x + nodeWidth + levelGap;\n let childY = y + subtreeSize.height / 2 - totalChildHeight / 2;\n\n for (let i = 0; i < item.children.length; i++) {\n const child = item.children[i];\n const childLayout = calculateTreeLayout(child, childX, childY);\n layoutNode.children.push(childLayout);\n childY += childSizes[i].height + siblingGap;\n }\n }\n }\n\n return layoutNode;\n }\n\n // 接続線を描画\n function drawConnector(\n parent: LayoutNode,\n child: LayoutNode,\n style: TreeConnectorStyle,\n sf: number,\n ox: number,\n oy: number,\n ) {\n const lineColor = style.color ?? \"333333\";\n const lineWidth = style.width ?? 2;\n\n if (layout === \"vertical\") {\n // 親の下端中央から子の上端中央へ\n const parentCenterX = ox + (parent.x + parent.width / 2) * sf;\n const parentBottomY = oy + (parent.y + parent.height) * sf;\n const childCenterX = ox + (child.x + child.width / 2) * sf;\n const childTopY = oy + child.y * sf;\n const midY = (parentBottomY + childTopY) / 2;\n\n // 垂直線(親から中間点まで)\n addStraightLine(\n ctx,\n {\n x1: parentCenterX,\n y1: parentBottomY,\n x2: parentCenterX,\n y2: midY,\n },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n\n // 水平線(中間点で)\n const minX = Math.min(parentCenterX, childCenterX);\n const maxX = Math.max(parentCenterX, childCenterX);\n if (maxX > minX) {\n addStraightLine(\n ctx,\n { x1: minX, y1: midY, x2: maxX, y2: midY },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n }\n\n // 垂直線(中間点から子まで)\n addStraightLine(\n ctx,\n { x1: childCenterX, y1: midY, x2: childCenterX, y2: childTopY },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n } else {\n // 親の右端中央から子の左端中央へ\n const parentRightX = ox + (parent.x + parent.width) * sf;\n const parentCenterY = oy + (parent.y + parent.height / 2) * sf;\n const childLeftX = ox + child.x * sf;\n const childCenterY = oy + (child.y + child.height / 2) * sf;\n const midX = (parentRightX + childLeftX) / 2;\n\n // 水平線(親から中間点まで)\n addStraightLine(\n ctx,\n { x1: parentRightX, y1: parentCenterY, x2: midX, y2: parentCenterY },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n\n // 垂直線(中間点で)\n const minY = Math.min(parentCenterY, childCenterY);\n const maxY = Math.max(parentCenterY, childCenterY);\n if (maxY > minY) {\n addStraightLine(\n ctx,\n { x1: midX, y1: minY, x2: midX, y2: maxY },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n }\n\n // 水平線(中間点から子まで)\n addStraightLine(\n ctx,\n { x1: midX, y1: childCenterY, x2: childLeftX, y2: childCenterY },\n { color: lineColor, lineWidth: lineWidth * sf },\n );\n }\n }\n\n // ノードを描画\n function drawTreeNode(\n layoutNode: LayoutNode,\n shape: TreeNodeShape,\n defaultNodeColor: string,\n sf: number,\n ox: number,\n oy: number,\n ) {\n const color = layoutNode.item.color ?? defaultNodeColor;\n const shapeType = (() => {\n switch (shape) {\n case \"rect\":\n return \"rect\";\n case \"roundRect\":\n return \"roundRect\";\n case \"ellipse\":\n return \"ellipse\";\n }\n })();\n\n const drawX = ox + layoutNode.x * sf;\n const drawY = oy + layoutNode.y * sf;\n const drawW = layoutNode.width * sf;\n const drawH = layoutNode.height * sf;\n\n addGlimpseShape(\n ctx,\n {\n geometry: { kind: \"preset\", preset: shapeType },\n ...createShapeBoundsInput({ x: drawX, y: drawY, w: drawW, h: drawH }),\n fill: solidShapeFill(color),\n outline: shapeOutline({ color: \"333333\", width: 1 * sf }),\n body: { anchor: \"middle\" },\n paragraphs: createGlimpseParagraphs(\n layoutNode.item.label,\n {\n fontSize: 12 * sf,\n fontFace: \"Noto Sans JP\",\n color: stripHash(layoutNode.item.textColor) ?? defaultTextColor,\n },\n { align: \"center\" },\n ),\n },\n { x: drawX, y: drawY, w: drawW, h: drawH },\n { fillColor: color },\n );\n }\n\n // すべての接続線を再帰的に描画\n function drawAllConnectors(\n layoutNode: LayoutNode,\n sf: number,\n ox: number,\n oy: number,\n ) {\n for (const child of layoutNode.children) {\n drawConnector(layoutNode, child, connectorStyle, sf, ox, oy);\n drawAllConnectors(child, sf, ox, oy);\n }\n }\n\n // すべてのノードを再帰的に描画\n function drawAllNodes(\n layoutNode: LayoutNode,\n sf: number,\n ox: number,\n oy: number,\n ) {\n drawTreeNode(layoutNode, nodeShape, defaultColor, sf, ox, oy);\n for (const child of layoutNode.children) {\n drawAllNodes(child, sf, ox, oy);\n }\n }\n\n // ツリーのサイズを計算\n const treeSize = calculateSubtreeSize(node.data);\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n treeSize,\n ctx,\n );\n\n // スケール後のサイズで中央配置オフセットを計算\n const scaledW = treeSize.width * scaleFactor;\n const scaledH = treeSize.height * scaleFactor;\n const offsetX = content.x + (content.w - scaledW) / 2;\n const offsetY = content.y + (content.h - scaledH) / 2;\n\n // レイアウト計算(原点(0,0)からの相対座標)\n const rootLayout = calculateTreeLayout(node.data, 0, 0);\n\n // 描画(接続線を先に、ノードを後に描画)\n drawAllConnectors(rootLayout, scaleFactor, offsetX, offsetY);\n drawAllNodes(rootLayout, scaleFactor, offsetX, offsetY);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { parseGradient, parseLinearGradient } from "../shared/gradient.js";
|
|
2
|
+
import { EMU_PER_IN, pxToEmu, pxToPt } from "./units.js";
|
|
3
|
+
import { createTextOptions, resolveSubSup } from "./textOptions.js";
|
|
4
|
+
import { addChart, addPicture, addShape, addTable, addTextBox, asEmu, asHundredthPt, asOoxmlAngle, asOoxmlPercent, asPt, createPptx, setSlideBackground } from "@pptx-glimpse/document";
|
|
5
|
+
//#region src/renderPptx/pptxAuthoring.ts
|
|
6
|
+
function cleanHex(color) {
|
|
7
|
+
const hex = color?.replace(/^#/, "").toUpperCase();
|
|
8
|
+
return hex?.length === 3 ? [...hex].map((character) => character.repeat(2)).join("") : hex;
|
|
9
|
+
}
|
|
10
|
+
function toColorInput(color, opacity) {
|
|
11
|
+
const hex = cleanHex(color);
|
|
12
|
+
if (!hex) return void 0;
|
|
13
|
+
return {
|
|
14
|
+
kind: "srgb",
|
|
15
|
+
hex,
|
|
16
|
+
transforms: opacity === void 0 ? void 0 : [{
|
|
17
|
+
kind: "alpha",
|
|
18
|
+
value: asOoxmlPercent(Math.round(opacity * 1e5))
|
|
19
|
+
}]
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function toUnderlineInput(underline) {
|
|
23
|
+
if (underline === void 0 || underline === false) return void 0;
|
|
24
|
+
if (underline === true) return true;
|
|
25
|
+
return {
|
|
26
|
+
style: underline.style,
|
|
27
|
+
color: toColorInput(underline.color)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function toBaselineInput(subscript, superscript) {
|
|
31
|
+
if (subscript) return {
|
|
32
|
+
type: "percent",
|
|
33
|
+
value: asOoxmlPercent(-4e4)
|
|
34
|
+
};
|
|
35
|
+
if (superscript) return {
|
|
36
|
+
type: "percent",
|
|
37
|
+
value: asOoxmlPercent(3e4)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function toGlowInput(glow) {
|
|
41
|
+
if (!glow) return void 0;
|
|
42
|
+
return {
|
|
43
|
+
radius: asEmu(Math.round(pxToEmu(glow.size ?? 8))),
|
|
44
|
+
color: toColorInput(glow.color ?? "FFFFFF", glow.opacity ?? .75)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function toOutlineInput(outline) {
|
|
48
|
+
if (!outline) return void 0;
|
|
49
|
+
return {
|
|
50
|
+
width: asEmu(Math.round(pxToEmu(outline.size ?? 1))),
|
|
51
|
+
color: toColorInput(outline.color ?? "FFFFFF")
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function toCharSpacing(letterSpacingPx) {
|
|
55
|
+
if (letterSpacingPx === void 0) return void 0;
|
|
56
|
+
return Math.round(pxToPt(letterSpacingPx) * 100);
|
|
57
|
+
}
|
|
58
|
+
function toTextGradientInput(value) {
|
|
59
|
+
if (!value) return void 0;
|
|
60
|
+
const linear = parseLinearGradient(value);
|
|
61
|
+
if (!linear) return void 0;
|
|
62
|
+
const dmlAngle = ((linear.angle - 90) % 360 + 360) % 360;
|
|
63
|
+
return {
|
|
64
|
+
gradientType: "linear",
|
|
65
|
+
angle: asOoxmlAngle(Math.round(dmlAngle * 6e4)),
|
|
66
|
+
stops: linear.stops.map((stop) => ({
|
|
67
|
+
position: asOoxmlPercent(Math.round(stop.position * 1e3)),
|
|
68
|
+
color: toColorInput(stop.color)
|
|
69
|
+
}))
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function stripUndefined(value) {
|
|
73
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
74
|
+
}
|
|
75
|
+
function resolveUnderline(node, run) {
|
|
76
|
+
if (run?.underline !== void 0) return run.underline;
|
|
77
|
+
if (node.underline !== void 0) return node.underline;
|
|
78
|
+
return run?.href ? true : void 0;
|
|
79
|
+
}
|
|
80
|
+
function buildRunProperties(node, run, gradientFill) {
|
|
81
|
+
const fontSizePx = run?.fontSize ?? node.fontSize ?? 24;
|
|
82
|
+
const subSup = run ? resolveSubSup(run, node) : node;
|
|
83
|
+
return stripUndefined({
|
|
84
|
+
fontFace: run?.fontFamily ?? node.fontFamily ?? "Noto Sans JP",
|
|
85
|
+
fontSize: asPt(pxToPt(fontSizePx)),
|
|
86
|
+
color: gradientFill ? void 0 : toColorInput(run?.color ?? node.color),
|
|
87
|
+
gradientFill,
|
|
88
|
+
bold: run?.bold ?? node.bold,
|
|
89
|
+
italic: run?.italic ?? node.italic,
|
|
90
|
+
underline: toUnderlineInput(resolveUnderline(node, run)),
|
|
91
|
+
strike: run?.strike ?? node.strike,
|
|
92
|
+
baseline: toBaselineInput(subSup.subscript, subSup.superscript),
|
|
93
|
+
highlight: toColorInput(run?.highlight ?? node.highlight),
|
|
94
|
+
glow: toGlowInput(node.glow),
|
|
95
|
+
outline: toOutlineInput(node.outline),
|
|
96
|
+
charSpacing: toCharSpacing(run?.letterSpacing ?? node.letterSpacing)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function buildParagraphs(node) {
|
|
100
|
+
const gradientFill = toTextGradientInput(node.textGradient);
|
|
101
|
+
const sourceRuns = node.runs && node.runs.length > 0 ? node.runs.map((run) => ({
|
|
102
|
+
text: run.text,
|
|
103
|
+
properties: buildRunProperties(node, run, gradientFill),
|
|
104
|
+
href: run.href
|
|
105
|
+
})) : [{
|
|
106
|
+
text: node.text ?? "",
|
|
107
|
+
properties: buildRunProperties(node, void 0, gradientFill)
|
|
108
|
+
}];
|
|
109
|
+
const paragraphRuns = [[]];
|
|
110
|
+
for (const run of sourceRuns) run.text.replace(/\r*\n/g, "\n").split("\n").forEach((line, index) => {
|
|
111
|
+
if (index > 0) paragraphRuns.push([]);
|
|
112
|
+
paragraphRuns.at(-1)?.push({
|
|
113
|
+
...run,
|
|
114
|
+
text: line
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
const lineHeight = node.lineHeight ?? 1.3;
|
|
118
|
+
const fontSizePx = node.fontSize ?? 24;
|
|
119
|
+
return paragraphRuns.map((runs) => ({
|
|
120
|
+
properties: {
|
|
121
|
+
align: node.textAlign,
|
|
122
|
+
marginLeft: asEmu(0),
|
|
123
|
+
indent: asEmu(0),
|
|
124
|
+
bullet: { type: "none" },
|
|
125
|
+
lineSpacing: asHundredthPt(Math.round(pxToPt(fontSizePx * lineHeight) * 100))
|
|
126
|
+
},
|
|
127
|
+
runs: runs.map((run) => ({
|
|
128
|
+
text: run.text,
|
|
129
|
+
properties: run.properties,
|
|
130
|
+
hyperlink: run.href
|
|
131
|
+
}))
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
function toGradientFill(value, opacity) {
|
|
135
|
+
const gradient = parseGradient(value);
|
|
136
|
+
if (!gradient) return void 0;
|
|
137
|
+
const stops = gradient.value.stops.map((stop) => ({
|
|
138
|
+
position: asOoxmlPercent(Math.round(stop.position * 1e3)),
|
|
139
|
+
color: toColorInput(stop.color, opacity)
|
|
140
|
+
}));
|
|
141
|
+
if (gradient.kind === "linear") {
|
|
142
|
+
const dmlAngle = ((gradient.value.angle - 90) % 360 + 360) % 360;
|
|
143
|
+
return {
|
|
144
|
+
kind: "gradient",
|
|
145
|
+
gradientType: "linear",
|
|
146
|
+
angle: asOoxmlAngle(Math.round(dmlAngle * 6e4)),
|
|
147
|
+
stops
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
kind: "gradient",
|
|
152
|
+
gradientType: "radial",
|
|
153
|
+
centerX: asOoxmlPercent(Math.round(gradient.value.centerX * 1e3)),
|
|
154
|
+
centerY: asOoxmlPercent(Math.round(gradient.value.centerY * 1e3)),
|
|
155
|
+
stops
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function withFillOpacity(fill, opacity) {
|
|
159
|
+
if (!fill || opacity === void 0 || fill.kind !== "solid") return fill;
|
|
160
|
+
return {
|
|
161
|
+
...fill,
|
|
162
|
+
color: toColorInput(fill.color.hex, opacity)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function toShadowEffects(shadow) {
|
|
166
|
+
if (!shadow) return void 0;
|
|
167
|
+
const common = {
|
|
168
|
+
blurRadius: asEmu(Math.round((shadow.blur ?? 3) * 12700)),
|
|
169
|
+
distance: asEmu(Math.round((shadow.offset ?? 23e3 / 12700) * 12700)),
|
|
170
|
+
direction: asOoxmlAngle(Math.round((shadow.angle ?? 90) * 6e4)),
|
|
171
|
+
color: toColorInput(shadow.color ?? "000000", shadow.opacity ?? .35)
|
|
172
|
+
};
|
|
173
|
+
return shadow.type === "inner" ? { innerShadow: common } : { outerShadow: {
|
|
174
|
+
...common,
|
|
175
|
+
alignment: "bl",
|
|
176
|
+
rotateWithShape: true
|
|
177
|
+
} };
|
|
178
|
+
}
|
|
179
|
+
function customGeometry(input) {
|
|
180
|
+
const commands = [];
|
|
181
|
+
let moved = false;
|
|
182
|
+
for (const point of input.points) {
|
|
183
|
+
if ("close" in point) {
|
|
184
|
+
if (moved) commands.push({ kind: "close" });
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
commands.push({
|
|
188
|
+
kind: moved ? "lineTo" : "moveTo",
|
|
189
|
+
x: Math.round(point.x * EMU_PER_IN),
|
|
190
|
+
y: Math.round(point.y * EMU_PER_IN)
|
|
191
|
+
});
|
|
192
|
+
moved = true;
|
|
193
|
+
}
|
|
194
|
+
if (!moved) return void 0;
|
|
195
|
+
return {
|
|
196
|
+
kind: "custom",
|
|
197
|
+
paths: [{
|
|
198
|
+
width: Math.round(input.width * EMU_PER_IN),
|
|
199
|
+
height: Math.round(input.height * EMU_PER_IN),
|
|
200
|
+
commands
|
|
201
|
+
}]
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function enrichShapeInput(input, options) {
|
|
205
|
+
const preset = input.geometry.kind === "preset" ? input.geometry.preset : "";
|
|
206
|
+
const geometry = options?.customGeometry ? customGeometry(options.customGeometry) ?? input.geometry : preset === "roundRect" && options?.rectRadius !== void 0 ? {
|
|
207
|
+
...input.geometry,
|
|
208
|
+
adjustValues: { adj: Math.round(options.rectRadius * 5e4) }
|
|
209
|
+
} : input.geometry;
|
|
210
|
+
const gradientFill = options?.backgroundGradient ? toGradientFill(options.backgroundGradient, options.fillOpacity) : void 0;
|
|
211
|
+
const outlineGradient = options?.outlineGradient ? toGradientFill(options.outlineGradient, options.outlineOpacity ?? options.fillOpacity) : void 0;
|
|
212
|
+
const outline = input.outline ? {
|
|
213
|
+
...input.outline,
|
|
214
|
+
fill: outlineGradient ?? withFillOpacity(input.outline.fill, options?.outlineOpacity),
|
|
215
|
+
dash: options?.dashType ?? input.outline.dash
|
|
216
|
+
} : outlineGradient ? { fill: outlineGradient } : void 0;
|
|
217
|
+
const glow = options?.glow ? {
|
|
218
|
+
radius: asEmu(Math.round(pxToEmu(options.glow.size ?? 8))),
|
|
219
|
+
color: toColorInput(options.glow.color ?? "FFFFFF", options.glow.opacity ?? .75)
|
|
220
|
+
} : input.effects?.glow;
|
|
221
|
+
const effects = {
|
|
222
|
+
...input.effects,
|
|
223
|
+
...toShadowEffects(options?.shadow),
|
|
224
|
+
...glow ? { glow } : {}
|
|
225
|
+
};
|
|
226
|
+
const width = preset === "line" && options?.zeroWidth ? asEmu(0) : input.width;
|
|
227
|
+
let height = preset === "line" && options?.zeroHeight ? asEmu(0) : input.height;
|
|
228
|
+
if (preset === "line" && width === 0 && height === 0) height = asEmu(1);
|
|
229
|
+
return {
|
|
230
|
+
...input,
|
|
231
|
+
geometry,
|
|
232
|
+
width,
|
|
233
|
+
height,
|
|
234
|
+
fill: gradientFill ?? withFillOpacity(input.fill, options?.fillOpacity),
|
|
235
|
+
outline,
|
|
236
|
+
effects: Object.keys(effects).length > 0 ? effects : void 0,
|
|
237
|
+
flipHorizontal: options?.flipH ?? input.flipHorizontal,
|
|
238
|
+
flipVertical: options?.flipV ?? input.flipVertical
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function applyHyperlinks(input, hyperlinks) {
|
|
242
|
+
if (!hyperlinks?.some(Boolean) || !input.paragraphs) return input;
|
|
243
|
+
let index = 0;
|
|
244
|
+
return {
|
|
245
|
+
...input,
|
|
246
|
+
paragraphs: input.paragraphs.map((paragraph) => ({
|
|
247
|
+
...paragraph,
|
|
248
|
+
runs: paragraph.runs.map((run) => ({
|
|
249
|
+
...run,
|
|
250
|
+
hyperlink: hyperlinks[index++]
|
|
251
|
+
}))
|
|
252
|
+
}))
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
var PptxAuthoringRegistry = class {
|
|
256
|
+
currentSource;
|
|
257
|
+
currentSlideHandle;
|
|
258
|
+
useLayoutTextMargins = false;
|
|
259
|
+
textCount = 0;
|
|
260
|
+
shapeCount = 0;
|
|
261
|
+
pictureCount = 0;
|
|
262
|
+
tableCount = 0;
|
|
263
|
+
chartCount = 0;
|
|
264
|
+
constructor() {
|
|
265
|
+
const source = createPptx();
|
|
266
|
+
this.currentSource = source;
|
|
267
|
+
this.currentSlideHandle = source.slides[0]?.handle;
|
|
268
|
+
}
|
|
269
|
+
initialize(source, useLayoutTextMargins = false) {
|
|
270
|
+
this.currentSource = source;
|
|
271
|
+
this.useLayoutTextMargins = useLayoutTextMargins;
|
|
272
|
+
}
|
|
273
|
+
selectSlide(handle) {
|
|
274
|
+
this.currentSlideHandle = handle;
|
|
275
|
+
}
|
|
276
|
+
get source() {
|
|
277
|
+
if (!this.currentSource) throw new Error("glimpse authoring is not initialized");
|
|
278
|
+
return this.currentSource;
|
|
279
|
+
}
|
|
280
|
+
get entries() {
|
|
281
|
+
return (this.source.edits ?? []).flatMap((edit) => (edit.kind === "addTextBox" || edit.kind === "addShape") && "xml" in edit ? [{
|
|
282
|
+
kind: "shape",
|
|
283
|
+
xml: edit.xml
|
|
284
|
+
}] : []);
|
|
285
|
+
}
|
|
286
|
+
replaceSource(source) {
|
|
287
|
+
this.currentSource = source;
|
|
288
|
+
}
|
|
289
|
+
get target() {
|
|
290
|
+
if (!this.currentSlideHandle) throw new Error("glimpse slide is not selected");
|
|
291
|
+
return this.currentSlideHandle;
|
|
292
|
+
}
|
|
293
|
+
register(node) {
|
|
294
|
+
const textOptions = createTextOptions(node);
|
|
295
|
+
this.registerTextBox({
|
|
296
|
+
offsetX: asEmu(Math.round(textOptions.x * EMU_PER_IN)),
|
|
297
|
+
offsetY: asEmu(Math.round(textOptions.y * EMU_PER_IN)),
|
|
298
|
+
width: asEmu(Math.round(textOptions.w * EMU_PER_IN)),
|
|
299
|
+
height: asEmu(Math.round(textOptions.h * EMU_PER_IN)),
|
|
300
|
+
rotation: node.rotate === void 0 ? void 0 : asOoxmlAngle(Math.round(node.rotate * 6e4)),
|
|
301
|
+
body: this.useLayoutTextMargins ? void 0 : {
|
|
302
|
+
anchor: "top",
|
|
303
|
+
marginLeft: asEmu(0),
|
|
304
|
+
marginRight: asEmu(0),
|
|
305
|
+
marginTop: asEmu(0),
|
|
306
|
+
marginBottom: asEmu(0)
|
|
307
|
+
},
|
|
308
|
+
paragraphs: buildParagraphs(node)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
registerTextBox(input, options) {
|
|
312
|
+
const name = options?.name ?? `Text ${++this.textCount}`;
|
|
313
|
+
this.currentSource = addTextBox(this.source, this.target, applyHyperlinks({
|
|
314
|
+
...input,
|
|
315
|
+
name
|
|
316
|
+
}, options?.hyperlinks));
|
|
317
|
+
}
|
|
318
|
+
registerShape(input, options) {
|
|
319
|
+
const name = options?.name ?? `Shape ${++this.shapeCount}`;
|
|
320
|
+
this.currentSource = addShape(this.source, this.target, enrichShapeInput({
|
|
321
|
+
...input,
|
|
322
|
+
name
|
|
323
|
+
}, options));
|
|
324
|
+
}
|
|
325
|
+
registerPicture(input, options) {
|
|
326
|
+
const name = options?.name ?? `Picture ${++this.pictureCount}`;
|
|
327
|
+
this.currentSource = addPicture(this.source, this.target, {
|
|
328
|
+
...input,
|
|
329
|
+
name,
|
|
330
|
+
effects: toShadowEffects(options?.shadow)
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
registerTable(input, options) {
|
|
334
|
+
const name = options?.name ?? `Table ${++this.tableCount}`;
|
|
335
|
+
this.currentSource = addTable(this.source, this.target, {
|
|
336
|
+
...input,
|
|
337
|
+
name
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
registerChart(input, options) {
|
|
341
|
+
const name = options?.name ?? `Chart ${++this.chartCount}`;
|
|
342
|
+
this.currentSource = addChart(this.source, this.target, {
|
|
343
|
+
...input,
|
|
344
|
+
name
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
setSlideBackgroundGradient(backgroundGradient, opacity) {
|
|
348
|
+
const fill = toGradientFill(backgroundGradient, opacity);
|
|
349
|
+
if (!fill || fill.kind !== "gradient") return false;
|
|
350
|
+
const background = fill.gradientType === "linear" ? {
|
|
351
|
+
kind: "gradient",
|
|
352
|
+
gradientType: "linear",
|
|
353
|
+
stops: fill.stops,
|
|
354
|
+
angle: fill.angle ?? asOoxmlAngle(0)
|
|
355
|
+
} : {
|
|
356
|
+
kind: "gradient",
|
|
357
|
+
gradientType: "radial",
|
|
358
|
+
stops: fill.stops,
|
|
359
|
+
centerX: fill.centerX,
|
|
360
|
+
centerY: fill.centerY
|
|
361
|
+
};
|
|
362
|
+
this.currentSource = setSlideBackground(this.source, this.target, background);
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
setSlideBackgroundSolid(color) {
|
|
366
|
+
this.currentSource = setSlideBackground(this.source, this.target, {
|
|
367
|
+
kind: "solid",
|
|
368
|
+
color: toColorInput(color)
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
setSlideBackgroundImage(bytes) {
|
|
372
|
+
this.currentSource = setSlideBackground(this.source, this.target, {
|
|
373
|
+
kind: "image",
|
|
374
|
+
bytes
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
//#endregion
|
|
379
|
+
export { PptxAuthoringRegistry, cleanHex, toColorInput };
|
|
380
|
+
|
|
381
|
+
//# sourceMappingURL=pptxAuthoring.js.map
|