@embedpdf/engine-services 3.0.0-next.4 → 3.0.0-next.5
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.
- package/dist/index.cjs +91 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -15
- package/dist/index.d.ts +18 -15
- package/dist/index.js +92 -44
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -633,23 +633,26 @@ declare class RedactionApplier {
|
|
|
633
633
|
//#region src/features/text/PageTextReader.d.ts
|
|
634
634
|
/**
|
|
635
635
|
* Per-page slow-path text reader. Acquires a `pagePtr` from the
|
|
636
|
-
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`),
|
|
637
|
-
*
|
|
638
|
-
* and releases everything in reverse order.
|
|
636
|
+
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`), extracts
|
|
637
|
+
* the page text, and releases everything in reverse order.
|
|
639
638
|
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
* to a JS string, faithfully preserving surrogate pairs.
|
|
639
|
+
* Index spaces (see engine-core `text/charmap.ts`): `charCount` is the
|
|
640
|
+
* CHARACTER space (`FPDFText_CountChars` — the space geometry runs tile);
|
|
641
|
+
* `text` is the TEXT projection. The two diverge when a character
|
|
642
|
+
* contributes zero text units (non-printing) or two (supplementary plane);
|
|
643
|
+
* `charMap` anchors encode exactly those deviations.
|
|
646
644
|
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
645
|
+
* Both come from the fork's batched extension calls, which share one
|
|
646
|
+
* encoding authority (`FX_UTF16Encode`) so text and map can never
|
|
647
|
+
* disagree:
|
|
648
|
+
*
|
|
649
|
+
* - `EPDFText_GetTextFull` — true UTF-16LE extraction; supplementary
|
|
650
|
+
* characters arrive as surrogate pairs instead of being silently
|
|
651
|
+
* dropped by `FPDFText_GetText`'s UCS-2 encoder. Called once with an
|
|
652
|
+
* upper-bound buffer (2 units per character + NUL), so no measure
|
|
653
|
+
* round-trip.
|
|
654
|
+
* - `EPDFText_GetCharToTextMap` — the anchors, measure-then-fill. Zero
|
|
655
|
+
* anchors is the common (identity) page and skips the fill call.
|
|
653
656
|
*/
|
|
654
657
|
declare class PageTextReader {
|
|
655
658
|
private readonly runtime;
|
package/dist/index.d.ts
CHANGED
|
@@ -633,23 +633,26 @@ declare class RedactionApplier {
|
|
|
633
633
|
//#region src/features/text/PageTextReader.d.ts
|
|
634
634
|
/**
|
|
635
635
|
* Per-page slow-path text reader. Acquires a `pagePtr` from the
|
|
636
|
-
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`),
|
|
637
|
-
*
|
|
638
|
-
* and releases everything in reverse order.
|
|
636
|
+
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`), extracts
|
|
637
|
+
* the page text, and releases everything in reverse order.
|
|
639
638
|
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
* to a JS string, faithfully preserving surrogate pairs.
|
|
639
|
+
* Index spaces (see engine-core `text/charmap.ts`): `charCount` is the
|
|
640
|
+
* CHARACTER space (`FPDFText_CountChars` — the space geometry runs tile);
|
|
641
|
+
* `text` is the TEXT projection. The two diverge when a character
|
|
642
|
+
* contributes zero text units (non-printing) or two (supplementary plane);
|
|
643
|
+
* `charMap` anchors encode exactly those deviations.
|
|
646
644
|
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
645
|
+
* Both come from the fork's batched extension calls, which share one
|
|
646
|
+
* encoding authority (`FX_UTF16Encode`) so text and map can never
|
|
647
|
+
* disagree:
|
|
648
|
+
*
|
|
649
|
+
* - `EPDFText_GetTextFull` — true UTF-16LE extraction; supplementary
|
|
650
|
+
* characters arrive as surrogate pairs instead of being silently
|
|
651
|
+
* dropped by `FPDFText_GetText`'s UCS-2 encoder. Called once with an
|
|
652
|
+
* upper-bound buffer (2 units per character + NUL), so no measure
|
|
653
|
+
* round-trip.
|
|
654
|
+
* - `EPDFText_GetCharToTextMap` — the anchors, measure-then-fill. Zero
|
|
655
|
+
* anchors is the common (identity) page and skips the fill call.
|
|
653
656
|
*/
|
|
654
657
|
declare class PageTextReader {
|
|
655
658
|
private readonly runtime;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbortError, EMPTY_TRANSFER, EngineError, EngineErrorCode, NO_ANNOTATION_FLAGS, PDF_SUBTYPE_TO_CODE, PdfAnnotationSubtypeCode, UNKNOWN_WEAK_ANNOTATION_STATE, appearanceImpactOf, buildPageTextLayout, buildSnippet, foldOptionsFor, foldText, invalidatesWeakIndexRefs, isValidPageObjectNumber, knownWeakAnnotationState, matchLiteral, matchRegex, normalizePdfRect, pdfQuadBounds, revisionTokensEqual, serializeError, shiftsExistingAnnotationIndices, sniffBinaryMetadata, subtypeFromCode, textSegmentsForRange, validateSearchQuery, wirePack } from "@embedpdf/engine-core/runtime";
|
|
1
|
+
import { AbortError, EMPTY_TRANSFER, EngineError, EngineErrorCode, NO_ANNOTATION_FLAGS, PDF_SUBTYPE_TO_CODE, PdfAnnotationSubtypeCode, UNKNOWN_WEAK_ANNOTATION_STATE, appearanceImpactOf, buildPageTextLayout, buildSnippet, charMapViolation, charRangeForTextOffsets, foldOptionsFor, foldText, invalidatesWeakIndexRefs, isValidPageObjectNumber, knownWeakAnnotationState, matchLiteral, matchRegex, normalizePdfRect, pdfQuadBounds, revisionTokensEqual, serializeError, shiftsExistingAnnotationIndices, sniffBinaryMetadata, subtypeFromCode, textSegmentsForRange, validateSearchQuery, wirePack } from "@embedpdf/engine-core/runtime";
|
|
2
2
|
import { NULL_PTR } from "@embedpdf/engine-runtime";
|
|
3
3
|
//#region src/runtime/lifecycle/bootstrap.ts
|
|
4
4
|
const initialized = /* @__PURE__ */ new WeakSet();
|
|
@@ -7061,23 +7061,26 @@ var RedactionApplier = class {
|
|
|
7061
7061
|
//#region src/features/text/PageTextReader.ts
|
|
7062
7062
|
/**
|
|
7063
7063
|
* Per-page slow-path text reader. Acquires a `pagePtr` from the
|
|
7064
|
-
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`),
|
|
7065
|
-
*
|
|
7066
|
-
* and releases everything in reverse order.
|
|
7064
|
+
* `PagePtrPool`, opens a PDFium text page (`FPDFText_LoadPage`), extracts
|
|
7065
|
+
* the page text, and releases everything in reverse order.
|
|
7067
7066
|
*
|
|
7068
|
-
*
|
|
7069
|
-
*
|
|
7070
|
-
*
|
|
7071
|
-
*
|
|
7072
|
-
*
|
|
7073
|
-
* to a JS string, faithfully preserving surrogate pairs.
|
|
7067
|
+
* Index spaces (see engine-core `text/charmap.ts`): `charCount` is the
|
|
7068
|
+
* CHARACTER space (`FPDFText_CountChars` — the space geometry runs tile);
|
|
7069
|
+
* `text` is the TEXT projection. The two diverge when a character
|
|
7070
|
+
* contributes zero text units (non-printing) or two (supplementary plane);
|
|
7071
|
+
* `charMap` anchors encode exactly those deviations.
|
|
7074
7072
|
*
|
|
7075
|
-
*
|
|
7076
|
-
*
|
|
7077
|
-
*
|
|
7078
|
-
*
|
|
7079
|
-
*
|
|
7080
|
-
*
|
|
7073
|
+
* Both come from the fork's batched extension calls, which share one
|
|
7074
|
+
* encoding authority (`FX_UTF16Encode`) so text and map can never
|
|
7075
|
+
* disagree:
|
|
7076
|
+
*
|
|
7077
|
+
* - `EPDFText_GetTextFull` — true UTF-16LE extraction; supplementary
|
|
7078
|
+
* characters arrive as surrogate pairs instead of being silently
|
|
7079
|
+
* dropped by `FPDFText_GetText`'s UCS-2 encoder. Called once with an
|
|
7080
|
+
* upper-bound buffer (2 units per character + NUL), so no measure
|
|
7081
|
+
* round-trip.
|
|
7082
|
+
* - `EPDFText_GetCharToTextMap` — the anchors, measure-then-fill. Zero
|
|
7083
|
+
* anchors is the common (identity) page and skips the fill call.
|
|
7081
7084
|
*/
|
|
7082
7085
|
var PageTextReader = class {
|
|
7083
7086
|
constructor(runtime, session) {
|
|
@@ -7086,7 +7089,7 @@ var PageTextReader = class {
|
|
|
7086
7089
|
}
|
|
7087
7090
|
read(pageObjectNumber, signal) {
|
|
7088
7091
|
throwIfAborted(signal);
|
|
7089
|
-
const { fn
|
|
7092
|
+
const { fn } = this.runtime;
|
|
7090
7093
|
const pool = this.session.pagePool();
|
|
7091
7094
|
const pagePtr = pool.acquire(pageObjectNumber);
|
|
7092
7095
|
try {
|
|
@@ -7095,10 +7098,18 @@ var PageTextReader = class {
|
|
|
7095
7098
|
if (!textPagePtr) throw new EngineError(EngineErrorCode.RuntimeUnavailable, `FPDFText_LoadPage returned null for page object ${pageObjectNumber}`);
|
|
7096
7099
|
try {
|
|
7097
7100
|
throwIfAborted(signal);
|
|
7098
|
-
const charCount = fn.FPDFText_CountChars(textPagePtr);
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7101
|
+
const charCount = Math.max(fn.FPDFText_CountChars(textPagePtr), 0);
|
|
7102
|
+
const text = readTextFull(this.runtime, textPagePtr, charCount);
|
|
7103
|
+
const charMap = readCharMap(this.runtime, textPagePtr, pageObjectNumber);
|
|
7104
|
+
const violation = charMapViolation(charCount, text.length, charMap);
|
|
7105
|
+
if (violation !== null) throw new EngineError(EngineErrorCode.RuntimeUnavailable, `char map invariant violated for page object ${pageObjectNumber}: ${violation}`);
|
|
7106
|
+
return charMap.length > 0 ? {
|
|
7107
|
+
text,
|
|
7108
|
+
charCount,
|
|
7109
|
+
charMap
|
|
7110
|
+
} : {
|
|
7111
|
+
text,
|
|
7112
|
+
charCount
|
|
7102
7113
|
};
|
|
7103
7114
|
} finally {
|
|
7104
7115
|
fn.FPDFText_ClosePage(textPagePtr);
|
|
@@ -7108,11 +7119,43 @@ var PageTextReader = class {
|
|
|
7108
7119
|
}
|
|
7109
7120
|
}
|
|
7110
7121
|
};
|
|
7111
|
-
|
|
7122
|
+
/**
|
|
7123
|
+
* Full-fidelity page text in one call: the buffer is sized at the maximum
|
|
7124
|
+
* possible expansion (every character a surrogate pair, plus the NUL), so
|
|
7125
|
+
* the returned requirement always fits and the measure round-trip is
|
|
7126
|
+
* skipped. The return value counts UTF-16 units INCLUDING the terminator.
|
|
7127
|
+
*/
|
|
7128
|
+
function readTextFull(runtime, textPagePtr, charCount) {
|
|
7112
7129
|
if (charCount <= 0) return "";
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7130
|
+
const { fn, mem } = runtime;
|
|
7131
|
+
const bufUnits = charCount * 2 + 1;
|
|
7132
|
+
return withScratch(mem, bufUnits * 2, (buf) => {
|
|
7133
|
+
const written = fn.EPDFText_GetTextFull(textPagePtr, buf, bufUnits);
|
|
7134
|
+
if (written <= 1) return "";
|
|
7135
|
+
return decodeUtf16Le(mem.readBytes(buf, (written - 1) * 2));
|
|
7136
|
+
});
|
|
7137
|
+
}
|
|
7138
|
+
function decodeUtf16Le(bytes) {
|
|
7139
|
+
const units = new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 1);
|
|
7140
|
+
let out = "";
|
|
7141
|
+
const CHUNK = 8192;
|
|
7142
|
+
for (let i = 0; i < units.length; i += CHUNK) out += String.fromCharCode(...units.subarray(i, Math.min(i + CHUNK, units.length)));
|
|
7143
|
+
return out;
|
|
7144
|
+
}
|
|
7145
|
+
/** Anchor struct layout: two little-endian i32s (see EPDF_CHAR_MAP_ANCHOR). */
|
|
7146
|
+
const ANCHOR_BYTES = 8;
|
|
7147
|
+
function readCharMap(runtime, textPagePtr, pageObjectNumber) {
|
|
7148
|
+
const { fn, mem } = runtime;
|
|
7149
|
+
const count = fn.EPDFText_GetCharToTextMap(textPagePtr, NULL_PTR, 0);
|
|
7150
|
+
if (count < 0) throw new EngineError(EngineErrorCode.RuntimeUnavailable, `EPDFText_GetCharToTextMap failed for page object ${pageObjectNumber}`);
|
|
7151
|
+
if (count === 0) return [];
|
|
7152
|
+
return withScratch(mem, count * ANCHOR_BYTES, (buf) => {
|
|
7153
|
+
fn.EPDFText_GetCharToTextMap(textPagePtr, buf, count);
|
|
7154
|
+
const bytes = mem.readBytes(buf, count * ANCHOR_BYTES);
|
|
7155
|
+
const words = new Int32Array(bytes.buffer, bytes.byteOffset, count * 2);
|
|
7156
|
+
const anchors = new Array(count);
|
|
7157
|
+
for (let i = 0; i < count; i++) anchors[i] = [words[i * 2], words[i * 2 + 1]];
|
|
7158
|
+
return anchors;
|
|
7116
7159
|
});
|
|
7117
7160
|
}
|
|
7118
7161
|
//#endregion
|
|
@@ -8753,7 +8796,7 @@ function emptyResult(index, status) {
|
|
|
8753
8796
|
//#endregion
|
|
8754
8797
|
//#region src/features/search/internal/pageCorpusCache.ts
|
|
8755
8798
|
/**
|
|
8756
|
-
* Per-session, per-page search corpus: the page's
|
|
8799
|
+
* Per-session, per-page search corpus: the page's text snapshot plus its
|
|
8757
8800
|
* DEFAULT fold (the one literal queries with default options search).
|
|
8758
8801
|
* This is the local engine's in-memory equivalent of the server's corpus
|
|
8759
8802
|
* artifacts — same fold version, same shape, built lazily on first search
|
|
@@ -8778,19 +8821,20 @@ function acquirePageCorpus(runtime, session, pageObjectNumber, signal) {
|
|
|
8778
8821
|
cache.set(session, pages);
|
|
8779
8822
|
}
|
|
8780
8823
|
const hit = pages.get(pageObjectNumber);
|
|
8781
|
-
if (hit && hit.seq === seq) return hit
|
|
8782
|
-
const
|
|
8783
|
-
const
|
|
8784
|
-
pages.delete(pageObjectNumber);
|
|
8785
|
-
pages.set(pageObjectNumber, {
|
|
8824
|
+
if (hit && hit.seq === seq) return hit;
|
|
8825
|
+
const snapshot = new PageTextReader(runtime, session).read(pageObjectNumber, signal);
|
|
8826
|
+
const entry = {
|
|
8786
8827
|
seq,
|
|
8787
|
-
folded
|
|
8788
|
-
|
|
8828
|
+
folded: foldText(snapshot.text),
|
|
8829
|
+
snapshot
|
|
8830
|
+
};
|
|
8831
|
+
pages.delete(pageObjectNumber);
|
|
8832
|
+
pages.set(pageObjectNumber, entry);
|
|
8789
8833
|
if (pages.size > MAX_CACHED_PAGES) {
|
|
8790
8834
|
const oldest = pages.keys().next().value;
|
|
8791
8835
|
if (oldest !== void 0) pages.delete(oldest);
|
|
8792
8836
|
}
|
|
8793
|
-
return
|
|
8837
|
+
return entry;
|
|
8794
8838
|
}
|
|
8795
8839
|
//#endregion
|
|
8796
8840
|
//#region src/features/search/internal/searchCursor.ts
|
|
@@ -8899,19 +8943,23 @@ var SearchReader = class {
|
|
|
8899
8943
|
throwIfAborted(signal);
|
|
8900
8944
|
const pon = order[scanned].pageObjectNumber;
|
|
8901
8945
|
const corpus = acquirePageCorpus(this.runtime, this.session, pon, signal);
|
|
8946
|
+
const text = corpus.snapshot.text;
|
|
8902
8947
|
let ranges;
|
|
8903
|
-
if (query.regex) ranges = matchRegex(
|
|
8904
|
-
else if (query.matchCase || query.matchDiacritics) ranges = matchLiteral(foldText(
|
|
8905
|
-
else ranges = matchLiteral(corpus, query);
|
|
8948
|
+
if (query.regex) ranges = matchRegex(text, query);
|
|
8949
|
+
else if (query.matchCase || query.matchDiacritics) ranges = matchLiteral(foldText(text, foldOptionsFor(query)), query);
|
|
8950
|
+
else ranges = matchLiteral(corpus.folded, query);
|
|
8906
8951
|
if (ranges.length > 0) {
|
|
8907
8952
|
const layout = buildPageTextLayout(new PageGeometryReader(this.runtime, this.session).read(pon, signal));
|
|
8908
|
-
for (const range of ranges)
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8953
|
+
for (const range of ranges) {
|
|
8954
|
+
const chars = charRangeForTextOffsets(corpus.snapshot, range.start, range.start + range.length);
|
|
8955
|
+
matches.push({
|
|
8956
|
+
pageObjectNumber: pon,
|
|
8957
|
+
charStart: chars.start,
|
|
8958
|
+
charCount: chars.end - chars.start,
|
|
8959
|
+
segments: textSegmentsForRange(layout, chars.start, chars.end - chars.start),
|
|
8960
|
+
...mode === "full" ? { snippet: buildSnippet(text, range) } : {}
|
|
8961
|
+
});
|
|
8962
|
+
}
|
|
8915
8963
|
}
|
|
8916
8964
|
scanned++;
|
|
8917
8965
|
pagesThisSlice++;
|