pdf-lite 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/EXAMPLES.md CHANGED
@@ -1109,12 +1109,17 @@ console.log('Created form-empty.pdf with empty form fields')
1109
1109
  const emptyFormBytes = await fs.readFile(`${tmpFolder}/form-empty.pdf`)
1110
1110
  const filledDocument = await PdfDocument.fromBytes([emptyFormBytes])
1111
1111
 
1112
- await filledDocument.acroForm.setFieldValues({
1112
+ const acroform = await filledDocument.acroForm.getAcroForm()
1113
+ if (!acroform) {
1114
+ throw new Error('No AcroForm found in the document')
1115
+ }
1116
+ acroform.importData({
1113
1117
  name: 'John Doe',
1114
1118
  email: 'john.doe@example.com',
1115
1119
  phone: '+1 (555) 123-4567',
1116
1120
  subscribe: 'Off', // For checkbox, use the "Yes/Off" value
1117
1121
  })
1122
+ await filledDocument.acroForm.write(acroform)
1118
1123
 
1119
1124
  // Save the filled form
1120
1125
  await fs.writeFile(`${tmpFolder}/form-filled.pdf`, filledDocument.toBytes())
@@ -1814,3 +1819,187 @@ console.log(
1814
1819
  JSON.stringify(validationResult, null, 2),
1815
1820
  )
1816
1821
  ```
1822
+
1823
+ ## Custom font embedding example
1824
+
1825
+ ```typescript
1826
+ // Demonstrates how to embed TrueType fonts and use standard PDF fonts
1827
+
1828
+ import { writeFileSync, readFileSync, existsSync } from 'fs'
1829
+ import { PdfArray } from 'pdf-lite/core/objects/pdf-array'
1830
+ import { PdfDictionary } from 'pdf-lite/core/objects/pdf-dictionary'
1831
+ import { PdfIndirectObject } from 'pdf-lite/core/objects/pdf-indirect-object'
1832
+ import { PdfName } from 'pdf-lite/core/objects/pdf-name'
1833
+ import { PdfNumber } from 'pdf-lite/core/objects/pdf-number'
1834
+ import { PdfStream } from 'pdf-lite/core/objects/pdf-stream'
1835
+ import { PdfDocument } from 'pdf-lite/pdf/pdf-document'
1836
+ import { parseFont } from 'pdf-lite'
1837
+
1838
+ // Helper to create a page
1839
+ function createPage(
1840
+ contentStreamRef: PdfIndirectObject<PdfStream>,
1841
+ resourcesRef: PdfIndirectObject<PdfDictionary>,
1842
+ pagesRef: PdfIndirectObject<PdfDictionary>,
1843
+ ): PdfIndirectObject<PdfDictionary> {
1844
+ const pageDict = new PdfDictionary()
1845
+ pageDict.set('Type', new PdfName('Page'))
1846
+ pageDict.set(
1847
+ 'MediaBox',
1848
+ new PdfArray([
1849
+ new PdfNumber(0),
1850
+ new PdfNumber(0),
1851
+ new PdfNumber(612),
1852
+ new PdfNumber(792),
1853
+ ]),
1854
+ )
1855
+ pageDict.set('Contents', contentStreamRef.reference)
1856
+ pageDict.set('Resources', resourcesRef.reference)
1857
+ pageDict.set('Parent', pagesRef.reference)
1858
+ return new PdfIndirectObject({ content: pageDict })
1859
+ }
1860
+
1861
+ function createPages(): PdfIndirectObject<PdfDictionary> {
1862
+ const pagesDict = new PdfDictionary()
1863
+ pagesDict.set('Type', new PdfName('Pages'))
1864
+ pagesDict.set('Kids', new PdfArray([]))
1865
+ pagesDict.set('Count', new PdfNumber(0))
1866
+ return new PdfIndirectObject({ content: pagesDict })
1867
+ }
1868
+
1869
+ function createCatalog(
1870
+ pagesRef: PdfIndirectObject<PdfDictionary>,
1871
+ ): PdfIndirectObject<PdfDictionary> {
1872
+ const catalogDict = new PdfDictionary()
1873
+ catalogDict.set('Type', new PdfName('Catalog'))
1874
+ catalogDict.set('Pages', pagesRef.reference)
1875
+ return new PdfIndirectObject({ content: catalogDict })
1876
+ }
1877
+
1878
+ async function main() {
1879
+ const document = new PdfDocument()
1880
+
1881
+ // Create document structure
1882
+ const pages = createPages()
1883
+ const catalog = createCatalog(pages)
1884
+
1885
+ document.add(pages, catalog)
1886
+ document.trailerDict.set('Root', catalog.reference)
1887
+ await document.commit()
1888
+
1889
+ // Embed a standard font (built into all PDF readers)
1890
+ const helveticaBold =
1891
+ await document.fonts.embedStandardFont('Helvetica-Bold')
1892
+ const timesRoman = await document.fonts.embedStandardFont('Times-Roman')
1893
+ const courier = await document.fonts.embedStandardFont('Courier')
1894
+
1895
+ console.log(
1896
+ `Embedded standard fonts: ${helveticaBold}, ${timesRoman}, ${courier}`,
1897
+ )
1898
+
1899
+ // Embed Roboto TrueType font
1900
+ const fontPath = `${import.meta.dirname}/tmp/Roboto-Regular.ttf`
1901
+
1902
+ if (!existsSync(fontPath)) {
1903
+ console.error(`Font not found: ${fontPath}`)
1904
+ console.error(
1905
+ 'Download it with: curl -L -o examples/tmp/Roboto-Regular.ttf "https://github.com/google/fonts/raw/main/ofl/roboto/Roboto%5Bwdth%2Cwght%5D.ttf"',
1906
+ )
1907
+ process.exit(1)
1908
+ }
1909
+
1910
+ const fontData = readFileSync(fontPath)
1911
+
1912
+ // Parse the font file to extract metrics automatically
1913
+ // parseFont() auto-detects TTF, OTF, and WOFF formats
1914
+ const parser = parseFont(fontData)
1915
+ const fontInfo = parser.getFontInfo()
1916
+ const fontDescriptor = parser.getFontDescriptor('Roboto')
1917
+
1918
+ console.log(`Parsed font: ${fontInfo.fullName} (${fontInfo.fontFamily})`)
1919
+
1920
+ const robotoFont = await document.fonts.embedTrueTypeFont(
1921
+ fontData,
1922
+ 'Roboto',
1923
+ fontDescriptor,
1924
+ )
1925
+ console.log(`Embedded Roboto TrueType font: ${robotoFont}`)
1926
+
1927
+ // Create resources dictionary with fonts
1928
+ const resourcesDict = new PdfDictionary()
1929
+ const fontDict = new PdfDictionary()
1930
+
1931
+ // Get font references from the font manager
1932
+ const helveticaFont = document.fonts.getFont('Helvetica-Bold')
1933
+ const timesFont = document.fonts.getFont('Times-Roman')
1934
+ const courierFont = document.fonts.getFont('Courier')
1935
+
1936
+ if (helveticaFont)
1937
+ fontDict.set(helveticaFont.baseFont, helveticaFont.fontRef.reference)
1938
+ if (timesFont) fontDict.set(timesFont.baseFont, timesFont.fontRef.reference)
1939
+ if (courierFont)
1940
+ fontDict.set(courierFont.baseFont, courierFont.fontRef.reference)
1941
+
1942
+ const roboto = document.fonts.getFont('Roboto')
1943
+ if (roboto) fontDict.set(roboto.baseFont, roboto.fontRef.reference)
1944
+
1945
+ resourcesDict.set('Font', fontDict)
1946
+ const resources = new PdfIndirectObject({ content: resourcesDict })
1947
+
1948
+ // Build content stream with different fonts
1949
+ // F1=Helvetica-Bold, F2=Times-Roman, F3=Courier, F4=Roboto
1950
+ const lines: string[] = [
1951
+ 'BT',
1952
+ '/F1 24 Tf',
1953
+ '72 700 Td',
1954
+ '(PDF-Lite Custom Fonts Demo) Tj',
1955
+ '/F4 16 Tf',
1956
+ '0 -40 Td',
1957
+ '(This line uses embedded Roboto font!) Tj',
1958
+ '/F2 14 Tf',
1959
+ '0 -30 Td',
1960
+ '(This line uses Times Roman) Tj',
1961
+ '/F3 12 Tf',
1962
+ '0 -30 Td',
1963
+ '(This line uses Courier - great for code!) Tj',
1964
+ '/F2 12 Tf',
1965
+ '0 -50 Td',
1966
+ '(Standard PDF fonts are built into all PDF readers:) Tj',
1967
+ '0 -20 Td',
1968
+ '(- Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique) Tj',
1969
+ '0 -20 Td',
1970
+ '(- Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic) Tj',
1971
+ '0 -20 Td',
1972
+ '(- Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique) Tj',
1973
+ '0 -20 Td',
1974
+ '(- Symbol, ZapfDingbats) Tj',
1975
+ '/F4 12 Tf',
1976
+ '0 -40 Td',
1977
+ '(Custom TrueType fonts like Roboto are embedded in the PDF file.) Tj',
1978
+ 'ET',
1979
+ ]
1980
+
1981
+ const contentStream = new PdfIndirectObject({
1982
+ content: new PdfStream({
1983
+ header: new PdfDictionary(),
1984
+ original: lines.join('\n'),
1985
+ }),
1986
+ })
1987
+
1988
+ // Create page
1989
+ const page = createPage(contentStream, resources, pages)
1990
+
1991
+ // Update pages collection
1992
+ pages.content.set('Kids', new PdfArray([page.reference]))
1993
+ pages.content.set('Count', new PdfNumber(1))
1994
+
1995
+ document.add(resources, contentStream, page)
1996
+ await document.commit()
1997
+
1998
+ // Write output
1999
+ const outputPath = `${import.meta.dirname}/tmp/fonts-demo.pdf`
2000
+ writeFileSync(outputPath, document.toBytes())
2001
+ console.log(`\nPDF written to: ${outputPath}`)
2002
+ }
2003
+
2004
+ main().catch(console.error)
2005
+ ```
@@ -0,0 +1,166 @@
1
+ import { PdfDocument } from '../pdf/pdf-document.js';
2
+ import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
3
+ import { PdfArray } from '../core/objects/pdf-array.js';
4
+ import { PdfString } from '../core/objects/pdf-string.js';
5
+ import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
6
+ import { PdfIndirectObject } from '../core/objects/pdf-indirect-object.js';
7
+ import { PdfName } from '../core/objects/pdf-name.js';
8
+ import { PdfBoolean } from '../core/objects/pdf-boolean.js';
9
+ import { PdfNumber } from '../core/objects/pdf-number.js';
10
+ /**
11
+ * Field types for AcroForm fields
12
+ */
13
+ export declare const PdfFieldType: {
14
+ readonly Text: "Tx";
15
+ readonly Button: "Btn";
16
+ readonly Choice: "Ch";
17
+ readonly Signature: "Sig";
18
+ };
19
+ export declare class PdfAcroFormField extends PdfDictionary<{
20
+ FT: PdfName<'Tx' | 'Btn' | 'Ch' | 'Sig'>;
21
+ T?: PdfString;
22
+ V?: PdfString | PdfName;
23
+ DV?: PdfString | PdfName;
24
+ DA?: PdfString;
25
+ AS?: PdfName;
26
+ Kids?: PdfArray<PdfObjectReference>;
27
+ P?: PdfObjectReference;
28
+ Rect?: PdfArray<PdfNumber>;
29
+ F?: PdfNumber;
30
+ Ff?: PdfNumber;
31
+ BS?: PdfDictionary;
32
+ MK?: PdfDictionary;
33
+ }> {
34
+ parent?: PdfAcroFormField;
35
+ readonly container?: PdfIndirectObject;
36
+ constructor(options?: {
37
+ container?: PdfIndirectObject;
38
+ });
39
+ /**
40
+ * Gets the field type
41
+ */
42
+ get fieldType(): string | null;
43
+ /**
44
+ * Gets the field name
45
+ */
46
+ get name(): string;
47
+ /**
48
+ * Sets the field name
49
+ */
50
+ set name(name: string);
51
+ /**
52
+ * Gets the default value
53
+ */
54
+ get defaultValue(): string;
55
+ /**
56
+ * Sets the default value
57
+ */
58
+ set defaultValue(val: string);
59
+ get value(): string;
60
+ set value(val: string);
61
+ get checked(): boolean;
62
+ set checked(isChecked: boolean);
63
+ get fontSize(): number | null;
64
+ set fontSize(size: number);
65
+ get fontName(): string | null;
66
+ set fontName(fontName: string);
67
+ /**
68
+ * Gets field flags (bitwise combination of field attributes)
69
+ */
70
+ get flags(): number;
71
+ /**
72
+ * Sets field flags
73
+ */
74
+ set flags(flags: number);
75
+ /**
76
+ * Checks if the field is read-only
77
+ */
78
+ get readOnly(): boolean;
79
+ /**
80
+ * Sets the field as read-only or editable
81
+ */
82
+ set readOnly(isReadOnly: boolean);
83
+ /**
84
+ * Checks if the field is required
85
+ */
86
+ get required(): boolean;
87
+ /**
88
+ * Sets the field as required or optional
89
+ */
90
+ set required(isRequired: boolean);
91
+ /**
92
+ * Checks if the field is multiline (for text fields)
93
+ */
94
+ get multiline(): boolean;
95
+ /**
96
+ * Sets the field as multiline (for text fields)
97
+ */
98
+ set multiline(isMultiline: boolean);
99
+ /**
100
+ * Checks if the field is a password field (for text fields)
101
+ */
102
+ get password(): boolean;
103
+ /**
104
+ * Sets the field as a password field (for text fields)
105
+ */
106
+ set password(isPassword: boolean);
107
+ }
108
+ export declare class PdfAcroForm<T extends Record<string, string> = Record<string, string>> extends PdfDictionary<{
109
+ Fields: PdfArray<PdfObjectReference>;
110
+ NeedAppearances?: PdfBoolean;
111
+ SigFlags?: PdfNumber;
112
+ CO?: PdfArray<PdfObjectReference>;
113
+ DR?: PdfDictionary;
114
+ DA?: PdfString;
115
+ Q?: PdfNumber;
116
+ }> {
117
+ fields: PdfAcroFormField[];
118
+ readonly container?: PdfIndirectObject;
119
+ constructor(options: {
120
+ dict: PdfDictionary;
121
+ fields?: PdfAcroFormField[];
122
+ container?: PdfIndirectObject;
123
+ });
124
+ /**
125
+ * Gets the NeedAppearances flag
126
+ */
127
+ get needAppearances(): boolean;
128
+ /**
129
+ * Sets the NeedAppearances flag to indicate that appearance streams need to be regenerated
130
+ */
131
+ set needAppearances(value: boolean);
132
+ /**
133
+ * Gets the signature flags
134
+ */
135
+ get signatureFlags(): number;
136
+ /**
137
+ * Sets the signature flags
138
+ */
139
+ set signatureFlags(flags: number);
140
+ /**
141
+ * Gets the default appearance string for the form
142
+ */
143
+ get defaultAppearance(): string | null;
144
+ /**
145
+ * Sets the default appearance string for the form
146
+ */
147
+ set defaultAppearance(da: string);
148
+ /**
149
+ * Gets the default quadding (alignment) for the form
150
+ * 0 = left, 1 = center, 2 = right
151
+ */
152
+ get defaultQuadding(): number;
153
+ /**
154
+ * Sets the default quadding (alignment) for the form
155
+ */
156
+ set defaultQuadding(q: number);
157
+ /**
158
+ * Sets multiple field values by field name.
159
+ * @param values Object with field names as keys and values to set
160
+ * */
161
+ setValues(values: Partial<T>): void;
162
+ importData(fields: T): void;
163
+ exportData(): Partial<T>;
164
+ static fromDocument(document: PdfDocument): Promise<PdfAcroForm | null>;
165
+ write(document: PdfDocument): Promise<void>;
166
+ }