@hirokisakabe/pom 10.1.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/dist/buildContext.js +1 -3
- package/dist/buildContext.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/registry/definitions/icon.js +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/types.js +1 -1
- package/package.json +2 -2
- package/dist/renderPptx/pptxAuthoring.js.map +0 -1
package/dist/buildContext.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FontRegistry } from "./calcYogaLayout/fontLoader.js";
|
|
2
|
-
import { PptxAuthoringRegistry } from "./renderPptx/pptxAuthoring.js";
|
|
3
2
|
import { DiagnosticCollector } from "./diagnostics.js";
|
|
4
3
|
//#region src/buildContext.ts
|
|
5
4
|
function createBuildContext(textMeasurementMode = "auto", fonts = []) {
|
|
@@ -9,8 +8,7 @@ function createBuildContext(textMeasurementMode = "auto", fonts = []) {
|
|
|
9
8
|
imageSizeCache: /* @__PURE__ */ new Map(),
|
|
10
9
|
imageDataCache: /* @__PURE__ */ new Map(),
|
|
11
10
|
iconRasterCache: /* @__PURE__ */ new Map(),
|
|
12
|
-
diagnostics: new DiagnosticCollector()
|
|
13
|
-
pptxAuthoring: new PptxAuthoringRegistry()
|
|
11
|
+
diagnostics: new DiagnosticCollector()
|
|
14
12
|
};
|
|
15
13
|
}
|
|
16
14
|
//#endregion
|
package/dist/buildContext.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildContext.js","names":[],"sources":["../src/buildContext.ts"],"sourcesContent":["import type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport { FontRegistry, type FontInput } from \"./calcYogaLayout/fontLoader.ts\";\nimport { DiagnosticCollector } from \"./diagnostics.ts\";\
|
|
1
|
+
{"version":3,"file":"buildContext.js","names":[],"sources":["../src/buildContext.ts"],"sourcesContent":["import type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport { FontRegistry, type FontInput } from \"./calcYogaLayout/fontLoader.ts\";\nimport { DiagnosticCollector } from \"./diagnostics.ts\";\n\nexport interface BuildContext {\n textMeasurementMode: TextMeasurementMode;\n fontRegistry: FontRegistry;\n imageSizeCache: Map<string, { widthPx: number; heightPx: number }>;\n imageDataCache: Map<string, string>;\n iconRasterCache: Map<string, string>;\n diagnostics: DiagnosticCollector;\n}\n\nexport function createBuildContext(\n textMeasurementMode: TextMeasurementMode = \"auto\",\n fonts: readonly FontInput[] = [],\n): BuildContext {\n return {\n textMeasurementMode,\n fontRegistry: new FontRegistry(fonts),\n imageSizeCache: new Map(),\n imageDataCache: new Map(),\n iconRasterCache: new Map(),\n diagnostics: new DiagnosticCollector(),\n };\n}\n"],"mappings":";;;AAaA,SAAgB,mBACd,sBAA2C,QAC3C,QAA8B,CAAC,GACjB;CACd,OAAO;EACL;EACA,cAAc,IAAI,aAAa,KAAK;EACpC,gCAAgB,IAAI,IAAI;EACxB,gCAAgB,IAAI,IAAI;EACxB,iCAAiB,IAAI,IAAI;EACzB,aAAa,IAAI,oBAAoB;CACvC;AACF"}
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/diagnostics.d.ts
|
|
2
|
-
type DiagnosticCode = "IMAGE_MEASURE_FAILED" | "IMAGE_NOT_PREFETCHED" | "AUTOFIT_OVERFLOW" | "SCALE_BELOW_THRESHOLD" | "MASTER_PPTX_PARSE_FAILED" | "ARROW_REF_NOT_FOUND" | "DUPLICATE_NODE_ID" | "PER_SIDE_BORDER_WITH_RADIUS" | "NODE_OUT_OF_BOUNDS" | "NODE_OVERLAP";
|
|
2
|
+
type DiagnosticCode = "IMAGE_MEASURE_FAILED" | "IMAGE_NOT_PREFETCHED" | "AUTOFIT_OVERFLOW" | "SCALE_BELOW_THRESHOLD" | "MASTER_PPTX_PARSE_FAILED" | "ARROW_REF_NOT_FOUND" | "ARROW_REF_NOT_CONNECTABLE" | "DUPLICATE_NODE_ID" | "PER_SIDE_BORDER_WITH_RADIUS" | "NODE_OUT_OF_BOUNDS" | "NODE_OVERLAP";
|
|
3
3
|
interface Diagnostic {
|
|
4
4
|
code: DiagnosticCode;
|
|
5
5
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","names":[],"sources":["../src/diagnostics.ts"],"mappings":";KAAY;
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","names":[],"sources":["../src/diagnostics.ts"],"mappings":";KAAY;UAaK;EACf,MAAM;EACN;;cAWW,yBAAyB;WACR,aAAa;EAAb,YAAA,aAAa"}
|
package/dist/diagnostics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["export type DiagnosticCode =\n | \"IMAGE_MEASURE_FAILED\"\n | \"IMAGE_NOT_PREFETCHED\"\n | \"AUTOFIT_OVERFLOW\"\n | \"SCALE_BELOW_THRESHOLD\"\n | \"MASTER_PPTX_PARSE_FAILED\"\n | \"ARROW_REF_NOT_FOUND\"\n | \"DUPLICATE_NODE_ID\"\n | \"PER_SIDE_BORDER_WITH_RADIUS\"\n | \"NODE_OUT_OF_BOUNDS\"\n | \"NODE_OVERLAP\";\n\nexport interface Diagnostic {\n code: DiagnosticCode;\n message: string;\n}\n\nexport class DiagnosticCollector {\n readonly items: Diagnostic[] = [];\n\n add(code: DiagnosticCode, message: string): void {\n this.items.push({ code, message });\n }\n}\n\nexport class DiagnosticsError extends Error {\n constructor(public readonly diagnostics: Diagnostic[]) {\n const summary = diagnostics\n .map((d) => `[${d.code}] ${d.message}`)\n .join(\"\\n\");\n super(`Build completed with diagnostics:\\n${summary}`);\n this.name = \"DiagnosticsError\";\n }\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"diagnostics.js","names":[],"sources":["../src/diagnostics.ts"],"sourcesContent":["export type DiagnosticCode =\n | \"IMAGE_MEASURE_FAILED\"\n | \"IMAGE_NOT_PREFETCHED\"\n | \"AUTOFIT_OVERFLOW\"\n | \"SCALE_BELOW_THRESHOLD\"\n | \"MASTER_PPTX_PARSE_FAILED\"\n | \"ARROW_REF_NOT_FOUND\"\n | \"ARROW_REF_NOT_CONNECTABLE\"\n | \"DUPLICATE_NODE_ID\"\n | \"PER_SIDE_BORDER_WITH_RADIUS\"\n | \"NODE_OUT_OF_BOUNDS\"\n | \"NODE_OVERLAP\";\n\nexport interface Diagnostic {\n code: DiagnosticCode;\n message: string;\n}\n\nexport class DiagnosticCollector {\n readonly items: Diagnostic[] = [];\n\n add(code: DiagnosticCode, message: string): void {\n this.items.push({ code, message });\n }\n}\n\nexport class DiagnosticsError extends Error {\n constructor(public readonly diagnostics: Diagnostic[]) {\n const summary = diagnostics\n .map((d) => `[${d.code}] ${d.message}`)\n .join(\"\\n\");\n super(`Build completed with diagnostics:\\n${summary}`);\n this.name = \"DiagnosticsError\";\n }\n}\n"],"mappings":";AAkBA,IAAa,sBAAb,MAAiC;CAC/B,QAA+B,CAAC;CAEhC,IAAI,MAAsB,SAAuB;EAC/C,KAAK,MAAM,KAAK;GAAE;GAAM;EAAQ,CAAC;CACnC;AACF;AAEA,IAAa,mBAAb,cAAsC,MAAM;CACd;CAA5B,YAAY,aAA2C;EACrD,MAAM,UAAU,YACb,KAAK,MAAM,IAAI,EAAE,KAAK,IAAI,EAAE,SAAS,CAAC,CACtC,KAAK,IAAI;EACZ,MAAM,sCAAsC,SAAS;EAJ3B,KAAA,cAAA;EAK1B,KAAK,OAAO;CACd;AACF"}
|
|
@@ -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";
|
|
@@ -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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"}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pxToEmu } from "../units.js";
|
|
2
|
+
import { arrowEndpoint, createShapeBoundsInput, solidShapeFill } from "../utils/glimpseShape.js";
|
|
3
|
+
import { resolveArrowType } from "../utils/straightLine.js";
|
|
4
|
+
import { asEmu } from "@pptx-glimpse/document";
|
|
2
5
|
//#region src/renderPptx/nodes/arrow.ts
|
|
6
|
+
function connectionSite(sites, other) {
|
|
7
|
+
const otherCenterX = other.x + other.w / 2;
|
|
8
|
+
const otherCenterY = other.y + other.h / 2;
|
|
9
|
+
return sites.reduce((nearest, candidate) => {
|
|
10
|
+
const nearestDistance = Math.hypot(nearest.x - otherCenterX, nearest.y - otherCenterY);
|
|
11
|
+
return Math.hypot(candidate.x - otherCenterX, candidate.y - otherCenterY) < nearestDistance ? candidate : nearest;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
3
14
|
function renderArrowNode(node, ctx) {
|
|
4
15
|
const fromBounds = ctx.idPositionMap.get(node.from);
|
|
5
16
|
const toBounds = ctx.idPositionMap.get(node.to);
|
|
@@ -11,12 +22,43 @@ function renderArrowNode(node, ctx) {
|
|
|
11
22
|
ctx.buildContext.diagnostics.add("ARROW_REF_NOT_FOUND", `Arrow: "to" ID "${node.to}" not found`);
|
|
12
23
|
return;
|
|
13
24
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
const fromTarget = ctx.connectorTargetMap.get(node.from);
|
|
26
|
+
const toTarget = ctx.connectorTargetMap.get(node.to);
|
|
27
|
+
if (!fromTarget || !toTarget) {
|
|
28
|
+
const id = !fromTarget ? node.from : node.to;
|
|
29
|
+
ctx.buildContext.diagnostics.add("ARROW_REF_NOT_CONNECTABLE", `Arrow: ID "${id}" does not reference a connector-compatible Shape geometry or Text node`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const startSite = connectionSite(fromTarget.sites, toTarget.bounds);
|
|
33
|
+
const endSite = connectionSite(toTarget.sites, fromTarget.bounds);
|
|
34
|
+
const minX = Math.min(startSite.x, endSite.x);
|
|
35
|
+
const minY = Math.min(startSite.y, endSite.y);
|
|
36
|
+
ctx.authoring.addConnector({
|
|
37
|
+
preset: "straightConnector1",
|
|
38
|
+
...createShapeBoundsInput({
|
|
39
|
+
x: minX,
|
|
40
|
+
y: minY,
|
|
41
|
+
w: Math.abs(endSite.x - startSite.x),
|
|
42
|
+
h: Math.abs(endSite.y - startSite.y)
|
|
43
|
+
}),
|
|
44
|
+
flipHorizontal: endSite.x < startSite.x,
|
|
45
|
+
flipVertical: endSite.y < startSite.y,
|
|
46
|
+
start: {
|
|
47
|
+
shapeHandle: fromTarget.handle,
|
|
48
|
+
connectionSiteIndex: startSite.index
|
|
49
|
+
},
|
|
50
|
+
end: {
|
|
51
|
+
shapeHandle: toTarget.handle,
|
|
52
|
+
connectionSiteIndex: endSite.index
|
|
53
|
+
},
|
|
54
|
+
outline: {
|
|
55
|
+
fill: solidShapeFill(node.color ?? "000000"),
|
|
56
|
+
width: node.lineWidth !== void 0 ? asEmu(Math.round(pxToEmu(node.lineWidth))) : asEmu(12700),
|
|
57
|
+
dash: node.dashType,
|
|
58
|
+
headEnd: arrowEndpoint(resolveArrowType(node.beginArrow)),
|
|
59
|
+
tailEnd: arrowEndpoint(resolveArrowType(node.endArrow))
|
|
60
|
+
}
|
|
61
|
+
});
|
|
20
62
|
}
|
|
21
63
|
//#endregion
|
|
22
64
|
export { renderArrowNode };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport {
|
|
1
|
+
{"version":3,"file":"arrow.js","names":[],"sources":["../../../src/renderPptx/nodes/arrow.ts"],"sourcesContent":["import { asEmu } from \"@pptx-glimpse/document\";\nimport type { PositionedNode } from \"../../types.ts\";\nimport type { RenderContext } from \"../types.ts\";\nimport { pxToEmu } from \"../units.ts\";\nimport {\n arrowEndpoint,\n createShapeBoundsInput,\n solidShapeFill,\n} from \"../utils/glimpseShape.ts\";\nimport { resolveArrowType } from \"../utils/straightLine.ts\";\nimport type { ConnectorSite } from \"../utils/connectorSites.ts\";\n\ntype ArrowPositionedNode = Extract<PositionedNode, { type: \"arrow\" }>;\n\nfunction connectionSite(\n sites: readonly ConnectorSite[],\n other: { x: number; y: number; w: number; h: number },\n): ConnectorSite {\n const otherCenterX = other.x + other.w / 2;\n const otherCenterY = other.y + other.h / 2;\n return sites.reduce((nearest, candidate) => {\n const nearestDistance = Math.hypot(\n nearest.x - otherCenterX,\n nearest.y - otherCenterY,\n );\n const candidateDistance = Math.hypot(\n candidate.x - otherCenterX,\n candidate.y - otherCenterY,\n );\n return candidateDistance < nearestDistance ? candidate : nearest;\n });\n}\n\nexport function renderArrowNode(\n node: ArrowPositionedNode,\n ctx: RenderContext,\n): void {\n const fromBounds = ctx.idPositionMap.get(node.from);\n const toBounds = ctx.idPositionMap.get(node.to);\n\n if (!fromBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"from\" ID \"${node.from}\" not found`,\n );\n return;\n }\n if (!toBounds) {\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_FOUND\",\n `Arrow: \"to\" ID \"${node.to}\" not found`,\n );\n return;\n }\n\n const fromTarget = ctx.connectorTargetMap.get(node.from);\n const toTarget = ctx.connectorTargetMap.get(node.to);\n if (!fromTarget || !toTarget) {\n const id = !fromTarget ? node.from : node.to;\n ctx.buildContext.diagnostics.add(\n \"ARROW_REF_NOT_CONNECTABLE\",\n `Arrow: ID \"${id}\" does not reference a connector-compatible Shape geometry or Text node`,\n );\n return;\n }\n\n const startSite = connectionSite(fromTarget.sites, toTarget.bounds);\n const endSite = connectionSite(toTarget.sites, fromTarget.bounds);\n const minX = Math.min(startSite.x, endSite.x);\n const minY = Math.min(startSite.y, endSite.y);\n\n ctx.authoring.addConnector({\n preset: \"straightConnector1\",\n ...createShapeBoundsInput({\n x: minX,\n y: minY,\n w: Math.abs(endSite.x - startSite.x),\n h: Math.abs(endSite.y - startSite.y),\n }),\n flipHorizontal: endSite.x < startSite.x,\n flipVertical: endSite.y < startSite.y,\n start: {\n shapeHandle: fromTarget.handle,\n connectionSiteIndex: startSite.index,\n },\n end: {\n shapeHandle: toTarget.handle,\n connectionSiteIndex: endSite.index,\n },\n outline: {\n fill: solidShapeFill(node.color ?? \"000000\"),\n width:\n node.lineWidth !== undefined\n ? asEmu(Math.round(pxToEmu(node.lineWidth)))\n : asEmu(12700),\n dash: node.dashType,\n headEnd: arrowEndpoint(resolveArrowType(node.beginArrow)),\n tailEnd: arrowEndpoint(resolveArrowType(node.endArrow)),\n },\n });\n}\n"],"mappings":";;;;;AAcA,SAAS,eACP,OACA,OACe;CACf,MAAM,eAAe,MAAM,IAAI,MAAM,IAAI;CACzC,MAAM,eAAe,MAAM,IAAI,MAAM,IAAI;CACzC,OAAO,MAAM,QAAQ,SAAS,cAAc;EAC1C,MAAM,kBAAkB,KAAK,MAC3B,QAAQ,IAAI,cACZ,QAAQ,IAAI,YACd;EAKA,OAJ0B,KAAK,MAC7B,UAAU,IAAI,cACd,UAAU,IAAI,YAEO,IAAI,kBAAkB,YAAY;CAC3D,CAAC;AACH;AAEA,SAAgB,gBACd,MACA,KACM;CACN,MAAM,aAAa,IAAI,cAAc,IAAI,KAAK,IAAI;CAClD,MAAM,WAAW,IAAI,cAAc,IAAI,KAAK,EAAE;CAE9C,IAAI,CAAC,YAAY;EACf,IAAI,aAAa,YAAY,IAC3B,uBACA,qBAAqB,KAAK,KAAK,YACjC;EACA;CACF;CACA,IAAI,CAAC,UAAU;EACb,IAAI,aAAa,YAAY,IAC3B,uBACA,mBAAmB,KAAK,GAAG,YAC7B;EACA;CACF;CAEA,MAAM,aAAa,IAAI,mBAAmB,IAAI,KAAK,IAAI;CACvD,MAAM,WAAW,IAAI,mBAAmB,IAAI,KAAK,EAAE;CACnD,IAAI,CAAC,cAAc,CAAC,UAAU;EAC5B,MAAM,KAAK,CAAC,aAAa,KAAK,OAAO,KAAK;EAC1C,IAAI,aAAa,YAAY,IAC3B,6BACA,cAAc,GAAG,wEACnB;EACA;CACF;CAEA,MAAM,YAAY,eAAe,WAAW,OAAO,SAAS,MAAM;CAClE,MAAM,UAAU,eAAe,SAAS,OAAO,WAAW,MAAM;CAChE,MAAM,OAAO,KAAK,IAAI,UAAU,GAAG,QAAQ,CAAC;CAC5C,MAAM,OAAO,KAAK,IAAI,UAAU,GAAG,QAAQ,CAAC;CAE5C,IAAI,UAAU,aAAa;EACzB,QAAQ;EACR,GAAG,uBAAuB;GACxB,GAAG;GACH,GAAG;GACH,GAAG,KAAK,IAAI,QAAQ,IAAI,UAAU,CAAC;GACnC,GAAG,KAAK,IAAI,QAAQ,IAAI,UAAU,CAAC;EACrC,CAAC;EACD,gBAAgB,QAAQ,IAAI,UAAU;EACtC,cAAc,QAAQ,IAAI,UAAU;EACpC,OAAO;GACL,aAAa,WAAW;GACxB,qBAAqB,UAAU;EACjC;EACA,KAAK;GACH,aAAa,SAAS;GACtB,qBAAqB,QAAQ;EAC/B;EACA,SAAS;GACP,MAAM,eAAe,KAAK,SAAS,QAAQ;GAC3C,OACE,KAAK,cAAc,KAAA,IACf,MAAM,KAAK,MAAM,QAAQ,KAAK,SAAS,CAAC,CAAC,IACzC,MAAM,KAAK;GACjB,MAAM,KAAK;GACX,SAAS,cAAc,iBAAiB,KAAK,UAAU,CAAC;GACxD,SAAS,cAAc,iBAAiB,KAAK,QAAQ,CAAC;EACxD;CACF,CAAC;AACH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { pxToEmu } from "../units.js";
|
|
2
2
|
import { getContentArea } from "../utils/contentArea.js";
|
|
3
|
-
import { toColorInput } from "../
|
|
3
|
+
import { toColorInput } from "../glimpseAdapter.js";
|
|
4
4
|
import { asEmu, asOoxmlPercent, asPt } from "@pptx-glimpse/document";
|
|
5
5
|
//#region src/renderPptx/nodes/chart.ts
|
|
6
6
|
const DEFAULT_BAR_CHART_COLORS = [
|
|
@@ -47,7 +47,7 @@ function renderChartNode(node, ctx) {
|
|
|
47
47
|
const series = normalizeChartSeries(node.data);
|
|
48
48
|
const chartColors = node.chartColors ?? (node.chartType === "pie" || node.chartType === "doughnut" ? DEFAULT_PIE_CHART_COLORS : DEFAULT_BAR_CHART_COLORS);
|
|
49
49
|
const pointColors = chartColors.length > 0 && (node.chartType === "pie" || node.chartType === "doughnut" || node.chartType === "bar" && node.data.length === 1 && node.chartColors !== void 0 && node.chartColors.length > 1) ? node.data[0]?.values.map((_value, index) => chartColors[index % chartColors.length]) : void 0;
|
|
50
|
-
ctx.
|
|
50
|
+
ctx.authoring.addChart({
|
|
51
51
|
chartType: node.chartType,
|
|
52
52
|
series: series.map((item, index) => ({
|
|
53
53
|
name: item.name,
|