@json-to-office/core-pptx 0.7.0 → 0.8.4

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.
@@ -12,8 +12,8 @@ interface ImageComponentProps {
12
12
  h?: number | string;
13
13
  sizing?: {
14
14
  type: string;
15
- w?: number;
16
- h?: number;
15
+ w?: number | string;
16
+ h?: number | string;
17
17
  };
18
18
  rotate?: number;
19
19
  rounding?: boolean;
@@ -32,6 +32,6 @@ interface ImageComponentProps {
32
32
  };
33
33
  alt?: string;
34
34
  }
35
- export declare function renderImageComponent(slide: PptxGenJS.Slide, props: ImageComponentProps, theme: PptxThemeConfig, warnings?: PipelineWarning[]): Promise<void>;
35
+ export declare function renderImageComponent(slide: PptxGenJS.Slide, props: ImageComponentProps, theme: PptxThemeConfig, warnings?: PipelineWarning[], slideWidth?: number, slideHeight?: number): Promise<void>;
36
36
  export {};
37
37
  //# sourceMappingURL=image.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/components/image.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA2BjE,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,SAAS,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAqCD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,CAAC,KAAK,EACtB,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,eAAe,EACtB,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CA8Gf"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/components/image.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA8BjE,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,SAAS,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA2DD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,CAAC,KAAK,EACtB,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,eAAe,EACtB,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,UAAU,SAAK,EACf,WAAW,SAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA+Jf"}
@@ -2,13 +2,12 @@
2
2
  * PPTX Component Renderers
3
3
  */
4
4
  import type PptxGenJS from 'pptxgenjs';
5
- import type { PptxThemeConfig, PptxComponentInput, PipelineWarning, SlideContext } from '../types';
6
- import type { ServicesConfig } from '@json-to-office/shared';
5
+ import type { PptxThemeConfig, PptxComponentInput, PipelineWarning, SlideRenderContext } from '../types';
7
6
  export { renderTextComponent } from './text';
8
7
  export { renderImageComponent } from './image';
9
8
  export { renderShapeComponent } from './shape';
10
9
  export { renderTableComponent } from './table';
11
10
  export { renderHighchartsComponent } from './highcharts';
12
11
  export { renderChartComponent } from './chart';
13
- export declare function renderComponent(slide: PptxGenJS.Slide, component: PptxComponentInput, theme: PptxThemeConfig, pptx: PptxGenJS, warnings?: PipelineWarning[], slideCtx?: SlideContext, services?: ServicesConfig): Promise<void>;
12
+ export declare function renderComponent(slide: PptxGenJS.Slide, component: PptxComponentInput, theme: PptxThemeConfig, pptx: PptxGenJS, warnings?: PipelineWarning[], ctx?: SlideRenderContext): Promise<void>;
14
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,YAAY,EACb,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAS7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,CAAC,KAAK,EACtB,SAAS,EAAE,kBAAkB,EAC7B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,SAAS,EACf,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,QAAQ,CAAC,EAAE,YAAY,EACvB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,IAAI,CAAC,CAuCf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EACnB,MAAM,UAAU,CAAC;AASlB,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,CAAC,KAAK,EACtB,SAAS,EAAE,kBAAkB,EAC7B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,SAAS,EACf,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,GAAG,CAAC,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EACV,qBAAqB,EACrB,eAAe,EAEhB,MAAM,UAAU,CAAC;AAOlB,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,qBAAqB,EAChC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,SAAS,CAAC,CAiOpB"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EACV,qBAAqB,EACrB,eAAe,EAGhB,MAAM,UAAU,CAAC;AAUlB,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,qBAAqB,EAChC,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,SAAS,CAAC,CAyOpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/core/structure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAEV,+BAA+B,EAC/B,qBAAqB,EAGtB,MAAM,UAAU,CAAC;AAQlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,qBAAqB,CAyFvB"}
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/core/structure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAEV,+BAA+B,EAC/B,qBAAqB,EAGtB,MAAM,UAAU,CAAC;AAQlB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,qBAAqB,CA6GvB"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export declare function getPptxCoreVersion(): string;
2
2
  export { generatePresentation, generateBufferFromJson, generateBufferWithWarnings, generateAndSaveFromJson, generateFromFile, savePresentation, isPresentationComponentDefinition, PresentationGenerator, } from './core/generator';
