@hirokisakabe/pom 8.9.0 → 9.1.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 +38 -1
- package/dist/autoFit/strategyResult.js.map +1 -1
- package/dist/buildPptx.d.ts +1 -1
- package/dist/calcYogaLayout/fontLoader.js +1 -1
- package/dist/calcYogaLayout/fontLoader.js.map +1 -1
- package/dist/extractSlideMastersAsPptx.d.ts +13 -0
- package/dist/extractSlideMastersAsPptx.d.ts.map +1 -0
- package/dist/extractSlideMastersAsPptx.js +140 -0
- package/dist/extractSlideMastersAsPptx.js.map +1 -0
- package/dist/extractThemeTokensFromPptx.d.ts +13 -0
- package/dist/extractThemeTokensFromPptx.d.ts.map +1 -0
- package/dist/extractThemeTokensFromPptx.js +139 -0
- package/dist/extractThemeTokensFromPptx.js.map +1 -0
- package/dist/icons/index.js +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -1
- package/dist/parseXml/coercionRules.js +1 -1
- package/dist/parseXml/parseXml.js +1 -1
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.js +1 -1
- package/dist/parseXml/serializeXml.js.map +1 -1
- package/dist/pptxLayoutEnumeration.js +152 -0
- package/dist/pptxLayoutEnumeration.js.map +1 -0
- package/dist/registry/definitions/list.js +2 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/registry/definitions/shape.js +3 -2
- package/dist/registry/definitions/shape.js.map +1 -1
- package/dist/registry/definitions/text.js +3 -2
- package/dist/registry/definitions/text.js.map +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/xmlChildRules.js.map +1 -1
- package/dist/renderPptx/glowEffects.js +8 -3
- package/dist/renderPptx/glowEffects.js.map +1 -1
- package/dist/renderPptx/gradientFills.js +1 -1
- package/dist/renderPptx/nodes/timeline.js +2 -1
- package/dist/renderPptx/nodes/timeline.js.map +1 -1
- package/dist/renderPptx/textOptions.js +1 -1
- package/dist/renderPptx/units.js +1 -1
- package/dist/renderPptx/utils/scaleToFit.js +1 -1
- package/dist/renderPptx/utils/straightLine.js +1 -1
- package/dist/renderPptx/utils/visualStyle.js +1 -1
- package/dist/shared/gradient.js +3 -3
- package/dist/shared/gradient.js.map +1 -1
- package/dist/types.d.ts +12 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/registry/definitions/shape.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderShapeNode } from \"../../renderPptx/nodes/shape.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nexport const shapeNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"shape\"),\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"shape\" }>;\n if (n.text) {\n const text = n.text;\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n }\n },\n render(node, ctx) {\n renderShapeNode(node as Extract<typeof node, { type: \"shape\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,MAAa,eAA+B;CAC1C,GAAG,gBAAgB,OAAO;CAC1B,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,IAAI,EAAE,MAAM;GACV,MAAM,OAAO,EAAE;GACf,MAAM,aAAa,EAAE,YAAY;GACjC,MAAM,aAAa,EAAE,cAAc;GACnC,MAAM,aAAa,EAAE,OAAO,SAAS;GACrC,MAAM,aAAa,EAAE,cAAc;GAEnC,GAAG,gBAAgB,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/registry/definitions/shape.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderShapeNode } from \"../../renderPptx/nodes/shape.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nexport const shapeNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"shape\"),\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"shape\" }>;\n if (n.text) {\n const text = n.text;\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n }\n },\n render(node, ctx) {\n renderShapeNode(node as Extract<typeof node, { type: \"shape\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,MAAa,eAA+B;CAC1C,GAAG,gBAAgB,OAAO;CAC1B,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,IAAI,EAAE,MAAM;GACV,MAAM,OAAO,EAAE;GACf,MAAM,aAAa,EAAE,YAAY;GACjC,MAAM,aAAa,EAAE,cAAc;GACnC,MAAM,aAAa,EAAE,OAAO,SAAS;GACrC,MAAM,aAAa,EAAE,cAAc;GAEnC,GAAG,gBAAgB,OAAO,cAAc;IACtC,MAAM,oBAAoB;KACxB,QAAQ,WAAR;MACE,KAAK,KAAK,wBACR,OAAO,OAAO;MAChB,KAAK,KAAK;MACV,KAAK,KAAK,sBACR,OAAO;MACT,SACE,OAAO,OAAO;KAClB;IACF,EAAA,CAAG;IAEH,MAAM,EAAE,SAAS,aAAa,YAC5B,MACA,YACA;KACE;KACA;KACA;KACA;IACF,GACA,IAAI,mBACN;IAEA,OAAO;KAAE,OAAO;KAAS,QAAQ;IAAS;GAC5C,CAAC;EACH;CACF;CACA,OAAO,MAAM,KAAK;EAChB,gBAAgB,MAAiD,GAAG;CACtE;AACF"}
|
|
@@ -14,14 +14,15 @@ const textNodeDef = {
|
|
|
14
14
|
const lineHeight = n.lineHeight ?? 1.3;
|
|
15
15
|
const letterSpacingPx = n.letterSpacing;
|
|
16
16
|
yn.setMeasureFunc((width, widthMode) => {
|
|
17
|
-
const
|
|
17
|
+
const maxWidthPx = (() => {
|
|
18
18
|
switch (widthMode) {
|
|
19
19
|
case yoga.MEASURE_MODE_UNDEFINED: return Number.POSITIVE_INFINITY;
|
|
20
20
|
case yoga.MEASURE_MODE_EXACTLY:
|
|
21
21
|
case yoga.MEASURE_MODE_AT_MOST: return width;
|
|
22
22
|
default: return Number.POSITIVE_INFINITY;
|
|
23
23
|
}
|
|
24
|
-
})()
|
|
24
|
+
})();
|
|
25
|
+
const { widthPx, heightPx } = measureText(text, maxWidthPx, {
|
|
25
26
|
fontFamily,
|
|
26
27
|
fontSizePx,
|
|
27
28
|
lineHeight,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","names":[],"sources":["../../../src/registry/definitions/text.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderTextNode } from \"../../renderPptx/nodes/text.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nexport const textNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"text\"),\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"text\" }>;\n const text = n.text;\n const baseFontSizePx = n.fontSize ?? 24;\n // runs に fontSize override がある場合は最大値で計測する(描画は run 単位で\n // 各自の fontSize が適用されるが、計測関数は単一 fontSize しか扱えないので\n // 最大値を採用して縦方向の clipping を防ぐ。\n // 横方向は最大値だと過剰評価になるが、典型ケース (大きな数字 + 小さい単位)\n // では小さい unit 部分が短く影響は軽微で、安全側に倒す)\n const fontSizePx = Math.max(\n baseFontSizePx,\n ...(n.runs?.map((r) => r.fontSize ?? baseFontSizePx) ?? []),\n );\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n const letterSpacingPx = n.letterSpacing;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n letterSpacingPx,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n },\n render(node, ctx) {\n renderTextNode(node as Extract<typeof node, { type: \"text\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,MAAa,cAA8B;CACzC,GAAG,gBAAgB,MAAM;CACzB,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,MAAM,OAAO,EAAE;EACf,MAAM,iBAAiB,EAAE,YAAY;EAMrC,MAAM,aAAa,KAAK,IACtB,gBACA,GAAI,EAAE,MAAM,KAAK,MAAM,EAAE,YAAY,cAAc,KAAK,CAAC,CAC3D;EACA,MAAM,aAAa,EAAE,cAAc;EACnC,MAAM,aAAa,EAAE,OAAO,SAAS;EACrC,MAAM,aAAa,EAAE,cAAc;EACnC,MAAM,kBAAkB,EAAE;EAE1B,GAAG,gBAAgB,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"text.js","names":[],"sources":["../../../src/registry/definitions/text.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderTextNode } from \"../../renderPptx/nodes/text.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nexport const textNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"text\"),\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"text\" }>;\n const text = n.text;\n const baseFontSizePx = n.fontSize ?? 24;\n // runs に fontSize override がある場合は最大値で計測する(描画は run 単位で\n // 各自の fontSize が適用されるが、計測関数は単一 fontSize しか扱えないので\n // 最大値を採用して縦方向の clipping を防ぐ。\n // 横方向は最大値だと過剰評価になるが、典型ケース (大きな数字 + 小さい単位)\n // では小さい unit 部分が短く影響は軽微で、安全側に倒す)\n const fontSizePx = Math.max(\n baseFontSizePx,\n ...(n.runs?.map((r) => r.fontSize ?? baseFontSizePx) ?? []),\n );\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n const letterSpacingPx = n.letterSpacing;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n letterSpacingPx,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n },\n render(node, ctx) {\n renderTextNode(node as Extract<typeof node, { type: \"text\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,MAAa,cAA8B;CACzC,GAAG,gBAAgB,MAAM;CACzB,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,MAAM,OAAO,EAAE;EACf,MAAM,iBAAiB,EAAE,YAAY;EAMrC,MAAM,aAAa,KAAK,IACtB,gBACA,GAAI,EAAE,MAAM,KAAK,MAAM,EAAE,YAAY,cAAc,KAAK,CAAC,CAC3D;EACA,MAAM,aAAa,EAAE,cAAc;EACnC,MAAM,aAAa,EAAE,OAAO,SAAS;EACrC,MAAM,aAAa,EAAE,cAAc;EACnC,MAAM,kBAAkB,EAAE;EAE1B,GAAG,gBAAgB,OAAO,cAAc;GACtC,MAAM,oBAAoB;IACxB,QAAQ,WAAR;KACE,KAAK,KAAK,wBACR,OAAO,OAAO;KAChB,KAAK,KAAK;KACV,KAAK,KAAK,sBACR,OAAO;KACT,SACE,OAAO,OAAO;IAClB;GACF,EAAA,CAAG;GAEH,MAAM,EAAE,SAAS,aAAa,YAC5B,MACA,YACA;IACE;IACA;IACA;IACA;IACA;GACF,GACA,IAAI,mBACN;GAEA,OAAO;IAAE,OAAO;IAAS,QAAQ;GAAS;EAC5C,CAAC;CACH;CACA,OAAO,MAAM,KAAK;EAChB,eAAe,MAAgD,GAAG;CACpE;AACF"}
|
package/dist/registry/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerNode } from "./nodeRegistry.js";
|
|
1
|
+
import { getNodeDef, registerNode } from "./nodeRegistry.js";
|
|
2
2
|
import { textNodeDef } from "./definitions/text.js";
|
|
3
3
|
import { olNodeDef, ulNodeDef } from "./definitions/list.js";
|
|
4
4
|
import { imageNodeDef } from "./definitions/image.js";
|
|
@@ -34,6 +34,6 @@ registerNode(hstackNodeDef);
|
|
|
34
34
|
registerNode(layerNodeDef);
|
|
35
35
|
registerNode(svgNodeDef);
|
|
36
36
|
//#endregion
|
|
37
|
-
export {};
|
|
37
|
+
export { getNodeDef };
|
|
38
38
|
|
|
39
39
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xmlChildRules.js","names":[],"sources":["../../src/registry/xmlChildRules.ts"],"sourcesContent":["/**\n * parseXml / serializeXml が共有する XML child handling のルール定義。\n *\n * - インライン装飾タグ (B/I/A/U/S/Sub/Sup/Mark/Span) と TextRun property の対応\n * - ノードごとの XML child element 受け入れルール (XmlChildRule)\n *\n * parse 側 (parseXml.ts) と serialize 側 (serializeXml.ts) の双方がこの\n * モジュールを参照することで、タグ名・対応 property・許容 child のズレを防ぐ。\n * 依存方向は parseXml / serializeXml → registry の一方向に保つ(このモジュール\n * からは parseXml / serializeXml を import しない)。\n */\n\n// ===== インライン装飾 (B/I/A/U/S/Sub/Sup/Mark/Span) =====\n\n/** Text / Shape / Li / Td 内のインライン装飾を表すテキスト run */\nexport interface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n subscript?: boolean;\n superscript?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n fontSize?: number;\n letterSpacing?: number;\n}\n\n/**\n * boolean 装飾タグ ↔ TextRun property の対応。\n * 配列の順序は serialize 時のネスト順(先頭が最も外側)。\n */\nexport const INLINE_BOOLEAN_FORMATS: readonly {\n readonly tag: string;\n readonly property:\n
|
|
1
|
+
{"version":3,"file":"xmlChildRules.js","names":[],"sources":["../../src/registry/xmlChildRules.ts"],"sourcesContent":["/**\n * parseXml / serializeXml が共有する XML child handling のルール定義。\n *\n * - インライン装飾タグ (B/I/A/U/S/Sub/Sup/Mark/Span) と TextRun property の対応\n * - ノードごとの XML child element 受け入れルール (XmlChildRule)\n *\n * parse 側 (parseXml.ts) と serialize 側 (serializeXml.ts) の双方がこの\n * モジュールを参照することで、タグ名・対応 property・許容 child のズレを防ぐ。\n * 依存方向は parseXml / serializeXml → registry の一方向に保つ(このモジュール\n * からは parseXml / serializeXml を import しない)。\n */\n\n// ===== インライン装飾 (B/I/A/U/S/Sub/Sup/Mark/Span) =====\n\n/** Text / Shape / Li / Td 内のインライン装飾を表すテキスト run */\nexport interface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n subscript?: boolean;\n superscript?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n fontSize?: number;\n letterSpacing?: number;\n}\n\n/**\n * boolean 装飾タグ ↔ TextRun property の対応。\n * 配列の順序は serialize 時のネスト順(先頭が最も外側)。\n */\nexport const INLINE_BOOLEAN_FORMATS: readonly {\n readonly tag: string;\n readonly property:\n \"bold\" | \"italic\" | \"underline\" | \"strike\" | \"subscript\" | \"superscript\";\n}[] = [\n { tag: \"B\", property: \"bold\" },\n { tag: \"I\", property: \"italic\" },\n { tag: \"U\", property: \"underline\" },\n { tag: \"S\", property: \"strike\" },\n { tag: \"Sub\", property: \"subscript\" },\n { tag: \"Sup\", property: \"superscript\" },\n];\n\n/** ハイパーリンクタグ。href 属性 → TextRun.href */\nexport const INLINE_LINK_TAG = \"A\";\n\n/** ハイライトタグ。color 属性 → TextRun.highlight(省略時は既定色) */\nexport const INLINE_MARK_TAG = \"Mark\";\n\n/** Mark の color 属性省略時に適用される既定のハイライト色 */\nexport const MARK_DEFAULT_HIGHLIGHT_COLOR = \"FFFF00\";\n\n/** 文字スタイルタグ。color / fontFamily / fontSize / letterSpacing 属性 → TextRun の同名 property */\nexport const INLINE_SPAN_TAG = \"Span\";\n\n/** インライン装飾として許容されるタグの一覧(エラーメッセージの列挙順) */\nexport const INLINE_FORMAT_TAG_LIST: readonly string[] = [\n \"B\",\n \"I\",\n \"A\",\n \"U\",\n \"S\",\n \"Sub\",\n \"Sup\",\n \"Mark\",\n \"Span\",\n];\n\n/** インライン装飾タグの集合(child element 判定用) */\nexport const INLINE_FORMAT_TAGS: ReadonlySet<string> = new Set(\n INLINE_FORMAT_TAG_LIST,\n);\n\n// ===== XML child element 受け入れルール =====\n\n/**\n * インライン装飾タグ (B/I/A/U/S/Mark/Span) のみを child として受け付け、\n * runs / text property へ変換するルール(Text 用)\n */\nexport interface InlineRunsChildRule {\n kind: \"inline-runs\";\n}\n\n/** 単一種類の child tag の繰り返しを受け取り、配列 property へ変換するルール */\nexport interface RepeatedChildRule {\n kind: \"repeated\";\n /** 受け付ける child tag 名 */\n childTag: string;\n /** 変換結果を格納する property 名 */\n property: string;\n /** 各 item が text content / インライン装飾タグを受け付けるか(Li 用) */\n allowsItemText?: boolean;\n}\n\n/**\n * parseXml 側の専用 converter で処理する複雑な child 構造\n * (ネスト構造や複数 property への振り分けを伴うもの)\n */\nexport interface NodeSpecificChildRule {\n kind: \"node-specific\";\n /** 直下で受け付ける child tag 名の一覧(unknown child エラーメッセージに使用) */\n expectedTags: readonly string[];\n}\n\nexport type XmlChildRule =\n InlineRunsChildRule | RepeatedChildRule | NodeSpecificChildRule;\n\n/**\n * unknown child エラーメッセージ用に期待タグ一覧を整形する。\n * 例: [\"A\"] → \"<A>\" / [\"A\",\"B\"] → \"<A> or <B>\" / [\"A\",\"B\",\"C\"] → \"<A>, <B>, or <C>\"\n */\nexport function formatExpectedTags(tags: readonly string[]): string {\n const wrapped = tags.map((tag) => `<${tag}>`);\n if (wrapped.length === 1) return wrapped[0];\n if (wrapped.length === 2) return `${wrapped[0]} or ${wrapped[1]}`;\n return `${wrapped.slice(0, -1).join(\", \")}, or ${wrapped[wrapped.length - 1]}`;\n}\n"],"mappings":";;;;;AAmCA,MAAa,yBAIP;CACJ;EAAE,KAAK;EAAK,UAAU;CAAO;CAC7B;EAAE,KAAK;EAAK,UAAU;CAAS;CAC/B;EAAE,KAAK;EAAK,UAAU;CAAY;CAClC;EAAE,KAAK;EAAK,UAAU;CAAS;CAC/B;EAAE,KAAK;EAAO,UAAU;CAAY;CACpC;EAAE,KAAK;EAAO,UAAU;CAAc;AACxC;;AAMA,MAAa,kBAAkB;;AAG/B,MAAa,+BAA+B;;AAG5C,MAAa,kBAAkB;;AAG/B,MAAa,yBAA4C;CACvD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,qBAA0C,IAAI,IACzD,sBACF;;;;;AAwCA,SAAgB,mBAAmB,MAAiC;CAClE,MAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,IAAI,EAAE;CAC5C,IAAI,QAAQ,WAAW,GAAG,OAAO,QAAQ;CACzC,IAAI,QAAQ,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,QAAQ;CAC7D,OAAO,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,OAAO,QAAQ,QAAQ,SAAS;AAC5E"}
|
|
@@ -27,7 +27,8 @@ var GlowEffectRegistry = class {
|
|
|
27
27
|
});
|
|
28
28
|
const existing = this.markerBySpec.get(specKey);
|
|
29
29
|
if (existing) return existing;
|
|
30
|
-
const
|
|
30
|
+
const index = this.registered.length;
|
|
31
|
+
const marker = `${MARKER_PREFIX}${index}`;
|
|
31
32
|
this.markerBySpec.set(specKey, marker);
|
|
32
33
|
this.registered.push({
|
|
33
34
|
marker,
|
|
@@ -81,7 +82,11 @@ function applyGlowToXml(xml, registry) {
|
|
|
81
82
|
result = result.replace(re, (_match, prefix, suffix) => {
|
|
82
83
|
const block = prefix;
|
|
83
84
|
const closingIdx = block.lastIndexOf("</a:effectLst>");
|
|
84
|
-
if (closingIdx >= 0)
|
|
85
|
+
if (closingIdx >= 0) {
|
|
86
|
+
const before = block.substring(0, closingIdx);
|
|
87
|
+
const after = block.substring(closingIdx);
|
|
88
|
+
return `${before}${glowXml}${after}${suffix}`;
|
|
89
|
+
}
|
|
85
90
|
return `${block}<a:effectLst>${glowXml}</a:effectLst>${suffix}`;
|
|
86
91
|
});
|
|
87
92
|
}
|
|
@@ -142,6 +147,6 @@ function patchPptxWriteForGlowEffects(pptx, registry) {
|
|
|
142
147
|
pptx.writeFile = patchedWriteFile;
|
|
143
148
|
}
|
|
144
149
|
//#endregion
|
|
145
|
-
export { GlowEffectRegistry, patchPptxWriteForGlowEffects };
|
|
150
|
+
export { GlowEffectRegistry, applyGlowEffects, patchPptxWriteForGlowEffects };
|
|
146
151
|
|
|
147
152
|
//# sourceMappingURL=glowEffects.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glowEffects.js","names":[],"sources":["../../src/renderPptx/glowEffects.ts"],"sourcesContent":["/**\n * Shape / Icon の glow (光彩) 効果の実現\n *\n * pptxgenjs の Shape options には glow 相当のネイティブサポートがないため\n * (TextPropsOptions の glow は文字グリフ用)、以下の方式で実現する:\n *\n * 1. レンダリング時: glow 指定のある shape に一意なマーカー名を `objectName`\n * として埋め込み、レジストリに登録する。マーカー名は `<p:cNvPr name=\"...\"/>`\n * として PPTX 出力 XML に書き込まれる。\n * 2. 出力時: pptx.write() / writeFile() をラップし、出力 zip 内のスライド XML\n * の該当 `<p:sp>` の `<p:spPr>` 末尾に DrawingML ネイティブの\n * `<a:effectLst><a:glow>...</a:glow></a:effectLst>` を挿入する。\n *\n * 文字列置換採用理由 / 注意点は gradientFills.ts と同様。\n */\nimport type { TextGlow } from \"../types.ts\";\nimport { pxToEmu } from \"./units.ts\";\n\ntype PptxGenJSInstance = import(\"pptxgenjs\").default;\ntype WriteProps = NonNullable<Parameters<PptxGenJSInstance[\"write\"]>[0]>;\ntype WriteFileProps = NonNullable<\n Parameters<PptxGenJSInstance[\"writeFile\"]>[0]\n>;\n\nasync function loadJSZip(): Promise<typeof import(\"jszip\")> {\n const mod = await import(\"jszip\");\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */\n return (mod as any).default ?? mod;\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */\n}\n\ninterface RegisteredGlow {\n /** objectName に埋め込むマーカー文字列 */\n marker: string;\n /** size (px) — XML 出力時に EMU に変換する */\n sizePx: number;\n /** opacity 0-1 */\n opacity: number;\n /** 6桁 HEX (# なし、大文字) */\n color: string;\n}\n\nconst MARKER_PREFIX = \"pom-glow:\";\n\n/**\n * glow 仕様を一意なマーカー名にマップし、後処理で\n * `<a:effectLst><a:glow>` 要素として挿入できるようにするレジストリ\n */\nexport class GlowEffectRegistry {\n private readonly markerBySpec = new Map<string, string>();\n private readonly registered: RegisteredGlow[] = [];\n\n /**\n * glow を登録し、`objectName` に渡すマーカー文字列を返す。\n * 同じ仕様の glow は同じマーカーを返す。\n */\n register(glow: TextGlow): string {\n const sizePx = glow.size ?? 8;\n const opacity = glow.opacity ?? 0.75;\n const color = (glow.color ?? \"FFFFFF\").replace(/^#/, \"\").toUpperCase();\n const specKey = JSON.stringify({ sizePx, opacity, color });\n const existing = this.markerBySpec.get(specKey);\n if (existing) return existing;\n\n const index = this.registered.length;\n const marker = `${MARKER_PREFIX}${index}`;\n this.markerBySpec.set(specKey, marker);\n this.registered.push({ marker, sizePx, opacity, color });\n return marker;\n }\n\n get isEmpty(): boolean {\n return this.registered.length === 0;\n }\n\n get entries(): readonly RegisteredGlow[] {\n return this.registered;\n }\n}\n\n/**\n * DrawingML の `<a:glow>` 要素を構築する (effectLst で囲まない、内側だけ)\n *\n * - rad (光彩半径): px → EMU\n * - alpha (透明度): 0-1 → 1/1000 % (0-100000)\n */\nfunction buildGlowXml(entry: RegisteredGlow): string {\n const rad = Math.round(pxToEmu(entry.sizePx));\n const alpha = Math.round(entry.opacity * 100000);\n return `<a:glow rad=\"${rad}\"><a:srgbClr val=\"${entry.color}\"><a:alpha val=\"${alpha}\"/></a:srgbClr></a:glow>`;\n}\n\n/**\n * 1 つの slide XML を受け取り、登録された glow を該当 shape に適用した XML を返す\n *\n * `<p:cNvPr ... name=\"pom-glow:N\">` を含む `<p:sp>` ブロックを正規表現で検出し、\n * 以下のいずれかで `<a:glow>` を挿入する:\n *\n * 1. 既に `<a:effectLst>...</a:effectLst>` が存在する場合\n * (= pptxgenjs が shape の `shadow` 等で同要素を生成済み):\n * その `effectLst` 内側の末尾 (`</a:effectLst>` の直前) に `<a:glow>` を追加する。\n * OOXML スキーマ上 `<p:spPr>` 内の `<a:effectLst>` は最大 1 個までで、二重に\n * 並べると不正になるため。\n * 2. 既存 `effectLst` が無い場合:\n * `</p:spPr>` の直前に新規 `<a:effectLst><a:glow/></a:effectLst>` を挿入する。\n *\n * pptxgenjs は cNvPr を `<p:cNvPr.../>` (self-closing) と\n * `<p:cNvPr...></p:cNvPr>` (open+close) のどちらの形式でも出力し得るため、\n * cNvPr の閉じ形式に依存せず name 属性のあとから lazy に進める。\n */\nfunction applyGlowToXml(xml: string, registry: GlowEffectRegistry): string {\n let result = xml;\n for (const entry of registry.entries) {\n const glowXml = buildGlowXml(entry);\n const re = new RegExp(\n `(<p:cNvPr[^>]*name=\"${entry.marker}\"[\\\\s\\\\S]*?)(</p:spPr>)`,\n \"g\",\n );\n result = result.replace(re, (_match, prefix, suffix) => {\n const block = prefix as string;\n // shape ブロック内に既存の effectLst があるかを `</a:effectLst>` の有無で判定する。\n // 別 shape の effectLst を誤って書き換えないよう、検索範囲は prefix\n // (= 該当 cNvPr 〜 直後の </p:spPr> の手前まで) に限定している。\n const closingIdx = block.lastIndexOf(\"</a:effectLst>\");\n if (closingIdx >= 0) {\n const before = block.substring(0, closingIdx);\n const after = block.substring(closingIdx);\n return `${before}${glowXml}${after}${suffix as string}`;\n }\n return `${block}<a:effectLst>${glowXml}</a:effectLst>${suffix as string}`;\n });\n }\n return result;\n}\n\n/**\n * 出力 zip 内のスライド XML に glow 効果を挿入する\n */\nexport async function applyGlowEffects(\n data: Uint8Array | ArrayBuffer,\n registry: GlowEffectRegistry,\n): Promise<import(\"jszip\")> {\n const JSZip = await loadJSZip();\n const zip = await JSZip.loadAsync(data);\n\n const slidePaths = Object.keys(zip.files).filter((path) =>\n /^ppt\\/slides\\/slide\\d+\\.xml$/.test(path),\n );\n for (const path of slidePaths) {\n const file = zip.file(path);\n if (!file) continue;\n const original = await file.async(\"text\");\n const replaced = applyGlowToXml(original, registry);\n if (replaced !== original) {\n zip.file(path, replaced);\n }\n }\n return zip;\n}\n\n/**\n * pptx インスタンスの write / writeFile をラップし、出力時に glow 後処理を適用する。\n *\n * 既に他の後処理 (gradientFills 等) によりラップされている場合に備え、\n * 元の関数を保存してチェーン可能にしている。\n */\nexport function patchPptxWriteForGlowEffects(\n pptx: PptxGenJSInstance,\n registry: GlowEffectRegistry,\n): void {\n if (registry.isEmpty) return;\n\n const originalWrite = pptx.write.bind(pptx);\n const originalWriteFile = pptx.writeFile.bind(pptx);\n\n const patchedWrite = async (rawProps?: WriteProps | string) => {\n const props: WriteProps | undefined =\n typeof rawProps === \"string\"\n ? ({ outputType: rawProps } as WriteProps)\n : rawProps;\n const data = (await originalWrite({\n outputType: \"uint8array\",\n })) as Uint8Array;\n const zip = await applyGlowEffects(data, registry);\n\n const outputType = props?.outputType;\n if (outputType === \"STREAM\") {\n return zip.generateAsync({\n type: \"nodebuffer\",\n compression: props?.compression ? \"DEFLATE\" : \"STORE\",\n });\n }\n if (outputType) {\n return zip.generateAsync({ type: outputType });\n }\n return zip.generateAsync({\n type: \"blob\",\n compression: props?.compression ? \"DEFLATE\" : \"STORE\",\n });\n };\n pptx.write = patchedWrite;\n\n const patchedWriteFile = async (rawProps?: WriteFileProps | string) => {\n const props: WriteFileProps | undefined =\n typeof rawProps === \"string\" ? { fileName: rawProps } : rawProps;\n const isNode =\n typeof process !== \"undefined\" && Boolean(process.versions?.node);\n if (!isNode) {\n return originalWriteFile(props);\n }\n const rawName = props?.fileName ?? \"Presentation.pptx\";\n const fileName = rawName.toLowerCase().endsWith(\".pptx\")\n ? rawName\n : `${rawName}.pptx`;\n const buffer = (await patchedWrite({\n outputType: \"nodebuffer\",\n compression: props?.compression,\n })) as Buffer;\n const fs = await import(\"fs\");\n await fs.promises.writeFile(fileName, buffer);\n return fileName;\n };\n pptx.writeFile = patchedWriteFile;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"glowEffects.js","names":[],"sources":["../../src/renderPptx/glowEffects.ts"],"sourcesContent":["/**\n * Shape / Icon の glow (光彩) 効果の実現\n *\n * pptxgenjs の Shape options には glow 相当のネイティブサポートがないため\n * (TextPropsOptions の glow は文字グリフ用)、以下の方式で実現する:\n *\n * 1. レンダリング時: glow 指定のある shape に一意なマーカー名を `objectName`\n * として埋め込み、レジストリに登録する。マーカー名は `<p:cNvPr name=\"...\"/>`\n * として PPTX 出力 XML に書き込まれる。\n * 2. 出力時: pptx.write() / writeFile() をラップし、出力 zip 内のスライド XML\n * の該当 `<p:sp>` の `<p:spPr>` 末尾に DrawingML ネイティブの\n * `<a:effectLst><a:glow>...</a:glow></a:effectLst>` を挿入する。\n *\n * 文字列置換採用理由 / 注意点は gradientFills.ts と同様。\n */\nimport type { TextGlow } from \"../types.ts\";\nimport { pxToEmu } from \"./units.ts\";\n\ntype PptxGenJSInstance = import(\"pptxgenjs\").default;\ntype WriteProps = NonNullable<Parameters<PptxGenJSInstance[\"write\"]>[0]>;\ntype WriteFileProps = NonNullable<\n Parameters<PptxGenJSInstance[\"writeFile\"]>[0]\n>;\n\nasync function loadJSZip(): Promise<typeof import(\"jszip\")> {\n const mod = await import(\"jszip\");\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */\n return (mod as any).default ?? mod;\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return */\n}\n\ninterface RegisteredGlow {\n /** objectName に埋め込むマーカー文字列 */\n marker: string;\n /** size (px) — XML 出力時に EMU に変換する */\n sizePx: number;\n /** opacity 0-1 */\n opacity: number;\n /** 6桁 HEX (# なし、大文字) */\n color: string;\n}\n\nconst MARKER_PREFIX = \"pom-glow:\";\n\n/**\n * glow 仕様を一意なマーカー名にマップし、後処理で\n * `<a:effectLst><a:glow>` 要素として挿入できるようにするレジストリ\n */\nexport class GlowEffectRegistry {\n private readonly markerBySpec = new Map<string, string>();\n private readonly registered: RegisteredGlow[] = [];\n\n /**\n * glow を登録し、`objectName` に渡すマーカー文字列を返す。\n * 同じ仕様の glow は同じマーカーを返す。\n */\n register(glow: TextGlow): string {\n const sizePx = glow.size ?? 8;\n const opacity = glow.opacity ?? 0.75;\n const color = (glow.color ?? \"FFFFFF\").replace(/^#/, \"\").toUpperCase();\n const specKey = JSON.stringify({ sizePx, opacity, color });\n const existing = this.markerBySpec.get(specKey);\n if (existing) return existing;\n\n const index = this.registered.length;\n const marker = `${MARKER_PREFIX}${index}`;\n this.markerBySpec.set(specKey, marker);\n this.registered.push({ marker, sizePx, opacity, color });\n return marker;\n }\n\n get isEmpty(): boolean {\n return this.registered.length === 0;\n }\n\n get entries(): readonly RegisteredGlow[] {\n return this.registered;\n }\n}\n\n/**\n * DrawingML の `<a:glow>` 要素を構築する (effectLst で囲まない、内側だけ)\n *\n * - rad (光彩半径): px → EMU\n * - alpha (透明度): 0-1 → 1/1000 % (0-100000)\n */\nfunction buildGlowXml(entry: RegisteredGlow): string {\n const rad = Math.round(pxToEmu(entry.sizePx));\n const alpha = Math.round(entry.opacity * 100000);\n return `<a:glow rad=\"${rad}\"><a:srgbClr val=\"${entry.color}\"><a:alpha val=\"${alpha}\"/></a:srgbClr></a:glow>`;\n}\n\n/**\n * 1 つの slide XML を受け取り、登録された glow を該当 shape に適用した XML を返す\n *\n * `<p:cNvPr ... name=\"pom-glow:N\">` を含む `<p:sp>` ブロックを正規表現で検出し、\n * 以下のいずれかで `<a:glow>` を挿入する:\n *\n * 1. 既に `<a:effectLst>...</a:effectLst>` が存在する場合\n * (= pptxgenjs が shape の `shadow` 等で同要素を生成済み):\n * その `effectLst` 内側の末尾 (`</a:effectLst>` の直前) に `<a:glow>` を追加する。\n * OOXML スキーマ上 `<p:spPr>` 内の `<a:effectLst>` は最大 1 個までで、二重に\n * 並べると不正になるため。\n * 2. 既存 `effectLst` が無い場合:\n * `</p:spPr>` の直前に新規 `<a:effectLst><a:glow/></a:effectLst>` を挿入する。\n *\n * pptxgenjs は cNvPr を `<p:cNvPr.../>` (self-closing) と\n * `<p:cNvPr...></p:cNvPr>` (open+close) のどちらの形式でも出力し得るため、\n * cNvPr の閉じ形式に依存せず name 属性のあとから lazy に進める。\n */\nfunction applyGlowToXml(xml: string, registry: GlowEffectRegistry): string {\n let result = xml;\n for (const entry of registry.entries) {\n const glowXml = buildGlowXml(entry);\n const re = new RegExp(\n `(<p:cNvPr[^>]*name=\"${entry.marker}\"[\\\\s\\\\S]*?)(</p:spPr>)`,\n \"g\",\n );\n result = result.replace(re, (_match, prefix, suffix) => {\n const block = prefix as string;\n // shape ブロック内に既存の effectLst があるかを `</a:effectLst>` の有無で判定する。\n // 別 shape の effectLst を誤って書き換えないよう、検索範囲は prefix\n // (= 該当 cNvPr 〜 直後の </p:spPr> の手前まで) に限定している。\n const closingIdx = block.lastIndexOf(\"</a:effectLst>\");\n if (closingIdx >= 0) {\n const before = block.substring(0, closingIdx);\n const after = block.substring(closingIdx);\n return `${before}${glowXml}${after}${suffix as string}`;\n }\n return `${block}<a:effectLst>${glowXml}</a:effectLst>${suffix as string}`;\n });\n }\n return result;\n}\n\n/**\n * 出力 zip 内のスライド XML に glow 効果を挿入する\n */\nexport async function applyGlowEffects(\n data: Uint8Array | ArrayBuffer,\n registry: GlowEffectRegistry,\n): Promise<import(\"jszip\")> {\n const JSZip = await loadJSZip();\n const zip = await JSZip.loadAsync(data);\n\n const slidePaths = Object.keys(zip.files).filter((path) =>\n /^ppt\\/slides\\/slide\\d+\\.xml$/.test(path),\n );\n for (const path of slidePaths) {\n const file = zip.file(path);\n if (!file) continue;\n const original = await file.async(\"text\");\n const replaced = applyGlowToXml(original, registry);\n if (replaced !== original) {\n zip.file(path, replaced);\n }\n }\n return zip;\n}\n\n/**\n * pptx インスタンスの write / writeFile をラップし、出力時に glow 後処理を適用する。\n *\n * 既に他の後処理 (gradientFills 等) によりラップされている場合に備え、\n * 元の関数を保存してチェーン可能にしている。\n */\nexport function patchPptxWriteForGlowEffects(\n pptx: PptxGenJSInstance,\n registry: GlowEffectRegistry,\n): void {\n if (registry.isEmpty) return;\n\n const originalWrite = pptx.write.bind(pptx);\n const originalWriteFile = pptx.writeFile.bind(pptx);\n\n const patchedWrite = async (rawProps?: WriteProps | string) => {\n const props: WriteProps | undefined =\n typeof rawProps === \"string\"\n ? ({ outputType: rawProps } as WriteProps)\n : rawProps;\n const data = (await originalWrite({\n outputType: \"uint8array\",\n })) as Uint8Array;\n const zip = await applyGlowEffects(data, registry);\n\n const outputType = props?.outputType;\n if (outputType === \"STREAM\") {\n return zip.generateAsync({\n type: \"nodebuffer\",\n compression: props?.compression ? \"DEFLATE\" : \"STORE\",\n });\n }\n if (outputType) {\n return zip.generateAsync({ type: outputType });\n }\n return zip.generateAsync({\n type: \"blob\",\n compression: props?.compression ? \"DEFLATE\" : \"STORE\",\n });\n };\n pptx.write = patchedWrite;\n\n const patchedWriteFile = async (rawProps?: WriteFileProps | string) => {\n const props: WriteFileProps | undefined =\n typeof rawProps === \"string\" ? { fileName: rawProps } : rawProps;\n const isNode =\n typeof process !== \"undefined\" && Boolean(process.versions?.node);\n if (!isNode) {\n return originalWriteFile(props);\n }\n const rawName = props?.fileName ?? \"Presentation.pptx\";\n const fileName = rawName.toLowerCase().endsWith(\".pptx\")\n ? rawName\n : `${rawName}.pptx`;\n const buffer = (await patchedWrite({\n outputType: \"nodebuffer\",\n compression: props?.compression,\n })) as Buffer;\n const fs = await import(\"fs\");\n await fs.promises.writeFile(fileName, buffer);\n return fileName;\n };\n pptx.writeFile = patchedWriteFile;\n}\n"],"mappings":"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"}
|
|
@@ -162,6 +162,6 @@ function patchPptxWriteForGradientFills(pptx, registry) {
|
|
|
162
162
|
pptx.writeFile = patchedWriteFile;
|
|
163
163
|
}
|
|
164
164
|
//#endregion
|
|
165
|
-
export { GradientFillRegistry, patchPptxWriteForGradientFills, registerBackgroundGradient, registerTextGradient };
|
|
165
|
+
export { GradientFillRegistry, applyGradientFills, patchPptxWriteForGradientFills, registerBackgroundGradient, registerTextGradient };
|
|
166
166
|
|
|
167
167
|
//# sourceMappingURL=gradientFills.js.map
|
|
@@ -71,7 +71,8 @@ function renderHorizontalTimeline(node, ctx, items, options) {
|
|
|
71
71
|
const titleGap = 8 * scaleFactor;
|
|
72
72
|
const descOffset = 32 * scaleFactor;
|
|
73
73
|
items.forEach((item, index) => {
|
|
74
|
-
const
|
|
74
|
+
const progress = itemCount === 1 ? .5 : index / (itemCount - 1);
|
|
75
|
+
const cx = startX + lineLength * progress;
|
|
75
76
|
const cy = lineY;
|
|
76
77
|
const color = item.color ?? defaultColor;
|
|
77
78
|
const dateColor = resolveItemDateColor(item, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.js","names":[],"sources":["../../../src/renderPptx/nodes/timeline.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 { measureTimeline } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\nimport { registerBackgroundGradient } from \"../gradientFills.ts\";\n\ntype TimelinePositionedNode = Extract<PositionedNode, { type: \"timeline\" }>;\n\ntype TimelineTextColors = {\n date: string;\n title: string;\n description: string;\n};\n\ntype TimelineRenderOptions = {\n defaultColor: string;\n nodeRadius: number;\n lineWidth: number;\n scaleFactor: number;\n textColors: TimelineTextColors;\n connectorLineColor: string;\n fontFace: string;\n useColorForDate: boolean;\n};\n\nexport function renderTimelineNode(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const items = node.items;\n const itemCount = items.length;\n\n if (itemCount === 0) return;\n\n const defaultColor = \"1D4ED8\"; // blue\n const baseNodeRadius = 12; // px\n const baseLineWidth = 4; // px\n\n const textColors: TimelineTextColors = {\n date: stripHash(node.dateColor) ?? \"64748B\",\n title: stripHash(node.titleColor) ?? \"1E293B\",\n description: stripHash(node.descriptionColor) ?? \"64748B\",\n };\n\n // 軸線色を解決する。connectorGradient が指定されていれば gradient registry に\n // 登録してマーカー色を採用する (後処理で gradFill に置換される)。\n // connectorColor が指定されていればそれを採用、未指定ならデフォルトの E2E8F0。\n const connectorGradientMarker = node.connectorGradient\n ? registerBackgroundGradient(\n node.connectorGradient,\n node.opacity,\n ctx.buildContext.gradientFills,\n )\n : undefined;\n const connectorLineColor =\n connectorGradientMarker ?? stripHash(node.connectorColor) ?? \"E2E8F0\";\n\n const fontFace = node.fontFamily ?? \"Noto Sans JP\";\n const useColorForDate = node.useColorForDate ?? false;\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureTimeline(node),\n ctx,\n );\n\n const nodeRadius = baseNodeRadius * scaleFactor;\n const lineWidth = baseLineWidth * scaleFactor;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n const options: TimelineRenderOptions = {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n useColorForDate,\n };\n\n if (direction === \"horizontal\") {\n renderHorizontalTimeline(contentNode, ctx, items, options);\n } else {\n renderVerticalTimeline(contentNode, ctx, items, options);\n }\n}\n\nfunction resolveItemDateColor(\n item: TimelinePositionedNode[\"items\"][number],\n options: TimelineRenderOptions,\n): string {\n // 優先順位: item.dateColor > (useColorForDate && item.color) > Timeline.dateColor\n const perItemDateColor = stripHash(item.dateColor);\n if (perItemDateColor) return perItemDateColor;\n if (options.useColorForDate && item.color) {\n const inherited = stripHash(item.color);\n if (inherited) return inherited;\n }\n return options.textColors.date;\n}\n\nfunction renderHorizontalTimeline(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n items: TimelinePositionedNode[\"items\"],\n options: TimelineRenderOptions,\n): void {\n const {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n } = options;\n const itemCount = items.length;\n const lineY = node.y + node.h / 2;\n const labelW = 120 * scaleFactor;\n // 極端に狭い node.w でも startX <= endX を保つため、インセットを node.w/2 で頭打ちする\n const inset = Math.min(labelW / 2, node.w / 2);\n const startX = node.x + inset;\n const endX = node.x + node.w - inset;\n const lineLength = endX - startX;\n\n // メインの線を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(lineY),\n w: pxToIn(lineLength),\n h: 0,\n line: { color: connectorLineColor, width: pxToPt(lineWidth) },\n });\n const dateLabelH = 24 * scaleFactor;\n const titleLabelH = 24 * scaleFactor;\n const descLabelH = 32 * scaleFactor;\n const dateOffset = 40 * scaleFactor;\n const titleGap = 8 * scaleFactor;\n const descOffset = 32 * scaleFactor;\n\n // 各アイテムを描画\n items.forEach((item, index) => {\n const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);\n const cx = startX + lineLength * progress;\n const cy = lineY;\n const color = item.color ?? defaultColor;\n const dateColor = resolveItemDateColor(item, options);\n\n // ノード(円)を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {\n x: pxToIn(cx - nodeRadius),\n y: pxToIn(cy - nodeRadius),\n w: pxToIn(nodeRadius * 2),\n h: pxToIn(nodeRadius * 2),\n fill: { color },\n line: { type: \"none\" as const },\n });\n\n // 日付を上に表示\n ctx.slide.addText(item.date, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy - nodeRadius - dateOffset),\n w: pxToIn(labelW),\n h: pxToIn(dateLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace,\n color: dateColor,\n align: \"center\",\n valign: \"bottom\",\n });\n\n // タイトルを下に表示\n ctx.slide.addText(item.title, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy + nodeRadius + titleGap),\n w: pxToIn(labelW),\n h: pxToIn(titleLabelH),\n fontSize: pxToPt(14 * scaleFactor),\n fontFace,\n color: textColors.title,\n bold: true,\n align: \"center\",\n valign: \"top\",\n });\n\n // 説明を表示\n if (item.description) {\n ctx.slide.addText(item.description, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy + nodeRadius + descOffset),\n w: pxToIn(labelW),\n h: pxToIn(descLabelH),\n fontSize: pxToPt(11 * scaleFactor),\n fontFace,\n color: textColors.description,\n align: \"center\",\n valign: \"top\",\n });\n }\n });\n}\n\nfunction renderVerticalTimeline(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n items: TimelinePositionedNode[\"items\"],\n options: TimelineRenderOptions,\n): void {\n const {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n } = options;\n const itemCount = items.length;\n const lineX = node.x + 40 * scaleFactor;\n const startY = node.y + nodeRadius;\n const endY = node.y + node.h - nodeRadius;\n const lineLength = endY - startY;\n\n // メインの線を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(lineX),\n y: pxToIn(startY),\n w: 0,\n h: pxToIn(lineLength),\n line: { color: connectorLineColor, width: pxToPt(lineWidth) },\n });\n\n const labelGap = 16 * scaleFactor;\n const dateLabelW = 100 * scaleFactor;\n const dateLabelH = 20 * scaleFactor;\n const titleLabelH = 24 * scaleFactor;\n const descLabelH = 32 * scaleFactor;\n const titleLabelW = node.w - 80 * scaleFactor;\n const descLabelW = node.w - 80 * scaleFactor;\n\n // 各アイテムを描画\n items.forEach((item, index) => {\n const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);\n const cx = lineX;\n const cy = startY + lineLength * progress;\n const color = item.color ?? defaultColor;\n const dateColor = resolveItemDateColor(item, options);\n\n // ノード(円)を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {\n x: pxToIn(cx - nodeRadius),\n y: pxToIn(cy - nodeRadius),\n w: pxToIn(nodeRadius * 2),\n h: pxToIn(nodeRadius * 2),\n fill: { color },\n line: { type: \"none\" as const },\n });\n\n // 日付を左上に表示\n ctx.slide.addText(item.date, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy - nodeRadius - 4 * scaleFactor),\n w: pxToIn(dateLabelW),\n h: pxToIn(dateLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace,\n color: dateColor,\n align: \"left\",\n valign: \"bottom\",\n });\n\n // タイトルを右に表示\n ctx.slide.addText(item.title, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy - 4 * scaleFactor),\n w: pxToIn(titleLabelW),\n h: pxToIn(titleLabelH),\n fontSize: pxToPt(14 * scaleFactor),\n fontFace,\n color: textColors.title,\n bold: true,\n align: \"left\",\n valign: \"top\",\n });\n\n // 説明を表示\n if (item.description) {\n ctx.slide.addText(item.description, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy + 20 * scaleFactor),\n w: pxToIn(descLabelW),\n h: pxToIn(descLabelH),\n fontSize: pxToPt(11 * scaleFactor),\n fontFace,\n color: textColors.description,\n align: \"left\",\n valign: \"top\",\n });\n }\n });\n}\n"],"mappings":";;;;;;;AA4BA,SAAgB,mBACd,MACA,KACM;CACN,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,QAAQ,KAAK;CAGnB,IAFkB,MAAM,WAEN,GAAG;CAErB,MAAM,eAAe;CACrB,MAAM,iBAAiB;CACvB,MAAM,gBAAgB;CAEtB,MAAM,aAAiC;EACrC,MAAM,UAAU,KAAK,SAAS,KAAK;EACnC,OAAO,UAAU,KAAK,UAAU,KAAK;EACrC,aAAa,UAAU,KAAK,gBAAgB,KAAK;CACnD;CAYA,MAAM,sBAP0B,KAAK,oBACjC,2BACE,KAAK,mBACL,KAAK,SACL,IAAI,aAAa,aACnB,IACA,KAAA,MAEyB,UAAU,KAAK,cAAc,KAAK;CAE/D,MAAM,WAAW,KAAK,cAAc;CACpC,MAAM,kBAAkB,KAAK,mBAAmB;CAGhD,MAAM,EAAE,SAAS,gBAAgB,yBAC/B,MACA,gBAAgB,IAAI,GACpB,GACF;CAEA,MAAM,aAAa,iBAAiB;CACpC,MAAM,YAAY,gBAAgB;CAGlC,MAAM,cAAc,kBAAkB,MAAM,OAAO;CAEnD,MAAM,UAAiC;EACrC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,IAAI,cAAc,cAChB,yBAAyB,aAAa,KAAK,OAAO,OAAO;MAEzD,uBAAuB,aAAa,KAAK,OAAO,OAAO;AAE3D;AAEA,SAAS,qBACP,MACA,SACQ;CAER,MAAM,mBAAmB,UAAU,KAAK,SAAS;CACjD,IAAI,kBAAkB,OAAO;CAC7B,IAAI,QAAQ,mBAAmB,KAAK,OAAO;EACzC,MAAM,YAAY,UAAU,KAAK,KAAK;EACtC,IAAI,WAAW,OAAO;CACxB;CACA,OAAO,QAAQ,WAAW;AAC5B;AAEA,SAAS,yBACP,MACA,KACA,OACA,SACM;CACN,MAAM,EACJ,cACA,YACA,WACA,aACA,YACA,oBACA,aACE;CACJ,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,KAAK,IAAI,KAAK,IAAI;CAChC,MAAM,SAAS,MAAM;CAErB,MAAM,QAAQ,KAAK,IAAI,SAAS,GAAG,KAAK,IAAI,CAAC;CAC7C,MAAM,SAAS,KAAK,IAAI;CAExB,MAAM,aADO,KAAK,IAAI,KAAK,IAAI,QACL;CAG1B,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;EAC1C,GAAG,OAAO,MAAM;EAChB,GAAG,OAAO,KAAK;EACf,GAAG,OAAO,UAAU;EACpB,GAAG;EACH,MAAM;GAAE,OAAO;GAAoB,OAAO,OAAO,SAAS;EAAE;CAC9D,CAAC;CACD,MAAM,aAAa,KAAK;CACxB,MAAM,cAAc,KAAK;CACzB,MAAM,aAAa,KAAK;CACxB,MAAM,aAAa,KAAK;CACxB,MAAM,WAAW,IAAI;CACrB,MAAM,aAAa,KAAK;CAGxB,MAAM,SAAS,MAAM,UAAU;EAE7B,MAAM,KAAK,SAAS,cADH,cAAc,IAAI,KAAM,SAAS,YAAY;EAE9D,MAAM,KAAK;EACX,MAAM,QAAQ,KAAK,SAAS;EAC5B,MAAM,YAAY,qBAAqB,MAAM,OAAO;EAGpD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,SAAS;GAC7C,GAAG,OAAO,KAAK,UAAU;GACzB,GAAG,OAAO,KAAK,UAAU;GACzB,GAAG,OAAO,aAAa,CAAC;GACxB,GAAG,OAAO,aAAa,CAAC;GACxB,MAAM,EAAE,MAAM;GACd,MAAM,EAAE,MAAM,OAAgB;EAChC,CAAC;EAGD,IAAI,MAAM,QAAQ,KAAK,MAAM;GAC3B,GAAG,OAAO,KAAK,SAAS,CAAC;GACzB,GAAG,OAAO,KAAK,aAAa,UAAU;GACtC,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,UAAU;GACpB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO;GACP,OAAO;GACP,QAAQ;EACV,CAAC;EAGD,IAAI,MAAM,QAAQ,KAAK,OAAO;GAC5B,GAAG,OAAO,KAAK,SAAS,CAAC;GACzB,GAAG,OAAO,KAAK,aAAa,QAAQ;GACpC,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,WAAW;GACrB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO,WAAW;GAClB,MAAM;GACN,OAAO;GACP,QAAQ;EACV,CAAC;EAGD,IAAI,KAAK,aACP,IAAI,MAAM,QAAQ,KAAK,aAAa;GAClC,GAAG,OAAO,KAAK,SAAS,CAAC;GACzB,GAAG,OAAO,KAAK,aAAa,UAAU;GACtC,GAAG,OAAO,MAAM;GAChB,GAAG,OAAO,UAAU;GACpB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO,WAAW;GAClB,OAAO;GACP,QAAQ;EACV,CAAC;CAEL,CAAC;AACH;AAEA,SAAS,uBACP,MACA,KACA,OACA,SACM;CACN,MAAM,EACJ,cACA,YACA,WACA,aACA,YACA,oBACA,aACE;CACJ,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,KAAK,IAAI,KAAK;CAC5B,MAAM,SAAS,KAAK,IAAI;CAExB,MAAM,aADO,KAAK,IAAI,KAAK,IAAI,aACL;CAG1B,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,MAAM;EAC1C,GAAG,OAAO,KAAK;EACf,GAAG,OAAO,MAAM;EAChB,GAAG;EACH,GAAG,OAAO,UAAU;EACpB,MAAM;GAAE,OAAO;GAAoB,OAAO,OAAO,SAAS;EAAE;CAC9D,CAAC;CAED,MAAM,WAAW,KAAK;CACtB,MAAM,aAAa,MAAM;CACzB,MAAM,aAAa,KAAK;CACxB,MAAM,cAAc,KAAK;CACzB,MAAM,aAAa,KAAK;CACxB,MAAM,cAAc,KAAK,IAAI,KAAK;CAClC,MAAM,aAAa,KAAK,IAAI,KAAK;CAGjC,MAAM,SAAS,MAAM,UAAU;EAC7B,MAAM,WAAW,cAAc,IAAI,KAAM,SAAS,YAAY;EAC9D,MAAM,KAAK;EACX,MAAM,KAAK,SAAS,aAAa;EACjC,MAAM,QAAQ,KAAK,SAAS;EAC5B,MAAM,YAAY,qBAAqB,MAAM,OAAO;EAGpD,IAAI,MAAM,SAAS,IAAI,KAAK,UAAU,SAAS;GAC7C,GAAG,OAAO,KAAK,UAAU;GACzB,GAAG,OAAO,KAAK,UAAU;GACzB,GAAG,OAAO,aAAa,CAAC;GACxB,GAAG,OAAO,aAAa,CAAC;GACxB,MAAM,EAAE,MAAM;GACd,MAAM,EAAE,MAAM,OAAgB;EAChC,CAAC;EAGD,IAAI,MAAM,QAAQ,KAAK,MAAM;GAC3B,GAAG,OAAO,KAAK,aAAa,QAAQ;GACpC,GAAG,OAAO,KAAK,aAAa,IAAI,WAAW;GAC3C,GAAG,OAAO,UAAU;GACpB,GAAG,OAAO,UAAU;GACpB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO;GACP,OAAO;GACP,QAAQ;EACV,CAAC;EAGD,IAAI,MAAM,QAAQ,KAAK,OAAO;GAC5B,GAAG,OAAO,KAAK,aAAa,QAAQ;GACpC,GAAG,OAAO,KAAK,IAAI,WAAW;GAC9B,GAAG,OAAO,WAAW;GACrB,GAAG,OAAO,WAAW;GACrB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO,WAAW;GAClB,MAAM;GACN,OAAO;GACP,QAAQ;EACV,CAAC;EAGD,IAAI,KAAK,aACP,IAAI,MAAM,QAAQ,KAAK,aAAa;GAClC,GAAG,OAAO,KAAK,aAAa,QAAQ;GACpC,GAAG,OAAO,KAAK,KAAK,WAAW;GAC/B,GAAG,OAAO,UAAU;GACpB,GAAG,OAAO,UAAU;GACpB,UAAU,OAAO,KAAK,WAAW;GACjC;GACA,OAAO,WAAW;GAClB,OAAO;GACP,QAAQ;EACV,CAAC;CAEL,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"timeline.js","names":[],"sources":["../../../src/renderPptx/nodes/timeline.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 { measureTimeline } from \"../../calcYogaLayout/measureCompositeNodes.ts\";\nimport { resolveScaledContentArea } from \"../utils/scaleToFit.ts\";\nimport { withContentBounds } from \"../utils/contentArea.ts\";\nimport { registerBackgroundGradient } from \"../gradientFills.ts\";\n\ntype TimelinePositionedNode = Extract<PositionedNode, { type: \"timeline\" }>;\n\ntype TimelineTextColors = {\n date: string;\n title: string;\n description: string;\n};\n\ntype TimelineRenderOptions = {\n defaultColor: string;\n nodeRadius: number;\n lineWidth: number;\n scaleFactor: number;\n textColors: TimelineTextColors;\n connectorLineColor: string;\n fontFace: string;\n useColorForDate: boolean;\n};\n\nexport function renderTimelineNode(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n): void {\n const direction = node.direction ?? \"horizontal\";\n const items = node.items;\n const itemCount = items.length;\n\n if (itemCount === 0) return;\n\n const defaultColor = \"1D4ED8\"; // blue\n const baseNodeRadius = 12; // px\n const baseLineWidth = 4; // px\n\n const textColors: TimelineTextColors = {\n date: stripHash(node.dateColor) ?? \"64748B\",\n title: stripHash(node.titleColor) ?? \"1E293B\",\n description: stripHash(node.descriptionColor) ?? \"64748B\",\n };\n\n // 軸線色を解決する。connectorGradient が指定されていれば gradient registry に\n // 登録してマーカー色を採用する (後処理で gradFill に置換される)。\n // connectorColor が指定されていればそれを採用、未指定ならデフォルトの E2E8F0。\n const connectorGradientMarker = node.connectorGradient\n ? registerBackgroundGradient(\n node.connectorGradient,\n node.opacity,\n ctx.buildContext.gradientFills,\n )\n : undefined;\n const connectorLineColor =\n connectorGradientMarker ?? stripHash(node.connectorColor) ?? \"E2E8F0\";\n\n const fontFace = node.fontFamily ?? \"Noto Sans JP\";\n const useColorForDate = node.useColorForDate ?? false;\n\n // スケール係数を計算(コンテンツ領域基準)\n const { content, scaleFactor } = resolveScaledContentArea(\n node,\n measureTimeline(node),\n ctx,\n );\n\n const nodeRadius = baseNodeRadius * scaleFactor;\n const lineWidth = baseLineWidth * scaleFactor;\n\n // コンテンツ領域を使用するための仮想ノードを作成\n const contentNode = withContentBounds(node, content);\n\n const options: TimelineRenderOptions = {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n useColorForDate,\n };\n\n if (direction === \"horizontal\") {\n renderHorizontalTimeline(contentNode, ctx, items, options);\n } else {\n renderVerticalTimeline(contentNode, ctx, items, options);\n }\n}\n\nfunction resolveItemDateColor(\n item: TimelinePositionedNode[\"items\"][number],\n options: TimelineRenderOptions,\n): string {\n // 優先順位: item.dateColor > (useColorForDate && item.color) > Timeline.dateColor\n const perItemDateColor = stripHash(item.dateColor);\n if (perItemDateColor) return perItemDateColor;\n if (options.useColorForDate && item.color) {\n const inherited = stripHash(item.color);\n if (inherited) return inherited;\n }\n return options.textColors.date;\n}\n\nfunction renderHorizontalTimeline(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n items: TimelinePositionedNode[\"items\"],\n options: TimelineRenderOptions,\n): void {\n const {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n } = options;\n const itemCount = items.length;\n const lineY = node.y + node.h / 2;\n const labelW = 120 * scaleFactor;\n // 極端に狭い node.w でも startX <= endX を保つため、インセットを node.w/2 で頭打ちする\n const inset = Math.min(labelW / 2, node.w / 2);\n const startX = node.x + inset;\n const endX = node.x + node.w - inset;\n const lineLength = endX - startX;\n\n // メインの線を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(startX),\n y: pxToIn(lineY),\n w: pxToIn(lineLength),\n h: 0,\n line: { color: connectorLineColor, width: pxToPt(lineWidth) },\n });\n const dateLabelH = 24 * scaleFactor;\n const titleLabelH = 24 * scaleFactor;\n const descLabelH = 32 * scaleFactor;\n const dateOffset = 40 * scaleFactor;\n const titleGap = 8 * scaleFactor;\n const descOffset = 32 * scaleFactor;\n\n // 各アイテムを描画\n items.forEach((item, index) => {\n const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);\n const cx = startX + lineLength * progress;\n const cy = lineY;\n const color = item.color ?? defaultColor;\n const dateColor = resolveItemDateColor(item, options);\n\n // ノード(円)を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {\n x: pxToIn(cx - nodeRadius),\n y: pxToIn(cy - nodeRadius),\n w: pxToIn(nodeRadius * 2),\n h: pxToIn(nodeRadius * 2),\n fill: { color },\n line: { type: \"none\" as const },\n });\n\n // 日付を上に表示\n ctx.slide.addText(item.date, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy - nodeRadius - dateOffset),\n w: pxToIn(labelW),\n h: pxToIn(dateLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace,\n color: dateColor,\n align: \"center\",\n valign: \"bottom\",\n });\n\n // タイトルを下に表示\n ctx.slide.addText(item.title, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy + nodeRadius + titleGap),\n w: pxToIn(labelW),\n h: pxToIn(titleLabelH),\n fontSize: pxToPt(14 * scaleFactor),\n fontFace,\n color: textColors.title,\n bold: true,\n align: \"center\",\n valign: \"top\",\n });\n\n // 説明を表示\n if (item.description) {\n ctx.slide.addText(item.description, {\n x: pxToIn(cx - labelW / 2),\n y: pxToIn(cy + nodeRadius + descOffset),\n w: pxToIn(labelW),\n h: pxToIn(descLabelH),\n fontSize: pxToPt(11 * scaleFactor),\n fontFace,\n color: textColors.description,\n align: \"center\",\n valign: \"top\",\n });\n }\n });\n}\n\nfunction renderVerticalTimeline(\n node: TimelinePositionedNode,\n ctx: RenderContext,\n items: TimelinePositionedNode[\"items\"],\n options: TimelineRenderOptions,\n): void {\n const {\n defaultColor,\n nodeRadius,\n lineWidth,\n scaleFactor,\n textColors,\n connectorLineColor,\n fontFace,\n } = options;\n const itemCount = items.length;\n const lineX = node.x + 40 * scaleFactor;\n const startY = node.y + nodeRadius;\n const endY = node.y + node.h - nodeRadius;\n const lineLength = endY - startY;\n\n // メインの線を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.line, {\n x: pxToIn(lineX),\n y: pxToIn(startY),\n w: 0,\n h: pxToIn(lineLength),\n line: { color: connectorLineColor, width: pxToPt(lineWidth) },\n });\n\n const labelGap = 16 * scaleFactor;\n const dateLabelW = 100 * scaleFactor;\n const dateLabelH = 20 * scaleFactor;\n const titleLabelH = 24 * scaleFactor;\n const descLabelH = 32 * scaleFactor;\n const titleLabelW = node.w - 80 * scaleFactor;\n const descLabelW = node.w - 80 * scaleFactor;\n\n // 各アイテムを描画\n items.forEach((item, index) => {\n const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);\n const cx = lineX;\n const cy = startY + lineLength * progress;\n const color = item.color ?? defaultColor;\n const dateColor = resolveItemDateColor(item, options);\n\n // ノード(円)を描画\n ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {\n x: pxToIn(cx - nodeRadius),\n y: pxToIn(cy - nodeRadius),\n w: pxToIn(nodeRadius * 2),\n h: pxToIn(nodeRadius * 2),\n fill: { color },\n line: { type: \"none\" as const },\n });\n\n // 日付を左上に表示\n ctx.slide.addText(item.date, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy - nodeRadius - 4 * scaleFactor),\n w: pxToIn(dateLabelW),\n h: pxToIn(dateLabelH),\n fontSize: pxToPt(12 * scaleFactor),\n fontFace,\n color: dateColor,\n align: \"left\",\n valign: \"bottom\",\n });\n\n // タイトルを右に表示\n ctx.slide.addText(item.title, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy - 4 * scaleFactor),\n w: pxToIn(titleLabelW),\n h: pxToIn(titleLabelH),\n fontSize: pxToPt(14 * scaleFactor),\n fontFace,\n color: textColors.title,\n bold: true,\n align: \"left\",\n valign: \"top\",\n });\n\n // 説明を表示\n if (item.description) {\n ctx.slide.addText(item.description, {\n x: pxToIn(cx + nodeRadius + labelGap),\n y: pxToIn(cy + 20 * scaleFactor),\n w: pxToIn(descLabelW),\n h: pxToIn(descLabelH),\n fontSize: pxToPt(11 * scaleFactor),\n fontFace,\n color: textColors.description,\n align: \"left\",\n valign: \"top\",\n });\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -106,6 +106,6 @@ function createTextOptions(node) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
//#endregion
|
|
109
|
-
export { convertGlow, convertOutline, convertStrike, convertUnderline, createTextOptions, resolveSubSup };
|
|
109
|
+
export { calcGlyphCenteringShiftPx, convertGlow, convertOutline, convertStrike, convertUnderline, createTextOptions, resolveSubSup };
|
|
110
110
|
|
|
111
111
|
//# sourceMappingURL=textOptions.js.map
|
package/dist/renderPptx/units.js
CHANGED
|
@@ -108,6 +108,6 @@ function resolveRectRadius(borderRadius, w, h) {
|
|
|
108
108
|
return borderRadius ? Math.min(borderRadius / Math.min(w, h) * 2, 1) : void 0;
|
|
109
109
|
}
|
|
110
110
|
//#endregion
|
|
111
|
-
export { BORDER_SIDES, convertBorderLine, convertShadow, hasVisibleBorder, resolveBackgroundFill, resolvePerSideBorders, resolveRectRadius, stripHash };
|
|
111
|
+
export { BORDER_SIDES, convertBorderLine, convertShadow, hasVisibleBorder, opacityToTransparency, resolveBackgroundFill, resolvePerSideBorders, resolveRectRadius, stripHash };
|
|
112
112
|
|
|
113
113
|
//# sourceMappingURL=visualStyle.js.map
|
package/dist/shared/gradient.js
CHANGED
|
@@ -103,8 +103,8 @@ function parseLinearGradient(value) {
|
|
|
103
103
|
stops
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
-
const SHAPE_KEYWORDS = new Set(["circle", "ellipse"]);
|
|
107
|
-
const SIZE_KEYWORDS = new Set([
|
|
106
|
+
const SHAPE_KEYWORDS = /* @__PURE__ */ new Set(["circle", "ellipse"]);
|
|
107
|
+
const SIZE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
108
108
|
"closest-side",
|
|
109
109
|
"closest-corner",
|
|
110
110
|
"farthest-side",
|
|
@@ -264,6 +264,6 @@ function parseGradient(value) {
|
|
|
264
264
|
return null;
|
|
265
265
|
}
|
|
266
266
|
//#endregion
|
|
267
|
-
export { parseGradient, parseLinearGradient };
|
|
267
|
+
export { parseGradient, parseLinearGradient, parseRadialGradient };
|
|
268
268
|
|
|
269
269
|
//# sourceMappingURL=gradient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gradient.js","names":[],"sources":["../../src/shared/gradient.ts"],"sourcesContent":["/**\n * CSS 風グラデーション文字列のパース\n *\n * linear-gradient と radial-gradient の 2 種類を扱う:\n * linear-gradient(135deg, #FF0000 0%, #0000FF 100%)\n * linear-gradient(to right, #FF0000, #00FF00, #0000FF)\n * linear-gradient(#FF0000, #0000FF)\n * radial-gradient(circle at center, #FF0000, #0000FF)\n * radial-gradient(ellipse farthest-corner at 50% 50%, #FF0000 0%, #0000FF 100%)\n * radial-gradient(#FF0000, #0000FF)\n *\n * - 角度 (linear): `<数値>deg` または `to <方向>` キーワード。省略時は 180deg。\n * - 形状 (radial): `circle` / `ellipse`。省略時は `ellipse`。\n * PowerPoint の DrawingML radial fill は shape を区別しないため、出力上は同一になる。\n * - サイズキーワード (radial): `closest-side` / `closest-corner` / `farthest-side` /\n * `farthest-corner`。省略時は `farthest-corner`。MVP では構文として受け付けるのみで\n * 出力は farthest-corner 相当 (PPT 標準) に固定。\n * - 中心位置 (radial): `at <position>` で指定。`center` / `top right` / `25% 75%` 等。\n * 省略時は `center` (50% 50%)。\n * - カラーストップ: 16進カラー (#RGB / #RRGGBB / RRGGBB) + 任意の位置 (%)。\n * 位置省略時は CSS と同様に補間する (先頭 0% / 末尾 100% / 中間は線形補間)。\n * - ストップは 2 つ以上必須。\n */\n\nexport interface GradientStop {\n /** 6桁大文字 HEX (# なし) */\n color: string;\n /** 0-100 (%) */\n position: number;\n}\n\nexport interface LinearGradient {\n /** CSS 基準の角度 (deg)。0 = 上向き、時計回り。0-360 に正規化済み */\n angle: number;\n stops: GradientStop[];\n}\n\nexport type RadialGradientShape = \"circle\" | \"ellipse\";\nexport type RadialGradientSize =\n | \"closest-side\"\n | \"closest-corner\"\n | \"farthest-side\"\n | \"farthest-corner\";\n\nexport interface RadialGradient {\n shape: RadialGradientShape;\n size: RadialGradientSize;\n /** 中心位置 X (%、0=左 / 100=右) */\n centerX: number;\n /** 中心位置 Y (%、0=上 / 100=下) */\n centerY: number;\n stops: GradientStop[];\n}\n\nexport type Gradient =\n | { kind: \"linear\"; value: LinearGradient }\n | { kind: \"radial\"; value: RadialGradient };\n\n/** `to <方向>` キーワード → CSS 角度 (deg)。コーナーは 45 度刻みの近似 */\nconst DIRECTION_KEYWORDS: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to right top\": 45,\n \"to bottom right\": 135,\n \"to right bottom\": 135,\n \"to bottom left\": 225,\n \"to left bottom\": 225,\n \"to top left\": 315,\n \"to left top\": 315,\n};\n\nconst COLOR_PATTERN = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;\n\nfunction normalizeColor(raw: string): string | null {\n const match = COLOR_PATTERN.exec(raw);\n if (!match) return null;\n const hex = match[1];\n if (hex.length === 3) {\n return hex\n .split(\"\")\n .map((c) => c + c)\n .join(\"\")\n .toUpperCase();\n }\n return hex.toUpperCase();\n}\n\n/**\n * 位置省略されたストップに CSS 互換のルールで位置を割り当てる。\n * - 先頭が省略なら 0、末尾が省略なら 100\n * - 中間の省略は前後の明示位置の間で均等配置\n * - 位置が前のストップより小さい場合は前の値に切り上げ (非減少を保証)\n */\nfunction resolveStopPositions(\n stops: { color: string; position: number | undefined }[],\n): GradientStop[] {\n const positions: (number | undefined)[] = stops.map((s) => s.position);\n if (positions[0] === undefined) positions[0] = 0;\n if (positions[positions.length - 1] === undefined) {\n positions[positions.length - 1] = 100;\n }\n\n let prevIndex = 0;\n for (let i = 1; i < positions.length; i++) {\n if (positions[i] === undefined) continue;\n const gap = i - prevIndex;\n if (gap > 1) {\n const start = positions[prevIndex]!;\n const end = positions[i]!;\n for (let j = 1; j < gap; j++) {\n positions[prevIndex + j] = start + ((end - start) * j) / gap;\n }\n }\n prevIndex = i;\n }\n\n let prev = 0;\n return stops.map((stop, i) => {\n const clamped = Math.min(Math.max(positions[i]!, 0), 100);\n const position = Math.max(clamped, prev);\n prev = position;\n return { color: stop.color, position };\n });\n}\n\n/** カラーストップ群 (`<color> [<pos>%]`) を parse する。失敗時 null */\nfunction parseColorStops(stopArgs: string[]): GradientStop[] | null {\n if (stopArgs.length < 2) return null;\n const stops: { color: string; position: number | undefined }[] = [];\n for (const stopArg of stopArgs) {\n const parts = stopArg.split(/\\s+/);\n if (parts.length === 0 || parts.length > 2) return null;\n const color = normalizeColor(parts[0]);\n if (color === null) return null;\n\n let position: number | undefined;\n if (parts.length === 2) {\n const posMatch = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(parts[1]);\n if (!posMatch) return null;\n position = Number(posMatch[1]);\n }\n stops.push({ color, position });\n }\n return resolveStopPositions(stops);\n}\n\n/**\n * linear-gradient() 構文をパースする。不正な構文の場合は null を返す。\n */\nexport function parseLinearGradient(value: string): LinearGradient | null {\n const match = /^\\s*linear-gradient\\s*\\(\\s*(.+?)\\s*\\)\\s*$/.exec(value);\n if (!match) return null;\n\n const args = match[1].split(\",\").map((s) => s.trim());\n if (args.length === 0) return null;\n\n let angle = 180;\n let stopArgs = args;\n\n const first = args[0];\n const angleMatch = /^(-?\\d+(?:\\.\\d+)?)deg$/.exec(first);\n const directionAngle =\n DIRECTION_KEYWORDS[first.toLowerCase().replace(/\\s+/g, \" \")];\n if (angleMatch) {\n angle = ((Number(angleMatch[1]) % 360) + 360) % 360;\n stopArgs = args.slice(1);\n } else if (directionAngle !== undefined) {\n angle = directionAngle;\n stopArgs = args.slice(1);\n }\n\n const stops = parseColorStops(stopArgs);\n if (!stops) return null;\n\n return { angle, stops };\n}\n\nconst SHAPE_KEYWORDS: ReadonlySet<string> = new Set([\"circle\", \"ellipse\"]);\nconst SIZE_KEYWORDS: ReadonlySet<string> = new Set([\n \"closest-side\",\n \"closest-corner\",\n \"farthest-side\",\n \"farthest-corner\",\n]);\nconst POSITION_X_KEYWORDS: Record<string, number> = {\n left: 0,\n center: 50,\n right: 100,\n};\nconst POSITION_Y_KEYWORDS: Record<string, number> = {\n top: 0,\n center: 50,\n bottom: 100,\n};\n\n/**\n * `at <position>` の <position> 部分を parse する。\n * 1〜2 トークンの組み合わせを受け取り、{ x, y } (各 0-100 %) を返す。\n *\n * 受け付ける形:\n * center / left / right / top / bottom\n * top right / left bottom / center top など (2 トークン)\n * 50% / 25% 75% (% 値)\n *\n * 不正な組み合わせは null。\n */\nfunction parsePosition(tokens: string[]): { x: number; y: number } | null {\n if (tokens.length === 0 || tokens.length > 2) return null;\n if (tokens.length === 1) {\n const t = tokens[0].toLowerCase();\n if (t === \"center\") return { x: 50, y: 50 };\n if (t in POSITION_X_KEYWORDS) {\n return { x: POSITION_X_KEYWORDS[t], y: 50 };\n }\n if (t in POSITION_Y_KEYWORDS) {\n return { x: 50, y: POSITION_Y_KEYWORDS[t] };\n }\n const pct = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(t);\n if (pct) return { x: Number(pct[1]), y: 50 };\n return null;\n }\n // 2 tokens. center は X/Y どちらにも割り当て可能なため一旦保留し、\n // 残りトークン処理後に未確定の軸へ振り分ける (CSS の `<position>` 2-value 構文に従う)。\n let x: number | null = null;\n let y: number | null = null;\n let centerCount = 0;\n for (const raw of tokens) {\n const t = raw.toLowerCase();\n const pct = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(t);\n if (pct) {\n const v = Number(pct[1]);\n if (x === null) x = v;\n else if (y === null) y = v;\n else return null;\n continue;\n }\n if (t === \"left\" || t === \"right\") {\n if (x !== null) return null;\n x = POSITION_X_KEYWORDS[t];\n continue;\n }\n if (t === \"top\" || t === \"bottom\") {\n if (y !== null) return null;\n y = POSITION_Y_KEYWORDS[t];\n continue;\n }\n if (t === \"center\") {\n centerCount++;\n continue;\n }\n return null;\n }\n // center を未確定軸に割り当てる。両方未確定なら 1 つ目 center で X=50、\n // 2 つ目 center で Y=50 になる。\n for (let i = 0; i < centerCount; i++) {\n if (x === null) x = 50;\n else if (y === null) y = 50;\n else return null;\n }\n return { x: x ?? 50, y: y ?? 50 };\n}\n\n/**\n * radial-gradient() 構文をパースする。不正な構文の場合は null を返す。\n *\n * 受け付ける構文:\n * radial-gradient(<color stops>)\n * radial-gradient(<shape>?, <color stops>) // 例: radial-gradient(circle, #FF0000, #0000FF)\n * radial-gradient(<shape>? <size>?, <color stops>) // 例: radial-gradient(circle farthest-side, ...)\n * radial-gradient(<shape>? <size>? at <position>, <color stops>) // 例: radial-gradient(ellipse at top right, ...)\n * radial-gradient(at <position>, <color stops>) // 例: radial-gradient(at 25% 75%, ...)\n */\nexport function parseRadialGradient(value: string): RadialGradient | null {\n const match = /^\\s*radial-gradient\\s*\\(\\s*(.+?)\\s*\\)\\s*$/.exec(value);\n if (!match) return null;\n\n const args = match[1].split(\",\").map((s) => s.trim());\n if (args.length === 0) return null;\n\n let shape: RadialGradientShape = \"ellipse\";\n let size: RadialGradientSize = \"farthest-corner\";\n let centerX = 50;\n let centerY = 50;\n let stopArgs = args;\n\n const first = args[0];\n const firstTokens = first.split(/\\s+/).filter((t) => t.length > 0);\n const firstLowerTokens = firstTokens.map((t) => t.toLowerCase());\n\n // prelude 判定: shape / size / \"at\" のいずれかキーワードが含まれていれば prelude として扱う。\n const hasPreludeKeyword = firstLowerTokens.some(\n (t) => SHAPE_KEYWORDS.has(t) || SIZE_KEYWORDS.has(t) || t === \"at\",\n );\n\n if (hasPreludeKeyword) {\n const atIdx = firstLowerTokens.indexOf(\"at\");\n const shapeSizeTokens =\n atIdx >= 0 ? firstLowerTokens.slice(0, atIdx) : firstLowerTokens;\n const positionTokens = atIdx >= 0 ? firstTokens.slice(atIdx + 1) : [];\n\n let shapeSeen = false;\n let sizeSeen = false;\n for (const token of shapeSizeTokens) {\n if (SHAPE_KEYWORDS.has(token)) {\n if (shapeSeen) return null;\n shape = token as RadialGradientShape;\n shapeSeen = true;\n } else if (SIZE_KEYWORDS.has(token)) {\n if (sizeSeen) return null;\n size = token as RadialGradientSize;\n sizeSeen = true;\n } else {\n return null;\n }\n }\n\n if (atIdx >= 0) {\n if (positionTokens.length === 0) return null;\n const pos = parsePosition(positionTokens);\n if (!pos) return null;\n centerX = pos.x;\n centerY = pos.y;\n }\n\n stopArgs = args.slice(1);\n }\n\n const stops = parseColorStops(stopArgs);\n if (!stops) return null;\n\n return { shape, size, centerX, centerY, stops };\n}\n\n/**\n * linear-gradient / radial-gradient のいずれかを parse する。\n */\nexport function parseGradient(value: string): Gradient | null {\n const linear = parseLinearGradient(value);\n if (linear) return { kind: \"linear\", value: linear };\n const radial = parseRadialGradient(value);\n if (radial) return { kind: \"radial\", value: radial };\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gradient.js","names":[],"sources":["../../src/shared/gradient.ts"],"sourcesContent":["/**\n * CSS 風グラデーション文字列のパース\n *\n * linear-gradient と radial-gradient の 2 種類を扱う:\n * linear-gradient(135deg, #FF0000 0%, #0000FF 100%)\n * linear-gradient(to right, #FF0000, #00FF00, #0000FF)\n * linear-gradient(#FF0000, #0000FF)\n * radial-gradient(circle at center, #FF0000, #0000FF)\n * radial-gradient(ellipse farthest-corner at 50% 50%, #FF0000 0%, #0000FF 100%)\n * radial-gradient(#FF0000, #0000FF)\n *\n * - 角度 (linear): `<数値>deg` または `to <方向>` キーワード。省略時は 180deg。\n * - 形状 (radial): `circle` / `ellipse`。省略時は `ellipse`。\n * PowerPoint の DrawingML radial fill は shape を区別しないため、出力上は同一になる。\n * - サイズキーワード (radial): `closest-side` / `closest-corner` / `farthest-side` /\n * `farthest-corner`。省略時は `farthest-corner`。MVP では構文として受け付けるのみで\n * 出力は farthest-corner 相当 (PPT 標準) に固定。\n * - 中心位置 (radial): `at <position>` で指定。`center` / `top right` / `25% 75%` 等。\n * 省略時は `center` (50% 50%)。\n * - カラーストップ: 16進カラー (#RGB / #RRGGBB / RRGGBB) + 任意の位置 (%)。\n * 位置省略時は CSS と同様に補間する (先頭 0% / 末尾 100% / 中間は線形補間)。\n * - ストップは 2 つ以上必須。\n */\n\nexport interface GradientStop {\n /** 6桁大文字 HEX (# なし) */\n color: string;\n /** 0-100 (%) */\n position: number;\n}\n\nexport interface LinearGradient {\n /** CSS 基準の角度 (deg)。0 = 上向き、時計回り。0-360 に正規化済み */\n angle: number;\n stops: GradientStop[];\n}\n\nexport type RadialGradientShape = \"circle\" | \"ellipse\";\nexport type RadialGradientSize =\n \"closest-side\" | \"closest-corner\" | \"farthest-side\" | \"farthest-corner\";\n\nexport interface RadialGradient {\n shape: RadialGradientShape;\n size: RadialGradientSize;\n /** 中心位置 X (%、0=左 / 100=右) */\n centerX: number;\n /** 中心位置 Y (%、0=上 / 100=下) */\n centerY: number;\n stops: GradientStop[];\n}\n\nexport type Gradient =\n | { kind: \"linear\"; value: LinearGradient }\n | { kind: \"radial\"; value: RadialGradient };\n\n/** `to <方向>` キーワード → CSS 角度 (deg)。コーナーは 45 度刻みの近似 */\nconst DIRECTION_KEYWORDS: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to right top\": 45,\n \"to bottom right\": 135,\n \"to right bottom\": 135,\n \"to bottom left\": 225,\n \"to left bottom\": 225,\n \"to top left\": 315,\n \"to left top\": 315,\n};\n\nconst COLOR_PATTERN = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;\n\nfunction normalizeColor(raw: string): string | null {\n const match = COLOR_PATTERN.exec(raw);\n if (!match) return null;\n const hex = match[1];\n if (hex.length === 3) {\n return hex\n .split(\"\")\n .map((c) => c + c)\n .join(\"\")\n .toUpperCase();\n }\n return hex.toUpperCase();\n}\n\n/**\n * 位置省略されたストップに CSS 互換のルールで位置を割り当てる。\n * - 先頭が省略なら 0、末尾が省略なら 100\n * - 中間の省略は前後の明示位置の間で均等配置\n * - 位置が前のストップより小さい場合は前の値に切り上げ (非減少を保証)\n */\nfunction resolveStopPositions(\n stops: { color: string; position: number | undefined }[],\n): GradientStop[] {\n const positions: (number | undefined)[] = stops.map((s) => s.position);\n if (positions[0] === undefined) positions[0] = 0;\n if (positions[positions.length - 1] === undefined) {\n positions[positions.length - 1] = 100;\n }\n\n let prevIndex = 0;\n for (let i = 1; i < positions.length; i++) {\n if (positions[i] === undefined) continue;\n const gap = i - prevIndex;\n if (gap > 1) {\n const start = positions[prevIndex]!;\n const end = positions[i]!;\n for (let j = 1; j < gap; j++) {\n positions[prevIndex + j] = start + ((end - start) * j) / gap;\n }\n }\n prevIndex = i;\n }\n\n let prev = 0;\n return stops.map((stop, i) => {\n const clamped = Math.min(Math.max(positions[i]!, 0), 100);\n const position = Math.max(clamped, prev);\n prev = position;\n return { color: stop.color, position };\n });\n}\n\n/** カラーストップ群 (`<color> [<pos>%]`) を parse する。失敗時 null */\nfunction parseColorStops(stopArgs: string[]): GradientStop[] | null {\n if (stopArgs.length < 2) return null;\n const stops: { color: string; position: number | undefined }[] = [];\n for (const stopArg of stopArgs) {\n const parts = stopArg.split(/\\s+/);\n if (parts.length === 0 || parts.length > 2) return null;\n const color = normalizeColor(parts[0]);\n if (color === null) return null;\n\n let position: number | undefined;\n if (parts.length === 2) {\n const posMatch = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(parts[1]);\n if (!posMatch) return null;\n position = Number(posMatch[1]);\n }\n stops.push({ color, position });\n }\n return resolveStopPositions(stops);\n}\n\n/**\n * linear-gradient() 構文をパースする。不正な構文の場合は null を返す。\n */\nexport function parseLinearGradient(value: string): LinearGradient | null {\n const match = /^\\s*linear-gradient\\s*\\(\\s*(.+?)\\s*\\)\\s*$/.exec(value);\n if (!match) return null;\n\n const args = match[1].split(\",\").map((s) => s.trim());\n if (args.length === 0) return null;\n\n let angle = 180;\n let stopArgs = args;\n\n const first = args[0];\n const angleMatch = /^(-?\\d+(?:\\.\\d+)?)deg$/.exec(first);\n const directionAngle =\n DIRECTION_KEYWORDS[first.toLowerCase().replace(/\\s+/g, \" \")];\n if (angleMatch) {\n angle = ((Number(angleMatch[1]) % 360) + 360) % 360;\n stopArgs = args.slice(1);\n } else if (directionAngle !== undefined) {\n angle = directionAngle;\n stopArgs = args.slice(1);\n }\n\n const stops = parseColorStops(stopArgs);\n if (!stops) return null;\n\n return { angle, stops };\n}\n\nconst SHAPE_KEYWORDS: ReadonlySet<string> = new Set([\"circle\", \"ellipse\"]);\nconst SIZE_KEYWORDS: ReadonlySet<string> = new Set([\n \"closest-side\",\n \"closest-corner\",\n \"farthest-side\",\n \"farthest-corner\",\n]);\nconst POSITION_X_KEYWORDS: Record<string, number> = {\n left: 0,\n center: 50,\n right: 100,\n};\nconst POSITION_Y_KEYWORDS: Record<string, number> = {\n top: 0,\n center: 50,\n bottom: 100,\n};\n\n/**\n * `at <position>` の <position> 部分を parse する。\n * 1〜2 トークンの組み合わせを受け取り、{ x, y } (各 0-100 %) を返す。\n *\n * 受け付ける形:\n * center / left / right / top / bottom\n * top right / left bottom / center top など (2 トークン)\n * 50% / 25% 75% (% 値)\n *\n * 不正な組み合わせは null。\n */\nfunction parsePosition(tokens: string[]): { x: number; y: number } | null {\n if (tokens.length === 0 || tokens.length > 2) return null;\n if (tokens.length === 1) {\n const t = tokens[0].toLowerCase();\n if (t === \"center\") return { x: 50, y: 50 };\n if (t in POSITION_X_KEYWORDS) {\n return { x: POSITION_X_KEYWORDS[t], y: 50 };\n }\n if (t in POSITION_Y_KEYWORDS) {\n return { x: 50, y: POSITION_Y_KEYWORDS[t] };\n }\n const pct = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(t);\n if (pct) return { x: Number(pct[1]), y: 50 };\n return null;\n }\n // 2 tokens. center は X/Y どちらにも割り当て可能なため一旦保留し、\n // 残りトークン処理後に未確定の軸へ振り分ける (CSS の `<position>` 2-value 構文に従う)。\n let x: number | null = null;\n let y: number | null = null;\n let centerCount = 0;\n for (const raw of tokens) {\n const t = raw.toLowerCase();\n const pct = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(t);\n if (pct) {\n const v = Number(pct[1]);\n if (x === null) x = v;\n else if (y === null) y = v;\n else return null;\n continue;\n }\n if (t === \"left\" || t === \"right\") {\n if (x !== null) return null;\n x = POSITION_X_KEYWORDS[t];\n continue;\n }\n if (t === \"top\" || t === \"bottom\") {\n if (y !== null) return null;\n y = POSITION_Y_KEYWORDS[t];\n continue;\n }\n if (t === \"center\") {\n centerCount++;\n continue;\n }\n return null;\n }\n // center を未確定軸に割り当てる。両方未確定なら 1 つ目 center で X=50、\n // 2 つ目 center で Y=50 になる。\n for (let i = 0; i < centerCount; i++) {\n if (x === null) x = 50;\n else if (y === null) y = 50;\n else return null;\n }\n return { x: x ?? 50, y: y ?? 50 };\n}\n\n/**\n * radial-gradient() 構文をパースする。不正な構文の場合は null を返す。\n *\n * 受け付ける構文:\n * radial-gradient(<color stops>)\n * radial-gradient(<shape>?, <color stops>) // 例: radial-gradient(circle, #FF0000, #0000FF)\n * radial-gradient(<shape>? <size>?, <color stops>) // 例: radial-gradient(circle farthest-side, ...)\n * radial-gradient(<shape>? <size>? at <position>, <color stops>) // 例: radial-gradient(ellipse at top right, ...)\n * radial-gradient(at <position>, <color stops>) // 例: radial-gradient(at 25% 75%, ...)\n */\nexport function parseRadialGradient(value: string): RadialGradient | null {\n const match = /^\\s*radial-gradient\\s*\\(\\s*(.+?)\\s*\\)\\s*$/.exec(value);\n if (!match) return null;\n\n const args = match[1].split(\",\").map((s) => s.trim());\n if (args.length === 0) return null;\n\n let shape: RadialGradientShape = \"ellipse\";\n let size: RadialGradientSize = \"farthest-corner\";\n let centerX = 50;\n let centerY = 50;\n let stopArgs = args;\n\n const first = args[0];\n const firstTokens = first.split(/\\s+/).filter((t) => t.length > 0);\n const firstLowerTokens = firstTokens.map((t) => t.toLowerCase());\n\n // prelude 判定: shape / size / \"at\" のいずれかキーワードが含まれていれば prelude として扱う。\n const hasPreludeKeyword = firstLowerTokens.some(\n (t) => SHAPE_KEYWORDS.has(t) || SIZE_KEYWORDS.has(t) || t === \"at\",\n );\n\n if (hasPreludeKeyword) {\n const atIdx = firstLowerTokens.indexOf(\"at\");\n const shapeSizeTokens =\n atIdx >= 0 ? firstLowerTokens.slice(0, atIdx) : firstLowerTokens;\n const positionTokens = atIdx >= 0 ? firstTokens.slice(atIdx + 1) : [];\n\n let shapeSeen = false;\n let sizeSeen = false;\n for (const token of shapeSizeTokens) {\n if (SHAPE_KEYWORDS.has(token)) {\n if (shapeSeen) return null;\n shape = token as RadialGradientShape;\n shapeSeen = true;\n } else if (SIZE_KEYWORDS.has(token)) {\n if (sizeSeen) return null;\n size = token as RadialGradientSize;\n sizeSeen = true;\n } else {\n return null;\n }\n }\n\n if (atIdx >= 0) {\n if (positionTokens.length === 0) return null;\n const pos = parsePosition(positionTokens);\n if (!pos) return null;\n centerX = pos.x;\n centerY = pos.y;\n }\n\n stopArgs = args.slice(1);\n }\n\n const stops = parseColorStops(stopArgs);\n if (!stops) return null;\n\n return { shape, size, centerX, centerY, stops };\n}\n\n/**\n * linear-gradient / radial-gradient のいずれかを parse する。\n */\nexport function parseGradient(value: string): Gradient | null {\n const linear = parseLinearGradient(value);\n if (linear) return { kind: \"linear\", value: linear };\n const radial = parseRadialGradient(value);\n if (radial) return { kind: \"radial\", value: radial };\n return null;\n}\n"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
|
+
interface ThemeTokens {
|
|
5
|
+
text: string;
|
|
6
|
+
background: string;
|
|
7
|
+
primary: string;
|
|
8
|
+
secondary: string;
|
|
9
|
+
accent3: string;
|
|
10
|
+
accent4: string;
|
|
11
|
+
accent5: string;
|
|
12
|
+
accent6: string;
|
|
13
|
+
}
|
|
14
|
+
declare const FALLBACK_THEME_TOKENS: ThemeTokens;
|
|
4
15
|
declare const alignItemsSchema: z.ZodEnum<{
|
|
5
16
|
start: "start";
|
|
6
17
|
center: "center";
|
|
@@ -3618,5 +3629,5 @@ type SlideMasterBackground = z.infer<typeof slideMasterBackgroundSchema>;
|
|
|
3618
3629
|
type SlideMasterMargin = z.infer<typeof slideMasterMarginSchema>;
|
|
3619
3630
|
type SlideMasterOptions = z.infer<typeof slideMasterOptionsSchema>;
|
|
3620
3631
|
//#endregion
|
|
3621
|
-
export { MasterImageObject, MasterLineObject, MasterObject, MasterRectObject, MasterTextObject, POMNode, SlideMasterBackground, SlideMasterMargin, SlideMasterOptions, SlideNumberOptions };
|
|
3632
|
+
export { AlignItems, ArrowNode, ChartNode, FALLBACK_THEME_TOKENS, FlexWrap, FlowNode, HStackNode, IconNode, ImageNode, JustifyContent, LayerNode, LineNode, MasterImageObject, MasterLineObject, MasterObject, MasterRectObject, MasterTextObject, MatrixNode, OlNode, POMNode, ProcessArrowNode, PyramidNode, ShapeNode, SlideMasterBackground, SlideMasterMargin, SlideMasterOptions, SlideNumberOptions, SvgNode, TableNode, TextNode, ThemeTokens, TimelineNode, TreeDataItem, TreeNode, UlNode, VStackNode, arrowNodeSchema, chartNodeSchema, flowNodeSchema, iconNodeSchema, imageNodeSchema, lineNodeSchema, masterObjectSchema, matrixNodeSchema, olNodeSchema, processArrowNodeSchema, pyramidNodeSchema, shapeNodeSchema, slideMasterOptionsSchema, svgNodeSchema, tableNodeSchema, textNodeSchema, timelineNodeSchema, treeNodeSchema, ulNodeSchema };
|
|
3622
3633
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;UAKiB,WAAA;EACf,IAAA;EACA,UAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,cAGW,qBAAA,EAAuB,WASnC;AAAA,cAyGK,gBAAA,EAAgB,CAAA,CAAA,OAAA;;;;;;cAMhB,cAAA,EAAc,CAAA,CAAA,OAAA;;;;;cAEd,oBAAA,EAAoB,CAAA,CAAA,OAAA;;;;;;;;KAiMd,UAAA,GAAa,CAAA,CAAE,KAAK,QAAQ,gBAAA;AAAA,KAC5B,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,KAC1B,cAAA,GAAiB,CAAA,CAAE,KAAK,QAAQ,oBAAA;AAAA,cA+BtC,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+BlB,WAAA,GAAc,CAAA,CAAE,KAAK,QAAQ,iBAAA;AAAA,cAoBrB,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsCd,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiBZ,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA2BZ,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuBf,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAcf,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,cAEzB,aAAA,EAAa,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAQd,OAAA,GAAU,CAAA,CAAE,KAAK,QAAQ,aAAA;AAAA,cA8BxB,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAQf,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAwCf,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAehB,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,KAE1B,MAAA,GAAS,CAAA,CAAE,KAAK,QAAQ,YAAA;AAAA,KACxB,MAAA,GAAS,CAAA,CAAE,KAAK,QAAQ,YAAA;AAAA,KACxB,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,eAAA;AAAA,KAC3B,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,eAAA;AAAA,KAC3B,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,eAAA;AAAA,KAC3B,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,eAAA;AAAA,cAa1B,kBAAA,EAAkB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAanB,YAAA,GAAe,CAAA,CAAE,KAAK,QAAQ,kBAAA;AAAA,cAuB7B,gBAAA,EAAgB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUjB,UAAA,GAAa,CAAA,CAAE,KAAK,QAAQ,gBAAA;AAAA,KAY5B,YAAA;EACV,KAAA;EACA,KAAA;EACA,SAAA;EACA,QAAA,GAAW,YAAY;AAAA;AAAA,cAYZ,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAef,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,cAWzB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgBvB,gBAAA,GAAmB,CAAA,CAAE,KAAK,QAAQ,sBAAA;AAAA,cAWjC,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KASlB,WAAA,GAAc,CAAA,CAAE,KAAK,QAAQ,iBAAA;AAAA,cA+C5B,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWf,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,cAkBzB,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAcf,QAAA,GAAW,CAAA,CAAE,KAAK,QAAQ,cAAA;AAAA,cAGzB,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWhB,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,eAAA;AAAA,KAQ3B,UAAA,GAAa,WAAA;EACvB,IAAA;EACA,QAAA,EAAU,OAAA;EACV,GAAA;EACA,UAAA,GAAa,UAAA;EACb,cAAA,GAAiB,cAAA;EACjB,QAAA,GAAW,QAAA;AAAA;AAAA,KAGD,UAAA,GAAa,WAAA;EACvB,IAAA;EACA,QAAA,EAAU,OAAA;EACV,GAAA;EACA,UAAA,GAAa,UAAA;EACb,cAAA,GAAiB,cAAA;EACjB,QAAA,GAAW,QAAA;AAAA;AAAA,KAIR,UAAA,GAAa,OAAO;EACvB,CAAA;EACA,CAAA;AAAA;AAAA,KAGU,SAAA,GAAY,WAAA;EACtB,IAAA;EACA,QAAA,EAAU,UAAU;AAAA;AAAA,KAGV,OAAA,GACR,QAAA,GACA,MAAA,GACA,MAAA,GACA,SAAA,GACA,SAAA,GACA,UAAA,GACA,UAAA,GACA,SAAA,GACA,SAAA,GACA,YAAA,GACA,UAAA,GACA,QAAA,GACA,QAAA,GACA,gBAAA,GACA,WAAA,GACA,QAAA,GACA,SAAA,GACA,SAAA,GACA,QAAA,GACA,OAAA;AAAA,cA4JE,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkBtB,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;;cASvB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;cAUtB,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;cASf,kBAAA,EAAkB,CAAA,CAAA,qBAAA,EAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAOzB,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;cAUxB,2BAAA,EAA2B,CAAA,CAAA,QAAA,WAAA,CAAA,CAAA,SAAA;;;;;;;;;cAO3B,uBAAA,EAAuB,CAAA,CAAA,QAAA,WAAA,CAAA,CAAA,SAAA,EAAA,CAAA,CAAA,SAAA;;;;;;cAUhB,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAQzB,gBAAA,GAAmB,CAAA,CAAE,KAAK,QAAQ,sBAAA;AAAA,KAClC,iBAAA,GAAoB,CAAA,CAAE,KAAK,QAAQ,uBAAA;AAAA,KACnC,gBAAA,GAAmB,CAAA,CAAE,KAAK,QAAQ,sBAAA;AAAA,KAClC,gBAAA,GAAmB,CAAA,CAAE,KAAK,QAAQ,sBAAA;AAAA,KAClC,YAAA,GAAe,CAAA,CAAE,KAAK,QAAQ,kBAAA;AAAA,KAC9B,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,wBAAA;AAAA,KACpC,qBAAA,GAAwB,CAAA,CAAE,KAAK,QAAQ,2BAAA;AAAA,KACvC,iBAAA,GAAoB,CAAA,CAAE,KAAK,QAAQ,uBAAA;AAAA,KACnC,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,wBAAA"}
|
package/dist/types.js
CHANGED
|
@@ -2,6 +2,16 @@ import { parseGradient, parseLinearGradient } from "./shared/gradient.js";
|
|
|
2
2
|
import { ICON_DATA } from "./icons/iconData.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/types.ts
|
|
5
|
+
const FALLBACK_THEME_TOKENS = {
|
|
6
|
+
text: "#000000",
|
|
7
|
+
background: "#FFFFFF",
|
|
8
|
+
primary: "#4472C4",
|
|
9
|
+
secondary: "#ED7D31",
|
|
10
|
+
accent3: "#A5A5A5",
|
|
11
|
+
accent4: "#FFC000",
|
|
12
|
+
accent5: "#5B9BD5",
|
|
13
|
+
accent6: "#70AD47"
|
|
14
|
+
};
|
|
5
15
|
const lengthSchema = z.union([
|
|
6
16
|
z.number(),
|
|
7
17
|
z.literal("max"),
|
|
@@ -915,6 +925,6 @@ z.object({
|
|
|
915
925
|
slideNumber: slideNumberOptionsSchema.optional()
|
|
916
926
|
});
|
|
917
927
|
//#endregion
|
|
918
|
-
export { arrowNodeSchema, chartNodeSchema, flowNodeSchema, hStackNodeSchema, iconNodeSchema, imageNodeSchema, layerNodeSchema, lineNodeSchema, matrixNodeSchema, olNodeSchema, processArrowNodeSchema, pyramidNodeSchema, shapeNodeSchema, svgNodeSchema, tableNodeSchema, textNodeSchema, timelineNodeSchema, treeNodeSchema, ulNodeSchema, vStackNodeSchema };
|
|
928
|
+
export { FALLBACK_THEME_TOKENS, arrowNodeSchema, chartNodeSchema, flowNodeSchema, hStackNodeSchema, iconNodeSchema, imageNodeSchema, layerNodeSchema, liNodeSchema, lineArrowSchema, lineNodeSchema, masterObjectSchema, matrixNodeSchema, olNodeSchema, processArrowNodeSchema, pyramidNodeSchema, shadowStyleSchema, shapeNodeSchema, svgNodeSchema, tableNodeSchema, textGlowSchema, textNodeSchema, textOutlineSchema, timelineNodeSchema, treeConnectorStyleSchema, treeNodeSchema, treeNodeShapeSchema, ulNodeSchema, underlineSchema, underlineStyleSchema, vStackNodeSchema };
|
|
919
929
|
|
|
920
930
|
//# sourceMappingURL=types.js.map
|