@json-to-office/core-docx 0.26.1 → 0.28.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.
@@ -27,6 +27,12 @@ export interface DocumentGeneratorOptions {
27
27
  deterministic?: boolean;
28
28
  /** Default build timestamp for generated metadata. */
29
29
  generatedAt?: string | Date;
30
+ /**
31
+ * Directory that relative asset paths (image `path` props) resolve against.
32
+ * Per-call `options.baseDir` overrides it; defaults to `process.cwd()`
33
+ * when neither is set (#142).
34
+ */
35
+ baseDir?: string;
30
36
  }
31
37
  /**
32
38
  * Create a document generator with chainable component registration.
@@ -1 +1 @@
1
- {"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAqnBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAgBvC"}
1
+ {"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAK7C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyoBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAiBvC"}
@@ -1915,6 +1915,9 @@ function resolveBuiltInTheme(themeName, options = {}) {
1915
1915
  return getThemeWithFallback(themeName);
1916
1916
  }
1917
1917
 
1918
+ // src/plugin/createDocumentGenerator.ts
1919
+ init_themes();
1920
+
1918
1921
  // src/core/generationContext.ts
1919
1922
  import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
1920
1923
 
@@ -1963,8 +1966,13 @@ function resolveThemeContext(documentIn, options = {}) {
1963
1966
  );
1964
1967
  }
1965
1968
  const document = documentIn.props === void 0 ? { ...documentIn, props: {} } : documentIn;
1966
- const baseThemeName = document.props.theme || "minimal";
1967
- let theme = resolveNamedTheme ? resolveNamedTheme(baseThemeName, warnings) : defaultNamedThemeLookup(baseThemeName, customThemes, warnings);
1969
+ const authoredThemeName = document.props.theme || void 0;
1970
+ const baseThemeName = authoredThemeName ?? "minimal";
1971
+ let theme = resolveNamedTheme ? resolveNamedTheme(
1972
+ baseThemeName,
1973
+ warnings,
1974
+ authoredThemeName !== void 0
1975
+ ) : defaultNamedThemeLookup(baseThemeName, customThemes, warnings);
1968
1976
  const themeOverrides = document.props.themeOverrides;
1969
1977
  let themeName = baseThemeName;
1970
1978
  if (themeOverrides) {
@@ -2862,9 +2870,34 @@ import {
2862
2870
  } from "docx";
2863
2871
 
2864
2872
  // src/utils/imageUtils.ts
2865
- init_widthUtils();
2866
2873
  import { readFileSync } from "fs";
2867
2874
  import probe from "probe-image-size";
2875
+
2876
+ // src/utils/generationContext.ts
2877
+ import { AsyncLocalStorage } from "async_hooks";
2878
+ import { isAbsolute, resolve } from "path";
2879
+ var generationDateStorage = new AsyncLocalStorage();
2880
+ function runWithGenerationDate(date, callback) {
2881
+ return generationDateStorage.run(date, callback);
2882
+ }
2883
+ function getGenerationDate() {
2884
+ return generationDateStorage.getStore() ?? /* @__PURE__ */ new Date();
2885
+ }
2886
+ var baseDirStorage = new AsyncLocalStorage();
2887
+ function runWithBaseDir(baseDir, callback) {
2888
+ return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
2889
+ }
2890
+ function getBaseDir() {
2891
+ return baseDirStorage.getStore();
2892
+ }
2893
+ function resolveFromBaseDir(filePath) {
2894
+ const base = baseDirStorage.getStore();
2895
+ if (!base || isAbsolute(filePath)) return filePath;
2896
+ return resolve(base, filePath);
2897
+ }
2898
+
2899
+ // src/utils/imageUtils.ts
2900
+ init_widthUtils();
2868
2901
  import { ImageRun } from "docx";
