@json-to-office/core-docx 3.3.0 → 4.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/index.js +353 -4
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +166 -1
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +26 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/rules.d.ts +38 -1
- package/dist/quality/rules.d.ts.map +1 -1
- package/dist/templates/themes/consulting.docx.theme.json +1 -0
- package/dist/templates/themes/devportal.docx.theme.json +1 -0
- package/dist/templates/themes/index.d.ts +5 -0
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/templates/themes/minimal.docx.theme.json +1 -0
- package/dist/templates/themes/vermilion.docx.theme.json +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -193,6 +193,7 @@ var init_minimal_docx_theme = __esm({
|
|
|
193
193
|
name: "minimal",
|
|
194
194
|
displayName: "Minimal Clean",
|
|
195
195
|
description: "A quiet, warm minimal theme \u2014 Calibri throughout, sage-green ink on ivory neutrals, a large tracked-tight bold title, wide margins and hairline rules",
|
|
196
|
+
whenToUse: "Quiet documents where the type carries the tone: notes, briefs, drafts and internal papers that want warmth without decoration.",
|
|
196
197
|
version: "4.0.0",
|
|
197
198
|
colors: {
|
|
198
199
|
primary: "#2B302B",
|
|
@@ -382,6 +383,7 @@ var init_devportal_docx_theme = __esm({
|
|
|
382
383
|
name: "devportal",
|
|
383
384
|
displayName: "Field Editorial",
|
|
384
385
|
description: "A compact editorial theme \u2014 Helvetica in near-black ink with a burnt-orange accent, tight condensed titles, letterspaced labels, warm tinted fills and hairline rules",
|
|
386
|
+
whenToUse: "Developer and product documentation, API guides and technical handbooks: dense text, code and tables that need compact, letterspaced structure.",
|
|
385
387
|
version: "4.0.0",
|
|
386
388
|
colors: {
|
|
387
389
|
primary: "#12191F",
|
|
@@ -580,6 +582,7 @@ var init_vermilion_docx_theme = __esm({
|
|
|
580
582
|
name: "vermilion",
|
|
581
583
|
displayName: "Vermilion Editorial",
|
|
582
584
|
description: "Poster-red editorial system \u2014 vermilion display headings, ink text, warm creams and hairline rules",
|
|
585
|
+
whenToUse: "Editorial and annual-report work that wants a strong red display voice: covers, feature-style sections, reports built around a few large headings.",
|
|
583
586
|
version: "1.0.0",
|
|
584
587
|
colors: {
|
|
585
588
|
primary: "#282829",
|
|
@@ -798,6 +801,7 @@ var init_consulting_docx_theme = __esm({
|
|
|
798
801
|
name: "consulting",
|
|
799
802
|
displayName: "Consulting House",
|
|
800
803
|
description: "The house style for client and technical reports \u2014 near-black ink, three greys and one deep-blue accent, Calibri body under Arial headings, hairline rules, no fills behind body text, safe fonts only",
|
|
804
|
+
whenToUse: "Client and technical reports, memos and anything a client will read as the house's own work; the default choice for a report unless the brief names a brand.",
|
|
801
805
|
version: "1.0.0",
|
|
802
806
|
colors: {
|
|
803
807
|
primary: "#1A1F26",
|
|
@@ -12132,8 +12136,10 @@ import {
|
|
|
12132
12136
|
} from "@json-to-office/quality";
|
|
12133
12137
|
import { DEFAULT_DOCX_RENDERER_ID as DEFAULT_DOCX_RENDERER_ID2 } from "@json-to-office/shared-docx";
|
|
12134
12138
|
import {
|
|
12139
|
+
designCanvas as designCanvas2,
|
|
12135
12140
|
designColors as designColors2,
|
|
12136
|
-
resolveDesignColor as resolveDesignColor2
|
|
12141
|
+
resolveDesignColor as resolveDesignColor2,
|
|
12142
|
+
typeScaleSizes
|
|
12137
12143
|
} from "@json-to-office/shared";
|
|
12138
12144
|
|
|
12139
12145
|
// src/json/normalizer.ts
|
|
@@ -12903,6 +12909,93 @@ function walkActive(node, path3, page, visit) {
|
|
|
12903
12909
|
(child, index) => walkActive(child, `${path3}/children/${index}`, page, visit)
|
|
12904
12910
|
);
|
|
12905
12911
|
}
|
|
12912
|
+
function textSizeFact(node, props, path3, typography, role) {
|
|
12913
|
+
const size = effectiveFontSize(node, props, typography);
|
|
12914
|
+
if (size === void 0) return void 0;
|
|
12915
|
+
return {
|
|
12916
|
+
id: `docx:text-size:${path3}`,
|
|
12917
|
+
kind: "docx/text-size",
|
|
12918
|
+
path: path3,
|
|
12919
|
+
role: role ?? styleKey(node, props),
|
|
12920
|
+
fontSizePt: size.fontSizePt,
|
|
12921
|
+
authored: size.authored,
|
|
12922
|
+
...size.authored && { sizePath: `${path3}/props/font/size` }
|
|
12923
|
+
};
|
|
12924
|
+
}
|
|
12925
|
+
function tableTextSizeFacts(props, authored, path3, typography, page) {
|
|
12926
|
+
const facts = [];
|
|
12927
|
+
const sizeOf = (holder) => finiteNumber(asRecord(asRecord(holder)?.font)?.size);
|
|
12928
|
+
const authoredSize = (holder, pointer, role) => {
|
|
12929
|
+
const size = sizeOf(holder);
|
|
12930
|
+
if (size === void 0) return;
|
|
12931
|
+
facts.push({
|
|
12932
|
+
id: `docx:text-size:${pointer}`,
|
|
12933
|
+
kind: "docx/text-size",
|
|
12934
|
+
path: pointer,
|
|
12935
|
+
role,
|
|
12936
|
+
fontSizePt: size,
|
|
12937
|
+
authored: true,
|
|
12938
|
+
sizePath: `${pointer}/font/size`
|
|
12939
|
+
});
|
|
12940
|
+
};
|
|
12941
|
+
const cellContent = (holder, pointer, role) => {
|
|
12942
|
+
const content = asRecord(holder)?.content;
|
|
12943
|
+
if (asRecord(content) === void 0) return;
|
|
12944
|
+
walkActive(content, `${pointer}/content`, page, (node, nodePath) => {
|
|
12945
|
+
if (node.name !== "paragraph" && node.name !== "heading") return;
|
|
12946
|
+
const nodeProps = asRecord(node.props) ?? {};
|
|
12947
|
+
if (typeof nodeProps.text !== "string" || nodeProps.text.trim() === "")
|
|
12948
|
+
return;
|
|
12949
|
+
const fact = textSizeFact(node, nodeProps, nodePath, typography, role);
|
|
12950
|
+
if (fact) facts.push(fact);
|
|
12951
|
+
});
|
|
12952
|
+
};
|
|
12953
|
+
if (authored) {
|
|
12954
|
+
authoredSize(
|
|
12955
|
+
authored.cellDefaults,
|
|
12956
|
+
`${path3}/props/cellDefaults`,
|
|
12957
|
+
"tableCell"
|
|
12958
|
+
);
|
|
12959
|
+
authoredSize(
|
|
12960
|
+
authored.headerCellDefaults,
|
|
12961
|
+
`${path3}/props/headerCellDefaults`,
|
|
12962
|
+
"tableHeader"
|
|
12963
|
+
);
|
|
12964
|
+
const columns = Array.isArray(authored.columns) ? authored.columns : [];
|
|
12965
|
+
columns.forEach((column, index) => {
|
|
12966
|
+
const record = asRecord(column) ?? {};
|
|
12967
|
+
const columnPath = `${path3}/props/columns/${index}`;
|
|
12968
|
+
authoredSize(
|
|
12969
|
+
record.cellDefaults,
|
|
12970
|
+
`${columnPath}/cellDefaults`,
|
|
12971
|
+
"tableCell"
|
|
12972
|
+
);
|
|
12973
|
+
authoredSize(record.header, `${columnPath}/header`, "tableHeader");
|
|
12974
|
+
cellContent(record.header, `${columnPath}/header`, "tableHeader");
|
|
12975
|
+
const cells = Array.isArray(record.cells) ? record.cells : [];
|
|
12976
|
+
cells.forEach((cell, cellIndex) => {
|
|
12977
|
+
authoredSize(cell, `${columnPath}/cells/${cellIndex}`, "tableCell");
|
|
12978
|
+
cellContent(cell, `${columnPath}/cells/${cellIndex}`, "tableCell");
|
|
12979
|
+
});
|
|
12980
|
+
});
|
|
12981
|
+
}
|
|
12982
|
+
for (const [key, role] of [
|
|
12983
|
+
["cellDefaults", "tableCell"],
|
|
12984
|
+
["headerCellDefaults", "tableHeader"]
|
|
12985
|
+
]) {
|
|
12986
|
+
const size = sizeOf(props[key]);
|
|
12987
|
+
if (size === void 0) continue;
|
|
12988
|
+
facts.push({
|
|
12989
|
+
id: `docx:text-size:${path3}:${role}`,
|
|
12990
|
+
kind: "docx/text-size",
|
|
12991
|
+
path: path3,
|
|
12992
|
+
role,
|
|
12993
|
+
fontSizePt: size,
|
|
12994
|
+
authored: false
|
|
12995
|
+
});
|
|
12996
|
+
}
|
|
12997
|
+
return facts;
|
|
12998
|
+
}
|
|
12906
12999
|
function prepareDocxQualityDocument(document, options = {}) {
|
|
12907
13000
|
const themed = options.context ?? resolveThemeContext(normalizeDocument(document)[0], {
|
|
12908
13001
|
customThemes: options.customThemes,
|
|
@@ -12972,6 +13065,43 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
12972
13065
|
const header = part("header");
|
|
12973
13066
|
const footer = part("footer");
|
|
12974
13067
|
inherited = { header, footer };
|
|
13068
|
+
for (const kind of ["header", "footer"]) {
|
|
13069
|
+
if (!Array.isArray(props[kind])) continue;
|
|
13070
|
+
const drawnByBlock = !Array.isArray(
|
|
13071
|
+
asRecord(
|
|
13072
|
+
asRecord(
|
|
13073
|
+
(Array.isArray(themed.document.children) ? themed.document.children : [])[index]
|
|
13074
|
+
)?.props
|
|
13075
|
+
)?.[kind]
|
|
13076
|
+
);
|
|
13077
|
+
const part2 = props[kind];
|
|
13078
|
+
const visitChrome = (child, childPath) => {
|
|
13079
|
+
if (child.name !== "paragraph" && child.name !== "heading") return;
|
|
13080
|
+
const childProps = asRecord(child.props) ?? {};
|
|
13081
|
+
if (typeof childProps.text !== "string" || childProps.text.trim() === "")
|
|
13082
|
+
return;
|
|
13083
|
+
const fact = textSizeFact(
|
|
13084
|
+
child,
|
|
13085
|
+
childProps,
|
|
13086
|
+
childPath,
|
|
13087
|
+
typography,
|
|
13088
|
+
kind
|
|
13089
|
+
);
|
|
13090
|
+
if (fact)
|
|
13091
|
+
addFact({
|
|
13092
|
+
...fact,
|
|
13093
|
+
generated: drawnByBlock || authoredPath(childPath) !== childPath
|
|
13094
|
+
});
|
|
13095
|
+
};
|
|
13096
|
+
part2.forEach(
|
|
13097
|
+
(child, childIndex) => walkActive(
|
|
13098
|
+
child,
|
|
13099
|
+
`/children/${index}/props/${kind}/${childIndex}`,
|
|
13100
|
+
basePage,
|
|
13101
|
+
visitChrome
|
|
13102
|
+
)
|
|
13103
|
+
);
|
|
13104
|
+
}
|
|
12975
13105
|
addFact({
|
|
12976
13106
|
id: `docx:section-chrome:${index}`,
|
|
12977
13107
|
kind: "docx/section-chrome",
|
|
@@ -13005,12 +13135,34 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13005
13135
|
(value) => `#${resolveDesignColor2(value, visualColors)}`
|
|
13006
13136
|
) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
|
|
13007
13137
|
const authoredPropsAt = (pointer) => asRecord(asRecord(nodeAtPointer(context.document, pointer))?.props);
|
|
13138
|
+
const roleSizesPt = {};
|
|
13139
|
+
for (const key of Object.keys(typography.styles)) {
|
|
13140
|
+
const size = effectiveFontSize(
|
|
13141
|
+
{ name: "paragraph" },
|
|
13142
|
+
{ themeStyle: key },
|
|
13143
|
+
typography
|
|
13144
|
+
);
|
|
13145
|
+
if (size) roleSizesPt[key] = size.fontSizePt;
|
|
13146
|
+
}
|
|
13147
|
+
const scale = resolved.theme.typography?.scale?.[designCanvas2("docx", resolved.theme.page?.size)];
|
|
13148
|
+
const typeScalePt = [
|
|
13149
|
+
.../* @__PURE__ */ new Set([
|
|
13150
|
+
...Object.values(roleSizesPt),
|
|
13151
|
+
...["heading", "body", "mono", "light"].flatMap((role) => {
|
|
13152
|
+
const size = resolveFontSize(resolved.theme, role);
|
|
13153
|
+
return size === void 0 ? [] : [size];
|
|
13154
|
+
}),
|
|
13155
|
+
...scale ? typeScaleSizes(scale) : []
|
|
13156
|
+
])
|
|
13157
|
+
].sort((a, b) => a - b);
|
|
13008
13158
|
addFact({
|
|
13009
13159
|
id: "docx:theme",
|
|
13010
13160
|
kind: "docx/theme",
|
|
13011
13161
|
path: "/props",
|
|
13012
13162
|
themeName: context.themeName,
|
|
13013
13163
|
paletteHexes,
|
|
13164
|
+
typeScalePt,
|
|
13165
|
+
roleSizesPt,
|
|
13014
13166
|
// `heading` and `body` only. A theme also names `mono` and `light`, but
|
|
13015
13167
|
// those paint nothing until a component asks for them — counting an
|
|
13016
13168
|
// unused `Courier New` against a document's family budget would flag a
|
|
@@ -13063,6 +13215,15 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13063
13215
|
if (node.name === "table") {
|
|
13064
13216
|
const fact = tableFact(props, path3, page.availableWidthTwips);
|
|
13065
13217
|
if (fact) addFact(fact);
|
|
13218
|
+
for (const size of tableTextSizeFacts(
|
|
13219
|
+
props,
|
|
13220
|
+
authoredPropsAt(path3),
|
|
13221
|
+
path3,
|
|
13222
|
+
typography,
|
|
13223
|
+
page
|
|
13224
|
+
)) {
|
|
13225
|
+
addFact({ ...size, generated: authoredPath(size.path) !== size.path });
|
|
13226
|
+
}
|
|
13066
13227
|
const design = tableDesignFact(
|
|
13067
13228
|
props,
|
|
13068
13229
|
path3,
|
|
@@ -13121,6 +13282,10 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
13121
13282
|
if (node.name === "paragraph" || node.name === "heading") {
|
|
13122
13283
|
const fact = lineBoxFact(node, props, path3, typography, context.document);
|
|
13123
13284
|
if (fact) addFact(fact);
|
|
13285
|
+
if (typeof props.text === "string" && props.text.trim() !== "") {
|
|
13286
|
+
const fact2 = textSizeFact(node, props, path3, typography);
|
|
13287
|
+
if (fact2) addFact({ ...fact2, generated: authoredPath(path3) !== path3 });
|
|
13288
|
+
}
|
|
13124
13289
|
}
|
|
13125
13290
|
if (node.name === "image" || node.name === "visual") {
|
|
13126
13291
|
for (const fact of svgTextFacts(props, path3)) addFact(fact);
|