@json-to-office/jto-ops 6.8.0 → 7.0.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/index.d.ts +197 -7
- package/dist/index.js +628 -81
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1061,6 +1061,7 @@ var DocxFormatAdapter = class {
|
|
|
1061
1061
|
options.services
|
|
1062
1062
|
);
|
|
1063
1063
|
const prepared = !hasPlugins && options.prepared?.format === "docx" ? options.prepared : void 0;
|
|
1064
|
+
const pluginPrepared = hasPlugins && options.prepared?.format === "docx" ? options.prepared : void 0;
|
|
1064
1065
|
const resolved = prepared ? void 0 : await this.resolveThemes(options);
|
|
1065
1066
|
const requestedTheme = resolved?.requested;
|
|
1066
1067
|
const customThemes = resolved?.customThemes;
|
|
@@ -1136,6 +1137,7 @@ var DocxFormatAdapter = class {
|
|
|
1136
1137
|
requestedTheme,
|
|
1137
1138
|
customThemes
|
|
1138
1139
|
);
|
|
1140
|
+
const usable = preparedFor(pluginPrepared, parsed);
|
|
1139
1141
|
const result = await generator.generateBuffer(docDefinition, {
|
|
1140
1142
|
validation: {
|
|
1141
1143
|
allowUnknownFields: options.validation?.allowUnknownFields
|
|
@@ -1144,10 +1146,12 @@ var DocxFormatAdapter = class {
|
|
|
1144
1146
|
generatedAt: options.generatedAt,
|
|
1145
1147
|
baseDir: options.baseDir,
|
|
1146
1148
|
renderer: options.renderer,
|
|
1147
|
-
svgRasterFallback: options.svgRasterFallback
|
|
1149
|
+
svgRasterFallback: options.svgRasterFallback,
|
|
1150
|
+
...usable && { prepared: usable }
|
|
1148
1151
|
});
|
|
1149
|
-
|
|
1150
|
-
|
|
1152
|
+
const emitted = withoutPreparedWarnings(result.warnings ?? [], usable);
|
|
1153
|
+
emitGenerationWarnings(emitted);
|
|
1154
|
+
options.warnings?.push(...toGenerationWarnings(emitted));
|
|
1151
1155
|
return result.buffer;
|
|
1152
1156
|
},
|
|
1153
1157
|
getStandardDefinition: generator.expandStandardDefinition ? async (config) => {
|
|
@@ -1230,15 +1234,35 @@ var DocxFormatAdapter = class {
|
|
|
1230
1234
|
resolved.requested,
|
|
1231
1235
|
resolved.customThemes
|
|
1232
1236
|
);
|
|
1233
|
-
const prepared =
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
customThemes:
|
|
1237
|
+
const prepared = options.plugins && options.plugins.length > 0 ? await (async () => {
|
|
1238
|
+
let generator = core.createDocumentGenerator({
|
|
1239
|
+
theme: resolved.requested,
|
|
1240
|
+
customThemes: resolved.requested ? {
|
|
1241
|
+
...resolved.customThemes,
|
|
1242
|
+
[CLI_THEME_KEY]: resolved.requested
|
|
1243
|
+
} : resolved.customThemes,
|
|
1244
|
+
services: withRequestedServices(
|
|
1245
|
+
buildDocxServices(),
|
|
1246
|
+
options.services
|
|
1247
|
+
),
|
|
1248
|
+
baseDir: options.baseDir,
|
|
1237
1249
|
fonts: options.fonts,
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1250
|
+
validation: {
|
|
1251
|
+
allowUnknownFields: options.validation?.allowUnknownFields
|
|
1252
|
+
},
|
|
1253
|
+
renderer: options.renderer
|
|
1254
|
+
});
|
|
1255
|
+
for (const plugin of options.plugins)
|
|
1256
|
+
generator = generator.addComponent(plugin);
|
|
1257
|
+
const result = await generator.prepareQuality(normalized.document);
|
|
1258
|
+
warnings.push(...result.warnings ?? []);
|
|
1259
|
+
return result.prepared;
|
|
1260
|
+
})() : core.prepareDocxQualityDocument(normalized.document, {
|
|
1261
|
+
customThemes: normalized.customThemes,
|
|
1262
|
+
fonts: options.fonts,
|
|
1263
|
+
renderer: options.renderer ?? documentRenderer(parsed),
|
|
1264
|
+
warnings
|
|
1265
|
+
});
|
|
1242
1266
|
return stampPrepared(
|
|
1243
1267
|
{
|
|
1244
1268
|
...prepared,
|
|
@@ -1269,7 +1293,7 @@ var DocxFormatAdapter = class {
|
|
|
1269
1293
|
async resolveTheme(options) {
|
|
1270
1294
|
const core = await import("@json-to-office/core-docx");
|
|
1271
1295
|
const { requested } = await this.resolveThemes(options);
|
|
1272
|
-
return requested ?? core.themes?.
|
|
1296
|
+
return requested ?? core.themes?.consulting ?? {};
|
|
1273
1297
|
}
|
|
1274
1298
|
/**
|
|
1275
1299
|
* Resolve `theme`/`themePath` once for a whole run: `themePath` is read a
|
|
@@ -1430,6 +1454,7 @@ var PptxFormatAdapter = class {
|
|
|
1430
1454
|
options.services
|
|
1431
1455
|
);
|
|
1432
1456
|
const prepared = !hasPlugins && options.prepared?.format === "pptx" ? options.prepared : void 0;
|
|
1457
|
+
const pluginPrepared = hasPlugins && options.prepared?.format === "pptx" ? options.prepared : void 0;
|
|
1433
1458
|
const resolved = prepared ? void 0 : await this.resolveThemes(options);
|
|
1434
1459
|
const requestedTheme = resolved?.requested;
|
|
1435
1460
|
const customThemes = resolved?.customThemes;
|
|
@@ -1504,6 +1529,7 @@ var PptxFormatAdapter = class {
|
|
|
1504
1529
|
requestedTheme,
|
|
1505
1530
|
customThemes
|
|
1506
1531
|
);
|
|
1532
|
+
const usable = preparedFor(pluginPrepared, parsed);
|
|
1507
1533
|
const result = await generator.generateBuffer(docDefinition, {
|
|
1508
1534
|
validation: {
|
|
1509
1535
|
allowUnknownFields: options.validation?.allowUnknownFields
|
|
@@ -1511,9 +1537,13 @@ var PptxFormatAdapter = class {
|
|
|
1511
1537
|
deterministic: options.deterministic,
|
|
1512
1538
|
generatedAt: options.generatedAt,
|
|
1513
1539
|
baseDir: options.baseDir,
|
|
1514
|
-
renderer: options.renderer
|
|
1540
|
+
renderer: options.renderer,
|
|
1541
|
+
...usable && { prepared: usable }
|
|
1515
1542
|
});
|
|
1516
|
-
const normalized =
|
|
1543
|
+
const normalized = withoutPreparedWarnings(
|
|
1544
|
+
toGenerationWarnings(result.warnings),
|
|
1545
|
+
usable
|
|
1546
|
+
);
|
|
1517
1547
|
emitGenerationWarnings(normalized);
|
|
1518
1548
|
options.warnings?.push(...normalized);
|
|
1519
1549
|
return result.buffer;
|
|
@@ -1580,19 +1610,37 @@ var PptxFormatAdapter = class {
|
|
|
1580
1610
|
resolved.requested,
|
|
1581
1611
|
resolved.customThemes
|
|
1582
1612
|
);
|
|
1583
|
-
const
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
customThemes: normalized.customThemes,
|
|
1587
|
-
fonts: options.fonts,
|
|
1588
|
-
services: withRequestedServices(
|
|
1589
|
-
buildServicesFromEnv(),
|
|
1590
|
-
options.services
|
|
1591
|
-
),
|
|
1592
|
-
renderer: options.renderer ?? documentRenderer(parsed),
|
|
1593
|
-
warnings
|
|
1594
|
-
}
|
|
1613
|
+
const services = withRequestedServices(
|
|
1614
|
+
buildServicesFromEnv(),
|
|
1615
|
+
options.services
|
|
1595
1616
|
);
|
|
1617
|
+
const prepared = options.plugins && options.plugins.length > 0 ? await (async () => {
|
|
1618
|
+
let generator = core.createPresentationGenerator({
|
|
1619
|
+
theme: resolved.requested,
|
|
1620
|
+
customThemes: resolved.requested ? {
|
|
1621
|
+
...resolved.customThemes,
|
|
1622
|
+
[CLI_THEME_KEY]: resolved.requested
|
|
1623
|
+
} : resolved.customThemes,
|
|
1624
|
+
services,
|
|
1625
|
+
baseDir: options.baseDir,
|
|
1626
|
+
fonts: options.fonts,
|
|
1627
|
+
validation: {
|
|
1628
|
+
allowUnknownFields: options.validation?.allowUnknownFields
|
|
1629
|
+
},
|
|
1630
|
+
renderer: options.renderer
|
|
1631
|
+
});
|
|
1632
|
+
for (const plugin of options.plugins)
|
|
1633
|
+
generator = generator.addComponent(plugin);
|
|
1634
|
+
const result = await generator.prepareQuality(normalized.document);
|
|
1635
|
+
warnings.push(...result.warnings ?? []);
|
|
1636
|
+
return result.prepared;
|
|
1637
|
+
})() : core.preparePptxQualityDocument(normalized.document, {
|
|
1638
|
+
customThemes: normalized.customThemes,
|
|
1639
|
+
fonts: options.fonts,
|
|
1640
|
+
services,
|
|
1641
|
+
renderer: options.renderer ?? documentRenderer(parsed),
|
|
1642
|
+
warnings
|
|
1643
|
+
});
|
|
1596
1644
|
return stampPrepared(
|
|
1597
1645
|
{
|
|
1598
1646
|
...prepared,
|
|
@@ -1624,7 +1672,7 @@ var PptxFormatAdapter = class {
|
|
|
1624
1672
|
const core = await import("@json-to-office/core-pptx");
|
|
1625
1673
|
const themes = core.pptxThemes || {};
|
|
1626
1674
|
const { requested } = await this.resolveThemes(options);
|
|
1627
|
-
return requested ?? themes.
|
|
1675
|
+
return requested ?? themes.consulting ?? {};
|
|
1628
1676
|
}
|
|
1629
1677
|
/**
|
|
1630
1678
|
* Resolve `theme`/`themePath` once for a whole run: `themePath` is read a
|
|
@@ -2179,7 +2227,7 @@ function authoredTextForMatch(text) {
|
|
|
2179
2227
|
function needleSegments(text) {
|
|
2180
2228
|
return authoredTextForMatch(text).split(FIELD).map(normalizeForMatch).filter((segment) => segment !== "");
|
|
2181
2229
|
}
|
|
2182
|
-
function indexDocument(pages, exclude = /* @__PURE__ */ new Set()) {
|
|
2230
|
+
function indexDocument(pages, exclude = /* @__PURE__ */ new Set(), order = pageOrder) {
|
|
2183
2231
|
const refs = [];
|
|
2184
2232
|
const fragments = [];
|
|
2185
2233
|
const positions = [];
|
|
@@ -2193,13 +2241,13 @@ function indexDocument(pages, exclude = /* @__PURE__ */ new Set()) {
|
|
|
2193
2241
|
positions.push(cursor);
|
|
2194
2242
|
cursor += fragment.length;
|
|
2195
2243
|
};
|
|
2196
|
-
const orders = pages.map((page) =>
|
|
2197
|
-
orders.forEach((
|
|
2198
|
-
for (const index of
|
|
2244
|
+
const orders = pages.map((page) => order(page.words, page.lines));
|
|
2245
|
+
orders.forEach((order2, pageIndex) => {
|
|
2246
|
+
for (const index of order2.upright) push(pageIndex, index);
|
|
2199
2247
|
});
|
|
2200
2248
|
const rotatedFrom = cursor;
|
|
2201
|
-
orders.forEach((
|
|
2202
|
-
for (const index of
|
|
2249
|
+
orders.forEach((order2, pageIndex) => {
|
|
2250
|
+
for (const index of order2.rotated) push(pageIndex, index);
|
|
2203
2251
|
});
|
|
2204
2252
|
return {
|
|
2205
2253
|
pages,
|
|
@@ -2224,6 +2272,16 @@ function pageOrder(words2, lines = []) {
|
|
|
2224
2272
|
rotated: [...rotated].sort((a, b) => a - b)
|
|
2225
2273
|
};
|
|
2226
2274
|
}
|
|
2275
|
+
function linedOrder(words2, lines = []) {
|
|
2276
|
+
const rotated = rotatedWords(words2, lines);
|
|
2277
|
+
const upright = words2.map((_, i) => i).filter((i) => !rotated.has(i));
|
|
2278
|
+
return {
|
|
2279
|
+
upright: groupRows(words2, upright).flatMap(
|
|
2280
|
+
(row) => [...row.words].sort((a, b) => words2[a].xMin - words2[b].xMin)
|
|
2281
|
+
),
|
|
2282
|
+
rotated: [...rotated].sort((a, b) => a - b)
|
|
2283
|
+
};
|
|
2284
|
+
}
|
|
2227
2285
|
function rotatedWords(words2, lines) {
|
|
2228
2286
|
const rotated = new Set(
|
|
2229
2287
|
words2.map((_, i) => i).filter((i) => {
|
|
@@ -2637,6 +2695,30 @@ function overprintedOccurrence(index, page, region, needle, claimed) {
|
|
|
2637
2695
|
})
|
|
2638
2696
|
};
|
|
2639
2697
|
}
|
|
2698
|
+
function linedOccurrence(lined, body, segments, claimed) {
|
|
2699
|
+
const bodyFragment = /* @__PURE__ */ new Map();
|
|
2700
|
+
body.refs.forEach((ref, i) => {
|
|
2701
|
+
if (body.fragments[i] !== "")
|
|
2702
|
+
bodyFragment.set(`${ref.pageIndex}:${ref.word}`, i);
|
|
2703
|
+
});
|
|
2704
|
+
for (const hit of findOccurrences(lined, segments)) {
|
|
2705
|
+
const claims = [];
|
|
2706
|
+
for (const part of hit.parts)
|
|
2707
|
+
for (const word of part.words) {
|
|
2708
|
+
const i = bodyFragment.get(`${part.pageIndex}:${word}`);
|
|
2709
|
+
if (i === void 0) continue;
|
|
2710
|
+
claims.push({
|
|
2711
|
+
at: body.positions[i],
|
|
2712
|
+
end: body.positions[i] + body.fragments[i].length
|
|
2713
|
+
});
|
|
2714
|
+
}
|
|
2715
|
+
if (claims.length === 0 || claims.some((claim) => claimed(claim.at)))
|
|
2716
|
+
continue;
|
|
2717
|
+
const at = Math.min(...claims.map((claim) => claim.at));
|
|
2718
|
+
return { occurrence: { ...hit, at, end: at }, claims };
|
|
2719
|
+
}
|
|
2720
|
+
return void 0;
|
|
2721
|
+
}
|
|
2640
2722
|
function assignInventory(pages, inventory) {
|
|
2641
2723
|
const results = /* @__PURE__ */ new Map();
|
|
2642
2724
|
const chromeWords = /* @__PURE__ */ new Set();
|
|
@@ -2676,6 +2758,7 @@ function assignInventory(pages, inventory) {
|
|
|
2676
2758
|
for (const row of pageNumberRows(pages, chromeWords))
|
|
2677
2759
|
claimRow(row.pageIndex, row.box);
|
|
2678
2760
|
const body = indexDocument(pages, chromeWords);
|
|
2761
|
+
let lined;
|
|
2679
2762
|
const claims = [];
|
|
2680
2763
|
const claimsOver = (o) => claims.filter((claim) => o.at < claim.end && claim.at < o.end);
|
|
2681
2764
|
let cursor = 0;
|
|
@@ -2705,6 +2788,19 @@ function assignInventory(pages, inventory) {
|
|
|
2705
2788
|
sparse = overprinted.claims;
|
|
2706
2789
|
}
|
|
2707
2790
|
}
|
|
2791
|
+
if (all.length === 0 && entry.page === void 0 && !entry.optional) {
|
|
2792
|
+
lined ??= indexDocument(pages, chromeWords, linedOrder);
|
|
2793
|
+
const found = linedOccurrence(
|
|
2794
|
+
lined,
|
|
2795
|
+
body,
|
|
2796
|
+
segments,
|
|
2797
|
+
(offset) => claims.some((claim) => claim.at <= offset && offset < claim.end)
|
|
2798
|
+
);
|
|
2799
|
+
if (found) {
|
|
2800
|
+
all = [found.occurrence];
|
|
2801
|
+
sparse = found.claims;
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2708
2804
|
if (all.length === 0 && segments.length === 1 && !entry.optional) {
|
|
2709
2805
|
const prefix = longestRenderedPrefix(
|
|
2710
2806
|
body,
|
|
@@ -3481,13 +3577,210 @@ function requestedFontsFromFacts(format, facts, resolvedFonts) {
|
|
|
3481
3577
|
// src/block-matrix.ts
|
|
3482
3578
|
import {
|
|
3483
3579
|
blockDependencies,
|
|
3580
|
+
blockReferencesFromDocument as blockReferencesFromDocument2,
|
|
3581
|
+
readBlockDefinitions as readBlockDefinitions2
|
|
3582
|
+
} from "@json-to-office/shared";
|
|
3583
|
+
|
|
3584
|
+
// src/matrix-inventory.ts
|
|
3585
|
+
import {
|
|
3586
|
+
blockReferencesFromDocument,
|
|
3484
3587
|
readBlockDefinitions
|
|
3485
3588
|
} from "@json-to-office/shared";
|
|
3589
|
+
function matrixUniverse(format, themes) {
|
|
3590
|
+
return {
|
|
3591
|
+
themes: [...themes],
|
|
3592
|
+
canvases: format === "docx" ? ["A4", "LETTER"] : ["wide169", "standard43"],
|
|
3593
|
+
fonts: ["design", "fallback"],
|
|
3594
|
+
edges: ["min", "max"]
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3598
|
+
function templateFormat(name, document) {
|
|
3599
|
+
const root = isRecord(document) ? document.name : void 0;
|
|
3600
|
+
if (root === "docx" || root === "pptx") return root;
|
|
3601
|
+
if (name.endsWith(".docx.json")) return "docx";
|
|
3602
|
+
if (name.endsWith(".pptx.json")) return "pptx";
|
|
3603
|
+
return void 0;
|
|
3604
|
+
}
|
|
3605
|
+
function authoredDeckCanvas(props) {
|
|
3606
|
+
const width = typeof props.slideWidth === "number" ? props.slideWidth : 10;
|
|
3607
|
+
const height = typeof props.slideHeight === "number" ? props.slideHeight : 7.5;
|
|
3608
|
+
return Math.abs(width / height - 16 / 9) < Math.abs(width / height - 4 / 3) ? "wide169" : "standard43";
|
|
3609
|
+
}
|
|
3610
|
+
function requiredRoles(format, profile) {
|
|
3611
|
+
const required = profile?.rules?.[`${format}/required-chrome`]?.parameters?.required;
|
|
3612
|
+
return Array.isArray(required) ? required.filter((role) => typeof role === "string") : [];
|
|
3613
|
+
}
|
|
3614
|
+
function templateConditions(format, props, universe) {
|
|
3615
|
+
const named = typeof props.theme === "string" ? props.theme : void 0;
|
|
3616
|
+
const canvas = format === "pptx" ? authoredDeckCanvas(props) : void 0;
|
|
3617
|
+
const canvasExclusions = (reason) => canvas === void 0 ? [] : universe.canvases.filter((c) => c !== canvas).map((c) => ({ condition: `canvas ${c}`, reason }));
|
|
3618
|
+
if (named !== void 0 && universe.themes.includes(named)) {
|
|
3619
|
+
return {
|
|
3620
|
+
theme: named,
|
|
3621
|
+
conditions: {
|
|
3622
|
+
...structuredClone(universe),
|
|
3623
|
+
...canvas !== void 0 && { canvases: [canvas] }
|
|
3624
|
+
},
|
|
3625
|
+
exclusions: canvasExclusions(
|
|
3626
|
+
`slot budgets are measured on the ${canvas} slide the template is drawn on; another shape lays out, but holds fewer words`
|
|
3627
|
+
)
|
|
3628
|
+
};
|
|
3629
|
+
}
|
|
3630
|
+
const theme = named ?? "inline";
|
|
3631
|
+
const why = named === void 0 ? "authored against the template's own theme object" : `authored against "${named}", which is no bundled theme`;
|
|
3632
|
+
const exclusions = [
|
|
3633
|
+
...universe.themes.map((t) => ({ condition: `theme ${t}`, reason: why })),
|
|
3634
|
+
...canvasExclusions(
|
|
3635
|
+
"absolute geometry fitted to the template's own slide size"
|
|
3636
|
+
),
|
|
3637
|
+
...canvas === void 0 ? universe.canvases.filter((c) => c !== "A4").map((c) => ({
|
|
3638
|
+
condition: `canvas ${c}`,
|
|
3639
|
+
reason: "absolute geometry fitted to the template's own page"
|
|
3640
|
+
})) : [],
|
|
3641
|
+
{
|
|
3642
|
+
condition: "font fallback",
|
|
3643
|
+
reason: "lines fitted to the template's own faces; a wider face is another design, not a boundary"
|
|
3644
|
+
}
|
|
3645
|
+
];
|
|
3646
|
+
return {
|
|
3647
|
+
theme,
|
|
3648
|
+
conditions: {
|
|
3649
|
+
themes: [theme],
|
|
3650
|
+
canvases: [canvas ?? "A4"],
|
|
3651
|
+
fonts: ["design"],
|
|
3652
|
+
edges: [...universe.edges]
|
|
3653
|
+
},
|
|
3654
|
+
exclusions
|
|
3655
|
+
};
|
|
3656
|
+
}
|
|
3657
|
+
function buildMatrixInventory(templates, options) {
|
|
3658
|
+
const inventory = { templates: [], entries: [] };
|
|
3659
|
+
for (const source of templates) {
|
|
3660
|
+
const format = templateFormat(source.name, source.document);
|
|
3661
|
+
if (!format || !isRecord(source.document)) continue;
|
|
3662
|
+
const props = isRecord(source.document.props) ? source.document.props : {};
|
|
3663
|
+
const universe = matrixUniverse(format, options.themes[format]);
|
|
3664
|
+
const blueprint = options.blueprints?.find(
|
|
3665
|
+
(b) => b.format === format && b.definitions === source.name
|
|
3666
|
+
);
|
|
3667
|
+
const profile = blueprint ? options.profiles?.[blueprint.profile] : void 0;
|
|
3668
|
+
const roles = requiredRoles(format, profile);
|
|
3669
|
+
const { theme, conditions: conditions2, exclusions } = templateConditions(
|
|
3670
|
+
format,
|
|
3671
|
+
props,
|
|
3672
|
+
universe
|
|
3673
|
+
);
|
|
3674
|
+
const definitions = Object.keys(readBlockDefinitions(source.document));
|
|
3675
|
+
const references = blockReferencesFromDocument(source.document, {
|
|
3676
|
+
template: source.name,
|
|
3677
|
+
format
|
|
3678
|
+
});
|
|
3679
|
+
const templateExclusions = [...exclusions];
|
|
3680
|
+
if (definitions.length > 0 && references.length === 0) {
|
|
3681
|
+
templateExclusions.push({
|
|
3682
|
+
condition: "definitions",
|
|
3683
|
+
reason: "the definitions do not validate, so discovery publishes none"
|
|
3684
|
+
});
|
|
3685
|
+
}
|
|
3686
|
+
inventory.templates.push({
|
|
3687
|
+
template: source.name,
|
|
3688
|
+
format,
|
|
3689
|
+
theme,
|
|
3690
|
+
...blueprint && { profile: blueprint.profile },
|
|
3691
|
+
requiredRoles: roles,
|
|
3692
|
+
definitions,
|
|
3693
|
+
conditions: conditions2,
|
|
3694
|
+
exclusions: templateExclusions
|
|
3695
|
+
});
|
|
3696
|
+
for (const reference of references) {
|
|
3697
|
+
const slotless = Object.keys(reference.definition.slots ?? {}).length === 0;
|
|
3698
|
+
inventory.entries.push({
|
|
3699
|
+
id: `${source.name}#${reference.definitionPointer}`,
|
|
3700
|
+
template: source.name,
|
|
3701
|
+
format,
|
|
3702
|
+
name: reference.name,
|
|
3703
|
+
definitionPointer: reference.definitionPointer,
|
|
3704
|
+
dependencies: reference.dependencies,
|
|
3705
|
+
...blueprint && { profile: blueprint.profile },
|
|
3706
|
+
requiredRoles: roles,
|
|
3707
|
+
themes: [...conditions2.themes],
|
|
3708
|
+
canvases: [...conditions2.canvases],
|
|
3709
|
+
fonts: [...conditions2.fonts],
|
|
3710
|
+
edges: slotless ? ["max"] : [...conditions2.edges],
|
|
3711
|
+
exclusions: [
|
|
3712
|
+
...exclusions,
|
|
3713
|
+
...slotless ? [
|
|
3714
|
+
{
|
|
3715
|
+
condition: "edge min",
|
|
3716
|
+
reason: "no slots, so min and max are the same document"
|
|
3717
|
+
}
|
|
3718
|
+
] : []
|
|
3719
|
+
]
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
return inventory;
|
|
3724
|
+
}
|
|
3725
|
+
function inventoryGaps(entry, universe) {
|
|
3726
|
+
const excluded = new Set(entry.exclusions.map((e) => e.condition));
|
|
3727
|
+
const gaps = [];
|
|
3728
|
+
const check = (kind, all, got) => {
|
|
3729
|
+
for (const value of all) {
|
|
3730
|
+
const condition = `${kind} ${value}`;
|
|
3731
|
+
const has = got.includes(value);
|
|
3732
|
+
if (has && excluded.has(condition)) gaps.push(`${condition}: both`);
|
|
3733
|
+
if (!has && !excluded.has(condition)) gaps.push(`${condition}: neither`);
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
check("theme", universe.themes, entry.themes);
|
|
3737
|
+
check("canvas", universe.canvases, entry.canvases);
|
|
3738
|
+
check("font", universe.fonts, entry.fonts);
|
|
3739
|
+
check("edge", universe.edges, entry.edges);
|
|
3740
|
+
return gaps;
|
|
3741
|
+
}
|
|
3742
|
+
function describeInventory(inventory) {
|
|
3743
|
+
const lines = [];
|
|
3744
|
+
for (const template of inventory.templates) {
|
|
3745
|
+
lines.push(
|
|
3746
|
+
`${template.template} (${template.format}, theme ${template.theme}${template.profile ? `, profile ${template.profile}` : ""}): ${template.definitions.length} definition(s)`
|
|
3747
|
+
);
|
|
3748
|
+
for (const entry of inventory.entries.filter(
|
|
3749
|
+
(e) => e.template === template.template
|
|
3750
|
+
)) {
|
|
3751
|
+
lines.push(
|
|
3752
|
+
` ${entry.name}: themes ${entry.themes.join(" ")} \xB7 canvases ${entry.canvases.join(
|
|
3753
|
+
" "
|
|
3754
|
+
)} \xB7 fonts ${entry.fonts.join(" ")} \xB7 edges ${entry.edges.join(" ")}`
|
|
3755
|
+
);
|
|
3756
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
3757
|
+
for (const exclusion of entry.exclusions) {
|
|
3758
|
+
reasons.set(exclusion.reason, [
|
|
3759
|
+
...reasons.get(exclusion.reason) ?? [],
|
|
3760
|
+
exclusion.condition
|
|
3761
|
+
]);
|
|
3762
|
+
}
|
|
3763
|
+
for (const [reason, conditions2] of reasons)
|
|
3764
|
+
lines.push(` not ${conditions2.join(", ")}: ${reason}`);
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
return lines.join("\n");
|
|
3768
|
+
}
|
|
3769
|
+
|
|
3770
|
+
// src/block-matrix.ts
|
|
3771
|
+
var PPTX_FALLBACK_FONTS = {
|
|
3772
|
+
heading: "DejaVu Sans",
|
|
3773
|
+
body: "DejaVu Sans"
|
|
3774
|
+
};
|
|
3775
|
+
var PPTX_CANVAS_SIZE = {
|
|
3776
|
+
wide169: { slideWidth: 13.333, slideHeight: 7.5 },
|
|
3777
|
+
standard43: { slideWidth: 10, slideHeight: 7.5 }
|
|
3778
|
+
};
|
|
3486
3779
|
var FALLBACK_FONTS = {
|
|
3487
3780
|
heading: { family: "DejaVu Sans" },
|
|
3488
3781
|
body: { family: "DejaVu Sans" }
|
|
3489
3782
|
};
|
|
3490
|
-
var MATRIX_IMAGE = "data:image/png;base64,
|
|
3783
|
+
var MATRIX_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAAEklEQVR42mOIrt34HxkzoAsAAE/xFEFoJgXRAAAAAElFTkSuQmCC";
|
|
3491
3784
|
var WORDS = [
|
|
3492
3785
|
"performance",
|
|
3493
3786
|
"delivery",
|
|
@@ -3522,7 +3815,7 @@ function widestNumber(length, seed = 0) {
|
|
|
3522
3815
|
const integer = group(digits);
|
|
3523
3816
|
return `\u2212${integer}.${"0".repeat(length - integer.length - 2)}`;
|
|
3524
3817
|
}
|
|
3525
|
-
var
|
|
3818
|
+
var isRecord2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3526
3819
|
var NUMERIC_SLOTS = /* @__PURE__ */ new Set(["value", "delta", "cells"]);
|
|
3527
3820
|
function stringValue(slot, name, edge, seed) {
|
|
3528
3821
|
if (slot.enum && slot.enum.length > 0) {
|
|
@@ -3564,14 +3857,17 @@ function stringValue(slot, name, edge, seed) {
|
|
|
3564
3857
|
return edge === "max" ? words(count, seed, false) : "01";
|
|
3565
3858
|
return words(count, seed, sentence);
|
|
3566
3859
|
}
|
|
3567
|
-
function componentValue(name, edge, seed) {
|
|
3568
|
-
|
|
3860
|
+
function componentValue(name, edge, seed, format = "docx") {
|
|
3861
|
+
const chart = name === "chart" || format === "pptx" && name === "content";
|
|
3862
|
+
if (chart && (name === "chart" || edge === "max")) {
|
|
3569
3863
|
const categories = edge === "max" ? 8 : 2;
|
|
3570
3864
|
const series = edge === "max" ? 3 : 1;
|
|
3571
3865
|
return {
|
|
3572
3866
|
name: "chart",
|
|
3573
3867
|
props: {
|
|
3574
|
-
|
|
3868
|
+
// The native column chart: `column` in a report, `bar` standing
|
|
3869
|
+
// upright in a deck.
|
|
3870
|
+
type: format === "pptx" ? "bar" : "column",
|
|
3575
3871
|
valAxisTitle: edge === "max" ? `${words(3, seed, false)} (\u20ACm)` : "Revenue (\u20ACm)",
|
|
3576
3872
|
...edge === "max" && { catAxisTitle: words(3, seed + 3, false) },
|
|
3577
3873
|
chartColors: ["primary", "secondary", "accent"].slice(0, series),
|
|
@@ -3592,6 +3888,12 @@ function componentValue(name, edge, seed) {
|
|
|
3592
3888
|
}
|
|
3593
3889
|
};
|
|
3594
3890
|
}
|
|
3891
|
+
if (format === "pptx") {
|
|
3892
|
+
return {
|
|
3893
|
+
name: "image",
|
|
3894
|
+
props: { path: MATRIX_IMAGE, alt: words(6, seed, false) }
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3595
3897
|
return {
|
|
3596
3898
|
name: "image",
|
|
3597
3899
|
props: {
|
|
@@ -3601,7 +3903,7 @@ function componentValue(name, edge, seed) {
|
|
|
3601
3903
|
}
|
|
3602
3904
|
};
|
|
3603
3905
|
}
|
|
3604
|
-
function boundarySlotValue(slot, name, edge, seed = 0) {
|
|
3906
|
+
function boundarySlotValue(slot, name, edge, seed = 0, format = "docx") {
|
|
3605
3907
|
switch (slot.type) {
|
|
3606
3908
|
case "string":
|
|
3607
3909
|
return stringValue(slot, name, edge, seed);
|
|
@@ -3611,12 +3913,18 @@ function boundarySlotValue(slot, name, edge, seed = 0) {
|
|
|
3611
3913
|
case "boolean":
|
|
3612
3914
|
return edge === "max" ? true : slot.default ?? true;
|
|
3613
3915
|
case "component":
|
|
3614
|
-
return componentValue(name, edge, seed);
|
|
3916
|
+
return componentValue(name, edge, seed, format);
|
|
3615
3917
|
case "object": {
|
|
3616
3918
|
const out = {};
|
|
3617
3919
|
for (const [key, property] of Object.entries(slot.properties ?? {})) {
|
|
3618
3920
|
if (edge === "min" && !property.required) continue;
|
|
3619
|
-
const value = boundarySlotValue(
|
|
3921
|
+
const value = boundarySlotValue(
|
|
3922
|
+
property,
|
|
3923
|
+
key,
|
|
3924
|
+
edge,
|
|
3925
|
+
seed + key.length,
|
|
3926
|
+
format
|
|
3927
|
+
);
|
|
3620
3928
|
if (value !== void 0) out[key] = value;
|
|
3621
3929
|
}
|
|
3622
3930
|
return out;
|
|
@@ -3626,21 +3934,21 @@ function boundarySlotValue(slot, name, edge, seed = 0) {
|
|
|
3626
3934
|
const item = slot.items ?? { type: "string" };
|
|
3627
3935
|
return Array.from(
|
|
3628
3936
|
{ length: count },
|
|
3629
|
-
(_, i) => boundarySlotValue(item, name, edge, seed + i)
|
|
3937
|
+
(_, i) => boundarySlotValue(item, name, edge, seed + i, format)
|
|
3630
3938
|
);
|
|
3631
3939
|
}
|
|
3632
3940
|
default:
|
|
3633
3941
|
return void 0;
|
|
3634
3942
|
}
|
|
3635
3943
|
}
|
|
3636
|
-
function boundaryInvocation(name, definition, edge, seed = 0,
|
|
3944
|
+
function boundaryInvocation(name, definition, edge, seed = 0, requiredRoles2 = [], format = "docx") {
|
|
3637
3945
|
const slots = {};
|
|
3638
3946
|
let offset = seed;
|
|
3639
3947
|
for (const [slotName, slot] of Object.entries(definition.slots)) {
|
|
3640
3948
|
offset += slotName.length;
|
|
3641
|
-
const required = slot.required === true || slot.role !== void 0 &&
|
|
3949
|
+
const required = slot.required === true || slot.role !== void 0 && requiredRoles2.includes(slot.role);
|
|
3642
3950
|
if (edge === "min" && !required) continue;
|
|
3643
|
-
const value = boundarySlotValue(slot, slotName, edge, offset);
|
|
3951
|
+
const value = boundarySlotValue(slot, slotName, edge, offset, format);
|
|
3644
3952
|
if (value !== void 0) slots[slotName] = value;
|
|
3645
3953
|
}
|
|
3646
3954
|
const labels = slots.labels;
|
|
@@ -3648,17 +3956,30 @@ function boundaryInvocation(name, definition, edge, seed = 0, requiredRoles = []
|
|
|
3648
3956
|
if (Array.isArray(labels) && Array.isArray(columns)) {
|
|
3649
3957
|
const cells = definition.slots.columns?.items?.properties?.cells;
|
|
3650
3958
|
for (const column of columns) {
|
|
3651
|
-
if (
|
|
3959
|
+
if (isRecord2(column) && Array.isArray(column.cells) && cells?.items) {
|
|
3652
3960
|
column.cells = labels.map(
|
|
3653
|
-
(_, i) => boundarySlotValue(
|
|
3961
|
+
(_, i) => boundarySlotValue(
|
|
3962
|
+
cells.items,
|
|
3963
|
+
"cells",
|
|
3964
|
+
edge,
|
|
3965
|
+
offset + i,
|
|
3966
|
+
format
|
|
3967
|
+
)
|
|
3654
3968
|
);
|
|
3655
3969
|
}
|
|
3656
3970
|
}
|
|
3657
3971
|
}
|
|
3658
3972
|
return { name: "block", props: { ref: name, slots } };
|
|
3659
3973
|
}
|
|
3660
|
-
function overBudgetInvocation(name, definition, seed = 0) {
|
|
3661
|
-
const invocation = boundaryInvocation(
|
|
3974
|
+
function overBudgetInvocation(name, definition, seed = 0, format = "docx") {
|
|
3975
|
+
const invocation = boundaryInvocation(
|
|
3976
|
+
name,
|
|
3977
|
+
definition,
|
|
3978
|
+
"max",
|
|
3979
|
+
seed,
|
|
3980
|
+
[],
|
|
3981
|
+
format
|
|
3982
|
+
);
|
|
3662
3983
|
const slots = invocation.props.slots;
|
|
3663
3984
|
for (const [slotName, slot] of Object.entries(definition.slots)) {
|
|
3664
3985
|
if (slot.type === "string" && slot.maxWords !== void 0) {
|
|
@@ -3676,27 +3997,41 @@ function overBudgetInvocation(name, definition, seed = 0) {
|
|
|
3676
3997
|
return void 0;
|
|
3677
3998
|
}
|
|
3678
3999
|
function enumerateBlockDefinitions(template, templateName) {
|
|
3679
|
-
const
|
|
4000
|
+
const format = templateFormat(templateName, template);
|
|
4001
|
+
if (!format)
|
|
4002
|
+
throw new Error(`${templateName} is neither a report nor a deck.`);
|
|
4003
|
+
const references = blockReferencesFromDocument2(template, {
|
|
4004
|
+
template: templateName,
|
|
4005
|
+
format
|
|
4006
|
+
});
|
|
4007
|
+
const declared = Object.keys(readBlockDefinitions2(template));
|
|
4008
|
+
if (references.length !== declared.length)
|
|
4009
|
+
throw new Error(
|
|
4010
|
+
`${templateName}: discovery publishes ${references.length} of ${declared.length} definitions; the rest do not validate.`
|
|
4011
|
+
);
|
|
3680
4012
|
const examples = /* @__PURE__ */ new Map();
|
|
3681
4013
|
const walk = (node) => {
|
|
3682
4014
|
if (Array.isArray(node)) {
|
|
3683
4015
|
node.forEach(walk);
|
|
3684
4016
|
return;
|
|
3685
4017
|
}
|
|
3686
|
-
if (!
|
|
4018
|
+
if (!isRecord2(node)) return;
|
|
3687
4019
|
const props = node.props;
|
|
3688
|
-
if (node.name === "block" &&
|
|
3689
|
-
examples.set(props.ref,
|
|
4020
|
+
if (node.name === "block" && isRecord2(props) && typeof props.ref === "string" && !examples.has(props.ref)) {
|
|
4021
|
+
examples.set(props.ref, isRecord2(props.slots) ? props.slots : {});
|
|
3690
4022
|
}
|
|
3691
4023
|
walk(node.children);
|
|
3692
4024
|
};
|
|
3693
|
-
walk(
|
|
3694
|
-
return
|
|
3695
|
-
name,
|
|
4025
|
+
walk(isRecord2(template) ? template.children : void 0);
|
|
4026
|
+
return references.map((reference) => ({
|
|
4027
|
+
name: reference.name,
|
|
4028
|
+
format,
|
|
3696
4029
|
template: templateName,
|
|
3697
|
-
pointer:
|
|
3698
|
-
definition,
|
|
3699
|
-
...examples.has(name) && {
|
|
4030
|
+
pointer: reference.definitionPointer,
|
|
4031
|
+
definition: reference.definition,
|
|
4032
|
+
...examples.has(reference.name) && {
|
|
4033
|
+
example: examples.get(reference.name)
|
|
4034
|
+
}
|
|
3700
4035
|
}));
|
|
3701
4036
|
}
|
|
3702
4037
|
var CHROME = ["cover", "running-head", "section-opener"];
|
|
@@ -3708,19 +4043,27 @@ function nominal(entry, name, definitions) {
|
|
|
3708
4043
|
props: { ref: name, slots: structuredClone(entry.example) }
|
|
3709
4044
|
};
|
|
3710
4045
|
}
|
|
3711
|
-
return boundaryInvocation(
|
|
4046
|
+
return boundaryInvocation(
|
|
4047
|
+
name,
|
|
4048
|
+
definitions[name],
|
|
4049
|
+
"min",
|
|
4050
|
+
0,
|
|
4051
|
+
[],
|
|
4052
|
+
entry.format
|
|
4053
|
+
);
|
|
3712
4054
|
}
|
|
3713
|
-
function inlineImages(value) {
|
|
3714
|
-
if (Array.isArray(value)) return value.map(inlineImages);
|
|
3715
|
-
if (!
|
|
3716
|
-
if (value.name === "image" &&
|
|
3717
|
-
const props = { ...value.props, base64: MATRIX_IMAGE };
|
|
3718
|
-
delete props.path;
|
|
4055
|
+
function inlineImages(value, format = "docx") {
|
|
4056
|
+
if (Array.isArray(value)) return value.map((v) => inlineImages(v, format));
|
|
4057
|
+
if (!isRecord2(value)) return value;
|
|
4058
|
+
if (value.name === "image" && isRecord2(value.props) && typeof value.props.path === "string" && !value.props.path.startsWith("data:")) {
|
|
4059
|
+
const props = format === "pptx" ? { ...value.props, path: MATRIX_IMAGE } : { ...value.props, base64: MATRIX_IMAGE };
|
|
4060
|
+
if (format === "docx") delete props.path;
|
|
3719
4061
|
return { ...value, props };
|
|
3720
4062
|
}
|
|
3721
|
-
if (value.name === "highcharts")
|
|
4063
|
+
if (value.name === "highcharts")
|
|
4064
|
+
return componentValue("chart", "min", 0, format);
|
|
3722
4065
|
return Object.fromEntries(
|
|
3723
|
-
Object.entries(value).map(([k, v]) => [k, inlineImages(v)])
|
|
4066
|
+
Object.entries(value).map(([k, v]) => [k, inlineImages(v, format)])
|
|
3724
4067
|
);
|
|
3725
4068
|
}
|
|
3726
4069
|
function withDefinitions(definitions, names) {
|
|
@@ -3736,9 +4079,9 @@ function withDefinitions(definitions, names) {
|
|
|
3736
4079
|
}
|
|
3737
4080
|
function conditions(props, children, theme, font, canvas) {
|
|
3738
4081
|
const sections = children.map((child) => {
|
|
3739
|
-
if (!
|
|
3740
|
-
const props2 =
|
|
3741
|
-
const page =
|
|
4082
|
+
if (!isRecord2(child) || child.name !== "section") return child;
|
|
4083
|
+
const props2 = isRecord2(child.props) ? child.props : {};
|
|
4084
|
+
const page = isRecord2(props2.page) ? props2.page : {};
|
|
3742
4085
|
return { ...child, props: { ...props2, page: { ...page, size: canvas } } };
|
|
3743
4086
|
});
|
|
3744
4087
|
const chart = JSON.stringify(sections).includes('"name":"chart"');
|
|
@@ -3754,12 +4097,12 @@ function conditions(props, children, theme, font, canvas) {
|
|
|
3754
4097
|
};
|
|
3755
4098
|
}
|
|
3756
4099
|
var BODY_COPY = words(40, 1e3, true);
|
|
3757
|
-
function blockCaseDocument(entries, name, edge, theme, { font = "design", canvas = "A4", requiredRoles = [] } = {}) {
|
|
4100
|
+
function blockCaseDocument(entries, name, edge, theme, { font = "design", canvas = "A4", requiredRoles: requiredRoles2 = [] } = {}) {
|
|
3758
4101
|
const definitions = Object.fromEntries(
|
|
3759
4102
|
entries.map((e) => [e.name, e.definition])
|
|
3760
4103
|
);
|
|
3761
4104
|
const byName = new Map(entries.map((e) => [e.name, e]));
|
|
3762
|
-
const under = (chrome) => chrome === name ? boundaryInvocation(name, definitions[name], edge, 0,
|
|
4105
|
+
const under = (chrome) => chrome === name ? boundaryInvocation(name, definitions[name], edge, 0, requiredRoles2) : inlineImages(nominal(byName.get(chrome), chrome, definitions));
|
|
3763
4106
|
const cover = under("cover");
|
|
3764
4107
|
const runningHead = under("running-head");
|
|
3765
4108
|
const opener = under("section-opener");
|
|
@@ -3771,7 +4114,7 @@ function blockCaseDocument(entries, name, edge, theme, { font = "design", canvas
|
|
|
3771
4114
|
);
|
|
3772
4115
|
}
|
|
3773
4116
|
body.push(
|
|
3774
|
-
boundaryInvocation(name, definitions[name], edge, 0,
|
|
4117
|
+
boundaryInvocation(name, definitions[name], edge, 0, requiredRoles2)
|
|
3775
4118
|
);
|
|
3776
4119
|
}
|
|
3777
4120
|
body.push({ name: "paragraph", props: { text: BODY_COPY } });
|
|
@@ -3802,26 +4145,26 @@ function blockCaseDocument(entries, name, edge, theme, { font = "design", canvas
|
|
|
3802
4145
|
canvas
|
|
3803
4146
|
);
|
|
3804
4147
|
}
|
|
3805
|
-
function reportCaseDocument(template, edge, theme, { font = "design", canvas = "A4", requiredRoles = [] } = {}) {
|
|
3806
|
-
if (!
|
|
4148
|
+
function reportCaseDocument(template, edge, theme, { font = "design", canvas = "A4", requiredRoles: requiredRoles2 = [] } = {}) {
|
|
4149
|
+
if (!isRecord2(template) || !isRecord2(template.props))
|
|
3807
4150
|
throw new Error("A template is a document with props.");
|
|
3808
|
-
const definitions =
|
|
4151
|
+
const definitions = readBlockDefinitions2(template);
|
|
3809
4152
|
let seed = 0;
|
|
3810
4153
|
const rewrite = (node) => {
|
|
3811
4154
|
if (Array.isArray(node)) return node.map(rewrite);
|
|
3812
|
-
if (!
|
|
4155
|
+
if (!isRecord2(node)) return node;
|
|
3813
4156
|
const props2 = node.props;
|
|
3814
|
-
if (node.name === "block" &&
|
|
4157
|
+
if (node.name === "block" && isRecord2(props2) && typeof props2.ref === "string" && definitions[props2.ref]) {
|
|
3815
4158
|
seed += 7;
|
|
3816
4159
|
return boundaryInvocation(
|
|
3817
4160
|
props2.ref,
|
|
3818
4161
|
definitions[props2.ref],
|
|
3819
4162
|
edge,
|
|
3820
4163
|
seed,
|
|
3821
|
-
|
|
4164
|
+
requiredRoles2
|
|
3822
4165
|
);
|
|
3823
4166
|
}
|
|
3824
|
-
if (node.name === "paragraph" &&
|
|
4167
|
+
if (node.name === "paragraph" && isRecord2(props2) && typeof props2.text === "string") {
|
|
3825
4168
|
return {
|
|
3826
4169
|
...node,
|
|
3827
4170
|
props: { ...props2, text: edge === "max" ? BODY_COPY : props2.text }
|
|
@@ -3882,6 +4225,200 @@ function generateBlockMatrix(template, templateName, options) {
|
|
|
3882
4225
|
}
|
|
3883
4226
|
return cases;
|
|
3884
4227
|
}
|
|
4228
|
+
function deckConditions(props, children, theme, font, canvas, themeObject) {
|
|
4229
|
+
const out = structuredClone(props);
|
|
4230
|
+
delete out.qualityProfile;
|
|
4231
|
+
const inline = typeof props.theme !== "string";
|
|
4232
|
+
if (!inline || theme !== "inline") {
|
|
4233
|
+
if (font === "fallback") {
|
|
4234
|
+
const base = themeObject?.(theme);
|
|
4235
|
+
if (!base)
|
|
4236
|
+
throw new Error(
|
|
4237
|
+
`The fallback case on "${theme}" needs the theme's object.`
|
|
4238
|
+
);
|
|
4239
|
+
const fonts = isRecord2(base.fonts) ? base.fonts : {};
|
|
4240
|
+
out.theme = {
|
|
4241
|
+
...structuredClone(base),
|
|
4242
|
+
fonts: { ...fonts, ...PPTX_FALLBACK_FONTS }
|
|
4243
|
+
};
|
|
4244
|
+
} else {
|
|
4245
|
+
out.theme = theme;
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
if ((canvas === "wide169" || canvas === "standard43") && authoredDeckCanvas(props) !== canvas)
|
|
4249
|
+
Object.assign(out, PPTX_CANVAS_SIZE[canvas]);
|
|
4250
|
+
return { name: "pptx", props: out, children };
|
|
4251
|
+
}
|
|
4252
|
+
function templateProps(template) {
|
|
4253
|
+
if (!isRecord2(template) || !isRecord2(template.props))
|
|
4254
|
+
throw new Error("A template is a document with props.");
|
|
4255
|
+
return template.props;
|
|
4256
|
+
}
|
|
4257
|
+
function deckBlockCaseDocument(template, entries, name, edge, theme, {
|
|
4258
|
+
font = "design",
|
|
4259
|
+
canvas = "wide169",
|
|
4260
|
+
requiredRoles: requiredRoles2 = [],
|
|
4261
|
+
themeObject
|
|
4262
|
+
} = {}) {
|
|
4263
|
+
const props = templateProps(template);
|
|
4264
|
+
const definitions = Object.fromEntries(
|
|
4265
|
+
entries.map((e) => [e.name, e.definition])
|
|
4266
|
+
);
|
|
4267
|
+
const byName = new Map(entries.map((e) => [e.name, e]));
|
|
4268
|
+
const used = /* @__PURE__ */ new Set([name]);
|
|
4269
|
+
const slides = [];
|
|
4270
|
+
if (name !== "cover" && byName.has("cover")) {
|
|
4271
|
+
used.add("cover");
|
|
4272
|
+
slides.push({
|
|
4273
|
+
name: "slide",
|
|
4274
|
+
children: [
|
|
4275
|
+
inlineImages(
|
|
4276
|
+
nominal(byName.get("cover"), "cover", definitions),
|
|
4277
|
+
"pptx"
|
|
4278
|
+
)
|
|
4279
|
+
]
|
|
4280
|
+
});
|
|
4281
|
+
}
|
|
4282
|
+
slides.push({
|
|
4283
|
+
name: "slide",
|
|
4284
|
+
children: [
|
|
4285
|
+
boundaryInvocation(
|
|
4286
|
+
name,
|
|
4287
|
+
definitions[name],
|
|
4288
|
+
edge,
|
|
4289
|
+
0,
|
|
4290
|
+
requiredRoles2,
|
|
4291
|
+
"pptx"
|
|
4292
|
+
)
|
|
4293
|
+
]
|
|
4294
|
+
});
|
|
4295
|
+
return deckConditions(
|
|
4296
|
+
{ ...props, blocks: withDefinitions(definitions, used) },
|
|
4297
|
+
slides,
|
|
4298
|
+
theme,
|
|
4299
|
+
font,
|
|
4300
|
+
canvas,
|
|
4301
|
+
themeObject
|
|
4302
|
+
);
|
|
4303
|
+
}
|
|
4304
|
+
function deckReportCaseDocument(template, edge, theme, {
|
|
4305
|
+
font = "design",
|
|
4306
|
+
canvas = "wide169",
|
|
4307
|
+
requiredRoles: requiredRoles2 = [],
|
|
4308
|
+
themeObject
|
|
4309
|
+
} = {}) {
|
|
4310
|
+
const props = templateProps(template);
|
|
4311
|
+
const definitions = readBlockDefinitions2(template);
|
|
4312
|
+
let seed = 0;
|
|
4313
|
+
const rewrite = (node) => {
|
|
4314
|
+
if (Array.isArray(node)) return node.map(rewrite);
|
|
4315
|
+
if (!isRecord2(node)) return node;
|
|
4316
|
+
const nodeProps = node.props;
|
|
4317
|
+
if (node.name === "block" && isRecord2(nodeProps) && typeof nodeProps.ref === "string" && definitions[nodeProps.ref]) {
|
|
4318
|
+
seed += 7;
|
|
4319
|
+
return boundaryInvocation(
|
|
4320
|
+
nodeProps.ref,
|
|
4321
|
+
definitions[nodeProps.ref],
|
|
4322
|
+
edge,
|
|
4323
|
+
seed,
|
|
4324
|
+
requiredRoles2,
|
|
4325
|
+
"pptx"
|
|
4326
|
+
);
|
|
4327
|
+
}
|
|
4328
|
+
return Array.isArray(node.children) ? { ...node, children: rewrite(node.children) } : node;
|
|
4329
|
+
};
|
|
4330
|
+
return deckConditions(
|
|
4331
|
+
props,
|
|
4332
|
+
rewrite(template.children),
|
|
4333
|
+
theme,
|
|
4334
|
+
font,
|
|
4335
|
+
canvas,
|
|
4336
|
+
themeObject
|
|
4337
|
+
);
|
|
4338
|
+
}
|
|
4339
|
+
var stem = (template) => template.replace(/\.(docx|pptx)\.json$/, "");
|
|
4340
|
+
function generateMatrixCases(inventory, templates, selection = {}, { themeObject } = {}) {
|
|
4341
|
+
const pick = (supported, wanted) => supported.filter((value) => !wanted || wanted.includes(value));
|
|
4342
|
+
const cases = [];
|
|
4343
|
+
for (const summary of inventory.templates) {
|
|
4344
|
+
if (selection.templates && !selection.templates.includes(summary.template))
|
|
4345
|
+
continue;
|
|
4346
|
+
const source = templates.find((t) => t.name === summary.template);
|
|
4347
|
+
const entries = inventory.entries.filter(
|
|
4348
|
+
(e) => e.template === summary.template
|
|
4349
|
+
);
|
|
4350
|
+
if (!source || entries.length === 0) continue;
|
|
4351
|
+
const definitions = enumerateBlockDefinitions(
|
|
4352
|
+
source.document,
|
|
4353
|
+
summary.template
|
|
4354
|
+
);
|
|
4355
|
+
const withSlots = entries.some((e) => e.edges.includes("min"));
|
|
4356
|
+
for (const theme of pick(summary.conditions.themes, selection.themes))
|
|
4357
|
+
for (const font of pick(summary.conditions.fonts, selection.fonts))
|
|
4358
|
+
for (const canvas of pick(
|
|
4359
|
+
summary.conditions.canvases,
|
|
4360
|
+
selection.canvases
|
|
4361
|
+
))
|
|
4362
|
+
for (const edge of pick(summary.conditions.edges, selection.edges)) {
|
|
4363
|
+
const shared = {
|
|
4364
|
+
format: summary.format,
|
|
4365
|
+
template: summary.template,
|
|
4366
|
+
...summary.profile && { profile: summary.profile },
|
|
4367
|
+
edge,
|
|
4368
|
+
theme,
|
|
4369
|
+
font,
|
|
4370
|
+
canvas
|
|
4371
|
+
};
|
|
4372
|
+
const conditions2 = {
|
|
4373
|
+
font,
|
|
4374
|
+
canvas,
|
|
4375
|
+
requiredRoles: summary.requiredRoles,
|
|
4376
|
+
themeObject
|
|
4377
|
+
};
|
|
4378
|
+
if (selection.blocks !== false)
|
|
4379
|
+
for (const entry of entries) {
|
|
4380
|
+
if (!entry.edges.includes(edge)) continue;
|
|
4381
|
+
cases.push({
|
|
4382
|
+
...shared,
|
|
4383
|
+
id: `${stem(summary.template)}/${entry.name}@${edge}/${theme}/${font}/${canvas}`,
|
|
4384
|
+
block: entry.name,
|
|
4385
|
+
document: summary.format === "docx" ? blockCaseDocument(
|
|
4386
|
+
definitions,
|
|
4387
|
+
entry.name,
|
|
4388
|
+
edge,
|
|
4389
|
+
theme,
|
|
4390
|
+
conditions2
|
|
4391
|
+
) : deckBlockCaseDocument(
|
|
4392
|
+
source.document,
|
|
4393
|
+
definitions,
|
|
4394
|
+
entry.name,
|
|
4395
|
+
edge,
|
|
4396
|
+
theme,
|
|
4397
|
+
conditions2
|
|
4398
|
+
)
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
if (selection.report !== false && withSlots)
|
|
4402
|
+
cases.push({
|
|
4403
|
+
...shared,
|
|
4404
|
+
id: `${stem(summary.template)}/report@${edge}/${theme}/${font}/${canvas}`,
|
|
4405
|
+
block: "report",
|
|
4406
|
+
document: summary.format === "docx" ? reportCaseDocument(
|
|
4407
|
+
source.document,
|
|
4408
|
+
edge,
|
|
4409
|
+
theme,
|
|
4410
|
+
conditions2
|
|
4411
|
+
) : deckReportCaseDocument(
|
|
4412
|
+
source.document,
|
|
4413
|
+
edge,
|
|
4414
|
+
theme,
|
|
4415
|
+
conditions2
|
|
4416
|
+
)
|
|
4417
|
+
});
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
return cases;
|
|
4421
|
+
}
|
|
3885
4422
|
export {
|
|
3886
4423
|
DocxFormatAdapter,
|
|
3887
4424
|
FALLBACK_FONTS,
|
|
@@ -3891,6 +4428,8 @@ export {
|
|
|
3891
4428
|
MATRIX_IMAGE,
|
|
3892
4429
|
MacOSCoreTextStager,
|
|
3893
4430
|
NoopFontStager,
|
|
4431
|
+
PPTX_CANVAS_SIZE,
|
|
4432
|
+
PPTX_FALLBACK_FONTS,
|
|
3894
4433
|
PptxFormatAdapter,
|
|
3895
4434
|
RENDERED_QUALITY_RULES,
|
|
3896
4435
|
VISIBLE_SPILL_PT,
|
|
@@ -3901,10 +4440,14 @@ export {
|
|
|
3901
4440
|
blockCaseDocument,
|
|
3902
4441
|
boundaryInvocation,
|
|
3903
4442
|
boundarySlotValue,
|
|
4443
|
+
buildMatrixInventory,
|
|
3904
4444
|
clearRasterizerCache,
|
|
3905
4445
|
createAdapter,
|
|
3906
4446
|
createLibreOfficePptxBatchRasterizer,
|
|
3907
4447
|
createLibreOfficePptxRasterizer,
|
|
4448
|
+
deckBlockCaseDocument,
|
|
4449
|
+
deckReportCaseDocument,
|
|
4450
|
+
describeInventory,
|
|
3908
4451
|
emitDiagnostic,
|
|
3909
4452
|
enumerateBlockDefinitions,
|
|
3910
4453
|
extractPdfFonts,
|
|
@@ -3912,9 +4455,12 @@ export {
|
|
|
3912
4455
|
extractPdfTextGeometry,
|
|
3913
4456
|
familyRendered,
|
|
3914
4457
|
generateBlockMatrix,
|
|
4458
|
+
generateMatrixCases,
|
|
3915
4459
|
getFontStager,
|
|
3916
4460
|
getRasterizerCacheStats,
|
|
3917
4461
|
inkedRows,
|
|
4462
|
+
inventoryGaps,
|
|
4463
|
+
matrixUniverse,
|
|
3918
4464
|
normalizeForMatch,
|
|
3919
4465
|
overBudgetInvocation,
|
|
3920
4466
|
pageInkFromPgm,
|
|
@@ -3929,6 +4475,7 @@ export {
|
|
|
3929
4475
|
requestedFontsFromFacts,
|
|
3930
4476
|
runWithDiagnosticSink,
|
|
3931
4477
|
stderrDiagnosticSink,
|
|
4478
|
+
templateFormat,
|
|
3932
4479
|
widestNumber
|
|
3933
4480
|
};
|
|
3934
4481
|
//# sourceMappingURL=index.js.map
|