@laminapdf/wasm 0.2.0-alpha.5 → 0.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.
@@ -44,16 +44,122 @@ export type PageLinkJs = {
44
44
  } & LinkToJs;
45
45
 
46
46
 
47
+ /**
48
+ * A change a signature's restriction forbids.
49
+ */
50
+ export interface ViolationJs {
51
+ /**
52
+ * The kind of change.
53
+ */
54
+ class: ModificationClass;
55
+ /**
56
+ * `docMdp`, `fieldMdp`, `usageRights`, `signedBytes` or `signedWidget`.
57
+ */
58
+ restriction: string;
59
+ /**
60
+ * The certification's `/P` (1, 2 or 3), for a `docMdp` restriction.
61
+ */
62
+ permission?: number;
63
+ /**
64
+ * The signature that carries the restriction.
65
+ */
66
+ signature: SignatureJs;
67
+ /**
68
+ * The form field whose widget a page edit deletes or reshows (its ID), for a
69
+ * `signedWidget` restriction or a `fieldMdp` one that a page edit breaks.
70
+ */
71
+ field?: string;
72
+ }
73
+
47
74
  /**
48
75
  * A colour for text options (the text module's records).
49
76
  */
50
77
  export type ColorInit = number[] | string;
51
78
 
79
+ /**
80
+ * A conformance claim the document's metadata no longer meets.
81
+ *
82
+ * Added in 0.2.0.
83
+ */
84
+ export type ConformanceWarning = { code: "pdfa-one-author"; authors: number } | { code: "pdfua-title-missing" } | { code: "pdfa-info-mismatch"; keys: MetadataKey[] };
85
+
52
86
  /**
53
87
  * A conformance profile.
54
88
  */
55
89
  export type ProfileInit = "PDF/UA-1" | "PDF/A-2b" | "PDF/A-2u" | "PDF/A-3b";
56
90
 
91
+ /**
92
+ * A document's metadata as one record, read from the Info dictionary and the XMP packet.
93
+ *
94
+ * When the two disagree, the values come from the XMP packet in a PDF 2.0 file (ISO 32000-2
95
+ * §14.3.3 deprecates the Info entries) or a file that claims PDF/A (whose packet is
96
+ * authoritative, ISO 19005-2 §6.6.2.3.1), and otherwise from the side whose modification date
97
+ * is newer, Info winning a tie. A field the winning side lacks is taken from the other.
98
+ * [`disagreements`](DocumentMetadata::disagreements) names the fields where the two differ, so
99
+ * a properties view can say so.
100
+ *
101
+ * Added in 0.2.0.
102
+ */
103
+ export interface DocumentMetadata {
104
+ /**
105
+ * The title.
106
+ */
107
+ title?: string;
108
+ /**
109
+ * The authors, in order (Info's `/Author` split at `;`).
110
+ */
111
+ authors: string[];
112
+ /**
113
+ * The subject.
114
+ */
115
+ subject?: string;
116
+ /**
117
+ * The keywords.
118
+ */
119
+ keywords?: string;
120
+ /**
121
+ * The application the content came from.
122
+ */
123
+ creator?: string;
124
+ /**
125
+ * The application that wrote the PDF.
126
+ */
127
+ producer?: string;
128
+ /**
129
+ * The creation date (a PDF date string on the wire).
130
+ */
131
+ created?: string;
132
+ /**
133
+ * The modification date.
134
+ */
135
+ modified?: string;
136
+ /**
137
+ * Which side the values come from.
138
+ */
139
+ source: MetadataSource;
140
+ /**
141
+ * The fields where Info and XMP hold different values.
142
+ */
143
+ disagreements: MetadataKey[];
144
+ /**
145
+ * What `/Metadata` holds.
146
+ */
147
+ packet: PacketStatus;
148
+ /**
149
+ * The PDF/A part and conformance the packet claims (`pdfaid:`), e.g. `"2B"`.
150
+ */
151
+ pdfa?: string;
152
+ /**
153
+ * The PDF/UA part the packet claims (`pdfuaid:part`).
154
+ */
155
+ pdfua?: number;
156
+ /**
157
+ * In a PDF 2.0 file, the Info entries besides the two dates: deprecated, kept as they
158
+ * were for older readers, and never written by an edit.
159
+ */
160
+ keptInfoKeys: MetadataKey[];
161
+ }
162
+
57
163
  /**
58
164
  * A document's properties, for a properties view.
59
165
  */
