@json-to-office/core-docx 6.4.1 → 6.8.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.
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/ir/compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAiD3D,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,wBAAwB,CAAC;AAuC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAEL,KAAK,MAAM,EAqCZ,MAAM,SAAS,CAAC;AAiBjB,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,EAAE,SAAS,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;IACrD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAoGD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,UAAU,EAClB,QAAQ,GAAE,iBAAiB,EAAO,EAClC,MAAM,GAAE,cAA0B,EAClC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,iBAAiB,CAiHnB"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/ir/compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAiD3D,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,wBAAwB,CAAC;AAuC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAEL,KAAK,MAAM,EAqCZ,MAAM,SAAS,CAAC;AAiBjB,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,EAAE,SAAS,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;IACrD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAoGD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,UAAU,EAClB,QAAQ,GAAE,iBAAiB,EAAO,EAClC,MAAM,GAAE,cAA0B,EAClC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,iBAAiB,CAiHnB"}
@@ -2642,9 +2642,7 @@ async function downloadImageFromUrl(url) {
2642
2642
  });
2643
2643
  clearTimeout(timeoutId);
2644
2644
  if (!response.ok) {
2645
- throw new Error(
2646
- `Failed to download image: HTTP ${response.status} ${response.statusText}`
2647
- );
2645
+ throw new Error(`HTTP ${response.status} ${response.statusText}`);
2648
2646
  }
2649
2647
  const contentType = response.headers.get("content-type") || void 0;
2650
2648
  const arrayBuffer = await response.arrayBuffer();
@@ -2656,9 +2654,9 @@ async function downloadImageFromUrl(url) {
2656
2654
  "Failed to download image: Request timeout after 10 seconds"
2657
2655
  );
2658
2656
  }
2659
- throw new Error(`Failed to download image from ${url}: ${error.message}`);
2657
+ throw new Error(`Failed to download image: ${error.message}`);
2660
2658
  }
2661
- throw new Error(`Failed to download image from ${url}: Unknown error`);
2659
+ throw new Error("Failed to download image: Unknown error");
2662
2660
  }
2663
2661
  }
2664
2662
  function resolveImageSource(props) {
@@ -6478,6 +6476,7 @@ async function loadImageResources(components) {
6478
6476
  const sources = /* @__PURE__ */ new Set();
6479
6477
  for (const component of components) collectSources(component, sources);
6480
6478
  const loaded = /* @__PURE__ */ new Map();
6479
+ const failures = /* @__PURE__ */ new Map();
6481
6480
  await Promise.all(
6482
6481
  [...sources].map(async (source) => {
6483
6482
  try {
@@ -6488,11 +6487,12 @@ async function loadImageResources(components) {
6488
6487
  ...result.contentType ? { contentType: result.contentType } : {},
6489
6488
  ...intrinsic ? { intrinsic } : {}
6490
6489
  });
6491
- } catch {
6490
+ } catch (error) {
6491
+ failures.set(source, error);
6492
6492
  }
6493
6493
  })
6494
6494
  );
6495
- return loaded;
6495
+ return Object.assign(loaded, { failures });
6496
6496
  }
