js.documents 12.1.0 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/edit/odf-repeated-runs.ts
3
+ const ROW_TAG = "table:table-row";
4
+ const CELL_TAG = "table:table-cell";
5
+ const COVERED_CELL_TAG = "table:covered-table-cell";
6
+ const ROW_REPEAT_ATTR = "table:number-rows-repeated";
7
+ const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
8
+ function isElementWithTag(tag) {
9
+ return (node) => node.type === "element" && node.tag === tag;
10
+ }
11
+ function isCellOrCoveredCell(node) {
12
+ return node.type === "element" && (node.tag === "table:table-cell" || node.tag === "table:covered-table-cell");
13
+ }
14
+ function validateIndex(value, label) {
15
+ if (!Number.isInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer, got ${value}`);
16
+ }
17
+ function readRunRepeatCount(node, attrName) {
18
+ const raw = node.attributes.find((attribute) => attribute.name === attrName)?.value;
19
+ if (raw === void 0) return 1;
20
+ const parsed = Number.parseInt(raw, 10);
21
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
22
+ }
23
+ function collectRunMembers(children, isMember, headerWrapperTag) {
24
+ const members = [];
25
+ children.forEach((node, outerPosition) => {
26
+ if (node.type !== "element") return;
27
+ if (headerWrapperTag !== void 0 && node.tag === headerWrapperTag) {
28
+ node.children.forEach((inner, innerPosition) => {
29
+ if (isMember(inner)) members.push({
30
+ node: inner,
31
+ container: node.children,
32
+ containerPosition: innerPosition,
33
+ outerPosition
34
+ });
35
+ });
36
+ return;
37
+ }
38
+ if (isMember(node)) members.push({
39
+ node,
40
+ container: children,
41
+ containerPosition: outerPosition,
42
+ outerPosition
43
+ });
44
+ });
45
+ return members;
46
+ }
47
+ function withRepeatCount(node, attrName, count) {
48
+ const clone = structuredClone(node);
49
+ clone.attributes = clone.attributes.filter((attribute) => attribute.name !== attrName);
50
+ if (count > 1) clone.attributes.push({
51
+ name: attrName,
52
+ value: String(count)
53
+ });
54
+ return clone;
55
+ }
56
+ function replaceRun(children, isMember, targetIndex, repeatAttr, buildEmpty, headerWrapperTag) {
57
+ validateIndex(targetIndex, "targetIndex");
58
+ const members = collectRunMembers(children, isMember, headerWrapperTag);
59
+ let cursor = 0;
60
+ for (const member of members) {
61
+ const count = readRunRepeatCount(member.node, repeatAttr);
62
+ if (targetIndex < cursor + count) {
63
+ const offset = targetIndex - cursor;
64
+ if (count === 1) return member.node;
65
+ const before = offset > 0 ? withRepeatCount(member.node, repeatAttr, offset) : void 0;
66
+ const target = withRepeatCount(member.node, repeatAttr, 1);
67
+ const replacement = [
68
+ before,
69
+ target,
70
+ count - offset - 1 > 0 ? withRepeatCount(member.node, repeatAttr, count - offset - 1) : void 0
71
+ ].filter((candidate) => candidate !== void 0);
72
+ member.container.splice(member.containerPosition, 1, ...replacement);
73
+ return target;
74
+ }
75
+ cursor += count;
76
+ }
77
+ const gap = targetIndex - cursor;
78
+ const lastMember = members[members.length - 1];
79
+ const insertAt = lastMember === void 0 ? children.length : lastMember.outerPosition + 1;
80
+ const toInsert = [];
81
+ if (gap > 0) toInsert.push(withRepeatCount(buildEmpty(), repeatAttr, gap));
82
+ const target = buildEmpty();
83
+ toInsert.push(target);
84
+ children.splice(insertAt, 0, ...toInsert);
85
+ return target;
86
+ }
87
+ //#endregion
88
+ exports.CELL_TAG = CELL_TAG;
89
+ exports.COLUMN_REPEAT_ATTR = COLUMN_REPEAT_ATTR;
90
+ exports.COVERED_CELL_TAG = COVERED_CELL_TAG;
91
+ exports.ROW_REPEAT_ATTR = ROW_REPEAT_ATTR;
92
+ exports.ROW_TAG = ROW_TAG;
93
+ exports.collectRunMembers = collectRunMembers;
94
+ exports.isCellOrCoveredCell = isCellOrCoveredCell;
95
+ exports.isElementWithTag = isElementWithTag;
96
+ exports.readRunRepeatCount = readRunRepeatCount;
97
+ exports.replaceRun = replaceRun;
98
+ exports.validateIndex = validateIndex;
99
+ exports.withRepeatCount = withRepeatCount;
@@ -0,0 +1,22 @@
1
+ import { XmlElement, XmlNode } from "odf.js";
2
+ //#region src/edit/odf-repeated-runs.d.ts
3
+ declare const ROW_TAG = "table:table-row";
4
+ declare const CELL_TAG = "table:table-cell";
5
+ declare const COVERED_CELL_TAG = "table:covered-table-cell";
6
+ declare const ROW_REPEAT_ATTR = "table:number-rows-repeated";
7
+ declare const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
8
+ declare function isElementWithTag(tag: string): (node: XmlNode) => node is XmlElement;
9
+ declare function isCellOrCoveredCell(node: XmlNode): node is XmlElement;
10
+ declare function validateIndex(value: number, label: string): void;
11
+ declare function readRunRepeatCount(node: XmlElement, attrName: string): number;
12
+ interface RunMember {
13
+ readonly node: XmlElement;
14
+ readonly container: XmlNode[];
15
+ readonly containerPosition: number;
16
+ readonly outerPosition: number;
17
+ }
18
+ declare function collectRunMembers(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, headerWrapperTag: string | undefined): RunMember[];
19
+ declare function withRepeatCount(node: XmlElement, attrName: string, count: number): XmlElement;
20
+ declare function replaceRun(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, targetIndex: number, repeatAttr: string, buildEmpty: () => XmlElement, headerWrapperTag?: string): XmlElement;
21
+ //#endregion
22
+ export { CELL_TAG, COLUMN_REPEAT_ATTR, COVERED_CELL_TAG, ROW_REPEAT_ATTR, ROW_TAG, RunMember, collectRunMembers, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, validateIndex, withRepeatCount };
@@ -0,0 +1,22 @@
1
+ import { XmlElement, XmlNode } from "odf.js";
2
+ //#region src/edit/odf-repeated-runs.d.ts
3
+ declare const ROW_TAG = "table:table-row";
4
+ declare const CELL_TAG = "table:table-cell";
5
+ declare const COVERED_CELL_TAG = "table:covered-table-cell";
6
+ declare const ROW_REPEAT_ATTR = "table:number-rows-repeated";
7
+ declare const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
8
+ declare function isElementWithTag(tag: string): (node: XmlNode) => node is XmlElement;
9
+ declare function isCellOrCoveredCell(node: XmlNode): node is XmlElement;
10
+ declare function validateIndex(value: number, label: string): void;
11
+ declare function readRunRepeatCount(node: XmlElement, attrName: string): number;
12
+ interface RunMember {
13
+ readonly node: XmlElement;
14
+ readonly container: XmlNode[];
15
+ readonly containerPosition: number;
16
+ readonly outerPosition: number;
17
+ }
18
+ declare function collectRunMembers(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, headerWrapperTag: string | undefined): RunMember[];
19
+ declare function withRepeatCount(node: XmlElement, attrName: string, count: number): XmlElement;
20
+ declare function replaceRun(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, targetIndex: number, repeatAttr: string, buildEmpty: () => XmlElement, headerWrapperTag?: string): XmlElement;
21
+ //#endregion
22
+ export { CELL_TAG, COLUMN_REPEAT_ATTR, COVERED_CELL_TAG, ROW_REPEAT_ATTR, ROW_TAG, RunMember, collectRunMembers, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, validateIndex, withRepeatCount };
@@ -0,0 +1,87 @@
1
+ //#region src/edit/odf-repeated-runs.ts
2
+ const ROW_TAG = "table:table-row";
3
+ const CELL_TAG = "table:table-cell";
4
+ const COVERED_CELL_TAG = "table:covered-table-cell";
5
+ const ROW_REPEAT_ATTR = "table:number-rows-repeated";
6
+ const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
7
+ function isElementWithTag(tag) {
8
+ return (node) => node.type === "element" && node.tag === tag;
9
+ }
10
+ function isCellOrCoveredCell(node) {
11
+ return node.type === "element" && (node.tag === "table:table-cell" || node.tag === "table:covered-table-cell");
12
+ }
13
+ function validateIndex(value, label) {
14
+ if (!Number.isInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer, got ${value}`);
15
+ }
16
+ function readRunRepeatCount(node, attrName) {
17
+ const raw = node.attributes.find((attribute) => attribute.name === attrName)?.value;
18
+ if (raw === void 0) return 1;
19
+ const parsed = Number.parseInt(raw, 10);
20
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
21
+ }
22
+ function collectRunMembers(children, isMember, headerWrapperTag) {
23
+ const members = [];
24
+ children.forEach((node, outerPosition) => {
25
+ if (node.type !== "element") return;
26
+ if (headerWrapperTag !== void 0 && node.tag === headerWrapperTag) {
27
+ node.children.forEach((inner, innerPosition) => {
28
+ if (isMember(inner)) members.push({
29
+ node: inner,
30
+ container: node.children,
31
+ containerPosition: innerPosition,
32
+ outerPosition
33
+ });
34
+ });
35
+ return;
36
+ }
37
+ if (isMember(node)) members.push({
38
+ node,
39
+ container: children,
40
+ containerPosition: outerPosition,
41
+ outerPosition
42
+ });
43
+ });
44
+ return members;
45
+ }
46
+ function withRepeatCount(node, attrName, count) {
47
+ const clone = structuredClone(node);
48
+ clone.attributes = clone.attributes.filter((attribute) => attribute.name !== attrName);
49
+ if (count > 1) clone.attributes.push({
50
+ name: attrName,
51
+ value: String(count)
52
+ });
53
+ return clone;
54
+ }
55
+ function replaceRun(children, isMember, targetIndex, repeatAttr, buildEmpty, headerWrapperTag) {
56
+ validateIndex(targetIndex, "targetIndex");
57
+ const members = collectRunMembers(children, isMember, headerWrapperTag);
58
+ let cursor = 0;
59
+ for (const member of members) {
60
+ const count = readRunRepeatCount(member.node, repeatAttr);
61
+ if (targetIndex < cursor + count) {
62
+ const offset = targetIndex - cursor;
63
+ if (count === 1) return member.node;
64
+ const before = offset > 0 ? withRepeatCount(member.node, repeatAttr, offset) : void 0;
65
+ const target = withRepeatCount(member.node, repeatAttr, 1);
66
+ const replacement = [
67
+ before,
68
+ target,
69
+ count - offset - 1 > 0 ? withRepeatCount(member.node, repeatAttr, count - offset - 1) : void 0
70
+ ].filter((candidate) => candidate !== void 0);
71
+ member.container.splice(member.containerPosition, 1, ...replacement);
72
+ return target;
73
+ }
74
+ cursor += count;
75
+ }
76
+ const gap = targetIndex - cursor;
77
+ const lastMember = members[members.length - 1];
78
+ const insertAt = lastMember === void 0 ? children.length : lastMember.outerPosition + 1;
79
+ const toInsert = [];
80
+ if (gap > 0) toInsert.push(withRepeatCount(buildEmpty(), repeatAttr, gap));
81
+ const target = buildEmpty();
82
+ toInsert.push(target);
83
+ children.splice(insertAt, 0, ...toInsert);
84
+ return target;
85
+ }
86
+ //#endregion
87
+ export { CELL_TAG, COLUMN_REPEAT_ATTR, COVERED_CELL_TAG, ROW_REPEAT_ATTR, ROW_TAG, collectRunMembers, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, validateIndex, withRepeatCount };
@@ -1,126 +1,34 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_xml_fragment = require("../../xml/fragment.cjs");
3
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
3
4
  //#region src/edit/ods/address.ts
