@json-to-office/core-docx 7.5.1 → 7.6.4
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/core/fontEmbedding.d.ts +39 -0
- package/dist/core/fontEmbedding.d.ts.map +1 -0
- package/dist/core/fontResolution.d.ts +13 -9
- package/dist/core/fontResolution.d.ts.map +1 -1
- package/dist/core/generateFromIr.d.ts +8 -1
- package/dist/core/generateFromIr.d.ts.map +1 -1
- package/dist/core/generationContext.d.ts.map +1 -1
- package/dist/index.js +225 -68
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +213 -56
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/renderers/docxjs/index.d.ts +3 -1
- package/dist/renderers/docxjs/index.d.ts.map +1 -1
- package/dist/renderers/types.d.ts +11 -1
- package/dist/renderers/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/packageDocument.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `embed` export mode's share of the DOCX pipeline: whether this render
|
|
3
|
+
* embeds at all, which faces it embeds, and the one summary warning.
|
|
4
|
+
*
|
|
5
|
+
* Face selection itself — slots, formats, licence bits — lives in
|
|
6
|
+
* `@json-to-office/shared/fonts/node` (`toEmbeddedFontFaces`), beside the
|
|
7
|
+
* other encoders of resolved fonts. What stays here is what only the DOCX
|
|
8
|
+
* pipeline knows: which renderer will write the package, and what the
|
|
9
|
+
* document references, which is what the summary has to answer for.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here imports `docx`: the faces travel to the adapter as a render
|
|
12
|
+
* option (`DocxRenderOptions.embeddedFonts`), and only the docx.js adapter
|
|
13
|
+
* reads it.
|
|
14
|
+
*/
|
|
15
|
+
import type { EmbeddedFontFace, FontRuntimeOpts, GenerationWarning, ResolvedFont } from '@json-to-office/shared';
|
|
16
|
+
import { type DocxRendererId } from '../renderers/types';
|
|
17
|
+
/**
|
|
18
|
+
* Whether this render embeds fonts: `embed` was asked for, and the renderer
|
|
19
|
+
* that will write the package can do it.
|
|
20
|
+
*
|
|
21
|
+
* `office-open` cannot yet. Its published docx embedding names the part after
|
|
22
|
+
* the family, which is the defect docx.js fixed in 9.7.0, writes the regular
|
|
23
|
+
* face only and leaves `embedTrueTypeFonts` off, so a request for it falls
|
|
24
|
+
* back to `custom` — references kept, nothing embedded — and says so rather
|
|
25
|
+
* than shipping a package Word repairs or drops the fonts from on re-save.
|
|
26
|
+
*/
|
|
27
|
+
export declare function embedsFonts(fonts: FontRuntimeOpts | undefined, renderer: DocxRendererId | undefined, warnings: GenerationWarning[]): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The faces to embed, with one `FONT_MODE_EMBED` summary for the document.
|
|
30
|
+
*
|
|
31
|
+
* The summary walks the resolved fonts rather than the report alone: the
|
|
32
|
+
* resolver hands back one entry per family the document and its theme
|
|
33
|
+
* reference — the same set `FONT_MODE_CUSTOM` is gated on — so a non-safe
|
|
34
|
+
* family that resolved to nothing still gets its line, instead of vanishing
|
|
35
|
+
* from a message that claims to account for the document's fonts. A document
|
|
36
|
+
* that references only safe fonts gets no summary, as in custom mode.
|
|
37
|
+
*/
|
|
38
|
+
export declare function selectEmbeddedFonts(resolved: readonly ResolvedFont[], warnings: GenerationWarning[]): EmbeddedFontFace[];
|
|
39
|
+
//# sourceMappingURL=fontEmbedding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fontEmbedding.d.ts","sourceRoot":"","sources":["../../src/core/fontEmbedding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACb,MAAM,wBAAwB,CAAC;AAMhC,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAY5B;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,eAAe,GAAG,SAAS,EAClC,QAAQ,EAAE,cAAc,GAAG,SAAS,EACpC,QAAQ,EAAE,iBAAiB,EAAE,GAC5B,OAAO,CAaT;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,QAAQ,EAAE,iBAAiB,EAAE,GAC5B,gBAAgB,EAAE,CAKpB"}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Font resolution for a DOCX render: validation, SAFE_FONTS awareness, Google
|
|
3
|
+
* Fonts materialization, and the `onResolved` side-channel consumed by the
|
|
4
|
+
* LibreOffice preview font stager.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* validation, SAFE_FONTS awareness, Google Fonts materialization, and the
|
|
9
|
-
* `onResolved` side-channel consumed by the LibreOffice preview font stager.
|
|
6
|
+
* One call site, `compileDocumentScoped` in `generateFromIr.ts`, which both
|
|
7
|
+
* public entry paths — `generator.ts` and the plugin-aware
|
|
8
|
+
* `plugin/createDocumentGenerator.ts` — reach, so they cannot disagree about
|
|
9
|
+
* any of the above.
|
|
10
10
|
*
|
|
11
11
|
* Materialization has two triggers: an `onResolved` listener, or the
|
|
12
12
|
* caller's `forceMaterialize` flag (set when the document contains a
|
|
13
13
|
* `visual`, whose PNG is produced by an out-of-process LibreOffice that
|
|
14
|
-
* needs real font files
|
|
15
|
-
*
|
|
14
|
+
* needs real font files, a `highcharts`, whose export server needs them
|
|
15
|
+
* likewise, or when `embed` mode will write them into the package). The
|
|
16
|
+
* resolved fonts are returned so the caller can forward them to whichever
|
|
17
|
+
* of those needs them.
|
|
16
18
|
*/
|
|
17
19
|
import type { FontRuntimeOpts, ResolvedFont, GenerationWarning } from '@json-to-office/shared';
|
|
18
20
|
import type { ThemeConfig } from '../styles';
|
|
@@ -24,6 +26,8 @@ export declare function resolveDocumentFonts(document: ReportComponentDefinition
|
|
|
24
26
|
* whose PNG is rendered by an out-of-process LibreOffice that needs the
|
|
25
27
|
* actual font files — there is no listener on the plain CLI path, so
|
|
26
28
|
* without this a visual-bearing build silently renders with fallbacks.
|
|
29
|
+
* `embed` mode sets it for the same reason: without it there would be
|
|
30
|
+
* nothing to embed.
|
|
27
31
|
*/
|
|
28
32
|
forceMaterialize?: boolean): Promise<ResolvedFont[]>;
|
|
29
33
|
//# sourceMappingURL=fontResolution.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontResolution.d.ts","sourceRoot":"","sources":["../../src/core/fontResolution.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fontResolution.d.ts","sourceRoot":"","sources":["../../src/core/fontResolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAehC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAE1D,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,yBAAyB,EACnC,KAAK,EAAE,WAAW,EAClB,KAAK,CAAC,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,iBAAiB,EAAE;AAC9B;;;;;;;;GAQG;AACH,gBAAgB,UAAQ,GACvB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyFzB"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
/// <reference types="node" />
|
|
16
16
|
/// <reference types="node" />
|
|
17
17
|
import type { GenerationWarning, ServicesConfig } from '@json-to-office/shared';
|
|
18
|
-
import type { FontRuntimeOpts } from '@json-to-office/shared';
|
|
18
|
+
import type { EmbeddedFontFace, FontRuntimeOpts } from '@json-to-office/shared';
|
|
19
19
|
import { compileDocument, type UnsupportedComponent } from '../ir/compiler';
|
|
20
20
|
import type { DocxIR } from '../ir/types';
|
|
21
21
|
import type { DocxRendererId } from '../renderers/types';
|
|
@@ -76,6 +76,13 @@ export interface CompiledDocx {
|
|
|
76
76
|
warnings: GenerationWarning[];
|
|
77
77
|
required: ReturnType<typeof compileDocument>['required'];
|
|
78
78
|
unsupported: UnsupportedComponent[];
|
|
79
|
+
/**
|
|
80
|
+
* The font faces `embed` mode writes into the package; empty in every other
|
|
81
|
+
* mode. Kept beside the IR rather than in it: they are a resource of this
|
|
82
|
+
* render, chosen for the renderer that will write it, not something the
|
|
83
|
+
* document says, and the IR stays the same in every mode.
|
|
84
|
+
*/
|
|
85
|
+
embeddedFonts: EmbeddedFontFace[];
|
|
79
86
|
}
|
|
80
87
|
/**
|
|
81
88
|
* Compile a report definition to DocxIR without rendering it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFromIr.d.ts","sourceRoot":"","sources":["../../src/core/generateFromIr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;;;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateFromIr.d.ts","sourceRoot":"","sources":["../../src/core/generateFromIr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;;;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAWhF,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAKlE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,iEAAiE;IACjE,QAAQ,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,SAAgB,IAAI,0BAA0B;IAC9C,SAAgB,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;gBAEhD,UAAU,EAAE,SAAS,oBAAoB,EAAE;CAiBxD;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,QAAQ,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,UAAU,CAAC,CAAC;IACzD,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC;;;;;OAKG;IACH,aAAa,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,yBAAyB,EACnC,OAAO,GAAE,uBAA4B,EACrC,SAAS,CAAC,EAAE,iBAAiB,EAAE,GAC9B,OAAO,CAAC,YAAY,CAAC,CAOvB;AAsHD,0EAA0E;AAC1E,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,yBAAyB,EACnC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAcjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generationContext.d.ts","sourceRoot":"","sources":["../../src/core/generationContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAMhC,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;KAAE,CAAC;IAC9C,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACzC,QAAQ,EAAE,OAAO,KACd,WAAW,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,EAAE,yBAAyB,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAoBD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,yBAAyB,EACrC,OAAO,GAAE,mBAAwB,GAChC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"generationContext.d.ts","sourceRoot":"","sources":["../../src/core/generationContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAMhC,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;KAAE,CAAC;IAC9C,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACzC,QAAQ,EAAE,OAAO,KACd,WAAW,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,EAAE,yBAAyB,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC;IACnB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAoBD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,yBAAyB,EACrC,OAAO,GAAE,mBAAwB,GAChC,sBAAsB,CAgExB"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,46 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// src/utils/generationContext.ts
|
|
18
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
19
|
+
import { isAbsolute, resolve } from "path";
|
|
20
|
+
function runWithBaseDir(baseDir, callback) {
|
|
21
|
+
return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
|
|
22
|
+
}
|
|
23
|
+
function getBaseDir() {
|
|
24
|
+
return baseDirStorage.getStore();
|
|
25
|
+
}
|
|
26
|
+
function resolveFromBaseDir(filePath) {
|
|
27
|
+
const base = baseDirStorage.getStore();
|
|
28
|
+
if (!base || isAbsolute(filePath)) return filePath;
|
|
29
|
+
return resolve(base, filePath);
|
|
30
|
+
}
|
|
31
|
+
function runWithWarnings(warnings, callback) {
|
|
32
|
+
return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
|
|
33
|
+
}
|
|
34
|
+
function reportWarning(component, code, message, context) {
|
|
35
|
+
const warnings = warningsStorage.getStore();
|
|
36
|
+
if (warnings) {
|
|
37
|
+
warnings.push({
|
|
38
|
+
component,
|
|
39
|
+
message,
|
|
40
|
+
severity: "warning",
|
|
41
|
+
context: { code, ...context }
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
console.warn(`[json-to-docx] [${code}] ${message}`);
|
|
46
|
+
}
|
|
47
|
+
var generationDateStorage, baseDirStorage, warningsStorage;
|
|
48
|
+
var init_generationContext = __esm({
|
|
49
|
+
"src/utils/generationContext.ts"() {
|
|
50
|
+
"use strict";
|
|
51
|
+
generationDateStorage = new AsyncLocalStorage();
|
|
52
|
+
baseDirStorage = new AsyncLocalStorage();
|
|
53
|
+
warningsStorage = new AsyncLocalStorage();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
17
57
|
// src/themes/defaults.ts
|
|
18
58
|
import { designColors } from "@json-to-office/shared";
|
|
19
59
|
function ensureThemeDefaults(theme) {
|
|
@@ -2447,43 +2487,6 @@ var init_widthUtils = __esm({
|
|
|
2447
2487
|
}
|
|
2448
2488
|
});
|
|
2449
2489
|
|
|
2450
|
-
// src/utils/generationContext.ts
|
|
2451
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
2452
|
-
import { isAbsolute, resolve } from "path";
|
|
2453
|
-
function runWithBaseDir(baseDir, callback) {
|
|
2454
|
-
return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
|
|
2455
|
-
}
|
|
2456
|
-
function resolveFromBaseDir(filePath) {
|
|
2457
|
-
const base = baseDirStorage.getStore();
|
|
2458
|
-
if (!base || isAbsolute(filePath)) return filePath;
|
|
2459
|
-
return resolve(base, filePath);
|
|
2460
|
-
}
|
|
2461
|
-
function runWithWarnings(warnings, callback) {
|
|
2462
|
-
return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
|
|
2463
|
-
}
|
|
2464
|
-
function reportWarning(component, code, message, context) {
|
|
2465
|
-
const warnings = warningsStorage.getStore();
|
|
2466
|
-
if (warnings) {
|
|
2467
|
-
warnings.push({
|
|
2468
|
-
component,
|
|
2469
|
-
message,
|
|
2470
|
-
severity: "warning",
|
|
2471
|
-
context: { code, ...context }
|
|
2472
|
-
});
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
2475
|
-
console.warn(`[json-to-docx] [${code}] ${message}`);
|
|
2476
|
-
}
|
|
2477
|
-
var generationDateStorage, baseDirStorage, warningsStorage;
|
|
2478
|
-
var init_generationContext = __esm({
|
|
2479
|
-
"src/utils/generationContext.ts"() {
|
|
2480
|
-
"use strict";
|
|
2481
|
-
generationDateStorage = new AsyncLocalStorage();
|
|
2482
|
-
baseDirStorage = new AsyncLocalStorage();
|
|
2483
|
-
warningsStorage = new AsyncLocalStorage();
|
|
2484
|
-
}
|
|
2485
|
-
});
|
|
2486
|
-
|
|
2487
2490
|
// src/utils/imageUtils.ts
|
|
2488
2491
|
import { readFileSync } from "fs";
|
|
2489
2492
|
import { availableParallelism } from "os";
|
|
@@ -4265,6 +4268,8 @@ var init_normalizeTextCase = __esm({
|
|
|
4265
4268
|
|
|
4266
4269
|
// src/utils/packageDocument.ts
|
|
4267
4270
|
import AdmZip from "adm-zip";
|
|
4271
|
+
import { createHash as createHash3 } from "crypto";
|
|
4272
|
+
import { posix } from "path";
|
|
4268
4273
|
function resolveGenerationDate(options) {
|
|
4269
4274
|
if (options?.generatedAt !== void 0) {
|
|
4270
4275
|
const date = new Date(options.generatedAt);
|
|
@@ -4332,6 +4337,70 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
4332
4337
|
if (entry) zip.updateFile(entry, Buffer.from(update.xml, "utf8"));
|
|
4333
4338
|
}
|
|
4334
4339
|
}
|
|
4340
|
+
function xorFontKey(bytes, guid) {
|
|
4341
|
+
const key = Buffer.from(guid.replace(/-/g, ""), "hex").reverse();
|
|
4342
|
+
const out = Buffer.from(bytes);
|
|
4343
|
+
for (let i = 0; i < Math.min(32, out.length); i++) out[i] ^= key[i % 16];
|
|
4344
|
+
return out;
|
|
4345
|
+
}
|
|
4346
|
+
function canonicalizeEmbeddedFontKeys(zip) {
|
|
4347
|
+
const table2 = zip.getEntry("word/fontTable.xml");
|
|
4348
|
+
if (!table2) return;
|
|
4349
|
+
const xml = table2.getData().toString("utf8");
|
|
4350
|
+
const embeds = [...xml.matchAll(FONT_EMBED)].flatMap(([element]) => {
|
|
4351
|
+
const id = /\br:id="([^"]+)"/.exec(element)?.[1];
|
|
4352
|
+
const key = /\bw:fontKey="\{([0-9A-Fa-f-]{36})\}"/.exec(element)?.[1];
|
|
4353
|
+
return id && key ? [{ id, key }] : [];
|
|
4354
|
+
});
|
|
4355
|
+
if (embeds.length === 0) return;
|
|
4356
|
+
const rels = zip.getEntry("word/_rels/fontTable.xml.rels")?.getData().toString("utf8") ?? "";
|
|
4357
|
+
const targets = /* @__PURE__ */ new Map();
|
|
4358
|
+
for (const [relationship] of rels.matchAll(/<Relationship\b[^>]*>/g)) {
|
|
4359
|
+
const id = /\bId="([^"]+)"/.exec(relationship)?.[1];
|
|
4360
|
+
const target = /\bTarget="([^"]+)"/.exec(relationship)?.[1];
|
|
4361
|
+
if (id && target) targets.set(id, target);
|
|
4362
|
+
}
|
|
4363
|
+
const rekey = /* @__PURE__ */ new Map();
|
|
4364
|
+
const parts = [];
|
|
4365
|
+
for (const { id, key } of embeds) {
|
|
4366
|
+
const target = targets.get(id);
|
|
4367
|
+
if (!target) continue;
|
|
4368
|
+
const name = target.startsWith("/") ? target.slice(1) : posix.normalize(posix.join("word", target));
|
|
4369
|
+
const part = zip.getEntry(name);
|
|
4370
|
+
if (!part) continue;
|
|
4371
|
+
const font = xorFontKey(part.getData(), key);
|
|
4372
|
+
const hex = createHash3("sha256").update(font).digest("hex").slice(0, 32).toUpperCase();
|
|
4373
|
+
const fresh = [
|
|
4374
|
+
hex.slice(0, 8),
|
|
4375
|
+
hex.slice(8, 12),
|
|
4376
|
+
hex.slice(12, 16),
|
|
4377
|
+
hex.slice(16, 20),
|
|
4378
|
+
hex.slice(20)
|
|
4379
|
+
].join("-");
|
|
4380
|
+
rekey.set(key.toUpperCase(), fresh);
|
|
4381
|
+
parts.push({ name, data: xorFontKey(font, fresh) });
|
|
4382
|
+
}
|
|
4383
|
+
if (rekey.size === 0) return;
|
|
4384
|
+
for (const { name, data } of parts) {
|
|
4385
|
+
const entry = zip.getEntry(name);
|
|
4386
|
+
if (entry) zip.updateFile(entry, data);
|
|
4387
|
+
}
|
|
4388
|
+
const fontTable = zip.getEntry("word/fontTable.xml");
|
|
4389
|
+
if (!fontTable) return;
|
|
4390
|
+
zip.updateFile(
|
|
4391
|
+
fontTable,
|
|
4392
|
+
Buffer.from(
|
|
4393
|
+
xml.replace(
|
|
4394
|
+
/\bw:fontKey="\{([0-9A-Fa-f-]{36})\}"/g,
|
|
4395
|
+
(whole, key) => {
|
|
4396
|
+
const fresh = rekey.get(key.toUpperCase());
|
|
4397
|
+
return fresh ? `w:fontKey="{${fresh}}"` : whole;
|
|
4398
|
+
}
|
|
4399
|
+
),
|
|
4400
|
+
"utf8"
|
|
4401
|
+
)
|
|
4402
|
+
);
|
|
4403
|
+
}
|
|
4335
4404
|
function canonicalizeEmbeddedPackages(zip, generatedAt, depth = 1) {
|
|
4336
4405
|
const names = zip.getEntries().map((entry) => entry.entryName).filter((name) => EMBEDDED_OFFICE_PACKAGE.test(name));
|
|
4337
4406
|
let changed = false;
|
|
@@ -4384,6 +4453,7 @@ function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
|
|
|
4384
4453
|
normalizeTextCase(zip);
|
|
4385
4454
|
canonicalizeRelationshipIds(zip);
|
|
4386
4455
|
canonicalizeEmbeddedPackages(zip, generatedAt);
|
|
4456
|
+
canonicalizeEmbeddedFontKeys(zip);
|
|
4387
4457
|
const isoTimestamp = generatedAt.toISOString();
|
|
4388
4458
|
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
4389
4459
|
if (coreProperties3) {
|
|
@@ -4400,13 +4470,14 @@ function normalizeDocxCaseBuffer(buffer) {
|
|
|
4400
4470
|
const zip = new AdmZip(buffer);
|
|
4401
4471
|
return normalizeTextCase(zip) ? zip.toBuffer() : buffer;
|
|
4402
4472
|
}
|
|
4403
|
-
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID, CORE_TIMESTAMP, EMBEDDED_OFFICE_PACKAGE, MAX_EMBEDDED_DEPTH;
|
|
4473
|
+
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID, FONT_EMBED, CORE_TIMESTAMP, EMBEDDED_OFFICE_PACKAGE, MAX_EMBEDDED_DEPTH;
|
|
4404
4474
|
var init_packageDocument = __esm({
|
|
4405
4475
|
"src/utils/packageDocument.ts"() {
|
|
4406
4476
|
"use strict";
|
|
4407
4477
|
init_normalizeTextCase();
|
|
4408
4478
|
DEFAULT_GENERATION_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
|
|
4409
4479
|
STABLE_RELATIONSHIP_ID = /^rId\d+$/;
|
|
4480
|
+
FONT_EMBED = /<w:embed(?:Regular|Bold|Italic|BoldItalic)\b[^>]*>/g;
|
|
4410
4481
|
CORE_TIMESTAMP = /(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g;
|
|
4411
4482
|
EMBEDDED_OFFICE_PACKAGE = /\.(?:docx|pptx|xlsx|xlsm)$/i;
|
|
4412
4483
|
MAX_EMBEDDED_DEPTH = 3;
|
|
@@ -5007,7 +5078,12 @@ function createDocxJsRenderer() {
|
|
|
5007
5078
|
});
|
|
5008
5079
|
}
|
|
5009
5080
|
const pageNumbers = needsPageNumbers(ir) ? await createPageNumberEstimator(ir) : void 0;
|
|
5010
|
-
const document = buildDocument(
|
|
5081
|
+
const document = buildDocument(
|
|
5082
|
+
ir,
|
|
5083
|
+
resources,
|
|
5084
|
+
pageNumbers,
|
|
5085
|
+
renderOptions?.embeddedFonts
|
|
5086
|
+
);
|
|
5011
5087
|
const packed = await Packer.toBuffer(document);
|
|
5012
5088
|
const fixed = fixFloatingImageIdsInBuffer(packed);
|
|
5013
5089
|
const repaired = markers ? repairDrawingGroupsInBuffer(fixed, markers) : fixed;
|
|
@@ -5025,10 +5101,17 @@ function createDocxJsRenderer() {
|
|
|
5025
5101
|
}
|
|
5026
5102
|
};
|
|
5027
5103
|
}
|
|
5028
|
-
function buildDocument(ir, resources = /* @__PURE__ */ new Map(), pageNumbers) {
|
|
5104
|
+
function buildDocument(ir, resources = /* @__PURE__ */ new Map(), pageNumbers, embeddedFonts) {
|
|
5029
5105
|
return new Document({
|
|
5030
5106
|
...pageNumbers ? { pageNumbers } : {},
|
|
5031
5107
|
styles: emitStyles(ir.styles),
|
|
5108
|
+
// word/fonts/font<N>.odttf, their `w:embed*` entries in the font table and
|
|
5109
|
+
// `w:embedTrueTypeFonts` in the settings, all from this one key. Passed
|
|
5110
|
+
// only when a face embeds, so a document in any other mode is built from
|
|
5111
|
+
// exactly the options it always was. `docx/layout` measures the text of an
|
|
5112
|
+
// embedded family from these files, so a contents field's page numbers
|
|
5113
|
+
// need nothing more.
|
|
5114
|
+
...embeddedFonts && embeddedFonts.length > 0 ? { fonts: embeddedFonts.map(fontOptions) } : {},
|
|
5032
5115
|
...ir.theme ? { theme: themeOptions(ir.theme) } : {},
|
|
5033
5116
|
sections: ir.sections.map((section2) => sectionOptions(section2, resources)),
|
|
5034
5117
|
...coreProperties(ir),
|
|
@@ -5059,6 +5142,15 @@ function buildDocument(ir, resources = /* @__PURE__ */ new Map(), pageNumbers) {
|
|
|
5059
5142
|
} : {}
|
|
5060
5143
|
});
|
|
5061
5144
|
}
|
|
5145
|
+
function fontOptions(face) {
|
|
5146
|
+
return {
|
|
5147
|
+
name: face.family,
|
|
5148
|
+
data: face.regular,
|
|
5149
|
+
...face.bold ? { bold: face.bold } : {},
|
|
5150
|
+
...face.italic ? { italic: face.italic } : {},
|
|
5151
|
+
...face.boldItalic ? { boldItalic: face.boldItalic } : {}
|
|
5152
|
+
};
|
|
5153
|
+
}
|
|
5062
5154
|
function themeOptions(theme) {
|
|
5063
5155
|
const colors = {};
|
|
5064
5156
|
for (const [slot, color] of Object.entries(theme.colors)) {
|
|
@@ -6979,6 +7071,7 @@ import {
|
|
|
6979
7071
|
import { assertRendererSupports } from "@json-to-office/shared/rendering";
|
|
6980
7072
|
|
|
6981
7073
|
// src/core/fontResolution.ts
|
|
7074
|
+
init_generationContext();
|
|
6982
7075
|
import {
|
|
6983
7076
|
collectFontNamesFromDocx,
|
|
6984
7077
|
validateFontReferences,
|
|
@@ -7032,8 +7125,14 @@ async function resolveDocumentFonts(document, theme, fonts, warnings, forceMater
|
|
|
7032
7125
|
if (!fonts?.onResolved && !forceMaterialize) return [];
|
|
7033
7126
|
const registry2 = new FontRegistry({
|
|
7034
7127
|
// Spread keeps baseDir/googleFonts/mode/substitution intact for
|
|
7035
|
-
// materializeSource; extraEntries carries the merged registry.
|
|
7036
|
-
|
|
7128
|
+
// materializeSource; extraEntries carries the merged registry. Without a
|
|
7129
|
+
// `fonts.baseDir` of its own, kind:"file" sources resolve against the
|
|
7130
|
+
// render's baseDir, as images do — not against process.cwd().
|
|
7131
|
+
opts: {
|
|
7132
|
+
...fonts,
|
|
7133
|
+
baseDir: fonts?.baseDir ?? getBaseDir(),
|
|
7134
|
+
extraEntries: registryEntries
|
|
7135
|
+
},
|
|
7037
7136
|
fileLoader: loadFileFontSource,
|
|
7038
7137
|
variableLoader: fetchVariableFontSource,
|
|
7039
7138
|
diskCache: fonts?.googleFonts?.cacheDir ? new FontDiskCache(fonts.googleFonts.cacheDir) : void 0
|
|
@@ -7054,6 +7153,67 @@ import {
|
|
|
7054
7153
|
toRasterizeFontFaces
|
|
7055
7154
|
} from "@json-to-office/shared/fonts/node";
|
|
7056
7155
|
|
|
7156
|
+
// src/core/fontEmbedding.ts
|
|
7157
|
+
import { isSafeFont } from "@json-to-office/shared";
|
|
7158
|
+
import {
|
|
7159
|
+
toEmbeddedFontFaces
|
|
7160
|
+
} from "@json-to-office/shared/fonts/node";
|
|
7161
|
+
|
|
7162
|
+
// src/renderers/types.ts
|
|
7163
|
+
import {
|
|
7164
|
+
DEFAULT_DOCX_RENDERER_ID
|
|
7165
|
+
} from "@json-to-office/shared-docx";
|
|
7166
|
+
|
|
7167
|
+
// src/core/fontEmbedding.ts
|
|
7168
|
+
var EMBEDDING_RENDERER = "docxjs";
|
|
7169
|
+
var warning = (code, message) => ({
|
|
7170
|
+
component: "fontRegistry",
|
|
7171
|
+
message,
|
|
7172
|
+
severity: "warning",
|
|
7173
|
+
context: { code }
|
|
7174
|
+
});
|
|
7175
|
+
function embedsFonts(fonts, renderer, warnings) {
|
|
7176
|
+
if (fonts?.mode !== "embed") return false;
|
|
7177
|
+
const id = renderer ?? DEFAULT_DOCX_RENDERER_ID;
|
|
7178
|
+
if (id === EMBEDDING_RENDERER) return true;
|
|
7179
|
+
warnings.push(
|
|
7180
|
+
warning(
|
|
7181
|
+
"FONT_EMBED_UNSUPPORTED_RENDERER",
|
|
7182
|
+
`Export mode "embed" needs the ${EMBEDDING_RENDERER} renderer; the ${id} renderer does not embed fonts, so references are kept as in custom mode and nothing is embedded.`
|
|
7183
|
+
)
|
|
7184
|
+
);
|
|
7185
|
+
return false;
|
|
7186
|
+
}
|
|
7187
|
+
function selectEmbeddedFonts(resolved, warnings) {
|
|
7188
|
+
const { faces, report } = toEmbeddedFontFaces(resolved, warnings);
|
|
7189
|
+
const summary = embedSummary(resolved, report);
|
|
7190
|
+
if (summary) warnings.push(warning("FONT_MODE_EMBED", summary));
|
|
7191
|
+
return faces;
|
|
7192
|
+
}
|
|
7193
|
+
function embedSummary(resolved, report) {
|
|
7194
|
+
const byFamily = new Map(report.map((r) => [r.family.toLowerCase(), r]));
|
|
7195
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7196
|
+
const lines = [];
|
|
7197
|
+
for (const font of resolved) {
|
|
7198
|
+
const key = font.family.toLowerCase();
|
|
7199
|
+
if (isSafeFont(font.family.trim()) || seen.has(key)) continue;
|
|
7200
|
+
seen.add(key);
|
|
7201
|
+
const entry = byFamily.get(key);
|
|
7202
|
+
if (!entry) {
|
|
7203
|
+
lines.push(`${font.family}: not embedded (unresolved)`);
|
|
7204
|
+
} else if (entry.slots.length === 0) {
|
|
7205
|
+
lines.push(
|
|
7206
|
+
`${font.family}: not embedded (${entry.reason === "no-regular-face" ? "no regular face" : "no TTF/OTF face it may embed"})`
|
|
7207
|
+
);
|
|
7208
|
+
} else {
|
|
7209
|
+
const nearest = entry.nearest.length ? ` (${entry.nearest.map((n) => `${n.slot} \u2190 ${n.weight}`).join(", ")})` : "";
|
|
7210
|
+
lines.push(`${font.family}: ${entry.slots.join(", ")}${nearest}`);
|
|
7211
|
+
}
|
|
7212
|
+
}
|
|
7213
|
+
if (lines.length === 0) return void 0;
|
|
7214
|
+
return `Export mode "embed": ${lines.join("; ")}. Readers without these fonts installed see the embedded faces; any face or family not embedded stays a reference, as in custom mode.`;
|
|
7215
|
+
}
|
|
7216
|
+
|
|
7057
7217
|
// src/core/prerasterizeVisuals.ts
|
|
7058
7218
|
import {
|
|
7059
7219
|
clampVisualDpi,
|
|
@@ -7540,7 +7700,7 @@ function assertExportServerAllowed(serverUrl, servicesConfig, warnings) {
|
|
|
7540
7700
|
const notice = remoteExportNotice(serverUrl, servicesConfig?.allowRemote);
|
|
7541
7701
|
if (!notice || !warnings) return;
|
|
7542
7702
|
const alreadySaid = warnings.some(
|
|
7543
|
-
(
|
|
7703
|
+
(warning2) => warning2.context?.code === REMOTE_EXPORT_WARNING && warning2.context?.serverUrl === serverUrl
|
|
7544
7704
|
);
|
|
7545
7705
|
if (alreadySaid) return;
|
|
7546
7706
|
warnings.push({
|
|
@@ -13586,13 +13746,6 @@ function warnOnce(ctx, component, message, code) {
|
|
|
13586
13746
|
import {
|
|
13587
13747
|
RendererRegistry
|
|
13588
13748
|
} from "@json-to-office/shared/rendering";
|
|
13589
|
-
|
|
13590
|
-
// src/renderers/types.ts
|
|
13591
|
-
import {
|
|
13592
|
-
DEFAULT_DOCX_RENDERER_ID
|
|
13593
|
-
} from "@json-to-office/shared-docx";
|
|
13594
|
-
|
|
13595
|
-
// src/renderers/registry.ts
|
|
13596
13749
|
var registry = new RendererRegistry(
|
|
13597
13750
|
"docx",
|
|
13598
13751
|
DEFAULT_DOCX_RENDERER_ID
|
|
@@ -16240,13 +16393,15 @@ async function compileDocumentScoped(document, options, warnings) {
|
|
|
16240
16393
|
const { context } = prepared.model;
|
|
16241
16394
|
const hasVisual = collectVisualProps(context.document).length > 0;
|
|
16242
16395
|
const hasHighcharts = containsComponent(context.document, "highcharts");
|
|
16396
|
+
const embedding = embedsFonts(options.fonts, options.renderer, warnings);
|
|
16243
16397
|
const resolvedFonts = await resolveDocumentFonts(
|
|
16244
16398
|
context.document,
|
|
16245
16399
|
context.theme,
|
|
16246
16400
|
options.fonts,
|
|
16247
16401
|
warnings,
|
|
16248
|
-
hasVisual || hasHighcharts
|
|
16402
|
+
hasVisual || hasHighcharts || embedding
|
|
16249
16403
|
);
|
|
16404
|
+
const embeddedFonts = embedding ? selectEmbeddedFonts(resolvedFonts, warnings) : [];
|
|
16250
16405
|
const visualFonts = hasVisual ? toRasterizeFontFaces(resolvedFonts, warnings) : [];
|
|
16251
16406
|
const chartFonts = hasHighcharts ? toChartFontFaces(resolvedFonts) : [];
|
|
16252
16407
|
const desugared = await desugarExternals(context.document, {
|
|
@@ -16286,7 +16441,8 @@ async function compileDocumentScoped(document, options, warnings) {
|
|
|
16286
16441
|
theme: context.theme,
|
|
16287
16442
|
warnings: compiled.warnings,
|
|
16288
16443
|
required: compiled.required,
|
|
16289
|
-
unsupported: compiled.unsupported
|
|
16444
|
+
unsupported: compiled.unsupported,
|
|
16445
|
+
embeddedFonts
|
|
16290
16446
|
};
|
|
16291
16447
|
}
|
|
16292
16448
|
async function generateBufferViaIr(document, options = {}) {
|
|
@@ -16310,6 +16466,7 @@ async function renderScoped(document, options, warnings) {
|
|
|
16310
16466
|
...options.deterministic !== void 0 ? { deterministic: options.deterministic } : {},
|
|
16311
16467
|
...options.generatedAt !== void 0 ? { generatedAt: toDate(options.generatedAt) } : {},
|
|
16312
16468
|
...options.svgRasterFallback !== void 0 ? { svgRasterFallback: options.svgRasterFallback } : {},
|
|
16469
|
+
...compiled.embeddedFonts.length > 0 ? { embeddedFonts: compiled.embeddedFonts } : {},
|
|
16313
16470
|
warnings: compiled.warnings
|
|
16314
16471
|
});
|
|
16315
16472
|
return { buffer: Buffer.from(bytes), warnings: compiled.warnings };
|
|
@@ -17815,10 +17972,10 @@ function generateWarningsDocument(warnings) {
|
|
|
17815
17972
|
}
|
|
17816
17973
|
];
|
|
17817
17974
|
const warningsByComponent = /* @__PURE__ */ new Map();
|
|
17818
|
-
for (const
|
|
17819
|
-
const existing = warningsByComponent.get(
|
|
17820
|
-
existing.push(
|
|
17821
|
-
warningsByComponent.set(
|
|
17975
|
+
for (const warning2 of warnings) {
|
|
17976
|
+
const existing = warningsByComponent.get(warning2.component) || [];
|
|
17977
|
+
existing.push(warning2);
|
|
17978
|
+
warningsByComponent.set(warning2.component, existing);
|
|
17822
17979
|
}
|
|
17823
17980
|
for (const [
|
|
17824
17981
|
componentName,
|
|
@@ -17832,10 +17989,10 @@ function generateWarningsDocument(warnings) {
|
|
|
17832
17989
|
}
|
|
17833
17990
|
});
|
|
17834
17991
|
const warningItems = [];
|
|
17835
|
-
for (const
|
|
17836
|
-
let warningText =
|
|
17837
|
-
if (
|
|
17838
|
-
const contextStr = Object.entries(
|
|
17992
|
+
for (const warning2 of componentWarnings) {
|
|
17993
|
+
let warningText = warning2.message;
|
|
17994
|
+
if (warning2.context && Object.keys(warning2.context).length > 0) {
|
|
17995
|
+
const contextStr = Object.entries(warning2.context).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(", ");
|
|
17839
17996
|
warningText += ` (${contextStr})`;
|
|
17840
17997
|
}
|
|
17841
17998
|
warningItems.push(warningText);
|
|
@@ -17871,10 +18028,10 @@ function formatWarningsText(warnings) {
|
|
|
17871
18028
|
""
|
|
17872
18029
|
];
|
|
17873
18030
|
const warningsByComponent = /* @__PURE__ */ new Map();
|
|
17874
|
-
for (const
|
|
17875
|
-
const existing = warningsByComponent.get(
|
|
17876
|
-
existing.push(
|
|
17877
|
-
warningsByComponent.set(
|
|
18031
|
+
for (const warning2 of warnings) {
|
|
18032
|
+
const existing = warningsByComponent.get(warning2.component) || [];
|
|
18033
|
+
existing.push(warning2);
|
|
18034
|
+
warningsByComponent.set(warning2.component, existing);
|
|
17878
18035
|
}
|
|
17879
18036
|
for (const [
|
|
17880
18037
|
componentName,
|
|
@@ -17883,10 +18040,10 @@ function formatWarningsText(warnings) {
|
|
|
17883
18040
|
lines.push(`Component: ${componentName}`);
|
|
17884
18041
|
lines.push("-".repeat(30));
|
|
17885
18042
|
for (let i = 0; i < componentWarnings.length; i++) {
|
|
17886
|
-
const
|
|
17887
|
-
lines.push(` ${i + 1}. ${
|
|
17888
|
-
if (
|
|
17889
|
-
lines.push(` Context: ${JSON.stringify(
|
|
18043
|
+
const warning2 = componentWarnings[i];
|
|
18044
|
+
lines.push(` ${i + 1}. ${warning2.message}`);
|
|
18045
|
+
if (warning2.context && Object.keys(warning2.context).length > 0) {
|
|
18046
|
+
lines.push(` Context: ${JSON.stringify(warning2.context, null, 2)}`);
|
|
17890
18047
|
}
|
|
17891
18048
|
}
|
|
17892
18049
|
lines.push("");
|