js.documents 2.0.0 → 2.2.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.
Files changed (91) hide show
  1. package/README.md +49 -29
  2. package/dist/codecs/registry.cjs +14 -0
  3. package/dist/codecs/registry.js +14 -0
  4. package/dist/convert/capability.cjs +10 -0
  5. package/dist/convert/capability.js +10 -0
  6. package/dist/convert/codec.cjs +30 -0
  7. package/dist/convert/codec.d.cts +7 -1
  8. package/dist/convert/codec.d.ts +7 -1
  9. package/dist/convert/codec.js +27 -3
  10. package/dist/convert/composition.cjs +49 -7
  11. package/dist/convert/composition.d.cts +12 -5
  12. package/dist/convert/composition.d.ts +12 -5
  13. package/dist/convert/composition.js +49 -7
  14. package/dist/convert/convert.cjs +48 -0
  15. package/dist/convert/convert.d.cts +30 -1
  16. package/dist/convert/convert.d.ts +30 -1
  17. package/dist/convert/convert.js +37 -1
  18. package/dist/convert/local.cjs +4 -1
  19. package/dist/convert/local.js +4 -1
  20. package/dist/convert/port.cjs +2 -0
  21. package/dist/convert/port.d.cts +5 -0
  22. package/dist/convert/port.d.ts +5 -0
  23. package/dist/convert/port.js +2 -0
  24. package/dist/csv/read.cjs +85 -0
  25. package/dist/csv/read.d.cts +10 -0
  26. package/dist/csv/read.d.ts +10 -0
  27. package/dist/csv/read.js +84 -0
  28. package/dist/csv/records.cjs +85 -0
  29. package/dist/csv/records.d.cts +10 -0
  30. package/dist/csv/records.d.ts +10 -0
  31. package/dist/csv/records.js +80 -0
  32. package/dist/csv/text.cjs +22 -0
  33. package/dist/csv/text.d.cts +8 -0
  34. package/dist/csv/text.d.ts +8 -0
  35. package/dist/csv/text.js +19 -0
  36. package/dist/csv/write.cjs +75 -0
  37. package/dist/csv/write.d.cts +22 -0
  38. package/dist/csv/write.d.ts +22 -0
  39. package/dist/csv/write.js +71 -0
  40. package/dist/edit/odg/scaffold.js +8 -8
  41. package/dist/edit/odp/scaffold.js +8 -8
  42. package/dist/edit/ods/scaffold.js +8 -8
  43. package/dist/edit/odt/scaffold.js +8 -8
  44. package/dist/index.cjs +48 -1
  45. package/dist/index.d.cts +13 -5
  46. package/dist/index.d.ts +13 -5
  47. package/dist/index.js +13 -5
  48. package/dist/layout/reconstruct.cjs +1 -1
  49. package/dist/layout/reconstruct.js +1 -1
  50. package/dist/metadata/write.cjs +2 -0
  51. package/dist/metadata/write.js +2 -0
  52. package/dist/model/bytes.cjs +7 -0
  53. package/dist/model/bytes.d.cts +3 -1
  54. package/dist/model/bytes.d.ts +3 -1
  55. package/dist/model/bytes.js +6 -1
  56. package/dist/odb/csv.cjs +3 -6
  57. package/dist/odb/csv.js +3 -6
  58. package/dist/svg/diagnostics.cjs +19 -0
  59. package/dist/svg/diagnostics.d.cts +10 -0
  60. package/dist/svg/diagnostics.d.ts +10 -0
  61. package/dist/svg/diagnostics.js +18 -0
  62. package/dist/svg/paint.cjs +817 -0
  63. package/dist/svg/paint.d.cts +19 -0
  64. package/dist/svg/paint.d.ts +19 -0
  65. package/dist/svg/paint.js +814 -0
  66. package/dist/svg/path.cjs +337 -0
  67. package/dist/svg/path.d.cts +22 -0
  68. package/dist/svg/path.d.ts +22 -0
  69. package/dist/svg/path.js +336 -0
  70. package/dist/svg/read.cjs +677 -0
  71. package/dist/svg/read.d.cts +12 -0
  72. package/dist/svg/read.d.ts +12 -0
  73. package/dist/svg/read.js +675 -0
  74. package/dist/svg/text.cjs +22 -0
  75. package/dist/svg/text.d.cts +8 -0
  76. package/dist/svg/text.d.ts +8 -0
  77. package/dist/svg/text.js +19 -0
  78. package/dist/svg/transform.cjs +206 -0
  79. package/dist/svg/transform.d.cts +23 -0
  80. package/dist/svg/transform.d.ts +23 -0
  81. package/dist/svg/transform.js +197 -0
  82. package/dist/svg/units.cjs +47 -0
  83. package/dist/svg/units.d.cts +12 -0
  84. package/dist/svg/units.d.ts +12 -0
  85. package/dist/svg/units.js +44 -0
  86. package/dist/svg/write.cjs +127 -0
  87. package/dist/svg/write.d.cts +23 -0
  88. package/dist/svg/write.d.ts +23 -0
  89. package/dist/svg/write.js +123 -0
  90. package/dist/xml/odf-text.js +2 -2
  91. package/package.json +1 -1