3
3
  export type { GenerationOptions, GenerationResult } from './core/generator';
4
- export type { PptxComponentInput, PresentationComponentDefinition, SlideComponentDefinition, ProcessedPresentation, ProcessedSlide, PptxThemeConfig, PipelineWarning, SlideContext, } from './types';
4
+ export type { PptxComponentInput, PresentationComponentDefinition, SlideComponentDefinition, ProcessedPresentation, ProcessedSlide, PptxThemeConfig, PipelineWarning, SlideContext, SlideRenderContext, } from './types';
5
5
  export { isPresentationComponent, isSlideComponent } from './types';
6
6
  export { W as WarningCodes } from './utils/warn';
7
7
  export type { WarningCode } from './utils/warn';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAGD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG5E,YAAY,EACV,kBAAkB,EAClB,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,eAAe,EACf,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGpE,OAAO,EAAE,CAAC,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,aAAa,EACb,2BAA2B,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,4BAA4B,EAC5B,qBAAqB,IAAI,2BAA2B,EACpD,4BAA4B,EAC5B,sBAAsB,IAAI,4BAA4B,EACtD,oBAAoB,IAAI,0BAA0B,EAClD,gBAAgB,IAAI,sBAAsB,EAC1C,0BAA0B,EAC1B,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,eAAe,IAAI,qBAAqB,GACzC,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,eAAe,GAChB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAGD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG5E,YAAY,EACV,kBAAkB,EAClB,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,eAAe,EACf,YAAY,EACZ,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGpE,OAAO,EAAE,CAAC,IAAI,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,aAAa,EACb,2BAA2B,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,4BAA4B,EAC5B,qBAAqB,IAAI,2BAA2B,EACpD,4BAA4B,EAC5B,sBAAsB,IAAI,4BAA4B,EACtD,oBAAoB,IAAI,0BAA0B,EAClD,gBAAgB,IAAI,sBAAsB,EAC1C,0BAA0B,EAC1B,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,eAAe,IAAI,qBAAqB,GACzC,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,eAAe,GAChB,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -25,7 +25,8 @@ var W = {
25
25
  PLACEHOLDER_NO_POSITION: "PLACEHOLDER_NO_POSITION",
26
26
  THEME_COLOR_FALLBACK: "THEME_COLOR_FALLBACK",
27
27
  UNKNOWN_COLOR: "UNKNOWN_COLOR",
28
- GRID_POSITION_CLAMPED: "GRID_POSITION_CLAMPED"
28
+ GRID_POSITION_CLAMPED: "GRID_POSITION_CLAMPED",
29
+ IMAGE_ZERO_BOX: "IMAGE_ZERO_BOX"
29
30
  };