6497
6497
  function readIntrinsic(bytes, source) {
6498
6498
  try {
@@ -6562,7 +6562,8 @@ function collectCellSource(content, out) {
6562
6562
  // src/ir/compiler.ts
6563
6563
  init_colorUtils();
6564
6564
  import {
6565
- FeatureRequirementCollector
6565
+ FeatureRequirementCollector,
6566
+ assetUnreadableError
6566
6567
  } from "@json-to-office/shared/rendering";
6567
6568
  import { capsFormatting as capsFormatting2, synthesizeFamilyName as synthesizeFamilyName2 } from "@json-to-office/shared";
6568
6569
  import {
@@ -9548,7 +9549,7 @@ function compileChromeImage(component, scope) {
9548
9549
  }
9549
9550
  const loaded = ctx.images.get(source);
9550
9551
  if (!loaded) {
9551
- throw new Error(`Failed to load image from ${source.substring(0, 50)}`);
9552
+ throw unreadableImage(source, ctx) ?? new Error(`Failed to load image from ${source.substring(0, 50)}`);
9552
9553
  }
9553
9554
  const mediaType = detectImageType(source, loaded.contentType);
9554
9555
  if (mediaType === "svg") ctx.features.require("svg-images", path3);
@@ -11157,6 +11158,10 @@ function visualPlacementPixels(props, canvas, reference) {
11157
11158
  );
11158
11159
  }
11159
11160
  var UNLOWERED_IMAGE_PROPS = ["comment"];
11161
+ function unreadableImage(source, ctx) {
11162
+ const { failures } = ctx.images;
11163
+ return failures?.has(source) ? assetUnreadableError(source, failures.get(source)) : void 0;
11164
+ }
11160
11165
  function compileImage2(component, scope) {
11161
11166
  const { ctx, path: path3 } = scope;
11162
11167
  const props = component.props ?? {};
@@ -11173,7 +11178,9 @@ function compileImage2(component, scope) {
11173
11178
  );
11174
11179
  }
11175
11180
  const loaded = ctx.images.get(source);
11176
- if (!loaded) throw new Error(`Failed to load image from ${source}`);
11181
+ if (!loaded) {
11182
+ throw unreadableImage(source, ctx) ?? new Error(`Failed to load image from ${source}`);
11183
+ }
11177
11184
  const mediaType = detectImageType(source, loaded.contentType);
11178
11185
  if (mediaType === "svg") ctx.features.require("svg-images", path3);
11179
11186
  if (typeof props.alt === "string" && props.alt) {
@@ -13748,6 +13755,55 @@ function textSizeFact(node, props, path3, typography, role) {
13748
13755
  ...size.authored && { sizePath: `${path3}/props/font/size` }
13749
13756
  };
13750
13757
  }
13758
+ function statisticSizeFacts(props, path3, typography) {
13759
+ const named = STATISTIC_SIZE_POINTS[String(props.size)];
13760
+ const styled = (id) => finiteNumber(asRecord2(typography.styles[id])?.size);
13761
+ const numberPoints = named ?? STATISTIC_SIZE_POINTS.medium;
13762
+ const painted = props.size === "small" || props.size === "large" ? numberPoints : styled("StatisticNumber") ?? numberPoints;
13763
+ const present = (value) => value !== void 0 && value !== null && String(value).trim() !== "";
13764
+ const facts = [];
13765
+ const add = (suffix, role, fontSizePt) => facts.push({
13766
+ id: `docx:text-size:${path3}:${suffix}`,
13767
+ kind: "docx/text-size",
13768
+ path: path3,
13769
+ role,
13770
+ fontSizePt,
13771
+ authored: false
13772
+ });
13773
+ if (present(props.number)) add("number", "statistic", painted);
13774
+ if (present(props.unit) || present(props.trend) || present(props.trendValue))
13775
+ add(
13776
+ "suffix",
13777
+ "statistic-suffix",
13778
+ Math.max(12, Math.round(numberPoints)) / 2
13779
+ );
13780
+ if (present(props.description))
13781
+ add(
13782
+ "description",
13783
+ "statistic-description",
13784
+ styled("StatisticDescription") ?? 10
13785
+ );
13786
+ return facts;
13787
+ }
13788
+ function tocSizeFacts(props, path3, typography) {
13789
+ const depth = asRecord2(props.depth);
13790
+ const from = finiteNumber(depth?.from) ?? 1;
13791
+ const to = finiteNumber(depth?.to) ?? 3;
13792
+ const facts = [];
13793
+ for (let level = from; level <= to; level++) {
13794
+ const size = finiteNumber(asRecord2(typography.styles[`TOC${level}`])?.size);
13795
+ if (size === void 0) continue;
13796
+ facts.push({
13797
+ id: `docx:text-size:${path3}:toc${level}`,
13798
+ kind: "docx/text-size",
13799
+ path: path3,
13800
+ role: `toc${level}`,
13801
+ fontSizePt: size,
13802
+ authored: false
13803
+ });
13804
+ }
13805
+ return facts;
13806
+ }
13751
13807
  function tableTextSizeFacts(props, authored, path3, typography, page) {
13752
13808
  const facts = [];
13753
13809
  const sizeOf = (holder) => finiteNumber(asRecord2(asRecord2(holder)?.font)?.size);
@@ -13961,6 +14017,16 @@ function prepareDocxQualityDocument(document, options = {}) {
13961
14017
  (value) => `#${resolveDesignColor2(value, visualColors)}`
13962
14018
  ) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
13963
14019
  const authoredPropsAt = (pointer) => asRecord2(asRecord2(nodeAtPointer(context.document, pointer))?.props);
14020
+ const ownSize = (fact) => {
14021
+ if (!fact?.sizePath) return fact;
14022
+ const written = finiteNumber(
14023
+ asRecord2(authoredPropsAt(fact.path)?.font)?.size
14024
+ );
14025
+ if (written !== void 0) return fact;
14026
+ const inherited2 = { ...fact, authored: false };
14027
+ delete inherited2.sizePath;
14028
+ return inherited2;
14029
+ };
13964
14030
  const roleSizesPt = {};
13965
14031
  for (const key of Object.keys(typography.styles)) {
13966
14032
  const size = effectiveFontSize(
@@ -14114,10 +14180,22 @@ function prepareDocxQualityDocument(document, options = {}) {
14114
14180
  const fact = lineBoxFact(node, props, path3, typography, context.document);
14115
14181
  if (fact) addFact(fact);
14116
14182
  if (typeof props.text === "string" && props.text.trim() !== "") {
14117
- const fact2 = textSizeFact(node, props, path3, typography);
14183
+ const fact2 = ownSize(textSizeFact(node, props, path3, typography));
14118
14184
  if (fact2) addFact({ ...fact2, generated: authoredPath(path3) !== path3 });
14119
14185
  }
14120
14186
  }
14187
+ if (node.name === "list" && Array.isArray(props.items) && props.items.length > 0) {
14188
+ const fact = ownSize(textSizeFact(node, props, path3, typography, "list"));
14189
+ if (fact) addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14190
+ }
14191
+ if (node.name === "statistic") {
14192
+ for (const fact of statisticSizeFacts(props, path3, typography))
14193
+ addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14194
+ }
14195
+ if (node.name === "toc") {
14196
+ for (const fact of tocSizeFacts(props, path3, typography))
14197
+ addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14198
+ }
14121
14199
  if (node.name === "image" || node.name === "visual") {
14122
14200
  for (const fact of svgTextFacts(props, path3)) addFact(fact);
14123
14201
  const drawn = drawnRatio(props);
@@ -14142,6 +14220,7 @@ function prepareDocxQualityDocument(document, options = {}) {
14142
14220
  kind: "docx/heading",
14143
14221
  path: `${path3}/props/level`,
14144
14222
  level,
14223
+ generated: authoredPath(path3) !== path3,
14145
14224
  keepNext: props.keepNext === true || props.keepNext === void 0 && styleKeepNext === true,
14146
14225
  ...previousHeadingLevel !== void 0 && {
14147
14226
  previousLevel: previousHeadingLevel
@@ -14182,7 +14261,10 @@ function prepareDocxQualityDocument(document, options = {}) {
14182
14261
  index,
14183
14262
  words: texts.filter((fact) => bodyRoles.has(fact.role)).reduce((total, fact) => total + wordsOf(fact.text), 0),
14184
14263
  exhibits: own.filter((fact) => exhibitKinds.has(fact.kind)).length,
14185
- headings: texts.filter((fact) => fact.role === "heading").length
14264
+ headings: texts.filter((fact) => fact.role === "heading").length,
14265
+ // Anything the reader sees on the section's own pages: a heading, a
14266
+ // contents field, body copy. Running heads repeat onto any page.
14267
+ rendersText: texts.some((fact) => fact.role !== "chrome")
14186
14268
  });
14187
14269
  if (hasColumnsComponent(rec)) return;
14188
14270
  const page = pageBox(
@@ -14258,10 +14340,15 @@ function isCaptioned(facts, image) {
14258
14340
  return facts.some((fact) => {
14259
14341
  if (fact.kind !== "docx/text") return false;
14260
14342
  const text = fact;
14261
- const near = siblingOf(text.path) === siblingOf(image) || text.path.startsWith(`${image}/`) || image.startsWith(`${text.path}/`);
14343
+ const node = text.path.replace(/\/props(?:\/.*)?$/, "");
14344
+ const beside = siblingOf(node) === siblingOf(image) && Math.abs(indexIn(node) - indexIn(image)) === 1;
14345
+ const near = beside || text.path.startsWith(`${image}/`) || image.startsWith(`${node}/`);
14262
14346
  return near && (text.role === "caption" || CAPTION_LABEL.test(text.text));
14263
14347
  });
14264
14348
  }
14349
+ function indexIn(pointer) {
14350
+ return Number(pointer.slice(pointer.lastIndexOf("/") + 1));
14351
+ }
14265
14352
  function siblingOf(pointer) {
14266
14353
  return pointer.slice(0, pointer.lastIndexOf("/"));
14267
14354
  }