@json-to-office/core-pptx 0.25.0 → 0.26.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.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Shared generation prologue.
3
+ *
4
+ * Both entry points — `generateBufferWithWarnings` (core) and
5
+ * `createPresentationGenerator` (plugin) — must resolve the same theme, run
6
+ * the same export-mode pre-pass, and derive the same cache key before slide
7
+ * processing runs. Keeping two copies of that is how DOCX silently dropped a
8
+ * root-level prop from one path (#133); this module is the single definition
9
+ * so the next root-level prop cannot diverge (#134). Mirrors
10
+ * core-docx/src/core/generationContext.ts.
11
+ *
12
+ * The prologue deliberately stops before font resolution: the core path
13
+ * resolves fonts straight after this, while the plugin path must first expand
14
+ * custom components (which can introduce new families). The export-mode
15
+ * pre-pass runs here, BEFORE expansion, so custom components reading
16
+ * `theme.fonts.*` during render see substituted names, not the original
17
+ * non-safe ones.
18
+ */
19
+ import type { PresentationComponentDefinition, PptxThemeConfig, PipelineWarning } from '../types';
20
+ import type { FontRuntimeOpts } from '@json-to-office/shared';
21
+ export interface ThemeContextOptions {
22
+ customThemes?: Record<string, PptxThemeConfig>;
23
+ fonts?: FontRuntimeOpts;
24
+ warnings?: PipelineWarning[];
25
+ /**
26
+ * Base theme name when the document doesn't name one. The plugin builder
27
+ * passes its constructor-supplied string theme; defaults to 'default'.
28
+ */
29
+ defaultThemeName?: string;
30
+ /**
31
+ * Theme lookup for the base `props.theme` name. The plugin builder passes
32
+ * its own (customThemes → constructor theme object → built-in); omit it to
33
+ * use customThemes → built-in.
34
+ */
35
+ resolveNamedTheme?: (name: string) => PptxThemeConfig;
36
+ }
37
+ export interface GenerationThemeContext {
38
+ /**
39
+ * The document after the export-mode pre-pass rewrote font references.
40
+ * `props.theme` stays as authored (name or inline object) — callers hand
41
+ * `theme` to `processPresentation` by value instead of round-tripping it
42
+ * through a name lookup (#135).
43
+ */
44
+ document: PresentationComponentDefinition;
45
+ theme: PptxThemeConfig;
46
+ /**
47
+ * Cache key: base theme name + export-mode scope. Nothing in PPTX consumes
48
+ * a theme by name after the prologue today; this is the key a future
49
+ * theme-keyed cache must use (a substitute-mode run rewrites the theme in
50
+ * place, so it must never share a slot with a custom-mode run of the same
51
+ * base name — the DOCX layout cache is keyed exactly this way).
52
+ */
53
+ themeName: string;
54
+ }
55
+ export declare function resolveThemeContext(documentIn: PresentationComponentDefinition, options?: ThemeContextOptions): GenerationThemeContext;
56
+ //# sourceMappingURL=generationContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generationContext.d.ts","sourceRoot":"","sources":["../../src/core/generationContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,eAAe,EAChB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;CACvD;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,QAAQ,EAAE,+BAA+B,CAAC;IAC1C,KAAK,EAAE,eAAe,CAAC;IACvB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,+BAA+B,EAC3C,OAAO,GAAE,mBAAwB,GAChC,sBAAsB,CA6DxB"}
@@ -19,6 +19,12 @@ export interface GenerationValidationOptions {
19
19
  */
20
20
  export interface GenerationOptions extends PresentationPackagingOptions {
21
21
  customThemes?: Record<string, PptxThemeConfig>;
22
+ /**
23
+ * Fully resolved theme, set by the generation prologue after the
24
+ * export-mode pre-pass. Wins over the `props.theme` name/inline lookup in
25
+ * `processPresentation` — omit it (direct callers) to fall back to that.
26
+ */
27
+ theme?: PptxThemeConfig;
22
28
  services?: ServicesConfig;
23
29
  fonts?: FontRuntimeOpts;
24
30
  validation?: GenerationValidationOptions;
@@ -35,6 +41,19 @@ export declare class PresentationValidationError extends Error {
35
41
  readonly errors: ValidationError[];
36
42
  constructor(errors: ValidationError[]);
37
43
  }
44
+ /**
45
+ * Structural rules the per-component schema can't express: image sources
46
+ * (path/base64/svg) are mutually exclusive, and text components carry
47
+ * exactly one of text/runs. Reject conflicting payloads before rendering so
48
+ * they can't be silently resolved by runtime precedence. Matches core-docx,
49
+ * which fails generation on the same image conflict.
50
+ *
51
+ * Runs unconditionally — the validators also collect these conflicts, so this
52
+ * is the net for `validation: { enabled: false }`. Shared with the plugin
53
+ * path, which checks the expanded tree (custom components can emit
54
+ * conflicting payloads too).
55
+ */
56
+ export declare function assertNoContentConflicts(document: unknown): void;
38
57
  /**
39
58
  * Type guard for presentation component
40
59
  */
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,eAAe,EACf,cAAc,EACf,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAM9E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,4BAA4B;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;CAC1C;AAID;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;gBAE9B,MAAM,EAAE,eAAe,EAAE;CAStC;AAqBD;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,+BAA+B,CAI/C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,YAAY,CAAC,EAAE,cAAc,EAAE,GAC9B,OAAO,CAAC,SAAS,CAAC,CA0BpB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAqG3B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAC"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,eAAe,EACf,cAAc,EACf,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,4BAA4B;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;CAC1C;AAID;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;gBAE9B,MAAM,EAAE,eAAe,EAAE;CAStC;AAqBD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAYhE;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,+BAA+B,CAI/C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,YAAY,CAAC,EAAE,cAAc,EAAE,GAC9B,OAAO,CAAC,SAAS,CAAC,CAWpB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/core/structure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAGV,+BAA+B,EAC/B,qBAAqB,EAGtB,MAAM,UAAU,CAAC;AAQlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAmCrD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,qBAAqB,CAmJvB"}
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/core/structure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAGV,+BAA+B,EAC/B,qBAAqB,EAGtB,MAAM,UAAU,CAAC;AAQlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAmCrD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,qBAAqB,CAuJvB"}
package/dist/index.js CHANGED
@@ -387,7 +387,7 @@ function buildSlideIndexMap(children) {
387
387
  }
388
388
  function processPresentation(document, options) {
389
389
  const { props, children = [] } = document;
390
- const baseTheme = typeof props.theme === "object" && props.theme !== null ? props.theme : options?.customThemes?.[props.theme ?? "default"] ?? getPptxTheme(props.theme ?? "default");
390
+ const baseTheme = options?.theme ?? (typeof props.theme === "object" && props.theme !== null ? props.theme : options?.customThemes?.[props.theme ?? "default"] ?? getPptxTheme(props.theme ?? "default"));
391
391
  const presDefaults = props.componentDefaults;
392
392
  const theme = presDefaults ? {
393
393
  ...baseTheme,
@@ -1913,8 +1913,40 @@ async function resolveDocumentFonts(document, theme, warnings, fonts) {
1913
1913
  return resolved;
1914
1914
  }
1915
1915
 
1916
- // src/core/generator.ts
1916
+ // src/core/generationContext.ts
1917
1917
  import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
1918
+ function resolveThemeContext(documentIn, options = {}) {
1919
+ const { customThemes, fonts, warnings, defaultThemeName, resolveNamedTheme } = options;
1920
+ if (documentIn.props === null) {
1921
+ throw new Error(
1922
+ "Document `props` is null. Omit it, or provide an object \u2014 a null props cannot carry a theme."
1923
+ );
1924
+ }
1925
+ let document = documentIn.props === void 0 ? { ...documentIn, props: {} } : documentIn;
1926
+ let inlineTheme;
1927
+ if (typeof document.props.theme === "object" && document.props.theme !== null) {
1928
+ inlineTheme = document.props.theme;
1929
+ }
1930
+ const baseThemeName = inlineTheme ? inlineTheme.name || "inline-theme" : document.props.theme ?? defaultThemeName ?? "default";
1931
+ let theme = inlineTheme ?? (resolveNamedTheme ? resolveNamedTheme(baseThemeName) : customThemes?.[baseThemeName] ?? getPptxTheme(baseThemeName));
1932
+ const mode = applyExportMode({ doc: document, theme, fonts });
1933
+ document = mode.doc;
1934
+ theme = mode.theme;
1935
+ for (const w of mode.warnings) {
1936
+ warnings?.push({
1937
+ code: w.code,
1938
+ message: w.message,
1939
+ component: "fontRegistry"
1940
+ });
1941
+ }
1942
+ return {
1943
+ document,
1944
+ theme,
1945
+ themeName: scopedThemeName(baseThemeName, fonts?.mode)
1946
+ };
1947
+ }
1948
+
1949
+ // src/core/generator.ts
1918
1950
  import {
1919
1951
  collectImageSourceConflicts,
1920
1952
  collectTextContentConflicts,
@@ -2093,16 +2125,7 @@ function assertValidPresentation(input, validation) {
2093
2125
  throw new PresentationValidationError(result.errors);
2094
2126
  }
2095
2127
  }
2096
- function isPresentationComponentDefinition(definition) {
2097
- if (typeof definition !== "object" || definition === null) return false;
2098
- const def = definition;
2099
- return def.name === "pptx" && "props" in def;
2100
- }
2101
- async function generatePresentation(document, options, warnings, pendingFills) {
2102
- assertValidPresentation(document, options?.validation);
2103
- if (!document || document.name !== "pptx") {
2104
- throw new Error("Top-level component must be a pptx component");
2105
- }
2128
+ function assertNoContentConflicts(document) {
2106
2129
  const sourceConflicts = [
2107
2130
  ...collectImageSourceConflicts(document),
2108
2131
  ...collectTextContentConflicts(document)
@@ -2113,6 +2136,18 @@ async function generatePresentation(document, options, warnings, pendingFills) {
2113
2136
  ${sourceConflicts.map((e) => ` - ${e.path}: ${e.message}`).join("\n")}`
2114
2137
  );
2115
2138
  }
2139
+ }
2140
+ function isPresentationComponentDefinition(definition) {
2141
+ if (typeof definition !== "object" || definition === null) return false;
2142
+ const def = definition;
2143
+ return def.name === "pptx" && "props" in def;
2144
+ }
2145
+ async function generatePresentation(document, options, warnings, pendingFills) {
2146
+ assertValidPresentation(document, options?.validation);
2147
+ if (!document || document.name !== "pptx") {
2148
+ throw new Error("Top-level component must be a pptx component");
2149
+ }
2150
+ assertNoContentConflicts(document);
2116
2151
  const processed = processPresentation(document, options);
2117
2152
  return await renderPresentation(processed, warnings, pendingFills);
2118
2153
  }
@@ -2133,56 +2168,21 @@ async function generateBufferWithWarnings(jsonConfig, options) {
2133
2168
  component = jsonConfig;
2134
2169
  }
2135
2170
  const warnings = [];
2136
- if (typeof component.props?.theme === "object" && component.props.theme !== null) {
2137
- const inlineTheme = component.props.theme;
2138
- const inlineName = inlineTheme.name || "inline-theme";
2139
- component = {
2140
- ...component,
2141
- props: { ...component.props, theme: inlineName }
2142
- };
2143
- options = {
2144
- ...options,
2145
- customThemes: {
2146
- ...options?.customThemes ?? {},
2147
- [inlineName]: inlineTheme
2148
- }
2149
- };
2150
- }
2151
- const baseThemeName = component.props?.theme ?? "default";
2152
- let resolvedTheme = options?.customThemes?.[baseThemeName] ?? getPptxTheme(baseThemeName);
2153
- const mode = applyExportMode({
2154
- doc: component,
2155
- theme: resolvedTheme,
2156
- fonts: options?.fonts
2171
+ const context = resolveThemeContext(component, {
2172
+ customThemes: options?.customThemes,
2173
+ fonts: options?.fonts,
2174
+ warnings
2157
2175
  });
2158
- component = mode.doc;
2159
- resolvedTheme = mode.theme;
2160
- for (const w of mode.warnings) {
2161
- warnings.push({
2162
- code: w.code,
2163
- message: w.message,
2164
- component: "fontRegistry"
2165
- });
2166
- }
2176
+ component = context.document;
2167
2177
  await resolveDocumentFonts(
2168
2178
  component,
2169
- resolvedTheme,
2179
+ context.theme,
2170
2180
  warnings,
2171
2181
  options?.fonts
2172
2182
  );
2173
- const themeName = scopedThemeName(baseThemeName, options?.fonts?.mode);
2174
- if (themeName !== baseThemeName) {
2175
- component = {
2176
- ...component,
2177
- props: { ...component.props, theme: themeName }
2178
- };
2179
- }
2180
2183
  const effectiveOptions = {
2181
2184
  ...options,
2182
- customThemes: {
2183
- ...options?.customThemes ?? {},
2184
- [themeName]: resolvedTheme
2185
- }
2185
+ theme: context.theme
2186
2186
  };
2187
2187
  const pendingFills = [];
2188
2188
  const pptx = await generatePresentation(
@@ -2350,7 +2350,6 @@ async function exportPluginSchema(customComponents, outputPath, options = {}) {
2350
2350
  }
2351
2351
 
2352
2352
  // src/plugin/createPresentationGenerator.ts
2353
- import { applyExportMode as applyExportMode2, scopedThemeName as scopedThemeName2 } from "@json-to-office/shared";
2354
2353
  function createBuilderImpl(state) {
2355
2354
  const componentMap = new Map(state.components.map((c) => [c.name, c]));
2356
2355
  async function processSlideComponents(components, warningsCollector, theme, validateEmitted, parentName, depth = 0) {
@@ -2494,41 +2493,23 @@ function createBuilderImpl(state) {
2494
2493
  } else if (!internalDocument || internalDocument.name !== "pptx") {
2495
2494
  throw new Error("Top-level component must be a pptx component");
2496
2495
  }
2497
- let inlineTheme;
2498
- if (typeof internalDocument.props.theme === "object" && internalDocument.props.theme !== null) {
2499
- inlineTheme = internalDocument.props.theme;
2500
- internalDocument = {
2501
- ...internalDocument,
2502
- props: {
2503
- ...internalDocument.props,
2504
- theme: inlineTheme.name || "inline-theme"
2505
- }
2506
- };
2507
- }
2508
- const docThemeName = internalDocument.props.theme;
2509
- const baseThemeName = docThemeName ?? (typeof state.theme === "string" ? state.theme : "default");
2510
- let resolvedTheme = inlineTheme ?? state.customThemes?.[baseThemeName] ?? (typeof state.theme === "object" && state.theme !== null ? state.theme : getPptxTheme(baseThemeName));
2511
2496
  const warnings = [];
2512
- const mode = applyExportMode2({
2513
- doc: internalDocument,
2514
- theme: resolvedTheme,
2515
- fonts: state.fonts
2497
+ const context = resolveThemeContext(internalDocument, {
2498
+ customThemes: state.customThemes,
2499
+ fonts: state.fonts,
2500
+ warnings,
2501
+ defaultThemeName: typeof state.theme === "string" ? state.theme : void 0,
2502
+ resolveNamedTheme: (name) => state.customThemes?.[name] ?? (typeof state.theme === "object" && state.theme !== null ? state.theme : getPptxTheme(name))
2516
2503
  });
2517
- resolvedTheme = mode.theme;
2518
- for (const w of mode.warnings) {
2519
- warnings.push({
2520
- code: w.code,
2521
- message: w.message,
2522
- component: "fontRegistry"
2523
- });
2524
- }
2504
+ const modedRoot = context.document;
2505
+ const resolvedTheme = context.theme;
2525
2506
  const validateEmitted = validationOptions.enabled === false ? void 0 : (emitted, componentLabel, parentName) => {
2526
2507
  let validationDocument;
2527
2508
  if (parentName === "pptx") {
2528
- validationDocument = { ...mode.doc, children: emitted };
2509
+ validationDocument = { ...modedRoot, children: emitted };
2529
2510
  } else if (parentName === "slide") {
2530
2511
  validationDocument = {
2531
- ...mode.doc,
2512
+ ...modedRoot,
2532
2513
  children: [{ name: "slide", props: {}, children: emitted }]
2533
2514
  };
2534
2515
  } else {
@@ -2549,19 +2530,16 @@ function createBuilderImpl(state) {
2549
2530
  );
2550
2531
  }
2551
2532
  };
2552
- const processedChildren = mode.doc.children ? await processAllSlides(
2553
- mode.doc.children,
2533
+ const processedChildren = modedRoot.children ? await processAllSlides(
2534
+ modedRoot.children,
2554
2535
  warnings,
2555
2536
  resolvedTheme,
2556
2537
  validateEmitted
2557
2538
  ) : [];
2558
- const themeName = scopedThemeName2(baseThemeName, state.fonts?.mode);
2559
- const docWithScopedTheme = themeName !== baseThemeName ? {
2560
- ...mode.doc,
2561
- props: { ...mode.doc.props, theme: themeName },
2539
+ const processedDocument = {
2540
+ ...modedRoot,
2562
2541
  children: processedChildren
2563
- } : { ...mode.doc, children: processedChildren };
2564
- const processedDocument = docWithScopedTheme;
2542
+ };
2565
2543
  if (validationOptions.enabled !== false) {
2566
2544
  const result = validatePresentation(processedDocument, [], {
2567
2545
  allowUnknownFields: validationOptions.allowUnknownFields
@@ -2582,12 +2560,9 @@ function createBuilderImpl(state) {
2582
2560
  warnings,
2583
2561
  state.fonts
2584
2562
  );
2585
- const effectiveCustomThemes = {
2586
- ...state.customThemes ?? {},
2587
- [themeName]: resolvedTheme
2588
- };
2563
+ assertNoContentConflicts(processedDocument);
2589
2564
  const processed = processPresentation(processedDocument, {
2590
- customThemes: effectiveCustomThemes,
2565
+ theme: resolvedTheme,
2591
2566
  services: state.services
2592
2567
  });
2593
2568
  const pendingFills = [];