@hirokisakabe/pom 10.0.0 → 10.2.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 +1 -1
- package/dist/autoFit/autoFit.js +55 -15
- package/dist/autoFit/autoFit.js.map +1 -1
- package/dist/autoFit/strategies/reduceFontSize.js.map +1 -1
- package/dist/buildContext.js +4 -4
- package/dist/buildContext.js.map +1 -1
- package/dist/buildPptx.d.ts +3 -2
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +1 -1
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/calcYogaLayout/fontLoader.d.ts +13 -0
- package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -0
- package/dist/calcYogaLayout/fontLoader.js +70 -3
- package/dist/calcYogaLayout/fontLoader.js.map +1 -1
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +6 -6
- package/dist/calcYogaLayout/measureText.js.map +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/extractSlideMastersAsPptx.d.ts.map +1 -1
- package/dist/extractThemeTokensFromPptx.d.ts +0 -1
- package/dist/extractThemeTokensFromPptx.d.ts.map +1 -1
- package/dist/icons/renderIcon.js +12 -10
- package/dist/icons/renderIcon.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/parseXml/coercionRules.js.map +1 -1
- package/dist/parseXml/parseXml.d.ts +0 -1
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.d.ts +0 -1
- package/dist/parseXml/serializeXml.d.ts.map +1 -1
- package/dist/parseXml/serializeXml.js.map +1 -1
- package/dist/registry/definitions/icon.js +1 -1
- package/dist/registry/definitions/list.js +1 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/registry/definitions/shape.js +1 -1
- package/dist/registry/definitions/shape.js.map +1 -1
- package/dist/registry/definitions/text.js +1 -1
- package/dist/registry/definitions/text.js.map +1 -1
- package/dist/renderPptx/authoringContext.js +101 -0
- package/dist/renderPptx/authoringContext.js.map +1 -0
- package/dist/renderPptx/{pptxAuthoring.js → glimpseAdapter.js} +83 -152
- package/dist/renderPptx/glimpseAdapter.js.map +1 -0
- package/dist/renderPptx/nodes/arrow.js +49 -7
- package/dist/renderPptx/nodes/arrow.js.map +1 -1
- package/dist/renderPptx/nodes/chart.js +2 -2
- package/dist/renderPptx/nodes/chart.js.map +1 -1
- package/dist/renderPptx/nodes/icon.js +1 -1
- package/dist/renderPptx/nodes/icon.js.map +1 -1
- package/dist/renderPptx/nodes/list.js +11 -19
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/shape.js +18 -19
- package/dist/renderPptx/nodes/shape.js.map +1 -1
- package/dist/renderPptx/nodes/table.js +12 -21
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +16 -1
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/renderPptx.js +93 -40
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/utils/connectorSites.js +58 -0
- package/dist/renderPptx/utils/connectorSites.js.map +1 -0
- package/dist/renderPptx/utils/glimpsePicture.js +2 -4
- package/dist/renderPptx/utils/glimpsePicture.js.map +1 -1
- package/dist/renderPptx/utils/glimpseShape.js +3 -3
- package/dist/renderPptx/utils/glimpseShape.js.map +1 -1
- package/dist/renderPptx/utils/glimpseTextBox.js +3 -30
- package/dist/renderPptx/utils/glimpseTextBox.js.map +1 -1
- package/dist/renderPptx/utils/straightLine.js.map +1 -1
- package/dist/renderPptx/writablePptx.d.ts +1 -1
- package/dist/renderPptx/writablePptx.d.ts.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +10 -6
- package/dist/renderPptx/pptxAuthoring.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializeXml.d.ts","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"serializeXml.d.ts","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"mappings":";;;;;;;;;;;;;;;;;;iBAsJgB,aAAa,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializeXml.js","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"sourcesContent":["import type { POMNode } from \"../types.ts\";\nimport { getNodeMetadata } from \"../registry/nodeMetadata.ts\";\nimport {\n INLINE_BOOLEAN_FORMATS,\n INLINE_LINK_TAG,\n INLINE_MARK_TAG,\n INLINE_SPAN_TAG,\n type TextRun,\n} from \"../registry/xmlChildRules.ts\";\n\n// runs と svgContent は専用の直列化パスで処理する\nconst SKIP_KEYS = new Set([\"type\", \"children\", \"runs\", \"svgContent\"]);\n\nfunction escapeAttrValue(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeXmlContent(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction serializePrimitive(value: string | number | boolean): string {\n if (typeof value === \"string\") return escapeAttrValue(value);\n if (typeof value === \"number\") return String(value);\n return value ? \"true\" : \"false\";\n}\n\nfunction serializeAttrs(node: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n if (SKIP_KEYS.has(key) || value === undefined) continue;\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n for (const [subKey, subValue] of Object.entries(\n value as Record<string, unknown>,\n )) {\n if (subValue !== undefined) {\n parts.push(\n `${key}.${subKey}=\"${serializePrimitive(subValue as string | number | boolean)}\"`,\n );\n }\n }\n } else if (Array.isArray(value)) {\n parts.push(`${key}=\"${escapeAttrValue(JSON.stringify(value))}\"`);\n } else if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n parts.push(`${key}=\"${serializePrimitive(value)}\"`);\n }\n }\n return parts.length > 0 ? \" \" + parts.join(\" \") : \"\";\n}\n\nfunction serializeRun(run: TextRun): string {\n let content = escapeXmlContent(run.text);\n\n if (run.href) {\n content = `<${INLINE_LINK_TAG} href=\"${escapeAttrValue(run.href)}\">${content}</${INLINE_LINK_TAG}>`;\n }\n if (run.highlight) {\n content = `<${INLINE_MARK_TAG} color=\"${escapeAttrValue(run.highlight)}\">${content}</${INLINE_MARK_TAG}>`;\n }\n const spanAttrs: string[] = [];\n if (run.color) spanAttrs.push(`color=\"${escapeAttrValue(run.color)}\"`);\n if (run.fontFamily)\n spanAttrs.push(`fontFamily=\"${escapeAttrValue(run.fontFamily)}\"`);\n if (run.fontSize !== undefined) spanAttrs.push(`fontSize=\"${run.fontSize}\"`);\n if (run.letterSpacing !== undefined)\n spanAttrs.push(`letterSpacing=\"${run.letterSpacing}\"`);\n if (spanAttrs.length > 0) {\n content = `<${INLINE_SPAN_TAG} ${spanAttrs.join(\" \")}>${content}</${INLINE_SPAN_TAG}>`;\n }\n // INLINE_BOOLEAN_FORMATS は外側→内側のネスト順なので、内側から順に包む\n for (let i = INLINE_BOOLEAN_FORMATS.length - 1; i >= 0; i--) {\n const { tag, property } = INLINE_BOOLEAN_FORMATS[i];\n if (run[property]) content = `<${tag}>${content}</${tag}>`;\n }\n return content;\n}\n\nfunction serializeRuns(runs: TextRun[]): string {\n return runs.map(serializeRun).join(\"\");\n}\n\nfunction serializeNode(node: POMNode, depth: number): string {\n const indent = \" \".repeat(depth);\n const def = getNodeMetadata(node.type);\n const tag = def.tagName;\n const nodeRecord = node as Record<string, unknown>;\n\n if (def.childPolicy.kind === \"pom-children\") {\n const children = (nodeRecord.children as POMNode[]) ?? [];\n const attrStr = serializeAttrs(nodeRecord);\n if (children.length === 0) {\n return `${indent}<${tag}${attrStr} />`;\n }\n const childrenStr = children\n .map((c) => serializeNode(c, depth + 1))\n .join(\"\\n\");\n return `${indent}<${tag}${attrStr}>\\n${childrenStr}\\n${indent}</${tag}>`;\n }\n\n if (node.type === \"svg\") {\n const svgContent = (nodeRecord.svgContent as string) ?? \"\";\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr}>\\n${svgContent}\\n${indent}</${tag}>`;\n }\n\n // Text / Shape: runs があればインライン child element として直列化し装飾を保持する\n if (\n def.supportsInlineRuns &&\n Array.isArray(nodeRecord.runs) &&\n (nodeRecord.runs as unknown[]).length > 0\n ) {\n const runs = nodeRecord.runs as TextRun[];\n // runs がある場合、text は runs から復元できるため属性からも除外する\n const attrsWithoutText = { ...nodeRecord, text: undefined };\n const attrStr = serializeAttrs(attrsWithoutText);\n const inlineContent = serializeRuns(runs);\n return `${indent}<${tag}${attrStr}>${inlineContent}</${tag}>`;\n }\n\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr} />`;\n}\n\n/**\n * POMNode 配列を XML 文字列に変換する。\n *\n * parseXml の逆操作として機能する。runs(インライン装飾)は\n * B/I/A/U/S/Sub/Sup/Mark/Span タグとして child element に直列化されるため、\n * テキストの装飾情報も保持される。\n *\n * @example\n * ```typescript\n * import { parseXml, serializeXml } from \"@hirokisakabe/pom\";\n *\n * const nodes = parseXml(xml);\n * // ... ノードの並び替えなど ...\n * const newXml = serializeXml(nodes);\n * ```\n */\nexport function serializeXml(nodes: POMNode[]): string {\n return nodes\n .map((node) => `<Slide>\\n${serializeNode(node, 1)}\\n</Slide>`)\n .join(\"\\n\");\n}\n"],"mappings":";;;AAWA,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAQ;CAAY;CAAQ;AAAY,CAAC;AAEpE,SAAS,gBAAgB,OAAuB;CAC9C,OAAO,MACJ,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,QAAQ,CAAC,CACvB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM;AACzB;AAEA,SAAS,iBAAiB,OAAuB;CAC/C,OAAO,MACJ,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM;AACzB;AAEA,SAAS,mBAAmB,OAA0C;CACpE,IAAI,OAAO,UAAU,UAAU,OAAO,gBAAgB,KAAK;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;CAClD,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,eAAe,MAAuC;CAC7D,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;EAC/C,IAAI,UAAU,IAAI,GAAG,KAAK,UAAU,KAAA,GAAW;EAC/C,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"serializeXml.js","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"sourcesContent":["import type { POMNode } from \"../types.ts\";\nimport { getNodeMetadata } from \"../registry/nodeMetadata.ts\";\nimport {\n INLINE_BOOLEAN_FORMATS,\n INLINE_LINK_TAG,\n INLINE_MARK_TAG,\n INLINE_SPAN_TAG,\n type TextRun,\n} from \"../registry/xmlChildRules.ts\";\n\n// runs と svgContent は専用の直列化パスで処理する\nconst SKIP_KEYS = new Set([\"type\", \"children\", \"runs\", \"svgContent\"]);\n\nfunction escapeAttrValue(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeXmlContent(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction serializePrimitive(value: string | number | boolean): string {\n if (typeof value === \"string\") return escapeAttrValue(value);\n if (typeof value === \"number\") return String(value);\n return value ? \"true\" : \"false\";\n}\n\nfunction serializeAttrs(node: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n if (SKIP_KEYS.has(key) || value === undefined) continue;\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n for (const [subKey, subValue] of Object.entries(\n value as Record<string, unknown>,\n )) {\n if (subValue !== undefined) {\n parts.push(\n `${key}.${subKey}=\"${serializePrimitive(subValue as string | number | boolean)}\"`,\n );\n }\n }\n } else if (Array.isArray(value)) {\n parts.push(`${key}=\"${escapeAttrValue(JSON.stringify(value))}\"`);\n } else if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n parts.push(`${key}=\"${serializePrimitive(value)}\"`);\n }\n }\n return parts.length > 0 ? \" \" + parts.join(\" \") : \"\";\n}\n\nfunction serializeRun(run: TextRun): string {\n let content = escapeXmlContent(run.text);\n\n if (run.href) {\n content = `<${INLINE_LINK_TAG} href=\"${escapeAttrValue(run.href)}\">${content}</${INLINE_LINK_TAG}>`;\n }\n if (run.highlight) {\n content = `<${INLINE_MARK_TAG} color=\"${escapeAttrValue(run.highlight)}\">${content}</${INLINE_MARK_TAG}>`;\n }\n const spanAttrs: string[] = [];\n if (run.color) spanAttrs.push(`color=\"${escapeAttrValue(run.color)}\"`);\n if (run.fontFamily)\n spanAttrs.push(`fontFamily=\"${escapeAttrValue(run.fontFamily)}\"`);\n if (run.fontSize !== undefined) spanAttrs.push(`fontSize=\"${run.fontSize}\"`);\n if (run.letterSpacing !== undefined)\n spanAttrs.push(`letterSpacing=\"${run.letterSpacing}\"`);\n if (spanAttrs.length > 0) {\n content = `<${INLINE_SPAN_TAG} ${spanAttrs.join(\" \")}>${content}</${INLINE_SPAN_TAG}>`;\n }\n // INLINE_BOOLEAN_FORMATS は外側→内側のネスト順なので、内側から順に包む\n for (let i = INLINE_BOOLEAN_FORMATS.length - 1; i >= 0; i--) {\n const { tag, property } = INLINE_BOOLEAN_FORMATS[i];\n if (run[property]) content = `<${tag}>${content}</${tag}>`;\n }\n return content;\n}\n\nfunction serializeRuns(runs: TextRun[]): string {\n return runs.map(serializeRun).join(\"\");\n}\n\nfunction serializeNode(node: POMNode, depth: number): string {\n const indent = \" \".repeat(depth);\n const def = getNodeMetadata(node.type);\n const tag = def.tagName;\n const nodeRecord = node as Record<string, unknown>;\n\n if (def.childPolicy.kind === \"pom-children\") {\n const children = (nodeRecord.children as POMNode[]) ?? [];\n const attrStr = serializeAttrs(nodeRecord);\n if (children.length === 0) {\n return `${indent}<${tag}${attrStr} />`;\n }\n const childrenStr = children\n .map((c) => serializeNode(c, depth + 1))\n .join(\"\\n\");\n return `${indent}<${tag}${attrStr}>\\n${childrenStr}\\n${indent}</${tag}>`;\n }\n\n if (node.type === \"svg\") {\n const svgContent = (nodeRecord.svgContent as string) ?? \"\";\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr}>\\n${svgContent}\\n${indent}</${tag}>`;\n }\n\n // Text / Shape: runs があればインライン child element として直列化し装飾を保持する\n if (\n def.supportsInlineRuns &&\n Array.isArray(nodeRecord.runs) &&\n (nodeRecord.runs as unknown[]).length > 0\n ) {\n const runs = nodeRecord.runs as TextRun[];\n // runs がある場合、text は runs から復元できるため属性からも除外する\n const attrsWithoutText = { ...nodeRecord, text: undefined };\n const attrStr = serializeAttrs(attrsWithoutText);\n const inlineContent = serializeRuns(runs);\n return `${indent}<${tag}${attrStr}>${inlineContent}</${tag}>`;\n }\n\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr} />`;\n}\n\n/**\n * POMNode 配列を XML 文字列に変換する。\n *\n * parseXml の逆操作として機能する。runs(インライン装飾)は\n * B/I/A/U/S/Sub/Sup/Mark/Span タグとして child element に直列化されるため、\n * テキストの装飾情報も保持される。\n *\n * @example\n * ```typescript\n * import { parseXml, serializeXml } from \"@hirokisakabe/pom\";\n *\n * const nodes = parseXml(xml);\n * // ... ノードの並び替えなど ...\n * const newXml = serializeXml(nodes);\n * ```\n */\nexport function serializeXml(nodes: POMNode[]): string {\n return nodes\n .map((node) => `<Slide>\\n${serializeNode(node, 1)}\\n</Slide>`)\n .join(\"\\n\");\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getNodeMetadata } from "../nodeMetadata.js";
|
|
2
1
|
import { getContentArea } from "../../renderPptx/utils/contentArea.js";
|
|
2
|
+
import { getNodeMetadata } from "../nodeMetadata.js";
|
|
3
3
|
import { rasterizeIcon } from "../../icons/renderIcon.js";
|
|
4
4
|
import "../../icons/index.js";
|
|
5
5
|
import { renderIconNode } from "../../renderPptx/nodes/icon.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","names":[],"sources":["../../../src/registry/definitions/list.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 { measureFontLineHeightRatio } from \"../../calcYogaLayout/fontLoader.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderUlNode, renderOlNode } from \"../../renderPptx/nodes/list.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nfunction applyListYogaStyle(\n node: POMNode,\n yn: YogaNode,\n yoga: Yoga,\n ctx: BuildContext,\n) {\n const n = node as Extract<POMNode, { type: \"ul\" | \"ol\" }>;\n const combinedText = n.items.map((item) => item.text).join(\"\\n\");\n const baseFontSizePx = n.fontSize ?? 24;\n // Li 単位の fontSize 上書きと、Li 内 <Span fontSize=\"...\"> による run 単位\n // 上書きを両方考慮した最大値で計測する。単一 fontSize でしか計測できない\n // 制約に対する保守的な見積もりで、横方向は過剰評価になるが縦方向 clipping\n // を防ぐ。\n const fontSizePx = Math.max(\n baseFontSizePx,\n ...n.items.flatMap((item) => [\n item.fontSize ?? baseFontSizePx,\n ...(item.runs?.map(\n (r) => r.fontSize ?? item.fontSize ?? baseFontSizePx,\n ) ?? []),\n ]),\n );\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const spacingMultiple = n.lineHeight ?? 1.3;\n\n const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);\n const lineHeight = fontMetricsRatio * spacingMultiple;\n\n // バレット/番号の互換インデント幅(27pt = 36px @96dpi)\n const bulletIndentPx = 36;\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 textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);\n\n const { widthPx, heightPx } = measureText(\n combinedText,\n textMaxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return {\n width: widthPx + bulletIndentPx,\n height: heightPx,\n };\n });\n}\n\nexport const ulNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"ul\"),\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderUlNode(node as Extract<typeof node, { type: \"ul\" }>, ctx);\n },\n};\n\nexport const olNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"ol\"),\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderOlNode(node as Extract<typeof node, { type: \"ol\" }>, ctx);\n },\n};\n"],"mappings":";;;;;AASA,SAAS,mBACP,MACA,IACA,MACA,KACA;CACA,MAAM,IAAI;CACV,MAAM,eAAe,EAAE,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI;CAC/D,MAAM,iBAAiB,EAAE,YAAY;CAKrC,MAAM,aAAa,KAAK,IACtB,gBACA,GAAG,EAAE,MAAM,SAAS,SAAS,CAC3B,KAAK,YAAY,gBACjB,GAAI,KAAK,MAAM,KACZ,MAAM,EAAE,YAAY,KAAK,YAAY,cACxC,KAAK,CAAC,CACR,CAAC,CACH;CACA,MAAM,aAAa,EAAE,cAAc;CACnC,MAAM,aAAa,EAAE,OAAO,SAAS;CACrC,MAAM,kBAAkB,EAAE,cAAc;CAGxC,MAAM,aADmB,2BAA2B,UAClB,IAAI;CAGtC,MAAM,iBAAiB;CAEvB,GAAG,gBAAgB,OAAO,cAAc;EACtC,MAAM,oBAAoB;GACxB,QAAQ,WAAR;IACE,KAAK,KAAK,wBACR,OAAO,OAAO;IAChB,KAAK,KAAK;IACV,KAAK,KAAK,sBACR,OAAO;IACT,SACE,OAAO,OAAO;GAClB;EACF,EAAA,CAAG;EAEH,MAAM,iBAAiB,KAAK,IAAI,GAAG,aAAa,cAAc;EAE9D,MAAM,EAAE,SAAS,aAAa,YAC5B,cACA,gBACA;GACE;GACA;GACA;GACA;EACF,GACA,IAAI,
|
|
1
|
+
{"version":3,"file":"list.js","names":[],"sources":["../../../src/registry/definitions/list.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 { measureFontLineHeightRatio } from \"../../calcYogaLayout/fontLoader.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderUlNode, renderOlNode } from \"../../renderPptx/nodes/list.ts\";\nimport { getNodeMetadata } from \"../nodeMetadata.ts\";\n\nfunction applyListYogaStyle(\n node: POMNode,\n yn: YogaNode,\n yoga: Yoga,\n ctx: BuildContext,\n) {\n const n = node as Extract<POMNode, { type: \"ul\" | \"ol\" }>;\n const combinedText = n.items.map((item) => item.text).join(\"\\n\");\n const baseFontSizePx = n.fontSize ?? 24;\n // Li 単位の fontSize 上書きと、Li 内 <Span fontSize=\"...\"> による run 単位\n // 上書きを両方考慮した最大値で計測する。単一 fontSize でしか計測できない\n // 制約に対する保守的な見積もりで、横方向は過剰評価になるが縦方向 clipping\n // を防ぐ。\n const fontSizePx = Math.max(\n baseFontSizePx,\n ...n.items.flatMap((item) => [\n item.fontSize ?? baseFontSizePx,\n ...(item.runs?.map(\n (r) => r.fontSize ?? item.fontSize ?? baseFontSizePx,\n ) ?? []),\n ]),\n );\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const spacingMultiple = n.lineHeight ?? 1.3;\n\n const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);\n const lineHeight = fontMetricsRatio * spacingMultiple;\n\n // バレット/番号の互換インデント幅(27pt = 36px @96dpi)\n const bulletIndentPx = 36;\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 textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);\n\n const { widthPx, heightPx } = measureText(\n combinedText,\n textMaxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n ctx.fontRegistry,\n );\n\n return {\n width: widthPx + bulletIndentPx,\n height: heightPx,\n };\n });\n}\n\nexport const ulNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"ul\"),\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderUlNode(node as Extract<typeof node, { type: \"ul\" }>, ctx);\n },\n};\n\nexport const olNodeDef: NodeDefinition = {\n ...getNodeMetadata(\"ol\"),\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderOlNode(node as Extract<typeof node, { type: \"ol\" }>, ctx);\n },\n};\n"],"mappings":";;;;;AASA,SAAS,mBACP,MACA,IACA,MACA,KACA;CACA,MAAM,IAAI;CACV,MAAM,eAAe,EAAE,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI;CAC/D,MAAM,iBAAiB,EAAE,YAAY;CAKrC,MAAM,aAAa,KAAK,IACtB,gBACA,GAAG,EAAE,MAAM,SAAS,SAAS,CAC3B,KAAK,YAAY,gBACjB,GAAI,KAAK,MAAM,KACZ,MAAM,EAAE,YAAY,KAAK,YAAY,cACxC,KAAK,CAAC,CACR,CAAC,CACH;CACA,MAAM,aAAa,EAAE,cAAc;CACnC,MAAM,aAAa,EAAE,OAAO,SAAS;CACrC,MAAM,kBAAkB,EAAE,cAAc;CAGxC,MAAM,aADmB,2BAA2B,UAClB,IAAI;CAGtC,MAAM,iBAAiB;CAEvB,GAAG,gBAAgB,OAAO,cAAc;EACtC,MAAM,oBAAoB;GACxB,QAAQ,WAAR;IACE,KAAK,KAAK,wBACR,OAAO,OAAO;IAChB,KAAK,KAAK;IACV,KAAK,KAAK,sBACR,OAAO;IACT,SACE,OAAO,OAAO;GAClB;EACF,EAAA,CAAG;EAEH,MAAM,iBAAiB,KAAK,IAAI,GAAG,aAAa,cAAc;EAE9D,MAAM,EAAE,SAAS,aAAa,YAC5B,cACA,gBACA;GACE;GACA;GACA;GACA;EACF,GACA,IAAI,qBACJ,IAAI,YACN;EAEA,OAAO;GACL,OAAO,UAAU;GACjB,QAAQ;EACV;CACF,CAAC;AACH;AAEA,MAAa,YAA4B;CACvC,GAAG,gBAAgB,IAAI;CACvB,gBAAgB;CAChB,OAAO,MAAM,KAAK;EAChB,aAAa,MAA8C,GAAG;CAChE;AACF;AAEA,MAAa,YAA4B;CACvC,GAAG,gBAAgB,IAAI;CACvB,gBAAgB;CAChB,OAAO,MAAM,KAAK;EAChB,aAAa,MAA8C,GAAG;CAChE;AACF"}
|
|
@@ -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;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,
|
|
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 ctx.fontRegistry,\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,qBACJ,IAAI,YACN;IAEA,OAAO;KAAE,OAAO;KAAS,QAAQ;IAAS;GAC5C,CAAC;EACH;CACF;CACA,OAAO,MAAM,KAAK;EAChB,gBAAgB,MAAiD,GAAG;CACtE;AACF"}
|
|
@@ -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;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,
|
|
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 ctx.fontRegistry,\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,qBACJ,IAAI,YACN;GAEA,OAAO;IAAE,OAAO;IAAS,QAAQ;GAAS;EAC5C,CAAC;CACH;CACA,OAAO,MAAM,KAAK;EAChB,eAAe,MAAgD,GAAG;CACpE;AACF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createPptxAuthoringSession } from "@pptx-glimpse/document";
|
|
2
|
+
//#region src/renderPptx/authoringContext.ts
|
|
3
|
+
/** Mutable state needed only while authoring a PPTX. */
|
|
4
|
+
var PptxAuthoringContext = class {
|
|
5
|
+
useLayoutTextMargins;
|
|
6
|
+
session;
|
|
7
|
+
currentTargetHandle;
|
|
8
|
+
currentTarget;
|
|
9
|
+
textCount = 0;
|
|
10
|
+
shapeCount = 0;
|
|
11
|
+
pictureCount = 0;
|
|
12
|
+
tableCount = 0;
|
|
13
|
+
chartCount = 0;
|
|
14
|
+
connectorCount = 0;
|
|
15
|
+
constructor(source, useLayoutTextMargins = false) {
|
|
16
|
+
this.useLayoutTextMargins = useLayoutTextMargins;
|
|
17
|
+
this.session = createPptxAuthoringSession(source);
|
|
18
|
+
const firstSlideHandle = source.slides[0]?.handle;
|
|
19
|
+
if (firstSlideHandle) this.selectTarget(firstSlideHandle);
|
|
20
|
+
}
|
|
21
|
+
selectTarget(handle) {
|
|
22
|
+
this.currentTargetHandle = handle;
|
|
23
|
+
this.currentTarget = this.session.target(handle);
|
|
24
|
+
}
|
|
25
|
+
get source() {
|
|
26
|
+
return this.session.source;
|
|
27
|
+
}
|
|
28
|
+
addEmptySlideFromLayout(input) {
|
|
29
|
+
return this.session.addEmptySlideFromLayout(input);
|
|
30
|
+
}
|
|
31
|
+
get target() {
|
|
32
|
+
if (!this.currentTarget) throw new Error("glimpse slide or master is not selected");
|
|
33
|
+
return this.currentTarget;
|
|
34
|
+
}
|
|
35
|
+
addTextBox(input, name) {
|
|
36
|
+
return this.target.addTextBox({
|
|
37
|
+
...input,
|
|
38
|
+
name: name ?? `Text ${++this.textCount}`
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
addShape(input, name) {
|
|
42
|
+
return this.target.addShape({
|
|
43
|
+
...input,
|
|
44
|
+
name: name ?? `Shape ${++this.shapeCount}`
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
addConnector(input, name) {
|
|
48
|
+
return this.target.addConnector({
|
|
49
|
+
...input,
|
|
50
|
+
name: name ?? `Connector ${++this.connectorCount}`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
currentTargetShapeHandles() {
|
|
54
|
+
return this.currentTargetShapes().map((shape) => {
|
|
55
|
+
if (!shape.handle) throw new Error("authored shape handle was not found");
|
|
56
|
+
return shape.handle;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
reorderCurrentTargetShapes(handles) {
|
|
60
|
+
this.target.reorderShapes(handles);
|
|
61
|
+
}
|
|
62
|
+
addPicture(input, name) {
|
|
63
|
+
this.target.addPicture({
|
|
64
|
+
...input,
|
|
65
|
+
name: name ?? `Picture ${++this.pictureCount}`
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
addTable(input, name) {
|
|
69
|
+
this.target.addTable({
|
|
70
|
+
...input,
|
|
71
|
+
name: name ?? `Table ${++this.tableCount}`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
addChart(input, name) {
|
|
75
|
+
this.target.addChart({
|
|
76
|
+
...input,
|
|
77
|
+
name: name ?? `Chart ${++this.chartCount}`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
addSlideNumber(input) {
|
|
81
|
+
this.target.addSlideNumber(input);
|
|
82
|
+
}
|
|
83
|
+
setSlideBackground(background) {
|
|
84
|
+
this.target.setSlideBackground(background);
|
|
85
|
+
}
|
|
86
|
+
currentTargetShapes() {
|
|
87
|
+
const partPath = this.currentTargetHandle?.partPath;
|
|
88
|
+
if (!partPath) throw new Error("glimpse slide or master is not selected");
|
|
89
|
+
const target = [
|
|
90
|
+
...this.source.slides,
|
|
91
|
+
...this.source.slideLayouts,
|
|
92
|
+
...this.source.slideMasters
|
|
93
|
+
].find((candidate) => candidate.partPath === partPath);
|
|
94
|
+
if (!target) throw new Error("glimpse authoring target was not found");
|
|
95
|
+
return target.shapes;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
export { PptxAuthoringContext };
|
|
100
|
+
|
|
101
|
+
//# sourceMappingURL=authoringContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoringContext.js","names":[],"sources":["../../src/renderPptx/authoringContext.ts"],"sourcesContent":["import {\n createPptxAuthoringSession,\n type AddChartInput,\n type AddConnectorInput,\n type AddEmptySlideFromLayoutInput,\n type AddPictureInput,\n type AddShapeInput,\n type AddSlideNumberInput,\n type AddTableInput,\n type AddTextBoxInput,\n type PptxAuthoringSession,\n type PptxAuthoringTarget,\n type PptxSourceModel,\n type SourceHandle,\n type SourceShapeNode,\n} from \"@pptx-glimpse/document\";\n\n/** Mutable state needed only while authoring a PPTX. */\nexport class PptxAuthoringContext {\n private readonly session: PptxAuthoringSession;\n private currentTargetHandle: SourceHandle | undefined;\n private currentTarget: PptxAuthoringTarget | undefined;\n private textCount = 0;\n private shapeCount = 0;\n private pictureCount = 0;\n private tableCount = 0;\n private chartCount = 0;\n private connectorCount = 0;\n\n constructor(\n source: PptxSourceModel,\n readonly useLayoutTextMargins = false,\n ) {\n this.session = createPptxAuthoringSession(source);\n const firstSlideHandle = source.slides[0]?.handle;\n if (firstSlideHandle) this.selectTarget(firstSlideHandle);\n }\n\n selectTarget(handle: SourceHandle): void {\n this.currentTargetHandle = handle;\n this.currentTarget = this.session.target(handle);\n }\n\n get source(): PptxSourceModel {\n return this.session.source;\n }\n\n addEmptySlideFromLayout(input: AddEmptySlideFromLayoutInput): SourceHandle {\n return this.session.addEmptySlideFromLayout(input);\n }\n\n private get target(): PptxAuthoringTarget {\n if (!this.currentTarget)\n throw new Error(\"glimpse slide or master is not selected\");\n return this.currentTarget;\n }\n\n addTextBox(input: AddTextBoxInput, name?: string): SourceHandle {\n return this.target.addTextBox({\n ...input,\n name: name ?? `Text ${++this.textCount}`,\n });\n }\n\n addShape(input: AddShapeInput, name?: string): SourceHandle {\n return this.target.addShape({\n ...input,\n name: name ?? `Shape ${++this.shapeCount}`,\n });\n }\n\n addConnector(input: AddConnectorInput, name?: string): SourceHandle {\n return this.target.addConnector({\n ...input,\n name: name ?? `Connector ${++this.connectorCount}`,\n });\n }\n\n currentTargetShapeHandles(): readonly SourceHandle[] {\n return this.currentTargetShapes().map((shape) => {\n if (!shape.handle) throw new Error(\"authored shape handle was not found\");\n return shape.handle;\n });\n }\n\n reorderCurrentTargetShapes(handles: readonly SourceHandle[]): void {\n this.target.reorderShapes(handles);\n }\n\n addPicture(input: AddPictureInput, name?: string): void {\n this.target.addPicture({\n ...input,\n name: name ?? `Picture ${++this.pictureCount}`,\n });\n }\n\n addTable(input: AddTableInput, name?: string): void {\n this.target.addTable({\n ...input,\n name: name ?? `Table ${++this.tableCount}`,\n });\n }\n\n addChart(input: AddChartInput, name?: string): void {\n this.target.addChart({\n ...input,\n name: name ?? `Chart ${++this.chartCount}`,\n });\n }\n\n addSlideNumber(input: AddSlideNumberInput): void {\n this.target.addSlideNumber(input);\n }\n\n setSlideBackground(\n background: Parameters<PptxAuthoringTarget[\"setSlideBackground\"]>[0],\n ): void {\n this.target.setSlideBackground(background);\n }\n\n private currentTargetShapes(): readonly SourceShapeNode[] {\n const partPath = this.currentTargetHandle?.partPath;\n if (!partPath) throw new Error(\"glimpse slide or master is not selected\");\n const target = [\n ...this.source.slides,\n ...this.source.slideLayouts,\n ...this.source.slideMasters,\n ].find((candidate) => candidate.partPath === partPath);\n if (!target) throw new Error(\"glimpse authoring target was not found\");\n return target.shapes;\n }\n}\n"],"mappings":";;;AAkBA,IAAa,uBAAb,MAAkC;CAarB;CAZX;CACA;CACA;CACA,YAAoB;CACpB,aAAqB;CACrB,eAAuB;CACvB,aAAqB;CACrB,aAAqB;CACrB,iBAAyB;CAEzB,YACE,QACA,uBAAgC,OAChC;EADS,KAAA,uBAAA;EAET,KAAK,UAAU,2BAA2B,MAAM;EAChD,MAAM,mBAAmB,OAAO,OAAO,EAAE,EAAE;EAC3C,IAAI,kBAAkB,KAAK,aAAa,gBAAgB;CAC1D;CAEA,aAAa,QAA4B;EACvC,KAAK,sBAAsB;EAC3B,KAAK,gBAAgB,KAAK,QAAQ,OAAO,MAAM;CACjD;CAEA,IAAI,SAA0B;EAC5B,OAAO,KAAK,QAAQ;CACtB;CAEA,wBAAwB,OAAmD;EACzE,OAAO,KAAK,QAAQ,wBAAwB,KAAK;CACnD;CAEA,IAAY,SAA8B;EACxC,IAAI,CAAC,KAAK,eACR,MAAM,IAAI,MAAM,yCAAyC;EAC3D,OAAO,KAAK;CACd;CAEA,WAAW,OAAwB,MAA6B;EAC9D,OAAO,KAAK,OAAO,WAAW;GAC5B,GAAG;GACH,MAAM,QAAQ,QAAQ,EAAE,KAAK;EAC/B,CAAC;CACH;CAEA,SAAS,OAAsB,MAA6B;EAC1D,OAAO,KAAK,OAAO,SAAS;GAC1B,GAAG;GACH,MAAM,QAAQ,SAAS,EAAE,KAAK;EAChC,CAAC;CACH;CAEA,aAAa,OAA0B,MAA6B;EAClE,OAAO,KAAK,OAAO,aAAa;GAC9B,GAAG;GACH,MAAM,QAAQ,aAAa,EAAE,KAAK;EACpC,CAAC;CACH;CAEA,4BAAqD;EACnD,OAAO,KAAK,oBAAoB,CAAC,CAAC,KAAK,UAAU;GAC/C,IAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,qCAAqC;GACxE,OAAO,MAAM;EACf,CAAC;CACH;CAEA,2BAA2B,SAAwC;EACjE,KAAK,OAAO,cAAc,OAAO;CACnC;CAEA,WAAW,OAAwB,MAAqB;EACtD,KAAK,OAAO,WAAW;GACrB,GAAG;GACH,MAAM,QAAQ,WAAW,EAAE,KAAK;EAClC,CAAC;CACH;CAEA,SAAS,OAAsB,MAAqB;EAClD,KAAK,OAAO,SAAS;GACnB,GAAG;GACH,MAAM,QAAQ,SAAS,EAAE,KAAK;EAChC,CAAC;CACH;CAEA,SAAS,OAAsB,MAAqB;EAClD,KAAK,OAAO,SAAS;GACnB,GAAG;GACH,MAAM,QAAQ,SAAS,EAAE,KAAK;EAChC,CAAC;CACH;CAEA,eAAe,OAAkC;EAC/C,KAAK,OAAO,eAAe,KAAK;CAClC;CAEA,mBACE,YACM;EACN,KAAK,OAAO,mBAAmB,UAAU;CAC3C;CAEA,sBAA0D;EACxD,MAAM,WAAW,KAAK,qBAAqB;EAC3C,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,yCAAyC;EACxE,MAAM,SAAS;GACb,GAAG,KAAK,OAAO;GACf,GAAG,KAAK,OAAO;GACf,GAAG,KAAK,OAAO;EACjB,CAAC,CAAC,MAAM,cAAc,UAAU,aAAa,QAAQ;EACrD,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,wCAAwC;EACrE,OAAO,OAAO;CAChB;AACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseGradient, parseLinearGradient } from "../shared/gradient.js";
|
|
2
2
|
import { EMU_PER_IN, pxToEmu, pxToPt } from "./units.js";
|
|
3
3
|
import { createTextOptions, resolveSubSup } from "./textOptions.js";
|
|
4
|
-
import {
|
|
5
|
-
//#region src/renderPptx/
|
|
4
|
+
import { asEmu, asHundredthPt, asOoxmlAngle, asOoxmlPercent, asPt } from "@pptx-glimpse/document";
|
|
5
|
+
//#region src/renderPptx/glimpseAdapter.ts
|
|
6
6
|
function cleanHex(color) {
|
|
7
7
|
const hex = color?.replace(/^#/, "").toUpperCase();
|
|
8
8
|
return hex?.length === 3 ? [...hex].map((character) => character.repeat(2)).join("") : hex;
|
|
@@ -69,9 +69,6 @@ function toTextGradientInput(value) {
|
|
|
69
69
|
}))
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
-
function stripUndefined(value) {
|
|
73
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
74
|
-
}
|
|
75
72
|
function resolveUnderline(node, run) {
|
|
76
73
|
if (run?.underline !== void 0) return run.underline;
|
|
77
74
|
if (node.underline !== void 0) return node.underline;
|
|
@@ -80,28 +77,59 @@ function resolveUnderline(node, run) {
|
|
|
80
77
|
function buildRunProperties(node, run, gradientFill) {
|
|
81
78
|
const fontSizePx = run?.fontSize ?? node.fontSize ?? 24;
|
|
82
79
|
const subSup = run ? resolveSubSup(run, node) : node;
|
|
83
|
-
return
|
|
84
|
-
fontFace: run?.fontFamily ?? node.fontFamily
|
|
85
|
-
fontSize:
|
|
86
|
-
color:
|
|
80
|
+
return createGlimpseRunProperties({
|
|
81
|
+
fontFace: run?.fontFamily ?? node.fontFamily,
|
|
82
|
+
fontSize: fontSizePx,
|
|
83
|
+
color: run?.color ?? node.color,
|
|
87
84
|
gradientFill,
|
|
88
85
|
bold: run?.bold ?? node.bold,
|
|
89
86
|
italic: run?.italic ?? node.italic,
|
|
90
|
-
underline:
|
|
87
|
+
underline: resolveUnderline(node, run),
|
|
91
88
|
strike: run?.strike ?? node.strike,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
subscript: subSup.subscript,
|
|
90
|
+
superscript: subSup.superscript,
|
|
91
|
+
highlight: run?.highlight ?? node.highlight,
|
|
92
|
+
glow: node.glow,
|
|
93
|
+
outline: node.outline,
|
|
94
|
+
letterSpacing: run?.letterSpacing ?? node.letterSpacing
|
|
97
95
|
});
|
|
98
96
|
}
|
|
97
|
+
function createGlimpseRunProperties(style) {
|
|
98
|
+
return {
|
|
99
|
+
fontFace: style.fontFace ?? "Noto Sans JP",
|
|
100
|
+
fontSize: asPt(pxToPt(style.fontSize ?? 24)),
|
|
101
|
+
color: style.gradientFill ? void 0 : toColorInput(style.color),
|
|
102
|
+
gradientFill: style.gradientFill,
|
|
103
|
+
bold: style.bold,
|
|
104
|
+
italic: style.italic,
|
|
105
|
+
underline: toUnderlineInput(style.underline),
|
|
106
|
+
strike: style.strike,
|
|
107
|
+
baseline: toBaselineInput(style.subscript, style.superscript),
|
|
108
|
+
highlight: toColorInput(style.highlight),
|
|
109
|
+
glow: toGlowInput(style.glow),
|
|
110
|
+
outline: toOutlineInput(style.outline),
|
|
111
|
+
charSpacing: toCharSpacing(style.letterSpacing)
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function createGlimpseShapeRunProperties(style) {
|
|
115
|
+
return {
|
|
116
|
+
...createGlimpseRunProperties(style),
|
|
117
|
+
baseline: style.subscript ? "subscript" : style.superscript ? "superscript" : void 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function createGlimpseTableRunProperties(style) {
|
|
121
|
+
return {
|
|
122
|
+
...createGlimpseRunProperties(style),
|
|
123
|
+
fontFace: style.fontFace,
|
|
124
|
+
color: cleanHex(style.color)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
99
127
|
function buildParagraphs(node) {
|
|
100
128
|
const gradientFill = toTextGradientInput(node.textGradient);
|
|
101
129
|
const sourceRuns = node.runs && node.runs.length > 0 ? node.runs.map((run) => ({
|
|
102
130
|
text: run.text,
|
|
103
131
|
properties: buildRunProperties(node, run, gradientFill),
|
|
104
|
-
|
|
132
|
+
hyperlink: run.href
|
|
105
133
|
})) : [{
|
|
106
134
|
text: node.text ?? "",
|
|
107
135
|
properties: buildRunProperties(node, void 0, gradientFill)
|
|
@@ -127,10 +155,28 @@ function buildParagraphs(node) {
|
|
|
127
155
|
runs: runs.map((run) => ({
|
|
128
156
|
text: run.text,
|
|
129
157
|
properties: run.properties,
|
|
130
|
-
hyperlink: run.
|
|
158
|
+
hyperlink: run.hyperlink
|
|
131
159
|
}))
|
|
132
160
|
}));
|
|
133
161
|
}
|
|
162
|
+
function createTextNodeInput(node, useLayoutTextMargins) {
|
|
163
|
+
const textOptions = createTextOptions(node);
|
|
164
|
+
return {
|
|
165
|
+
offsetX: asEmu(Math.round(textOptions.x * EMU_PER_IN)),
|
|
166
|
+
offsetY: asEmu(Math.round(textOptions.y * EMU_PER_IN)),
|
|
167
|
+
width: asEmu(Math.round(textOptions.w * EMU_PER_IN)),
|
|
168
|
+
height: asEmu(Math.round(textOptions.h * EMU_PER_IN)),
|
|
169
|
+
rotation: node.rotate === void 0 ? void 0 : asOoxmlAngle(Math.round(node.rotate * 6e4)),
|
|
170
|
+
body: useLayoutTextMargins ? void 0 : {
|
|
171
|
+
anchor: "top",
|
|
172
|
+
marginLeft: asEmu(0),
|
|
173
|
+
marginRight: asEmu(0),
|
|
174
|
+
marginTop: asEmu(0),
|
|
175
|
+
marginBottom: asEmu(0)
|
|
176
|
+
},
|
|
177
|
+
paragraphs: buildParagraphs(node)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
134
180
|
function toGradientFill(value, opacity) {
|
|
135
181
|
const gradient = parseGradient(value);
|
|
136
182
|
if (!gradient) return void 0;
|
|
@@ -238,144 +284,29 @@ function enrichShapeInput(input, options) {
|
|
|
238
284
|
flipVertical: options?.flipV ?? input.flipVertical
|
|
239
285
|
};
|
|
240
286
|
}
|
|
241
|
-
function
|
|
242
|
-
if (!hyperlinks?.some(Boolean) || !input.paragraphs) return input;
|
|
243
|
-
let index = 0;
|
|
287
|
+
function enrichPictureInput(input, shadow) {
|
|
244
288
|
return {
|
|
245
289
|
...input,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
290
|
+
effects: toShadowEffects(shadow)
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function toSlideBackgroundGradient(backgroundGradient, opacity) {
|
|
294
|
+
const fill = toGradientFill(backgroundGradient, opacity);
|
|
295
|
+
if (!fill || fill.kind !== "gradient") return void 0;
|
|
296
|
+
return fill.gradientType === "linear" ? {
|
|
297
|
+
kind: "gradient",
|
|
298
|
+
gradientType: "linear",
|
|
299
|
+
stops: fill.stops,
|
|
300
|
+
angle: fill.angle ?? asOoxmlAngle(0)
|
|
301
|
+
} : {
|
|
302
|
+
kind: "gradient",
|
|
303
|
+
gradientType: "radial",
|
|
304
|
+
stops: fill.stops,
|
|
305
|
+
centerX: fill.centerX,
|
|
306
|
+
centerY: fill.centerY
|
|
253
307
|
};
|
|
254
308
|
}
|
|
255
|
-
var PptxAuthoringRegistry = class {
|
|
256
|
-
currentSource;
|
|
257
|
-
currentSlideHandle;
|
|
258
|
-
useLayoutTextMargins = false;
|
|
259
|
-
textCount = 0;
|
|
260
|
-
shapeCount = 0;
|
|
261
|
-
pictureCount = 0;
|
|
262
|
-
tableCount = 0;
|
|
263
|
-
chartCount = 0;
|
|
264
|
-
constructor() {
|
|
265
|
-
const source = createPptx();
|
|
266
|
-
this.currentSource = source;
|
|
267
|
-
this.currentSlideHandle = source.slides[0]?.handle;
|
|
268
|
-
}
|
|
269
|
-
initialize(source, useLayoutTextMargins = false) {
|
|
270
|
-
this.currentSource = source;
|
|
271
|
-
this.useLayoutTextMargins = useLayoutTextMargins;
|
|
272
|
-
}
|
|
273
|
-
selectSlide(handle) {
|
|
274
|
-
this.currentSlideHandle = handle;
|
|
275
|
-
}
|
|
276
|
-
get source() {
|
|
277
|
-
if (!this.currentSource) throw new Error("glimpse authoring is not initialized");
|
|
278
|
-
return this.currentSource;
|
|
279
|
-
}
|
|
280
|
-
get entries() {
|
|
281
|
-
return (this.source.edits ?? []).flatMap((edit) => (edit.kind === "addTextBox" || edit.kind === "addShape") && "xml" in edit ? [{
|
|
282
|
-
kind: "shape",
|
|
283
|
-
xml: edit.xml
|
|
284
|
-
}] : []);
|
|
285
|
-
}
|
|
286
|
-
replaceSource(source) {
|
|
287
|
-
this.currentSource = source;
|
|
288
|
-
}
|
|
289
|
-
get target() {
|
|
290
|
-
if (!this.currentSlideHandle) throw new Error("glimpse slide is not selected");
|
|
291
|
-
return this.currentSlideHandle;
|
|
292
|
-
}
|
|
293
|
-
register(node) {
|
|
294
|
-
const textOptions = createTextOptions(node);
|
|
295
|
-
this.registerTextBox({
|
|
296
|
-
offsetX: asEmu(Math.round(textOptions.x * EMU_PER_IN)),
|
|
297
|
-
offsetY: asEmu(Math.round(textOptions.y * EMU_PER_IN)),
|
|
298
|
-
width: asEmu(Math.round(textOptions.w * EMU_PER_IN)),
|
|
299
|
-
height: asEmu(Math.round(textOptions.h * EMU_PER_IN)),
|
|
300
|
-
rotation: node.rotate === void 0 ? void 0 : asOoxmlAngle(Math.round(node.rotate * 6e4)),
|
|
301
|
-
body: this.useLayoutTextMargins ? void 0 : {
|
|
302
|
-
anchor: "top",
|
|
303
|
-
marginLeft: asEmu(0),
|
|
304
|
-
marginRight: asEmu(0),
|
|
305
|
-
marginTop: asEmu(0),
|
|
306
|
-
marginBottom: asEmu(0)
|
|
307
|
-
},
|
|
308
|
-
paragraphs: buildParagraphs(node)
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
registerTextBox(input, options) {
|
|
312
|
-
const name = options?.name ?? `Text ${++this.textCount}`;
|
|
313
|
-
this.currentSource = addTextBox(this.source, this.target, applyHyperlinks({
|
|
314
|
-
...input,
|
|
315
|
-
name
|
|
316
|
-
}, options?.hyperlinks));
|
|
317
|
-
}
|
|
318
|
-
registerShape(input, options) {
|
|
319
|
-
const name = options?.name ?? `Shape ${++this.shapeCount}`;
|
|
320
|
-
this.currentSource = addShape(this.source, this.target, enrichShapeInput({
|
|
321
|
-
...input,
|
|
322
|
-
name
|
|
323
|
-
}, options));
|
|
324
|
-
}
|
|
325
|
-
registerPicture(input, options) {
|
|
326
|
-
const name = options?.name ?? `Picture ${++this.pictureCount}`;
|
|
327
|
-
this.currentSource = addPicture(this.source, this.target, {
|
|
328
|
-
...input,
|
|
329
|
-
name,
|
|
330
|
-
effects: toShadowEffects(options?.shadow)
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
registerTable(input, options) {
|
|
334
|
-
const name = options?.name ?? `Table ${++this.tableCount}`;
|
|
335
|
-
this.currentSource = addTable(this.source, this.target, {
|
|
336
|
-
...input,
|
|
337
|
-
name
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
registerChart(input, options) {
|
|
341
|
-
const name = options?.name ?? `Chart ${++this.chartCount}`;
|
|
342
|
-
this.currentSource = addChart(this.source, this.target, {
|
|
343
|
-
...input,
|
|
344
|
-
name
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
setSlideBackgroundGradient(backgroundGradient, opacity) {
|
|
348
|
-
const fill = toGradientFill(backgroundGradient, opacity);
|
|
349
|
-
if (!fill || fill.kind !== "gradient") return false;
|
|
350
|
-
const background = fill.gradientType === "linear" ? {
|
|
351
|
-
kind: "gradient",
|
|
352
|
-
gradientType: "linear",
|
|
353
|
-
stops: fill.stops,
|
|
354
|
-
angle: fill.angle ?? asOoxmlAngle(0)
|
|
355
|
-
} : {
|
|
356
|
-
kind: "gradient",
|
|
357
|
-
gradientType: "radial",
|
|
358
|
-
stops: fill.stops,
|
|
359
|
-
centerX: fill.centerX,
|
|
360
|
-
centerY: fill.centerY
|
|
361
|
-
};
|
|
362
|
-
this.currentSource = setSlideBackground(this.source, this.target, background);
|
|
363
|
-
return true;
|
|
364
|
-
}
|
|
365
|
-
setSlideBackgroundSolid(color) {
|
|
366
|
-
this.currentSource = setSlideBackground(this.source, this.target, {
|
|
367
|
-
kind: "solid",
|
|
368
|
-
color: toColorInput(color)
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
setSlideBackgroundImage(bytes) {
|
|
372
|
-
this.currentSource = setSlideBackground(this.source, this.target, {
|
|
373
|
-
kind: "image",
|
|
374
|
-
bytes
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
309
|
//#endregion
|
|
379
|
-
export {
|
|
310
|
+
export { cleanHex, createGlimpseRunProperties, createGlimpseShapeRunProperties, createGlimpseTableRunProperties, createTextNodeInput, enrichPictureInput, enrichShapeInput, toColorInput, toSlideBackgroundGradient };
|
|
380
311
|
|
|
381
|
-
//# sourceMappingURL=
|
|
312
|
+
//# sourceMappingURL=glimpseAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glimpseAdapter.js","names":[],"sources":["../../src/renderPptx/glimpseAdapter.ts"],"sourcesContent":["import {\n asEmu,\n asHundredthPt,\n asOoxmlAngle,\n asOoxmlPercent,\n asPt,\n type AddPictureInput,\n type AddShapeColorInput,\n type AddShapeCustomGeometryPathCommandInput,\n type AddShapeEffectsInput,\n type AddShapeFillInput,\n type AddShapeGeometryInput,\n type AddShapeInput,\n type AddShapeOutlineInput,\n type AddShapeRunPropertiesInput,\n type AddTableRunPropertiesInput,\n type AddTextBoxGradientFillInput,\n type AddTextBoxInput,\n type AddTextBoxParagraphInput,\n type AddTextBoxRunPropertiesInput,\n} from \"@pptx-glimpse/document\";\nimport { parseGradient, parseLinearGradient } from \"../shared/gradient.ts\";\nimport type {\n BorderStyle,\n PositionedNode,\n ShadowStyle,\n TextGlow,\n TextOutline,\n Underline,\n} from \"../types.ts\";\nimport { createTextOptions, resolveSubSup } from \"./textOptions.ts\";\nimport { EMU_PER_IN, pxToEmu, pxToPt } from \"./units.ts\";\n\n/** Pure POM style / geometry conversions for glimpse authoring inputs. */\n\ntype TextPositionedNode = Extract<PositionedNode, { type: \"text\" }>;\n\ninterface GlimpseTextRun {\n text: string;\n properties: AddTextBoxRunPropertiesInput;\n hyperlink?: string;\n}\n\nexport type GlimpseTextRunStyle = {\n fontSize?: number;\n fontFace?: string;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: Underline;\n strike?: boolean;\n subscript?: boolean;\n superscript?: boolean;\n highlight?: string;\n glow?: TextGlow;\n outline?: TextOutline;\n letterSpacing?: number;\n gradientFill?: AddTextBoxGradientFillInput;\n};\n\nexport function cleanHex(color: string | undefined): string | undefined {\n const hex = color?.replace(/^#/, \"\").toUpperCase();\n return hex?.length === 3\n ? [...hex].map((character) => character.repeat(2)).join(\"\")\n : hex;\n}\n\nexport function toColorInput(\n color: string | undefined,\n opacity?: number,\n): AddShapeColorInput | undefined {\n const hex = cleanHex(color);\n if (!hex) return undefined;\n return {\n kind: \"srgb\",\n hex,\n transforms:\n opacity === undefined\n ? undefined\n : [\n {\n kind: \"alpha\",\n value: asOoxmlPercent(Math.round(opacity * 100000)),\n },\n ],\n };\n}\n\nfunction toUnderlineInput(underline: Underline | undefined) {\n if (underline === undefined || underline === false) return undefined;\n if (underline === true) return true;\n return {\n style: underline.style,\n color: toColorInput(underline.color),\n };\n}\n\nfunction toBaselineInput(\n subscript: boolean | undefined,\n superscript: boolean | undefined,\n) {\n if (subscript) {\n return {\n type: \"percent\" as const,\n value: asOoxmlPercent(-40000),\n };\n }\n if (superscript) {\n return {\n type: \"percent\" as const,\n value: asOoxmlPercent(30000),\n };\n }\n return undefined;\n}\n\nfunction toGlowInput(glow: TextGlow | undefined) {\n if (!glow) return undefined;\n return {\n radius: asEmu(Math.round(pxToEmu(glow.size ?? 8))),\n color: toColorInput(glow.color ?? \"FFFFFF\", glow.opacity ?? 0.75)!,\n };\n}\n\nfunction toOutlineInput(outline: TextOutline | undefined) {\n if (!outline) return undefined;\n return {\n width: asEmu(Math.round(pxToEmu(outline.size ?? 1))),\n color: toColorInput(outline.color ?? \"FFFFFF\"),\n };\n}\n\nfunction toCharSpacing(letterSpacingPx: number | undefined) {\n if (letterSpacingPx === undefined) return undefined;\n return Math.round(pxToPt(letterSpacingPx) * 100);\n}\n\nfunction toTextGradientInput(\n value: string | undefined,\n): AddTextBoxGradientFillInput | undefined {\n if (!value) return undefined;\n const linear = parseLinearGradient(value);\n if (!linear) return undefined;\n const dmlAngle = (((linear.angle - 90) % 360) + 360) % 360;\n return {\n gradientType: \"linear\",\n angle: asOoxmlAngle(Math.round(dmlAngle * 60000)),\n stops: linear.stops.map((stop) => ({\n position: asOoxmlPercent(Math.round(stop.position * 1000)),\n color: toColorInput(stop.color)!,\n })),\n };\n}\n\nfunction resolveUnderline(\n node: TextPositionedNode,\n run: NonNullable<TextPositionedNode[\"runs\"]>[number] | undefined,\n): Underline | undefined {\n if (run?.underline !== undefined) return run.underline;\n if (node.underline !== undefined) return node.underline;\n return run?.href ? true : undefined;\n}\n\nfunction buildRunProperties(\n node: TextPositionedNode,\n run: NonNullable<TextPositionedNode[\"runs\"]>[number] | undefined,\n gradientFill: AddTextBoxGradientFillInput | undefined,\n): AddTextBoxRunPropertiesInput {\n const fontSizePx = run?.fontSize ?? node.fontSize ?? 24;\n const subSup = run ? resolveSubSup(run, node) : node;\n return createGlimpseRunProperties({\n fontFace: run?.fontFamily ?? node.fontFamily,\n fontSize: fontSizePx,\n color: run?.color ?? node.color,\n gradientFill,\n bold: run?.bold ?? node.bold,\n italic: run?.italic ?? node.italic,\n underline: resolveUnderline(node, run),\n strike: run?.strike ?? node.strike,\n subscript: subSup.subscript,\n superscript: subSup.superscript,\n highlight: run?.highlight ?? node.highlight,\n glow: node.glow,\n outline: node.outline,\n letterSpacing: run?.letterSpacing ?? node.letterSpacing,\n });\n}\n\nexport function createGlimpseRunProperties(\n style: GlimpseTextRunStyle,\n): AddTextBoxRunPropertiesInput {\n return {\n fontFace: style.fontFace ?? \"Noto Sans JP\",\n fontSize: asPt(pxToPt(style.fontSize ?? 24)),\n color: style.gradientFill ? undefined : toColorInput(style.color),\n gradientFill: style.gradientFill,\n bold: style.bold,\n italic: style.italic,\n underline: toUnderlineInput(style.underline),\n strike: style.strike,\n baseline: toBaselineInput(style.subscript, style.superscript),\n highlight: toColorInput(style.highlight),\n glow: toGlowInput(style.glow),\n outline: toOutlineInput(style.outline),\n charSpacing: toCharSpacing(style.letterSpacing),\n };\n}\n\nexport function createGlimpseShapeRunProperties(\n style: GlimpseTextRunStyle,\n): AddShapeRunPropertiesInput {\n const properties = createGlimpseRunProperties(style);\n return {\n ...properties,\n baseline: style.subscript\n ? \"subscript\"\n : style.superscript\n ? \"superscript\"\n : undefined,\n };\n}\n\nexport function createGlimpseTableRunProperties(\n style: GlimpseTextRunStyle,\n): AddTableRunPropertiesInput {\n const properties = createGlimpseRunProperties(style);\n return {\n ...properties,\n fontFace: style.fontFace,\n color: cleanHex(style.color),\n };\n}\n\nfunction buildParagraphs(node: TextPositionedNode): AddTextBoxParagraphInput[] {\n const gradientFill = toTextGradientInput(node.textGradient);\n const sourceRuns: GlimpseTextRun[] =\n node.runs && node.runs.length > 0\n ? node.runs.map((run) => ({\n text: run.text,\n properties: buildRunProperties(node, run, gradientFill),\n hyperlink: run.href,\n }))\n : [\n {\n text: node.text ?? \"\",\n properties: buildRunProperties(node, undefined, gradientFill),\n },\n ];\n const paragraphRuns: GlimpseTextRun[][] = [[]];\n for (const run of sourceRuns) {\n const lines = run.text.replace(/\\r*\\n/g, \"\\n\").split(\"\\n\");\n lines.forEach((line, index) => {\n if (index > 0) paragraphRuns.push([]);\n paragraphRuns.at(-1)?.push({ ...run, text: line });\n });\n }\n const lineHeight = node.lineHeight ?? 1.3;\n const fontSizePx = node.fontSize ?? 24;\n return paragraphRuns.map((runs) => ({\n properties: {\n align: node.textAlign,\n marginLeft: asEmu(0),\n indent: asEmu(0),\n bullet: { type: \"none\" },\n lineSpacing: asHundredthPt(\n Math.round(pxToPt(fontSizePx * lineHeight) * 100),\n ),\n },\n runs: runs.map((run) => ({\n text: run.text,\n properties: run.properties,\n hyperlink: run.hyperlink,\n })),\n }));\n}\n\nexport function createTextNodeInput(\n node: TextPositionedNode,\n useLayoutTextMargins: boolean,\n): AddTextBoxInput {\n const textOptions = createTextOptions(node);\n return {\n offsetX: asEmu(Math.round(textOptions.x * EMU_PER_IN)),\n offsetY: asEmu(Math.round(textOptions.y * EMU_PER_IN)),\n width: asEmu(Math.round(textOptions.w * EMU_PER_IN)),\n height: asEmu(Math.round(textOptions.h * EMU_PER_IN)),\n rotation:\n node.rotate === undefined\n ? undefined\n : asOoxmlAngle(Math.round(node.rotate * 60000)),\n body: useLayoutTextMargins\n ? undefined\n : {\n anchor: \"top\",\n marginLeft: asEmu(0),\n marginRight: asEmu(0),\n marginTop: asEmu(0),\n marginBottom: asEmu(0),\n },\n paragraphs: buildParagraphs(node),\n };\n}\n\nexport type CustomGeometryXmlInput = {\n width: number;\n height: number;\n points: readonly ({ x: number; y: number } | { close: true })[];\n};\n\nexport type GlimpseShapeXmlOptions = {\n fillColor?: string;\n fillOpacity?: number;\n backgroundGradient?: string;\n outlineGradient?: string;\n outlineOpacity?: number;\n glow?: TextGlow;\n shadow?: ShadowStyle;\n rectRadius?: number;\n dashType?: BorderStyle[\"dashType\"];\n flipH?: boolean;\n flipV?: boolean;\n zeroWidth?: boolean;\n zeroHeight?: boolean;\n customGeometry?: CustomGeometryXmlInput;\n};\n\nfunction toGradientFill(\n value: string,\n opacity?: number,\n): AddShapeFillInput | undefined {\n const gradient = parseGradient(value);\n if (!gradient) return undefined;\n const stops = gradient.value.stops.map((stop) => ({\n position: asOoxmlPercent(Math.round(stop.position * 1000)),\n color: toColorInput(stop.color, opacity)!,\n }));\n if (gradient.kind === \"linear\") {\n const dmlAngle = (((gradient.value.angle - 90) % 360) + 360) % 360;\n return {\n kind: \"gradient\",\n gradientType: \"linear\",\n angle: asOoxmlAngle(Math.round(dmlAngle * 60000)),\n stops,\n };\n }\n return {\n kind: \"gradient\",\n gradientType: \"radial\",\n centerX: asOoxmlPercent(Math.round(gradient.value.centerX * 1000)),\n centerY: asOoxmlPercent(Math.round(gradient.value.centerY * 1000)),\n stops,\n };\n}\n\nfunction withFillOpacity(\n fill: AddShapeFillInput | undefined,\n opacity: number | undefined,\n): AddShapeFillInput | undefined {\n if (!fill || opacity === undefined || fill.kind !== \"solid\") return fill;\n return {\n ...fill,\n color: toColorInput(fill.color.hex, opacity)!,\n };\n}\n\nfunction toShadowEffects(\n shadow: ShadowStyle | undefined,\n): AddShapeEffectsInput | undefined {\n if (!shadow) return undefined;\n const common = {\n blurRadius: asEmu(Math.round((shadow.blur ?? 3) * 12700)),\n distance: asEmu(Math.round((shadow.offset ?? 23000 / 12700) * 12700)),\n direction: asOoxmlAngle(Math.round((shadow.angle ?? 90) * 60000)),\n color: toColorInput(shadow.color ?? \"000000\", shadow.opacity ?? 0.35)!,\n };\n return shadow.type === \"inner\"\n ? { innerShadow: common }\n : {\n outerShadow: {\n ...common,\n alignment: \"bl\",\n rotateWithShape: true,\n },\n };\n}\n\nfunction customGeometry(\n input: CustomGeometryXmlInput,\n): AddShapeGeometryInput | undefined {\n const commands: AddShapeCustomGeometryPathCommandInput[] = [];\n let moved = false;\n for (const point of input.points) {\n if (\"close\" in point) {\n if (moved) commands.push({ kind: \"close\" });\n continue;\n }\n commands.push({\n kind: moved ? \"lineTo\" : \"moveTo\",\n x: Math.round(point.x * EMU_PER_IN),\n y: Math.round(point.y * EMU_PER_IN),\n });\n moved = true;\n }\n if (!moved) return undefined;\n return {\n kind: \"custom\",\n paths: [\n {\n width: Math.round(input.width * EMU_PER_IN),\n height: Math.round(input.height * EMU_PER_IN),\n commands,\n },\n ],\n };\n}\n\nexport function enrichShapeInput(\n input: AddShapeInput,\n options: GlimpseShapeXmlOptions | undefined,\n): AddShapeInput {\n const preset = input.geometry.kind === \"preset\" ? input.geometry.preset : \"\";\n const geometry = options?.customGeometry\n ? (customGeometry(options.customGeometry) ?? input.geometry)\n : preset === \"roundRect\" && options?.rectRadius !== undefined\n ? {\n ...input.geometry,\n adjustValues: {\n adj: Math.round(options.rectRadius * 50000),\n },\n }\n : input.geometry;\n const gradientFill = options?.backgroundGradient\n ? toGradientFill(options.backgroundGradient, options.fillOpacity)\n : undefined;\n const outlineGradient = options?.outlineGradient\n ? toGradientFill(\n options.outlineGradient,\n options.outlineOpacity ?? options.fillOpacity,\n )\n : undefined;\n const outline: AddShapeOutlineInput | undefined = input.outline\n ? {\n ...input.outline,\n fill:\n outlineGradient ??\n withFillOpacity(input.outline.fill, options?.outlineOpacity),\n dash: options?.dashType ?? input.outline.dash,\n }\n : outlineGradient\n ? { fill: outlineGradient }\n : undefined;\n const glow = options?.glow\n ? {\n radius: asEmu(Math.round(pxToEmu(options.glow.size ?? 8))),\n color: toColorInput(\n options.glow.color ?? \"FFFFFF\",\n options.glow.opacity ?? 0.75,\n )!,\n }\n : input.effects?.glow;\n const effects: AddShapeEffectsInput = {\n ...input.effects,\n ...toShadowEffects(options?.shadow),\n ...(glow ? { glow } : {}),\n };\n const width =\n preset === \"line\" && options?.zeroWidth ? asEmu(0) : input.width;\n let height =\n preset === \"line\" && options?.zeroHeight ? asEmu(0) : input.height;\n if (preset === \"line\" && width === 0 && height === 0) height = asEmu(1);\n return {\n ...input,\n geometry,\n width,\n height,\n fill: gradientFill ?? withFillOpacity(input.fill, options?.fillOpacity),\n outline,\n effects: Object.keys(effects).length > 0 ? effects : undefined,\n flipHorizontal: options?.flipH ?? input.flipHorizontal,\n flipVertical: options?.flipV ?? input.flipVertical,\n };\n}\n\nexport function enrichPictureInput(\n input: AddPictureInput,\n shadow: ShadowStyle | undefined,\n): AddPictureInput {\n return {\n ...input,\n effects: toShadowEffects(shadow),\n };\n}\n\nexport function toSlideBackgroundGradient(\n backgroundGradient: string,\n opacity?: number,\n) {\n const fill = toGradientFill(backgroundGradient, opacity);\n if (!fill || fill.kind !== \"gradient\") return undefined;\n return fill.gradientType === \"linear\"\n ? {\n kind: \"gradient\" as const,\n gradientType: \"linear\" as const,\n stops: fill.stops,\n angle: fill.angle ?? asOoxmlAngle(0),\n }\n : {\n kind: \"gradient\" as const,\n gradientType: \"radial\" as const,\n stops: fill.stops,\n centerX: fill.centerX,\n centerY: fill.centerY,\n };\n}\n"],"mappings":"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"}
|