odf-kit 0.9.7 → 0.9.9

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,139 @@
1
+ /**
2
+ * ODS reader type definitions.
3
+ *
4
+ * These types describe the in-memory model returned by readOds().
5
+ */
6
+ /** Top-level ODS document model returned by readOds(). */
7
+ export interface OdsDocumentModel {
8
+ /** Sheets in tab order. */
9
+ sheets: OdsSheetModel[];
10
+ /** Document metadata from meta.xml. */
11
+ metadata?: OdsMetadata;
12
+ }
13
+ /** Document metadata from meta.xml. */
14
+ export interface OdsMetadata {
15
+ title?: string;
16
+ creator?: string;
17
+ description?: string;
18
+ creationDate?: string;
19
+ lastModified?: string;
20
+ }
21
+ /** A single sheet (tab) in the spreadsheet. */
22
+ export interface OdsSheetModel {
23
+ /** Sheet tab name. */
24
+ name: string;
25
+ /** Tab color if set (hex or CSS named color). */
26
+ tabColor?: string;
27
+ /** Rows in order. Sparse rows (e.g. from table:number-rows-repeated) are expanded. */
28
+ rows: OdsRowModel[];
29
+ /** Column widths by zero-based column index. */
30
+ columnWidths: Map<number, string>;
31
+ /** Number of frozen rows (from settings.xml). */
32
+ freezeRows?: number;
33
+ /** Number of frozen columns (from settings.xml). */
34
+ freezeColumns?: number;
35
+ }
36
+ /** A row of cells. */
37
+ export interface OdsRowModel {
38
+ /** Zero-based row index within the sheet. */
39
+ index: number;
40
+ /** Cells in column order. Covered cells have type "covered". */
41
+ cells: OdsCellModel[];
42
+ /** Row height if explicitly set. */
43
+ height?: string;
44
+ }
45
+ /**
46
+ * A single cell in the spreadsheet.
47
+ *
48
+ * Cell types:
49
+ * - `"string"` — text value; `value` is a string
50
+ * - `"float"` — numeric value; `value` is a number
51
+ * - `"date"` — date/datetime; `value` is a Date (UTC)
52
+ * - `"boolean"` — boolean; `value` is true or false
53
+ * - `"formula"` — formula cell; `value` is the cached result, `formula` is the original string
54
+ * - `"empty"` — no content; `value` is null
55
+ * - `"covered"` — covered by a merge from a primary cell; `value` is null
56
+ */
57
+ export interface OdsCellModel {
58
+ /** Zero-based column index. Always correct regardless of merges. */
59
+ colIndex: number;
60
+ /** Cell type. */
61
+ type: "string" | "float" | "date" | "boolean" | "formula" | "empty" | "covered";
62
+ /**
63
+ * The typed JavaScript value.
64
+ * - string → string
65
+ * - float → number
66
+ * - date → Date (UTC)
67
+ * - boolean → boolean
68
+ * - formula → cached result (number, string, or boolean)
69
+ * - empty/covered → null
70
+ */
71
+ value: string | number | boolean | Date | null;
72
+ /**
73
+ * Original formula string for formula cells (e.g. `"=SUM(A1:A10)"`).
74
+ * The `of:` OpenFormula prefix is stripped.
75
+ * Undefined for non-formula cells.
76
+ */
77
+ formula?: string;
78
+ /**
79
+ * Display text as it appears in the cell (the text:p content).
80
+ * e.g. `"1,234.56"` for a formatted number, `"15/01/2026"` for a date.
81
+ * May differ from `value` when number or date formatting is applied.
82
+ */
83
+ displayText?: string;
84
+ /**
85
+ * Number of columns this cell spans (1 = no merge).
86
+ * Only set when > 1.
87
+ */
88
+ colSpan?: number;
89
+ /**
90
+ * Number of rows this cell spans (1 = no merge).
91
+ * Only set when > 1.
92
+ */
93
+ rowSpan?: number;
94
+ /** Cell formatting extracted from the cell style. */
95
+ formatting?: OdsCellFormatting;
96
+ }
97
+ /** Cell formatting properties extracted from ODS automatic styles. */
98
+ export interface OdsCellFormatting {
99
+ bold?: boolean;
100
+ italic?: boolean;
101
+ underline?: boolean;
102
+ fontSize?: string;
103
+ fontFamily?: string;
104
+ /** Text color. */
105
+ color?: string;
106
+ /** Cell background color. */
107
+ backgroundColor?: string;
108
+ /** Horizontal text alignment. */
109
+ textAlign?: "left" | "center" | "right";
110
+ /** Vertical alignment. */
111
+ verticalAlign?: "top" | "middle" | "bottom";
112
+ /** Number format string (e.g. `"decimal:2"`, `"currency:EUR"`, `"percentage"`). */
113
+ numberFormat?: string;
114
+ /** Date format string (e.g. `"YYYY-MM-DD"`, `"DD/MM/YYYY"`). */
115
+ dateFormat?: string;
116
+ }
117
+ /** Options for {@link readOds}. */
118
+ export interface ReadOdsOptions {
119
+ /**
120
+ * Whether to include cell formatting in the model.
121
+ * Defaults to `true`. Set to `false` for faster parsing when
122
+ * only values and types are needed.
123
+ */
124
+ includeFormatting?: boolean;
125
+ }
126
+ /** Options for {@link odsToHtml}. */
127
+ export interface OdsHtmlOptions {
128
+ /**
129
+ * Whether to include inline styles from cell formatting.
130
+ * Defaults to `true`.
131
+ */
132
+ includeStyles?: boolean;
133
+ /**
134
+ * CSS class prefix for generated elements.
135
+ * Defaults to `"ods"`.
136
+ */
137
+ classPrefix?: string;
138
+ }
139
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ods-reader/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * ODS reader type definitions.
3
+ *
4
+ * These types describe the in-memory model returned by readOds().
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ods-reader/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * XLSX → ODS converter.
3
+ *
4
+ * Maps an XlsxWorkbook intermediate model to an OdsDocument and saves it.
5
+ */
6
+ import type { OdsDateFormat } from "../ods/types.js";
7
+ import type { XlsxWorkbook } from "./reader.js";
8
+ export interface XlsxToOdsOptions {
9
+ /**
10
+ * Date display format for date cells.
11
+ * Defaults to "YYYY-MM-DD".
12
+ */
13
+ dateFormat?: OdsDateFormat;
14
+ /**
15
+ * Document metadata for the output ODS file.
16
+ */
17
+ metadata?: {
18
+ title?: string;
19
+ creator?: string;
20
+ description?: string;
21
+ };
22
+ }
23
+ /**
24
+ * Convert an XlsxWorkbook model to an ODS file.
25
+ *
26
+ * @param workbook - Parsed XLSX workbook from readXlsx().
27
+ * @param options - Conversion options.
28
+ * @returns Promise resolving to a Uint8Array containing the .ods file.
29
+ */
30
+ export declare function convertXlsxToOds(workbook: XlsxWorkbook, options?: XlsxToOdsOptions): Promise<Uint8Array>;
31
+ //# sourceMappingURL=converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/xlsx/converter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,aAAa,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAuHD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAYrB"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * XLSX → ODS converter.
3
+ *
4
+ * Maps an XlsxWorkbook intermediate model to an OdsDocument and saves it.
5
+ */
6
+ import { OdsDocument } from "../ods/document.js";
7
+ // ─── Cell Mapping ─────────────────────────────────────────────────────
8
+ function mapCell(cell, options) {
9
+ switch (cell.type) {
10
+ case "string":
11
+ return { value: cell.value, type: "string" };
12
+ case "number":
13
+ return { value: cell.value, type: "float" };
14
+ case "boolean":
15
+ return { value: cell.value, type: "boolean" };
16
+ case "date":
17
+ return {
18
+ value: cell.value,
19
+ type: "date",
20
+ ...(options.dateFormat ? { dateFormat: options.dateFormat } : {}),
21
+ };
22
+ case "formula": {
23
+ // Determine the cell type from the cached value
24
+ const val = cell.value;
25
+ let type = "formula";
26
+ if (typeof val === "string")
27
+ type = "formula";
28
+ else if (typeof val === "boolean")
29
+ type = "formula";
30
+ else if (val instanceof Date)
31
+ type = "formula";
32
+ else
33
+ type = "formula";
34
+ return {
35
+ value: val,
36
+ type,
37
+ formula: cell.formula ? `=${cell.formula.replace(/^=/, "")}` : undefined,
38
+ };
39
+ }
40
+ case "error":
41
+ // Represent errors as strings
42
+ return { value: String(cell.value), type: "string" };
43
+ default:
44
+ return { value: null, type: "string" };
45
+ }
46
+ }
47
+ // ─── Sheet Conversion ─────────────────────────────────────────────────
48
+ function convertSheet(xlSheet, options, doc) {
49
+ const sheet = doc.addSheet(xlSheet.name);
50
+ if (xlSheet.freezeRows)
51
+ sheet.freezeRows(xlSheet.freezeRows);
52
+ if (xlSheet.freezeColumns)
53
+ sheet.freezeColumns(xlSheet.freezeColumns);
54
+ if (xlSheet.rows.size === 0)
55
+ return;
56
+ // Determine row/column extent
57
+ let maxRow = 0;
58
+ let maxCol = 0;
59
+ for (const [rowIdx, row] of xlSheet.rows) {
60
+ if (rowIdx > maxRow)
61
+ maxRow = rowIdx;
62
+ for (const colIdx of row.cells.keys()) {
63
+ if (colIdx > maxCol)
64
+ maxCol = colIdx;
65
+ }
66
+ }
67
+ // Also account for merge extents
68
+ for (const [key, span] of xlSheet.merges) {
69
+ const [c, r] = key.split(":").map(Number);
70
+ const endRow = r + span.rowSpan - 1;
71
+ const endCol = c + span.colSpan - 1;
72
+ if (endRow > maxRow)
73
+ maxRow = endRow;
74
+ if (endCol > maxCol)
75
+ maxCol = endCol;
76
+ }
77
+ for (let r = 0; r <= maxRow; r++) {
78
+ const xlRow = xlSheet.rows.get(r);
79
+ const cells = [];
80
+ let hasContent = false;
81
+ for (let c = 0; c <= maxCol; c++) {
82
+ const cellKey = `${c}:${r}`;
83
+ // Skip covered cells — OdsDocument handles them automatically via colSpan/rowSpan
84
+ if (xlSheet.coveredCells.has(cellKey)) {
85
+ cells.push(null);
86
+ continue;
87
+ }
88
+ const xlCell = xlRow?.cells.get(c);
89
+ if (!xlCell || xlCell.type === "empty") {
90
+ cells.push(null);
91
+ continue;
92
+ }
93
+ const cellObj = mapCell(xlCell, options);
94
+ // Apply merge spans
95
+ const merge = xlSheet.merges.get(cellKey);
96
+ if (merge) {
97
+ if (merge.colSpan > 1)
98
+ cellObj.colSpan = merge.colSpan;
99
+ if (merge.rowSpan > 1)
100
+ cellObj.rowSpan = merge.rowSpan;
101
+ }
102
+ cells.push(cellObj);
103
+ hasContent = true;
104
+ }
105
+ if (hasContent) {
106
+ sheet.addRow(cells);
107
+ }
108
+ else {
109
+ // Emit an empty row to preserve row positioning
110
+ sheet.addRow([]);
111
+ }
112
+ }
113
+ }
114
+ // ─── Public API ───────────────────────────────────────────────────────
115
+ /**
116
+ * Convert an XlsxWorkbook model to an ODS file.
117
+ *
118
+ * @param workbook - Parsed XLSX workbook from readXlsx().
119
+ * @param options - Conversion options.
120
+ * @returns Promise resolving to a Uint8Array containing the .ods file.
121
+ */
122
+ export async function convertXlsxToOds(workbook, options = {}) {
123
+ const doc = new OdsDocument();
124
+ if (options.metadata) {
125
+ doc.setMetadata(options.metadata);
126
+ }
127
+ for (const xlSheet of workbook.sheets) {
128
+ convertSheet(xlSheet, options, doc);
129
+ }
130
+ return doc.save();
131
+ }
132
+ //# sourceMappingURL=converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.js","sourceRoot":"","sources":["../../src/xlsx/converter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { XlsxToOdsOptions } from "./converter.js";
2
+ export { readXlsx } from "./reader.js";
3
+ export type { XlsxWorkbook, XlsxSheet, XlsxRow, XlsxCell } from "./reader.js";
4
+ export type { XlsxToOdsOptions } from "./converter.js";
5
+ /**
6
+ * Convert an .xlsx file to an .ods file.
7
+ *
8
+ * Parses the XLSX XML directly — no external dependencies beyond fflate.
9
+ * Runs in Node.js and browsers.
10
+ *
11
+ * @param bytes - Raw .xlsx file bytes (Uint8Array or ArrayBuffer).
12
+ * @param options - Optional conversion options.
13
+ * @returns Promise resolving to a Uint8Array containing the .ods file.
14
+ *
15
+ * @example
16
+ * import { xlsxToOds } from "odf-kit/xlsx"
17
+ * import { readFileSync, writeFileSync } from "fs"
18
+ *
19
+ * const bytes = await xlsxToOds(readFileSync("report.xlsx"))
20
+ * writeFileSync("report.ods", bytes)
21
+ */
22
+ export declare function xlsxToOds(bytes: Uint8Array | ArrayBuffer, options?: XlsxToOdsOptions): Promise<Uint8Array>;
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/xlsx/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,UAAU,GAAG,WAAW,EAC/B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,UAAU,CAAC,CAGrB"}
@@ -0,0 +1,25 @@
1
+ import { readXlsx } from "./reader.js";
2
+ import { convertXlsxToOds } from "./converter.js";
3
+ export { readXlsx } from "./reader.js";
4
+ /**
5
+ * Convert an .xlsx file to an .ods file.
6
+ *
7
+ * Parses the XLSX XML directly — no external dependencies beyond fflate.
8
+ * Runs in Node.js and browsers.
9
+ *
10
+ * @param bytes - Raw .xlsx file bytes (Uint8Array or ArrayBuffer).
11
+ * @param options - Optional conversion options.
12
+ * @returns Promise resolving to a Uint8Array containing the .ods file.
13
+ *
14
+ * @example
15
+ * import { xlsxToOds } from "odf-kit/xlsx"
16
+ * import { readFileSync, writeFileSync } from "fs"
17
+ *
18
+ * const bytes = await xlsxToOds(readFileSync("report.xlsx"))
19
+ * writeFileSync("report.ods", bytes)
20
+ */
21
+ export async function xlsxToOds(bytes, options) {
22
+ const workbook = readXlsx(bytes);
23
+ return convertXlsxToOds(workbook, options);
24
+ }
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/xlsx/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAA+B,EAC/B,OAA0B;IAE1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * XLSX reader — parses an .xlsx file into an intermediate XlsxWorkbook model.
3
+ *
4
+ * Parsing pipeline:
5
+ * 1. Unzip the .xlsx bytes with fflate
6
+ * 2. Parse xl/workbook.xml → sheet names and rIds
7
+ * 3. Parse xl/_rels/workbook.xml.rels → rId → file path map
8
+ * 4. Parse xl/sharedStrings.xml → string lookup array
9
+ * 5. Parse xl/styles.xml → style index → date format detection
10
+ * 6. Parse each xl/worksheets/sheet*.xml → rows, cells, merges, freeze
11
+ * 7. Return XlsxWorkbook
12
+ *
13
+ * No external dependencies — uses fflate for ZIP and our existing xml-parser.
14
+ */
15
+ export interface XlsxWorkbook {
16
+ sheets: XlsxSheet[];
17
+ }
18
+ export interface XlsxSheet {
19
+ name: string;
20
+ /** rowIndex → row */
21
+ rows: Map<number, XlsxRow>;
22
+ /** "col:row" → merge span for primary cell */
23
+ merges: Map<string, {
24
+ colSpan: number;
25
+ rowSpan: number;
26
+ }>;
27
+ /** Set of "col:row" keys that are covered by a merge (non-primary) */
28
+ coveredCells: Set<string>;
29
+ freezeRows?: number;
30
+ freezeColumns?: number;
31
+ }
32
+ export interface XlsxRow {
33
+ /** colIndex → cell */
34
+ cells: Map<number, XlsxCell>;
35
+ }
36
+ export interface XlsxCell {
37
+ type: "string" | "number" | "boolean" | "date" | "formula" | "error" | "empty";
38
+ value: string | number | boolean | Date | null;
39
+ /** Original formula string, if cell has a formula. */
40
+ formula?: string;
41
+ }
42
+ /**
43
+ * Parse a cell reference like "A1", "Z3", "AA10" into zero-based col/row indices.
44
+ */
45
+ export declare function parseCellRef(ref: string): {
46
+ col: number;
47
+ row: number;
48
+ };
49
+ /**
50
+ * Parse a merge range like "A1:C2" into start position and span.
51
+ */
52
+ export declare function parseMergeRef(ref: string): {
53
+ startCol: number;
54
+ startRow: number;
55
+ colSpan: number;
56
+ rowSpan: number;
57
+ };
58
+ /**
59
+ * Returns true if a custom number format code represents a date/time.
60
+ * Strips quoted strings first, then checks for date tokens (y, m, d, h).
61
+ */
62
+ export declare function isDateFormatCode(code: string): boolean;
63
+ /**
64
+ * Returns true if the given style index refers to a date/time format.
65
+ */
66
+ export declare function isDateStyle(styleIndex: number, cellXfs: number[], customFormats: Map<number, string>): boolean;
67
+ /**
68
+ * Convert an XLSX serial date number to a JavaScript Date (UTC).
69
+ *
70
+ * Excel stores dates as days since January 0, 1900, with a deliberate
71
+ * off-by-one bug inherited from Lotus 1-2-3 (Excel incorrectly treats
72
+ * 1900 as a leap year). The correct epoch is December 30, 1899 UTC.
73
+ */
74
+ export declare function xlsxSerialToDate(serial: number): Date;
75
+ /**
76
+ * Parse an XLSX file into an intermediate XlsxWorkbook model.
77
+ *
78
+ * @param bytes - Raw .xlsx file bytes (Uint8Array or ArrayBuffer).
79
+ * @returns XlsxWorkbook with typed cell values.
80
+ */
81
+ export declare function readXlsx(bytes: Uint8Array | ArrayBuffer): XlsxWorkbook;
82
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/xlsx/reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,sEAAsE;IACtE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,sBAAsB;IACtB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/E,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;IAC/C,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkCD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUtE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAUA;AA2CD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMtD;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EAAE,EACjB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,OAAO,CAMT;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAUrD;AAsRD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,CA2CtE"}