@fin.cx/einvoice 5.0.2

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.
Files changed (171) hide show
  1. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts/00_commitinfo_data.js +9 -0
  3. package/dist_ts/classes.decoder.d.ts +40 -0
  4. package/dist_ts/classes.decoder.js +320 -0
  5. package/dist_ts/classes.encoder.d.ts +51 -0
  6. package/dist_ts/classes.encoder.js +293 -0
  7. package/dist_ts/classes.xinvoice.d.ts +136 -0
  8. package/dist_ts/classes.xinvoice.js +352 -0
  9. package/dist_ts/einvoice.d.ts +217 -0
  10. package/dist_ts/einvoice.js +505 -0
  11. package/dist_ts/errors.d.ts +121 -0
  12. package/dist_ts/errors.js +241 -0
  13. package/dist_ts/formats/base/base.decoder.d.ts +32 -0
  14. package/dist_ts/formats/base/base.decoder.js +52 -0
  15. package/dist_ts/formats/base/base.encoder.d.ts +13 -0
  16. package/dist_ts/formats/base/base.encoder.js +7 -0
  17. package/dist_ts/formats/base/base.validator.d.ts +44 -0
  18. package/dist_ts/formats/base/base.validator.js +39 -0
  19. package/dist_ts/formats/base.decoder.d.ts +19 -0
  20. package/dist_ts/formats/base.decoder.js +130 -0
  21. package/dist_ts/formats/base.validator.d.ts +44 -0
  22. package/dist_ts/formats/base.validator.js +39 -0
  23. package/dist_ts/formats/cii/cii.decoder.d.ts +61 -0
  24. package/dist_ts/formats/cii/cii.decoder.js +111 -0
  25. package/dist_ts/formats/cii/cii.encoder.d.ts +43 -0
  26. package/dist_ts/formats/cii/cii.encoder.js +48 -0
  27. package/dist_ts/formats/cii/cii.types.d.ts +31 -0
  28. package/dist_ts/formats/cii/cii.types.js +40 -0
  29. package/dist_ts/formats/cii/cii.validator.d.ts +56 -0
  30. package/dist_ts/formats/cii/cii.validator.js +146 -0
  31. package/dist_ts/formats/cii/facturx/facturx.decoder.d.ts +43 -0
  32. package/dist_ts/formats/cii/facturx/facturx.decoder.js +207 -0
  33. package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +82 -0
  34. package/dist_ts/formats/cii/facturx/facturx.encoder.js +400 -0
  35. package/dist_ts/formats/cii/facturx/facturx.types.d.ts +10 -0
  36. package/dist_ts/formats/cii/facturx/facturx.types.js +15 -0
  37. package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +32 -0
  38. package/dist_ts/formats/cii/facturx/facturx.validator.js +138 -0
  39. package/dist_ts/formats/cii/zugferd/zugferd.decoder.d.ts +43 -0
  40. package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +218 -0
  41. package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +97 -0
  42. package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +550 -0
  43. package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +10 -0
  44. package/dist_ts/formats/cii/zugferd/zugferd.types.js +15 -0
  45. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +49 -0
  46. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +229 -0
  47. package/dist_ts/formats/cii/zugferd/zugferd.validator.d.ts +16 -0
  48. package/dist_ts/formats/cii/zugferd/zugferd.validator.js +29 -0
  49. package/dist_ts/formats/decoder.factory.d.ts +15 -0
  50. package/dist_ts/formats/decoder.factory.js +46 -0
  51. package/dist_ts/formats/factories/decoder.factory.d.ts +13 -0
  52. package/dist_ts/formats/factories/decoder.factory.js +56 -0
  53. package/dist_ts/formats/factories/encoder.factory.d.ts +14 -0
  54. package/dist_ts/formats/factories/encoder.factory.js +40 -0
  55. package/dist_ts/formats/factories/validator.factory.d.ts +12 -0
  56. package/dist_ts/formats/factories/validator.factory.js +110 -0
  57. package/dist_ts/formats/factorx.decoder.d.ts +18 -0
  58. package/dist_ts/formats/factorx.decoder.js +178 -0
  59. package/dist_ts/formats/factorx.encoder.d.ts +51 -0
  60. package/dist_ts/formats/factorx.encoder.js +293 -0
  61. package/dist_ts/formats/facturx.decoder.d.ts +18 -0
  62. package/dist_ts/formats/facturx.decoder.js +210 -0
  63. package/dist_ts/formats/facturx.encoder.d.ts +51 -0
  64. package/dist_ts/formats/facturx.encoder.js +293 -0
  65. package/dist_ts/formats/facturx.validator.d.ts +67 -0
  66. package/dist_ts/formats/facturx.validator.js +266 -0
  67. package/dist_ts/formats/pdf/extractors/associated.extractor.d.ts +14 -0
  68. package/dist_ts/formats/pdf/extractors/associated.extractor.js +68 -0
  69. package/dist_ts/formats/pdf/extractors/base.extractor.d.ts +92 -0
  70. package/dist_ts/formats/pdf/extractors/base.extractor.js +319 -0
  71. package/dist_ts/formats/pdf/extractors/index.d.ts +4 -0
  72. package/dist_ts/formats/pdf/extractors/index.js +5 -0
  73. package/dist_ts/formats/pdf/extractors/standard.extractor.d.ts +13 -0
  74. package/dist_ts/formats/pdf/extractors/standard.extractor.js +74 -0
  75. package/dist_ts/formats/pdf/extractors/text.extractor.d.ts +45 -0
  76. package/dist_ts/formats/pdf/extractors/text.extractor.js +151 -0
  77. package/dist_ts/formats/pdf/pdf.embedder.d.ts +69 -0
  78. package/dist_ts/formats/pdf/pdf.embedder.js +183 -0
  79. package/dist_ts/formats/pdf/pdf.extractor.d.ts +49 -0
  80. package/dist_ts/formats/pdf/pdf.extractor.js +98 -0
  81. package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +40 -0
  82. package/dist_ts/formats/pdf/robust-pdf.extractor.js +324 -0
  83. package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +18 -0
  84. package/dist_ts/formats/ubl/en16931.ubl.validator.js +169 -0
  85. package/dist_ts/formats/ubl/generic/ubl.encoder.d.ts +151 -0
  86. package/dist_ts/formats/ubl/generic/ubl.encoder.js +892 -0
  87. package/dist_ts/formats/ubl/ubl.decoder.d.ts +61 -0
  88. package/dist_ts/formats/ubl/ubl.decoder.js +95 -0
  89. package/dist_ts/formats/ubl/ubl.encoder.d.ts +38 -0
  90. package/dist_ts/formats/ubl/ubl.encoder.js +46 -0
  91. package/dist_ts/formats/ubl/ubl.types.d.ts +16 -0
  92. package/dist_ts/formats/ubl/ubl.types.js +21 -0
  93. package/dist_ts/formats/ubl/ubl.validator.d.ts +50 -0
  94. package/dist_ts/formats/ubl/ubl.validator.js +112 -0
  95. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.d.ts +34 -0
  96. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +424 -0
  97. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +75 -0
  98. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +555 -0
  99. package/dist_ts/formats/ubl/xrechnung.validator.d.ts +15 -0
  100. package/dist_ts/formats/ubl/xrechnung.validator.js +107 -0
  101. package/dist_ts/formats/ubl.validator.d.ts +82 -0
  102. package/dist_ts/formats/ubl.validator.js +306 -0
  103. package/dist_ts/formats/utils/format.detector.d.ts +62 -0
  104. package/dist_ts/formats/utils/format.detector.js +249 -0
  105. package/dist_ts/formats/validation/en16931.validator.d.ts +23 -0
  106. package/dist_ts/formats/validation/en16931.validator.js +119 -0
  107. package/dist_ts/formats/validator.factory.d.ts +18 -0
  108. package/dist_ts/formats/validator.factory.js +78 -0
  109. package/dist_ts/formats/xinvoice.decoder.d.ts +28 -0
  110. package/dist_ts/formats/xinvoice.decoder.js +332 -0
  111. package/dist_ts/formats/xinvoice.encoder.d.ts +19 -0
  112. package/dist_ts/formats/xinvoice.encoder.js +282 -0
  113. package/dist_ts/index.d.ts +51 -0
  114. package/dist_ts/index.js +90 -0
  115. package/dist_ts/interfaces/common.d.ts +79 -0
  116. package/dist_ts/interfaces/common.js +24 -0
  117. package/dist_ts/interfaces.d.ts +87 -0
  118. package/dist_ts/interfaces.js +23 -0
  119. package/dist_ts/plugins.d.ts +14 -0
  120. package/dist_ts/plugins.js +31 -0
  121. package/npmextra.json +35 -0
  122. package/package.json +71 -0
  123. package/readme.hints.md +1107 -0
  124. package/readme.howtofixtests.md +38 -0
  125. package/readme.literature.md +1 -0
  126. package/readme.md +998 -0
  127. package/readme.plan.md +481 -0
  128. package/ts/00_commitinfo_data.ts +8 -0
  129. package/ts/einvoice.ts +603 -0
  130. package/ts/errors.ts +341 -0
  131. package/ts/formats/base/base.decoder.ts +68 -0
  132. package/ts/formats/base/base.encoder.ts +14 -0
  133. package/ts/formats/base/base.validator.ts +64 -0
  134. package/ts/formats/cii/cii.decoder.ts +139 -0
  135. package/ts/formats/cii/cii.encoder.ts +64 -0
  136. package/ts/formats/cii/cii.types.ts +44 -0
  137. package/ts/formats/cii/cii.validator.ts +171 -0
  138. package/ts/formats/cii/facturx/facturx.decoder.ts +243 -0
  139. package/ts/formats/cii/facturx/facturx.encoder.ts +483 -0
  140. package/ts/formats/cii/facturx/facturx.types.ts +18 -0
  141. package/ts/formats/cii/facturx/facturx.validator.ts +180 -0
  142. package/ts/formats/cii/zugferd/zugferd.decoder.ts +256 -0
  143. package/ts/formats/cii/zugferd/zugferd.encoder.ts +661 -0
  144. package/ts/formats/cii/zugferd/zugferd.types.ts +18 -0
  145. package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +267 -0
  146. package/ts/formats/cii/zugferd/zugferd.validator.ts +31 -0
  147. package/ts/formats/factories/decoder.factory.ts +62 -0
  148. package/ts/formats/factories/encoder.factory.ts +47 -0
  149. package/ts/formats/factories/validator.factory.ts +134 -0
  150. package/ts/formats/pdf/extractors/associated.extractor.ts +78 -0
  151. package/ts/formats/pdf/extractors/base.extractor.ts +355 -0
  152. package/ts/formats/pdf/extractors/index.ts +4 -0
  153. package/ts/formats/pdf/extractors/standard.extractor.ts +86 -0
  154. package/ts/formats/pdf/extractors/text.extractor.ts +162 -0
  155. package/ts/formats/pdf/pdf.embedder.ts +242 -0
  156. package/ts/formats/pdf/pdf.extractor.ts +141 -0
  157. package/ts/formats/ubl/en16931.ubl.validator.ts +216 -0
  158. package/ts/formats/ubl/generic/ubl.encoder.ts +1041 -0
  159. package/ts/formats/ubl/ubl.decoder.ts +121 -0
  160. package/ts/formats/ubl/ubl.encoder.ts +63 -0
  161. package/ts/formats/ubl/ubl.types.ts +22 -0
  162. package/ts/formats/ubl/ubl.validator.ts +133 -0
  163. package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +471 -0
  164. package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +619 -0
  165. package/ts/formats/ubl/xrechnung.validator.ts +185 -0
  166. package/ts/formats/utils/format.detector.ts +306 -0
  167. package/ts/formats/validation/en16931.validator.ts +135 -0
  168. package/ts/index.ts +164 -0
  169. package/ts/interfaces/common.ts +90 -0
  170. package/ts/interfaces.ts +98 -0
  171. package/ts/plugins.ts +61 -0
