@json-to-office/core-pptx 0.25.0 → 0.27.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,60 @@
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 → doc-named built-in → constructor theme object →
33
+ * built-in); omit it to use customThemes → built-in. `authored` is true
34
+ * when the name came from the document's own `props.theme` (as opposed to
35
+ * `defaultThemeName` or the 'default' fallback), so the lookup can honor
36
+ * an explicitly doc-named built-in without the constructor object
37
+ * swallowing the default name too (#141).
38
+ */
39
+ resolveNamedTheme?: (name: string, authored: boolean) => PptxThemeConfig;
40
+ }
41
+ export interface GenerationThemeContext {
42
+ /**
43
+ * The document after the export-mode pre-pass rewrote font references.
44
+ * `props.theme` stays as authored (name or inline object) — callers hand
45
+ * `theme` to `processPresentation` by value instead of round-tripping it
46
+ * through a name lookup (#135).
47
+ */
48
+ document: PresentationComponentDefinition;
49
+ theme: PptxThemeConfig;
50
+ /**
51
+ * Cache key: base theme name + export-mode scope. Nothing in PPTX consumes
52
+ * a theme by name after the prologue today; this is the key a future
53
+ * theme-keyed cache must use (a substitute-mode run rewrites the theme in
54
+ * place, so it must never share a slot with a custom-mode run of the same
55
+ * base name — the DOCX layout cache is keyed exactly this way).
56
+ */
57
+ themeName: string;
58
+ }
59
+ export declare function resolveThemeContext(documentIn: PresentationComponentDefinition, options?: ThemeContextOptions): GenerationThemeContext;
60
+ //# 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;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,eAAe,CAAC;CAC1E;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
@@ -214,6 +214,9 @@ var PPTX_THEMES = {
214
214
  function getPptxTheme(name) {
215
215
  return PPTX_THEMES[name] || DEFAULT_PPTX_THEME;
216
216
  }
217
+ function hasPptxTheme(name) {
218
+ return Object.prototype.hasOwnProperty.call(PPTX_THEMES, name);
219
+ }
217
220
  var pptxThemes = PPTX_THEMES;
218
221
 
219
222
  // src/utils/componentDefaults.ts
@@ -387,7 +390,7 @@ function buildSlideIndexMap(children) {
387
390
  }
388
391
  function processPresentation(document, options) {
389
392
  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");
393
+ const baseTheme = options?.theme ?? (typeof props.theme === "object" && props.theme !== null ? props.theme : options?.customThemes?.[props.theme ?? "default"] ?? getPptxTheme(props.theme ?? "default"));
391
394
  const presDefaults = props.componentDefaults;
392
395
  const theme = presDefaults ? {
393
396
  ...baseTheme,
@@ -1913,8 +1916,41 @@ async function resolveDocumentFonts(document, theme, warnings, fonts) {
1913
1916
  return resolved;
1914
1917
  }
1915
1918
 
1916
- // src/core/generator.ts
1919
+ // src/core/generationContext.ts
1917
1920
  import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
1921
+ function resolveThemeContext(documentIn, options = {}) {
1922
+ const { customThemes, fonts, warnings, defaultThemeName, resolveNamedTheme } = options;
1923
+ if (documentIn.props === null) {
1924
+ throw new Error(
1925
+ "Document `props` is null. Omit it, or provide an object \u2014 a null props cannot carry a theme."
1926
+ );
1927
+ }
1928
+ let document = documentIn.props === void 0 ? { ...documentIn, props: {} } : documentIn;
1929
+ let inlineTheme;
1930
+ if (typeof document.props.theme === "object" && document.props.theme !== null) {
1931
+ inlineTheme = document.props.theme;
1932
+ }
1933
+ const authoredThemeName = typeof document.props.theme === "string" ? document.props.theme : void 0;
1934
+ const baseThemeName = inlineTheme ? inlineTheme.name || "inline-theme" : authoredThemeName ?? defaultThemeName ?? "default";
1935
+ let theme = inlineTheme ?? (resolveNamedTheme ? resolveNamedTheme(baseThemeName, authoredThemeName !== void 0) : customThemes?.[baseThemeName] ?? getPptxTheme(baseThemeName));
1936
+ const mode = applyExportMode({ doc: document, theme, fonts });
1937
+ document = mode.doc;
1938
+ theme = mode.theme;
1939
+ for (const w of mode.warnings) {
1940
+ warnings?.push({
1941
+ code: w.code,
1942
+ message: w.message,
1943
+ component: "fontRegistry"
1944
+ });
1945
+ }
1946
+ return {
1947
+ document,
1948
+ theme,
1949
+ themeName: scopedThemeName(baseThemeName, fonts?.mode)
1950
+ };
1951
+ }
1952
+
1953
+ // src/core/generator.ts
1918
1954
  import {
1919
1955
  collectImageSourceConflicts,
1920
1956
  collectTextContentConflicts,
@@ -2093,16 +2129,7 @@ function assertValidPresentation(input, validation) {
2093
2129
  throw new PresentationValidationError(result.errors);
2094
2130
  }
2095
2131
  }
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
- }
2132
+ function assertNoContentConflicts(document) {
2106
2133
  const sourceConflicts = [
2107
2134
  ...collectImageSourceConflicts(document),
2108
2135
  ...collectTextContentConflicts(document)
@@ -2113,6 +2140,18 @@ async function generatePresentation(document, options, warnings, pendingFills) {
2113
2140
  ${sourceConflicts.map((e) => ` - ${e.path}: ${e.message}`).join("\n")}`
2114
2141
  );
2115
2142
  }
2143
+ }
2144
+ function isPresentationComponentDefinition(definition) {
2145
+ if (typeof definition !== "object" || definition === null) return false;
2146
+ const def = definition;
2147
+ return def.name === "pptx" && "props" in def;
2148
+ }
2149
+ async function generatePresentation(document, options, warnings, pendingFills) {
2150
+ assertValidPresentation(document, options?.validation);
2151
+ if (!document || document.name !== "pptx") {
2152
+ throw new Error("Top-level component must be a pptx component");
2153
+ }
2154
+ assertNoContentConflicts(document);
2116
2155
  const processed = processPresentation(document, options);
2117
2156
  return await renderPresentation(processed, warnings, pendingFills);
2118
2157
  }
@@ -2133,56 +2172,21 @@ async function generateBufferWithWarnings(jsonConfig, options) {
2133
2172
  component = jsonConfig;
2134
2173
  }
2135
2174
  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
2175
+ const context = resolveThemeContext(component, {
2176
+ customThemes: options?.customThemes,
2177
+ fonts: options?.fonts,
2178
+ warnings
2157
2179
  });
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
- }
2180
+ component = context.document;
2167
2181
  await resolveDocumentFonts(
2168
2182
  component,
2169
- resolvedTheme,
2183
+ context.theme,
2170
2184
  warnings,
2171
2185
  options?.fonts
2172
2186
  );
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
2187
  const effectiveOptions = {
2181
2188
  ...options,
2182
- customThemes: {
2183
- ...options?.customThemes ?? {},
2184
- [themeName]: resolvedTheme
2185
- }
2189
+ theme: context.theme
2186
2190
  };
2187
2191
  const pendingFills = [];
2188
2192
  const pptx = await generatePresentation(
@@ -2350,7 +2354,6 @@ async function exportPluginSchema(customComponents, outputPath, options = {}) {
2350
2354
  }
2351
2355
 
2352
2356
  // src/plugin/createPresentationGenerator.ts
2353
- import { applyExportMode as applyExportMode2, scopedThemeName as scopedThemeName2 } from "@json-to-office/shared";
2354
2357
  function createBuilderImpl(state) {
2355
2358
  const componentMap = new Map(state.components.map((c) => [c.name, c]));
2356
2359
  async function processSlideComponents(components, warningsCollector, theme, validateEmitted, parentName, depth = 0) {
@@ -2494,41 +2497,23 @@ function createBuilderImpl(state) {
2494
2497
  } else if (!internalDocument || internalDocument.name !== "pptx") {
2495
2498
  throw new Error("Top-level component must be a pptx component");
2496
2499
  }
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
2500
  const warnings = [];
2512
- const mode = applyExportMode2({
2513
- doc: internalDocument,
2514
- theme: resolvedTheme,
2515
- fonts: state.fonts
2501
+ const context = resolveThemeContext(internalDocument, {
2502
+ customThemes: state.customThemes,
2503
+ fonts: state.fonts,
2504
+ warnings,
2505
+ defaultThemeName: typeof state.theme === "string" ? state.theme : void 0,
2506
+ resolveNamedTheme: (name, authored) => state.customThemes?.[name] ?? (authored && hasPptxTheme(name) ? getPptxTheme(name) : void 0) ?? (typeof state.theme === "object" && state.theme !== null ? state.theme : getPptxTheme(name))
2516
2507
  });
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
- }
2508
+ const modedRoot = context.document;
2509
+ const resolvedTheme = context.theme;
2525
2510
  const validateEmitted = validationOptions.enabled === false ? void 0 : (emitted, componentLabel, parentName) => {
2526
2511
  let validationDocument;
2527
2512
  if (parentName === "pptx") {
2528
- validationDocument = { ...mode.doc, children: emitted };
2513
+ validationDocument = { ...modedRoot, children: emitted };
2529
2514
  } else if (parentName === "slide") {
2530
2515
  validationDocument = {
2531
- ...mode.doc,
2516
+ ...modedRoot,
2532
2517
  children: [{ name: "slide", props: {}, children: emitted }]
2533
2518
  };
2534
2519
  } else {
@@ -2549,19 +2534,16 @@ function createBuilderImpl(state) {
2549
2534
  );
2550
2535
  }
2551
2536
  };
2552
- const processedChildren = mode.doc.children ? await processAllSlides(
2553
- mode.doc.children,
2537
+ const processedChildren = modedRoot.children ? await processAllSlides(
2538
+ modedRoot.children,
2554
2539
  warnings,
2555
2540
  resolvedTheme,
2556
2541
  validateEmitted
2557
2542
  ) : [];
2558
- const themeName = scopedThemeName2(baseThemeName, state.fonts?.mode);
2559
- const docWithScopedTheme = themeName !== baseThemeName ? {
2560
- ...mode.doc,
2561
- props: { ...mode.doc.props, theme: themeName },
2543
+ const processedDocument = {
2544
+ ...modedRoot,
2562
2545
  children: processedChildren
2563
- } : { ...mode.doc, children: processedChildren };
2564
- const processedDocument = docWithScopedTheme;
2546
+ };
2565
2547
  if (validationOptions.enabled !== false) {
2566
2548
  const result = validatePresentation(processedDocument, [], {
2567
2549
  allowUnknownFields: validationOptions.allowUnknownFields
@@ -2582,12 +2564,9 @@ function createBuilderImpl(state) {
2582
2564
  warnings,
2583
2565
  state.fonts
2584
2566
  );
2585
- const effectiveCustomThemes = {
2586
- ...state.customThemes ?? {},
2587
- [themeName]: resolvedTheme
2588
- };
2567
+ assertNoContentConflicts(processedDocument);
2589
2568
  const processed = processPresentation(processedDocument, {
2590
- customThemes: effectiveCustomThemes,
2569
+ theme: resolvedTheme,
2591
2570
  services: state.services
2592
2571
  });
2593
2572
  const pendingFills = [];