officeparser 7.0.3 → 7.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.
- package/README.md +152 -18
- package/dist/OfficeGenerator.d.ts +1 -1
- package/dist/OfficeGenerator.js +16 -7
- package/dist/OfficeParser.js +6 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +12 -3
- package/dist/defaults.js +27 -1
- package/dist/generators/BaseGenerator.d.ts +3 -3
- package/dist/generators/ChunkingGenerator.js +31 -4
- package/dist/generators/CsvGenerator.d.ts +1 -1
- package/dist/generators/HtmlGenerator.d.ts +2 -1
- package/dist/generators/HtmlGenerator.js +462 -40
- package/dist/generators/MarkdownGenerator.d.ts +1 -1
- package/dist/generators/MarkdownGenerator.js +3 -1
- package/dist/generators/PdfGenerator.d.ts +1 -1
- package/dist/generators/PdfGenerator.js +51 -10
- package/dist/generators/RtfGenerator.d.ts +2 -1
- package/dist/generators/RtfGenerator.js +43 -6
- package/dist/generators/TextGenerator.d.ts +1 -1
- package/dist/officeparser.browser.d.ts +377 -53
- package/dist/officeparser.browser.iife.js +380 -93
- package/dist/officeparser.browser.mjs +380 -93
- package/dist/parsers/CsvParser.js +6 -1
- package/dist/parsers/ExcelParser.js +69 -21
- package/dist/parsers/HtmlParser.js +15 -1
- package/dist/parsers/MarkdownParser.js +18 -10
- package/dist/parsers/OpenOfficeParser.js +61 -34
- package/dist/parsers/PdfParser.js +26 -1
- package/dist/parsers/PowerPointParser.js +168 -40
- package/dist/parsers/RtfParser.js +30 -24
- package/dist/parsers/WordParser.js +158 -11
- package/dist/sbom.cdx.json +100 -100
- package/dist/types.d.ts +383 -53
- package/dist/types.js +4 -0
- package/dist/utils/astUtils.d.ts +2 -2
- package/dist/utils/astUtils.js +2 -1
- package/dist/utils/configUtils.d.ts +5 -0
- package/dist/utils/configUtils.js +69 -2
- package/dist/utils/errorUtils.d.ts +20 -0
- package/dist/utils/errorUtils.js +39 -3
- package/dist/utils/moduleLoader.js +3 -3
- package/dist/utils/ocrUtils.js +271 -66
- package/dist/utils/xmlUtils.d.ts +17 -0
- package/dist/utils/xmlUtils.js +85 -1
- package/package.json +3 -2
|
@@ -37,7 +37,7 @@ export declare class MarkdownGenerator extends BaseGenerator<'md'> {
|
|
|
37
37
|
*
|
|
38
38
|
* @returns A Markdown string
|
|
39
39
|
*/
|
|
40
|
-
generate(): Promise<ConversionResult
|
|
40
|
+
generate(): Promise<ConversionResult<'md'>>;
|
|
41
41
|
/**
|
|
42
42
|
* Recursively processes nodes and builds output.
|
|
43
43
|
* Overridden to provide AST optimization (merging adjacent text nodes).
|
|
@@ -136,7 +136,9 @@ class MarkdownGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
136
136
|
else if (this.config.generateIds) {
|
|
137
137
|
id = ` {#${this.slugify(this.getNodeText(node))}}`;
|
|
138
138
|
}
|
|
139
|
-
const anchors =
|
|
139
|
+
const anchors = this.config.mdConfig.fallbackToHtml
|
|
140
|
+
? remainingAnchors.map(aid => `<a name="${aid}"></a>`).join('')
|
|
141
|
+
: '';
|
|
140
142
|
let content = `${prefix}${childrenOutput}${id}`;
|
|
141
143
|
// Alignment fallback via HTML div/p
|
|
142
144
|
if (this.config.mdConfig.fallbackToHtml && meta?.alignment && meta.alignment !== 'left') {
|
|
@@ -9,7 +9,7 @@ import { BaseGenerator } from './BaseGenerator.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class PdfGenerator extends BaseGenerator<'pdf'> {
|
|
11
11
|
constructor(ast: OfficeParserAST, config?: GeneratorConfig<'pdf'>);
|
|
12
|
-
generate(): Promise<ConversionResult
|
|
12
|
+
generate(): Promise<ConversionResult<'pdf'>>;
|
|
13
13
|
/**
|
|
14
14
|
* Node.js implementation using Puppeteer.
|
|
15
15
|
* Uses dynamic import to avoid bundling puppeteer into the library core.
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PdfGenerator = void 0;
|
|
4
4
|
const types_js_1 = require("../types.js");
|
|
5
5
|
const envUtils_js_1 = require("../utils/envUtils.js");
|
|
6
|
+
const errorUtils_js_1 = require("../utils/errorUtils.js");
|
|
6
7
|
const BaseGenerator_js_1 = require("./BaseGenerator.js");
|
|
7
8
|
const HtmlGenerator_js_1 = require("./HtmlGenerator.js");
|
|
8
9
|
/**
|
|
@@ -22,12 +23,6 @@ class PdfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
22
23
|
const htmlGenerator = new HtmlGenerator_js_1.HtmlGenerator(this.ast, {
|
|
23
24
|
...this.config,
|
|
24
25
|
htmlConfig: { ...this.config.htmlConfig, standalone: true },
|
|
25
|
-
mdConfig: undefined,
|
|
26
|
-
chunksConfig: undefined,
|
|
27
|
-
csvConfig: undefined,
|
|
28
|
-
textConfig: undefined,
|
|
29
|
-
pdfConfig: undefined,
|
|
30
|
-
rtfConfig: undefined,
|
|
31
26
|
});
|
|
32
27
|
const htmlResult = await htmlGenerator.generate();
|
|
33
28
|
const html = typeof htmlResult.value === 'string' ? htmlResult.value : '';
|
|
@@ -44,6 +39,24 @@ class PdfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
44
39
|
* Uses dynamic import to avoid bundling puppeteer into the library core.
|
|
45
40
|
*/
|
|
46
41
|
async generateInNode(html) {
|
|
42
|
+
const signal = this.config.abortSignal;
|
|
43
|
+
if (signal?.aborted) {
|
|
44
|
+
throw (0, errorUtils_js_1.getAbortError)();
|
|
45
|
+
}
|
|
46
|
+
let browser;
|
|
47
|
+
const onAbort = async () => {
|
|
48
|
+
if (browser) {
|
|
49
|
+
try {
|
|
50
|
+
await browser.close();
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
// ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
if (signal) {
|
|
58
|
+
signal.addEventListener('abort', onAbort);
|
|
59
|
+
}
|
|
47
60
|
try {
|
|
48
61
|
// Dynamic import for peer dependency
|
|
49
62
|
// @ts-ignore
|
|
@@ -70,11 +83,16 @@ class PdfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
70
83
|
// to ensure transparency about the environment state. Programmatically fixing this
|
|
71
84
|
// would require force-downloading a ~300MB arm64 browser binary or switching to
|
|
72
85
|
// a system-installed Chrome, both of which are too intrusive for a library.
|
|
73
|
-
|
|
86
|
+
browser = await puppeteer.launch(launchOptions);
|
|
74
87
|
const page = await browser.newPage();
|
|
88
|
+
const pdfConfig = this.config.pdfConfig;
|
|
89
|
+
const timeout = pdfConfig.timeout;
|
|
90
|
+
if (timeout !== undefined && timeout > 0) {
|
|
91
|
+
page.setDefaultTimeout(timeout);
|
|
92
|
+
page.setDefaultNavigationTimeout(timeout);
|
|
93
|
+
}
|
|
75
94
|
// Set content and wait for network/assets to load
|
|
76
95
|
await page.setContent(html, { waitUntil: 'networkidle0' });
|
|
77
|
-
const pdfConfig = this.config.pdfConfig;
|
|
78
96
|
const pdfBuffer = await page.pdf({
|
|
79
97
|
format: pdfConfig.format,
|
|
80
98
|
width: pdfConfig.width,
|
|
@@ -88,18 +106,41 @@ class PdfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
88
106
|
footerTemplate: pdfConfig.footerTemplate,
|
|
89
107
|
});
|
|
90
108
|
await browser.close();
|
|
109
|
+
browser = null;
|
|
91
110
|
return {
|
|
92
111
|
value: new Uint8Array(pdfBuffer),
|
|
93
112
|
messages: this.messages
|
|
94
113
|
};
|
|
95
114
|
}
|
|
96
115
|
catch (err) {
|
|
97
|
-
|
|
116
|
+
if (browser) {
|
|
117
|
+
try {
|
|
118
|
+
await browser.close();
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
// ignore
|
|
122
|
+
}
|
|
123
|
+
browser = null;
|
|
124
|
+
}
|
|
125
|
+
if (signal?.aborted) {
|
|
126
|
+
throw (0, errorUtils_js_1.getAbortError)();
|
|
127
|
+
}
|
|
128
|
+
if (err.message && (err.message.includes('timeout') || err.message.includes('Timeout'))) {
|
|
129
|
+
this.warn(types_js_1.OfficeWarningType.PAGE_LOAD_FAILED, `PDF generation timed out: ${err.message}`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
this.warn(types_js_1.OfficeWarningType.DEPENDENCY_LOAD_FAILED, `puppeteer. Please install it with 'npm install puppeteer'. Error: ${err.message}`);
|
|
133
|
+
}
|
|
98
134
|
return {
|
|
99
|
-
value:
|
|
135
|
+
value: new Uint8Array(),
|
|
100
136
|
messages: this.messages
|
|
101
137
|
};
|
|
102
138
|
}
|
|
139
|
+
finally {
|
|
140
|
+
if (signal) {
|
|
141
|
+
signal.removeEventListener('abort', onAbort);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
103
144
|
}
|
|
104
145
|
/**
|
|
105
146
|
* Browser implementation using hidden iframe and native print.
|
|
@@ -7,9 +7,10 @@ export declare class RtfGenerator extends BaseGenerator<'rtf'> {
|
|
|
7
7
|
private colorTable;
|
|
8
8
|
private inTable;
|
|
9
9
|
constructor(ast: OfficeParserAST, config?: GeneratorConfig<'rtf'>);
|
|
10
|
-
generate(): Promise<ConversionResult
|
|
10
|
+
generate(): Promise<ConversionResult<'rtf'>>;
|
|
11
11
|
protected processNodeRecursive(node: OfficeContentNode, processor: (node: OfficeContentNode, childrenOutput: string) => Promise<string>): Promise<string>;
|
|
12
12
|
private renderBody;
|
|
13
13
|
private getColorIndex;
|
|
14
|
+
private isLightColor;
|
|
14
15
|
private escapeRtf;
|
|
15
16
|
}
|
|
@@ -15,7 +15,7 @@ class RtfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
15
15
|
this.colorTable = [];
|
|
16
16
|
// We first process all nodes to collect colors and analyze structure
|
|
17
17
|
const bodyContent = await this.renderBody(this.ast);
|
|
18
|
-
let output = '{\\rtf1\\ansi\\deff0\n';
|
|
18
|
+
let output = '{\\rtf1\\ansi\\uc1\\deff0\n';
|
|
19
19
|
// 1. Info Group (Metadata)
|
|
20
20
|
if (this.config.renderMetadata && this.ast.metadata) {
|
|
21
21
|
output += '{\\info';
|
|
@@ -100,16 +100,34 @@ class RtfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
100
100
|
suffix = '\\strike0 ' + suffix;
|
|
101
101
|
}
|
|
102
102
|
if (f.color) {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// RTF default background is white. Ensure light text without a dark background remains readable.
|
|
104
|
+
const isTextLight = this.isLightColor(f.color);
|
|
105
|
+
const isBgLight = !f.backgroundColor || this.isLightColor(f.backgroundColor);
|
|
106
|
+
if (!(isTextLight && isBgLight)) {
|
|
107
|
+
const idx = this.getColorIndex(f.color);
|
|
108
|
+
prefix += `\\cf${idx + 1} `;
|
|
109
|
+
}
|
|
105
110
|
}
|
|
106
111
|
if (f.backgroundColor) {
|
|
107
112
|
const idx = this.getColorIndex(f.backgroundColor);
|
|
108
113
|
prefix += `\\highlight${idx + 1} `;
|
|
109
114
|
}
|
|
110
115
|
if (f.size) {
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
let pt = 12; // default
|
|
117
|
+
const val = parseFloat(f.size);
|
|
118
|
+
if (!isNaN(val)) {
|
|
119
|
+
if (f.size.includes('in'))
|
|
120
|
+
pt = val * 72;
|
|
121
|
+
else if (f.size.includes('cm'))
|
|
122
|
+
pt = val * 28.3465;
|
|
123
|
+
else if (f.size.includes('mm'))
|
|
124
|
+
pt = val * 2.83465;
|
|
125
|
+
else if (f.size.includes('px'))
|
|
126
|
+
pt = val * 0.75;
|
|
127
|
+
else
|
|
128
|
+
pt = val;
|
|
129
|
+
}
|
|
130
|
+
prefix += `\\fs${Math.round(pt * 2)} `;
|
|
113
131
|
}
|
|
114
132
|
text = `{\\f0 ${prefix}${text}${suffix}}`;
|
|
115
133
|
}
|
|
@@ -214,13 +232,32 @@ class RtfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
214
232
|
}
|
|
215
233
|
return idx;
|
|
216
234
|
}
|
|
235
|
+
isLightColor(hex) {
|
|
236
|
+
if (!hex || hex.length !== 7 || !hex.startsWith('#'))
|
|
237
|
+
return false;
|
|
238
|
+
const r = parseInt(hex.substring(1, 3), 16);
|
|
239
|
+
const g = parseInt(hex.substring(3, 5), 16);
|
|
240
|
+
const b = parseInt(hex.substring(5, 7), 16);
|
|
241
|
+
if (isNaN(r) || isNaN(g) || isNaN(b))
|
|
242
|
+
return false;
|
|
243
|
+
// Simple luminance calculation
|
|
244
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
245
|
+
return luminance > 0.8;
|
|
246
|
+
}
|
|
217
247
|
escapeRtf(text) {
|
|
218
248
|
return text
|
|
219
249
|
.replace(/\\/g, '\\\\')
|
|
220
250
|
.replace(/{/g, '\\{')
|
|
221
251
|
.replace(/}/g, '\\}')
|
|
222
252
|
.replace(/[^\x00-\x7F]/g, (match) => {
|
|
223
|
-
|
|
253
|
+
let code = match.charCodeAt(0);
|
|
254
|
+
if (code < 256) {
|
|
255
|
+
return `\\'${code.toString(16).padStart(2, '0')}`;
|
|
256
|
+
}
|
|
257
|
+
if (code > 32767) {
|
|
258
|
+
code -= 65536;
|
|
259
|
+
}
|
|
260
|
+
return `{\\uc0\\u${code}}`;
|
|
224
261
|
});
|
|
225
262
|
}
|
|
226
263
|
}
|