officeparser 7.1.0 → 7.2.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/README.md +152 -56
- package/dist/OfficeGenerator.d.ts +6 -2
- package/dist/OfficeGenerator.js +30 -9
- package/dist/OfficeParser.d.ts +1 -1
- package/dist/OfficeParser.js +1 -1
- package/dist/cli.d.ts +18 -12
- package/dist/cli.js +255 -81
- package/dist/defaults.js +12 -1
- package/dist/generators/BaseGenerator.d.ts +4 -3
- package/dist/generators/BaseGenerator.js +13 -1
- package/dist/generators/ChunkingGenerator.js +32 -5
- package/dist/generators/CsvGenerator.d.ts +1 -1
- package/dist/generators/HtmlGenerator.d.ts +2 -1
- package/dist/generators/HtmlGenerator.js +481 -42
- package/dist/generators/MarkdownGenerator.d.ts +1 -1
- package/dist/generators/MarkdownGenerator.js +35 -2
- package/dist/generators/PdfGenerator.d.ts +1 -1
- package/dist/generators/PdfGenerator.js +0 -6
- package/dist/generators/RtfGenerator.d.ts +2 -1
- package/dist/generators/RtfGenerator.js +49 -6
- package/dist/generators/TextGenerator.d.ts +1 -1
- package/dist/generators/TextGenerator.js +6 -0
- package/dist/officeparser.browser.d.ts +267 -54
- package/dist/officeparser.browser.iife.js +599 -187
- package/dist/officeparser.browser.mjs +599 -187
- package/dist/parsers/CsvParser.js +1 -1
- package/dist/parsers/ExcelParser.js +63 -19
- package/dist/parsers/HtmlParser.js +10 -1
- package/dist/parsers/MarkdownParser.js +13 -10
- package/dist/parsers/OpenOfficeParser.js +57 -34
- package/dist/parsers/PdfParser.js +28 -3
- package/dist/parsers/PowerPointParser.js +164 -40
- package/dist/parsers/RtfParser.js +28 -24
- package/dist/parsers/WordParser.js +154 -11
- package/dist/sbom.cdx.json +100 -100
- package/dist/types.d.ts +268 -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 +55 -1
- package/dist/utils/errorUtils.js +3 -1
- package/dist/utils/moduleLoader.js +55 -11
- package/dist/utils/xmlUtils.d.ts +9 -0
- package/dist/utils/xmlUtils.js +53 -1
- package/package.json +6 -3
|
@@ -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') {
|
|
@@ -216,6 +218,11 @@ class MarkdownGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
216
218
|
const anchors = this.renderAnchors(node.metadata);
|
|
217
219
|
return `\n---\n\n${anchors}${anchors ? '\n' : ''}${childrenOutput}\n\n`;
|
|
218
220
|
}
|
|
221
|
+
case 'note': {
|
|
222
|
+
const meta = node.metadata;
|
|
223
|
+
const typeLabel = meta?.noteType === 'footnote' ? 'Footnote' : (meta?.noteType === 'endnote' ? 'Endnote' : 'Note');
|
|
224
|
+
return `> **${typeLabel}:** ${childrenOutput.trim()}\n\n`;
|
|
225
|
+
}
|
|
219
226
|
default:
|
|
220
227
|
return childrenOutput;
|
|
221
228
|
}
|
|
@@ -239,6 +246,13 @@ class MarkdownGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
239
246
|
}
|
|
240
247
|
output += result;
|
|
241
248
|
}
|
|
249
|
+
if (this.collectedNotes.length > 0) {
|
|
250
|
+
let notesMd = '\n\n---\n\n### Notes\n\n';
|
|
251
|
+
for (const note of this.collectedNotes) {
|
|
252
|
+
notesMd += await this.processNodeRecursive(note, processor);
|
|
253
|
+
}
|
|
254
|
+
output += notesMd;
|
|
255
|
+
}
|
|
242
256
|
return {
|
|
243
257
|
value: (output + '\n\n' + this.hoistedContent.join('\n\n')).trim(),
|
|
244
258
|
messages: this.messages
|
|
@@ -265,7 +279,18 @@ class MarkdownGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
265
279
|
childrenOutput += await this.processNodeRecursive(child, processor);
|
|
266
280
|
}
|
|
267
281
|
}
|
|
268
|
-
|
|
282
|
+
if (node.notes && node.notes.length > 0) {
|
|
283
|
+
if (node.type !== 'slide') {
|
|
284
|
+
this.collectedNotes.push(...node.notes);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
let result = await processor(node, childrenOutput);
|
|
288
|
+
if (node.type === 'slide' && node.notes && node.notes.length > 0) {
|
|
289
|
+
for (const note of node.notes) {
|
|
290
|
+
result += await this.processNodeRecursive(note, processor);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
269
294
|
}
|
|
270
295
|
/**
|
|
271
296
|
* Merges adjacent text nodes with identical formatting and metadata.
|
|
@@ -282,9 +307,17 @@ class MarkdownGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
282
307
|
current.text = (current.text || '') + (node.text || '');
|
|
283
308
|
if (current.rawContent && node.rawContent)
|
|
284
309
|
current.rawContent += node.rawContent;
|
|
310
|
+
if (node.notes && node.notes.length > 0) {
|
|
311
|
+
if (!current.notes)
|
|
312
|
+
current.notes = [];
|
|
313
|
+
current.notes.push(...node.notes);
|
|
314
|
+
}
|
|
285
315
|
}
|
|
286
316
|
else {
|
|
287
317
|
current = { ...node }; // Clone
|
|
318
|
+
if (node.notes) {
|
|
319
|
+
current.notes = [...node.notes];
|
|
320
|
+
}
|
|
288
321
|
result.push(current);
|
|
289
322
|
}
|
|
290
323
|
}
|
|
@@ -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.
|
|
@@ -23,12 +23,6 @@ class PdfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
23
23
|
const htmlGenerator = new HtmlGenerator_js_1.HtmlGenerator(this.ast, {
|
|
24
24
|
...this.config,
|
|
25
25
|
htmlConfig: { ...this.config.htmlConfig, standalone: true },
|
|
26
|
-
mdConfig: undefined,
|
|
27
|
-
chunksConfig: undefined,
|
|
28
|
-
csvConfig: undefined,
|
|
29
|
-
textConfig: undefined,
|
|
30
|
-
pdfConfig: undefined,
|
|
31
|
-
rtfConfig: undefined,
|
|
32
26
|
});
|
|
33
27
|
const htmlResult = await htmlGenerator.generate();
|
|
34
28
|
const html = typeof htmlResult.value === 'string' ? htmlResult.value : '';
|
|
@@ -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
|
}
|
|
@@ -203,6 +221,12 @@ class RtfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
203
221
|
for (const node of ast.content) {
|
|
204
222
|
body += await this.processNodeRecursive(node, processor);
|
|
205
223
|
}
|
|
224
|
+
if (this.collectedNotes.length > 0) {
|
|
225
|
+
body += '\\pard\\sb120\\sa120\\keepn{\\b Notes:}\\par\n';
|
|
226
|
+
for (const note of this.collectedNotes) {
|
|
227
|
+
body += await this.processNodeRecursive(note, processor);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
206
230
|
return body;
|
|
207
231
|
}
|
|
208
232
|
getColorIndex(hex) {
|
|
@@ -214,13 +238,32 @@ class RtfGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
214
238
|
}
|
|
215
239
|
return idx;
|
|
216
240
|
}
|
|
241
|
+
isLightColor(hex) {
|
|
242
|
+
if (!hex || hex.length !== 7 || !hex.startsWith('#'))
|
|
243
|
+
return false;
|
|
244
|
+
const r = parseInt(hex.substring(1, 3), 16);
|
|
245
|
+
const g = parseInt(hex.substring(3, 5), 16);
|
|
246
|
+
const b = parseInt(hex.substring(5, 7), 16);
|
|
247
|
+
if (isNaN(r) || isNaN(g) || isNaN(b))
|
|
248
|
+
return false;
|
|
249
|
+
// Simple luminance calculation
|
|
250
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
251
|
+
return luminance > 0.8;
|
|
252
|
+
}
|
|
217
253
|
escapeRtf(text) {
|
|
218
254
|
return text
|
|
219
255
|
.replace(/\\/g, '\\\\')
|
|
220
256
|
.replace(/{/g, '\\{')
|
|
221
257
|
.replace(/}/g, '\\}')
|
|
222
258
|
.replace(/[^\x00-\x7F]/g, (match) => {
|
|
223
|
-
|
|
259
|
+
let code = match.charCodeAt(0);
|
|
260
|
+
if (code < 256) {
|
|
261
|
+
return `\\'${code.toString(16).padStart(2, '0')}`;
|
|
262
|
+
}
|
|
263
|
+
if (code > 32767) {
|
|
264
|
+
code -= 65536;
|
|
265
|
+
}
|
|
266
|
+
return `{\\uc0\\u${code}}`;
|
|
224
267
|
});
|
|
225
268
|
}
|
|
226
269
|
}
|
|
@@ -62,6 +62,12 @@ class TextGenerator extends BaseGenerator_js_1.BaseGenerator {
|
|
|
62
62
|
for (const node of this.ast.content) {
|
|
63
63
|
output += await this.processNodeRecursive(node, processor);
|
|
64
64
|
}
|
|
65
|
+
if (this.collectedNotes.length > 0) {
|
|
66
|
+
output += `${newline}${newline}--- Notes ---${newline}`;
|
|
67
|
+
for (const note of this.collectedNotes) {
|
|
68
|
+
output += await this.processNodeRecursive(note, processor);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
65
71
|
return {
|
|
66
72
|
value: output.trim(),
|
|
67
73
|
messages: this.messages
|