@json-to-office/core-docx 2.6.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blocks/document.d.ts +16 -0
- package/dist/blocks/document.d.ts.map +1 -0
- package/dist/blocks/index.d.ts +1 -57
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/core/generationContext.d.ts +3 -0
- package/dist/core/generationContext.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +322 -234
- package/dist/index.js.map +1 -1
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.js +317 -227
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/plugin/types.d.ts +2 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/quality/facts.d.ts +2 -2
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/blocks/keyTakeaways.d.ts +0 -20
- package/dist/blocks/keyTakeaways.d.ts.map +0 -1
- package/dist/blocks/types.d.ts +0 -15
- package/dist/blocks/types.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -8454,210 +8454,6 @@ function emptyToUndefined(formatting) {
|
|
|
8454
8454
|
return entries.length === 0 ? void 0 : Object.fromEntries(entries);
|
|
8455
8455
|
}
|
|
8456
8456
|
|
|
8457
|
-
// src/blocks/index.ts
|
|
8458
|
-
import { KEY_TAKEAWAYS_BUDGET } from "@json-to-office/shared-docx";
|
|
8459
|
-
|
|
8460
|
-
// src/blocks/keyTakeaways.ts
|
|
8461
|
-
var MIN_RULE_PT = 0.25;
|
|
8462
|
-
var MAX_RULE_PT = 12;
|
|
8463
|
-
var KEY_TAKEAWAYS_DEFAULT_LABEL = "Key takeaways";
|
|
8464
|
-
var FALLBACK_RECIPE = {
|
|
8465
|
-
ruleWeightPt: 1.5,
|
|
8466
|
-
ruleColor: "accent",
|
|
8467
|
-
padPt: 6,
|
|
8468
|
-
type: "label"
|
|
8469
|
-
};
|
|
8470
|
-
function compileKeyTakeaways(props, theme) {
|
|
8471
|
-
const recipe = theme.chrome?.keyTakeaways;
|
|
8472
|
-
const labelRole = recipe?.type ?? FALLBACK_RECIPE.type;
|
|
8473
|
-
const labelStyle = theme.styles?.[labelRole];
|
|
8474
|
-
const ruleWeightPt = Math.min(
|
|
8475
|
-
MAX_RULE_PT,
|
|
8476
|
-
Math.max(
|
|
8477
|
-
MIN_RULE_PT,
|
|
8478
|
-
recipe?.rule?.weightPt ?? FALLBACK_RECIPE.ruleWeightPt
|
|
8479
|
-
)
|
|
8480
|
-
);
|
|
8481
|
-
const ruleColor = recipe?.rule?.color ?? recipe?.color ?? FALLBACK_RECIPE.ruleColor;
|
|
8482
|
-
const padPt = recipe?.padPt ?? FALLBACK_RECIPE.padPt;
|
|
8483
|
-
const children = [
|
|
8484
|
-
{
|
|
8485
|
-
name: "divider",
|
|
8486
|
-
props: {
|
|
8487
|
-
thickness: ruleWeightPt,
|
|
8488
|
-
color: ruleColor,
|
|
8489
|
-
spacing: { before: 12, after: padPt }
|
|
8490
|
-
}
|
|
8491
|
-
},
|
|
8492
|
-
{
|
|
8493
|
-
name: "paragraph",
|
|
8494
|
-
props: {
|
|
8495
|
-
text: props.label ?? KEY_TAKEAWAYS_DEFAULT_LABEL,
|
|
8496
|
-
keepNext: true,
|
|
8497
|
-
spacing: { after: 4 },
|
|
8498
|
-
// The label role when the theme resolves one; a bold run in the
|
|
8499
|
-
// recipe's colour otherwise, so the label still reads as a label.
|
|
8500
|
-
...labelStyle ? { themeStyle: labelRole } : {
|
|
8501
|
-
font: {
|
|
8502
|
-
bold: true,
|
|
8503
|
-
...recipe?.color !== void 0 && { color: recipe.color }
|
|
8504
|
-
}
|
|
8505
|
-
}
|
|
8506
|
-
}
|
|
8507
|
-
},
|
|
8508
|
-
{
|
|
8509
|
-
name: "list",
|
|
8510
|
-
props: { items: [...props.items] }
|
|
8511
|
-
},
|
|
8512
|
-
{
|
|
8513
|
-
name: "divider",
|
|
8514
|
-
props: {
|
|
8515
|
-
thickness: 0.5,
|
|
8516
|
-
color: "borderPrimary",
|
|
8517
|
-
spacing: { before: padPt, after: 12 }
|
|
8518
|
-
}
|
|
8519
|
-
}
|
|
8520
|
-
];
|
|
8521
|
-
return {
|
|
8522
|
-
children,
|
|
8523
|
-
sourceMap: {
|
|
8524
|
-
"/children/0": "",
|
|
8525
|
-
"/children/1": "",
|
|
8526
|
-
"/children/1/props/text": "/props/label",
|
|
8527
|
-
"/children/2": "",
|
|
8528
|
-
"/children/2/props/items": "/props/items",
|
|
8529
|
-
"/children/3": ""
|
|
8530
|
-
}
|
|
8531
|
-
};
|
|
8532
|
-
}
|
|
8533
|
-
|
|
8534
|
-
// src/blocks/index.ts
|
|
8535
|
-
var BLOCK_NAMES = ["key-takeaways"];
|
|
8536
|
-
var BLOCKS = {
|
|
8537
|
-
"key-takeaways": {
|
|
8538
|
-
compile: (props, theme) => compileKeyTakeaways(props, theme),
|
|
8539
|
-
budgets: (props, pointer) => (Array.isArray(props.items) ? props.items : []).flatMap(
|
|
8540
|
-
(item, index) => typeof item === "string" ? [
|
|
8541
|
-
{
|
|
8542
|
-
block: "key-takeaways",
|
|
8543
|
-
slot: "items",
|
|
8544
|
-
path: `${pointer}/props/items/${index}`,
|
|
8545
|
-
words: wordCount(item),
|
|
8546
|
-
maxWords: KEY_TAKEAWAYS_BUDGET.items.maxWords
|
|
8547
|
-
}
|
|
8548
|
-
] : []
|
|
8549
|
-
)
|
|
8550
|
-
}
|
|
8551
|
-
};
|
|
8552
|
-
function isBlockName(name) {
|
|
8553
|
-
return BLOCK_NAMES.includes(name);
|
|
8554
|
-
}
|
|
8555
|
-
function isRecord(value) {
|
|
8556
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8557
|
-
}
|
|
8558
|
-
function expandBlocks(document, theme) {
|
|
8559
|
-
const sourceMap = {};
|
|
8560
|
-
const blocks = [];
|
|
8561
|
-
const walk2 = (node, pointer) => {
|
|
8562
|
-
if (Array.isArray(node)) {
|
|
8563
|
-
return node.map((child, index) => walk2(child, `${pointer}/${index}`));
|
|
8564
|
-
}
|
|
8565
|
-
if (!isRecord(node)) return node;
|
|
8566
|
-
if (typeof node.name === "string" && isRecord(node.props)) {
|
|
8567
|
-
if (node.enabled !== false && isBlockName(node.name)) {
|
|
8568
|
-
const compiled = BLOCKS[node.name].compile(node.props, theme);
|
|
8569
|
-
blocks.push(pointer);
|
|
8570
|
-
for (const [emitted, authored] of Object.entries(compiled.sourceMap)) {
|
|
8571
|
-
sourceMap[`${pointer}${emitted}`] = `${pointer}${authored}`;
|
|
8572
|
-
}
|
|
8573
|
-
return { ...node, children: compiled.children };
|
|
8574
|
-
}
|
|
8575
|
-
}
|
|
8576
|
-
const next = { ...node };
|
|
8577
|
-
if (isRecord(node.props)) {
|
|
8578
|
-
const props = { ...node.props };
|
|
8579
|
-
let changed = false;
|
|
8580
|
-
for (const key of ["header", "footer"]) {
|
|
8581
|
-
if (Array.isArray(props[key])) {
|
|
8582
|
-
props[key] = walk2(props[key], `${pointer}/props/${key}`);
|
|
8583
|
-
changed = true;
|
|
8584
|
-
}
|
|
8585
|
-
}
|
|
8586
|
-
if (Array.isArray(props.columns)) {
|
|
8587
|
-
props.columns = props.columns.map((column, index) => {
|
|
8588
|
-
if (!isRecord(column)) return column;
|
|
8589
|
-
const base = `${pointer}/props/columns/${index}`;
|
|
8590
|
-
const out = { ...column };
|
|
8591
|
-
if (isRecord(column.header) && "content" in column.header) {
|
|
8592
|
-
out.header = {
|
|
8593
|
-
...column.header,
|
|
8594
|
-
content: walk2(column.header.content, `${base}/header/content`)
|
|
8595
|
-
};
|
|
8596
|
-
}
|
|
8597
|
-
if (Array.isArray(column.cells)) {
|
|
8598
|
-
out.cells = column.cells.map(
|
|
8599
|
-
(cell, cellIndex) => isRecord(cell) && "content" in cell ? {
|
|
8600
|
-
...cell,
|
|
8601
|
-
content: walk2(
|
|
8602
|
-
cell.content,
|
|
8603
|
-
`${base}/cells/${cellIndex}/content`
|
|
8604
|
-
)
|
|
8605
|
-
} : cell
|
|
8606
|
-
);
|
|
8607
|
-
}
|
|
8608
|
-
return out;
|
|
8609
|
-
});
|
|
8610
|
-
changed = true;
|
|
8611
|
-
}
|
|
8612
|
-
if (changed) next.props = props;
|
|
8613
|
-
}
|
|
8614
|
-
if (Array.isArray(node.children)) {
|
|
8615
|
-
next.children = walk2(node.children, `${pointer}/children`);
|
|
8616
|
-
}
|
|
8617
|
-
return next;
|
|
8618
|
-
};
|
|
8619
|
-
const expanded = walk2(document, "");
|
|
8620
|
-
return {
|
|
8621
|
-
document: blocks.length > 0 ? expanded : document,
|
|
8622
|
-
sourceMap,
|
|
8623
|
-
blocks
|
|
8624
|
-
};
|
|
8625
|
-
}
|
|
8626
|
-
function toAuthoredPointer(sourceMap, pointer) {
|
|
8627
|
-
let best;
|
|
8628
|
-
for (const emitted of Object.keys(sourceMap)) {
|
|
8629
|
-
if ((pointer === emitted || pointer.startsWith(`${emitted}/`)) && (best === void 0 || emitted.length > best.length)) {
|
|
8630
|
-
best = emitted;
|
|
8631
|
-
}
|
|
8632
|
-
}
|
|
8633
|
-
if (best === void 0) return pointer;
|
|
8634
|
-
return `${sourceMap[best]}${pointer.slice(best.length)}`;
|
|
8635
|
-
}
|
|
8636
|
-
function blockSlotBudgets(document, blocks) {
|
|
8637
|
-
return blocks.flatMap((pointer) => {
|
|
8638
|
-
const node = nodeAt(document, pointer);
|
|
8639
|
-
if (!isRecord(node) || !isRecord(node.props) || !isBlockName(node.name)) {
|
|
8640
|
-
return [];
|
|
8641
|
-
}
|
|
8642
|
-
return BLOCKS[node.name].budgets(node.props, pointer);
|
|
8643
|
-
});
|
|
8644
|
-
}
|
|
8645
|
-
function wordCount(text) {
|
|
8646
|
-
const trimmed = text.trim();
|
|
8647
|
-
return trimmed === "" ? 0 : trimmed.split(/\s+/).length;
|
|
8648
|
-
}
|
|
8649
|
-
function nodeAt(root, pointer) {
|
|
8650
|
-
if (pointer === "") return root;
|
|
8651
|
-
let current = root;
|
|
8652
|
-
for (const segment of pointer.slice(1).split("/")) {
|
|
8653
|
-
const key = segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
8654
|
-
if (Array.isArray(current)) current = current[Number(key)];
|
|
8655
|
-
else if (isRecord(current)) current = current[key];
|
|
8656
|
-
else return void 0;
|
|
8657
|
-
}
|
|
8658
|
-
return current;
|
|
8659
|
-
}
|
|
8660
|
-
|
|
8661
8457
|
// src/ir/compiler.ts
|
|
8662
8458
|
init_types();
|
|
8663
8459
|
init_units();
|
|
@@ -8955,33 +8751,47 @@ function compileChromeParagraph(component, scope) {
|
|
|
8955
8751
|
const text = String(props.text ?? "");
|
|
8956
8752
|
if (reportUnlowered(component, props, text, scope)) return [];
|
|
8957
8753
|
const font = props.font ?? {};
|
|
8958
|
-
const
|
|
8754
|
+
const named = chromeStyle(ctx.theme, props.themeStyle);
|
|
8755
|
+
const base = { ...getNormalStyle(ctx.theme), ...named };
|
|
8756
|
+
const styleId = named ? paragraphStyleId(props.themeStyle) ?? "Normal" : "Normal";
|
|
8757
|
+
if (styleId !== "Normal" && !ctx.styleIds.has(styleId)) {
|
|
8758
|
+
ctx.styleIds.add(styleId);
|
|
8759
|
+
}
|
|
8959
8760
|
const chromeProps = {
|
|
8960
8761
|
text,
|
|
8961
|
-
...
|
|
8762
|
+
...named ? { themeStyle: props.themeStyle } : {},
|
|
8763
|
+
...props.alignment ? { alignment: props.alignment } : named?.alignment ? { alignment: named.alignment } : {},
|
|
8962
8764
|
...props.spacing ? { spacing: props.spacing } : {},
|
|
8765
|
+
...props.indent ? { indent: props.indent } : {},
|
|
8766
|
+
...props.tabStops ? { tabStops: props.tabStops } : {},
|
|
8963
8767
|
...props.boldColor ? { boldColor: props.boldColor } : {},
|
|
8964
8768
|
font: {
|
|
8965
|
-
family: font.family || resolveFontFamily(ctx.theme,
|
|
8966
|
-
size: font.size ??
|
|
8967
|
-
color: font.color ||
|
|
8968
|
-
bold: font.bold ?? false,
|
|
8969
|
-
italic: font.italic ?? false,
|
|
8769
|
+
family: font.family || resolveFontFamily(ctx.theme, base.font) || getThemeFonts(ctx.theme).body.family,
|
|
8770
|
+
size: font.size ?? base.size ?? 11,
|
|
8771
|
+
color: font.color || base.color || "textPrimary",
|
|
8772
|
+
bold: font.bold ?? base.bold ?? false,
|
|
8773
|
+
italic: font.italic ?? base.italic ?? false,
|
|
8970
8774
|
...font.underline !== void 0 ? { underline: font.underline } : {},
|
|
8971
|
-
...font.fontWeight !== void 0 ? { fontWeight: font.fontWeight } : {},
|
|
8972
|
-
...font.case !== void 0 ? { case: font.case } : {},
|
|
8775
|
+
...(font.fontWeight ?? base.fontWeight) !== void 0 ? { fontWeight: font.fontWeight ?? base.fontWeight } : {},
|
|
8776
|
+
...(font.case ?? base.case) !== void 0 ? { case: font.case ?? base.case } : {},
|
|
8777
|
+
...(font.characterSpacing ?? base.characterSpacing) !== void 0 ? { characterSpacing: font.characterSpacing ?? base.characterSpacing } : {},
|
|
8973
8778
|
...font.lineSpacing !== void 0 ? { lineSpacing: font.lineSpacing } : {}
|
|
8974
8779
|
}
|
|
8975
8780
|
};
|
|
8976
8781
|
return [
|
|
8977
8782
|
paragraphNode(scope, compileRuns(chromeProps, text, ctx, scope.path), {
|
|
8978
|
-
styleId
|
|
8783
|
+
styleId,
|
|
8979
8784
|
formatting: paragraphFormatting(chromeProps, ctx, {
|
|
8980
8785
|
alwaysSpacing: true
|
|
8981
8786
|
})
|
|
8982
8787
|
})
|
|
8983
8788
|
];
|
|
8984
8789
|
}
|
|
8790
|
+
function chromeStyle(theme, themeStyle) {
|
|
8791
|
+
if (typeof themeStyle !== "string" || !themeStyle) return void 0;
|
|
8792
|
+
const styles = getThemeStyles(theme);
|
|
8793
|
+
return styles[themeStyle] ?? styles[themeStyle.toLowerCase()];
|
|
8794
|
+
}
|
|
8985
8795
|
function compileChromeImage(component, scope) {
|
|
8986
8796
|
const { ctx, path: path4 } = scope;
|
|
8987
8797
|
const props = component.props ?? {};
|
|
@@ -9069,7 +8879,7 @@ function compileComponent(component, scope) {
|
|
|
9069
8879
|
case "table":
|
|
9070
8880
|
return compileTable(component, scope);
|
|
9071
8881
|
default:
|
|
9072
|
-
if (
|
|
8882
|
+
if (component.name === "group") {
|
|
9073
8883
|
if (component.enabled === false) return [];
|
|
9074
8884
|
return compileBlock(component, scope);
|
|
9075
8885
|
}
|
|
@@ -9081,8 +8891,8 @@ function compileComponent(component, scope) {
|
|
|
9081
8891
|
}
|
|
9082
8892
|
}
|
|
9083
8893
|
function compileBlock(component, scope) {
|
|
9084
|
-
const children = component.children
|
|
9085
|
-
if (children
|
|
8894
|
+
const children = component.children;
|
|
8895
|
+
if (!Array.isArray(children)) {
|
|
9086
8896
|
scope.ctx.unsupported.push({ name: component.name, path: scope.path });
|
|
9087
8897
|
return [];
|
|
9088
8898
|
}
|
|
@@ -12274,6 +12084,204 @@ function normalizeDocument(document) {
|
|
|
12274
12084
|
return [normalized];
|
|
12275
12085
|
}
|
|
12276
12086
|
|
|
12087
|
+
// src/blocks/document.ts
|
|
12088
|
+
init_styles();
|
|
12089
|
+
init_widthUtils();
|
|
12090
|
+
import {
|
|
12091
|
+
JsonBlockEvaluator,
|
|
12092
|
+
BlockEvaluationError,
|
|
12093
|
+
composeBlocksWithPlugins,
|
|
12094
|
+
readBlockDefinitions,
|
|
12095
|
+
blockValueAt,
|
|
12096
|
+
isBlockRecord,
|
|
12097
|
+
toAuthoredBlockPointer
|
|
12098
|
+
} from "@json-to-office/shared";
|
|
12099
|
+
import { blockSlotBudgets } from "@json-to-office/shared";
|
|
12100
|
+
import { validateDocument } from "@json-to-office/shared-docx";
|
|
12101
|
+
var toAuthoredPointer = toAuthoredBlockPointer;
|
|
12102
|
+
function docxBlockContext(document, theme, path4 = "") {
|
|
12103
|
+
const index = /^\/children\/(\d+)/.exec(path4)?.[1];
|
|
12104
|
+
const section2 = index === void 0 ? void 0 : blockValueAt(document, `/children/${index}`);
|
|
12105
|
+
const page = isBlockRecord(section2) && isBlockRecord(section2.props) && isBlockRecord(section2.props.page) ? section2.props.page : {};
|
|
12106
|
+
const margins = getDocumentMargins(theme);
|
|
12107
|
+
const dimensions = getPageDimensions(
|
|
12108
|
+
page.size ?? theme.page.size
|
|
12109
|
+
);
|
|
12110
|
+
const overrides = isBlockRecord(page.margins) ? page.margins : {};
|
|
12111
|
+
const width = Object.keys(page).length ? Math.max(
|
|
12112
|
+
0,
|
|
12113
|
+
dimensions.width - Number(overrides.left ?? margins.left ?? 1440) - Number(overrides.right ?? margins.right ?? 1440)
|
|
12114
|
+
) : getAvailableWidthTwips(theme);
|
|
12115
|
+
const height = Object.keys(page).length ? Math.max(
|
|
12116
|
+
0,
|
|
12117
|
+
dimensions.height - Number(overrides.top ?? margins.top ?? 1440) - Number(overrides.bottom ?? margins.bottom ?? 1440)
|
|
12118
|
+
) : getAvailableHeightTwips(theme);
|
|
12119
|
+
return {
|
|
12120
|
+
document: blockValueAt(document, "/props/metadata") ?? {},
|
|
12121
|
+
page: { width, height },
|
|
12122
|
+
section: {}
|
|
12123
|
+
};
|
|
12124
|
+
}
|
|
12125
|
+
function createDocxBlockEvaluator(document, theme, extra = {}) {
|
|
12126
|
+
return new JsonBlockEvaluator(readBlockDefinitions(document), {
|
|
12127
|
+
format: "docx",
|
|
12128
|
+
theme,
|
|
12129
|
+
contextAt: (path4) => docxBlockContext(document, theme, path4),
|
|
12130
|
+
contextSources: { "/document": "/props/metadata" },
|
|
12131
|
+
measure: (axis, unit, context) => Number(blockValueAt(context, `/page/${axis}`)) / (unit === "twip" ? 1 : unit === "in" ? 1440 : 20),
|
|
12132
|
+
...extra
|
|
12133
|
+
});
|
|
12134
|
+
}
|
|
12135
|
+
function expandBlocks(document, theme) {
|
|
12136
|
+
const effects = [];
|
|
12137
|
+
const evaluator = createDocxBlockEvaluator(document, theme, {
|
|
12138
|
+
onSection: (effect) => effects.push(effect)
|
|
12139
|
+
});
|
|
12140
|
+
const expanded = evaluator.expand(document);
|
|
12141
|
+
return finishDocxBlocks(expanded, document, theme, evaluator, effects);
|
|
12142
|
+
}
|
|
12143
|
+
function validateEffects(document, effects) {
|
|
12144
|
+
for (const effect of effects) {
|
|
12145
|
+
const parts = effect.path.split("/").slice(1);
|
|
12146
|
+
const section2 = blockValueAt(document, "/" + parts.slice(0, 2).join("/"));
|
|
12147
|
+
let valid = parts.length >= 4 && parts[0] === "children" && parts[2] === "children" && isBlockRecord(section2) && section2.name === "section";
|
|
12148
|
+
for (let i = 4; i < parts.length; i += 2) {
|
|
12149
|
+
const parent = blockValueAt(document, "/" + parts.slice(0, i).join("/"));
|
|
12150
|
+
valid &&= parts[i] === "children" && isBlockRecord(parent) && parent.name === "group";
|
|
12151
|
+
}
|
|
12152
|
+
if (!valid)
|
|
12153
|
+
throw new BlockEvaluationError([
|
|
12154
|
+
{
|
|
12155
|
+
path: effect.environment.source,
|
|
12156
|
+
code: "invalid_placement",
|
|
12157
|
+
message: "Section effects require a block in a top-level section body, optionally nested in transparent groups."
|
|
12158
|
+
}
|
|
12159
|
+
]);
|
|
12160
|
+
}
|
|
12161
|
+
}
|
|
12162
|
+
function finishDocxBlocks(expanded, document, theme, evaluator, effects, validate = true) {
|
|
12163
|
+
if (isBlockRecord(expanded) && Array.isArray(expanded.children)) {
|
|
12164
|
+
let inherited;
|
|
12165
|
+
expanded.children.forEach((section2, index) => {
|
|
12166
|
+
if (!isBlockRecord(section2) || section2.name !== "section" || section2.enabled === false)
|
|
12167
|
+
return;
|
|
12168
|
+
const path4 = `/children/${index}`;
|
|
12169
|
+
const local = effects.filter(
|
|
12170
|
+
(e) => e.path.startsWith(`${path4}/children/`)
|
|
12171
|
+
);
|
|
12172
|
+
let tracker;
|
|
12173
|
+
let trackerSource = path4;
|
|
12174
|
+
for (const effect of local) {
|
|
12175
|
+
if (effect.settings.tracker !== void 0) {
|
|
12176
|
+
tracker = evaluator.evaluate(
|
|
12177
|
+
effect.settings.tracker,
|
|
12178
|
+
effect.environment,
|
|
12179
|
+
`${path4}/props/tracker`,
|
|
12180
|
+
`${effect.environment.definition}/section/tracker`
|
|
12181
|
+
);
|
|
12182
|
+
trackerSource = toAuthoredPointer(
|
|
12183
|
+
evaluator.sourceMap,
|
|
12184
|
+
`${path4}/props/tracker`
|
|
12185
|
+
);
|
|
12186
|
+
}
|
|
12187
|
+
}
|
|
12188
|
+
let chrome = inherited;
|
|
12189
|
+
for (const effect of local) {
|
|
12190
|
+
if (effect.settings.header !== void 0 || effect.settings.footer !== void 0) {
|
|
12191
|
+
chrome = effect;
|
|
12192
|
+
if (effect.settings.scope === "following") inherited = effect;
|
|
12193
|
+
}
|
|
12194
|
+
}
|
|
12195
|
+
const props = isBlockRecord(section2.props) ? { ...section2.props } : {};
|
|
12196
|
+
if (chrome) {
|
|
12197
|
+
const environment = {
|
|
12198
|
+
...chrome.environment,
|
|
12199
|
+
context: {
|
|
12200
|
+
...docxBlockContext(document, theme, path4),
|
|
12201
|
+
section: { tracker }
|
|
12202
|
+
},
|
|
12203
|
+
contextSources: {
|
|
12204
|
+
"/document": "/props/metadata",
|
|
12205
|
+
"/section/tracker": trackerSource
|
|
12206
|
+
}
|
|
12207
|
+
};
|
|
12208
|
+
for (const part of ["header", "footer"]) {
|
|
12209
|
+
if (props[part] !== void 0 || chrome.settings[part] === void 0)
|
|
12210
|
+
continue;
|
|
12211
|
+
const compiled = evaluator.evaluate(
|
|
12212
|
+
chrome.settings[part],
|
|
12213
|
+
environment,
|
|
12214
|
+
`${path4}/props/${part}`,
|
|
12215
|
+
`${environment.definition}/section/${part}`
|
|
12216
|
+
);
|
|
12217
|
+
props[part] = evaluator.expand(compiled, `${path4}/props/${part}`);
|
|
12218
|
+
}
|
|
12219
|
+
if (props.pageBreak === void 0)
|
|
12220
|
+
props.pageBreak = chrome.settings.pageBreak ?? true;
|
|
12221
|
+
}
|
|
12222
|
+
for (const effect of local)
|
|
12223
|
+
if (effect.settings.pageBreak !== void 0 && props.pageBreak === void 0)
|
|
12224
|
+
props.pageBreak = effect.settings.pageBreak;
|
|
12225
|
+
section2.props = props;
|
|
12226
|
+
});
|
|
12227
|
+
}
|
|
12228
|
+
validateEffects(expanded, effects);
|
|
12229
|
+
if (evaluator.blocks.length && validate) {
|
|
12230
|
+
const result = validateDocument(expanded);
|
|
12231
|
+
if (!result.valid)
|
|
12232
|
+
throw new BlockEvaluationError(
|
|
12233
|
+
result.errors.map((issue) => ({
|
|
12234
|
+
path: toAuthoredPointer(evaluator.sourceMap, issue.path),
|
|
12235
|
+
code: issue.code ?? "block_invalid_output",
|
|
12236
|
+
message: issue.message
|
|
12237
|
+
}))
|
|
12238
|
+
);
|
|
12239
|
+
}
|
|
12240
|
+
return {
|
|
12241
|
+
document: expanded,
|
|
12242
|
+
sourceMap: evaluator.sourceMap,
|
|
12243
|
+
blocks: evaluator.blocks
|
|
12244
|
+
};
|
|
12245
|
+
}
|
|
12246
|
+
async function expandBlocksWithPlugins(document, theme, plugins, render, preserve = /* @__PURE__ */ new Set()) {
|
|
12247
|
+
const effects = [];
|
|
12248
|
+
const evaluator = createDocxBlockEvaluator(document, theme, {
|
|
12249
|
+
reservedNames: [...plugins],
|
|
12250
|
+
onSection: (effect) => effects.push(effect)
|
|
12251
|
+
});
|
|
12252
|
+
const walk2 = (value) => composeBlocksWithPlugins(evaluator, value, {
|
|
12253
|
+
plugins,
|
|
12254
|
+
render,
|
|
12255
|
+
preserve
|
|
12256
|
+
});
|
|
12257
|
+
const first = await walk2(document);
|
|
12258
|
+
const finished = finishDocxBlocks(
|
|
12259
|
+
first.standard,
|
|
12260
|
+
document,
|
|
12261
|
+
theme,
|
|
12262
|
+
evaluator,
|
|
12263
|
+
effects,
|
|
12264
|
+
false
|
|
12265
|
+
);
|
|
12266
|
+
const second = await walk2(finished.document);
|
|
12267
|
+
validateEffects(second.standard, effects);
|
|
12268
|
+
const result = validateDocument(second.standard);
|
|
12269
|
+
if (!result.valid)
|
|
12270
|
+
throw new BlockEvaluationError(
|
|
12271
|
+
result.errors.map((issue) => ({
|
|
12272
|
+
path: toAuthoredPointer(evaluator.sourceMap, issue.path),
|
|
12273
|
+
code: issue.code ?? "block_invalid_output",
|
|
12274
|
+
message: issue.message
|
|
12275
|
+
}))
|
|
12276
|
+
);
|
|
12277
|
+
return {
|
|
12278
|
+
document: second.standard,
|
|
12279
|
+
preserved: first.preserved,
|
|
12280
|
+
sourceMap: evaluator.sourceMap,
|
|
12281
|
+
blocks: evaluator.blocks
|
|
12282
|
+
};
|
|
12283
|
+
}
|
|
12284
|
+
|
|
12277
12285
|
// src/quality/facts.ts
|
|
12278
12286
|
init_styleHelpers();
|
|
12279
12287
|
init_defaults();
|
|
@@ -12716,7 +12724,10 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12716
12724
|
const facts = [];
|
|
12717
12725
|
const provenance = {};
|
|
12718
12726
|
let previousHeadingLevel;
|
|
12719
|
-
const authoredPath = (path4) => toAuthoredPointer(
|
|
12727
|
+
const authoredPath = (path4) => toAuthoredPointer(
|
|
12728
|
+
themed.sourceMap ?? {},
|
|
12729
|
+
toAuthoredPointer(expanded.sourceMap, path4)
|
|
12730
|
+
);
|
|
12720
12731
|
const addFact = (raw) => {
|
|
12721
12732
|
const fact = {
|
|
12722
12733
|
...raw,
|
|
@@ -12731,7 +12742,7 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12731
12742
|
...fact.relatedPaths && { relatedPaths: fact.relatedPaths }
|
|
12732
12743
|
};
|
|
12733
12744
|
};
|
|
12734
|
-
for (const budget of blockSlotBudgets(
|
|
12745
|
+
for (const budget of blockSlotBudgets(themed.document, expanded.blocks)) {
|
|
12735
12746
|
addFact({
|
|
12736
12747
|
id: `docx:block-slot:${budget.path}`,
|
|
12737
12748
|
kind: "docx/block-slot",
|
|
@@ -12881,11 +12892,19 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12881
12892
|
facts,
|
|
12882
12893
|
provenance,
|
|
12883
12894
|
renderer: options.renderer ?? DEFAULT_DOCX_RENDERER_ID2,
|
|
12884
|
-
...expanded.blocks.length > 0 && {
|
|
12895
|
+
...(expanded.blocks.length > 0 || (themed.blockPaths?.length ?? 0) > 0) && {
|
|
12885
12896
|
metadata: {
|
|
12886
12897
|
blocks: {
|
|
12887
|
-
sourceMap:
|
|
12888
|
-
|
|
12898
|
+
sourceMap: {
|
|
12899
|
+
...themed.sourceMap,
|
|
12900
|
+
...Object.fromEntries(
|
|
12901
|
+
Object.entries(expanded.sourceMap).map(([key, value]) => [
|
|
12902
|
+
key,
|
|
12903
|
+
toAuthoredPointer(themed.sourceMap ?? {}, value)
|
|
12904
|
+
])
|
|
12905
|
+
)
|
|
12906
|
+
},
|
|
12907
|
+
blocks: [...themed.blockPaths ?? [], ...expanded.blocks],
|
|
12889
12908
|
document: context.document
|
|
12890
12909
|
}
|
|
12891
12910
|
}
|
|
@@ -14315,7 +14334,7 @@ function validateComponentProps(schema, props, componentName, opts) {
|
|
|
14315
14334
|
componentName
|
|
14316
14335
|
});
|
|
14317
14336
|
}
|
|
14318
|
-
function
|
|
14337
|
+
function validateDocument2(document, customComponents, options) {
|
|
14319
14338
|
const knownCustomNames = new Set(customComponents.map((c) => c.name));
|
|
14320
14339
|
const documentResult = validateDocumentUnified(document, {
|
|
14321
14340
|
knownCustomNames,
|
|
@@ -14719,7 +14738,7 @@ function createBuilderImpl(state) {
|
|
|
14719
14738
|
...options?.validation
|
|
14720
14739
|
};
|
|
14721
14740
|
if (vOpts.enabled !== false) {
|
|
14722
|
-
const result =
|
|
14741
|
+
const result = validateDocument2(
|
|
14723
14742
|
validationDocument,
|
|
14724
14743
|
state.components,
|
|
14725
14744
|
{ allowUnknownFields: vOpts.allowUnknownFields }
|
|
@@ -14734,12 +14753,12 @@ function createBuilderImpl(state) {
|
|
|
14734
14753
|
);
|
|
14735
14754
|
}
|
|
14736
14755
|
}
|
|
14737
|
-
const validateEmitted = vOpts.enabled === false ? void 0 : (emitted, componentLabel) => {
|
|
14738
|
-
const result =
|
|
14756
|
+
const validateEmitted = vOpts.enabled === false ? void 0 : (emitted, componentLabel, sourcePath) => {
|
|
14757
|
+
const result = validateDocument2(
|
|
14739
14758
|
{
|
|
14740
14759
|
...internalDocument,
|
|
14741
14760
|
...renderer !== void 0 ? { renderer } : {},
|
|
14742
|
-
children: emitted
|
|
14761
|
+
children: sourcePath === void 0 ? emitted : [{ name: "section", props: {}, children: emitted }]
|
|
14743
14762
|
},
|
|
14744
14763
|
state.components,
|
|
14745
14764
|
{ allowUnknownFields: vOpts.allowUnknownFields }
|
|
@@ -14747,7 +14766,10 @@ function createBuilderImpl(state) {
|
|
|
14747
14766
|
if (!result.valid) {
|
|
14748
14767
|
throw new ComponentValidationError2(
|
|
14749
14768
|
(result.errors ?? []).map((e) => ({
|
|
14750
|
-
path: e.path ?? ""
|
|
14769
|
+
path: sourcePath === void 0 ? e.path ?? "" : (e.path ?? "").replace(
|
|
14770
|
+
/^\/children\/0\/children\/\d+/,
|
|
14771
|
+
sourcePath
|
|
14772
|
+
),
|
|
14751
14773
|
message: `custom component '${componentLabel}' emitted invalid output \u2014 ${e.message}`
|
|
14752
14774
|
})),
|
|
14753
14775
|
emitted
|
|
@@ -14765,6 +14787,62 @@ function createBuilderImpl(state) {
|
|
|
14765
14787
|
warnings,
|
|
14766
14788
|
resolveNamedTheme: resolveDocumentTheme
|
|
14767
14789
|
});
|
|
14790
|
+
if (modedRoot.props.blocks !== void 0) {
|
|
14791
|
+
const expanded = await expandBlocksWithPlugins(
|
|
14792
|
+
modedRoot,
|
|
14793
|
+
modedTheme,
|
|
14794
|
+
new Set(componentMap.keys()),
|
|
14795
|
+
async (component, path4) => {
|
|
14796
|
+
const custom = componentMap.get(String(component.name));
|
|
14797
|
+
const version = resolveComponentVersion(
|
|
14798
|
+
custom.name,
|
|
14799
|
+
custom.versions,
|
|
14800
|
+
component.version
|
|
14801
|
+
);
|
|
14802
|
+
const checked = validateComponentProps(
|
|
14803
|
+
version,
|
|
14804
|
+
component.props ?? {},
|
|
14805
|
+
custom.name,
|
|
14806
|
+
{ clean: vOpts.allowUnknownFields === true }
|
|
14807
|
+
);
|
|
14808
|
+
if (!checked.valid)
|
|
14809
|
+
throw new ComponentValidationError2(
|
|
14810
|
+
(checked.errors ?? []).map((e) => ({ path: path4, message: e.message })),
|
|
14811
|
+
component
|
|
14812
|
+
);
|
|
14813
|
+
const output = await version.render({
|
|
14814
|
+
props: cleanComponentProps(version, component.props ?? {}),
|
|
14815
|
+
theme: modedTheme,
|
|
14816
|
+
children: component.children,
|
|
14817
|
+
addWarning: (message, context) => warnings.push({
|
|
14818
|
+
component: custom.name,
|
|
14819
|
+
message,
|
|
14820
|
+
severity: "warning",
|
|
14821
|
+
context
|
|
14822
|
+
})
|
|
14823
|
+
});
|
|
14824
|
+
const emitted = Array.isArray(output) ? output : [output];
|
|
14825
|
+
validateEmitted?.(emitted, custom.name, path4);
|
|
14826
|
+
return emitted;
|
|
14827
|
+
},
|
|
14828
|
+
preserveSet
|
|
14829
|
+
);
|
|
14830
|
+
const [modedDoc2] = normalizeDocument(expanded.document);
|
|
14831
|
+
return {
|
|
14832
|
+
modedRoot,
|
|
14833
|
+
modedTheme,
|
|
14834
|
+
themeName,
|
|
14835
|
+
modedDoc: modedDoc2,
|
|
14836
|
+
sourceMap: expanded.sourceMap,
|
|
14837
|
+
blockPaths: expanded.blocks,
|
|
14838
|
+
warnings,
|
|
14839
|
+
preserveSet,
|
|
14840
|
+
processed: {
|
|
14841
|
+
standard: modedDoc2.children ?? [],
|
|
14842
|
+
preserved: expanded.preserved.children ?? []
|
|
14843
|
+
}
|
|
14844
|
+
};
|
|
14845
|
+
}
|
|
14768
14846
|
const processed = await processDocumentComponents(
|
|
14769
14847
|
modedRoot.children || [],
|
|
14770
14848
|
preserveSet,
|
|
@@ -14789,9 +14867,13 @@ function createBuilderImpl(state) {
|
|
|
14789
14867
|
}
|
|
14790
14868
|
async function expandStandardDefinition(document, options) {
|
|
14791
14869
|
try {
|
|
14792
|
-
const { modedDoc, warnings } = await expandDocument(
|
|
14870
|
+
const { modedDoc, warnings, sourceMap } = await expandDocument(
|
|
14871
|
+
document,
|
|
14872
|
+
options
|
|
14873
|
+
);
|
|
14793
14874
|
return {
|
|
14794
14875
|
standardDefinition: modedDoc,
|
|
14876
|
+
...sourceMap && { sourceMap },
|
|
14795
14877
|
warnings: warnings.length > 0 ? warnings : null
|
|
14796
14878
|
};
|
|
14797
14879
|
} catch (error) {
|
|
@@ -14809,6 +14891,8 @@ function createBuilderImpl(state) {
|
|
|
14809
14891
|
themeName,
|
|
14810
14892
|
processed,
|
|
14811
14893
|
modedDoc,
|
|
14894
|
+
sourceMap,
|
|
14895
|
+
blockPaths,
|
|
14812
14896
|
warnings,
|
|
14813
14897
|
preserveSet
|
|
14814
14898
|
} = await expandDocument(document, options);
|
|
@@ -14819,7 +14903,13 @@ function createBuilderImpl(state) {
|
|
|
14819
14903
|
const { buffer } = await generateBufferViaIr(modedDoc, {
|
|
14820
14904
|
// The prologue already ran: the theme had to be resolved before custom
|
|
14821
14905
|
// components expanded, because each one's `render` is handed it.
|
|
14822
|
-
context: {
|
|
14906
|
+
context: {
|
|
14907
|
+
document: modedDoc,
|
|
14908
|
+
theme: modedTheme,
|
|
14909
|
+
themeName,
|
|
14910
|
+
...sourceMap !== void 0 && { sourceMap },
|
|
14911
|
+
...blockPaths !== void 0 && { blockPaths }
|
|
14912
|
+
},
|
|
14823
14913
|
...state.services ? { services: state.services } : {},
|
|
14824
14914
|
...state.fonts ? { fonts: state.fonts } : {},
|
|
14825
14915
|
...baseDir !== void 0 ? { baseDir } : {},
|
|
@@ -14876,7 +14966,7 @@ function createBuilderImpl(state) {
|
|
|
14876
14966
|
function validate(document) {
|
|
14877
14967
|
try {
|
|
14878
14968
|
const internalDocument = document;
|
|
14879
|
-
const result =
|
|
14969
|
+
const result = validateDocument2(
|
|
14880
14970
|
internalDocument,
|
|
14881
14971
|
state.components
|
|
14882
14972
|
);
|
|
@@ -14955,7 +15045,6 @@ function getCoreVersion() {
|
|
|
14955
15045
|
return "Core v1.0.0";
|
|
14956
15046
|
}
|
|
14957
15047
|
export {
|
|
14958
|
-
BLOCK_NAMES,
|
|
14959
15048
|
ComponentValidationError2 as ComponentValidationError,
|
|
14960
15049
|
DocumentGenerator as CoreDocumentGenerator,
|
|
14961
15050
|
DEFAULT_DOCX_RENDERER_ID,
|
|
@@ -14970,7 +15059,6 @@ export {
|
|
|
14970
15059
|
analyzeDocxQuality,
|
|
14971
15060
|
blockSlotBudgets,
|
|
14972
15061
|
cleanComponentProps,
|
|
14973
|
-
compileKeyTakeaways,
|
|
14974
15062
|
consultingTheme,
|
|
14975
15063
|
createComponent,
|
|
14976
15064
|
createDocumentGenerator,
|
|
@@ -15027,7 +15115,7 @@ export {
|
|
|
15027
15115
|
themes,
|
|
15028
15116
|
toAuthoredPointer,
|
|
15029
15117
|
validateComponentProps,
|
|
15030
|
-
validateDocument,
|
|
15118
|
+
validateDocument2 as validateDocument,
|
|
15031
15119
|
validateJsonSchema,
|
|
15032
15120
|
validateThemeJsonString,
|
|
15033
15121
|
vermilionTheme
|