document-cli 1.11.0 → 1.11.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/dist/cli.js +23 -170
- package/dist/index.cjs +21 -317
- package/dist/index.js +23 -319
- package/dist/{odb-structure-Du1w_hOU.js → odb-structure-CS2Eybob.js} +2 -151
- package/dist/{tui-DWXPty2k.js → tui-Bw_z7xq6.js} +5 -32
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, UnrecognizedDocumentSchemaError,
|
|
2
|
+
import { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, UnrecognizedDocumentSchemaError, UnsupportedFontSourceFormatError, buildDocumentBytes, createLocalDocumentConverter, decodePackage, documentFromJson, documentPackageWithSchema, evaluateSelect, extractSourceFontsForFormat, hsqldbCellDisplayText, layoutDocumentWithSchema, odbReportToDocx, odbReportToOdt, odbReportToPdf, odbToCsv, odbToXlsx, odmToPdf, parseSelect, readDocumentMetadata, readDocxExtras, readOdbForms, readOdbInventory, readOdbReportContent, readOdbReports, readOdbTables, readPdf, setDocumentMetadata } from "documents.js";
|
|
3
|
+
import { readFontFace } from "pdf-codec";
|
|
3
4
|
import { basename, dirname, extname, join } from "node:path";
|
|
4
5
|
import { Command, InvalidArgumentError } from "commander";
|
|
5
|
-
import { decodePackage as decodePackage$1
|
|
6
|
+
import { decodePackage as decodePackage$1 } from "odf.js";
|
|
6
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
8
|
//#region src/format.ts
|
|
8
9
|
const EXTENSION_TO_FORMAT = {
|
|
@@ -163,166 +164,17 @@ function mapErrorToExit(error, abortReason) {
|
|
|
163
164
|
if (abortReason === "timeout") return 124;
|
|
164
165
|
if (error instanceof OdmUnresolvedSectionError || error instanceof OdbTableNotSpecifiedError || error instanceof OdbTableNotFoundError || error instanceof OdbNoEmbeddedDataSourceError || error instanceof OdbUnsupportedFormatError || error instanceof OdbReportNotSpecifiedError) return 3;
|
|
165
166
|
if (error instanceof HsqldbSqlUnsupportedError || error instanceof HsqldbSqlParseError || error instanceof HsqldbSqlEvaluationError) return 1;
|
|
167
|
+
if (error instanceof UnsupportedFontSourceFormatError) return 2;
|
|
166
168
|
if (error instanceof PdfEncryptedError || error instanceof PdfParseError) return 1;
|
|
167
169
|
return 1;
|
|
168
170
|
}
|
|
169
171
|
//#endregion
|
|
170
|
-
//#region src/runtime/font-face.ts
|
|
171
|
-
var FontFaceError = class extends Error {
|
|
172
|
-
constructor(message) {
|
|
173
|
-
super(message);
|
|
174
|
-
this.name = "FontFaceError";
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
const SFNT_VERSION_TRUETYPE = 65536;
|
|
178
|
-
const SFNT_VERSION_CFF = 1330926671;
|
|
179
|
-
const SFNT_VERSION_APPLE_TRUE = 1953658213;
|
|
180
|
-
const SFNT_VERSION_APPLE_TYP1 = 1954115633;
|
|
181
|
-
const SFNT_VERSION_COLLECTION = 1953784678;
|
|
182
|
-
const SFNT_VERSIONS = /* @__PURE__ */ new Set([
|
|
183
|
-
SFNT_VERSION_TRUETYPE,
|
|
184
|
-
SFNT_VERSION_CFF,
|
|
185
|
-
SFNT_VERSION_APPLE_TRUE,
|
|
186
|
-
SFNT_VERSION_APPLE_TYP1
|
|
187
|
-
]);
|
|
188
|
-
const TABLE_DIRECTORY_HEADER_SIZE = 12;
|
|
189
|
-
const TABLE_RECORD_SIZE = 16;
|
|
190
|
-
const TABLE_TAG_SIZE = 4;
|
|
191
|
-
const NAME_HEADER_SIZE = 6;
|
|
192
|
-
const NAME_RECORD_SIZE = 12;
|
|
193
|
-
const NAME_ID_FAMILY = 1;
|
|
194
|
-
const NAME_ID_TYPOGRAPHIC_FAMILY = 16;
|
|
195
|
-
const PLATFORM_UNICODE = 0;
|
|
196
|
-
const PLATFORM_MACINTOSH = 1;
|
|
197
|
-
const PLATFORM_WINDOWS = 3;
|
|
198
|
-
const MACINTOSH_ENCODING_ROMAN = 0;
|
|
199
|
-
const OS2_FS_SELECTION_OFFSET = 62;
|
|
200
|
-
const OS2_MINIMUM_SIZE = 64;
|
|
201
|
-
const OS2_FS_SELECTION_ITALIC = 1;
|
|
202
|
-
const OS2_FS_SELECTION_BOLD = 32;
|
|
203
|
-
const HEAD_MAC_STYLE_OFFSET = 44;
|
|
204
|
-
const HEAD_MINIMUM_SIZE = 46;
|
|
205
|
-
const HEAD_MAC_STYLE_BOLD = 1;
|
|
206
|
-
const HEAD_MAC_STYLE_ITALIC = 2;
|
|
207
|
-
function viewOf(bytes) {
|
|
208
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
209
|
-
}
|
|
210
|
-
function decodeTag(view, offset) {
|
|
211
|
-
let tag = "";
|
|
212
|
-
for (let i = 0; i < TABLE_TAG_SIZE; i++) tag += String.fromCharCode(view.getUint8(offset + i));
|
|
213
|
-
return tag;
|
|
214
|
-
}
|
|
215
|
-
function decodeUtf16Be(view, offset, length) {
|
|
216
|
-
let text = "";
|
|
217
|
-
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(view.getUint16(offset + i));
|
|
218
|
-
return text;
|
|
219
|
-
}
|
|
220
|
-
function decodeMacintoshAscii(view, offset, length) {
|
|
221
|
-
let text = "";
|
|
222
|
-
for (let i = 0; i < length; i++) {
|
|
223
|
-
const byte = view.getUint8(offset + i);
|
|
224
|
-
if (byte > 126) return;
|
|
225
|
-
text += String.fromCharCode(byte);
|
|
226
|
-
}
|
|
227
|
-
return text;
|
|
228
|
-
}
|
|
229
|
-
function readTableDirectory(view, source) {
|
|
230
|
-
if (view.byteLength < TABLE_DIRECTORY_HEADER_SIZE) throw new FontFaceError(`${source} is too short to be a font file (${String(view.byteLength)} bytes)`);
|
|
231
|
-
const sfntVersion = view.getUint32(0);
|
|
232
|
-
if (sfntVersion === SFNT_VERSION_COLLECTION) throw new FontFaceError(`${source} is a TrueType Collection (.ttc), which packs several faces into one file; extract the single face you want and pass that instead`);
|
|
233
|
-
if (!SFNT_VERSIONS.has(sfntVersion)) throw new FontFaceError(`${source} is not a TrueType/OpenType font file (no recognised sfnt version); a .woff/.woff2 file must be converted to .ttf/.otf first`);
|
|
234
|
-
const numTables = view.getUint16(4);
|
|
235
|
-
if (view.byteLength < TABLE_DIRECTORY_HEADER_SIZE + numTables * TABLE_RECORD_SIZE) throw new FontFaceError(`${source} declares ${String(numTables)} tables but is too short to hold that many table records`);
|
|
236
|
-
const tables = /* @__PURE__ */ new Map();
|
|
237
|
-
for (let i = 0; i < numTables; i++) {
|
|
238
|
-
const recordOffset = TABLE_DIRECTORY_HEADER_SIZE + i * TABLE_RECORD_SIZE;
|
|
239
|
-
const tag = decodeTag(view, recordOffset);
|
|
240
|
-
const offset = view.getUint32(recordOffset + 8);
|
|
241
|
-
const length = view.getUint32(recordOffset + 12);
|
|
242
|
-
if (offset + length > view.byteLength || tables.has(tag)) continue;
|
|
243
|
-
tables.set(tag, {
|
|
244
|
-
offset,
|
|
245
|
-
length
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
return tables;
|
|
249
|
-
}
|
|
250
|
-
function tableView(bytes, table) {
|
|
251
|
-
return new DataView(bytes.buffer, bytes.byteOffset + table.offset, table.length);
|
|
252
|
-
}
|
|
253
|
-
function readNameRecords(name) {
|
|
254
|
-
if (name.byteLength < NAME_HEADER_SIZE) return [];
|
|
255
|
-
const count = name.getUint16(2);
|
|
256
|
-
const storageOffset = name.getUint16(4);
|
|
257
|
-
if (name.byteLength < NAME_HEADER_SIZE + count * NAME_RECORD_SIZE) return [];
|
|
258
|
-
const records = [];
|
|
259
|
-
for (let i = 0; i < count; i++) {
|
|
260
|
-
const recordOffset = NAME_HEADER_SIZE + i * NAME_RECORD_SIZE;
|
|
261
|
-
records.push({
|
|
262
|
-
platformId: name.getUint16(recordOffset),
|
|
263
|
-
encodingId: name.getUint16(recordOffset + 2),
|
|
264
|
-
nameId: name.getUint16(recordOffset + 6),
|
|
265
|
-
length: name.getUint16(recordOffset + 8),
|
|
266
|
-
stringOffset: storageOffset + name.getUint16(recordOffset + 10)
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
return records;
|
|
270
|
-
}
|
|
271
|
-
function platformPreference(record) {
|
|
272
|
-
if (record.platformId === PLATFORM_WINDOWS) return 0;
|
|
273
|
-
if (record.platformId === PLATFORM_UNICODE) return 1;
|
|
274
|
-
if (record.platformId === PLATFORM_MACINTOSH && record.encodingId === MACINTOSH_ENCODING_ROMAN) return 2;
|
|
275
|
-
return Number.POSITIVE_INFINITY;
|
|
276
|
-
}
|
|
277
|
-
function readNameString(name, records, nameId) {
|
|
278
|
-
const candidates = records.filter((record) => record.nameId === nameId && Number.isFinite(platformPreference(record))).sort((left, right) => platformPreference(left) - platformPreference(right));
|
|
279
|
-
for (const record of candidates) {
|
|
280
|
-
if (record.stringOffset + record.length > name.byteLength) continue;
|
|
281
|
-
const text = record.platformId === PLATFORM_MACINTOSH ? decodeMacintoshAscii(name, record.stringOffset, record.length) : decodeUtf16Be(name, record.stringOffset, record.length);
|
|
282
|
-
if (text !== void 0 && text.length > 0) return text;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
function readStyleBits(bytes, tables, source) {
|
|
286
|
-
const os2 = tables.get("OS/2");
|
|
287
|
-
if (os2 !== void 0 && os2.length >= OS2_MINIMUM_SIZE) {
|
|
288
|
-
const fsSelection = tableView(bytes, os2).getUint16(OS2_FS_SELECTION_OFFSET);
|
|
289
|
-
return {
|
|
290
|
-
bold: (fsSelection & OS2_FS_SELECTION_BOLD) !== 0,
|
|
291
|
-
italic: (fsSelection & OS2_FS_SELECTION_ITALIC) !== 0
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
const head = tables.get("head");
|
|
295
|
-
if (head !== void 0 && head.length >= HEAD_MINIMUM_SIZE) {
|
|
296
|
-
const macStyle = tableView(bytes, head).getUint16(HEAD_MAC_STYLE_OFFSET);
|
|
297
|
-
return {
|
|
298
|
-
bold: (macStyle & HEAD_MAC_STYLE_BOLD) !== 0,
|
|
299
|
-
italic: (macStyle & HEAD_MAC_STYLE_ITALIC) !== 0
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
throw new FontFaceError(`${source} declares neither a readable 'OS/2' nor a readable 'head' table, so its weight and slope cannot be determined`);
|
|
303
|
-
}
|
|
304
|
-
function describeFontFace(bytes, source) {
|
|
305
|
-
const tables = readTableDirectory(viewOf(bytes), source);
|
|
306
|
-
const nameTable = tables.get("name");
|
|
307
|
-
if (nameTable === void 0) throw new FontFaceError(`${source} declares no 'name' table, so the font family it provides cannot be determined`);
|
|
308
|
-
const name = tableView(bytes, nameTable);
|
|
309
|
-
const records = readNameRecords(name);
|
|
310
|
-
const family = readNameString(name, records, NAME_ID_TYPOGRAPHIC_FAMILY) ?? readNameString(name, records, NAME_ID_FAMILY);
|
|
311
|
-
if (family === void 0) throw new FontFaceError(`${source} declares no family name in its 'name' table, so the font family it provides cannot be determined`);
|
|
312
|
-
const { bold, italic } = readStyleBits(bytes, tables, source);
|
|
313
|
-
return {
|
|
314
|
-
family,
|
|
315
|
-
bold,
|
|
316
|
-
italic
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
//#endregion
|
|
320
172
|
//#region src/runtime/fonts.ts
|
|
321
173
|
async function loadProvidedFonts(paths, options) {
|
|
322
174
|
const fonts = [];
|
|
323
175
|
for (const path of paths) {
|
|
324
176
|
const bytes = new Uint8Array(await readFile(path, { signal: options?.signal }));
|
|
325
|
-
const face =
|
|
177
|
+
const face = readFontFace(bytes, path);
|
|
326
178
|
fonts.push({
|
|
327
179
|
family: face.family,
|
|
328
180
|
bold: face.bold,
|
|
@@ -616,27 +468,6 @@ function registerDocxExtrasCommand(program) {
|
|
|
616
468
|
}
|
|
617
469
|
//#endregion
|
|
618
470
|
//#region src/commands/fonts.ts
|
|
619
|
-
const FONT_SOURCE_FORMATS = {
|
|
620
|
-
docx: true,
|
|
621
|
-
pptx: true,
|
|
622
|
-
odt: true,
|
|
623
|
-
odp: true,
|
|
624
|
-
ods: true,
|
|
625
|
-
odg: true
|
|
626
|
-
};
|
|
627
|
-
function isFontSourceFormat(format) {
|
|
628
|
-
return format in FONT_SOURCE_FORMATS;
|
|
629
|
-
}
|
|
630
|
-
function resolveFontSourcePackage(format, bytes) {
|
|
631
|
-
if (format === "docx" || format === "pptx") return {
|
|
632
|
-
kind: format,
|
|
633
|
-
package: decodePackage(bytes)
|
|
634
|
-
};
|
|
635
|
-
return {
|
|
636
|
-
kind: "odf",
|
|
637
|
-
package: decodePackage$1(bytes)
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
471
|
async function runFonts(input, options) {
|
|
641
472
|
const command = "fonts";
|
|
642
473
|
const { signal, getAbortReason } = createRuntimeSignal({});
|
|
@@ -646,13 +477,8 @@ async function runFonts(input, options) {
|
|
|
646
477
|
process.stderr.write(`[${command}] cannot infer a document format from '${input}'; expected one of docx, pptx, odt, odp, ods, odg\n`);
|
|
647
478
|
return 2;
|
|
648
479
|
}
|
|
649
|
-
if (!isFontSourceFormat(format)) {
|
|
650
|
-
process.stderr.write(`[${command}] '${format}' documents carry no source-embedded font faces this command can extract; expected one of docx, pptx, odt, odp, ods, odg\n`);
|
|
651
|
-
return 2;
|
|
652
|
-
}
|
|
653
480
|
const inputBytes = await readInput(input, { signal });
|
|
654
|
-
const
|
|
655
|
-
const summaries = extractSourceFonts(source).map((face) => ({
|
|
481
|
+
const summaries = extractSourceFontsForFormat(format, new Uint8Array(inputBytes)).map((face) => ({
|
|
656
482
|
family: face.family,
|
|
657
483
|
bold: face.bold,
|
|
658
484
|
italic: face.italic,
|
|
@@ -697,23 +523,6 @@ function registerFormatsCommand(program) {
|
|
|
697
523
|
}
|
|
698
524
|
//#endregion
|
|
699
525
|
//#region src/commands/from-package.ts
|
|
700
|
-
function buildBytesForTarget(pkg, target) {
|
|
701
|
-
if (target === "pdf") {
|
|
702
|
-
if (pkg.layout === void 0) throw new Error("this DocumentPackage has no layout -- only a package dumped from a <format>-to-pdf or pdf-to-<format> conversion carries one; a bridge conversion's own dump (e.g. odt-to-docx) never does, so 'pdf' is not a reachable target from it");
|
|
703
|
-
return writePdf(pkg.layout);
|
|
704
|
-
}
|
|
705
|
-
switch (target) {
|
|
706
|
-
case "docx": return encodePackage(buildDocxPackage(pkg.content));
|
|
707
|
-
case "pptx": return encodePackage(buildPptxPackage(pkg.content));
|
|
708
|
-
case "odt": return encodePackage$1(buildOdtPackage(pkg.content));
|
|
709
|
-
case "odp": return encodePackage$1(buildOdpPackage(pkg.content));
|
|
710
|
-
case "ods": return encodePackage$1(buildOdsPackage(pkg.content));
|
|
711
|
-
case "odg": return encodePackage$1(buildOdgPackage(pkg.content));
|
|
712
|
-
case "markdown": return encodeMarkdownText(buildMarkdownText(pkg.content));
|
|
713
|
-
case "xlsx": throw new Error("'xlsx' cannot be built from a DocumentPackage directly -- documents.js does not re-export a ContentDocument-to-xlsx builder; convert to 'ods' here, then run 'ods-to-xlsx' on the result instead");
|
|
714
|
-
case "odf": throw new Error("'odf' (a standalone formula document) cannot be built from a DocumentPackage -- there is no ContentDocument-to-odf builder");
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
526
|
async function runFromPackage(input, output, options) {
|
|
718
527
|
const command = "from-package";
|
|
719
528
|
if (output !== void 0 && options.out !== void 0 && output !== options.out) {
|
|
@@ -742,7 +551,7 @@ async function runFromPackage(input, output, options) {
|
|
|
742
551
|
process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentPackage -- only a file written by --dump-package can be read back by this command\n`);
|
|
743
552
|
return 2;
|
|
744
553
|
}
|
|
745
|
-
const bytes =
|
|
554
|
+
const bytes = buildDocumentBytes(result.value, target.format);
|
|
746
555
|
await writeOutput(resolvedOutput, bytes);
|
|
747
556
|
createDiagnosticReporter({
|
|
748
557
|
json: options.json,
|
|
@@ -801,20 +610,6 @@ function formatMetadataLines(metadata) {
|
|
|
801
610
|
}
|
|
802
611
|
//#endregion
|
|
803
612
|
//#region src/commands/metadata.ts
|
|
804
|
-
function readMetadataForFormat(format, bytes, signal) {
|
|
805
|
-
switch (format) {
|
|
806
|
-
case "docx": return readDocxContent(decodePackage(bytes)).metadata;
|
|
807
|
-
case "pptx": return readPptxContent(decodePackage(bytes)).metadata;
|
|
808
|
-
case "odt": return readOdtContent(decodePackage$1(bytes)).metadata;
|
|
809
|
-
case "odp": return readOdpContent(decodePackage$1(bytes)).metadata;
|
|
810
|
-
case "ods": return readOdsContent(decodePackage$1(bytes)).metadata;
|
|
811
|
-
case "odg": return readOdgContent(decodePackage$1(bytes)).metadata;
|
|
812
|
-
case "odf": return readOdfFormulaContent(decodePackage$1(bytes)).metadata;
|
|
813
|
-
case "markdown": return readMarkdownContent(decodeMarkdownText(bytes)).metadata;
|
|
814
|
-
case "pdf": return readPdf(bytes, { signal }).metadata;
|
|
815
|
-
case "xlsx": return readPdf(xlsxToPdf(bytes, { signal }), { signal }).metadata;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
613
|
async function runMetadata(input, options) {
|
|
819
614
|
const command = "metadata";
|
|
820
615
|
const source = inferFormatFromExtension(input);
|
|
@@ -825,7 +620,7 @@ async function runMetadata(input, options) {
|
|
|
825
620
|
const { signal, getAbortReason } = createRuntimeSignal({});
|
|
826
621
|
try {
|
|
827
622
|
const inputBytes = await readInput(input, { signal });
|
|
828
|
-
const metadata =
|
|
623
|
+
const metadata = readDocumentMetadata(source, new Uint8Array(inputBytes), { signal });
|
|
829
624
|
if (options.json) {
|
|
830
625
|
process.stdout.write(`${JSON.stringify(metadata)}\n`);
|
|
831
626
|
return 0;
|
|
@@ -1205,32 +1000,6 @@ const ODB_REPORT_TARGET_FORMATS = {
|
|
|
1205
1000
|
function isOdbReportTargetFormat(format) {
|
|
1206
1001
|
return format in ODB_REPORT_TARGET_FORMATS;
|
|
1207
1002
|
}
|
|
1208
|
-
function renderOdbReportBytes(content, target, options) {
|
|
1209
|
-
if (target === "docx") return encodePackage(buildDocxPackage(content));
|
|
1210
|
-
if (target === "odt") return encodePackage$1(buildOdtPackage(content));
|
|
1211
|
-
if (content.kind !== "wordprocessing") throw new Error("readOdbReportContent returned a non-wordprocessing ContentDocument");
|
|
1212
|
-
const fonts = createFontRegistry({
|
|
1213
|
-
fonts: options.fonts,
|
|
1214
|
-
onSubstitution: (substitution) => {
|
|
1215
|
-
if (options.reportFontSubstitution !== void 0) {
|
|
1216
|
-
options.reportFontSubstitution(substitution);
|
|
1217
|
-
return;
|
|
1218
|
-
}
|
|
1219
|
-
options.onDiagnosticCounted();
|
|
1220
|
-
options.reporter.report(fontSubstitutionToDiagnostic(substitution));
|
|
1221
|
-
}
|
|
1222
|
-
});
|
|
1223
|
-
const { document: layout, formulas } = convertWordprocessingToLayout(content, { measurer: createFontMeasurer(fonts) });
|
|
1224
|
-
return writePdf(layout, {
|
|
1225
|
-
signal: options.signal,
|
|
1226
|
-
onSubstitution: (substitution, context) => {
|
|
1227
|
-
options.onDiagnosticCounted();
|
|
1228
|
-
options.reporter.report(substitutionToDiagnostic(substitution, context.pageIndex));
|
|
1229
|
-
},
|
|
1230
|
-
formulas,
|
|
1231
|
-
fonts
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
1003
|
async function runOdbRenderReport(input, output, options) {
|
|
1235
1004
|
const command = "odb-render-report";
|
|
1236
1005
|
if (output !== void 0 && options.out !== void 0 && output !== options.out) {
|
|
@@ -1264,13 +1033,21 @@ async function runOdbRenderReport(input, output, options) {
|
|
|
1264
1033
|
const inputBytes = await readInput(input, { signal });
|
|
1265
1034
|
const fonts = await loadProvidedFonts(options.fontFile ?? [], { signal });
|
|
1266
1035
|
const pkg = decodePackage$1(new Uint8Array(inputBytes));
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1036
|
+
const content = readOdbReportContent(pkg, { report: options.report });
|
|
1037
|
+
const bytes = targetFormat === "docx" ? odbReportToDocx(content) : targetFormat === "odt" ? odbReportToOdt(content) : odbReportToPdf(content, {
|
|
1269
1038
|
signal,
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1039
|
+
fonts,
|
|
1040
|
+
onFontSubstitution: (substitution) => {
|
|
1041
|
+
if (reportFontSubstitution !== void 0) {
|
|
1042
|
+
reportFontSubstitution(substitution);
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
diagnosticCount += 1;
|
|
1046
|
+
reporter.report(fontSubstitutionToDiagnostic(substitution));
|
|
1047
|
+
},
|
|
1048
|
+
onSubstitution: (substitution, context) => {
|
|
1273
1049
|
diagnosticCount += 1;
|
|
1050
|
+
reporter.report(substitutionToDiagnostic(substitution, context.pageIndex));
|
|
1274
1051
|
}
|
|
1275
1052
|
});
|
|
1276
1053
|
await writeOutput(resolvedOutput, bytes);
|
|
@@ -1513,63 +1290,9 @@ function registerPdfInspectCommand(program) {
|
|
|
1513
1290
|
}
|
|
1514
1291
|
//#endregion
|
|
1515
1292
|
//#region src/commands/set-metadata.ts
|
|
1516
|
-
const REBUILD_FORMATS = {
|
|
1517
|
-
docx: true,
|
|
1518
|
-
pptx: true,
|
|
1519
|
-
odt: true,
|
|
1520
|
-
odp: true,
|
|
1521
|
-
ods: true,
|
|
1522
|
-
odg: true,
|
|
1523
|
-
markdown: true
|
|
1524
|
-
};
|
|
1525
|
-
function isRebuildFormat(format) {
|
|
1526
|
-
return format in REBUILD_FORMATS;
|
|
1527
|
-
}
|
|
1528
|
-
function readContentForFormat(format, bytes) {
|
|
1529
|
-
switch (format) {
|
|
1530
|
-
case "docx": return readDocxContent(decodePackage(bytes));
|
|
1531
|
-
case "pptx": return readPptxContent(decodePackage(bytes));
|
|
1532
|
-
case "odt": return readOdtContent(decodePackage$1(bytes));
|
|
1533
|
-
case "odp": return readOdpContent(decodePackage$1(bytes));
|
|
1534
|
-
case "ods": return readOdsContent(decodePackage$1(bytes));
|
|
1535
|
-
case "odg": return readOdgContent(decodePackage$1(bytes));
|
|
1536
|
-
case "markdown": return readMarkdownContent(decodeMarkdownText(bytes));
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
function buildBytesForRebuildFormat(format, content) {
|
|
1540
|
-
switch (format) {
|
|
1541
|
-
case "docx": return encodePackage(buildDocxPackage(content));
|
|
1542
|
-
case "pptx": return encodePackage(buildPptxPackage(content));
|
|
1543
|
-
case "odt": return encodePackage$1(buildOdtPackage(content));
|
|
1544
|
-
case "odp": return encodePackage$1(buildOdpPackage(content));
|
|
1545
|
-
case "ods": return encodePackage$1(buildOdsPackage(content));
|
|
1546
|
-
case "odg": return encodePackage$1(buildOdgPackage(content));
|
|
1547
|
-
case "markdown": return encodeMarkdownText(buildMarkdownText(content));
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
function mergeMetadata(current, overrides) {
|
|
1551
|
-
return {
|
|
1552
|
-
...current,
|
|
1553
|
-
...overrides.title !== void 0 ? { title: overrides.title } : {},
|
|
1554
|
-
...overrides.author !== void 0 ? { author: overrides.author } : {},
|
|
1555
|
-
...overrides.subject !== void 0 ? { subject: overrides.subject } : {},
|
|
1556
|
-
...overrides.keywords !== void 0 ? { keywords: overrides.keywords } : {}
|
|
1557
|
-
};
|
|
1558
|
-
}
|
|
1559
1293
|
function parseKeywords(csv) {
|
|
1560
1294
|
return csv.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
1561
1295
|
}
|
|
1562
|
-
function classifyWritePath(source, target) {
|
|
1563
|
-
if (source === "pdf" && target === "pdf") return { kind: "pdf" };
|
|
1564
|
-
if (target === "xlsx" || source === "xlsx") return { errorMessage: "'xlsx' is not a supported set-metadata source or target -- documents.js does not re-export a ContentDocument-to-xlsx builder or a readXlsxContent from its own public surface (see that package's own README, Architecture section); convert with 'xlsx-to-ods'/'ods-to-xlsx' first, then set metadata on the ods" };
|
|
1565
|
-
if (target === "odf" || source === "odf") return { errorMessage: "'odf' (a standalone formula document) is not a supported set-metadata source or target -- it has no write path back out at all" };
|
|
1566
|
-
if (!isRebuildFormat(source) || !isRebuildFormat(target)) return { errorMessage: `set-metadata only patches metadata in place; it does not convert format -- source ('${source}') and target ('${target}') must be the same format (or both 'pdf'). Run 'convert'/'from-package' first if you need a different target format.` };
|
|
1567
|
-
if (source !== target) return { errorMessage: `set-metadata only patches metadata in place; it does not convert format -- source ('${source}') and target ('${target}') must be the same format. Run 'convert'/'from-package' first if you need a different target format.` };
|
|
1568
|
-
return {
|
|
1569
|
-
kind: "rebuild",
|
|
1570
|
-
format: source
|
|
1571
|
-
};
|
|
1572
|
-
}
|
|
1573
1296
|
async function runSetMetadata(input, output, options) {
|
|
1574
1297
|
const command = "set-metadata";
|
|
1575
1298
|
if (output !== void 0 && options.out !== void 0 && output !== options.out) {
|
|
@@ -1586,11 +1309,6 @@ async function runSetMetadata(input, output, options) {
|
|
|
1586
1309
|
process.stderr.write(`[${command}] cannot infer a source format from '${input}'; rename the file with a recognised extension (${KNOWN_DOCUMENT_FORMATS})\n`);
|
|
1587
1310
|
return 2;
|
|
1588
1311
|
}
|
|
1589
|
-
const writePath = classifyWritePath(source, target.format);
|
|
1590
|
-
if ("errorMessage" in writePath) {
|
|
1591
|
-
process.stderr.write(`[${command}] ${writePath.errorMessage}\n`);
|
|
1592
|
-
return 2;
|
|
1593
|
-
}
|
|
1594
1312
|
const overrides = {
|
|
1595
1313
|
title: options.setTitle,
|
|
1596
1314
|
author: options.setAuthor,
|
|
@@ -1601,21 +1319,7 @@ async function runSetMetadata(input, output, options) {
|
|
|
1601
1319
|
const { signal, getAbortReason } = createRuntimeSignal({ timeoutMs: options.timeout });
|
|
1602
1320
|
try {
|
|
1603
1321
|
const inputBytes = await readInput(input, { signal });
|
|
1604
|
-
const bytes =
|
|
1605
|
-
const layout = readPdf(new Uint8Array(inputBytes), { signal });
|
|
1606
|
-
const patched = {
|
|
1607
|
-
...layout,
|
|
1608
|
-
metadata: mergeMetadata(layout.metadata, overrides)
|
|
1609
|
-
};
|
|
1610
|
-
return writePdf(patched, { signal });
|
|
1611
|
-
})() : (() => {
|
|
1612
|
-
const content = readContentForFormat(writePath.format, new Uint8Array(inputBytes));
|
|
1613
|
-
const nextContent = {
|
|
1614
|
-
...content,
|
|
1615
|
-
metadata: mergeMetadata(content.metadata, overrides)
|
|
1616
|
-
};
|
|
1617
|
-
return buildBytesForRebuildFormat(writePath.format, nextContent);
|
|
1618
|
-
})();
|
|
1322
|
+
const bytes = setDocumentMetadata(source, target.format, new Uint8Array(inputBytes), overrides, { signal });
|
|
1619
1323
|
await writeOutput(resolvedOutput, bytes);
|
|
1620
1324
|
createDiagnosticReporter({
|
|
1621
1325
|
json: options.json,
|
|
@@ -1660,7 +1364,7 @@ function registerSetMetadataCommand(program) {
|
|
|
1660
1364
|
}
|
|
1661
1365
|
//#endregion
|
|
1662
1366
|
//#region package.json
|
|
1663
|
-
var version = "1.11.
|
|
1367
|
+
var version = "1.11.1";
|
|
1664
1368
|
//#endregion
|
|
1665
1369
|
//#region src/program.ts
|
|
1666
1370
|
function createProgram() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import "documents.js";
|
|
3
|
+
import { readFontFace } from "pdf-codec";
|
|
3
4
|
import { basename, dirname, extname, join } from "node:path";
|
|
4
5
|
//#region src/format.ts
|
|
5
6
|
const EXTENSION_TO_FORMAT = {
|
|
@@ -42,162 +43,12 @@ function formatToExtension(format) {
|
|
|
42
43
|
return FORMAT_TO_EXTENSION[format];
|
|
43
44
|
}
|
|
44
45
|
//#endregion
|
|
45
|
-
//#region src/runtime/font-face.ts
|
|
46
|
-
var FontFaceError = class extends Error {
|
|
47
|
-
constructor(message) {
|
|
48
|
-
super(message);
|
|
49
|
-
this.name = "FontFaceError";
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
const SFNT_VERSION_TRUETYPE = 65536;
|
|
53
|
-
const SFNT_VERSION_CFF = 1330926671;
|
|
54
|
-
const SFNT_VERSION_APPLE_TRUE = 1953658213;
|
|
55
|
-
const SFNT_VERSION_APPLE_TYP1 = 1954115633;
|
|
56
|
-
const SFNT_VERSION_COLLECTION = 1953784678;
|
|
57
|
-
const SFNT_VERSIONS = /* @__PURE__ */ new Set([
|
|
58
|
-
SFNT_VERSION_TRUETYPE,
|
|
59
|
-
SFNT_VERSION_CFF,
|
|
60
|
-
SFNT_VERSION_APPLE_TRUE,
|
|
61
|
-
SFNT_VERSION_APPLE_TYP1
|
|
62
|
-
]);
|
|
63
|
-
const TABLE_DIRECTORY_HEADER_SIZE = 12;
|
|
64
|
-
const TABLE_RECORD_SIZE = 16;
|
|
65
|
-
const TABLE_TAG_SIZE = 4;
|
|
66
|
-
const NAME_HEADER_SIZE = 6;
|
|
67
|
-
const NAME_RECORD_SIZE = 12;
|
|
68
|
-
const NAME_ID_FAMILY = 1;
|
|
69
|
-
const NAME_ID_TYPOGRAPHIC_FAMILY = 16;
|
|
70
|
-
const PLATFORM_UNICODE = 0;
|
|
71
|
-
const PLATFORM_MACINTOSH = 1;
|
|
72
|
-
const PLATFORM_WINDOWS = 3;
|
|
73
|
-
const MACINTOSH_ENCODING_ROMAN = 0;
|
|
74
|
-
const OS2_FS_SELECTION_OFFSET = 62;
|
|
75
|
-
const OS2_MINIMUM_SIZE = 64;
|
|
76
|
-
const OS2_FS_SELECTION_ITALIC = 1;
|
|
77
|
-
const OS2_FS_SELECTION_BOLD = 32;
|
|
78
|
-
const HEAD_MAC_STYLE_OFFSET = 44;
|
|
79
|
-
const HEAD_MINIMUM_SIZE = 46;
|
|
80
|
-
const HEAD_MAC_STYLE_BOLD = 1;
|
|
81
|
-
const HEAD_MAC_STYLE_ITALIC = 2;
|
|
82
|
-
function viewOf(bytes) {
|
|
83
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
84
|
-
}
|
|
85
|
-
function decodeTag(view, offset) {
|
|
86
|
-
let tag = "";
|
|
87
|
-
for (let i = 0; i < TABLE_TAG_SIZE; i++) tag += String.fromCharCode(view.getUint8(offset + i));
|
|
88
|
-
return tag;
|
|
89
|
-
}
|
|
90
|
-
function decodeUtf16Be(view, offset, length) {
|
|
91
|
-
let text = "";
|
|
92
|
-
for (let i = 0; i + 1 < length; i += 2) text += String.fromCharCode(view.getUint16(offset + i));
|
|
93
|
-
return text;
|
|
94
|
-
}
|
|
95
|
-
function decodeMacintoshAscii(view, offset, length) {
|
|
96
|
-
let text = "";
|
|
97
|
-
for (let i = 0; i < length; i++) {
|
|
98
|
-
const byte = view.getUint8(offset + i);
|
|
99
|
-
if (byte > 126) return;
|
|
100
|
-
text += String.fromCharCode(byte);
|
|
101
|
-
}
|
|
102
|
-
return text;
|
|
103
|
-
}
|
|
104
|
-
function readTableDirectory(view, source) {
|
|
105
|
-
if (view.byteLength < TABLE_DIRECTORY_HEADER_SIZE) throw new FontFaceError(`${source} is too short to be a font file (${String(view.byteLength)} bytes)`);
|
|
106
|
-
const sfntVersion = view.getUint32(0);
|
|
107
|
-
if (sfntVersion === SFNT_VERSION_COLLECTION) throw new FontFaceError(`${source} is a TrueType Collection (.ttc), which packs several faces into one file; extract the single face you want and pass that instead`);
|
|
108
|
-
if (!SFNT_VERSIONS.has(sfntVersion)) throw new FontFaceError(`${source} is not a TrueType/OpenType font file (no recognised sfnt version); a .woff/.woff2 file must be converted to .ttf/.otf first`);
|
|
109
|
-
const numTables = view.getUint16(4);
|
|
110
|
-
if (view.byteLength < TABLE_DIRECTORY_HEADER_SIZE + numTables * TABLE_RECORD_SIZE) throw new FontFaceError(`${source} declares ${String(numTables)} tables but is too short to hold that many table records`);
|
|
111
|
-
const tables = /* @__PURE__ */ new Map();
|
|
112
|
-
for (let i = 0; i < numTables; i++) {
|
|
113
|
-
const recordOffset = TABLE_DIRECTORY_HEADER_SIZE + i * TABLE_RECORD_SIZE;
|
|
114
|
-
const tag = decodeTag(view, recordOffset);
|
|
115
|
-
const offset = view.getUint32(recordOffset + 8);
|
|
116
|
-
const length = view.getUint32(recordOffset + 12);
|
|
117
|
-
if (offset + length > view.byteLength || tables.has(tag)) continue;
|
|
118
|
-
tables.set(tag, {
|
|
119
|
-
offset,
|
|
120
|
-
length
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
return tables;
|
|
124
|
-
}
|
|
125
|
-
function tableView(bytes, table) {
|
|
126
|
-
return new DataView(bytes.buffer, bytes.byteOffset + table.offset, table.length);
|
|
127
|
-
}
|
|
128
|
-
function readNameRecords(name) {
|
|
129
|
-
if (name.byteLength < NAME_HEADER_SIZE) return [];
|
|
130
|
-
const count = name.getUint16(2);
|
|
131
|
-
const storageOffset = name.getUint16(4);
|
|
132
|
-
if (name.byteLength < NAME_HEADER_SIZE + count * NAME_RECORD_SIZE) return [];
|
|
133
|
-
const records = [];
|
|
134
|
-
for (let i = 0; i < count; i++) {
|
|
135
|
-
const recordOffset = NAME_HEADER_SIZE + i * NAME_RECORD_SIZE;
|
|
136
|
-
records.push({
|
|
137
|
-
platformId: name.getUint16(recordOffset),
|
|
138
|
-
encodingId: name.getUint16(recordOffset + 2),
|
|
139
|
-
nameId: name.getUint16(recordOffset + 6),
|
|
140
|
-
length: name.getUint16(recordOffset + 8),
|
|
141
|
-
stringOffset: storageOffset + name.getUint16(recordOffset + 10)
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
return records;
|
|
145
|
-
}
|
|
146
|
-
function platformPreference(record) {
|
|
147
|
-
if (record.platformId === PLATFORM_WINDOWS) return 0;
|
|
148
|
-
if (record.platformId === PLATFORM_UNICODE) return 1;
|
|
149
|
-
if (record.platformId === PLATFORM_MACINTOSH && record.encodingId === MACINTOSH_ENCODING_ROMAN) return 2;
|
|
150
|
-
return Number.POSITIVE_INFINITY;
|
|
151
|
-
}
|
|
152
|
-
function readNameString(name, records, nameId) {
|
|
153
|
-
const candidates = records.filter((record) => record.nameId === nameId && Number.isFinite(platformPreference(record))).sort((left, right) => platformPreference(left) - platformPreference(right));
|
|
154
|
-
for (const record of candidates) {
|
|
155
|
-
if (record.stringOffset + record.length > name.byteLength) continue;
|
|
156
|
-
const text = record.platformId === PLATFORM_MACINTOSH ? decodeMacintoshAscii(name, record.stringOffset, record.length) : decodeUtf16Be(name, record.stringOffset, record.length);
|
|
157
|
-
if (text !== void 0 && text.length > 0) return text;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function readStyleBits(bytes, tables, source) {
|
|
161
|
-
const os2 = tables.get("OS/2");
|
|
162
|
-
if (os2 !== void 0 && os2.length >= OS2_MINIMUM_SIZE) {
|
|
163
|
-
const fsSelection = tableView(bytes, os2).getUint16(OS2_FS_SELECTION_OFFSET);
|
|
164
|
-
return {
|
|
165
|
-
bold: (fsSelection & OS2_FS_SELECTION_BOLD) !== 0,
|
|
166
|
-
italic: (fsSelection & OS2_FS_SELECTION_ITALIC) !== 0
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
const head = tables.get("head");
|
|
170
|
-
if (head !== void 0 && head.length >= HEAD_MINIMUM_SIZE) {
|
|
171
|
-
const macStyle = tableView(bytes, head).getUint16(HEAD_MAC_STYLE_OFFSET);
|
|
172
|
-
return {
|
|
173
|
-
bold: (macStyle & HEAD_MAC_STYLE_BOLD) !== 0,
|
|
174
|
-
italic: (macStyle & HEAD_MAC_STYLE_ITALIC) !== 0
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
throw new FontFaceError(`${source} declares neither a readable 'OS/2' nor a readable 'head' table, so its weight and slope cannot be determined`);
|
|
178
|
-
}
|
|
179
|
-
function describeFontFace(bytes, source) {
|
|
180
|
-
const tables = readTableDirectory(viewOf(bytes), source);
|
|
181
|
-
const nameTable = tables.get("name");
|
|
182
|
-
if (nameTable === void 0) throw new FontFaceError(`${source} declares no 'name' table, so the font family it provides cannot be determined`);
|
|
183
|
-
const name = tableView(bytes, nameTable);
|
|
184
|
-
const records = readNameRecords(name);
|
|
185
|
-
const family = readNameString(name, records, NAME_ID_TYPOGRAPHIC_FAMILY) ?? readNameString(name, records, NAME_ID_FAMILY);
|
|
186
|
-
if (family === void 0) throw new FontFaceError(`${source} declares no family name in its 'name' table, so the font family it provides cannot be determined`);
|
|
187
|
-
const { bold, italic } = readStyleBits(bytes, tables, source);
|
|
188
|
-
return {
|
|
189
|
-
family,
|
|
190
|
-
bold,
|
|
191
|
-
italic
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
//#endregion
|
|
195
46
|
//#region src/runtime/fonts.ts
|
|
196
47
|
async function loadProvidedFonts(paths, options) {
|
|
197
48
|
const fonts = [];
|
|
198
49
|
for (const path of paths) {
|
|
199
50
|
const bytes = new Uint8Array(await readFile(path, { signal: options?.signal }));
|
|
200
|
-
const face =
|
|
51
|
+
const face = readFontFace(bytes, path);
|
|
201
52
|
fonts.push({
|
|
202
53
|
family: face.family,
|
|
203
54
|
bold: face.bold,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as formatDocxExtrasLines, f as loadProvidedFonts, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, p as formatToExtension, r as formatOdbFormLines, t as describeOdbForm } from "./odb-structure-
|
|
1
|
+
import { c as formatDocxExtrasLines, f as loadProvidedFonts, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, p as formatToExtension, r as formatOdbFormLines, t as describeOdbForm } from "./odb-structure-CS2Eybob.js";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import {
|
|
3
|
+
import { bytesToBase64, createDocx, createOdg, createOdp, createOds, createOdt, createPdf, createPptx, decodeMarkdownText, docxToPdf, encodeMarkdownText, hsqldbCellDisplayText, markdownToPdf, odbReportToDocx, odbReportToOdt, odbReportToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openMarkdown, openOdg, openOdp, openOds, openOdt, openPdf, openPptx, parseXml, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, xlsxToPdf } from "documents.js";
|
|
4
4
|
import { basename, dirname, extname, join } from "node:path";
|
|
5
|
-
import { cellReference, columnIndexToLetters, decodePackage as decodePackage$1
|
|
5
|
+
import { cellReference, columnIndexToLetters, decodePackage as decodePackage$1 } from "odf.js";
|
|
6
6
|
import { readdirSync } from "node:fs";
|
|
7
7
|
import { Box, Text, render, useApp, useInput, useWindowSize } from "ink";
|
|
8
8
|
import { createContext, useContext, useEffect, useReducer, useState } from "react";
|
|
@@ -3808,40 +3808,13 @@ const REPORT_RENDER_TARGET_FORMATS = {
|
|
|
3808
3808
|
function isReportRenderTargetFormat(format) {
|
|
3809
3809
|
return format !== void 0 && format in REPORT_RENDER_TARGET_FORMATS;
|
|
3810
3810
|
}
|
|
3811
|
-
function renderReportBytes(content, format, fonts, options) {
|
|
3812
|
-
if (format === "docx") return encodePackage(buildDocxPackage(content));
|
|
3813
|
-
if (format === "odt") return encodePackage$1(buildOdtPackage(content));
|
|
3814
|
-
if (content.kind !== "wordprocessing") throw new Error("readOdbReportContent returned a non-wordprocessing ContentDocument");
|
|
3815
|
-
const registry = createFontRegistry({
|
|
3816
|
-
fonts,
|
|
3817
|
-
onSubstitution: (substitution) => {
|
|
3818
|
-
const requested = `${substitution.requestedFamily}${substitution.requestedBold ? " bold" : ""}${substitution.requestedItalic ? " italic" : ""}`;
|
|
3819
|
-
options.onDiagnostic({
|
|
3820
|
-
severity: "info",
|
|
3821
|
-
message: `No "${requested}" face available; drew it in "${substitution.resolvedFamily}"`
|
|
3822
|
-
});
|
|
3823
|
-
}
|
|
3824
|
-
});
|
|
3825
|
-
const { document: layout, formulas } = convertWordprocessingToLayout(content, { measurer: createFontMeasurer(registry) });
|
|
3826
|
-
return writePdf(layout, {
|
|
3827
|
-
signal: options.signal,
|
|
3828
|
-
onSubstitution: (substitution, context) => {
|
|
3829
|
-
options.onDiagnostic({
|
|
3830
|
-
severity: "info",
|
|
3831
|
-
message: `Substituted "${substitution.to}" for "${substitution.from}"`,
|
|
3832
|
-
pageIndex: context.pageIndex
|
|
3833
|
-
});
|
|
3834
|
-
},
|
|
3835
|
-
formulas,
|
|
3836
|
-
fonts: registry
|
|
3837
|
-
});
|
|
3838
|
-
}
|
|
3839
3811
|
async function renderOdbReportTo(doc, destinationPath, options) {
|
|
3840
3812
|
const format = detectFormat(destinationPath);
|
|
3841
3813
|
if (!isReportRenderTargetFormat(format)) throw new Error(`Cannot tell whether to render "${options.reportName}" as docx, odt, or pdf from '${destinationPath}' -- give the destination one of those three extensions`);
|
|
3842
3814
|
const fonts = await loadProvidedFonts(options.fontFiles ?? [], { signal: options.signal });
|
|
3843
3815
|
const pkg = decodePackage$1(new Uint8Array(await readFile(doc.path)));
|
|
3844
|
-
const
|
|
3816
|
+
const content = readOdbReportContent(pkg, { report: options.reportName });
|
|
3817
|
+
const bytes = format === "docx" ? odbReportToDocx(content) : format === "odt" ? odbReportToOdt(content) : odbReportToPdf(content, toPdfOptions(options, fonts));
|
|
3845
3818
|
await writeFile(destinationPath, bytes);
|
|
3846
3819
|
}
|
|
3847
3820
|
//#endregion
|