@json-to-office/core-docx 6.6.0 → 6.8.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.
@@ -3764,7 +3764,9 @@ function createDocxJsRenderer() {
3764
3764
  function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
3765
3765
  return new Document({
3766
3766
  styles: emitStyles(ir.styles),
3767
- sections: ir.sections.map((section2) => sectionOptions(section2, resources)),
3767
+ sections: ir.sections.map(
3768
+ (section2, index) => sectionOptions(section2, resources, index === ir.sections.length - 1)
3769
+ ),
3768
3770
  ...coreProperties(ir),
3769
3771
  features: {
3770
3772
  updateFields: ir.settings.updateFields,
@@ -3920,7 +3922,7 @@ function collectImagePlacements(ir) {
3920
3922
  }
3921
3923
  return placements;
3922
3924
  }
3923
- function sectionOptions(section2, resources) {
3925
+ function sectionOptions(section2, resources, closesDocument = false) {
3924
3926
  const { page, columns } = section2.properties;
3925
3927
  const options = {
3926
3928
  properties: {
@@ -3959,7 +3961,7 @@ function sectionOptions(section2, resources) {
3959
3961
  }
3960
3962
  } : {}
3961
3963
  },
3962
- children: sectionChildren(section2, resources)
3964
+ children: sectionChildren(section2, resources, closesDocument)
3963
3965
  };
3964
3966
  const headers = chromeSlots(section2.headers, Header, resources);
3965
3967
  if (headers) options.headers = headers;
@@ -3981,12 +3983,13 @@ function chromeSlots(set, Part, resources) {
3981
3983
  function partChildren(part, resources) {
3982
3984
  return part.children.map((block2) => emitBlock(block2, resources));
3983
3985
  }
3984
- function sectionChildren(section2, resources) {
3986
+ function sectionChildren(section2, resources, closesDocument = false) {
3985
3987
  const blocks = section2.children.map((block2) => emitBlock(block2, resources));
3986
3988
  const bookmark = section2.bookmark;
3987
- if (!bookmark) return blocks;
3989
+ const endsInFrame = closesDocument && lastBlockIsFrame(section2);
3990
+ if (!bookmark && !endsInFrame) return blocks;
3988
3991
  const out = [...blocks];
3989
- if (bookmark.opens) {
3992
+ if (bookmark?.opens) {
3990
3993
  const start = new BookmarkStart2(bookmark.name, bookmark.id);
3991
3994
  const first = out[0];
3992
3995
  if (first instanceof Paragraph2) {
@@ -3995,20 +3998,26 @@ function sectionChildren(section2, resources) {
3995
3998
  out.unshift(anchorParagraph(start));
3996
3999
  }
3997
4000
  }
3998
- if (bookmark.closes) {
4001
+ if (bookmark?.closes) {
3999
4002
  const end = new BookmarkEnd2(bookmark.id);
4000
4003
  const last = out[out.length - 1];
4001
- if (last instanceof Paragraph2) {
4004
+ if (last instanceof Paragraph2 && !endsInFrame) {
4002
4005
  last.addChildElement(end);
4003
4006
  } else {
4004
4007
  out.push(anchorParagraph(end));
4005
4008
  }
4009
+ } else if (endsInFrame) {
4010
+ out.push(anchorParagraph());
4006
4011
  }
4007
4012
  return out;
4008
4013
  }
4014
+ function lastBlockIsFrame(section2) {
4015
+ const last = section2.children[section2.children.length - 1];
4016
+ return last?.kind === "paragraph" && last.frame !== void 0;
4017
+ }
4009
4018
  function anchorParagraph(anchor) {
4010
4019
  return new Paragraph2({
4011
- children: [anchor],
4020
+ children: anchor ? [anchor] : [],
4012
4021
  spacing: { before: 0, after: 0, line: 20, lineRule: LineRuleType2.EXACT }
4013
4022
  });
4014
4023
  }
@@ -4827,7 +4836,7 @@ function borders2(value) {
4827
4836
  }
4828
4837
  return out;
4829
4838
  }
4830
- function section(value, ctx) {
4839
+ function section(value, ctx, closesDocument = false) {
4831
4840
  const { page, columns } = value.properties;
4832
4841
  return {
4833
4842
  properties: {
@@ -4879,7 +4888,7 @@ function section(value, ctx) {
4879
4888
  }
4880
4889
  } : {}
4881
4890
  },
4882
- children: sectionChildren2(value, ctx),
4891
+ children: sectionChildren2(value, ctx, closesDocument),
4883
4892
  ...value.headers ? { headers: headerFooterSet(value.headers, ctx) } : {},
4884
4893
  ...value.footers ? { footers: headerFooterSet(value.footers, ctx) } : {}
4885
4894
  };
@@ -4892,8 +4901,16 @@ function headerFooterSet(set, ctx) {
4892
4901
  }
4893
4902
  return out;
4894
4903
  }
4895
- function sectionChildren2(value, ctx) {
4904
+ function sectionChildren2(value, ctx, closesDocument = false) {
4896
4905
  const blocks = value.children.map((child) => block(child, ctx));
4906
+ const last = value.children[value.children.length - 1];
4907
+ if (closesDocument && last?.kind === "paragraph" && last.frame !== void 0)
4908
+ blocks.push({
4909
+ paragraph: {
4910
+ children: [],
4911
+ spacing: { before: 0, after: 0, line: 20, lineRule: "exact" }
4912
+ }
4913
+ });
4897
4914
  const bookmark = value.bookmark;
4898
4915
  if (!bookmark) return blocks;
4899
4916
  return [
@@ -5062,7 +5079,9 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback) {
5062
5079
  };
5063
5080
  return {
5064
5081
  styles: emitStyles2(ir.styles),
5065
- sections: ir.sections.map((value) => section(value, ctx)),
5082
+ sections: ir.sections.map(
5083
+ (value, index) => section(value, ctx, index === ir.sections.length - 1)
5084
+ ),
5066
5085
  ...coreProperties2(ir),
5067
5086
  features: {
5068
5087
  updateFields: ir.settings.updateFields,
@@ -13755,6 +13774,55 @@ function textSizeFact(node, props, path3, typography, role) {
13755
13774
  ...size.authored && { sizePath: `${path3}/props/font/size` }
13756
13775
  };
13757
13776
  }
13777
+ function statisticSizeFacts(props, path3, typography) {
13778
+ const named = STATISTIC_SIZE_POINTS[String(props.size)];
13779
+ const styled = (id) => finiteNumber(asRecord2(typography.styles[id])?.size);
13780
+ const numberPoints = named ?? STATISTIC_SIZE_POINTS.medium;
13781
+ const painted = props.size === "small" || props.size === "large" ? numberPoints : styled("StatisticNumber") ?? numberPoints;
13782
+ const present = (value) => value !== void 0 && value !== null && String(value).trim() !== "";
13783
+ const facts = [];
13784
+ const add = (suffix, role, fontSizePt) => facts.push({
13785
+ id: `docx:text-size:${path3}:${suffix}`,
13786
+ kind: "docx/text-size",
13787
+ path: path3,
13788
+ role,
13789
+ fontSizePt,
13790
+ authored: false
13791
+ });
13792
+ if (present(props.number)) add("number", "statistic", painted);
13793
+ if (present(props.unit) || present(props.trend) || present(props.trendValue))
13794
+ add(
13795
+ "suffix",
13796
+ "statistic-suffix",
13797
+ Math.max(12, Math.round(numberPoints)) / 2
13798
+ );
13799
+ if (present(props.description))
13800
+ add(
13801
+ "description",
13802
+ "statistic-description",
13803
+ styled("StatisticDescription") ?? 10
13804
+ );
13805
+ return facts;
13806
+ }
13807
+ function tocSizeFacts(props, path3, typography) {
13808
+ const depth = asRecord2(props.depth);
13809
+ const from = finiteNumber(depth?.from) ?? 1;
13810
+ const to = finiteNumber(depth?.to) ?? 3;
13811
+ const facts = [];
13812
+ for (let level = from; level <= to; level++) {
13813
+ const size = finiteNumber(asRecord2(typography.styles[`TOC${level}`])?.size);
13814
+ if (size === void 0) continue;
13815
+ facts.push({
13816
+ id: `docx:text-size:${path3}:toc${level}`,
13817
+ kind: "docx/text-size",
13818
+ path: path3,
13819
+ role: `toc${level}`,
13820
+ fontSizePt: size,
13821
+ authored: false
13822
+ });
13823
+ }
13824
+ return facts;
13825
+ }
13758
13826
  function tableTextSizeFacts(props, authored, path3, typography, page) {
13759
13827
  const facts = [];
13760
13828
  const sizeOf = (holder) => finiteNumber(asRecord2(asRecord2(holder)?.font)?.size);
@@ -13968,6 +14036,16 @@ function prepareDocxQualityDocument(document, options = {}) {
13968
14036
  (value) => `#${resolveDesignColor2(value, visualColors)}`
13969
14037
  ) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
13970
14038
  const authoredPropsAt = (pointer) => asRecord2(asRecord2(nodeAtPointer(context.document, pointer))?.props);
14039
+ const ownSize = (fact) => {
14040
+ if (!fact?.sizePath) return fact;
14041
+ const written = finiteNumber(
14042
+ asRecord2(authoredPropsAt(fact.path)?.font)?.size
14043
+ );
14044
+ if (written !== void 0) return fact;
14045
+ const inherited2 = { ...fact, authored: false };
14046
+ delete inherited2.sizePath;
14047
+ return inherited2;
14048
+ };
13971
14049
  const roleSizesPt = {};
13972
14050
  for (const key of Object.keys(typography.styles)) {
13973
14051
  const size = effectiveFontSize(
@@ -14121,10 +14199,22 @@ function prepareDocxQualityDocument(document, options = {}) {
14121
14199
  const fact = lineBoxFact(node, props, path3, typography, context.document);
14122
14200
  if (fact) addFact(fact);
14123
14201
  if (typeof props.text === "string" && props.text.trim() !== "") {
14124
- const fact2 = textSizeFact(node, props, path3, typography);
14202
+ const fact2 = ownSize(textSizeFact(node, props, path3, typography));
14125
14203
  if (fact2) addFact({ ...fact2, generated: authoredPath(path3) !== path3 });
14126
14204
  }
14127
14205
  }
14206
+ if (node.name === "list" && Array.isArray(props.items) && props.items.length > 0) {
14207
+ const fact = ownSize(textSizeFact(node, props, path3, typography, "list"));
14208
+ if (fact) addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14209
+ }
14210
+ if (node.name === "statistic") {
14211
+ for (const fact of statisticSizeFacts(props, path3, typography))
14212
+ addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14213
+ }
14214
+ if (node.name === "toc") {
14215
+ for (const fact of tocSizeFacts(props, path3, typography))
14216
+ addFact({ ...fact, generated: authoredPath(path3) !== path3 });
14217
+ }
14128
14218
  if (node.name === "image" || node.name === "visual") {
14129
14219
  for (const fact of svgTextFacts(props, path3)) addFact(fact);
14130
14220
  const drawn = drawnRatio(props);
@@ -14149,6 +14239,7 @@ function prepareDocxQualityDocument(document, options = {}) {
14149
14239
  kind: "docx/heading",
14150
14240
  path: `${path3}/props/level`,
14151
14241
  level,
14242
+ generated: authoredPath(path3) !== path3,
14152
14243
  keepNext: props.keepNext === true || props.keepNext === void 0 && styleKeepNext === true,
14153
14244
  ...previousHeadingLevel !== void 0 && {
14154
14245
  previousLevel: previousHeadingLevel
@@ -14189,7 +14280,10 @@ function prepareDocxQualityDocument(document, options = {}) {
14189
14280
  index,
14190
14281
  words: texts.filter((fact) => bodyRoles.has(fact.role)).reduce((total, fact) => total + wordsOf(fact.text), 0),
14191
14282
  exhibits: own.filter((fact) => exhibitKinds.has(fact.kind)).length,
14192
- headings: texts.filter((fact) => fact.role === "heading").length
14283
+ headings: texts.filter((fact) => fact.role === "heading").length,
14284
+ // Anything the reader sees on the section's own pages: a heading, a
14285
+ // contents field, body copy. Running heads repeat onto any page.
14286
+ rendersText: texts.some((fact) => fact.role !== "chrome")
14193
14287
  });
14194
14288
  if (hasColumnsComponent(rec)) return;
14195
14289
  const page = pageBox(
@@ -14265,10 +14359,15 @@ function isCaptioned(facts, image) {
14265
14359
  return facts.some((fact) => {
14266
14360
  if (fact.kind !== "docx/text") return false;
14267
14361
  const text = fact;
14268
- const near = siblingOf(text.path) === siblingOf(image) || text.path.startsWith(`${image}/`) || image.startsWith(`${text.path}/`);
14362
+ const node = text.path.replace(/\/props(?:\/.*)?$/, "");
14363
+ const beside = siblingOf(node) === siblingOf(image) && Math.abs(indexIn(node) - indexIn(image)) === 1;
14364
+ const near = beside || text.path.startsWith(`${image}/`) || image.startsWith(`${node}/`);
14269
14365
  return near && (text.role === "caption" || CAPTION_LABEL.test(text.text));
14270
14366
  });
14271
14367
  }
14368
+ function indexIn(pointer) {
14369
+ return Number(pointer.slice(pointer.lastIndexOf("/") + 1));
14370
+ }
14272
14371
  function siblingOf(pointer) {
14273
14372
  return pointer.slice(0, pointer.lastIndexOf("/"));
14274
14373
  }