4
- const ROW_TAG = "table:table-row";
5
5
  const COLUMN_TAG = "table:table-column";
6
- const CELL_TAG = "table:table-cell";
7
- const COVERED_CELL_TAG = "table:covered-table-cell";
8
- const ROW_REPEAT_ATTR = "table:number-rows-repeated";
9
- const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
10
6
  const HEADER_ROWS_TAG = "table:table-header-rows";
11
7
  const HEADER_COLUMNS_TAG = "table:table-header-columns";
12
- function isElementWithTag(tag) {
13
- return (node) => node.type === "element" && node.tag === tag;
14
- }
15
- function isCellOrCoveredCell(node) {
16
- return node.type === "element" && (node.tag === "table:table-cell" || node.tag === "table:covered-table-cell");
17
- }
18
- function validateIndex(value, label) {
19
- if (!Number.isInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer, got ${value}`);
20
- }
21
- function readRunRepeatCount(node, attrName) {
22
- const raw = node.attributes.find((attribute) => attribute.name === attrName)?.value;
23
- if (raw === void 0) return 1;
24
- const parsed = Number.parseInt(raw, 10);
25
- return Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
26
- }
27
- function collectRunMembers(children, isMember, headerWrapperTag) {
28
- const members = [];
29
- children.forEach((node, outerPosition) => {
30
- if (node.type !== "element") return;
31
- if (headerWrapperTag !== void 0 && node.tag === headerWrapperTag) {
32
- node.children.forEach((inner, innerPosition) => {
33
- if (isMember(inner)) members.push({
34
- node: inner,
35
- container: node.children,
36
- containerPosition: innerPosition,
37
- outerPosition
38
- });
39
- });
40
- return;
41
- }
42
- if (isMember(node)) members.push({
43
- node,
44
- container: children,
45
- containerPosition: outerPosition,
46
- outerPosition
47
- });
48
- });
49
- return members;
50
- }
51
- function withRepeatCount(node, attrName, count) {
52
- const clone = structuredClone(node);
53
- clone.attributes = clone.attributes.filter((attribute) => attribute.name !== attrName);
54
- if (count > 1) clone.attributes.push({
55
- name: attrName,
56
- value: String(count)
57
- });
58
- return clone;
59
- }
60
- function replaceRun(children, isMember, targetIndex, repeatAttr, buildEmpty, headerWrapperTag) {
61
- validateIndex(targetIndex, "targetIndex");
62
- const members = collectRunMembers(children, isMember, headerWrapperTag);
63
- let cursor = 0;
64
- for (const member of members) {
65
- const count = readRunRepeatCount(member.node, repeatAttr);
66
- if (targetIndex < cursor + count) {
67
- const offset = targetIndex - cursor;
68
- if (count === 1) return member.node;
69
- const before = offset > 0 ? withRepeatCount(member.node, repeatAttr, offset) : void 0;
70
- const target = withRepeatCount(member.node, repeatAttr, 1);
71
- const replacement = [
72
- before,
73
- target,
74
- count - offset - 1 > 0 ? withRepeatCount(member.node, repeatAttr, count - offset - 1) : void 0
75
- ].filter((candidate) => candidate !== void 0);
76
- member.container.splice(member.containerPosition, 1, ...replacement);
77
- return target;
78
- }
79
- cursor += count;
80
- }
81
- const gap = targetIndex - cursor;
82
- const lastMember = members[members.length - 1];
83
- const insertAt = lastMember === void 0 ? children.length : lastMember.outerPosition + 1;
84
- const toInsert = [];
85
- if (gap > 0) toInsert.push(withRepeatCount(buildEmpty(), repeatAttr, gap));
86
- const target = buildEmpty();
87
- toInsert.push(target);
88
- children.splice(insertAt, 0, ...toInsert);
89
- return target;
90
- }
91
8
  function ensureColumnCoverage(tableElement, minCount) {
92
9
  if (minCount <= 0) return;
93
- const columnMembers = collectRunMembers(tableElement.children, isElementWithTag(COLUMN_TAG), HEADER_COLUMNS_TAG);
94
- const covered = columnMembers.reduce((sum, member) => sum + readRunRepeatCount(member.node, COLUMN_REPEAT_ATTR), 0);
10
+ const columnMembers = require_edit_odf_repeated_runs.collectRunMembers(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(COLUMN_TAG), HEADER_COLUMNS_TAG);
11
+ const covered = columnMembers.reduce((sum, member) => sum + require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR), 0);
95
12
  if (covered >= minCount) return;
96
13
  const additional = minCount - covered;
97
- const newColumn = withRepeatCount(require_xml_fragment.el(COLUMN_TAG), COLUMN_REPEAT_ATTR, additional);
14
+ const newColumn = require_edit_odf_repeated_runs.withRepeatCount(require_xml_fragment.el(COLUMN_TAG), require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, additional);
98
15
  const lastColumn = columnMembers[columnMembers.length - 1];
99
16
  if (lastColumn === void 0) {
100
- const firstRowOrHeaderPosition = tableElement.children.findIndex((node) => isElementWithTag("table:table-row")(node) || isElementWithTag("table:table-header-rows")(node));
17
+ const firstRowOrHeaderPosition = tableElement.children.findIndex((node) => require_edit_odf_repeated_runs.isElementWithTag("table:table-row")(node) || require_edit_odf_repeated_runs.isElementWithTag("table:table-header-rows")(node));
101
18
  const insertAt = firstRowOrHeaderPosition === -1 ? tableElement.children.length : firstRowOrHeaderPosition;
102
19
  tableElement.children.splice(insertAt, 0, newColumn);
103
20
  } else tableElement.children.splice(lastColumn.outerPosition + 1, 0, newColumn);
104
21
  }
105
22
  function resolveCellNode(tableElement, row, column) {
106
- validateIndex(row, "row");
107
- validateIndex(column, "column");
23
+ require_edit_odf_repeated_runs.validateIndex(row, "row");
24
+ require_edit_odf_repeated_runs.validateIndex(column, "column");
108
25
  ensureColumnCoverage(tableElement, column + 1);
109
- return replaceRun(replaceRun(tableElement.children, isElementWithTag(ROW_TAG), row, ROW_REPEAT_ATTR, () => require_xml_fragment.el(ROW_TAG), HEADER_ROWS_TAG).children, isCellOrCoveredCell, column, COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(CELL_TAG));
26
+ const rowElement = require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_odf_repeated_runs.ROW_TAG), row, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_odf_repeated_runs.ROW_TAG), HEADER_ROWS_TAG);
27
+ return require_edit_odf_repeated_runs.replaceRun(rowElement.children, require_edit_odf_repeated_runs.isCellOrCoveredCell, column, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_odf_repeated_runs.CELL_TAG));
110
28
  }
111
29
  //#endregion
112
- exports.CELL_TAG = CELL_TAG;
113
- exports.COLUMN_REPEAT_ATTR = COLUMN_REPEAT_ATTR;
114
30
  exports.COLUMN_TAG = COLUMN_TAG;
115
- exports.COVERED_CELL_TAG = COVERED_CELL_TAG;
116
31
  exports.HEADER_COLUMNS_TAG = HEADER_COLUMNS_TAG;
117
32
  exports.HEADER_ROWS_TAG = HEADER_ROWS_TAG;
118
- exports.ROW_REPEAT_ATTR = ROW_REPEAT_ATTR;
119
- exports.ROW_TAG = ROW_TAG;
120
- exports.collectRunMembers = collectRunMembers;
121
33
  exports.ensureColumnCoverage = ensureColumnCoverage;
122
- exports.isCellOrCoveredCell = isCellOrCoveredCell;
123
- exports.isElementWithTag = isElementWithTag;
124
- exports.readRunRepeatCount = readRunRepeatCount;
125
- exports.replaceRun = replaceRun;
126
34
  exports.resolveCellNode = resolveCellNode;
@@ -1,25 +1,9 @@
1
- import { XmlElement, XmlNode } from "odf.js";
1
+ import { XmlElement } from "odf.js";
2
2
  //#region src/edit/ods/address.d.ts
3
- declare const ROW_TAG = "table:table-row";
4
3
  declare const COLUMN_TAG = "table:table-column";
5
- declare const CELL_TAG = "table:table-cell";
6
- declare const COVERED_CELL_TAG = "table:covered-table-cell";
7
- declare const ROW_REPEAT_ATTR = "table:number-rows-repeated";
8
- declare const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
9
4
  declare const HEADER_ROWS_TAG = "table:table-header-rows";
10
5
  declare const HEADER_COLUMNS_TAG = "table:table-header-columns";
11
- declare function isElementWithTag(tag: string): (node: XmlNode) => node is XmlElement;
12
- declare function isCellOrCoveredCell(node: XmlNode): node is XmlElement;
13
- declare function readRunRepeatCount(node: XmlElement, attrName: string): number;
14
- interface RunMember {
15
- readonly node: XmlElement;
16
- readonly container: XmlNode[];
17
- readonly containerPosition: number;
18
- readonly outerPosition: number;
19
- }
20
- declare function collectRunMembers(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, headerWrapperTag: string | undefined): RunMember[];
21
- declare function replaceRun(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, targetIndex: number, repeatAttr: string, buildEmpty: () => XmlElement, headerWrapperTag?: string): XmlElement;
22
6
  declare function ensureColumnCoverage(tableElement: XmlElement, minCount: number): void;
23
7
  declare function resolveCellNode(tableElement: XmlElement, row: number, column: number): XmlElement;
24
8
  //#endregion
25
- export { CELL_TAG, COLUMN_REPEAT_ATTR, COLUMN_TAG, COVERED_CELL_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, RunMember, collectRunMembers, ensureColumnCoverage, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, resolveCellNode };
9
+ export { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ensureColumnCoverage, resolveCellNode };
@@ -1,25 +1,9 @@
1
- import { XmlElement, XmlNode } from "odf.js";
1
+ import { XmlElement } from "odf.js";
2
2
  //#region src/edit/ods/address.d.ts
3
- declare const ROW_TAG = "table:table-row";
4
3
  declare const COLUMN_TAG = "table:table-column";
5
- declare const CELL_TAG = "table:table-cell";
6
- declare const COVERED_CELL_TAG = "table:covered-table-cell";
7
- declare const ROW_REPEAT_ATTR = "table:number-rows-repeated";
8
- declare const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
9
4
  declare const HEADER_ROWS_TAG = "table:table-header-rows";
10
5
  declare const HEADER_COLUMNS_TAG = "table:table-header-columns";
11
- declare function isElementWithTag(tag: string): (node: XmlNode) => node is XmlElement;
12
- declare function isCellOrCoveredCell(node: XmlNode): node is XmlElement;
13
- declare function readRunRepeatCount(node: XmlElement, attrName: string): number;
14
- interface RunMember {
15
- readonly node: XmlElement;
16
- readonly container: XmlNode[];
17
- readonly containerPosition: number;
18
- readonly outerPosition: number;
19
- }
20
- declare function collectRunMembers(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, headerWrapperTag: string | undefined): RunMember[];
21
- declare function replaceRun(children: XmlNode[], isMember: (node: XmlNode) => node is XmlElement, targetIndex: number, repeatAttr: string, buildEmpty: () => XmlElement, headerWrapperTag?: string): XmlElement;
22
6
  declare function ensureColumnCoverage(tableElement: XmlElement, minCount: number): void;
23
7
  declare function resolveCellNode(tableElement: XmlElement, row: number, column: number): XmlElement;
24
8
  //#endregion
25
- export { CELL_TAG, COLUMN_REPEAT_ATTR, COLUMN_TAG, COVERED_CELL_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, RunMember, collectRunMembers, ensureColumnCoverage, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, resolveCellNode };
9
+ export { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ensureColumnCoverage, resolveCellNode };
@@ -1,92 +1,9 @@
1
1
  import { el } from "../../xml/fragment.js";
2
+ import { CELL_TAG, COLUMN_REPEAT_ATTR, ROW_REPEAT_ATTR, ROW_TAG, collectRunMembers, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, validateIndex, withRepeatCount } from "../odf-repeated-runs.js";
2
3
  //#region src/edit/ods/address.ts
3
- const ROW_TAG = "table:table-row";
4
4
  const COLUMN_TAG = "table:table-column";
5
- const CELL_TAG = "table:table-cell";
6
- const COVERED_CELL_TAG = "table:covered-table-cell";
7
- const ROW_REPEAT_ATTR = "table:number-rows-repeated";
8
- const COLUMN_REPEAT_ATTR = "table:number-columns-repeated";
9
5
  const HEADER_ROWS_TAG = "table:table-header-rows";
10
6
  const HEADER_COLUMNS_TAG = "table:table-header-columns";
11
- function isElementWithTag(tag) {
12
- return (node) => node.type === "element" && node.tag === tag;
13
- }
14
- function isCellOrCoveredCell(node) {
15
- return node.type === "element" && (node.tag === "table:table-cell" || node.tag === "table:covered-table-cell");
16
- }
17
- function validateIndex(value, label) {
18
- if (!Number.isInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer, got ${value}`);
19
- }
20
- function readRunRepeatCount(node, attrName) {
21
- const raw = node.attributes.find((attribute) => attribute.name === attrName)?.value;
22
- if (raw === void 0) return 1;
23
- const parsed = Number.parseInt(raw, 10);
24
- return Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
25
- }
26
- function collectRunMembers(children, isMember, headerWrapperTag) {
27
- const members = [];
28
- children.forEach((node, outerPosition) => {
29
- if (node.type !== "element") return;
30
- if (headerWrapperTag !== void 0 && node.tag === headerWrapperTag) {
31
- node.children.forEach((inner, innerPosition) => {
32
- if (isMember(inner)) members.push({
33
- node: inner,
34
- container: node.children,
35
- containerPosition: innerPosition,
36
- outerPosition
37
- });
38
- });
39
- return;
40
- }
41
- if (isMember(node)) members.push({
42
- node,
43
- container: children,
44
- containerPosition: outerPosition,
45
- outerPosition
46
- });
47
- });
48
- return members;
49
- }
50
- function withRepeatCount(node, attrName, count) {
51
- const clone = structuredClone(node);
52
- clone.attributes = clone.attributes.filter((attribute) => attribute.name !== attrName);
53
- if (count > 1) clone.attributes.push({
54
- name: attrName,
55
- value: String(count)
56
- });
57
- return clone;
58
- }
59
- function replaceRun(children, isMember, targetIndex, repeatAttr, buildEmpty, headerWrapperTag) {
60
- validateIndex(targetIndex, "targetIndex");
61
- const members = collectRunMembers(children, isMember, headerWrapperTag);
62
- let cursor = 0;
63
- for (const member of members) {
64
- const count = readRunRepeatCount(member.node, repeatAttr);
65
- if (targetIndex < cursor + count) {
66
- const offset = targetIndex - cursor;
67
- if (count === 1) return member.node;
68
- const before = offset > 0 ? withRepeatCount(member.node, repeatAttr, offset) : void 0;
69
- const target = withRepeatCount(member.node, repeatAttr, 1);
70
- const replacement = [
71
- before,
72
- target,
73
- count - offset - 1 > 0 ? withRepeatCount(member.node, repeatAttr, count - offset - 1) : void 0
74
- ].filter((candidate) => candidate !== void 0);
75
- member.container.splice(member.containerPosition, 1, ...replacement);
76
- return target;
77
- }
78
- cursor += count;
79
- }
80
- const gap = targetIndex - cursor;
81
- const lastMember = members[members.length - 1];
82
- const insertAt = lastMember === void 0 ? children.length : lastMember.outerPosition + 1;
83
- const toInsert = [];
84
- if (gap > 0) toInsert.push(withRepeatCount(buildEmpty(), repeatAttr, gap));
85
- const target = buildEmpty();
86
- toInsert.push(target);
87
- children.splice(insertAt, 0, ...toInsert);
88
- return target;
89
- }
90
7
  function ensureColumnCoverage(tableElement, minCount) {
91
8
  if (minCount <= 0) return;
92
9
  const columnMembers = collectRunMembers(tableElement.children, isElementWithTag(COLUMN_TAG), HEADER_COLUMNS_TAG);
@@ -105,7 +22,8 @@ function resolveCellNode(tableElement, row, column) {
105
22
  validateIndex(row, "row");
106
23
  validateIndex(column, "column");
107
24
  ensureColumnCoverage(tableElement, column + 1);
108
- return replaceRun(replaceRun(tableElement.children, isElementWithTag(ROW_TAG), row, ROW_REPEAT_ATTR, () => el(ROW_TAG), HEADER_ROWS_TAG).children, isCellOrCoveredCell, column, COLUMN_REPEAT_ATTR, () => el(CELL_TAG));
25
+ const rowElement = replaceRun(tableElement.children, isElementWithTag(ROW_TAG), row, ROW_REPEAT_ATTR, () => el(ROW_TAG), HEADER_ROWS_TAG);
26
+ return replaceRun(rowElement.children, isCellOrCoveredCell, column, COLUMN_REPEAT_ATTR, () => el(CELL_TAG));
109
27
  }
110
28
  //#endregion
111
- export { CELL_TAG, COLUMN_REPEAT_ATTR, COLUMN_TAG, COVERED_CELL_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, collectRunMembers, ensureColumnCoverage, isCellOrCoveredCell, isElementWithTag, readRunRepeatCount, replaceRun, resolveCellNode };
29
+ export { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ensureColumnCoverage, resolveCellNode };
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_xml_fragment = require("../../xml/fragment.cjs");
3
3
  const require_xml_edit = require("../../xml/edit.cjs");
4
4
  const require_edit_odt_automatic_styles = require("../odt/automatic-styles.cjs");
5
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
5
6
  const require_edit_ods_address = require("./address.cjs");
6
7
  let ooxml_js = require("ooxml.js");
7
8
  let odf_js = require("odf.js");
@@ -32,7 +33,7 @@ function currentRowStyleProperties(pkg, rowElement) {
32
33
  }
33
34
  function applyColumnStyleProperties(pkg, tableElement, index, changes) {
34
35
  require_edit_ods_address.ensureColumnCoverage(tableElement, index + 1);
35
- const columnElement = require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.COLUMN_TAG), index, require_edit_ods_address.COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG);
36
+ const columnElement = require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_ods_address.COLUMN_TAG), index, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG);
36
37
  const current = currentColumnStyleProperties(pkg, columnElement);