@@ -141,6 +247,25 @@ export interface PropertiesJs {
141
247
  */
142
248
  export type EncodingJs = { kind: "named"; name: string } | { kind: "custom" };
143
249
 
250
+ /**
251
+ * A header or footer: text at the start, centre and end, with `{page}`, `{pages}`, `{section}`
252
+ * and `{title}` filled in.
253
+ */
254
+ export interface PageRegionInit {
255
+ /**
256
+ * At the start of the line.
257
+ */
258
+ start?: string;
259
+ /**
260
+ * Centred.
261
+ */
262
+ center?: string;
263
+ /**
264
+ * At the end of the line.
265
+ */
266
+ end?: string;
267
+ }
268
+
144
269
  /**
145
270
  * A job's progress (`laminapdf::Step::Progress`).
146
271
  */
@@ -212,12 +337,33 @@ export interface TextLinkInit {
212
337
  * ```
213
338
  *
214
339
  * [ADR 0006]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0006-op-log-and-undo.md
340
+ *
341
+ * Added in 0.2.0.
215
342
  */
216
343
  export interface OpLog {
217
344
  v: 1;
218
345
  ops: Op[];
219
346
  }
220
347
 
348
+ /**
349
+ * A metadata field Lamina PDF keeps in step in the Info dictionary and the XMP packet: what
350
+ * [`RemoveMetadata`] removes and [`DocumentMetadata::disagreements`] names.
351
+ *
352
+ * | Key | Info | XMP |
353
+ * | --- | --- | --- |
354
+ * | `title` | `/Title` | `dc:title` |
355
+ * | `authors` | `/Author` (joined with `; `) | `dc:creator` |
356
+ * | `subject` | `/Subject` | `dc:description` |
357
+ * | `keywords` | `/Keywords` | `pdf:Keywords` |
358
+ * | `creator` | `/Creator` | `xmp:CreatorTool` |
359
+ * | `producer` | `/Producer` | `pdf:Producer` |
360
+ * | `created` | `/CreationDate` | `xmp:CreateDate` |
361
+ * | `modified` | `/ModDate` | `xmp:ModifyDate` |
362
+ *
363
+ * Added in 0.2.0.
364
+ */
365
+ export type MetadataKey = "title" | "authors" | "subject" | "keywords" | "creator" | "producer" | "created" | "modified";
366
+
221
367
  /**
222
368
  * A model result the job waits for.
223
369
  */
@@ -308,6 +454,24 @@ export interface RectJs {
308
454
  */
309
455
  export type RegionLabelName = "text" | "title" | "section-header" | "list-item" | "table" | "picture" | "caption" | "footnote" | "formula" | "page-header" | "page-footer" | "other";
310
456
 
457
+ /**
458
+ * A signature the planner found.
459
+ */
460
+ export interface SignatureJs {
461
+ /**
462
+ * `approval`, `certification`, `docTimeStamp` or `usageRights`.
463
+ */
464
+ kind: string;
465
+ /**
466
+ * The signature field's ID, when a field holds it.
467
+ */
468
+ field?: string;
469
+ /**
470
+ * The 1-based revision the signature closes, when known.
471
+ */
472
+ revision?: number;
473
+ }
474
+
311
475
  /**
312
476
  * A step's progress, and the model result the job waits for, if any.
313
477
  */
@@ -391,8 +555,10 @@ export interface AttachmentInit {
391
555
  * ```
392
556
  *
393
557
  * [ADR 0006]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0006-op-log-and-undo.md
558
+ *
559
+ * Added in 0.2.0.
394
560
  */
395
- export type Op = { op: "setInfo"; args: SetInfo } | { op: "rotatePage"; args: RotatePage };
561
+ export type Op = { op: "setInfo"; args: SetInfo } | { op: "rotatePage"; args: RotatePage } | { op: "setMetadata"; args: SetMetadata } | { op: "removeMetadata"; args: RemoveMetadata };
396
562
 
397
563
  /**
398
564
  * Changes to the Info dictionary's text entries. For each field, `None` leaves the entry
@@ -401,6 +567,8 @@ export type Op = { op: "setInfo"; args: SetInfo } | { op: "rotatePage"; args: Ro
401
567
  *
402
568
  * On the wire an absent field is left alone and `null` clears: `{ "title": "Report",
403
569
  * "author": null }`.
570
+ *
571
+ * Added in 0.2.0.
404
572
  */
405
573
  export interface InfoPatch {
406
574
  /**
@@ -429,13 +597,75 @@ export interface InfoPatch {
429
597
  producer?: string | null;
430
598
  }
431
599
 
600
+ /**
601
+ * Changes to the document's metadata. For each field, `None` leaves it alone, `Some(None)`
602
+ * removes it and `Some(Some(value))` sets it, in Info and XMP alike.
603
+ *
604
+ * On the wire an absent field is left alone and `null` removes: `{ "title": "Report",
605
+ * "authors": ["Ada Lovelace", "Charles Babbage"], "keywords": null }`; dates are PDF date
606
+ * strings (`"D:20261110093000+01'00'"`).
607
+ *
608
+ * ```
609
+ * use laminapdf_ops::MetadataPatch;
610
+ *
611
+ * let patch = MetadataPatch::new().title(Some("Quarterly figures")).authors(&["Ada Lovelace", "Charles Babbage"]);
612
+ * assert_eq!(patch.authors, Some(Some(vec!["Ada Lovelace".to_owned(), "Charles Babbage".to_owned()])));
613
+ * assert_eq!(serde_json::to_string(&patch)?, r#"{"title":"Quarterly figures","authors":["Ada Lovelace","Charles Babbage"]}"#);
614
+ * # Ok::<(), serde_json::Error>(())
615
+ * ```
616
+ *
617
+ * Added in 0.2.0.
618
+ */
619
+ export interface MetadataPatch {
620
+ /**
621
+ * `/Title`, `dc:title`.
622
+ */
623
+ title?: string | null;
624
+ /**
625
+ * `/Author` (joined with `; `), `dc:creator` (in order). An empty list removes them.
626
+ */
627
+ authors?: string[] | null;
628
+ /**
629
+ * `/Subject`, `dc:description`.
630
+ */
631
+ subject?: string | null;
632
+ /**
633
+ * `/Keywords`, `pdf:Keywords`.
634
+ */
635
+ keywords?: string | null;
636
+ /**
637
+ * `/Creator`, `xmp:CreatorTool`: the application the content came from.
638
+ */
639
+ creator?: string | null;
640
+ /**
641
+ * `/Producer`, `pdf:Producer`: the application that wrote the PDF.
642
+ */
643
+ producer?: string | null;
644
+ /**
645
+ * `/CreationDate`, `xmp:CreateDate`.
646
+ */
647
+ created?: string | null;
648
+ /**
649
+ * `/ModDate`, `xmp:ModifyDate`.
650
+ */
651
+ modified?: string | null;
652
+ }
653
+
432
654
  /**
433
655
  * Edits the Info dictionary: applies `patch` and, when `at` is given, sets `/ModDate` to it.
656
+ *
657
+ * **Deprecated:** use [`SetMetadata`](crate::SetMetadata), which writes authors as a list and
658
+ * the dates, and edits files whose metadata is in XMP alone. `SetInfo` stays, with its v1 wire
659
+ * form (`setInfo`) and meaning, so op logs already written still apply (ADR 0006 §6). It now
660
+ * goes through the same writer, so a document's XMP packet, when it has one, changes with it.
661
+ * It adds a packet only to a PDF 2.0 file, where the fields other than the dates belong in XMP.
434
662
  * The date is part of the op, never read from a clock, so the same op gives the same bytes
435
663
  * everywhere (ADR 0006 §1).
436
664
  *
437
665
  * An Info dictionary written directly in the trailer, or missing, becomes a new indirect
438
666
  * object that the trailer's `/Info` points to (the first time the op changes something).
667
+ *
668
+ * Added in 0.2.0.
439
669
  */
440
670
  export interface SetInfo {
441
671
  /**
@@ -448,6 +678,71 @@ export interface SetInfo {
448
678
  at?: string;
449
679
  }
450
680
 
681
+ /**
682
+ * Edits the document's metadata: applies `patch` to the Info dictionary and the XMP packet
683
+ * together and, when `at` is given, records it as the modification date (`/ModDate`,
684
+ * `xmp:ModifyDate`) and as `xmp:MetadataDate`, unless the patch sets the modification date
685
+ * itself. The date is part of the op, never read from a clock (ADR 0006 §1).
686
+ *
687
+ * ```
688
+ * use laminapdf_ops::{MetadataPatch, Op, SetMetadata};
689
+ *
690
+ * let op = Op::from(SetMetadata::new(MetadataPatch::new().title(Some("Minutes")), Some("D:20261110093000Z".parse()?)));
691
+ * assert_eq!(
692
+ * serde_json::to_string(&op)?,
693
+ * r#"{"op":"setMetadata","args":{"patch":{"title":"Minutes"},"at":"D:20261110093000Z"}}"#
694
+ * );
695
+ * # Ok::<(), Box<dyn std::error::Error>>(())
696
+ * ```
697
+ *
698
+ * Added in 0.2.0.
699
+ */
700
+ export interface SetMetadata {
701
+ /**
702
+ * The fields to set or remove.
703
+ */
704
+ patch?: MetadataPatch;
705
+ /**
706
+ * The modification date the edit writes.
707
+ */
708
+ at?: string;
709
+ /**
710
+ * Replace an XMP packet that can't be read with a new one, losing whatever it held.
711
+ * Without it, such a packet makes the op fail with `malformed-xmp`, so nothing is lost
712
+ * without the user saying so.
713
+ */
714
+ replaceMalformed?: boolean;
715
+ }
716
+
717
+ /**
718
+ * How `flow` reads its document.
719
+ */
720
+ export interface FlowOptionsInit {
721
+ /**
722
+ * The values a template's `$data`, `$each` and `$item` placeholders read; without it, the
723
+ * document is read as it is.
724
+ */
725
+ data?: unknown;
726
+ }
727
+
728
+ /**
729
+ * How `markdown` lays a document out.
730
+ */
731
+ export interface MarkdownOptionsInit {
732
+ /**
733
+ * The body text's size in points (10.5 by default); headings scale from it.
734
+ */
735
+ size?: number;
736
+ /**
737
+ * A contents page listing headings of levels 1 to `contents`, at the start.
738
+ */
739
+ contents?: number;
740
+ /**
741
+ * The pages (by default A4, 56-point margins, "Page {page} of {pages}" in the footer).
742
+ */
743
+ page?: PageTemplateInit;
744
+ }
745
+
451
746
  /**
452
747
  * How a destination shows its page (§12.3.2.2).
453
748
  */
@@ -509,6 +804,65 @@ export interface TextOptionsInit {
509
804
  direction?: DirectionInit;
510
805
  }
511
806
 
807
+ /**
808
+ * How a save would go (`laminapdf::PlannedSave`).
809
+ */
810
+ export interface PlannedSaveJs {
811
+ /**
812
+ * The mode the save resolves to; absent when it would be refused.
813
+ */
814
+ mode?: SaveModeJs;
815
+ /**
816
+ * The code the save would be refused with.
817
+ */
818
+ refusal?: string;
819
+ /**
820
+ * `free`, `appendOnly`, `requiresRewrite` or `conflict`.
821
+ */
822
+ constraint: string;
823
+ /**
824
+ * Every signature, in the order found.
825
+ */
826
+ signatures: SignatureJs[];
827
+ /**
828
+ * The certification's `/P` (1, 2 or 3), when the document is certified.
829
+ */
830
+ docMdp?: number;
831
+ /**
832
+ * Why only a full rewrite is safe: `repairedBase`, `encryptedBase`, `noBase`,
833
+ * `opRequiresRewrite`.
834
+ */
835
+ rewriteReasons: string[];
836
+ /**
837
+ * The pending changes a signature's restriction forbids.
838
+ */
839
+ violations: ViolationJs[];
840
+ /**
841
+ * The signatures the save would invalidate (only with `invalidateSignatures`).
842
+ */
843
+ wouldInvalidate: SignatureJs[];
844
+ /**
845
+ * Whether the save writes an encrypted document as plaintext.
846
+ */
847
+ removesEncryption: boolean;
848
+ /**
849
+ * What the save does with the save-time metadata: `none`, `stamp` or `skipped`.
850
+ */
851
+ metadata: string;
852
+ /**
853
+ * Whether an edit to save rewrote the XMP packet whole.
854
+ */
855
+ packetRewritten: boolean;
856
+ /**
857
+ * The PDF/A and PDF/UA claims the edited metadata breaks (warnings that never block).
858
+ */
859
+ conformanceWarnings: Diagnostic[];
860
+ /**
861
+ * The document has no changes.
862
+ */
863
+ unchanged: boolean;
864
+ }
865
+
512
866
  /**
513
867
  * How a target shows its page, in page space; an unset coordinate is left out.
514
868
  */
@@ -985,6 +1339,17 @@ export interface SaveOptionsInit {
985
1339
  * The cross-reference form.
986
1340
  */
987
1341
  xref?: XrefJs;
1342
+ /**
1343
+ * When the save happens, as the app's clock reads it: a PDF date (`D:20261110093000Z`)
1344
+ * or an ISO 8601 date-time. A save that writes changes stamps it as the modification and
1345
+ * metadata dates and gives the XMP packet a new instance ID.
1346
+ */
1347
+ metadataDate?: string;
1348
+ /**
1349
+ * The XMP instance ID the save writes, a UUID (`uuid:` optional); without it, one is
1350
+ * derived from the content.
1351
+ */
1352
+ instanceId?: string;
988
1353
  }
989
1354
 
990
1355
  /**
@@ -992,6 +1357,37 @@ export interface SaveOptionsInit {
992
1357
  */
993
1358
  export type DirectionInit = "ltr" | "rtl";
994
1359
 
1360
+ /**
1361
+ * Removes metadata fields from the Info dictionary and the XMP packet; the packet's other
1362
+ * properties stay (J.10).
1363
+ *
1364
+ * The values stay in the file's earlier revisions until a full rewrite: an incremental save
1365
+ * appends the change and keeps the original bytes. When it removed anything, the op's result
1366
+ * says so ([`Applied::still_in_earlier_revisions`](crate::Applied::still_in_earlier_revisions)),
1367
+ * so the caller can offer a full rewrite (on a signed file, the override that removes the
1368
+ * signatures).
1369
+ *
1370
+ * ```
1371
+ * use laminapdf_ops::{MetadataKey, Op, RemoveMetadata};
1372
+ *
1373
+ * let op = Op::from(RemoveMetadata::new(vec![MetadataKey::Authors, MetadataKey::Creator]));
1374
+ * assert_eq!(serde_json::to_string(&op)?, r#"{"op":"removeMetadata","args":{"keys":["authors","creator"]}}"#);
1375
+ * # Ok::<(), serde_json::Error>(())
1376
+ * ```
1377
+ *
1378
+ * Added in 0.2.0.
1379
+ */
1380
+ export interface RemoveMetadata {
1381
+ /**
1382
+ * The fields to remove.
1383
+ */
1384
+ keys: MetadataKey[];
1385
+ /**
1386
+ * As [`SetMetadata::replace_malformed`].
1387
+ */
1388
+ replaceMalformed?: boolean;
1389
+ }
1390
+
995
1391
  /**
996
1392
  * Sets a page's rotation to `rotate` (absolute, not relative to the current value).
997
1393
  *
@@ -1004,6 +1400,8 @@ export type DirectionInit = "ltr" | "rtl";
1004
1400
  * On the wire: `{ "op": "rotatePage", "args": { "page": "p12.0", "rotate": 90 } }`.
1005
1401
  *
1006
1402
  * [ADR 0005]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0005-document-model.md
1403
+ *
1404
+ * Added in 0.2.0.
1007
1405
  */
1008
1406
  export interface RotatePage {
1009
1407
  /**
@@ -1109,6 +1507,8 @@ export interface MetadataInit {
1109
1507
  * permissions and the document's `SaveConstraint` ([ADR 0007]).
1110
1508
  *
1111
1509
  * [ADR 0007]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0007-save-planner.md
1510
+ *
1511
+ * Added in 0.2.0.
1112
1512
  */
1113
1513
  export type ModificationClass = "metadata" | "formFill" | "annotation" | "signature" | "pageStructure" | "content" | "document";
1114
1514
 
@@ -1134,6 +1534,32 @@ export interface ModelsInit {
1134
1534
  langs?: string[];
1135
1535
  }
1136
1536
 
1537
+ /**
1538
+ * The pages a Markdown document flows through.
1539
+ */
1540
+ export interface PageTemplateInit {
1541
+ /**
1542
+ * The page's width and height in points.
1543
+ */
1544
+ size: [number, number];
1545
+ /**
1546
+ * Top, right, bottom and left margins in points (72 each by default).
1547
+ */
1548
+ margins?: [number, number, number, number];
1549
+ /**
1550
+ * The header.
1551
+ */
1552
+ header?: PageRegionInit;
1553
+ /**
1554
+ * The footer.
1555
+ */
1556
+ footer?: PageRegionInit;
1557
+ /**
1558
+ * The size of the header and footer text, in the regular font (8 points by default).
1559
+ */
1560
+ furnitureSize?: number;
1561
+ }
1562
+
1137
1563
  /**
1138
1564
  * The pages an edit touched.
1139
1565
  */
@@ -1142,6 +1568,20 @@ export interface EditedJs {
1142
1568
  * IDs of the pages whose content or attributes changed.
1143
1569
  */
1144
1570
  touchedPages: string[];
1571
+ /**
1572
+ * A metadata edit rewrote the XMP packet whole (UTF-16, or marked read-only).
1573
+ */
1574
+ packetRewritten: boolean;
1575
+ /**
1576
+ * A metadata edit removed values the file's earlier revisions still hold, which only a
1577
+ * full rewrite drops.
1578
+ */
1579
+ stillInEarlierRevisions: boolean;
1580
+ /**
1581
+ * Whether the edit changed the document: one that only set values they already had leaves
1582
+ * no step to undo.
1583
+ */
1584
+ changed: boolean;
1145
1585
  }
1146
1586
 
1147
1587
  /**
@@ -1159,6 +1599,26 @@ export type SaveModeJs = "auto" | "incremental" | "fullRewrite";
1159
1599
  */
1160
1600
  export type ExtractFormat = "markdown" | "json" | "text" | "chunks";
1161
1601
 
1602
+ /**
1603
+ * What `flow` added.
1604
+ */
1605
+ export interface FlowReportJs {
1606
+ /**
1607
+ * The pages it added, in order, by ID.
1608
+ */
1609
+ pages: string[];
1610
+ }
1611
+
1612
+ /**
1613
+ * What `markdown` added.
1614
+ */
1615
+ export interface MarkdownReportJs {
1616
+ /**
1617
+ * The pages it added, in order, by ID.
1618
+ */
1619
+ pages: string[];
1620
+ }
1621
+
1162
1622
  /**
1163
1623
  * What `provide` takes.
1164
1624
  */
@@ -1272,6 +1732,24 @@ export interface SaveReportJs {
1272
1732
  * Whether encryption was removed.
1273
1733
  */
1274
1734
  encryptionRemoved: boolean;
1735
+ /**
1736
+ * Whether the save stamped the save-time metadata (`metadataDate`, `instanceId`).
1737
+ */
1738
+ metadataUpdated: boolean;
1739
+ /**
1740
+ * Whether the options asked for the stamp and the save left it out, because it would have
1741
+ * broken a signature's restriction the saved changes keep.
1742
+ */
1743
+ metadataNotUpdated: boolean;
1744
+ /**
1745
+ * Whether an edit saved here rewrote the XMP packet whole.
1746
+ */
1747
+ packetRewritten: boolean;
1748
+ /**
1749
+ * Whether the save emptied the undo history (a full rewrite, or an incremental save that
1750
+ * freed objects); for a copy, whether adopting it would.
1751
+ */
1752
+ historyCleared: boolean;
1275
1753
  }
1276
1754
 
1277
1755
  /**
@@ -1279,6 +1757,20 @@ export interface SaveReportJs {
1279
1757
  */
1280
1758
  export type OutputJs = "whole" | "appendedOnly";
1281
1759
 
1760
+ /**
1761
+ * What an undo or redo did (`laminapdf::Reverted`).
1762
+ */
1763
+ export interface RevertedJs {
1764
+ /**
1765
+ * How it went.
1766
+ */
1767
+ outcome: UndoOutcomeJs;
1768
+ /**
1769
+ * IDs of the pages the undone or redone transaction touched: draw these again.
1770
+ */
1771
+ touchedPages: string[];
1772
+ }
1773
+
1282
1774
  /**
1283
1775
  * What following a link does, by `kind`.
1284
1776
  */
@@ -1304,6 +1796,13 @@ export interface DropInit {
1304
1796
  */
1305
1797
  export type OverflowInit = "clip" | "error";
1306
1798
 
1799
+ /**
1800
+ * What the document's `/Metadata` holds.
1801
+ *
1802
+ * Added in 0.2.0.
1803
+ */
1804
+ export type PacketStatus = "absent" | "parsed" | "malformed";
1805
+
1307
1806
  /**
1308
1807
  * Where a link or outline item goes.
1309
1808
  */
@@ -1319,6 +1818,13 @@ export type SplitOnName = "headings" | "blocks" | "pages";
1319
1818
  */
1320
1819
  export type ReadingOrderName = "auto" | "tagged" | "layout" | "content-stream";
1321
1820
 
1821
+ /**
1822
+ * Which side [`DocumentMetadata`]'s values come from.
1823
+ *
1824
+ * Added in 0.2.0.
1825
+ */
1826
+ export type MetadataSource = "info" | "xmp";
1827
+
1322
1828
  /**
1323
1829
  * Which table detectors run.
1324
1830
  */
@@ -1422,6 +1928,18 @@ export class WasmBuilder {
1422
1928
  * `invalid-page-labels`, `invalid-geometry`, `subset-failed`.
1423
1929
  */
1424
1930
  finish(): WasmDocument;
1931
+ /**
1932
+ * Lays `document` out as tagged pages that flow, after any pages already added, filled from
1933
+ * `options.data` first when it is given. The document's profiles are the builder's to set
1934
+ * (`profiles` in its options); its warnings are the finished document's.
1935
+ *
1936
+ * # Errors
1937
+ * `builder-finished`; `unknown-option`, `invalid-argument`; `invalid-document` with the JSON
1938
+ * Pointer at fault and the closest keys in `didYouMean`; `template-data-missing`,
1939
+ * `template-data-type`, `template-too-large`; `unknown-font` and `unknown-image` for a name
1940
+ * `resources` lacks; `missing-glyph`, `flow-content-too-large`.
1941
+ */
1942
+ flow(document: unknown, resources: WasmFlowResources, options: FlowOptionsInit | undefined): FlowReportJs;
1425
1943
  /**
1426
1944
  * Loads a font from its bytes (TrueType or OpenType/CFF) and registers it; it is
1427
1945
  * subset to the glyphs drawn.
@@ -1430,6 +1948,13 @@ export class WasmBuilder {
1430
1948
  * `builder-finished`; `invalid-font`, `font-not-embeddable`.
1431
1949
  */
1432
1950
  fontBytes(bytes: Uint8Array): WasmFont;
1951
+ /**
1952
+ * Loads face `index` (from 0) of a font collection (`.ttc`, `.otc`) and registers it.
1953
+ *
1954
+ * # Errors
1955
+ * `builder-finished`; `invalid-font`, `collection-index` (no such face), `font-not-embeddable`.
1956
+ */
1957
+ fontCollection(bytes: Uint8Array, index: number): WasmFont;
1433
1958
  /**
1434
1959
  * The natural language (`/Lang`), a BCP 47 tag.
1435
1960
  *
@@ -1437,6 +1962,17 @@ export class WasmBuilder {
1437
1962
  * `builder-finished`.
1438
1963
  */
1439
1964
  lang(lang: string): void;
1965
+ /**
1966
+ * Lays `markdown` out as tagged pages that flow, after any pages already added; its front
1967
+ * matter's title, language, author and subject become the document's. Its warnings
1968
+ * (`markdown-html-ignored`, `markdown-image-missing`, the flow's) are the finished
1969
+ * document's.
1970
+ *
1971
+ * # Errors
1972
+ * `builder-finished`; `unknown-option`, `invalid-argument`; `missing-glyph`,
1973
+ * `flow-content-too-large`; `unknown-font` at `finish` for a font another builder registered.
1974
+ */
1975
+ markdown(markdown: string, resources: WasmMarkdownOptions, options: MarkdownOptionsInit | undefined): MarkdownReportJs;
1440
1976
  /**
1441
1977
  * The metadata, written as the Info dictionary and an XMP packet.
1442
1978
  *
@@ -1494,6 +2030,15 @@ export class WasmDocument {
1494
2030
  private constructor();
1495
2031
  free(): void;
1496
2032
  [Symbol.dispose](): void;
2033
+ /**
2034
+ * Makes `bytes`, the whole output of `saveCopy`, the document's saved file (it rebases onto
2035
+ * them), once they are written where the document lives; `historyCleared` is the copy's
2036
+ * report's.
2037
+ *
2038
+ * # Errors
2039
+ * `nested-transaction`, `saved-not-rebased`; `not-rebased` when `bytes` can't be read.
2040
+ */
2041
+ adoptCopy(bytes: Uint8Array, historyCleared: boolean): void;
1497
2042
  /**
1498
2043
  * Applies an op log (`{ "v": 1, "ops": [ … ] }`) as one transaction.
1499
2044
  *
@@ -1539,6 +2084,10 @@ export class WasmDocument {
1539
2084
  * Reading errors.
1540
2085
  */
1541
2086
  info(): DocumentInfoJs;
2087
+ /**
2088
+ * Whether the file is encrypted (it opened with its password, or the empty one).
2089
+ */
2090
+ isEncrypted(): boolean;
1542
2091
  /**
1543
2092
  * Whether the document says it is tagged (`/MarkInfo /Marked true`; the extract and text modules).
1544
2093
  *
@@ -1546,6 +2095,14 @@ export class WasmDocument {
1546
2095
  * Reading errors.
1547
2096
  */
1548
2097
  isTagged(): boolean;
2098
+ /**
2099
+ * The document's metadata, read from Info and XMP together, with the fields where they
2100
+ * disagree.
2101
+ *
2102
+ * # Errors
2103
+ * Reading errors.
2104
+ */
2105
+ metadata(): DocumentMetadata;
1549
2106
  /**
1550
2107
  * The named destination `name`, or `undefined` when the document has none by that name or
1551
2108
  * it names no page here (the extract and text modules).
@@ -1621,6 +2178,13 @@ export class WasmDocument {
1621
2178
  * `page-index-out-of-range`; reading errors.
1622
2179
  */
1623
2180
  page(index: number): WasmPage;
2181
+ /**
2182
+ * How a save with `options` would go, without saving.
2183
+ *
2184
+ * # Errors
2185
+ * `invalid-argument` / `unknown-option` for bad options; reading errors.
2186
+ */
2187
+ plan(options: SaveOptionsInit | undefined): PlannedSaveJs;
1624
2188
  /**
1625
2189
  * The document's properties (the extract and text modules). Reads every object once.
1626
2190
  *
@@ -1636,12 +2200,21 @@ export class WasmDocument {
1636
2200
  */
1637
2201
  rebase(bytes: Uint8Array): void;
1638
2202
  /**
1639
- * Redoes the newest undone transaction; `undefined` when there is nothing to redo.
2203
+ * Redoes the newest undone transaction: how it went and the pages it touched; `undefined`
2204
+ * when there is nothing to redo.
1640
2205
  *
1641
2206
  * # Errors
1642
2207
  * As [`WasmDocument::undo`].
1643
2208
  */
1644
- redo(): UndoOutcomeJs | undefined;
2209
+ redo(): RevertedJs | undefined;
2210
+ /**
2211
+ * Writes what `save` would and leaves the document as it was: not rebased, its changes
2212
+ * still unsaved, the save-time stamp in the copy only (Save a copy).
2213
+ *
2214
+ * # Errors
2215
+ * As `save`; the document is unchanged either way.
2216
+ */
2217
+ saveCopy(options: SaveOptionsInit | undefined): { bytes: Uint8Array<ArrayBuffer>; report: SaveReportJs };
1645
2218
  /**
1646
2219
  * A save as a job, stepped with a budget of work units (ADR 0028 §3, §4).
1647
2220
  *
@@ -1665,16 +2238,24 @@ export class WasmDocument {
1665
2238
  */
1666
2239
  structureTree(): StructureNodeJs[] | undefined;
1667
2240
  /**
1668
- * Undoes the newest transaction; `undefined` when there is nothing to undo.
2241
+ * Undoes the newest transaction: how it went and the pages it touched; `undefined` when
2242
+ * there is nothing to undo.
1669
2243
  *
1670
2244
  * # Errors
1671
2245
  * `nested-transaction`, `saved-not-rebased`; reading errors.
1672
2246
  */
1673
- undo(): UndoOutcomeJs | undefined;
2247
+ undo(): RevertedJs | undefined;
1674
2248
  /**
1675
2249
  * A cursor over the warnings so far (build warnings first), each as the §1 object.
1676
2250
  */
1677
2251
  warnings(): WasmWarningCursor;
2252
+ /**
2253
+ * The signature restrictions `op` would break if it were applied and saved.
2254
+ *
2255
+ * # Errors
2256
+ * `invalid-argument` for a value that isn't an op; reading errors.
2257
+ */
2258
+ wouldViolate(op: Op): ViolationJs[];
1678
2259
  }
1679
2260
 
1680
2261
  /**
@@ -1709,6 +2290,26 @@ export class WasmExtractJob {
1709
2290
  step(budget: number): ({ state: "progress" } & ExtractProgressJs) | { state: "done"; output: string };
1710
2291
  }
1711
2292
 
2293
+ /**
2294
+ * The fonts and images a document names, by the names it gives them.
2295
+ */
2296
+ export class WasmFlowResources {
2297
+ free(): void;
2298
+ [Symbol.dispose](): void;
2299
+ /**
2300
+ * `font` for the styles that name `name`; the same name again replaces it.
2301
+ */
2302
+ font(name: string, font: WasmFont): void;
2303
+ /**
2304
+ * `image` for the figures that name `name`; the same name again replaces it.
2305
+ */
2306
+ image(name: string, image: WasmImage): void;
2307
+ /**
2308
+ * No fonts and no images.
2309
+ */
2310
+ constructor();
2311
+ }
2312
+
1712
2313
  /**
1713
2314
  * A font registered with a [`WasmBuilder`].
1714
2315
  */
@@ -1768,6 +2369,30 @@ export class WasmImage {
1768
2369
  readonly width: number;
1769
2370
  }
1770
2371
 
2372
+ /**
2373
+ * The fonts and images of a Markdown build, by role and by the target the Markdown names.
2374
+ */
2375
+ export class WasmMarkdownOptions {
2376
+ free(): void;
2377
+ [Symbol.dispose](): void;
2378
+ /**
2379
+ * `font` for `role`: `regular`, `bold` (headings too), `italic`, `boldItalic`, `mono`, or
2380
+ * `fallback` (each call adds one) for characters the others lack.
2381
+ *
2382
+ * # Errors
2383
+ * `invalid-argument` for another role.
2384
+ */
2385
+ font(role: string, font: WasmFont): void;
2386
+ /**
2387
+ * `image` for the images whose target is `target`, as the Markdown writes it.
2388
+ */
2389
+ image(target: string, image: WasmImage): void;
2390
+ /**
2391
+ * No fonts (the standard 14 Helvetica family and Courier) and no images.
2392
+ */
2393
+ constructor();
2394
+ }
2395
+
1771
2396
  /**
1772
2397
  * A page of a [`WasmDocument`], held by its ID (F2): moving pages doesn't retarget it.
1773
2398
  */
@@ -2103,8 +2728,10 @@ export interface InitOutput {
2103
2728
  readonly __wbg_wasmbuilder_free: (a: number, b: number) => void;
2104
2729
  readonly __wbg_wasmdocument_free: (a: number, b: number) => void;
2105
2730
  readonly __wbg_wasmextractjob_free: (a: number, b: number) => void;
2731
+ readonly __wbg_wasmflowresources_free: (a: number, b: number) => void;
2106
2732
  readonly __wbg_wasmfont_free: (a: number, b: number) => void;
2107
2733
  readonly __wbg_wasmimage_free: (a: number, b: number) => void;
2734
+ readonly __wbg_wasmmarkdownoptions_free: (a: number, b: number) => void;
2108
2735
  readonly __wbg_wasmpage_free: (a: number, b: number) => void;
2109
2736
  readonly __wbg_wasmpagebuilder_free: (a: number, b: number) => void;
2110
2737
  readonly __wbg_wasmsavejob_free: (a: number, b: number) => void;
@@ -2116,8 +2743,11 @@ export interface InitOutput {
2116
2743
  readonly wasmbuilder_attach: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: any) => [number, number];
2117
2744
  readonly wasmbuilder_destination: (a: number, b: number, c: number, d: number, e: any) => [number, number];
2118
2745
  readonly wasmbuilder_finish: (a: number) => [number, number, number];
2746
+ readonly wasmbuilder_flow: (a: number, b: any, c: number, d: any) => [number, number, number];
2119
2747
  readonly wasmbuilder_fontBytes: (a: number, b: number, c: number) => [number, number, number];
2748
+ readonly wasmbuilder_fontCollection: (a: number, b: number, c: number, d: number) => [number, number, number];
2120
2749
  readonly wasmbuilder_lang: (a: number, b: number, c: number) => [number, number];
2750
+ readonly wasmbuilder_markdown: (a: number, b: number, c: number, d: number, e: any) => [number, number, number];
2121
2751
  readonly wasmbuilder_metadata: (a: number, b: any) => [number, number];
2122
2752
  readonly wasmbuilder_new: (a: any) => [number, number, number];
2123
2753
  readonly wasmbuilder_outline: (a: number, b: any) => [number, number, number];
@@ -2125,13 +2755,16 @@ export interface InitOutput {
2125
2755
  readonly wasmbuilder_pageLabels: (a: number, b: any) => [number, number];
2126
2756
  readonly wasmbuilder_standardFont: (a: number, b: number, c: number) => [number, number, number];
2127
2757
  readonly wasmbuilder_viewerPreferences: (a: number, b: any) => [number, number];
2758
+ readonly wasmdocument_adoptCopy: (a: number, b: number, c: number, d: number) => [number, number];
2128
2759
  readonly wasmdocument_apply: (a: number, b: any) => [number, number, number];
2129
2760
  readonly wasmdocument_applyLog: (a: number, b: number, c: number) => [number, number, number];
2130
2761
  readonly wasmdocument_extract: (a: number, b: any) => [number, number, number, number];
2131
2762
  readonly wasmdocument_extractJob: (a: number, b: any) => [number, number, number];
2132
2763
  readonly wasmdocument_hasUnsavedChanges: (a: number) => number;
2133
2764
  readonly wasmdocument_info: (a: number) => [number, number, number];
2765
+ readonly wasmdocument_isEncrypted: (a: number) => number;
2134
2766
  readonly wasmdocument_isTagged: (a: number) => [number, number, number];
2767
+ readonly wasmdocument_metadata: (a: number) => [number, number, number];
2135
2768
  readonly wasmdocument_namedDestination: (a: number, b: number, c: number) => [number, number, number];
2136
2769
  readonly wasmdocument_openBytes: (a: number, b: number, c: any) => [number, number, number];
2137
2770
  readonly wasmdocument_openSource: (a: number, b: any) => [number, number, number];
@@ -2142,17 +2775,23 @@ export interface InitOutput {
2142
2775
  readonly wasmdocument_pageInfo: (a: number, b: number) => [number, number, number];
2143
2776
  readonly wasmdocument_pageInfos: (a: number) => [number, number, number];
2144
2777
  readonly wasmdocument_pageLinks: (a: number, b: number) => [number, number, number];
2778
+ readonly wasmdocument_plan: (a: number, b: any) => [number, number, number];
2145
2779
  readonly wasmdocument_properties: (a: number) => [number, number, number];
2146
2780
  readonly wasmdocument_rebase: (a: number, b: number, c: number) => [number, number];
2147
2781
  readonly wasmdocument_redo: (a: number) => [number, number, number];
2148
2782
  readonly wasmdocument_save: (a: number, b: any) => [number, number, number];
2783
+ readonly wasmdocument_saveCopy: (a: number, b: any) => [number, number, number];
2149
2784
  readonly wasmdocument_saveJob: (a: number, b: any) => [number, number, number];
2150
2785
  readonly wasmdocument_structureTree: (a: number) => [number, number, number];
2151
2786
  readonly wasmdocument_undo: (a: number) => [number, number, number];
2152
2787
  readonly wasmdocument_warnings: (a: number) => number;
2788
+ readonly wasmdocument_wouldViolate: (a: number, b: any) => [number, number, number];
2153
2789
  readonly wasmextractjob_cancel: (a: number) => void;
2154
2790
  readonly wasmextractjob_provide: (a: number, b: any) => [number, number];
2155
2791
  readonly wasmextractjob_step: (a: number, b: number) => [number, number, number];
2792
+ readonly wasmflowresources_font: (a: number, b: number, c: number, d: number) => void;
2793
+ readonly wasmflowresources_image: (a: number, b: number, c: number, d: number) => void;
2794
+ readonly wasmflowresources_new: () => number;
2156
2795
  readonly wasmfont_family: (a: number) => [number, number];
2157
2796
  readonly wasmfont_isStandard: (a: number) => number;
2158
2797
  readonly wasmfont_postscriptName: (a: number) => [number, number];
@@ -2161,6 +2800,9 @@ export interface InitOutput {
2161
2800
  readonly wasmimage_png: (a: number, b: number) => [number, number, number];
2162
2801
  readonly wasmimage_rgba: (a: number, b: number, c: number, d: number) => [number, number, number];
2163
2802
  readonly wasmimage_width: (a: number) => number;
2803
+ readonly wasmmarkdownoptions_font: (a: number, b: number, c: number, d: number) => [number, number];
2804
+ readonly wasmmarkdownoptions_image: (a: number, b: number, c: number, d: number) => void;
2805
+ readonly wasmmarkdownoptions_new: () => number;
2164
2806
  readonly wasmpage_id: (a: number) => [number, number];
2165
2807
  readonly wasmpage_index: (a: number) => [number, number, number];
2166
2808
  readonly wasmpage_info: (a: number) => [number, number, number];