@hirokisakabe/pom 8.2.1 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -25
- 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/buildContext.js +3 -1
- package/dist/buildContext.js.map +1 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +5 -1
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +18 -28
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/calcYogaLayout/fontLoader.js.map +1 -1
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +9 -2
- package/dist/calcYogaLayout/measureText.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/icons/renderIcon.js.map +1 -1
- package/dist/parseMasterPptx.js.map +1 -1
- package/dist/parseXml/coercionRules.js +48 -9
- 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 -209
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.d.ts.map +1 -1
- package/dist/parseXml/serializeXml.js +13 -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 +5 -3
- 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/gradientFills.js +139 -0
- package/dist/renderPptx/gradientFills.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 +22 -15
- 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 +18 -30
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/textOptions.js +34 -9
- 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 +107 -59
- 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/gradient.js +103 -0
- package/dist/shared/gradient.js.map +1 -0
- package/dist/shared/measureImage.js.map +1 -1
- package/dist/shared/tableUtils.js.map +1 -1
- 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 +1166 -93
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +54 -18
- package/dist/types.js.map +1 -1
- package/package.json +10 -9
|
@@ -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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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { pxToIn, pxToPt } from "../units.js";
|
|
2
|
-
import {
|
|
2
|
+
import { withContentBounds } from "../utils/contentArea.js";
|
|
3
3
|
import { convertStrike, convertUnderline } from "../textOptions.js";
|
|
4
|
+
import { stripHash } from "../utils/visualStyle.js";
|
|
4
5
|
import { ARROW_DEPTH_RATIO } from "../../shared/processArrowConstants.js";
|
|
5
6
|
import { measureProcessArrow } from "../../calcYogaLayout/measureCompositeNodes.js";
|
|
6
|
-
import {
|
|
7
|
+
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
7
8
|
//#region src/renderPptx/nodes/processArrow.ts
|
|
8
9
|
function renderProcessArrowNode(node, ctx) {
|
|
9
10
|
const direction = node.direction ?? "horizontal";
|
|
@@ -16,20 +17,12 @@ function renderProcessArrowNode(node, ctx) {
|
|
|
16
17
|
const itemHeight = node.itemHeight ?? 80;
|
|
17
18
|
const arrowDepth = itemHeight * ARROW_DEPTH_RATIO;
|
|
18
19
|
const gap = node.gap ?? -arrowDepth;
|
|
19
|
-
const content =
|
|
20
|
-
const intrinsic = measureProcessArrow(node);
|
|
21
|
-
const scaleFactor = calcScaleFactor(content.w, content.h, intrinsic.width, intrinsic.height, "processArrow", ctx.buildContext.diagnostics);
|
|
20
|
+
const { content, scaleFactor } = resolveScaledContentArea(node, measureProcessArrow(node), ctx);
|
|
22
21
|
const scaledItemWidth = itemWidth * scaleFactor;
|
|
23
22
|
const scaledItemHeight = itemHeight * scaleFactor;
|
|
24
23
|
const scaledGap = gap * scaleFactor;
|
|
25
24
|
const scaledArrowDepth = arrowDepth * scaleFactor;
|
|
26
|
-
const contentNode =
|
|
27
|
-
...node,
|
|
28
|
-
x: content.x,
|
|
29
|
-
y: content.y,
|
|
30
|
-
w: content.w,
|
|
31
|
-
h: content.h
|
|
32
|
-
};
|
|
25
|
+
const contentNode = withContentBounds(node, content);
|
|
33
26
|
if (direction === "horizontal") renderHorizontalProcessArrow(contentNode, ctx, steps, stepCount, scaledItemWidth, scaledItemHeight, scaledGap, scaledArrowDepth, defaultColor, defaultTextColor, scaleFactor);
|
|
34
27
|
else renderVerticalProcessArrow(contentNode, ctx, steps, stepCount, scaledItemWidth, scaledItemHeight, scaledGap, scaledArrowDepth, defaultColor, defaultTextColor, scaleFactor);
|
|
35
28
|
}
|
|
@@ -40,8 +33,8 @@ function renderHorizontalProcessArrow(node, ctx, steps, stepCount, itemWidth, it
|
|
|
40
33
|
steps.forEach((step, index) => {
|
|
41
34
|
const stepX = startX + index * (itemWidth + gap);
|
|
42
35
|
const stepY = centerY - itemHeight / 2;
|
|
43
|
-
const fillColor = step.color
|
|
44
|
-
const textColor = step.textColor
|
|
36
|
+
const fillColor = stripHash(step.color) ?? defaultColor;
|
|
37
|
+
const textColor = stripHash(step.textColor) ?? defaultTextColor;
|
|
45
38
|
const isFirst = index === 0;
|
|
46
39
|
const points = isFirst ? [
|
|
47
40
|
{
|
|
@@ -128,8 +121,8 @@ function renderVerticalProcessArrow(node, ctx, steps, stepCount, itemWidth, item
|
|
|
128
121
|
steps.forEach((step, index) => {
|
|
129
122
|
const stepX = centerX - itemWidth / 2;
|
|
130
123
|
const stepY = startY + index * (itemHeight + gap);
|
|
131
|
-
const fillColor = step.color
|
|
132
|
-
const textColor = step.textColor
|
|
124
|
+
const fillColor = stripHash(step.color) ?? defaultColor;
|
|
125
|
+
const textColor = stripHash(step.textColor) ?? defaultTextColor;
|
|
133
126
|
const isFirst = index === 0;
|
|
134
127
|
const points = isFirst ? [
|
|
135
128
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processArrow.js","names":[],"sources":["../../../src/renderPptx/nodes/processArrow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { convertUnderline, convertStrike } from \"../textOptions.ts\";\nimport { measureProcessArrow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { calcScaleFactor } from \"../utils/scaleToFit.ts\";\nimport {\n ARROW_DEPTH_RATIO,\n DEFAULT_PROCESS_ARROW_ITEM_WIDTH,\n DEFAULT_PROCESS_ARROW_ITEM_HEIGHT,\n} from \"../../shared/processArrowConstants.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\n\ntype ProcessArrowPositionedNode = Extract<\n PositionedNode,\n { type: \"processArrow\" }\n>;\n\nexport function renderProcessArrowNode(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const steps = node.steps;\n const stepCount = steps.length;\n\n if (stepCount === 0) return;\n\n const defaultColor = \"4472C4\"; // PowerPoint標準の青\n const defaultTextColor = \"FFFFFF\";\n const itemWidth = node.itemWidth ?? DEFAULT_PROCESS_ARROW_ITEM_WIDTH;\n const itemHeight = node.itemHeight ?? DEFAULT_PROCESS_ARROW_ITEM_HEIGHT;\n const arrowDepth = itemHeight * ARROW_DEPTH_RATIO;\n const gap = node.gap ?? -arrowDepth;\n\n // スケール係数を計算(コンテンツ領域基準)\n const content = getContentArea(node);\n const intrinsic = measureProcessArrow(node);\n const scaleFactor = calcScaleFactor(\n content.w,\n content.h,\n intrinsic.width,\n intrinsic.height,\n \"processArrow\",\n ctx.buildContext.diagnostics,\n );\n\n const scaledItemWidth = itemWidth * scaleFactor;\n const scaledItemHeight = itemHeight * scaleFactor;\n const scaledGap = gap * scaleFactor;\n const scaledArrowDepth = arrowDepth * scaleFactor;\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 if (direction === \"horizontal\") {\n renderHorizontalProcessArrow(\n contentNode,\n ctx,\n steps,\n stepCount,\n scaledItemWidth,\n scaledItemHeight,\n scaledGap,\n scaledArrowDepth,\n defaultColor,\n defaultTextColor,\n scaleFactor,\n );\n } else {\n renderVerticalProcessArrow(\n contentNode,\n ctx,\n steps,\n stepCount,\n scaledItemWidth,\n scaledItemHeight,\n scaledGap,\n scaledArrowDepth,\n defaultColor,\n defaultTextColor,\n scaleFactor,\n );\n }\n}\n\nfunction renderHorizontalProcessArrow(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n steps: ProcessArrowPositionedNode[\"steps\"],\n stepCount: number,\n itemWidth: number,\n itemHeight: number,\n gap: number,\n arrowDepth: number,\n defaultColor: string,\n defaultTextColor: string,\n scaleFactor: number,\n): void {\n const totalWidth = stepCount * itemWidth + (stepCount - 1) * gap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n steps.forEach((step, index) => {\n const stepX = startX + index * (itemWidth + gap);\n const stepY = centerY - itemHeight / 2;\n const fillColor = step.color?.replace(\"#\", \"\") ?? defaultColor;\n const textColor = step.textColor?.replace(\"#\", \"\") ?? defaultTextColor;\n\n // custGeom でシェブロン形状を描画\n const isFirst = index === 0;\n const points = isFirst\n ? [\n // homePlate 風: 左辺フラット、右辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth - arrowDepth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight / 2) },\n { x: pxToIn(itemWidth - arrowDepth), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight) },\n { close: true as const },\n ]\n : [\n // chevron 風: 左辺に切り欠き、右辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth - arrowDepth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight / 2) },\n { x: pxToIn(itemWidth - arrowDepth), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight) },\n { x: pxToIn(arrowDepth), y: pxToIn(itemHeight / 2) },\n { close: true as const },\n ];\n\n ctx.slide.addShape(\"custGeom\" as never, {\n x: pxToIn(stepX),\n y: pxToIn(stepY),\n w: pxToIn(itemWidth),\n h: pxToIn(itemHeight),\n points,\n fill: { color: fillColor },\n line: { type: \"none\" as const },\n });\n\n // テキストを図形の中央(矢印部分を除いた領域)に配置\n const textOffsetLeft = isFirst ? 0 : arrowDepth;\n const textWidth = Math.max(1, itemWidth - arrowDepth - textOffsetLeft);\n\n ctx.slide.addText(step.label, {\n x: pxToIn(stepX + textOffsetLeft),\n y: pxToIn(stepY),\n w: pxToIn(textWidth),\n h: pxToIn(itemHeight),\n fontSize: pxToPt((node.fontSize ?? 14) * scaleFactor),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n color: textColor,\n bold: node.bold ?? false,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n align: \"center\",\n valign: \"middle\",\n });\n });\n}\n\nfunction renderVerticalProcessArrow(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n steps: ProcessArrowPositionedNode[\"steps\"],\n stepCount: number,\n itemWidth: number,\n itemHeight: number,\n gap: number,\n arrowDepth: number,\n defaultColor: string,\n defaultTextColor: string,\n scaleFactor: number,\n): void {\n const totalHeight = stepCount * itemHeight + (stepCount - 1) * gap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n steps.forEach((step, index) => {\n const stepX = centerX - itemWidth / 2;\n const stepY = startY + index * (itemHeight + gap);\n const fillColor = step.color?.replace(\"#\", \"\") ?? defaultColor;\n const textColor = step.textColor?.replace(\"#\", \"\") ?? defaultTextColor;\n\n const isFirst = index === 0;\n const points = isFirst\n ? [\n // rect 風: 上辺フラット、下辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight - arrowDepth) },\n { x: pxToIn(itemWidth / 2), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight - arrowDepth) },\n { close: true as const },\n ]\n : [\n // pentagon 風: 上辺に切り欠き、下辺が矢印\n { x: pxToIn(itemWidth / 2), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(arrowDepth) },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight - arrowDepth) },\n { x: pxToIn(itemWidth / 2), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight - arrowDepth) },\n { x: 0, y: pxToIn(arrowDepth) },\n { close: true as const },\n ];\n\n ctx.slide.addShape(\"custGeom\" as never, {\n x: pxToIn(stepX),\n y: pxToIn(stepY),\n w: pxToIn(itemWidth),\n h: pxToIn(itemHeight),\n points,\n fill: { color: fillColor },\n line: { type: \"none\" as const },\n });\n\n // テキストを図形の中央(矢印部分を除いた領域)に配置\n const textOffsetTop = isFirst ? 0 : arrowDepth;\n const textHeight = Math.max(1, itemHeight - arrowDepth - textOffsetTop);\n\n ctx.slide.addText(step.label, {\n x: pxToIn(stepX),\n y: pxToIn(stepY + textOffsetTop),\n w: pxToIn(itemWidth),\n h: pxToIn(textHeight),\n fontSize: pxToPt((node.fontSize ?? 14) * scaleFactor),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n color: textColor,\n bold: node.bold ?? false,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n align: \"center\",\n valign: \"middle\",\n });\n });\n}\n"],"mappings":";;;;;;;AAkBA,SAAgB,uBACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,QAAQ,KAAK;CACnB,MAAM,YAAY,MAAM;CAExB,IAAI,cAAc,GAAG;CAErB,MAAM,eAAe;CACrB,MAAM,mBAAmB;CACzB,MAAM,YAAY,KAAK,aAAA;CACvB,MAAM,aAAa,KAAK,cAAA;CACxB,MAAM,aAAa,aAAa;CAChC,MAAM,MAAM,KAAK,OAAO,CAAC;CAGzB,MAAM,UAAU,eAAe,IAAI;CACnC,MAAM,YAAY,oBAAoB,IAAI;CAC1C,MAAM,cAAc,gBAClB,QAAQ,GACR,QAAQ,GACR,UAAU,OACV,UAAU,QACV,gBACA,IAAI,aAAa,WACnB;CAEA,MAAM,kBAAkB,YAAY;CACpC,MAAM,mBAAmB,aAAa;CACtC,MAAM,YAAY,MAAM;CACxB,MAAM,mBAAmB,aAAa;CAGtC,MAAM,cAAc;EAClB,GAAG;EACH,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;CACb;CAEA,IAAI,cAAc,cAChB,6BACE,aACA,KACA,OACA,WACA,iBACA,kBACA,WACA,kBACA,cACA,kBACA,WACF;MAEA,2BACE,aACA,KACA,OACA,WACA,iBACA,kBACA,WACA,kBACA,cACA,kBACA,WACF;AAEJ;AAEA,SAAS,6BACP,MACA,KACA,OACA,WACA,WACA,YACA,KACA,YACA,cACA,kBACA,aACM;CACN,MAAM,aAAa,YAAY,aAAa,YAAY,KAAK;CAC7D,MAAM,SAAS,KAAK,KAAK,KAAK,IAAI,cAAc;CAChD,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI;CAElC,MAAM,SAAS,MAAM,UAAU;EAC7B,MAAM,QAAQ,SAAS,SAAS,YAAY;EAC5C,MAAM,QAAQ,UAAU,aAAa;EACrC,MAAM,YAAY,KAAK,OAAO,QAAQ,KAAK,EAAE,KAAK;EAClD,MAAM,YAAY,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK;EAGtD,MAAM,UAAU,UAAU;EAC1B,MAAM,SAAS,UACX;GAEE;IAAE,GAAG;IAAG,GAAG;GAAE;GACb;IAAE,GAAG,OAAO,YAAY,UAAU;IAAG,GAAG;GAAE;GAC1C;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG,OAAO,aAAa,CAAC;GAAE;GAClD;IAAE,GAAG,OAAO,YAAY,UAAU;IAAG,GAAG,OAAO,UAAU;GAAE;GAC3D;IAAE,GAAG;IAAG,GAAG,OAAO,UAAU;GAAE;GAC9B,EAAE,OAAO,KAAc;EACzB,IACA;GAEE;IAAE,GAAG;IAAG,GAAG;GAAE;GACb;IAAE,GAAG,OAAO,YAAY,UAAU;IAAG,GAAG;GAAE;GAC1C;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG,OAAO,aAAa,CAAC;GAAE;GAClD;IAAE,GAAG,OAAO,YAAY,UAAU;IAAG,GAAG,OAAO,UAAU;GAAE;GAC3D;IAAE,GAAG;IAAG,GAAG,OAAO,UAAU;GAAE;GAC9B;IAAE,GAAG,OAAO,UAAU;IAAG,GAAG,OAAO,aAAa,CAAC;GAAE;GACnD,EAAE,OAAO,KAAc;EACzB;EAEJ,IAAI,MAAM,SAAS,YAAqB;GACtC,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,SAAS;GACnB,GAAG,OAAO,UAAU;GACpB;GACA,MAAM,EAAE,OAAO,UAAU;GACzB,MAAM,EAAE,MAAM,OAAgB;EAChC,CAAC;EAGD,MAAM,iBAAiB,UAAU,IAAI;EACrC,MAAM,YAAY,KAAK,IAAI,GAAG,YAAY,aAAa,cAAc;EAErE,IAAI,MAAM,QAAQ,KAAK,OAAO;GAC5B,GAAG,OAAO,QAAQ,cAAc;GAChC,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,SAAS;GACnB,GAAG,OAAO,UAAU;GACpB,UAAU,QAAQ,KAAK,YAAY,MAAM,WAAW;GACpD,UAAU,KAAK,cAAc;GAC7B,OAAO;GACP,MAAM,KAAK,QAAQ;GACnB,QAAQ,KAAK;GACb,WAAW,iBAAiB,KAAK,SAAS;GAC1C,QAAQ,cAAc,KAAK,MAAM;GACjC,WAAW,KAAK;GAChB,OAAO;GACP,QAAQ;EACV,CAAC;CACH,CAAC;AACH;AAEA,SAAS,2BACP,MACA,KACA,OACA,WACA,WACA,YACA,KACA,YACA,cACA,kBACA,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,MAAM,SAAS,MAAM,UAAU;EAC7B,MAAM,QAAQ,UAAU,YAAY;EACpC,MAAM,QAAQ,SAAS,SAAS,aAAa;EAC7C,MAAM,YAAY,KAAK,OAAO,QAAQ,KAAK,EAAE,KAAK;EAClD,MAAM,YAAY,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK;EAEtD,MAAM,UAAU,UAAU;EAC1B,MAAM,SAAS,UACX;GAEE;IAAE,GAAG;IAAG,GAAG;GAAE;GACb;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG;GAAE;GAC7B;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG,OAAO,aAAa,UAAU;GAAE;GAC3D;IAAE,GAAG,OAAO,YAAY,CAAC;IAAG,GAAG,OAAO,UAAU;GAAE;GAClD;IAAE,GAAG;IAAG,GAAG,OAAO,aAAa,UAAU;GAAE;GAC3C,EAAE,OAAO,KAAc;EACzB,IACA;GAEE;IAAE,GAAG,OAAO,YAAY,CAAC;IAAG,GAAG;GAAE;GACjC;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG,OAAO,UAAU;GAAE;GAC9C;IAAE,GAAG,OAAO,SAAS;IAAG,GAAG,OAAO,aAAa,UAAU;GAAE;GAC3D;IAAE,GAAG,OAAO,YAAY,CAAC;IAAG,GAAG,OAAO,UAAU;GAAE;GAClD;IAAE,GAAG;IAAG,GAAG,OAAO,aAAa,UAAU;GAAE;GAC3C;IAAE,GAAG;IAAG,GAAG,OAAO,UAAU;GAAE;GAC9B,EAAE,OAAO,KAAc;EACzB;EAEJ,IAAI,MAAM,SAAS,YAAqB;GACtC,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,SAAS;GACnB,GAAG,OAAO,UAAU;GACpB;GACA,MAAM,EAAE,OAAO,UAAU;GACzB,MAAM,EAAE,MAAM,OAAgB;EAChC,CAAC;EAGD,MAAM,gBAAgB,UAAU,IAAI;EACpC,MAAM,aAAa,KAAK,IAAI,GAAG,aAAa,aAAa,aAAa;EAEtE,IAAI,MAAM,QAAQ,KAAK,OAAO;GAC5B,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,QAAQ,aAAa;GAC/B,GAAG,OAAO,SAAS;GACnB,GAAG,OAAO,UAAU;GACpB,UAAU,QAAQ,KAAK,YAAY,MAAM,WAAW;GACpD,UAAU,KAAK,cAAc;GAC7B,OAAO;GACP,MAAM,KAAK,QAAQ;GACnB,QAAQ,KAAK;GACb,WAAW,iBAAiB,KAAK,SAAS;GAC1C,QAAQ,cAAc,KAAK,MAAM;GACjC,WAAW,KAAK;GAChB,OAAO;GACP,QAAQ;EACV,CAAC;CACH,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"processArrow.js","names":[],"sources":["../../../src/renderPptx/nodes/processArrow.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 { convertUnderline, convertStrike } from \"../textOptions.ts\";\nimport { measureProcessArrow } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport {\n ARROW_DEPTH_RATIO,\n DEFAULT_PROCESS_ARROW_ITEM_WIDTH,\n DEFAULT_PROCESS_ARROW_ITEM_HEIGHT,\n} from \"../../shared/processArrowConstants.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\n\ntype ProcessArrowPositionedNode = Extract<\n PositionedNode,\n { type: \"processArrow\" }\n>;\n\nexport function renderProcessArrowNode(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const steps = node.steps;\n const stepCount = steps.length;\n\n if (stepCount === 0) return;\n\n const defaultColor = \"4472C4\"; // PowerPoint標準の青\n const defaultTextColor = \"FFFFFF\";\n const itemWidth = node.itemWidth ?? DEFAULT_PROCESS_ARROW_ITEM_WIDTH;\n const itemHeight = node.itemHeight ?? DEFAULT_PROCESS_ARROW_ITEM_HEIGHT;\n const arrowDepth = itemHeight * ARROW_DEPTH_RATIO;\n const gap = node.gap ?? -arrowDepth;\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureProcessArrow(node),\n ctx,\n );\n\n const scaledItemWidth = itemWidth * scaleFactor;\n const scaledItemHeight = itemHeight * scaleFactor;\n const scaledGap = gap * scaleFactor;\n const scaledArrowDepth = arrowDepth * scaleFactor;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n if (direction === \"horizontal\") {\n renderHorizontalProcessArrow(\n contentNode,\n ctx,\n steps,\n stepCount,\n scaledItemWidth,\n scaledItemHeight,\n scaledGap,\n scaledArrowDepth,\n defaultColor,\n defaultTextColor,\n scaleFactor,\n );\n } else {\n renderVerticalProcessArrow(\n contentNode,\n ctx,\n steps,\n stepCount,\n scaledItemWidth,\n scaledItemHeight,\n scaledGap,\n scaledArrowDepth,\n defaultColor,\n defaultTextColor,\n scaleFactor,\n );\n }\n}\n\nfunction renderHorizontalProcessArrow(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n steps: ProcessArrowPositionedNode[\"steps\"],\n stepCount: number,\n itemWidth: number,\n itemHeight: number,\n gap: number,\n arrowDepth: number,\n defaultColor: string,\n defaultTextColor: string,\n scaleFactor: number,\n): void {\n const totalWidth = stepCount * itemWidth + (stepCount - 1) * gap;\n const startX = node.x + (node.w - totalWidth) / 2;\n const centerY = node.y + node.h / 2;\n\n steps.forEach((step, index) => {\n const stepX = startX + index * (itemWidth + gap);\n const stepY = centerY - itemHeight / 2;\n const fillColor = stripHash(step.color) ?? defaultColor;\n const textColor = stripHash(step.textColor) ?? defaultTextColor;\n\n // custGeom でシェブロン形状を描画\n const isFirst = index === 0;\n const points = isFirst\n ? [\n // homePlate 風: 左辺フラット、右辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth - arrowDepth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight / 2) },\n { x: pxToIn(itemWidth - arrowDepth), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight) },\n { close: true as const },\n ]\n : [\n // chevron 風: 左辺に切り欠き、右辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth - arrowDepth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight / 2) },\n { x: pxToIn(itemWidth - arrowDepth), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight) },\n { x: pxToIn(arrowDepth), y: pxToIn(itemHeight / 2) },\n { close: true as const },\n ];\n\n ctx.slide.addShape(\"custGeom\" as never, {\n x: pxToIn(stepX),\n y: pxToIn(stepY),\n w: pxToIn(itemWidth),\n h: pxToIn(itemHeight),\n points,\n fill: { color: fillColor },\n line: { type: \"none\" as const },\n });\n\n // テキストを図形の中央(矢印部分を除いた領域)に配置\n const textOffsetLeft = isFirst ? 0 : arrowDepth;\n const textWidth = Math.max(1, itemWidth - arrowDepth - textOffsetLeft);\n\n ctx.slide.addText(step.label, {\n x: pxToIn(stepX + textOffsetLeft),\n y: pxToIn(stepY),\n w: pxToIn(textWidth),\n h: pxToIn(itemHeight),\n fontSize: pxToPt((node.fontSize ?? 14) * scaleFactor),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n color: textColor,\n bold: node.bold ?? false,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n align: \"center\",\n valign: \"middle\",\n });\n });\n}\n\nfunction renderVerticalProcessArrow(\n node: ProcessArrowPositionedNode,\n ctx: RenderContext,\n steps: ProcessArrowPositionedNode[\"steps\"],\n stepCount: number,\n itemWidth: number,\n itemHeight: number,\n gap: number,\n arrowDepth: number,\n defaultColor: string,\n defaultTextColor: string,\n scaleFactor: number,\n): void {\n const totalHeight = stepCount * itemHeight + (stepCount - 1) * gap;\n const startY = node.y + (node.h - totalHeight) / 2;\n const centerX = node.x + node.w / 2;\n\n steps.forEach((step, index) => {\n const stepX = centerX - itemWidth / 2;\n const stepY = startY + index * (itemHeight + gap);\n const fillColor = stripHash(step.color) ?? defaultColor;\n const textColor = stripHash(step.textColor) ?? defaultTextColor;\n\n const isFirst = index === 0;\n const points = isFirst\n ? [\n // rect 風: 上辺フラット、下辺が矢印\n { x: 0, y: 0 },\n { x: pxToIn(itemWidth), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight - arrowDepth) },\n { x: pxToIn(itemWidth / 2), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight - arrowDepth) },\n { close: true as const },\n ]\n : [\n // pentagon 風: 上辺に切り欠き、下辺が矢印\n { x: pxToIn(itemWidth / 2), y: 0 },\n { x: pxToIn(itemWidth), y: pxToIn(arrowDepth) },\n { x: pxToIn(itemWidth), y: pxToIn(itemHeight - arrowDepth) },\n { x: pxToIn(itemWidth / 2), y: pxToIn(itemHeight) },\n { x: 0, y: pxToIn(itemHeight - arrowDepth) },\n { x: 0, y: pxToIn(arrowDepth) },\n { close: true as const },\n ];\n\n ctx.slide.addShape(\"custGeom\" as never, {\n x: pxToIn(stepX),\n y: pxToIn(stepY),\n w: pxToIn(itemWidth),\n h: pxToIn(itemHeight),\n points,\n fill: { color: fillColor },\n line: { type: \"none\" as const },\n });\n\n // テキストを図形の中央(矢印部分を除いた領域)に配置\n const textOffsetTop = isFirst ? 0 : arrowDepth;\n const textHeight = Math.max(1, itemHeight - arrowDepth - textOffsetTop);\n\n ctx.slide.addText(step.label, {\n x: pxToIn(stepX),\n y: pxToIn(stepY + textOffsetTop),\n w: pxToIn(itemWidth),\n h: pxToIn(textHeight),\n fontSize: pxToPt((node.fontSize ?? 14) * scaleFactor),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n color: textColor,\n bold: node.bold ?? false,\n italic: node.italic,\n underline: convertUnderline(node.underline),\n strike: convertStrike(node.strike),\n highlight: node.highlight,\n align: \"center\",\n valign: \"middle\",\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 { measurePyramid } from "../../calcYogaLayout/measureCompositeNodes.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveScaledContentArea } from "../utils/scaleToFit.js";
|
|
5
5
|
//#region src/renderPptx/nodes/pyramid.ts
|
|
6
6
|
function renderPyramidNode(node, ctx) {
|
|
7
7
|
const direction = node.direction ?? "up";
|
|
@@ -10,9 +10,7 @@ function renderPyramidNode(node, ctx) {
|
|
|
10
10
|
if (levelCount === 0) return;
|
|
11
11
|
const defaultColor = "4472C4";
|
|
12
12
|
const defaultTextColor = "FFFFFF";
|
|
13
|
-
const content =
|
|
14
|
-
const intrinsic = measurePyramid(node);
|
|
15
|
-
const scaleFactor = calcScaleFactor(content.w, content.h, intrinsic.width, intrinsic.height, "pyramid", ctx.buildContext.diagnostics);
|
|
13
|
+
const { content, scaleFactor } = resolveScaledContentArea(node, measurePyramid(node), ctx);
|
|
16
14
|
const baseWidth = 400 * scaleFactor;
|
|
17
15
|
const layerHeight = 50 * scaleFactor;
|
|
18
16
|
const gap = 2 * scaleFactor;
|
|
@@ -21,8 +19,8 @@ function renderPyramidNode(node, ctx) {
|
|
|
21
19
|
const startY = content.y + (content.h - totalHeight) / 2;
|
|
22
20
|
for (let i = 0; i < levelCount; i++) {
|
|
23
21
|
const level = levels[i];
|
|
24
|
-
const fillColor = level.color
|
|
25
|
-
const textColor = level.textColor
|
|
22
|
+
const fillColor = stripHash(level.color) ?? defaultColor;
|
|
23
|
+
const textColor = stripHash(level.textColor) ?? defaultTextColor;
|
|
26
24
|
const layerY = startY + i * (layerHeight + gap);
|
|
27
25
|
let topWidthRatio;
|
|
28
26
|
let bottomWidthRatio;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyramid.js","names":[],"sources":["../../../src/renderPptx/nodes/pyramid.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"pyramid.js","names":[],"sources":["../../../src/renderPptx/nodes/pyramid.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 { measurePyramid } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\n\ntype PyramidPositionedNode = Extract<PositionedNode, { type: \"pyramid\" }>;\n\nexport function renderPyramidNode(\n node: PyramidPositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"up\";\n const levels = node.levels;\n const levelCount = levels.length;\n\n if (levelCount === 0) return;\n\n const defaultColor = \"4472C4\";\n const defaultTextColor = \"FFFFFF\";\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measurePyramid(node),\n ctx,\n );\n\n const baseWidth = 400 * scaleFactor;\n const layerHeight = 50 * scaleFactor;\n const gap = 2 * scaleFactor;\n\n const totalHeight = levelCount * layerHeight + (levelCount - 1) * gap;\n const startX = content.x + (content.w - baseWidth) / 2;\n const startY = content.y + (content.h - totalHeight) / 2;\n\n for (let i = 0; i < levelCount; i++) {\n const level = levels[i];\n const fillColor = stripHash(level.color) ?? defaultColor;\n const textColor = stripHash(level.textColor) ?? defaultTextColor;\n\n const layerY = startY + i * (layerHeight + gap);\n\n // direction=\"up\": i=0 が最上段(最も狭い=三角形)、i=levelCount-1 が最下段(最も広い)\n // direction=\"down\": i=0 が最上段(最も広い)、i=levelCount-1 が最下段(最も狭い=三角形)\n // 頂点層の上辺は幅0(三角形)、それ以外は台形\n let topWidthRatio: number;\n let bottomWidthRatio: number;\n\n if (direction === \"up\") {\n topWidthRatio = i / levelCount;\n bottomWidthRatio = (i + 1) / levelCount;\n } else {\n topWidthRatio = (levelCount - i) / levelCount;\n bottomWidthRatio = (levelCount - i - 1) / levelCount;\n }\n\n const topWidth = baseWidth * topWidthRatio;\n const bottomWidth = baseWidth * bottomWidthRatio;\n\n const topLeftX = startX + (baseWidth - topWidth) / 2;\n const topRightX = topLeftX + topWidth;\n const bottomLeftX = startX + (baseWidth - bottomWidth) / 2;\n const bottomRightX = bottomLeftX + bottomWidth;\n\n // custGeom のバウンディングボックス\n const bboxX = Math.min(topLeftX, bottomLeftX);\n const bboxW = Math.max(topRightX, bottomRightX) - bboxX;\n\n // points はバウンディングボックス内の相対インチ座標\n const points = [\n { x: pxToIn(topLeftX - bboxX), y: 0 },\n { x: pxToIn(topRightX - bboxX), y: 0 },\n { x: pxToIn(bottomRightX - bboxX), y: pxToIn(layerHeight) },\n { x: pxToIn(bottomLeftX - bboxX), y: pxToIn(layerHeight) },\n { close: true as const },\n ];\n\n // 図形を描画(頂点層は三角形、それ以外は台形)\n ctx.slide.addShape(\"custGeom\" as never, {\n x: pxToIn(bboxX),\n y: pxToIn(layerY),\n w: pxToIn(bboxW),\n h: pxToIn(layerHeight),\n points,\n fill: { color: fillColor },\n line: { type: \"none\" as const },\n });\n\n // テキストを図形の中央に重ねて描画\n ctx.slide.addText(level.label, {\n x: pxToIn(bboxX),\n y: pxToIn(layerY),\n w: pxToIn(bboxW),\n h: pxToIn(layerHeight),\n fontSize: pxToPt((node.fontSize ?? 14) * scaleFactor),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\n color: textColor,\n bold: node.bold ?? false,\n align: \"center\",\n valign: \"middle\",\n autoFit: true,\n });\n }\n}\n"],"mappings":";;;;;AASA,SAAgB,kBACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,SAAS,KAAK;CACpB,MAAM,aAAa,OAAO;CAE1B,IAAI,eAAe,GAAG;CAEtB,MAAM,eAAe;CACrB,MAAM,mBAAmB;CAGzB,MAAM,EAAE,SAAS,gBAAgB,yBAC/B,MACA,eAAe,IAAI,GACnB,GACF;CAEA,MAAM,YAAY,MAAM;CACxB,MAAM,cAAc,KAAK;CACzB,MAAM,MAAM,IAAI;CAEhB,MAAM,cAAc,aAAa,eAAe,aAAa,KAAK;CAClE,MAAM,SAAS,QAAQ,KAAK,QAAQ,IAAI,aAAa;CACrD,MAAM,SAAS,QAAQ,KAAK,QAAQ,IAAI,eAAe;CAEvD,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,KAAK;EACnC,MAAM,QAAQ,OAAO;EACrB,MAAM,YAAY,UAAU,MAAM,KAAK,KAAK;EAC5C,MAAM,YAAY,UAAU,MAAM,SAAS,KAAK;EAEhD,MAAM,SAAS,SAAS,KAAK,cAAc;EAK3C,IAAI;EACJ,IAAI;EAEJ,IAAI,cAAc,MAAM;GACtB,gBAAgB,IAAI;GACpB,oBAAoB,IAAI,KAAK;EAC/B,OAAO;GACL,iBAAiB,aAAa,KAAK;GACnC,oBAAoB,aAAa,IAAI,KAAK;EAC5C;EAEA,MAAM,WAAW,YAAY;EAC7B,MAAM,cAAc,YAAY;EAEhC,MAAM,WAAW,UAAU,YAAY,YAAY;EACnD,MAAM,YAAY,WAAW;EAC7B,MAAM,cAAc,UAAU,YAAY,eAAe;EACzD,MAAM,eAAe,cAAc;EAGnC,MAAM,QAAQ,KAAK,IAAI,UAAU,WAAW;EAC5C,MAAM,QAAQ,KAAK,IAAI,WAAW,YAAY,IAAI;EAGlD,MAAM,SAAS;GACb;IAAE,GAAG,OAAO,WAAW,KAAK;IAAG,GAAG;GAAE;GACpC;IAAE,GAAG,OAAO,YAAY,KAAK;IAAG,GAAG;GAAE;GACrC;IAAE,GAAG,OAAO,eAAe,KAAK;IAAG,GAAG,OAAO,WAAW;GAAE;GAC1D;IAAE,GAAG,OAAO,cAAc,KAAK;IAAG,GAAG,OAAO,WAAW;GAAE;GACzD,EAAE,OAAO,KAAc;EACzB;EAGA,IAAI,MAAM,SAAS,YAAqB;GACtC,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,WAAW;GACrB;GACA,MAAM,EAAE,OAAO,UAAU;GACzB,MAAM,EAAE,MAAM,OAAgB;EAChC,CAAC;EAGD,IAAI,MAAM,QAAQ,MAAM,OAAO;GAC7B,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,KAAK;GACf,GAAG,OAAO,WAAW;GACrB,UAAU,QAAQ,KAAK,YAAY,MAAM,WAAW;GACpD,UAAU,KAAK,cAAc;GAC7B,OAAO;GACP,MAAM,KAAK,QAAQ;GACnB,OAAO;GACP,QAAQ;GACR,SAAS;EACX,CAAC;CACH;AACF"}
|
|
@@ -1,31 +1,18 @@
|
|
|
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
|
+
import { convertBorderLine, convertShadow } from "../utils/visualStyle.js";
|
|
4
5
|
//#region src/renderPptx/nodes/shape.ts
|
|
5
6
|
function renderShapeNode(node, ctx) {
|
|
6
|
-
const content = getContentArea(node);
|
|
7
7
|
const shapeOptions = {
|
|
8
|
-
|
|
9
|
-
y: pxToIn(content.y),
|
|
10
|
-
w: pxToIn(content.w),
|
|
11
|
-
h: pxToIn(content.h),
|
|
8
|
+
...getContentAreaIn(node),
|
|
12
9
|
fill: node.fill ? {
|
|
13
10
|
color: node.fill.color,
|
|
14
11
|
transparency: node.fill.transparency
|
|
15
12
|
} : void 0,
|
|
16
|
-
line: node.line ?
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
dashType: node.line.dashType
|
|
20
|
-
} : void 0,
|
|
21
|
-
shadow: node.shadow ? {
|
|
22
|
-
type: node.shadow.type ?? "outer",
|
|
23
|
-
opacity: node.shadow.opacity,
|
|
24
|
-
blur: node.shadow.blur,
|
|
25
|
-
angle: node.shadow.angle,
|
|
26
|
-
offset: node.shadow.offset,
|
|
27
|
-
color: node.shadow.color
|
|
28
|
-
} : void 0
|
|
13
|
+
line: node.line ? convertBorderLine(node.line) : void 0,
|
|
14
|
+
shadow: convertShadow(node.shadow),
|
|
15
|
+
rotate: node.rotate
|
|
29
16
|
};
|
|
30
17
|
if (node.text) ctx.slide.addText(node.text, {
|
|
31
18
|
...shapeOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/renderPptx/nodes/shape.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/renderPptx/nodes/shape.ts"],"sourcesContent":["import type { PositionedNode } 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\";\nimport { convertBorderLine, convertShadow } from \"../utils/visualStyle.ts\";\n\ntype ShapePositionedNode = Extract<PositionedNode, { type: \"shape\" }>;\n\nexport function renderShapeNode(\n node: ShapePositionedNode,\n ctx: RenderContext,\n): void {\n const shapeOptions = {\n ...getContentAreaIn(node),\n fill: node.fill\n ? {\n color: node.fill.color,\n transparency: node.fill.transparency,\n }\n : undefined,\n line: node.line ? convertBorderLine(node.line) : undefined,\n shadow: convertShadow(node.shadow),\n rotate: node.rotate,\n };\n\n if (node.text) {\n // テキストがある場合:addTextでshapeを指定\n ctx.slide.addText(node.text, {\n ...shapeOptions,\n shape: node.shapeType,\n fontSize: pxToPt(node.fontSize ?? 24),\n fontFace: node.fontFamily ?? \"Noto Sans JP\",\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 align: node.textAlign ?? \"center\",\n valign: \"middle\" as const,\n lineSpacingMultiple: node.lineHeight ?? 1.3,\n });\n } else {\n // テキストがない場合:addShapeを使用\n ctx.slide.addShape(node.shapeType, shapeOptions);\n }\n}\n"],"mappings":";;;;;AASA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,eAAe;EACnB,GAAG,iBAAiB,IAAI;EACxB,MAAM,KAAK,OACP;GACE,OAAO,KAAK,KAAK;GACjB,cAAc,KAAK,KAAK;EAC1B,IACA,KAAA;EACJ,MAAM,KAAK,OAAO,kBAAkB,KAAK,IAAI,IAAI,KAAA;EACjD,QAAQ,cAAc,KAAK,MAAM;EACjC,QAAQ,KAAK;CACf;CAEA,IAAI,KAAK,MAEP,IAAI,MAAM,QAAQ,KAAK,MAAM;EAC3B,GAAG;EACH,OAAO,KAAK;EACZ,UAAU,OAAO,KAAK,YAAY,EAAE;EACpC,UAAU,KAAK,cAAc;EAC7B,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,iBAAiB,KAAK,SAAS;EAC1C,QAAQ,cAAc,KAAK,MAAM;EACjC,WAAW,KAAK;EAChB,OAAO,KAAK,aAAa;EACzB,QAAQ;EACR,qBAAqB,KAAK,cAAc;CAC1C,CAAC;MAGD,IAAI,MAAM,SAAS,KAAK,WAAW,YAAY;AAEnD"}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rectPxToIn } from "../units.js";
|
|
2
2
|
//#region src/renderPptx/nodes/svg.ts
|
|
3
3
|
function renderSvgNode(node, ctx) {
|
|
4
4
|
ctx.slide.addImage({
|
|
5
5
|
data: node.iconImageData,
|
|
6
|
-
|
|
7
|
-
y: pxToIn(node.y),
|
|
8
|
-
w: pxToIn(node.w),
|
|
9
|
-
h: pxToIn(node.h)
|
|
6
|
+
...rectPxToIn(node)
|
|
10
7
|
});
|
|
11
8
|
}
|
|
12
9
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svg.js","names":[],"sources":["../../../src/renderPptx/nodes/svg.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"svg.js","names":[],"sources":["../../../src/renderPptx/nodes/svg.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { rectPxToIn } from \"../units.ts\";\n\ntype SvgPositionedNode = Extract<PositionedNode, { type: \"svg\" }>;\n\nexport function renderSvgNode(\n node: SvgPositionedNode,\n ctx: RenderContext,\n): void {\n ctx.slide.addImage({\n data: node.iconImageData,\n ...rectPxToIn(node),\n });\n}\n"],"mappings":";;AAMA,SAAgB,cACd,MACA,KACM;CACN,IAAI,MAAM,SAAS;EACjB,MAAM,KAAK;EACX,GAAG,WAAW,IAAI;CACpB,CAAC;AACH"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pxToIn, pxToPt } from "../units.js";
|
|
1
|
+
import { pxToIn, pxToPt, rectPxToIn } from "../units.js";
|
|
2
2
|
import { getContentArea } from "../utils/contentArea.js";
|
|
3
3
|
import { convertStrike, convertUnderline } from "../textOptions.js";
|
|
4
4
|
import { resolveColumnWidths, resolveRowHeights } from "../../shared/tableUtils.js";
|
|
@@ -49,10 +49,7 @@ function renderTableNode(node, ctx) {
|
|
|
49
49
|
}));
|
|
50
50
|
const content = getContentArea(node);
|
|
51
51
|
const tableOptions = {
|
|
52
|
-
|
|
53
|
-
y: pxToIn(content.y),
|
|
54
|
-
w: pxToIn(content.w),
|
|
55
|
-
h: pxToIn(content.h),
|
|
52
|
+
...rectPxToIn(content),
|
|
56
53
|
colW: resolveColumnWidths(node, content.w).map((width) => pxToIn(width)),
|
|
57
54
|
rowH: resolveRowHeights(node).map((height) => pxToIn(height)),
|
|
58
55
|
margin: 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.js","names":[],"sources":["../../../src/renderPptx/nodes/table.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n resolveColumnWidths,\n resolveRowHeights,\n} from \"../../shared/tableUtils.ts\";\nimport { pxToIn, pxToPt } from \"../units.ts\";\nimport { convertUnderline, convertStrike } from \"../textOptions.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\n\ntype TablePositionedNode = Extract<PositionedNode, { type: \"table\" }>;\n\nexport function renderTableNode(\n node: TablePositionedNode,\n ctx: RenderContext,\n): void {\n const tableRows = node.rows.map((row) =>\n row.cells.map((cell) => {\n const cellFontFace = cell.fontFamily;\n const cellOptions: Record<string, unknown> = {\n fontSize: pxToPt(cell.fontSize ?? 18),\n fontFace: cellFontFace,\n color: cell.color,\n bold: cell.bold,\n italic: cell.italic,\n underline: convertUnderline(cell.underline),\n strike: convertStrike(cell.strike),\n highlight: cell.highlight,\n align: cell.textAlign ?? \"left\",\n fill: cell.backgroundColor\n ? { color: cell.backgroundColor }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n };\n\n if (cell.runs && cell.runs.length > 0) {\n const textItems = cell.runs.map((run) => ({\n text: run.text,\n options: {\n fontSize: pxToPt(cell.fontSize ?? 18),\n fontFace: run.fontFamily ?? cellFontFace,\n color: run.color ?? cell.color,\n bold: run.bold ?? cell.bold,\n italic: run.italic ?? cell.italic,\n underline: convertUnderline(run.underline ?? cell.underline),\n strike: convertStrike(run.strike ?? cell.strike),\n highlight: run.highlight ?? cell.highlight,\n ...(run.href ? { hyperlink: { url: run.href } } : {}),\n },\n }));\n return {\n text: textItems,\n options: {\n align: cell.textAlign ?? \"left\",\n fill: cell.backgroundColor\n ? { color: cell.backgroundColor }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n },\n };\n }\n\n return {\n text: cell.text,\n options: cellOptions,\n };\n }),\n );\n\n const content = getContentArea(node);\n const tableOptions: Record<string, unknown> = {\n
|
|
1
|
+
{"version":3,"file":"table.js","names":[],"sources":["../../../src/renderPptx/nodes/table.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n resolveColumnWidths,\n resolveRowHeights,\n} from \"../../shared/tableUtils.ts\";\nimport { pxToIn, pxToPt, rectPxToIn } from \"../units.ts\";\nimport { convertUnderline, convertStrike } from \"../textOptions.ts\";\nimport { getContentArea } from \"../utils/contentArea.ts\";\n\ntype TablePositionedNode = Extract<PositionedNode, { type: \"table\" }>;\n\nexport function renderTableNode(\n node: TablePositionedNode,\n ctx: RenderContext,\n): void {\n const tableRows = node.rows.map((row) =>\n row.cells.map((cell) => {\n const cellFontFace = cell.fontFamily;\n const cellOptions: Record<string, unknown> = {\n fontSize: pxToPt(cell.fontSize ?? 18),\n fontFace: cellFontFace,\n color: cell.color,\n bold: cell.bold,\n italic: cell.italic,\n underline: convertUnderline(cell.underline),\n strike: convertStrike(cell.strike),\n highlight: cell.highlight,\n align: cell.textAlign ?? \"left\",\n fill: cell.backgroundColor\n ? { color: cell.backgroundColor }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n };\n\n if (cell.runs && cell.runs.length > 0) {\n const textItems = cell.runs.map((run) => ({\n text: run.text,\n options: {\n fontSize: pxToPt(cell.fontSize ?? 18),\n fontFace: run.fontFamily ?? cellFontFace,\n color: run.color ?? cell.color,\n bold: run.bold ?? cell.bold,\n italic: run.italic ?? cell.italic,\n underline: convertUnderline(run.underline ?? cell.underline),\n strike: convertStrike(run.strike ?? cell.strike),\n highlight: run.highlight ?? cell.highlight,\n ...(run.href ? { hyperlink: { url: run.href } } : {}),\n },\n }));\n return {\n text: textItems,\n options: {\n align: cell.textAlign ?? \"left\",\n fill: cell.backgroundColor\n ? { color: cell.backgroundColor }\n : undefined,\n colspan: cell.colspan,\n rowspan: cell.rowspan,\n },\n };\n }\n\n return {\n text: cell.text,\n options: cellOptions,\n };\n }),\n );\n\n const content = getContentArea(node);\n const tableOptions: Record<string, unknown> = {\n ...rectPxToIn(content),\n colW: resolveColumnWidths(node, content.w).map((width) => pxToIn(width)),\n rowH: resolveRowHeights(node).map((height) => pxToIn(height)),\n margin: 0,\n };\n\n if (node.cellBorder) {\n tableOptions.border = {\n color: node.cellBorder.color ?? \"000000\",\n pt:\n node.cellBorder.width !== undefined ? pxToPt(node.cellBorder.width) : 1,\n type: node.cellBorder.dashType ?? \"solid\",\n };\n }\n\n ctx.slide.addTable(tableRows, tableOptions);\n}\n"],"mappings":";;;;;AAYA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,KAAK,KAAK,QAC/B,IAAI,MAAM,KAAK,SAAS;EACtB,MAAM,eAAe,KAAK;EAC1B,MAAM,cAAuC;GAC3C,UAAU,OAAO,KAAK,YAAY,EAAE;GACpC,UAAU;GACV,OAAO,KAAK;GACZ,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,WAAW,iBAAiB,KAAK,SAAS;GAC1C,QAAQ,cAAc,KAAK,MAAM;GACjC,WAAW,KAAK;GAChB,OAAO,KAAK,aAAa;GACzB,MAAM,KAAK,kBACP,EAAE,OAAO,KAAK,gBAAgB,IAC9B,KAAA;GACJ,SAAS,KAAK;GACd,SAAS,KAAK;EAChB;EAEA,IAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,GAelC,OAAO;GACL,MAfgB,KAAK,KAAK,KAAK,SAAS;IACxC,MAAM,IAAI;IACV,SAAS;KACP,UAAU,OAAO,KAAK,YAAY,EAAE;KACpC,UAAU,IAAI,cAAc;KAC5B,OAAO,IAAI,SAAS,KAAK;KACzB,MAAM,IAAI,QAAQ,KAAK;KACvB,QAAQ,IAAI,UAAU,KAAK;KAC3B,WAAW,iBAAiB,IAAI,aAAa,KAAK,SAAS;KAC3D,QAAQ,cAAc,IAAI,UAAU,KAAK,MAAM;KAC/C,WAAW,IAAI,aAAa,KAAK;KACjC,GAAI,IAAI,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,KAAK,EAAE,IAAI,CAAC;IACrD;GACF,EAEgB;GACd,SAAS;IACP,OAAO,KAAK,aAAa;IACzB,MAAM,KAAK,kBACP,EAAE,OAAO,KAAK,gBAAgB,IAC9B,KAAA;IACJ,SAAS,KAAK;IACd,SAAS,KAAK;GAChB;EACF;EAGF,OAAO;GACL,MAAM,KAAK;GACX,SAAS;EACX;CACF,CAAC,CACH;CAEA,MAAM,UAAU,eAAe,IAAI;CACnC,MAAM,eAAwC;EAC5C,GAAG,WAAW,OAAO;EACrB,MAAM,oBAAoB,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,OAAO,KAAK,CAAC;EACvE,MAAM,kBAAkB,IAAI,CAAC,CAAC,KAAK,WAAW,OAAO,MAAM,CAAC;EAC5D,QAAQ;CACV;CAEA,IAAI,KAAK,YACP,aAAa,SAAS;EACpB,OAAO,KAAK,WAAW,SAAS;EAChC,IACE,KAAK,WAAW,UAAU,KAAA,IAAY,OAAO,KAAK,WAAW,KAAK,IAAI;EACxE,MAAM,KAAK,WAAW,YAAY;CACpC;CAGF,IAAI,MAAM,SAAS,WAAW,YAAY;AAC5C"}
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import { pxToPt } from "../units.js";
|
|
2
|
-
import { convertStrike, convertUnderline, createTextOptions } from "../textOptions.js";
|
|
2
|
+
import { convertGlow, convertOutline, convertStrike, convertUnderline, createTextOptions } from "../textOptions.js";
|
|
3
3
|
//#region src/renderPptx/nodes/text.ts
|
|
4
4
|
function renderTextNode(node, ctx) {
|
|
5
5
|
const textOptions = createTextOptions(node);
|
|
6
6
|
if (node.runs && node.runs.length > 0) {
|
|
7
7
|
const fontSizePx = node.fontSize ?? 24;
|
|
8
8
|
const fontFamily = node.fontFamily ?? "Noto Sans JP";
|
|
9
|
-
const textItems = node.runs.map((run) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
const textItems = node.runs.map((run) => {
|
|
10
|
+
const letterSpacingPx = run.letterSpacing ?? node.letterSpacing;
|
|
11
|
+
return {
|
|
12
|
+
text: run.text,
|
|
13
|
+
options: {
|
|
14
|
+
fontSize: pxToPt(fontSizePx),
|
|
15
|
+
fontFace: run.fontFamily ?? fontFamily,
|
|
16
|
+
color: run.color ?? node.color,
|
|
17
|
+
bold: run.bold ?? node.bold,
|
|
18
|
+
italic: run.italic ?? node.italic,
|
|
19
|
+
underline: convertUnderline(run.underline ?? node.underline),
|
|
20
|
+
strike: convertStrike(run.strike ?? node.strike),
|
|
21
|
+
highlight: run.highlight ?? node.highlight,
|
|
22
|
+
glow: convertGlow(node.glow),
|
|
23
|
+
outline: convertOutline(node.outline),
|
|
24
|
+
charSpacing: letterSpacingPx !== void 0 ? pxToPt(letterSpacingPx) : void 0,
|
|
25
|
+
...run.href ? { hyperlink: { url: run.href } } : {}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
});
|
|
23
29
|
ctx.slide.addText(textItems, {
|
|
24
30
|
x: textOptions.x,
|
|
25
31
|
y: textOptions.y,
|
|
26
32
|
w: textOptions.w,
|
|
27
33
|
h: textOptions.h,
|
|
34
|
+
rotate: textOptions.rotate,
|
|
28
35
|
align: textOptions.align,
|
|
29
36
|
valign: textOptions.valign,
|
|
30
37
|
margin: textOptions.margin,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":[],"sources":["../../../src/renderPptx/nodes/text.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n createTextOptions,\n convertUnderline,\n convertStrike,\n} from \"../textOptions.ts\";\nimport { pxToPt } from \"../units.ts\";\n\ntype TextPositionedNode = Extract<PositionedNode, { type: \"text\" }>;\n\nexport function renderTextNode(\n node: TextPositionedNode,\n ctx: RenderContext,\n): void {\n const textOptions = createTextOptions(node);\n\n if (node.runs && node.runs.length > 0) {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const textItems = node.runs.map((run) =>
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../src/renderPptx/nodes/text.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {\n createTextOptions,\n convertUnderline,\n convertStrike,\n convertGlow,\n convertOutline,\n} from \"../textOptions.ts\";\nimport { pxToPt } from \"../units.ts\";\n\ntype TextPositionedNode = Extract<PositionedNode, { type: \"text\" }>;\n\nexport function renderTextNode(\n node: TextPositionedNode,\n ctx: RenderContext,\n): void {\n const textOptions = createTextOptions(node);\n\n if (node.runs && node.runs.length > 0) {\n const fontSizePx = node.fontSize ?? 24;\n const fontFamily = node.fontFamily ?? \"Noto Sans JP\";\n const textItems = node.runs.map((run) => {\n const letterSpacingPx = run.letterSpacing ?? node.letterSpacing;\n return {\n text: run.text,\n options: {\n fontSize: pxToPt(fontSizePx),\n fontFace: run.fontFamily ?? fontFamily,\n color: run.color ?? node.color,\n bold: run.bold ?? node.bold,\n italic: run.italic ?? node.italic,\n underline: convertUnderline(run.underline ?? node.underline),\n strike: convertStrike(run.strike ?? node.strike),\n highlight: run.highlight ?? node.highlight,\n // glow / outline はノード単位指定のみ (run 単位はスコープ外)\n glow: convertGlow(node.glow),\n outline: convertOutline(node.outline),\n charSpacing:\n letterSpacingPx !== undefined ? pxToPt(letterSpacingPx) : undefined,\n ...(run.href ? { hyperlink: { url: run.href } } : {}),\n },\n };\n });\n ctx.slide.addText(textItems, {\n x: textOptions.x,\n y: textOptions.y,\n w: textOptions.w,\n h: textOptions.h,\n rotate: textOptions.rotate,\n align: textOptions.align,\n valign: textOptions.valign,\n margin: textOptions.margin,\n lineSpacingMultiple: textOptions.lineSpacingMultiple,\n });\n } else {\n ctx.slide.addText(node.text ?? \"\", textOptions);\n }\n}\n"],"mappings":";;;AAaA,SAAgB,eACd,MACA,KACM;CACN,MAAM,cAAc,kBAAkB,IAAI;CAE1C,IAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,GAAG;EACrC,MAAM,aAAa,KAAK,YAAY;EACpC,MAAM,aAAa,KAAK,cAAc;EACtC,MAAM,YAAY,KAAK,KAAK,KAAK,QAAQ;GACvC,MAAM,kBAAkB,IAAI,iBAAiB,KAAK;GAClD,OAAO;IACL,MAAM,IAAI;IACV,SAAS;KACP,UAAU,OAAO,UAAU;KAC3B,UAAU,IAAI,cAAc;KAC5B,OAAO,IAAI,SAAS,KAAK;KACzB,MAAM,IAAI,QAAQ,KAAK;KACvB,QAAQ,IAAI,UAAU,KAAK;KAC3B,WAAW,iBAAiB,IAAI,aAAa,KAAK,SAAS;KAC3D,QAAQ,cAAc,IAAI,UAAU,KAAK,MAAM;KAC/C,WAAW,IAAI,aAAa,KAAK;KAEjC,MAAM,YAAY,KAAK,IAAI;KAC3B,SAAS,eAAe,KAAK,OAAO;KACpC,aACE,oBAAoB,KAAA,IAAY,OAAO,eAAe,IAAI,KAAA;KAC5D,GAAI,IAAI,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,KAAK,EAAE,IAAI,CAAC;IACrD;GACF;EACF,CAAC;EACD,IAAI,MAAM,QAAQ,WAAW;GAC3B,GAAG,YAAY;GACf,GAAG,YAAY;GACf,GAAG,YAAY;GACf,GAAG,YAAY;GACf,QAAQ,YAAY;GACpB,OAAO,YAAY;GACnB,QAAQ,YAAY;GACpB,QAAQ,YAAY;GACpB,qBAAqB,YAAY;EACnC,CAAC;CACH,OACE,IAAI,MAAM,QAAQ,KAAK,QAAQ,IAAI,WAAW;AAElD"}
|