@json-to-office/core-docx 1.7.0 → 1.9.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 +261 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/plugin/example/index.js +202 -9
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/facts.d.ts +22 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/quality/rules.d.ts +1 -0
- package/dist/quality/rules.d.ts.map +1 -1
- package/dist/renderers/docxjs/emit.d.ts.map +1 -1
- package/dist/renderers/docxjs/index.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1188,6 +1188,15 @@ function resolveFontFamily(theme, fontRef) {
|
|
|
1188
1188
|
}
|
|
1189
1189
|
return theme.fonts[fontRef]?.family || theme.fonts.body.family;
|
|
1190
1190
|
}
|
|
1191
|
+
function resolveFontSize(theme, fontRef) {
|
|
1192
|
+
if (!theme?.fonts?.body?.size) {
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
if (!fontRef) {
|
|
1196
|
+
return theme.fonts.body.size;
|
|
1197
|
+
}
|
|
1198
|
+
return theme.fonts[fontRef]?.size || theme.fonts.body.size;
|
|
1199
|
+
}
|
|
1191
1200
|
function resolveFontProperties(theme, fontRef) {
|
|
1192
1201
|
const targetFontKey = fontRef || "body";
|
|
1193
1202
|
if (!theme?.fonts?.[targetFontKey]) {
|
|
@@ -2512,6 +2521,14 @@ function paragraphOptions(formatting) {
|
|
|
2512
2521
|
if (formatting.outlineLevel !== void 0) {
|
|
2513
2522
|
options.outlineLevel = formatting.outlineLevel;
|
|
2514
2523
|
}
|
|
2524
|
+
if (formatting.borders) {
|
|
2525
|
+
const borders3 = {};
|
|
2526
|
+
for (const side of ["top", "bottom", "left", "right", "between"]) {
|
|
2527
|
+
const emitted = emitBorder(formatting.borders[side]);
|
|
2528
|
+
if (emitted) borders3[side] = emitted;
|
|
2529
|
+
}
|
|
2530
|
+
if (Object.keys(borders3).length > 0) options.border = borders3;
|
|
2531
|
+
}
|
|
2515
2532
|
return options;
|
|
2516
2533
|
}
|
|
2517
2534
|
function emitParagraph(block2, resources = /* @__PURE__ */ new Map()) {
|
|
@@ -2695,7 +2712,11 @@ function emitBorder(border3) {
|
|
|
2695
2712
|
return {
|
|
2696
2713
|
style: BORDER_STYLE[border3.style] ?? BorderStyle.SINGLE,
|
|
2697
2714
|
size: border3.sizeEighthPoints ?? 0,
|
|
2698
|
-
color: border3.color?.hex ?? "000000"
|
|
2715
|
+
color: border3.color?.hex ?? "000000",
|
|
2716
|
+
// Stated only when the IR states it, so every border that predates the
|
|
2717
|
+
// rule component emits exactly the bytes it did before. office-open
|
|
2718
|
+
// already carries `w:space`; this is what keeps the two agreeing.
|
|
2719
|
+
...border3.spacePoints !== void 0 ? { space: border3.spacePoints } : {}
|
|
2699
2720
|
};
|
|
2700
2721
|
}
|
|
2701
2722
|
var ALIGNMENT2, PAGE_FIELD, WRAP_TYPE, VERTICAL_ALIGN, TABLE_ANCHOR, HORIZONTAL_POSITION, VERTICAL_POSITION, BORDER_STYLE;
|
|
@@ -3365,6 +3386,7 @@ var init_docxjs = __esm({
|
|
|
3365
3386
|
"endnotes",
|
|
3366
3387
|
"revisions",
|
|
3367
3388
|
"breaks",
|
|
3389
|
+
"borders",
|
|
3368
3390
|
"tab-stops",
|
|
3369
3391
|
"proofing-language",
|
|
3370
3392
|
"custom-properties"
|
|
@@ -4664,6 +4686,7 @@ var init_office_open = __esm({
|
|
|
4664
4686
|
"endnotes",
|
|
4665
4687
|
"revisions",
|
|
4666
4688
|
"breaks",
|
|
4689
|
+
"borders",
|
|
4667
4690
|
"tab-stops",
|
|
4668
4691
|
"proofing-language",
|
|
4669
4692
|
"custom-properties"
|
|
@@ -6521,17 +6544,17 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
|
|
|
6521
6544
|
"subtitle"
|
|
6522
6545
|
]);
|
|
6523
6546
|
if (theme.styles) {
|
|
6524
|
-
for (const [
|
|
6525
|
-
if (predefinedStyleKeys.has(
|
|
6547
|
+
for (const [styleKey2, styleValue] of Object.entries(theme.styles)) {
|
|
6548
|
+
if (predefinedStyleKeys.has(styleKey2)) {
|
|
6526
6549
|
continue;
|
|
6527
6550
|
}
|
|
6528
6551
|
if (!styleValue) {
|
|
6529
6552
|
continue;
|
|
6530
6553
|
}
|
|
6531
|
-
const tocMatch = /^TOC([1-9])$/.exec(
|
|
6532
|
-
const customStyle = tocMatch ? styleValue : resolveStyleWithBaseStyle(theme,
|
|
6533
|
-
const styleId = tocMatch ? `TOC${tocMatch[1]}` :
|
|
6534
|
-
const styleName = tocMatch ? `TOC ${tocMatch[1]}` :
|
|
6554
|
+
const tocMatch = /^TOC([1-9])$/.exec(styleKey2);
|
|
6555
|
+
const customStyle = tocMatch ? styleValue : resolveStyleWithBaseStyle(theme, styleKey2) || styleValue;
|
|
6556
|
+
const styleId = tocMatch ? `TOC${tocMatch[1]}` : styleKey2;
|
|
6557
|
+
const styleName = tocMatch ? `TOC ${tocMatch[1]}` : styleKey2.replace(/([A-Z])/g, " $1").trim();
|
|
6535
6558
|
const mapBaseStyleId = (base) => {
|
|
6536
6559
|
if (!base) return "Normal";
|
|
6537
6560
|
const lower = base.toLowerCase();
|
|
@@ -8455,6 +8478,8 @@ function compileComponent(component, scope) {
|
|
|
8455
8478
|
return compileStatistic(component, scope);
|
|
8456
8479
|
case "toc":
|
|
8457
8480
|
return compileToc(component, scope);
|
|
8481
|
+
case "rule":
|
|
8482
|
+
return compileRule(component, scope);
|
|
8458
8483
|
case "text-box":
|
|
8459
8484
|
return compileTextBox(component, scope);
|
|
8460
8485
|
case "columns":
|
|
@@ -9031,6 +9056,100 @@ function compileToc(component, scope) {
|
|
|
9031
9056
|
});
|
|
9032
9057
|
return blocks;
|
|
9033
9058
|
}
|
|
9059
|
+
var DEFAULT_RULE_SPACING_PT = 6;
|
|
9060
|
+
var DEFAULT_RULE_THICKNESS_PT = 1;
|
|
9061
|
+
var RULE_LINE_TWIPS = 20;
|
|
9062
|
+
var RULE_BORDER_STYLE = {
|
|
9063
|
+
solid: "single",
|
|
9064
|
+
dashed: "dashed",
|
|
9065
|
+
dotted: "dotted",
|
|
9066
|
+
double: "double"
|
|
9067
|
+
};
|
|
9068
|
+
function compileRule(component, scope) {
|
|
9069
|
+
const { ctx, path: path4 } = scope;
|
|
9070
|
+
const props = component.props ?? {};
|
|
9071
|
+
ctx.features.require("borders", path4);
|
|
9072
|
+
const thicknessPt = Math.min(
|
|
9073
|
+
12,
|
|
9074
|
+
Math.max(
|
|
9075
|
+
0.25,
|
|
9076
|
+
typeof props.thickness === "number" && Number.isFinite(props.thickness) ? props.thickness : DEFAULT_RULE_THICKNESS_PT
|
|
9077
|
+
)
|
|
9078
|
+
);
|
|
9079
|
+
const spacing = props.spacing ?? {};
|
|
9080
|
+
const beforePt = typeof spacing.before === "number" && Number.isFinite(spacing.before) ? spacing.before : DEFAULT_RULE_SPACING_PT;
|
|
9081
|
+
const afterPt = typeof spacing.after === "number" && Number.isFinite(spacing.after) ? spacing.after : DEFAULT_RULE_SPACING_PT;
|
|
9082
|
+
return [
|
|
9083
|
+
{
|
|
9084
|
+
kind: "paragraph",
|
|
9085
|
+
id: scope.id,
|
|
9086
|
+
path: path4,
|
|
9087
|
+
styleId: "Normal",
|
|
9088
|
+
children: [],
|
|
9089
|
+
formatting: {
|
|
9090
|
+
spacing: {
|
|
9091
|
+
beforeTwips: pointsToTwips2(beforePt),
|
|
9092
|
+
afterTwips: pointsToTwips2(afterPt),
|
|
9093
|
+
lineTwips: RULE_LINE_TWIPS,
|
|
9094
|
+
lineRule: "exact"
|
|
9095
|
+
},
|
|
9096
|
+
...ruleIndent(props, ctx, path4),
|
|
9097
|
+
borders: {
|
|
9098
|
+
bottom: {
|
|
9099
|
+
style: RULE_BORDER_STYLE[String(props.style)] ?? "single",
|
|
9100
|
+
sizeEighthPoints: pointsToEighthPoints(thicknessPt),
|
|
9101
|
+
color: irColor(
|
|
9102
|
+
resolveColor(String(props.color ?? "border"), ctx.theme)
|
|
9103
|
+
),
|
|
9104
|
+
// The border hangs off the paragraph edge; any gap the author
|
|
9105
|
+
// wants belongs to `spacing`, where they can see it.
|
|
9106
|
+
spacePoints: 0
|
|
9107
|
+
}
|
|
9108
|
+
}
|
|
9109
|
+
}
|
|
9110
|
+
}
|
|
9111
|
+
];
|
|
9112
|
+
}
|
|
9113
|
+
function ruleIndent(props, ctx, path4) {
|
|
9114
|
+
const width = props.width;
|
|
9115
|
+
if (width === void 0) return {};
|
|
9116
|
+
const page = getPageSetup(ctx.theme);
|
|
9117
|
+
const measureTwips = Math.max(
|
|
9118
|
+
0,
|
|
9119
|
+
page.size.width - page.margin.left - page.margin.right
|
|
9120
|
+
);
|
|
9121
|
+
let usedTwips;
|
|
9122
|
+
if (typeof width === "number" && Number.isFinite(width)) {
|
|
9123
|
+
usedTwips = pointsToTwips2(width);
|
|
9124
|
+
} else if (typeof width === "string" && width.trim().endsWith("%")) {
|
|
9125
|
+
const percent = Number(width.trim().slice(0, -1));
|
|
9126
|
+
if (Number.isFinite(percent)) {
|
|
9127
|
+
usedTwips = Math.round(measureTwips * percent / 100);
|
|
9128
|
+
}
|
|
9129
|
+
}
|
|
9130
|
+
if (usedTwips === void 0) return {};
|
|
9131
|
+
const remainder = measureTwips - usedTwips;
|
|
9132
|
+
if (remainder <= 0) {
|
|
9133
|
+
if (remainder < 0) {
|
|
9134
|
+
warnOnce(
|
|
9135
|
+
ctx,
|
|
9136
|
+
"rule",
|
|
9137
|
+
`Rule width ${JSON.stringify(width)} at ${path4} is wider than the ${Math.round(measureTwips / 20)}pt text measure; it runs the full measure instead.`
|
|
9138
|
+
);
|
|
9139
|
+
}
|
|
9140
|
+
return {};
|
|
9141
|
+
}
|
|
9142
|
+
switch (props.alignment) {
|
|
9143
|
+
case "right":
|
|
9144
|
+
return { indent: { leftTwips: remainder } };
|
|
9145
|
+
case "center": {
|
|
9146
|
+
const half = Math.round(remainder / 2);
|
|
9147
|
+
return { indent: { leftTwips: half, rightTwips: remainder - half } };
|
|
9148
|
+
}
|
|
9149
|
+
default:
|
|
9150
|
+
return { indent: { rightTwips: remainder } };
|
|
9151
|
+
}
|
|
9152
|
+
}
|
|
9034
9153
|
var TREND_GLYPHS = {
|
|
9035
9154
|
up: "\u25B2",
|
|
9036
9155
|
down: "\u25BC",
|
|
@@ -11019,8 +11138,8 @@ function getHeadingDefaults(theme) {
|
|
|
11019
11138
|
function getHeadingDefaultsForLevel(theme, level) {
|
|
11020
11139
|
const defaults = {};
|
|
11021
11140
|
if (theme.styles) {
|
|
11022
|
-
const
|
|
11023
|
-
const headingStyle = theme.styles[
|
|
11141
|
+
const styleKey2 = `heading${level}`;
|
|
11142
|
+
const headingStyle = theme.styles[styleKey2];
|
|
11024
11143
|
if (headingStyle?.alignment) {
|
|
11025
11144
|
defaults.alignment = headingStyle.alignment;
|
|
11026
11145
|
}
|
|
@@ -11461,6 +11580,8 @@ function normalizeDocument(document) {
|
|
|
11461
11580
|
}
|
|
11462
11581
|
|
|
11463
11582
|
// src/quality/facts.ts
|
|
11583
|
+
init_styleHelpers();
|
|
11584
|
+
init_defaults();
|
|
11464
11585
|
init_widthUtils();
|
|
11465
11586
|
function asRecord(value) {
|
|
11466
11587
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
@@ -11550,6 +11671,70 @@ function characterSpacingPt(spacing) {
|
|
|
11550
11671
|
if (rule === void 0 || value === void 0) return 0;
|
|
11551
11672
|
return rule.type === "condensed" ? -value / TWIPS_PER_POINT3 : value / TWIPS_PER_POINT3;
|
|
11552
11673
|
}
|
|
11674
|
+
function pointerExists(root, pointer) {
|
|
11675
|
+
let current = root;
|
|
11676
|
+
for (const token of pointer.split("/").slice(1)) {
|
|
11677
|
+
if (Array.isArray(current)) {
|
|
11678
|
+
const index = Number(token);
|
|
11679
|
+
if (!Number.isInteger(index)) return false;
|
|
11680
|
+
current = current[index];
|
|
11681
|
+
continue;
|
|
11682
|
+
}
|
|
11683
|
+
const record = asRecord(current);
|
|
11684
|
+
if (!record) return false;
|
|
11685
|
+
current = record[token];
|
|
11686
|
+
}
|
|
11687
|
+
return current !== void 0;
|
|
11688
|
+
}
|
|
11689
|
+
function styleKey(node, props) {
|
|
11690
|
+
if (node.name === "heading") {
|
|
11691
|
+
return `heading${finiteNumber(props.level) ?? 1}`;
|
|
11692
|
+
}
|
|
11693
|
+
return typeof props.themeStyle === "string" && props.themeStyle !== "" ? props.themeStyle : "normal";
|
|
11694
|
+
}
|
|
11695
|
+
function effectiveFontSize(node, props, typography) {
|
|
11696
|
+
const authored = finiteNumber(asRecord(props.font)?.size);
|
|
11697
|
+
if (authored !== void 0) return { fontSizePt: authored, authored: true };
|
|
11698
|
+
const { styles, theme } = typography;
|
|
11699
|
+
const style = asRecord(styles[styleKey(node, props)]) ?? asRecord(styles.normal);
|
|
11700
|
+
const stated = finiteNumber(style?.size);
|
|
11701
|
+
if (stated !== void 0) return { fontSizePt: stated, authored: false };
|
|
11702
|
+
const reference = style?.font === "heading" || style?.font === "body" || style?.font === "mono" || style?.font === "light" ? style.font : void 0;
|
|
11703
|
+
const inherited = resolveFontSize(theme, reference);
|
|
11704
|
+
return inherited === void 0 ? void 0 : { fontSizePt: inherited, authored: false };
|
|
11705
|
+
}
|
|
11706
|
+
function pinnedLineBox(props, path4) {
|
|
11707
|
+
const candidates = [
|
|
11708
|
+
[props.lineSpacing, `${path4}/props/lineSpacing`],
|
|
11709
|
+
[asRecord(props.font)?.lineSpacing, `${path4}/props/font/lineSpacing`]
|
|
11710
|
+
];
|
|
11711
|
+
for (const [spacing, pointer] of candidates) {
|
|
11712
|
+
if (spacing === void 0) continue;
|
|
11713
|
+
const rule = asRecord(spacing);
|
|
11714
|
+
if (rule?.type !== "exactly") return void 0;
|
|
11715
|
+
const lineBoxPt = finiteNumber(rule.value);
|
|
11716
|
+
return lineBoxPt === void 0 ? void 0 : { lineBoxPt, pointer };
|
|
11717
|
+
}
|
|
11718
|
+
return void 0;
|
|
11719
|
+
}
|
|
11720
|
+
function lineBoxFact(node, props, path4, typography, authored) {
|
|
11721
|
+
if (typeof props.text !== "string" || props.text.trim() === "") {
|
|
11722
|
+
return void 0;
|
|
11723
|
+
}
|
|
11724
|
+
const pinned = pinnedLineBox(props, path4);
|
|
11725
|
+
if (!pinned) return void 0;
|
|
11726
|
+
const size = effectiveFontSize(node, props, typography);
|
|
11727
|
+
if (size === void 0) return void 0;
|
|
11728
|
+
return {
|
|
11729
|
+
id: `docx:line-box:${path4}`,
|
|
11730
|
+
kind: "docx/line-box",
|
|
11731
|
+
path: pinned.pointer,
|
|
11732
|
+
lineBoxPt: pinned.lineBoxPt,
|
|
11733
|
+
fontSizePt: size.fontSizePt,
|
|
11734
|
+
fontSizeAuthored: size.authored,
|
|
11735
|
+
patchable: pointerExists(authored, pinned.pointer)
|
|
11736
|
+
};
|
|
11737
|
+
}
|
|
11553
11738
|
function frameSignature(floating) {
|
|
11554
11739
|
const horizontal = asRecord(floating.horizontalPosition);
|
|
11555
11740
|
const vertical = asRecord(floating.verticalPosition);
|
|
@@ -11666,6 +11851,10 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
11666
11851
|
});
|
|
11667
11852
|
const resolved = resolveDocumentTree(context.document, context.theme);
|
|
11668
11853
|
const basePage = pageBox(resolved.theme, context.themeName);
|
|
11854
|
+
const typography = {
|
|
11855
|
+
styles: getThemeStyles(resolved.theme),
|
|
11856
|
+
theme: resolved.theme
|
|
11857
|
+
};
|
|
11669
11858
|
const facts = [];
|
|
11670
11859
|
const provenance = {};
|
|
11671
11860
|
let previousHeadingLevel;
|
|
@@ -11696,6 +11885,10 @@ function prepareDocxQualityDocument(document, options = {}) {
|
|
|
11696
11885
|
if (fact) addFact(fact);
|
|
11697
11886
|
}
|
|
11698
11887
|
}
|
|
11888
|
+
if (node.name === "paragraph" || node.name === "heading") {
|
|
11889
|
+
const fact = lineBoxFact(node, props, path4, typography, context.document);
|
|
11890
|
+
if (fact) addFact(fact);
|
|
11891
|
+
}
|
|
11699
11892
|
if (node.name === "image" || node.name === "visual") {
|
|
11700
11893
|
for (const fact of svgTextFacts(props, path4)) addFact(fact);
|
|
11701
11894
|
}
|
|
@@ -12513,6 +12706,63 @@ var docxSvgTextBoundsRule = {
|
|
|
12513
12706
|
];
|
|
12514
12707
|
})
|
|
12515
12708
|
};
|
|
12709
|
+
var LINE_BOX_MIN_RATIO = 0.7;
|
|
12710
|
+
function tenths(value) {
|
|
12711
|
+
return Math.round(value * 10) / 10;
|
|
12712
|
+
}
|
|
12713
|
+
var docxLineBoxRule = {
|
|
12714
|
+
id: "docx/line-box",
|
|
12715
|
+
code: QUALITY_CODES.LINE_BOX_COLLAPSE,
|
|
12716
|
+
category: "legibility",
|
|
12717
|
+
defaultSeverity: "warning",
|
|
12718
|
+
defaultCertainty: "measured",
|
|
12719
|
+
formats: ["docx"],
|
|
12720
|
+
defaultParameters: { minimumLineBoxRatio: LINE_BOX_MIN_RATIO },
|
|
12721
|
+
evaluate: ({ facts, configuration }) => {
|
|
12722
|
+
const ratio = numberParameter(
|
|
12723
|
+
configuration.parameters,
|
|
12724
|
+
"minimumLineBoxRatio",
|
|
12725
|
+
LINE_BOX_MIN_RATIO
|
|
12726
|
+
);
|
|
12727
|
+
return facts.filter((fact) => fact.kind === "docx/line-box").flatMap((fact) => {
|
|
12728
|
+
const floorPt = Math.ceil(fact.fontSizePt * ratio * 10) / 10;
|
|
12729
|
+
if (fact.lineBoxPt >= floorPt) return [];
|
|
12730
|
+
const repairPt = Math.max(tenths(fact.fontSizePt), floorPt);
|
|
12731
|
+
const inherited = fact.fontSizeAuthored ? "" : " inherited from the paragraph style";
|
|
12732
|
+
return [
|
|
12733
|
+
{
|
|
12734
|
+
message: `An exact ${tenths(fact.lineBoxPt)}pt line box holds ${tenths(fact.fontSizePt)}pt text${inherited} \u2014 shorter than the capitals it contains, so the lines overlap or lose their tops.`,
|
|
12735
|
+
path: fact.path,
|
|
12736
|
+
// The second sentence is the exit from the incentive that
|
|
12737
|
+
// produced this geometry: the reported route to a 3pt rule was a
|
|
12738
|
+
// collapsed line box on 8pt type, because nothing else drew one.
|
|
12739
|
+
suggestion: `Set the box to at least ${repairPt}pt \u2014 as tall as the type it holds \u2014 or use "atLeast" so the line grows to fit the text. To draw a line rather than set leading, use the "rule" component.${fact.patchable ? "" : " This box is not stated on the component: it arrives through `componentDefaults` and has to be repaired there."}`,
|
|
12740
|
+
context: {
|
|
12741
|
+
lineBoxPt: tenths(fact.lineBoxPt),
|
|
12742
|
+
fontSizePt: tenths(fact.fontSizePt),
|
|
12743
|
+
capHeightFloorPt: floorPt
|
|
12744
|
+
},
|
|
12745
|
+
evidence: {
|
|
12746
|
+
actual: tenths(fact.lineBoxPt),
|
|
12747
|
+
expected: floorPt,
|
|
12748
|
+
unit: "pt"
|
|
12749
|
+
},
|
|
12750
|
+
// Only when the pointer exists in the authored document: a box
|
|
12751
|
+
// arriving through `componentDefaults` has to be repaired there.
|
|
12752
|
+
...fact.patchable && {
|
|
12753
|
+
fixes: [
|
|
12754
|
+
{
|
|
12755
|
+
op: "add",
|
|
12756
|
+
path: `${fact.path}/value`,
|
|
12757
|
+
value: repairPt
|
|
12758
|
+
}
|
|
12759
|
+
]
|
|
12760
|
+
}
|
|
12761
|
+
}
|
|
12762
|
+
];
|
|
12763
|
+
});
|
|
12764
|
+
}
|
|
12765
|
+
};
|
|
12516
12766
|
var DOCX_QUALITY_RULES = {
|
|
12517
12767
|
id: "docx/default",
|
|
12518
12768
|
rules: [
|
|
@@ -12520,7 +12770,8 @@ var DOCX_QUALITY_RULES = {
|
|
|
12520
12770
|
docxHeadingHierarchyRule,
|
|
12521
12771
|
docxTextFitRule,
|
|
12522
12772
|
docxFrameCollisionRule,
|
|
12523
|
-
docxSvgTextBoundsRule
|
|
12773
|
+
docxSvgTextBoundsRule,
|
|
12774
|
+
docxLineBoxRule
|
|
12524
12775
|
]
|
|
12525
12776
|
};
|
|
12526
12777
|
var DOCX_QUALITY_PROFILES = {
|