37
38
  const widthPt = changes.widthPt ?? current.widthPt;
38
39
  const manualBreak = changes.manualBreak ?? current.manualBreak;
@@ -48,7 +49,7 @@ function applyColumnStyleProperties(pkg, tableElement, index, changes) {
48
49
  require_xml_edit.setAttr(columnElement, "table:style-name", styleName);
49
50
  }
50
51
  function applyRowStyleProperties(pkg, tableElement, index, changes) {
51
- const rowElement = require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.ROW_TAG), index, require_edit_ods_address.ROW_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG);
52
+ const rowElement = require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_odf_repeated_runs.ROW_TAG), index, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_odf_repeated_runs.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG);
52
53
  const current = currentRowStyleProperties(pkg, rowElement);
53
54
  const heightPt = changes.heightPt ?? current.heightPt;
54
55
  const manualBreak = changes.manualBreak ?? current.manualBreak;
@@ -71,10 +72,10 @@ function writeRowHeight(pkg, tableElement, index, heightPt) {
71
72
  }
72
73
  function ensureColumnDefaultWidth(pkg, tableElement, index) {
73
74
  require_edit_ods_address.ensureColumnCoverage(tableElement, index + 1);
74
- if (currentColumnStyleProperties(pkg, require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag("table:table-column"), index, "table:number-columns-repeated", () => require_xml_fragment.el("table:table-column"), "table:table-header-columns")).widthPt === void 0) writeColumnWidth(pkg, tableElement, index, DEFAULT_COLUMN_WIDTH_PT);
75
+ if (currentColumnStyleProperties(pkg, require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag("table:table-column"), index, "table:number-columns-repeated", () => require_xml_fragment.el("table:table-column"), "table:table-header-columns")).widthPt === void 0) writeColumnWidth(pkg, tableElement, index, DEFAULT_COLUMN_WIDTH_PT);
75
76
  }
