@laminapdf/wasm 0.2.0 → 0.3.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.
@@ -44,6 +44,27 @@ export type PageLinkJs = {
44
44
  } & LinkToJs;
45
45
 
46
46
 
47
+ /**
48
+ * A bookmark's look: its colour (`/C`; `None` is the viewer's default, black) and type style
49
+ * (`/F`: bit 1 italic, bit 2 bold).
50
+ *
51
+ * Added in 0.3.0.
52
+ */
53
+ export interface OutlineStyle {
54
+ /**
55
+ * The colour.
56
+ */
57
+ color?: string | null;
58
+ /**
59
+ * Bold.
60
+ */
61
+ bold?: boolean;
62
+ /**
63
+ * Italic.
64
+ */
65
+ italic?: boolean;
66
+ }
67
+
47
68
  /**
48
69
  * A change a signature's restriction forbids.
49
70
  */
@@ -71,12 +92,20 @@ export interface ViolationJs {
71
92
  field?: string;
72
93
  }
73
94
 
95
+ /**
96
+ * A colour of 8 bits a channel, `"#rrggbb"` on the wire. A bookmark's `/C` (§12.3.3,
97
+ * Table 151) holds it as three numbers from 0 to 1.
98
+ *
99
+ * Added in 0.3.0.
100
+ */
101
+ export type Rgb = string;
102
+
74
103
  /**
75
104
  * A conformance claim the document's metadata no longer meets.
76
105
  *
77
106
  * Added in 0.2.0.
78
107
  */
79
- export type ConformanceWarning = { code: "pdfa-one-author"; authors: number } | { code: "pdfua-title-missing" } | { code: "pdfa-info-mismatch"; keys: MetadataKey[] };
108
+ export type ConformanceWarning = { code: "pdfa-one-author"; authors: number } | { code: "pdfua-title-missing" } | { code: "pdfa-info-mismatch"; keys: MetadataKey[] } | { code: "duplicate-tags-incomplete" } | { code: "imported-tags-dropped" } | { code: "imported-pdfa-unchecked" };
80
109
 
81
110
  /**
82
111
  * A conformance profile.
@@ -370,6 +399,32 @@ export interface ModelInfoInit {
370
399
  licence: string;
371
400
  }
372
401
 
402
+ /**
403
+ * A move in user space (ISO 32000-2 §8.3.2.3: y up), in user-space units. Both distances are
404
+ * finite: [`Offset::new`] and the wire form refuse anything else, so a move never writes a
405
+ * coordinate a PDF can't hold.
406
+ *
407
+ * Added in 0.3.0.
408
+ */
409
+ export interface Offset {
410
+ dx: number;
411
+ dy: number;
412
+ }
413
+
414
+ /**
415
+ * A named destination brought in under another name.
416
+ */
417
+ export interface RenamedDestinationJs {
418
+ /**
419
+ * Its name in the source.
420
+ */
421
+ from: string;
422
+ /**
423
+ * Its name in this document.
424
+ */
425
+ to: string;
426
+ }
427
+
373
428
  /**
374
429
  * A page and how to show it.
375
430
  */
@@ -384,11 +439,60 @@ export interface TargetJs {
384
439
  view: TargetViewJs;
385
440
  }
386
441
 
442
+ /**
443
+ * A page of this document and how to show it: what `/Dest [page /XYZ …]` holds.
444
+ *
445
+ * Added in 0.3.0.
446
+ */
447
+ export interface ExplicitDestination {
448
+ /**
449
+ * The page.
450
+ */
451
+ page: string;
452
+ /**
453
+ * How to show it.
454
+ */
455
+ view: DestinationView;
456
+ }
457
+
387
458
  /**
388
459
  * A page-label numbering style.
389
460
  */
390
461
  export type LabelStyleInit = "decimal" | "upperRoman" | "lowerRoman" | "upperLetters" | "lowerLetters";
391
462
 
463
+ /**
464
+ * A patch of the window entries of `/ViewerPreferences` ([`WindowPreferences`]): each field
465
+ * left out keeps what the file has, `true` sets the entry, `false` removes it.
466
+ *
467
+ * Added in 0.3.0.
468
+ */
469
+ export interface WindowPreferencesPatch {
470
+ /**
471
+ * `/HideToolbar`.
472
+ */
473
+ hideToolbar?: boolean;
474
+ /**
475
+ * `/HideMenubar`.
476
+ */
477
+ hideMenubar?: boolean;
478
+ /**
479
+ * `/HideWindowUI`.
480
+ */
481
+ hideWindowUi?: boolean;
482
+ /**
483
+ * `/FitWindow`.
484
+ */
485
+ fitWindow?: boolean;
486
+ /**
487
+ * `/CenterWindow`.
488
+ */
489
+ centerWindow?: boolean;
490
+ /**
491
+ * `/DisplayDocTitle`.
492
+ */
493
+ displayDocTitle?: boolean;
494
+ }
495
+
392
496
  /**
393
497
  * A region's kind.
394
498
  */
@@ -434,6 +538,60 @@ export interface ExtractProgressJs {
434
538
  request?: ModelRequestJs;
435
539
  }
436
540
 
541
+ /**
542
+ * Adds a bookmark under `parent` (`null`: the top level) at `at`, with its title, target and
543
+ * style. It has no children, so it has no open state yet (`/Count`, §12.3.3): set it with
544
+ * [`UpdateOutlineItem::open`] once it has some. The new item's ID is in
545
+ * [`Applied::created_outline_items`](crate::Applied::created_outline_items).
546
+ *
547
+ * On the wire: `{ "op": "addOutlineItem", "args": { "parent": null, "at": "last", "title":
548
+ * "Chapter 1", "target": { "destination": { "page": "p3.0", "view": { "kind": "fit" } } } } }`.
549
+ *
550
+ * Added in 0.3.0.
551
+ */
552
+ export interface AddOutlineItem {
553
+ /**
554
+ * The parent item; `None` for the top level.
555
+ */
556
+ parent?: string | null;
557
+ /**
558
+ * Where among the parent's children.
559
+ */
560
+ at: "first" | "last" | { before: string } | { after: string };
561
+ /**
562
+ * The title.
563
+ */
564
+ title: string;
565
+ /**
566
+ * Where the bookmark goes.
567
+ */
568
+ target: OutlineTarget;
569
+ /**
570
+ * Its colour and type style.
571
+ */
572
+ style?: OutlineStyle;
573
+ }
574
+
575
+ /**
576
+ * Adds a named destination, or points an existing one at `destination`. A name the catalog's
577
+ * `/Dests` dictionary holds stays there; any other goes into the `/Names /Dests` tree.
578
+ *
579
+ * On the wire: `{ "op": "setNamedDestination", "args": { "name": "results", "destination": {
580
+ * "page": "p7.0", "view": { "kind": "fitH", "top": 700 } } } }`.
581
+ *
582
+ * Added in 0.3.0.
583
+ */
584
+ export interface SetNamedDestination {
585
+ /**
586
+ * The name.
587
+ */
588
+ name: string;
589
+ /**
590
+ * Where it points.
591
+ */
592
+ destination: ExplicitDestination;
593
+ }
594
+
437
595
  /**
438
596
  * An OCR word, its box as a region's.
439
597
  */
@@ -452,6 +610,47 @@ export interface WordInit {
452
610
  confidence: number;
453
611
  }
454
612
 
613
+ /**
614
+ * An XMP property declared in a PDF/A file's extension schemas.
615
+ */
616
+ export interface ExtensionPropertyJs {
617
+ /**
618
+ * The schema's namespace URI.
619
+ */
620
+ namespace: string;
621
+ /**
622
+ * The prefix the packet writes the namespace with.
623
+ */
624
+ prefix: string;
625
+ /**
626
+ * The property's local name.
627
+ */
628
+ name: string;
629
+ /**
630
+ * Its declared type, e.g. `Text` or `Seq Integer`.
631
+ */
632
+ valueType: string;
633
+ }
634
+
635
+ /**
636
+ * An annotation's own geometry, by `kind`; points are flat `[x, y, …]` lists in page space.
637
+ */
638
+ export type GeometryJs = { kind: "none" } | { kind: "quads"; quads: number[] } | { kind: "ink"; strokes: number[][] } | { kind: "vertices"; points: number[] } | { kind: "line"; points: number[] } | { kind: "callout"; points: number[] };
639
+
640
+ /**
641
+ * An article thread: its title and its parts in reading order.
642
+ */
643
+ export interface ThreadJs {
644
+ /**
645
+ * Its title (document text), when it has one.
646
+ */
647
+ title?: string;
648
+ /**
649
+ * Its parts.
650
+ */
651
+ parts: ThreadPartJs[];
652
+ }
653
+
455
654
  /**
456
655
  * An attached file's options.
457
656
  */
