@hirokisakabe/pom 0.1.6 → 0.1.8
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 +173 -35
- package/dist/buildPptx.d.ts +3 -0
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +9 -3
- package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +41 -6
- package/dist/calcYogaLayout/measureImage.d.ts +13 -2
- package/dist/calcYogaLayout/measureImage.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureImage.js +79 -3
- package/dist/calcYogaLayout/measureText.d.ts +9 -0
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +155 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/inputSchema.d.ts +75 -7
- package/dist/inputSchema.d.ts.map +1 -1
- package/dist/inputSchema.js +14 -3
- package/dist/renderPptx/renderPptx.d.ts.map +1 -1
- package/dist/renderPptx/renderPptx.js +22 -3
- package/dist/renderPptx/textOptions.d.ts +22 -1
- package/dist/renderPptx/textOptions.d.ts.map +1 -1
- package/dist/renderPptx/textOptions.js +27 -1
- package/dist/table/utils.d.ts +10 -0
- package/dist/table/utils.d.ts.map +1 -1
- package/dist/table/utils.js +18 -1
- package/dist/toPositioned/toPositioned.d.ts.map +1 -1
- package/dist/toPositioned/toPositioned.js +9 -0
- package/dist/types.d.ts +137 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +46 -4
- package/package.json +18 -2
|
@@ -1,10 +1,122 @@
|
|
|
1
1
|
import { createCanvas } from "canvas";
|
|
2
2
|
const canvas = createCanvas(1, 1);
|
|
3
3
|
const ctx = canvas.getContext("2d");
|
|
4
|
+
// フォント利用可否のキャッシュ
|
|
5
|
+
const fontAvailabilityCache = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* 指定されたフォントが利用可能かどうかをチェックする
|
|
8
|
+
* 既知のフォントと未知のフォントで同じ幅になるかチェックし、
|
|
9
|
+
* 同じなら「フォントが利用できない」と判定する
|
|
10
|
+
*/
|
|
11
|
+
function isFontAvailable(fontFamily, fontSizePx) {
|
|
12
|
+
const cacheKey = `${fontFamily}:${fontSizePx}`;
|
|
13
|
+
const cached = fontAvailabilityCache.get(cacheKey);
|
|
14
|
+
if (cached !== undefined) {
|
|
15
|
+
return cached;
|
|
16
|
+
}
|
|
17
|
+
// テスト文字列(日本語と英語を含む)
|
|
18
|
+
const testString = "あいうABC123";
|
|
19
|
+
// 存在しないフォント名でテスト
|
|
20
|
+
const nonExistentFont = "NonExistentFont_12345_XYZ";
|
|
21
|
+
ctx.font = `${fontSizePx}px "${fontFamily}"`;
|
|
22
|
+
const targetWidth = ctx.measureText(testString).width;
|
|
23
|
+
ctx.font = `${fontSizePx}px "${nonExistentFont}"`;
|
|
24
|
+
const fallbackWidth = ctx.measureText(testString).width;
|
|
25
|
+
// 幅が同じなら、フォントが利用できない(フォールバックされている)
|
|
26
|
+
const isAvailable = Math.abs(targetWidth - fallbackWidth) > 0.1;
|
|
27
|
+
fontAvailabilityCache.set(cacheKey, isAvailable);
|
|
28
|
+
return isAvailable;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 文字がCJK(日本語・中国語・韓国語)文字かどうかを判定する
|
|
32
|
+
*/
|
|
33
|
+
function isCJKChar(char) {
|
|
34
|
+
const code = char.codePointAt(0);
|
|
35
|
+
if (code === undefined)
|
|
36
|
+
return false;
|
|
37
|
+
// CJK統合漢字
|
|
38
|
+
if (code >= 0x4e00 && code <= 0x9fff)
|
|
39
|
+
return true;
|
|
40
|
+
// CJK統合漢字拡張A
|
|
41
|
+
if (code >= 0x3400 && code <= 0x4dbf)
|
|
42
|
+
return true;
|
|
43
|
+
// CJK統合漢字拡張B-F
|
|
44
|
+
if (code >= 0x20000 && code <= 0x2ebef)
|
|
45
|
+
return true;
|
|
46
|
+
// ひらがな
|
|
47
|
+
if (code >= 0x3040 && code <= 0x309f)
|
|
48
|
+
return true;
|
|
49
|
+
// カタカナ
|
|
50
|
+
if (code >= 0x30a0 && code <= 0x30ff)
|
|
51
|
+
return true;
|
|
52
|
+
// 全角英数字・記号
|
|
53
|
+
if (code >= 0xff00 && code <= 0xffef)
|
|
54
|
+
return true;
|
|
55
|
+
// CJK記号
|
|
56
|
+
if (code >= 0x3000 && code <= 0x303f)
|
|
57
|
+
return true;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* フォールバック計算で文字の幅を推定する
|
|
62
|
+
* - CJK文字: 1em(= fontSizePx)
|
|
63
|
+
* - 英数字・半角記号: 0.5em
|
|
64
|
+
*/
|
|
65
|
+
function estimateCharWidth(char, fontSizePx) {
|
|
66
|
+
if (isCJKChar(char)) {
|
|
67
|
+
return fontSizePx; // 1em
|
|
68
|
+
}
|
|
69
|
+
return fontSizePx * 0.5; // 0.5em
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* フォールバック計算でテキスト幅を推定する
|
|
73
|
+
*/
|
|
74
|
+
function estimateTextWidth(text, fontSizePx) {
|
|
75
|
+
let width = 0;
|
|
76
|
+
for (const char of text) {
|
|
77
|
+
width += estimateCharWidth(char, fontSizePx);
|
|
78
|
+
}
|
|
79
|
+
return width;
|
|
80
|
+
}
|
|
81
|
+
// 現在のテキスト計測モード
|
|
82
|
+
let currentMode = "auto";
|
|
83
|
+
/**
|
|
84
|
+
* テキスト計測モードを設定する
|
|
85
|
+
*/
|
|
86
|
+
export function setTextMeasurementMode(mode) {
|
|
87
|
+
currentMode = mode;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 現在のテキスト計測モードを取得する
|
|
91
|
+
*/
|
|
92
|
+
export function getTextMeasurementMode() {
|
|
93
|
+
return currentMode;
|
|
94
|
+
}
|
|
4
95
|
/**
|
|
5
96
|
* テキストを折り返し付きでレイアウトし、そのサイズを測定する
|
|
6
97
|
*/
|
|
7
98
|
export function measureText(text, maxWidthPx, opts) {
|
|
99
|
+
const { fontFamily, fontSizePx } = opts;
|
|
100
|
+
// 計測方法を決定
|
|
101
|
+
const shouldUseFallback = (() => {
|
|
102
|
+
switch (currentMode) {
|
|
103
|
+
case "canvas":
|
|
104
|
+
return false;
|
|
105
|
+
case "fallback":
|
|
106
|
+
return true;
|
|
107
|
+
case "auto":
|
|
108
|
+
return !isFontAvailable(fontFamily, fontSizePx);
|
|
109
|
+
}
|
|
110
|
+
})();
|
|
111
|
+
if (shouldUseFallback) {
|
|
112
|
+
return measureTextFallback(text, maxWidthPx, opts);
|
|
113
|
+
}
|
|
114
|
+
return measureTextCanvas(text, maxWidthPx, opts);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* canvas を使ったテキスト計測
|
|
118
|
+
*/
|
|
119
|
+
function measureTextCanvas(text, maxWidthPx, opts) {
|
|
8
120
|
applyFontStyle(opts);
|
|
9
121
|
// まず改行で段落に分割
|
|
10
122
|
const paragraphs = text.split("\n");
|
|
@@ -44,6 +156,49 @@ export function measureText(text, maxWidthPx, opts) {
|
|
|
44
156
|
// 端数切り上げ+余裕分 10px を足す
|
|
45
157
|
return { widthPx: widthPx + 10, heightPx };
|
|
46
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* フォールバック計算を使ったテキスト計測
|
|
161
|
+
*/
|
|
162
|
+
function measureTextFallback(text, maxWidthPx, opts) {
|
|
163
|
+
const { fontSizePx } = opts;
|
|
164
|
+
// まず改行で段落に分割
|
|
165
|
+
const paragraphs = text.split("\n");
|
|
166
|
+
const lines = [];
|
|
167
|
+
for (const paragraph of paragraphs) {
|
|
168
|
+
// 空の段落(連続した改行)も1行としてカウント
|
|
169
|
+
if (paragraph === "") {
|
|
170
|
+
lines.push({ widthPx: 0 });
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const words = splitForWrap(paragraph);
|
|
174
|
+
let current = "";
|
|
175
|
+
let currentWidth = 0;
|
|
176
|
+
for (const word of words) {
|
|
177
|
+
const candidate = current ? current + word : word;
|
|
178
|
+
const w = estimateTextWidth(candidate, fontSizePx);
|
|
179
|
+
if (w <= maxWidthPx || !current) {
|
|
180
|
+
// まだ詰められる
|
|
181
|
+
current = candidate;
|
|
182
|
+
currentWidth = w;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// 折り返す
|
|
186
|
+
lines.push({ widthPx: currentWidth });
|
|
187
|
+
current = word;
|
|
188
|
+
currentWidth = estimateTextWidth(word, fontSizePx);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (current) {
|
|
192
|
+
lines.push({ widthPx: currentWidth });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const lineHeightRatio = opts.lineHeight ?? 1.3;
|
|
196
|
+
const lineHeightPx = fontSizePx * lineHeightRatio;
|
|
197
|
+
const widthPx = lines.length ? Math.max(...lines.map((l) => l.widthPx)) : 0;
|
|
198
|
+
const heightPx = lines.length * lineHeightPx;
|
|
199
|
+
// 端数切り上げ+余裕分 10px を足す
|
|
200
|
+
return { widthPx: widthPx + 10, heightPx };
|
|
201
|
+
}
|
|
47
202
|
function applyFontStyle(opts) {
|
|
48
203
|
const { fontFamily, fontSizePx, fontWeight = "normal" } = opts;
|
|
49
204
|
ctx.font = `${fontWeight} ${fontSizePx}px "${fontFamily}"`;
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/inputSchema.d.ts
CHANGED
|
@@ -88,6 +88,32 @@ export declare const inputTextNodeSchema: z.ZodObject<{
|
|
|
88
88
|
bold: z.ZodOptional<z.ZodBoolean>;
|
|
89
89
|
fontFamily: z.ZodOptional<z.ZodString>;
|
|
90
90
|
lineSpacingMultiple: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
bullet: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
92
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
93
|
+
number: "number";
|
|
94
|
+
bullet: "bullet";
|
|
95
|
+
}>>;
|
|
96
|
+
indent: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
numberType: z.ZodOptional<z.ZodEnum<{
|
|
98
|
+
alphaLcParenBoth: "alphaLcParenBoth";
|
|
99
|
+
alphaLcParenR: "alphaLcParenR";
|
|
100
|
+
alphaLcPeriod: "alphaLcPeriod";
|
|
101
|
+
alphaUcParenBoth: "alphaUcParenBoth";
|
|
102
|
+
alphaUcParenR: "alphaUcParenR";
|
|
103
|
+
alphaUcPeriod: "alphaUcPeriod";
|
|
104
|
+
arabicParenBoth: "arabicParenBoth";
|
|
105
|
+
arabicParenR: "arabicParenR";
|
|
106
|
+
arabicPeriod: "arabicPeriod";
|
|
107
|
+
arabicPlain: "arabicPlain";
|
|
108
|
+
romanLcParenBoth: "romanLcParenBoth";
|
|
109
|
+
romanLcParenR: "romanLcParenR";
|
|
110
|
+
romanLcPeriod: "romanLcPeriod";
|
|
111
|
+
romanUcParenBoth: "romanUcParenBoth";
|
|
112
|
+
romanUcParenR: "romanUcParenR";
|
|
113
|
+
romanUcPeriod: "romanUcPeriod";
|
|
114
|
+
}>>;
|
|
115
|
+
numberStartAt: z.ZodOptional<z.ZodNumber>;
|
|
116
|
+
}, z.core.$strip>]>>;
|
|
91
117
|
}, z.core.$strip>;
|
|
92
118
|
export declare const inputImageNodeSchema: z.ZodObject<{
|
|
93
119
|
w: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"max">, z.ZodString]>>;
|
|
@@ -150,7 +176,7 @@ export declare const inputTableNodeSchema: z.ZodObject<{
|
|
|
150
176
|
}, z.core.$strip>>;
|
|
151
177
|
type: z.ZodLiteral<"table">;
|
|
152
178
|
columns: z.ZodArray<z.ZodObject<{
|
|
153
|
-
width: z.ZodNumber
|
|
179
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
154
180
|
}, z.core.$strip>>;
|
|
155
181
|
rows: z.ZodArray<z.ZodObject<{
|
|
156
182
|
cells: z.ZodArray<z.ZodObject<{
|
|
@@ -409,17 +435,62 @@ export declare const inputShapeNodeSchema: z.ZodObject<{
|
|
|
409
435
|
color: z.ZodOptional<z.ZodString>;
|
|
410
436
|
}, z.core.$strip>>;
|
|
411
437
|
fontPx: z.ZodOptional<z.ZodNumber>;
|
|
412
|
-
|
|
438
|
+
color: z.ZodOptional<z.ZodString>;
|
|
413
439
|
alignText: z.ZodOptional<z.ZodEnum<{
|
|
414
440
|
right: "right";
|
|
415
441
|
left: "left";
|
|
416
442
|
center: "center";
|
|
417
443
|
}>>;
|
|
418
444
|
}, z.core.$strip>;
|
|
445
|
+
export declare const inputChartNodeSchema: z.ZodObject<{
|
|
446
|
+
w: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"max">, z.ZodString]>>;
|
|
447
|
+
h: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"max">, z.ZodString]>>;
|
|
448
|
+
minW: z.ZodOptional<z.ZodNumber>;
|
|
449
|
+
maxW: z.ZodOptional<z.ZodNumber>;
|
|
450
|
+
minH: z.ZodOptional<z.ZodNumber>;
|
|
451
|
+
maxH: z.ZodOptional<z.ZodNumber>;
|
|
452
|
+
padding: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
|
|
453
|
+
top: z.ZodOptional<z.ZodNumber>;
|
|
454
|
+
right: z.ZodOptional<z.ZodNumber>;
|
|
455
|
+
bottom: z.ZodOptional<z.ZodNumber>;
|
|
456
|
+
left: z.ZodOptional<z.ZodNumber>;
|
|
457
|
+
}, z.core.$strip>]>>;
|
|
458
|
+
backgroundColor: z.ZodOptional<z.ZodString>;
|
|
459
|
+
border: z.ZodOptional<z.ZodObject<{
|
|
460
|
+
color: z.ZodOptional<z.ZodString>;
|
|
461
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
462
|
+
dashType: z.ZodOptional<z.ZodEnum<{
|
|
463
|
+
solid: "solid";
|
|
464
|
+
dash: "dash";
|
|
465
|
+
dashDot: "dashDot";
|
|
466
|
+
lgDash: "lgDash";
|
|
467
|
+
lgDashDot: "lgDashDot";
|
|
468
|
+
lgDashDotDot: "lgDashDotDot";
|
|
469
|
+
sysDash: "sysDash";
|
|
470
|
+
sysDot: "sysDot";
|
|
471
|
+
}>>;
|
|
472
|
+
}, z.core.$strip>>;
|
|
473
|
+
type: z.ZodLiteral<"chart">;
|
|
474
|
+
chartType: z.ZodEnum<{
|
|
475
|
+
line: "line";
|
|
476
|
+
pie: "pie";
|
|
477
|
+
bar: "bar";
|
|
478
|
+
}>;
|
|
479
|
+
data: z.ZodArray<z.ZodObject<{
|
|
480
|
+
name: z.ZodOptional<z.ZodString>;
|
|
481
|
+
labels: z.ZodArray<z.ZodString>;
|
|
482
|
+
values: z.ZodArray<z.ZodNumber>;
|
|
483
|
+
}, z.core.$strip>>;
|
|
484
|
+
showLegend: z.ZodOptional<z.ZodBoolean>;
|
|
485
|
+
showTitle: z.ZodOptional<z.ZodBoolean>;
|
|
486
|
+
title: z.ZodOptional<z.ZodString>;
|
|
487
|
+
chartColors: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
488
|
+
}, z.core.$strip>;
|
|
419
489
|
export type InputTextNode = z.infer<typeof inputTextNodeSchema>;
|
|
420
490
|
export type InputImageNode = z.infer<typeof inputImageNodeSchema>;
|
|
421
491
|
export type InputTableNode = z.infer<typeof inputTableNodeSchema>;
|
|
422
492
|
export type InputShapeNode = z.infer<typeof inputShapeNodeSchema>;
|
|
493
|
+
export type InputChartNode = z.infer<typeof inputChartNodeSchema>;
|
|
423
494
|
export type InputBoxNode = InputBaseNode & {
|
|
424
495
|
type: "box";
|
|
425
496
|
children: InputPOMNode;
|
|
@@ -438,7 +509,7 @@ export type InputHStackNode = InputBaseNode & {
|
|
|
438
509
|
alignItems?: AlignItems;
|
|
439
510
|
justifyContent?: JustifyContent;
|
|
440
511
|
};
|
|
441
|
-
export type InputPOMNode = InputTextNode | InputImageNode | InputTableNode | InputBoxNode | InputVStackNode | InputHStackNode | InputShapeNode;
|
|
512
|
+
export type InputPOMNode = InputTextNode | InputImageNode | InputTableNode | InputBoxNode | InputVStackNode | InputHStackNode | InputShapeNode | InputChartNode;
|
|
442
513
|
export declare const inputBoxNodeSchema: z.ZodType<InputBoxNode>;
|
|
443
514
|
export declare const inputVStackNodeSchema: z.ZodType<InputVStackNode>;
|
|
444
515
|
export declare const inputHStackNodeSchema: z.ZodType<InputHStackNode>;
|
|
@@ -472,10 +543,7 @@ export declare const inputMasterSlideOptionsSchema: z.ZodObject<{
|
|
|
472
543
|
}>;
|
|
473
544
|
}, z.core.$strip>>;
|
|
474
545
|
date: z.ZodOptional<z.ZodObject<{
|
|
475
|
-
|
|
476
|
-
"YYYY/MM/DD": "YYYY/MM/DD";
|
|
477
|
-
locale: "locale";
|
|
478
|
-
}>;
|
|
546
|
+
value: z.ZodString;
|
|
479
547
|
}, z.core.$strip>>;
|
|
480
548
|
}, z.core.$strip>;
|
|
481
549
|
export type InputMasterSlideOptions = z.infer<typeof inputMasterSlideOptionsSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputSchema.d.ts","sourceRoot":"","sources":["../src/inputSchema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"inputSchema.d.ts","sourceRoot":"","sources":["../src/inputSchema.ts"],"names":[],"mappings":"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"}
|
package/dist/inputSchema.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
import { z } from "zod";
|
|
20
|
-
import { lengthSchema, paddingSchema, borderStyleSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, tableColumnSchema, tableRowSchema, pageNumberPositionSchema,
|
|
20
|
+
import { lengthSchema, paddingSchema, borderStyleSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, tableColumnSchema, tableRowSchema, pageNumberPositionSchema, chartTypeSchema, chartDataSchema, bulletOptionsSchema, } from "./types";
|
|
21
21
|
// ===== Base Node Schema =====
|
|
22
22
|
export const inputBaseNodeSchema = z.object({
|
|
23
23
|
w: lengthSchema.optional(),
|
|
@@ -40,6 +40,7 @@ export const inputTextNodeSchema = inputBaseNodeSchema.extend({
|
|
|
40
40
|
bold: z.boolean().optional(),
|
|
41
41
|
fontFamily: z.string().optional(),
|
|
42
42
|
lineSpacingMultiple: z.number().optional(),
|
|
43
|
+
bullet: z.union([z.boolean(), bulletOptionsSchema]).optional(),
|
|
43
44
|
});
|
|
44
45
|
export const inputImageNodeSchema = inputBaseNodeSchema.extend({
|
|
45
46
|
type: z.literal("image"),
|
|
@@ -59,9 +60,18 @@ export const inputShapeNodeSchema = inputBaseNodeSchema.extend({
|
|
|
59
60
|
line: borderStyleSchema.optional(),
|
|
60
61
|
shadow: shadowStyleSchema.optional(),
|
|
61
62
|
fontPx: z.number().optional(),
|
|
62
|
-
|
|
63
|
+
color: z.string().optional(),
|
|
63
64
|
alignText: z.enum(["left", "center", "right"]).optional(),
|
|
64
65
|
});
|
|
66
|
+
export const inputChartNodeSchema = inputBaseNodeSchema.extend({
|
|
67
|
+
type: z.literal("chart"),
|
|
68
|
+
chartType: chartTypeSchema,
|
|
69
|
+
data: z.array(chartDataSchema),
|
|
70
|
+
showLegend: z.boolean().optional(),
|
|
71
|
+
showTitle: z.boolean().optional(),
|
|
72
|
+
title: z.string().optional(),
|
|
73
|
+
chartColors: z.array(z.string()).optional(),
|
|
74
|
+
});
|
|
65
75
|
// ===== Recursive Node Schemas =====
|
|
66
76
|
const inputBoxNodeSchemaBase = inputBaseNodeSchema.extend({
|
|
67
77
|
type: z.literal("box"),
|
|
@@ -110,6 +120,7 @@ export const inputPomNodeSchema = z.lazy(() => z.discriminatedUnion("type", [
|
|
|
110
120
|
inputVStackNodeSchemaBase,
|
|
111
121
|
inputHStackNodeSchemaBase,
|
|
112
122
|
inputShapeNodeSchema,
|
|
123
|
+
inputChartNodeSchema,
|
|
113
124
|
]));
|
|
114
125
|
// ===== Master Slide Options Schema =====
|
|
115
126
|
export const inputMasterSlideOptionsSchema = z.object({
|
|
@@ -122,7 +133,7 @@ export const inputMasterSlideOptionsSchema = z.object({
|
|
|
122
133
|
.optional(),
|
|
123
134
|
date: z
|
|
124
135
|
.object({
|
|
125
|
-
|
|
136
|
+
value: z.string(),
|
|
126
137
|
})
|
|
127
138
|
.optional(),
|
|
128
139
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,OAAO,iBA8MnE"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module";
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
3
|
const PptxGenJS = require("pptxgenjs");
|
|
4
|
-
import { resolveRowHeights } from "../table/utils";
|
|
4
|
+
import { resolveColumnWidths, resolveRowHeights } from "../table/utils";
|
|
5
5
|
import { createTextOptions } from "./textOptions";
|
|
6
6
|
import { pxToIn, pxToPt } from "./units";
|
|
7
7
|
export { createTextOptions } from "./textOptions";
|
|
@@ -104,7 +104,7 @@ export function renderPptx(pages, slidePx) {
|
|
|
104
104
|
y: pxToIn(node.y),
|
|
105
105
|
w: pxToIn(node.w),
|
|
106
106
|
h: pxToIn(node.h),
|
|
107
|
-
colW: node.
|
|
107
|
+
colW: resolveColumnWidths(node, node.w).map((width) => pxToIn(width)),
|
|
108
108
|
rowH: resolveRowHeights(node).map((height) => pxToIn(height)),
|
|
109
109
|
margin: 0,
|
|
110
110
|
};
|
|
@@ -150,7 +150,7 @@ export function renderPptx(pages, slidePx) {
|
|
|
150
150
|
shape: node.shapeType,
|
|
151
151
|
fontSize: pxToPt(node.fontPx ?? 24),
|
|
152
152
|
fontFace: "Noto Sans JP",
|
|
153
|
-
color: node.
|
|
153
|
+
color: node.color,
|
|
154
154
|
align: node.alignText ?? "center",
|
|
155
155
|
valign: "middle",
|
|
156
156
|
lineSpacingMultiple: 1.3,
|
|
@@ -162,6 +162,25 @@ export function renderPptx(pages, slidePx) {
|
|
|
162
162
|
}
|
|
163
163
|
break;
|
|
164
164
|
}
|
|
165
|
+
case "chart": {
|
|
166
|
+
const chartData = node.data.map((d) => ({
|
|
167
|
+
name: d.name,
|
|
168
|
+
labels: d.labels,
|
|
169
|
+
values: d.values,
|
|
170
|
+
}));
|
|
171
|
+
const chartOptions = {
|
|
172
|
+
x: pxToIn(node.x),
|
|
173
|
+
y: pxToIn(node.y),
|
|
174
|
+
w: pxToIn(node.w),
|
|
175
|
+
h: pxToIn(node.h),
|
|
176
|
+
showLegend: node.showLegend ?? false,
|
|
177
|
+
showTitle: node.showTitle ?? false,
|
|
178
|
+
title: node.title,
|
|
179
|
+
chartColors: node.chartColors,
|
|
180
|
+
};
|
|
181
|
+
slide.addChart(node.chartType, chartData, chartOptions);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
165
184
|
}
|
|
166
185
|
}
|
|
167
186
|
renderNode(data);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type { PositionedNode } from "../types";
|
|
1
|
+
import type { PositionedNode, BulletOptions } from "../types";
|
|
2
2
|
type TextNode = Extract<PositionedNode, {
|
|
3
3
|
type: "text";
|
|
4
4
|
}>;
|
|
5
|
+
type PptxBulletOptions = {
|
|
6
|
+
type?: "bullet" | "number";
|
|
7
|
+
indent?: number;
|
|
8
|
+
numberType?: BulletOptions["numberType"];
|
|
9
|
+
numberStartAt?: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function createBulletOptions(bullet: boolean | BulletOptions): PptxBulletOptions | boolean;
|
|
5
12
|
export declare function createTextOptions(node: TextNode): {
|
|
6
13
|
x: number;
|
|
7
14
|
y: number;
|
|
@@ -15,6 +22,20 @@ export declare function createTextOptions(node: TextNode): {
|
|
|
15
22
|
lineSpacingMultiple: number;
|
|
16
23
|
color: string;
|
|
17
24
|
bold: boolean;
|
|
25
|
+
} | {
|
|
26
|
+
bullet: boolean | PptxBulletOptions;
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
w: number;
|
|
30
|
+
h: number;
|
|
31
|
+
fontSize: number;
|
|
32
|
+
fontFace: string;
|
|
33
|
+
align: "right" | "left" | "center";
|
|
34
|
+
valign: "top";
|
|
35
|
+
margin: number;
|
|
36
|
+
lineSpacingMultiple: number;
|
|
37
|
+
color: string;
|
|
38
|
+
bold: boolean;
|
|
18
39
|
};
|
|
19
40
|
export {};
|
|
20
41
|
//# sourceMappingURL=textOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textOptions.d.ts","sourceRoot":"","sources":["../../src/renderPptx/textOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"textOptions.d.ts","sourceRoot":"","sources":["../../src/renderPptx/textOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9D,KAAK,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D,KAAK,iBAAiB,GAAG;IACvB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,GAAG,aAAa,GAC9B,iBAAiB,GAAG,OAAO,CAqB7B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B/C"}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import { pxToIn, pxToPt } from "./units";
|
|
2
|
+
export function createBulletOptions(bullet) {
|
|
3
|
+
if (typeof bullet === "boolean") {
|
|
4
|
+
return bullet;
|
|
5
|
+
}
|
|
6
|
+
const options = {};
|
|
7
|
+
if (bullet.type !== undefined) {
|
|
8
|
+
options.type = bullet.type;
|
|
9
|
+
}
|
|
10
|
+
if (bullet.indent !== undefined) {
|
|
11
|
+
options.indent = bullet.indent;
|
|
12
|
+
}
|
|
13
|
+
if (bullet.numberType !== undefined) {
|
|
14
|
+
options.numberType = bullet.numberType;
|
|
15
|
+
}
|
|
16
|
+
if (bullet.numberStartAt !== undefined) {
|
|
17
|
+
options.numberStartAt = bullet.numberStartAt;
|
|
18
|
+
}
|
|
19
|
+
return options;
|
|
20
|
+
}
|
|
2
21
|
export function createTextOptions(node) {
|
|
3
22
|
const fontSizePx = node.fontPx ?? 24;
|
|
4
23
|
const fontFamily = node.fontFamily ?? "Noto Sans JP";
|
|
5
24
|
const lineSpacingMultiple = node.lineSpacingMultiple ?? 1.3;
|
|
6
|
-
|
|
25
|
+
const baseOptions = {
|
|
7
26
|
x: pxToIn(node.x),
|
|
8
27
|
y: pxToIn(node.y),
|
|
9
28
|
w: pxToIn(node.w),
|
|
@@ -17,4 +36,11 @@ export function createTextOptions(node) {
|
|
|
17
36
|
color: node.color,
|
|
18
37
|
bold: node.bold,
|
|
19
38
|
};
|
|
39
|
+
if (node.bullet !== undefined) {
|
|
40
|
+
return {
|
|
41
|
+
...baseOptions,
|
|
42
|
+
bullet: createBulletOptions(node.bullet),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return baseOptions;
|
|
20
46
|
}
|
package/dist/table/utils.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import type { TableNode } from "../types";
|
|
2
2
|
export declare const DEFAULT_TABLE_ROW_HEIGHT = 32;
|
|
3
|
+
export declare const DEFAULT_TABLE_COLUMN_WIDTH = 100;
|
|
3
4
|
export declare function calcTableIntrinsicSize(node: TableNode): {
|
|
4
5
|
width: number;
|
|
5
6
|
height: number;
|
|
6
7
|
};
|
|
7
8
|
export declare function resolveRowHeights(node: TableNode): number[];
|
|
9
|
+
/**
|
|
10
|
+
* テーブルの各カラム幅を解決する
|
|
11
|
+
* - 幅が指定されているカラムはその値を使用
|
|
12
|
+
* - 幅が未指定のカラムは、残りの幅を均等分割
|
|
13
|
+
*
|
|
14
|
+
* @param node テーブルノード
|
|
15
|
+
* @param tableWidth テーブル全体の幅(レイアウト計算後の確定値)
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveColumnWidths(node: TableNode, tableWidth: number): number[];
|
|
8
18
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/table/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,wBAAwB,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/table/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS;;;EAQrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,YAGhD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAeV"}
|
package/dist/table/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const DEFAULT_TABLE_ROW_HEIGHT = 32;
|
|
2
|
+
export const DEFAULT_TABLE_COLUMN_WIDTH = 100;
|
|
2
3
|
export function calcTableIntrinsicSize(node) {
|
|
3
|
-
const width = node.columns.reduce((sum, column) => sum + column.width, 0);
|
|
4
|
+
const width = node.columns.reduce((sum, column) => sum + (column.width ?? DEFAULT_TABLE_COLUMN_WIDTH), 0);
|
|
4
5
|
const height = resolveRowHeights(node).reduce((sum, h) => sum + h, 0);
|
|
5
6
|
return { width, height };
|
|
6
7
|
}
|
|
@@ -8,3 +9,19 @@ export function resolveRowHeights(node) {
|
|
|
8
9
|
const fallbackRowHeight = node.defaultRowHeight ?? DEFAULT_TABLE_ROW_HEIGHT;
|
|
9
10
|
return node.rows.map((row) => row.height ?? fallbackRowHeight);
|
|
10
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* テーブルの各カラム幅を解決する
|
|
14
|
+
* - 幅が指定されているカラムはその値を使用
|
|
15
|
+
* - 幅が未指定のカラムは、残りの幅を均等分割
|
|
16
|
+
*
|
|
17
|
+
* @param node テーブルノード
|
|
18
|
+
* @param tableWidth テーブル全体の幅(レイアウト計算後の確定値)
|
|
19
|
+
*/
|
|
20
|
+
export function resolveColumnWidths(node, tableWidth) {
|
|
21
|
+
const specifiedTotal = node.columns.reduce((sum, col) => sum + (col.width ?? 0), 0);
|
|
22
|
+
const unspecifiedCount = node.columns.filter((col) => col.width === undefined).length;
|
|
23
|
+
// 未指定カラムがない場合、または未指定カラムに割り当てる幅を計算
|
|
24
|
+
const remainingWidth = Math.max(0, tableWidth - specifiedTotal);
|
|
25
|
+
const widthPerUnspecified = unspecifiedCount > 0 ? remainingWidth / unspecifiedCount : 0;
|
|
26
|
+
return node.columns.map((col) => col.width ?? widthPerUnspecified);
|
|
27
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,
|
|
1
|
+
{"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CA0FhB"}
|
|
@@ -49,6 +49,15 @@ export function toPositioned(pom, parentX = 0, parentY = 0) {
|
|
|
49
49
|
h: layout.height,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
case "chart": {
|
|
53
|
+
return {
|
|
54
|
+
...pom,
|
|
55
|
+
x: absoluteX,
|
|
56
|
+
y: absoluteY,
|
|
57
|
+
w: layout.width,
|
|
58
|
+
h: layout.height,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
52
61
|
case "box": {
|
|
53
62
|
return {
|
|
54
63
|
...pom,
|