76
77
  function ensureRowDefaultHeight(pkg, tableElement, index) {
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
+ if (currentRowStyleProperties(pkg, require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.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
79
  }
79
80
  function ensureColumnElementDefaultWidth(pkg, columnElement) {
80
81
  if (currentColumnStyleProperties(pkg, columnElement).widthPt !== void 0) return;
@@ -104,13 +105,13 @@ function writeRowManualBreak(pkg, tableElement, index) {
104
105
  }
105
106
  function writeColumnHidden(pkg, tableElement, index, hidden) {
106
107
  ensureColumnDefaultWidth(pkg, tableElement, index);
107
- const columnElement = require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.COLUMN_TAG), index, require_edit_ods_address.COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG);
108
+ const columnElement = require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_ods_address.COLUMN_TAG), index, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG);
108
109
  if (hidden) require_xml_edit.setAttr(columnElement, VISIBILITY_ATTR, VISIBILITY_COLLAPSE);
109
110
  else require_xml_edit.removeAttr(columnElement, VISIBILITY_ATTR);
110
111
  }
111
112
  function writeRowHidden(pkg, tableElement, index, hidden) {
112
113
  ensureRowDefaultHeight(pkg, tableElement, index);
113
- const rowElement = require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.ROW_TAG), index, require_edit_ods_address.ROW_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_ods_address.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG);
114
+ const rowElement = require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_odf_repeated_runs.ROW_TAG), index, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR, () => require_xml_fragment.el(require_edit_odf_repeated_runs.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG);
114
115
  if (hidden) require_xml_edit.setAttr(rowElement, VISIBILITY_ATTR, VISIBILITY_COLLAPSE);
