pptx-custom 0.4.0 → 0.5.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 +2 -1
- package/README.zh-CN.md +2 -1
- package/dist/index.d.mts +46 -31
- package/dist/index.d.ts +46 -31
- package/dist/index.js +25 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +25 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm i pptx-custom
|
|
|
21
21
|
- `applyCustomTheme(deck, themeInput)`
|
|
22
22
|
|
|
23
23
|
Types are also exported, including:
|
|
24
|
-
`CustomSlide`, `
|
|
24
|
+
`CustomSlide`, `Presentation`, `PresentationData`, `PresentationTheme`, `PptxCustomContentInput`, `PptxCustomThemeInput`,
|
|
25
25
|
`PptxCustomOptions`, `TemplateJson`, `TemplateJsonSlide`, `TemplateJsonElement`,
|
|
26
26
|
`TemplateJsonTheme`.
|
|
27
27
|
|
|
@@ -129,3 +129,4 @@ Example NDJSON:
|
|
|
129
129
|
- When both `backgroundImage` and `backgroundColor` are provided, background color is
|
|
130
130
|
applied as a 50% alpha overlay color on targeted slides.
|
|
131
131
|
- `clearBackgroundImage` also clears logo images in current behavior.
|
|
132
|
+
- `Deck` remains available as a compatibility alias, but the recommended root type name is `Presentation`.
|
package/README.zh-CN.md
CHANGED
|
@@ -21,7 +21,7 @@ npm i pptx-custom
|
|
|
21
21
|
- `applyCustomTheme(deck, themeInput)`
|
|
22
22
|
|
|
23
23
|
同时导出类型,包括:
|
|
24
|
-
`CustomSlide`、`
|
|
24
|
+
`CustomSlide`、`Presentation`、`PresentationData`、`PresentationTheme`、`PptxCustomContentInput`、`PptxCustomThemeInput`、
|
|
25
25
|
`PptxCustomOptions`、`TemplateJson`、`TemplateJsonSlide`、`TemplateJsonElement`、
|
|
26
26
|
`TemplateJsonTheme`。
|
|
27
27
|
|
|
@@ -129,3 +129,4 @@ NDJSON 示例:
|
|
|
129
129
|
- 当同时提供 `backgroundImage` 与 `backgroundColor` 时,会在目标页应用
|
|
130
130
|
50% 透明度的背景色叠加效果。
|
|
131
131
|
- 当前行为下,`clearBackgroundImage` 也会同时清除 logo 图片。
|
|
132
|
+
- `Deck` 仍保留为兼容别名,但新的推荐根类型命名是 `Presentation`。
|
package/dist/index.d.mts
CHANGED
|
@@ -26,6 +26,26 @@ type TemplateJsonOutline = {
|
|
|
26
26
|
color: string;
|
|
27
27
|
style: string;
|
|
28
28
|
};
|
|
29
|
+
type FillGradientStop = {
|
|
30
|
+
pos: number;
|
|
31
|
+
color: string;
|
|
32
|
+
};
|
|
33
|
+
type FillGradient = {
|
|
34
|
+
type: string;
|
|
35
|
+
rotate: number;
|
|
36
|
+
colors: FillGradientStop[];
|
|
37
|
+
};
|
|
38
|
+
type ElementFill = {
|
|
39
|
+
type: 'solid';
|
|
40
|
+
color: string;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'gradient';
|
|
43
|
+
gradient: FillGradient;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'image';
|
|
46
|
+
src: string;
|
|
47
|
+
opacity?: number;
|
|
48
|
+
};
|
|
29
49
|
type TemplateJsonElementBase = {
|
|
30
50
|
type: string;
|
|
31
51
|
id: string;
|
|
@@ -43,7 +63,7 @@ type TemplateJsonShape = TemplateJsonElementBase & {
|
|
|
43
63
|
type: 'shape';
|
|
44
64
|
viewBox: [number, number];
|
|
45
65
|
path: string;
|
|
46
|
-
fill:
|
|
66
|
+
fill: ElementFill;
|
|
47
67
|
fixedRatio?: boolean;
|
|
48
68
|
shadow?: TemplateJsonShadow;
|
|
49
69
|
outline?: TemplateJsonOutline;
|
|
@@ -85,10 +105,7 @@ type TemplateJsonElement = TemplateJsonShape | TemplateJsonText | TemplateJsonLi
|
|
|
85
105
|
type TemplateJsonSlide = {
|
|
86
106
|
id: string;
|
|
87
107
|
elements: TemplateJsonElement[];
|
|
88
|
-
background?:
|
|
89
|
-
type: string;
|
|
90
|
-
color: string;
|
|
91
|
-
};
|
|
108
|
+
background?: ElementFill;
|
|
92
109
|
type?: string;
|
|
93
110
|
};
|
|
94
111
|
type TemplateJson = {
|
|
@@ -108,8 +125,7 @@ type SlideElement = {
|
|
|
108
125
|
width?: number;
|
|
109
126
|
height?: number;
|
|
110
127
|
rotate?: number;
|
|
111
|
-
fill?:
|
|
112
|
-
pattern?: string;
|
|
128
|
+
fill?: ElementFill;
|
|
113
129
|
path?: string;
|
|
114
130
|
viewBox?: [number, number];
|
|
115
131
|
pathFormula?: string;
|
|
@@ -183,36 +199,35 @@ type Slide = {
|
|
|
183
199
|
id?: string;
|
|
184
200
|
elements?: SlideElement[];
|
|
185
201
|
remark?: string;
|
|
186
|
-
background?:
|
|
187
|
-
|
|
202
|
+
background?: ElementFill;
|
|
203
|
+
type?: string;
|
|
204
|
+
};
|
|
205
|
+
type PresentationTheme = {
|
|
206
|
+
themeColors?: string[];
|
|
207
|
+
fontName?: string;
|
|
208
|
+
fontColor?: string;
|
|
209
|
+
backgroundColor?: string;
|
|
210
|
+
shadow?: {
|
|
211
|
+
h?: number;
|
|
212
|
+
v?: number;
|
|
213
|
+
blur?: number;
|
|
188
214
|
color?: string;
|
|
189
|
-
src?: string;
|
|
190
215
|
};
|
|
191
|
-
|
|
216
|
+
outline?: {
|
|
217
|
+
width?: number;
|
|
218
|
+
color?: string;
|
|
219
|
+
style?: string;
|
|
220
|
+
};
|
|
192
221
|
};
|
|
193
|
-
type
|
|
222
|
+
type Presentation = {
|
|
194
223
|
title?: string;
|
|
195
224
|
width?: number;
|
|
196
225
|
height?: number;
|
|
197
226
|
slides?: Slide[];
|
|
198
|
-
theme?:
|
|
199
|
-
themeColors?: string[];
|
|
200
|
-
fontName?: string;
|
|
201
|
-
fontColor?: string;
|
|
202
|
-
backgroundColor?: string;
|
|
203
|
-
shadow?: {
|
|
204
|
-
h?: number;
|
|
205
|
-
v?: number;
|
|
206
|
-
blur?: number;
|
|
207
|
-
color?: string;
|
|
208
|
-
};
|
|
209
|
-
outline?: {
|
|
210
|
-
width?: number;
|
|
211
|
-
color?: string;
|
|
212
|
-
style?: string;
|
|
213
|
-
};
|
|
214
|
-
};
|
|
227
|
+
theme?: PresentationTheme;
|
|
215
228
|
};
|
|
229
|
+
type PresentationData = Presentation;
|
|
230
|
+
type Deck = Presentation;
|
|
216
231
|
type BackendCoverData = {
|
|
217
232
|
title: string;
|
|
218
233
|
text: string;
|
|
@@ -285,6 +300,6 @@ declare const applyCustomContentToTemplate: (template: TemplateJson, CustomSlide
|
|
|
285
300
|
|
|
286
301
|
declare function applyCustomContent(template: TemplateJson, input: PptxCustomContentInput): TemplateJson;
|
|
287
302
|
|
|
288
|
-
declare function applyCustomTheme(deck:
|
|
303
|
+
declare function applyCustomTheme(deck: Presentation, input: PptxCustomThemeInput): Presentation;
|
|
289
304
|
|
|
290
|
-
export { type CustomSlide, type Deck, type PptxCustomContentInput, type PptxCustomOptions, type PptxCustomThemeInput, type TemplateJson, type TemplateJsonElement, type TemplateJsonSlide, type TemplateJsonTheme, applyCustomContent, applyCustomContentToTemplate, applyCustomTheme, parseCustomContent };
|
|
305
|
+
export { type CustomSlide, type Deck, type PptxCustomContentInput, type PptxCustomOptions, type PptxCustomThemeInput, type Presentation, type PresentationData, type PresentationTheme, type TemplateJson, type TemplateJsonElement, type TemplateJsonSlide, type TemplateJsonTheme, applyCustomContent, applyCustomContentToTemplate, applyCustomTheme, parseCustomContent };
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,26 @@ type TemplateJsonOutline = {
|
|
|
26
26
|
color: string;
|
|
27
27
|
style: string;
|
|
28
28
|
};
|
|
29
|
+
type FillGradientStop = {
|
|
30
|
+
pos: number;
|
|
31
|
+
color: string;
|
|
32
|
+
};
|
|
33
|
+
type FillGradient = {
|
|
34
|
+
type: string;
|
|
35
|
+
rotate: number;
|
|
36
|
+
colors: FillGradientStop[];
|
|
37
|
+
};
|
|
38
|
+
type ElementFill = {
|
|
39
|
+
type: 'solid';
|
|
40
|
+
color: string;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'gradient';
|
|
43
|
+
gradient: FillGradient;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'image';
|
|
46
|
+
src: string;
|
|
47
|
+
opacity?: number;
|
|
48
|
+
};
|
|
29
49
|
type TemplateJsonElementBase = {
|
|
30
50
|
type: string;
|
|
31
51
|
id: string;
|
|
@@ -43,7 +63,7 @@ type TemplateJsonShape = TemplateJsonElementBase & {
|
|
|
43
63
|
type: 'shape';
|
|
44
64
|
viewBox: [number, number];
|
|
45
65
|
path: string;
|
|
46
|
-
fill:
|
|
66
|
+
fill: ElementFill;
|
|
47
67
|
fixedRatio?: boolean;
|
|
48
68
|
shadow?: TemplateJsonShadow;
|
|
49
69
|
outline?: TemplateJsonOutline;
|
|
@@ -85,10 +105,7 @@ type TemplateJsonElement = TemplateJsonShape | TemplateJsonText | TemplateJsonLi
|
|
|
85
105
|
type TemplateJsonSlide = {
|
|
86
106
|
id: string;
|
|
87
107
|
elements: TemplateJsonElement[];
|
|
88
|
-
background?:
|
|
89
|
-
type: string;
|
|
90
|
-
color: string;
|
|
91
|
-
};
|
|
108
|
+
background?: ElementFill;
|
|
92
109
|
type?: string;
|
|
93
110
|
};
|
|
94
111
|
type TemplateJson = {
|
|
@@ -108,8 +125,7 @@ type SlideElement = {
|
|
|
108
125
|
width?: number;
|
|
109
126
|
height?: number;
|
|
110
127
|
rotate?: number;
|
|
111
|
-
fill?:
|
|
112
|
-
pattern?: string;
|
|
128
|
+
fill?: ElementFill;
|
|
113
129
|
path?: string;
|
|
114
130
|
viewBox?: [number, number];
|
|
115
131
|
pathFormula?: string;
|
|
@@ -183,36 +199,35 @@ type Slide = {
|
|
|
183
199
|
id?: string;
|
|
184
200
|
elements?: SlideElement[];
|
|
185
201
|
remark?: string;
|
|
186
|
-
background?:
|
|
187
|
-
|
|
202
|
+
background?: ElementFill;
|
|
203
|
+
type?: string;
|
|
204
|
+
};
|
|
205
|
+
type PresentationTheme = {
|
|
206
|
+
themeColors?: string[];
|
|
207
|
+
fontName?: string;
|
|
208
|
+
fontColor?: string;
|
|
209
|
+
backgroundColor?: string;
|
|
210
|
+
shadow?: {
|
|
211
|
+
h?: number;
|
|
212
|
+
v?: number;
|
|
213
|
+
blur?: number;
|
|
188
214
|
color?: string;
|
|
189
|
-
src?: string;
|
|
190
215
|
};
|
|
191
|
-
|
|
216
|
+
outline?: {
|
|
217
|
+
width?: number;
|
|
218
|
+
color?: string;
|
|
219
|
+
style?: string;
|
|
220
|
+
};
|
|
192
221
|
};
|
|
193
|
-
type
|
|
222
|
+
type Presentation = {
|
|
194
223
|
title?: string;
|
|
195
224
|
width?: number;
|
|
196
225
|
height?: number;
|
|
197
226
|
slides?: Slide[];
|
|
198
|
-
theme?:
|
|
199
|
-
themeColors?: string[];
|
|
200
|
-
fontName?: string;
|
|
201
|
-
fontColor?: string;
|
|
202
|
-
backgroundColor?: string;
|
|
203
|
-
shadow?: {
|
|
204
|
-
h?: number;
|
|
205
|
-
v?: number;
|
|
206
|
-
blur?: number;
|
|
207
|
-
color?: string;
|
|
208
|
-
};
|
|
209
|
-
outline?: {
|
|
210
|
-
width?: number;
|
|
211
|
-
color?: string;
|
|
212
|
-
style?: string;
|
|
213
|
-
};
|
|
214
|
-
};
|
|
227
|
+
theme?: PresentationTheme;
|
|
215
228
|
};
|
|
229
|
+
type PresentationData = Presentation;
|
|
230
|
+
type Deck = Presentation;
|
|
216
231
|
type BackendCoverData = {
|
|
217
232
|
title: string;
|
|
218
233
|
text: string;
|
|
@@ -285,6 +300,6 @@ declare const applyCustomContentToTemplate: (template: TemplateJson, CustomSlide
|
|
|
285
300
|
|
|
286
301
|
declare function applyCustomContent(template: TemplateJson, input: PptxCustomContentInput): TemplateJson;
|
|
287
302
|
|
|
288
|
-
declare function applyCustomTheme(deck:
|
|
303
|
+
declare function applyCustomTheme(deck: Presentation, input: PptxCustomThemeInput): Presentation;
|
|
289
304
|
|
|
290
|
-
export { type CustomSlide, type Deck, type PptxCustomContentInput, type PptxCustomOptions, type PptxCustomThemeInput, type TemplateJson, type TemplateJsonElement, type TemplateJsonSlide, type TemplateJsonTheme, applyCustomContent, applyCustomContentToTemplate, applyCustomTheme, parseCustomContent };
|
|
305
|
+
export { type CustomSlide, type Deck, type PptxCustomContentInput, type PptxCustomOptions, type PptxCustomThemeInput, type Presentation, type PresentationData, type PresentationTheme, type TemplateJson, type TemplateJsonElement, type TemplateJsonSlide, type TemplateJsonTheme, applyCustomContent, applyCustomContentToTemplate, applyCustomTheme, parseCustomContent };
|
package/dist/index.js
CHANGED
|
@@ -665,18 +665,29 @@ function buildSingleMapping(from, to) {
|
|
|
665
665
|
}
|
|
666
666
|
|
|
667
667
|
// src/custom-theme/replacers.ts
|
|
668
|
+
function applyColorToStyleAttribute(styles, color) {
|
|
669
|
+
const declarations = styles.split(";").map((item) => item.trim()).filter(Boolean);
|
|
670
|
+
let updated = false;
|
|
671
|
+
const nextDeclarations = declarations.map((declaration) => {
|
|
672
|
+
const separatorIndex = declaration.indexOf(":");
|
|
673
|
+
if (separatorIndex < 0) return declaration;
|
|
674
|
+
const property = declaration.slice(0, separatorIndex).trim().toLowerCase();
|
|
675
|
+
if (property !== "color") return declaration;
|
|
676
|
+
updated = true;
|
|
677
|
+
return `color: ${color}`;
|
|
678
|
+
});
|
|
679
|
+
if (!updated) {
|
|
680
|
+
nextDeclarations.push(`color: ${color}`);
|
|
681
|
+
}
|
|
682
|
+
return nextDeclarations.join("; ");
|
|
683
|
+
}
|
|
668
684
|
function applyFontColorToHtml(value, fontColor) {
|
|
669
685
|
if (!value || !fontColor) return value;
|
|
670
686
|
const normalized = normalizeThemeColor(fontColor) ?? fontColor;
|
|
671
|
-
const hasStyleColor = /\bcolor\s*:/i.test(value);
|
|
672
|
-
if (hasStyleColor) {
|
|
673
|
-
return value.replace(/color\s*:\s*([^;"']+)/gi, () => `color: ${normalized}`);
|
|
674
|
-
}
|
|
675
687
|
return value.replace(
|
|
676
688
|
/(<[^>]+style\s*=\s*["'])([^"']*)(["'])/gi,
|
|
677
689
|
(_match, start, styles, end) => {
|
|
678
|
-
|
|
679
|
-
const nextStyles = styles.trim() ? `${styles.trim()}; color: ${normalized}` : `color: ${normalized}`;
|
|
690
|
+
const nextStyles = applyColorToStyleAttribute(styles, normalized);
|
|
680
691
|
return `${start}${nextStyles}${end}`;
|
|
681
692
|
}
|
|
682
693
|
);
|
|
@@ -787,16 +798,12 @@ function applyTheme2Json(deck, update) {
|
|
|
787
798
|
update.fontColor
|
|
788
799
|
);
|
|
789
800
|
if (!nextBackground) return nextSlide;
|
|
790
|
-
const currentColor = nextSlide.background?.color;
|
|
801
|
+
const currentColor = nextSlide.background?.type === "solid" ? nextSlide.background.color : void 0;
|
|
791
802
|
const shouldUpdate = !currentColor || prevBackground && colorsEqual(currentColor, prevBackground) || !prevBackground && isWhiteColor(currentColor);
|
|
792
803
|
if (!shouldUpdate) return nextSlide;
|
|
793
804
|
return {
|
|
794
805
|
...nextSlide,
|
|
795
|
-
background:
|
|
796
|
-
...nextSlide.background ?? {},
|
|
797
|
-
type: nextSlide.background?.type ?? "solid",
|
|
798
|
-
color: nextBackground
|
|
799
|
-
}
|
|
806
|
+
background: createSolidBackground(nextBackground)
|
|
800
807
|
};
|
|
801
808
|
});
|
|
802
809
|
return {
|
|
@@ -810,6 +817,12 @@ function applyTheme2Json(deck, update) {
|
|
|
810
817
|
slides
|
|
811
818
|
};
|
|
812
819
|
}
|
|
820
|
+
function createSolidBackground(color) {
|
|
821
|
+
return {
|
|
822
|
+
type: "solid",
|
|
823
|
+
color
|
|
824
|
+
};
|
|
825
|
+
}
|
|
813
826
|
|
|
814
827
|
// src/custom-theme/index.ts
|
|
815
828
|
function applyCustomTheme(deck, input) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/custom-content/index.ts","../src/custom-content/parser.ts","../src/custom-content/html.ts","../src/custom-content/slide-appliers.ts","../src/custom-content/template-builder.ts","../src/custom-theme/index.ts","../src/custom-theme/color-utils.ts","../src/custom-theme/media.ts","../src/custom-theme/mappings.ts","../src/custom-theme/replacers.ts","../src/custom-theme/theme-applier.ts"],"sourcesContent":["import { applyCustomContent, parseCustomContent, applyCustomContentToTemplate } from './custom-content/index'\nimport { applyCustomTheme } from './custom-theme/index'\n\nexport {\n parseCustomContent,\n applyCustomContent,\n applyCustomContentToTemplate,\n\n applyCustomTheme,\n}\n\nexport type {\n CustomSlide,\n Deck,\n PptxCustomContentInput,\n PptxCustomOptions,\n PptxCustomThemeInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonSlide,\n TemplateJsonTheme\n} from './types'\n","import { parseDocument } from 'json2pptx-schema'\nimport type {\n PptxCustomContentInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonImage\n} from '../types'\nimport { parseCustomContent } from './parser'\nimport { applyCustomContentToTemplate } from './template-builder'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\n\nfunction isLogoImageElement (\n element: TemplateJsonElement\n): element is TemplateJsonImage {\n return element.type === 'image' && element.imageType === 'logo'\n}\n\nfunction fitSize (\n width: number,\n height: number,\n maxWidth: number,\n maxHeight: number\n): { width: number; height: number } {\n const safeWidth = width > 0 ? width : maxWidth\n const safeHeight = height > 0 ? height : maxHeight\n const scale = Math.min(maxWidth / safeWidth, maxHeight / safeHeight)\n return {\n width: safeWidth * scale,\n height: safeHeight * scale\n }\n}\n\nfunction normalizeLogoElements (deck: TemplateJson): TemplateJson {\n const slideWidth = deck.width || FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height || FALLBACK_SLIDE_HEIGHT\n const logoMaxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const logoMaxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n\n const slides = deck.slides.map(slide => {\n let changed = false\n const elements = slide.elements.map(element => {\n if (!isLogoImageElement(element)) return element\n\n const size = fitSize(\n element.width ?? logoMaxWidth,\n element.height ?? logoMaxHeight,\n logoMaxWidth,\n logoMaxHeight\n )\n const isLeft = (element.left ?? 0) < slideWidth / 2\n const left = isLeft\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - size.width - LOGO_MARGIN_X)\n const top = LOGO_MARGIN_Y\n const { clip: _clip, ...rest } = element\n\n changed = true\n return {\n ...rest,\n left,\n top,\n width: size.width,\n height: size.height,\n fixedRatio: true\n }\n })\n\n return changed ? { ...slide, elements } : slide\n })\n\n return { ...deck, slides }\n}\n\nexport function applyCustomContent (\n template: TemplateJson,\n input: PptxCustomContentInput\n): TemplateJson {\n const normalizedTemplate = parseDocument(template) as unknown as TemplateJson\n const CustomSlides = typeof input === 'string' ? parseCustomContent(input) : input\n const updated = applyCustomContentToTemplate(normalizedTemplate, CustomSlides)\n const withNormalizedLogo = normalizeLogoElements(updated)\n return parseDocument(withNormalizedLogo) as unknown as TemplateJson\n}\n\nexport { parseCustomContent, applyCustomContentToTemplate }\n","import type { BackendContentItem, CustomSlide } from '../types'\n\ntype UnknownRecord = Record<string, unknown>\n\nconst isRecord = (value: unknown): value is UnknownRecord =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst asString = (value: unknown): string | null =>\n typeof value === 'string' ? value : null\n\nconst asStringArray = (value: unknown): string[] | null => {\n if (!Array.isArray(value)) return null\n const normalized = value\n .map(item => asString(item))\n .filter((item): item is string => item !== null)\n return normalized.length === value.length ? normalized : null\n}\n\nconst normalizeType = (value: unknown): CustomSlide['type'] | null => {\n const raw = asString(value)?.trim().toLowerCase()\n if (!raw) return null\n if (raw === 'agenda') return 'contents'\n if (raw === 'section') return 'transition'\n if (raw === 'ending') return 'end'\n if (\n raw === 'cover' ||\n raw === 'contents' ||\n raw === 'transition' ||\n raw === 'content' ||\n raw === 'end'\n ) {\n return raw\n }\n return null\n}\n\nconst normalizeContentItems = (value: unknown): BackendContentItem[] | null => {\n if (!Array.isArray(value)) return null\n const normalized: BackendContentItem[] = []\n for (const item of value) {\n if (!isRecord(item)) return null\n const title = asString(item.title)\n const text = asString(item.text)\n if (title == null || text == null) return null\n normalized.push({ title, text })\n }\n return normalized\n}\n\nconst normalizeSlide = (value: unknown): CustomSlide | null => {\n if (!isRecord(value)) return null\n const type = normalizeType(value.type)\n if (!type) return null\n\n const rawData = isRecord(value.data) ? value.data : {}\n\n if (type === 'cover') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'contents') {\n const items = asStringArray(rawData.items)\n if (!items) return null\n return { type, data: { items } }\n }\n\n if (type === 'transition') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'content') {\n const title = asString(rawData.title)\n const items = normalizeContentItems(rawData.items)\n if (title == null || !items) return null\n return { type, data: { title, items } }\n }\n\n return { type }\n}\n\nconst parseNdJsonSlides = (raw: string): unknown[] =>\n raw\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => JSON.parse(line) as unknown)\n\nconst parseStructuredSlides = (raw: string): unknown[] | null => {\n const trimmed = raw.trim()\n if (!trimmed) return []\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n return null\n }\n if (Array.isArray(parsed)) return parsed\n if (!isRecord(parsed)) return null\n if (Array.isArray(parsed.slides)) return parsed.slides\n if ('type' in parsed) return [parsed]\n return null\n}\n\nexport const parseCustomContent = (raw: string): CustomSlide[] => {\n const candidates = parseStructuredSlides(raw) ?? parseNdJsonSlides(raw)\n const slides = candidates\n .map(item => normalizeSlide(item))\n .filter((item): item is CustomSlide => item !== null)\n\n if (slides.length !== candidates.length) {\n throw new Error('Invalid custom content format')\n }\n return slides\n}\n","import type { TemplateJsonElement } from '../types'\n\nexport const updateHtmlContent = (html: string, text: string) => {\n if (typeof DOMParser === 'undefined') {\n return `<p>${text}</p>`\n }\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n const spans = Array.from(doc.querySelectorAll('span'))\n if (spans.length > 0) {\n spans.forEach((span, index) => {\n span.textContent = index === 0 ? text : ''\n })\n } else {\n const paragraph = doc.querySelector('p')\n if (paragraph) {\n paragraph.textContent = text\n } else {\n doc.body.textContent = text\n }\n }\n return doc.body.innerHTML\n}\n\nexport const setElementText = (element: TemplateJsonElement, text: string) => {\n if (element.type !== 'text') return\n element.content = updateHtmlContent(element.content, text)\n}\n","import type {\n BackendContentData,\n BackendContentsData,\n BackendCoverData,\n BackendTransitionData,\n TemplateJsonSlide\n} from '../types'\nimport { setElementText, updateHtmlContent } from './html'\n\nfunction setShapeTextByType (\n slide: TemplateJsonSlide,\n textType: string,\n text: string\n): boolean {\n const shape = slide.elements.find((element) => {\n if (element.type !== 'shape') return false\n const maybeShape = element as unknown as {\n text?: { type?: string; content?: string }\n }\n return maybeShape.text?.type === textType\n })\n\n if (!shape) return false\n\n const shapeWithText = shape as unknown as {\n text?: { type?: string; content?: string }\n }\n if (!shapeWithText.text || typeof shapeWithText.text.content !== 'string') {\n return false\n }\n\n shapeWithText.text.content = updateHtmlContent(shapeWithText.text.content, text)\n return true\n}\n\nexport const applyCoverData = (slide: TemplateJsonSlide, data: BackendCoverData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n}\n\nexport const applyContentsData = (\n slide: TemplateJsonSlide,\n data: BackendContentsData\n) => {\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n items.forEach((element, index) => {\n const text = data.items[index]\n if (text) setElementText(element, text)\n })\n}\n\nexport const applyTransitionData = (\n slide: TemplateJsonSlide,\n data: BackendTransitionData,\n sectionIndex: number\n) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n const partNumber = slide.elements.find(\n element => element.type === 'text' && element.textType === 'partNumber'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n const formattedSectionIndex = `${sectionIndex}`.padStart(2, '0')\n if (partNumber) {\n setElementText(partNumber, formattedSectionIndex)\n } else {\n setShapeTextByType(slide, 'partNumber', formattedSectionIndex)\n }\n}\n\nexport const applyContentData = (slide: TemplateJsonSlide, data: BackendContentData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n if (title) setElementText(title, data.title)\n\n const itemTitles = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'itemTitle'\n )\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n\n data.items.forEach((item, index) => {\n const titleEl = itemTitles[index]\n const textEl = items[index]\n if (titleEl) setElementText(titleEl, item.title)\n if (textEl) setElementText(textEl, item.text)\n })\n}\n","import type { CustomSlide, TemplateJson, TemplateJsonSlide } from '../types'\nimport {\n applyContentData,\n applyContentsData,\n applyCoverData,\n applyTransitionData\n} from './slide-appliers'\n\nconst cloneSlide = (slide: TemplateJsonSlide): TemplateJsonSlide =>\n JSON.parse(JSON.stringify(slide)) as TemplateJsonSlide\n\nfunction normalizeLabel (value: string): string {\n return value\n .replace(/\\s+/g, ' ')\n .replace(/[,。、“”‘’:;!?【】()《》〈〉·,.:;!?()[\\]{}\"'`~\\-_/\\\\]/g, '')\n .trim()\n .toLowerCase()\n}\n\nfunction resolveTransitionIndex (\n customSlides: CustomSlide[],\n currentSlideIndex: number,\n transitionTitle: string,\n fallbackIndex: number\n): number {\n const normalizedTitle = normalizeLabel(transitionTitle)\n if (!normalizedTitle) return fallbackIndex\n\n const contentsItems = customSlides\n .slice(0, currentSlideIndex + 1)\n .filter((slide): slide is Extract<CustomSlide, { type: 'contents' }> => slide.type === 'contents')\n .flatMap(slide => slide.data.items)\n\n for (let index = 0; index < contentsItems.length; index += 1) {\n const normalizedItem = normalizeLabel(contentsItems[index])\n if (!normalizedItem) continue\n if (\n normalizedItem === normalizedTitle ||\n normalizedItem.includes(normalizedTitle) ||\n normalizedTitle.includes(normalizedItem)\n ) {\n return index + 1\n }\n }\n\n return fallbackIndex\n}\n\nexport const applyCustomContentToTemplate = (\n template: TemplateJson,\n CustomSlides: CustomSlide[]\n): TemplateJson => {\n const grouped = template.slides.reduce<Record<string, TemplateJsonSlide[]>>(\n (acc, slide) => {\n const key = slide.type || 'default'\n if (!acc[key]) acc[key] = []\n acc[key].push(slide)\n return acc\n },\n {}\n )\n\n const usage = new Map<string, number>()\n const getTextTypeCount = (slide: TemplateJsonSlide, textType: string) =>\n slide.elements.filter(\n element => element.type === 'text' && element.textType === textType\n ).length\n\n const getContentCapacity = (slide: TemplateJsonSlide) => {\n const titleSlots = getTextTypeCount(slide, 'itemTitle')\n const itemSlots = getTextTypeCount(slide, 'item')\n return Math.min(titleSlots, itemSlots)\n }\n\n const pickFromPool = (key: string, pool: TemplateJsonSlide[]) => {\n const index = usage.get(key) ?? 0\n usage.set(key, index + 1)\n return cloneSlide(pool[index % pool.length])\n }\n\n const pickSlide = (type: string, desiredCount?: number) => {\n const pool = grouped[type] || grouped.default || template.slides\n if (desiredCount == null || pool.length === 1) {\n return pickFromPool(type, pool)\n }\n\n const scored = pool.map(slide => {\n const capacity =\n type === 'content'\n ? getContentCapacity(slide)\n : getTextTypeCount(slide, 'item')\n return { slide, capacity }\n })\n const eligible = scored.filter(item => item.capacity >= desiredCount)\n if (eligible.length > 0) {\n const minCapacity = Math.min(...eligible.map(item => item.capacity))\n const best = eligible\n .filter(item => item.capacity === minCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, best)\n }\n const maxCapacity = Math.max(...scored.map(item => item.capacity))\n const fallback = scored\n .filter(item => item.capacity === maxCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, fallback)\n }\n\n let transitionIndex = 0\n const slides = CustomSlides.map((item, index) => {\n const desiredCount =\n item.type === 'contents'\n ? item.data.items.length\n : item.type === 'content'\n ? item.data.items.length\n : undefined\n const slide = pickSlide(item.type, desiredCount)\n if (item.type === 'cover') {\n applyCoverData(slide, item.data)\n } else if (item.type === 'contents') {\n applyContentsData(slide, item.data)\n } else if (item.type === 'transition') {\n transitionIndex += 1\n const partNumber = resolveTransitionIndex(\n CustomSlides,\n index,\n item.data.title,\n transitionIndex\n )\n applyTransitionData(slide, item.data, partNumber)\n } else if (item.type === 'content') {\n applyContentData(slide, item.data)\n }\n return slide\n })\n\n return {\n ...template,\n slides\n }\n}\n","import { parseDocument } from 'json2pptx-schema'\nimport type { Deck, PptxCustomThemeInput } from '../types'\nimport { replaceScopedMedia } from './media'\nimport { applyTheme2Json } from './theme-applier'\n\nexport function applyCustomTheme (\n deck: Deck,\n input: PptxCustomThemeInput\n): Deck {\n const normalizedDeck = parseDocument(deck) as unknown as Deck\n const withColors = applyTheme2Json(normalizedDeck, input)\n const withMedia = replaceScopedMedia(withColors, input)\n return parseDocument(withMedia) as unknown as Deck\n}\n\nexport { applyTheme2Json }\n","import type { ColorMapping, RGB } from './types'\n\nexport function normalizeHexColor (value: string): string | null {\n const raw = value.trim()\n const withHash = raw.startsWith('#') ? raw.slice(1) : raw\n if (withHash.length !== 3 && withHash.length !== 6) return null\n if (!/^[0-9a-fA-F]+$/.test(withHash)) return null\n const expanded =\n withHash.length === 3\n ? withHash\n .split('')\n .map((char) => char + char)\n .join('')\n : withHash\n return `#${expanded.toUpperCase()}`\n}\n\nexport function parseColorToRgb (\n value: string\n): (RGB & { alpha?: number }) | null {\n const hex = normalizeHexColor(value)\n if (hex) {\n const raw = hex.slice(1)\n const r = Number.parseInt(raw.slice(0, 2), 16)\n const g = Number.parseInt(raw.slice(2, 4), 16)\n const b = Number.parseInt(raw.slice(4, 6), 16)\n return { r, g, b }\n }\n\n const match = value.match(\n /rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)/i\n )\n if (!match) return null\n const r = Math.round(Number(match[1]))\n const g = Math.round(Number(match[2]))\n const b = Math.round(Number(match[3]))\n const alpha = match[4] !== undefined ? Number(match[4]) : undefined\n return {\n r,\n g,\n b,\n ...(Number.isFinite(alpha) ? { alpha } : {})\n }\n}\n\nexport function normalizeThemeColor (value: string): string | null {\n const hex = normalizeHexColor(value)\n if (hex) return hex\n const parsed = parseColorToRgb(value)\n if (!parsed) return null\n if (parsed.alpha !== undefined) {\n return `rgba(${parsed.r},${parsed.g},${parsed.b},${parsed.alpha})`\n }\n return `rgb(${parsed.r},${parsed.g},${parsed.b})`\n}\n\nexport function isPureColorString (value: string): boolean {\n const trimmed = value.trim()\n if (!trimmed) return false\n if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(trimmed)) return true\n return /^rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)$/i.test(\n trimmed\n )\n}\n\nfunction normalizeColorKey (value?: string): string | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = parseColorToRgb(trimmed)\n if (parsed) {\n return `${parsed.r},${parsed.g},${parsed.b},${parsed.alpha ?? 'none'}`\n }\n const hex = normalizeHexColor(trimmed)\n if (hex) return hex\n return trimmed.toLowerCase()\n}\n\nexport function colorsEqual (a: string, b: string): boolean {\n const aKey = normalizeColorKey(a)\n const bKey = normalizeColorKey(b)\n if (!aKey || !bKey) return false\n return aKey === bKey\n}\n\nexport function isWhiteColor (value?: string): boolean {\n const key = normalizeColorKey(value)\n if (!key) return false\n return (\n key === '#FFFFFF' ||\n key === '255,255,255,none' ||\n key === '255,255,255,1'\n )\n}\n\nexport function rgbToString (rgb: RGB): string {\n return `rgb(${rgb.r},${rgb.g},${rgb.b})`\n}\n\nexport function findMappingForColor (\n value: string,\n mappings: ColorMapping[]\n): ColorMapping | undefined {\n const parsed = parseColorToRgb(value)\n if (!parsed) return undefined\n return mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n}\n","import type {\n Deck,\n PptxCustomThemeInput,\n Slide,\n SlideElement,\n ThemeScope\n} from '../types'\nimport { parseColorToRgb } from './color-utils'\nimport type {\n BackgroundElementInput,\n LogoElementInput,\n LogoSize,\n MediaElementType,\n SlideScopeKey\n} from './types'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\nconst DEFAULT_LOGO_ASPECT_RATIO = 3.2\n\nfunction mapSlideTypeToScopeKey (type?: string): SlideScopeKey {\n const normalized = type?.trim().toLowerCase()\n if (!normalized) return null\n\n if (normalized === 'cover') return 'cover'\n if (normalized === 'contents' || normalized === 'agenda') return 'contents'\n if (normalized === 'transition' || normalized === 'section') return 'transition'\n if (normalized === 'content') return 'content'\n if (normalized === 'end' || normalized === 'ending') return 'end'\n\n return null\n}\n\nfunction isSlideInScope (slide: Slide, scope: ThemeScope): boolean {\n const key = mapSlideTypeToScopeKey(slide.type)\n if (!key) return false\n return Boolean(scope[key])\n}\n\nfunction createElementId (\n prefix: MediaElementType,\n slideIndex: number\n): string {\n const random = Math.random().toString(36).slice(2, 10)\n return `${prefix}-${slideIndex}-${random}`\n}\n\nfunction toHalfOpacityColor (value: string): string {\n const rgb = parseColorToRgb(value)\n if (!rgb) return value\n return `rgba(${rgb.r},${rgb.g},${rgb.b},0.5)`\n}\n\nfunction buildBackgroundElement (input: BackgroundElementInput): SlideElement {\n const { src, slideWidth, slideHeight, slideIndex } = input\n return {\n type: 'image',\n id: createElementId('background', slideIndex),\n src,\n width: slideWidth,\n height: slideHeight,\n left: 0,\n top: 0,\n fixedRatio: true,\n rotate: 0,\n imageType: 'background',\n filters: {\n opacity: '100%'\n }\n }\n}\n\nfunction resolveLogoAspectRatio (\n width?: number,\n height?: number\n): number {\n if (\n typeof width === 'number' &&\n typeof height === 'number' &&\n width > 0 &&\n height > 0\n ) {\n return width / height\n }\n return DEFAULT_LOGO_ASPECT_RATIO\n}\n\nfunction resolveLogoSize (input: LogoElementInput): LogoSize {\n const {\n slideWidth,\n slideHeight,\n logoWidth,\n logoHeight\n } = input\n\n const aspectRatio = resolveLogoAspectRatio(logoWidth, logoHeight)\n const maxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const maxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n let width = maxWidth\n let height = width / aspectRatio\n\n if (height > maxHeight) {\n height = maxHeight\n width = height * aspectRatio\n }\n\n return { width, height }\n}\n\nfunction buildLogoElement (input: LogoElementInput): SlideElement {\n const { src, slideWidth, slideIndex, position } = input\n const { width, height } = resolveLogoSize(input)\n\n const left =\n position === 'left'\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - width - LOGO_MARGIN_X)\n\n return {\n type: 'image',\n id: createElementId('logo', slideIndex),\n src,\n width,\n height,\n left,\n top: LOGO_MARGIN_Y,\n fixedRatio: true,\n rotate: 0,\n imageType: 'logo'\n }\n}\n\nexport function replaceScopedMedia (\n deck: Deck,\n input: PptxCustomThemeInput\n): Deck {\n if (!deck.slides?.length) return deck\n\n const slideWidth = deck.width ?? FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height ?? FALLBACK_SLIDE_HEIGHT\n const backgroundInput = input.backgroundImage\n const logoInput = input.logoImage\n const shouldClearBackground = Boolean(input.clearBackgroundImage)\n const shouldClearLogo = Boolean(input.clearLogoImage || shouldClearBackground)\n\n if (\n !backgroundInput?.src &&\n !logoInput?.src &&\n !shouldClearBackground &&\n !shouldClearLogo\n ) {\n return deck\n }\n\n const slides = deck.slides.map((slide, slideIndex) => {\n let nextElements = slide.elements ? [...slide.elements] : []\n let nextBackground = slide.background\n let changed = false\n\n if (shouldClearBackground) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n if (nextElements.length !== before) {\n changed = true\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: input.backgroundColor\n }\n }\n }\n }\n\n if (shouldClearLogo) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n if (nextElements.length !== before) {\n changed = true\n }\n }\n\n if (backgroundInput?.src && isSlideInScope(slide, backgroundInput.scope)) {\n const withoutBackground = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n nextElements = [\n buildBackgroundElement({\n src: backgroundInput.src,\n slideWidth,\n slideHeight,\n slideIndex\n }),\n ...withoutBackground\n ]\n changed = true\n\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: toHalfOpacityColor(input.backgroundColor)\n }\n }\n }\n\n if (logoInput?.src && isSlideInScope(slide, logoInput.scope)) {\n const withoutLogo = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n nextElements = [\n ...withoutLogo,\n buildLogoElement({\n src: logoInput.src,\n slideWidth,\n slideHeight,\n slideIndex,\n position: logoInput.position,\n logoWidth: logoInput.width,\n logoHeight: logoInput.height\n })\n ]\n changed = true\n }\n\n if (!changed && nextBackground === slide.background) return slide\n\n return {\n ...slide,\n ...(changed ? { elements: nextElements } : {}),\n ...(nextBackground ? { background: nextBackground } : {})\n }\n })\n\n return { ...deck, slides }\n}\n","import { normalizeHexColor, parseColorToRgb } from './color-utils'\nimport type { ColorMapping } from './types'\n\nexport function buildColorMappings (\n previous: string[],\n next: string[]\n): ColorMapping[] {\n const mappings: ColorMapping[] = []\n const length = Math.min(previous.length, next.length)\n for (let i = 0; i < length; i += 1) {\n const fromParsed = parseColorToRgb(previous[i])\n const toParsed = parseColorToRgb(next[i])\n if (!fromParsed || !toParsed) continue\n const toHex = normalizeHexColor(next[i]) ?? undefined\n mappings.push({\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n })\n }\n return mappings\n}\n\nexport function buildSingleMapping (\n from?: string,\n to?: string\n): ColorMapping | null {\n if (!from || !to) return null\n const fromParsed = parseColorToRgb(from)\n const toParsed = parseColorToRgb(to)\n if (!fromParsed || !toParsed) return null\n const toHex = normalizeHexColor(to) ?? undefined\n return {\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n }\n}\n","import type { Slide, SlideElement } from '../types'\nimport {\n findMappingForColor,\n isPureColorString,\n normalizeThemeColor,\n parseColorToRgb,\n rgbToString\n} from './color-utils'\nimport type { ColorMapping } from './types'\n\nfunction applyFontColorToHtml (value: string, fontColor: string): string {\n if (!value || !fontColor) return value\n const normalized = normalizeThemeColor(fontColor) ?? fontColor\n const hasStyleColor = /\\bcolor\\s*:/i.test(value)\n if (hasStyleColor) {\n return value.replace(/color\\s*:\\s*([^;\"']+)/gi, () => `color: ${normalized}`)\n }\n return value.replace(\n /(<[^>]+style\\s*=\\s*[\"'])([^\"']*)([\"'])/gi,\n (_match, start, styles, end) => {\n if (/\\bcolor\\s*:/i.test(styles)) return _match\n const nextStyles = styles.trim()\n ? `${styles.trim()}; color: ${normalized}`\n : `color: ${normalized}`\n return `${start}${nextStyles}${end}`\n }\n )\n}\n\nfunction replaceColorValue (value: string, mappings: ColorMapping[]): string {\n const mapping = findMappingForColor(value, mappings)\n if (!mapping) return value\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n if (parsed.alpha !== undefined) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceRgbaString (value: string, mappings: ColorMapping[]): string {\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n const mapping = mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n if (!mapping) return value\n if (parsed.alpha !== undefined || value.toLowerCase().startsWith('rgba')) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha ?? 1})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceColorsInText (value: string, mappings: ColorMapping[]): string {\n let next = value\n next = next.replace(/#([0-9a-f]{3}|[0-9a-f]{6})/gi, (match) => {\n const mapping = findMappingForColor(match, mappings)\n if (!mapping) return match\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n })\n next = next.replace(/rgba?\\([^)]*\\)/gi, (match) =>\n replaceRgbaString(match, mappings)\n )\n return next\n}\n\nfunction replaceColorsDeep (value: unknown, mappings: ColorMapping[]): unknown {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n const pureColor = isPureColorString(trimmed)\n if (pureColor) {\n const replaced = replaceColorValue(trimmed, mappings)\n return value === trimmed ? replaced : value.replace(trimmed, replaced)\n }\n return replaceColorsInText(value, mappings)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => replaceColorsDeep(item, mappings))\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n const next: Record<string, unknown> = {}\n for (const [key, item] of entries) {\n next[key] = replaceColorsDeep(item, mappings)\n }\n return next\n }\n\n return value\n}\n\nfunction replaceTextElementColors (\n element: SlideElement,\n fontMappings: ColorMapping[],\n fontColor: string\n): SlideElement {\n const next = replaceColorsDeep(element, fontMappings) as SlideElement\n const normalizedFontColor = normalizeThemeColor(fontColor) ?? fontColor\n const withDefault =\n normalizedFontColor && 'defaultColor' in next\n ? { ...next, defaultColor: normalizedFontColor }\n : next\n if (!('content' in withDefault) || typeof withDefault.content !== 'string') {\n return withDefault\n }\n return {\n ...withDefault,\n content: applyFontColorToHtml(withDefault.content, normalizedFontColor)\n }\n}\n\nexport function replaceSlideColors (\n slide: Slide,\n themeMappings: ColorMapping[],\n fontMappings: ColorMapping[],\n fontColor: string\n): Slide {\n const { elements, ...rest } = slide\n const nextSlide = replaceColorsDeep(rest, themeMappings) as Slide\n if (!elements) return nextSlide\n\n const nextElements: SlideElement[] = elements.map((element) => {\n if (element && typeof element === 'object' && element.type === 'text') {\n return replaceTextElementColors(element, fontMappings, fontColor)\n }\n return replaceColorsDeep(element, themeMappings) as SlideElement\n })\n\n return { ...nextSlide, elements: nextElements }\n}\n","import type { Deck, PptxCustomThemeInput } from '../types'\nimport { colorsEqual, isWhiteColor } from './color-utils'\nimport { buildColorMappings, buildSingleMapping } from './mappings'\nimport { replaceSlideColors } from './replacers'\n\nexport function applyTheme2Json (deck: Deck, update: PptxCustomThemeInput): Deck {\n const previousTheme = deck.theme ?? {}\n const themeColors = update.themeColors.slice(0, 6)\n const themeMappings = buildColorMappings(\n previousTheme.themeColors ?? [],\n themeColors\n )\n const fontMapping = buildSingleMapping(\n previousTheme.fontColor,\n update.fontColor\n )\n const fontMappings = fontMapping ? [fontMapping] : []\n\n const nextBackground = update.backgroundColor ?? previousTheme.backgroundColor\n const prevBackground = previousTheme.backgroundColor\n const slides = deck.slides?.map((slide) => {\n const nextSlide = replaceSlideColors(\n slide,\n themeMappings,\n fontMappings,\n update.fontColor\n )\n if (!nextBackground) return nextSlide\n const currentColor = nextSlide.background?.color\n const shouldUpdate =\n !currentColor ||\n (prevBackground && colorsEqual(currentColor, prevBackground)) ||\n (!prevBackground && isWhiteColor(currentColor))\n if (!shouldUpdate) return nextSlide\n return {\n ...nextSlide,\n background: {\n ...(nextSlide.background ?? {}),\n type: nextSlide.background?.type ?? 'solid',\n color: nextBackground\n }\n }\n })\n\n return {\n ...deck,\n theme: {\n ...previousTheme,\n themeColors,\n fontColor: update.fontColor,\n backgroundColor: update.backgroundColor ?? previousTheme.backgroundColor\n },\n slides\n }\n}\n"],"mappings":"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","names":["import_json2pptx_schema","r","g","b","FALLBACK_SLIDE_WIDTH","FALLBACK_SLIDE_HEIGHT","LOGO_MARGIN_X","LOGO_MARGIN_Y","LOGO_MAX_WIDTH_RATIO","LOGO_MAX_HEIGHT_RATIO"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/custom-content/index.ts","../src/custom-content/parser.ts","../src/custom-content/html.ts","../src/custom-content/slide-appliers.ts","../src/custom-content/template-builder.ts","../src/custom-theme/index.ts","../src/custom-theme/color-utils.ts","../src/custom-theme/media.ts","../src/custom-theme/mappings.ts","../src/custom-theme/replacers.ts","../src/custom-theme/theme-applier.ts"],"sourcesContent":["import { applyCustomContent, parseCustomContent, applyCustomContentToTemplate } from './custom-content/index'\nimport { applyCustomTheme } from './custom-theme/index'\n\nexport {\n parseCustomContent,\n applyCustomContent,\n applyCustomContentToTemplate,\n\n applyCustomTheme,\n}\n\nexport type {\n CustomSlide,\n Deck,\n Presentation,\n PresentationData,\n PresentationTheme,\n PptxCustomContentInput,\n PptxCustomOptions,\n PptxCustomThemeInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonSlide,\n TemplateJsonTheme\n} from './types'\n","import { parseDocument } from 'json2pptx-schema'\nimport type {\n PptxCustomContentInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonImage\n} from '../types'\nimport { parseCustomContent } from './parser'\nimport { applyCustomContentToTemplate } from './template-builder'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\n\nfunction isLogoImageElement (\n element: TemplateJsonElement\n): element is TemplateJsonImage {\n return element.type === 'image' && element.imageType === 'logo'\n}\n\nfunction fitSize (\n width: number,\n height: number,\n maxWidth: number,\n maxHeight: number\n): { width: number; height: number } {\n const safeWidth = width > 0 ? width : maxWidth\n const safeHeight = height > 0 ? height : maxHeight\n const scale = Math.min(maxWidth / safeWidth, maxHeight / safeHeight)\n return {\n width: safeWidth * scale,\n height: safeHeight * scale\n }\n}\n\nfunction normalizeLogoElements (deck: TemplateJson): TemplateJson {\n const slideWidth = deck.width || FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height || FALLBACK_SLIDE_HEIGHT\n const logoMaxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const logoMaxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n\n const slides = deck.slides.map(slide => {\n let changed = false\n const elements = slide.elements.map(element => {\n if (!isLogoImageElement(element)) return element\n\n const size = fitSize(\n element.width ?? logoMaxWidth,\n element.height ?? logoMaxHeight,\n logoMaxWidth,\n logoMaxHeight\n )\n const isLeft = (element.left ?? 0) < slideWidth / 2\n const left = isLeft\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - size.width - LOGO_MARGIN_X)\n const top = LOGO_MARGIN_Y\n const { clip: _clip, ...rest } = element\n\n changed = true\n return {\n ...rest,\n left,\n top,\n width: size.width,\n height: size.height,\n fixedRatio: true\n }\n })\n\n return changed ? { ...slide, elements } : slide\n })\n\n return { ...deck, slides }\n}\n\nexport function applyCustomContent (\n template: TemplateJson,\n input: PptxCustomContentInput\n): TemplateJson {\n const normalizedTemplate = parseDocument(template) as unknown as TemplateJson\n const CustomSlides = typeof input === 'string' ? parseCustomContent(input) : input\n const updated = applyCustomContentToTemplate(normalizedTemplate, CustomSlides)\n const withNormalizedLogo = normalizeLogoElements(updated)\n return parseDocument(withNormalizedLogo) as unknown as TemplateJson\n}\n\nexport { parseCustomContent, applyCustomContentToTemplate }\n","import type { BackendContentItem, CustomSlide } from '../types'\n\ntype UnknownRecord = Record<string, unknown>\n\nconst isRecord = (value: unknown): value is UnknownRecord =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst asString = (value: unknown): string | null =>\n typeof value === 'string' ? value : null\n\nconst asStringArray = (value: unknown): string[] | null => {\n if (!Array.isArray(value)) return null\n const normalized = value\n .map(item => asString(item))\n .filter((item): item is string => item !== null)\n return normalized.length === value.length ? normalized : null\n}\n\nconst normalizeType = (value: unknown): CustomSlide['type'] | null => {\n const raw = asString(value)?.trim().toLowerCase()\n if (!raw) return null\n if (raw === 'agenda') return 'contents'\n if (raw === 'section') return 'transition'\n if (raw === 'ending') return 'end'\n if (\n raw === 'cover' ||\n raw === 'contents' ||\n raw === 'transition' ||\n raw === 'content' ||\n raw === 'end'\n ) {\n return raw\n }\n return null\n}\n\nconst normalizeContentItems = (value: unknown): BackendContentItem[] | null => {\n if (!Array.isArray(value)) return null\n const normalized: BackendContentItem[] = []\n for (const item of value) {\n if (!isRecord(item)) return null\n const title = asString(item.title)\n const text = asString(item.text)\n if (title == null || text == null) return null\n normalized.push({ title, text })\n }\n return normalized\n}\n\nconst normalizeSlide = (value: unknown): CustomSlide | null => {\n if (!isRecord(value)) return null\n const type = normalizeType(value.type)\n if (!type) return null\n\n const rawData = isRecord(value.data) ? value.data : {}\n\n if (type === 'cover') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'contents') {\n const items = asStringArray(rawData.items)\n if (!items) return null\n return { type, data: { items } }\n }\n\n if (type === 'transition') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'content') {\n const title = asString(rawData.title)\n const items = normalizeContentItems(rawData.items)\n if (title == null || !items) return null\n return { type, data: { title, items } }\n }\n\n return { type }\n}\n\nconst parseNdJsonSlides = (raw: string): unknown[] =>\n raw\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => JSON.parse(line) as unknown)\n\nconst parseStructuredSlides = (raw: string): unknown[] | null => {\n const trimmed = raw.trim()\n if (!trimmed) return []\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n return null\n }\n if (Array.isArray(parsed)) return parsed\n if (!isRecord(parsed)) return null\n if (Array.isArray(parsed.slides)) return parsed.slides\n if ('type' in parsed) return [parsed]\n return null\n}\n\nexport const parseCustomContent = (raw: string): CustomSlide[] => {\n const candidates = parseStructuredSlides(raw) ?? parseNdJsonSlides(raw)\n const slides = candidates\n .map(item => normalizeSlide(item))\n .filter((item): item is CustomSlide => item !== null)\n\n if (slides.length !== candidates.length) {\n throw new Error('Invalid custom content format')\n }\n return slides\n}\n","import type { TemplateJsonElement } from '../types'\n\nexport const updateHtmlContent = (html: string, text: string) => {\n if (typeof DOMParser === 'undefined') {\n return `<p>${text}</p>`\n }\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n const spans = Array.from(doc.querySelectorAll('span'))\n if (spans.length > 0) {\n spans.forEach((span, index) => {\n span.textContent = index === 0 ? text : ''\n })\n } else {\n const paragraph = doc.querySelector('p')\n if (paragraph) {\n paragraph.textContent = text\n } else {\n doc.body.textContent = text\n }\n }\n return doc.body.innerHTML\n}\n\nexport const setElementText = (element: TemplateJsonElement, text: string) => {\n if (element.type !== 'text') return\n element.content = updateHtmlContent(element.content, text)\n}\n","import type {\n BackendContentData,\n BackendContentsData,\n BackendCoverData,\n BackendTransitionData,\n TemplateJsonSlide\n} from '../types'\nimport { setElementText, updateHtmlContent } from './html'\n\nfunction setShapeTextByType (\n slide: TemplateJsonSlide,\n textType: string,\n text: string\n): boolean {\n const shape = slide.elements.find((element) => {\n if (element.type !== 'shape') return false\n const maybeShape = element as unknown as {\n text?: { type?: string; content?: string }\n }\n return maybeShape.text?.type === textType\n })\n\n if (!shape) return false\n\n const shapeWithText = shape as unknown as {\n text?: { type?: string; content?: string }\n }\n if (!shapeWithText.text || typeof shapeWithText.text.content !== 'string') {\n return false\n }\n\n shapeWithText.text.content = updateHtmlContent(shapeWithText.text.content, text)\n return true\n}\n\nexport const applyCoverData = (slide: TemplateJsonSlide, data: BackendCoverData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n}\n\nexport const applyContentsData = (\n slide: TemplateJsonSlide,\n data: BackendContentsData\n) => {\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n items.forEach((element, index) => {\n const text = data.items[index]\n if (text) setElementText(element, text)\n })\n}\n\nexport const applyTransitionData = (\n slide: TemplateJsonSlide,\n data: BackendTransitionData,\n sectionIndex: number\n) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n const partNumber = slide.elements.find(\n element => element.type === 'text' && element.textType === 'partNumber'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n const formattedSectionIndex = `${sectionIndex}`.padStart(2, '0')\n if (partNumber) {\n setElementText(partNumber, formattedSectionIndex)\n } else {\n setShapeTextByType(slide, 'partNumber', formattedSectionIndex)\n }\n}\n\nexport const applyContentData = (slide: TemplateJsonSlide, data: BackendContentData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n if (title) setElementText(title, data.title)\n\n const itemTitles = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'itemTitle'\n )\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n\n data.items.forEach((item, index) => {\n const titleEl = itemTitles[index]\n const textEl = items[index]\n if (titleEl) setElementText(titleEl, item.title)\n if (textEl) setElementText(textEl, item.text)\n })\n}\n","import type { CustomSlide, TemplateJson, TemplateJsonSlide } from '../types'\nimport {\n applyContentData,\n applyContentsData,\n applyCoverData,\n applyTransitionData\n} from './slide-appliers'\n\nconst cloneSlide = (slide: TemplateJsonSlide): TemplateJsonSlide =>\n JSON.parse(JSON.stringify(slide)) as TemplateJsonSlide\n\nfunction normalizeLabel (value: string): string {\n return value\n .replace(/\\s+/g, ' ')\n .replace(/[,。、“”‘’:;!?【】()《》〈〉·,.:;!?()[\\]{}\"'`~\\-_/\\\\]/g, '')\n .trim()\n .toLowerCase()\n}\n\nfunction resolveTransitionIndex (\n customSlides: CustomSlide[],\n currentSlideIndex: number,\n transitionTitle: string,\n fallbackIndex: number\n): number {\n const normalizedTitle = normalizeLabel(transitionTitle)\n if (!normalizedTitle) return fallbackIndex\n\n const contentsItems = customSlides\n .slice(0, currentSlideIndex + 1)\n .filter((slide): slide is Extract<CustomSlide, { type: 'contents' }> => slide.type === 'contents')\n .flatMap(slide => slide.data.items)\n\n for (let index = 0; index < contentsItems.length; index += 1) {\n const normalizedItem = normalizeLabel(contentsItems[index])\n if (!normalizedItem) continue\n if (\n normalizedItem === normalizedTitle ||\n normalizedItem.includes(normalizedTitle) ||\n normalizedTitle.includes(normalizedItem)\n ) {\n return index + 1\n }\n }\n\n return fallbackIndex\n}\n\nexport const applyCustomContentToTemplate = (\n template: TemplateJson,\n CustomSlides: CustomSlide[]\n): TemplateJson => {\n const grouped = template.slides.reduce<Record<string, TemplateJsonSlide[]>>(\n (acc, slide) => {\n const key = slide.type || 'default'\n if (!acc[key]) acc[key] = []\n acc[key].push(slide)\n return acc\n },\n {}\n )\n\n const usage = new Map<string, number>()\n const getTextTypeCount = (slide: TemplateJsonSlide, textType: string) =>\n slide.elements.filter(\n element => element.type === 'text' && element.textType === textType\n ).length\n\n const getContentCapacity = (slide: TemplateJsonSlide) => {\n const titleSlots = getTextTypeCount(slide, 'itemTitle')\n const itemSlots = getTextTypeCount(slide, 'item')\n return Math.min(titleSlots, itemSlots)\n }\n\n const pickFromPool = (key: string, pool: TemplateJsonSlide[]) => {\n const index = usage.get(key) ?? 0\n usage.set(key, index + 1)\n return cloneSlide(pool[index % pool.length])\n }\n\n const pickSlide = (type: string, desiredCount?: number) => {\n const pool = grouped[type] || grouped.default || template.slides\n if (desiredCount == null || pool.length === 1) {\n return pickFromPool(type, pool)\n }\n\n const scored = pool.map(slide => {\n const capacity =\n type === 'content'\n ? getContentCapacity(slide)\n : getTextTypeCount(slide, 'item')\n return { slide, capacity }\n })\n const eligible = scored.filter(item => item.capacity >= desiredCount)\n if (eligible.length > 0) {\n const minCapacity = Math.min(...eligible.map(item => item.capacity))\n const best = eligible\n .filter(item => item.capacity === minCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, best)\n }\n const maxCapacity = Math.max(...scored.map(item => item.capacity))\n const fallback = scored\n .filter(item => item.capacity === maxCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, fallback)\n }\n\n let transitionIndex = 0\n const slides = CustomSlides.map((item, index) => {\n const desiredCount =\n item.type === 'contents'\n ? item.data.items.length\n : item.type === 'content'\n ? item.data.items.length\n : undefined\n const slide = pickSlide(item.type, desiredCount)\n if (item.type === 'cover') {\n applyCoverData(slide, item.data)\n } else if (item.type === 'contents') {\n applyContentsData(slide, item.data)\n } else if (item.type === 'transition') {\n transitionIndex += 1\n const partNumber = resolveTransitionIndex(\n CustomSlides,\n index,\n item.data.title,\n transitionIndex\n )\n applyTransitionData(slide, item.data, partNumber)\n } else if (item.type === 'content') {\n applyContentData(slide, item.data)\n }\n return slide\n })\n\n return {\n ...template,\n slides\n }\n}\n","import { parseDocument } from 'json2pptx-schema'\nimport type { Presentation, PptxCustomThemeInput } from '../types'\nimport { replaceScopedMedia } from './media'\nimport { applyTheme2Json } from './theme-applier'\n\ntype PresentationDocument = ReturnType<typeof parseDocument>\n\nexport function applyCustomTheme (\n deck: Presentation,\n input: PptxCustomThemeInput\n): Presentation {\n const normalizedDeck: PresentationDocument = parseDocument(deck)\n const withColors = applyTheme2Json(normalizedDeck as unknown as Presentation, input)\n const withMedia = replaceScopedMedia(withColors, input)\n return parseDocument(withMedia) as unknown as Presentation\n}\n\nexport { applyTheme2Json }\n","import type { ColorMapping, RGB } from './types'\n\nexport function normalizeHexColor (value: string): string | null {\n const raw = value.trim()\n const withHash = raw.startsWith('#') ? raw.slice(1) : raw\n if (withHash.length !== 3 && withHash.length !== 6) return null\n if (!/^[0-9a-fA-F]+$/.test(withHash)) return null\n const expanded =\n withHash.length === 3\n ? withHash\n .split('')\n .map((char) => char + char)\n .join('')\n : withHash\n return `#${expanded.toUpperCase()}`\n}\n\nexport function parseColorToRgb (\n value: string\n): (RGB & { alpha?: number }) | null {\n const hex = normalizeHexColor(value)\n if (hex) {\n const raw = hex.slice(1)\n const r = Number.parseInt(raw.slice(0, 2), 16)\n const g = Number.parseInt(raw.slice(2, 4), 16)\n const b = Number.parseInt(raw.slice(4, 6), 16)\n return { r, g, b }\n }\n\n const match = value.match(\n /rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)/i\n )\n if (!match) return null\n const r = Math.round(Number(match[1]))\n const g = Math.round(Number(match[2]))\n const b = Math.round(Number(match[3]))\n const alpha = match[4] !== undefined ? Number(match[4]) : undefined\n return {\n r,\n g,\n b,\n ...(Number.isFinite(alpha) ? { alpha } : {})\n }\n}\n\nexport function normalizeThemeColor (value: string): string | null {\n const hex = normalizeHexColor(value)\n if (hex) return hex\n const parsed = parseColorToRgb(value)\n if (!parsed) return null\n if (parsed.alpha !== undefined) {\n return `rgba(${parsed.r},${parsed.g},${parsed.b},${parsed.alpha})`\n }\n return `rgb(${parsed.r},${parsed.g},${parsed.b})`\n}\n\nexport function isPureColorString (value: string): boolean {\n const trimmed = value.trim()\n if (!trimmed) return false\n if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(trimmed)) return true\n return /^rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)$/i.test(\n trimmed\n )\n}\n\nfunction normalizeColorKey (value?: string): string | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = parseColorToRgb(trimmed)\n if (parsed) {\n return `${parsed.r},${parsed.g},${parsed.b},${parsed.alpha ?? 'none'}`\n }\n const hex = normalizeHexColor(trimmed)\n if (hex) return hex\n return trimmed.toLowerCase()\n}\n\nexport function colorsEqual (a: string, b: string): boolean {\n const aKey = normalizeColorKey(a)\n const bKey = normalizeColorKey(b)\n if (!aKey || !bKey) return false\n return aKey === bKey\n}\n\nexport function isWhiteColor (value?: string): boolean {\n const key = normalizeColorKey(value)\n if (!key) return false\n return (\n key === '#FFFFFF' ||\n key === '255,255,255,none' ||\n key === '255,255,255,1'\n )\n}\n\nexport function rgbToString (rgb: RGB): string {\n return `rgb(${rgb.r},${rgb.g},${rgb.b})`\n}\n\nexport function findMappingForColor (\n value: string,\n mappings: ColorMapping[]\n): ColorMapping | undefined {\n const parsed = parseColorToRgb(value)\n if (!parsed) return undefined\n return mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n}\n","import type {\n Presentation,\n PptxCustomThemeInput,\n Slide,\n SlideElement,\n ThemeScope\n} from '../types'\nimport { parseColorToRgb } from './color-utils'\nimport type {\n BackgroundElementInput,\n LogoElementInput,\n LogoSize,\n MediaElementType,\n SlideScopeKey\n} from './types'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\nconst DEFAULT_LOGO_ASPECT_RATIO = 3.2\n\nfunction mapSlideTypeToScopeKey (type?: string): SlideScopeKey {\n const normalized = type?.trim().toLowerCase()\n if (!normalized) return null\n\n if (normalized === 'cover') return 'cover'\n if (normalized === 'contents' || normalized === 'agenda') return 'contents'\n if (normalized === 'transition' || normalized === 'section') return 'transition'\n if (normalized === 'content') return 'content'\n if (normalized === 'end' || normalized === 'ending') return 'end'\n\n return null\n}\n\nfunction isSlideInScope (slide: Slide, scope: ThemeScope): boolean {\n const key = mapSlideTypeToScopeKey(slide.type)\n if (!key) return false\n return Boolean(scope[key])\n}\n\nfunction createElementId (\n prefix: MediaElementType,\n slideIndex: number\n): string {\n const random = Math.random().toString(36).slice(2, 10)\n return `${prefix}-${slideIndex}-${random}`\n}\n\nfunction toHalfOpacityColor (value: string): string {\n const rgb = parseColorToRgb(value)\n if (!rgb) return value\n return `rgba(${rgb.r},${rgb.g},${rgb.b},0.5)`\n}\n\nfunction buildBackgroundElement (input: BackgroundElementInput): SlideElement {\n const { src, slideWidth, slideHeight, slideIndex } = input\n return {\n type: 'image',\n id: createElementId('background', slideIndex),\n src,\n width: slideWidth,\n height: slideHeight,\n left: 0,\n top: 0,\n fixedRatio: true,\n rotate: 0,\n imageType: 'background',\n filters: {\n opacity: '100%'\n }\n }\n}\n\nfunction resolveLogoAspectRatio (\n width?: number,\n height?: number\n): number {\n if (\n typeof width === 'number' &&\n typeof height === 'number' &&\n width > 0 &&\n height > 0\n ) {\n return width / height\n }\n return DEFAULT_LOGO_ASPECT_RATIO\n}\n\nfunction resolveLogoSize (input: LogoElementInput): LogoSize {\n const {\n slideWidth,\n slideHeight,\n logoWidth,\n logoHeight\n } = input\n\n const aspectRatio = resolveLogoAspectRatio(logoWidth, logoHeight)\n const maxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const maxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n let width = maxWidth\n let height = width / aspectRatio\n\n if (height > maxHeight) {\n height = maxHeight\n width = height * aspectRatio\n }\n\n return { width, height }\n}\n\nfunction buildLogoElement (input: LogoElementInput): SlideElement {\n const { src, slideWidth, slideIndex, position } = input\n const { width, height } = resolveLogoSize(input)\n\n const left =\n position === 'left'\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - width - LOGO_MARGIN_X)\n\n return {\n type: 'image',\n id: createElementId('logo', slideIndex),\n src,\n width,\n height,\n left,\n top: LOGO_MARGIN_Y,\n fixedRatio: true,\n rotate: 0,\n imageType: 'logo'\n }\n}\n\nexport function replaceScopedMedia (\n deck: Presentation,\n input: PptxCustomThemeInput\n): Presentation {\n if (!deck.slides?.length) return deck\n\n const slideWidth = deck.width ?? FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height ?? FALLBACK_SLIDE_HEIGHT\n const backgroundInput = input.backgroundImage\n const logoInput = input.logoImage\n const shouldClearBackground = Boolean(input.clearBackgroundImage)\n const shouldClearLogo = Boolean(input.clearLogoImage || shouldClearBackground)\n\n if (\n !backgroundInput?.src &&\n !logoInput?.src &&\n !shouldClearBackground &&\n !shouldClearLogo\n ) {\n return deck\n }\n\n const slides = deck.slides.map((slide, slideIndex) => {\n let nextElements = slide.elements ? [...slide.elements] : []\n let nextBackground = slide.background\n let changed = false\n\n if (shouldClearBackground) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n if (nextElements.length !== before) {\n changed = true\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: input.backgroundColor\n }\n }\n }\n }\n\n if (shouldClearLogo) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n if (nextElements.length !== before) {\n changed = true\n }\n }\n\n if (backgroundInput?.src && isSlideInScope(slide, backgroundInput.scope)) {\n const withoutBackground = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n nextElements = [\n buildBackgroundElement({\n src: backgroundInput.src,\n slideWidth,\n slideHeight,\n slideIndex\n }),\n ...withoutBackground\n ]\n changed = true\n\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: toHalfOpacityColor(input.backgroundColor)\n }\n }\n }\n\n if (logoInput?.src && isSlideInScope(slide, logoInput.scope)) {\n const withoutLogo = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n nextElements = [\n ...withoutLogo,\n buildLogoElement({\n src: logoInput.src,\n slideWidth,\n slideHeight,\n slideIndex,\n position: logoInput.position,\n logoWidth: logoInput.width,\n logoHeight: logoInput.height\n })\n ]\n changed = true\n }\n\n if (!changed && nextBackground === slide.background) return slide\n\n return {\n ...slide,\n ...(changed ? { elements: nextElements } : {}),\n ...(nextBackground ? { background: nextBackground } : {})\n }\n })\n\n return { ...deck, slides }\n}\n","import { normalizeHexColor, parseColorToRgb } from './color-utils'\nimport type { ColorMapping } from './types'\n\nexport function buildColorMappings (\n previous: string[],\n next: string[]\n): ColorMapping[] {\n const mappings: ColorMapping[] = []\n const length = Math.min(previous.length, next.length)\n for (let i = 0; i < length; i += 1) {\n const fromParsed = parseColorToRgb(previous[i])\n const toParsed = parseColorToRgb(next[i])\n if (!fromParsed || !toParsed) continue\n const toHex = normalizeHexColor(next[i]) ?? undefined\n mappings.push({\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n })\n }\n return mappings\n}\n\nexport function buildSingleMapping (\n from?: string,\n to?: string\n): ColorMapping | null {\n if (!from || !to) return null\n const fromParsed = parseColorToRgb(from)\n const toParsed = parseColorToRgb(to)\n if (!fromParsed || !toParsed) return null\n const toHex = normalizeHexColor(to) ?? undefined\n return {\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n }\n}\n","import type { Slide, SlideElement } from '../types'\nimport {\n findMappingForColor,\n isPureColorString,\n normalizeThemeColor,\n parseColorToRgb,\n rgbToString\n} from './color-utils'\nimport type { ColorMapping } from './types'\n\nfunction applyColorToStyleAttribute (\n styles: string,\n color: string\n): string {\n const declarations = styles\n .split(';')\n .map(item => item.trim())\n .filter(Boolean)\n\n let updated = false\n const nextDeclarations = declarations.map((declaration) => {\n const separatorIndex = declaration.indexOf(':')\n if (separatorIndex < 0) return declaration\n\n const property = declaration.slice(0, separatorIndex).trim().toLowerCase()\n if (property !== 'color') return declaration\n\n updated = true\n return `color: ${color}`\n })\n\n if (!updated) {\n nextDeclarations.push(`color: ${color}`)\n }\n\n return nextDeclarations.join('; ')\n}\n\nfunction applyFontColorToHtml (value: string, fontColor: string): string {\n if (!value || !fontColor) return value\n const normalized = normalizeThemeColor(fontColor) ?? fontColor\n\n return value.replace(\n /(<[^>]+style\\s*=\\s*[\"'])([^\"']*)([\"'])/gi,\n (_match, start, styles, end): string => {\n const nextStyles = applyColorToStyleAttribute(styles, normalized)\n return `${start}${nextStyles}${end}`\n }\n )\n}\n\nfunction replaceColorValue (value: string, mappings: ColorMapping[]): string {\n const mapping = findMappingForColor(value, mappings)\n if (!mapping) return value\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n if (parsed.alpha !== undefined) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceRgbaString (value: string, mappings: ColorMapping[]): string {\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n const mapping = mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n if (!mapping) return value\n if (parsed.alpha !== undefined || value.toLowerCase().startsWith('rgba')) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha ?? 1})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceColorsInText (value: string, mappings: ColorMapping[]): string {\n let next = value\n next = next.replace(/#([0-9a-f]{3}|[0-9a-f]{6})/gi, (match) => {\n const mapping = findMappingForColor(match, mappings)\n if (!mapping) return match\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n })\n next = next.replace(/rgba?\\([^)]*\\)/gi, (match) =>\n replaceRgbaString(match, mappings)\n )\n return next\n}\n\nfunction replaceColorsDeep (value: unknown, mappings: ColorMapping[]): unknown {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n const pureColor = isPureColorString(trimmed)\n if (pureColor) {\n const replaced = replaceColorValue(trimmed, mappings)\n return value === trimmed ? replaced : value.replace(trimmed, replaced)\n }\n return replaceColorsInText(value, mappings)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => replaceColorsDeep(item, mappings))\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n const next: Record<string, unknown> = {}\n for (const [key, item] of entries) {\n next[key] = replaceColorsDeep(item, mappings)\n }\n return next\n }\n\n return value\n}\n\nfunction replaceTextElementColors (\n element: SlideElement,\n fontMappings: ColorMapping[],\n fontColor: string\n): SlideElement {\n const next = replaceColorsDeep(element, fontMappings) as SlideElement\n const normalizedFontColor = normalizeThemeColor(fontColor) ?? fontColor\n const withDefault =\n normalizedFontColor && 'defaultColor' in next\n ? { ...next, defaultColor: normalizedFontColor }\n : next\n if (!('content' in withDefault) || typeof withDefault.content !== 'string') {\n return withDefault\n }\n return {\n ...withDefault,\n content: applyFontColorToHtml(withDefault.content, normalizedFontColor)\n }\n}\n\nexport function replaceSlideColors (\n slide: Slide,\n themeMappings: ColorMapping[],\n fontMappings: ColorMapping[],\n fontColor: string\n): Slide {\n const { elements, ...rest } = slide\n const nextSlide = replaceColorsDeep(rest, themeMappings) as Slide\n if (!elements) return nextSlide\n\n const nextElements: SlideElement[] = elements.map((element) => {\n if (element && typeof element === 'object' && element.type === 'text') {\n return replaceTextElementColors(element, fontMappings, fontColor)\n }\n return replaceColorsDeep(element, themeMappings) as SlideElement\n })\n\n return { ...nextSlide, elements: nextElements }\n}\n","import type { Presentation, PptxCustomThemeInput } from '../types'\nimport { colorsEqual, isWhiteColor } from './color-utils'\nimport { buildColorMappings, buildSingleMapping } from './mappings'\nimport { replaceSlideColors } from './replacers'\n\ntype SolidBackground = Extract<NonNullable<Presentation['slides']>[number]['background'], { type: 'solid' }>\n\nexport function applyTheme2Json (deck: Presentation, update: PptxCustomThemeInput): Presentation {\n const previousTheme = deck.theme ?? {}\n const themeColors = update.themeColors.slice(0, 6)\n const themeMappings = buildColorMappings(\n previousTheme.themeColors ?? [],\n themeColors\n )\n const fontMapping = buildSingleMapping(\n previousTheme.fontColor,\n update.fontColor\n )\n const fontMappings = fontMapping ? [fontMapping] : []\n\n const nextBackground = update.backgroundColor ?? previousTheme.backgroundColor\n const prevBackground = previousTheme.backgroundColor\n const slides = deck.slides?.map((slide) => {\n const nextSlide = replaceSlideColors(\n slide,\n themeMappings,\n fontMappings,\n update.fontColor\n )\n if (!nextBackground) return nextSlide\n const currentColor =\n nextSlide.background?.type === 'solid' ? nextSlide.background.color : undefined\n const shouldUpdate =\n !currentColor ||\n (prevBackground && colorsEqual(currentColor, prevBackground)) ||\n (!prevBackground && isWhiteColor(currentColor))\n if (!shouldUpdate) return nextSlide\n return {\n ...nextSlide,\n background: createSolidBackground(nextBackground)\n }\n })\n\n return {\n ...deck,\n theme: {\n ...previousTheme,\n themeColors,\n fontColor: update.fontColor,\n backgroundColor: update.backgroundColor ?? previousTheme.backgroundColor\n },\n slides\n }\n}\n\nfunction createSolidBackground (color: string): SolidBackground {\n return {\n type: 'solid',\n color\n }\n}\n"],"mappings":"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","names":["import_json2pptx_schema","r","g","b","FALLBACK_SLIDE_WIDTH","FALLBACK_SLIDE_HEIGHT","LOGO_MARGIN_X","LOGO_MARGIN_Y","LOGO_MAX_WIDTH_RATIO","LOGO_MAX_HEIGHT_RATIO"]}
|
package/dist/index.mjs
CHANGED
|
@@ -636,18 +636,29 @@ function buildSingleMapping(from, to) {
|
|
|
636
636
|
}
|
|
637
637
|
|
|
638
638
|
// src/custom-theme/replacers.ts
|
|
639
|
+
function applyColorToStyleAttribute(styles, color) {
|
|
640
|
+
const declarations = styles.split(";").map((item) => item.trim()).filter(Boolean);
|
|
641
|
+
let updated = false;
|
|
642
|
+
const nextDeclarations = declarations.map((declaration) => {
|
|
643
|
+
const separatorIndex = declaration.indexOf(":");
|
|
644
|
+
if (separatorIndex < 0) return declaration;
|
|
645
|
+
const property = declaration.slice(0, separatorIndex).trim().toLowerCase();
|
|
646
|
+
if (property !== "color") return declaration;
|
|
647
|
+
updated = true;
|
|
648
|
+
return `color: ${color}`;
|
|
649
|
+
});
|
|
650
|
+
if (!updated) {
|
|
651
|
+
nextDeclarations.push(`color: ${color}`);
|
|
652
|
+
}
|
|
653
|
+
return nextDeclarations.join("; ");
|
|
654
|
+
}
|
|
639
655
|
function applyFontColorToHtml(value, fontColor) {
|
|
640
656
|
if (!value || !fontColor) return value;
|
|
641
657
|
const normalized = normalizeThemeColor(fontColor) ?? fontColor;
|
|
642
|
-
const hasStyleColor = /\bcolor\s*:/i.test(value);
|
|
643
|
-
if (hasStyleColor) {
|
|
644
|
-
return value.replace(/color\s*:\s*([^;"']+)/gi, () => `color: ${normalized}`);
|
|
645
|
-
}
|
|
646
658
|
return value.replace(
|
|
647
659
|
/(<[^>]+style\s*=\s*["'])([^"']*)(["'])/gi,
|
|
648
660
|
(_match, start, styles, end) => {
|
|
649
|
-
|
|
650
|
-
const nextStyles = styles.trim() ? `${styles.trim()}; color: ${normalized}` : `color: ${normalized}`;
|
|
661
|
+
const nextStyles = applyColorToStyleAttribute(styles, normalized);
|
|
651
662
|
return `${start}${nextStyles}${end}`;
|
|
652
663
|
}
|
|
653
664
|
);
|
|
@@ -758,16 +769,12 @@ function applyTheme2Json(deck, update) {
|
|
|
758
769
|
update.fontColor
|
|
759
770
|
);
|
|
760
771
|
if (!nextBackground) return nextSlide;
|
|
761
|
-
const currentColor = nextSlide.background?.color;
|
|
772
|
+
const currentColor = nextSlide.background?.type === "solid" ? nextSlide.background.color : void 0;
|
|
762
773
|
const shouldUpdate = !currentColor || prevBackground && colorsEqual(currentColor, prevBackground) || !prevBackground && isWhiteColor(currentColor);
|
|
763
774
|
if (!shouldUpdate) return nextSlide;
|
|
764
775
|
return {
|
|
765
776
|
...nextSlide,
|
|
766
|
-
background:
|
|
767
|
-
...nextSlide.background ?? {},
|
|
768
|
-
type: nextSlide.background?.type ?? "solid",
|
|
769
|
-
color: nextBackground
|
|
770
|
-
}
|
|
777
|
+
background: createSolidBackground(nextBackground)
|
|
771
778
|
};
|
|
772
779
|
});
|
|
773
780
|
return {
|
|
@@ -781,6 +788,12 @@ function applyTheme2Json(deck, update) {
|
|
|
781
788
|
slides
|
|
782
789
|
};
|
|
783
790
|
}
|
|
791
|
+
function createSolidBackground(color) {
|
|
792
|
+
return {
|
|
793
|
+
type: "solid",
|
|
794
|
+
color
|
|
795
|
+
};
|
|
796
|
+
}
|
|
784
797
|
|
|
785
798
|
// src/custom-theme/index.ts
|
|
786
799
|
function applyCustomTheme(deck, input) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/custom-content/index.ts","../src/custom-content/parser.ts","../src/custom-content/html.ts","../src/custom-content/slide-appliers.ts","../src/custom-content/template-builder.ts","../src/custom-theme/index.ts","../src/custom-theme/color-utils.ts","../src/custom-theme/media.ts","../src/custom-theme/mappings.ts","../src/custom-theme/replacers.ts","../src/custom-theme/theme-applier.ts"],"sourcesContent":["import { parseDocument } from 'json2pptx-schema'\nimport type {\n PptxCustomContentInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonImage\n} from '../types'\nimport { parseCustomContent } from './parser'\nimport { applyCustomContentToTemplate } from './template-builder'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\n\nfunction isLogoImageElement (\n element: TemplateJsonElement\n): element is TemplateJsonImage {\n return element.type === 'image' && element.imageType === 'logo'\n}\n\nfunction fitSize (\n width: number,\n height: number,\n maxWidth: number,\n maxHeight: number\n): { width: number; height: number } {\n const safeWidth = width > 0 ? width : maxWidth\n const safeHeight = height > 0 ? height : maxHeight\n const scale = Math.min(maxWidth / safeWidth, maxHeight / safeHeight)\n return {\n width: safeWidth * scale,\n height: safeHeight * scale\n }\n}\n\nfunction normalizeLogoElements (deck: TemplateJson): TemplateJson {\n const slideWidth = deck.width || FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height || FALLBACK_SLIDE_HEIGHT\n const logoMaxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const logoMaxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n\n const slides = deck.slides.map(slide => {\n let changed = false\n const elements = slide.elements.map(element => {\n if (!isLogoImageElement(element)) return element\n\n const size = fitSize(\n element.width ?? logoMaxWidth,\n element.height ?? logoMaxHeight,\n logoMaxWidth,\n logoMaxHeight\n )\n const isLeft = (element.left ?? 0) < slideWidth / 2\n const left = isLeft\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - size.width - LOGO_MARGIN_X)\n const top = LOGO_MARGIN_Y\n const { clip: _clip, ...rest } = element\n\n changed = true\n return {\n ...rest,\n left,\n top,\n width: size.width,\n height: size.height,\n fixedRatio: true\n }\n })\n\n return changed ? { ...slide, elements } : slide\n })\n\n return { ...deck, slides }\n}\n\nexport function applyCustomContent (\n template: TemplateJson,\n input: PptxCustomContentInput\n): TemplateJson {\n const normalizedTemplate = parseDocument(template) as unknown as TemplateJson\n const CustomSlides = typeof input === 'string' ? parseCustomContent(input) : input\n const updated = applyCustomContentToTemplate(normalizedTemplate, CustomSlides)\n const withNormalizedLogo = normalizeLogoElements(updated)\n return parseDocument(withNormalizedLogo) as unknown as TemplateJson\n}\n\nexport { parseCustomContent, applyCustomContentToTemplate }\n","import type { BackendContentItem, CustomSlide } from '../types'\n\ntype UnknownRecord = Record<string, unknown>\n\nconst isRecord = (value: unknown): value is UnknownRecord =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst asString = (value: unknown): string | null =>\n typeof value === 'string' ? value : null\n\nconst asStringArray = (value: unknown): string[] | null => {\n if (!Array.isArray(value)) return null\n const normalized = value\n .map(item => asString(item))\n .filter((item): item is string => item !== null)\n return normalized.length === value.length ? normalized : null\n}\n\nconst normalizeType = (value: unknown): CustomSlide['type'] | null => {\n const raw = asString(value)?.trim().toLowerCase()\n if (!raw) return null\n if (raw === 'agenda') return 'contents'\n if (raw === 'section') return 'transition'\n if (raw === 'ending') return 'end'\n if (\n raw === 'cover' ||\n raw === 'contents' ||\n raw === 'transition' ||\n raw === 'content' ||\n raw === 'end'\n ) {\n return raw\n }\n return null\n}\n\nconst normalizeContentItems = (value: unknown): BackendContentItem[] | null => {\n if (!Array.isArray(value)) return null\n const normalized: BackendContentItem[] = []\n for (const item of value) {\n if (!isRecord(item)) return null\n const title = asString(item.title)\n const text = asString(item.text)\n if (title == null || text == null) return null\n normalized.push({ title, text })\n }\n return normalized\n}\n\nconst normalizeSlide = (value: unknown): CustomSlide | null => {\n if (!isRecord(value)) return null\n const type = normalizeType(value.type)\n if (!type) return null\n\n const rawData = isRecord(value.data) ? value.data : {}\n\n if (type === 'cover') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'contents') {\n const items = asStringArray(rawData.items)\n if (!items) return null\n return { type, data: { items } }\n }\n\n if (type === 'transition') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'content') {\n const title = asString(rawData.title)\n const items = normalizeContentItems(rawData.items)\n if (title == null || !items) return null\n return { type, data: { title, items } }\n }\n\n return { type }\n}\n\nconst parseNdJsonSlides = (raw: string): unknown[] =>\n raw\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => JSON.parse(line) as unknown)\n\nconst parseStructuredSlides = (raw: string): unknown[] | null => {\n const trimmed = raw.trim()\n if (!trimmed) return []\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n return null\n }\n if (Array.isArray(parsed)) return parsed\n if (!isRecord(parsed)) return null\n if (Array.isArray(parsed.slides)) return parsed.slides\n if ('type' in parsed) return [parsed]\n return null\n}\n\nexport const parseCustomContent = (raw: string): CustomSlide[] => {\n const candidates = parseStructuredSlides(raw) ?? parseNdJsonSlides(raw)\n const slides = candidates\n .map(item => normalizeSlide(item))\n .filter((item): item is CustomSlide => item !== null)\n\n if (slides.length !== candidates.length) {\n throw new Error('Invalid custom content format')\n }\n return slides\n}\n","import type { TemplateJsonElement } from '../types'\n\nexport const updateHtmlContent = (html: string, text: string) => {\n if (typeof DOMParser === 'undefined') {\n return `<p>${text}</p>`\n }\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n const spans = Array.from(doc.querySelectorAll('span'))\n if (spans.length > 0) {\n spans.forEach((span, index) => {\n span.textContent = index === 0 ? text : ''\n })\n } else {\n const paragraph = doc.querySelector('p')\n if (paragraph) {\n paragraph.textContent = text\n } else {\n doc.body.textContent = text\n }\n }\n return doc.body.innerHTML\n}\n\nexport const setElementText = (element: TemplateJsonElement, text: string) => {\n if (element.type !== 'text') return\n element.content = updateHtmlContent(element.content, text)\n}\n","import type {\n BackendContentData,\n BackendContentsData,\n BackendCoverData,\n BackendTransitionData,\n TemplateJsonSlide\n} from '../types'\nimport { setElementText, updateHtmlContent } from './html'\n\nfunction setShapeTextByType (\n slide: TemplateJsonSlide,\n textType: string,\n text: string\n): boolean {\n const shape = slide.elements.find((element) => {\n if (element.type !== 'shape') return false\n const maybeShape = element as unknown as {\n text?: { type?: string; content?: string }\n }\n return maybeShape.text?.type === textType\n })\n\n if (!shape) return false\n\n const shapeWithText = shape as unknown as {\n text?: { type?: string; content?: string }\n }\n if (!shapeWithText.text || typeof shapeWithText.text.content !== 'string') {\n return false\n }\n\n shapeWithText.text.content = updateHtmlContent(shapeWithText.text.content, text)\n return true\n}\n\nexport const applyCoverData = (slide: TemplateJsonSlide, data: BackendCoverData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n}\n\nexport const applyContentsData = (\n slide: TemplateJsonSlide,\n data: BackendContentsData\n) => {\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n items.forEach((element, index) => {\n const text = data.items[index]\n if (text) setElementText(element, text)\n })\n}\n\nexport const applyTransitionData = (\n slide: TemplateJsonSlide,\n data: BackendTransitionData,\n sectionIndex: number\n) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n const partNumber = slide.elements.find(\n element => element.type === 'text' && element.textType === 'partNumber'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n const formattedSectionIndex = `${sectionIndex}`.padStart(2, '0')\n if (partNumber) {\n setElementText(partNumber, formattedSectionIndex)\n } else {\n setShapeTextByType(slide, 'partNumber', formattedSectionIndex)\n }\n}\n\nexport const applyContentData = (slide: TemplateJsonSlide, data: BackendContentData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n if (title) setElementText(title, data.title)\n\n const itemTitles = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'itemTitle'\n )\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n\n data.items.forEach((item, index) => {\n const titleEl = itemTitles[index]\n const textEl = items[index]\n if (titleEl) setElementText(titleEl, item.title)\n if (textEl) setElementText(textEl, item.text)\n })\n}\n","import type { CustomSlide, TemplateJson, TemplateJsonSlide } from '../types'\nimport {\n applyContentData,\n applyContentsData,\n applyCoverData,\n applyTransitionData\n} from './slide-appliers'\n\nconst cloneSlide = (slide: TemplateJsonSlide): TemplateJsonSlide =>\n JSON.parse(JSON.stringify(slide)) as TemplateJsonSlide\n\nfunction normalizeLabel (value: string): string {\n return value\n .replace(/\\s+/g, ' ')\n .replace(/[,。、“”‘’:;!?【】()《》〈〉·,.:;!?()[\\]{}\"'`~\\-_/\\\\]/g, '')\n .trim()\n .toLowerCase()\n}\n\nfunction resolveTransitionIndex (\n customSlides: CustomSlide[],\n currentSlideIndex: number,\n transitionTitle: string,\n fallbackIndex: number\n): number {\n const normalizedTitle = normalizeLabel(transitionTitle)\n if (!normalizedTitle) return fallbackIndex\n\n const contentsItems = customSlides\n .slice(0, currentSlideIndex + 1)\n .filter((slide): slide is Extract<CustomSlide, { type: 'contents' }> => slide.type === 'contents')\n .flatMap(slide => slide.data.items)\n\n for (let index = 0; index < contentsItems.length; index += 1) {\n const normalizedItem = normalizeLabel(contentsItems[index])\n if (!normalizedItem) continue\n if (\n normalizedItem === normalizedTitle ||\n normalizedItem.includes(normalizedTitle) ||\n normalizedTitle.includes(normalizedItem)\n ) {\n return index + 1\n }\n }\n\n return fallbackIndex\n}\n\nexport const applyCustomContentToTemplate = (\n template: TemplateJson,\n CustomSlides: CustomSlide[]\n): TemplateJson => {\n const grouped = template.slides.reduce<Record<string, TemplateJsonSlide[]>>(\n (acc, slide) => {\n const key = slide.type || 'default'\n if (!acc[key]) acc[key] = []\n acc[key].push(slide)\n return acc\n },\n {}\n )\n\n const usage = new Map<string, number>()\n const getTextTypeCount = (slide: TemplateJsonSlide, textType: string) =>\n slide.elements.filter(\n element => element.type === 'text' && element.textType === textType\n ).length\n\n const getContentCapacity = (slide: TemplateJsonSlide) => {\n const titleSlots = getTextTypeCount(slide, 'itemTitle')\n const itemSlots = getTextTypeCount(slide, 'item')\n return Math.min(titleSlots, itemSlots)\n }\n\n const pickFromPool = (key: string, pool: TemplateJsonSlide[]) => {\n const index = usage.get(key) ?? 0\n usage.set(key, index + 1)\n return cloneSlide(pool[index % pool.length])\n }\n\n const pickSlide = (type: string, desiredCount?: number) => {\n const pool = grouped[type] || grouped.default || template.slides\n if (desiredCount == null || pool.length === 1) {\n return pickFromPool(type, pool)\n }\n\n const scored = pool.map(slide => {\n const capacity =\n type === 'content'\n ? getContentCapacity(slide)\n : getTextTypeCount(slide, 'item')\n return { slide, capacity }\n })\n const eligible = scored.filter(item => item.capacity >= desiredCount)\n if (eligible.length > 0) {\n const minCapacity = Math.min(...eligible.map(item => item.capacity))\n const best = eligible\n .filter(item => item.capacity === minCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, best)\n }\n const maxCapacity = Math.max(...scored.map(item => item.capacity))\n const fallback = scored\n .filter(item => item.capacity === maxCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, fallback)\n }\n\n let transitionIndex = 0\n const slides = CustomSlides.map((item, index) => {\n const desiredCount =\n item.type === 'contents'\n ? item.data.items.length\n : item.type === 'content'\n ? item.data.items.length\n : undefined\n const slide = pickSlide(item.type, desiredCount)\n if (item.type === 'cover') {\n applyCoverData(slide, item.data)\n } else if (item.type === 'contents') {\n applyContentsData(slide, item.data)\n } else if (item.type === 'transition') {\n transitionIndex += 1\n const partNumber = resolveTransitionIndex(\n CustomSlides,\n index,\n item.data.title,\n transitionIndex\n )\n applyTransitionData(slide, item.data, partNumber)\n } else if (item.type === 'content') {\n applyContentData(slide, item.data)\n }\n return slide\n })\n\n return {\n ...template,\n slides\n }\n}\n","import { parseDocument } from 'json2pptx-schema'\nimport type { Deck, PptxCustomThemeInput } from '../types'\nimport { replaceScopedMedia } from './media'\nimport { applyTheme2Json } from './theme-applier'\n\nexport function applyCustomTheme (\n deck: Deck,\n input: PptxCustomThemeInput\n): Deck {\n const normalizedDeck = parseDocument(deck) as unknown as Deck\n const withColors = applyTheme2Json(normalizedDeck, input)\n const withMedia = replaceScopedMedia(withColors, input)\n return parseDocument(withMedia) as unknown as Deck\n}\n\nexport { applyTheme2Json }\n","import type { ColorMapping, RGB } from './types'\n\nexport function normalizeHexColor (value: string): string | null {\n const raw = value.trim()\n const withHash = raw.startsWith('#') ? raw.slice(1) : raw\n if (withHash.length !== 3 && withHash.length !== 6) return null\n if (!/^[0-9a-fA-F]+$/.test(withHash)) return null\n const expanded =\n withHash.length === 3\n ? withHash\n .split('')\n .map((char) => char + char)\n .join('')\n : withHash\n return `#${expanded.toUpperCase()}`\n}\n\nexport function parseColorToRgb (\n value: string\n): (RGB & { alpha?: number }) | null {\n const hex = normalizeHexColor(value)\n if (hex) {\n const raw = hex.slice(1)\n const r = Number.parseInt(raw.slice(0, 2), 16)\n const g = Number.parseInt(raw.slice(2, 4), 16)\n const b = Number.parseInt(raw.slice(4, 6), 16)\n return { r, g, b }\n }\n\n const match = value.match(\n /rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)/i\n )\n if (!match) return null\n const r = Math.round(Number(match[1]))\n const g = Math.round(Number(match[2]))\n const b = Math.round(Number(match[3]))\n const alpha = match[4] !== undefined ? Number(match[4]) : undefined\n return {\n r,\n g,\n b,\n ...(Number.isFinite(alpha) ? { alpha } : {})\n }\n}\n\nexport function normalizeThemeColor (value: string): string | null {\n const hex = normalizeHexColor(value)\n if (hex) return hex\n const parsed = parseColorToRgb(value)\n if (!parsed) return null\n if (parsed.alpha !== undefined) {\n return `rgba(${parsed.r},${parsed.g},${parsed.b},${parsed.alpha})`\n }\n return `rgb(${parsed.r},${parsed.g},${parsed.b})`\n}\n\nexport function isPureColorString (value: string): boolean {\n const trimmed = value.trim()\n if (!trimmed) return false\n if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(trimmed)) return true\n return /^rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)$/i.test(\n trimmed\n )\n}\n\nfunction normalizeColorKey (value?: string): string | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = parseColorToRgb(trimmed)\n if (parsed) {\n return `${parsed.r},${parsed.g},${parsed.b},${parsed.alpha ?? 'none'}`\n }\n const hex = normalizeHexColor(trimmed)\n if (hex) return hex\n return trimmed.toLowerCase()\n}\n\nexport function colorsEqual (a: string, b: string): boolean {\n const aKey = normalizeColorKey(a)\n const bKey = normalizeColorKey(b)\n if (!aKey || !bKey) return false\n return aKey === bKey\n}\n\nexport function isWhiteColor (value?: string): boolean {\n const key = normalizeColorKey(value)\n if (!key) return false\n return (\n key === '#FFFFFF' ||\n key === '255,255,255,none' ||\n key === '255,255,255,1'\n )\n}\n\nexport function rgbToString (rgb: RGB): string {\n return `rgb(${rgb.r},${rgb.g},${rgb.b})`\n}\n\nexport function findMappingForColor (\n value: string,\n mappings: ColorMapping[]\n): ColorMapping | undefined {\n const parsed = parseColorToRgb(value)\n if (!parsed) return undefined\n return mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n}\n","import type {\n Deck,\n PptxCustomThemeInput,\n Slide,\n SlideElement,\n ThemeScope\n} from '../types'\nimport { parseColorToRgb } from './color-utils'\nimport type {\n BackgroundElementInput,\n LogoElementInput,\n LogoSize,\n MediaElementType,\n SlideScopeKey\n} from './types'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\nconst DEFAULT_LOGO_ASPECT_RATIO = 3.2\n\nfunction mapSlideTypeToScopeKey (type?: string): SlideScopeKey {\n const normalized = type?.trim().toLowerCase()\n if (!normalized) return null\n\n if (normalized === 'cover') return 'cover'\n if (normalized === 'contents' || normalized === 'agenda') return 'contents'\n if (normalized === 'transition' || normalized === 'section') return 'transition'\n if (normalized === 'content') return 'content'\n if (normalized === 'end' || normalized === 'ending') return 'end'\n\n return null\n}\n\nfunction isSlideInScope (slide: Slide, scope: ThemeScope): boolean {\n const key = mapSlideTypeToScopeKey(slide.type)\n if (!key) return false\n return Boolean(scope[key])\n}\n\nfunction createElementId (\n prefix: MediaElementType,\n slideIndex: number\n): string {\n const random = Math.random().toString(36).slice(2, 10)\n return `${prefix}-${slideIndex}-${random}`\n}\n\nfunction toHalfOpacityColor (value: string): string {\n const rgb = parseColorToRgb(value)\n if (!rgb) return value\n return `rgba(${rgb.r},${rgb.g},${rgb.b},0.5)`\n}\n\nfunction buildBackgroundElement (input: BackgroundElementInput): SlideElement {\n const { src, slideWidth, slideHeight, slideIndex } = input\n return {\n type: 'image',\n id: createElementId('background', slideIndex),\n src,\n width: slideWidth,\n height: slideHeight,\n left: 0,\n top: 0,\n fixedRatio: true,\n rotate: 0,\n imageType: 'background',\n filters: {\n opacity: '100%'\n }\n }\n}\n\nfunction resolveLogoAspectRatio (\n width?: number,\n height?: number\n): number {\n if (\n typeof width === 'number' &&\n typeof height === 'number' &&\n width > 0 &&\n height > 0\n ) {\n return width / height\n }\n return DEFAULT_LOGO_ASPECT_RATIO\n}\n\nfunction resolveLogoSize (input: LogoElementInput): LogoSize {\n const {\n slideWidth,\n slideHeight,\n logoWidth,\n logoHeight\n } = input\n\n const aspectRatio = resolveLogoAspectRatio(logoWidth, logoHeight)\n const maxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const maxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n let width = maxWidth\n let height = width / aspectRatio\n\n if (height > maxHeight) {\n height = maxHeight\n width = height * aspectRatio\n }\n\n return { width, height }\n}\n\nfunction buildLogoElement (input: LogoElementInput): SlideElement {\n const { src, slideWidth, slideIndex, position } = input\n const { width, height } = resolveLogoSize(input)\n\n const left =\n position === 'left'\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - width - LOGO_MARGIN_X)\n\n return {\n type: 'image',\n id: createElementId('logo', slideIndex),\n src,\n width,\n height,\n left,\n top: LOGO_MARGIN_Y,\n fixedRatio: true,\n rotate: 0,\n imageType: 'logo'\n }\n}\n\nexport function replaceScopedMedia (\n deck: Deck,\n input: PptxCustomThemeInput\n): Deck {\n if (!deck.slides?.length) return deck\n\n const slideWidth = deck.width ?? FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height ?? FALLBACK_SLIDE_HEIGHT\n const backgroundInput = input.backgroundImage\n const logoInput = input.logoImage\n const shouldClearBackground = Boolean(input.clearBackgroundImage)\n const shouldClearLogo = Boolean(input.clearLogoImage || shouldClearBackground)\n\n if (\n !backgroundInput?.src &&\n !logoInput?.src &&\n !shouldClearBackground &&\n !shouldClearLogo\n ) {\n return deck\n }\n\n const slides = deck.slides.map((slide, slideIndex) => {\n let nextElements = slide.elements ? [...slide.elements] : []\n let nextBackground = slide.background\n let changed = false\n\n if (shouldClearBackground) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n if (nextElements.length !== before) {\n changed = true\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: input.backgroundColor\n }\n }\n }\n }\n\n if (shouldClearLogo) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n if (nextElements.length !== before) {\n changed = true\n }\n }\n\n if (backgroundInput?.src && isSlideInScope(slide, backgroundInput.scope)) {\n const withoutBackground = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n nextElements = [\n buildBackgroundElement({\n src: backgroundInput.src,\n slideWidth,\n slideHeight,\n slideIndex\n }),\n ...withoutBackground\n ]\n changed = true\n\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: toHalfOpacityColor(input.backgroundColor)\n }\n }\n }\n\n if (logoInput?.src && isSlideInScope(slide, logoInput.scope)) {\n const withoutLogo = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n nextElements = [\n ...withoutLogo,\n buildLogoElement({\n src: logoInput.src,\n slideWidth,\n slideHeight,\n slideIndex,\n position: logoInput.position,\n logoWidth: logoInput.width,\n logoHeight: logoInput.height\n })\n ]\n changed = true\n }\n\n if (!changed && nextBackground === slide.background) return slide\n\n return {\n ...slide,\n ...(changed ? { elements: nextElements } : {}),\n ...(nextBackground ? { background: nextBackground } : {})\n }\n })\n\n return { ...deck, slides }\n}\n","import { normalizeHexColor, parseColorToRgb } from './color-utils'\nimport type { ColorMapping } from './types'\n\nexport function buildColorMappings (\n previous: string[],\n next: string[]\n): ColorMapping[] {\n const mappings: ColorMapping[] = []\n const length = Math.min(previous.length, next.length)\n for (let i = 0; i < length; i += 1) {\n const fromParsed = parseColorToRgb(previous[i])\n const toParsed = parseColorToRgb(next[i])\n if (!fromParsed || !toParsed) continue\n const toHex = normalizeHexColor(next[i]) ?? undefined\n mappings.push({\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n })\n }\n return mappings\n}\n\nexport function buildSingleMapping (\n from?: string,\n to?: string\n): ColorMapping | null {\n if (!from || !to) return null\n const fromParsed = parseColorToRgb(from)\n const toParsed = parseColorToRgb(to)\n if (!fromParsed || !toParsed) return null\n const toHex = normalizeHexColor(to) ?? undefined\n return {\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n }\n}\n","import type { Slide, SlideElement } from '../types'\nimport {\n findMappingForColor,\n isPureColorString,\n normalizeThemeColor,\n parseColorToRgb,\n rgbToString\n} from './color-utils'\nimport type { ColorMapping } from './types'\n\nfunction applyFontColorToHtml (value: string, fontColor: string): string {\n if (!value || !fontColor) return value\n const normalized = normalizeThemeColor(fontColor) ?? fontColor\n const hasStyleColor = /\\bcolor\\s*:/i.test(value)\n if (hasStyleColor) {\n return value.replace(/color\\s*:\\s*([^;\"']+)/gi, () => `color: ${normalized}`)\n }\n return value.replace(\n /(<[^>]+style\\s*=\\s*[\"'])([^\"']*)([\"'])/gi,\n (_match, start, styles, end) => {\n if (/\\bcolor\\s*:/i.test(styles)) return _match\n const nextStyles = styles.trim()\n ? `${styles.trim()}; color: ${normalized}`\n : `color: ${normalized}`\n return `${start}${nextStyles}${end}`\n }\n )\n}\n\nfunction replaceColorValue (value: string, mappings: ColorMapping[]): string {\n const mapping = findMappingForColor(value, mappings)\n if (!mapping) return value\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n if (parsed.alpha !== undefined) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceRgbaString (value: string, mappings: ColorMapping[]): string {\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n const mapping = mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n if (!mapping) return value\n if (parsed.alpha !== undefined || value.toLowerCase().startsWith('rgba')) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha ?? 1})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceColorsInText (value: string, mappings: ColorMapping[]): string {\n let next = value\n next = next.replace(/#([0-9a-f]{3}|[0-9a-f]{6})/gi, (match) => {\n const mapping = findMappingForColor(match, mappings)\n if (!mapping) return match\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n })\n next = next.replace(/rgba?\\([^)]*\\)/gi, (match) =>\n replaceRgbaString(match, mappings)\n )\n return next\n}\n\nfunction replaceColorsDeep (value: unknown, mappings: ColorMapping[]): unknown {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n const pureColor = isPureColorString(trimmed)\n if (pureColor) {\n const replaced = replaceColorValue(trimmed, mappings)\n return value === trimmed ? replaced : value.replace(trimmed, replaced)\n }\n return replaceColorsInText(value, mappings)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => replaceColorsDeep(item, mappings))\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n const next: Record<string, unknown> = {}\n for (const [key, item] of entries) {\n next[key] = replaceColorsDeep(item, mappings)\n }\n return next\n }\n\n return value\n}\n\nfunction replaceTextElementColors (\n element: SlideElement,\n fontMappings: ColorMapping[],\n fontColor: string\n): SlideElement {\n const next = replaceColorsDeep(element, fontMappings) as SlideElement\n const normalizedFontColor = normalizeThemeColor(fontColor) ?? fontColor\n const withDefault =\n normalizedFontColor && 'defaultColor' in next\n ? { ...next, defaultColor: normalizedFontColor }\n : next\n if (!('content' in withDefault) || typeof withDefault.content !== 'string') {\n return withDefault\n }\n return {\n ...withDefault,\n content: applyFontColorToHtml(withDefault.content, normalizedFontColor)\n }\n}\n\nexport function replaceSlideColors (\n slide: Slide,\n themeMappings: ColorMapping[],\n fontMappings: ColorMapping[],\n fontColor: string\n): Slide {\n const { elements, ...rest } = slide\n const nextSlide = replaceColorsDeep(rest, themeMappings) as Slide\n if (!elements) return nextSlide\n\n const nextElements: SlideElement[] = elements.map((element) => {\n if (element && typeof element === 'object' && element.type === 'text') {\n return replaceTextElementColors(element, fontMappings, fontColor)\n }\n return replaceColorsDeep(element, themeMappings) as SlideElement\n })\n\n return { ...nextSlide, elements: nextElements }\n}\n","import type { Deck, PptxCustomThemeInput } from '../types'\nimport { colorsEqual, isWhiteColor } from './color-utils'\nimport { buildColorMappings, buildSingleMapping } from './mappings'\nimport { replaceSlideColors } from './replacers'\n\nexport function applyTheme2Json (deck: Deck, update: PptxCustomThemeInput): Deck {\n const previousTheme = deck.theme ?? {}\n const themeColors = update.themeColors.slice(0, 6)\n const themeMappings = buildColorMappings(\n previousTheme.themeColors ?? [],\n themeColors\n )\n const fontMapping = buildSingleMapping(\n previousTheme.fontColor,\n update.fontColor\n )\n const fontMappings = fontMapping ? [fontMapping] : []\n\n const nextBackground = update.backgroundColor ?? previousTheme.backgroundColor\n const prevBackground = previousTheme.backgroundColor\n const slides = deck.slides?.map((slide) => {\n const nextSlide = replaceSlideColors(\n slide,\n themeMappings,\n fontMappings,\n update.fontColor\n )\n if (!nextBackground) return nextSlide\n const currentColor = nextSlide.background?.color\n const shouldUpdate =\n !currentColor ||\n (prevBackground && colorsEqual(currentColor, prevBackground)) ||\n (!prevBackground && isWhiteColor(currentColor))\n if (!shouldUpdate) return nextSlide\n return {\n ...nextSlide,\n background: {\n ...(nextSlide.background ?? {}),\n type: nextSlide.background?.type ?? 'solid',\n color: nextBackground\n }\n }\n })\n\n return {\n ...deck,\n theme: {\n ...previousTheme,\n themeColors,\n fontColor: update.fontColor,\n backgroundColor: update.backgroundColor ?? previousTheme.backgroundColor\n },\n slides\n }\n}\n"],"mappings":"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","names":["parseDocument","r","g","b","FALLBACK_SLIDE_WIDTH","FALLBACK_SLIDE_HEIGHT","LOGO_MARGIN_X","LOGO_MARGIN_Y","LOGO_MAX_WIDTH_RATIO","LOGO_MAX_HEIGHT_RATIO","parseDocument"]}
|
|
1
|
+
{"version":3,"sources":["../src/custom-content/index.ts","../src/custom-content/parser.ts","../src/custom-content/html.ts","../src/custom-content/slide-appliers.ts","../src/custom-content/template-builder.ts","../src/custom-theme/index.ts","../src/custom-theme/color-utils.ts","../src/custom-theme/media.ts","../src/custom-theme/mappings.ts","../src/custom-theme/replacers.ts","../src/custom-theme/theme-applier.ts"],"sourcesContent":["import { parseDocument } from 'json2pptx-schema'\nimport type {\n PptxCustomContentInput,\n TemplateJson,\n TemplateJsonElement,\n TemplateJsonImage\n} from '../types'\nimport { parseCustomContent } from './parser'\nimport { applyCustomContentToTemplate } from './template-builder'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\n\nfunction isLogoImageElement (\n element: TemplateJsonElement\n): element is TemplateJsonImage {\n return element.type === 'image' && element.imageType === 'logo'\n}\n\nfunction fitSize (\n width: number,\n height: number,\n maxWidth: number,\n maxHeight: number\n): { width: number; height: number } {\n const safeWidth = width > 0 ? width : maxWidth\n const safeHeight = height > 0 ? height : maxHeight\n const scale = Math.min(maxWidth / safeWidth, maxHeight / safeHeight)\n return {\n width: safeWidth * scale,\n height: safeHeight * scale\n }\n}\n\nfunction normalizeLogoElements (deck: TemplateJson): TemplateJson {\n const slideWidth = deck.width || FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height || FALLBACK_SLIDE_HEIGHT\n const logoMaxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const logoMaxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n\n const slides = deck.slides.map(slide => {\n let changed = false\n const elements = slide.elements.map(element => {\n if (!isLogoImageElement(element)) return element\n\n const size = fitSize(\n element.width ?? logoMaxWidth,\n element.height ?? logoMaxHeight,\n logoMaxWidth,\n logoMaxHeight\n )\n const isLeft = (element.left ?? 0) < slideWidth / 2\n const left = isLeft\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - size.width - LOGO_MARGIN_X)\n const top = LOGO_MARGIN_Y\n const { clip: _clip, ...rest } = element\n\n changed = true\n return {\n ...rest,\n left,\n top,\n width: size.width,\n height: size.height,\n fixedRatio: true\n }\n })\n\n return changed ? { ...slide, elements } : slide\n })\n\n return { ...deck, slides }\n}\n\nexport function applyCustomContent (\n template: TemplateJson,\n input: PptxCustomContentInput\n): TemplateJson {\n const normalizedTemplate = parseDocument(template) as unknown as TemplateJson\n const CustomSlides = typeof input === 'string' ? parseCustomContent(input) : input\n const updated = applyCustomContentToTemplate(normalizedTemplate, CustomSlides)\n const withNormalizedLogo = normalizeLogoElements(updated)\n return parseDocument(withNormalizedLogo) as unknown as TemplateJson\n}\n\nexport { parseCustomContent, applyCustomContentToTemplate }\n","import type { BackendContentItem, CustomSlide } from '../types'\n\ntype UnknownRecord = Record<string, unknown>\n\nconst isRecord = (value: unknown): value is UnknownRecord =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst asString = (value: unknown): string | null =>\n typeof value === 'string' ? value : null\n\nconst asStringArray = (value: unknown): string[] | null => {\n if (!Array.isArray(value)) return null\n const normalized = value\n .map(item => asString(item))\n .filter((item): item is string => item !== null)\n return normalized.length === value.length ? normalized : null\n}\n\nconst normalizeType = (value: unknown): CustomSlide['type'] | null => {\n const raw = asString(value)?.trim().toLowerCase()\n if (!raw) return null\n if (raw === 'agenda') return 'contents'\n if (raw === 'section') return 'transition'\n if (raw === 'ending') return 'end'\n if (\n raw === 'cover' ||\n raw === 'contents' ||\n raw === 'transition' ||\n raw === 'content' ||\n raw === 'end'\n ) {\n return raw\n }\n return null\n}\n\nconst normalizeContentItems = (value: unknown): BackendContentItem[] | null => {\n if (!Array.isArray(value)) return null\n const normalized: BackendContentItem[] = []\n for (const item of value) {\n if (!isRecord(item)) return null\n const title = asString(item.title)\n const text = asString(item.text)\n if (title == null || text == null) return null\n normalized.push({ title, text })\n }\n return normalized\n}\n\nconst normalizeSlide = (value: unknown): CustomSlide | null => {\n if (!isRecord(value)) return null\n const type = normalizeType(value.type)\n if (!type) return null\n\n const rawData = isRecord(value.data) ? value.data : {}\n\n if (type === 'cover') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'contents') {\n const items = asStringArray(rawData.items)\n if (!items) return null\n return { type, data: { items } }\n }\n\n if (type === 'transition') {\n const title = asString(rawData.title)\n const text = asString(rawData.text)\n if (title == null || text == null) return null\n return { type, data: { title, text } }\n }\n\n if (type === 'content') {\n const title = asString(rawData.title)\n const items = normalizeContentItems(rawData.items)\n if (title == null || !items) return null\n return { type, data: { title, items } }\n }\n\n return { type }\n}\n\nconst parseNdJsonSlides = (raw: string): unknown[] =>\n raw\n .split(/\\r?\\n/)\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => JSON.parse(line) as unknown)\n\nconst parseStructuredSlides = (raw: string): unknown[] | null => {\n const trimmed = raw.trim()\n if (!trimmed) return []\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n return null\n }\n if (Array.isArray(parsed)) return parsed\n if (!isRecord(parsed)) return null\n if (Array.isArray(parsed.slides)) return parsed.slides\n if ('type' in parsed) return [parsed]\n return null\n}\n\nexport const parseCustomContent = (raw: string): CustomSlide[] => {\n const candidates = parseStructuredSlides(raw) ?? parseNdJsonSlides(raw)\n const slides = candidates\n .map(item => normalizeSlide(item))\n .filter((item): item is CustomSlide => item !== null)\n\n if (slides.length !== candidates.length) {\n throw new Error('Invalid custom content format')\n }\n return slides\n}\n","import type { TemplateJsonElement } from '../types'\n\nexport const updateHtmlContent = (html: string, text: string) => {\n if (typeof DOMParser === 'undefined') {\n return `<p>${text}</p>`\n }\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n const spans = Array.from(doc.querySelectorAll('span'))\n if (spans.length > 0) {\n spans.forEach((span, index) => {\n span.textContent = index === 0 ? text : ''\n })\n } else {\n const paragraph = doc.querySelector('p')\n if (paragraph) {\n paragraph.textContent = text\n } else {\n doc.body.textContent = text\n }\n }\n return doc.body.innerHTML\n}\n\nexport const setElementText = (element: TemplateJsonElement, text: string) => {\n if (element.type !== 'text') return\n element.content = updateHtmlContent(element.content, text)\n}\n","import type {\n BackendContentData,\n BackendContentsData,\n BackendCoverData,\n BackendTransitionData,\n TemplateJsonSlide\n} from '../types'\nimport { setElementText, updateHtmlContent } from './html'\n\nfunction setShapeTextByType (\n slide: TemplateJsonSlide,\n textType: string,\n text: string\n): boolean {\n const shape = slide.elements.find((element) => {\n if (element.type !== 'shape') return false\n const maybeShape = element as unknown as {\n text?: { type?: string; content?: string }\n }\n return maybeShape.text?.type === textType\n })\n\n if (!shape) return false\n\n const shapeWithText = shape as unknown as {\n text?: { type?: string; content?: string }\n }\n if (!shapeWithText.text || typeof shapeWithText.text.content !== 'string') {\n return false\n }\n\n shapeWithText.text.content = updateHtmlContent(shapeWithText.text.content, text)\n return true\n}\n\nexport const applyCoverData = (slide: TemplateJsonSlide, data: BackendCoverData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n}\n\nexport const applyContentsData = (\n slide: TemplateJsonSlide,\n data: BackendContentsData\n) => {\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n items.forEach((element, index) => {\n const text = data.items[index]\n if (text) setElementText(element, text)\n })\n}\n\nexport const applyTransitionData = (\n slide: TemplateJsonSlide,\n data: BackendTransitionData,\n sectionIndex: number\n) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n const content = slide.elements.find(\n element => element.type === 'text' && element.textType === 'content'\n )\n const partNumber = slide.elements.find(\n element => element.type === 'text' && element.textType === 'partNumber'\n )\n if (title) setElementText(title, data.title)\n if (content) setElementText(content, data.text)\n const formattedSectionIndex = `${sectionIndex}`.padStart(2, '0')\n if (partNumber) {\n setElementText(partNumber, formattedSectionIndex)\n } else {\n setShapeTextByType(slide, 'partNumber', formattedSectionIndex)\n }\n}\n\nexport const applyContentData = (slide: TemplateJsonSlide, data: BackendContentData) => {\n const title = slide.elements.find(\n element => element.type === 'text' && element.textType === 'title'\n )\n if (title) setElementText(title, data.title)\n\n const itemTitles = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'itemTitle'\n )\n const items = slide.elements.filter(\n element => element.type === 'text' && element.textType === 'item'\n )\n\n data.items.forEach((item, index) => {\n const titleEl = itemTitles[index]\n const textEl = items[index]\n if (titleEl) setElementText(titleEl, item.title)\n if (textEl) setElementText(textEl, item.text)\n })\n}\n","import type { CustomSlide, TemplateJson, TemplateJsonSlide } from '../types'\nimport {\n applyContentData,\n applyContentsData,\n applyCoverData,\n applyTransitionData\n} from './slide-appliers'\n\nconst cloneSlide = (slide: TemplateJsonSlide): TemplateJsonSlide =>\n JSON.parse(JSON.stringify(slide)) as TemplateJsonSlide\n\nfunction normalizeLabel (value: string): string {\n return value\n .replace(/\\s+/g, ' ')\n .replace(/[,。、“”‘’:;!?【】()《》〈〉·,.:;!?()[\\]{}\"'`~\\-_/\\\\]/g, '')\n .trim()\n .toLowerCase()\n}\n\nfunction resolveTransitionIndex (\n customSlides: CustomSlide[],\n currentSlideIndex: number,\n transitionTitle: string,\n fallbackIndex: number\n): number {\n const normalizedTitle = normalizeLabel(transitionTitle)\n if (!normalizedTitle) return fallbackIndex\n\n const contentsItems = customSlides\n .slice(0, currentSlideIndex + 1)\n .filter((slide): slide is Extract<CustomSlide, { type: 'contents' }> => slide.type === 'contents')\n .flatMap(slide => slide.data.items)\n\n for (let index = 0; index < contentsItems.length; index += 1) {\n const normalizedItem = normalizeLabel(contentsItems[index])\n if (!normalizedItem) continue\n if (\n normalizedItem === normalizedTitle ||\n normalizedItem.includes(normalizedTitle) ||\n normalizedTitle.includes(normalizedItem)\n ) {\n return index + 1\n }\n }\n\n return fallbackIndex\n}\n\nexport const applyCustomContentToTemplate = (\n template: TemplateJson,\n CustomSlides: CustomSlide[]\n): TemplateJson => {\n const grouped = template.slides.reduce<Record<string, TemplateJsonSlide[]>>(\n (acc, slide) => {\n const key = slide.type || 'default'\n if (!acc[key]) acc[key] = []\n acc[key].push(slide)\n return acc\n },\n {}\n )\n\n const usage = new Map<string, number>()\n const getTextTypeCount = (slide: TemplateJsonSlide, textType: string) =>\n slide.elements.filter(\n element => element.type === 'text' && element.textType === textType\n ).length\n\n const getContentCapacity = (slide: TemplateJsonSlide) => {\n const titleSlots = getTextTypeCount(slide, 'itemTitle')\n const itemSlots = getTextTypeCount(slide, 'item')\n return Math.min(titleSlots, itemSlots)\n }\n\n const pickFromPool = (key: string, pool: TemplateJsonSlide[]) => {\n const index = usage.get(key) ?? 0\n usage.set(key, index + 1)\n return cloneSlide(pool[index % pool.length])\n }\n\n const pickSlide = (type: string, desiredCount?: number) => {\n const pool = grouped[type] || grouped.default || template.slides\n if (desiredCount == null || pool.length === 1) {\n return pickFromPool(type, pool)\n }\n\n const scored = pool.map(slide => {\n const capacity =\n type === 'content'\n ? getContentCapacity(slide)\n : getTextTypeCount(slide, 'item')\n return { slide, capacity }\n })\n const eligible = scored.filter(item => item.capacity >= desiredCount)\n if (eligible.length > 0) {\n const minCapacity = Math.min(...eligible.map(item => item.capacity))\n const best = eligible\n .filter(item => item.capacity === minCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, best)\n }\n const maxCapacity = Math.max(...scored.map(item => item.capacity))\n const fallback = scored\n .filter(item => item.capacity === maxCapacity)\n .map(item => item.slide)\n return pickFromPool(`${type}:${desiredCount}`, fallback)\n }\n\n let transitionIndex = 0\n const slides = CustomSlides.map((item, index) => {\n const desiredCount =\n item.type === 'contents'\n ? item.data.items.length\n : item.type === 'content'\n ? item.data.items.length\n : undefined\n const slide = pickSlide(item.type, desiredCount)\n if (item.type === 'cover') {\n applyCoverData(slide, item.data)\n } else if (item.type === 'contents') {\n applyContentsData(slide, item.data)\n } else if (item.type === 'transition') {\n transitionIndex += 1\n const partNumber = resolveTransitionIndex(\n CustomSlides,\n index,\n item.data.title,\n transitionIndex\n )\n applyTransitionData(slide, item.data, partNumber)\n } else if (item.type === 'content') {\n applyContentData(slide, item.data)\n }\n return slide\n })\n\n return {\n ...template,\n slides\n }\n}\n","import { parseDocument } from 'json2pptx-schema'\nimport type { Presentation, PptxCustomThemeInput } from '../types'\nimport { replaceScopedMedia } from './media'\nimport { applyTheme2Json } from './theme-applier'\n\ntype PresentationDocument = ReturnType<typeof parseDocument>\n\nexport function applyCustomTheme (\n deck: Presentation,\n input: PptxCustomThemeInput\n): Presentation {\n const normalizedDeck: PresentationDocument = parseDocument(deck)\n const withColors = applyTheme2Json(normalizedDeck as unknown as Presentation, input)\n const withMedia = replaceScopedMedia(withColors, input)\n return parseDocument(withMedia) as unknown as Presentation\n}\n\nexport { applyTheme2Json }\n","import type { ColorMapping, RGB } from './types'\n\nexport function normalizeHexColor (value: string): string | null {\n const raw = value.trim()\n const withHash = raw.startsWith('#') ? raw.slice(1) : raw\n if (withHash.length !== 3 && withHash.length !== 6) return null\n if (!/^[0-9a-fA-F]+$/.test(withHash)) return null\n const expanded =\n withHash.length === 3\n ? withHash\n .split('')\n .map((char) => char + char)\n .join('')\n : withHash\n return `#${expanded.toUpperCase()}`\n}\n\nexport function parseColorToRgb (\n value: string\n): (RGB & { alpha?: number }) | null {\n const hex = normalizeHexColor(value)\n if (hex) {\n const raw = hex.slice(1)\n const r = Number.parseInt(raw.slice(0, 2), 16)\n const g = Number.parseInt(raw.slice(2, 4), 16)\n const b = Number.parseInt(raw.slice(4, 6), 16)\n return { r, g, b }\n }\n\n const match = value.match(\n /rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)/i\n )\n if (!match) return null\n const r = Math.round(Number(match[1]))\n const g = Math.round(Number(match[2]))\n const b = Math.round(Number(match[3]))\n const alpha = match[4] !== undefined ? Number(match[4]) : undefined\n return {\n r,\n g,\n b,\n ...(Number.isFinite(alpha) ? { alpha } : {})\n }\n}\n\nexport function normalizeThemeColor (value: string): string | null {\n const hex = normalizeHexColor(value)\n if (hex) return hex\n const parsed = parseColorToRgb(value)\n if (!parsed) return null\n if (parsed.alpha !== undefined) {\n return `rgba(${parsed.r},${parsed.g},${parsed.b},${parsed.alpha})`\n }\n return `rgb(${parsed.r},${parsed.g},${parsed.b})`\n}\n\nexport function isPureColorString (value: string): boolean {\n const trimmed = value.trim()\n if (!trimmed) return false\n if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(trimmed)) return true\n return /^rgba?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*,\\s*([0-9.]+)\\s*(?:,\\s*([0-9.]+)\\s*)?\\)$/i.test(\n trimmed\n )\n}\n\nfunction normalizeColorKey (value?: string): string | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = parseColorToRgb(trimmed)\n if (parsed) {\n return `${parsed.r},${parsed.g},${parsed.b},${parsed.alpha ?? 'none'}`\n }\n const hex = normalizeHexColor(trimmed)\n if (hex) return hex\n return trimmed.toLowerCase()\n}\n\nexport function colorsEqual (a: string, b: string): boolean {\n const aKey = normalizeColorKey(a)\n const bKey = normalizeColorKey(b)\n if (!aKey || !bKey) return false\n return aKey === bKey\n}\n\nexport function isWhiteColor (value?: string): boolean {\n const key = normalizeColorKey(value)\n if (!key) return false\n return (\n key === '#FFFFFF' ||\n key === '255,255,255,none' ||\n key === '255,255,255,1'\n )\n}\n\nexport function rgbToString (rgb: RGB): string {\n return `rgb(${rgb.r},${rgb.g},${rgb.b})`\n}\n\nexport function findMappingForColor (\n value: string,\n mappings: ColorMapping[]\n): ColorMapping | undefined {\n const parsed = parseColorToRgb(value)\n if (!parsed) return undefined\n return mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n}\n","import type {\n Presentation,\n PptxCustomThemeInput,\n Slide,\n SlideElement,\n ThemeScope\n} from '../types'\nimport { parseColorToRgb } from './color-utils'\nimport type {\n BackgroundElementInput,\n LogoElementInput,\n LogoSize,\n MediaElementType,\n SlideScopeKey\n} from './types'\n\nconst FALLBACK_SLIDE_WIDTH = 1000\nconst FALLBACK_SLIDE_HEIGHT = 562.5\nconst LOGO_MARGIN_X = 24\nconst LOGO_MARGIN_Y = 18\nconst LOGO_MAX_WIDTH_RATIO = 0.34\nconst LOGO_MAX_HEIGHT_RATIO = 0.16\nconst DEFAULT_LOGO_ASPECT_RATIO = 3.2\n\nfunction mapSlideTypeToScopeKey (type?: string): SlideScopeKey {\n const normalized = type?.trim().toLowerCase()\n if (!normalized) return null\n\n if (normalized === 'cover') return 'cover'\n if (normalized === 'contents' || normalized === 'agenda') return 'contents'\n if (normalized === 'transition' || normalized === 'section') return 'transition'\n if (normalized === 'content') return 'content'\n if (normalized === 'end' || normalized === 'ending') return 'end'\n\n return null\n}\n\nfunction isSlideInScope (slide: Slide, scope: ThemeScope): boolean {\n const key = mapSlideTypeToScopeKey(slide.type)\n if (!key) return false\n return Boolean(scope[key])\n}\n\nfunction createElementId (\n prefix: MediaElementType,\n slideIndex: number\n): string {\n const random = Math.random().toString(36).slice(2, 10)\n return `${prefix}-${slideIndex}-${random}`\n}\n\nfunction toHalfOpacityColor (value: string): string {\n const rgb = parseColorToRgb(value)\n if (!rgb) return value\n return `rgba(${rgb.r},${rgb.g},${rgb.b},0.5)`\n}\n\nfunction buildBackgroundElement (input: BackgroundElementInput): SlideElement {\n const { src, slideWidth, slideHeight, slideIndex } = input\n return {\n type: 'image',\n id: createElementId('background', slideIndex),\n src,\n width: slideWidth,\n height: slideHeight,\n left: 0,\n top: 0,\n fixedRatio: true,\n rotate: 0,\n imageType: 'background',\n filters: {\n opacity: '100%'\n }\n }\n}\n\nfunction resolveLogoAspectRatio (\n width?: number,\n height?: number\n): number {\n if (\n typeof width === 'number' &&\n typeof height === 'number' &&\n width > 0 &&\n height > 0\n ) {\n return width / height\n }\n return DEFAULT_LOGO_ASPECT_RATIO\n}\n\nfunction resolveLogoSize (input: LogoElementInput): LogoSize {\n const {\n slideWidth,\n slideHeight,\n logoWidth,\n logoHeight\n } = input\n\n const aspectRatio = resolveLogoAspectRatio(logoWidth, logoHeight)\n const maxWidth = slideWidth * LOGO_MAX_WIDTH_RATIO\n const maxHeight = slideHeight * LOGO_MAX_HEIGHT_RATIO\n let width = maxWidth\n let height = width / aspectRatio\n\n if (height > maxHeight) {\n height = maxHeight\n width = height * aspectRatio\n }\n\n return { width, height }\n}\n\nfunction buildLogoElement (input: LogoElementInput): SlideElement {\n const { src, slideWidth, slideIndex, position } = input\n const { width, height } = resolveLogoSize(input)\n\n const left =\n position === 'left'\n ? LOGO_MARGIN_X\n : Math.max(LOGO_MARGIN_X, slideWidth - width - LOGO_MARGIN_X)\n\n return {\n type: 'image',\n id: createElementId('logo', slideIndex),\n src,\n width,\n height,\n left,\n top: LOGO_MARGIN_Y,\n fixedRatio: true,\n rotate: 0,\n imageType: 'logo'\n }\n}\n\nexport function replaceScopedMedia (\n deck: Presentation,\n input: PptxCustomThemeInput\n): Presentation {\n if (!deck.slides?.length) return deck\n\n const slideWidth = deck.width ?? FALLBACK_SLIDE_WIDTH\n const slideHeight = deck.height ?? FALLBACK_SLIDE_HEIGHT\n const backgroundInput = input.backgroundImage\n const logoInput = input.logoImage\n const shouldClearBackground = Boolean(input.clearBackgroundImage)\n const shouldClearLogo = Boolean(input.clearLogoImage || shouldClearBackground)\n\n if (\n !backgroundInput?.src &&\n !logoInput?.src &&\n !shouldClearBackground &&\n !shouldClearLogo\n ) {\n return deck\n }\n\n const slides = deck.slides.map((slide, slideIndex) => {\n let nextElements = slide.elements ? [...slide.elements] : []\n let nextBackground = slide.background\n let changed = false\n\n if (shouldClearBackground) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n if (nextElements.length !== before) {\n changed = true\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: input.backgroundColor\n }\n }\n }\n }\n\n if (shouldClearLogo) {\n const before = nextElements.length\n nextElements = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n if (nextElements.length !== before) {\n changed = true\n }\n }\n\n if (backgroundInput?.src && isSlideInScope(slide, backgroundInput.scope)) {\n const withoutBackground = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'background')\n )\n nextElements = [\n buildBackgroundElement({\n src: backgroundInput.src,\n slideWidth,\n slideHeight,\n slideIndex\n }),\n ...withoutBackground\n ]\n changed = true\n\n if (input.backgroundColor) {\n nextBackground = {\n ...(nextBackground ?? {}),\n type: 'solid',\n color: toHalfOpacityColor(input.backgroundColor)\n }\n }\n }\n\n if (logoInput?.src && isSlideInScope(slide, logoInput.scope)) {\n const withoutLogo = nextElements.filter(\n element => !(element.type === 'image' && element.imageType === 'logo')\n )\n nextElements = [\n ...withoutLogo,\n buildLogoElement({\n src: logoInput.src,\n slideWidth,\n slideHeight,\n slideIndex,\n position: logoInput.position,\n logoWidth: logoInput.width,\n logoHeight: logoInput.height\n })\n ]\n changed = true\n }\n\n if (!changed && nextBackground === slide.background) return slide\n\n return {\n ...slide,\n ...(changed ? { elements: nextElements } : {}),\n ...(nextBackground ? { background: nextBackground } : {})\n }\n })\n\n return { ...deck, slides }\n}\n","import { normalizeHexColor, parseColorToRgb } from './color-utils'\nimport type { ColorMapping } from './types'\n\nexport function buildColorMappings (\n previous: string[],\n next: string[]\n): ColorMapping[] {\n const mappings: ColorMapping[] = []\n const length = Math.min(previous.length, next.length)\n for (let i = 0; i < length; i += 1) {\n const fromParsed = parseColorToRgb(previous[i])\n const toParsed = parseColorToRgb(next[i])\n if (!fromParsed || !toParsed) continue\n const toHex = normalizeHexColor(next[i]) ?? undefined\n mappings.push({\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n })\n }\n return mappings\n}\n\nexport function buildSingleMapping (\n from?: string,\n to?: string\n): ColorMapping | null {\n if (!from || !to) return null\n const fromParsed = parseColorToRgb(from)\n const toParsed = parseColorToRgb(to)\n if (!fromParsed || !toParsed) return null\n const toHex = normalizeHexColor(to) ?? undefined\n return {\n fromRgb: { r: fromParsed.r, g: fromParsed.g, b: fromParsed.b },\n toRgb: { r: toParsed.r, g: toParsed.g, b: toParsed.b },\n toHex\n }\n}\n","import type { Slide, SlideElement } from '../types'\nimport {\n findMappingForColor,\n isPureColorString,\n normalizeThemeColor,\n parseColorToRgb,\n rgbToString\n} from './color-utils'\nimport type { ColorMapping } from './types'\n\nfunction applyColorToStyleAttribute (\n styles: string,\n color: string\n): string {\n const declarations = styles\n .split(';')\n .map(item => item.trim())\n .filter(Boolean)\n\n let updated = false\n const nextDeclarations = declarations.map((declaration) => {\n const separatorIndex = declaration.indexOf(':')\n if (separatorIndex < 0) return declaration\n\n const property = declaration.slice(0, separatorIndex).trim().toLowerCase()\n if (property !== 'color') return declaration\n\n updated = true\n return `color: ${color}`\n })\n\n if (!updated) {\n nextDeclarations.push(`color: ${color}`)\n }\n\n return nextDeclarations.join('; ')\n}\n\nfunction applyFontColorToHtml (value: string, fontColor: string): string {\n if (!value || !fontColor) return value\n const normalized = normalizeThemeColor(fontColor) ?? fontColor\n\n return value.replace(\n /(<[^>]+style\\s*=\\s*[\"'])([^\"']*)([\"'])/gi,\n (_match, start, styles, end): string => {\n const nextStyles = applyColorToStyleAttribute(styles, normalized)\n return `${start}${nextStyles}${end}`\n }\n )\n}\n\nfunction replaceColorValue (value: string, mappings: ColorMapping[]): string {\n const mapping = findMappingForColor(value, mappings)\n if (!mapping) return value\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n if (parsed.alpha !== undefined) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceRgbaString (value: string, mappings: ColorMapping[]): string {\n const parsed = parseColorToRgb(value)\n if (!parsed) return value\n const mapping = mappings.find(\n (item) =>\n item.fromRgb.r === parsed.r &&\n item.fromRgb.g === parsed.g &&\n item.fromRgb.b === parsed.b\n )\n if (!mapping) return value\n if (parsed.alpha !== undefined || value.toLowerCase().startsWith('rgba')) {\n return `rgba(${mapping.toRgb.r},${mapping.toRgb.g},${mapping.toRgb.b},${parsed.alpha ?? 1})`\n }\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n}\n\nfunction replaceColorsInText (value: string, mappings: ColorMapping[]): string {\n let next = value\n next = next.replace(/#([0-9a-f]{3}|[0-9a-f]{6})/gi, (match) => {\n const mapping = findMappingForColor(match, mappings)\n if (!mapping) return match\n return mapping.toHex ?? rgbToString(mapping.toRgb)\n })\n next = next.replace(/rgba?\\([^)]*\\)/gi, (match) =>\n replaceRgbaString(match, mappings)\n )\n return next\n}\n\nfunction replaceColorsDeep (value: unknown, mappings: ColorMapping[]): unknown {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n const pureColor = isPureColorString(trimmed)\n if (pureColor) {\n const replaced = replaceColorValue(trimmed, mappings)\n return value === trimmed ? replaced : value.replace(trimmed, replaced)\n }\n return replaceColorsInText(value, mappings)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => replaceColorsDeep(item, mappings))\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n const next: Record<string, unknown> = {}\n for (const [key, item] of entries) {\n next[key] = replaceColorsDeep(item, mappings)\n }\n return next\n }\n\n return value\n}\n\nfunction replaceTextElementColors (\n element: SlideElement,\n fontMappings: ColorMapping[],\n fontColor: string\n): SlideElement {\n const next = replaceColorsDeep(element, fontMappings) as SlideElement\n const normalizedFontColor = normalizeThemeColor(fontColor) ?? fontColor\n const withDefault =\n normalizedFontColor && 'defaultColor' in next\n ? { ...next, defaultColor: normalizedFontColor }\n : next\n if (!('content' in withDefault) || typeof withDefault.content !== 'string') {\n return withDefault\n }\n return {\n ...withDefault,\n content: applyFontColorToHtml(withDefault.content, normalizedFontColor)\n }\n}\n\nexport function replaceSlideColors (\n slide: Slide,\n themeMappings: ColorMapping[],\n fontMappings: ColorMapping[],\n fontColor: string\n): Slide {\n const { elements, ...rest } = slide\n const nextSlide = replaceColorsDeep(rest, themeMappings) as Slide\n if (!elements) return nextSlide\n\n const nextElements: SlideElement[] = elements.map((element) => {\n if (element && typeof element === 'object' && element.type === 'text') {\n return replaceTextElementColors(element, fontMappings, fontColor)\n }\n return replaceColorsDeep(element, themeMappings) as SlideElement\n })\n\n return { ...nextSlide, elements: nextElements }\n}\n","import type { Presentation, PptxCustomThemeInput } from '../types'\nimport { colorsEqual, isWhiteColor } from './color-utils'\nimport { buildColorMappings, buildSingleMapping } from './mappings'\nimport { replaceSlideColors } from './replacers'\n\ntype SolidBackground = Extract<NonNullable<Presentation['slides']>[number]['background'], { type: 'solid' }>\n\nexport function applyTheme2Json (deck: Presentation, update: PptxCustomThemeInput): Presentation {\n const previousTheme = deck.theme ?? {}\n const themeColors = update.themeColors.slice(0, 6)\n const themeMappings = buildColorMappings(\n previousTheme.themeColors ?? [],\n themeColors\n )\n const fontMapping = buildSingleMapping(\n previousTheme.fontColor,\n update.fontColor\n )\n const fontMappings = fontMapping ? [fontMapping] : []\n\n const nextBackground = update.backgroundColor ?? previousTheme.backgroundColor\n const prevBackground = previousTheme.backgroundColor\n const slides = deck.slides?.map((slide) => {\n const nextSlide = replaceSlideColors(\n slide,\n themeMappings,\n fontMappings,\n update.fontColor\n )\n if (!nextBackground) return nextSlide\n const currentColor =\n nextSlide.background?.type === 'solid' ? nextSlide.background.color : undefined\n const shouldUpdate =\n !currentColor ||\n (prevBackground && colorsEqual(currentColor, prevBackground)) ||\n (!prevBackground && isWhiteColor(currentColor))\n if (!shouldUpdate) return nextSlide\n return {\n ...nextSlide,\n background: createSolidBackground(nextBackground)\n }\n })\n\n return {\n ...deck,\n theme: {\n ...previousTheme,\n themeColors,\n fontColor: update.fontColor,\n backgroundColor: update.backgroundColor ?? previousTheme.backgroundColor\n },\n slides\n }\n}\n\nfunction createSolidBackground (color: string): SolidBackground {\n return {\n type: 'solid',\n color\n }\n}\n"],"mappings":"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","names":["parseDocument","r","g","b","FALLBACK_SLIDE_WIDTH","FALLBACK_SLIDE_HEIGHT","LOGO_MARGIN_X","LOGO_MARGIN_Y","LOGO_MAX_WIDTH_RATIO","LOGO_MAX_HEIGHT_RATIO","parseDocument"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptx-custom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Custom content and theme utilities for PPTX JSON templates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"prepublishOnly": "pnpm run build"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"json2pptx-schema": "
|
|
41
|
+
"json2pptx-schema": "workspace:*"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsup": "^8.5.1",
|
|
45
45
|
"typescript": "^5.6.3"
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
}
|