@pdftron/pdfnet-node-samples 10.8.0 → 10.9.0-1
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/{samples/AddImageTest → AddImageTest}/AddImageTest.js +115 -115
- package/{samples/AdvancedImagingTest → AdvancedImagingTest}/AdvancedImagingTest.js +78 -78
- package/{samples/AnnotationTest → AnnotationTest}/AnnotationTest.js +641 -641
- package/{samples/BookmarkTest → BookmarkTest}/BookmarkTest.js +219 -219
- package/{samples/CAD2PDFTest → CAD2PDFTest}/CAD2PDFTest.js +79 -79
- package/{samples/ContentReplacerTest → ContentReplacerTest}/ContentReplacerTest.js +75 -75
- package/{samples/ConvertPrintTest → ConvertPrintTest}/ConvertPrintTest.js +153 -153
- package/{samples/ConvertTest → ConvertTest}/ConvertTest.js +203 -203
- package/{samples/DataExtractionTest → DataExtractionTest}/DataExtractionTest.js +214 -214
- package/{samples/DigitalSignaturesTest → DigitalSignaturesTest}/DigitalSignaturesTest.js +621 -526
- package/{samples/DocumentCreationTest → DocumentCreationTest}/DocumentCreationTest.js +409 -409
- package/{samples/ElementBuilderTest → ElementBuilderTest}/ElementBuilderTest.js +513 -513
- package/{samples/ElementEditTest → ElementEditTest}/ElementEditTest.js +110 -110
- package/{samples/ElementReaderAdvTest → ElementReaderAdvTest}/ElementReaderAdvTest.js +305 -305
- package/{samples/ElementReaderTest → ElementReaderTest}/ElementReaderTest.js +77 -77
- package/{samples/EncTest → EncTest}/EncTest.js +175 -175
- package/{samples/FDFTest → FDFTest}/FDFTest.js +218 -218
- package/{samples/HTML2PDFTest → HTML2PDFTest}/HTML2PDFTest.js +164 -164
- package/{samples/HighlightsTest → HighlightsTest}/HighlightsTest.js +97 -97
- package/{samples/ImageExtractTest → ImageExtractTest}/ImageExtractTest.js +129 -129
- package/{samples/ImpositionTest → ImpositionTest}/ImpositionTest.js +86 -86
- package/{samples/InteractiveFormsTest → InteractiveFormsTest}/InteractiveFormsTest.js +381 -381
- package/{samples/JBIG2Test → JBIG2Test}/JBIG2Test.js +88 -88
- package/{samples/LicenseKey → LicenseKey}/LicenseKey.js +11 -11
- package/{samples/LogicalStructureTest → LogicalStructureTest}/LogicalStructureTest.js +250 -250
- package/{samples/OCRTest → OCRTest}/OCRTest.js +235 -235
- package/{samples/OfficeTemplateTest → OfficeTemplateTest}/OfficeTemplateTest.js +79 -79
- package/{samples/OfficeToPDFTest → OfficeToPDFTest}/OfficeToPDFTest.js +125 -125
- package/{samples/OptimizerTest → OptimizerTest}/OptimizerTest.js +191 -191
- package/{samples/PDF2HtmlTest → PDF2HtmlTest}/PDF2HtmlTest.js +123 -123
- package/{samples/PDF2OfficeTest → PDF2OfficeTest}/PDF2OfficeTest.js +158 -158
- package/{samples/PDFATest → PDFATest}/PDFATest.js +85 -85
- package/{samples/PDFDocMemoryTest → PDFDocMemoryTest}/PDFDocMemoryTest.js +84 -84
- package/{samples/PDFDrawTest → PDFDrawTest}/PDFDrawTest.js +305 -305
- package/{samples/PDFLayersTest → PDFLayersTest}/PDFLayersTest.js +294 -294
- package/{samples/PDFPackageTest → PDFPackageTest}/PDFPackageTest.js +111 -111
- package/{samples/PDFPageTest → PDFPageTest}/PDFPageTest.js +189 -189
- package/{samples/PDFRedactTest → PDFRedactTest}/PDFRedactTest.js +74 -74
- package/{samples/PageLabelsTest → PageLabelsTest}/PageLabelsTest.js +138 -138
- package/{samples/PatternTest → PatternTest}/PatternTest.js +226 -226
- package/{samples/RectTest → RectTest}/RectTest.js +40 -40
- package/{samples/SDFTest → SDFTest}/SDFTest.js +87 -87
- package/{samples/StamperTest → StamperTest}/StamperTest.js +255 -255
- package/{samples/TestFiles → TestFiles}/Misc-Fixed.pfa +1166 -1166
- package/{samples/TestFiles → TestFiles}/SHA-2 Root USERTrust RSA CA Sectigo timestamping.crt +34 -34
- package/{samples/TestFiles → TestFiles}/form1_annots.xfdf +33 -33
- package/{samples/TestFiles → TestFiles}/form1_data.xfdf +139 -139
- package/{samples/TestFiles → TestFiles}/my_stream.txt +2310 -2310
- package/{samples/TestFiles → TestFiles}/tiger.svg +378 -378
- package/{samples/TextExtractTest → TextExtractTest}/TextExtractTest.js +286 -286
- package/{samples/TextSearchTest → TextSearchTest}/TextSearchTest.js +121 -121
- package/{samples/U3DTest → U3DTest}/U3DTest.js +104 -104
- package/{samples/UndoRedoTest → UndoRedoTest}/UndoRedoTest.js +101 -101
- package/{samples/UnicodeWriteTest → UnicodeWriteTest}/UnicodeWriteTest.js +173 -173
- package/{samples/WebViewerConvertTest → WebViewerConvertTest}/WebViewerConvertTest.js +135 -135
- package/legal.txt +632 -0
- package/license.pdf +0 -0
- package/package.json +20 -21
- package/readme.md +38 -13
- package/{samples/runall.bat → runall.bat} +12 -12
- package/{samples/runall.sh → runall.sh} +15 -15
- /package/{samples/TestFiles → TestFiles}/BusinessCardTemplate.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/Fishermen.docx +0 -0
- /package/{samples/TestFiles → TestFiles}/Font_licenses.txt +0 -0
- /package/{samples/TestFiles → TestFiles}/GlobalSignRootForTST.cer +0 -0
- /package/{samples/TestFiles → TestFiles}/License.txt +0 -0
- /package/{samples/TestFiles → TestFiles}/NotoSans_with_hindi.ttf +0 -0
- /package/{samples/TestFiles → TestFiles}/Output/empty +0 -0
- /package/{samples/TestFiles → TestFiles}/SYH_Letter.docx +0 -0
- /package/{samples/TestFiles → TestFiles}/TigerText.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/US061222892-a.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/butterfly.png +0 -0
- /package/{samples/TestFiles → TestFiles}/credit card numbers.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/dice.jpg +0 -0
- /package/{samples/TestFiles → TestFiles}/dice.u3d +0 -0
- /package/{samples/TestFiles → TestFiles}/doc_to_sign.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/factsheet_Arabic.docx +0 -0
- /package/{samples/TestFiles → TestFiles}/financial.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/fish.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/font.ttf +0 -0
- /package/{samples/TestFiles → TestFiles}/form1.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/form1_data.fdf +0 -0
- /package/{samples/TestFiles → TestFiles}/formfields-scanned-withfields.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/formfields-scanned.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/formfields.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/grayscale.tif +0 -0
- /package/{samples/TestFiles → TestFiles}/hindi_sample_utf16le.txt +0 -0
- /package/{samples/TestFiles → TestFiles}/imagemask.dat +0 -0
- /package/{samples/TestFiles → TestFiles}/logo_red.png +0 -0
- /package/{samples/TestFiles → TestFiles}/lorem_ipsum.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/multipage.tif +0 -0
- /package/{samples/TestFiles → TestFiles}/newsletter.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/newsletter.xod +0 -0
- /package/{samples/TestFiles → TestFiles}/numbered.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/op_blend_test.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/palm.jp2 +0 -0
- /package/{samples/TestFiles → TestFiles}/paragraphs_and_tables.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/pdfnet.gif +0 -0
- /package/{samples/TestFiles → TestFiles}/pdftron.bmp +0 -0
- /package/{samples/TestFiles → TestFiles}/pdftron.cer +0 -0
- /package/{samples/TestFiles → TestFiles}/pdftron.pfx +0 -0
- /package/{samples/TestFiles → TestFiles}/pdftron_smart_substitution.plugin +0 -0
- /package/{samples/TestFiles → TestFiles}/peppers.jpg +0 -0
- /package/{samples/TestFiles → TestFiles}/signature.jpg +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-emf.emf +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-excel_2007.xlsx +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-outlook.msg +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-powerpoint_2007.pptx +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-publisher.pub +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-rtf.rtf +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-text.txt +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-visio.vsd +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage.html +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage.mht +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/colorschememapping.xml +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/filelist.xml +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image001.gif +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image002.png +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image003.jpg +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image004.emz +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image005.gif +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image006.png +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/image007.gif +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/oledata.mso +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-webpage_files/themedata.thmx +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-word_2007.docx +0 -0
- /package/{samples/TestFiles → TestFiles}/simple-xps.xps +0 -0
- /package/{samples/TestFiles → TestFiles}/table.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/tagged.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/the_rime_of_the_ancient_mariner.docx +0 -0
- /package/{samples/TestFiles → TestFiles}/tiger.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/waiver.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/waiver_withApprovalField.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/waiver_withApprovalField_certified.pdf +0 -0
- /package/{samples/TestFiles → TestFiles}/waiver_withApprovalField_certified_approved.pdf +0 -0
|
@@ -1,251 +1,251 @@
|
|
|
1
|
-
//---------------------------------------------------------------------------------------
|
|
2
|
-
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
|
|
3
|
-
// Consult legal.txt regarding legal and license information.
|
|
4
|
-
//---------------------------------------------------------------------------------------
|
|
5
|
-
|
|
6
|
-
//---------------------------------------------------------------------------------------
|
|
7
|
-
// This sample explores the structure and content of a tagged PDF document and dumps
|
|
8
|
-
// the structure information to the console window.
|
|
9
|
-
//
|
|
10
|
-
// In tagged PDF documents StructTree acts as a central repository for information
|
|
11
|
-
// related to a PDF document's logical structure. The tree consists of StructElement-s
|
|
12
|
-
// and ContentItem-s which are leaf nodes of the structure tree.
|
|
13
|
-
//
|
|
14
|
-
// The sample can be extended to access and extract the marked-content elements such
|
|
15
|
-
// as text and images.
|
|
16
|
-
//---------------------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const { PDFNet } = require('@pdftron/pdfnet-node');
|
|
20
|
-
const PDFTronLicense = require('../LicenseKey/LicenseKey');
|
|
21
|
-
|
|
22
|
-
((exports) => {
|
|
23
|
-
|
|
24
|
-
exports.runLogicalStructureTest = () => {
|
|
25
|
-
|
|
26
|
-
const printAndIndent = (printState, indent) => {
|
|
27
|
-
console.log(printState.str);
|
|
28
|
-
|
|
29
|
-
let indentStr = '';
|
|
30
|
-
for (let i = 0; i < indent; ++i) {
|
|
31
|
-
indentStr += ' ';
|
|
32
|
-
}
|
|
33
|
-
printState.str = indentStr;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Used in code snippet 1.
|
|
37
|
-
const processStructElement = async(element, indent, printState) => {
|
|
38
|
-
if (!(await element.isValid())) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Print out the type and title info, if any.
|
|
44
|
-
printAndIndent(printState, indent++);
|
|
45
|
-
printState.str += 'Type: ' + (await element.getType());
|
|
46
|
-
if (await element.hasTitle()) {
|
|
47
|
-
printState.str += '. Title: ' + (await element.getTitle());
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const num = await element.getNumKids();
|
|
51
|
-
for (let i = 0; i < num; ++i) {
|
|
52
|
-
// Check is the kid is a leaf node (i.e. it is a ContentItem).
|
|
53
|
-
if (await element.isContentItem(i)) {
|
|
54
|
-
const cont = await element.getAsContentItem(i);
|
|
55
|
-
const type = await cont.getType();
|
|
56
|
-
|
|
57
|
-
const page = await cont.getPage();
|
|
58
|
-
|
|
59
|
-
printAndIndent(printState, indent);
|
|
60
|
-
printState.str += 'Content Item. Part of page #' + (await page.getIndex());
|
|
61
|
-
|
|
62
|
-
printAndIndent(printState, indent);
|
|
63
|
-
switch (type) {
|
|
64
|
-
case PDFNet.ContentItem.Type.e_MCID:
|
|
65
|
-
case PDFNet.ContentItem.Type.e_MCR:
|
|
66
|
-
printState.str += 'MCID: ' + (await cont.getMCID());
|
|
67
|
-
break;
|
|
68
|
-
case PDFNet.ContentItem.Type.e_OBJR:
|
|
69
|
-
{
|
|
70
|
-
printState.str += 'OBJR ';
|
|
71
|
-
const refObj = await cont.getRefObj();
|
|
72
|
-
if (refObj) {
|
|
73
|
-
printState.str += '- Referenced Object#: ' + refObj.getObjNum();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
break;
|
|
77
|
-
default:
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
} else { // the kid is another StructElement node.
|
|
81
|
-
await processStructElement(await element.getAsStructElem(i), indent, printState);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
// Used in code snippet 2.
|
|
87
|
-
const processElements = async(reader, printState) => {
|
|
88
|
-
let element;
|
|
89
|
-
while (element = await reader.next()) { // Read page contents
|
|
90
|
-
// In this sample we process only paths & text, but the code can be
|
|
91
|
-
// extended to handle any element type.
|
|
92
|
-
const type = await element.getType();
|
|
93
|
-
if (type === PDFNet.Element.Type.e_path || type === PDFNet.Element.Type.e_text || type === PDFNet.Element.Type.e_path) {
|
|
94
|
-
switch (type) {
|
|
95
|
-
case PDFNet.Element.Type.e_path: // Process path ...
|
|
96
|
-
printState.str += '\nPATH: ';
|
|
97
|
-
break;
|
|
98
|
-
case PDFNet.Element.Type.e_text: // Process text ...
|
|
99
|
-
printState.str += '\nTEXT: ' + (await element.getTextString()) + '\n';
|
|
100
|
-
break;
|
|
101
|
-
case PDFNet.Element.Type.e_form: // Process form XObjects
|
|
102
|
-
printState.str += '\nFORM XObject: ';
|
|
103
|
-
// reader.formBegin();
|
|
104
|
-
// await ProcessElements(reader);
|
|
105
|
-
// reader.end();
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check if the element is associated with any structural element.
|
|
110
|
-
// Content items are leaf nodes of the structure tree.
|
|
111
|
-
const structParent = await element.getParentStructElement();
|
|
112
|
-
if (await structParent.isValid()) {
|
|
113
|
-
// Print out the parent structural element's type, title, and object number.
|
|
114
|
-
printState.str += ' Type: ' + (await structParent.getType()) + ', MCID: ' + (await element.getStructMCID());
|
|
115
|
-
if (await structParent.hasTitle()) {
|
|
116
|
-
printState.str += '. Title: ' + (await structParent.getTitle());
|
|
117
|
-
}
|
|
118
|
-
printState.str += ', Obj#: ' + (await (await structParent.getSDFObj()).getObjNum());
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// Used in code snippet 3.
|
|
125
|
-
const processElements2 = async(reader, mcidPageMap) => {
|
|
126
|
-
let element;
|
|
127
|
-
while (element = await reader.next()) { // Read page contents
|
|
128
|
-
// In this sample we process only text, but the code can be extended
|
|
129
|
-
// to handle paths, images, or any other Element type.
|
|
130
|
-
const mcid = await element.getStructMCID();
|
|
131
|
-
if (mcid >= 0 && (await element.getType()) === PDFNet.Element.Type.e_text) {
|
|
132
|
-
const val = await element.getTextString();
|
|
133
|
-
if (mcid in mcidPageMap) {
|
|
134
|
-
mcidPageMap[mcid] += val;
|
|
135
|
-
} else {
|
|
136
|
-
mcidPageMap[mcid] = val;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// Used in code snippet 3.
|
|
143
|
-
const processStructElement2 = async(element, mcidDocMap, indent, printState) => {
|
|
144
|
-
if (!(await element.isValid())) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Print out the type and title info, if any.
|
|
149
|
-
printAndIndent(printState, indent);
|
|
150
|
-
printState.str += '<' + (await element.getType());
|
|
151
|
-
if (await element.hasTitle()) {
|
|
152
|
-
printState.str += ' title="' + (await element.getTitle()) + '"';
|
|
153
|
-
}
|
|
154
|
-
printState.str += '>';
|
|
155
|
-
|
|
156
|
-
const num = await element.getNumKids();
|
|
157
|
-
for (let i = 0; i < num; ++i) {
|
|
158
|
-
if (await element.isContentItem(i)) {
|
|
159
|
-
const cont = await element.getAsContentItem(i);
|
|
160
|
-
if ((await cont.getType()) === PDFNet.ContentItem.Type.e_MCID) {
|
|
161
|
-
const pageNum = await (await cont.getPage()).getIndex();
|
|
162
|
-
const mcidPageMap = mcidDocMap[pageNum];
|
|
163
|
-
if (mcidPageMap) {
|
|
164
|
-
const mcid = await cont.getMCID();
|
|
165
|
-
if (mcid in mcidPageMap) {
|
|
166
|
-
printState.str += mcidPageMap[mcid];
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
} else { // the kid is another StructElement node.
|
|
171
|
-
await processStructElement2(await element.getAsStructElem(i), mcidDocMap, indent + 1, printState);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
printAndIndent(printState, indent);
|
|
176
|
-
printState.str += '</' + (await element.getType()) + '>';
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const main = async() => {
|
|
180
|
-
// Relative path to the folder containing test files.
|
|
181
|
-
const inputPath = '../TestFiles/';
|
|
182
|
-
const printState = { str: '' };
|
|
183
|
-
try { // Extract logical structure from a PDF document
|
|
184
|
-
const doc = await PDFNet.PDFDoc.createFromFilePath(inputPath + 'tagged.pdf');
|
|
185
|
-
doc.initSecurityHandler();
|
|
186
|
-
|
|
187
|
-
let reader = null;
|
|
188
|
-
let tree = null;
|
|
189
|
-
|
|
190
|
-
console.log('____________________________________________________________');
|
|
191
|
-
console.log('Sample 1 - Traverse logical structure tree...');
|
|
192
|
-
tree = await doc.getStructTree();
|
|
193
|
-
if (await tree.isValid()) {
|
|
194
|
-
console.log('Document has a StructTree root.');
|
|
195
|
-
for (let i = 0, numKids = await tree.getNumKids(); i < numKids; ++i) {
|
|
196
|
-
// Recursively get structure info for all child elements.
|
|
197
|
-
await processStructElement(await tree.getKid(i), 0, printState);
|
|
198
|
-
}
|
|
199
|
-
} else {
|
|
200
|
-
console.log('This document does not contain any logical structure.');
|
|
201
|
-
}
|
|
202
|
-
printAndIndent(printState, 0);
|
|
203
|
-
console.log('Done 1.');
|
|
204
|
-
|
|
205
|
-
console.log('____________________________________________________________');
|
|
206
|
-
console.log('Sample 2 - Get parent logical structure elements from');
|
|
207
|
-
console.log('layout elements.');
|
|
208
|
-
reader = await PDFNet.ElementReader.create();
|
|
209
|
-
for (let itr = await doc.getPageIterator(); await itr.hasNext(); itr.next()) {
|
|
210
|
-
reader.beginOnPage(await itr.current());
|
|
211
|
-
await processElements(reader, printState);
|
|
212
|
-
reader.end();
|
|
213
|
-
}
|
|
214
|
-
printAndIndent(printState, 0);
|
|
215
|
-
console.log('Done 2.');
|
|
216
|
-
|
|
217
|
-
console.log('____________________________________________________________');
|
|
218
|
-
console.log("Sample 3 - 'XML style' extraction of PDF logical structure and page content.");
|
|
219
|
-
{
|
|
220
|
-
const mcidDocMap = {};
|
|
221
|
-
for (let itr = await doc.getPageIterator(); await itr.hasNext(); itr.next()) {
|
|
222
|
-
const page = await itr.current();
|
|
223
|
-
reader.beginOnPage(page);
|
|
224
|
-
const pageNum = await page.getIndex();
|
|
225
|
-
const pageMcidMap = {};
|
|
226
|
-
mcidDocMap[pageNum] = pageMcidMap;
|
|
227
|
-
await processElements2(reader, pageMcidMap);
|
|
228
|
-
reader.end();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
tree = await doc.getStructTree();
|
|
232
|
-
if (await tree.isValid()) {
|
|
233
|
-
for (let i = 0, numKids = await tree.getNumKids(); i < numKids; ++i) {
|
|
234
|
-
await processStructElement2(await tree.getKid(i), mcidDocMap, 0, printState);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
printAndIndent(printState, 0);
|
|
239
|
-
console.log('Done 3.');
|
|
240
|
-
await doc.save(inputPath + 'Output/LogicalStructure.pdf', 0);
|
|
241
|
-
} catch (err) {
|
|
242
|
-
console.log(err);
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error){console.log('Error: ' + JSON.stringify(error));}).then(function(){return PDFNet.shutdown();});
|
|
247
|
-
};
|
|
248
|
-
exports.runLogicalStructureTest();
|
|
249
|
-
})(exports);
|
|
250
|
-
// eslint-disable-next-line spaced-comment
|
|
1
|
+
//---------------------------------------------------------------------------------------
|
|
2
|
+
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
|
|
3
|
+
// Consult legal.txt regarding legal and license information.
|
|
4
|
+
//---------------------------------------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
//---------------------------------------------------------------------------------------
|
|
7
|
+
// This sample explores the structure and content of a tagged PDF document and dumps
|
|
8
|
+
// the structure information to the console window.
|
|
9
|
+
//
|
|
10
|
+
// In tagged PDF documents StructTree acts as a central repository for information
|
|
11
|
+
// related to a PDF document's logical structure. The tree consists of StructElement-s
|
|
12
|
+
// and ContentItem-s which are leaf nodes of the structure tree.
|
|
13
|
+
//
|
|
14
|
+
// The sample can be extended to access and extract the marked-content elements such
|
|
15
|
+
// as text and images.
|
|
16
|
+
//---------------------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const { PDFNet } = require('@pdftron/pdfnet-node');
|
|
20
|
+
const PDFTronLicense = require('../LicenseKey/LicenseKey');
|
|
21
|
+
|
|
22
|
+
((exports) => {
|
|
23
|
+
|
|
24
|
+
exports.runLogicalStructureTest = () => {
|
|
25
|
+
|
|
26
|
+
const printAndIndent = (printState, indent) => {
|
|
27
|
+
console.log(printState.str);
|
|
28
|
+
|
|
29
|
+
let indentStr = '';
|
|
30
|
+
for (let i = 0; i < indent; ++i) {
|
|
31
|
+
indentStr += ' ';
|
|
32
|
+
}
|
|
33
|
+
printState.str = indentStr;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Used in code snippet 1.
|
|
37
|
+
const processStructElement = async(element, indent, printState) => {
|
|
38
|
+
if (!(await element.isValid())) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// Print out the type and title info, if any.
|
|
44
|
+
printAndIndent(printState, indent++);
|
|
45
|
+
printState.str += 'Type: ' + (await element.getType());
|
|
46
|
+
if (await element.hasTitle()) {
|
|
47
|
+
printState.str += '. Title: ' + (await element.getTitle());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const num = await element.getNumKids();
|
|
51
|
+
for (let i = 0; i < num; ++i) {
|
|
52
|
+
// Check is the kid is a leaf node (i.e. it is a ContentItem).
|
|
53
|
+
if (await element.isContentItem(i)) {
|
|
54
|
+
const cont = await element.getAsContentItem(i);
|
|
55
|
+
const type = await cont.getType();
|
|
56
|
+
|
|
57
|
+
const page = await cont.getPage();
|
|
58
|
+
|
|
59
|
+
printAndIndent(printState, indent);
|
|
60
|
+
printState.str += 'Content Item. Part of page #' + (await page.getIndex());
|
|
61
|
+
|
|
62
|
+
printAndIndent(printState, indent);
|
|
63
|
+
switch (type) {
|
|
64
|
+
case PDFNet.ContentItem.Type.e_MCID:
|
|
65
|
+
case PDFNet.ContentItem.Type.e_MCR:
|
|
66
|
+
printState.str += 'MCID: ' + (await cont.getMCID());
|
|
67
|
+
break;
|
|
68
|
+
case PDFNet.ContentItem.Type.e_OBJR:
|
|
69
|
+
{
|
|
70
|
+
printState.str += 'OBJR ';
|
|
71
|
+
const refObj = await cont.getRefObj();
|
|
72
|
+
if (refObj) {
|
|
73
|
+
printState.str += '- Referenced Object#: ' + refObj.getObjNum();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
} else { // the kid is another StructElement node.
|
|
81
|
+
await processStructElement(await element.getAsStructElem(i), indent, printState);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Used in code snippet 2.
|
|
87
|
+
const processElements = async(reader, printState) => {
|
|
88
|
+
let element;
|
|
89
|
+
while (element = await reader.next()) { // Read page contents
|
|
90
|
+
// In this sample we process only paths & text, but the code can be
|
|
91
|
+
// extended to handle any element type.
|
|
92
|
+
const type = await element.getType();
|
|
93
|
+
if (type === PDFNet.Element.Type.e_path || type === PDFNet.Element.Type.e_text || type === PDFNet.Element.Type.e_path) {
|
|
94
|
+
switch (type) {
|
|
95
|
+
case PDFNet.Element.Type.e_path: // Process path ...
|
|
96
|
+
printState.str += '\nPATH: ';
|
|
97
|
+
break;
|
|
98
|
+
case PDFNet.Element.Type.e_text: // Process text ...
|
|
99
|
+
printState.str += '\nTEXT: ' + (await element.getTextString()) + '\n';
|
|
100
|
+
break;
|
|
101
|
+
case PDFNet.Element.Type.e_form: // Process form XObjects
|
|
102
|
+
printState.str += '\nFORM XObject: ';
|
|
103
|
+
// reader.formBegin();
|
|
104
|
+
// await ProcessElements(reader);
|
|
105
|
+
// reader.end();
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check if the element is associated with any structural element.
|
|
110
|
+
// Content items are leaf nodes of the structure tree.
|
|
111
|
+
const structParent = await element.getParentStructElement();
|
|
112
|
+
if (await structParent.isValid()) {
|
|
113
|
+
// Print out the parent structural element's type, title, and object number.
|
|
114
|
+
printState.str += ' Type: ' + (await structParent.getType()) + ', MCID: ' + (await element.getStructMCID());
|
|
115
|
+
if (await structParent.hasTitle()) {
|
|
116
|
+
printState.str += '. Title: ' + (await structParent.getTitle());
|
|
117
|
+
}
|
|
118
|
+
printState.str += ', Obj#: ' + (await (await structParent.getSDFObj()).getObjNum());
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Used in code snippet 3.
|
|
125
|
+
const processElements2 = async(reader, mcidPageMap) => {
|
|
126
|
+
let element;
|
|
127
|
+
while (element = await reader.next()) { // Read page contents
|
|
128
|
+
// In this sample we process only text, but the code can be extended
|
|
129
|
+
// to handle paths, images, or any other Element type.
|
|
130
|
+
const mcid = await element.getStructMCID();
|
|
131
|
+
if (mcid >= 0 && (await element.getType()) === PDFNet.Element.Type.e_text) {
|
|
132
|
+
const val = await element.getTextString();
|
|
133
|
+
if (mcid in mcidPageMap) {
|
|
134
|
+
mcidPageMap[mcid] += val;
|
|
135
|
+
} else {
|
|
136
|
+
mcidPageMap[mcid] = val;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Used in code snippet 3.
|
|
143
|
+
const processStructElement2 = async(element, mcidDocMap, indent, printState) => {
|
|
144
|
+
if (!(await element.isValid())) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Print out the type and title info, if any.
|
|
149
|
+
printAndIndent(printState, indent);
|
|
150
|
+
printState.str += '<' + (await element.getType());
|
|
151
|
+
if (await element.hasTitle()) {
|
|
152
|
+
printState.str += ' title="' + (await element.getTitle()) + '"';
|
|
153
|
+
}
|
|
154
|
+
printState.str += '>';
|
|
155
|
+
|
|
156
|
+
const num = await element.getNumKids();
|
|
157
|
+
for (let i = 0; i < num; ++i) {
|
|
158
|
+
if (await element.isContentItem(i)) {
|
|
159
|
+
const cont = await element.getAsContentItem(i);
|
|
160
|
+
if ((await cont.getType()) === PDFNet.ContentItem.Type.e_MCID) {
|
|
161
|
+
const pageNum = await (await cont.getPage()).getIndex();
|
|
162
|
+
const mcidPageMap = mcidDocMap[pageNum];
|
|
163
|
+
if (mcidPageMap) {
|
|
164
|
+
const mcid = await cont.getMCID();
|
|
165
|
+
if (mcid in mcidPageMap) {
|
|
166
|
+
printState.str += mcidPageMap[mcid];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
} else { // the kid is another StructElement node.
|
|
171
|
+
await processStructElement2(await element.getAsStructElem(i), mcidDocMap, indent + 1, printState);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
printAndIndent(printState, indent);
|
|
176
|
+
printState.str += '</' + (await element.getType()) + '>';
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const main = async() => {
|
|
180
|
+
// Relative path to the folder containing test files.
|
|
181
|
+
const inputPath = '../TestFiles/';
|
|
182
|
+
const printState = { str: '' };
|
|
183
|
+
try { // Extract logical structure from a PDF document
|
|
184
|
+
const doc = await PDFNet.PDFDoc.createFromFilePath(inputPath + 'tagged.pdf');
|
|
185
|
+
doc.initSecurityHandler();
|
|
186
|
+
|
|
187
|
+
let reader = null;
|
|
188
|
+
let tree = null;
|
|
189
|
+
|
|
190
|
+
console.log('____________________________________________________________');
|
|
191
|
+
console.log('Sample 1 - Traverse logical structure tree...');
|
|
192
|
+
tree = await doc.getStructTree();
|
|
193
|
+
if (await tree.isValid()) {
|
|
194
|
+
console.log('Document has a StructTree root.');
|
|
195
|
+
for (let i = 0, numKids = await tree.getNumKids(); i < numKids; ++i) {
|
|
196
|
+
// Recursively get structure info for all child elements.
|
|
197
|
+
await processStructElement(await tree.getKid(i), 0, printState);
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
console.log('This document does not contain any logical structure.');
|
|
201
|
+
}
|
|
202
|
+
printAndIndent(printState, 0);
|
|
203
|
+
console.log('Done 1.');
|
|
204
|
+
|
|
205
|
+
console.log('____________________________________________________________');
|
|
206
|
+
console.log('Sample 2 - Get parent logical structure elements from');
|
|
207
|
+
console.log('layout elements.');
|
|
208
|
+
reader = await PDFNet.ElementReader.create();
|
|
209
|
+
for (let itr = await doc.getPageIterator(); await itr.hasNext(); itr.next()) {
|
|
210
|
+
reader.beginOnPage(await itr.current());
|
|
211
|
+
await processElements(reader, printState);
|
|
212
|
+
reader.end();
|
|
213
|
+
}
|
|
214
|
+
printAndIndent(printState, 0);
|
|
215
|
+
console.log('Done 2.');
|
|
216
|
+
|
|
217
|
+
console.log('____________________________________________________________');
|
|
218
|
+
console.log("Sample 3 - 'XML style' extraction of PDF logical structure and page content.");
|
|
219
|
+
{
|
|
220
|
+
const mcidDocMap = {};
|
|
221
|
+
for (let itr = await doc.getPageIterator(); await itr.hasNext(); itr.next()) {
|
|
222
|
+
const page = await itr.current();
|
|
223
|
+
reader.beginOnPage(page);
|
|
224
|
+
const pageNum = await page.getIndex();
|
|
225
|
+
const pageMcidMap = {};
|
|
226
|
+
mcidDocMap[pageNum] = pageMcidMap;
|
|
227
|
+
await processElements2(reader, pageMcidMap);
|
|
228
|
+
reader.end();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
tree = await doc.getStructTree();
|
|
232
|
+
if (await tree.isValid()) {
|
|
233
|
+
for (let i = 0, numKids = await tree.getNumKids(); i < numKids; ++i) {
|
|
234
|
+
await processStructElement2(await tree.getKid(i), mcidDocMap, 0, printState);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
printAndIndent(printState, 0);
|
|
239
|
+
console.log('Done 3.');
|
|
240
|
+
await doc.save(inputPath + 'Output/LogicalStructure.pdf', 0);
|
|
241
|
+
} catch (err) {
|
|
242
|
+
console.log(err);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error){console.log('Error: ' + JSON.stringify(error));}).then(function(){return PDFNet.shutdown();});
|
|
247
|
+
};
|
|
248
|
+
exports.runLogicalStructureTest();
|
|
249
|
+
})(exports);
|
|
250
|
+
// eslint-disable-next-line spaced-comment
|
|
251
251
|
//# sourceURL=LogicalStructureTest.js
|