115
116
  else require_xml_edit.removeAttr(rowElement, VISIBILITY_ATTR);
116
117
  }
@@ -1,7 +1,8 @@
1
1
  import { el } from "../../xml/fragment.js";
2
2
  import { directChildElement, removeAttr, setAttr } from "../../xml/edit.js";
3
3
  import { ensureAutomaticStyles, nextStyleName } from "../odt/automatic-styles.js";
4
- import { COLUMN_REPEAT_ATTR, COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, ensureColumnCoverage, isElementWithTag, replaceRun } from "./address.js";
4
+ import { COLUMN_REPEAT_ATTR, ROW_REPEAT_ATTR, ROW_TAG, isElementWithTag, replaceRun } from "../odf-repeated-runs.js";
5
+ import { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ensureColumnCoverage } from "./address.js";
5
6
  import { attr } from "ooxml.js";
6
7
  import { findStyleElement, formatOdfLength, parseOdfLength } from "odf.js";
7
8
  //#region src/edit/ods/column-row.ts
@@ -3,6 +3,7 @@ const require_xml_fragment = require("../../xml/fragment.cjs");
3
3
  const require_xml_edit = require("../../xml/edit.cjs");
4
4
  const require_odf_package_formula = require("../../odf-package/formula.cjs");
5
5
  const require_odf_package_media = require("../../odf-package/media.cjs");
6
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
6
7
  const require_edit_ods_address = require("./address.cjs");
7
8
  let ooxml_js = require("ooxml.js");
8
9
  let odf_js = require("odf.js");
