@json-to-office/core-docx 0.16.0 → 0.17.1

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.
@@ -1,6 +1,6 @@
1
1
  import { type ThemeConfig } from '../styles';
2
2
  import type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';
3
- import type { DocumentGeneratorBuilder } from './types';
3
+ import type { DocumentGeneratorBuilder, GenerationValidationOptions } from './types';
4
4
  /**
5
5
  * Options for creating a document generator
6
6
  */
@@ -17,6 +17,12 @@ export interface DocumentGeneratorOptions {
17
17
  services?: ServicesConfig;
18
18
  /** Font resolution options — extraEntries, Google Fonts config, onResolved hook. */
19
19
  fonts?: FontRuntimeOpts;
20
+ /**
21
+ * Default validation behavior for every generate/generateBuffer/generateFile
22
+ * call. Per-call `options.validation` overrides these. Validation is on by
23
+ * default; pass `{ enabled: false }` to opt out.
24
+ */
25
+ validation?: GenerationValidationOptions;
20
26
  }
21
27
  /**
22
28
  * 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":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,KAAK,EAEV,wBAAwB,EAOzB,MAAM,SAAS,CAAC;AAejB;;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;CACzB;AAiiBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAavC"}
1
+ {"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAejB;;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;CAC1C;AAgmBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAcvC"}
@@ -1904,22 +1904,20 @@ import {
1904
1904
  ComponentValidationError as ComponentValidationError2,
1905
1905
  UnknownPreservedComponentError
1906
1906
  } from "@json-to-office/shared/plugin";
1907
- function validateComponentProps(schema, props, componentName) {
1907
+ function validateComponentProps(schema, props, componentName, opts) {
1908
1908
  return validateCustomComponentProps(schema.propsSchema, props, {
1909
- clean: true,
1910
- applyDefaults: true,
1909
+ clean: opts?.clean ?? true,
1910
+ applyDefaults: opts?.applyDefaults ?? true,
1911
1911
  componentName
1912
1912
  });
1913
1913
  }
1914
- function validateDocument(document, customComponents) {
1914
+ function validateDocument(document, customComponents, options) {
1915
+ const knownCustomNames = new Set(customComponents.map((c) => c.name));
1915
1916
  const documentResult = validateDocumentUnified(document, {
1916
- clean: true,
1917
- applyDefaults: true
1917
+ knownCustomNames,
1918
+ allowUnknownFields: options?.allowUnknownFields
1918
1919
  });
1919
- if (!documentResult.valid) {
1920
- return { ...documentResult, success: false };
1921
- }
1922
- const errors = [];
1920
+ const errors = [...documentResult.errors || []];
1923
1921
  function validateComponents(components, pathPrefix = "children") {
1924
1922
  components.forEach((componentData, index) => {
1925
1923
  const customComponent = customComponents.find(
@@ -1936,7 +1934,9 @@ function validateDocument(document, customComponents) {
1936
1934
  const validation = validateComponentProps(
1937
1935
  versionEntry,
1938
1936
  componentData.props,
1939
- customComponent.name
1937
+ customComponent.name,
1938
+ // Reject unknown custom props unless the caller allows them.
1939
+ { clean: options?.allowUnknownFields === true }
1940
1940
  );
1941
1941
  if (!validation.valid && validation.errors) {
1942
1942
  const indexedErrors = validation.errors.map(
@@ -7133,7 +7133,7 @@ function createBuilderImpl(state) {
7133
7133
  }
7134
7134
  return getThemeWithFallback(themeName);
7135
7135
  }
7136
- async function processDocumentComponents(components, preserveSet, warningsCollector, resolvedTheme, depth = 0) {
7136
+ async function processDocumentComponents(components, preserveSet, warningsCollector, resolvedTheme, validateEmitted, depth = 0) {
7137
7137
  if (depth > 20) {
7138
7138
  throw new Error(
7139
7139
  "Maximum component nesting depth exceeded (20). Check for circular component references."
@@ -7173,6 +7173,7 @@ function createBuilderImpl(state) {
7173
7173
  preserveSet,
7174
7174
  warningsCollector,
7175
7175
  resolvedTheme,
7176
+ validateEmitted,
7176
7177
  depth + 1
7177
7178
  );
7178
7179
  nestedChildren = nested.standard;
@@ -7193,11 +7194,15 @@ function createBuilderImpl(state) {
7193
7194
  children: nestedChildren
7194
7195
  });
7195
7196
  const resultComponents = Array.isArray(result) ? result : [result];
7197
+ if (validateEmitted) {
7198
+ validateEmitted(resultComponents, versionLabel);
7199
+ }
7196
7200
  const processedResult = await processDocumentComponents(
7197
7201
  resultComponents,
7198
7202
  preserveSet,
7199
7203
  warningsCollector,
7200
7204
  resolvedTheme,
7205
+ validateEmitted,
7201
7206
  depth + 1
7202
7207
  );
7203
7208
  standardOut.push(...processedResult.standard);
@@ -7227,6 +7232,7 @@ function createBuilderImpl(state) {
7227
7232
  preserveSet,
7228
7233
  warningsCollector,
7229
7234
  resolvedTheme,
7235
+ validateEmitted,
7230
7236
  depth + 1
7231
7237
  );
7232
7238
  standardOut.push({
@@ -7287,10 +7293,42 @@ function createBuilderImpl(state) {
7287
7293
  try {
7288
7294
  const preserveSet = resolvePreserveSet(options);
7289
7295
  const internalDocument = document;
7290
- validateDocument(
7291
- internalDocument,
7292
- state.components
7293
- );
7296
+ const vOpts = {
7297
+ ...state.validation,
7298
+ ...options?.validation
7299
+ };
7300
+ if (vOpts.enabled !== false) {
7301
+ const result = validateDocument(
7302
+ internalDocument,
7303
+ state.components,
7304
+ { allowUnknownFields: vOpts.allowUnknownFields }
7305
+ );
7306
+ if (!result.valid) {
7307
+ throw new ComponentValidationError2(
7308
+ (result.errors ?? []).map((e) => ({
7309
+ path: e.path ?? "",
7310
+ message: e.message
7311
+ })),
7312
+ internalDocument
7313
+ );
7314
+ }
7315
+ }
7316
+ const validateEmitted = vOpts.enabled === false ? void 0 : (emitted, componentLabel) => {
7317
+ const result = validateDocument(
7318
+ { ...internalDocument, children: emitted },
7319
+ state.components,
7320
+ { allowUnknownFields: vOpts.allowUnknownFields }
7321
+ );
7322
+ if (!result.valid) {
7323
+ throw new ComponentValidationError2(
7324
+ (result.errors ?? []).map((e) => ({
7325
+ path: e.path ?? "",
7326
+ message: `custom component '${componentLabel}' emitted invalid output \u2014 ${e.message}`
7327
+ })),
7328
+ emitted
7329
+ );
7330
+ }
7331
+ };
7294
7332
  const baseThemeName = internalDocument.props.theme || "minimal";
7295
7333
  const docTheme = resolveDocumentTheme(baseThemeName);
7296
7334
  const warnings = [];
@@ -7313,7 +7351,8 @@ function createBuilderImpl(state) {
7313
7351
  mode.doc.children || [],
7314
7352
  preserveSet,
7315
7353
  warnings,
7316
- modedTheme
7354
+ modedTheme,
7355
+ validateEmitted
7317
7356
  );
7318
7357
  const processedDocument = {
7319
7358
  ...mode.doc,
@@ -7384,21 +7423,21 @@ function createBuilderImpl(state) {
7384
7423
  function validate(document) {
7385
7424
  try {
7386
7425
  const internalDocument = document;
7387
- validateDocument(
7426
+ const result = validateDocument(
7388
7427
  internalDocument,
7389
7428
  state.components
7390
7429
  );
7391
- return { valid: true };
7392
- } catch (error) {
7393
- if (error instanceof ComponentValidationError2) {
7394
- return {
7395
- valid: false,
7396
- errors: error.errors.map((e) => ({
7397
- path: e.path,
7398
- message: e.message
7399
- }))
7400
- };
7430
+ if (result.valid) {
7431
+ return { valid: true };
7401
7432
  }
7433
+ return {
7434
+ valid: false,
7435
+ errors: (result.errors ?? []).map((e) => ({
7436
+ path: e.path ?? "",
7437
+ message: e.message
7438
+ }))
7439
+ };
7440
+ } catch (error) {
7402
7441
  return {
7403
7442
  valid: false,
7404
7443
  errors: [
@@ -7448,7 +7487,8 @@ function createDocumentGenerator(options) {
7448
7487
  debug: options.debug ?? false,
7449
7488
  enableCache: options.enableCache ?? false,
7450
7489
  services: options.services,
7451
- fonts: options.fonts
7490
+ fonts: options.fonts,
7491
+ validation: options.validation
7452
7492
  };
7453
7493
  return createBuilderImpl(initialState);
7454
7494
  }