@hirokisakabe/pom 8.3.0 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -23
- package/dist/autoFit/autoFit.js +1 -1
- package/dist/autoFit/autoFit.js.map +1 -1
- package/dist/autoFit/strategies/reduceFontSize.js +16 -14
- package/dist/autoFit/strategies/reduceFontSize.js.map +1 -1
- package/dist/autoFit/strategies/reduceGapAndPadding.js +13 -20
- package/dist/autoFit/strategies/reduceGapAndPadding.js.map +1 -1
- package/dist/autoFit/strategies/reduceTableRowHeight.js +8 -2
- package/dist/autoFit/strategies/reduceTableRowHeight.js.map +1 -1
- package/dist/autoFit/strategies/uniformScale.js +19 -20
- package/dist/autoFit/strategies/uniformScale.js.map +1 -1
- package/dist/autoFit/strategyResult.js +15 -0
- package/dist/autoFit/strategyResult.js.map +1 -0
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +4 -2
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +16 -27
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/parseXml/coercionRules.js +43 -8
- package/dist/parseXml/coercionRules.js.map +1 -1
- package/dist/parseXml/parseXml.d.ts +8 -3
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js +192 -212
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.d.ts.map +1 -1
- package/dist/parseXml/serializeXml.js +12 -17
- package/dist/parseXml/serializeXml.js.map +1 -1
- package/dist/registry/definitions/arrow.js +2 -2
- package/dist/registry/definitions/arrow.js.map +1 -1
- package/dist/registry/definitions/chart.js +2 -2
- package/dist/registry/definitions/chart.js.map +1 -1
- package/dist/registry/definitions/compositeNodes.js +7 -12
- package/dist/registry/definitions/compositeNodes.js.map +1 -1
- package/dist/registry/definitions/icon.js +2 -2
- package/dist/registry/definitions/icon.js.map +1 -1
- package/dist/registry/definitions/image.js +2 -2
- package/dist/registry/definitions/image.js.map +1 -1
- package/dist/registry/definitions/layer.js +4 -5
- package/dist/registry/definitions/layer.js.map +1 -1
- package/dist/registry/definitions/line.js +2 -2
- package/dist/registry/definitions/line.js.map +1 -1
- package/dist/registry/definitions/list.js +3 -4
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/registry/definitions/shape.js +2 -2
- package/dist/registry/definitions/shape.js.map +1 -1
- package/dist/registry/definitions/stack.js +3 -4
- package/dist/registry/definitions/stack.js.map +1 -1
- package/dist/registry/definitions/svg.js +2 -2
- package/dist/registry/definitions/svg.js.map +1 -1
- package/dist/registry/definitions/table.js +2 -2
- package/dist/registry/definitions/table.js.map +1 -1
- package/dist/registry/definitions/text.js +2 -2
- package/dist/registry/definitions/text.js.map +1 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/nodeMetadata.js +208 -0
- package/dist/registry/nodeMetadata.js.map +1 -0
- package/dist/registry/nodeRegistry.js +3 -0
- package/dist/registry/nodeRegistry.js.map +1 -1
- package/dist/registry/xmlChildRules.js +55 -0
- package/dist/registry/xmlChildRules.js.map +1 -0
- package/dist/renderPptx/nodes/arrow.js +7 -28
- package/dist/renderPptx/nodes/arrow.js.map +1 -1
- package/dist/renderPptx/nodes/chart.js +2 -7
- package/dist/renderPptx/nodes/chart.js.map +1 -1
- package/dist/renderPptx/nodes/flow.js +6 -13
- package/dist/renderPptx/nodes/flow.js.map +1 -1
- package/dist/renderPptx/nodes/icon.js +4 -2
- package/dist/renderPptx/nodes/icon.js.map +1 -1
- package/dist/renderPptx/nodes/image.js +5 -13
- package/dist/renderPptx/nodes/image.js.map +1 -1
- package/dist/renderPptx/nodes/line.js +9 -33
- package/dist/renderPptx/nodes/line.js.map +1 -1
- package/dist/renderPptx/nodes/list.js +8 -20
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/matrix.js +10 -11
- package/dist/renderPptx/nodes/matrix.js.map +1 -1
- package/dist/renderPptx/nodes/processArrow.js +9 -16
- package/dist/renderPptx/nodes/processArrow.js.map +1 -1
- package/dist/renderPptx/nodes/pyramid.js +5 -7
- package/dist/renderPptx/nodes/pyramid.js.map +1 -1
- package/dist/renderPptx/nodes/shape.js +7 -20
- 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 +2 -5
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +4 -1
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/nodes/timeline.js +20 -22
- package/dist/renderPptx/nodes/timeline.js.map +1 -1
- package/dist/renderPptx/nodes/tree.js +5 -5
- package/dist/renderPptx/nodes/tree.js.map +1 -1
- package/dist/renderPptx/renderPptx.js +13 -29
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/textOptions.js +32 -8
- package/dist/renderPptx/textOptions.js.map +1 -1
- package/dist/renderPptx/units.js +11 -1
- package/dist/renderPptx/units.js.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.js +103 -57
- package/dist/renderPptx/utils/backgroundBorder.js.map +1 -1
- package/dist/renderPptx/utils/contentArea.js +26 -9
- package/dist/renderPptx/utils/contentArea.js.map +1 -1
- package/dist/renderPptx/utils/scaleToFit.js +17 -1
- package/dist/renderPptx/utils/scaleToFit.js.map +1 -1
- package/dist/renderPptx/utils/straightLine.js +41 -0
- package/dist/renderPptx/utils/straightLine.js.map +1 -0
- package/dist/renderPptx/utils/visualStyle.js +113 -0
- package/dist/renderPptx/utils/visualStyle.js.map +1 -0
- package/dist/shared/boxSpacing.js +63 -0
- package/dist/shared/boxSpacing.js.map +1 -0
- package/dist/shared/walkTree.js +1 -7
- package/dist/shared/walkTree.js.map +1 -1
- package/dist/toPositioned/toPositioned.js +1 -1
- package/dist/toPositioned/toPositioned.js.map +1 -1
- package/dist/types.d.ts +1127 -95
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +47 -17
- package/dist/types.js.map +1 -1
- package/dist/validatePositioned/validatePositioned.js +92 -0
- package/dist/validatePositioned/validatePositioned.js.map +1 -0
- package/package.json +4 -3
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { resolveArrowType } from "./line.js";
|
|
1
|
+
import { addStraightLine } from "../utils/straightLine.js";
|
|
3
2
|
//#region src/renderPptx/nodes/arrow.ts
|
|
4
3
|
function renderArrowNode(node, ctx) {
|
|
5
4
|
const fromBounds = ctx.idPositionMap.get(node.from);
|
|
@@ -12,32 +11,12 @@ function renderArrowNode(node, ctx) {
|
|
|
12
11
|
ctx.buildContext.diagnostics.add("ARROW_REF_NOT_FOUND", `Arrow: "to" ID "${node.to}" not found`);
|
|
13
12
|
return;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const lineW = Math.abs(x2 - x1);
|
|
22
|
-
const lineH = Math.abs(y2 - y1);
|
|
23
|
-
const flipH = x2 < x1;
|
|
24
|
-
const flipV = y2 < y1;
|
|
25
|
-
const { color, lineWidth, dashType, beginArrow, endArrow } = node;
|
|
26
|
-
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
27
|
-
x: pxToIn(minX),
|
|
28
|
-
y: pxToIn(minY),
|
|
29
|
-
w: pxToIn(lineW),
|
|
30
|
-
h: pxToIn(lineH),
|
|
31
|
-
flipH,
|
|
32
|
-
flipV,
|
|
33
|
-
line: {
|
|
34
|
-
color: color ?? "000000",
|
|
35
|
-
width: lineWidth !== void 0 ? pxToPt(lineWidth) : 1,
|
|
36
|
-
dashType,
|
|
37
|
-
beginArrowType: resolveArrowType(beginArrow),
|
|
38
|
-
endArrowType: resolveArrowType(endArrow)
|
|
39
|
-
}
|
|
40
|
-
});
|
|
14
|
+
addStraightLine(ctx, {
|
|
15
|
+
x1: fromBounds.x + fromBounds.w / 2,
|
|
16
|
+
y1: fromBounds.y + fromBounds.h / 2,
|
|
17
|
+
x2: toBounds.x + toBounds.w / 2,
|
|
18
|
+
y2: toBounds.y + toBounds.h / 2
|
|
19
|
+
}, node);
|
|
41
20
|
}
|
|
42
21
|
//#endregion
|
|
43
22
|
export { renderArrowNode };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { addStraightLine } from \"../utils/straightLine.ts\";\n\ntype ArrowPositionedNode = Extract<PositionedNode, { type: \"arrow\" }>;\n\nexport function renderArrowNode(\n node: ArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const fromBounds = ctx.idPositionMap.get(node.from);\n const toBounds = ctx.idPositionMap.get(node.to);\n\n if (!fromBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"from\" ID \"${node.from}\" not found`,\n );\n return;\n }\n if (!toBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"to\" ID \"${node.to}\" not found`,\n );\n return;\n }\n\n // 参照ノードの中心同士を結ぶ\n addStraightLine(\n ctx,\n {\n x1: fromBounds.x + fromBounds.w / 2,\n y1: fromBounds.y + fromBounds.h / 2,\n x2: toBounds.x + toBounds.w / 2,\n y2: toBounds.y + toBounds.h / 2,\n },\n node,\n );\n}\n"],"mappings":";;AAMA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,aAAa,IAAI,cAAc,IAAI,KAAK,IAAI;CAClD,MAAM,WAAW,IAAI,cAAc,IAAI,KAAK,EAAE;CAE9C,IAAI,CAAC,YAAY;EACf,IAAI,aAAa,YAAY,IAC3B,uBACA,qBAAqB,KAAK,KAAK,YACjC;EACA;CACF;CACA,IAAI,CAAC,UAAU;EACb,IAAI,aAAa,YAAY,IAC3B,uBACA,mBAAmB,KAAK,GAAG,YAC7B;EACA;CACF;CAGA,gBACE,KACA;EACE,IAAI,WAAW,IAAI,WAAW,IAAI;EAClC,IAAI,WAAW,IAAI,WAAW,IAAI;EAClC,IAAI,SAAS,IAAI,SAAS,IAAI;EAC9B,IAAI,SAAS,IAAI,SAAS,IAAI;CAChC,GACA,IACF;AACF"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getContentArea } from "../utils/contentArea.js";
|
|
1
|
+
import { getContentAreaIn } from "../utils/contentArea.js";
|
|
3
2
|
//#region src/renderPptx/nodes/chart.ts
|
|
4
3
|
function renderChartNode(node, ctx) {
|
|
5
4
|
const chartData = node.data.map((d) => ({
|
|
@@ -7,12 +6,8 @@ function renderChartNode(node, ctx) {
|
|
|
7
6
|
labels: d.labels,
|
|
8
7
|
values: d.values
|
|
9
8
|
}));
|
|
10
|
-
const content = getContentArea(node);
|
|
11
9
|
const chartOptions = {
|
|
12
|
-
|
|
13
|
-
y: pxToIn(content.y),
|
|
14
|
-
w: pxToIn(content.w),
|
|
15
|
-
h: pxToIn(content.h),
|
|
10
|
+
...getContentAreaIn(node),
|
|
16
11
|
showLegend: node.showLegend ?? false,
|
|
17
12
|
showTitle: node.showTitle ?? false,
|
|
18
13
|
title: node.title,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart.js","names":[],"sources":["../../../src/renderPptx/nodes/chart.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"chart.js","names":[],"sources":["../../../src/renderPptx/nodes/chart.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { getContentAreaIn } from \"../utils/contentArea.ts\";\n\ntype ChartPositionedNode = Extract<PositionedNode, { type: \"chart\" }>;\n\nexport function renderChartNode(\n node: ChartPositionedNode,\n ctx: RenderContext,\n): void {\n const chartData = node.data.map((d) => ({\n name: d.name,\n labels: d.labels,\n values: d.values,\n }));\n\n const chartOptions: Record<string, unknown> = {\n ...getContentAreaIn(node),\n showLegend: node.showLegend ?? false,\n showTitle: node.showTitle ?? false,\n title: node.title,\n chartColors: node.chartColors,\n };\n\n // radar専用オプション\n if (node.chartType === \"radar\" && node.radarStyle) {\n chartOptions.radarStyle = node.radarStyle;\n }\n\n ctx.slide.addChart(node.chartType, chartData, chartOptions);\n}\n"],"mappings":";;AAMA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,KAAK,KAAK,OAAO;EACtC,MAAM,EAAE;EACR,QAAQ,EAAE;EACV,QAAQ,EAAE;CACZ,EAAE;CAEF,MAAM,eAAwC;EAC5C,GAAG,iBAAiB,IAAI;EACxB,YAAY,KAAK,cAAc;EAC/B,WAAW,KAAK,aAAa;EAC7B,OAAO,KAAK;EACZ,aAAa,KAAK;CACpB;CAGA,IAAI,KAAK,cAAc,WAAW,KAAK,YACrC,aAAa,aAAa,KAAK;CAGjC,IAAI,MAAM,SAAS,KAAK,WAAW,WAAW,YAAY;AAC5D"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { pxToIn, pxToPt } from "../units.js";
|
|
2
|
-
import {
|
|
2
|
+
import { withContentBounds } from "../utils/contentArea.js";
|
|
3
|
+
import { stripHash } from "../utils/visualStyle.js";
|
|
3
4
|
import { measureFlow } from "../../calcYogaLayout/measureCompositeNodes.js";
|
|
4
|
-
import {
|
|
5
|
+
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
5
6
|
//#region src/renderPptx/nodes/flow.ts
|
|
6
7
|
function renderFlowNode(node, ctx) {
|
|
7
8
|
const direction = node.direction ?? "horizontal";
|
|
@@ -10,21 +11,13 @@ function renderFlowNode(node, ctx) {
|
|
|
10
11
|
const nodeGap = node.nodeGap ?? 80;
|
|
11
12
|
const connectorStyle = node.connectorStyle ?? {};
|
|
12
13
|
const defaultColor = "1D4ED8";
|
|
13
|
-
const content =
|
|
14
|
-
const intrinsic = measureFlow(node);
|
|
15
|
-
const scaleFactor = calcScaleFactor(content.w, content.h, intrinsic.width, intrinsic.height, "flow", ctx.buildContext.diagnostics);
|
|
14
|
+
const { content, scaleFactor } = resolveScaledContentArea(node, measureFlow(node), ctx);
|
|
16
15
|
const scaledNodeWidth = nodeWidth * scaleFactor;
|
|
17
16
|
const scaledNodeHeight = nodeHeight * scaleFactor;
|
|
18
17
|
const scaledNodeGap = nodeGap * scaleFactor;
|
|
19
18
|
const layouts = /* @__PURE__ */ new Map();
|
|
20
19
|
const nodeCount = node.nodes.length;
|
|
21
|
-
const contentNode =
|
|
22
|
-
...node,
|
|
23
|
-
x: content.x,
|
|
24
|
-
y: content.y,
|
|
25
|
-
w: content.w,
|
|
26
|
-
h: content.h
|
|
27
|
-
};
|
|
20
|
+
const contentNode = withContentBounds(node, content);
|
|
28
21
|
if (direction === "horizontal") calculateHorizontalLayout(contentNode, layouts, nodeCount, scaledNodeWidth, scaledNodeHeight, scaledNodeGap, scaleFactor);
|
|
29
22
|
else calculateVerticalLayout(contentNode, layouts, nodeCount, scaledNodeWidth, scaledNodeHeight, scaledNodeGap, scaleFactor);
|
|
30
23
|
for (const conn of node.connections) {
|
|
@@ -44,7 +37,7 @@ function renderFlowNode(node, ctx) {
|
|
|
44
37
|
h: pxToIn(labelH),
|
|
45
38
|
fontSize: pxToPt(10 * scaleFactor),
|
|
46
39
|
fontFace: "Noto Sans JP",
|
|
47
|
-
color: "64748B",
|
|
40
|
+
color: stripHash(conn.labelColor) ?? stripHash(connectorStyle.labelColor) ?? "64748B",
|
|
48
41
|
align: "center",
|
|
49
42
|
valign: "middle"
|
|
50
43
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/renderPptx/nodes/flow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { measureFlow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { calcScaleFactor } from \"../utils/scaleToFit.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\n\ntype FlowPositionedNode = Extract<PositionedNode, { type: \"flow\" }>;\n\ninterface FlowNodeLayout {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n item: FlowPositionedNode[\"nodes\"][0];\n}\n\nexport function renderFlowNode(\n node: FlowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 60;\n const nodeGap = node.nodeGap ?? 80;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const content = getContentArea(node);\n const intrinsic = measureFlow(node);\n const scaleFactor = calcScaleFactor(\n content.w,\n content.h,\n intrinsic.width,\n intrinsic.height,\n \"flow\",\n ctx.buildContext.diagnostics,\n );\n\n const scaledNodeWidth = nodeWidth * scaleFactor;\n const scaledNodeHeight = nodeHeight * scaleFactor;\n const scaledNodeGap = nodeGap * scaleFactor;\n\n const layouts = new Map<string, FlowNodeLayout>();\n const nodeCount = node.nodes.length;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = {\n ...node,\n x: content.x,\n y: content.y,\n w: content.w,\n h: content.h,\n };\n\n // ノードのレイアウトを計算\n if (direction === \"horizontal\") {\n calculateHorizontalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n } else {\n calculateVerticalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n }\n\n // 接続線を描画(ノードより先に描画して背面に配置)\n for (const conn of node.connections) {\n const fromLayout = layouts.get(conn.from);\n const toLayout = layouts.get(conn.to);\n\n if (!fromLayout || !toLayout) continue;\n\n const lineColor = conn.color ?? connectorStyle.color ?? \"333333\";\n const lineWidth = (connectorStyle.width ?? 2) * scaleFactor;\n const arrowType = connectorStyle.arrowType ?? \"triangle\";\n\n drawConnection(\n ctx,\n direction,\n fromLayout,\n toLayout,\n lineColor,\n lineWidth,\n arrowType,\n );\n\n // ラベルを描画\n if (conn.label) {\n const labelX =\n (fromLayout.x +\n fromLayout.width / 2 +\n toLayout.x +\n toLayout.width / 2) /\n 2;\n const labelY =\n (fromLayout.y +\n fromLayout.height / 2 +\n toLayout.y +\n toLayout.height / 2) /\n 2;\n\n const labelW = 60 * scaleFactor;\n const labelH = 20 * scaleFactor;\n\n ctx.slide.addText(conn.label, {\n x: pxToIn(labelX - labelW / 2),\n y: pxToIn(labelY - labelH / 2),\n w: pxToIn(labelW),\n h: pxToIn(labelH),\n fontSize: pxToPt(10 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: \"64748B\",\n align: \"center\",\n valign: \"middle\",\n });\n }\n }\n\n // ノードを描画\n for (const item of node.nodes) {\n const layout = layouts.get(item.id);\n if (!layout) continue;\n\n const fillColor = item.color ?? defaultColor;\n const textColor = item.textColor ?? \"FFFFFF\";\n\n // 図形を描画\n ctx.slide.addText(item.text, {\n x: pxToIn(layout.x),\n y: pxToIn(layout.y),\n w: pxToIn(layout.width),\n h: pxToIn(layout.height),\n shape: item.shape,\n fill: { color: fillColor },\n line: { color: \"333333\", width: pxToPt(1 * scaleFactor) },\n fontSize: pxToPt(14 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: textColor,\n align: \"center\",\n valign: \"middle\",\n });\n }\n}\n\nfunction calculateHorizontalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalWidth = nodeCount * nodeWidth + (nodeCount - 1) * nodeGap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: startX + index * (nodeWidth + nodeGap) + (nodeWidth - w) / 2,\n y: centerY - h / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction calculateVerticalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalHeight = nodeCount * nodeHeight + (nodeCount - 1) * nodeGap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: centerX - w / 2,\n y: startY + index * (nodeHeight + nodeGap) + (nodeHeight - h) / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction drawConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n fromLayout: FlowNodeLayout,\n toLayout: FlowNodeLayout,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n let startX: number, startY: number, endX: number, endY: number;\n\n if (direction === \"horizontal\") {\n // 水平: 右端から左端へ\n startX = fromLayout.x + fromLayout.width;\n startY = fromLayout.y + fromLayout.height / 2;\n endX = toLayout.x;\n endY = toLayout.y + toLayout.height / 2;\n } else {\n // 垂直: 下端から上端へ\n startX = fromLayout.x + fromLayout.width / 2;\n startY = fromLayout.y + fromLayout.height;\n endX = toLayout.x + toLayout.width / 2;\n endY = toLayout.y;\n }\n\n // 直線接続(シンプルなケース)\n const isHorizontalLine = Math.abs(startY - endY) < 1;\n const isVerticalLine = Math.abs(startX - endX) < 1;\n\n if (isHorizontalLine || isVerticalLine) {\n // 直線で描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(Math.min(startY, endY)),\n w: pxToIn(Math.abs(endX - startX)),\n h: pxToIn(Math.abs(endY - startY)),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // L字型接続\n drawLShapedConnection(\n ctx,\n direction,\n startX,\n startY,\n endX,\n endY,\n lineColor,\n lineWidth,\n arrowType,\n );\n }\n}\n\nfunction drawLShapedConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n const midX = (startX + endX) / 2;\n const midY = (startY + endY) / 2;\n\n if (direction === \"horizontal\") {\n // 水平→垂直→水平\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: pxToIn(midX - startX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(Math.min(startY, endY)),\n w: 0,\n h: pxToIn(Math.abs(endY - startY)),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(endY),\n w: pxToIn(endX - midX),\n h: 0,\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // 垂直→水平→垂直\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: 0,\n h: pxToIn(midY - startY),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(midY),\n w: pxToIn(Math.abs(endX - startX)),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(endX),\n y: pxToIn(midY),\n w: 0,\n h: pxToIn(endY - midY),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n }\n}\n"],"mappings":";;;;;AAkBA,SAAgB,eACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,iBAAiB,KAAK,kBAAkB,CAAC;CAC/C,MAAM,eAAe;CAGrB,MAAM,UAAU,eAAe,IAAI;CACnC,MAAM,YAAY,YAAY,IAAI;CAClC,MAAM,cAAc,gBAClB,QAAQ,GACR,QAAQ,GACR,UAAU,OACV,UAAU,QACV,QACA,IAAI,aAAa,WACnB;CAEA,MAAM,kBAAkB,YAAY;CACpC,MAAM,mBAAmB,aAAa;CACtC,MAAM,gBAAgB,UAAU;CAEhC,MAAM,0BAAU,IAAI,IAA4B;CAChD,MAAM,YAAY,KAAK,MAAM;CAG7B,MAAM,cAAc;EAClB,GAAG;EACH,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;CACb;CAGA,IAAI,cAAc,cAChB,0BACE,aACA,SACA,WACA,iBACA,kBACA,eACA,WACF;MAEA,wBACE,aACA,SACA,WACA,iBACA,kBACA,eACA,WACF;CAIF,KAAK,MAAM,QAAQ,KAAK,aAAa;EACnC,MAAM,aAAa,QAAQ,IAAI,KAAK,IAAI;EACxC,MAAM,WAAW,QAAQ,IAAI,KAAK,EAAE;EAEpC,IAAI,CAAC,cAAc,CAAC,UAAU;EAM9B,eACE,KACA,WACA,YACA,UARgB,KAAK,SAAS,eAAe,SAAS,WACrC,eAAe,SAAS,KAAK,aAC9B,eAAe,aAAa,UAU9C;EAGA,IAAI,KAAK,OAAO;GACd,MAAM,UACH,WAAW,IACV,WAAW,QAAQ,IACnB,SAAS,IACT,SAAS,QAAQ,KACnB;GACF,MAAM,UACH,WAAW,IACV,WAAW,SAAS,IACpB,SAAS,IACT,SAAS,SAAS,KACpB;GAEF,MAAM,SAAS,KAAK;GACpB,MAAM,SAAS,KAAK;GAEpB,IAAI,MAAM,QAAQ,KAAK,OAAO;IAC5B,GAAG,OAAO,SAAS,SAAS,CAAC;IAC7B,GAAG,OAAO,SAAS,SAAS,CAAC;IAC7B,GAAG,OAAO,MAAM;IAChB,GAAG,OAAO,MAAM;IAChB,UAAU,OAAO,KAAK,WAAW;IACjC,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;GACV,CAAC;EACH;CACF;CAGA,KAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,MAAM,SAAS,QAAQ,IAAI,KAAK,EAAE;EAClC,IAAI,CAAC,QAAQ;EAEb,MAAM,YAAY,KAAK,SAAS;EAChC,MAAM,YAAY,KAAK,aAAa;EAGpC,IAAI,MAAM,QAAQ,KAAK,MAAM;GAC3B,GAAG,OAAO,OAAO,CAAC;GAClB,GAAG,OAAO,OAAO,CAAC;GAClB,GAAG,OAAO,OAAO,KAAK;GACtB,GAAG,OAAO,OAAO,MAAM;GACvB,OAAO,KAAK;GACZ,MAAM,EAAE,OAAO,UAAU;GACzB,MAAM;IAAE,OAAO;IAAU,OAAO,OAAO,IAAI,WAAW;GAAE;GACxD,UAAU,OAAO,KAAK,WAAW;GACjC,UAAU;GACV,OAAO;GACP,OAAO;GACP,QAAQ;EACV,CAAC;CACH;AACF;AAEA,SAAS,0BACP,MACA,SACA,WACA,WACA,YACA,SACA,aACM;CACN,MAAM,aAAa,YAAY,aAAa,YAAY,KAAK;CAC7D,MAAM,SAAS,KAAK,KAAK,KAAK,IAAI,cAAc;CAChD,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI;CAElC,KAAK,MAAM,SAAS,MAAM,UAAU;EAClC,MAAM,KAAK,KAAK,SAAS,YAAY,eAAe;EACpD,MAAM,KAAK,KAAK,UAAU,aAAa,eAAe;EACtD,QAAQ,IAAI,KAAK,IAAI;GACnB,IAAI,KAAK;GACT,GAAG,SAAS,SAAS,YAAY,YAAY,YAAY,KAAK;GAC9D,GAAG,UAAU,IAAI;GACjB,OAAO;GACP,QAAQ;GACR;EACF,CAAC;CACH,CAAC;AACH;AAEA,SAAS,wBACP,MACA,SACA,WACA,WACA,YACA,SACA,aACM;CACN,MAAM,cAAc,YAAY,cAAc,YAAY,KAAK;CAC/D,MAAM,SAAS,KAAK,KAAK,KAAK,IAAI,eAAe;CACjD,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI;CAElC,KAAK,MAAM,SAAS,MAAM,UAAU;EAClC,MAAM,KAAK,KAAK,SAAS,YAAY,eAAe;EACpD,MAAM,KAAK,KAAK,UAAU,aAAa,eAAe;EACtD,QAAQ,IAAI,KAAK,IAAI;GACnB,IAAI,KAAK;GACT,GAAG,UAAU,IAAI;GACjB,GAAG,SAAS,SAAS,aAAa,YAAY,aAAa,KAAK;GAChE,OAAO;GACP,QAAQ;GACR;EACF,CAAC;CACH,CAAC;AACH;AAEA,SAAS,eACP,KACA,WACA,YACA,UACA,WACA,WACA,WACM;CACN,IAAI,QAAgB,QAAgB,MAAc;CAElD,IAAI,cAAc,cAAc;EAE9B,SAAS,WAAW,IAAI,WAAW;EACnC,SAAS,WAAW,IAAI,WAAW,SAAS;EAC5C,OAAO,SAAS;EAChB,OAAO,SAAS,IAAI,SAAS,SAAS;CACxC,OAAO;EAEL,SAAS,WAAW,IAAI,WAAW,QAAQ;EAC3C,SAAS,WAAW,IAAI,WAAW;EACnC,OAAO,SAAS,IAAI,SAAS,QAAQ;EACrC,OAAO,SAAS;CAClB;CAGA,MAAM,mBAAmB,KAAK,IAAI,SAAS,IAAI,IAAI;CACnD,MAAM,iBAAiB,KAAK,IAAI,SAAS,IAAI,IAAI;CAEjD,IAAI,oBAAoB,gBAEtB,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;EAC1C,GAAG,OAAO,KAAK,IAAI,QAAQ,IAAI,CAAC;EAChC,GAAG,OAAO,KAAK,IAAI,QAAQ,IAAI,CAAC;EAChC,GAAG,OAAO,KAAK,IAAI,OAAO,MAAM,CAAC;EACjC,GAAG,OAAO,KAAK,IAAI,OAAO,MAAM,CAAC;EACjC,MAAM;GACJ,OAAO;GACP,OAAO,OAAO,SAAS;GACvB,cAAc;EAChB;CACF,CAAC;MAGD,sBACE,KACA,WACA,QACA,QACA,MACA,MACA,WACA,WACA,SACF;AAEJ;AAEA,SAAS,sBACP,KACA,WACA,QACA,QACA,MACA,MACA,WACA,WACA,WACM;CACN,MAAM,QAAQ,SAAS,QAAQ;CAC/B,MAAM,QAAQ,SAAS,QAAQ;CAE/B,IAAI,cAAc,cAAc;EAE9B,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,OAAO,MAAM;GACvB,GAAG;GACH,MAAM;IAAE,OAAO;IAAW,OAAO,OAAO,SAAS;GAAE;EACrD,CAAC;EACD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,IAAI;GACd,GAAG,OAAO,KAAK,IAAI,QAAQ,IAAI,CAAC;GAChC,GAAG;GACH,GAAG,OAAO,KAAK,IAAI,OAAO,MAAM,CAAC;GACjC,MAAM;IAAE,OAAO;IAAW,OAAO,OAAO,SAAS;GAAE;EACrD,CAAC;EACD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,IAAI;GACd,GAAG,OAAO,IAAI;GACd,GAAG,OAAO,OAAO,IAAI;GACrB,GAAG;GACH,MAAM;IACJ,OAAO;IACP,OAAO,OAAO,SAAS;IACvB,cAAc;GAChB;EACF,CAAC;CACH,OAAO;EAEL,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,MAAM;GAChB,GAAG;GACH,GAAG,OAAO,OAAO,MAAM;GACvB,MAAM;IAAE,OAAO;IAAW,OAAO,OAAO,SAAS;GAAE;EACrD,CAAC;EACD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,KAAK,IAAI,QAAQ,IAAI,CAAC;GAChC,GAAG,OAAO,IAAI;GACd,GAAG,OAAO,KAAK,IAAI,OAAO,MAAM,CAAC;GACjC,GAAG;GACH,MAAM;IAAE,OAAO;IAAW,OAAO,OAAO,SAAS;GAAE;EACrD,CAAC;EACD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;GAC1C,GAAG,OAAO,IAAI;GACd,GAAG,OAAO,IAAI;GACd,GAAG;GACH,GAAG,OAAO,OAAO,IAAI;GACrB,MAAM;IACJ,OAAO;IACP,OAAO,OAAO,SAAS;IACvB,cAAc;GAChB;EACF,CAAC;CACH;AACF"}
|
|
1
|
+
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/renderPptx/nodes/flow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { measureFlow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\n\ntype FlowPositionedNode = Extract<PositionedNode, { type: \"flow\" }>;\n\ninterface FlowNodeLayout {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n item: FlowPositionedNode[\"nodes\"][0];\n}\n\nexport function renderFlowNode(\n node: FlowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const nodeWidth = node.nodeWidth ?? 120;\n const nodeHeight = node.nodeHeight ?? 60;\n const nodeGap = node.nodeGap ?? 80;\n const connectorStyle = node.connectorStyle ?? {};\n const defaultColor = \"1D4ED8\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureFlow(node),\n ctx,\n );\n\n const scaledNodeWidth = nodeWidth * scaleFactor;\n const scaledNodeHeight = nodeHeight * scaleFactor;\n const scaledNodeGap = nodeGap * scaleFactor;\n\n const layouts = new Map<string, FlowNodeLayout>();\n const nodeCount = node.nodes.length;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n // ノードのレイアウトを計算\n if (direction === \"horizontal\") {\n calculateHorizontalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n } else {\n calculateVerticalLayout(\n contentNode,\n layouts,\n nodeCount,\n scaledNodeWidth,\n scaledNodeHeight,\n scaledNodeGap,\n scaleFactor,\n );\n }\n\n // 接続線を描画(ノードより先に描画して背面に配置)\n for (const conn of node.connections) {\n const fromLayout = layouts.get(conn.from);\n const toLayout = layouts.get(conn.to);\n\n if (!fromLayout || !toLayout) continue;\n\n const lineColor = conn.color ?? connectorStyle.color ?? \"333333\";\n const lineWidth = (connectorStyle.width ?? 2) * scaleFactor;\n const arrowType = connectorStyle.arrowType ?? \"triangle\";\n\n drawConnection(\n ctx,\n direction,\n fromLayout,\n toLayout,\n lineColor,\n lineWidth,\n arrowType,\n );\n\n // ラベルを描画\n if (conn.label) {\n const labelX =\n (fromLayout.x +\n fromLayout.width / 2 +\n toLayout.x +\n toLayout.width / 2) /\n 2;\n const labelY =\n (fromLayout.y +\n fromLayout.height / 2 +\n toLayout.y +\n toLayout.height / 2) /\n 2;\n\n const labelW = 60 * scaleFactor;\n const labelH = 20 * scaleFactor;\n\n ctx.slide.addText(conn.label, {\n x: pxToIn(labelX - labelW / 2),\n y: pxToIn(labelY - labelH / 2),\n w: pxToIn(labelW),\n h: pxToIn(labelH),\n fontSize: pxToPt(10 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color:\n stripHash(conn.labelColor) ??\n stripHash(connectorStyle.labelColor) ??\n \"64748B\",\n align: \"center\",\n valign: \"middle\",\n });\n }\n }\n\n // ノードを描画\n for (const item of node.nodes) {\n const layout = layouts.get(item.id);\n if (!layout) continue;\n\n const fillColor = item.color ?? defaultColor;\n const textColor = item.textColor ?? \"FFFFFF\";\n\n // 図形を描画\n ctx.slide.addText(item.text, {\n x: pxToIn(layout.x),\n y: pxToIn(layout.y),\n w: pxToIn(layout.width),\n h: pxToIn(layout.height),\n shape: item.shape,\n fill: { color: fillColor },\n line: { color: \"333333\", width: pxToPt(1 * scaleFactor) },\n fontSize: pxToPt(14 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: textColor,\n align: \"center\",\n valign: \"middle\",\n });\n }\n}\n\nfunction calculateHorizontalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalWidth = nodeCount * nodeWidth + (nodeCount - 1) * nodeGap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: startX + index * (nodeWidth + nodeGap) + (nodeWidth - w) / 2,\n y: centerY - h / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction calculateVerticalLayout(\n node: FlowPositionedNode,\n layouts: Map<string, FlowNodeLayout>,\n nodeCount: number,\n nodeWidth: number,\n nodeHeight: number,\n nodeGap: number,\n scaleFactor: number,\n): void {\n const totalHeight = nodeCount * nodeHeight + (nodeCount - 1) * nodeGap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n node.nodes.forEach((item, index) => {\n const w = (item.width ?? nodeWidth / scaleFactor) * scaleFactor;\n const h = (item.height ?? nodeHeight / scaleFactor) * scaleFactor;\n layouts.set(item.id, {\n id: item.id,\n x: centerX - w / 2,\n y: startY + index * (nodeHeight + nodeGap) + (nodeHeight - h) / 2,\n width: w,\n height: h,\n item,\n });\n });\n}\n\nfunction drawConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n fromLayout: FlowNodeLayout,\n toLayout: FlowNodeLayout,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n let startX: number, startY: number, endX: number, endY: number;\n\n if (direction === \"horizontal\") {\n // 水平: 右端から左端へ\n startX = fromLayout.x + fromLayout.width;\n startY = fromLayout.y + fromLayout.height / 2;\n endX = toLayout.x;\n endY = toLayout.y + toLayout.height / 2;\n } else {\n // 垂直: 下端から上端へ\n startX = fromLayout.x + fromLayout.width / 2;\n startY = fromLayout.y + fromLayout.height;\n endX = toLayout.x + toLayout.width / 2;\n endY = toLayout.y;\n }\n\n // 直線接続(シンプルなケース)\n const isHorizontalLine = Math.abs(startY - endY) < 1;\n const isVerticalLine = Math.abs(startX - endX) < 1;\n\n if (isHorizontalLine || isVerticalLine) {\n // 直線で描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(Math.min(startY, endY)),\n w: pxToIn(Math.abs(endX - startX)),\n h: pxToIn(Math.abs(endY - startY)),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // L字型接続\n drawLShapedConnection(\n ctx,\n direction,\n startX,\n startY,\n endX,\n endY,\n lineColor,\n lineWidth,\n arrowType,\n );\n }\n}\n\nfunction drawLShapedConnection(\n ctx: RenderContext,\n direction: \"horizontal\" | \"vertical\",\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n lineColor: string,\n lineWidth: number,\n arrowType: \"none\" | \"arrow\" | \"diamond\" | \"oval\" | \"stealth\" | \"triangle\",\n): void {\n const midX = (startX + endX) / 2;\n const midY = (startY + endY) / 2;\n\n if (direction === \"horizontal\") {\n // 水平→垂直→水平\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: pxToIn(midX - startX),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(Math.min(startY, endY)),\n w: 0,\n h: pxToIn(Math.abs(endY - startY)),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(midX),\n y: pxToIn(endY),\n w: pxToIn(endX - midX),\n h: 0,\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n } else {\n // 垂直→水平→垂直\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(startY),\n w: 0,\n h: pxToIn(midY - startY),\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(Math.min(startX, endX)),\n y: pxToIn(midY),\n w: pxToIn(Math.abs(endX - startX)),\n h: 0,\n line: { color: lineColor, width: pxToPt(lineWidth) },\n });\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(endX),\n y: pxToIn(midY),\n w: 0,\n h: pxToIn(endY - midY),\n line: {\n color: lineColor,\n width: pxToPt(lineWidth),\n endArrowType: arrowType,\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -16,7 +16,8 @@ function renderIconNode(node, ctx) {
|
|
|
16
16
|
color: colorValue,
|
|
17
17
|
width: 1.5
|
|
18
18
|
},
|
|
19
|
-
rectRadius: isCircle ? void 0 : .1
|
|
19
|
+
rectRadius: isCircle ? void 0 : .1,
|
|
20
|
+
rotate: node.rotate
|
|
20
21
|
};
|
|
21
22
|
ctx.slide.addShape(shapeType, shapeOptions);
|
|
22
23
|
}
|
|
@@ -25,7 +26,8 @@ function renderIconNode(node, ctx) {
|
|
|
25
26
|
x: pxToIn(node.iconX ?? node.x),
|
|
26
27
|
y: pxToIn(node.iconY ?? node.y),
|
|
27
28
|
w: pxToIn(node.iconW ?? node.w),
|
|
28
|
-
h: pxToIn(node.iconH ?? node.h)
|
|
29
|
+
h: pxToIn(node.iconH ?? node.h),
|
|
30
|
+
rotate: node.rotate
|
|
29
31
|
});
|
|
30
32
|
}
|
|
31
33
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn } from \"../units.ts\";\n\ntype IconPositionedNode = Extract<PositionedNode, { type: \"icon\" }>;\n\nexport function renderIconNode(\n node: IconPositionedNode,\n ctx: RenderContext,\n): void {\n // variant 指定時は背景図形を描画\n if (node.variant) {\n const isCircle = node.variant.startsWith(\"circle\");\n const isFilled = node.variant.endsWith(\"-filled\");\n const bgColor = node.bgColor ?? \"#E0E0E0\";\n const colorValue = bgColor.replace(/^#/, \"\");\n\n const shapeType = isCircle ? \"ellipse\" : \"roundRect\";\n const shapeOptions: Record<string, unknown> = {\n x: pxToIn(node.bgX ?? node.x),\n y: pxToIn(node.bgY ?? node.y),\n w: pxToIn(node.bgW ?? node.w),\n h: pxToIn(node.bgH ?? node.h),\n fill: isFilled ? { color: colorValue } : { type: \"none\" as const },\n line: isFilled ? undefined : { color: colorValue, width: 1.5 },\n rectRadius: isCircle ? undefined : 0.1,\n };\n\n ctx.slide.addShape(shapeType, shapeOptions);\n }\n\n ctx.slide.addImage({\n data: node.iconImageData,\n x: pxToIn(node.iconX ?? node.x),\n y: pxToIn(node.iconY ?? node.y),\n w: pxToIn(node.iconW ?? node.w),\n h: pxToIn(node.iconH ?? node.h),\n });\n}\n"],"mappings":";;AAMA,SAAgB,eACd,MACA,KACM;CAEN,IAAI,KAAK,SAAS;EAChB,MAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;EACjD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS;EAEhD,MAAM,cADU,KAAK,WAAW,UAAA,CACL,QAAQ,MAAM,EAAE;EAE3C,MAAM,YAAY,WAAW,YAAY;EACzC,MAAM,eAAwC;GAC5C,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,MAAM,WAAW,EAAE,OAAO,WAAW,IAAI,EAAE,MAAM,OAAgB;GACjE,MAAM,WAAW,KAAA,IAAY;IAAE,OAAO;IAAY,OAAO;GAAI;GAC7D,YAAY,WAAW,KAAA,IAAY;
|
|
1
|
+
{"version":3,"file":"icon.js","names":[],"sources":["../../../src/renderPptx/nodes/icon.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn } from \"../units.ts\";\n\ntype IconPositionedNode = Extract<PositionedNode, { type: \"icon\" }>;\n\nexport function renderIconNode(\n node: IconPositionedNode,\n ctx: RenderContext,\n): void {\n // variant 指定時は背景図形を描画\n if (node.variant) {\n const isCircle = node.variant.startsWith(\"circle\");\n const isFilled = node.variant.endsWith(\"-filled\");\n const bgColor = node.bgColor ?? \"#E0E0E0\";\n const colorValue = bgColor.replace(/^#/, \"\");\n\n const shapeType = isCircle ? \"ellipse\" : \"roundRect\";\n const shapeOptions: Record<string, unknown> = {\n x: pxToIn(node.bgX ?? node.x),\n y: pxToIn(node.bgY ?? node.y),\n w: pxToIn(node.bgW ?? node.w),\n h: pxToIn(node.bgH ?? node.h),\n fill: isFilled ? { color: colorValue } : { type: \"none\" as const },\n line: isFilled ? undefined : { color: colorValue, width: 1.5 },\n rectRadius: isCircle ? undefined : 0.1,\n rotate: node.rotate,\n };\n\n ctx.slide.addShape(shapeType, shapeOptions);\n }\n\n ctx.slide.addImage({\n data: node.iconImageData,\n x: pxToIn(node.iconX ?? node.x),\n y: pxToIn(node.iconY ?? node.y),\n w: pxToIn(node.iconW ?? node.w),\n h: pxToIn(node.iconH ?? node.h),\n rotate: node.rotate,\n });\n}\n"],"mappings":";;AAMA,SAAgB,eACd,MACA,KACM;CAEN,IAAI,KAAK,SAAS;EAChB,MAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;EACjD,MAAM,WAAW,KAAK,QAAQ,SAAS,SAAS;EAEhD,MAAM,cADU,KAAK,WAAW,UAAA,CACL,QAAQ,MAAM,EAAE;EAE3C,MAAM,YAAY,WAAW,YAAY;EACzC,MAAM,eAAwC;GAC5C,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;GAC5B,MAAM,WAAW,EAAE,OAAO,WAAW,IAAI,EAAE,MAAM,OAAgB;GACjE,MAAM,WAAW,KAAA,IAAY;IAAE,OAAO;IAAY,OAAO;GAAI;GAC7D,YAAY,WAAW,KAAA,IAAY;GACnC,QAAQ,KAAK;EACf;EAEA,IAAI,MAAM,SAAS,WAAW,YAAY;CAC5C;CAEA,IAAI,MAAM,SAAS;EACjB,MAAM,KAAK;EACX,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;EAC9B,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;EAC9B,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;EAC9B,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;EAC9B,QAAQ,KAAK;CACf,CAAC;AACH"}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import { pxToIn } from "../units.js";
|
|
1
|
+
import { pxToIn, rectPxToIn } from "../units.js";
|
|
2
2
|
import { getContentArea } from "../utils/contentArea.js";
|
|
3
|
+
import { convertShadow } from "../utils/visualStyle.js";
|
|
3
4
|
//#region src/renderPptx/nodes/image.ts
|
|
4
5
|
function renderImageNode(node, ctx) {
|
|
5
6
|
const content = getContentArea(node);
|
|
6
7
|
const imageOptions = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
h: pxToIn(content.h),
|
|
11
|
-
shadow: node.shadow ? {
|
|
12
|
-
type: node.shadow.type ?? "outer",
|
|
13
|
-
opacity: node.shadow.opacity,
|
|
14
|
-
blur: node.shadow.blur,
|
|
15
|
-
angle: node.shadow.angle,
|
|
16
|
-
offset: node.shadow.offset,
|
|
17
|
-
color: node.shadow.color
|
|
18
|
-
} : void 0
|
|
8
|
+
...rectPxToIn(content),
|
|
9
|
+
shadow: convertShadow(node.shadow),
|
|
10
|
+
rotate: node.rotate
|
|
19
11
|
};
|
|
20
12
|
if (node.sizing) imageOptions.sizing = {
|
|
21
13
|
type: node.sizing.type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","names":[],"sources":["../../../src/renderPptx/nodes/image.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\n\ntype ImagePositionedNode = Extract<PositionedNode, { type: \"image\" }>;\n\nexport function renderImageNode(\n node: ImagePositionedNode,\n ctx: RenderContext,\n): void {\n const content = getContentArea(node);\n const imageOptions: Record<string, unknown> = {\n
|
|
1
|
+
{"version":3,"file":"image.js","names":[],"sources":["../../../src/renderPptx/nodes/image.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn, rectPxToIn } from \"../units.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\nimport { convertShadow } from \"../utils/visualStyle.ts\";\n\ntype ImagePositionedNode = Extract<PositionedNode, { type: \"image\" }>;\n\nexport function renderImageNode(\n node: ImagePositionedNode,\n ctx: RenderContext,\n): void {\n const content = getContentArea(node);\n const imageOptions: Record<string, unknown> = {\n ...rectPxToIn(content),\n shadow: convertShadow(node.shadow),\n rotate: node.rotate,\n };\n\n if (node.sizing) {\n imageOptions.sizing = {\n type: node.sizing.type,\n w: pxToIn(node.sizing.w ?? content.w),\n h: pxToIn(node.sizing.h ?? content.h),\n ...(node.sizing.x !== undefined && { x: pxToIn(node.sizing.x) }),\n ...(node.sizing.y !== undefined && { y: pxToIn(node.sizing.y) }),\n };\n }\n\n if (node.imageData) {\n // Base64 データがある場合は data プロパティを使用(リモート画像)\n ctx.slide.addImage({ ...imageOptions, data: node.imageData });\n } else {\n // ローカルパスの場合は path プロパティを使用\n ctx.slide.addImage({ ...imageOptions, path: node.src });\n }\n}\n"],"mappings":";;;;AAQA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,UAAU,eAAe,IAAI;CACnC,MAAM,eAAwC;EAC5C,GAAG,WAAW,OAAO;EACrB,QAAQ,cAAc,KAAK,MAAM;EACjC,QAAQ,KAAK;CACf;CAEA,IAAI,KAAK,QACP,aAAa,SAAS;EACpB,MAAM,KAAK,OAAO;EAClB,GAAG,OAAO,KAAK,OAAO,KAAK,QAAQ,CAAC;EACpC,GAAG,OAAO,KAAK,OAAO,KAAK,QAAQ,CAAC;EACpC,GAAI,KAAK,OAAO,MAAM,KAAA,KAAa,EAAE,GAAG,OAAO,KAAK,OAAO,CAAC,EAAE;EAC9D,GAAI,KAAK,OAAO,MAAM,KAAA,KAAa,EAAE,GAAG,OAAO,KAAK,OAAO,CAAC,EAAE;CAChE;CAGF,IAAI,KAAK,WAEP,IAAI,MAAM,SAAS;EAAE,GAAG;EAAc,MAAM,KAAK;CAAU,CAAC;MAG5D,IAAI,MAAM,SAAS;EAAE,GAAG;EAAc,MAAM,KAAK;CAAI,CAAC;AAE1D"}
|
|
@@ -1,39 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { addStraightLine } from "../utils/straightLine.js";
|
|
2
2
|
//#region src/renderPptx/nodes/line.ts
|
|
3
|
-
/**
|
|
4
|
-
* boolean | LineArrowOptions から pptxgenjs の arrow type を取得
|
|
5
|
-
*/
|
|
6
|
-
function resolveArrowType(arrow) {
|
|
7
|
-
if (arrow === void 0) return;
|
|
8
|
-
if (arrow === false) return "none";
|
|
9
|
-
if (arrow === true) return "triangle";
|
|
10
|
-
return arrow.type ?? "triangle";
|
|
11
|
-
}
|
|
12
3
|
function renderLineNode(node, ctx) {
|
|
13
|
-
const { x1, y1, x2, y2
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
21
|
-
x: pxToIn(minX),
|
|
22
|
-
y: pxToIn(minY),
|
|
23
|
-
w: pxToIn(lineW),
|
|
24
|
-
h: pxToIn(lineH),
|
|
25
|
-
flipH,
|
|
26
|
-
flipV,
|
|
27
|
-
line: {
|
|
28
|
-
color: color ?? "000000",
|
|
29
|
-
width: lineWidth !== void 0 ? pxToPt(lineWidth) : 1,
|
|
30
|
-
dashType,
|
|
31
|
-
beginArrowType: resolveArrowType(beginArrow),
|
|
32
|
-
endArrowType: resolveArrowType(endArrow)
|
|
33
|
-
}
|
|
34
|
-
});
|
|
4
|
+
const { x1, y1, x2, y2 } = node;
|
|
5
|
+
addStraightLine(ctx, {
|
|
6
|
+
x1,
|
|
7
|
+
y1,
|
|
8
|
+
x2,
|
|
9
|
+
y2
|
|
10
|
+
}, node);
|
|
35
11
|
}
|
|
36
12
|
//#endregion
|
|
37
|
-
export { renderLineNode
|
|
13
|
+
export { renderLineNode };
|
|
38
14
|
|
|
39
15
|
//# sourceMappingURL=line.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.js","names":[],"sources":["../../../src/renderPptx/nodes/line.ts"],"sourcesContent":["import type { PositionedNode
|
|
1
|
+
{"version":3,"file":"line.js","names":[],"sources":["../../../src/renderPptx/nodes/line.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { addStraightLine } from \"../utils/straightLine.ts\";\n\ntype LinePositionedNode = Extract<PositionedNode, { type: \"line\" }>;\n\nexport function renderLineNode(\n node: LinePositionedNode,\n ctx: RenderContext,\n): void {\n const { x1, y1, x2, y2 } = node;\n addStraightLine(ctx, { x1, y1, x2, y2 }, node);\n}\n"],"mappings":";;AAMA,SAAgB,eACd,MACA,KACM;CACN,MAAM,EAAE,IAAI,IAAI,IAAI,OAAO;CAC3B,gBAAgB,KAAK;EAAE;EAAI;EAAI;EAAI;CAAG,GAAG,IAAI;AAC/C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { pxToPt } from "../units.js";
|
|
2
|
+
import { getContentAreaIn } from "../utils/contentArea.js";
|
|
3
3
|
import { convertStrike, convertUnderline } from "../textOptions.js";
|
|
4
4
|
//#region src/renderPptx/nodes/list.ts
|
|
5
5
|
function resolveStyle(li, parent) {
|
|
@@ -68,14 +68,11 @@ function renderUlNode(node, ctx) {
|
|
|
68
68
|
const fontSizePx = node.fontSize ?? 24;
|
|
69
69
|
const fontFamily = node.fontFamily ?? "Noto Sans JP";
|
|
70
70
|
const lineHeight = node.lineHeight ?? 1.3;
|
|
71
|
-
const
|
|
71
|
+
const contentIn = getContentAreaIn(node);
|
|
72
72
|
if (hasItemStyleOverride(node.items)) {
|
|
73
73
|
const textItems = buildListTextItems(node.items, node, true);
|
|
74
74
|
ctx.slide.addText(textItems, {
|
|
75
|
-
|
|
76
|
-
y: pxToIn(content.y),
|
|
77
|
-
w: pxToIn(content.w),
|
|
78
|
-
h: pxToIn(content.h),
|
|
75
|
+
...contentIn,
|
|
79
76
|
align: node.textAlign ?? "left",
|
|
80
77
|
valign: "top",
|
|
81
78
|
margin: 0,
|
|
@@ -84,10 +81,7 @@ function renderUlNode(node, ctx) {
|
|
|
84
81
|
} else {
|
|
85
82
|
const text = node.items.map((li) => li.text).join("\n");
|
|
86
83
|
ctx.slide.addText(text, {
|
|
87
|
-
|
|
88
|
-
y: pxToIn(content.y),
|
|
89
|
-
w: pxToIn(content.w),
|
|
90
|
-
h: pxToIn(content.h),
|
|
84
|
+
...contentIn,
|
|
91
85
|
fontSize: pxToPt(fontSizePx),
|
|
92
86
|
fontFace: fontFamily,
|
|
93
87
|
align: node.textAlign ?? "left",
|
|
@@ -108,17 +102,14 @@ function renderOlNode(node, ctx) {
|
|
|
108
102
|
const fontSizePx = node.fontSize ?? 24;
|
|
109
103
|
const fontFamily = node.fontFamily ?? "Noto Sans JP";
|
|
110
104
|
const lineHeight = node.lineHeight ?? 1.3;
|
|
111
|
-
const
|
|
105
|
+
const contentIn = getContentAreaIn(node);
|
|
112
106
|
const bulletOptions = { type: "number" };
|
|
113
107
|
if (node.numberType !== void 0) bulletOptions.numberType = node.numberType;
|
|
114
108
|
if (node.numberStartAt !== void 0) bulletOptions.numberStartAt = node.numberStartAt;
|
|
115
109
|
if (hasItemStyleOverride(node.items)) {
|
|
116
110
|
const textItems = buildListTextItems(node.items, node, bulletOptions);
|
|
117
111
|
ctx.slide.addText(textItems, {
|
|
118
|
-
|
|
119
|
-
y: pxToIn(content.y),
|
|
120
|
-
w: pxToIn(content.w),
|
|
121
|
-
h: pxToIn(content.h),
|
|
112
|
+
...contentIn,
|
|
122
113
|
align: node.textAlign ?? "left",
|
|
123
114
|
valign: "top",
|
|
124
115
|
margin: 0,
|
|
@@ -127,10 +118,7 @@ function renderOlNode(node, ctx) {
|
|
|
127
118
|
} else {
|
|
128
119
|
const text = node.items.map((li) => li.text).join("\n");
|
|
129
120
|
ctx.slide.addText(text, {
|
|
130
|
-
|
|
131
|
-
y: pxToIn(content.y),
|
|
132
|
-
w: pxToIn(content.w),
|
|
133
|
-
h: pxToIn(content.h),
|
|
121
|
+
...contentIn,
|
|
134
122
|
fontSize: pxToPt(fontSizePx),
|
|
135
123
|
fontFace: fontFamily,
|
|
136
124
|
align: node.textAlign ?? "left",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","names":[],"sources":["../../../src/renderPptx/nodes/list.ts"],"sourcesContent":["import type { PositionedNode, LiNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"list.js","names":[],"sources":["../../../src/renderPptx/nodes/list.ts"],"sourcesContent":["import type { PositionedNode, LiNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToPt } from \"../units.ts\";\nimport { convertUnderline, convertStrike } from \"../textOptions.ts\";\nimport { getContentAreaIn } from \"../utils/contentArea.ts\";\n\ntype UlPositionedNode = Extract<PositionedNode, { type: \"ul\" }>;\ntype OlPositionedNode = Extract<PositionedNode, { type: \"ol\" }>;\n\nfunction resolveStyle(li: LiNode, parent: UlPositionedNode | OlPositionedNode) {\n return {\n fontSize: li.fontSize ?? parent.fontSize ?? 24,\n color: li.color ?? parent.color,\n bold: li.bold ?? parent.bold,\n italic: li.italic ?? parent.italic,\n underline: li.underline ?? parent.underline,\n strike: li.strike ?? parent.strike,\n highlight: li.highlight ?? parent.highlight,\n fontFamily: li.fontFamily ?? parent.fontFamily ?? \"Noto Sans JP\",\n };\n}\n\nfunction buildListTextItems(\n items: LiNode[],\n parent: UlPositionedNode | OlPositionedNode,\n bullet: boolean | Record<string, unknown>,\n) {\n const textItems: { text: string; options: Record<string, unknown> }[] = [];\n for (let i = 0; i < items.length; i++) {\n const li = items[i];\n const style = resolveStyle(li, parent);\n const isLast = i === items.length - 1;\n const baseOptions = {\n fontSize: pxToPt(style.fontSize),\n fontFace: style.fontFamily,\n color: style.color,\n underline: convertUnderline(style.underline),\n strike: convertStrike(style.strike),\n highlight: style.highlight,\n };\n\n if (li.runs && li.runs.length > 0) {\n for (let j = 0; j < li.runs.length; j++) {\n const run = li.runs[j];\n const isLastRun = j === li.runs.length - 1;\n let text = run.text;\n if (isLastRun && !isLast) text += \"\\n\";\n textItems.push({\n text,\n options: {\n ...baseOptions,\n fontFace: run.fontFamily ?? style.fontFamily,\n color: run.color ?? style.color,\n bold: run.bold ?? style.bold,\n italic: run.italic ?? style.italic,\n underline: convertUnderline(run.underline ?? style.underline),\n strike: convertStrike(run.strike ?? style.strike),\n highlight: run.highlight ?? style.highlight,\n bullet: j === 0 ? bullet : false,\n ...(run.href ? { hyperlink: { url: run.href } } : {}),\n },\n });\n }\n } else {\n textItems.push({\n text: isLast ? li.text : li.text + \"\\n\",\n options: {\n ...baseOptions,\n bold: style.bold,\n italic: style.italic,\n bullet,\n },\n });\n }\n }\n return textItems;\n}\n\nfunction hasItemStyleOverride(items: LiNode[]): boolean {\n return items.some(\n (li) =>\n li.fontSize !== undefined ||\n li.color !== undefined ||\n li.bold !== undefined ||\n li.italic !== undefined ||\n li.underline !== undefined ||\n li.strike !== undefined ||\n li.highlight !== undefined ||\n li.fontFamily !== undefined ||\n li.runs !== undefined,\n );\n}\n\nexport function renderUlNode(node: UlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const lineHeight = node.lineHeight ?? 1.3;\n const contentIn = getContentAreaIn(node);\n\n if (hasItemStyleOverride(node.items)) {\n // Li に個別スタイルがある場合は配列形式を使用\n const textItems = buildListTextItems(node.items, node, true);\n\n ctx.slide.addText(textItems, {\n ...contentIn,\n align: node.textAlign ?? \"left\",\n valign: \"top\" as const,\n margin: 0,\n lineSpacingMultiple: lineHeight,\n });\n } else {\n // Li にスタイルオーバーライドがない場合は単一文字列形式を使用\n const text = node.items.map((li) => li.text).join(\"\\n\");\n\n ctx.slide.addText(text, {\n ...contentIn,\n fontSize: pxToPt(fontSizePx),\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\" as const,\n margin: 0,\n lineSpacingMultiple: lineHeight,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n bullet: true,\n });\n }\n}\n\nexport function renderOlNode(node: OlPositionedNode, ctx: RenderContext): void {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const lineHeight = node.lineHeight ?? 1.3;\n const contentIn = getContentAreaIn(node);\n\n const bulletOptions: Record<string, unknown> = { type: \"number\" };\n if (node.numberType !== undefined) {\n bulletOptions.numberType = node.numberType;\n }\n if (node.numberStartAt !== undefined) {\n bulletOptions.numberStartAt = node.numberStartAt;\n }\n\n if (hasItemStyleOverride(node.items)) {\n const textItems = buildListTextItems(node.items, node, bulletOptions);\n\n ctx.slide.addText(textItems, {\n ...contentIn,\n align: node.textAlign ?? \"left\",\n valign: \"top\" as const,\n margin: 0,\n lineSpacingMultiple: lineHeight,\n });\n } else {\n const text = node.items.map((li) => li.text).join(\"\\n\");\n\n ctx.slide.addText(text, {\n ...contentIn,\n fontSize: pxToPt(fontSizePx),\n fontFace: fontFamily,\n align: node.textAlign ?? \"left\",\n valign: \"top\" as const,\n margin: 0,\n lineSpacingMultiple: lineHeight,\n color: node.color,\n bold: node.bold,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n bullet: bulletOptions,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pxToIn, pxToPt } from "../units.js";
|
|
2
|
-
import {
|
|
2
|
+
import { stripHash } from "../utils/visualStyle.js";
|
|
3
3
|
import { measureMatrix } from "../../calcYogaLayout/measureCompositeNodes.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
5
5
|
//#region src/renderPptx/nodes/matrix.ts
|
|
6
6
|
function renderMatrixNode(node, ctx) {
|
|
7
7
|
const items = node.items;
|
|
@@ -11,9 +11,9 @@ function renderMatrixNode(node, ctx) {
|
|
|
11
11
|
const baseItemSize = 24;
|
|
12
12
|
const baseLineWidth = 2;
|
|
13
13
|
const axisColor = "E2E8F0";
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
14
|
+
const axisLabelColor = stripHash(node.axisLabelColor) ?? "64748B";
|
|
15
|
+
const itemLabelColor = stripHash(node.itemLabelColor) ?? "1E293B";
|
|
16
|
+
const { content, scaleFactor } = resolveScaledContentArea(node, measureMatrix(node), ctx);
|
|
17
17
|
const itemSize = baseItemSize * scaleFactor;
|
|
18
18
|
const lineWidth = baseLineWidth * scaleFactor;
|
|
19
19
|
const axisMargin = 60 * scaleFactor;
|
|
@@ -52,7 +52,7 @@ function renderMatrixNode(node, ctx) {
|
|
|
52
52
|
h: pxToIn(axisLabelH),
|
|
53
53
|
fontSize: pxToPt(12 * scaleFactor),
|
|
54
54
|
fontFace: "Noto Sans JP",
|
|
55
|
-
color:
|
|
55
|
+
color: axisLabelColor,
|
|
56
56
|
align: "center",
|
|
57
57
|
valign: "top"
|
|
58
58
|
});
|
|
@@ -65,12 +65,12 @@ function renderMatrixNode(node, ctx) {
|
|
|
65
65
|
h: pxToIn(yLabelH),
|
|
66
66
|
fontSize: pxToPt(12 * scaleFactor),
|
|
67
67
|
fontFace: "Noto Sans JP",
|
|
68
|
-
color:
|
|
68
|
+
color: axisLabelColor,
|
|
69
69
|
align: "center",
|
|
70
70
|
valign: "middle",
|
|
71
71
|
rotate: 270
|
|
72
72
|
});
|
|
73
|
-
if (quadrants) renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY, scaleFactor);
|
|
73
|
+
if (quadrants) renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY, scaleFactor, stripHash(node.quadrantLabelColor) ?? "94A3B8");
|
|
74
74
|
const itemLabelW = 100 * scaleFactor;
|
|
75
75
|
const itemLabelH = 18 * scaleFactor;
|
|
76
76
|
for (const item of items) {
|
|
@@ -92,16 +92,15 @@ function renderMatrixNode(node, ctx) {
|
|
|
92
92
|
h: pxToIn(itemLabelH),
|
|
93
93
|
fontSize: pxToPt(11 * scaleFactor),
|
|
94
94
|
fontFace: "Noto Sans JP",
|
|
95
|
-
color:
|
|
95
|
+
color: stripHash(item.textColor) ?? itemLabelColor,
|
|
96
96
|
bold: true,
|
|
97
97
|
align: "center",
|
|
98
98
|
valign: "bottom"
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
function renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY, scaleFactor) {
|
|
102
|
+
function renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY, scaleFactor, quadrantColor) {
|
|
103
103
|
const quadrantFontSize = 11 * scaleFactor;
|
|
104
|
-
const quadrantColor = "94A3B8";
|
|
105
104
|
const quadrantInset = 10 * scaleFactor;
|
|
106
105
|
const quadrantW = areaW / 2 - 20 * scaleFactor;
|
|
107
106
|
const quadrantH = 48 * scaleFactor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix.js","names":[],"sources":["../../../src/renderPptx/nodes/matrix.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"matrix.js","names":[],"sources":["../../../src/renderPptx/nodes/matrix.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { stripHash } from \"../utils/visualStyle.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { measureMatrix } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\n\ntype MatrixPositionedNode = Extract<PositionedNode, { type: \"matrix\" }>;\n\nexport function renderMatrixNode(\n node: MatrixPositionedNode,\n ctx: RenderContext,\n): void {\n const items = node.items;\n const axes = node.axes;\n const quadrants = node.quadrants;\n\n const defaultItemColor = \"1D4ED8\"; // blue\n const baseItemSize = 24; // px\n const baseLineWidth = 2; // px\n const axisColor = \"E2E8F0\";\n const axisLabelColor = stripHash(node.axisLabelColor) ?? \"64748B\";\n const itemLabelColor = stripHash(node.itemLabelColor) ?? \"1E293B\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureMatrix(node),\n ctx,\n );\n\n const itemSize = baseItemSize * scaleFactor;\n const lineWidth = baseLineWidth * scaleFactor;\n\n // マトリクスの描画領域(軸ラベル用の余白を考慮)\n const axisMargin = 60 * scaleFactor; // 軸ラベル用の余白\n const areaX = content.x + axisMargin;\n const areaY = content.y + axisMargin;\n const areaW = content.w - axisMargin * 2;\n const areaH = content.h - axisMargin * 2;\n\n // 中心座標\n const centerX = areaX + areaW / 2;\n const centerY = areaY + areaH / 2;\n\n // === 1. 十字線(軸線)を描画 ===\n // 横線(X軸)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(areaX),\n y: pxToIn(centerY),\n w: pxToIn(areaW),\n h: 0,\n line: { color: axisColor, width: pxToPt(lineWidth) },\n });\n\n // 縦線(Y軸)\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(centerX),\n y: pxToIn(areaY),\n w: 0,\n h: pxToIn(areaH),\n line: { color: axisColor, width: pxToPt(lineWidth) },\n });\n\n // === 2. 軸ラベルを描画 ===\n const axisLabelW = 120 * scaleFactor;\n const axisLabelH = 24 * scaleFactor;\n\n // X軸ラベル(下部中央)\n ctx.slide.addText(axes.x, {\n x: pxToIn(centerX - axisLabelW / 2),\n y: pxToIn(areaY + areaH + 8 * scaleFactor),\n w: pxToIn(axisLabelW),\n h: pxToIn(axisLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: axisLabelColor,\n align: \"center\",\n valign: \"top\",\n });\n\n // Y軸ラベル(左部中央)270° 回転で下から上読み。w が視覚的な高さになるため CJK 5 文字以上も収まる幅を確保\n const yLabelW = 100 * scaleFactor;\n const yLabelH = 20 * scaleFactor;\n ctx.slide.addText(axes.y, {\n x: pxToIn(content.x + axisMargin / 2 - yLabelW / 2),\n y: pxToIn(centerY - yLabelH / 2),\n w: pxToIn(yLabelW),\n h: pxToIn(yLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: axisLabelColor,\n align: \"center\",\n valign: \"middle\",\n rotate: 270,\n });\n\n // === 3. 象限ラベルを描画 ===\n if (quadrants) {\n renderQuadrantLabels(\n ctx,\n quadrants,\n areaX,\n areaY,\n areaW,\n areaH,\n centerX,\n centerY,\n scaleFactor,\n stripHash(node.quadrantLabelColor) ?? \"94A3B8\",\n );\n }\n\n // === 4. アイテムをプロット ===\n const itemLabelW = 100 * scaleFactor;\n const itemLabelH = 18 * scaleFactor;\n\n for (const item of items) {\n // 座標変換: (0,0)=左下, (1,1)=右上\n // x: 0 -> areaX, 1 -> areaX + areaW\n // y: 0 -> areaY + areaH, 1 -> areaY (反転)\n const itemX = areaX + item.x * areaW;\n const itemY = areaY + (1 - item.y) * areaH; // Y軸反転\n const itemColor = item.color ?? defaultItemColor;\n\n // 円を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {\n x: pxToIn(itemX - itemSize / 2),\n y: pxToIn(itemY - itemSize / 2),\n w: pxToIn(itemSize),\n h: pxToIn(itemSize),\n fill: { color: itemColor },\n line: { type: \"none\" as const },\n });\n\n // ラベルを描画(円の上)\n ctx.slide.addText(item.label, {\n x: pxToIn(itemX - itemLabelW / 2),\n y: pxToIn(itemY - itemSize / 2 - 20 * scaleFactor),\n w: pxToIn(itemLabelW),\n h: pxToIn(itemLabelH),\n fontSize: pxToPt(11 * scaleFactor),\n fontFace: \"Noto Sans JP\",\n color: stripHash(item.textColor) ?? itemLabelColor,\n bold: true,\n align: \"center\",\n valign: \"bottom\",\n });\n }\n}\n\nfunction renderQuadrantLabels(\n ctx: RenderContext,\n quadrants: NonNullable<MatrixPositionedNode[\"quadrants\"]>,\n areaX: number,\n areaY: number,\n areaW: number,\n areaH: number,\n centerX: number,\n centerY: number,\n scaleFactor: number,\n quadrantColor: string,\n): void {\n const quadrantFontSize = 11 * scaleFactor;\n const quadrantInset = 10 * scaleFactor;\n const quadrantW = areaW / 2 - 20 * scaleFactor;\n const quadrantH = 48 * scaleFactor;\n\n // 左上\n ctx.slide.addText(quadrants.topLeft, {\n x: pxToIn(areaX + quadrantInset),\n y: pxToIn(areaY + quadrantInset),\n w: pxToIn(quadrantW),\n h: pxToIn(quadrantH),\n fontSize: pxToPt(quadrantFontSize),\n fontFace: \"Noto Sans JP\",\n color: quadrantColor,\n align: \"left\",\n valign: \"top\",\n });\n\n // 右上\n ctx.slide.addText(quadrants.topRight, {\n x: pxToIn(centerX + quadrantInset),\n y: pxToIn(areaY + quadrantInset),\n w: pxToIn(quadrantW),\n h: pxToIn(quadrantH),\n fontSize: pxToPt(quadrantFontSize),\n fontFace: \"Noto Sans JP\",\n color: quadrantColor,\n align: \"right\",\n valign: \"top\",\n });\n\n // 左下\n ctx.slide.addText(quadrants.bottomLeft, {\n x: pxToIn(areaX + quadrantInset),\n y: pxToIn(centerY + areaH / 2 - quadrantH - quadrantInset),\n w: pxToIn(quadrantW),\n h: pxToIn(quadrantH),\n fontSize: pxToPt(quadrantFontSize),\n fontFace: \"Noto Sans JP\",\n color: quadrantColor,\n align: \"left\",\n valign: \"bottom\",\n });\n\n // 右下\n ctx.slide.addText(quadrants.bottomRight, {\n x: pxToIn(centerX + quadrantInset),\n y: pxToIn(centerY + areaH / 2 - quadrantH - quadrantInset),\n w: pxToIn(quadrantW),\n h: pxToIn(quadrantH),\n fontSize: pxToPt(quadrantFontSize),\n fontFace: \"Noto Sans JP\",\n color: quadrantColor,\n align: \"right\",\n valign: \"bottom\",\n });\n}\n"],"mappings":"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"}
|