js.documents 7.20.34 → 7.20.36

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.
@@ -7,6 +7,7 @@ const require_ports_abort = require("../ports/abort.cjs");
7
7
  const require_layout_lattice = require("./lattice.cjs");
8
8
  let pdf_codec_fonts = require("pdf-codec/fonts");
9
9
  let pdf_codec_afm_widths = require("pdf-codec/afm-widths");
10
+ let pdf_codec_text_group = require("pdf-codec/text-group");
10
11
  //#region src/layout/reconstruct.ts
11
12
  const ZERO_MARGINS = {
12
13
  topPt: 0,
@@ -15,6 +16,9 @@ const ZERO_MARGINS = {
15
16
  leftPt: 0
16
17
  };
17
18
  const LINE_BASELINE_TOLERANCE_FACTOR = .5;
19
+ function sharesBaseline(anchor, item) {
20
+ return (0, pdf_codec_text_group.runsShareBaseline)(anchor, item, { baselineToleranceEm: LINE_BASELINE_TOLERANCE_FACTOR });
21
+ }
18
22
  const DUPLICATE_PAINT_BUCKET_PT = .1;
19
23
  function duplicatePaintKey(item) {
20
24
  const xBucket = Math.round(item.xPt / DUPLICATE_PAINT_BUCKET_PT);
@@ -50,10 +54,9 @@ const REDRAW_PASS_SIMILARITY_THRESHOLD = .6;
50
54
  function groupByBaselineInDocumentOrder(items) {
51
55
  const groups = [];
52
56
  for (const item of items) {
53
- const tolerance = LINE_BASELINE_TOLERANCE_FACTOR * item.sizePt;
54
- const group = groups.find((g) => Math.abs(g.baselineY - item.yPt) <= tolerance);
57
+ const group = groups.find((g) => sharesBaseline(g.anchor, item));
55
58
  if (group === void 0) groups.push({
56
- baselineY: item.yPt,
59
+ anchor: item,
57
60
  items: [item]
58
61
  });
59
62
  else group.items.push(item);
@@ -126,11 +129,11 @@ function clusterIntoLines(items) {
126
129
  const sorted = [...dropDuplicatePaints(dropFuzzyRedrawnPasses(items))].sort((a, b) => b.yPt - a.yPt || a.xPt - b.xPt);
127
130
  const working = [];
128
131
  for (const item of sorted) {
129
- const tolerance = LINE_BASELINE_TOLERANCE_FACTOR * item.sizePt;
130
- const line = working.find((l) => Math.abs(l.baselineY - item.yPt) <= tolerance);
132
+ const line = working.find((l) => sharesBaseline(l.anchor, item));
131
133
  if (line === void 0) working.push({
132
134
  items: [item],
133
- baselineY: item.yPt
135
+ baselineY: item.yPt,
136
+ anchor: item
134
137
  });
135
138
  else line.items.push(item);
136
139
  }
@@ -160,6 +163,10 @@ function textItemToContentRun(item) {
160
163
  };
161
164
  }
162
165
  const MIN_WORD_GAP_PT = .5;
166
+ function gapExceeds(previous, next, thresholdPt) {
167
+ const gap = (0, pdf_codec_text_group.runGapPt)(previous, next);
168
+ return gap !== void 0 && gap > thresholdPt;
169
+ }
163
170
  function textBoxOfItem(item, pageIndex) {
164
171
  const { ascentPt, descentPt } = textItemVerticalExtent(item);
165
172
  return {
@@ -194,9 +201,8 @@ function pushRunsForLine(runs, line, pageIndex) {
194
201
  line.items.forEach((item, itemIndex) => {
195
202
  if (itemIndex > 0) {
196
203
  const prevItem = line.items[itemIndex - 1];
197
- const gap = item.xPt - (prevItem.xPt + (prevItem.widthPt ?? 0));
198
- if (gap > LARGE_GAP_EM_MULTIPLIER * item.sizePt) runs.push({ text: " " });
199
- else if (gap > MIN_WORD_GAP_PT) runs[runs.length - 1].text += " ";
204
+ if (gapExceeds(prevItem, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) runs.push({ text: " " });
205
+ else if (gapExceeds(prevItem, item, MIN_WORD_GAP_PT)) runs[runs.length - 1].text += " ";
200
206
  }
201
207
  const run = textItemToContentRun(item);
202
208
  require_layout_shared.stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
@@ -720,7 +726,7 @@ function splitLineByLargeGaps(line) {
720
726
  line.items.forEach((item, i) => {
721
727
  if (i > 0) {
722
728
  const prev = line.items[i - 1];
723
- if (item.xPt - (prev.xPt + (prev.widthPt ?? 0)) > LARGE_GAP_EM_MULTIPLIER * item.sizePt) {
729
+ if (gapExceeds(prev, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) {
724
730
  segments.push({
725
731
  items: current,
726
732
  baselineY: line.baselineY
@@ -1340,7 +1346,7 @@ function joinCellText(items) {
1340
1346
  sorted.forEach((item, i) => {
1341
1347
  if (i > 0) {
1342
1348
  const prev = sorted[i - 1];
1343
- if (item.xPt - (prev.xPt + (prev.widthPt ?? 0)) > MIN_WORD_GAP_PT) text += " ";
1349
+ if (gapExceeds(prev, item, MIN_WORD_GAP_PT)) text += " ";
1344
1350
  }
1345
1351
  text += item.text;
1346
1352
  });
@@ -6,6 +6,7 @@ import { throwIfAborted } from "../ports/abort.js";
6
6
  import { detectGridLattice, findColumnIndex, findRowIndex } from "./lattice.js";
7
7
  import { resolveStandardFont } from "pdf-codec/fonts";
8
8
  import { STANDARD_METRICS } from "pdf-codec/afm-widths";
9
+ import { runGapPt, runsShareBaseline } from "pdf-codec/text-group";
9
10
  //#region src/layout/reconstruct.ts
10
11
  const ZERO_MARGINS = {
11
12
  topPt: 0,
@@ -14,6 +15,9 @@ const ZERO_MARGINS = {
14
15
  leftPt: 0
15
16
  };
16
17
  const LINE_BASELINE_TOLERANCE_FACTOR = .5;
18
+ function sharesBaseline(anchor, item) {
19
+ return runsShareBaseline(anchor, item, { baselineToleranceEm: LINE_BASELINE_TOLERANCE_FACTOR });
20
+ }
17
21
  const DUPLICATE_PAINT_BUCKET_PT = .1;
18
22
  function duplicatePaintKey(item) {
19
23
  const xBucket = Math.round(item.xPt / DUPLICATE_PAINT_BUCKET_PT);
@@ -49,10 +53,9 @@ const REDRAW_PASS_SIMILARITY_THRESHOLD = .6;
49
53
  function groupByBaselineInDocumentOrder(items) {
50
54
  const groups = [];
51
55
  for (const item of items) {
52
- const tolerance = LINE_BASELINE_TOLERANCE_FACTOR * item.sizePt;
53
- const group = groups.find((g) => Math.abs(g.baselineY - item.yPt) <= tolerance);
56
+ const group = groups.find((g) => sharesBaseline(g.anchor, item));
54
57
  if (group === void 0) groups.push({
55
- baselineY: item.yPt,
58
+ anchor: item,
56
59
  items: [item]
57
60
  });
58
61
  else group.items.push(item);
@@ -125,11 +128,11 @@ function clusterIntoLines(items) {
125
128
  const sorted = [...dropDuplicatePaints(dropFuzzyRedrawnPasses(items))].sort((a, b) => b.yPt - a.yPt || a.xPt - b.xPt);
126
129
  const working = [];
127
130
  for (const item of sorted) {
128
- const tolerance = LINE_BASELINE_TOLERANCE_FACTOR * item.sizePt;
129
- const line = working.find((l) => Math.abs(l.baselineY - item.yPt) <= tolerance);
131
+ const line = working.find((l) => sharesBaseline(l.anchor, item));
130
132
  if (line === void 0) working.push({
131
133
  items: [item],
132
- baselineY: item.yPt
134
+ baselineY: item.yPt,
135
+ anchor: item
133
136
  });
134
137
  else line.items.push(item);
135
138
  }
@@ -159,6 +162,10 @@ function textItemToContentRun(item) {
159
162
  };
160
163
  }
161
164
  const MIN_WORD_GAP_PT = .5;
165
+ function gapExceeds(previous, next, thresholdPt) {
166
+ const gap = runGapPt(previous, next);
167
+ return gap !== void 0 && gap > thresholdPt;
168
+ }
162
169
  function textBoxOfItem(item, pageIndex) {
163
170
  const { ascentPt, descentPt } = textItemVerticalExtent(item);
164
171
  return {
@@ -193,9 +200,8 @@ function pushRunsForLine(runs, line, pageIndex) {
193
200
  line.items.forEach((item, itemIndex) => {
194
201
  if (itemIndex > 0) {
195
202
  const prevItem = line.items[itemIndex - 1];
196
- const gap = item.xPt - (prevItem.xPt + (prevItem.widthPt ?? 0));
197
- if (gap > LARGE_GAP_EM_MULTIPLIER * item.sizePt) runs.push({ text: " " });
198
- else if (gap > MIN_WORD_GAP_PT) runs[runs.length - 1].text += " ";
203
+ if (gapExceeds(prevItem, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) runs.push({ text: " " });
204
+ else if (gapExceeds(prevItem, item, MIN_WORD_GAP_PT)) runs[runs.length - 1].text += " ";
199
205
  }
200
206
  const run = textItemToContentRun(item);
201
207
  stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
@@ -719,7 +725,7 @@ function splitLineByLargeGaps(line) {
719
725
  line.items.forEach((item, i) => {
720
726
  if (i > 0) {
721
727
  const prev = line.items[i - 1];
722
- if (item.xPt - (prev.xPt + (prev.widthPt ?? 0)) > LARGE_GAP_EM_MULTIPLIER * item.sizePt) {
728
+ if (gapExceeds(prev, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) {
723
729
  segments.push({
724
730
  items: current,
725
731
  baselineY: line.baselineY
@@ -1339,7 +1345,7 @@ function joinCellText(items) {
1339
1345
  sorted.forEach((item, i) => {
1340
1346
  if (i > 0) {
1341
1347
  const prev = sorted[i - 1];
1342
- if (item.xPt - (prev.xPt + (prev.widthPt ?? 0)) > MIN_WORD_GAP_PT) text += " ";
1348
+ if (gapExceeds(prev, item, MIN_WORD_GAP_PT)) text += " ";
1343
1349
  }
1344
1350
  text += item.text;
1345
1351
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js.documents",
3
- "version": "7.20.34",
3
+ "version": "7.20.36",
4
4
  "description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -86,7 +86,7 @@
86
86
  "markdown-codec": "7.0.1",
87
87
  "odf.js": "8.0.1",
88
88
  "ooxml.js": "9.1.2",
89
- "pdf-codec": "5.0.1",
89
+ "pdf-codec": "5.2.0",
90
90
  "ppt-codec": "2.0.1",
91
91
  "rtf-codec": "5.0.1",
92
92
  "temml": "0.13.4",