js.documents 1.87.3 → 1.87.5
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/README.md +1 -1
- package/dist/edit/ods/column-row.cjs +22 -0
- package/dist/edit/ods/column-row.d.cts +3 -1
- package/dist/edit/ods/column-row.d.ts +3 -1
- package/dist/edit/ods/column-row.js +21 -1
- package/dist/edit/ods/print-settings.cjs +5 -3
- package/dist/edit/ods/print-settings.js +6 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -629,7 +629,7 @@ To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
|
|
|
629
629
|
- **`ContentStroke.style` (`solid`/`dashed`/`dotted`/`double`) is not written by any vector writer, ODF or DrawingML.** `LayoutLine`/`LayoutPath` DO carry an optional `style` enum now (`document-schema.js` 2.1.0), and a reconstruction path could populate it — but neither vector writer reads the field: `src/edit/drawingml/vector.ts`'s `outline()` writes `a:ln` with width + colour only (no `a:prstDash`), and `src/edit/odg/style.ts` writes `draw:stroke` + `svg:stroke-color`/`svg:stroke-width` only (no `draw:stroke-dash`). A hand-built `ContentVector` setting `stroke.style` consequently paints solid; a real, bounded gap rather than an oversight. Cell borders are a separate path — `pushCellBorderLines` does set the style and pdf-codec renders it (see the cell-border gotcha below) — and `a:prstDash` has no `double` member to map the fourth value onto regardless.
|
|
630
630
|
- **`pdfToOds` recovers what was printed, not what was entered.** `reconstructSpreadsheet` (`src/layout/reconstruct.ts`) tries a real gridline lattice first: it scans the page's `LayoutLine`/stroked-single-segment-`LayoutPath` items (see the `interpret.ts` gotcha above) for enough parallel horizontal and vertical lines at consistent positions to call it a printed grid (`MIN_GRIDLINE_COUNT_PER_AXIS = 3` per axis, i.e. at least a 2×2 grid, and a span-consistency check that rejects a scatter of unrelated short strokes — a page border or a couple of decorative rules — as not a genuine lattice), and uses those line positions DIRECTLY as cell boundaries when found. Absent a lattice, it clusters text into a grid from geometry alone instead: rows reuse `clusterIntoLines` verbatim (a spreadsheet cell's own text is never wrapped across lines, so a text line already IS a row), and columns generalise `clusterIntoParagraphs`'s own single `dominantLeftX` to several recurring x-position anchors, first merging directly-adjacent same-line fragments (`splitLineByLargeGaps`, the same >2em-gap signal `reconstructPresentation`'s own block clustering uses) so a cell whose text arrived as several run-level-split `LayoutText` items isn't scattered across spurious columns. Column widths and row heights are genuinely measured from whichever geometry was used (drawn gridline gaps, or measured text/anchor extents), never invented. Every recovered cell always carries its own extracted `displayText` verbatim, and additionally carries a **heuristically re-typed** `value` wherever `src/layout/cell-typing.ts` finds exactly one defensible reading of that string; a formula is still never claimed. See the dedicated heuristic-re-typing gotcha below and [Fidelity](#fidelity) for the full framing. `buildOdsPackage` (`src/edit/ods/content.ts`) is `pdfToOds`'s own package-building half, mirroring `buildOdtPackage`/`buildOdpPackage`/`buildOdgPackage`'s role for `pdfToOdt`/`pdfToOdp`/`pdfToOdg`.
|
|
631
631
|
- **`OdsSheet.printSettings` (`src/edit/ods/print-settings.ts`) now round-trips every field `ContentSheetPrintSettingsSchema` carries, not just the five it started with.** `pageSize`/`margins`/`gridlines`/`headers`/`pageOrder` resolve through the `table:style-name` → `style:style[family="table"]` → `style:master-page-name` → `style:master-page` → `style:page-layout` → `style:page-layout-properties` chain (`odf.js`'s own exported `findStyleElement`/`resolvePageLayoutProperties`/`parsePageSize`/`parseMargins`); the setter mints a fresh `style:page-layout` + `style:master-page` + `style:style[family="table"]` triple and repoints the sheet's own `table:style-name` to it on every call, the same append-only style-editing convention `src/edit/odg/style.ts` already documents. The remaining, previously-unimplemented fields are now implemented too: `printRange` reads/writes `table:print-ranges` directly on `table:table`; `scalePercent`/`fitToPages` read/write `style:scale-to` and `style:scale-to-X`/`style:scale-to-Y` on the page-layout-properties element; `repeatColumns`/`repeatRows` are read via `scanTableStructure`, a scoped-down mirror of `odf.js`'s own private `readTable`'s table-wide column/row cursor tracking (the same walk that function performs before ever calling its own `readPrintSettings`), and written by moving the real `table:table-column`/`table:table-row` elements covering the given range into a fresh `table:table-header-columns`/`table:table-header-rows` wrapper; `manualBreaks` read/write `fo:break-before="page"` on the named row/column's own style. Writing `repeatRows`/`repeatColumns` required teaching `address.ts`'s row/column addressing that a row/column may now live nested one level inside a header wrapper rather than as a direct `table:table` child, so a subsequent cell/column/row write against a wrapped index finds the real element instead of creating a spurious duplicate outside it; the width/height and manual-break writers all target the same `style:table-column-properties`/`style:table-row-properties` element, so each reads the column/row's current style first and mints a fresh style carrying the merged result, rather than a naive single-property mint clobbering whatever an earlier call had already set. No known gap remains in `ContentSheetPrintSettingsSchema` coverage.
|
|
632
|
-
- **`OdsSheet` now has a real column-width/row-height setter (`setColumnWidth`/`setRowHeight`, `src/edit/ods/column-row.ts`), closing a gap that escalated from cosmetic to a genuine correctness bug once `xlsxToPdf`/`pdfToXlsx` started composing through `buildOdsPackage` internally.** `OdsSheet.cell()`'s own column/row-materialisation (`address.ts`) creates a real, explicit `table:table-column`/`table:table-row` element for any position a caller ever addresses, but previously never gave it a width/height style. This is a genuinely different failure shape from a column/row with NO element at all: `sheets.ts`'s own `resolveAxis` only falls back to `DEFAULT_COLUMN_WIDTH_PT`/`DEFAULT_ROW_HEIGHT_PT` for an index with no `ContentSheetColumn`/`ContentSheetRow` entry whatsoever — an explicit-but-unstyled element reads back at `widthPt`/`heightPt` 0 (`odf.js`'s own `resolveColumnWidthPt`/`readRowLayout`), and that explicit zero wins over the fallback. While `buildOdsPackage`'s own output was only ever a terminal deliverable (`pdfToOds`, or a caller's own `readOdsContent` round trip), this was cosmetic: a real app reopening it would use its own defaults instead of the source's. `xlsxToPdf` (`xlsxToOds` then `odsToPdf`) made it a real bug instead — the intermediate ods bytes get laid out again by `convertSpreadsheetToLayout`, and a zero-size grid collapses every cell onto the same physical position rather than merely losing precision. `setColumnWidth`/`setRowHeight` mint a fresh `style:style[family="table-column"|"table-row"]` per column/row and repoint its own `table:style-name`, the same append-only style-minting convention `writeSheetPrintSettings`/`src/edit/odg/style.ts` already establish; `buildOdsPackage` now calls both for every `ContentSheetColumn`/`ContentSheetRow` a source sheet carries. Column/row HIDDEN state and `ContentSheetImage`/formula `embeddedObjects` are no longer gaps either, closed in the same phase: `OdsSheet.setColumnHidden`/`setRowHidden` set or clear `table:visibility="collapse"` directly on the `table:table-column`/`table:table-row` element — a plain attribute, not a style property, so it never interacts with the width/height setters above — and `buildOdsPackage` calls one of these for every column/row whose `hidden` field is `true`. **The "explicit but unstyled" hazard itself is now closed at its source, not just worked around by callers who remember to call `setColumnWidth`/`setRowHeight` explicitly.** `column-row.ts`'s `ensureColumnDefaultWidth`/`ensureRowDefaultHeight` stamp `DEFAULT_COLUMN_WIDTH_PT`/`DEFAULT_ROW_HEIGHT_PT` (matching `sheets.ts`'s own fallback values exactly) onto a column/row the moment any of `OdsSheet.cell()`, `mergeCells()`, `setColumnHidden()`, or `setRowHidden()` individuates it for the first time — but only when it has no width/height style at all yet, never overwriting a width a caller (or a real source document opened via `openOds`) already set. A plain `createOds()` sheet touched only through `.cell()` now reads back with a real, positive `widthPt`/`heightPt` on every column/row it addressed, never the ambiguous 0 that used to require an explicit `setColumnWidth`/`setRowHeight` call to avoid.
|
|
632
|
+
- **`OdsSheet` now has a real column-width/row-height setter (`setColumnWidth`/`setRowHeight`, `src/edit/ods/column-row.ts`), closing a gap that escalated from cosmetic to a genuine correctness bug once `xlsxToPdf`/`pdfToXlsx` started composing through `buildOdsPackage` internally.** `OdsSheet.cell()`'s own column/row-materialisation (`address.ts`) creates a real, explicit `table:table-column`/`table:table-row` element for any position a caller ever addresses, but previously never gave it a width/height style. This is a genuinely different failure shape from a column/row with NO element at all: `sheets.ts`'s own `resolveAxis` only falls back to `DEFAULT_COLUMN_WIDTH_PT`/`DEFAULT_ROW_HEIGHT_PT` for an index with no `ContentSheetColumn`/`ContentSheetRow` entry whatsoever — an explicit-but-unstyled element reads back at `widthPt`/`heightPt` 0 (`odf.js`'s own `resolveColumnWidthPt`/`readRowLayout`), and that explicit zero wins over the fallback. While `buildOdsPackage`'s own output was only ever a terminal deliverable (`pdfToOds`, or a caller's own `readOdsContent` round trip), this was cosmetic: a real app reopening it would use its own defaults instead of the source's. `xlsxToPdf` (`xlsxToOds` then `odsToPdf`) made it a real bug instead — the intermediate ods bytes get laid out again by `convertSpreadsheetToLayout`, and a zero-size grid collapses every cell onto the same physical position rather than merely losing precision. `setColumnWidth`/`setRowHeight` mint a fresh `style:style[family="table-column"|"table-row"]` per column/row and repoint its own `table:style-name`, the same append-only style-minting convention `writeSheetPrintSettings`/`src/edit/odg/style.ts` already establish; `buildOdsPackage` now calls both for every `ContentSheetColumn`/`ContentSheetRow` a source sheet carries. Column/row HIDDEN state and `ContentSheetImage`/formula `embeddedObjects` are no longer gaps either, closed in the same phase: `OdsSheet.setColumnHidden`/`setRowHidden` set or clear `table:visibility="collapse"` directly on the `table:table-column`/`table:table-row` element — a plain attribute, not a style property, so it never interacts with the width/height setters above — and `buildOdsPackage` calls one of these for every column/row whose `hidden` field is `true`. **The "explicit but unstyled" hazard itself is now closed at its source, not just worked around by callers who remember to call `setColumnWidth`/`setRowHeight` explicitly.** `column-row.ts`'s `ensureColumnDefaultWidth`/`ensureRowDefaultHeight` stamp `DEFAULT_COLUMN_WIDTH_PT`/`DEFAULT_ROW_HEIGHT_PT` (matching `sheets.ts`'s own fallback values exactly) onto a column/row the moment any of `OdsSheet.cell()`, `mergeCells()`, `setColumnHidden()`, or `setRowHidden()` individuates it for the first time — but only when it has no width/height style at all yet, never overwriting a width a caller (or a real source document opened via `openOds`) already set. A plain `createOds()` sheet touched only through `.cell()` now reads back with a real, positive `widthPt`/`heightPt` on every column/row it addressed, never the ambiguous 0 that used to require an explicit `setColumnWidth`/`setRowHeight` call to avoid. The identical hazard through print settings is now closed too: `print-settings.ts`'s `wrapRepeatRange` (the `repeatColumns`/`repeatRows` writer) stamps a real default width/height on every repeat-range element that lacks one via `column-row.ts`'s `ensureColumnElementDefaultWidth`/`ensureRowElementDefaultHeight`, the element-addressed counterparts to the index-addressed helpers above — so a `repeatColumns`/`repeatRows` range set beyond any cell a caller has touched no longer produces zero-width/zero-height columns and rows. Those helpers mint the default style directly on whatever element `collectRangeElements` hands back (a single-position element OR a repeated run covering several), so a compressed repeated run keeps its compression rather than being split one element per position just to give each an identical default. `OdsSheet.addImage` (`src/edit/ods/floating.ts`) writes a real floating `draw:frame`/`draw:image` into `table:shapes` (the ODF 1.3 content-model container for spreadsheet floating shapes, always `table:table`'s own first child in a package this editor builds), resolving a `ContentSheetImage`'s `anchorRow`/`anchorColumn` plus `offsetXPt`/`offsetYPt` to an absolute `svg:x`/`svg:y` by summing the real, currently-declared width/height of every column/row strictly before the anchor (header-wrapper-aware, hidden columns/rows contributing zero, falling back to the same default column/row size the layout engine assumes once the walk runs past what the sheet has declared) — reusing `addImageMedia` for the binary part and manifest entry, the same mechanism `src/edit/odp/image.ts` already uses for a slide. `OdsSheet.addEmbeddedObject` writes a real embedded ODF formula sub-document for `objectKind === 'formula'` (reusing `addFormulaObject`, the same mechanism `OdtBody.appendFormula` already uses); every other `objectKind` (`wordprocessing`/`presentation`/`spreadsheet`/`drawing`) is left unwritten, a documented, bounded gap mirroring `buildOdtPackage`'s identical narrowing for a `'drawing'` embedded object, since embedding one would mean writing that document's own package as a nested OLE sub-object, which no writer in this codebase implements. `buildOdsPackage` calls both for every sheet's images/embedded objects, after every column/row width/height/hidden call, so an image's own anchor resolves against the sheet's final, real column/row sizing. This is no longer write-only: `odf.js` 2.2.0's own `readOds` reads a sheet's floating shapes and embedded objects back (it previously hardcoded `images: []` and never set `embeddedObjects`), so a written image now verifies as a genuine `ContentDocument` re-read round trip — bytes, declared size, and anchor quartet — on top of the direct written-XML structural checks these tests already made.
|
|
633
633
|
- **`reconstructDrawing` maps recovered geometry back onto ODF shapes near-1:1, with no clustering — and every vector kind in this package's own `.odg` fixture now survives the round trip, where a stroked rect, an ellipse, and a line used to collapse to a generic `path`.** Every painted `LayoutItem` maps onto a `ContentVector`/`ContentShape` directly, in the exact z-order it was recovered — `LayoutRect` → `rect`, `LayoutEllipse` → `ellipse`, `LayoutLine` → `line`, `LayoutPath` → `path`, `LayoutText`/`LayoutImage` → `ContentShape` — a fundamentally more tractable problem than `reconstructWordprocessing`/`reconstructPresentation`'s own paragraph/shape geometry clustering, since a drawing has no semantic structure to infer at all. How much *kind* information survives is decided upstream, by what `readPdf` can hand it: pdf-codec's own shape-pattern detection (see the gotcha above) now recovers a rect under any fill/stroke combination, a real ellipse from the four kappa-ratio cubics `writeEllipse` emits, and a real line, so `reconstructDrawing` receives — and therefore emits — the original kind in each case. What still narrows: a rotation that is not a multiple of 90° leaves no axis-aligned pattern to match, so a rect turned by 30° comes back as a `path` carrying its four rotated corners exactly. Position, size, and fill/stroke colour survive regardless of kind (within ordinary floating-point/string-formatting tolerance). A `path` vector's own reconstructed `frame` is a further, separate approximation: it is the *tight* bounding box of every recovered point, cubic control points included (a cubic curve is guaranteed to lie within their convex hull, so this never clips the curve) — which can legitimately be *larger* than whatever frame the original path's own author declared, if that frame didn't tightly bound its own control points to begin with (a real, valid ODF/SVG authoring pattern: a `viewBox`/frame is a declared coordinate window, not a guaranteed tight bounding box). A single original drawing text box that PDF's own greedy line-wrapper split across several lines does **not** reconstruct as one multi-line shape: `reconstructDrawing` maps each recovered `LayoutText` item to its own separate `ContentShape` (the same one-`LayoutItem`-to-one-shape rule every other kind follows), so a wrapped multi-line text box comes back as several small, independently-positioned text boxes, one per original line — confirmed visually against real LibreOffice (see the real-file verification note below); the full text content still survives, just redistributed. `buildOdgPackage` (`src/edit/odg/content.ts`) is `pdfToOdg`'s own package-building half, mirroring `buildOdtPackage`/`buildOdpPackage`'s role for `pdfToOdt`/`pdfToOdp`.
|
|
634
634
|
- **Two real, confirmed-against-actual-LibreOffice-rendering fill bugs were fixed as part of building `reconstructDrawing`/`pdfToOdg`, not by it.** Both are pre-existing gaps in code that `reconstructDrawing`'s own real-file verification exposed, not something the reconstruction algorithm itself introduced, and both apply to every `.odg` this package writes, not only a reconstructed one: (1) `src/edit/odg/style.ts`'s `graphicPropertyAttrs` wrote `draw:fill-color` alone, with no accompanying `draw:fill="solid"` — real LibreOffice 26.2 fills a `draw:rect`/`draw:ellipse` that way fine, but silently renders a `draw:path` with the identical omission as unfilled, even with a fill colour declared. `draw:fill="solid"` is now written explicitly whenever a fill is set, for every vector kind. (2) `writeEllipse` (pdf-codec's own `content-write.ts`) never emitted a PDF closepath (`h`) operator, even though its four Bezier arcs already return exactly to their own starting point — PDF fill operators close every subpath implicitly regardless (ISO 32000-1 8.5.3.1), but `readPdf`'s own general path tracking only marks a subpath `closed: true` when it actually sees an explicit `h`, so a PDF-round-tripped ellipse came back with `closed: false`, which correctly-behaving ODF/SVG consumers then refuse to fill even with `draw:fill="solid"` set. `writeEllipse` now emits `h` before its paint operator, drawing no additional ink (the path was already geometrically closed) but recording that closure explicitly.
|
|
635
635
|
- **A vector primitive's own fill/stroke needed a self-contained graphic-family style writer, not `odf.js`'s own `StyleRegistry`.** `'graphic'` is a recognised `StyleFamily` member (`odf.js`'s `src/styles/registry.ts`), but `StylePropertiesSchema`/`buildStylePropertyElements` (`properties.ts`/`serialize.ts`) only ever model text/paragraph formatting and never emit a `style:graphic-properties` element for any family — extending that shared package for one narrow, documents.js-local need (`draw:fill(-color)`/`draw:stroke` + `svg:stroke-color`/`svg:stroke-width`) would be scope creep into a foreign package for a two-attribute-group writer this package can express directly. `src/edit/odg/style.ts` is that writer: it still reuses `odf.js`'s general append-only style-editing invariant (a setter always mints a fresh `style:style` and repoints `draw:style-name`, never mutates an existing entry — verified by the same `assertAutomaticStylesOnlyAppended` helper `OdpEditor`'s own live-view fidelity test uses) and `src/edit/odt/automatic-styles.ts`'s `ensureAutomaticStyles`/`nextStyleName` (the "find-or-create `office:automatic-styles`, mint the next unused name" logic every other hand-rolled style helper in this package already shares), rather than a third reimplementation of either.
|
|
@@ -76,6 +76,26 @@ function ensureColumnDefaultWidth(pkg, tableElement, index) {
|
|
|
76
76
|
function ensureRowDefaultHeight(pkg, tableElement, index) {
|
|
77
77
|
if (currentRowStyleProperties(pkg, require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag("table:table-row"), index, "table:number-rows-repeated", () => require_xml_fragment.el("table:table-row"), "table:table-header-rows")).heightPt === void 0) writeRowHeight(pkg, tableElement, index, DEFAULT_ROW_HEIGHT_PT);
|
|
78
78
|
}
|
|
79
|
+
function ensureColumnElementDefaultWidth(pkg, columnElement) {
|
|
80
|
+
if (currentColumnStyleProperties(pkg, columnElement).widthPt !== void 0) return;
|
|
81
|
+
const automaticStyles = require_edit_odt_automatic_styles.ensureAutomaticStyles(pkg);
|
|
82
|
+
const styleName = require_edit_odt_automatic_styles.nextStyleName(automaticStyles, "style:style", "OdsColumn");
|
|
83
|
+
automaticStyles.children.push(require_xml_fragment.el("style:style", {
|
|
84
|
+
"style:name": styleName,
|
|
85
|
+
"style:family": "table-column"
|
|
86
|
+
}, [require_xml_fragment.el("style:table-column-properties", { "style:column-width": (0, odf_js.formatOdfLength)(DEFAULT_COLUMN_WIDTH_PT) })]));
|
|
87
|
+
require_xml_edit.setAttr(columnElement, "table:style-name", styleName);
|
|
88
|
+
}
|
|
89
|
+
function ensureRowElementDefaultHeight(pkg, rowElement) {
|
|
90
|
+
if (currentRowStyleProperties(pkg, rowElement).heightPt !== void 0) return;
|
|
91
|
+
const automaticStyles = require_edit_odt_automatic_styles.ensureAutomaticStyles(pkg);
|
|
92
|
+
const styleName = require_edit_odt_automatic_styles.nextStyleName(automaticStyles, "style:style", "OdsRow");
|
|
93
|
+
automaticStyles.children.push(require_xml_fragment.el("style:style", {
|
|
94
|
+
"style:name": styleName,
|
|
95
|
+
"style:family": "table-row"
|
|
96
|
+
}, [require_xml_fragment.el("style:table-row-properties", { "style:row-height": (0, odf_js.formatOdfLength)(DEFAULT_ROW_HEIGHT_PT) })]));
|
|
97
|
+
require_xml_edit.setAttr(rowElement, "table:style-name", styleName);
|
|
98
|
+
}
|
|
79
99
|
function writeColumnManualBreak(pkg, tableElement, index) {
|
|
80
100
|
applyColumnStyleProperties(pkg, tableElement, index, { manualBreak: true });
|
|
81
101
|
}
|
|
@@ -96,7 +116,9 @@ function writeRowHidden(pkg, tableElement, index, hidden) {
|
|
|
96
116
|
}
|
|
97
117
|
//#endregion
|
|
98
118
|
exports.ensureColumnDefaultWidth = ensureColumnDefaultWidth;
|
|
119
|
+
exports.ensureColumnElementDefaultWidth = ensureColumnElementDefaultWidth;
|
|
99
120
|
exports.ensureRowDefaultHeight = ensureRowDefaultHeight;
|
|
121
|
+
exports.ensureRowElementDefaultHeight = ensureRowElementDefaultHeight;
|
|
100
122
|
exports.writeColumnHidden = writeColumnHidden;
|
|
101
123
|
exports.writeColumnManualBreak = writeColumnManualBreak;
|
|
102
124
|
exports.writeColumnWidth = writeColumnWidth;
|
|
@@ -4,9 +4,11 @@ declare function writeColumnWidth(pkg: Package, tableElement: XmlElement, index:
|
|
|
4
4
|
declare function writeRowHeight(pkg: Package, tableElement: XmlElement, index: number, heightPt: number): void;
|
|
5
5
|
declare function ensureColumnDefaultWidth(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
6
6
|
declare function ensureRowDefaultHeight(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
7
|
+
declare function ensureColumnElementDefaultWidth(pkg: Package, columnElement: XmlElement): void;
|
|
8
|
+
declare function ensureRowElementDefaultHeight(pkg: Package, rowElement: XmlElement): void;
|
|
7
9
|
declare function writeColumnManualBreak(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
8
10
|
declare function writeRowManualBreak(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
9
11
|
declare function writeColumnHidden(pkg: Package, tableElement: XmlElement, index: number, hidden: boolean): void;
|
|
10
12
|
declare function writeRowHidden(pkg: Package, tableElement: XmlElement, index: number, hidden: boolean): void;
|
|
11
13
|
//#endregion
|
|
12
|
-
export { ensureColumnDefaultWidth, ensureRowDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
14
|
+
export { ensureColumnDefaultWidth, ensureColumnElementDefaultWidth, ensureRowDefaultHeight, ensureRowElementDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
@@ -4,9 +4,11 @@ declare function writeColumnWidth(pkg: Package, tableElement: XmlElement, index:
|
|
|
4
4
|
declare function writeRowHeight(pkg: Package, tableElement: XmlElement, index: number, heightPt: number): void;
|
|
5
5
|
declare function ensureColumnDefaultWidth(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
6
6
|
declare function ensureRowDefaultHeight(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
7
|
+
declare function ensureColumnElementDefaultWidth(pkg: Package, columnElement: XmlElement): void;
|
|
8
|
+
declare function ensureRowElementDefaultHeight(pkg: Package, rowElement: XmlElement): void;
|
|
7
9
|
declare function writeColumnManualBreak(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
8
10
|
declare function writeRowManualBreak(pkg: Package, tableElement: XmlElement, index: number): void;
|
|
9
11
|
declare function writeColumnHidden(pkg: Package, tableElement: XmlElement, index: number, hidden: boolean): void;
|
|
10
12
|
declare function writeRowHidden(pkg: Package, tableElement: XmlElement, index: number, hidden: boolean): void;
|
|
11
13
|
//#endregion
|
|
12
|
-
export { ensureColumnDefaultWidth, ensureRowDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
14
|
+
export { ensureColumnDefaultWidth, ensureColumnElementDefaultWidth, ensureRowDefaultHeight, ensureRowElementDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
@@ -75,6 +75,26 @@ function ensureColumnDefaultWidth(pkg, tableElement, index) {
|
|
|
75
75
|
function ensureRowDefaultHeight(pkg, tableElement, index) {
|
|
76
76
|
if (currentRowStyleProperties(pkg, replaceRun(tableElement.children, isElementWithTag("table:table-row"), index, "table:number-rows-repeated", () => el("table:table-row"), "table:table-header-rows")).heightPt === void 0) writeRowHeight(pkg, tableElement, index, DEFAULT_ROW_HEIGHT_PT);
|
|
77
77
|
}
|
|
78
|
+
function ensureColumnElementDefaultWidth(pkg, columnElement) {
|
|
79
|
+
if (currentColumnStyleProperties(pkg, columnElement).widthPt !== void 0) return;
|
|
80
|
+
const automaticStyles = ensureAutomaticStyles(pkg);
|
|
81
|
+
const styleName = nextStyleName(automaticStyles, "style:style", "OdsColumn");
|
|
82
|
+
automaticStyles.children.push(el("style:style", {
|
|
83
|
+
"style:name": styleName,
|
|
84
|
+
"style:family": "table-column"
|
|
85
|
+
}, [el("style:table-column-properties", { "style:column-width": formatOdfLength(DEFAULT_COLUMN_WIDTH_PT) })]));
|
|
86
|
+
setAttr(columnElement, "table:style-name", styleName);
|
|
87
|
+
}
|
|
88
|
+
function ensureRowElementDefaultHeight(pkg, rowElement) {
|
|
89
|
+
if (currentRowStyleProperties(pkg, rowElement).heightPt !== void 0) return;
|
|
90
|
+
const automaticStyles = ensureAutomaticStyles(pkg);
|
|
91
|
+
const styleName = nextStyleName(automaticStyles, "style:style", "OdsRow");
|
|
92
|
+
automaticStyles.children.push(el("style:style", {
|
|
93
|
+
"style:name": styleName,
|
|
94
|
+
"style:family": "table-row"
|
|
95
|
+
}, [el("style:table-row-properties", { "style:row-height": formatOdfLength(DEFAULT_ROW_HEIGHT_PT) })]));
|
|
96
|
+
setAttr(rowElement, "table:style-name", styleName);
|
|
97
|
+
}
|
|
78
98
|
function writeColumnManualBreak(pkg, tableElement, index) {
|
|
79
99
|
applyColumnStyleProperties(pkg, tableElement, index, { manualBreak: true });
|
|
80
100
|
}
|
|
@@ -94,4 +114,4 @@ function writeRowHidden(pkg, tableElement, index, hidden) {
|
|
|
94
114
|
else removeAttr(rowElement, VISIBILITY_ATTR);
|
|
95
115
|
}
|
|
96
116
|
//#endregion
|
|
97
|
-
export { ensureColumnDefaultWidth, ensureRowDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
117
|
+
export { ensureColumnDefaultWidth, ensureColumnElementDefaultWidth, ensureRowDefaultHeight, ensureRowElementDefaultHeight, writeColumnHidden, writeColumnManualBreak, writeColumnWidth, writeRowHeight, writeRowHidden, writeRowManualBreak };
|
|
@@ -183,11 +183,13 @@ function collectRangeElements(children, tag, repeatAttr, start, end) {
|
|
|
183
183
|
});
|
|
184
184
|
return found;
|
|
185
185
|
}
|
|
186
|
-
function wrapRepeatRange(tableElement, memberTag, repeatAttr, wrapperTag, range, buildEmpty) {
|
|
186
|
+
function wrapRepeatRange(tableElement, memberTag, repeatAttr, wrapperTag, range, buildEmpty, pkg) {
|
|
187
187
|
require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(memberTag), range.start, repeatAttr, buildEmpty);
|
|
188
188
|
require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(memberTag), range.end, repeatAttr, buildEmpty);
|
|
189
189
|
const found = collectRangeElements(tableElement.children, memberTag, repeatAttr, range.start, range.end);
|
|
190
190
|
if (found.length === 0) return;
|
|
191
|
+
for (const entry of found) if (memberTag === "table:table-column") require_edit_ods_column_row.ensureColumnElementDefaultWidth(pkg, entry.element);
|
|
192
|
+
else require_edit_ods_column_row.ensureRowElementDefaultHeight(pkg, entry.element);
|
|
191
193
|
const firstPosition = found[0].position;
|
|
192
194
|
const elements = found.map((entry) => entry.element);
|
|
193
195
|
const positions = found.map((entry) => entry.position);
|
|
@@ -233,9 +235,9 @@ function writeSheetPrintSettings(pkg, tableElement, settings) {
|
|
|
233
235
|
require_xml_edit.setAttr(tableElement, "table:print-ranges", formatPrintRange(sheetName, settings.printRange));
|
|
234
236
|
}
|
|
235
237
|
unwrapHeaderGroup(tableElement, require_edit_ods_address.HEADER_COLUMNS_TAG);
|
|
236
|
-
if (settings.repeatColumns !== void 0) wrapRepeatRange(tableElement, require_edit_ods_address.COLUMN_TAG, require_edit_ods_address.COLUMN_REPEAT_ATTR, require_edit_ods_address.HEADER_COLUMNS_TAG, settings.repeatColumns, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG));
|
|
238
|
+
if (settings.repeatColumns !== void 0) wrapRepeatRange(tableElement, require_edit_ods_address.COLUMN_TAG, require_edit_ods_address.COLUMN_REPEAT_ATTR, require_edit_ods_address.HEADER_COLUMNS_TAG, settings.repeatColumns, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), pkg);
|
|
237
239
|
unwrapHeaderGroup(tableElement, require_edit_ods_address.HEADER_ROWS_TAG);
|
|
238
|
-
if (settings.repeatRows !== void 0) wrapRepeatRange(tableElement, require_edit_ods_address.ROW_TAG, require_edit_ods_address.ROW_REPEAT_ATTR, require_edit_ods_address.HEADER_ROWS_TAG, settings.repeatRows, () => require_xml_fragment.el(require_edit_ods_address.ROW_TAG));
|
|
240
|
+
if (settings.repeatRows !== void 0) wrapRepeatRange(tableElement, require_edit_ods_address.ROW_TAG, require_edit_ods_address.ROW_REPEAT_ATTR, require_edit_ods_address.HEADER_ROWS_TAG, settings.repeatRows, () => require_xml_fragment.el(require_edit_ods_address.ROW_TAG), pkg);
|
|
239
241
|
if (settings.manualBreaks !== void 0) {
|
|
240
242
|
for (const columnIndex of settings.manualBreaks.columns) require_edit_ods_column_row.writeColumnManualBreak(pkg, tableElement, columnIndex);
|
|
241
243
|
for (const rowIndex of settings.manualBreaks.rows) require_edit_ods_column_row.writeRowManualBreak(pkg, tableElement, rowIndex);
|
|
@@ -3,7 +3,7 @@ import { el } from "../../xml/fragment.js";
|
|
|
3
3
|
import { setAttr } from "../../xml/edit.js";
|
|
4
4
|
import { nextStyleName } from "../odt/automatic-styles.js";
|
|
5
5
|
import { COLUMN_REPEAT_ATTR, COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, isElementWithTag, readRunRepeatCount, replaceRun } from "./address.js";
|
|
6
|
-
import { writeColumnManualBreak, writeRowManualBreak } from "./column-row.js";
|
|
6
|
+
import { ensureColumnElementDefaultWidth, ensureRowElementDefaultHeight, writeColumnManualBreak, writeRowManualBreak } from "./column-row.js";
|
|
7
7
|
import { attr } from "ooxml.js";
|
|
8
8
|
import { cellReference, findStyleElement, formatOdfLength, parseCellReference, parseMargins, parsePageSize, resolvePageLayoutProperties } from "odf.js";
|
|
9
9
|
//#region src/edit/ods/print-settings.ts
|
|
@@ -182,11 +182,13 @@ function collectRangeElements(children, tag, repeatAttr, start, end) {
|
|
|
182
182
|
});
|
|
183
183
|
return found;
|
|
184
184
|
}
|
|
185
|
-
function wrapRepeatRange(tableElement, memberTag, repeatAttr, wrapperTag, range, buildEmpty) {
|
|
185
|
+
function wrapRepeatRange(tableElement, memberTag, repeatAttr, wrapperTag, range, buildEmpty, pkg) {
|
|
186
186
|
replaceRun(tableElement.children, isElementWithTag(memberTag), range.start, repeatAttr, buildEmpty);
|
|
187
187
|
replaceRun(tableElement.children, isElementWithTag(memberTag), range.end, repeatAttr, buildEmpty);
|
|
188
188
|
const found = collectRangeElements(tableElement.children, memberTag, repeatAttr, range.start, range.end);
|
|
189
189
|
if (found.length === 0) return;
|
|
190
|
+
for (const entry of found) if (memberTag === "table:table-column") ensureColumnElementDefaultWidth(pkg, entry.element);
|
|
191
|
+
else ensureRowElementDefaultHeight(pkg, entry.element);
|
|
190
192
|
const firstPosition = found[0].position;
|
|
191
193
|
const elements = found.map((entry) => entry.element);
|
|
192
194
|
const positions = found.map((entry) => entry.position);
|
|
@@ -232,9 +234,9 @@ function writeSheetPrintSettings(pkg, tableElement, settings) {
|
|
|
232
234
|
setAttr(tableElement, "table:print-ranges", formatPrintRange(sheetName, settings.printRange));
|
|
233
235
|
}
|
|
234
236
|
unwrapHeaderGroup(tableElement, HEADER_COLUMNS_TAG);
|
|
235
|
-
if (settings.repeatColumns !== void 0) wrapRepeatRange(tableElement, COLUMN_TAG, COLUMN_REPEAT_ATTR, HEADER_COLUMNS_TAG, settings.repeatColumns, () => el(COLUMN_TAG));
|
|
237
|
+
if (settings.repeatColumns !== void 0) wrapRepeatRange(tableElement, COLUMN_TAG, COLUMN_REPEAT_ATTR, HEADER_COLUMNS_TAG, settings.repeatColumns, () => el(COLUMN_TAG), pkg);
|
|
236
238
|
unwrapHeaderGroup(tableElement, HEADER_ROWS_TAG);
|
|
237
|
-
if (settings.repeatRows !== void 0) wrapRepeatRange(tableElement, ROW_TAG, ROW_REPEAT_ATTR, HEADER_ROWS_TAG, settings.repeatRows, () => el(ROW_TAG));
|
|
239
|
+
if (settings.repeatRows !== void 0) wrapRepeatRange(tableElement, ROW_TAG, ROW_REPEAT_ATTR, HEADER_ROWS_TAG, settings.repeatRows, () => el(ROW_TAG), pkg);
|
|
238
240
|
if (settings.manualBreaks !== void 0) {
|
|
239
241
|
for (const columnIndex of settings.manualBreaks.columns) writeColumnManualBreak(pkg, tableElement, columnIndex);
|
|
240
242
|
for (const rowIndex of settings.manualBreaks.rows) writeRowManualBreak(pkg, tableElement, rowIndex);
|
package/package.json
CHANGED