@hirokisakabe/pom 5.1.0 → 5.2.1
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 +10 -11
- package/dist/autoFit/autoFit.d.ts +2 -1
- package/dist/autoFit/autoFit.d.ts.map +1 -1
- package/dist/autoFit/autoFit.js +7 -7
- package/dist/autoFit/strategies/reduceFontSize.js +1 -1
- package/dist/autoFit/strategies/reduceGapAndPadding.js +1 -1
- package/dist/autoFit/strategies/reduceTableRowHeight.js +1 -1
- package/dist/autoFit/strategies/uniformScale.js +1 -1
- package/dist/buildContext.d.ts +12 -0
- package/dist/buildContext.d.ts.map +1 -0
- package/dist/buildContext.js +8 -0
- package/dist/buildPptx.d.ts +1 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +15 -15
- package/dist/calcYogaLayout/calcYogaLayout.d.ts +3 -1
- package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +85 -341
- package/dist/calcYogaLayout/measureText.d.ts +1 -5
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +2 -10
- package/dist/icons/renderIcon.d.ts +1 -1
- package/dist/icons/renderIcon.d.ts.map +1 -1
- package/dist/icons/renderIcon.js +3 -4
- package/dist/parseXml/coercionRules.d.ts +35 -0
- package/dist/parseXml/coercionRules.d.ts.map +1 -0
- package/dist/parseXml/coercionRules.js +477 -0
- package/dist/parseXml/inputSchema.d.ts +326 -64
- package/dist/parseXml/inputSchema.d.ts.map +1 -1
- package/dist/parseXml/inputSchema.js +13 -3
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js +40 -270
- package/dist/registry/definitions/box.d.ts +3 -0
- package/dist/registry/definitions/box.d.ts.map +1 -0
- package/dist/registry/definitions/box.js +6 -0
- package/dist/registry/definitions/chart.d.ts +3 -0
- package/dist/registry/definitions/chart.d.ts.map +1 -0
- package/dist/registry/definitions/chart.js +8 -0
- package/dist/registry/definitions/compositeNodes.d.ts +8 -0
- package/dist/registry/definitions/compositeNodes.d.ts.map +1 -0
- package/dist/registry/definitions/compositeNodes.js +81 -0
- package/dist/registry/definitions/icon.d.ts +3 -0
- package/dist/registry/definitions/icon.d.ts.map +1 -0
- package/dist/registry/definitions/icon.js +28 -0
- package/dist/registry/definitions/image.d.ts +3 -0
- package/dist/registry/definitions/image.d.ts.map +1 -0
- package/dist/registry/definitions/image.js +34 -0
- package/dist/registry/definitions/layer.d.ts +3 -0
- package/dist/registry/definitions/layer.d.ts.map +1 -0
- package/dist/registry/definitions/layer.js +49 -0
- package/dist/registry/definitions/line.d.ts +3 -0
- package/dist/registry/definitions/line.d.ts.map +1 -0
- package/dist/registry/definitions/line.js +26 -0
- package/dist/registry/definitions/list.d.ts +4 -0
- package/dist/registry/definitions/list.d.ts.map +1 -0
- package/dist/registry/definitions/list.js +53 -0
- package/dist/registry/definitions/shape.d.ts +3 -0
- package/dist/registry/definitions/shape.d.ts.map +1 -0
- package/dist/registry/definitions/shape.js +37 -0
- package/dist/registry/definitions/stack.d.ts +4 -0
- package/dist/registry/definitions/stack.d.ts.map +1 -0
- package/dist/registry/definitions/stack.js +78 -0
- package/dist/registry/definitions/table.d.ts +3 -0
- package/dist/registry/definitions/table.d.ts.map +1 -0
- package/dist/registry/definitions/table.js +16 -0
- package/dist/registry/definitions/text.d.ts +3 -0
- package/dist/registry/definitions/text.d.ts.map +1 -0
- package/dist/registry/definitions/text.js +35 -0
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +34 -0
- package/dist/registry/nodeRegistry.d.ts +7 -0
- package/dist/registry/nodeRegistry.d.ts.map +1 -0
- package/dist/registry/nodeRegistry.js +13 -0
- package/dist/registry/types.d.ts +26 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +1 -0
- package/dist/renderPptx/renderPptx.d.ts +2 -1
- package/dist/renderPptx/renderPptx.d.ts.map +1 -1
- package/dist/renderPptx/renderPptx.js +30 -61
- package/dist/renderPptx/types.d.ts +2 -0
- package/dist/renderPptx/types.d.ts.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.js +1 -1
- package/dist/shared/freeYogaTree.d.ts.map +1 -0
- package/dist/shared/measureImage.d.ts +13 -3
- package/dist/shared/measureImage.d.ts.map +1 -1
- package/dist/shared/measureImage.js +14 -19
- package/dist/shared/walkTree.d.ts.map +1 -0
- package/dist/toPositioned/toPositioned.d.ts +8 -1
- package/dist/toPositioned/toPositioned.d.ts.map +1 -1
- package/dist/toPositioned/toPositioned.js +32 -189
- package/dist/types.d.ts +371 -37
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +20 -1
- package/package.json +3 -3
- package/dist/autoFit/freeYogaTree.d.ts.map +0 -1
- package/dist/autoFit/walkTree.d.ts.map +0 -1
- package/dist/renderPptx/nodes/index.d.ts +0 -15
- package/dist/renderPptx/nodes/index.d.ts.map +0 -1
- package/dist/renderPptx/nodes/index.js +0 -14
- /package/dist/{autoFit → shared}/freeYogaTree.d.ts +0 -0
- /package/dist/{autoFit → shared}/freeYogaTree.js +0 -0
- /package/dist/{autoFit → shared}/walkTree.d.ts +0 -0
- /package/dist/{autoFit → shared}/walkTree.js +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { toPositioned, omitYogaNode } from "../../toPositioned/toPositioned.js";
|
|
2
|
+
export const layerNodeDef = {
|
|
3
|
+
type: "layer",
|
|
4
|
+
category: "absolute-child",
|
|
5
|
+
// applyYogaStyle: layer は子を絶対配置するコンテナ。サイズは明示的に指定されることを期待
|
|
6
|
+
toPositioned(pom, absoluteX, absoluteY, layout, ctx) {
|
|
7
|
+
const n = pom;
|
|
8
|
+
// layer の子要素は layer 内の相対座標(child.x, child.y)を持つ
|
|
9
|
+
// layer の絶対座標に加算してスライド上の絶対座標に変換
|
|
10
|
+
return {
|
|
11
|
+
...omitYogaNode(n),
|
|
12
|
+
x: absoluteX,
|
|
13
|
+
y: absoluteY,
|
|
14
|
+
w: layout.width,
|
|
15
|
+
h: layout.height,
|
|
16
|
+
children: n.children.map((child) => {
|
|
17
|
+
const childX = child.x ?? 0;
|
|
18
|
+
const childY = child.y ?? 0;
|
|
19
|
+
// line ノードは特別な処理が必要
|
|
20
|
+
// x1, y1, x2, y2 は layer 内の相対座標として扱い、layer の座標を加算
|
|
21
|
+
if (child.type === "line") {
|
|
22
|
+
const lineAbsoluteX = absoluteX + childX;
|
|
23
|
+
const lineAbsoluteY = absoluteY + childY;
|
|
24
|
+
const adjustedX1 = child.x1 + lineAbsoluteX;
|
|
25
|
+
const adjustedY1 = child.y1 + lineAbsoluteY;
|
|
26
|
+
const adjustedX2 = child.x2 + lineAbsoluteX;
|
|
27
|
+
const adjustedY2 = child.y2 + lineAbsoluteY;
|
|
28
|
+
return {
|
|
29
|
+
...omitYogaNode(child),
|
|
30
|
+
x1: adjustedX1,
|
|
31
|
+
y1: adjustedY1,
|
|
32
|
+
x2: adjustedX2,
|
|
33
|
+
y2: adjustedY2,
|
|
34
|
+
x: Math.min(adjustedX1, adjustedX2),
|
|
35
|
+
y: Math.min(adjustedY1, adjustedY2),
|
|
36
|
+
w: Math.abs(adjustedX2 - adjustedX1),
|
|
37
|
+
h: Math.abs(adjustedY2 - adjustedY1),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// その他のノードは通常の処理
|
|
41
|
+
const childLayout = child.yogaNode.getComputedLayout();
|
|
42
|
+
const adjustedParentX = absoluteX + childX - childLayout.left;
|
|
43
|
+
const adjustedParentY = absoluteY + childY - childLayout.top;
|
|
44
|
+
return toPositioned(child, ctx, adjustedParentX, adjustedParentY);
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
// render: category ベースの子要素再帰で対応
|
|
49
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/line.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,eAAO,MAAM,WAAW,EAAE,cAuBzB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { renderLineNode } from "../../renderPptx/nodes/line.js";
|
|
2
|
+
import { omitYogaNode } from "../../toPositioned/toPositioned.js";
|
|
3
|
+
export const lineNodeDef = {
|
|
4
|
+
type: "line",
|
|
5
|
+
category: "leaf",
|
|
6
|
+
applyYogaStyle(_node, yn) {
|
|
7
|
+
// line ノードは絶対座標を使用するため、Yoga レイアウトではサイズ 0 として扱う
|
|
8
|
+
yn.setWidth(0);
|
|
9
|
+
yn.setHeight(0);
|
|
10
|
+
},
|
|
11
|
+
toPositioned(pom, _absoluteX, _absoluteY, _layout) {
|
|
12
|
+
const n = pom;
|
|
13
|
+
// line ノードは絶対座標(x1, y1, x2, y2)を持つため、
|
|
14
|
+
// yogaNode の座標ではなく自身の座標からバウンディングボックスを計算
|
|
15
|
+
return {
|
|
16
|
+
...omitYogaNode(n),
|
|
17
|
+
x: Math.min(n.x1, n.x2),
|
|
18
|
+
y: Math.min(n.y1, n.y2),
|
|
19
|
+
w: Math.abs(n.x2 - n.x1),
|
|
20
|
+
h: Math.abs(n.y2 - n.y1),
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
render(node, ctx) {
|
|
24
|
+
renderLineNode(node, ctx);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AA0DxD,eAAO,MAAM,SAAS,EAAE,cAOvB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,cAOvB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { measureText } from "../../calcYogaLayout/measureText.js";
|
|
2
|
+
import { measureFontLineHeightRatio } from "../../calcYogaLayout/fontLoader.js";
|
|
3
|
+
import { renderUlNode, renderOlNode } from "../../renderPptx/nodes/list.js";
|
|
4
|
+
function applyListYogaStyle(node, yn, yoga, ctx) {
|
|
5
|
+
const n = node;
|
|
6
|
+
const combinedText = n.items.map((item) => item.text).join("\n");
|
|
7
|
+
const fontSizePx = n.fontSize ?? 24;
|
|
8
|
+
const fontFamily = "Noto Sans JP";
|
|
9
|
+
const fontWeight = n.bold ? "bold" : "normal";
|
|
10
|
+
const spacingMultiple = n.lineHeight ?? 1.3;
|
|
11
|
+
const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);
|
|
12
|
+
const lineHeight = fontMetricsRatio * spacingMultiple;
|
|
13
|
+
// バレット/番号のインデント幅(pptxgenjs DEF_BULLET_MARGIN = 27pt = 36px @96dpi)
|
|
14
|
+
const bulletIndentPx = 36;
|
|
15
|
+
yn.setMeasureFunc((width, widthMode) => {
|
|
16
|
+
const maxWidthPx = (() => {
|
|
17
|
+
switch (widthMode) {
|
|
18
|
+
case yoga.MEASURE_MODE_UNDEFINED:
|
|
19
|
+
return Number.POSITIVE_INFINITY;
|
|
20
|
+
case yoga.MEASURE_MODE_EXACTLY:
|
|
21
|
+
case yoga.MEASURE_MODE_AT_MOST:
|
|
22
|
+
return width;
|
|
23
|
+
}
|
|
24
|
+
})();
|
|
25
|
+
const textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);
|
|
26
|
+
const { widthPx, heightPx } = measureText(combinedText, textMaxWidthPx, {
|
|
27
|
+
fontFamily,
|
|
28
|
+
fontSizePx,
|
|
29
|
+
lineHeight,
|
|
30
|
+
fontWeight,
|
|
31
|
+
}, ctx.textMeasurementMode);
|
|
32
|
+
return {
|
|
33
|
+
width: widthPx + bulletIndentPx,
|
|
34
|
+
height: heightPx,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export const ulNodeDef = {
|
|
39
|
+
type: "ul",
|
|
40
|
+
category: "leaf",
|
|
41
|
+
applyYogaStyle: applyListYogaStyle,
|
|
42
|
+
render(node, ctx) {
|
|
43
|
+
renderUlNode(node, ctx);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
export const olNodeDef = {
|
|
47
|
+
type: "ol",
|
|
48
|
+
category: "leaf",
|
|
49
|
+
applyYogaStyle: applyListYogaStyle,
|
|
50
|
+
render(node, ctx) {
|
|
51
|
+
renderOlNode(node, ctx);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/shape.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAMxD,eAAO,MAAM,YAAY,EAAE,cA0C1B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { measureText } from "../../calcYogaLayout/measureText.js";
|
|
2
|
+
import { renderShapeNode } from "../../renderPptx/nodes/shape.js";
|
|
3
|
+
export const shapeNodeDef = {
|
|
4
|
+
type: "shape",
|
|
5
|
+
category: "leaf",
|
|
6
|
+
applyYogaStyle(node, yn, yoga, ctx) {
|
|
7
|
+
const n = node;
|
|
8
|
+
if (n.text) {
|
|
9
|
+
const text = n.text;
|
|
10
|
+
const fontSizePx = n.fontSize ?? 24;
|
|
11
|
+
const fontFamily = n.fontFamily ?? "Noto Sans JP";
|
|
12
|
+
const fontWeight = n.bold ? "bold" : "normal";
|
|
13
|
+
const lineHeight = n.lineHeight ?? 1.3;
|
|
14
|
+
yn.setMeasureFunc((width, widthMode) => {
|
|
15
|
+
const maxWidthPx = (() => {
|
|
16
|
+
switch (widthMode) {
|
|
17
|
+
case yoga.MEASURE_MODE_UNDEFINED:
|
|
18
|
+
return Number.POSITIVE_INFINITY;
|
|
19
|
+
case yoga.MEASURE_MODE_EXACTLY:
|
|
20
|
+
case yoga.MEASURE_MODE_AT_MOST:
|
|
21
|
+
return width;
|
|
22
|
+
}
|
|
23
|
+
})();
|
|
24
|
+
const { widthPx, heightPx } = measureText(text, maxWidthPx, {
|
|
25
|
+
fontFamily,
|
|
26
|
+
fontSizePx,
|
|
27
|
+
lineHeight,
|
|
28
|
+
fontWeight,
|
|
29
|
+
}, ctx.textMeasurementMode);
|
|
30
|
+
return { width: widthPx, height: heightPx };
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
render(node, ctx) {
|
|
35
|
+
renderShapeNode(node, ctx);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/stack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAuExD,eAAO,MAAM,aAAa,EAAE,cAQ3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,cAQ3B,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vstack/hstack 共通の Flex プロパティを適用する
|
|
3
|
+
*/
|
|
4
|
+
function applyFlexProperties(node, yn, yoga) {
|
|
5
|
+
if (node.gap !== undefined) {
|
|
6
|
+
yn.setGap(yoga.GUTTER_ROW, node.gap);
|
|
7
|
+
yn.setGap(yoga.GUTTER_COLUMN, node.gap);
|
|
8
|
+
}
|
|
9
|
+
if (node.alignItems !== undefined) {
|
|
10
|
+
switch (node.alignItems) {
|
|
11
|
+
case "start":
|
|
12
|
+
yn.setAlignItems(yoga.ALIGN_FLEX_START);
|
|
13
|
+
break;
|
|
14
|
+
case "center":
|
|
15
|
+
yn.setAlignItems(yoga.ALIGN_CENTER);
|
|
16
|
+
break;
|
|
17
|
+
case "end":
|
|
18
|
+
yn.setAlignItems(yoga.ALIGN_FLEX_END);
|
|
19
|
+
break;
|
|
20
|
+
case "stretch":
|
|
21
|
+
yn.setAlignItems(yoga.ALIGN_STRETCH);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (node.justifyContent !== undefined) {
|
|
26
|
+
switch (node.justifyContent) {
|
|
27
|
+
case "start":
|
|
28
|
+
yn.setJustifyContent(yoga.JUSTIFY_FLEX_START);
|
|
29
|
+
break;
|
|
30
|
+
case "center":
|
|
31
|
+
yn.setJustifyContent(yoga.JUSTIFY_CENTER);
|
|
32
|
+
break;
|
|
33
|
+
case "end":
|
|
34
|
+
yn.setJustifyContent(yoga.JUSTIFY_FLEX_END);
|
|
35
|
+
break;
|
|
36
|
+
case "spaceBetween":
|
|
37
|
+
yn.setJustifyContent(yoga.JUSTIFY_SPACE_BETWEEN);
|
|
38
|
+
break;
|
|
39
|
+
case "spaceAround":
|
|
40
|
+
yn.setJustifyContent(yoga.JUSTIFY_SPACE_AROUND);
|
|
41
|
+
break;
|
|
42
|
+
case "spaceEvenly":
|
|
43
|
+
yn.setJustifyContent(yoga.JUSTIFY_SPACE_EVENLY);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (node.flexWrap !== undefined) {
|
|
48
|
+
switch (node.flexWrap) {
|
|
49
|
+
case "nowrap":
|
|
50
|
+
yn.setFlexWrap(yoga.WRAP_NO_WRAP);
|
|
51
|
+
break;
|
|
52
|
+
case "wrap":
|
|
53
|
+
yn.setFlexWrap(yoga.WRAP_WRAP);
|
|
54
|
+
break;
|
|
55
|
+
case "wrapReverse":
|
|
56
|
+
yn.setFlexWrap(yoga.WRAP_WRAP_REVERSE);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export const vstackNodeDef = {
|
|
62
|
+
type: "vstack",
|
|
63
|
+
category: "multi-child",
|
|
64
|
+
applyYogaStyle(node, yn, yoga) {
|
|
65
|
+
yn.setFlexDirection(yoga.FLEX_DIRECTION_COLUMN);
|
|
66
|
+
applyFlexProperties(node, yn, yoga);
|
|
67
|
+
},
|
|
68
|
+
// render: category ベースの子要素再帰で対応
|
|
69
|
+
};
|
|
70
|
+
export const hstackNodeDef = {
|
|
71
|
+
type: "hstack",
|
|
72
|
+
category: "multi-child",
|
|
73
|
+
applyYogaStyle(node, yn, yoga) {
|
|
74
|
+
yn.setFlexDirection(yoga.FLEX_DIRECTION_ROW);
|
|
75
|
+
applyFlexProperties(node, yn, yoga);
|
|
76
|
+
},
|
|
77
|
+
// render: category ベースの子要素再帰で対応
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/table.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,eAAO,MAAM,YAAY,EAAE,cAa1B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { calcTableIntrinsicSize } from "../../shared/tableUtils.js";
|
|
2
|
+
import { renderTableNode } from "../../renderPptx/nodes/table.js";
|
|
3
|
+
export const tableNodeDef = {
|
|
4
|
+
type: "table",
|
|
5
|
+
category: "leaf",
|
|
6
|
+
applyYogaStyle(node, yn) {
|
|
7
|
+
const n = node;
|
|
8
|
+
yn.setMeasureFunc(() => {
|
|
9
|
+
const { width, height } = calcTableIntrinsicSize(n);
|
|
10
|
+
return { width, height };
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
render(node, ctx) {
|
|
14
|
+
renderTableNode(node, ctx);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAMxD,eAAO,MAAM,WAAW,EAAE,cAwCzB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { measureText } from "../../calcYogaLayout/measureText.js";
|
|
2
|
+
import { renderTextNode } from "../../renderPptx/nodes/text.js";
|
|
3
|
+
export const textNodeDef = {
|
|
4
|
+
type: "text",
|
|
5
|
+
category: "leaf",
|
|
6
|
+
applyYogaStyle(node, yn, yoga, ctx) {
|
|
7
|
+
const n = node;
|
|
8
|
+
const text = n.text;
|
|
9
|
+
const fontSizePx = n.fontSize ?? 24;
|
|
10
|
+
const fontFamily = "Noto Sans JP";
|
|
11
|
+
const fontWeight = n.bold ? "bold" : "normal";
|
|
12
|
+
const lineHeight = 1.3;
|
|
13
|
+
yn.setMeasureFunc((width, widthMode) => {
|
|
14
|
+
const maxWidthPx = (() => {
|
|
15
|
+
switch (widthMode) {
|
|
16
|
+
case yoga.MEASURE_MODE_UNDEFINED:
|
|
17
|
+
return Number.POSITIVE_INFINITY;
|
|
18
|
+
case yoga.MEASURE_MODE_EXACTLY:
|
|
19
|
+
case yoga.MEASURE_MODE_AT_MOST:
|
|
20
|
+
return width;
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
const { widthPx, heightPx } = measureText(text, maxWidthPx, {
|
|
24
|
+
fontFamily,
|
|
25
|
+
fontSizePx,
|
|
26
|
+
lineHeight,
|
|
27
|
+
fontWeight,
|
|
28
|
+
}, ctx.textMeasurementMode);
|
|
29
|
+
return { width: widthPx, height: heightPx };
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
render(node, ctx) {
|
|
33
|
+
renderTextNode(node, ctx);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AA0CA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { registerNode } from "./nodeRegistry.js";
|
|
2
|
+
import { textNodeDef } from "./definitions/text.js";
|
|
3
|
+
import { ulNodeDef, olNodeDef } from "./definitions/list.js";
|
|
4
|
+
import { imageNodeDef } from "./definitions/image.js";
|
|
5
|
+
import { tableNodeDef } from "./definitions/table.js";
|
|
6
|
+
import { shapeNodeDef } from "./definitions/shape.js";
|
|
7
|
+
import { chartNodeDef } from "./definitions/chart.js";
|
|
8
|
+
import { iconNodeDef } from "./definitions/icon.js";
|
|
9
|
+
import { lineNodeDef } from "./definitions/line.js";
|
|
10
|
+
import { timelineNodeDef, matrixNodeDef, treeNodeDef, flowNodeDef, processArrowNodeDef, pyramidNodeDef, } from "./definitions/compositeNodes.js";
|
|
11
|
+
import { boxNodeDef } from "./definitions/box.js";
|
|
12
|
+
import { vstackNodeDef, hstackNodeDef } from "./definitions/stack.js";
|
|
13
|
+
import { layerNodeDef } from "./definitions/layer.js";
|
|
14
|
+
// 全ノード定義を登録
|
|
15
|
+
registerNode(textNodeDef);
|
|
16
|
+
registerNode(ulNodeDef);
|
|
17
|
+
registerNode(olNodeDef);
|
|
18
|
+
registerNode(imageNodeDef);
|
|
19
|
+
registerNode(tableNodeDef);
|
|
20
|
+
registerNode(shapeNodeDef);
|
|
21
|
+
registerNode(chartNodeDef);
|
|
22
|
+
registerNode(iconNodeDef);
|
|
23
|
+
registerNode(lineNodeDef);
|
|
24
|
+
registerNode(timelineNodeDef);
|
|
25
|
+
registerNode(matrixNodeDef);
|
|
26
|
+
registerNode(treeNodeDef);
|
|
27
|
+
registerNode(flowNodeDef);
|
|
28
|
+
registerNode(processArrowNodeDef);
|
|
29
|
+
registerNode(pyramidNodeDef);
|
|
30
|
+
registerNode(boxNodeDef);
|
|
31
|
+
registerNode(vstackNodeDef);
|
|
32
|
+
registerNode(hstackNodeDef);
|
|
33
|
+
registerNode(layerNodeDef);
|
|
34
|
+
export { getNodeDef } from "./nodeRegistry.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { POMNode } from "../types.ts";
|
|
2
|
+
import type { NodeDefinition } from "./types.ts";
|
|
3
|
+
type NodeType = POMNode["type"];
|
|
4
|
+
export declare function registerNode(def: NodeDefinition): void;
|
|
5
|
+
export declare function getNodeDef(type: NodeType): NodeDefinition;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=nodeRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeRegistry.d.ts","sourceRoot":"","sources":["../../src/registry/nodeRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAIhC,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAKtD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAIzD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
export function registerNode(def) {
|
|
3
|
+
if (registry.has(def.type)) {
|
|
4
|
+
throw new Error(`Duplicate node registration: ${def.type}`);
|
|
5
|
+
}
|
|
6
|
+
registry.set(def.type, def);
|
|
7
|
+
}
|
|
8
|
+
export function getNodeDef(type) {
|
|
9
|
+
const def = registry.get(type);
|
|
10
|
+
if (!def)
|
|
11
|
+
throw new Error(`Unknown node type: ${type}`);
|
|
12
|
+
return def;
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { POMNode, PositionedNode } from "../types.ts";
|
|
2
|
+
import type { Node as YogaNode } from "yoga-layout";
|
|
3
|
+
import type { RenderContext } from "../renderPptx/types.ts";
|
|
4
|
+
import type { loadYoga } from "yoga-layout/load";
|
|
5
|
+
import type { BuildContext } from "../buildContext.ts";
|
|
6
|
+
export type Yoga = Awaited<ReturnType<typeof loadYoga>>;
|
|
7
|
+
/** ノードのカテゴリ。子要素の扱い方を決定する */
|
|
8
|
+
export type NodeCategory = "leaf" | "single-child" | "multi-child" | "absolute-child";
|
|
9
|
+
export interface NodeDefinition {
|
|
10
|
+
/** ノードタイプ名 */
|
|
11
|
+
type: POMNode["type"];
|
|
12
|
+
/** ノードカテゴリ */
|
|
13
|
+
category: NodeCategory;
|
|
14
|
+
/** YogaNode にノード固有のスタイル/measureFunc を適用する */
|
|
15
|
+
applyYogaStyle?: (node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) => void | Promise<void>;
|
|
16
|
+
/** POMNode → PositionedNode へのカスタム変換(未定義なら category ベースのデフォルト) */
|
|
17
|
+
toPositioned?: (pom: POMNode, absoluteX: number, absoluteY: number, layout: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}, ctx: BuildContext) => PositionedNode;
|
|
21
|
+
/** PositionedNode をスライドにレンダリングする(リーフノード用) */
|
|
22
|
+
render?: (node: PositionedNode, ctx: RenderContext) => void;
|
|
23
|
+
/** 画像ソース収集(prefetch 用) */
|
|
24
|
+
collectImageSources?: (node: POMNode) => string[];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC;AAExD,4BAA4B;AAC5B,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,cAAc,GACd,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,cAAc;IACd,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtB,cAAc;IACd,QAAQ,EAAE,YAAY,CAAC;IAEvB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,YAAY,KACd,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,kEAAkE;IAClE,YAAY,CAAC,EAAE,CACb,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EACzC,GAAG,EAAE,YAAY,KACd,cAAc,CAAC;IAEpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5D,0BAA0B;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;CACnD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PositionedNode, SlideMasterOptions } from "../types.ts";
|
|
2
|
+
import type { BuildContext } from "../buildContext.ts";
|
|
2
3
|
type SlidePx = {
|
|
3
4
|
w: number;
|
|
4
5
|
h: number;
|
|
@@ -10,6 +11,6 @@ type SlidePx = {
|
|
|
10
11
|
* @param master スライドマスターオプション(省略可能)
|
|
11
12
|
* @returns PptxGenJS インスタンス
|
|
12
13
|
*/
|
|
13
|
-
export declare function renderPptx(pages: PositionedNode[], slidePx: SlidePx, master?: SlideMasterOptions): import("pptxgenjs").default;
|
|
14
|
+
export declare function renderPptx(pages: PositionedNode[], slidePx: SlidePx, buildContext: BuildContext, master?: SlideMasterOptions): import("pptxgenjs").default;
|
|
14
15
|
export {};
|
|
15
16
|
//# sourceMappingURL=renderPptx.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAEnB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQvD,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA+JxC;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,YAAY,EAC1B,MAAM,CAAC,EAAE,kBAAkB,+BAsI5B"}
|
|
@@ -9,8 +9,18 @@ import { pxToIn, pxToPt } from "./units.js";
|
|
|
9
9
|
import { convertUnderline, convertStrike } from "./textOptions.js";
|
|
10
10
|
import { getImageData } from "../shared/measureImage.js";
|
|
11
11
|
import { renderBackgroundAndBorder } from "./utils/backgroundBorder.js";
|
|
12
|
-
import {
|
|
12
|
+
import { getNodeDef } from "../registry/index.js";
|
|
13
13
|
const DEFAULT_MASTER_NAME = "POM_MASTER";
|
|
14
|
+
/**
|
|
15
|
+
* zIndex でソートして描画順を制御する(安定ソート)
|
|
16
|
+
* zIndex が小さいノードが先に描画される(PowerPoint は追加順に重ねるため)
|
|
17
|
+
*/
|
|
18
|
+
function sortByZIndex(children) {
|
|
19
|
+
// すべての子要素に zIndex が未設定の場合はそのまま返す
|
|
20
|
+
if (children.every((c) => c.zIndex === undefined))
|
|
21
|
+
return children;
|
|
22
|
+
return [...children].sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0));
|
|
23
|
+
}
|
|
14
24
|
/**
|
|
15
25
|
* MasterObject を pptxgenjs の objects 形式に変換する
|
|
16
26
|
*/
|
|
@@ -155,7 +165,7 @@ function defineSlideMasterFromOptions(pptx, master) {
|
|
|
155
165
|
* @param master スライドマスターオプション(省略可能)
|
|
156
166
|
* @returns PptxGenJS インスタンス
|
|
157
167
|
*/
|
|
158
|
-
export function renderPptx(pages, slidePx, master) {
|
|
168
|
+
export function renderPptx(pages, slidePx, buildContext, master) {
|
|
159
169
|
const slideIn = { w: pxToIn(slidePx.w), h: pxToIn(slidePx.h) }; // layout(=px) → PptxGenJS(=inch) への最終変換
|
|
160
170
|
const pptx = new PptxGenJS();
|
|
161
171
|
pptx.defineLayout({ name: "custom", width: slideIn.w, height: slideIn.h });
|
|
@@ -167,7 +177,7 @@ export function renderPptx(pages, slidePx, master) {
|
|
|
167
177
|
for (const data of pages) {
|
|
168
178
|
// マスターが指定されている場合は masterName を使用
|
|
169
179
|
const slide = masterName ? pptx.addSlide({ masterName }) : pptx.addSlide();
|
|
170
|
-
const ctx = { slide, pptx };
|
|
180
|
+
const ctx = { slide, pptx, buildContext };
|
|
171
181
|
// ルートノードの backgroundColor はスライドの background プロパティとして適用
|
|
172
182
|
// これにより、マスタースライドのオブジェクトを覆い隠さない
|
|
173
183
|
// line ノードは backgroundColor を持たないためスキップ
|
|
@@ -182,7 +192,7 @@ export function renderPptx(pages, slidePx, master) {
|
|
|
182
192
|
// backgroundColor と backgroundImage の両方がある場合、backgroundImage が優先
|
|
183
193
|
const rootBackgroundImage = data.type !== "line" ? data.backgroundImage : undefined;
|
|
184
194
|
if (rootBackgroundImage) {
|
|
185
|
-
const cachedData = getImageData(rootBackgroundImage.src);
|
|
195
|
+
const cachedData = getImageData(rootBackgroundImage.src, buildContext.imageDataCache);
|
|
186
196
|
if (cachedData) {
|
|
187
197
|
slide.background = { data: cachedData };
|
|
188
198
|
}
|
|
@@ -234,69 +244,28 @@ export function renderPptx(pages, slidePx, master) {
|
|
|
234
244
|
renderBackgroundAndBorder(node, ctx);
|
|
235
245
|
}
|
|
236
246
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
renderUlNode(node, ctx);
|
|
243
|
-
break;
|
|
244
|
-
case "ol":
|
|
245
|
-
renderOlNode(node, ctx);
|
|
246
|
-
break;
|
|
247
|
-
case "image":
|
|
248
|
-
renderImageNode(node, ctx);
|
|
249
|
-
break;
|
|
250
|
-
case "icon":
|
|
251
|
-
renderIconNode(node, ctx);
|
|
252
|
-
break;
|
|
253
|
-
case "box":
|
|
254
|
-
// 子要素を再帰的に処理
|
|
255
|
-
renderNode(node.children);
|
|
256
|
-
break;
|
|
257
|
-
case "vstack":
|
|
258
|
-
case "hstack":
|
|
259
|
-
// 子要素を再帰的に処理
|
|
260
|
-
for (const child of node.children) {
|
|
261
|
-
renderNode(child);
|
|
247
|
+
const def = getNodeDef(node.type);
|
|
248
|
+
switch (def.category) {
|
|
249
|
+
case "leaf":
|
|
250
|
+
if (!def.render) {
|
|
251
|
+
throw new Error(`No render function registered for leaf node: ${node.type}`);
|
|
262
252
|
}
|
|
253
|
+
def.render(node, ctx);
|
|
263
254
|
break;
|
|
264
|
-
case "
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
case "shape":
|
|
268
|
-
renderShapeNode(node, ctx);
|
|
255
|
+
case "single-child": {
|
|
256
|
+
const boxNode = node;
|
|
257
|
+
renderNode(boxNode.children);
|
|
269
258
|
break;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
case "matrix":
|
|
277
|
-
renderMatrixNode(node, ctx);
|
|
278
|
-
break;
|
|
279
|
-
case "tree":
|
|
280
|
-
renderTreeNode(node, ctx);
|
|
281
|
-
break;
|
|
282
|
-
case "flow":
|
|
283
|
-
renderFlowNode(node, ctx);
|
|
284
|
-
break;
|
|
285
|
-
case "processArrow":
|
|
286
|
-
renderProcessArrowNode(node, ctx);
|
|
287
|
-
break;
|
|
288
|
-
case "pyramid":
|
|
289
|
-
renderPyramidNode(node, ctx);
|
|
290
|
-
break;
|
|
291
|
-
case "line":
|
|
292
|
-
renderLineNode(node, ctx);
|
|
293
|
-
break;
|
|
294
|
-
case "layer":
|
|
295
|
-
// layer の子要素を配列順に描画(後の要素が上に来る)
|
|
296
|
-
for (const child of node.children) {
|
|
259
|
+
}
|
|
260
|
+
case "multi-child":
|
|
261
|
+
case "absolute-child": {
|
|
262
|
+
const containerNode = node;
|
|
263
|
+
// zIndex でソートして描画順を制御(値が小さいものが先に描画される)
|
|
264
|
+
for (const child of sortByZIndex(containerNode.children)) {
|
|
297
265
|
renderNode(child);
|
|
298
266
|
}
|
|
299
267
|
break;
|
|
268
|
+
}
|
|
300
269
|
}
|
|
301
270
|
}
|
|
302
271
|
renderNode(data, true); // ルートノードとして処理
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { BuildContext } from "../buildContext.ts";
|
|
1
2
|
type PptxGenJSClass = import("pptxgenjs").default;
|
|
2
3
|
export type SlideInstance = ReturnType<PptxGenJSClass["addSlide"]>;
|
|
3
4
|
export type PptxInstance = PptxGenJSClass;
|
|
4
5
|
export type RenderContext = {
|
|
5
6
|
slide: SlideInstance;
|
|
6
7
|
pptx: PptxInstance;
|
|
8
|
+
buildContext: BuildContext;
|
|
7
9
|
};
|
|
8
10
|
export {};
|
|
9
11
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderPptx/types.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG,OAAO,WAAW,EAAE,OAAO,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderPptx/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,KAAK,cAAc,GAAG,OAAO,WAAW,EAAE,OAAO,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backgroundBorder.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/backgroundBorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,aAAa,GACjB,IAAI,
|
|
1
|
+
{"version":3,"file":"backgroundBorder.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/backgroundBorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,aAAa,GACjB,IAAI,CA4HN"}
|