@@ -0,0 +1,85 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_layout_cell_typing = require("../layout/cell-typing.cjs");
3
+ const require_csv_records = require("./records.cjs");
4
+ let document_schema_js = require("document-schema.js");
5
+ //#region src/csv/read.ts
6
+ const HEADER_ROW_INDEX = 0;
7
+ const SHEET_NAME = "Sheet1";
8
+ const COLUMN_WIDTH_PT = 64;
9
+ const ROW_HEIGHT_PT = 15;
10
+ const MARGIN_PT = 56.69291338582677;
11
+ const DEFAULT_PRINT_SETTINGS = {
12
+ pageSize: document_schema_js.PAGE_SIZE_A4,
13
+ margins: {
14
+ topPt: MARGIN_PT,
15
+ rightPt: MARGIN_PT,
16
+ bottomPt: MARGIN_PT,
17
+ leftPt: MARGIN_PT
18
+ },
19
+ gridlines: true,
20
+ headers: true,
21
+ pageOrder: "downThenOver"
22
+ };
23
+ function dataCell(rowIndex, columnIndex, field, onCellTypeInference) {
24
+ const inference = field === "" ? void 0 : require_layout_cell_typing.inferCellValue(field);
25
+ if (inference !== void 0) onCellTypeInference?.({
26
+ sheetIndex: 0,
27
+ row: rowIndex,
28
+ column: columnIndex,
29
+ displayText: field,
30
+ ...inference
31
+ });
32
+ return {
33
+ row: rowIndex,
34
+ column: columnIndex,
35
+ value: field === "" ? { kind: "empty" } : inference?.outcome === "retyped" ? inference.value : {
36
+ kind: "string",
37
+ value: field
38
+ },
39
+ displayText: field
40
+ };
41
+ }
42
+ function readCsvContent(text, options) {
43
+ const records = require_csv_records.parseCsvRecords(text, options?.delimiter ?? ",");
44
+ const onCellTypeInference = options?.onCellTypeInference;
45
+ const columnCount = records.reduce((max, record) => Math.max(max, record.length), 0);
46
+ const cells = [];
47
+ records.forEach((record, rowIndex) => {
48
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
49
+ const field = record[columnIndex] ?? "";
50
+ if (rowIndex === HEADER_ROW_INDEX) cells.push({
51
+ row: rowIndex,
52
+ column: columnIndex,
53
+ value: {
54
+ kind: "string",
55
+ value: field
56
+ },
57
+ displayText: field
58
+ });
59
+ else cells.push(dataCell(rowIndex, columnIndex, field, onCellTypeInference));
60
+ }
61
+ });
62
+ const columns = Array.from({ length: columnCount }, (_unused, index) => ({
63
+ index,
64
+ widthPt: COLUMN_WIDTH_PT
65
+ }));
66
+ const rows = Array.from({ length: records.length }, (_unused, index) => ({
67
+ index,
68
+ heightPt: ROW_HEIGHT_PT
69
+ }));
70
+ return {
71
+ kind: "spreadsheet",
72
+ formatVersion: document_schema_js.CONTENT_FORMAT_VERSION,
73
+ metadata: {},
74
+ sheets: [{
75
+ name: SHEET_NAME,
76
+ cells,
77
+ columns,
78
+ rows,
79
+ images: [],
80
+ printSettings: DEFAULT_PRINT_SETTINGS
81
+ }]
82
+ };
83
+ }
84
+ //#endregion
85
+ exports.readCsvContent = readCsvContent;
@@ -0,0 +1,10 @@
1
+ import { CellTypeInferenceSink } from "../layout/cell-typing.cjs";
2
+ import { ContentDocument } from "document-schema.js";
3
+ //#region src/csv/read.d.ts
4
+ interface ReadCsvContentOptions {
5
+ readonly delimiter?: string;
6
+ readonly onCellTypeInference?: CellTypeInferenceSink;
7
+ }
8
+ declare function readCsvContent(text: string, options?: ReadCsvContentOptions): ContentDocument;
9
+ //#endregion
10
+ export { ReadCsvContentOptions, readCsvContent };
@@ -0,0 +1,10 @@
1
+ import { CellTypeInferenceSink } from "../layout/cell-typing.js";
2
+ import { ContentDocument } from "document-schema.js";
3
+ //#region src/csv/read.d.ts
4
+ interface ReadCsvContentOptions {
5
+ readonly delimiter?: string;
6
+ readonly onCellTypeInference?: CellTypeInferenceSink;
7
+ }
8
+ declare function readCsvContent(text: string, options?: ReadCsvContentOptions): ContentDocument;
9
+ //#endregion
10
+ export { ReadCsvContentOptions, readCsvContent };
@@ -0,0 +1,84 @@
1
+ import { inferCellValue } from "../layout/cell-typing.js";
2
+ import { parseCsvRecords } from "./records.js";
3
+ import { CONTENT_FORMAT_VERSION, PAGE_SIZE_A4 } from "document-schema.js";
4
+ //#region src/csv/read.ts
5
+ const HEADER_ROW_INDEX = 0;
6
+ const SHEET_NAME = "Sheet1";
7
+ const COLUMN_WIDTH_PT = 64;
8
+ const ROW_HEIGHT_PT = 15;
9
+ const MARGIN_PT = 56.69291338582677;
10
+ const DEFAULT_PRINT_SETTINGS = {
11
+ pageSize: PAGE_SIZE_A4,
12
+ margins: {
13
+ topPt: MARGIN_PT,
14
+ rightPt: MARGIN_PT,
15
+ bottomPt: MARGIN_PT,
16
+ leftPt: MARGIN_PT
17
+ },
18
+ gridlines: true,
19
+ headers: true,
20
+ pageOrder: "downThenOver"
21
+ };
22
+ function dataCell(rowIndex, columnIndex, field, onCellTypeInference) {
23
+ const inference = field === "" ? void 0 : inferCellValue(field);
24
+ if (inference !== void 0) onCellTypeInference?.({
25
+ sheetIndex: 0,
26
+ row: rowIndex,
27
+ column: columnIndex,
28
+ displayText: field,
29
+ ...inference
30
+ });
31
+ return {
32
+ row: rowIndex,
33
+ column: columnIndex,
34
+ value: field === "" ? { kind: "empty" } : inference?.outcome === "retyped" ? inference.value : {
35
+ kind: "string",
36
+ value: field
37
+ },
38
+ displayText: field
39
+ };
40
+ }
41
+ function readCsvContent(text, options) {
42
+ const records = parseCsvRecords(text, options?.delimiter ?? ",");
43
+ const onCellTypeInference = options?.onCellTypeInference;
44
+ const columnCount = records.reduce((max, record) => Math.max(max, record.length), 0);
45
+ const cells = [];
46
+ records.forEach((record, rowIndex) => {
47
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
48
+ const field = record[columnIndex] ?? "";
49
+ if (rowIndex === HEADER_ROW_INDEX) cells.push({
50
+ row: rowIndex,
51
+ column: columnIndex,
52
+ value: {
53
+ kind: "string",
54
+ value: field
55
+ },
56
+ displayText: field
57
+ });
58
+ else cells.push(dataCell(rowIndex, columnIndex, field, onCellTypeInference));
59
+ }
60
+ });
61
+ const columns = Array.from({ length: columnCount }, (_unused, index) => ({
62
+ index,
63
+ widthPt: COLUMN_WIDTH_PT
64
+ }));
65
+ const rows = Array.from({ length: records.length }, (_unused, index) => ({
66
+ index,
67
+ heightPt: ROW_HEIGHT_PT
68
+ }));
69
+ return {
70
+ kind: "spreadsheet",
71
+ formatVersion: CONTENT_FORMAT_VERSION,
72
+ metadata: {},
73
+ sheets: [{
74
+ name: SHEET_NAME,
75
+ cells,
76
+ columns,
77
+ rows,
78
+ images: [],
79
+ printSettings: DEFAULT_PRINT_SETTINGS
80
+ }]
81
+ };
82
+ }
83
+ //#endregion
84
+ export { readCsvContent };
@@ -0,0 +1,85 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/csv/records.ts
3
+ const DEFAULT_CSV_DELIMITER = ",";
4
+ const TSV_DELIMITER = " ";
5
+ var CsvParseError = class extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "CsvParseError";
9
+ }
10
+ };
11
+ function requireSingleCharacterDelimiter(delimiter) {
12
+ if (delimiter.length !== 1) throw new CsvParseError(`delimiter must be exactly one character, got ${JSON.stringify(delimiter)}`);
13
+ }
14
+ function isBlankRecord(record) {
15
+ return record.length === 1 && record[0] === "";
16
+ }
17
+ function parseCsvRecords(text, delimiter = ",") {
18
+ requireSingleCharacterDelimiter(delimiter);
19
+ const records = [];
20
+ let record = [];
21
+ let field = "";
22
+ let inQuotedField = false;
23
+ let fieldStarted = false;
24
+ const endField = () => {
25
+ record.push(field);
26
+ field = "";
27
+ fieldStarted = false;
28
+ };
29
+ const endRecord = () => {
30
+ endField();
31
+ records.push(record);
32
+ record = [];
33
+ };
34
+ let index = 0;
35
+ while (index < text.length) {
36
+ const ch = text[index];
37
+ if (inQuotedField) {
38
+ if (ch === "\"") {
39
+ if (text[index + 1] === "\"") {
40
+ field += "\"";
41
+ index += 2;
42
+ continue;
43
+ }
44
+ inQuotedField = false;
45
+ index += 1;
46
+ continue;
47
+ }
48
+ field += ch;
49
+ index += 1;
50
+ continue;
51
+ }
52
+ if (ch === "\"" && !fieldStarted) {
53
+ inQuotedField = true;
54
+ fieldStarted = true;
55
+ index += 1;
56
+ continue;
57
+ }
58
+ if (ch === delimiter) {
59
+ endField();
60
+ index += 1;
61
+ continue;
62
+ }
63
+ if (ch === "\r" || ch === "\n") {
64
+ if (ch === "\r" && text[index + 1] === "\n") index += 2;
65
+ else index += 1;
66
+ endRecord();
67
+ continue;
68
+ }
69
+ field += ch;
70
+ fieldStarted = true;
71
+ index += 1;
72
+ }
73
+ if (inQuotedField) throw new CsvParseError(`unterminated quoted field: no closing double quote before end of input (field so far: ${field.slice(0, 40)})`);
74
+ if (fieldStarted || field !== "" || record.length > 0) endRecord();
75
+ return records.filter((candidate) => !isBlankRecord(candidate));
76
+ }
77
+ function quoteCsvField(field, delimiter = ",") {
78
+ return field.includes(delimiter) || field.includes("\"") || field.includes("\r") || field.includes("\n") ? `"${field.replaceAll("\"", "\"\"")}"` : field;
79
+ }
80
+ //#endregion
81
+ exports.CsvParseError = CsvParseError;
82
+ exports.DEFAULT_CSV_DELIMITER = DEFAULT_CSV_DELIMITER;
83
+ exports.TSV_DELIMITER = TSV_DELIMITER;
84
+ exports.parseCsvRecords = parseCsvRecords;
85
+ exports.quoteCsvField = quoteCsvField;
@@ -0,0 +1,10 @@
1
+ //#region src/csv/records.d.ts
2
+ declare const DEFAULT_CSV_DELIMITER = ",";
3
+ declare const TSV_DELIMITER = "\t";
4
+ declare class CsvParseError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ declare function parseCsvRecords(text: string, delimiter?: string): string[][];
8
+ declare function quoteCsvField(field: string, delimiter?: string): string;
9
+ //#endregion
10
+ export { CsvParseError, DEFAULT_CSV_DELIMITER, TSV_DELIMITER, parseCsvRecords, quoteCsvField };
@@ -0,0 +1,10 @@
1
+ //#region src/csv/records.d.ts
2
+ declare const DEFAULT_CSV_DELIMITER = ",";
3
+ declare const TSV_DELIMITER = "\t";
4
+ declare class CsvParseError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ declare function parseCsvRecords(text: string, delimiter?: string): string[][];
8
+ declare function quoteCsvField(field: string, delimiter?: string): string;
9
+ //#endregion
10
+ export { CsvParseError, DEFAULT_CSV_DELIMITER, TSV_DELIMITER, parseCsvRecords, quoteCsvField };
@@ -0,0 +1,80 @@
1
+ //#region src/csv/records.ts
2
+ const DEFAULT_CSV_DELIMITER = ",";
3
+ const TSV_DELIMITER = " ";
4
+ var CsvParseError = class extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "CsvParseError";
8
+ }
9
+ };
10
+ function requireSingleCharacterDelimiter(delimiter) {
11
+ if (delimiter.length !== 1) throw new CsvParseError(`delimiter must be exactly one character, got ${JSON.stringify(delimiter)}`);
12
+ }
13
+ function isBlankRecord(record) {
14
+ return record.length === 1 && record[0] === "";
15
+ }
16
+ function parseCsvRecords(text, delimiter = ",") {
17
+ requireSingleCharacterDelimiter(delimiter);
18
+ const records = [];
19
+ let record = [];
20
+ let field = "";
21
+ let inQuotedField = false;
22
+ let fieldStarted = false;
23
+ const endField = () => {
24
+ record.push(field);
25
+ field = "";
26
+ fieldStarted = false;
27
+ };
28
+ const endRecord = () => {
29
+ endField();
30
+ records.push(record);
31
+ record = [];
32
+ };
33
+ let index = 0;
34
+ while (index < text.length) {
35
+ const ch = text[index];
36
+ if (inQuotedField) {
37
+ if (ch === "\"") {
38
+ if (text[index + 1] === "\"") {
39
+ field += "\"";
40
+ index += 2;
41
+ continue;
42
+ }
43
+ inQuotedField = false;
44
+ index += 1;
45
+ continue;
46
+ }
47
+ field += ch;
48
+ index += 1;
49
+ continue;
50
+ }
51
+ if (ch === "\"" && !fieldStarted) {
52
+ inQuotedField = true;
53
+ fieldStarted = true;
54
+ index += 1;
55
+ continue;
56
+ }
57
+ if (ch === delimiter) {
58
+ endField();
59
+ index += 1;
60
+ continue;
61
+ }
62
+ if (ch === "\r" || ch === "\n") {
63
+ if (ch === "\r" && text[index + 1] === "\n") index += 2;
64
+ else index += 1;
65
+ endRecord();
66
+ continue;
67
+ }
68
+ field += ch;
69
+ fieldStarted = true;
70
+ index += 1;
71
+ }
72
+ if (inQuotedField) throw new CsvParseError(`unterminated quoted field: no closing double quote before end of input (field so far: ${field.slice(0, 40)})`);
73
+ if (fieldStarted || field !== "" || record.length > 0) endRecord();
74
+ return records.filter((candidate) => !isBlankRecord(candidate));
75
+ }
76
+ function quoteCsvField(field, delimiter = ",") {
77
+ return field.includes(delimiter) || field.includes("\"") || field.includes("\r") || field.includes("\n") ? `"${field.replaceAll("\"", "\"\"")}"` : field;
78
+ }
79
+ //#endregion
80
+ export { CsvParseError, DEFAULT_CSV_DELIMITER, TSV_DELIMITER, parseCsvRecords, quoteCsvField };
@@ -0,0 +1,22 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/csv/text.ts
3
+ var CsvInvalidUtf8Error = class extends Error {
4
+ constructor() {
5
+ super("csv text must be well-formed UTF-8");
6
+ this.name = "CsvInvalidUtf8Error";
7
+ }
8
+ };
9
+ function decodeCsvText(bytes) {
10
+ try {
11
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
12
+ } catch {
13
+ throw new CsvInvalidUtf8Error();
14
+ }
15
+ }
16
+ function encodeCsvText(text) {
17
+ return new TextEncoder().encode(text);
18
+ }
19
+ //#endregion
20
+ exports.CsvInvalidUtf8Error = CsvInvalidUtf8Error;
21
+ exports.decodeCsvText = decodeCsvText;
22
+ exports.encodeCsvText = encodeCsvText;
@@ -0,0 +1,8 @@
1
+ //#region src/csv/text.d.ts
2
+ declare class CsvInvalidUtf8Error extends Error {
3
+ constructor();
4
+ }
5
+ declare function decodeCsvText(bytes: Uint8Array): string;
6
+ declare function encodeCsvText(text: string): Uint8Array<ArrayBuffer>;
7
+ //#endregion
8
+ export { CsvInvalidUtf8Error, decodeCsvText, encodeCsvText };
@@ -0,0 +1,8 @@
1
+ //#region src/csv/text.d.ts
2
+ declare class CsvInvalidUtf8Error extends Error {
3
+ constructor();
4
+ }
5
+ declare function decodeCsvText(bytes: Uint8Array): string;
6
+ declare function encodeCsvText(text: string): Uint8Array<ArrayBuffer>;
7
+ //#endregion
8
+ export { CsvInvalidUtf8Error, decodeCsvText, encodeCsvText };
@@ -0,0 +1,19 @@
1
+ //#region src/csv/text.ts
2
+ var CsvInvalidUtf8Error = class extends Error {
3
+ constructor() {
4
+ super("csv text must be well-formed UTF-8");
5
+ this.name = "CsvInvalidUtf8Error";
6
+ }
7
+ };
8
+ function decodeCsvText(bytes) {
9
+ try {
10
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
11
+ } catch {
12
+ throw new CsvInvalidUtf8Error();
13
+ }
14
+ }
15
+ function encodeCsvText(text) {
16
+ return new TextEncoder().encode(text);
17
+ }
18
+ //#endregion
19
+ export { CsvInvalidUtf8Error, decodeCsvText, encodeCsvText };
@@ -0,0 +1,75 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_csv_records = require("./records.cjs");
3
+ //#region src/csv/write.ts
4
+ var CsvUnsupportedDocumentKindError = class extends Error {
5
+ kind;
6
+ constructor(kind) {
7
+ super(`buildCsvText: expected a spreadsheet ContentDocument, got kind '${kind}'`);
8
+ this.name = "CsvUnsupportedDocumentKindError";
9
+ this.kind = kind;
10
+ }
11
+ };
12
+ var CsvSheetNotSpecifiedError = class extends Error {
13
+ availableSheets;
14
+ constructor(availableSheets) {
15
+ super(`buildCsvText: this document has more than one sheet (${availableSheets.join(", ")}) -- pass { sheet: '<name>' } to select one`);
16
+ this.name = "CsvSheetNotSpecifiedError";
17
+ this.availableSheets = availableSheets;
18
+ }
19
+ };
20
+ var CsvSheetNotFoundError = class extends Error {
21
+ sheet;
22
+ availableSheets;
23
+ constructor(sheet, availableSheets) {
24
+ super(`buildCsvText: sheet "${sheet}" not found -- available sheet(s): ${availableSheets.length === 0 ? "(none)" : availableSheets.join(", ")}`);
25
+ this.name = "CsvSheetNotFoundError";
26
+ this.sheet = sheet;
27
+ this.availableSheets = availableSheets;
28
+ }
29
+ };
30
+ function selectSheet(sheets, sheetName) {
31
+ const availableNames = sheets.map((candidate) => candidate.name);
32
+ if (sheetName !== void 0) {
33
+ const found = sheets.find((candidate) => candidate.name === sheetName);
34
+ if (found === void 0) throw new CsvSheetNotFoundError(sheetName, availableNames);
35
+ return found;
36
+ }
37
+ if (sheets.length === 0) throw new CsvSheetNotFoundError("(unspecified)", availableNames);
38
+ if (sheets.length > 1) throw new CsvSheetNotSpecifiedError(availableNames);
39
+ const only = sheets[0];
40
+ if (only === void 0) throw new CsvSheetNotFoundError("(unspecified)", availableNames);
41
+ return only;
42
+ }
43
+ function buildCsvText(content, options) {
44
+ if (content.kind !== "spreadsheet") throw new CsvUnsupportedDocumentKindError(content.kind);
45
+ const sheet = selectSheet(content.sheets, options?.sheet);
46
+ const delimiter = options?.delimiter ?? ",";
47
+ const fieldsByRow = /* @__PURE__ */ new Map();
48
+ let maxRowIndex = -1;
49
+ let maxColumnIndex = -1;
50
+ for (const cell of sheet.cells) {
51
+ let row = fieldsByRow.get(cell.row);
52
+ if (row === void 0) {
53
+ row = /* @__PURE__ */ new Map();
54
+ fieldsByRow.set(cell.row, row);
55
+ }
56
+ row.set(cell.column, cell.displayText);
57
+ maxRowIndex = Math.max(maxRowIndex, cell.row);
58
+ maxColumnIndex = Math.max(maxColumnIndex, cell.column);
59
+ }
60
+ const rowCount = Math.max(sheet.rows.length, maxRowIndex + 1);
61
+ const columnCount = Math.max(sheet.columns.length, maxColumnIndex + 1);
62
+ const lines = [];
63
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
64
+ const row = fieldsByRow.get(rowIndex);
65
+ const fields = [];
66
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) fields.push(require_csv_records.quoteCsvField(row?.get(columnIndex) ?? "", delimiter));
67
+ lines.push(fields.join(delimiter));
68
+ }
69
+ return lines.length === 0 ? "" : `${lines.join("\r\n")}\r\n`;
70
+ }
71
+ //#endregion
72
+ exports.CsvSheetNotFoundError = CsvSheetNotFoundError;
73
+ exports.CsvSheetNotSpecifiedError = CsvSheetNotSpecifiedError;
74
+ exports.CsvUnsupportedDocumentKindError = CsvUnsupportedDocumentKindError;
75
+ exports.buildCsvText = buildCsvText;
@@ -0,0 +1,22 @@
1
+ import { ContentDocument } from "document-schema.js";
2
+ //#region src/csv/write.d.ts
3
+ declare class CsvUnsupportedDocumentKindError extends Error {
4
+ readonly kind: ContentDocument['kind'];
5
+ constructor(kind: ContentDocument['kind']);
6
+ }
7
+ declare class CsvSheetNotSpecifiedError extends Error {
8
+ readonly availableSheets: readonly string[];
9
+ constructor(availableSheets: readonly string[]);
10
+ }
11
+ declare class CsvSheetNotFoundError extends Error {
12
+ readonly sheet: string;
13
+ readonly availableSheets: readonly string[];
14
+ constructor(sheet: string, availableSheets: readonly string[]);
15
+ }
16
+ interface BuildCsvTextOptions {
17
+ readonly delimiter?: string;
18
+ readonly sheet?: string;
19
+ }
20
+ declare function buildCsvText(content: ContentDocument, options?: BuildCsvTextOptions): string;
21
+ //#endregion
22
+ export { BuildCsvTextOptions, CsvSheetNotFoundError, CsvSheetNotSpecifiedError, CsvUnsupportedDocumentKindError, buildCsvText };
@@ -0,0 +1,22 @@
1
+ import { ContentDocument } from "document-schema.js";
2
+ //#region src/csv/write.d.ts
3
+ declare class CsvUnsupportedDocumentKindError extends Error {
4
+ readonly kind: ContentDocument['kind'];
5
+ constructor(kind: ContentDocument['kind']);
6
+ }
7
+ declare class CsvSheetNotSpecifiedError extends Error {
8
+ readonly availableSheets: readonly string[];
9
+ constructor(availableSheets: readonly string[]);
10
+ }
11
+ declare class CsvSheetNotFoundError extends Error {
12
+ readonly sheet: string;
13
+ readonly availableSheets: readonly string[];
14
+ constructor(sheet: string, availableSheets: readonly string[]);
15
+ }
16
+ interface BuildCsvTextOptions {
17
+ readonly delimiter?: string;
18
+ readonly sheet?: string;
19
+ }
20
+ declare function buildCsvText(content: ContentDocument, options?: BuildCsvTextOptions): string;
21
+ //#endregion
22
+ export { BuildCsvTextOptions, CsvSheetNotFoundError, CsvSheetNotSpecifiedError, CsvUnsupportedDocumentKindError, buildCsvText };
@@ -0,0 +1,71 @@
1
+ import { quoteCsvField } from "./records.js";
2
+ //#region src/csv/write.ts
3
+ var CsvUnsupportedDocumentKindError = class extends Error {
4
+ kind;
5
+ constructor(kind) {
6
+ super(`buildCsvText: expected a spreadsheet ContentDocument, got kind '${kind}'`);
7
+ this.name = "CsvUnsupportedDocumentKindError";
8
+ this.kind = kind;
9
+ }
10
+ };
11
+ var CsvSheetNotSpecifiedError = class extends Error {
12
+ availableSheets;
13
+ constructor(availableSheets) {
14
+ super(`buildCsvText: this document has more than one sheet (${availableSheets.join(", ")}) -- pass { sheet: '<name>' } to select one`);
15
+ this.name = "CsvSheetNotSpecifiedError";
16
+ this.availableSheets = availableSheets;
17
+ }
18
+ };
19
+ var CsvSheetNotFoundError = class extends Error {
20
+ sheet;
21
+ availableSheets;
22
+ constructor(sheet, availableSheets) {
23
+ super(`buildCsvText: sheet "${sheet}" not found -- available sheet(s): ${availableSheets.length === 0 ? "(none)" : availableSheets.join(", ")}`);
24
+ this.name = "CsvSheetNotFoundError";
25
+ this.sheet = sheet;
26
+ this.availableSheets = availableSheets;
27
+ }
28
+ };
29
+ function selectSheet(sheets, sheetName) {
30
+ const availableNames = sheets.map((candidate) => candidate.name);
31
+ if (sheetName !== void 0) {
32
+ const found = sheets.find((candidate) => candidate.name === sheetName);
33
+ if (found === void 0) throw new CsvSheetNotFoundError(sheetName, availableNames);
34
+ return found;
35
+ }
36
+ if (sheets.length === 0) throw new CsvSheetNotFoundError("(unspecified)", availableNames);
37
+ if (sheets.length > 1) throw new CsvSheetNotSpecifiedError(availableNames);
38
+ const only = sheets[0];
39
+ if (only === void 0) throw new CsvSheetNotFoundError("(unspecified)", availableNames);
40
+ return only;
41
+ }
42
+ function buildCsvText(content, options) {
43
+ if (content.kind !== "spreadsheet") throw new CsvUnsupportedDocumentKindError(content.kind);
44
+ const sheet = selectSheet(content.sheets, options?.sheet);
45
+ const delimiter = options?.delimiter ?? ",";
46
+ const fieldsByRow = /* @__PURE__ */ new Map();
47
+ let maxRowIndex = -1;
48
+ let maxColumnIndex = -1;
49
+ for (const cell of sheet.cells) {
50
+ let row = fieldsByRow.get(cell.row);
51
+ if (row === void 0) {
52
+ row = /* @__PURE__ */ new Map();
53
+ fieldsByRow.set(cell.row, row);
54
+ }
55
+ row.set(cell.column, cell.displayText);
56
+ maxRowIndex = Math.max(maxRowIndex, cell.row);
57
+ maxColumnIndex = Math.max(maxColumnIndex, cell.column);
58
+ }
59
+ const rowCount = Math.max(sheet.rows.length, maxRowIndex + 1);
60
+ const columnCount = Math.max(sheet.columns.length, maxColumnIndex + 1);
61
+ const lines = [];
62
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
63
+ const row = fieldsByRow.get(rowIndex);
64
+ const fields = [];
65
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) fields.push(quoteCsvField(row?.get(columnIndex) ?? "", delimiter));
66
+ lines.push(fields.join(delimiter));
67
+ }
68
+ return lines.length === 0 ? "" : `${lines.join("\r\n")}\r\n`;
69
+ }
70
+ //#endregion
71
+ export { CsvSheetNotFoundError, CsvSheetNotSpecifiedError, CsvUnsupportedDocumentKindError, buildCsvText };
@@ -1,5 +1,5 @@
1
1
  import { el, txt } from "../../xml/fragment.js";