2869
2902
  function parseWidthValue(width, availableWidthPx) {
2870
2903
  if (typeof width === "number") {
@@ -3040,7 +3073,7 @@ async function getImageBuffer(imagePath) {
3040
3073
  if (isValidUrl(imagePath)) {
3041
3074
  return await downloadImageFromUrl(imagePath);
3042
3075
  }
3043
- return { buffer: readFileSync(imagePath) };
3076
+ return { buffer: readFileSync(resolveFromBaseDir(imagePath)) };
3044
3077
  }
3045
3078
  async function getImageDimensions(imagePath) {
3046
3079
  try {
@@ -4112,16 +4145,6 @@ function parseTextWithHyperlinks(text, baseStyle = {}, options = {}) {
4112
4145
  return runs;
4113
4146
  }
4114
4147
 
4115
- // src/utils/generationContext.ts
4116
- import { AsyncLocalStorage } from "async_hooks";
4117
- var generationDateStorage = new AsyncLocalStorage();
4118
- function runWithGenerationDate(date, callback) {
4119
- return generationDateStorage.run(date, callback);
4120
- }
4121
- function getGenerationDate() {
4122
- return generationDateStorage.getStore() ?? /* @__PURE__ */ new Date();
4123
- }
4124
-
4125
4148
  // src/utils/placeholderProcessor.ts
4126
4149
  function styledPlaceholderText(text, context) {
4127
4150
  return new TextRun2({
@@ -4468,8 +4491,9 @@ async function renderComponentWithCache(component, theme, themeName, context, by
4468
4491
  const themeHash = createThemeHash(theme);
4469
4492
  const contextKey = context?.section ? `${context.section.currentLayout}:${context.section.columnCount}` : "no-section";
4470
4493
  const generationDateKey = getGenerationDate().toISOString();
4494
+ const baseDirKey = getBaseDir() ?? "";
4471
4495
  const childrenKey = "children" in component && component.children ? `:children:${JSON.stringify(component.children)}` : "";
4472
- const cacheKey = `component:${component.name}:${themeHash}:${contextKey}:${generationDateKey}:${componentProps}${childrenKey}`;
4496
+ const cacheKey = `component:${component.name}:${themeHash}:${contextKey}:${generationDateKey}:${baseDirKey}:${componentProps}${childrenKey}`;
4473
4497
  const cached = await componentCache.get(cacheKey);
4474
4498
  if (cached) {
4475
4499
  return cached.result;
@@ -7164,14 +7188,14 @@ function visualToImageOptions(props) {
7164
7188
  ...props.keepLines !== void 0 && { keepLines: props.keepLines }
7165
7189
  };
7166
7190
  }
7167
- async function rasterize(presentation, dpi, propsServerUrl, serviceConfig) {
7191
+ async function rasterize(presentation, dpi, propsServerUrl, serviceConfig, baseDir) {
7168
7192
  if (!isNodeEnvironment()) {
7169
7193
  throw new Error(
7170
7194
  "Visual rasterization requires a Node.js environment. It is not available in browser environments."
7171
7195
  );
7172
7196
  }
7173
7197
  if (serviceConfig?.render) {
7174
- return serviceConfig.render({ presentation, dpi });
7198
+ return serviceConfig.render({ presentation, dpi, baseDir });
7175
7199
  }
7176
7200
  const serverUrl = resolveServiceUrl(
7177
7201
  propsServerUrl,
@@ -7181,7 +7205,7 @@ async function rasterize(presentation, dpi, propsServerUrl, serviceConfig) {
7181
7205
  const response = await postJsonToService({
7182
7206
  url: serverUrl,
7183
7207
  path: "/rasterize",
7184
- body: { presentation, dpi },
7208
+ body: { presentation, dpi, ...baseDir !== void 0 && { baseDir } },
7185
7209
  headers: serviceConfig?.headers,
7186
7210
  serviceLabel: "PPTX rasterization service",
7187
7211
  onUnreachable: (url, cause) => `PPTX rasterization service is not reachable at ${url}. Configure services.pptx with a \`render\` callback or a running \`serverUrl\`.
@@ -7214,7 +7238,8 @@ async function renderVisualComponent(component, theme, themeName, context) {
7214
7238
  presentation,
7215
7239
  dpi,
7216
7240
  props.serverUrl,
7217
- serviceConfig
7241
+ serviceConfig,
7242
+ getBaseDir()
7218
7243
  );
7219
7244
  return await createImage(
7220
7245
  result.base64DataUri,
@@ -7308,10 +7333,13 @@ function coreProperties(metadata) {
7308
7333
  async function renderDocument(structure, layout, options) {
7309
7334
  return runWithGenerationDate(
7310
7335
  structure.metadata.date,
7311
- () => globalBookmarkRegistry.runScoped(
7312
- () => globalRevisionIdRegistry.runScoped(
7313
- () => globalNumberingRegistry.runScoped(
7314
- () => renderDocumentScoped(structure, layout, options)
7336
+ () => runWithBaseDir(
7337
+ options?.baseDir,
7338
+ () => globalBookmarkRegistry.runScoped(
7339
+ () => globalRevisionIdRegistry.runScoped(
7340
+ () => globalNumberingRegistry.runScoped(
7341
+ () => renderDocumentScoped(structure, layout, options)
7342
+ )
7315
7343
  )
7316
7344
  )
7317
7345
  )
@@ -7837,7 +7865,7 @@ async function packageDocument(document, options) {
7837
7865
  // src/plugin/createDocumentGenerator.ts
7838
7866
  function createBuilderImpl(state) {
7839
7867
  const componentMap = new Map(state.components.map((c) => [c.name, c]));
7840
- function resolveDocumentTheme(themeName, warnings) {
7868
+ function resolveDocumentTheme(themeName, warnings, authored) {
7841
7869
  if (state.customThemes) {
7842
7870
  if (state.customThemes[themeName]) {
7843
7871
  return state.customThemes[themeName];
@@ -7849,6 +7877,12 @@ function createBuilderImpl(state) {
7849
7877
  return state.customThemes[key];
7850
7878
  }
7851
7879
  }
7880
+ if (authored && hasTheme(themeName)) {
7881
+ return resolveBuiltInTheme(themeName, {
7882
+ customThemes: state.customThemes,
7883
+ warnings
7884
+ });
7885
+ }
7852
7886
  if (state.theme) {
7853
7887
  return state.theme;
7854
7888
  }
@@ -7995,7 +8029,8 @@ function createBuilderImpl(state) {
7995
8029
  fonts: state.fonts,
7996
8030
  validation: state.validation,
7997
8031
  deterministic: state.deterministic,
7998
- generatedAt: state.generatedAt
8032
+ generatedAt: state.generatedAt,
8033
+ baseDir: state.baseDir
7999
8034
  };
8000
8035
  return createBuilderImpl(
8001
8036
  newState
@@ -8094,7 +8129,8 @@ function createBuilderImpl(state) {
8094
8129
  const layout = applyLayout(structure.sections, modedTheme, themeName);
8095
8130
  const generatedDocument = await renderDocument(structure, layout, {
8096
8131
  services: state.services,
8097
- bypassCache: !state.enableCache
8132
+ bypassCache: !state.enableCache,
8133
+ baseDir: options?.baseDir ?? state.baseDir
8098
8134
  });
8099
8135
  const preservedDefinition = preserveSet ? {
8100
8136
  ...modedRoot,
@@ -8224,7 +8260,8 @@ function createDocumentGenerator(options) {
8224
8260
  fonts: options.fonts,
8225
8261
  validation: options.validation,
8226
8262
  deterministic: options.deterministic ?? true,
8227
- generatedAt: options.generatedAt
8263
+ generatedAt: options.generatedAt,
8264
+ baseDir: options.baseDir
8228
8265
  };
8229
8266
  return createBuilderImpl(initialState);
8230
8267
  }
@@ -8278,7 +8315,7 @@ var WeatherV2PropsSchema = Type3.Object(
8278
8315
  }
8279
8316
  );
8280
8317
  async function fetchWeather(city, units) {
8281
- await new Promise((resolve) => setTimeout(resolve, 100));
8318
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
8282
8319
  const mockData = {
8283
8320
  London: {
8284
8321
  temperature: units === "imperial" ? 59 : 15,
@@ -8311,7 +8348,7 @@ async function fetchWeather(city, units) {
8311
8348
  };
8312
8349
  }
8313
8350
  async function fetchForecast(city, units, days) {
8314
- await new Promise((resolve) => setTimeout(resolve, 50));
8351
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
8315
8352
  const dayNames = ["Mon", "Tue", "Wed", "Thu", "Fri"];
8316
8353
  const base = units === "imperial" ? 65 : 18;
8317
8354
  return dayNames.slice(0, days).map((day, i) => ({