30
31
  function warn(warnings, code, message, extra) {
31
32
  if (warnings) {
@@ -212,11 +213,113 @@ function getPptxTheme(name) {
212
213
  }
213
214
  var pptxThemes = PPTX_THEMES;
214
215
 
216
+ // src/utils/componentDefaults.ts
217
+ import { mergeWithDefaults } from "@json-to-office/shared";
218
+ function getComponentDefaults(theme) {
219
+ return theme.componentDefaults || {};
220
+ }
221
+ function getTextDefaults(theme) {
222
+ return getComponentDefaults(theme).text || {};
223
+ }
224
+ function getImageDefaults(theme) {
225
+ return getComponentDefaults(theme).image || {};
226
+ }
227
+ function getShapeDefaults(theme) {
228
+ return getComponentDefaults(theme).shape || {};
229
+ }
230
+ function getTableDefaults(theme) {
231
+ return getComponentDefaults(theme).table || {};
232
+ }
233
+ function getHighchartsDefaults(theme) {
234
+ return getComponentDefaults(theme).highcharts || {};
235
+ }
236
+ function getChartDefaults(theme) {
237
+ return getComponentDefaults(theme).chart || {};
238
+ }
239
+ function getCustomComponentDefaults(theme, componentName) {
240
+ const defaults = getComponentDefaults(theme);
241
+ return defaults?.[componentName] || {};
242
+ }
243
+ function resolveTextProps(props, theme) {
244
+ return mergeWithDefaults(props, getTextDefaults(theme));
245
+ }
246
+ function resolveImageProps(props, theme) {
247
+ return mergeWithDefaults(props, getImageDefaults(theme));
248
+ }
249
+ function resolveShapeProps(props, theme) {
250
+ return mergeWithDefaults(props, getShapeDefaults(theme));
251
+ }
252
+ function resolveTableProps(props, theme) {
253
+ return mergeWithDefaults(props, getTableDefaults(theme));
254
+ }
255
+ function resolveHighchartsProps(props, theme) {
256
+ return mergeWithDefaults(props, getHighchartsDefaults(theme));
257
+ }
258
+ function resolveChartProps(props, theme) {
259
+ return mergeWithDefaults(props, getChartDefaults(theme));
260
+ }
261
+ function resolveCustomComponentProps(props, theme, componentName) {
262
+ const defaults = getCustomComponentDefaults(theme, componentName);
263
+ return mergeWithDefaults(props, defaults);
264
+ }
265
+ var TYPE_GETTERS = {
266
+ text: getTextDefaults,
267
+ image: getImageDefaults,
268
+ shape: getShapeDefaults,
269
+ table: getTableDefaults,
270
+ highcharts: getHighchartsDefaults,
271
+ chart: getChartDefaults
272
+ };
273
+ function getDefaultsForType(componentName, theme) {
274
+ const getter = TYPE_GETTERS[componentName];
275
+ return getter ? getter(theme) : getCustomComponentDefaults(theme, componentName);
276
+ }
277
+
278
+ // src/utils/resolveComponentTree.ts
279
+ var RESOLVER_MAP = {
280
+ text: resolveTextProps,
281
+ image: resolveImageProps,
282
+ shape: resolveShapeProps,
283
+ table: resolveTableProps,
284
+ highcharts: resolveHighchartsProps,
285
+ chart: resolveChartProps
286
+ };
287
+ function resolveComponentDefaults(component, theme) {
288
+ const resolver = RESOLVER_MAP[component.name];
289
+ const resolvedProps = resolver ? resolver(component.props, theme) : resolveCustomComponentProps(
290
+ component.props,
291
+ theme,
292
+ component.name
293
+ );
294
+ return { ...component, props: resolvedProps };
295
+ }
296
+ function resolveComponentTree(components, theme) {
297
+ return components.map((component) => {
298
+ const resolved = resolveComponentDefaults(component, theme);
299
+ if (resolved.children && resolved.children.length > 0) {
300
+ return {
301
+ ...resolved,
302
+ children: resolveComponentTree(resolved.children, theme)
303
+ };
304
+ }
305
+ return resolved;
306
+ });
307
+ }
308
+
215
309
  // src/core/structure.ts
310
+ import { mergeWithDefaults as mergeWithDefaults2 } from "@json-to-office/shared";
216
311
  function processPresentation(document, options) {
217
312
  const { props, children = [] } = document;
218
313
  const themeName = props.theme ?? "default";
219
- const theme = options?.customThemes?.[themeName] ?? getPptxTheme(themeName);
314
+ const baseTheme = options?.customThemes?.[themeName] ?? getPptxTheme(themeName);
315
+ const presDefaults = props.componentDefaults;
316
+ const theme = presDefaults ? {
317
+ ...baseTheme,
318
+ componentDefaults: mergeWithDefaults2(
319
+ presDefaults,
320
+ baseTheme.componentDefaults || {}
321
+ )
322
+ } : baseTheme;
220
323
  const slideWidth = props.slideWidth ?? 10;
221
324
  const slideHeight = props.slideHeight ?? 7.5;
222
325
  let templates;
@@ -240,7 +343,8 @@ function processPresentation(document, options) {
240
343
  grid: void 0
241
344
  };
242
345
  });
243
- const resolvedObjects = m.objects?.map(
346
+ const defaultedObjects = m.objects ? resolveComponentTree(m.objects, theme) : void 0;
347
+ const resolvedObjects = defaultedObjects?.map(
244
348
  (obj) => resolveComponentGridPosition(
245
349
  obj,
246
350
  effectiveGrid,
@@ -260,8 +364,9 @@ function processPresentation(document, options) {
260
364
  slideComponents.push(slideChild);
261
365
  }
262
366
  }
367
+ const resolvedComponents = resolveComponentTree(slideComponents, theme);
263
368
  slides.push({
264
- components: slideComponents,
369
+ components: resolvedComponents,
265
370
  background: child.props.background,
266
371
  notes: child.props.notes,
267
372
  layout: child.props.layout,
@@ -412,7 +517,8 @@ import probe from "probe-image-size";
412
517
  function isPrivateUrl(urlStr) {
413
518
  try {
414
519
  const { hostname } = new URL(urlStr);
415
- if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]" || hostname.startsWith("10.") || hostname.startsWith("192.168.") || hostname.startsWith("169.254.") || hostname.endsWith(".local") || hostname.endsWith(".internal")) return true;
520
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]" || hostname.startsWith("10.") || hostname.startsWith("192.168.") || hostname.startsWith("169.254.") || hostname.endsWith(".local") || hostname.endsWith(".internal"))
521
+ return true;
416
522
  if (hostname.startsWith("172.")) {
417
523
  const second = parseInt(hostname.split(".")[1], 10);
418
524
  if (second >= 16 && second <= 31) return true;
@@ -442,30 +548,75 @@ async function probeImageSize(imagePath, warnings) {
442
548
  const result = await probe(createReadStream(resolved));
443
549
  return result ? { width: result.width, height: result.height } : void 0;
444
550
  } catch (err) {
445
- warn(warnings, W.IMAGE_PROBE_FAILED, `Image probe failed: ${err instanceof Error ? err.message : String(err)}`, { component: "image" });
551
+ warn(
552
+ warnings,
553
+ W.IMAGE_PROBE_FAILED,
554
+ `Image probe failed: ${err instanceof Error ? err.message : String(err)}`,
555
+ { component: "image" }
556
+ );
446
557
  return void 0;
447
558
  }
448
559
  }
449
- async function renderImageComponent(slide, props, theme, warnings) {
560
+ function resolveDimension(value, axisLength) {
561
+ if (typeof value === "number") return value;
562
+ if (value.endsWith("%")) {
563
+ const pct = parseFloat(value);
564
+ return !Number.isNaN(pct) && pct >= 0 ? pct / 100 * axisLength : 0;
565
+ }
566
+ const n = Number(value);
567
+ return Number.isNaN(n) ? 0 : n;
568
+ }
569
+ async function renderImageComponent(slide, props, theme, warnings, slideWidth = 10, slideHeight = 7.5) {
450
570
  const opts = {};
571
+ const source = props.path || props.base64;
572
+ if (!source) {
573
+ warn(
574
+ warnings,
575
+ W.IMAGE_NO_SOURCE,
576
+ "Image component missing both path and base64",
577
+ { component: "image" }
578
+ );
579
+ return;
580
+ }
451
581
  if (props.path) {
452
582
  opts.path = props.path;
453
- } else if (props.base64) {
454
- opts.data = props.base64;
455
583
  } else {
456
- warn(warnings, W.IMAGE_NO_SOURCE, "Image component missing both path and base64", { component: "image" });
457
- return;
584
+ opts.data = props.base64;
458
585
  }
459
586
  if (props.x !== void 0) opts.x = props.x;
460
587
  if (props.y !== void 0) opts.y = props.y;
461
588
  if (props.w !== void 0) opts.w = props.w;
462
589
  if (props.h !== void 0) opts.h = props.h;
590
+ const hasW = props.w !== void 0;
591
+ const hasH = props.h !== void 0;
592
+ const needsProbe = hasW !== hasH && !props.sizing || props.sizing?.type === "contain" || props.sizing?.type === "cover";
593
+ const intrinsic = needsProbe ? await probeImageSize(source, warnings) : void 0;
594
+ if (hasW !== hasH && !props.sizing) {
595
+ if (intrinsic && intrinsic.width > 0 && intrinsic.height > 0) {
596
+ const aspect = intrinsic.width / intrinsic.height;
597
+ if (hasW && !hasH) {
598
+ const wInches = resolveDimension(props.w, slideWidth);
599
+ opts.w = wInches;
600
+ opts.h = wInches / aspect;
601
+ } else {
602
+ const hInches = resolveDimension(props.h, slideHeight);
603
+ opts.h = hInches;
604
+ opts.w = hInches * aspect;
605
+ }
606
+ }
607
+ }
463
608
  if (props.sizing && (props.sizing.type === "contain" || props.sizing.type === "cover")) {
464
- const source = props.path || props.base64;
465
- const intrinsic = source ? await probeImageSize(source, warnings) : void 0;
466
- const boxW = Number(props.sizing.w ?? props.w);
467
- const boxH = Number(props.sizing.h ?? props.h);
468
- if (intrinsic && !isNaN(boxW) && !isNaN(boxH)) {
609
+ const boxW = resolveDimension(props.sizing.w ?? props.w ?? 0, slideWidth);
610
+ const boxH = resolveDimension(props.sizing.h ?? props.h ?? 0, slideHeight);
611
+ if (boxW <= 0 || boxH <= 0) {
612
+ warn(
613
+ warnings,
614
+ W.IMAGE_ZERO_BOX,
615
+ `Image sizing box resolved to zero (${boxW}x${boxH})`,
616
+ { component: "image" }
617
+ );
618
+ }
619
+ if (intrinsic && intrinsic.width > 0 && intrinsic.height > 0 && boxW > 0 && boxH > 0) {
469
620
  const imgAspect = intrinsic.width / intrinsic.height;
470
621
  if (props.sizing.type === "contain") {
471
622
  const boxAspect = boxW / boxH;
@@ -477,8 +628,8 @@ async function renderImageComponent(slide, props, theme, warnings) {
477
628
  fitH = boxH;
478
629
  fitW = boxH * imgAspect;
479
630
  }
480
- const baseX = Number(props.x ?? 0);
481
- const baseY = Number(props.y ?? 0);
631
+ const baseX = resolveDimension(props.x ?? 0, slideWidth);
632
+ const baseY = resolveDimension(props.y ?? 0, slideHeight);
482
633
  opts.x = baseX + (boxW - fitW) / 2;
483
634
  opts.y = baseY + (boxH - fitH) / 2;
484
635
  opts.w = fitW;
@@ -494,8 +645,8 @@ async function renderImageComponent(slide, props, theme, warnings) {
494
645
  } else if (props.sizing) {
495
646
  opts.sizing = {
496
647
  ...props.sizing,
497
- w: props.sizing.w ?? props.w,
498
- h: props.sizing.h ?? props.h
648
+ w: resolveDimension(props.sizing.w ?? props.w ?? 0, slideWidth),
649
+ h: resolveDimension(props.sizing.h ?? props.h ?? 0, slideHeight)
499
650
  };
500
651
  }
501
652
  if (props.rotate !== void 0) opts.rotate = props.rotate;
@@ -946,16 +1097,23 @@ function renderChartComponent(slide, props, theme, _pptx, warnings) {
946
1097
  }
947
1098
 
948
1099
  // src/components/index.ts
949
- async function renderComponent(slide, component, theme, pptx, warnings, slideCtx, services) {
1100
+ async function renderComponent(slide, component, theme, pptx, warnings, ctx) {
950
1101
  if (component.enabled === false) return;
951
1102
  const { name, props } = component;
952
1103
  const p = props;
953
1104
  switch (name) {
954
1105
  case "text":
955
- renderTextComponent(slide, p, theme, warnings, slideCtx);
1106
+ renderTextComponent(slide, p, theme, warnings, ctx?.slideCtx);
956
1107
  break;
957
1108
  case "image":
958
- await renderImageComponent(slide, p, theme, warnings);
1109
+ await renderImageComponent(
1110
+ slide,
1111
+ p,
1112
+ theme,
1113
+ warnings,
1114
+ ctx?.slideWidth,
1115
+ ctx?.slideHeight
1116
+ );
959
1117
  break;
960
1118
  case "shape":
961
1119
  renderShapeComponent(slide, p, theme, pptx, warnings);
@@ -969,7 +1127,7 @@ async function renderComponent(slide, component, theme, pptx, warnings, slideCtx
969
1127
  p,
970
1128
  theme,
971
1129
  warnings,
972
- services?.highcharts
1130
+ ctx?.services?.highcharts
973
1131
  );
974
1132
  break;
975
1133
  case "chart":
@@ -1014,6 +1172,7 @@ function buildSlideTemplateProps(def, theme, warnings) {
1014
1172
  }
1015
1173
 
1016
1174
  // src/core/render.ts
1175
+ import { mergeWithDefaults as mergeWithDefaults3 } from "@json-to-office/shared";
1017
1176
  async function renderPresentation(processed, warnings) {
1018
1177
  const pptx = new PptxGenJS();
1019
1178
  if (processed.metadata.title) pptx.title = processed.metadata.title;
@@ -1054,6 +1213,12 @@ async function renderPresentation(processed, warnings) {
1054
1213
  totalSlides,
1055
1214
  pageNumberFormat: processed.pageNumberFormat
1056
1215
  };
1216
+ const renderCtx = {
1217
+ slideCtx,
1218
+ services: processed.services,
1219
+ slideWidth: processed.slideWidth,
1220
+ slideHeight: processed.slideHeight
1221
+ };
1057
1222
  const slide = slideData.template ? pptx.addSlide({ masterName: slideData.template }) : pptx.addSlide();
1058
1223
  if (slideData.background) {
1059
1224
  if (slideData.background.color) {
@@ -1093,8 +1258,7 @@ async function renderPresentation(processed, warnings) {
1093
1258
  processed.theme,
1094
1259
  pptx,
1095
1260
  warnings,
1096
- slideCtx,
1097
- processed.services
1261
+ renderCtx
1098
1262
  );
1099
1263
  }
1100
1264
  }
@@ -1112,8 +1276,7 @@ async function renderPresentation(processed, warnings) {
1112
1276
  processed.theme,
1113
1277
  pptx,
1114
1278
  warnings,
1115
- slideCtx,
1116
- processed.services
1279
+ renderCtx
1117
1280
  );
1118
1281
  }
1119
1282
  if (slideData.placeholders) {
@@ -1141,34 +1304,39 @@ async function renderPresentation(processed, warnings) {
1141
1304
  processed.slideHeight,
1142
1305
  warnings
1143
1306
  );
1307
+ const typeDefaults = getDefaultsForType(
1308
+ component.name,
1309
+ processed.theme
1310
+ );
1144
1311
  const posDefaults = {};
1145
1312
  if (phDef.x != null) posDefaults.x = phDef.x;
1146
1313
  if (phDef.y != null) posDefaults.y = phDef.y;
1147
1314
  if (phDef.w != null) posDefaults.w = phDef.w;
1148
1315
  if (phDef.h != null) posDefaults.h = phDef.h;
1149
- const props = {
1150
- ...posDefaults,
1151
- ...phDef.defaults?.props ?? {},
1152
- ...gridResolved.props
1153
- };
1316
+ let props = mergeWithDefaults3(posDefaults, typeDefaults);
1317
+ props = mergeWithDefaults3(phDef.defaults?.props ?? {}, props);
1318
+ props = mergeWithDefaults3(gridResolved.props, props);
1154
1319
  await renderComponent(
1155
1320
  slide,
1156
1321
  { ...gridResolved, props },
1157
1322
  processed.theme,
1158
1323
  pptx,
1159
1324
  warnings,
1160
- slideCtx,
1161
- processed.services
1325
+ renderCtx
1162
1326
  );
1163
1327
  }
1164
1328
  } else {
1165
1329
  for (const [phName, component] of Object.entries(
1166
1330
  slideData.placeholders
1167
1331
  )) {
1168
- const hasPosition = component.props.x != null || component.props.y != null || component.props.grid;
1332
+ const defaulted = resolveComponentDefaults(
1333
+ component,
1334
+ processed.theme
1335
+ );
1336
+ const hasPosition = defaulted.props.x != null || defaulted.props.y != null || defaulted.props.grid;
1169
1337
  if (hasPosition) {
1170
1338
  const resolved = resolveComponentGridPosition(
1171
- component,
1339
+ defaulted,
1172
1340
  effectiveGrid,
1173
1341
  processed.slideWidth,
1174
1342
  processed.slideHeight,
@@ -1180,8 +1348,7 @@ async function renderPresentation(processed, warnings) {
1180
1348
  processed.theme,
1181
1349
  pptx,
1182
1350
  warnings,
1183
- slideCtx,
1184
- processed.services
1351
+ renderCtx
1185
1352
  );
1186
1353
  } else {
1187
1354
  warn(