2
- import { encodeXmlText } from "../../xml/entities.js";
2
+ import { encodeXmlText as encodeXmlText$1 } from "../../xml/entities.js";
3
3
  import { PAGE_SIZE_A4 } from "document-schema.js";
4
4
  import { ODF_MEDIA_TYPES, setDocumentMediaType, syncManifest, xmlnsAttributes } from "odf.js";
5
5
  //#region src/edit/odg/scaffold.ts
@@ -78,13 +78,13 @@ function buildContentXml() {
78
78
  function buildOfficeMeta(metadata) {
79
79
  if (metadata === void 0) return [];
80
80
  const children = [];
81
- if (metadata.title !== void 0) children.push(el("dc:title", {}, [txt(encodeXmlText(metadata.title))]));
82
- if (metadata.author !== void 0) children.push(el("meta:initial-creator", {}, [txt(encodeXmlText(metadata.author))]));
83
- if (metadata.subject !== void 0) children.push(el("dc:subject", {}, [txt(encodeXmlText(metadata.subject))]));
84
- for (const keyword of metadata.keywords ?? []) children.push(el("meta:keyword", {}, [txt(encodeXmlText(keyword))]));
85
- if (metadata.creator !== void 0) children.push(el("meta:generator", {}, [txt(encodeXmlText(metadata.creator))]));
86
- if (metadata.createdIso !== void 0) children.push(el("meta:creation-date", {}, [txt(encodeXmlText(metadata.createdIso))]));
87
- if (metadata.modifiedIso !== void 0) children.push(el("dc:date", {}, [txt(encodeXmlText(metadata.modifiedIso))]));
81
+ if (metadata.title !== void 0) children.push(el("dc:title", {}, [txt(encodeXmlText$1(metadata.title))]));
82
+ if (metadata.author !== void 0) children.push(el("meta:initial-creator", {}, [txt(encodeXmlText$1(metadata.author))]));
83
+ if (metadata.subject !== void 0) children.push(el("dc:subject", {}, [txt(encodeXmlText$1(metadata.subject))]));
84
+ for (const keyword of metadata.keywords ?? []) children.push(el("meta:keyword", {}, [txt(encodeXmlText$1(keyword))]));
85
+ if (metadata.creator !== void 0) children.push(el("meta:generator", {}, [txt(encodeXmlText$1(metadata.creator))]));
86
+ if (metadata.createdIso !== void 0) children.push(el("meta:creation-date", {}, [txt(encodeXmlText$1(metadata.createdIso))]));
87
+ if (metadata.modifiedIso !== void 0) children.push(el("dc:date", {}, [txt(encodeXmlText$1(metadata.modifiedIso))]));
88
88
  return children;
89
89
  }
90
90
  function buildMetaXml(metadata) {