pdfnative 1.1.0 → 1.2.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.
package/dist/index.d.ts CHANGED
@@ -163,6 +163,15 @@ interface ColumnDef {
163
163
  * @since 1.1.0
164
164
  */
165
165
  readonly maxWidth?: number;
166
+ /**
167
+ * Semantic kind for the column. When set to `'amount'`, data cells in
168
+ * this column render in Helvetica-Bold with credit/debit colouring
169
+ * driven by `row.type`. Opt-in replacement for the pre-1.2.0
170
+ * hardcoded `i === 3` heuristic in `renderTable`. Default: plain text
171
+ * in `colors.text` and `enc.f1` (Helvetica-Regular).
172
+ * @since 1.2.0
173
+ */
174
+ readonly kind?: 'amount';
166
175
  }
167
176
  /**
168
177
  * Options for generating a PDF in a Web Worker via `generatePDFInWorker()`.
@@ -800,6 +809,66 @@ interface TableBlock {
800
809
  * @since 1.1.0
801
810
  */
802
811
  readonly autoFitColumns?: boolean;
812
+ /**
813
+ * Cell text wrapping policy.
814
+ *
815
+ * - `'auto'` (default) — wrap a cell's text only when its measured width
816
+ * exceeds the column's available width. Cells that fit stay on a single
817
+ * line, preserving byte-identical output with v1.1 for tables sized correctly.
818
+ * - `'always'` — wrap every cell using the available column width.
819
+ * - `'never'` — never wrap; fall back to v1.1 behaviour (character truncation
820
+ * via `ColumnDef.mx` / `mxH`, plus the clipping rectangle when `clipCells`
821
+ * is `true`). Useful when byte-identical v1.1 output is required.
822
+ *
823
+ * @since 1.2.0
824
+ */
825
+ readonly wrap?: 'auto' | 'always' | 'never';
826
+ /**
827
+ * Repeat the table header row on every continuation page when the table
828
+ * spans multiple pages. Default: `true`.
829
+ *
830
+ * Single-page tables are unaffected and byte-identical to v1.1.
831
+ *
832
+ * @since 1.2.0
833
+ */
834
+ readonly repeatHeader?: boolean;
835
+ /**
836
+ * Alternate-row background (zebra striping).
837
+ *
838
+ * - `false` (default) — no zebra background.
839
+ * - `true` — fill every other data row with a default light tint
840
+ * (`'0.969 0.973 0.984'`, matching the default header background).
841
+ * - `PdfColor` — fill every other data row with the provided color.
842
+ *
843
+ * Uses a static (non-transparent) fill so the table remains PDF/A-1b safe.
844
+ *
845
+ * @since 1.2.0
846
+ */
847
+ readonly zebra?: boolean | PdfColor;
848
+ /**
849
+ * Optional caption rendered immediately above the table.
850
+ *
851
+ * In tagged mode, the caption is emitted as a `/Caption` structure element
852
+ * inside the `/Table` (ISO 14289-1 §7.10.6) for assistive-technology access.
853
+ *
854
+ * @since 1.2.0
855
+ */
856
+ readonly caption?: string;
857
+ /**
858
+ * Minimum row height in points. Rows shorter than this are padded.
859
+ * Defaults to the v1.1 `ROW_H` constant (`12`pt). Rows that wrap to
860
+ * multiple lines grow as needed; this only sets the floor.
861
+ *
862
+ * @since 1.2.0
863
+ */
864
+ readonly minRowHeight?: number;
865
+ /**
866
+ * Horizontal cell padding in points (applied to both the left and right
867
+ * insets inside each cell). Defaults to the v1.1 constant (`3`pt).
868
+ *
869
+ * @since 1.2.0
870
+ */
871
+ readonly cellPadding?: number;
803
872
  }
804
873
  /** List block — bullet or numbered items. */