@@ -493,7 +692,146 @@ export interface AttachmentInit {
493
692
  *
494
693
  * Added in 0.2.0.
495
694
  */
496
- export type Op = { op: "setInfo"; args: SetInfo } | { op: "rotatePage"; args: RotatePage } | { op: "setMetadata"; args: SetMetadata } | { op: "removeMetadata"; args: RemoveMetadata };
695
+ export type Op = { op: "setInfo"; args: SetInfo } | { op: "rotatePage"; args: RotatePage } | { op: "setMetadata"; args: SetMetadata } | { op: "removeMetadata"; args: RemoveMetadata } | { op: "setInitialView"; args: SetInitialView } | { op: "addOutlineItem"; args: AddOutlineItem } | { op: "updateOutlineItem"; args: UpdateOutlineItem } | { op: "moveOutlineItem"; args: MoveOutlineItem } | { op: "deleteOutlineItem"; args: DeleteOutlineItem } | { op: "setNamedDestination"; args: SetNamedDestination } | { op: "renameNamedDestination"; args: RenameNamedDestination } | { op: "deleteNamedDestination"; args: DeleteNamedDestination } | { op: "setXmpProperty"; args: SetXmpProperty } | { op: "removeXmpProperty"; args: RemoveXmpProperty } | { op: "replaceXmpPacket"; args: ReplaceXmpPacket } | { op: "insertBlankPages"; args: InsertBlankPages } | { op: "deletePages"; args: DeletePages } | { op: "movePages"; args: MovePages } | { op: "rotatePages"; args: RotatePages } | { op: "reversePages"; args: ReversePages } | { op: "duplicatePages"; args: DuplicatePages } | { op: "insertPagesFrom"; args: InsertPagesFrom } | { op: "replacePages"; args: ReplacePages } | { op: "mergeDocuments"; args: MergeDocuments } | { op: "updateAnnot"; args: UpdateAnnot } | { op: "deleteAnnot"; args: DeleteAnnot } | { op: "setPageLabels"; args: SetPageLabels };
696
+
697
+ /**
698
+ * Changes a bookmark's title, target, style or open state. An absent field is left alone. A
699
+ * target held as another action (JavaScript, `Launch`, …) is replaced only when `target` is
700
+ * given; the item's other entries are kept.
701
+ *
702
+ * On the wire: `{ "op": "updateOutlineItem", "args": { "item": "o12.0", "title": "Results",
703
+ * "open": true } }`.
704
+ *
705
+ * Added in 0.3.0.
706
+ */
707
+ export interface UpdateOutlineItem {
708
+ /**
709
+ * The item.
710
+ */
711
+ item: string;
712
+ /**
713
+ * A new title.
714
+ */
715
+ title?: string;
716
+ /**
717
+ * A new target.
718
+ */
719
+ target?: OutlineTarget;
720
+ /**
721
+ * A new style (colour and type style together).
722
+ */
723
+ style?: OutlineStyle;
724
+ /**
725
+ * Open (children shown) or closed; a bookmark without children has nowhere to keep it
726
+ * (`/Count`, §12.3.3), so it writes nothing there.
727
+ */
728
+ open?: boolean;
729
+ }
730
+
731
+ /**
732
+ * Changes an annotation's common and markup entries and moves it.
733
+ *
734
+ * An absent field leaves the entry alone and `null` removes it. `translate` moves `/Rect` and
735
+ * the subtype's geometry (`/QuadPoints`, `/InkList`, `/Vertices`, `/L`, `/CL`) and the
736
+ * annotation's Popup with it, and keeps the appearance, which §12.5.5 maps onto the new
737
+ * `/Rect`. A `Locked` annotation refuses everything but a change of its flags and its
738
+ * contents; a `LockedContents` one refuses a change of its contents (`annotation-locked`).
739
+ * Widgets and annotations stored as direct dictionaries are refused (`annotation-not-editable`).
740
+ *
741
+ * On the wire: `{ "op": "updateAnnot", "args": { "id": "a12.0", "contents": "Checked",
742
+ * "translate": { "dx": 0, "dy": -10 } } }`.
743
+ *
744
+ * Added in 0.3.0.
745
+ */
746
+ export interface UpdateAnnot {
747
+ /**
748
+ * The annotation.
749
+ */
750
+ id: string;
751
+ /**
752
+ * `/Contents`: the comment, or the alternative description.
753
+ */
754
+ contents?: string | null;
755
+ /**
756
+ * `/T`: the author.
757
+ */
758
+ author?: string | null;
759
+ /**
760
+ * `/Subj`.
761
+ */
762
+ subject?: string | null;
763
+ /**
764
+ * `/M`, the modification date the edit writes.
765
+ */
766
+ modified?: string;
767
+ /**
768
+ * `/F`, all the flags at once (Table 167).
769
+ */
770
+ flags?: number;
771
+ /**
772
+ * A move in user space.
773
+ */
774
+ translate?: Offset;
775
+ }
776
+
777
+ /**
778
+ * Changes how the document asks to be shown when it opens. Each field is a patch: left out,
779
+ * it keeps what the file has; `null` removes the entry, so readers use their default; a value
780
+ * sets it.
781
+ *
782
+ * * `open`: the page and zoom to open at, written as an explicit destination in
783
+ * `/OpenAction` (§12.3.2.2). An `/OpenAction` that is an action other than `GoTo`
784
+ * (JavaScript, a named action, a link to another file) is never replaced or removed: the op
785
+ * fails with [`Error::OpenActionNotDestination`].
786
+ * * `page_mode`, `page_layout`: the panel to show and how to lay the pages out.
787
+ * * `preferences`: the window entries of `/ViewerPreferences` (§12.2, Table 147); `true` sets
788
+ * one, `false` removes it (its default), and other entries (`/Direction`, `/PrintScaling`, …)
789
+ * are kept.
790
+ *
791
+ * When a value needs a later PDF version than the file declares (`UseAttachments` 1.6,
792
+ * `UseOC` and the two-page layouts 1.5, `/DisplayDocTitle` 1.4), the catalog's `/Version` is
793
+ * raised to it. The op is class [`Document`](crate::ModificationClass::Document) and touches no
794
+ * page.
795
+ *
796
+ * On the wire:
797
+ * `{ "op": "setInitialView", "args": { "open": { "page": "p12.0", "zoom": "fitWidth" },
798
+ * "pageMode": "outlines", "pageLayout": null, "preferences": { "displayDocTitle": true } } }`.
799
+ *
800
+ * ```
801
+ * use laminapdf_ops::{OpenAt, OpenZoom, SetInitialView, WindowPreferencesPatch};
802
+ * use laminapdf_model::PageMode;
803
+ *
804
+ * let op = SetInitialView::default()
805
+ * .with_open(Some(OpenAt::new("p3.0".parse()?, OpenZoom::FitWidth)))
806
+ * .with_page_mode(Some(PageMode::Outlines))
807
+ * .with_preferences(WindowPreferencesPatch::default().with_display_doc_title(true));
808
+ * assert_eq!(
809
+ * serde_json::to_string(&op)?,
810
+ * r#"{"open":{"page":"p3.0","zoom":"fitWidth"},"pageMode":"outlines","preferences":{"displayDocTitle":true}}"#
811
+ * );
812
+ * # Ok::<(), Box<dyn std::error::Error>>(())
813
+ * ```
814
+ *
815
+ * Added in 0.3.0.
816
+ */
817
+ export interface SetInitialView {
818
+ /**
819
+ * The page and zoom to open at.
820
+ */
821
+ open?: OpenAt | null;
822
+ /**
823
+ * The panel to show (`/PageMode`).
824
+ */
825
+ pageMode?: "none" | "outlines" | "thumbnails" | "fullScreen" | "optionalContent" | "attachments" | null;
826
+ /**
827
+ * How to lay the pages out (`/PageLayout`).
828
+ */
829
+ pageLayout?: "singlePage" | "oneColumn" | "twoColumnLeft" | "twoColumnRight" | "twoPageLeft" | "twoPageRight" | null;
830
+ /**
831
+ * The window entries of `/ViewerPreferences`.
832
+ */
833
+ preferences?: WindowPreferencesPatch;
834
+ }
497
835
 
498
836
  /**
499
837
  * Changes to the Info dictionary's text entries. For each field, `None` leaves the entry
@@ -586,6 +924,148 @@ export interface MetadataPatch {
586
924
  modified?: string | null;
587
925
  }
588
926
 
927
+ /**
928
+ * Copies `pages` (each once, in the order given) to `at`. A copy shares its source's content
929
+ * streams and resources and shows what it shows, inherited attributes included (ISO 32000-2
930
+ * §7.7.3.4). Its annotations are new objects with a new `/NM`; a form field's widget becomes
931
+ * a new field named `<partial>#<n>` with its own value, and a signature's widget is not copied
932
+ * (both in [`Applied::fields`](crate::Applied::fields)). In a tagged document the copy gets
933
+ * its own `/StructParents` key and clones of the elements whose content lies only on its
934
+ * source; content of elements that span pages is left untagged and the copy is listed in
935
+ * [`Applied::tags_incomplete`](crate::Applied::tags_incomplete). Page labels continue the range
936
+ * each copy lands in.
937
+ *
938
+ * On the wire: `{ "op": "duplicatePages", "args": { "pages": ["p7.0"], "at": { "after": "p7.0" } } }`.
939
+ *
940
+ * Added in 0.3.0.
941
+ */
942
+ export interface DuplicatePages {
943
+ /**
944
+ * The pages to copy.
945
+ */
946
+ pages: string[];
947
+ /**
948
+ * Where the copies go.
949
+ */
950
+ at: "start" | "end" | { before: string } | { after: string };
951
+ }
952
+
953
+ /**
954
+ * Copies pages of a source document into this one at `at`, in the order given (each once).
955
+ * The copies are new objects with new IDs, sharing nothing with the source. Their
956
+ * annotations point at them and get a new `/NM`; a link to a page that didn't come along is
957
+ * removed ([`Applied::links_removed`](crate::Applied::links_removed)), and the named
958
+ * destinations the others use come along, renamed `<name>#<n>` on a clash. Form fields join
959
+ * the form under their own names, or per [`Carry::fields`] when the name is taken
960
+ * ([`Applied::fields`](crate::Applied::fields)); signature fields are left off. The copies
961
+ * lose their tags ([`Applied::tags_dropped`](crate::Applied::tags_dropped)), page labels
962
+ * continue the range each copy lands in, and the document's version rises to the source's
963
+ * when that is newer.
964
+ *
965
+ * On the wire: `{ "op": "insertPagesFrom", "args": { "source": "<64 hex digits>", "pages":
966
+ * ["p3.0"], "at": "end" } }`, with `carry` optional.
967
+ *
968
+ * Added in 0.3.0.
969
+ */
970
+ export interface InsertPagesFrom {
971
+ /**
972
+ * The source document.
973
+ */
974
+ source: string;
975
+ /**
976
+ * The source's pages to copy, by their IDs in the source.
977
+ */
978
+ pages: string[];
979
+ /**
980
+ * Where the copies go.
981
+ */
982
+ at: "start" | "end" | { before: string } | { after: string };
983
+ /**
984
+ * What comes along with the pages.
985
+ */
986
+ carry?: Carry;
987
+ }
988
+
989
+ /**
990
+ * Deletes `pages` (each once; unknown pages are an error). Outline items, links and `GoTo`
991
+ * actions on surviving pages, named destinations and `/OpenAction` that named a deleted page
992
+ * follow `references` ([`ReferencePolicy`]); structure elements whose content was all on
993
+ * deleted pages are removed with their `/ParentTree` entries, and the widgets on deleted pages
994
+ * leave the form (a field left with none leaves it too). The page objects stay in the file's
995
+ * earlier revisions. Deleting every page is [`Error::NoPagesLeft`].
996
+ *
997
+ * On the wire: `{ "op": "deletePages", "args": { "pages": ["p7.0"], "references": "retarget" } }`.
998
+ *
999
+ * Added in 0.3.0.
1000
+ */
1001
+ export interface DeletePages {
1002
+ /**
1003
+ * The pages.
1004
+ */
1005
+ pages: string[];
1006
+ /**
1007
+ * What happens to destinations that name them; `retarget` when left out.
1008
+ */
1009
+ references?: ReferencePolicy;
1010
+ }
1011
+
1012
+ /**
1013
+ * Deletes a bookmark, and its children with it or moved up into its place.
1014
+ *
1015
+ * On the wire: `{ "op": "deleteOutlineItem", "args": { "item": "o12.0", "children":
1016
+ * "promote" } }`.
1017
+ *
1018
+ * Added in 0.3.0.
1019
+ */
1020
+ export interface DeleteOutlineItem {
1021
+ /**
1022
+ * The item.
1023
+ */
1024
+ item: string;
1025
+ /**
1026
+ * What happens to its children.
1027
+ */
1028
+ children: ChildItems;
1029
+ }
1030
+
1031
+ /**
1032
+ * Deletes a named destination, from both stores when both hold it. Its uses in this file are left as they are and reported
1033
+ * ([`Applied::destination_uses`](crate::Applied::destination_uses)): a bookmark or link that
1034
+ * names it no longer goes anywhere.
1035
+ *
1036
+ * On the wire: `{ "op": "deleteNamedDestination", "args": { "name": "draft-notes" } }`.
1037
+ *
1038
+ * Added in 0.3.0.
1039
+ */
1040
+ export interface DeleteNamedDestination {
1041
+ /**
1042
+ * The name.
1043
+ */
1044
+ name: string;
1045
+ }
1046
+
1047
+ /**
1048
+ * Deletes an annotation with what belongs to it: its Popup, every reply whose `/IRT` chain
1049
+ * reaches it, and, for a member of a group (`/RT /Group`, §12.5.6.2), the whole group, which
1050
+ * is one unit. Chains are followed through cycles once. In a tagged document, the structure
1051
+ * element's object reference to each deleted annotation is removed, and so is an element left
1052
+ * with nothing in it. Each deleted object is freed.
1053
+ *
1054
+ * A `Locked` annotation is refused (`annotation-locked`), and so are widgets and direct
1055
+ * dictionaries (`annotation-not-editable`). Deleting a Popup alone removes the `/Popup` entry
1056
+ * that names it.
1057
+ *
1058
+ * On the wire: `{ "op": "deleteAnnot", "args": { "id": "a12.0" } }`.
1059
+ *
1060
+ * Added in 0.3.0.
1061
+ */
1062
+ export interface DeleteAnnot {
1063
+ /**
1064
+ * The annotation.
1065
+ */
1066
+ id: string;
1067
+ }
1068
+
589
1069
  /**
590
1070
  * Edits the Info dictionary: applies `patch` and, when `at` is given, sets `/ModDate` to it.
591
1071
  *
@@ -650,36 +1130,115 @@ export interface SetMetadata {
650
1130
  }
651
1131
 
652
1132
  /**
653
- * How a destination shows its page (§12.3.2.2).
1133
+ * How [`RotatePages`] reads its angle.
1134
+ *
1135
+ * Added in 0.3.0.
654
1136
  */
655
- export type FitInit = { type: "page" } | { type: "width"; top?: number } | { type: "height"; left?: number } | { type: "xyz"; left?: number; top?: number; zoom?: number } | { type: "rect"; x: number; y: number; width: number; height: number } | { type: "bounds" };
1137
+ export type RotateMode = "set" | "turn";
656
1138
 
657
1139
  /**
658
- * How a file is encrypted, and what its author permits.
1140
+ * How [`images_to_pdf`] sizes its pages.
659
1141
  */
660
- export interface EncryptionJs {
1142
+ export interface ImagesOptionsInit {
661
1143
  /**
662
- * `/V`.
1144
+ * Each page this size, `[width, height]` in points, turned the image's way, the image fitted
1145
+ * inside the margins and centred. Without it, each page is its image's size at the image's
1146
+ * resolution.
663
1147
  */
664
- version: number;
1148
+ fit?: [number, number];
665
1149
  /**
666
- * `/R`.
1150
+ * The space around each image, in points (0 by default).
667
1151
  */
668
- revision: number;
1152
+ margin?: number;
669
1153
  /**
670
- * The key length in bits.
1154
+ * The resolution of an image whose file gives none, in dots per inch (72 by default).
671
1155
  */
672
- keyBits: number;
1156
+ defaultDpi?: number;
673
1157
  /**
674
- * The cipher streams use.
1158
+ * The new document's version, file ID, producer, creation date and compression.
675
1159
  */
676
- cipher: CipherJs;
1160
+ build?: BuildOptionsInit;
1161
+ }
1162
+
1163
+ /**
1164
+ * How a destination shows its page (§12.3.2.2).
1165
+ */
1166
+ export type FitInit = { type: "page" } | { type: "width"; top?: number } | { type: "height"; left?: number } | { type: "xyz"; left?: number; top?: number; zoom?: number } | { type: "rect"; x: number; y: number; width: number; height: number } | { type: "bounds" };
1167
+
1168
+ /**
1169
+ * How a destination shows its page (§12.3.2.2, Table 149), in the page's user space. A `None`
1170
+ * coordinate keeps the viewer's current one (`null` in the file).
1171
+ *
1172
+ * Every number must be finite: the ops refuse any other with `view-not-finite`.
1173
+ *
1174
+ * Added in 0.3.0.
1175
+ */
1176
+ export type DestinationView = { kind: "xyz"; left: number | undefined; top: number | undefined; zoom: number | undefined } | { kind: "fit" } | { kind: "fitH"; top: number | undefined } | { kind: "fitV"; left: number | undefined } | { kind: "fitR"; left: number; bottom: number; right: number; top: number } | { kind: "fitB" } | { kind: "fitBH"; top: number | undefined } | { kind: "fitBV"; left: number | undefined };
1177
+
1178
+ /**
1179
+ * How a document asks to be shown when it opens.
1180
+ */
1181
+ export interface InitialViewJs {
1182
+ /**
1183
+ * Where it opens.
1184
+ */
1185
+ open: OpenTargetJs;
1186
+ /**
1187
+ * The panel to show; left out when the file leaves it to the reader.
1188
+ */
1189
+ pageMode?: "none" | "outlines" | "thumbnails" | "fullScreen" | "optionalContent" | "attachments";
1190
+ /**
1191
+ * How to lay the pages out; left out when the file leaves it to the reader.
1192
+ */
1193
+ pageLayout?: "singlePage" | "oneColumn" | "twoColumnLeft" | "twoColumnRight" | "twoPageLeft" | "twoPageRight";
1194
+ /**
1195
+ * The window's viewer preferences.
1196
+ */
1197
+ preferences: WindowPreferencesJs;
1198
+ }
1199
+
1200
+ /**
1201
+ * How a file is encrypted, and what its author permits.
1202
+ */
1203
+ export interface EncryptionJs {
1204
+ /**
1205
+ * `/V`.
1206
+ */
1207
+ version: number;
1208
+ /**
1209
+ * `/R`.
1210
+ */
1211
+ revision: number;
1212
+ /**
1213
+ * The key length in bits.
1214
+ */
1215
+ keyBits: number;
1216
+ /**
1217
+ * The cipher streams use.
1218
+ */
1219
+ cipher: CipherJs;
677
1220
  /**
678
1221
  * What `/P` permits; absent when the handler gives no permissions.
679
1222
  */
680
1223
  permissions?: PermissionsJs;
681
1224
  }
682
1225
 
1226
+ /**
1227
+ * How a merge brings in what the sources hold besides their pages.
1228
+ *
1229
+ * Added in 0.3.0.
1230
+ */
1231
+ export interface MergeOptions {
1232
+ /**
1233
+ * What becomes of the sources' bookmarks; `perFile` when left out.
1234
+ */
1235
+ outline?: OutlineMerge;
1236
+ /**
1237
+ * What happens to a form field whose name is already used; `rename` when left out.
1238
+ */
1239
+ fields?: FieldClash;
1240
+ }
1241
+
683
1242
  /**
684
1243
  * How a save would go (`laminapdf::PlannedSave`).
685
1244
  */
@@ -795,11 +1354,234 @@ export interface ViewerPreferencesInit {
795
1354
  pageLayout?: PageLayoutInit;
796
1355
  }
797
1356
 
1357
+ /**
1358
+ * Inserts `count` blank pages of `size` at `at`, each showing at `rotate`. Each new page
1359
+ * gets a new object and [`PageId`] (ADR 0005 §5), an empty `/Resources` and no content; in
1360
+ * a labelled document they continue the label range they land in. A count outside 1 to
1361
+ * 10,000, or a side that isn't above 0 and at most 14,400 points, is
1362
+ * [`Error::InvalidOp`](crate::Error::InvalidOp).
1363
+ *
1364
+ * On the wire: `{ "op": "insertBlankPages", "args": { "at": { "after": "p3.0" }, "count": 2,
1365
+ * "size": { "width": 612, "height": 792 }, "rotate": 0 } }`.
1366
+ *
1367
+ * Added in 0.3.0.
1368
+ */
1369
+ export interface InsertBlankPages {
1370
+ /**
1371
+ * Where the pages go.
1372
+ */
1373
+ at: "start" | "end" | { before: string } | { after: string };
1374
+ /**
1375
+ * How many pages, at least 1.
1376
+ */
1377
+ count: number;
1378
+ /**
1379
+ * Their `/MediaBox` size, in points: `{ "width": 612, "height": 792 }`.
1380
+ */
1381
+ size: { width: number; height: number };
1382
+ /**
1383
+ * Their rotation in degrees clockwise: 0, 90, 180 or 270.
1384
+ */
1385
+ rotate: 0 | 90 | 180 | 270;
1386
+ }
1387
+
1388
+ /**
1389
+ * Merges source documents into this one at `at`, one after another, as one edit. Each
1390
+ * source's pages come in as [`InsertPagesFrom`](crate::InsertPagesFrom) brings them (their
1391
+ * annotations, links and the named destinations those use, form fields under the clash rule
1392
+ * of `options.fields`, signature fields left off, tags dropped), and with them what belongs to
1393
+ * the whole source:
1394
+ *
1395
+ * - its bookmarks, per `options.outline`, going to the copies of their pages; a bookmark whose
1396
+ * page didn't come along is left out unless one of its children came
1397
+ * ([`Applied::bookmarks_dropped`](crate::Applied::bookmarks_dropped));
1398
+ * - its layers (optional content groups the copied pages use), added to this document's list
1399
+ * in the source's order and visible or hidden as the source showed them;
1400
+ * - its page labels: each copy keeps the label it had in its source, and this document's
1401
+ * pages keep theirs (a document without labels numbers its pages from 1);
1402
+ * - its form's default appearance and `/NeedAppearances`, and its PDF version when newer.
1403
+ *
1404
+ * Named destinations that clash are renamed `<name>#<n>`
1405
+ * ([`Applied::renamed_destinations`](crate::Applied::renamed_destinations)).
1406
+ *
1407
+ * On the wire: `{ "op": "mergeDocuments", "args": { "sources": [{ "source": "<64 hex
1408
+ * digits>" }], "at": "end" } }`, with each source's `pages` and `title`, and `options`,
1409
+ * optional.
1410
+ *
1411
+ * Added in 0.3.0.
1412
+ */
1413
+ export interface MergeDocuments {
1414
+ /**
1415
+ * The documents to bring in, in order.
1416
+ */
1417
+ sources: MergeSource[];
1418
+ /**
1419
+ * Where their pages go.
1420
+ */
1421
+ at: "start" | "end" | { before: string } | { after: string };
1422
+ /**
1423
+ * What comes along besides the pages.
1424
+ */
1425
+ options?: MergeOptions;
1426
+ }
1427
+
1428
+ /**
1429
+ * Moves `pages` to `to`. They keep their order among themselves (the order given, each page
1430
+ * once) and their IDs; an anchor that is itself moved is replaced by the nearest page that
1431
+ * stays.
1432
+ *
1433
+ * On the wire: `{ "op": "movePages", "args": { "pages": ["p7.0", "p8.0"], "to": "start" } }`.
1434
+ *
1435
+ * Added in 0.3.0.
1436
+ */
1437
+ export interface MovePages {
1438
+ /**
1439
+ * The pages, in the order they take at `to`.
1440
+ */
1441
+ pages: string[];
1442
+ /**
1443
+ * Where they go.
1444
+ */
1445
+ to: "start" | "end" | { before: string } | { after: string };
1446
+ }
1447
+
1448
+ /**
1449
+ * Moves a bookmark, with its children, under `parent` (`null`: the top level) at `at`. The
1450
+ * item keeps its ID.
1451
+ *
1452
+ * On the wire: `{ "op": "moveOutlineItem", "args": { "item": "o12.0", "parent": "o9.0", "at":
1453
+ * { "after": "o10.0" } } }`.
1454
+ *
1455
+ * Added in 0.3.0.
1456
+ */
1457
+ export interface MoveOutlineItem {
1458
+ /**
1459
+ * The item.
1460
+ */
1461
+ item: string;
1462
+ /**
1463
+ * The new parent; `None` for the top level.
1464
+ */
1465
+ parent?: string | null;
1466
+ /**
1467
+ * Where among the new parent's children.
1468
+ */
1469
+ at: "first" | "last" | { before: string } | { after: string };
1470
+ }
1471
+
798
1472
  /**
799
1473
  * Object numbering in a full rewrite.
800
1474
  */
801
1475
  export type RenumberJs = "keep" | "compact";
802
1476
 
1477
+ /**
1478
+ * One annotation on a page, in page space.
1479
+ */
1480
+ export interface PageAnnotationJs {
1481
+ /**
1482
+ * Its ID (`a12.0`), as `updateAnnot` and `deleteAnnot` take it.
1483
+ */
1484
+ id: string;
1485
+ /**
1486
+ * Its position in the page's `/Annots`.
1487
+ */
1488
+ index: number;
1489
+ /**
1490
+ * Its subtype as written (`Highlight`, `Text`, …).
1491
+ */
1492
+ subtype: string;
1493
+ /**
1494
+ * Its rectangle: `[x0, y0, x1, y1]`, top-left and bottom-right; left out when it has none.
1495
+ */
1496
+ rect?: [number, number, number, number];
1497
+ /**
1498
+ * `/Contents` (document text).
1499
+ */
1500
+ contents?: string;
1501
+ /**
1502
+ * `/NM` (document text), only a hint.
1503
+ */
1504
+ name?: string;
1505
+ /**
1506
+ * `/T`, the author.
1507
+ */
1508
+ author?: string;
1509
+ /**
1510
+ * `/Subj`.
1511
+ */
1512
+ subject?: string;
1513
+ /**
1514
+ * `/CreationDate` as stored.
1515
+ */
1516
+ created?: string;
1517
+ /**
1518
+ * `/M` as stored.
1519
+ */
1520
+ modified?: string;
1521
+ /**
1522
+ * `/F`, the flags.
1523
+ */
1524
+ flags: number;
1525
+ /**
1526
+ * `/C`: no components (transparent), one (gray), three (RGB) or four (CMYK).
1527
+ */
1528
+ color: number[];
1529
+ /**
1530
+ * `/CA`, the opacity.
1531
+ */
1532
+ opacity?: number;
1533
+ /**
1534
+ * The ID of the annotation this one replies to or is grouped with.
1535
+ */
1536
+ inReplyTo?: string;
1537
+ /**
1538
+ * Whether `inReplyTo` is a group rather than a reply.
1539
+ */
1540
+ grouped: boolean;
1541
+ /**
1542
+ * The ID of its Popup.
1543
+ */
1544
+ popup?: string;
1545
+ /**
1546
+ * For a Popup, the ID of the annotation it belongs to.
1547
+ */
1548
+ parent?: string;
1549
+ /**
1550
+ * Whether it has a normal appearance stream.
1551
+ */
1552
+ hasAppearance: boolean;
1553
+ /**
1554
+ * Whether it has rich-text contents.
1555
+ */
1556
+ hasRichText: boolean;
1557
+ /**
1558
+ * The subtype's own geometry, as flat `[x, y, …]` lists in page space.
1559
+ */
1560
+ geometry: GeometryJs;
1561
+ }
1562
+
1563
+ /**
1564
+ * One document a merge brings in.
1565
+ *
1566
+ * Added in 0.3.0.
1567
+ */
1568
+ export interface MergeSource {
1569
+ /**
1570
+ * The source document, added with [`Document::add_source`](crate::Document::add_source).
1571
+ */
1572
+ source: string;
1573
+ /**
1574
+ * The source's pages to bring in, by their IDs in the source, in order; all of them when
1575
+ * left out.
1576
+ */
1577
+ pages?: string[];
1578
+ /**
1579
+ * The name of the bookmark [`OutlineMerge::PerFile`] gives the source's bookmarks (a file
1580
+ * name, say); the source's own title when left out.
1581
+ */
1582
+ title?: string;
1583
+ }
1584
+
803
1585
  /**
804
1586
  * One element of the structure tree (`laminapdf::StructureNode`; its strings are document text).
805
1587
  */
@@ -826,6 +1608,14 @@ export interface StructureNodeJs {
826
1608
  kids: StructureKidJs[];
827
1609
  }
828
1610
 
1611
+ /**
1612
+ * One entry of a language alternative, under the name TypeScript gives it.
1613
+ */
1614
+ export interface XmpLangText {
1615
+ lang: string;
1616
+ text: string;
1617
+ }
1618
+
829
1619
  /**
830
1620
  * One font the document uses.
831
1621
  */
@@ -852,6 +1642,20 @@ export interface FontJs {
852
1642
  encoding?: EncodingJs;
853
1643
  }
854
1644
 
1645
+ /**
1646
+ * One named destination and where it goes.
1647
+ */
1648
+ export interface NamedDestinationJs {
1649
+ /**
1650
+ * The name.
1651
+ */
1652
+ name: string;
1653
+ /**
1654
+ * Where it goes, when it names a page of this document.
1655
+ */
1656
+ target?: TargetJs;
1657
+ }
1658
+
855
1659
  /**
856
1660
  * One outline item and its children.
857
1661
  */
@@ -890,6 +1694,10 @@ export interface OutlineEntryInit {
890
1694
  * One outline item.
891
1695
  */
892
1696
  export interface OutlineNodeJs {
1697
+ /**
1698
+ * Its ID (`o12.0`), which the outline ops take.
1699
+ */
1700
+ id: string;
893
1701
  /**
894
1702
  * Its title (document text).
895
1703
  */
@@ -902,6 +1710,30 @@ export interface OutlineNodeJs {
902
1710
  * Where it goes, when its destination names a page of this document.
903
1711
  */
904
1712
  target?: TargetJs;
1713
+ /**
1714
+ * The named destination it goes to, when it names one.
1715
+ */
1716
+ destinationName?: string;
1717
+ /**
1718
+ * The web address it opens, when it has one.
1719
+ */
1720
+ uri?: string;
1721
+ /**
1722
+ * Its action's type when that is neither `GoTo` nor `URI` (`JavaScript`, `Launch`, …).
1723
+ */
1724
+ otherAction?: string;
1725
+ /**
1726
+ * Its colour as `"#rrggbb"`, when it isn't the default black.
1727
+ */
1728
+ color?: string;
1729
+ /**
1730
+ * Shown in bold.
1731
+ */
1732
+ bold: boolean;
1733
+ /**
1734
+ * Shown in italic.
1735
+ */
1736
+ italic: boolean;
905
1737
  /**
906
1738
  * Its children, in order.
907
1739
  */
@@ -960,6 +1792,73 @@ export interface PageLabelInit {
960
1792
  first?: number;
961
1793
  }
962
1794
 
1795
+ /**
1796
+ * One part of an article thread.
1797
+ */
1798
+ export interface ThreadPartJs {
1799
+ /**
1800
+ * The page's 0-based index; left out when the part names a page the document lacks.
1801
+ */
1802
+ page?: number;
1803
+ /**
1804
+ * Its rectangle, `[x0, y0, x1, y1]` in page space; left out when unreadable.
1805
+ */
1806
+ rect?: [number, number, number, number];
1807
+ }
1808
+
1809
+ /**
1810
+ * One range of [`SetPageLabels`]: the labels from `page` up to the next range's page.
1811
+ *
1812
+ * Added in 0.3.0.
1813
+ */
1814
+ export interface PageLabelRange {
1815
+ /**
1816
+ * The range's first page.
1817
+ */
1818
+ page: string;
1819
+ /**
1820
+ * The numbering style; without one, each label is the prefix alone. On the wire:
1821
+ * `decimal`, `upperRoman`, `lowerRoman`, `upperLetters` or `lowerLetters`.
1822
+ */
1823
+ style?: "decimal" | "upperRoman" | "lowerRoman" | "upperLetters" | "lowerLetters";
1824
+ /**
1825
+ * Text before each number (`A-` in `A-1`).
1826
+ */
1827
+ prefix?: string;
1828
+ /**
1829
+ * The number of the range's first page, 1 or more (a `u32`, as the builder's page labels
1830
+ * take).
1831
+ */
1832
+ first?: number;
1833
+ }
1834
+
1835
+ /**
1836
+ * One reference to a deleted page and what the deletion did to it.
1837
+ */
1838
+ export interface ReferenceEditJs {
1839
+ /**
1840
+ * The deleted page it named.
1841
+ */
1842
+ page: string;
1843
+ /**
1844
+ * `outlineItem`, `link`, `namedDestination`, `openAction`, `structureElement`,
1845
+ * `structureKid` or `widget`.
1846
+ */
1847
+ kind: "outlineItem" | "link" | "namedDestination" | "openAction" | "structureElement" | "structureKid" | "widget";
1848
+ /**
1849
+ * The named destination's name, for a `namedDestination`.
1850
+ */
1851
+ name?: string;
1852
+ /**
1853
+ * `retargeted` or `removed`.
1854
+ */
1855
+ outcome: "retargeted" | "removed";
1856
+ /**
1857
+ * The surviving page it now names, when retargeted.
1858
+ */
1859
+ to?: string;
1860
+ }
1861
+
963
1862
  /**
964
1863
  * One text run (`laminapdf::extract::PageTextRun`): glyphs of one font, size, direction and marked
965
1864
  * content on one baseline, in logical order.
@@ -1145,41 +2044,219 @@ export interface SaveOptionsInit {
1145
2044
  */
1146
2045
  metadataDate?: string;
1147
2046
  /**
1148
- * The XMP instance ID the save writes, a UUID (`uuid:` optional); without it, one is
1149
- * derived from the content.
2047
+ * The XMP instance ID the save writes, a UUID (`uuid:` optional); without it, one is
2048
+ * derived from the content.
2049
+ */
2050
+ instanceId?: string;
2051
+ }
2052
+
2053
+ /**
2054
+ * Removes an XMP property, every copy of it in the packet; a property the Info dictionary
2055
+ * mirrors is removed from both. The value stays in the file's earlier revisions until a full
2056
+ * rewrite ([`Applied::still_in_earlier_revisions`](crate::Applied::still_in_earlier_revisions)).
2057
+ *
2058
+ * ```
2059
+ * use laminapdf_ops::{Op, RemoveXmpProperty};
2060
+ *
2061
+ * let op = Op::from(RemoveXmpProperty::new("http://example.com/ns/", "batch"));
2062
+ * assert_eq!(
2063
+ * serde_json::to_string(&op)?,
2064
+ * r#"{"op":"removeXmpProperty","args":{"namespace":"http://example.com/ns/","name":"batch"}}"#
2065
+ * );
2066
+ * # Ok::<(), serde_json::Error>(())
2067
+ * ```
2068
+ *
2069
+ * Added in 0.3.0.
2070
+ */
2071
+ export interface RemoveXmpProperty {
2072
+ /**
2073
+ * The property's namespace URI.
2074
+ */
2075
+ namespace: string;
2076
+ /**
2077
+ * The property's local name.
2078
+ */
2079
+ name: string;
2080
+ /**
2081
+ * As [`SetMetadata::replace_malformed`](crate::SetMetadata::replace_malformed).
2082
+ */
2083
+ replaceMalformed?: boolean;
2084
+ }
2085
+
2086
+ /**
2087
+ * Removes metadata fields from the Info dictionary and the XMP packet; the packet's other
2088
+ * properties stay (J.10).
2089
+ *
2090
+ * The values stay in the file's earlier revisions until a full rewrite: an incremental save
2091
+ * appends the change and keeps the original bytes. When it removed anything, the op's result
2092
+ * says so ([`Applied::still_in_earlier_revisions`](crate::Applied::still_in_earlier_revisions)),
2093
+ * so the caller can offer a full rewrite (on a signed file, the override that removes the
2094
+ * signatures).
2095
+ *
2096
+ * ```
2097
+ * use laminapdf_ops::{MetadataKey, Op, RemoveMetadata};
2098
+ *
2099
+ * let op = Op::from(RemoveMetadata::new(vec![MetadataKey::Authors, MetadataKey::Creator]));
2100
+ * assert_eq!(serde_json::to_string(&op)?, r#"{"op":"removeMetadata","args":{"keys":["authors","creator"]}}"#);
2101
+ * # Ok::<(), serde_json::Error>(())
2102
+ * ```
2103
+ *
2104
+ * Added in 0.2.0.
2105
+ */
2106
+ export interface RemoveMetadata {
2107
+ /**
2108
+ * The fields to remove.
2109
+ */
2110
+ keys: MetadataKey[];
2111
+ /**
2112
+ * As [`SetMetadata::replace_malformed`].
2113
+ */
2114
+ replaceMalformed?: boolean;
2115
+ }
2116
+
2117
+ /**
2118
+ * Renames a named destination, keeping it where it is. With `links: follow` (the default) the
2119
+ * bookmarks, links and `GoTo` actions of this file that name it are renamed too, in the form
2120
+ * they named it in.
2121
+ *
2122
+ * On the wire: `{ "op": "renameNamedDestination", "args": { "from": "sec2", "to": "methods" } }`.
2123
+ *
2124
+ * Added in 0.3.0.
2125
+ */
2126
+ export interface RenameNamedDestination {
2127
+ /**
2128
+ * The current name.
2129
+ */
2130
+ from: string;
2131
+ /**
2132
+ * The new name; no destination may have it yet.
2133
+ */
2134
+ to: string;
2135
+ /**
2136
+ * Whether the uses follow.
2137
+ */
2138
+ links?: RenameLinks;
2139
+ }
2140
+
2141
+ /**
2142
+ * Replaces pages of this document with pages of a source document, pair by pair: the first
2143
+ * source page takes the first target's place, and so on. What pointed at a replaced page
2144
+ * (outline items, links, named destinations, `GoTo` actions, `/OpenAction`) now points at
2145
+ * the page that took its place, with the view `/Fit`, since coordinates on the old page mean
2146
+ * nothing on the new one. Targets left over are deleted (their references retargeted to the
2147
+ * nearest surviving page); source pages left over go after the last copy. The copies come
2148
+ * in as with [`InsertPagesFrom`]; the replaced pages are deleted as with
2149
+ * [`DeletePages`](crate::DeletePages), structure, widgets and earlier revisions included.
2150
+ *
2151
+ * On the wire: `{ "op": "replacePages", "args": { "targets": ["p7.0"], "source": "<64 hex
2152
+ * digits>", "pages": ["p3.0"] } }`, with `carry` optional.
2153
+ *
2154
+ * Added in 0.3.0.
2155
+ */
2156
+ export interface ReplacePages {
2157
+ /**
2158
+ * The pages to replace, in order.
2159
+ */
2160
+ targets: string[];
2161
+ /**
2162
+ * The source document.
2163
+ */
2164
+ source: string;
2165
+ /**
2166
+ * The source's pages that take their places, by their IDs in the source.
2167
+ */
2168
+ pages: string[];
2169
+ /**
2170
+ * What comes along with the pages.
1150
2171
  */
1151
- instanceId?: string;
2172
+ carry?: Carry;
1152
2173
  }
1153
2174
 
1154
2175
  /**
1155
- * Removes metadata fields from the Info dictionary and the XMP packet; the packet's other
1156
- * properties stay (J.10).
2176
+ * Replaces the document's page labels with `ranges`; an empty list removes them, so viewers
2177
+ * show page numbers again.
1157
2178
  *
1158
- * The values stay in the file's earlier revisions until a full rewrite: an incremental save
1159
- * appends the change and keeps the original bytes. When it removed anything, the op's result
1160
- * says so ([`Applied::still_in_earlier_revisions`](crate::Applied::still_in_earlier_revisions)),
1161
- * so the caller can offer a full rewrite (on a signed file, the override that removes the
1162
- * signatures).
2179
+ * Each range starts at a page, named by its ID, and labels that page and the ones after it up
2180
+ * to the next range. The ranges must be in page order, two never on one page, the first on
2181
+ * the document's first page (the number tree must have an entry for page 0, §12.4.2), and
2182
+ * each numbered from 1 or more; otherwise the op fails with `invalid-label-ranges`. Nothing
2183
+ * is written when the catalog already holds exactly these labels
2184
+ * ([`PageLabels::is_written`]); any other tree, a damaged one included, is replaced.
2185
+ *
2186
+ * On the wire:
2187
+ * `{ "op": "setPageLabels", "args": { "ranges": [{ "page": "p3.0", "style": "lowerRoman" }] } }`.
2188
+ *
2189
+ * Added in 0.3.0.
2190
+ */
2191
+ export interface SetPageLabels {
2192
+ /**
2193
+ * The ranges, in page order.
2194
+ */
2195
+ ranges: PageLabelRange[];
2196
+ }
2197
+
2198
+ /**
2199
+ * Replaces the whole XMP packet with `xml`, for what the property ops can't write
2200
+ * (structures, qualifiers, comments). The packet is parsed before it applies and refused if it
2201
+ * doesn't parse (`invalid-xmp-packet`) or changes the PDF/A or PDF/UA identification
2202
+ * (`xmp-claim-read-only`). Info's mirrored entries follow the new packet; in a file that
2203
+ * claims PDF/A, the extension schema entries its properties lack are added and reported
2204
+ * ([`Applied::declared`](crate::Applied::declared)). The old packet stays in the file's
2205
+ * earlier revisions until a full rewrite.
1163
2206
  *
1164
2207
  * ```
1165
- * use laminapdf_ops::{MetadataKey, Op, RemoveMetadata};
2208
+ * use laminapdf_ops::{Op, ReplaceXmpPacket};
1166
2209
  *
1167
- * let op = Op::from(RemoveMetadata::new(vec![MetadataKey::Authors, MetadataKey::Creator]));
1168
- * assert_eq!(serde_json::to_string(&op)?, r#"{"op":"removeMetadata","args":{"keys":["authors","creator"]}}"#);
2210
+ * let op = Op::from(ReplaceXmpPacket::new("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">…</x:xmpmeta>"));
2211
+ * assert!(serde_json::to_string(&op)?.starts_with(r#"{"op":"replaceXmpPacket","args":{"xml":"<x:xmpmeta"#));
1169
2212
  * # Ok::<(), serde_json::Error>(())
1170
2213
  * ```
1171
2214
  *
1172
- * Added in 0.2.0.
2215
+ * Added in 0.3.0.
1173
2216
  */
1174
- export interface RemoveMetadata {
2217
+ export interface ReplaceXmpPacket {
1175
2218
  /**
1176
- * The fields to remove.
2219
+ * The new packet's XML, with or without its `<?xpacket … ?>` wrapper.
1177
2220
  */
1178
- keys: MetadataKey[];
2221
+ xml: string;
2222
+ }
2223
+
2224
+ /**
2225
+ * Reverses the order of `pages` within the places they hold: the first of them (in page
2226
+ * order) takes the last one's place, and so on; the other pages don't move.
2227
+ *
2228
+ * On the wire: `{ "op": "reversePages", "args": { "pages": ["p3.0", "p4.0", "p5.0"] } }`.
2229
+ *
2230
+ * Added in 0.3.0.
2231
+ */
2232
+ export interface ReversePages {
1179
2233
  /**
1180
- * As [`SetMetadata::replace_malformed`].
2234
+ * The pages; their order here doesn't matter.
1181
2235
  */
1182
- replaceMalformed?: boolean;
2236
+ pages: string[];
2237
+ }
2238
+
2239
+ /**
2240
+ * Rotates `pages` by `angle`, set or turned ([`RotateMode`]); each page as
2241
+ * [`RotatePage`] does, keeping its object and [`PageId`].
2242
+ *
2243
+ * On the wire: `{ "op": "rotatePages", "args": { "pages": ["p3.0"], "angle": 90, "mode": "turn" } }`.
2244
+ *
2245
+ * Added in 0.3.0.
2246
+ */
2247
+ export interface RotatePages {
2248
+ /**
2249
+ * The pages.
2250
+ */
2251
+ pages: string[];
2252
+ /**
2253
+ * The angle in degrees clockwise: 0, 90, 180 or 270.
2254
+ */
2255
+ angle: 0 | 90 | 180 | 270;
2256
+ /**
2257
+ * Whether the angle is set or added; `set` when left out.
2258
+ */
2259
+ mode?: RotateMode;
1183
2260
  }
1184
2261
 
1185
2262
  /**
@@ -1208,6 +2285,60 @@ export interface RotatePage {
1208
2285
  rotate: 0 | 90 | 180 | 270;
1209
2286
  }
1210
2287
 
2288
+ /**
2289
+ * Sets any XMP property: text, a URI, a number, a boolean, a date, a language alternative,
2290
+ * or an ordered or unordered array of simple values. A file without a packet gets one.
2291
+ *
2292
+ * `prefix` names the namespace when the packet binds no prefix to it. A property the Info
2293
+ * dictionary mirrors (`dc:title`, `pdf:Producer`, …) is set in both, as
2294
+ * [`SetMetadata`](crate::SetMetadata) sets it, and must have its shape: text, or a language
2295
+ * alternative of the `x-default` entry alone, for `dc:title` and `dc:description`; an array of
2296
+ * text for `dc:creator`; a date for the dates.
2297
+ *
2298
+ * ```
2299
+ * use laminapdf_ops::{Op, SetXmpProperty};
2300
+ * use laminapdf_model::xmp::XmpValue;
2301
+ *
2302
+ * let op = Op::from(SetXmpProperty::new("http://example.com/ns/", "acme", "batch", XmpValue::Integer(42)));
2303
+ * assert_eq!(
2304
+ * serde_json::to_string(&op)?,
2305
+ * r#"{"op":"setXmpProperty","args":{"namespace":"http://example.com/ns/","prefix":"acme","name":"batch","value":{"type":"integer","value":42}}}"#
2306
+ * );
2307
+ * # Ok::<(), serde_json::Error>(())
2308
+ * ```
2309
+ *
2310
+ * Added in 0.3.0.
2311
+ */
2312
+ export interface SetXmpProperty {
2313
+ /**
2314
+ * The property's namespace URI.
2315
+ */
2316
+ namespace: string;
2317
+ /**
2318
+ * The prefix to write the namespace with when the packet binds none.
2319
+ */
2320
+ prefix: string;
2321
+ /**
2322
+ * The property's local name.
2323
+ */
2324
+ name: string;
2325
+ /**
2326
+ * The new value.
2327
+ */
2328
+ value: XmpValue;
2329
+ /**
2330
+ * As [`SetMetadata::replace_malformed`](crate::SetMetadata::replace_malformed).
2331
+ */
2332
+ replaceMalformed?: boolean;
2333
+ }
2334
+
2335
+ /**
2336
+ * Something in the file that names a destination.
2337
+ *
2338
+ * Added in 0.3.0.
2339
+ */
2340
+ export type DestinationUse = { kind: "outlineItem"; item: string } | { kind: "annotation"; page: string; annot: string } | { kind: "catalog" };
2341
+
1211
2342
  /**
1212
2343
  * The Info dictionary's text entries; absent ones are left out (document text).
1213
2344
  */
@@ -1291,6 +2422,24 @@ export interface MetadataInit {
1291
2422
  modDate?: string;
1292
2423
  }
1293
2424
 
2425
+ /**
2426
+ * The document's XMP packet as text (`laminapdf::XmpText`).
2427
+ */
2428
+ export interface XmpTextJs {
2429
+ /**
2430
+ * Whether there is a packet, and whether it was read.
2431
+ */
2432
+ status: PacketStatus;
2433
+ /**
2434
+ * The packet's XML, with the edits made so far.
2435
+ */
2436
+ xml?: string;
2437
+ /**
2438
+ * The PDF/A part and conformance the packet claims, e.g. `"2B"`.
2439
+ */
2440
+ pdfa?: string;
2441
+ }
2442
+
1294
2443
  /**
1295
2444
  * The kind of change an op makes. The save planner checks it against `DocMDP` / `FieldMDP`
1296
2445
  * permissions and the document's `SaveConstraint` ([ADR 0007]).
@@ -1323,6 +2472,22 @@ export interface ModelsInit {
1323
2472
  langs?: string[];
1324
2473
  }
1325
2474
 
2475
+ /**
2476
+ * The page and zoom a document opens at.
2477
+ *
2478
+ * Added in 0.3.0.
2479
+ */
2480
+ export interface OpenAt {
2481
+ /**
2482
+ * The page.
2483
+ */
2484
+ page: string;
2485
+ /**
2486
+ * The zoom.
2487
+ */
2488
+ zoom?: "default" | "fitPage" | "fitWidth" | number;
2489
+ }
2490
+
1326
2491
  /**
1327
2492
  * The pages an edit touched.
1328
2493
  */
@@ -1340,11 +2505,71 @@ export interface EditedJs {
1340
2505
  * full rewrite drops.
1341
2506
  */
1342
2507
  stillInEarlierRevisions: boolean;
2508
+ /**
2509
+ * IDs of annotations an annotation op deleted besides the one it names (Popups, replies,
2510
+ * the rest of a group); left out when there are none.
2511
+ */
2512
+ alsoDeleted?: string[];
1343
2513
  /**
1344
2514
  * Whether the edit changed the document: one that only set values they already had leaves
1345
2515
  * no step to undo.
1346
2516
  */
1347
2517
  changed: boolean;
2518
+ /**
2519
+ * The IDs of the bookmarks the edit added, in order.
2520
+ */
2521
+ createdOutlineItems: string[];
2522
+ /**
2523
+ * An outline edit found the outline's links broken and rewrote them whole; bookmarks
2524
+ * stored inside others have new IDs.
2525
+ */
2526
+ outlineRepaired: boolean;
2527
+ /**
2528
+ * What still names a named destination the edit deleted.
2529
+ */
2530
+ destinationUses: DestinationUse[];
2531
+ /**
2532
+ * The XMP properties the edit declared in a PDF/A file's extension schemas.
2533
+ */
2534
+ declared: ExtensionPropertyJs[];
2535
+ /**
2536
+ * The page IDs in order after the edit, when it changed the page list.
2537
+ */
2538
+ pageOrder?: string[];
2539
+ /**
2540
+ * What a page deletion did to the references to the deleted pages.
2541
+ */
2542
+ references: ReferenceEditJs[];
2543
+ /**
2544
+ * What a page duplication did to the form fields whose widgets the copied pages show;
2545
+ * left out when there are none.
2546
+ */
2547
+ fields?: FieldEditJs[];
2548
+ /**
2549
+ * The copies a page duplication made whose tags couldn't all be cloned; left out when
2550
+ * there are none.
2551
+ */
2552
+ tagsIncomplete?: string[];
2553
+ /**
2554
+ * The page holding each link a page copied in from another document lost, one entry per
2555
+ * link; left out when there are none.
2556
+ */
2557
+ linksRemoved?: string[];
2558
+ /**
2559
+ * The pages copied in from another document without the tags their source gave them; left
2560
+ * out when there are none.
2561
+ */
2562
+ tagsDropped?: string[];
2563
+ /**
2564
+ * The named destinations a merge or a page import brought in under another name, because
2565
+ * the document already used theirs; left out when there are none.
2566
+ */
2567
+ renamedDestinations?: RenamedDestinationJs[];
2568
+ /**
2569
+ * The bookmarks a merge left out because the pages they went to didn't come along; left
2570
+ * out when there are none.
2571
+ */
2572
+ bookmarksDropped?: number;
1348
2573
  }
1349
2574
 
1350
2575
  /**
@@ -1357,6 +2582,55 @@ export type PageModeInit = "none" | "outlines" | "thumbnails" | "fullScreen" | "
1357
2582
  */
1358
2583
  export type SaveModeJs = "auto" | "incremental" | "fullRewrite";
1359
2584
 
2585
+ /**
2586
+ * The wire form, under the name TypeScript gives it.
2587
+ */
2588
+ export type XmpValue = { type: "text"; value: string } | { type: "uri"; value: string } | { type: "integer"; value: number } | { type: "real"; value: number } | { type: "boolean"; value: boolean } | { type: "date"; value: string } | { type: "langAlt"; value: XmpLangText[] } | { type: "seq"; value: XmpValue[] } | { type: "bag"; value: XmpValue[] };
2589
+
2590
+ /**
2591
+ * The yes-or-no window entries of the viewer preferences.
2592
+ */
2593
+ export interface WindowPreferencesJs {
2594
+ /**
2595
+ * Hide the reader's toolbars.
2596
+ */
2597
+ hideToolbar: boolean;
2598
+ /**
2599
+ * Hide the reader's menu bar.
2600
+ */
2601
+ hideMenubar: boolean;
2602
+ /**
2603
+ * Hide the scroll bars and navigation controls.
2604
+ */
2605
+ hideWindowUi: boolean;
2606
+ /**
2607
+ * Resize the window to fit the first page.
2608
+ */
2609
+ fitWindow: boolean;
2610
+ /**
2611
+ * Put the window in the middle of the screen.
2612
+ */
2613
+ centerWindow: boolean;
2614
+ /**
2615
+ * Show the document's title in the title bar.
2616
+ */
2617
+ displayDocTitle: boolean;
2618
+ }
2619
+
2620
+ /**
2621
+ * What [`DeleteOutlineItem`](super::DeleteOutlineItem) does with the item's children.
2622
+ *
2623
+ * Added in 0.3.0.
2624
+ */
2625
+ export type ChildItems = "delete" | "promote";
2626
+
2627
+ /**
2628
+ * What [`DeletePages`] does with a destination that names a deleted page.
2629
+ *
2630
+ * Added in 0.3.0.
2631
+ */
2632
+ export type ReferencePolicy = "retarget" | "remove";
2633
+
1360
2634
  /**
1361
2635
  * What `WasmDocument.extract` returns.
1362
2636
  */
@@ -1423,6 +2697,33 @@ export interface PermissionsJs {
1423
2697
  assemble: boolean;
1424
2698
  }
1425
2699
 
2700
+ /**
2701
+ * What a page duplication or a page copied in did to one form field.
2702
+ */
2703
+ export interface FieldEditJs {
2704
+ /**
2705
+ * The field on the source page (in the source document, for a page copied in).
2706
+ */
2707
+ field: string;
2708
+ /**
2709
+ * The copy whose widget it concerns.
2710
+ */
2711
+ page: string;
2712
+ /**
2713
+ * `renamed` (the copy's widget belongs to a new field), `linked` (it joined the field of
2714
+ * the same name) or `notCopied` (a signature's widget).
2715
+ */
2716
+ outcome: "renamed" | "linked" | "notCopied";
2717
+ /**
2718
+ * The new field's ID, when renamed; the field it joined, when linked.
2719
+ */
2720
+ to?: string;
2721
+ /**
2722
+ * The new field's fully qualified name, when renamed.
2723
+ */
2724
+ name?: string;
2725
+ }
2726
+
1426
2727
  /**
1427
2728
  * What a save wrote (`laminapdf::SaveReport`).
1428
2729
  */
@@ -1490,11 +2791,44 @@ export interface RevertedJs {
1490
2791
  touchedPages: string[];
1491
2792
  }
1492
2793
 
2794
+ /**
2795
+ * What becomes of the sources' outlines (bookmarks) in a merge.
2796
+ *
2797
+ * Added in 0.3.0.
2798
+ */
2799
+ export type OutlineMerge = "perFile" | "keep" | "none";
2800
+
2801
+ /**
2802
+ * What comes along with pages copied from another document.
2803
+ *
2804
+ * Added in 0.3.0.
2805
+ */
2806
+ export interface Carry {
2807
+ /**
2808
+ * Whether the pages' annotations other than form fields come along (links, comments,
2809
+ * markup); `true` when left out.
2810
+ */
2811
+ annotations?: boolean;
2812
+ /**
2813
+ * What happens to a form field whose name the target already uses; `rename` when left
2814
+ * out.
2815
+ */
2816
+ fields?: FieldClash;
2817
+ }
2818
+
1493
2819
  /**
1494
2820
  * What following a link does, by `kind`.
1495
2821
  */
1496
2822
  export type LinkToJs = { kind: "dest"; target?: TargetJs } | { kind: "named"; name: string; target?: TargetJs } | { kind: "uri"; uri: string } | { kind: "remote"; file?: string } | { kind: "named-action"; name: string } | { kind: "unsupported"; action: string };
1497
2823
 
2824
+ /**
2825
+ * What happens to a copied form field whose fully qualified name the target already uses
2826
+ * (E2 plan §11).
2827
+ *
2828
+ * Added in 0.3.0.
2829
+ */
2830
+ export type FieldClash = "rename" | "link";
2831
+
1498
2832
  /**
1499
2833
  * What happens to hidden text and page furniture.
1500
2834
  */
@@ -1517,6 +2851,18 @@ export interface DropInit {
1517
2851
  */
1518
2852
  export type PacketStatus = "absent" | "parsed" | "malformed";
1519
2853
 
2854
+ /**
2855
+ * Where a bookmark goes.
2856
+ *
2857
+ * Added in 0.3.0.
2858
+ */
2859
+ export type OutlineTarget = { destination: ExplicitDestination } | { named: string } | { uri: string };
2860
+
2861
+ /**
2862
+ * Where a document opens, by `kind`.
2863
+ */
2864
+ export type OpenTargetJs = { kind: "default" } | { kind: "page"; target: TargetJs } | { kind: "action"; action: string };
2865
+
1520
2866
  /**
1521
2867
  * Where a link or outline item goes.
1522
2868
  */
@@ -1532,6 +2878,14 @@ export type SplitOnName = "headings" | "blocks" | "pages";
1532
2878
  */
1533
2879
  export type ReadingOrderName = "auto" | "tagged" | "layout" | "content-stream";
1534
2880
 
2881
+ /**
2882
+ * Whether [`RenameNamedDestination`](super::RenameNamedDestination) renames the uses of the
2883
+ * name in this file too.
2884
+ *
2885
+ * Added in 0.3.0.
2886
+ */
2887
+ export type RenameLinks = "keep" | "follow";
2888
+
1535
2889
  /**
1536
2890
  * Which side [`DocumentMetadata`]'s values come from.
1537
2891
  *
@@ -1698,6 +3052,15 @@ export class WasmDocument {
1698
3052
  private constructor();
1699
3053
  free(): void;
1700
3054
  [Symbol.dispose](): void;
3055
+ /**
3056
+ * Adds another PDF as a source document: `{ id, pages }`, its ID (64 hex digits, the
3057
+ * SHA-256 of `bytes`) and its page IDs in order. An encrypted one opens with `password`,
3058
+ * which no op ever holds.
3059
+ *
3060
+ * # Errors
3061
+ * `wrong-password`, `password-required`, and the errors of a file that doesn't open.
3062
+ */
3063
+ addSource(bytes: Uint8Array, password?: string | null): { id: string; pages: string[] };
1701
3064
  /**
1702
3065
  * Makes `bytes`, the whole output of `saveCopy`, the document's saved file (it rebases onto
1703
3066
  * them), once they are written where the document lives; `historyCleared` is the copy's
@@ -1722,6 +3085,14 @@ export class WasmDocument {
1722
3085
  * error (nothing is applied).
1723
3086
  */
1724
3087
  apply(ops: Op[]): EditedJs;
3088
+ /**
3089
+ * `view` (page space) on page `page` as the destination the outline and named-destination
3090
+ * ops take, in the page's user space (the extract and text modules).
3091
+ *
3092
+ * # Errors
3093
+ * `invalid-argument` for a view that isn't one; `page-index-out-of-range`; reading errors.
3094
+ */
3095
+ destinationAt(page: number, view: TargetViewJs): ExplicitDestination;
1725
3096
  /**
1726
3097
  * An extraction stepped a page at a time, whose models the host runs: each step returns
1727
3098
  * its progress, with the result it waits for under `request` (render that page at `dpi`,
@@ -1732,6 +3103,14 @@ export class WasmDocument {
1732
3103
  * As `extract`, for the options and the pages asked for.
1733
3104
  */
1734
3105
  extractJob(options: ExtractInit): WasmExtractJob;
3106
+ /**
3107
+ * A new document of `pages` of this one, in the order given.
3108
+ *
3109
+ * # Errors
3110
+ * `invalid-argument` for a value that isn't a list of page IDs, `unknown-page`; reading
3111
+ * errors.
3112
+ */
3113
+ extractPages(pages: string[]): WasmDocument;
1735
3114
  /**
1736
3115
  * The document's text for retrieval and LLMs, as one string: Markdown, plain text, the
1737
3116
  * `laminapdf.extract/1` JSON, or the chunks as a JSON array (the extract and text modules).
@@ -1752,6 +3131,13 @@ export class WasmDocument {
1752
3131
  * Reading errors.
1753
3132
  */
1754
3133
  info(): DocumentInfoJs;
3134
+ /**
3135
+ * How the document asks to be shown when it opens (the extract and text modules).
3136
+ *
3137
+ * # Errors
3138
+ * `data-pending` and the reading errors.
3139
+ */
3140
+ initialView(): InitialViewJs;
1755
3141
  /**
1756
3142
  * Whether the file is encrypted (it opened with its password, or the empty one).
1757
3143
  */
@@ -1763,6 +3149,16 @@ export class WasmDocument {
1763
3149
  * Reading errors.
1764
3150
  */
1765
3151
  isTagged(): boolean;
3152
+ /**
3153
+ * A new document of `inputs` (each `{ bytes, password?, title? }`) one after another,
3154
+ * with their bookmarks, named destinations, form fields, layers and page labels; `options`
3155
+ * as `mergeDocuments`' (`outline`, `fields`).
3156
+ *
3157
+ * # Errors
3158
+ * `invalid-argument` / `unknown-option` for bad values, `wrong-password`,
3159
+ * `password-required`, and the errors of a file that doesn't open.
3160
+ */
3161
+ static merge(inputs: { bytes: Uint8Array; password?: string; title?: string }[], options: MergeOptions | undefined): WasmDocument;
1766
3162
  /**
1767
3163
  * The document's metadata, read from Info and XMP together, with the fields where they
1768
3164
  * disagree.
@@ -1779,6 +3175,13 @@ export class WasmDocument {
1779
3175
  * `data-pending` and the reading errors.
1780
3176
  */
1781
3177
  namedDestination(name: string): TargetJs | undefined;
3178
+ /**
3179
+ * Every named destination, sorted by name (the extract and text modules).
3180
+ *
3181
+ * # Errors
3182
+ * `data-pending` and the reading errors.
3183
+ */
3184
+ namedDestinations(): NamedDestinationJs[];
1782
3185
  /**
1783
3186
  * Opens a document from its bytes.
1784
3187
  *
@@ -1804,6 +3207,14 @@ export class WasmDocument {
1804
3207
  * `data-pending` and the reading errors.
1805
3208
  */
1806
3209
  outline(): OutlineNodeJs[];
3210
+ /**
3211
+ * The annotations on page `index`, in the order of its `/Annots`, every subtype included
3212
+ * (the extract and text modules).
3213
+ *
3214
+ * # Errors
3215
+ * `page-index-out-of-range`, `data-pending` and the reading errors.
3216
+ */
3217
+ pageAnnotations(index: number): PageAnnotationJs[];
1807
3218
  /**
1808
3219
  * A handle on the page with `id` (`p12.0`).
1809
3220
  *
@@ -1906,6 +3317,17 @@ export class WasmDocument {
1906
3317
  * The save's errors (`would-invalidate-signatures`, `requires-rewrite`, …).
1907
3318
  */
1908
3319
  save(options: SaveOptionsInit | undefined): { bytes: Uint8Array<ArrayBuffer>; report: SaveReportJs };
3320
+ /**
3321
+ * This document cut into new ones: `{ count: n }` parts of `n` pages, `{ ranges: [[id, …],
3322
+ * …] }` one part per list of page IDs, or `{ bookmarks: level }` a part from each bookmark
3323
+ * at that depth (1: the top level). Each part carries what its pages reach and the
3324
+ * bookmarks that go to them.
3325
+ *
3326
+ * # Errors
3327
+ * `invalid-argument` / `unknown-option` for a value that isn't one of those, `unknown-page`,
3328
+ * `no-pages-left` for an empty list; reading errors.
3329
+ */
3330
+ split(by: { readonly count: number } | { readonly ranges: readonly (readonly string[])[] } | { readonly bookmarks: number }): WasmDocument[];
1909
3331
  /**
1910
3332
  * The structure tree's top-level elements in reading order, or `undefined` without one (the
1911
3333
  * extract and text modules, beside `WasmPage.text`, whose runs it links by MCID).
@@ -1914,6 +3336,13 @@ export class WasmDocument {
1914
3336
  * Reading errors.
1915
3337
  */
1916
3338
  structureTree(): StructureNodeJs[] | undefined;
3339
+ /**
3340
+ * The document's article threads; empty without any (the extract and text modules).
3341
+ *
3342
+ * # Errors
3343
+ * `data-pending` and the reading errors.
3344
+ */
3345
+ threads(): ThreadJs[];
1917
3346
  /**
1918
3347
  * Undoes the newest transaction: how it went and the pages it touched; `undefined` when
1919
3348
  * there is nothing to undo.
@@ -1933,6 +3362,13 @@ export class WasmDocument {
1933
3362
  * `invalid-argument` for a value that isn't an op; reading errors.
1934
3363
  */
1935
3364
  wouldViolate(op: Op): ViolationJs[];
3365
+ /**
3366
+ * The document's XMP packet as text, with the edits made so far.
3367
+ *
3368
+ * # Errors
3369
+ * Reading errors.
3370
+ */
3371
+ xmpPacket(): XmpTextJs;
1936
3372
  }
1937
3373
 
1938
3374
  /**
@@ -2005,6 +3441,23 @@ export class WasmImage {
2005
3441
  readonly width: number;
2006
3442
  }
2007
3443
 
3444
+ /**
3445
+ * The images of [`images_to_pdf`], in page order. Images are JavaScript-owned objects, which a
3446
+ * record can't carry, so they are added one by one.
3447
+ */
3448
+ export class WasmImageList {
3449
+ free(): void;
3450
+ [Symbol.dispose](): void;
3451
+ /**
3452
+ * An empty list.
3453
+ */
3454
+ constructor();
3455
+ /**
3456
+ * Adds `image` as the next page. The image stays usable: the list holds its own copy.
3457
+ */
3458
+ push(image: WasmImage): void;
3459
+ }
3460
+
2008
3461
  /**
2009
3462
  * A page of a [`WasmDocument`], held by its ID (F2): moving pages doesn't retarget it.
2010
3463
  */
@@ -2311,6 +3764,16 @@ export function allocationFailed(): boolean;
2311
3764
  */
2312
3765
  export function hasText(): boolean;
2313
3766
 
3767
+ /**
3768
+ * A new document with one page per image of `images`, in order: a JPEG embedded as it is, a PNG
3769
+ * with its transparency, each drawn the way up its EXIF orientation says.
3770
+ *
3771
+ * # Errors
3772
+ * `invalid-geometry` for no images, a negative margin or resolution, or a page too small for its
3773
+ * margins; `unknown-option`, `invalid-argument` for bad options.
3774
+ */
3775
+ export function imagesToPdf(images: WasmImageList, options: ImagesOptionsInit | undefined): WasmDocument;
3776
+
2314
3777
  /**
2315
3778
  * The crate version (`@laminapdf/wasm`'s).
2316
3779
  */
@@ -2324,6 +3787,7 @@ export interface InitOutput {
2324
3787
  readonly __wbg_wasmdocument_free: (a: number, b: number) => void;
2325
3788
  readonly __wbg_wasmextractjob_free: (a: number, b: number) => void;
2326
3789
  readonly __wbg_wasmimage_free: (a: number, b: number) => void;
3790
+ readonly __wbg_wasmimagelist_free: (a: number, b: number) => void;
2327
3791
  readonly __wbg_wasmpage_free: (a: number, b: number) => void;
2328
3792
  readonly __wbg_wasmpagebuilder_free: (a: number, b: number) => void;
2329
3793
  readonly __wbg_wasmsavejob_free: (a: number, b: number) => void;
@@ -2331,6 +3795,7 @@ export interface InitOutput {
2331
3795
  readonly __wbg_wasmwarningcursor_free: (a: number, b: number) => void;
2332
3796
  readonly allocationFailed: () => number;
2333
3797
  readonly hasText: () => number;
3798
+ readonly imagesToPdf: (a: number, b: any) => [number, number, number];
2334
3799
  readonly version: () => [number, number];
2335
3800
  readonly wasmbuilder_attach: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: any) => [number, number];
2336
3801
  readonly wasmbuilder_destination: (a: number, b: number, c: number, d: number, e: any) => [number, number];
@@ -2342,21 +3807,28 @@ export interface InitOutput {
2342
3807
  readonly wasmbuilder_page: (a: number, b: number, c: number) => number;
2343
3808
  readonly wasmbuilder_pageLabels: (a: number, b: any) => [number, number];
2344
3809
  readonly wasmbuilder_viewerPreferences: (a: number, b: any) => [number, number];
3810
+ readonly wasmdocument_addSource: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
2345
3811
  readonly wasmdocument_adoptCopy: (a: number, b: number, c: number, d: number) => [number, number];
2346
3812
  readonly wasmdocument_apply: (a: number, b: any) => [number, number, number];
2347
3813
  readonly wasmdocument_applyLog: (a: number, b: number, c: number) => [number, number, number];
3814
+ readonly wasmdocument_destinationAt: (a: number, b: number, c: any) => [number, number, number];
2348
3815
  readonly wasmdocument_extract: (a: number, b: any) => [number, number, number, number];
2349
3816
  readonly wasmdocument_extractJob: (a: number, b: any) => [number, number, number];
3817
+ readonly wasmdocument_extractPages: (a: number, b: any) => [number, number, number];
2350
3818
  readonly wasmdocument_hasUnsavedChanges: (a: number) => number;
2351
3819
  readonly wasmdocument_info: (a: number) => [number, number, number];
3820
+ readonly wasmdocument_initialView: (a: number) => [number, number, number];
2352
3821
  readonly wasmdocument_isEncrypted: (a: number) => number;
2353
3822
  readonly wasmdocument_isTagged: (a: number) => [number, number, number];
3823
+ readonly wasmdocument_merge: (a: any, b: any) => [number, number, number];
2354
3824
  readonly wasmdocument_metadata: (a: number) => [number, number, number];
2355
3825
  readonly wasmdocument_namedDestination: (a: number, b: number, c: number) => [number, number, number];
3826
+ readonly wasmdocument_namedDestinations: (a: number) => [number, number, number];
2356
3827
  readonly wasmdocument_openBytes: (a: number, b: number, c: any) => [number, number, number];
2357
3828
  readonly wasmdocument_openSource: (a: number, b: any) => [number, number, number];
2358
3829
  readonly wasmdocument_outline: (a: number) => [number, number, number];
2359
3830
  readonly wasmdocument_page: (a: number, b: number) => [number, number, number];
3831
+ readonly wasmdocument_pageAnnotations: (a: number, b: number) => [number, number, number];
2360
3832
  readonly wasmdocument_pageById: (a: number, b: number, c: number) => [number, number, number];
2361
3833
  readonly wasmdocument_pageCount: (a: number) => [number, number, number];
2362
3834
  readonly wasmdocument_pageInfo: (a: number, b: number) => [number, number, number];
@@ -2370,10 +3842,13 @@ export interface InitOutput {
2370
3842
  readonly wasmdocument_save: (a: number, b: any) => [number, number, number];
2371
3843
  readonly wasmdocument_saveCopy: (a: number, b: any) => [number, number, number];
2372
3844
  readonly wasmdocument_saveJob: (a: number, b: any) => [number, number, number];
3845
+ readonly wasmdocument_split: (a: number, b: any) => [number, number, number];
2373
3846
  readonly wasmdocument_structureTree: (a: number) => [number, number, number];
3847
+ readonly wasmdocument_threads: (a: number) => [number, number, number];
2374
3848
  readonly wasmdocument_undo: (a: number) => [number, number, number];
2375
3849
  readonly wasmdocument_warnings: (a: number) => number;
2376
3850
  readonly wasmdocument_wouldViolate: (a: number, b: any) => [number, number, number];
3851
+ readonly wasmdocument_xmpPacket: (a: number) => [number, number, number];
2377
3852
  readonly wasmextractjob_cancel: (a: number) => void;
2378
3853
  readonly wasmextractjob_provide: (a: number, b: any) => [number, number];
2379
3854
  readonly wasmextractjob_step: (a: number, b: number) => [number, number, number];
@@ -2382,6 +3857,8 @@ export interface InitOutput {
2382
3857
  readonly wasmimage_png: (a: number, b: number) => [number, number, number];
2383
3858
  readonly wasmimage_rgba: (a: number, b: number, c: number, d: number) => [number, number, number];
2384
3859
  readonly wasmimage_width: (a: number) => number;
3860
+ readonly wasmimagelist_new: () => number;
3861
+ readonly wasmimagelist_push: (a: number, b: number) => void;
2385
3862
  readonly wasmpage_id: (a: number) => [number, number];
2386
3863
  readonly wasmpage_index: (a: number) => [number, number, number];
2387
3864
  readonly wasmpage_info: (a: number) => [number, number, number];
@@ -2422,8 +3899,8 @@ export interface InitOutput {
2422
3899
  readonly __wbindgen_exn_store: (a: number) => void;
2423
3900
  readonly __externref_table_alloc: () => number;
2424
3901
  readonly __wbindgen_externrefs: WebAssembly.Table;
2425
- readonly __wbindgen_free: (a: number, b: number, c: number) => void;
2426
3902
  readonly __externref_table_dealloc: (a: number) => void;
3903
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
2427
3904
  readonly __wbindgen_start: () => void;
2428
3905
  }
2429
3906