odf.js 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/index.cjs +909 -48
- package/dist/index.d.cts +66 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +896 -49
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1420,6 +1420,25 @@ function cellReference(columnIndex, rowIndex) {
|
|
|
1420
1420
|
if (!Number.isInteger(rowIndex) || rowIndex < 0) throw new Error(`cellReference: rowIndex must be a non-negative integer, got ${rowIndex}`);
|
|
1421
1421
|
return `${columnIndexToLetters(columnIndex)}${rowIndex + 1}`;
|
|
1422
1422
|
}
|
|
1423
|
+
function columnLettersToIndex(letters) {
|
|
1424
|
+
if (!/^[A-Z]+$/.test(letters)) return;
|
|
1425
|
+
let index = 0;
|
|
1426
|
+
for (const char of letters) index = index * ALPHABET_SIZE + (char.charCodeAt(0) - ALPHABET_START_CODE + 1);
|
|
1427
|
+
return index - 1;
|
|
1428
|
+
}
|
|
1429
|
+
function parseCellReference(reference) {
|
|
1430
|
+
const match = /^([A-Z]+)(\d+)$/.exec(reference);
|
|
1431
|
+
if (match === null) return;
|
|
1432
|
+
const [, letters, digits] = match;
|
|
1433
|
+
if (letters === void 0 || digits === void 0) return;
|
|
1434
|
+
const column = columnLettersToIndex(letters);
|
|
1435
|
+
const row = Number.parseInt(digits, 10) - 1;
|
|
1436
|
+
if (column === void 0 || row < 0) return;
|
|
1437
|
+
return {
|
|
1438
|
+
column,
|
|
1439
|
+
row
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1423
1442
|
function validateRepeatCount(repeatCount, caller) {
|
|
1424
1443
|
if (!Number.isInteger(repeatCount) || repeatCount < 1) throw new Error(`${caller}: repeatCount must be a positive integer, got ${repeatCount}`);
|
|
1425
1444
|
}
|
|
@@ -1494,6 +1513,28 @@ function parseBox(element) {
|
|
|
1494
1513
|
heightPt
|
|
1495
1514
|
};
|
|
1496
1515
|
}
|
|
1516
|
+
function parseLinePoints(element) {
|
|
1517
|
+
const x1Value = attrValue(element, "svg:x1");
|
|
1518
|
+
const y1Value = attrValue(element, "svg:y1");
|
|
1519
|
+
const x2Value = attrValue(element, "svg:x2");
|
|
1520
|
+
const y2Value = attrValue(element, "svg:y2");
|
|
1521
|
+
if (x1Value === void 0 || y1Value === void 0 || x2Value === void 0 || y2Value === void 0) return;
|
|
1522
|
+
const x1Pt = parseOdfLength(x1Value);
|
|
1523
|
+
const y1Pt = parseOdfLength(y1Value);
|
|
1524
|
+
const x2Pt = parseOdfLength(x2Value);
|
|
1525
|
+
const y2Pt = parseOdfLength(y2Value);
|
|
1526
|
+
if (x1Pt === void 0 || y1Pt === void 0 || x2Pt === void 0 || y2Pt === void 0) return;
|
|
1527
|
+
return {
|
|
1528
|
+
from: {
|
|
1529
|
+
xPt: x1Pt,
|
|
1530
|
+
yPt: y1Pt
|
|
1531
|
+
},
|
|
1532
|
+
to: {
|
|
1533
|
+
xPt: x2Pt,
|
|
1534
|
+
yPt: y2Pt
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1497
1538
|
//#endregion
|
|
1498
1539
|
//#region src/typed/shared/cascade.ts
|
|
1499
1540
|
const STYLE_PARTS = ["content.xml", "styles.xml"];
|
|
@@ -1679,7 +1720,7 @@ function readOdfParagraph(pElement, pkg) {
|
|
|
1679
1720
|
}
|
|
1680
1721
|
//#endregion
|
|
1681
1722
|
//#region src/typed/shared/table.ts
|
|
1682
|
-
function readRepeatCount(element, attrName) {
|
|
1723
|
+
function readRepeatCount$1(element, attrName) {
|
|
1683
1724
|
const raw = attrValue(element, attrName);
|
|
1684
1725
|
if (raw === void 0) return 1;
|
|
1685
1726
|
const parsed = Number.parseInt(raw, 10);
|
|
@@ -1722,11 +1763,11 @@ function readTableRow(rowElement, pkg) {
|
|
|
1722
1763
|
for (const child of rowElement.children) {
|
|
1723
1764
|
if (child.type !== "element") continue;
|
|
1724
1765
|
if (child.tag === "table:covered-table-cell") {
|
|
1725
|
-
const repeat = readRepeatCount(child, "table:number-columns-repeated");
|
|
1766
|
+
const repeat = readRepeatCount$1(child, "table:number-columns-repeated");
|
|
1726
1767
|
for (let i = 0; i < repeat; i++) cells.push({ blocks: [] });
|
|
1727
1768
|
} else if (child.tag === "table:table-cell") {
|
|
1728
1769
|
const cell = readTableCell(child, pkg);
|
|
1729
|
-
const repeat = readRepeatCount(child, "table:number-columns-repeated");
|
|
1770
|
+
const repeat = readRepeatCount$1(child, "table:number-columns-repeated");
|
|
1730
1771
|
for (let i = 0; i < repeat; i++) cells.push(cell);
|
|
1731
1772
|
}
|
|
1732
1773
|
}
|
|
@@ -1739,13 +1780,13 @@ function readOdfTable(tableElement, pkg) {
|
|
|
1739
1780
|
const columnWidthsPt = [];
|
|
1740
1781
|
for (const column of childrenWithTag(tableElement, "table:table-column")) {
|
|
1741
1782
|
const widthPt = resolveColumnWidthPt(column, pkg);
|
|
1742
|
-
const repeat = readRepeatCount(column, "table:number-columns-repeated");
|
|
1783
|
+
const repeat = readRepeatCount$1(column, "table:number-columns-repeated");
|
|
1743
1784
|
for (let i = 0; i < repeat; i++) columnWidthsPt.push(widthPt);
|
|
1744
1785
|
}
|
|
1745
1786
|
const rows = [];
|
|
1746
1787
|
for (const rowElement of childrenWithTag(tableElement, "table:table-row")) {
|
|
1747
1788
|
const row = readTableRow(rowElement, pkg);
|
|
1748
|
-
const repeat = readRepeatCount(rowElement, "table:number-rows-repeated");
|
|
1789
|
+
const repeat = readRepeatCount$1(rowElement, "table:number-rows-repeated");
|
|
1749
1790
|
for (let i = 0; i < repeat; i++) rows.push(row);
|
|
1750
1791
|
}
|
|
1751
1792
|
return {
|
|
@@ -1858,6 +1899,294 @@ function composeOdfGroupTransform(groupFunctions, child) {
|
|
|
1858
1899
|
};
|
|
1859
1900
|
}
|
|
1860
1901
|
//#endregion
|
|
1902
|
+
//#region src/typed/shared/masterpage.ts
|
|
1903
|
+
const STYLES_PART$1 = "styles.xml";
|
|
1904
|
+
const AUTOMATIC_STYLE_PARTS$1 = ["content.xml", STYLES_PART$1];
|
|
1905
|
+
function findMasterPageElement(pkg, masterPageName) {
|
|
1906
|
+
if (masterPageName === void 0) return;
|
|
1907
|
+
const stylesPart = pkg.parts[STYLES_PART$1];
|
|
1908
|
+
if (stylesPart?.kind !== "xml") return;
|
|
1909
|
+
const root = rootElement(stylesPart.nodes);
|
|
1910
|
+
const masterStyles = root === void 0 ? void 0 : findChildElement(root.children, "office:master-styles");
|
|
1911
|
+
if (masterStyles === void 0) return;
|
|
1912
|
+
return childrenWithTag(masterStyles, "style:master-page").find((element) => attrValue(element, "style:name") === masterPageName);
|
|
1913
|
+
}
|
|
1914
|
+
function findPageLayoutElement$1(pkg, pageLayoutName) {
|
|
1915
|
+
if (pageLayoutName === void 0) return;
|
|
1916
|
+
for (const partPath of AUTOMATIC_STYLE_PARTS$1) {
|
|
1917
|
+
const part = pkg.parts[partPath];
|
|
1918
|
+
if (part?.kind !== "xml") continue;
|
|
1919
|
+
const root = rootElement(part.nodes);
|
|
1920
|
+
const automaticStyles = root === void 0 ? void 0 : findChildElement(root.children, "office:automatic-styles");
|
|
1921
|
+
if (automaticStyles === void 0) continue;
|
|
1922
|
+
const found = childrenWithTag(automaticStyles, "style:page-layout").find((element) => attrValue(element, "style:name") === pageLayoutName);
|
|
1923
|
+
if (found !== void 0) return found;
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
function resolvePageLayoutProperties(pkg, masterPageName) {
|
|
1927
|
+
const masterPage = findMasterPageElement(pkg, masterPageName);
|
|
1928
|
+
const pageLayout = findPageLayoutElement$1(pkg, masterPage === void 0 ? void 0 : attrValue(masterPage, "style:page-layout-name"));
|
|
1929
|
+
return pageLayout === void 0 ? void 0 : childrenWithTag(pageLayout, "style:page-layout-properties")[0];
|
|
1930
|
+
}
|
|
1931
|
+
function resolveDrawPageSize(page, pkg) {
|
|
1932
|
+
const properties = resolvePageLayoutProperties(pkg, attrValue(page, "draw:master-page-name"));
|
|
1933
|
+
return properties === void 0 ? void 0 : parsePageSize(properties);
|
|
1934
|
+
}
|
|
1935
|
+
//#endregion
|
|
1936
|
+
//#region src/typed/shared/path.ts
|
|
1937
|
+
const VIEW_BOX_PATTERN = /^(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)$/;
|
|
1938
|
+
function parseOdfViewBox(value) {
|
|
1939
|
+
const match = VIEW_BOX_PATTERN.exec(value.trim());
|
|
1940
|
+
if (match === null) return;
|
|
1941
|
+
const minX = Number(match[1]);
|
|
1942
|
+
const minY = Number(match[2]);
|
|
1943
|
+
const width = Number(match[3]);
|
|
1944
|
+
const height = Number(match[4]);
|
|
1945
|
+
if (width <= 0 || height <= 0) return;
|
|
1946
|
+
return {
|
|
1947
|
+
minX,
|
|
1948
|
+
minY,
|
|
1949
|
+
width,
|
|
1950
|
+
height
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
function parseOdfPointsList(value) {
|
|
1954
|
+
const points = [];
|
|
1955
|
+
for (const pair of value.trim().split(/\s+/)) {
|
|
1956
|
+
if (pair.length === 0) continue;
|
|
1957
|
+
const [xRaw, yRaw] = pair.split(",");
|
|
1958
|
+
if (xRaw === void 0 || yRaw === void 0) continue;
|
|
1959
|
+
const x = Number(xRaw);
|
|
1960
|
+
const y = Number(yRaw);
|
|
1961
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) continue;
|
|
1962
|
+
points.push({
|
|
1963
|
+
x,
|
|
1964
|
+
y
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
return points;
|
|
1968
|
+
}
|
|
1969
|
+
function rawSubpathFromPoints(points, closed) {
|
|
1970
|
+
const start = points[0];
|
|
1971
|
+
if (start === void 0) return;
|
|
1972
|
+
return {
|
|
1973
|
+
start,
|
|
1974
|
+
segments: points.slice(1).map((to) => ({
|
|
1975
|
+
kind: "line",
|
|
1976
|
+
to
|
|
1977
|
+
})),
|
|
1978
|
+
closed
|
|
1979
|
+
};
|
|
1980
|
+
}
|
|
1981
|
+
const COMMAND_LETTERS = /* @__PURE__ */ new Set([
|
|
1982
|
+
"M",
|
|
1983
|
+
"m",
|
|
1984
|
+
"L",
|
|
1985
|
+
"l",
|
|
1986
|
+
"H",
|
|
1987
|
+
"h",
|
|
1988
|
+
"V",
|
|
1989
|
+
"v",
|
|
1990
|
+
"C",
|
|
1991
|
+
"c",
|
|
1992
|
+
"S",
|
|
1993
|
+
"s",
|
|
1994
|
+
"Q",
|
|
1995
|
+
"q",
|
|
1996
|
+
"T",
|
|
1997
|
+
"t",
|
|
1998
|
+
"A",
|
|
1999
|
+
"a",
|
|
2000
|
+
"Z",
|
|
2001
|
+
"z"
|
|
2002
|
+
]);
|
|
2003
|
+
function isCommandLetter(token) {
|
|
2004
|
+
return COMMAND_LETTERS.has(token);
|
|
2005
|
+
}
|
|
2006
|
+
const PATH_TOKEN_PATTERN = /[MmLlHhVvCcSsQqTtAaZz]|-?(?:\d+\.\d+|\.\d+|\d+)(?:[eE][-+]?\d+)?/g;
|
|
2007
|
+
function tokenizePathData(d) {
|
|
2008
|
+
return d.match(PATH_TOKEN_PATTERN) ?? [];
|
|
2009
|
+
}
|
|
2010
|
+
function parseOdfPathData(d) {
|
|
2011
|
+
const tokens = tokenizePathData(d);
|
|
2012
|
+
const subpaths = [];
|
|
2013
|
+
let current = {
|
|
2014
|
+
x: 0,
|
|
2015
|
+
y: 0
|
|
2016
|
+
};
|
|
2017
|
+
let subpathStart = {
|
|
2018
|
+
x: 0,
|
|
2019
|
+
y: 0
|
|
2020
|
+
};
|
|
2021
|
+
let activeSubpath;
|
|
2022
|
+
let command;
|
|
2023
|
+
let firstMInCommand = true;
|
|
2024
|
+
function startSubpath(point) {
|
|
2025
|
+
activeSubpath = {
|
|
2026
|
+
start: point,
|
|
2027
|
+
segments: [],
|
|
2028
|
+
closed: false
|
|
2029
|
+
};
|
|
2030
|
+
subpaths.push(activeSubpath);
|
|
2031
|
+
subpathStart = point;
|
|
2032
|
+
current = point;
|
|
2033
|
+
}
|
|
2034
|
+
function pushSegment(segment, to) {
|
|
2035
|
+
if (activeSubpath !== void 0) activeSubpath.segments.push(segment);
|
|
2036
|
+
current = to;
|
|
2037
|
+
}
|
|
2038
|
+
let i = 0;
|
|
2039
|
+
while (i < tokens.length) {
|
|
2040
|
+
const token = tokens[i];
|
|
2041
|
+
if (token === void 0) break;
|
|
2042
|
+
if (isCommandLetter(token)) {
|
|
2043
|
+
if (token === "Z" || token === "z") {
|
|
2044
|
+
if (activeSubpath !== void 0) {
|
|
2045
|
+
activeSubpath.closed = true;
|
|
2046
|
+
current = subpathStart;
|
|
2047
|
+
}
|
|
2048
|
+
command = void 0;
|
|
2049
|
+
i += 1;
|
|
2050
|
+
continue;
|
|
2051
|
+
}
|
|
2052
|
+
command = token;
|
|
2053
|
+
firstMInCommand = true;
|
|
2054
|
+
i += 1;
|
|
2055
|
+
continue;
|
|
2056
|
+
}
|
|
2057
|
+
if (command === void 0) {
|
|
2058
|
+
i += 1;
|
|
2059
|
+
continue;
|
|
2060
|
+
}
|
|
2061
|
+
const upper = command.toUpperCase();
|
|
2062
|
+
const relative = command !== upper;
|
|
2063
|
+
if (upper === "M" || upper === "L") {
|
|
2064
|
+
const xTok = tokens[i];
|
|
2065
|
+
const yTok = tokens[i + 1];
|
|
2066
|
+
i += 2;
|
|
2067
|
+
if (xTok === void 0 || yTok === void 0) break;
|
|
2068
|
+
const x = Number(xTok);
|
|
2069
|
+
const y = Number(yTok);
|
|
2070
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) continue;
|
|
2071
|
+
const point = relative ? {
|
|
2072
|
+
x: current.x + x,
|
|
2073
|
+
y: current.y + y
|
|
2074
|
+
} : {
|
|
2075
|
+
x,
|
|
2076
|
+
y
|
|
2077
|
+
};
|
|
2078
|
+
if (upper === "M" && firstMInCommand) {
|
|
2079
|
+
startSubpath(point);
|
|
2080
|
+
firstMInCommand = false;
|
|
2081
|
+
} else pushSegment({
|
|
2082
|
+
kind: "line",
|
|
2083
|
+
to: point
|
|
2084
|
+
}, point);
|
|
2085
|
+
} else if (upper === "H") {
|
|
2086
|
+
const xTok = tokens[i];
|
|
2087
|
+
i += 1;
|
|
2088
|
+
if (xTok === void 0) break;
|
|
2089
|
+
const x = Number(xTok);
|
|
2090
|
+
if (!Number.isFinite(x)) continue;
|
|
2091
|
+
const point = relative ? {
|
|
2092
|
+
x: current.x + x,
|
|
2093
|
+
y: current.y
|
|
2094
|
+
} : {
|
|
2095
|
+
x,
|
|
2096
|
+
y: current.y
|
|
2097
|
+
};
|
|
2098
|
+
pushSegment({
|
|
2099
|
+
kind: "line",
|
|
2100
|
+
to: point
|
|
2101
|
+
}, point);
|
|
2102
|
+
} else if (upper === "V") {
|
|
2103
|
+
const yTok = tokens[i];
|
|
2104
|
+
i += 1;
|
|
2105
|
+
if (yTok === void 0) break;
|
|
2106
|
+
const y = Number(yTok);
|
|
2107
|
+
if (!Number.isFinite(y)) continue;
|
|
2108
|
+
const point = relative ? {
|
|
2109
|
+
x: current.x,
|
|
2110
|
+
y: current.y + y
|
|
2111
|
+
} : {
|
|
2112
|
+
x: current.x,
|
|
2113
|
+
y
|
|
2114
|
+
};
|
|
2115
|
+
pushSegment({
|
|
2116
|
+
kind: "line",
|
|
2117
|
+
to: point
|
|
2118
|
+
}, point);
|
|
2119
|
+
} else if (upper === "C") {
|
|
2120
|
+
const rawArgs = tokens.slice(i, i + 6);
|
|
2121
|
+
i += 6;
|
|
2122
|
+
if (rawArgs.length < 6) break;
|
|
2123
|
+
const x1 = Number(rawArgs[0]);
|
|
2124
|
+
const y1 = Number(rawArgs[1]);
|
|
2125
|
+
const x2 = Number(rawArgs[2]);
|
|
2126
|
+
const y2 = Number(rawArgs[3]);
|
|
2127
|
+
const x = Number(rawArgs[4]);
|
|
2128
|
+
const y = Number(rawArgs[5]);
|
|
2129
|
+
if (![
|
|
2130
|
+
x1,
|
|
2131
|
+
y1,
|
|
2132
|
+
x2,
|
|
2133
|
+
y2,
|
|
2134
|
+
x,
|
|
2135
|
+
y
|
|
2136
|
+
].every(Number.isFinite)) continue;
|
|
2137
|
+
const control1 = relative ? {
|
|
2138
|
+
x: current.x + x1,
|
|
2139
|
+
y: current.y + y1
|
|
2140
|
+
} : {
|
|
2141
|
+
x: x1,
|
|
2142
|
+
y: y1
|
|
2143
|
+
};
|
|
2144
|
+
const control2 = relative ? {
|
|
2145
|
+
x: current.x + x2,
|
|
2146
|
+
y: current.y + y2
|
|
2147
|
+
} : {
|
|
2148
|
+
x: x2,
|
|
2149
|
+
y: y2
|
|
2150
|
+
};
|
|
2151
|
+
const to = relative ? {
|
|
2152
|
+
x: current.x + x,
|
|
2153
|
+
y: current.y + y
|
|
2154
|
+
} : {
|
|
2155
|
+
x,
|
|
2156
|
+
y
|
|
2157
|
+
};
|
|
2158
|
+
pushSegment({
|
|
2159
|
+
kind: "cubic",
|
|
2160
|
+
control1,
|
|
2161
|
+
control2,
|
|
2162
|
+
to
|
|
2163
|
+
}, to);
|
|
2164
|
+
} else i += 1;
|
|
2165
|
+
}
|
|
2166
|
+
return subpaths;
|
|
2167
|
+
}
|
|
2168
|
+
function scaleOdfRawPoint(point, viewBox, frame) {
|
|
2169
|
+
return {
|
|
2170
|
+
xPt: (point.x - viewBox.minX) * (frame.widthPt / viewBox.width),
|
|
2171
|
+
yPt: (point.y - viewBox.minY) * (frame.heightPt / viewBox.height)
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
function buildOdfSubpaths(rawSubpaths, viewBox, frame) {
|
|
2175
|
+
return rawSubpaths.map((raw) => ({
|
|
2176
|
+
start: scaleOdfRawPoint(raw.start, viewBox, frame),
|
|
2177
|
+
closed: raw.closed,
|
|
2178
|
+
segments: raw.segments.map((segment) => segment.kind === "line" ? {
|
|
2179
|
+
kind: "line",
|
|
2180
|
+
to: scaleOdfRawPoint(segment.to, viewBox, frame)
|
|
2181
|
+
} : {
|
|
2182
|
+
kind: "cubic",
|
|
2183
|
+
control1: scaleOdfRawPoint(segment.control1, viewBox, frame),
|
|
2184
|
+
control2: scaleOdfRawPoint(segment.control2, viewBox, frame),
|
|
2185
|
+
to: scaleOdfRawPoint(segment.to, viewBox, frame)
|
|
2186
|
+
})
|
|
2187
|
+
}));
|
|
2188
|
+
}
|
|
2189
|
+
//#endregion
|
|
1861
2190
|
//#region src/typed/draw/shapes.ts
|
|
1862
2191
|
const ZERO_INSETS = {
|
|
1863
2192
|
insetLeftPt: 0,
|
|
@@ -1939,37 +2268,224 @@ function walkDrawShapes(children, groupFunctions, pkg, out) {
|
|
|
1939
2268
|
}
|
|
1940
2269
|
}
|
|
1941
2270
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
2271
|
+
function readOdfFillAndStroke(element, pkg) {
|
|
2272
|
+
const { elements } = resolveStyleElementChain(attrValue(element, "draw:style-name"), "graphic", pkg);
|
|
2273
|
+
let fill;
|
|
2274
|
+
let stroke;
|
|
2275
|
+
for (const styleElement of elements) {
|
|
2276
|
+
const props = childrenWithTag(styleElement, "style:graphic-properties")[0];
|
|
2277
|
+
if (props === void 0) continue;
|
|
2278
|
+
if (attrValue(props, "draw:fill") === "none") fill = void 0;
|
|
2279
|
+
else {
|
|
2280
|
+
const fillColorValue = attrValue(props, "draw:fill-color");
|
|
2281
|
+
const parsedFill = fillColorValue === void 0 ? void 0 : parseOdfColor(fillColorValue);
|
|
2282
|
+
if (parsedFill !== void 0) fill = parsedFill;
|
|
2283
|
+
}
|
|
2284
|
+
if (attrValue(props, "draw:stroke") === "none") stroke = void 0;
|
|
2285
|
+
else {
|
|
2286
|
+
const strokeColorValue = attrValue(props, "svg:stroke-color");
|
|
2287
|
+
const strokeWidthValue = attrValue(props, "svg:stroke-width");
|
|
2288
|
+
const strokeColor = strokeColorValue === void 0 ? void 0 : parseOdfColor(strokeColorValue);
|
|
2289
|
+
const strokeWidthPt = strokeWidthValue === void 0 ? void 0 : parseOdfLength(strokeWidthValue);
|
|
2290
|
+
if (strokeColor !== void 0 && strokeWidthPt !== void 0 && strokeWidthPt > 0) stroke = {
|
|
2291
|
+
color: strokeColor,
|
|
2292
|
+
widthPt: strokeWidthPt
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
return {
|
|
2297
|
+
fill,
|
|
2298
|
+
stroke
|
|
2299
|
+
};
|
|
1955
2300
|
}
|
|
1956
|
-
function
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2301
|
+
function resolveVectorFrame(element, groupFunctions) {
|
|
2302
|
+
const geometry = resolveOdfShapeGeometry(element);
|
|
2303
|
+
if (geometry === void 0) return;
|
|
2304
|
+
return composeOdfGroupTransform(groupFunctions, geometry).frame;
|
|
2305
|
+
}
|
|
2306
|
+
function readDrawRectVector(element, groupFunctions, pkg) {
|
|
2307
|
+
const frame = resolveVectorFrame(element, groupFunctions);
|
|
2308
|
+
if (frame === void 0) return;
|
|
2309
|
+
const { fill, stroke } = readOdfFillAndStroke(element, pkg);
|
|
2310
|
+
return {
|
|
2311
|
+
kind: "rect",
|
|
2312
|
+
frame,
|
|
2313
|
+
fill,
|
|
2314
|
+
stroke
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
function readDrawEllipseVector(element, groupFunctions, pkg) {
|
|
2318
|
+
const frame = resolveVectorFrame(element, groupFunctions);
|
|
2319
|
+
if (frame === void 0) return;
|
|
2320
|
+
const { fill, stroke } = readOdfFillAndStroke(element, pkg);
|
|
2321
|
+
return {
|
|
2322
|
+
kind: "ellipse",
|
|
2323
|
+
frame,
|
|
2324
|
+
fill,
|
|
2325
|
+
stroke
|
|
2326
|
+
};
|
|
2327
|
+
}
|
|
2328
|
+
function readDrawLineVector(element, groupFunctions, pkg) {
|
|
2329
|
+
const raw = parseLinePoints(element);
|
|
2330
|
+
if (raw === void 0) return;
|
|
2331
|
+
const from = groupFunctions.length === 0 ? raw.from : applyOdfTransform(groupFunctions, raw.from);
|
|
2332
|
+
const to = groupFunctions.length === 0 ? raw.to : applyOdfTransform(groupFunctions, raw.to);
|
|
2333
|
+
const { stroke } = readOdfFillAndStroke(element, pkg);
|
|
2334
|
+
if (stroke === void 0) return;
|
|
2335
|
+
return {
|
|
2336
|
+
kind: "line",
|
|
2337
|
+
from,
|
|
2338
|
+
to,
|
|
2339
|
+
stroke
|
|
2340
|
+
};
|
|
2341
|
+
}
|
|
2342
|
+
function readDrawPathVector(element, groupFunctions, pkg) {
|
|
2343
|
+
const frame = resolveVectorFrame(element, groupFunctions);
|
|
2344
|
+
if (frame === void 0) return;
|
|
2345
|
+
const viewBoxValue = attrValue(element, "svg:viewBox");
|
|
2346
|
+
const viewBox = viewBoxValue === void 0 ? void 0 : parseOdfViewBox(viewBoxValue);
|
|
2347
|
+
if (viewBox === void 0) return;
|
|
2348
|
+
let rawSubpaths;
|
|
2349
|
+
if (element.tag === "draw:path") {
|
|
2350
|
+
const d = attrValue(element, "svg:d");
|
|
2351
|
+
rawSubpaths = d === void 0 ? [] : parseOdfPathData(d);
|
|
2352
|
+
} else {
|
|
2353
|
+
const pointsValue = attrValue(element, "draw:points");
|
|
2354
|
+
const subpath = rawSubpathFromPoints(pointsValue === void 0 ? [] : parseOdfPointsList(pointsValue), element.tag === "draw:polygon");
|
|
2355
|
+
rawSubpaths = subpath === void 0 ? [] : [subpath];
|
|
2356
|
+
}
|
|
2357
|
+
if (rawSubpaths.length === 0) return;
|
|
2358
|
+
const subpaths = buildOdfSubpaths(rawSubpaths, viewBox, frame);
|
|
2359
|
+
const { fill, stroke } = readOdfFillAndStroke(element, pkg);
|
|
2360
|
+
return {
|
|
2361
|
+
kind: "path",
|
|
2362
|
+
frame,
|
|
2363
|
+
subpaths,
|
|
2364
|
+
fill,
|
|
2365
|
+
stroke
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
const RECOGNIZED_CUSTOM_SHAPE_PRESETS = /* @__PURE__ */ new Set([
|
|
2369
|
+
"rectangle",
|
|
2370
|
+
"round-rectangle",
|
|
2371
|
+
"ellipse"
|
|
2372
|
+
]);
|
|
2373
|
+
function readCustomShapeVector(element, groupFunctions, pkg) {
|
|
2374
|
+
const geometryElement = childrenWithTag(element, "draw:enhanced-geometry")[0];
|
|
2375
|
+
const type = geometryElement === void 0 ? void 0 : attrValue(geometryElement, "draw:type");
|
|
2376
|
+
if (type === void 0 || !RECOGNIZED_CUSTOM_SHAPE_PRESETS.has(type)) return;
|
|
2377
|
+
const frame = resolveVectorFrame(element, groupFunctions);
|
|
2378
|
+
if (frame === void 0) return;
|
|
2379
|
+
const { fill, stroke } = readOdfFillAndStroke(element, pkg);
|
|
2380
|
+
return {
|
|
2381
|
+
kind: type === "ellipse" ? "ellipse" : "rect",
|
|
2382
|
+
frame,
|
|
2383
|
+
fill,
|
|
2384
|
+
stroke
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
function readCustomShapeAsTextShape(element, groupFunctions, pkg) {
|
|
2388
|
+
const paragraphs = elementsWithTag(element.children, "text:p").map((p) => readOdfParagraph(p, pkg));
|
|
2389
|
+
if (!paragraphs.some((paragraph) => paragraph.runs.some((run) => run.text.length > 0))) return;
|
|
2390
|
+
const ownGeometry = resolveOdfShapeGeometry(element);
|
|
2391
|
+
if (ownGeometry === void 0) return;
|
|
2392
|
+
const geometry = composeOdfGroupTransform(groupFunctions, ownGeometry);
|
|
2393
|
+
return {
|
|
2394
|
+
name: attrValue(element, "draw:name"),
|
|
2395
|
+
frame: geometry.frame,
|
|
2396
|
+
rotationDeg: geometry.rotationDeg,
|
|
2397
|
+
...readFrameInsets(element, pkg),
|
|
2398
|
+
blocks: paragraphs
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
function nextDocumentIndex(state) {
|
|
2402
|
+
const value = state.next;
|
|
2403
|
+
state.next += 1;
|
|
2404
|
+
return value;
|
|
2405
|
+
}
|
|
2406
|
+
function paintOrderKey(element, state) {
|
|
2407
|
+
const documentIndex = nextDocumentIndex(state);
|
|
2408
|
+
const raw = attrValue(element, "draw:z-index");
|
|
2409
|
+
if (raw === void 0) return documentIndex;
|
|
2410
|
+
const parsed = Number.parseInt(raw, 10);
|
|
2411
|
+
return Number.isInteger(parsed) && parsed >= 0 ? parsed : documentIndex;
|
|
2412
|
+
}
|
|
2413
|
+
function byPaintOrder(items) {
|
|
2414
|
+
return items.slice().sort((a, b) => a.zIndex - b.zIndex).map((item) => item.value);
|
|
2415
|
+
}
|
|
2416
|
+
function walkDrawPageContent(children, groupFunctions, pkg, indexState, shapesOut, vectorsOut) {
|
|
2417
|
+
for (const node of children) {
|
|
2418
|
+
if (node.type !== "element") continue;
|
|
2419
|
+
if (node.tag === "draw:frame") {
|
|
2420
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2421
|
+
const shape = readDrawFrame(node, groupFunctions, pkg);
|
|
2422
|
+
if (shape !== void 0) shapesOut.push({
|
|
2423
|
+
value: shape,
|
|
2424
|
+
zIndex
|
|
2425
|
+
});
|
|
2426
|
+
} else if (node.tag === "draw:g") {
|
|
2427
|
+
const ownFunctions = readOwnTransformFunctions(node);
|
|
2428
|
+
const nested = ownFunctions.length === 0 ? groupFunctions : [...ownFunctions, ...groupFunctions];
|
|
2429
|
+
walkDrawPageContent(node.children, nested, pkg, indexState, shapesOut, vectorsOut);
|
|
2430
|
+
} else if (node.tag === "draw:rect") {
|
|
2431
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2432
|
+
const vector = readDrawRectVector(node, groupFunctions, pkg);
|
|
2433
|
+
if (vector !== void 0) vectorsOut.push({
|
|
2434
|
+
value: vector,
|
|
2435
|
+
zIndex
|
|
2436
|
+
});
|
|
2437
|
+
} else if (node.tag === "draw:ellipse" || node.tag === "draw:circle") {
|
|
2438
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2439
|
+
const vector = readDrawEllipseVector(node, groupFunctions, pkg);
|
|
2440
|
+
if (vector !== void 0) vectorsOut.push({
|
|
2441
|
+
value: vector,
|
|
2442
|
+
zIndex
|
|
2443
|
+
});
|
|
2444
|
+
} else if (node.tag === "draw:line") {
|
|
2445
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2446
|
+
const vector = readDrawLineVector(node, groupFunctions, pkg);
|
|
2447
|
+
if (vector !== void 0) vectorsOut.push({
|
|
2448
|
+
value: vector,
|
|
2449
|
+
zIndex
|
|
2450
|
+
});
|
|
2451
|
+
} else if (node.tag === "draw:path" || node.tag === "draw:polygon" || node.tag === "draw:polyline") {
|
|
2452
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2453
|
+
const vector = readDrawPathVector(node, groupFunctions, pkg);
|
|
2454
|
+
if (vector !== void 0) vectorsOut.push({
|
|
2455
|
+
value: vector,
|
|
2456
|
+
zIndex
|
|
2457
|
+
});
|
|
2458
|
+
} else if (node.tag === "draw:custom-shape") {
|
|
2459
|
+
const zIndex = paintOrderKey(node, indexState);
|
|
2460
|
+
const vector = readCustomShapeVector(node, groupFunctions, pkg);
|
|
2461
|
+
if (vector !== void 0) vectorsOut.push({
|
|
2462
|
+
value: vector,
|
|
2463
|
+
zIndex
|
|
2464
|
+
});
|
|
2465
|
+
else {
|
|
2466
|
+
const shape = readCustomShapeAsTextShape(node, groupFunctions, pkg);
|
|
2467
|
+
if (shape !== void 0) shapesOut.push({
|
|
2468
|
+
value: shape,
|
|
2469
|
+
zIndex
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
1966
2473
|
}
|
|
1967
2474
|
}
|
|
2475
|
+
function readDrawPageContent(children, pkg) {
|
|
2476
|
+
const shapesOut = [];
|
|
2477
|
+
const vectorsOut = [];
|
|
2478
|
+
walkDrawPageContent(children, [], pkg, { next: 0 }, shapesOut, vectorsOut);
|
|
2479
|
+
return {
|
|
2480
|
+
shapes: byPaintOrder(shapesOut),
|
|
2481
|
+
vectors: byPaintOrder(vectorsOut)
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
//#endregion
|
|
2485
|
+
//#region src/typed/odp/read.ts
|
|
2486
|
+
const CONTENT_PART$3 = "content.xml";
|
|
1968
2487
|
function readSlideSize(page, pkg) {
|
|
1969
|
-
|
|
1970
|
-
const pageLayout = findPageLayoutElement$1(pkg, masterPage === void 0 ? void 0 : attrValue(masterPage, "style:page-layout-name"));
|
|
1971
|
-
const properties = pageLayout === void 0 ? void 0 : childrenWithTag(pageLayout, "style:page-layout-properties")[0];
|
|
1972
|
-
return (properties === void 0 ? void 0 : parsePageSize(properties)) ?? SLIDE_SIZE_WIDESCREEN;
|
|
2488
|
+
return resolveDrawPageSize(page, pkg) ?? SLIDE_SIZE_WIDESCREEN;
|
|
1973
2489
|
}
|
|
1974
2490
|
function readSlideNotes(page) {
|
|
1975
2491
|
const notes = childrenWithTag(page, "presentation:notes")[0];
|
|
@@ -1986,7 +2502,7 @@ function readSlide(page, pkg) {
|
|
|
1986
2502
|
};
|
|
1987
2503
|
}
|
|
1988
2504
|
function readOdp(pkg) {
|
|
1989
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2505
|
+
const contentPart = pkg.parts[CONTENT_PART$3];
|
|
1990
2506
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
1991
2507
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
1992
2508
|
const presentation = body === void 0 ? void 0 : findChildElement(body.children, "office:presentation");
|
|
@@ -1998,9 +2514,9 @@ function readOdp(pkg) {
|
|
|
1998
2514
|
}
|
|
1999
2515
|
//#endregion
|
|
2000
2516
|
//#region src/typed/odt/read.ts
|
|
2001
|
-
const CONTENT_PART = "content.xml";
|
|
2517
|
+
const CONTENT_PART$2 = "content.xml";
|
|
2002
2518
|
const STYLES_PART = "styles.xml";
|
|
2003
|
-
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART, STYLES_PART];
|
|
2519
|
+
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART$2, STYLES_PART];
|
|
2004
2520
|
function readOutlineLevel(headingElement) {
|
|
2005
2521
|
const raw = attrValue(headingElement, "text:outline-level");
|
|
2006
2522
|
if (raw === void 0) return 1;
|
|
@@ -2043,18 +2559,18 @@ function readBlocks(nodes, pkg, listIdState) {
|
|
|
2043
2559
|
}
|
|
2044
2560
|
return blocks;
|
|
2045
2561
|
}
|
|
2046
|
-
function parseKnownOdfLength(value) {
|
|
2562
|
+
function parseKnownOdfLength$1(value) {
|
|
2047
2563
|
const parsed = parseOdfLength(value);
|
|
2048
2564
|
if (parsed === void 0) throw new Error(`readOdt: internal error -- "${value}" is not a valid ODF length literal`);
|
|
2049
2565
|
return parsed;
|
|
2050
2566
|
}
|
|
2051
|
-
const DEFAULT_PAGE_SIZE = PAGE_SIZE_A4;
|
|
2052
|
-
const DEFAULT_MARGIN_PT = parseKnownOdfLength("2cm");
|
|
2053
|
-
const DEFAULT_MARGINS = {
|
|
2054
|
-
topPt: DEFAULT_MARGIN_PT,
|
|
2055
|
-
rightPt: DEFAULT_MARGIN_PT,
|
|
2056
|
-
bottomPt: DEFAULT_MARGIN_PT,
|
|
2057
|
-
leftPt: DEFAULT_MARGIN_PT
|
|
2567
|
+
const DEFAULT_PAGE_SIZE$2 = PAGE_SIZE_A4;
|
|
2568
|
+
const DEFAULT_MARGIN_PT$1 = parseKnownOdfLength$1("2cm");
|
|
2569
|
+
const DEFAULT_MARGINS$1 = {
|
|
2570
|
+
topPt: DEFAULT_MARGIN_PT$1,
|
|
2571
|
+
rightPt: DEFAULT_MARGIN_PT$1,
|
|
2572
|
+
bottomPt: DEFAULT_MARGIN_PT$1,
|
|
2573
|
+
leftPt: DEFAULT_MARGIN_PT$1
|
|
2058
2574
|
};
|
|
2059
2575
|
function findPageLayoutElement(pkg, pageLayoutName) {
|
|
2060
2576
|
if (pageLayoutName === void 0) return;
|
|
@@ -2078,17 +2594,17 @@ function readFirstMasterPageGeometry(pkg) {
|
|
|
2078
2594
|
const pageSize = properties === void 0 ? void 0 : parsePageSize(properties);
|
|
2079
2595
|
const margins = properties === void 0 ? void 0 : parseMargins(properties);
|
|
2080
2596
|
return {
|
|
2081
|
-
pageSize: pageSize ?? DEFAULT_PAGE_SIZE,
|
|
2082
|
-
margins: margins ?? DEFAULT_MARGINS
|
|
2597
|
+
pageSize: pageSize ?? DEFAULT_PAGE_SIZE$2,
|
|
2598
|
+
margins: margins ?? DEFAULT_MARGINS$1
|
|
2083
2599
|
};
|
|
2084
2600
|
}
|
|
2085
2601
|
function readOdt(pkg) {
|
|
2086
|
-
const contentPart = pkg.parts[CONTENT_PART];
|
|
2087
|
-
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART} part`);
|
|
2602
|
+
const contentPart = pkg.parts[CONTENT_PART$2];
|
|
2603
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART$2} part`);
|
|
2088
2604
|
const contentRoot = rootElement(contentPart.nodes);
|
|
2089
2605
|
const body = contentRoot === void 0 ? void 0 : findChildElement(contentRoot.children, "office:body");
|
|
2090
2606
|
const textElement = body === void 0 ? void 0 : findChildElement(body.children, "office:text");
|
|
2091
|
-
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART} has no office:body/office:text element`);
|
|
2607
|
+
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART$2} has no office:body/office:text element`);
|
|
2092
2608
|
const metadata = readOdfMetadata(pkg);
|
|
2093
2609
|
const { pageSize, margins } = readFirstMasterPageGeometry(pkg);
|
|
2094
2610
|
return {
|
|
@@ -2101,4 +2617,335 @@ function readOdt(pkg) {
|
|
|
2101
2617
|
};
|
|
2102
2618
|
}
|
|
2103
2619
|
//#endregion
|
|
2104
|
-
|
|
2620
|
+
//#region src/typed/odg/read.ts
|
|
2621
|
+
const CONTENT_PART$1 = "content.xml";
|
|
2622
|
+
const DEFAULT_PAGE_SIZE$1 = PAGE_SIZE_A4;
|
|
2623
|
+
function readPage(page, pkg) {
|
|
2624
|
+
const size = resolveDrawPageSize(page, pkg) ?? DEFAULT_PAGE_SIZE$1;
|
|
2625
|
+
const { shapes, vectors } = readDrawPageContent(page.children, pkg);
|
|
2626
|
+
return {
|
|
2627
|
+
size,
|
|
2628
|
+
shapes,
|
|
2629
|
+
vectors
|
|
2630
|
+
};
|
|
2631
|
+
}
|
|
2632
|
+
function readOdg(pkg) {
|
|
2633
|
+
const contentPart = pkg.parts[CONTENT_PART$1];
|
|
2634
|
+
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2635
|
+
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2636
|
+
const drawing = body === void 0 ? void 0 : findChildElement(body.children, "office:drawing");
|
|
2637
|
+
const pages = drawing === void 0 ? [] : childrenWithTag(drawing, "draw:page");
|
|
2638
|
+
return {
|
|
2639
|
+
metadata: readOdfMetadata(pkg),
|
|
2640
|
+
pages: pages.map((page) => readPage(page, pkg))
|
|
2641
|
+
};
|
|
2642
|
+
}
|
|
2643
|
+
//#endregion
|
|
2644
|
+
//#region src/typed/ods/read.ts
|
|
2645
|
+
const CONTENT_PART = "content.xml";
|
|
2646
|
+
function parseKnownOdfLength(value) {
|
|
2647
|
+
const parsed = parseOdfLength(value);
|
|
2648
|
+
if (parsed === void 0) throw new Error(`readOds: internal error -- "${value}" is not a valid ODF length literal`);
|
|
2649
|
+
return parsed;
|
|
2650
|
+
}
|
|
2651
|
+
const DEFAULT_PAGE_SIZE = PAGE_SIZE_A4;
|
|
2652
|
+
const DEFAULT_MARGIN_PT = parseKnownOdfLength("2cm");
|
|
2653
|
+
const DEFAULT_MARGINS = {
|
|
2654
|
+
topPt: DEFAULT_MARGIN_PT,
|
|
2655
|
+
rightPt: DEFAULT_MARGIN_PT,
|
|
2656
|
+
bottomPt: DEFAULT_MARGIN_PT,
|
|
2657
|
+
leftPt: DEFAULT_MARGIN_PT
|
|
2658
|
+
};
|
|
2659
|
+
function readRepeatCount(element, attrName) {
|
|
2660
|
+
const raw = attrValue(element, attrName);
|
|
2661
|
+
if (raw === void 0) return 1;
|
|
2662
|
+
const parsed = Number.parseInt(raw, 10);
|
|
2663
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : 1;
|
|
2664
|
+
}
|
|
2665
|
+
function isHidden(element) {
|
|
2666
|
+
return attrValue(element, "table:visibility") === "collapse";
|
|
2667
|
+
}
|
|
2668
|
+
function readColumnLayout(columnElement, pkg) {
|
|
2669
|
+
const styleName = attrValue(columnElement, "table:style-name");
|
|
2670
|
+
const styleElement = styleName === void 0 ? void 0 : findStyleElement(styleName, "table-column", pkg);
|
|
2671
|
+
const properties = styleElement === void 0 ? void 0 : childrenWithTag(styleElement, "style:table-column-properties")[0];
|
|
2672
|
+
const widthValue = properties === void 0 ? void 0 : attrValue(properties, "style:column-width");
|
|
2673
|
+
return {
|
|
2674
|
+
widthPt: widthValue === void 0 ? 0 : parseOdfLength(widthValue) ?? 0,
|
|
2675
|
+
manualBreak: (properties === void 0 ? void 0 : attrValue(properties, "fo:break-before")) === "page"
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
function readRowLayout(rowElement, pkg) {
|
|
2679
|
+
const styleName = attrValue(rowElement, "table:style-name");
|
|
2680
|
+
const styleElement = styleName === void 0 ? void 0 : findStyleElement(styleName, "table-row", pkg);
|
|
2681
|
+
const properties = styleElement === void 0 ? void 0 : childrenWithTag(styleElement, "style:table-row-properties")[0];
|
|
2682
|
+
const heightValue = properties === void 0 ? void 0 : attrValue(properties, "style:row-height");
|
|
2683
|
+
return {
|
|
2684
|
+
heightPt: heightValue === void 0 ? 0 : parseOdfLength(heightValue) ?? 0,
|
|
2685
|
+
manualBreak: (properties === void 0 ? void 0 : attrValue(properties, "fo:break-before")) === "page"
|
|
2686
|
+
};
|
|
2687
|
+
}
|
|
2688
|
+
function readCellText(cellElement, pkg) {
|
|
2689
|
+
const paragraphs = childrenWithTag(cellElement, "text:p");
|
|
2690
|
+
const runs = [];
|
|
2691
|
+
paragraphs.forEach((paragraph, index) => {
|
|
2692
|
+
if (index > 0) runs.push({ text: "\n" });
|
|
2693
|
+
runs.push(...readOdfParagraph(paragraph, pkg).runs);
|
|
2694
|
+
});
|
|
2695
|
+
return {
|
|
2696
|
+
runs,
|
|
2697
|
+
displayText: runs.map((run) => run.text).join("")
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
function readCellValue(cellElement, displayText) {
|
|
2701
|
+
const valueType = attrValue(cellElement, "office:value-type");
|
|
2702
|
+
const stringFallback = {
|
|
2703
|
+
kind: "string",
|
|
2704
|
+
value: displayText
|
|
2705
|
+
};
|
|
2706
|
+
switch (valueType) {
|
|
2707
|
+
case "float": {
|
|
2708
|
+
const value = parseRequiredNumber(attrValue(cellElement, "office:value"));
|
|
2709
|
+
return value === void 0 ? stringFallback : {
|
|
2710
|
+
kind: "number",
|
|
2711
|
+
value
|
|
2712
|
+
};
|
|
2713
|
+
}
|
|
2714
|
+
case "percentage": {
|
|
2715
|
+
const value = parseRequiredNumber(attrValue(cellElement, "office:value"));
|
|
2716
|
+
return value === void 0 ? stringFallback : {
|
|
2717
|
+
kind: "percentage",
|
|
2718
|
+
value
|
|
2719
|
+
};
|
|
2720
|
+
}
|
|
2721
|
+
case "currency": {
|
|
2722
|
+
const value = parseRequiredNumber(attrValue(cellElement, "office:value"));
|
|
2723
|
+
if (value === void 0) return stringFallback;
|
|
2724
|
+
const currency = attrValue(cellElement, "office:currency");
|
|
2725
|
+
return currency === void 0 ? {
|
|
2726
|
+
kind: "currency",
|
|
2727
|
+
value
|
|
2728
|
+
} : {
|
|
2729
|
+
kind: "currency",
|
|
2730
|
+
value,
|
|
2731
|
+
currency
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2734
|
+
case "boolean": {
|
|
2735
|
+
const raw = attrValue(cellElement, "office:boolean-value");
|
|
2736
|
+
return raw === void 0 ? stringFallback : {
|
|
2737
|
+
kind: "boolean",
|
|
2738
|
+
value: raw === "true"
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
case "date": return {
|
|
2742
|
+
kind: "date",
|
|
2743
|
+
value: attrValue(cellElement, "office:date-value") ?? displayText
|
|
2744
|
+
};
|
|
2745
|
+
case "time": return {
|
|
2746
|
+
kind: "time",
|
|
2747
|
+
value: attrValue(cellElement, "office:time-value") ?? displayText
|
|
2748
|
+
};
|
|
2749
|
+
case "string": return {
|
|
2750
|
+
kind: "string",
|
|
2751
|
+
value: attrValue(cellElement, "office:string-value") ?? displayText
|
|
2752
|
+
};
|
|
2753
|
+
default: return { kind: "empty" };
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
function parseRequiredNumber(raw) {
|
|
2757
|
+
if (raw === void 0) return;
|
|
2758
|
+
const value = Number(raw);
|
|
2759
|
+
return Number.isNaN(value) ? void 0 : value;
|
|
2760
|
+
}
|
|
2761
|
+
function parsePrintRanges(value) {
|
|
2762
|
+
const first = value.split(" ").find((part) => part.length > 0);
|
|
2763
|
+
if (first === void 0) return;
|
|
2764
|
+
const separatorIndex = first.indexOf(":");
|
|
2765
|
+
if (separatorIndex === -1) return;
|
|
2766
|
+
const start = parseA1WithOptionalSheetPrefix(first.slice(0, separatorIndex));
|
|
2767
|
+
const end = parseA1WithOptionalSheetPrefix(first.slice(separatorIndex + 1));
|
|
2768
|
+
if (start === void 0 || end === void 0) return;
|
|
2769
|
+
return {
|
|
2770
|
+
startRow: start.row,
|
|
2771
|
+
startColumn: start.column,
|
|
2772
|
+
endRow: end.row,
|
|
2773
|
+
endColumn: end.column
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
function parseA1WithOptionalSheetPrefix(cellPart) {
|
|
2777
|
+
const dotIndex = cellPart.lastIndexOf(".");
|
|
2778
|
+
return parseCellReference(dotIndex === -1 ? cellPart : cellPart.slice(dotIndex + 1));
|
|
2779
|
+
}
|
|
2780
|
+
function parseScalePercentage(value) {
|
|
2781
|
+
const match = /^(\d+(?:\.\d+)?)%$/.exec(value);
|
|
2782
|
+
if (match === null) return;
|
|
2783
|
+
const numeric = match[1];
|
|
2784
|
+
return numeric === void 0 ? void 0 : Number(numeric);
|
|
2785
|
+
}
|
|
2786
|
+
function parseNonNegativeInteger(value) {
|
|
2787
|
+
if (value === void 0) return;
|
|
2788
|
+
const parsed = Number.parseInt(value, 10);
|
|
2789
|
+
return Number.isInteger(parsed) && parsed >= 0 ? parsed : void 0;
|
|
2790
|
+
}
|
|
2791
|
+
function readTable(tableElement, pkg) {
|
|
2792
|
+
const columns = [];
|
|
2793
|
+
const rows = [];
|
|
2794
|
+
const cells = [];
|
|
2795
|
+
const manualBreakRows = [];
|
|
2796
|
+
const manualBreakColumns = [];
|
|
2797
|
+
let repeatColumns;
|
|
2798
|
+
let repeatRows;
|
|
2799
|
+
let columnCursor = 0;
|
|
2800
|
+
const cursor = new TableCursor();
|
|
2801
|
+
function processColumn(columnElement) {
|
|
2802
|
+
const startIndex = columnCursor;
|
|
2803
|
+
const { widthPt, manualBreak } = readColumnLayout(columnElement, pkg);
|
|
2804
|
+
columns.push({
|
|
2805
|
+
index: startIndex,
|
|
2806
|
+
widthPt,
|
|
2807
|
+
hidden: isHidden(columnElement) ? true : void 0
|
|
2808
|
+
});
|
|
2809
|
+
if (manualBreak) manualBreakColumns.push(startIndex);
|
|
2810
|
+
columnCursor += readRepeatCount(columnElement, "table:number-columns-repeated");
|
|
2811
|
+
}
|
|
2812
|
+
function processRowCells(rowElement) {
|
|
2813
|
+
for (const child of rowElement.children) {
|
|
2814
|
+
if (child.type !== "element") continue;
|
|
2815
|
+
if (child.tag === "table:covered-table-cell") cursor.nextCell(readRepeatCount(child, "table:number-columns-repeated"));
|
|
2816
|
+
else if (child.tag === "table:table-cell") {
|
|
2817
|
+
const columnIndex = cursor.columnIndex;
|
|
2818
|
+
const rowIndex = cursor.rowIndex;
|
|
2819
|
+
cursor.nextCell(readRepeatCount(child, "table:number-columns-repeated"));
|
|
2820
|
+
const formula = attrValue(child, "table:formula");
|
|
2821
|
+
const { runs, displayText } = readCellText(child, pkg);
|
|
2822
|
+
if (!(attrValue(child, "office:value-type") !== void 0) && formula === void 0 && displayText.length === 0) continue;
|
|
2823
|
+
const value = readCellValue(child, displayText);
|
|
2824
|
+
const colSpan = parseNonNegativeInteger(attrValue(child, "table:number-columns-spanned"));
|
|
2825
|
+
const rowSpan = parseNonNegativeInteger(attrValue(child, "table:number-rows-spanned"));
|
|
2826
|
+
const cell = {
|
|
2827
|
+
row: rowIndex,
|
|
2828
|
+
column: columnIndex,
|
|
2829
|
+
value,
|
|
2830
|
+
displayText
|
|
2831
|
+
};
|
|
2832
|
+
if (formula !== void 0) cell.formula = formula;
|
|
2833
|
+
if (runs.length > 0) cell.runs = runs;
|
|
2834
|
+
if (colSpan !== void 0) cell.colSpan = colSpan;
|
|
2835
|
+
if (rowSpan !== void 0) cell.rowSpan = rowSpan;
|
|
2836
|
+
cells.push(cell);
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
function processRow(rowElement) {
|
|
2841
|
+
const startIndex = cursor.rowIndex;
|
|
2842
|
+
processRowCells(rowElement);
|
|
2843
|
+
const { heightPt, manualBreak } = readRowLayout(rowElement, pkg);
|
|
2844
|
+
rows.push({
|
|
2845
|
+
index: startIndex,
|
|
2846
|
+
heightPt,
|
|
2847
|
+
hidden: isHidden(rowElement) ? true : void 0
|
|
2848
|
+
});
|
|
2849
|
+
if (manualBreak) manualBreakRows.push(startIndex);
|
|
2850
|
+
cursor.nextRow(readRepeatCount(rowElement, "table:number-rows-repeated"));
|
|
2851
|
+
}
|
|
2852
|
+
for (const child of tableElement.children) {
|
|
2853
|
+
if (child.type !== "element") continue;
|
|
2854
|
+
if (child.tag === "table:table-column") processColumn(child);
|
|
2855
|
+
else if (child.tag === "table:table-header-columns") {
|
|
2856
|
+
const startIndex = columnCursor;
|
|
2857
|
+
for (const headerChild of child.children) if (headerChild.type === "element" && headerChild.tag === "table:table-column") processColumn(headerChild);
|
|
2858
|
+
if (columnCursor > startIndex) repeatColumns = {
|
|
2859
|
+
start: startIndex,
|
|
2860
|
+
end: columnCursor - 1
|
|
2861
|
+
};
|
|
2862
|
+
} else if (child.tag === "table:table-row") processRow(child);
|
|
2863
|
+
else if (child.tag === "table:table-header-rows") {
|
|
2864
|
+
const startIndex = cursor.rowIndex;
|
|
2865
|
+
for (const headerChild of child.children) if (headerChild.type === "element" && headerChild.tag === "table:table-row") processRow(headerChild);
|
|
2866
|
+
if (cursor.rowIndex > startIndex) repeatRows = {
|
|
2867
|
+
start: startIndex,
|
|
2868
|
+
end: cursor.rowIndex - 1
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
return {
|
|
2873
|
+
columns,
|
|
2874
|
+
rows,
|
|
2875
|
+
cells,
|
|
2876
|
+
repeatColumns,
|
|
2877
|
+
repeatRows,
|
|
2878
|
+
manualBreakRows,
|
|
2879
|
+
manualBreakColumns
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2882
|
+
function readPrintSettings(tableElement, pkg, repeatColumns, repeatRows, manualBreakRows, manualBreakColumns) {
|
|
2883
|
+
const tableStyleName = attrValue(tableElement, "table:style-name");
|
|
2884
|
+
const tableStyleElement = tableStyleName === void 0 ? void 0 : findStyleElement(tableStyleName, "table", pkg);
|
|
2885
|
+
const layoutProperties = resolvePageLayoutProperties(pkg, tableStyleElement === void 0 ? void 0 : attrValue(tableStyleElement, "style:master-page-name"));
|
|
2886
|
+
const pageSize = layoutProperties === void 0 ? void 0 : parsePageSize(layoutProperties);
|
|
2887
|
+
const margins = layoutProperties === void 0 ? void 0 : parseMargins(layoutProperties);
|
|
2888
|
+
const printTokens = new Set((layoutProperties === void 0 ? void 0 : attrValue(layoutProperties, "style:print"))?.split(" ").filter((token) => token.length > 0));
|
|
2889
|
+
const pageOrder = (layoutProperties === void 0 ? void 0 : attrValue(layoutProperties, "style:print-page-order")) === "ltr" ? "overThenDown" : "downThenOver";
|
|
2890
|
+
const scaleToRaw = layoutProperties === void 0 ? void 0 : attrValue(layoutProperties, "style:scale-to");
|
|
2891
|
+
const scale = scaleToRaw === void 0 ? void 0 : parseScalePercentage(scaleToRaw);
|
|
2892
|
+
const scaleToXRaw = layoutProperties === void 0 ? void 0 : attrValue(layoutProperties, "style:scale-to-X");
|
|
2893
|
+
const scaleToYRaw = layoutProperties === void 0 ? void 0 : attrValue(layoutProperties, "style:scale-to-Y");
|
|
2894
|
+
const fitWidth = parseNonNegativeInteger(scaleToXRaw);
|
|
2895
|
+
const fitHeight = parseNonNegativeInteger(scaleToYRaw);
|
|
2896
|
+
const fitToPages = fitWidth === void 0 || fitHeight === void 0 ? void 0 : {
|
|
2897
|
+
width: fitWidth,
|
|
2898
|
+
height: fitHeight
|
|
2899
|
+
};
|
|
2900
|
+
const printRangesRaw = attrValue(tableElement, "table:print-ranges");
|
|
2901
|
+
const printRange = printRangesRaw === void 0 ? void 0 : parsePrintRanges(printRangesRaw);
|
|
2902
|
+
const manualBreaks = manualBreakRows.length > 0 || manualBreakColumns.length > 0 ? {
|
|
2903
|
+
rows: manualBreakRows,
|
|
2904
|
+
columns: manualBreakColumns
|
|
2905
|
+
} : void 0;
|
|
2906
|
+
const settings = {
|
|
2907
|
+
pageSize: pageSize ?? DEFAULT_PAGE_SIZE,
|
|
2908
|
+
margins: margins ?? DEFAULT_MARGINS,
|
|
2909
|
+
gridlines: printTokens.has("grid"),
|
|
2910
|
+
headers: printTokens.has("headers"),
|
|
2911
|
+
pageOrder
|
|
2912
|
+
};
|
|
2913
|
+
if (printRange !== void 0) settings.printRange = printRange;
|
|
2914
|
+
if (scale !== void 0) settings.scale = scale;
|
|
2915
|
+
if (fitToPages !== void 0) settings.fitToPages = fitToPages;
|
|
2916
|
+
if (repeatRows !== void 0) settings.repeatRows = repeatRows;
|
|
2917
|
+
if (repeatColumns !== void 0) settings.repeatColumns = repeatColumns;
|
|
2918
|
+
if (manualBreaks !== void 0) settings.manualBreaks = manualBreaks;
|
|
2919
|
+
return settings;
|
|
2920
|
+
}
|
|
2921
|
+
function readSheet(tableElement, pkg) {
|
|
2922
|
+
const name = attrValue(tableElement, "table:name");
|
|
2923
|
+
if (name === void 0) return;
|
|
2924
|
+
const { columns, rows, cells, repeatColumns, repeatRows, manualBreakRows, manualBreakColumns } = readTable(tableElement, pkg);
|
|
2925
|
+
return {
|
|
2926
|
+
name,
|
|
2927
|
+
cells,
|
|
2928
|
+
columns,
|
|
2929
|
+
rows,
|
|
2930
|
+
images: [],
|
|
2931
|
+
printSettings: readPrintSettings(tableElement, pkg, repeatColumns, repeatRows, manualBreakRows, manualBreakColumns)
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
function readOds(pkg) {
|
|
2935
|
+
const contentPart = pkg.parts[CONTENT_PART];
|
|
2936
|
+
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2937
|
+
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2938
|
+
const spreadsheet = body === void 0 ? void 0 : findChildElement(body.children, "office:spreadsheet");
|
|
2939
|
+
const tables = spreadsheet === void 0 ? [] : childrenWithTag(spreadsheet, "table:table");
|
|
2940
|
+
const sheets = [];
|
|
2941
|
+
for (const table of tables) {
|
|
2942
|
+
const sheet = readSheet(table, pkg);
|
|
2943
|
+
if (sheet !== void 0) sheets.push(sheet);
|
|
2944
|
+
}
|
|
2945
|
+
return {
|
|
2946
|
+
metadata: readOdfMetadata(pkg),
|
|
2947
|
+
sheets
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
//#endregion
|
|
2951
|
+
export { AlignmentSchema, AttributeSchema, BinaryPartSchema, MANIFEST_PART, META_PART, MIMETYPE_PART, ManifestEntrySchema, ManifestProblemSchema, ManifestSchema, ODF_MEDIA_TYPES, ODF_NAMESPACES, PackageSchema, PartSchema, STYLE_FAMILIES, StylePropertiesSchema, StyleRegistry, TableCursor, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, applyOdfTransform, attrValue, base64ToBytes, buildManifest, buildOdfSubpaths, buildStylePropertyElements, buildXml, bytesToBase64, canonicalPropertiesString, cellReference, childrenWithTag, columnIndexToLetters, columnLettersToIndex, composeOdfGroupTransform, decodeOdfText, decodePackage, decodeXmlText, el, elementsWithTag, encodePackage, encodeXmlText, ensureSpan, findChildElement, findStyleElement, formatOdfColor, formatOdfLength, formatPercentageMultiplier, formatPt, getOdfSpaceCount, isStyleFamily, isXmlNode, measureOdfNodeLength, mediaTypeForExtension, netRotationDeg, packageCodec, paragraphPropertiesToAttributes, parseBox, parseCellReference, parseLength, parseLinePoints, parseMargins, parseOdfColor, parseOdfLength, parseOdfPathData, parseOdfPointsList, parseOdfTransform, parseOdfViewBox, parsePackage, parsePageSize, parseParagraphProperties, parseStyleElementProperties, parseTextProperties, parseXml, rawSubpathFromPoints, readDrawFrame, readDrawPageContent, readManifest, readMimetype, readOdfMetadata, readOdfParagraph, readOdfTable, readOdg, readOdp, readOds, readOdt, resolveDrawPageSize, resolveOdfShapeGeometry, resolvePageLayoutProperties, resolveStyle, resolveStyleElementChain, rootElement, scaleOdfRawPoint, serializePackage, setDocumentMediaType, sniffImageFormat, sumOdfNodeLength, syncManifest, textPropertiesToAttributes, txt, unzipPackage, validateManifest, walkDrawShapes, writeManifest, writeMimetype, xmlCodec, xmlnsAttributes, zipPackage };
|