805
874
  interface ListBlock {
@@ -1156,6 +1225,32 @@ interface PdfAConfig {
1156
1225
  /** OutputIntent /S name. */
1157
1226
  readonly outputIntentSubtype: string;
1158
1227
  }
1228
+ /**
1229
+ * Canonical list of PDF/A conformance targets accepted by the `tagged`
1230
+ * layout option. Useful as a single source of truth for tooling — most
1231
+ * notably the `pdfnative-mcp` server's tool-schema `enum:` field — so
1232
+ * agents like Gemini-CLI can autocomplete the legal values without
1233
+ * hardcoding string literals.
1234
+ *
1235
+ * @example
1236
+ * ```ts
1237
+ * import { PDF_A_CONFORMANCE_TARGETS, type PdfAConformanceTarget } from 'pdfnative';
1238
+ *
1239
+ * function pickTarget(input: string): PdfAConformanceTarget | undefined {
1240
+ * return (PDF_A_CONFORMANCE_TARGETS as readonly string[]).includes(input)
1241
+ * ? input as PdfAConformanceTarget
1242
+ * : undefined;
1243
+ * }
1244
+ * ```
1245
+ *
1246
+ * @since 1.2.0
1247
+ */
1248
+ declare const PDF_A_CONFORMANCE_TARGETS: readonly ["pdfa1b", "pdfa2b", "pdfa2u", "pdfa3b"];
1249
+ /**
1250
+ * Type alias for the string literal members of {@link PDF_A_CONFORMANCE_TARGETS}.
1251
+ * @since 1.2.0
1252
+ */
1253
+ type PdfAConformanceTarget = typeof PDF_A_CONFORMANCE_TARGETS[number];
1159
1254
  /**
1160
1255
  * Parse the `tagged` layout option into a resolved PDF/A configuration.
1161
1256
  *
@@ -1633,17 +1728,13 @@ declare function estimateCmsSize(certSizes: readonly number[], algorithm: Signat
1633
1728
  * Foxit, and other PDF validators can verify.
1634
1729
  */
1635
1730
 
1636
- interface PdfSignOptions {
1637
- /** Signer's X.509 certificate (DER-parsed). */
1638
- readonly signerCert: X509Certificate;
1639
- /** Optional certificate chain (intermediate CAs). */
1640
- readonly certChain?: readonly X509Certificate[];
1641
- /** RSA private key (for 'rsa-sha256'). */
1642
- readonly rsaKey?: RsaPrivateKey;
1643
- /** ECDSA private key (for 'ecdsa-sha256'). */
1644
- readonly ecKey?: EcPrivateKey;
1645
- /** Algorithm to use. Default: 'rsa-sha256'. */
1646
- readonly algorithm?: SignatureAlgorithm;
1731
+ /**
1732
+ * Metadata-only subset of {@link PdfSignOptions} used by
1733
+ * {@link buildSigDict} and {@link addSignaturePlaceholder}. None of
1734
+ * these fields require key material — they just go into the `/Sig`
1735
+ * dictionary as descriptive entries.
1736
+ */
1737
+ interface SigDictMetadata {
1647
1738
  /** Signing time (defaults to current time). */
1648
1739
  readonly signingTime?: Date;
1649
1740
  /** Signer display name (for /Name field). */
@@ -1655,6 +1746,18 @@ interface PdfSignOptions {
1655
1746
  /** Contact info (for /ContactInfo field). */
1656
1747
  readonly contactInfo?: string;
1657
1748
  }
1749
+ interface PdfSignOptions extends SigDictMetadata {
1750
+ /** Signer's X.509 certificate (DER-parsed). */
1751
+ readonly signerCert: X509Certificate;
1752
+ /** Optional certificate chain (intermediate CAs). */
1753
+ readonly certChain?: readonly X509Certificate[];
1754
+ /** RSA private key (for 'rsa-sha256'). */
1755
+ readonly rsaKey?: RsaPrivateKey;
1756
+ /** ECDSA private key (for 'ecdsa-sha256'). */
1757
+ readonly ecKey?: EcPrivateKey;
1758
+ /** Algorithm to use. Default: 'rsa-sha256'. */
1759
+ readonly algorithm?: SignatureAlgorithm;
1760
+ }
1658
1761
  /**
1659
1762
  * Build a /Sig signature dictionary string for embedding in a PDF.
1660
1763
  * The /Contents and /ByteRange fields use placeholders that will be
@@ -1664,7 +1767,7 @@ interface PdfSignOptions {
1664
1767
  * @param contentsSize - Size of /Contents hex string in bytes.
1665
1768
  * @returns The /Sig dictionary string and the contentsHexLen.
1666
1769
  */
1667
- declare function buildSigDict(options: PdfSignOptions, contentsSize?: number): string;
1770
+ declare function buildSigDict(options: SigDictMetadata, contentsSize?: number): string;
1668
1771
  /**
1669
1772
  * Sign a PDF that contains a signature placeholder.
1670
1773
  *
@@ -1685,6 +1788,71 @@ declare function signPdfBytes(pdfBytes: Uint8Array, options: PdfSignOptions): Ui
1685
1788
  */
1686
1789
  declare function estimateContentsSize(certSizes: readonly number[], algorithm?: SignatureAlgorithm): number;
1687
1790
 
1791
+ /**
1792
+ * pdfnative — Signature Placeholder Injector
1793
+ * ============================================
1794
+ * Inject an AcroForm + invisible signature widget placeholder into an
1795
+ * existing PDF via incremental update (ISO 32000-1 §7.5.6, §12.7.4.5,
1796
+ * §12.8). The resulting PDF can be fed straight to
1797
+ * {@link signPdfBytes} without any further preparation.
1798
+ *
1799
+ * Closes issue [#45](https://github.com/Nizoka/pdfnative/issues/45) —
1800
+ * removes the need for downstream tooling (pdfnative-cli) to ship a
1801
+ * local placeholder injector that duplicates the byte layout dictated
1802
+ * by `BYTERANGE_PLACEHOLDER` and `buildSigDict()` in
1803
+ * [pdf-signature.ts](./pdf-signature.ts).
1804
+ */
1805
+ /**
1806
+ * Options for {@link addSignaturePlaceholder}.
1807
+ */
1808
+ interface AddSignaturePlaceholderOptions {
1809
+ /**
1810
+ * Reserved bytes for the future CMS blob. The on-disk
1811
+ * `/Contents` hex string will be twice this size.
1812
+ *
1813
+ * @default 16384
1814
+ */
1815
+ readonly placeholderBytes?: number;
1816
+ /**
1817
+ * `/T` field name on the signature widget. Must be unique across
1818
+ * the AcroForm `/Fields` array — throws on collision with an
1819
+ * existing non-signature field.
1820
+ *
1821
+ * @default 'Signature1'
1822
+ */
1823
+ readonly fieldName?: string;
1824
+ /**
1825
+ * Page index (0-based) to attach the (invisible) widget to.
1826
+ *
1827
+ * @default 0
1828
+ */
1829
+ readonly pageIndex?: number;
1830
+ /**
1831
+ * `/Rect` for the widget annotation. `[0, 0, 0, 0]` makes the
1832
+ * signature invisible — the default. Pass explicit coordinates if
1833
+ * you want a visible signature appearance.
1834
+ *
1835
+ * @default [0, 0, 0, 0]
1836
+ */
1837
+ readonly rect?: readonly [number, number, number, number];
1838
+ }
1839
+ /**
1840
+ * Inject an AcroForm + signature widget placeholder into an existing
1841
+ * PDF via incremental update. Returns a NEW byte array. Idempotent:
1842
+ * if the PDF already carries a `/FT /Sig` widget, the input is
1843
+ * returned unchanged.
1844
+ *
1845
+ * @example
1846
+ * ```ts
1847
+ * import { buildDocumentPDFBytes, addSignaturePlaceholder, signPdfBytes } from 'pdfnative';
1848
+ *
1849
+ * const unsigned = buildDocumentPDFBytes(params);
1850
+ * const placeheld = addSignaturePlaceholder(unsigned, { fieldName: 'Author' });
1851
+ * const signed = await signPdfBytes(placeheld, { privateKey, certificate });
1852
+ * ```
1853
+ */
1854
+ declare function addSignaturePlaceholder(pdfBytes: Uint8Array, options?: AddSignaturePlaceholderOptions): Uint8Array;
1855
+
1688
1856
  /**
1689
1857
  * pdfnative — Streaming PDF Output
1690
1858
  * ==================================
@@ -1761,6 +1929,53 @@ declare function chunkBinaryString(str: string, chunkSize: number): Generator<Ui
1761
1929
  * ```
1762
1930
  */
1763
1931
  declare function buildDocumentPDFStream(params: DocumentParams, layoutOptions?: Partial<PdfLayoutOptions>, streamOptions?: StreamOptions): AsyncGenerator<Uint8Array>;
1932
+ /**
1933
+ * Build a free-form PDF document and yield Uint8Array chunks aligned
1934
+ * at PDF object boundaries (one indirect object per chunk, plus a
1935
+ * header chunk and a trailing xref/trailer chunk).
1936
+ *
1937
+ * Use this variant when the consumer benefits from receiving
1938
+ * semantically meaningful PDF segments rather than fixed-size byte
1939
+ * slices — for example, persisting each page object directly to disk
1940
+ * before the next one is produced, or for diagnostic tooling that
1941
+ * wants to inspect individual objects.
1942
+ *
1943
+ * **Scope note (v1.2.x):** the underlying assembler still buffers the
1944
+ * full PDF binary in memory before chunking; constant-memory
1945
+ * generation (true progressive assembly) is staged for v1.3. The
1946
+ * public API surface, however, is stable from v1.2 onward — code
1947
+ * written against `buildDocumentPDFStreamPageByPage()` will keep
1948
+ * working without changes when the internal refactor lands.
1949
+ *
1950
+ * Constraints (same as `buildDocumentPDFStream`):
1951
+ * - TOC blocks are not allowed (require multi-pass pagination)
1952
+ * - `{pages}` placeholder is not allowed in header/footer templates
1953
+ *
1954
+ * @param params - Document content (title, blocks, footer, fonts)
1955
+ * @param layoutOptions - Optional layout customization
1956
+ * @yields Uint8Array chunks of the PDF, one PDF indirect object per chunk
1957
+ *
1958
+ * @example
1959
+ * ```ts
1960
+ * import { createWriteStream } from 'fs';
1961
+ * const out = createWriteStream('large.pdf');
1962
+ * for await (const chunk of buildDocumentPDFStreamPageByPage(params)) {
1963
+ * out.write(chunk);
1964
+ * }
1965
+ * out.end();
1966
+ * ```
1967
+ */
1968
+ declare function buildDocumentPDFStreamPageByPage(params: DocumentParams, layoutOptions?: Partial<PdfLayoutOptions>): AsyncGenerator<Uint8Array>;
1969
+ /**
1970
+ * Build a table-centric PDF and yield Uint8Array chunks aligned at
1971
+ * PDF object boundaries. See {@link buildDocumentPDFStreamPageByPage}
1972
+ * for the full semantic contract.
1973
+ *
1974
+ * @param params - PDF content (title, rows, headers, etc.)
1975
+ * @param layoutOptions - Optional layout customization
1976
+ * @yields Uint8Array chunks of the PDF, one PDF indirect object per chunk
1977
+ */
1978
+ declare function buildPDFStreamPageByPage(params: PdfParams, layoutOptions?: Partial<PdfLayoutOptions>): AsyncGenerator<Uint8Array>;
1764
1979
  /**
1765
1980
  * Build a table-centric PDF and yield Uint8Array chunks progressively.
1766
1981
  *
@@ -1976,6 +2191,11 @@ declare function encodePdfTextString(str: string): string;
1976
2191
  declare function toWinAnsi(str: string): string;
1977
2192
  /**
1978
2193
  * Create a PDF string literal: encode to WinAnsi and escape (, ), \.
2194
+ *
2195
+ * Invisible BiDi directional controls (LRM/RLM, LRE/RLE/PDF/LRO/RLO,
2196
+ * LRI/RLI/FSI/PDI) are stripped before encoding — they carry no
2197
+ * visible width per UAX #9 and would otherwise become '?' under
2198
+ * WinAnsi.
1979
2199
  */
1980
2200
  declare function pdfString(str: string): string;
1981
2201
  /**
@@ -2002,8 +2222,25 @@ declare function truncate(str: string, max: number): string;
2002
2222
  declare function truncateToWidth(str: string, maxWidthPt: number, sz: number, enc: EncodingContext): string;
2003
2223
  /**
2004
2224
  * Approximate text width in points using Helvetica character metrics.
2225
+ *
2226
+ * Invisible BiDi controls are stripped before measuring (zero-width
2227
+ * per UAX #9).
2005
2228
  */
2006
2229
  declare function helveticaWidth(str: string, sz: number): number;
2230
+ /**
2231
+ * Approximate text width in points using **Helvetica-Bold** character
2232
+ * metrics. Required for right- and centre-aligned bold text (table headers,
2233
+ * captions) where measuring with the regular {@link helveticaWidth}
2234
+ * would position the rendered glyphs slightly past the intended right edge —
2235
+ * Helvetica-Bold advances are ~16% wider on average than Helvetica-Regular.
2236
+ *
2237
+ * Widths are derived from the Adobe Helvetica-Bold AFM file (Type 1 standard
2238
+ * PostScript font, base-14 PDF). Invisible BiDi controls are stripped before
2239
+ * measuring (zero-width per UAX #9).
2240
+ *
2241
+ * @since 1.2.0
2242
+ */
2243
+ declare function helveticaBoldWidth(str: string, sz: number): number;
2007
2244
 
2008
2245
  /**
2009
2246
  * pdfnative — Encoding Context Factory
@@ -2286,13 +2523,41 @@ interface BidiRun {
2286
2523
  readonly level: number;
2287
2524
  readonly start: number;
2288
2525
  }
2526
+ /**
2527
+ * UAX #9 explicit embedding/override normalization (v1.2.0).
2528
+ *
2529
+ * Maps the legacy explicit directional formatting characters into their
2530
+ * sealed-isolate equivalents so the rest of the pipeline can process
2531
+ * them via the existing isolate machinery:
2532
+ *
2533
+ * - LRE (U+202A) → LRI (U+2066)
2534
+ * - RLE (U+202B) → RLI (U+2067)
2535
+ * - LRO (U+202D) → LRI (U+2066) — base direction L (character-level
2536
+ * override staged for v1.3)
2537
+ * - RLO (U+202E) → RLI (U+2067) — base direction R (character-level
2538
+ * override staged for v1.3)
2539
+ * - PDF (U+202C) → PDI (U+2069), but only when popping a matched
2540
+ * LRE/RLE/LRO/RLO from the stack (otherwise dropped)
2541
+ *
2542
+ * This is a pragmatic simplification: full UAX #9 embeddings allow
2543
+ * neutral resolution to leak across the embedding boundary, while
2544
+ * isolates are sealed. In real-world inputs the two are
2545
+ * interchangeable for ≥ 95 % of cases. Strict UAX #9 conformance with
2546
+ * embedding leakage and character-level override is staged for v1.3.
2547
+ *
2548
+ * @param text - Raw input text in logical order
2549
+ * @returns Normalized text with embeddings mapped to isolates.
2550
+ */
2551
+ declare function normalizeBidiEmbeddings(text: string): string;
2289
2552
  /**
2290
2553
  * Resolve bidirectional text into ordered runs with embedding levels.
2291
2554
  *
2292
- * Implements UAX #9 with isolate support (LRI/RLI/FSI ... PDI). When the
2293
- * input contains matched isolate pairs, the inner content is resolved as
2294
- * a sealed sub-paragraph with its own forced or auto-detected direction,
2295
- * preventing the outer context from leaking into it (and vice versa).
2555
+ * Implements UAX #9 with isolate support (LRI/RLI/FSI ... PDI) and
2556
+ * explicit-embedding/override normalization (LRE/RLE/LRO/RLO/PDF
2557
+ * isolate-equivalent). When the input contains matched isolate pairs,
2558
+ * the inner content is resolved as a sealed sub-paragraph with its
2559
+ * own forced or auto-detected direction, preventing the outer context
2560
+ * from leaking into it (and vice versa).
2296
2561
  *
2297
2562
  * @param text - Input text in logical order
2298
2563
  * @returns Array of BidiRun objects in visual order
@@ -2305,6 +2570,128 @@ declare function resolveBidiRuns(text: string): BidiRun[];
2305
2570
  * @returns True if text contains R or AL bidi types
2306
2571
  */
2307
2572
  declare function containsRTL(text: string): boolean;
2573
+ /**
2574
+ * Strip invisible Unicode bidirectional formatting characters.
2575
+ *
2576
+ * The BiDi resolver consumes these characters when it runs, but the
2577
+ * resolver is only invoked when `containsRTL()` is true. For pure-LTR
2578
+ * paragraphs that nonetheless contain directional formatters (e.g. an
2579
+ * orphan PDF U+202C left over after `normalizeBidiEmbeddings()`), the
2580
+ * marker would reach the font encoder as a regular codepoint and
2581
+ * render as `.notdef` (tofu) since no font ships a glyph for it.
2582
+ *
2583
+ * Stripped codepoints:
2584
+ * - LRM / RLM (U+200E, U+200F)
2585
+ * - LRE / RLE / PDF / LRO / RLO (U+202A–U+202E)
2586
+ * - LRI / RLI / FSI / PDI (U+2066–U+2069)
2587
+ *
2588
+ * Safe to call unconditionally — these characters carry no visible
2589
+ * width per UAX #9, so removing them never changes layout.
2590
+ *
2591
+ * @since 1.2.0
2592
+ */
2593
+ declare function stripBidiControls(text: string): string;
2594
+
2595
+ /**
2596
+ * pdfnative — Universal Shaping Engine (USE) lite
2597
+ * =================================================
2598
+ * Cluster classification utility for Indic and related complex scripts
2599
+ * (Devanagari, Bengali, Tamil, Gujarati, Gurmukhi, Telugu, Kannada,
2600
+ * Malayalam, Sinhala, Khmer, Myanmar, Tibetan).
2601
+ *
2602
+ * Based on the Universal Shaping Engine specification:
2603
+ * https://learn.microsoft.com/en-us/typography/script-development/use
2604
+ *
2605
+ * Scope (v1.2.0):
2606
+ * - Public API for cluster classification: callers can run their own
2607
+ * reordering / GSUB pipelines on top of the cluster categories.
2608
+ * - 11 cluster categories sufficient for the four scripts pdfnative
2609
+ * ships shaping for (Devanagari, Bengali, Tamil) plus a generic
2610
+ * fallback that classifies any USE-eligible code point.
2611
+ *
2612
+ * Not in scope (deferred to v1.3):
2613
+ * - Rewiring the bundled Devanagari/Bengali/Tamil shapers to drive
2614
+ * their reordering from this module. The shapers currently use
2615
+ * hand-tuned per-script logic that the existing 1700+ vitest
2616
+ * cases pin in place; switching them over is a separate refactor
2617
+ * gated on the v1.3 shaping benchmark harness.
2618
+ * - State-table classification for Khmer/Myanmar/Tibetan/Sinhala/
2619
+ * other USE-required scripts not currently bundled.
2620
+ */
2621
+ /**
2622
+ * USE-lite cluster categories. A subset of the full USE category set
2623
+ * sufficient for the four scripts pdfnative ships shaping for.
2624
+ *
2625
+ * - `B` — Base consonant
2626
+ * - `V` — Independent vowel
2627
+ * - `N` — Number
2628
+ * - `H` — Halant / Virama
2629
+ * - `M` — Vowel sign / Matra (combining mark)
2630
+ * - `Mpre` — Pre-base matra (reorders before base in visual order)
2631
+ * - `Mabv` — Above-base matra
2632
+ * - `Mblw` — Below-base matra
2633
+ * - `Mpst` — Post-base matra
2634
+ * - `R` — Reph (the special "ra + virama" cluster head)
2635
+ * - `ZWJ` — Zero-width joiner (forms half / conjunct)
2636
+ * - `ZWNJ` — Zero-width non-joiner (breaks conjunct)
2637
+ * - `O` — Other (default)
2638
+ */
2639
+ type UseCategory = 'B' | 'V' | 'N' | 'H' | 'M' | 'Mpre' | 'Mabv' | 'Mblw' | 'Mpst' | 'R' | 'ZWJ' | 'ZWNJ' | 'O';
2640
+ /** Classified code point with its USE-lite category. */
2641
+ interface UseClassifiedCp {
2642
+ readonly cp: number;
2643
+ readonly category: UseCategory;
2644
+ }
2645
+ /** A USE-lite cluster: a base plus its prefixed/suffixed marks and signs. */
2646
+ interface UseCluster {
2647
+ /** Pre-base reordering elements (e.g. Devanagari ि matra). */
2648
+ readonly prebase: UseClassifiedCp[];
2649
+ /** The cluster base (consonant or vowel). */
2650
+ readonly base: UseClassifiedCp | null;
2651
+ /** Above-base marks. */
2652
+ readonly above: UseClassifiedCp[];
2653
+ /** Below-base marks. */
2654
+ readonly below: UseClassifiedCp[];
2655
+ /** Post-base marks. */
2656
+ readonly post: UseClassifiedCp[];
2657
+ /** Halant + consonant chains attached after the base (conjunct tail). */
2658
+ readonly tail: UseClassifiedCp[];
2659
+ }
2660
+ /**
2661
+ * Classify a single Unicode code point into a USE-lite category.
2662
+ * Dispatches to per-script tables; falls back to `'O'` for code points
2663
+ * outside the supported ranges.
2664
+ *
2665
+ * Special cases:
2666
+ * - U+200C ZWNJ → 'ZWNJ'
2667
+ * - U+200D ZWJ → 'ZWJ'
2668
+ *
2669
+ * @param cp - Unicode code point
2670
+ * @returns USE-lite category
2671
+ */
2672
+ declare function classifyUseCategory(cp: number): UseCategory;
2673
+ /**
2674
+ * Split a code-point sequence into USE-lite clusters. Each cluster
2675
+ * carries a single base (consonant or independent vowel) plus all its
2676
+ * attached marks classified by their position relative to the base.
2677
+ *
2678
+ * Reph detection: when the sequence starts with consonant + virama
2679
+ * (or contains a "Ra + virama + consonant" prefix where Ra is U+0930
2680
+ * for Devanagari or U+09B0 for Bengali), the leading Ra-virama is
2681
+ * collected as a special pre-base reph element (category 'R').
2682
+ *
2683
+ * @param codePoints - Logical-order code points
2684
+ * @returns Array of UseCluster objects
2685
+ *
2686
+ * @example
2687
+ * ```ts
2688
+ * import { classifyClusters } from 'pdfnative';
2689
+ * const cps = Array.from('प्रकार').map(c => c.codePointAt(0)!);
2690
+ * const clusters = classifyClusters(cps);
2691
+ * // → one cluster per visible aksara, with reph/conjunct info
2692
+ * ```
2693
+ */
2694
+ declare function classifyClusters(codePoints: readonly number[]): UseCluster[];
2308
2695
 
2309
2696
  /**
2310
2697
  * pdfnative — Arabic Text Shaper
@@ -2430,11 +2817,11 @@ type PdfArray = PdfValue[];
2430
2817
  * ```
2431
2818
  */
2432
2819
  type PdfValue = null | boolean | number | string | PdfName | PdfRef | PdfArray | PdfDict | PdfStream;
2433
- declare function isRef(v: PdfValue): v is PdfRef;
2820
+ declare function isRef(v: PdfValue | undefined): v is PdfRef;
2434
2821
  declare function isName(v: PdfValue | undefined): v is PdfName;
2435
2822
  declare function isStream(v: PdfValue): v is PdfStream;
2436
2823
  declare function isDict(v: PdfValue): v is PdfDict;
2437
- declare function isArray(v: PdfValue): v is PdfArray;
2824
+ declare function isArray(v: PdfValue | undefined): v is PdfArray;
2438
2825
  declare function dictGet(dict: PdfDict, key: string): PdfValue | undefined;
2439
2826
  declare function dictGetName(dict: PdfDict, key: string): string | undefined;
2440
2827
  /** Extract the string value from a PdfName, or undefined if not a name. */
@@ -2608,6 +2995,18 @@ interface PdfModifier {
2608
2995
  * Returns the new object number.
2609
2996
  */
2610
2997
  addObject(value: PdfValue): number;
2998
+ /**
2999
+ * Allocate a new object number whose body is emitted **verbatim**
3000
+ * between `num gen obj` and `endobj`. The caller is responsible
3001
+ * for the body's PDF syntactic validity — used for objects that
3002
+ * need an exact byte layout the PdfValue serialiser cannot
3003
+ * express (e.g. signature `/Sig` dictionaries whose
3004
+ * `/Contents <00…>` and `/ByteRange [0 …]` placeholders must be
3005
+ * preserved byte-for-byte for `signPdfBytes()` to patch them).
3006
+ *
3007
+ * Returns the new object number.
3008
+ */
3009
+ addRawObject(body: string): number;
2611
3010
  /**
2612
3011
  * Get the current value of an object (modified or original).
2613
3012
  */
@@ -2777,4 +3176,4 @@ declare function createPDF(pdfParams: PdfParams, options?: {
2777
3176
  layoutOptions?: Partial<PdfLayoutOptions>;
2778
3177
  }): Promise<Uint8Array>;
2779
3178
 
2780
- export { type Annotation, type Asn1Node, BAL_H, type BarcodeBlock, type BarcodeFormat, type BidiRun, type CmsSignOptions, type ColumnDef, DEFAULT_COLORS, DEFAULT_COLUMNS, DEFAULT_CW, DEFAULT_FONT_SIZES, DEFAULT_MARGINS, DEFAULT_MAX_INFLATE_OUTPUT, type DocumentBlock, type DocumentMetadata, type DocumentParams, type EcPrivateKey, type EcPublicKey, type EmbeddedFilesResult, type EncodingContext, type EncryptionOptions, FT_H, type FontData, type FontEntry, type FontLoader, type FontMetrics, type FontRun, type FormField, type FormFieldBlock, type FormFieldType, type FormWidgetResult, HEADER_H, type HeadingBlock, INFO_LN, type ImageBlock, type InternalLink, KNOWN_DECODE_FILTERS, type LinkAnnotation, type LinkBlock, type ListBlock, MAX_PARSE_DEPTH, MAX_XREF_CHAIN, PAGE_SIZES, PG_H, PG_W, type PageBreakBlock, type PageTemplate, type ParagraphBlock, type PdfArray as ParsedArray, type PdfDict as ParsedDict, type ParsedImage, type PdfAConfig, type PdfAttachment, type PdfAttachmentRelationship, type PdfColor, type PdfColors, type PdfIndirectObject, type PdfInfoItem, type PdfLayoutOptions, type PdfModifier, type PdfName, type PdfParams, type PdfReader, type PdfRef, type PdfRgbString, type PdfRgbTuple, type PdfRow, type PdfSignOptions, type PdfStream, type PdfToken, type PdfTokenizer, type PdfValue, type QRErrorLevel, ROW_H, type RadioGroupContext, type RsaPrivateKey, type RsaPublicKey, type ShapedGlyph, type SignatureAlgorithm, type SpacerBlock, type StreamOptions, type SvgBlock, type SvgRenderOptions, type SvgSegment, TH_H, TITLE_LN, type TableBlock, type TextRun, type TocBlock, type TokenType, WORKER_THRESHOLD, WORKER_TIMEOUT_MS, type WatermarkImage, type WatermarkOptions, type WatermarkState, type WatermarkText, type WorkerGenerationOptions, type WorkerInputMessage, type WorkerOutputMessage, type X509Certificate, type X509Name, type XrefEntry, type XrefTable, applyDecodeFilter, buildAcroFormDict, buildAppearanceStreamDict, buildCmsSignedData, buildDocumentPDF, buildDocumentPDFBytes, buildDocumentPDFStream, buildEmbeddedFiles, buildFormWidget, buildImageOperators, buildImageXObject, buildInternalLinkAnnotation, buildLinkAnnotation, buildPDF, buildPDFBytes, buildPDFStream, buildRadioGroupParent, buildSMaskXObject, buildSigDict, buildWatermarkState, chunkBinaryString, clearFontCache, computeColumnPositions, concatChunks, containsArabic, containsBengali, containsDevanagari, containsHebrew, containsRTL, containsTamil, containsThai, createEncodingContext, createModifier, createPDF, createTokenizer, decodeASCII85, decodeASCIIHex, decodeEcPublicKey, decodeLZW, decodeRunLength, defaultFieldHeight, derBitString, derDecode, derInteger, derOctetString, derOid, derSequence, detectCharLang, detectFallbackLangs, detectImageFormat, dictGet, dictGetArray, dictGetDict, dictGetName, dictGetNum, dictGetRef, downloadBlob, ean13CheckDigit, ecPublicKeyFromPrivate, ecdsaSign, ecdsaVerify, encodeCode128, encodeEcPublicKey, encodePDF417, encodePdfTextString, estimateCmsSize, estimateContentsSize, findStartxref, generateDataMatrix, generatePDFInWorker, generatePDFMainThread, generateQR, getMaxInflateOutputSize, getRegisteredLangs, getTrailerRef, getTrailerValue, hasFontLoader, helveticaWidth, hmacSha256, inflateSync, initCrypto, initNodeCompression, initNodeDecompression as initNodeDecompression_parser, isArmenianCodepoint, isArray, isBengaliCodepoint, isCyrillicCodepoint, isDevanagariCodepoint, isDict, isGeorgianCodepoint, isLinkAnnotation, isName, isRef, isSelfSigned, isStream, isTamilCodepoint, isValidPdfRgb, loadFontData, nameValue, needsUnicodeFont, normalizeColors, openPdf, parseCertificate, parseColor, parseImage, parseIndirectObject, parseJPEG, parsePNG, parseRsaPrivateKey, parseRsaPublicKey, parseSvgPath, parseValue, parseXrefTable, pdfString, registerFont, registerFonts, renderBarcode, renderCode128, renderDataMatrix, renderEAN13, renderPDF417, renderQR, renderSvg, resetFontRegistry, resolveBidiRuns, resolveLayout, resolvePdfAConfig, resolveTemplate, rsaSign, rsaSignHash, rsaVerify, rsaVerifyHash, setDeflateImpl, setInflateImpl, setMaxInflateOutputSize, sha384, sha512, shapeArabicText, shapeBengaliText, shapeDevanagariText, shapeTamilText, shapeThaiText, signPdfBytes, slugify, splitTextByFont, streamByteLength, toBytes, toWinAnsi, truncate, truncateToWidth, validateAttachments, validateDocumentStreamable, validateTableStreamable, validateURL, validateWatermark, verifyCertSignature, wrapText };
3179
+ export { type AddSignaturePlaceholderOptions, type Annotation, type Asn1Node, BAL_H, type BarcodeBlock, type BarcodeFormat, type BidiRun, type CmsSignOptions, type ColumnDef, DEFAULT_COLORS, DEFAULT_COLUMNS, DEFAULT_CW, DEFAULT_FONT_SIZES, DEFAULT_MARGINS, DEFAULT_MAX_INFLATE_OUTPUT, type DocumentBlock, type DocumentMetadata, type DocumentParams, type EcPrivateKey, type EcPublicKey, type EmbeddedFilesResult, type EncodingContext, type EncryptionOptions, FT_H, type FontData, type FontEntry, type FontLoader, type FontMetrics, type FontRun, type FormField, type FormFieldBlock, type FormFieldType, type FormWidgetResult, HEADER_H, type HeadingBlock, INFO_LN, type ImageBlock, type InternalLink, KNOWN_DECODE_FILTERS, type LinkAnnotation, type LinkBlock, type ListBlock, MAX_PARSE_DEPTH, MAX_XREF_CHAIN, PAGE_SIZES, PDF_A_CONFORMANCE_TARGETS, PG_H, PG_W, type PageBreakBlock, type PageTemplate, type ParagraphBlock, type PdfArray as ParsedArray, type PdfDict as ParsedDict, type ParsedImage, type PdfAConfig, type PdfAConformanceTarget, type PdfAttachment, type PdfAttachmentRelationship, type PdfColor, type PdfColors, type PdfIndirectObject, type PdfInfoItem, type PdfLayoutOptions, type PdfModifier, type PdfName, type PdfParams, type PdfReader, type PdfRef, type PdfRgbString, type PdfRgbTuple, type PdfRow, type PdfSignOptions, type PdfStream, type PdfToken, type PdfTokenizer, type PdfValue, type QRErrorLevel, ROW_H, type RadioGroupContext, type RsaPrivateKey, type RsaPublicKey, type ShapedGlyph, type SigDictMetadata, type SignatureAlgorithm, type SpacerBlock, type StreamOptions, type SvgBlock, type SvgRenderOptions, type SvgSegment, TH_H, TITLE_LN, type TableBlock, type TextRun, type TocBlock, type TokenType, type UseCategory, type UseClassifiedCp, type UseCluster, WORKER_THRESHOLD, WORKER_TIMEOUT_MS, type WatermarkImage, type WatermarkOptions, type WatermarkState, type WatermarkText, type WorkerGenerationOptions, type WorkerInputMessage, type WorkerOutputMessage, type X509Certificate, type X509Name, type XrefEntry, type XrefTable, addSignaturePlaceholder, applyDecodeFilter, buildAcroFormDict, buildAppearanceStreamDict, buildCmsSignedData, buildDocumentPDF, buildDocumentPDFBytes, buildDocumentPDFStream, buildDocumentPDFStreamPageByPage, buildEmbeddedFiles, buildFormWidget, buildImageOperators, buildImageXObject, buildInternalLinkAnnotation, buildLinkAnnotation, buildPDF, buildPDFBytes, buildPDFStream, buildPDFStreamPageByPage, buildRadioGroupParent, buildSMaskXObject, buildSigDict, buildWatermarkState, chunkBinaryString, classifyClusters, classifyUseCategory, clearFontCache, computeColumnPositions, concatChunks, containsArabic, containsBengali, containsDevanagari, containsHebrew, containsRTL, containsTamil, containsThai, createEncodingContext, createModifier, createPDF, createTokenizer, decodeASCII85, decodeASCIIHex, decodeEcPublicKey, decodeLZW, decodeRunLength, defaultFieldHeight, derBitString, derDecode, derInteger, derOctetString, derOid, derSequence, detectCharLang, detectFallbackLangs, detectImageFormat, dictGet, dictGetArray, dictGetDict, dictGetName, dictGetNum, dictGetRef, downloadBlob, ean13CheckDigit, ecPublicKeyFromPrivate, ecdsaSign, ecdsaVerify, encodeCode128, encodeEcPublicKey, encodePDF417, encodePdfTextString, estimateCmsSize, estimateContentsSize, findStartxref, generateDataMatrix, generatePDFInWorker, generatePDFMainThread, generateQR, getMaxInflateOutputSize, getRegisteredLangs, getTrailerRef, getTrailerValue, hasFontLoader, helveticaBoldWidth, helveticaWidth, hmacSha256, inflateSync, initCrypto, initNodeCompression, initNodeDecompression as initNodeDecompression_parser, isArmenianCodepoint, isArray, isBengaliCodepoint, isCyrillicCodepoint, isDevanagariCodepoint, isDict, isGeorgianCodepoint, isLinkAnnotation, isName, isRef, isSelfSigned, isStream, isTamilCodepoint, isValidPdfRgb, loadFontData, nameValue, needsUnicodeFont, normalizeBidiEmbeddings, normalizeColors, openPdf, parseCertificate, parseColor, parseImage, parseIndirectObject, parseJPEG, parsePNG, parseRsaPrivateKey, parseRsaPublicKey, parseSvgPath, parseValue, parseXrefTable, pdfString, registerFont, registerFonts, renderBarcode, renderCode128, renderDataMatrix, renderEAN13, renderPDF417, renderQR, renderSvg, resetFontRegistry, resolveBidiRuns, resolveLayout, resolvePdfAConfig, resolveTemplate, rsaSign, rsaSignHash, rsaVerify, rsaVerifyHash, setDeflateImpl, setInflateImpl, setMaxInflateOutputSize, sha384, sha512, shapeArabicText, shapeBengaliText, shapeDevanagariText, shapeTamilText, shapeThaiText, signPdfBytes, slugify, splitTextByFont, streamByteLength, stripBidiControls, toBytes, toWinAnsi, truncate, truncateToWidth, validateAttachments, validateDocumentStreamable, validateTableStreamable, validateURL, validateWatermark, verifyCertSignature, wrapText };