@@ -0,0 +1,14 @@
1
+ import { BaseXMLExtractor } from './base.extractor.js';
2
+ /**
3
+ * Associated files extractor for PDF/A-3 documents
4
+ * Extracts XML from associated files (AF entry in the catalog)
5
+ * Particularly useful for ZUGFeRD v1 and some Factur-X documents
6
+ */
7
+ export declare class AssociatedFilesExtractor extends BaseXMLExtractor {
8
+ /**
9
+ * Extract XML from a PDF buffer using associated files
10
+ * @param pdfBuffer PDF buffer
11
+ * @returns XML content or null if not found
12
+ */
13
+ extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null>;
14
+ }
@@ -0,0 +1,68 @@
1
+ import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } from '../../../plugins.js';
2
+ import { BaseXMLExtractor } from './base.extractor.js';
3
+ /**
4
+ * Associated files extractor for PDF/A-3 documents
5
+ * Extracts XML from associated files (AF entry in the catalog)
6
+ * Particularly useful for ZUGFeRD v1 and some Factur-X documents
7
+ */
8
+ export class AssociatedFilesExtractor extends BaseXMLExtractor {
9
+ /**
10
+ * Extract XML from a PDF buffer using associated files
11
+ * @param pdfBuffer PDF buffer
12
+ * @returns XML content or null if not found
13
+ */
14
+ async extractXml(pdfBuffer) {
15
+ try {
16
+ const pdfDoc = await PDFDocument.load(pdfBuffer);
17
+ // Try to find associated files via the AF entry in the catalog
18
+ const afArray = pdfDoc.catalog.lookup(PDFName.of('AF'));
19
+ if (!(afArray instanceof PDFArray)) {
20
+ console.warn('No AF (Associated Files) entry found in PDF catalog');
21
+ return null;
22
+ }
23
+ // Process each associated file
24
+ for (let i = 0; i < afArray.size(); i++) {
25
+ const fileSpec = afArray.lookup(i);
26
+ if (!(fileSpec instanceof PDFDict)) {
27
+ continue;
28
+ }
29
+ // Get the file name
30
+ const fileNameObj = fileSpec.lookup(PDFName.of('F')) || fileSpec.lookup(PDFName.of('UF'));
31
+ if (!(fileNameObj instanceof PDFString)) {
32
+ continue;
33
+ }
34
+ const fileName = fileNameObj.decodeText();
35
+ // Check if it's a known invoice XML file name
36
+ const isKnownFileName = this.knownFileNames.some(knownName => fileName.toLowerCase() === knownName.toLowerCase());
37
+ // Check if it's any XML file or has invoice-related keywords
38
+ const isXmlFile = fileName.toLowerCase().endsWith('.xml') ||
39
+ fileName.toLowerCase().includes('zugferd') ||
40
+ fileName.toLowerCase().includes('factur-x') ||
41
+ fileName.toLowerCase().includes('xrechnung') ||
42
+ fileName.toLowerCase().includes('invoice');
43
+ if (isKnownFileName || isXmlFile) {
44
+ // Get the embedded file dictionary
45
+ const efDict = fileSpec.lookup(PDFName.of('EF'));
46
+ if (!(efDict instanceof PDFDict)) {
47
+ continue;
48
+ }
49
+ // Get the file stream
50
+ const fileStream = efDict.lookup(PDFName.of('F'));
51
+ if (fileStream instanceof PDFRawStream) {
52
+ const xmlContent = await this.extractXmlFromStream(fileStream, fileName);
53
+ if (xmlContent) {
54
+ return xmlContent;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ console.warn('No valid XML found in associated files');
60
+ return null;
61
+ }
62
+ catch (error) {
63
+ console.error('Error in associated files extraction:', error);
64
+ return null;
65
+ }
66
+ }
67
+ }
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzb2NpYXRlZC5leHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9mb3JtYXRzL3BkZi9leHRyYWN0b3JzL2Fzc29jaWF0ZWQuZXh0cmFjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXZEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sd0JBQXlCLFNBQVEsZ0JBQWdCO0lBQzVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsVUFBVSxDQUFDLFNBQThCO1FBQ3BELElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUVqRCwrREFBK0Q7WUFDL0QsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3hELElBQUksQ0FBQyxDQUFDLE9BQU8sWUFBWSxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNuQyxPQUFPLENBQUMsSUFBSSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7Z0JBQ3BFLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUVELCtCQUErQjtZQUMvQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3hDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxDQUFDLFFBQVEsWUFBWSxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNuQyxTQUFTO2dCQUNYLENBQUM7Z0JBRUQsb0JBQW9CO2dCQUNwQixNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDMUYsSUFBSSxDQUFDLENBQUMsV0FBVyxZQUFZLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQ3hDLFNBQVM7Z0JBQ1gsQ0FBQztnQkFFRCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBRTFDLDhDQUE4QztnQkFDOUMsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQzlDLFNBQVMsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxLQUFLLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FDaEUsQ0FBQztnQkFFRiw2REFBNkQ7Z0JBQzdELE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO29CQUN2QyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztvQkFDMUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7b0JBQzNDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO29CQUM1QyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUU3RCxJQUFJLGVBQWUsSUFBSSxTQUFTLEVBQUUsQ0FBQztvQkFDakMsbUNBQW1DO29CQUNuQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztvQkFDakQsSUFBSSxDQUFDLENBQUMsTUFBTSxZQUFZLE9BQU8sQ0FBQyxFQUFFLENBQUM7d0JBQ2pDLFNBQVM7b0JBQ1gsQ0FBQztvQkFFRCxzQkFBc0I7b0JBQ3RCLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUNsRCxJQUFJLFVBQVUsWUFBWSxZQUFZLEVBQUUsQ0FBQzt3QkFDdkMsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO3dCQUN6RSxJQUFJLFVBQVUsRUFBRSxDQUFDOzRCQUNmLE9BQU8sVUFBVSxDQUFDO3dCQUNwQixDQUFDO29CQUNILENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7WUFFRCxPQUFPLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxDQUFDLENBQUM7WUFDdkQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDOUQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
@@ -0,0 +1,92 @@
1
+ import { PDFRawStream } from '../../../plugins.js';
2
+ /**
3
+ * Base class for PDF XML extractors with common functionality
4
+ */
5
+ export declare abstract class BaseXMLExtractor {
6
+ /**
7
+ * Known XML file names for different invoice formats
8
+ */
9
+ protected readonly knownFileNames: string[];
10
+ /**
11
+ * Known XML formats to validate extracted content
12
+ */
13
+ protected readonly knownFormats: string[];
14
+ /**
15
+ * Known XML end tags for extracting content from strings
16
+ */
17
+ protected readonly knownEndTags: string[];
18
+ /**
19
+ * Extract XML from a PDF buffer
20
+ * @param pdfBuffer PDF buffer
21
+ * @returns XML content or null if not found
22
+ */
23
+ abstract extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null>;
24
+ /**
25
+ * Check if an XML string is valid
26
+ * @param xmlString XML string to check
27
+ * @returns True if the XML is valid
28
+ */
29
+ protected isValidXml(xmlString: string): boolean;
30
+ /**
31
+ * Check if the XML string contains a known element
32
+ * @param xmlString XML string to check
33
+ * @returns True if the XML contains a known element
34
+ */
35
+ protected hasKnownXmlElement(xmlString: string): boolean;
36
+ /**
37
+ * Check if the XML string contains a known format
38
+ * @param xmlString XML string to check
39
+ * @returns True if the XML contains a known format
40
+ */
41
+ protected hasKnownFormat(xmlString: string): boolean;
42
+ /**
43
+ * Check if the XML string has a proper structure
44
+ * @param xmlString XML string to check
45
+ * @returns True if the XML has a proper structure
46
+ */
47
+ protected hasProperXmlStructure(xmlString: string): boolean;
48
+ /**
49
+ * Check if the XML string contains binary data
50
+ * @param xmlString XML string to check
51
+ * @returns True if the XML contains binary data
52
+ */
53
+ protected hasBinaryData(xmlString: string): boolean;
54
+ /**
55
+ * Extract XML from a string
56
+ * @param text Text to extract XML from
57
+ * @param startIndex Index to start extraction from
58
+ * @returns XML content or null if not found
59
+ */
60
+ protected extractXmlFromString(text: string, startIndex?: number): string | null;
61
+ /**
62
+ * Decompress and decode XML content from a PDF stream
63
+ * @param stream PDF stream containing XML data
64
+ * @param fileName Name of the file (for logging)
65
+ * @returns XML content or null if not valid
66
+ */
67
+ protected extractXmlFromStream(stream: PDFRawStream, fileName: string): Promise<string | null>;
68
+ /**
69
+ * Try to decompress a buffer using different methods
70
+ * @param buffer Buffer to decompress
71
+ * @returns Decompressed buffer or null if decompression failed
72
+ */
73
+ protected tryDecompress(buffer: Uint8Array): Uint8Array | null;
74
+ /**
75
+ * Try to decode a buffer to a string using different encodings
76
+ * @param buffer Buffer to decode
77
+ * @returns Decoded string or null if decoding failed
78
+ */
79
+ protected tryDecodeBuffer(buffer: Uint8Array): string | null;
80
+ /**
81
+ * Decode a buffer using ISO-8859-1 (Latin1) encoding
82
+ * @param buffer Buffer to decode
83
+ * @returns Decoded string
84
+ */
85
+ protected decodeLatin1(buffer: Uint8Array): string;
86
+ /**
87
+ * Check if a string is plausibly XML (quick check before validation)
88
+ * @param content String to check
89
+ * @returns True if the string is plausibly XML
90
+ */
91
+ protected isPlausibleXml(content: string): boolean;
92
+ }
@@ -0,0 +1,319 @@
1
+ import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, pako } from '../../../plugins.js';
2
+ /**
3
+ * Base class for PDF XML extractors with common functionality
4
+ */
5
+ export class BaseXMLExtractor {
6
+ constructor() {
7
+ /**
8
+ * Known XML file names for different invoice formats
9
+ */
10
+ this.knownFileNames = [
11
+ 'factur-x.xml',
12
+ 'zugferd-invoice.xml',
13
+ 'ZUGFeRD-invoice.xml',
14
+ 'xrechnung.xml',
15
+ 'ubl-invoice.xml',
16
+ 'invoice.xml',
17
+ 'metadata.xml'
18
+ ];
19
+ /**
20
+ * Known XML formats to validate extracted content
21
+ */
22
+ this.knownFormats = [
23
+ 'CrossIndustryInvoice',
24
+ 'CrossIndustryDocument',
25
+ 'Invoice',
26
+ 'CreditNote',
27
+ 'ubl:Invoice',
28
+ 'ubl:CreditNote',
29
+ 'rsm:CrossIndustryInvoice',
30
+ 'rsm:CrossIndustryDocument',
31
+ 'ram:CrossIndustryDocument',
32
+ 'urn:un:unece:uncefact',
33
+ 'urn:ferd:CrossIndustryDocument',
34
+ 'urn:zugferd',
35
+ 'urn:factur-x',
36
+ 'factur-x.eu',
37
+ 'ZUGFeRD',
38
+ 'FatturaElettronica'
39
+ ];
40
+ /**
41
+ * Known XML end tags for extracting content from strings
42
+ */
43
+ this.knownEndTags = [
44
+ '</CrossIndustryInvoice>',
45
+ '</CrossIndustryDocument>',
46
+ '</Invoice>',
47
+ '</CreditNote>',
48
+ '</rsm:CrossIndustryInvoice>',
49
+ '</rsm:CrossIndustryDocument>',
50
+ '</ram:CrossIndustryDocument>',
51
+ '</ubl:Invoice>',
52
+ '</ubl:CreditNote>',
53
+ '</FatturaElettronica>'
54
+ ];
55
+ }
56
+ /**
57
+ * Check if an XML string is valid
58
+ * @param xmlString XML string to check
59
+ * @returns True if the XML is valid
60
+ */
61
+ isValidXml(xmlString) {
62
+ try {
63
+ // Basic checks for XML validity
64
+ if (!xmlString || typeof xmlString !== 'string') {
65
+ return false;
66
+ }
67
+ // Check if it starts with XML declaration or a valid element
68
+ if (!xmlString.includes('<?xml') && !this.hasKnownXmlElement(xmlString)) {
69
+ return false;
70
+ }
71
+ // Check if the XML string contains known invoice formats
72
+ const hasKnownFormat = this.hasKnownFormat(xmlString);
73
+ if (!hasKnownFormat) {
74
+ return false;
75
+ }
76
+ // Check if the XML string contains binary data or invalid characters
77
+ if (this.hasBinaryData(xmlString)) {
78
+ return false;
79
+ }
80
+ // Check if the XML string is too short
81
+ if (xmlString.length < 100) {
82
+ return false;
83
+ }
84
+ // Check if XML has a proper structure (contains both opening and closing tags)
85
+ if (!this.hasProperXmlStructure(xmlString)) {
86
+ return false;
87
+ }
88
+ return true;
89
+ }
90
+ catch (error) {
91
+ console.error('Error validating XML:', error);
92
+ return false;
93
+ }
94
+ }
95
+ /**
96
+ * Check if the XML string contains a known element
97
+ * @param xmlString XML string to check
98
+ * @returns True if the XML contains a known element
99
+ */
100
+ hasKnownXmlElement(xmlString) {
101
+ for (const format of this.knownFormats) {
102
+ // Check for opening tag of format
103
+ if (xmlString.includes(`<${format}`)) {
104
+ return true;
105
+ }
106
+ }
107
+ return false;
108
+ }
109
+ /**
110
+ * Check if the XML string contains a known format
111
+ * @param xmlString XML string to check
112
+ * @returns True if the XML contains a known format
113
+ */
114
+ hasKnownFormat(xmlString) {
115
+ for (const format of this.knownFormats) {
116
+ if (xmlString.includes(format)) {
117
+ return true;
118
+ }
119
+ }
120
+ return false;
121
+ }
122
+ /**
123
+ * Check if the XML string has a proper structure
124
+ * @param xmlString XML string to check
125
+ * @returns True if the XML has a proper structure
126
+ */
127
+ hasProperXmlStructure(xmlString) {
128
+ // Check for at least one matching opening and closing tag
129
+ for (const endTag of this.knownEndTags) {
130
+ const startTag = endTag.replace('/', '');
131
+ if (xmlString.includes(startTag) && xmlString.includes(endTag)) {
132
+ return true;
133
+ }
134
+ }
135
+ // If no specific tag is found but it has a basic XML structure
136
+ return ((xmlString.includes('<?xml') && xmlString.includes('?>')) ||
137
+ (xmlString.match(/<[^>]+>/) !== null && xmlString.match(/<\/[^>]+>/) !== null));
138
+ }
139
+ /**
140
+ * Check if the XML string contains binary data
141
+ * @param xmlString XML string to check
142
+ * @returns True if the XML contains binary data
143
+ */
144
+ hasBinaryData(xmlString) {
145
+ // Check for common binary data indicators
146
+ const binaryChars = ['\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005'];
147
+ const consecutiveNulls = '\u0000\u0000\u0000';
148
+ // Check for control characters that shouldn't be in XML
149
+ if (binaryChars.some(char => xmlString.includes(char))) {
150
+ return true;
151
+ }
152
+ // Check for consecutive null bytes which indicate binary data
153
+ if (xmlString.includes(consecutiveNulls)) {
154
+ return true;
155
+ }
156
+ // Check for high concentration of non-printable characters
157
+ const nonPrintableCount = (xmlString.match(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g) || []).length;
158
+ if (nonPrintableCount > xmlString.length * 0.05) { // More than 5% non-printable
159
+ return true;
160
+ }
161
+ return false;
162
+ }
163
+ /**
164
+ * Extract XML from a string
165
+ * @param text Text to extract XML from
166
+ * @param startIndex Index to start extraction from
167
+ * @returns XML content or null if not found
168
+ */
169
+ extractXmlFromString(text, startIndex = 0) {
170
+ try {
171
+ // Find the start of the XML document
172
+ let xmlStartIndex = text.indexOf('<?xml', startIndex);
173
+ // If no XML declaration, try to find known elements
174
+ if (xmlStartIndex === -1) {
175
+ for (const format of this.knownFormats) {
176
+ const formatStartIndex = text.indexOf(`<${format.split(':').pop()}`, startIndex);
177
+ if (formatStartIndex !== -1) {
178
+ xmlStartIndex = formatStartIndex;
179
+ break;
180
+ }
181
+ }
182
+ // Still didn't find any start marker
183
+ if (xmlStartIndex === -1) {
184
+ return null;
185
+ }
186
+ }
187
+ // Try to find the end of the XML document
188
+ let xmlEndIndex = -1;
189
+ for (const endTag of this.knownEndTags) {
190
+ const endIndex = text.indexOf(endTag, xmlStartIndex);
191
+ if (endIndex !== -1) {
192
+ xmlEndIndex = endIndex + endTag.length;
193
+ break;
194
+ }
195
+ }
196
+ // If no known end tag found, try to use a heuristic approach
197
+ if (xmlEndIndex === -1) {
198
+ // Try to find the last closing tag
199
+ const lastClosingTagMatch = text.slice(xmlStartIndex).match(/<\/[^>]+>(?!.*<\/[^>]+>)/);
200
+ if (lastClosingTagMatch && lastClosingTagMatch.index !== undefined) {
201
+ xmlEndIndex = xmlStartIndex + lastClosingTagMatch.index + lastClosingTagMatch[0].length;
202
+ }
203
+ else {
204
+ return null;
205
+ }
206
+ }
207
+ // Extract the XML content
208
+ const xmlContent = text.substring(xmlStartIndex, xmlEndIndex);
209
+ // Validate the extracted content
210
+ if (this.isValidXml(xmlContent)) {
211
+ return xmlContent;
212
+ }
213
+ return null;
214
+ }
215
+ catch (error) {
216
+ console.error('Error extracting XML from string:', error);
217
+ return null;
218
+ }
219
+ }
220
+ /**
221
+ * Decompress and decode XML content from a PDF stream
222
+ * @param stream PDF stream containing XML data
223
+ * @param fileName Name of the file (for logging)
224
+ * @returns XML content or null if not valid
225
+ */
226
+ async extractXmlFromStream(stream, fileName) {
227
+ try {
228
+ // Get the raw bytes from the stream
229
+ const rawBytes = stream.getContents();
230
+ // First try without decompression (in case the content is not compressed)
231
+ let xmlContent = this.tryDecodeBuffer(rawBytes);
232
+ if (xmlContent && this.isValidXml(xmlContent)) {
233
+ console.log(`Successfully extracted uncompressed XML from PDF file. File name: ${fileName}`);
234
+ return xmlContent;
235
+ }
236
+ // Try with decompression
237
+ try {
238
+ const decompressedBytes = this.tryDecompress(rawBytes);
239
+ if (decompressedBytes) {
240
+ xmlContent = this.tryDecodeBuffer(decompressedBytes);
241
+ if (xmlContent && this.isValidXml(xmlContent)) {
242
+ console.log(`Successfully extracted decompressed XML from PDF file. File name: ${fileName}`);
243
+ return xmlContent;
244
+ }
245
+ }
246
+ }
247
+ catch (decompressError) {
248
+ console.log(`Decompression failed for ${fileName}: ${decompressError}`);
249
+ }
250
+ return null;
251
+ }
252
+ catch (error) {
253
+ console.error('Error extracting XML from stream:', error);
254
+ return null;
255
+ }
256
+ }
257
+ /**
258
+ * Try to decompress a buffer using different methods
259
+ * @param buffer Buffer to decompress
260
+ * @returns Decompressed buffer or null if decompression failed
261
+ */
262
+ tryDecompress(buffer) {
263
+ try {
264
+ // Try pako inflate (for deflate/zlib compression)
265
+ return pako.inflate(buffer);
266
+ }
267
+ catch (error) {
268
+ // If pako fails, try other methods if needed
269
+ console.warn('Pako decompression failed, might be uncompressed or using a different algorithm');
270
+ return null;
271
+ }
272
+ }
273
+ /**
274
+ * Try to decode a buffer to a string using different encodings
275
+ * @param buffer Buffer to decode
276
+ * @returns Decoded string or null if decoding failed
277
+ */
278
+ tryDecodeBuffer(buffer) {
279
+ try {
280
+ // Try UTF-8 first
281
+ let content = new TextDecoder('utf-8').decode(buffer);
282
+ if (this.isPlausibleXml(content)) {
283
+ return content;
284
+ }
285
+ // Try ISO-8859-1 (Latin1)
286
+ content = this.decodeLatin1(buffer);
287
+ if (this.isPlausibleXml(content)) {
288
+ return content;
289
+ }
290
+ return null;
291
+ }
292
+ catch (error) {
293
+ console.warn('Error decoding buffer:', error);
294
+ return null;
295
+ }
296
+ }
297
+ /**
298
+ * Decode a buffer using ISO-8859-1 (Latin1) encoding
299
+ * @param buffer Buffer to decode
300
+ * @returns Decoded string
301
+ */
302
+ decodeLatin1(buffer) {
303
+ return Array.from(buffer)
304
+ .map(byte => String.fromCharCode(byte))
305
+ .join('');
306
+ }
307
+ /**
308
+ * Check if a string is plausibly XML (quick check before validation)
309
+ * @param content String to check
310
+ * @returns True if the string is plausibly XML
311
+ */
312
+ isPlausibleXml(content) {
313
+ return content.includes('<') &&
314
+ content.includes('>') &&
315
+ (content.includes('<?xml') ||
316
+ this.knownFormats.some(format => content.includes(format)));
317
+ }
318
+ }
319
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5leHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9mb3JtYXRzL3BkZi9leHRyYWN0b3JzL2Jhc2UuZXh0cmFjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU3Rzs7R0FFRztBQUNILE1BQU0sT0FBZ0IsZ0JBQWdCO0lBQXRDO1FBQ0U7O1dBRUc7UUFDZ0IsbUJBQWMsR0FBRztZQUNsQyxjQUFjO1lBQ2QscUJBQXFCO1lBQ3JCLHFCQUFxQjtZQUNyQixlQUFlO1lBQ2YsaUJBQWlCO1lBQ2pCLGFBQWE7WUFDYixjQUFjO1NBQ2YsQ0FBQztRQUVGOztXQUVHO1FBQ2dCLGlCQUFZLEdBQUc7WUFDaEMsc0JBQXNCO1lBQ3RCLHVCQUF1QjtZQUN2QixTQUFTO1lBQ1QsWUFBWTtZQUNaLGFBQWE7WUFDYixnQkFBZ0I7WUFDaEIsMEJBQTBCO1lBQzFCLDJCQUEyQjtZQUMzQiwyQkFBMkI7WUFDM0IsdUJBQXVCO1lBQ3ZCLGdDQUFnQztZQUNoQyxhQUFhO1lBQ2IsY0FBYztZQUNkLGFBQWE7WUFDYixTQUFTO1lBQ1Qsb0JBQW9CO1NBQ3JCLENBQUM7UUFFRjs7V0FFRztRQUNnQixpQkFBWSxHQUFHO1lBQ2hDLHlCQUF5QjtZQUN6QiwwQkFBMEI7WUFDMUIsWUFBWTtZQUNaLGVBQWU7WUFDZiw2QkFBNkI7WUFDN0IsOEJBQThCO1lBQzlCLDhCQUE4QjtZQUM5QixnQkFBZ0I7WUFDaEIsbUJBQW1CO1lBQ25CLHVCQUF1QjtTQUN4QixDQUFDO0lBMlNKLENBQUM7SUFsU0M7Ozs7T0FJRztJQUNPLFVBQVUsQ0FBQyxTQUFpQjtRQUNwQyxJQUFJLENBQUM7WUFDSCxnQ0FBZ0M7WUFDaEMsSUFBSSxDQUFDLFNBQVMsSUFBSSxP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
@@ -0,0 +1,4 @@
1
+ export * from './base.extractor.js';
2
+ export * from './standard.extractor.js';
3
+ export * from './associated.extractor.js';
4
+ export * from './text.extractor.js';
@@ -0,0 +1,5 @@
1
+ export * from './base.extractor.js';
2
+ export * from './standard.extractor.js';
3
+ export * from './associated.extractor.js';
4
+ export * from './text.extractor.js';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9mb3JtYXRzL3BkZi9leHRyYWN0b3JzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMscUJBQXFCLENBQUMifQ==
@@ -0,0 +1,13 @@
1
+ import { BaseXMLExtractor } from './base.extractor.js';
2
+ /**
3
+ * Standard PDF XML extractor that extracts XML from embedded files
4
+ * Works with PDF/A-3 documents that follow the standard for embedding files
5
+ */
6
+ export declare class StandardXMLExtractor extends BaseXMLExtractor {
7
+ /**
8
+ * Extract XML from a PDF buffer using standard PDF/A-3 embedded files
9
+ * @param pdfBuffer PDF buffer
10
+ * @returns XML content or null if not found
11
+ */
12
+ extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null>;
13
+ }
@@ -0,0 +1,74 @@
1
+ import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } from '../../../plugins.js';
2
+ import { BaseXMLExtractor } from './base.extractor.js';
3
+ /**
4
+ * Standard PDF XML extractor that extracts XML from embedded files
5
+ * Works with PDF/A-3 documents that follow the standard for embedding files
6
+ */
7
+ export class StandardXMLExtractor extends BaseXMLExtractor {
8
+ /**
9
+ * Extract XML from a PDF buffer using standard PDF/A-3 embedded files
10
+ * @param pdfBuffer PDF buffer
11
+ * @returns XML content or null if not found
12
+ */
13
+ async extractXml(pdfBuffer) {
14
+ try {
15
+ const pdfDoc = await PDFDocument.load(pdfBuffer);
16
+ // Get the document's metadata dictionary
17
+ const namesDictObj = pdfDoc.catalog.lookup(PDFName.of('Names'));
18
+ if (!(namesDictObj instanceof PDFDict)) {
19
+ console.warn('No Names dictionary found in PDF! This PDF does not contain embedded files.');
20
+ return null;
21
+ }
22
+ // Get the embedded files dictionary
23
+ const embeddedFilesDictObj = namesDictObj.lookup(PDFName.of('EmbeddedFiles'));
24
+ if (!(embeddedFilesDictObj instanceof PDFDict)) {
25
+ console.warn('No EmbeddedFiles dictionary found! This PDF does not contain embedded files.');
26
+ return null;
27
+ }
28
+ // Get the names array
29
+ const filesSpecObj = embeddedFilesDictObj.lookup(PDFName.of('Names'));
30
+ if (!(filesSpecObj instanceof PDFArray)) {
31
+ console.warn('No files specified in EmbeddedFiles dictionary!');
32
+ return null;
33
+ }
34
+ // Try to find an XML file in the embedded files
35
+ for (let i = 0; i < filesSpecObj.size(); i += 2) {
36
+ const fileNameObj = filesSpecObj.lookup(i);
37
+ const fileSpecObj = filesSpecObj.lookup(i + 1);
38
+ if (!(fileNameObj instanceof PDFString) || !(fileSpecObj instanceof PDFDict)) {
39
+ continue;
40
+ }
41
+ // Get the filename as string
42
+ const fileName = fileNameObj.decodeText();
43
+ // Check if it's a known invoice XML file name
44
+ const isKnownFileName = this.knownFileNames.some(knownName => fileName.toLowerCase() === knownName.toLowerCase());
45
+ // Check if it's any XML file or has invoice-related keywords
46
+ const isXmlFile = fileName.toLowerCase().endsWith('.xml') ||
47
+ fileName.toLowerCase().includes('zugferd') ||
48
+ fileName.toLowerCase().includes('factur-x') ||
49
+ fileName.toLowerCase().includes('xrechnung') ||
50
+ fileName.toLowerCase().includes('invoice');
51
+ if (isKnownFileName || isXmlFile) {
52
+ const efDictObj = fileSpecObj.lookup(PDFName.of('EF'));
53
+ if (!(efDictObj instanceof PDFDict)) {
54
+ continue;
55
+ }
56
+ const fileStream = efDictObj.lookup(PDFName.of('F'));
57
+ if (fileStream instanceof PDFRawStream) {
58
+ const xmlContent = await this.extractXmlFromStream(fileStream, fileName);
59
+ if (xmlContent) {
60
+ return xmlContent;
61
+ }
62
+ }
63
+ }
64
+ }
65
+ console.warn('No valid XML found in embedded files');
66
+ return null;
67
+ }
68
+ catch (error) {
69
+ console.error('Error in standard extraction:', error);
70
+ return null;
71
+ }
72
+ }
73
+ }
74
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhbmRhcmQuZXh0cmFjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvZm9ybWF0cy9wZGYvZXh0cmFjdG9ycy9zdGFuZGFyZC5leHRyYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLG9CQUFxQixTQUFRLGdCQUFnQjtJQUN4RDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLFVBQVUsQ0FBQyxTQUE4QjtRQUNwRCxJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFakQseUNBQXlDO1lBQ3pDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsQ0FBQyxZQUFZLFlBQVksT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDdkMsT0FBTyxDQUFDLElBQUksQ0FBQyw2RUFBNkUsQ0FBQyxDQUFDO2dCQUM1RixPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7WUFFRCxvQ0FBb0M7WUFDcEMsTUFBTSxvQkFBb0IsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztZQUM5RSxJQUFJLENBQUMsQ0FBQyxvQkFBb0IsWUFBWSxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUMvQyxPQUFPLENBQUMsSUFBSSxDQUFDLDhFQUE4RSxDQUFDLENBQUM7Z0JBQzdGLE9BQU8sSUFB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
@@ -0,0 +1,45 @@
1
+ import { BaseXMLExtractor } from './base.extractor.js';
2
+ /**
3
+ * Text-based XML extractor for PDF documents
4
+ * Extracts XML by searching for XML patterns in the PDF text
5
+ * Used as a fallback when other extraction methods fail
6
+ */
7
+ export declare class TextXMLExtractor extends BaseXMLExtractor {
8
+ private readonly CHUNK_SIZE;
9
+ private readonly MAX_CHUNKS;
10
+ private readonly XML_PATTERNS;
11
+ /**
12
+ * Extract XML from a PDF buffer by searching for XML patterns in the text
13
+ * Uses a chunked approach to handle large files efficiently
14
+ * @param pdfBuffer PDF buffer
15
+ * @returns XML content or null if not found
16
+ */
17
+ extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null>;
18
+ /**
19
+ * Extract XML from buffer using a chunked approach
20
+ * This helps avoid memory issues with large PDFs
21
+ * @param buffer Buffer to search in
22
+ * @returns XML content or null if not found
23
+ */
24
+ private extractXmlFromBufferChunked;
25
+ /**
26
+ * Process a single chunk of the PDF buffer
27
+ * @param chunk Chunk buffer to process
28
+ * @param chunkOffset Offset position of the chunk in the original buffer
29
+ * @returns XML content or null if not found
30
+ */
31
+ private processChunk;
32
+ /**
33
+ * Safely decode a buffer to string using the specified encoding
34
+ * @param buffer Buffer to decode
35
+ * @param encoding Encoding to use ('utf-8' or 'latin1')
36
+ * @returns Decoded string
37
+ */
38
+ private decodeBufferToString;
39
+ /**
40
+ * Search for XML patterns in a string
41
+ * @param content String to search in
42
+ * @returns XML content or null if not found
43
+ */
44
+ private searchForXmlInString;
45
+ }