@@ -39,9 +40,9 @@ function resolvedRowHeightPt(pkg, rowElement) {
39
40
  function cumulativeColumnOffsetPt(pkg, tableElement, anchorColumn) {
40
41
  let cursor = 0;
41
42
  let offsetPt = 0;
42
- for (const member of require_edit_ods_address.collectRunMembers(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG)) {
43
+ for (const member of require_edit_odf_repeated_runs.collectRunMembers(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_ods_address.COLUMN_TAG), require_edit_ods_address.HEADER_COLUMNS_TAG)) {
43
44
  if (cursor >= anchorColumn) break;
44
- const count = require_edit_ods_address.readRunRepeatCount(member.node, require_edit_ods_address.COLUMN_REPEAT_ATTR);
45
+ const count = require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR);
45
46
  const overlap = Math.min(count, anchorColumn - cursor);
46
47
  offsetPt += overlap * resolvedColumnWidthPt(pkg, member.node);
47
48
  cursor += count;
@@ -52,9 +53,9 @@ function cumulativeColumnOffsetPt(pkg, tableElement, anchorColumn) {
52
53
  function cumulativeRowOffsetPt(pkg, tableElement, anchorRow) {
53
54
  let cursor = 0;
54
55
  let offsetPt = 0;
55
- for (const member of require_edit_ods_address.collectRunMembers(tableElement.children, require_edit_ods_address.isElementWithTag(require_edit_ods_address.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG)) {
56
+ for (const member of require_edit_odf_repeated_runs.collectRunMembers(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(require_edit_odf_repeated_runs.ROW_TAG), require_edit_ods_address.HEADER_ROWS_TAG)) {
56
57
  if (cursor >= anchorRow) break;
57
- const count = require_edit_ods_address.readRunRepeatCount(member.node, require_edit_ods_address.ROW_REPEAT_ATTR);
58
+ const count = require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR);
58
59
  const overlap = Math.min(count, anchorRow - cursor);
59
60
  offsetPt += overlap * resolvedRowHeightPt(pkg, member.node);
60
61
  cursor += count;
@@ -2,7 +2,8 @@ import { el } from "../../xml/fragment.js";
2
2
  import { directChildElement } from "../../xml/edit.js";
3
3
  import { addFormulaObject } from "../../odf-package/formula.js";
4
4
  import { addImageMedia } from "../../odf-package/media.js";
5
- import { COLUMN_REPEAT_ATTR, COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, collectRunMembers, isElementWithTag, readRunRepeatCount } from "./address.js";
5
+ import { COLUMN_REPEAT_ATTR, ROW_REPEAT_ATTR, ROW_TAG, collectRunMembers, isElementWithTag, readRunRepeatCount } from "../odf-repeated-runs.js";
6
+ import { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG } from "./address.js";
6
7
  import { attr } from "ooxml.js";
7
8
  import { base64ToBytes as base64ToBytes$1, findStyleElement, formatOdfLength, parseOdfLength, writeEmbeddedObject } from "odf.js";
8
9
  //#region src/edit/ods/floating.ts
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_xml_fragment = require("../../xml/fragment.cjs");
3
3
  const require_xml_edit = require("../../xml/edit.cjs");
4
4
  const require_edit_odt_automatic_styles = require("../odt/automatic-styles.cjs");
5
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
5
6
  const require_edit_ods_address = require("./address.cjs");
6
7
  const require_edit_ods_column_row = require("./column-row.cjs");
7
8
  let ooxml_js = require("ooxml.js");
@@ -56,12 +57,12 @@ function scanTableStructure(pkg, tableElement) {
56
57
  const manualBreakRows = [];
57
58
  function processColumn(columnElement) {
58
59
  if (hasManualBreak(pkg, columnElement, "table-column", "style:table-column-properties")) manualBreakColumns.push(columnCursor);
59
- columnCursor += require_edit_ods_address.readRunRepeatCount(columnElement, require_edit_ods_address.COLUMN_REPEAT_ATTR);
60
+ columnCursor += require_edit_odf_repeated_runs.readRunRepeatCount(columnElement, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR);
60
61
  }
61
62
  function processRow(rowElement) {
62
63
  const startIndex = rowCursor;
63
64
  if (hasManualBreak(pkg, rowElement, "table-row", "style:table-row-properties")) manualBreakRows.push(startIndex);
64
- rowCursor += require_edit_ods_address.readRunRepeatCount(rowElement, require_edit_ods_address.ROW_REPEAT_ATTR);
65
+ rowCursor += require_edit_odf_repeated_runs.readRunRepeatCount(rowElement, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR);
65
66
  }
66
67
  for (const child of tableElement.children) {
67
68
  if (child.type !== "element") continue;
@@ -174,7 +175,7 @@ function collectRangeElements(children, tag, repeatAttr, start, end) {
174
175
  const found = [];
175
176
  children.forEach((node, position) => {
176
177
  if (node.type !== "element" || node.tag !== tag) return;
177
- const count = require_edit_ods_address.readRunRepeatCount(node, repeatAttr);
178
+ const count = require_edit_odf_repeated_runs.readRunRepeatCount(node, repeatAttr);
178
179
  if (cursor >= start && cursor + count - 1 <= end) found.push({
179
180
  position,
180
181
  element: node
@@ -184,8 +185,8 @@ function collectRangeElements(children, tag, repeatAttr, start, end) {
184
185
  return found;
185
186
  }
186
187
  function wrapRepeatRange(tableElement, memberTag, repeatAttr, wrapperTag, range, buildEmpty, pkg) {
187
- require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(memberTag), range.start, repeatAttr, buildEmpty);
188
- require_edit_ods_address.replaceRun(tableElement.children, require_edit_ods_address.isElementWithTag(memberTag), range.end, repeatAttr, buildEmpty);
188
+ require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(memberTag), range.start, repeatAttr, buildEmpty);
189
+ require_edit_odf_repeated_runs.replaceRun(tableElement.children, require_edit_odf_repeated_runs.isElementWithTag(memberTag), range.end, repeatAttr, buildEmpty);
189
190
  for (const entry of collectRangeElements(tableElement.children, memberTag, repeatAttr, 0, range.end)) if (memberTag === "table:table-column") require_edit_ods_column_row.ensureColumnElementDefaultWidth(pkg, entry.element);
190
191
  else require_edit_ods_column_row.ensureRowElementDefaultHeight(pkg, entry.element);
191
192
  const found = collectRangeElements(tableElement.children, memberTag, repeatAttr, range.start, range.end);
@@ -235,9 +236,9 @@ function writeSheetPrintSettings(pkg, tableElement, settings) {
235
236
  require_xml_edit.setAttr(tableElement, "table:print-ranges", formatPrintRange(sheetName, settings.printRange));
236
237
  }
237
238
  unwrapHeaderGroup(tableElement, require_edit_ods_address.HEADER_COLUMNS_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);
239
+ if (settings.repeatColumns !== void 0) wrapRepeatRange(tableElement, require_edit_ods_address.COLUMN_TAG, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, require_edit_ods_address.HEADER_COLUMNS_TAG, settings.repeatColumns, () => require_xml_fragment.el(require_edit_ods_address.COLUMN_TAG), pkg);
239
240
  unwrapHeaderGroup(tableElement, require_edit_ods_address.HEADER_ROWS_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);
241
+ if (settings.repeatRows !== void 0) wrapRepeatRange(tableElement, require_edit_odf_repeated_runs.ROW_TAG, require_edit_odf_repeated_runs.ROW_REPEAT_ATTR, require_edit_ods_address.HEADER_ROWS_TAG, settings.repeatRows, () => require_xml_fragment.el(require_edit_odf_repeated_runs.ROW_TAG), pkg);
241
242
  if (settings.manualBreaks !== void 0) {
242
243
  for (const columnIndex of settings.manualBreaks.columns) require_edit_ods_column_row.writeColumnManualBreak(pkg, tableElement, columnIndex);
243
244
  for (const rowIndex of settings.manualBreaks.rows) require_edit_ods_column_row.writeRowManualBreak(pkg, tableElement, rowIndex);
@@ -1,7 +1,8 @@
1
1
  import { el } from "../../xml/fragment.js";
2
2
  import { setAttr } from "../../xml/edit.js";
3
3
  import { nextStyleName } from "../odt/automatic-styles.js";
4
- import { COLUMN_REPEAT_ATTR, COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG, ROW_REPEAT_ATTR, ROW_TAG, isElementWithTag, readRunRepeatCount, replaceRun } from "./address.js";
4
+ import { COLUMN_REPEAT_ATTR, ROW_REPEAT_ATTR, ROW_TAG, isElementWithTag, readRunRepeatCount, replaceRun } from "../odf-repeated-runs.js";
5
+ import { COLUMN_TAG, HEADER_COLUMNS_TAG, HEADER_ROWS_TAG } from "./address.js";
5
6
  import { ensureColumnElementDefaultWidth, ensureRowElementDefaultHeight, writeColumnManualBreak, writeRowManualBreak } from "./column-row.js";
6
7
  import { attr } from "ooxml.js";
7
8
  import { PAGE_SIZE_A4, cellReference, parseCellReference } from "document-schema.js";
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_xml_edit = require("../../xml/edit.cjs");
3
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
3
4
  const require_edit_ods_address = require("./address.cjs");
4
5
  const require_edit_ods_cell = require("./cell.cjs");
5
6
  const require_edit_ods_column_row = require("./column-row.cjs");
@@ -86,7 +87,7 @@ var OdsSheet = class {
86
87
  for (let rowOffset = 0; rowOffset < rowSpan; rowOffset++) for (let columnOffset = 0; columnOffset < colSpan; columnOffset++) {
87
88
  if (rowOffset === 0 && columnOffset === 0) continue;
88
89
  const coveredNode = require_edit_ods_address.resolveCellNode(tableElement, startRow + rowOffset, startColumn + columnOffset);
89
- coveredNode.tag = require_edit_ods_address.COVERED_CELL_TAG;
90
+ coveredNode.tag = require_edit_odf_repeated_runs.COVERED_CELL_TAG;
90
91
  coveredNode.attributes = [];
91
92
  coveredNode.children = [];
92
93
  }
@@ -1,5 +1,6 @@
1
1
  import { removeChild, setAttr } from "../../xml/edit.js";
2
- import { COVERED_CELL_TAG, resolveCellNode } from "./address.js";
2
+ import { COVERED_CELL_TAG } from "../odf-repeated-runs.js";
3
+ import { resolveCellNode } from "./address.js";
3
4
  import { OdsCell } from "./cell.js";
4
5
  import { ensureColumnDefaultWidth, ensureRowDefaultHeight, writeColumnHidden, writeColumnWidth, writeRowHeight, writeRowHidden } from "./column-row.js";
5
6
  import { insertSheetEmbeddedObject, insertSheetImage } from "./floating.js";
@@ -4,6 +4,7 @@ const require_xml_edit = require("../../xml/edit.cjs");
4
4
  const require_edit_table_grid = require("../table-grid.cjs");
5
5
  const require_edit_odt_automatic_styles = require("./automatic-styles.cjs");
6
6
  const require_edit_odt_paragraph = require("./paragraph.cjs");
7
+ const require_edit_odf_repeated_runs = require("../odf-repeated-runs.cjs");
7
8
  let ooxml_js = require("ooxml.js");
8
9
  let document_schema_js = require("document-schema.js");
9
10
  let odf_js = require("odf.js");
@@ -250,16 +251,41 @@ function retagAsCovered(element) {
250
251
  element.attributes = element.attributes.filter((attribute) => attribute.name === COVERED_CELL_KEPT_ATTRIBUTE);
251
252
  element.children = [];
252
253
  }
253
- function gridCellElements(row) {
254
+ function gridColumnElements(row) {
254
255
  const out = [];
255
- for (const child of row.children) if (child.type === "element" && (child.tag === "table:table-cell" || child.tag === "table:covered-table-cell")) out.push(child);
256
+ let columnIndex = 0;
257
+ for (const member of require_edit_odf_repeated_runs.collectRunMembers(row.children, require_edit_odf_repeated_runs.isCellOrCoveredCell, void 0)) {
258
+ const repeat = require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR);
259
+ for (let offset = 0; offset < repeat; offset++) out.push({
260
+ columnIndex: columnIndex + offset,
261
+ element: member.node
262
+ });
263
+ columnIndex += repeat;
264
+ }
256
265
  return out;
257
266
  }
267
+ function rowGridColumnCount(row) {
268
+ return require_edit_odf_repeated_runs.collectRunMembers(row.children, require_edit_odf_repeated_runs.isCellOrCoveredCell, void 0).reduce((sum, member) => sum + require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR), 0);
269
+ }
270
+ function locateGridColumnElement(row, columnIndex) {
271
+ if (columnIndex < 0) return;
272
+ let cursor = 0;
273
+ for (const member of require_edit_odf_repeated_runs.collectRunMembers(row.children, require_edit_odf_repeated_runs.isCellOrCoveredCell, void 0)) {
274
+ const count = require_edit_odf_repeated_runs.readRunRepeatCount(member.node, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR);
275
+ if (columnIndex < cursor + count) return member.node;
276
+ cursor += count;
277
+ }
278
+ }
279
+ function individuateGridColumn(row, columnIndex) {
280
+ return require_edit_odf_repeated_runs.replaceRun(row.children, require_edit_odf_repeated_runs.isCellOrCoveredCell, columnIndex, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR, () => {
281
+ throw new Error(`individuateGridColumn: column ${columnIndex} has no existing element to individuate in this row -- callers must bounds-check against rowGridColumnCount first`);
282
+ });
283
+ }
258
284
  function tableRowElements(table) {
259
285
  return table.children.filter((child) => child.type === "element" && child.tag === "table:table-row");
260
286
  }
261
287
  function placedCells(row, pkg) {
262
- return gridCellElements(row).flatMap((element, columnIndex) => {
288
+ return gridColumnElements(row).flatMap(({ columnIndex, element }) => {
263
289
  if (element.tag !== "table:table-cell") return [];
264
290
  const cell = new OdtTableCell(element, pkg);
265
291
  return [{
@@ -275,7 +301,7 @@ function resolveOdtGrid(table, pkg) {
275
301
  let declaredColumns = 0;
276
302
  for (const child of table.children) {
277
303
  if (child.type !== "element") continue;
278
- if (child.tag === "table:table-column") declaredColumns++;
304
+ if (child.tag === "table:table-column") declaredColumns += require_edit_odf_repeated_runs.readRunRepeatCount(child, require_edit_odf_repeated_runs.COLUMN_REPEAT_ATTR);
279
305
  else if (child.tag === "table:table-row") placedRows.push(placedCells(child, pkg));
280
306
  }
281
307
  return require_edit_table_grid.resolveLiveTableGrid(placedRows, declaredColumns);
@@ -319,14 +345,15 @@ function refuseMerge(rowIndex, reason) {
319
345
  }
320
346
  function planMerge(table, pkg, target, rows) {
321
347
  const [anchorRow, ...coveredRows] = rows;
322
- const anchorCells = gridCellElements(anchorRow);
323
- const coveredCells = coveredRows.map(gridCellElements);
324
- const anchor = anchorCells[target.column];
325
- if (anchor === void 0) return refuseMerge(target.row, `column ${target.column} does not exist in this row`);
348
+ const anchorElement = locateGridColumnElement(anchorRow, target.column);
349
+ if (anchorElement === void 0) return refuseMerge(target.row, `column ${target.column} does not exist in this row`);
326
350
  const endColumn = target.column + target.columnSpan;
327
- for (const [offset, cells] of [anchorCells, ...coveredCells].entries()) if (endColumn > cells.length) return refuseMerge(target.row + offset, `colSpan ${target.columnSpan} starting at column ${target.column} exceeds this row's own ${cells.length} grid columns`);
351
+ for (const [offset, row] of rows.entries()) {
352
+ const totalColumns = rowGridColumnCount(row);
353
+ if (endColumn > totalColumns) return refuseMerge(target.row + offset, `colSpan ${target.columnSpan} starting at column ${target.column} exceeds this row's own ${totalColumns} grid columns`);
354
+ }
328
355
  const regions = anchorRegions(resolveOdtGrid(table, pkg));
329
- if (anchor.tag === "table:covered-table-cell") {
356
+ if (anchorElement.tag === "table:covered-table-cell") {
330
357
  const covering = regions.find((region) => regionCovers(region, target.row, target.column));
331
358
  return refuseMerge(target.row, covering === void 0 ? `column ${target.column} is a covered position that no merge anchors` : `column ${target.column} is covered by ${describeRegionAnchor(covering)}`);
332
359
  }
@@ -335,14 +362,26 @@ function planMerge(table, pkg, target, rows) {
335
362
  const column = Math.max(cutting.column, target.column);
336
363
  return refuseMerge(Math.max(cutting.row, target.row), `column ${column} belongs to ${describeRegionAnchor(cutting)}, which reaches outside the region being merged and cannot be merged over`);
337
364
  }
365
+ const consumed = [];
366
+ for (let column = target.column + 1; column < endColumn; column++) consumed.push({
367
+ row: anchorRow,
368
+ column
369
+ });
370
+ for (const row of coveredRows) for (let column = target.column; column < endColumn; column++) consumed.push({
371
+ row,
372
+ column
373
+ });
338
374
  return {
339
- anchor,
340
- consumed: [...anchorCells.slice(target.column + 1, endColumn), ...coveredCells.flatMap((cells) => cells.slice(target.column, endColumn))]
375
+ anchor: {
376
+ row: anchorRow,
377
+ column: target.column
378
+ },
379
+ consumed
341
380
  };
342
381
  }
343
382
  function applyMerge(plan, target, pkg) {
344
- for (const element of plan.consumed) retagAsCovered(element);
345
- const anchor = new OdtTableCell(plan.anchor, pkg);
383
+ for (const position of plan.consumed) retagAsCovered(individuateGridColumn(position.row, position.column));
384
+ const anchor = new OdtTableCell(individuateGridColumn(plan.anchor.row, plan.anchor.column), pkg);
346
385
  anchor.colSpan = target.columnSpan;
347
386
  if (target.rowSpan > 1) anchor.rowSpan = target.rowSpan;
348
387
  return anchor;
@@ -402,12 +441,12 @@ var OdtTableRow = class {
402
441
  return applyMerge(plan, target, this.pkg);
403
442
  }
404
443
  markCellCovered(columnIndex) {
405
- const element = gridCellElements(this.node)[columnIndex];
406
- if (element === void 0) throw new Error(`markCellCovered: column ${columnIndex} does not exist in this row`);
444
+ const totalColumns = rowGridColumnCount(this.node);
445
+ if (columnIndex < 0 || columnIndex >= totalColumns) throw new Error(`markCellCovered: column ${columnIndex} does not exist in this row`);
407
446
  const rowIndex = tableRowElements(this.table).indexOf(this.node);
408
447
  const anchored = anchorRegions(resolveOdtGrid(this.table, this.pkg)).find((region) => region.row === rowIndex && region.column === columnIndex && (region.rowSpan > 1 || region.columnSpan > 1));
409
448
  if (anchored !== void 0) throw new Error(`markCellCovered: column ${columnIndex} anchors a merge with rowSpan ${anchored.rowSpan} and colSpan ${anchored.columnSpan}, so covering it would leave the rest of that merge without an anchor`);
410
- retagAsCovered(element);
449
+ retagAsCovered(individuateGridColumn(this.node, columnIndex));
411
450
  }
412
451
  };
413
452
  function buildCell(pkg) {
@@ -3,6 +3,7 @@ import { removeAttr, removeChild, setAttr } from "../../xml/edit.js";
3
3
  import { resolveLiveTableGrid } from "../table-grid.js";
4
4
  import { ensureAutomaticStyles, nextStyleName } from "./automatic-styles.js";
5
5
  import { OdtParagraph, buildParagraph } from "./paragraph.js";
6
+ import { COLUMN_REPEAT_ATTR, collectRunMembers, isCellOrCoveredCell, readRunRepeatCount, replaceRun } from "../odf-repeated-runs.js";
6
7
  import { attr } from "ooxml.js";
7
8
  import { tableCellColumnSpan, tableCellRowSpan } from "document-schema.js";
8
9
  import { findStyleElement, formatOdfColor, formatOdfLength, parseOdfColor, parseOdfLength } from "odf.js";
@@ -249,16 +250,41 @@ function retagAsCovered(element) {
249
250
  element.attributes = element.attributes.filter((attribute) => attribute.name === COVERED_CELL_KEPT_ATTRIBUTE);
250
251
  element.children = [];
251
252
  }
252
- function gridCellElements(row) {
253
+ function gridColumnElements(row) {
253
254
  const out = [];
254
- for (const child of row.children) if (child.type === "element" && (child.tag === "table:table-cell" || child.tag === "table:covered-table-cell")) out.push(child);
255
+ let columnIndex = 0;
256
+ for (const member of collectRunMembers(row.children, isCellOrCoveredCell, void 0)) {
257
+ const repeat = readRunRepeatCount(member.node, COLUMN_REPEAT_ATTR);
258
+ for (let offset = 0; offset < repeat; offset++) out.push({
259
+ columnIndex: columnIndex + offset,
260
+ element: member.node
261
+ });
262
+ columnIndex += repeat;
263
+ }
255
264
  return out;
256
265
  }
266
+ function rowGridColumnCount(row) {
267
+ return collectRunMembers(row.children, isCellOrCoveredCell, void 0).reduce((sum, member) => sum + readRunRepeatCount(member.node, COLUMN_REPEAT_ATTR), 0);
268
+ }
269
+ function locateGridColumnElement(row, columnIndex) {
270
+ if (columnIndex < 0) return;
271
+ let cursor = 0;
272
+ for (const member of collectRunMembers(row.children, isCellOrCoveredCell, void 0)) {
273
+ const count = readRunRepeatCount(member.node, COLUMN_REPEAT_ATTR);
274
+ if (columnIndex < cursor + count) return member.node;
275
+ cursor += count;
276
+ }
277
+ }
278
+ function individuateGridColumn(row, columnIndex) {
279
+ return replaceRun(row.children, isCellOrCoveredCell, columnIndex, COLUMN_REPEAT_ATTR, () => {
280
+ throw new Error(`individuateGridColumn: column ${columnIndex} has no existing element to individuate in this row -- callers must bounds-check against rowGridColumnCount first`);
281
+ });
282
+ }
257
283
  function tableRowElements(table) {
258
284
  return table.children.filter((child) => child.type === "element" && child.tag === "table:table-row");
259
285
  }
260
286
  function placedCells(row, pkg) {
261
- return gridCellElements(row).flatMap((element, columnIndex) => {
287
+ return gridColumnElements(row).flatMap(({ columnIndex, element }) => {
262
288
  if (element.tag !== "table:table-cell") return [];
263
289
  const cell = new OdtTableCell(element, pkg);
264
290
  return [{
@@ -274,7 +300,7 @@ function resolveOdtGrid(table, pkg) {
274
300
  let declaredColumns = 0;
275
301
  for (const child of table.children) {
276
302
  if (child.type !== "element") continue;
277
- if (child.tag === "table:table-column") declaredColumns++;
303
+ if (child.tag === "table:table-column") declaredColumns += readRunRepeatCount(child, COLUMN_REPEAT_ATTR);
278
304
  else if (child.tag === "table:table-row") placedRows.push(placedCells(child, pkg));
279
305
  }
280
306
  return resolveLiveTableGrid(placedRows, declaredColumns);
@@ -318,14 +344,15 @@ function refuseMerge(rowIndex, reason) {
318
344
  }
319
345
  function planMerge(table, pkg, target, rows) {
320
346
  const [anchorRow, ...coveredRows] = rows;
321
- const anchorCells = gridCellElements(anchorRow);
322
- const coveredCells = coveredRows.map(gridCellElements);
323
- const anchor = anchorCells[target.column];
324
- if (anchor === void 0) return refuseMerge(target.row, `column ${target.column} does not exist in this row`);
347
+ const anchorElement = locateGridColumnElement(anchorRow, target.column);
348
+ if (anchorElement === void 0) return refuseMerge(target.row, `column ${target.column} does not exist in this row`);
325
349
  const endColumn = target.column + target.columnSpan;
326
- for (const [offset, cells] of [anchorCells, ...coveredCells].entries()) if (endColumn > cells.length) return refuseMerge(target.row + offset, `colSpan ${target.columnSpan} starting at column ${target.column} exceeds this row's own ${cells.length} grid columns`);
350
+ for (const [offset, row] of rows.entries()) {
351
+ const totalColumns = rowGridColumnCount(row);
352
+ if (endColumn > totalColumns) return refuseMerge(target.row + offset, `colSpan ${target.columnSpan} starting at column ${target.column} exceeds this row's own ${totalColumns} grid columns`);
353
+ }
327
354
  const regions = anchorRegions(resolveOdtGrid(table, pkg));
328
- if (anchor.tag === "table:covered-table-cell") {
355
+ if (anchorElement.tag === "table:covered-table-cell") {
329
356
  const covering = regions.find((region) => regionCovers(region, target.row, target.column));
330
357
  return refuseMerge(target.row, covering === void 0 ? `column ${target.column} is a covered position that no merge anchors` : `column ${target.column} is covered by ${describeRegionAnchor(covering)}`);
331
358
  }
@@ -334,14 +361,26 @@ function planMerge(table, pkg, target, rows) {
334
361
  const column = Math.max(cutting.column, target.column);
335
362
  return refuseMerge(Math.max(cutting.row, target.row), `column ${column} belongs to ${describeRegionAnchor(cutting)}, which reaches outside the region being merged and cannot be merged over`);
336
363
  }
364
+ const consumed = [];
365
+ for (let column = target.column + 1; column < endColumn; column++) consumed.push({
366
+ row: anchorRow,
367
+ column
368
+ });
369
+ for (const row of coveredRows) for (let column = target.column; column < endColumn; column++) consumed.push({
370
+ row,
371
+ column
372
+ });
337
373
  return {
338
- anchor,
339
- consumed: [...anchorCells.slice(target.column + 1, endColumn), ...coveredCells.flatMap((cells) => cells.slice(target.column, endColumn))]
374
+ anchor: {
375
+ row: anchorRow,
376
+ column: target.column
377
+ },
378
+ consumed
340
379
  };
341
380
  }
342
381
  function applyMerge(plan, target, pkg) {
343
- for (const element of plan.consumed) retagAsCovered(element);
344
- const anchor = new OdtTableCell(plan.anchor, pkg);
382
+ for (const position of plan.consumed) retagAsCovered(individuateGridColumn(position.row, position.column));
383
+ const anchor = new OdtTableCell(individuateGridColumn(plan.anchor.row, plan.anchor.column), pkg);
345
384
  anchor.colSpan = target.columnSpan;
346
385
  if (target.rowSpan > 1) anchor.rowSpan = target.rowSpan;
347
386
  return anchor;
@@ -401,12 +440,12 @@ var OdtTableRow = class {
401
440
  return applyMerge(plan, target, this.pkg);
402
441
  }
403
442
  markCellCovered(columnIndex) {
404
- const element = gridCellElements(this.node)[columnIndex];
405
- if (element === void 0) throw new Error(`markCellCovered: column ${columnIndex} does not exist in this row`);
443
+ const totalColumns = rowGridColumnCount(this.node);
444
+ if (columnIndex < 0 || columnIndex >= totalColumns) throw new Error(`markCellCovered: column ${columnIndex} does not exist in this row`);
406
445
  const rowIndex = tableRowElements(this.table).indexOf(this.node);
407
446
  const anchored = anchorRegions(resolveOdtGrid(this.table, this.pkg)).find((region) => region.row === rowIndex && region.column === columnIndex && (region.rowSpan > 1 || region.columnSpan > 1));
408
447
  if (anchored !== void 0) throw new Error(`markCellCovered: column ${columnIndex} anchors a merge with rowSpan ${anchored.rowSpan} and colSpan ${anchored.columnSpan}, so covering it would leave the rest of that merge without an anchor`);
409
- retagAsCovered(element);
448
+ retagAsCovered(individuateGridColumn(this.node, columnIndex));
410
449
  }
411
450
  };
412
451
  function buildCell(pkg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js.documents",
3
- "version": "12.1.0",
3
+ "version": "13.0.0",
4
4
  "description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {