reamkit 1.15.4 → 1.17.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/esm/core/bidi/segments.js +1 -2
- package/dist/esm/core/converter/facade.d.ts +5 -0
- package/dist/esm/core/converter/project.js +5 -1
- package/dist/esm/core/converter/ream.d.ts +6 -0
- package/dist/esm/core/converter/ream.js +34 -8
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +659 -7
- package/dist/esm/core/drawingml/chart-geometry.d.ts +34 -10
- package/dist/esm/core/drawingml/chart-geometry.js +424 -92
- package/dist/esm/core/drawingml/chart-parser.js +301 -11
- package/dist/esm/core/drawingml/colors.d.ts +7 -7
- package/dist/esm/core/drawingml/colors.js +84 -18
- package/dist/esm/core/drawingml/preset-geometry.js +240 -6
- package/dist/esm/core/drawingml/shape-render.d.ts +12 -0
- package/dist/esm/core/drawingml/shape-render.js +116 -3
- package/dist/esm/core/drawingml/sparkline-geometry.js +6 -4
- package/dist/esm/core/drawingml/theme-parser.d.ts +51 -0
- package/dist/esm/core/drawingml/theme-parser.js +92 -1
- package/dist/esm/core/font/measure.d.ts +5 -0
- package/dist/esm/core/font/measure.js +21 -1
- package/dist/esm/core/font/ttf-subset.js +26 -1
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +353 -43
- package/dist/esm/core/indexed-colors.d.ts +11 -0
- package/dist/esm/core/indexed-colors.js +81 -0
- package/dist/esm/core/ir/flow.d.ts +23 -1
- package/dist/esm/core/ir/sheet.d.ts +61 -0
- package/dist/esm/{excel → core}/number-format.d.ts +37 -0
- package/dist/esm/core/number-format.js +800 -0
- package/dist/esm/core/numbering/apply.d.ts +5 -3
- package/dist/esm/core/numbering/apply.js +42 -11
- package/dist/esm/core/numbering/index.js +2 -0
- package/dist/esm/core/numbering/state.d.ts +13 -1
- package/dist/esm/core/numbering/state.js +256 -15
- package/dist/esm/core/opc/alternate-content.d.ts +13 -0
- package/dist/esm/core/opc/alternate-content.js +72 -0
- package/dist/esm/core/opc/core-properties.js +1 -0
- package/dist/esm/core/opc/package.d.ts +14 -1
- package/dist/esm/core/opc/package.js +43 -4
- package/dist/esm/core/opc/relationships.js +1 -0
- package/dist/esm/core/opc/xml-entities.d.ts +12 -0
- package/dist/esm/core/opc/xml-entities.js +91 -0
- package/dist/esm/core/po-helpers.js +16 -1
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +137 -0
- package/dist/esm/core/style-cascade/resolver.js +66 -11
- package/dist/esm/core/style-cascade/table.js +35 -11
- package/dist/esm/core/style-cascade/types.d.ts +42 -1
- package/dist/esm/core/style-cascade/types.js +4 -0
- package/dist/esm/core/vector.d.ts +30 -0
- package/dist/esm/excel/activex-parser.js +1 -0
- package/dist/esm/excel/column-bands.d.ts +26 -1
- package/dist/esm/excel/column-bands.js +156 -20
- package/dist/esm/excel/comments-parser.js +5 -3
- package/dist/esm/excel/conditional-format.d.ts +25 -2
- package/dist/esm/excel/conditional-format.js +63 -19
- package/dist/esm/excel/escaped-text.d.ts +9 -0
- package/dist/esm/excel/escaped-text.js +20 -0
- package/dist/esm/excel/form-control-parser.js +1 -0
- package/dist/esm/excel/formula/dates.js +1 -1
- package/dist/esm/excel/header-footer.d.ts +9 -1
- package/dist/esm/excel/header-footer.js +162 -14
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/index.js +2 -2
- package/dist/esm/excel/pivot-table-parser.js +1 -0
- package/dist/esm/excel/print-model.d.ts +75 -0
- package/dist/esm/excel/print-model.js +899 -77
- package/dist/esm/excel/printer-settings.d.ts +16 -0
- package/dist/esm/excel/printer-settings.js +36 -0
- package/dist/esm/excel/rich-value.d.ts +13 -0
- package/dist/esm/excel/rich-value.js +120 -0
- package/dist/esm/excel/shared-strings-parser.js +11 -7
- package/dist/esm/excel/sheet-drawing.d.ts +11 -0
- package/dist/esm/excel/sheet-drawing.js +26 -3
- package/dist/esm/excel/sheet-shape-parser.d.ts +53 -1
- package/dist/esm/excel/sheet-shape-parser.js +461 -32
- package/dist/esm/excel/sheet-to-flow.d.ts +23 -2
- package/dist/esm/excel/sheet-to-flow.js +553 -36
- package/dist/esm/excel/slicer-parser.js +1 -0
- package/dist/esm/excel/styles-parser.d.ts +30 -2
- package/dist/esm/excel/styles-parser.js +177 -40
- package/dist/esm/excel/table-parser.js +1 -0
- package/dist/esm/excel/vml-drawing.d.ts +68 -0
- package/dist/esm/excel/vml-drawing.js +158 -0
- package/dist/esm/excel/workbook-parser.d.ts +5 -0
- package/dist/esm/excel/workbook-parser.js +5 -1
- package/dist/esm/excel/worksheet-parser.d.ts +2 -1
- package/dist/esm/excel/worksheet-parser.js +150 -61
- package/dist/esm/excel/xlsx-reader.js +242 -11
- package/dist/esm/excel/xlsx-to-pdf.js +12 -1
- package/dist/esm/html/html-writer.js +29 -6
- package/dist/esm/layout/page-doc.d.ts +87 -1
- package/dist/esm/layout/styled-layout.d.ts +46 -2
- package/dist/esm/layout/styled-layout.js +2345 -274
- package/dist/esm/pdf/cid-font.js +20 -9
- package/dist/esm/pdf/objects.d.ts +13 -0
- package/dist/esm/pdf/objects.js +18 -1
- package/dist/esm/pdf/shading.js +76 -6
- package/dist/esm/pdf/styled-page-emitter.js +355 -49
- package/dist/esm/pdf/text-page-renderer.js +1 -0
- package/dist/esm/pdf/vector-graphics.d.ts +31 -2
- package/dist/esm/pdf/vector-graphics.js +103 -3
- package/dist/esm/pptx/pptx-reader.js +2 -0
- package/dist/esm/pptx/slide-parser.d.ts +21 -4
- package/dist/esm/pptx/slide-parser.js +98 -24
- package/dist/esm/svg/svg-writer.js +23 -4
- package/dist/esm/word/document-parser.d.ts +96 -7
- package/dist/esm/word/document-parser.js +538 -116
- package/dist/esm/word/docx-reader.js +135 -43
- package/dist/esm/word/docx-writer.js +6 -1
- package/dist/esm/word/drawing-parser.d.ts +86 -5
- package/dist/esm/word/drawing-parser.js +1590 -54
- package/dist/esm/word/index.d.ts +4 -4
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +108 -21
- package/dist/esm/word/paragraph-properties.d.ts +11 -1
- package/dist/esm/word/paragraph-properties.js +219 -10
- package/dist/esm/word/run-properties.js +45 -1
- package/dist/esm/word/settings-parser.d.ts +24 -0
- package/dist/esm/word/settings-parser.js +32 -5
- package/dist/esm/word/shading.d.ts +11 -0
- package/dist/esm/word/shading.js +64 -0
- package/dist/esm/word/styles-parser.js +9 -2
- package/dist/esm/word/table-parser.d.ts +9 -1
- package/dist/esm/word/table-parser.js +182 -30
- package/package.json +7 -3
- package/dist/esm/excel/number-format.js +0 -476
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the entities an internal DTD subset declares and remove the subset,
|
|
3
|
+
* so what reaches the XML parser is a well-formed part with no `&name;` left
|
|
4
|
+
* to leak. Markup inside an entity value is escaped to text rather than
|
|
5
|
+
* spliced in — an entity that opens a tag is a document we will not build.
|
|
6
|
+
*
|
|
7
|
+
* Text with no `<!DOCTYPE` is returned unchanged, which is every real file.
|
|
8
|
+
*
|
|
9
|
+
* @param xml The decoded part, as read from the package.
|
|
10
|
+
* @returns The part with its internal subset resolved and stripped.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveInternalEntities(xml: string): string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region src/core/opc/xml-entities.ts
|
|
2
|
+
/** Longest text any one declared entity may expand to. */
|
|
3
|
+
var MAX_EXPANSION = 65536;
|
|
4
|
+
/** Longest total the substitutions may add to one part. */
|
|
5
|
+
var MAX_TOTAL = 1048576;
|
|
6
|
+
var DOCTYPE = /<!DOCTYPE\s[^[>]*(?:\[[\s\S]*?\]\s*)?>/;
|
|
7
|
+
var ENTITY_DECL = /<!ENTITY\s+([^\s%<>&;]+)\s+(?:"([^"]*)"|'([^']*)')\s*>/g;
|
|
8
|
+
var REFERENCE = /&([^\s;&<>]+);/g;
|
|
9
|
+
/** The five entities XML predefines; a declaration never overrides them. */
|
|
10
|
+
var PREDEFINED = new Set([
|
|
11
|
+
"lt",
|
|
12
|
+
"gt",
|
|
13
|
+
"amp",
|
|
14
|
+
"apos",
|
|
15
|
+
"quot"
|
|
16
|
+
]);
|
|
17
|
+
/** Escape resolved text so it re-enters the document as characters, not markup. */
|
|
18
|
+
function escape(text) {
|
|
19
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Substitute every entity reference in `text` using `valueOf`, leaving the
|
|
23
|
+
* predefined and numeric references for the XML parser. Returns undefined once
|
|
24
|
+
* the result passes `cap` — the caller drops what it was building.
|
|
25
|
+
*/
|
|
26
|
+
function substitute(text, cap, valueOf) {
|
|
27
|
+
if (!text.includes("&")) return text.length > cap ? void 0 : text;
|
|
28
|
+
let out = "";
|
|
29
|
+
let last = 0;
|
|
30
|
+
for (const m of text.matchAll(REFERENCE)) {
|
|
31
|
+
const name = m[1] ?? "";
|
|
32
|
+
out += text.slice(last, m.index);
|
|
33
|
+
last = m.index + m[0].length;
|
|
34
|
+
out += PREDEFINED.has(name) || name.startsWith("#") ? m[0] : valueOf(name);
|
|
35
|
+
if (out.length > cap) return void 0;
|
|
36
|
+
}
|
|
37
|
+
out += text.slice(last);
|
|
38
|
+
return out.length > cap ? void 0 : out;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Expand each declaration once, so a name referenced ten thousand times costs
|
|
42
|
+
* one expansion rather than ten thousand. A cycle, an undeclared name and a
|
|
43
|
+
* value that outgrows MAX_EXPANSION all resolve to the empty string: XML says
|
|
44
|
+
* such a document is in error, and drawing the reference's own spelling is the
|
|
45
|
+
* one answer that is certainly wrong.
|
|
46
|
+
*/
|
|
47
|
+
function expander(declared) {
|
|
48
|
+
const done = /* @__PURE__ */ new Map();
|
|
49
|
+
const active = /* @__PURE__ */ new Set();
|
|
50
|
+
const valueOf = (name) => {
|
|
51
|
+
const memo = done.get(name);
|
|
52
|
+
if (memo !== void 0) return memo;
|
|
53
|
+
if (active.has(name)) return "";
|
|
54
|
+
const raw = declared.get(name);
|
|
55
|
+
if (raw === void 0) return "";
|
|
56
|
+
active.add(name);
|
|
57
|
+
const out = substitute(raw, MAX_EXPANSION, valueOf) ?? "";
|
|
58
|
+
active.delete(name);
|
|
59
|
+
done.set(name, out);
|
|
60
|
+
return out;
|
|
61
|
+
};
|
|
62
|
+
return valueOf;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the entities an internal DTD subset declares and remove the subset,
|
|
66
|
+
* so what reaches the XML parser is a well-formed part with no `&name;` left
|
|
67
|
+
* to leak. Markup inside an entity value is escaped to text rather than
|
|
68
|
+
* spliced in — an entity that opens a tag is a document we will not build.
|
|
69
|
+
*
|
|
70
|
+
* Text with no `<!DOCTYPE` is returned unchanged, which is every real file.
|
|
71
|
+
*
|
|
72
|
+
* @param xml The decoded part, as read from the package.
|
|
73
|
+
* @returns The part with its internal subset resolved and stripped.
|
|
74
|
+
*/
|
|
75
|
+
function resolveInternalEntities(xml) {
|
|
76
|
+
if (!xml.includes("<!DOCTYPE")) return xml;
|
|
77
|
+
const doctype = DOCTYPE.exec(xml);
|
|
78
|
+
if (!doctype) return xml;
|
|
79
|
+
const declared = /* @__PURE__ */ new Map();
|
|
80
|
+
for (const decl of doctype[0].matchAll(ENTITY_DECL)) {
|
|
81
|
+
const name = decl[1];
|
|
82
|
+
if (name === void 0 || name.startsWith("%") || PREDEFINED.has(name)) continue;
|
|
83
|
+
if (!declared.has(name)) declared.set(name, decl[2] ?? decl[3] ?? "");
|
|
84
|
+
}
|
|
85
|
+
const body = xml.slice(0, doctype.index) + xml.slice(doctype.index + doctype[0].length);
|
|
86
|
+
if (!body.includes("&")) return body;
|
|
87
|
+
const valueOf = expander(declared);
|
|
88
|
+
return substitute(body, MAX_TOTAL, (name) => escape(valueOf(name))) ?? substitute(body, MAX_TOTAL, () => "") ?? body;
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { resolveInternalEntities };
|
|
@@ -65,7 +65,22 @@ function poIntAttr(node, name) {
|
|
|
65
65
|
const v = poAttr(node, name);
|
|
66
66
|
if (v === void 0) return void 0;
|
|
67
67
|
const n = Number(v);
|
|
68
|
-
|
|
68
|
+
if (Number.isFinite(n)) return n;
|
|
69
|
+
return universalMeasureTwips(v);
|
|
70
|
+
}
|
|
71
|
+
var MEASURE_TWIPS = new Map([
|
|
72
|
+
["pt", 20],
|
|
73
|
+
["pc", 240],
|
|
74
|
+
["pi", 240],
|
|
75
|
+
["in", 1440],
|
|
76
|
+
["cm", 1440 / 2.54],
|
|
77
|
+
["mm", 144 / 2.54]
|
|
78
|
+
]);
|
|
79
|
+
function universalMeasureTwips(raw) {
|
|
80
|
+
const m = /^\s*(-?[0-9]+(?:\.[0-9]+)?)(pt|pc|pi|in|cm|mm)\s*$/iu.exec(raw);
|
|
81
|
+
if (!m) return void 0;
|
|
82
|
+
const per = MEASURE_TWIPS.get(m[2].toLowerCase());
|
|
83
|
+
return per === void 0 ? void 0 : Number(m[1]) * per;
|
|
69
84
|
}
|
|
70
85
|
/** Shorthand for the `val` attribute (`@w:val`/…). */
|
|
71
86
|
function poVal(node) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { CellType, WorksheetCell, ColumnWidth, MergedRange, RowHeight, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRuleTop10, CfRuleAboveAverage, CfRuleDupUnique, CfRuleText, CfRuleExpression, CfRuleTimePeriod, TimePeriodKind, CfRule, ConditionalFormat, DataValidationType, DataValidation, HyperlinkRef, HeaderFooter, FormControlRef, OleObjectRef, SheetRichRun, SparklineKind, ParsedSparkline, ExcelTable, PivotTable, SheetPane, } from './types.js';
|
|
1
|
+
export type { CellType, WorksheetCell, ColumnStyle, ColumnWidth, MergedRange, RowHeight, RowStyle, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRuleTop10, CfRuleAboveAverage, CfRuleDupUnique, CfRuleText, CfRuleExpression, CfRuleTimePeriod, TimePeriodKind, CfRule, ConditionalFormat, DataValidationType, DataValidation, HyperlinkRef, HeaderFooter, FormControlRef, OleObjectRef, SheetRichRun, SparklineKind, ParsedSparkline, ExcelTable, PivotTable, SheetPane, } from './types.js';
|
|
@@ -11,12 +11,40 @@ export interface WorksheetCell {
|
|
|
11
11
|
readonly inlineText?: string;
|
|
12
12
|
/** Index into the workbook's `cellXfs` (`xl/styles.xml`). 0 means default style. */
|
|
13
13
|
readonly styleIndex?: number;
|
|
14
|
+
/**
|
|
15
|
+
* §18.3.1.4 `vm` — 1-based index into `xl/metadata.xml`'s `<valueMetadata>`.
|
|
16
|
+
* A cell whose value is a rich value stores a legacy error in `<v>` for
|
|
17
|
+
* readers that predate the feature, and points here for the real one.
|
|
18
|
+
*/
|
|
19
|
+
readonly valueMetadataIndex?: number;
|
|
14
20
|
}
|
|
15
21
|
/** §18.3.1.13 `<col>` — a width (in character units) for the column span `min..max`. */
|
|
16
22
|
export interface ColumnWidth {
|
|
17
23
|
readonly min: number;
|
|
18
24
|
readonly max: number;
|
|
19
25
|
readonly widthChars: number;
|
|
26
|
+
/** §18.3.1.13 `hidden` — Excel and LibreOffice print neither the column nor its cells. */
|
|
27
|
+
readonly hidden?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* §18.3.1.13 `<col style>` / §18.3.1.73 `<row s customFormat>` — the style a
|
|
31
|
+
* cell takes when the file gives it none of its own.
|
|
32
|
+
*
|
|
33
|
+
* A spreadsheet formats whole columns and whole rows without writing a `<c>`
|
|
34
|
+
* for each one: 51710.xlsx paints its column A grey with a single `<col
|
|
35
|
+
* min="1" max="1" style="1"/>`, and 588 of its rows carry no A cell at all.
|
|
36
|
+
* The band is on the page in Excel and in LibreOffice, so the default has to
|
|
37
|
+
* reach the paint even where there is nothing to paint it on.
|
|
38
|
+
*/
|
|
39
|
+
export interface ColumnStyle {
|
|
40
|
+
readonly min: number;
|
|
41
|
+
readonly max: number;
|
|
42
|
+
readonly styleIndex: number;
|
|
43
|
+
}
|
|
44
|
+
/** §18.3.1.73 — the style a row hands to its unwritten cells. */
|
|
45
|
+
export interface RowStyle {
|
|
46
|
+
readonly row: number;
|
|
47
|
+
readonly styleIndex: number;
|
|
20
48
|
}
|
|
21
49
|
/** §18.3.1.55 `<mergeCell>` — a merged cell rectangle (0-indexed, inclusive bounds). */
|
|
22
50
|
export interface MergedRange {
|
|
@@ -34,6 +62,8 @@ export interface RowHeight {
|
|
|
34
62
|
readonly row: number;
|
|
35
63
|
readonly heightPt: number;
|
|
36
64
|
readonly customHeight: boolean;
|
|
65
|
+
/** §18.3.1.73 `hidden` — the row is not printed at all. */
|
|
66
|
+
readonly hidden?: boolean;
|
|
37
67
|
}
|
|
38
68
|
/** ECMA-376 Part 1 §18.3.1.62 — `<pageMargins>`. All attributes are in inches. */
|
|
39
69
|
export interface XlsxPageMargins {
|
|
@@ -59,6 +89,18 @@ export interface XlsxPageSetup {
|
|
|
59
89
|
readonly fitToWidth?: number;
|
|
60
90
|
/** Number of pages tall to fit to; default 1. */
|
|
61
91
|
readonly fitToHeight?: number;
|
|
92
|
+
/**
|
|
93
|
+
* `r:id` of the sheet's `printerSettings` part. When `paperSize` is absent the
|
|
94
|
+
* paper is whatever that part's DEVMODE says, which is how Excel records the
|
|
95
|
+
* choice made in the print dialog rather than in the sheet.
|
|
96
|
+
*/
|
|
97
|
+
readonly printerSettingsRelId?: string;
|
|
98
|
+
/**
|
|
99
|
+
* §18.3.1.63 `cellComments` — where the sheet's notes are printed:
|
|
100
|
+
* `none` (the default) prints none of them, `asDisplayed` prints them where
|
|
101
|
+
* they float, `atEnd` gathers them after the grid.
|
|
102
|
+
*/
|
|
103
|
+
readonly cellComments?: 'none' | 'asDisplayed' | 'atEnd';
|
|
62
104
|
}
|
|
63
105
|
/**
|
|
64
106
|
* ECMA-376 Part 1 §18.3.1.70 — `<printOptions>`. Controls what is rendered when
|
|
@@ -68,6 +110,11 @@ export interface XlsxPageSetup {
|
|
|
68
110
|
*/
|
|
69
111
|
export interface XlsxPrintOptions {
|
|
70
112
|
readonly gridLines?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* §18.3.1.70 `headings` — print the column letters across the top and the row
|
|
115
|
+
* numbers down the left, the way the sheet looks on screen. Off by default.
|
|
116
|
+
*/
|
|
117
|
+
readonly headings?: boolean;
|
|
71
118
|
readonly horizontalCentered?: boolean;
|
|
72
119
|
readonly verticalCentered?: boolean;
|
|
73
120
|
}
|
|
@@ -83,6 +130,10 @@ export interface ParsedWorksheet {
|
|
|
83
130
|
readonly columns: ReadonlyArray<ColumnWidth>;
|
|
84
131
|
readonly merges: ReadonlyArray<MergedRange>;
|
|
85
132
|
readonly rowHeights: ReadonlyArray<RowHeight>;
|
|
133
|
+
/** §18.3.1.13 `<col style>` — the default style of a whole column span. */
|
|
134
|
+
readonly columnStyles?: ReadonlyArray<ColumnStyle>;
|
|
135
|
+
/** §18.3.1.73 `<row s customFormat="1">` — the default style of a whole row. */
|
|
136
|
+
readonly rowStyles?: ReadonlyArray<RowStyle>;
|
|
86
137
|
/**
|
|
87
138
|
* ECMA-376 §18.3.1.81 `<sheetFormatPr defaultRowHeight>` — the height, in
|
|
88
139
|
* points, of every row that carries no `ht` of its own. A row in a
|
|
@@ -120,6 +171,12 @@ export interface ParsedWorksheet {
|
|
|
120
171
|
readonly colBreaks?: ReadonlyArray<number>;
|
|
121
172
|
/** §18.3.1.36 `<drawing r:id>` — the sheet's drawing part (charts/shapes). */
|
|
122
173
|
readonly drawingRelId?: string;
|
|
174
|
+
/**
|
|
175
|
+
* §18.3.1.36 `<legacyDrawing r:id>` — the relationship to the sheet's VML
|
|
176
|
+
* drawing part. A form control put on the sheet by Excel's Forms toolbar is
|
|
177
|
+
* declared there and nowhere else.
|
|
178
|
+
*/
|
|
179
|
+
readonly legacyDrawingRelId?: string;
|
|
123
180
|
/** §18.3.1.18 `<conditionalFormatting>` — value-driven cell formats (E-SHEET SC1). */
|
|
124
181
|
readonly conditionalFormats?: ReadonlyArray<ConditionalFormat>;
|
|
125
182
|
/**
|
|
@@ -254,6 +311,8 @@ export interface XlsxFont {
|
|
|
254
311
|
readonly bold?: boolean;
|
|
255
312
|
readonly italic?: boolean;
|
|
256
313
|
readonly underline?: boolean;
|
|
314
|
+
/** §18.8.37 `<strike/>` — the font is struck through. */
|
|
315
|
+
readonly strike?: boolean;
|
|
257
316
|
readonly colorHex?: string;
|
|
258
317
|
readonly name?: string;
|
|
259
318
|
}
|
|
@@ -341,6 +400,18 @@ export interface XlsxStyles {
|
|
|
341
400
|
export interface Dxf {
|
|
342
401
|
readonly font?: XlsxFont;
|
|
343
402
|
readonly fill?: XlsxFill;
|
|
403
|
+
/**
|
|
404
|
+
* §18.8.9 `<border>` inside a dxf — a rule may format a cell with nothing but
|
|
405
|
+
* an edge, and half the differential formats in a real workbook do exactly
|
|
406
|
+
* that (a rule under every year boundary, a box around a total).
|
|
407
|
+
*/
|
|
408
|
+
readonly border?: XlsxBorder;
|
|
409
|
+
/**
|
|
410
|
+
* §18.8.9 `<numFmt formatCode>` — a rule may change how the VALUE reads, not
|
|
411
|
+
* just how the cell looks: two decimals where a threshold is crossed. Every
|
|
412
|
+
* dxf in new_cond_format_test.xlsx is one of these and nothing else.
|
|
413
|
+
*/
|
|
414
|
+
readonly numberFormat?: string;
|
|
344
415
|
}
|
|
345
416
|
/**
|
|
346
417
|
* ECMA-376 Part 1 §18.2.5 — `<definedName>`. A workbook-scoped (or sheet-scoped,
|
|
@@ -364,6 +435,12 @@ export interface CfRuleCellIs {
|
|
|
364
435
|
readonly operator: CfOperator;
|
|
365
436
|
readonly formulas: ReadonlyArray<string>;
|
|
366
437
|
readonly dxfId: number;
|
|
438
|
+
/**
|
|
439
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
440
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
441
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
442
|
+
*/
|
|
443
|
+
readonly dxf?: Dxf;
|
|
367
444
|
}
|
|
368
445
|
/**
|
|
369
446
|
* §18.3.1.11 ST_CfvoType — how a `<cfvo>` stop's threshold is derived.
|
|
@@ -406,6 +483,12 @@ export interface CfRuleDataBar {
|
|
|
406
483
|
readonly colorHex: string;
|
|
407
484
|
readonly minLength?: number;
|
|
408
485
|
readonly maxLength?: number;
|
|
486
|
+
/**
|
|
487
|
+
* §18.3.1.28 `showValue` — false means the cell shows the BAR ONLY, with its
|
|
488
|
+
* number hidden. Excel's "Show Bar Only" checkbox; a dashboard uses it so the
|
|
489
|
+
* figure does not sit on top of its own gauge.
|
|
490
|
+
*/
|
|
491
|
+
readonly showValue?: boolean;
|
|
409
492
|
}
|
|
410
493
|
/**
|
|
411
494
|
* §18.3.1.49 `<cfRule type="iconSet">` — picks one glyph per cell from a named
|
|
@@ -432,6 +515,12 @@ export interface CfRuleTop10 {
|
|
|
432
515
|
readonly percent: boolean;
|
|
433
516
|
readonly bottom: boolean;
|
|
434
517
|
readonly dxfId: number;
|
|
518
|
+
/**
|
|
519
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
520
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
521
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
522
|
+
*/
|
|
523
|
+
readonly dxf?: Dxf;
|
|
435
524
|
}
|
|
436
525
|
/**
|
|
437
526
|
* §18.3.1.10 `<cfRule type="aboveAverage">` — cells above (default) or below the
|
|
@@ -445,6 +534,12 @@ export interface CfRuleAboveAverage {
|
|
|
445
534
|
readonly equalAverage: boolean;
|
|
446
535
|
readonly stdDev?: number;
|
|
447
536
|
readonly dxfId: number;
|
|
537
|
+
/**
|
|
538
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
539
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
540
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
541
|
+
*/
|
|
542
|
+
readonly dxf?: Dxf;
|
|
448
543
|
}
|
|
449
544
|
/**
|
|
450
545
|
* §18.3.1.10 `<cfRule type="duplicateValues" | "uniqueValues">` — cells whose
|
|
@@ -456,6 +551,12 @@ export interface CfRuleDupUnique {
|
|
|
456
551
|
readonly type: 'duplicateValues' | 'uniqueValues';
|
|
457
552
|
readonly priority: number;
|
|
458
553
|
readonly dxfId: number;
|
|
554
|
+
/**
|
|
555
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
556
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
557
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
558
|
+
*/
|
|
559
|
+
readonly dxf?: Dxf;
|
|
459
560
|
}
|
|
460
561
|
/**
|
|
461
562
|
* §18.3.1.10 `<cfRule type="containsText" | "notContainsText" | "beginsWith" |
|
|
@@ -468,6 +569,12 @@ export interface CfRuleText {
|
|
|
468
569
|
readonly priority: number;
|
|
469
570
|
readonly text: string;
|
|
470
571
|
readonly dxfId: number;
|
|
572
|
+
/**
|
|
573
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
574
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
575
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
576
|
+
*/
|
|
577
|
+
readonly dxf?: Dxf;
|
|
471
578
|
readonly formula?: string;
|
|
472
579
|
}
|
|
473
580
|
/**
|
|
@@ -483,6 +590,12 @@ export interface CfRuleExpression {
|
|
|
483
590
|
readonly priority: number;
|
|
484
591
|
readonly formula: string;
|
|
485
592
|
readonly dxfId: number;
|
|
593
|
+
/**
|
|
594
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
595
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
596
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
597
|
+
*/
|
|
598
|
+
readonly dxf?: Dxf;
|
|
486
599
|
}
|
|
487
600
|
/** §18.18.82 ST_TimePeriod — the clock-relative window a `timePeriod` rule tests. */
|
|
488
601
|
export type TimePeriodKind = 'today' | 'yesterday' | 'tomorrow' | 'last7Days' | 'thisWeek' | 'lastWeek' | 'nextWeek' | 'thisMonth' | 'lastMonth' | 'nextMonth';
|
|
@@ -499,6 +612,12 @@ export interface CfRuleTimePeriod {
|
|
|
499
612
|
readonly priority: number;
|
|
500
613
|
readonly timePeriod: TimePeriodKind;
|
|
501
614
|
readonly dxfId: number;
|
|
615
|
+
/**
|
|
616
|
+
* The format itself, when the rule carries it instead of pointing at the
|
|
617
|
+
* workbook's table — the 2009 extension (`<x14:cfRule><x14:dxf>`) writes it
|
|
618
|
+
* inline, and `dxfId` names nothing there. Takes precedence when present.
|
|
619
|
+
*/
|
|
620
|
+
readonly dxf?: Dxf;
|
|
502
621
|
readonly formula?: string;
|
|
503
622
|
}
|
|
504
623
|
/** One conditional-format rule (`<cfRule>`): the union over the supported `type`s. */
|
|
@@ -542,6 +661,18 @@ export interface HeaderFooter {
|
|
|
542
661
|
export interface FormControlRef {
|
|
543
662
|
readonly name?: string;
|
|
544
663
|
readonly relId: string;
|
|
664
|
+
/**
|
|
665
|
+
* §18.3.1.19 `@shapeId` — the id of this control's shape in the sheet's legacy
|
|
666
|
+
* VML drawing. It is what tells an ActiveX control's VML shape apart from a
|
|
667
|
+
* Forms-toolbar control that has no `<control>` entry at all.
|
|
668
|
+
*/
|
|
669
|
+
readonly shapeId?: string;
|
|
670
|
+
/**
|
|
671
|
+
* §18.3.1.20 `<controlPr print>` — Excel's "Print object" checkbox. It
|
|
672
|
+
* defaults to true, and a control that clears it is on screen only: neither
|
|
673
|
+
* Excel nor Calc puts it on the page.
|
|
674
|
+
*/
|
|
675
|
+
readonly print?: boolean;
|
|
545
676
|
}
|
|
546
677
|
/**
|
|
547
678
|
* §18.3.* `<oleObjects><oleObject progId r:id>` — an embedded OLE / ActiveX
|
|
@@ -567,6 +698,12 @@ export interface SheetRichRun {
|
|
|
567
698
|
readonly bold?: boolean;
|
|
568
699
|
readonly italic?: boolean;
|
|
569
700
|
readonly underline?: boolean;
|
|
701
|
+
/**
|
|
702
|
+
* §18.8.37 `<strike/>` on the run — struck-through text inside a cell that is
|
|
703
|
+
* otherwise not. 58315.xlsx crosses out the middle of "320-338 350", which is
|
|
704
|
+
* the whole point of the cell.
|
|
705
|
+
*/
|
|
706
|
+
readonly strike?: boolean;
|
|
570
707
|
readonly colorHex?: string;
|
|
571
708
|
readonly sizePt?: number;
|
|
572
709
|
/** §18.4.2 `<vertAlign>` — superscript / subscript within the cell text. */
|
|
@@ -38,8 +38,10 @@ function resolveRunProperties(runDirect, paragraphDirect, sheet) {
|
|
|
38
38
|
}
|
|
39
39
|
function computeRunProperties(runDirect, paragraphDirect, sheet) {
|
|
40
40
|
let acc = mergeRun(DEFAULT_RESOLVED_RUN, sheet.defaultRunProperties);
|
|
41
|
-
if (paragraphDirect.
|
|
42
|
-
|
|
41
|
+
if (paragraphDirect.inheritedRun) acc = mergeRun(acc, paragraphDirect.inheritedRun);
|
|
42
|
+
const styleId = paragraphDirect.styleId ?? defaultParagraphStyleId(sheet);
|
|
43
|
+
if (styleId) {
|
|
44
|
+
const chain = resolveStyleChain(styleId, sheet);
|
|
43
45
|
acc = mergeRun(acc, chain.rPr);
|
|
44
46
|
}
|
|
45
47
|
if (runDirect.styleId) {
|
|
@@ -71,12 +73,27 @@ function resolveParagraphProperties(paragraphDirect, sheet) {
|
|
|
71
73
|
}
|
|
72
74
|
function computeParagraphProperties(paragraphDirect, sheet) {
|
|
73
75
|
let acc = mergePar(DEFAULT_RESOLVED_PARAGRAPH, sheet.defaultParagraphProperties);
|
|
74
|
-
if (paragraphDirect.
|
|
75
|
-
|
|
76
|
+
if (paragraphDirect.tableStyle ?? paragraphDirect.inheritedRun) acc = mergePar(acc, {
|
|
77
|
+
...paragraphDirect.tableStyle,
|
|
78
|
+
...paragraphDirect.inheritedRun ? { runProperties: paragraphDirect.inheritedRun } : {}
|
|
79
|
+
});
|
|
80
|
+
const styleId = paragraphDirect.styleId ?? defaultParagraphStyleId(sheet);
|
|
81
|
+
if (styleId) {
|
|
82
|
+
const chain = resolveStyleChain(styleId, sheet);
|
|
76
83
|
acc = mergePar(acc, chain.pPr);
|
|
77
84
|
}
|
|
78
85
|
return mergePar(acc, paragraphDirect);
|
|
79
86
|
}
|
|
87
|
+
/** The id of the `w:default="1"` paragraph style, cached per sheet. */
|
|
88
|
+
var defaultParagraphStyleCache = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
function defaultParagraphStyleId(sheet) {
|
|
90
|
+
const hit = defaultParagraphStyleCache.get(sheet);
|
|
91
|
+
if (hit !== void 0) return hit ?? void 0;
|
|
92
|
+
let found = null;
|
|
93
|
+
for (const style of sheet.styles.values()) if (style.type === "paragraph" && style.isDefault) found = style.id;
|
|
94
|
+
defaultParagraphStyleCache.set(sheet, found);
|
|
95
|
+
return found ?? void 0;
|
|
96
|
+
}
|
|
80
97
|
function resolveStyleChain(styleId, sheet) {
|
|
81
98
|
const chain = [];
|
|
82
99
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -108,40 +125,72 @@ function mergeRun(base, override) {
|
|
|
108
125
|
bold: override.bold ?? base.bold,
|
|
109
126
|
italic: override.italic ?? base.italic,
|
|
110
127
|
underline: override.underline ?? base.underline,
|
|
128
|
+
...override.underlineColorHex ?? base.underlineColorHex ? { underlineColorHex: override.underlineColorHex ?? base.underlineColorHex } : {},
|
|
111
129
|
strike: override.strike ?? base.strike,
|
|
130
|
+
caps: override.caps ?? base.caps,
|
|
131
|
+
smallCaps: override.smallCaps ?? base.smallCaps,
|
|
112
132
|
fontSizePt: override.fontSizePt ?? base.fontSizePt,
|
|
113
133
|
colorHex: override.colorHex ?? base.colorHex,
|
|
114
134
|
fontFamily: override.fontFamily ?? base.fontFamily,
|
|
115
135
|
verticalAlign: override.verticalAlign ?? base.verticalAlign,
|
|
116
136
|
rtl: override.rtl ?? base.rtl,
|
|
117
|
-
...lang !== void 0 ? { lang } : {}
|
|
137
|
+
...lang !== void 0 ? { lang } : {},
|
|
138
|
+
...(override.shadingColorHex ?? base.shadingColorHex) !== void 0 ? { shadingColorHex: override.shadingColorHex ?? base.shadingColorHex } : {},
|
|
139
|
+
...(override.letterSpacingPt ?? base.letterSpacingPt) !== void 0 ? { letterSpacingPt: override.letterSpacingPt ?? base.letterSpacingPt } : {}
|
|
118
140
|
};
|
|
119
141
|
}
|
|
120
142
|
function mergePar(base, override) {
|
|
121
143
|
const outlineLevel = override.outlineLevel ?? base.outlineLevel;
|
|
122
144
|
const styleId = override.styleId ?? base.styleId;
|
|
123
|
-
const numbering = override.numbering ?? base.numbering
|
|
145
|
+
const numbering = override.numbering ?? (override.numberingLevel !== void 0 && base.numbering !== void 0 ? {
|
|
146
|
+
...base.numbering,
|
|
147
|
+
ilvl: override.numberingLevel
|
|
148
|
+
} : base.numbering);
|
|
149
|
+
const runProperties = override.runProperties ?? base.runProperties;
|
|
150
|
+
const frame = override.frame ?? base.frame;
|
|
151
|
+
const sectionBreak = override.sectionBreak ?? base.sectionBreak;
|
|
152
|
+
const textDirection = override.textDirection ?? base.textDirection;
|
|
153
|
+
const snapToGrid = override.snapToGrid ?? base.snapToGrid;
|
|
124
154
|
return {
|
|
125
155
|
alignment: override.alignment ?? base.alignment,
|
|
126
|
-
spacingBefore: override.spacingBefore ?? base.spacingBefore,
|
|
127
|
-
spacingAfter: override.spacingAfter ?? base.spacingAfter,
|
|
156
|
+
spacingBefore: override.spacingBeforeAuto ?? override.spacingBefore ?? base.spacingBefore,
|
|
157
|
+
spacingAfter: override.spacingAfterAuto ?? override.spacingAfter ?? base.spacingAfter,
|
|
128
158
|
spacingLine: override.spacingLine ?? base.spacingLine,
|
|
129
159
|
spacingLineRule: override.spacingLineRule ?? base.spacingLineRule,
|
|
130
160
|
indentLeft: override.indentLeft ?? base.indentLeft,
|
|
131
161
|
indentRight: override.indentRight ?? base.indentRight,
|
|
132
162
|
indentFirstLine: override.indentFirstLine ?? base.indentFirstLine,
|
|
133
163
|
pageBreakBefore: override.pageBreakBefore ?? base.pageBreakBefore,
|
|
164
|
+
contextualSpacing: override.contextualSpacing ?? base.contextualSpacing,
|
|
165
|
+
tabs: override.tabs ?? base.tabs,
|
|
134
166
|
bidi: override.bidi ?? base.bidi,
|
|
167
|
+
...override.borders ?? base.borders ? { borders: override.borders ?? base.borders } : {},
|
|
168
|
+
...override.shading ?? base.shading ? { shading: override.shading ?? base.shading } : {},
|
|
135
169
|
...outlineLevel !== void 0 ? { outlineLevel } : {},
|
|
136
170
|
...styleId !== void 0 ? { styleId } : {},
|
|
137
|
-
...numbering !== void 0 ? { numbering } : {}
|
|
171
|
+
...numbering !== void 0 ? { numbering } : {},
|
|
172
|
+
...runProperties !== void 0 ? { runProperties } : {},
|
|
173
|
+
...frame !== void 0 ? { frame } : {},
|
|
174
|
+
...sectionBreak !== void 0 ? { sectionBreak } : {},
|
|
175
|
+
...textDirection !== void 0 ? { textDirection } : {},
|
|
176
|
+
...snapToGrid !== void 0 ? { snapToGrid } : {}
|
|
138
177
|
};
|
|
139
178
|
}
|
|
140
179
|
function mergeRunPartial(base, override) {
|
|
141
180
|
return copyDefined(base, override);
|
|
142
181
|
}
|
|
143
182
|
function mergeParPartial(base, override) {
|
|
144
|
-
|
|
183
|
+
const out = copyDefined(base, override);
|
|
184
|
+
if (override.numbering === void 0 && override.numberingLevel !== void 0) {
|
|
185
|
+
if (base.numbering !== void 0) return {
|
|
186
|
+
...out,
|
|
187
|
+
numbering: {
|
|
188
|
+
...base.numbering,
|
|
189
|
+
ilvl: override.numberingLevel
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
145
194
|
}
|
|
146
195
|
function copyDefined(base, override) {
|
|
147
196
|
const out = { ...base };
|
|
@@ -188,7 +237,13 @@ function resolveBodyStyles(body, sheet) {
|
|
|
188
237
|
const visit = (el) => {
|
|
189
238
|
if (el.kind === "paragraph") visitParagraph(el.paragraph);
|
|
190
239
|
else if (el.kind === "table") for (const row of el.table.rows) for (const cell of row.cells) for (const child of cell.content) visit(child);
|
|
191
|
-
else if (el.kind === "shape"
|
|
240
|
+
else if (el.kind === "shape") {
|
|
241
|
+
const shapeText = (sh) => {
|
|
242
|
+
for (const child of sh.text?.content ?? []) visit(child);
|
|
243
|
+
for (const member of sh.children ?? []) shapeText(member.shape);
|
|
244
|
+
};
|
|
245
|
+
shapeText(el.shape);
|
|
246
|
+
}
|
|
192
247
|
};
|
|
193
248
|
for (const el of body) visit(el);
|
|
194
249
|
return body;
|
|
@@ -22,8 +22,10 @@ function applyTableStyle(table, sheet) {
|
|
|
22
22
|
const folded = foldTableStyleChain(styleId, sheet);
|
|
23
23
|
if (!folded) return;
|
|
24
24
|
const tp = table.properties;
|
|
25
|
+
const directBorders = tp.borders;
|
|
25
26
|
if (!tp.borders && folded.base.borders) tp.borders = folded.base.borders;
|
|
26
27
|
if (!tp.defaultCellMargins && folded.base.cellMargins) tp.defaultCellMargins = folded.base.cellMargins;
|
|
28
|
+
if (tp.indentPt === void 0 && folded.base.indentPt !== void 0) tp.indentPt = folded.base.indentPt;
|
|
27
29
|
const look = table.properties.look ?? {};
|
|
28
30
|
const rows = table.rows;
|
|
29
31
|
const colCount = Math.max(table.grid.length, ...rows.map((r) => r.cells.reduce((s, c) => s + (c.properties.colSpan ?? 1), 0)));
|
|
@@ -33,8 +35,8 @@ function applyTableStyle(table, sheet) {
|
|
|
33
35
|
for (const cell of row.cells) {
|
|
34
36
|
const span = cell.properties.colSpan ?? 1;
|
|
35
37
|
const layer = cellLayer(folded, look, {
|
|
36
|
-
firstRow: r === 0,
|
|
37
|
-
lastRow: r === rows.length - 1,
|
|
38
|
+
firstRow: r === 0 || row.properties.conditional?.firstRow === true,
|
|
39
|
+
lastRow: r === rows.length - 1 || row.properties.conditional?.lastRow === true,
|
|
38
40
|
firstCol: colStart === 0,
|
|
39
41
|
lastCol: colStart + span >= colCount,
|
|
40
42
|
rowBand: bandIndex(r, look.firstRow === true, folded.rowBandSize),
|
|
@@ -42,20 +44,34 @@ function applyTableStyle(table, sheet) {
|
|
|
42
44
|
noHBand: look.noHBand === true,
|
|
43
45
|
noVBand: look.noVBand === true
|
|
44
46
|
});
|
|
47
|
+
const pos = {
|
|
48
|
+
firstRow: r === 0 || row.properties.conditional?.firstRow === true,
|
|
49
|
+
lastRow: r === rows.length - 1 || row.properties.conditional?.lastRow === true,
|
|
50
|
+
firstCol: colStart === 0,
|
|
51
|
+
lastCol: colStart + span >= colCount
|
|
52
|
+
};
|
|
45
53
|
colStart += span;
|
|
46
54
|
if (!layer) continue;
|
|
47
|
-
applyLayerToCell(cell, layer);
|
|
55
|
+
applyLayerToCell(cell, layer, directBorders, pos);
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
|
-
function applyLayerToCell(tableCell, layer) {
|
|
59
|
+
function applyLayerToCell(tableCell, layer, directBorders, pos) {
|
|
52
60
|
const cell = tableCell;
|
|
53
61
|
if (layer.shading && !cell.properties.shading) cell.properties.shading = layer.shading;
|
|
54
62
|
if (layer.cellMargins && !cell.properties.margins) cell.properties.margins = layer.cellMargins;
|
|
55
63
|
if (layer.borders) {
|
|
56
64
|
const own = cell.properties.borders ?? {};
|
|
65
|
+
const fromStyle = { ...layer.borders };
|
|
66
|
+
if (directBorders) {
|
|
67
|
+
const stated = (side, outer) => (outer ? directBorders[side] : directBorders[side === "top" || side === "bottom" ? "insideH" : "insideV"]) !== void 0;
|
|
68
|
+
if (stated("top", pos.firstRow)) delete fromStyle.top;
|
|
69
|
+
if (stated("bottom", pos.lastRow)) delete fromStyle.bottom;
|
|
70
|
+
if (stated("left", pos.firstCol)) delete fromStyle.left;
|
|
71
|
+
if (stated("right", pos.lastCol)) delete fromStyle.right;
|
|
72
|
+
}
|
|
57
73
|
const merged = {
|
|
58
|
-
...
|
|
74
|
+
...fromStyle,
|
|
59
75
|
...definedOnly(own)
|
|
60
76
|
};
|
|
61
77
|
cell.properties.borders = merged;
|
|
@@ -64,12 +80,18 @@ function applyLayerToCell(tableCell, layer) {
|
|
|
64
80
|
if (el.kind !== "paragraph") continue;
|
|
65
81
|
const p = el.paragraph;
|
|
66
82
|
if (layer.paragraphProperties) p.properties = {
|
|
67
|
-
...
|
|
68
|
-
|
|
83
|
+
...p.properties,
|
|
84
|
+
tableStyle: {
|
|
85
|
+
...p.properties.tableStyle,
|
|
86
|
+
...layer.paragraphProperties
|
|
87
|
+
}
|
|
69
88
|
};
|
|
70
|
-
if (layer.runProperties)
|
|
71
|
-
...
|
|
72
|
-
|
|
89
|
+
if (layer.runProperties) p.properties = {
|
|
90
|
+
...p.properties,
|
|
91
|
+
inheritedRun: {
|
|
92
|
+
...p.properties.inheritedRun,
|
|
93
|
+
...layer.runProperties
|
|
94
|
+
}
|
|
73
95
|
};
|
|
74
96
|
}
|
|
75
97
|
}
|
|
@@ -79,7 +101,8 @@ function bandIndex(index, skipFirst, bandSize) {
|
|
|
79
101
|
return Math.floor(adjusted / Math.max(1, bandSize));
|
|
80
102
|
}
|
|
81
103
|
function cellLayer(folded, look, pos) {
|
|
82
|
-
const
|
|
104
|
+
const { borders: _tableWide, ...withoutBorders } = folded.base;
|
|
105
|
+
const layers = [withoutBorders];
|
|
83
106
|
const cond = (t) => folded.conditions.get(t);
|
|
84
107
|
if (!pos.noVBand && pos.colBand >= 0) layers.push(pos.colBand % 2 === 0 ? cond("band1Vert") : cond("band2Vert"));
|
|
85
108
|
if (!pos.noHBand && pos.rowBand >= 0) layers.push(pos.rowBand % 2 === 0 ? cond("band1Horz") : cond("band2Horz"));
|
|
@@ -145,6 +168,7 @@ function mergeLayer(base, override) {
|
|
|
145
168
|
...base.cellMargins,
|
|
146
169
|
...definedOnly(override.cellMargins ?? {})
|
|
147
170
|
} } : {},
|
|
171
|
+
...(override.indentPt ?? base.indentPt) !== void 0 ? { indentPt: override.indentPt ?? base.indentPt } : {},
|
|
148
172
|
...override.shading ?? base.shading ? { shading: override.shading ?? base.shading } : {},
|
|
149
173
|
...override.runProperties ?? base.runProperties ? { runProperties: {
|
|
150
174
|
...base.runProperties,
|