@rowsncolumns/utils 9.5.1 → 9.5.4

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 (61) hide show
  1. package/dist/cjs/clipboard-html-sanitize.d.ts +15 -0
  2. package/dist/cjs/clipboard-html-sanitize.d.ts.map +1 -0
  3. package/dist/cjs/clipboard-html-sanitize.js +237 -0
  4. package/dist/cjs/condition-operand.d.ts +54 -0
  5. package/dist/cjs/condition-operand.d.ts.map +1 -0
  6. package/dist/cjs/condition-operand.js +223 -0
  7. package/dist/cjs/conditional-format.d.ts.map +1 -1
  8. package/dist/cjs/conditional-format.js +5 -59
  9. package/dist/cjs/data-validation.d.ts +9 -0
  10. package/dist/cjs/data-validation.d.ts.map +1 -1
  11. package/dist/cjs/data-validation.js +29 -60
  12. package/dist/cjs/date.d.ts +16 -0
  13. package/dist/cjs/date.d.ts.map +1 -1
  14. package/dist/cjs/date.js +33 -4
  15. package/dist/cjs/index.d.ts +4 -0
  16. package/dist/cjs/index.d.ts.map +1 -1
  17. package/dist/cjs/index.js +4 -0
  18. package/dist/cjs/rich-text-html.d.ts +9 -0
  19. package/dist/cjs/rich-text-html.d.ts.map +1 -1
  20. package/dist/cjs/rich-text-html.js +52 -23
  21. package/dist/cjs/sheet-names.d.ts +60 -0
  22. package/dist/cjs/sheet-names.d.ts.map +1 -0
  23. package/dist/cjs/sheet-names.js +157 -0
  24. package/dist/cjs/sheet-protection.d.ts +9 -0
  25. package/dist/cjs/sheet-protection.d.ts.map +1 -0
  26. package/dist/cjs/sheet-protection.js +11 -0
  27. package/dist/cjs/string.d.ts +31 -0
  28. package/dist/cjs/string.d.ts.map +1 -1
  29. package/dist/cjs/string.js +73 -3
  30. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  31. package/dist/esm/clipboard-html-sanitize.d.ts +15 -0
  32. package/dist/esm/clipboard-html-sanitize.d.ts.map +1 -0
  33. package/dist/esm/clipboard-html-sanitize.js +192 -0
  34. package/dist/esm/condition-operand.d.ts +54 -0
  35. package/dist/esm/condition-operand.d.ts.map +1 -0
  36. package/dist/esm/condition-operand.js +203 -0
  37. package/dist/esm/conditional-format.d.ts.map +1 -1
  38. package/dist/esm/conditional-format.js +5 -57
  39. package/dist/esm/data-validation.d.ts +9 -0
  40. package/dist/esm/data-validation.d.ts.map +1 -1
  41. package/dist/esm/data-validation.js +27 -57
  42. package/dist/esm/date.d.ts +16 -0
  43. package/dist/esm/date.d.ts.map +1 -1
  44. package/dist/esm/date.js +22 -1
  45. package/dist/esm/index.d.ts +4 -0
  46. package/dist/esm/index.d.ts.map +1 -1
  47. package/dist/esm/index.js +4 -0
  48. package/dist/esm/rich-text-html.d.ts +9 -0
  49. package/dist/esm/rich-text-html.d.ts.map +1 -1
  50. package/dist/esm/rich-text-html.js +20 -4
  51. package/dist/esm/sheet-names.d.ts +60 -0
  52. package/dist/esm/sheet-names.d.ts.map +1 -0
  53. package/dist/esm/sheet-names.js +109 -0
  54. package/dist/esm/sheet-protection.d.ts +9 -0
  55. package/dist/esm/sheet-protection.d.ts.map +1 -0
  56. package/dist/esm/sheet-protection.js +8 -0
  57. package/dist/esm/string.d.ts +31 -0
  58. package/dist/esm/string.d.ts.map +1 -1
  59. package/dist/esm/string.js +62 -2
  60. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  61. package/package.json +2 -2
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildDataValidationExpression = exports.isDataValidationFormulaRule = exports.dataValidationOptionMatchesCellValue = exports.stripDataValidationTextPrefix = void 0;
4
- var selection_1 = require("./selection");
4
+ var condition_operand_1 = require("./condition-operand");
5
5
  var FORMULA_PREDICATE_BASE_CELL_REF = "A1";
6
- var NUMBER_LITERAL_PATTERN = /^-?\d+(?:\.\d+)?$/;
7
- var BOOLEAN_LITERAL_PATTERN = /^(TRUE|FALSE)$/i;
8
- var escapeFormulaText = function (value) { return value.replace(/"/g, '""'); };
9
6
  /**
10
7
  * A leading apostrophe in a data-validation / conditional-format list entry is
11
8
  * Excel's text prefix — `'000s` is the text "000s" and a bare `'` is empty
@@ -29,57 +26,6 @@ var dataValidationOptionMatchesCellValue = function (option, cellValue) {
29
26
  return normalizedOption.toLowerCase() === normalizedValue.toLowerCase();
30
27
  };
31
28
  exports.dataValidationOptionMatchesCellValue = dataValidationOptionMatchesCellValue;
32
- /**
33
- * Parse a locale-formatted numeric string (e.g., "6,5" in fr-FR) into a JS
34
- * number. Uses `Intl.NumberFormat` to detect decimal/group separators.
35
- * Returns NaN on failure.
36
- */
37
- var parseLocaleNumberLoose = function (value, locale) {
38
- var _a, _b, _c, _d;
39
- try {
40
- var parts = new Intl.NumberFormat(locale).formatToParts(1234.5);
41
- var decimal = (_b = (_a = parts.find(function (part) { return part.type === "decimal"; })) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ".";
42
- var group = (_d = (_c = parts.find(function (part) { return part.type === "group"; })) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : ",";
43
- var cleaned = value.split(group).join("").replace(decimal, ".");
44
- return Number(cleaned);
45
- }
46
- catch (_e) {
47
- return NaN;
48
- }
49
- };
50
- /**
51
- * Normalize a condition value for use in a formula expression.
52
- * Handles locale-specific number formats (e.g., "6,5" -> "6.5").
53
- */
54
- var normalizeConditionValue = function (raw, allowStringLiteral, locale) {
55
- if (allowStringLiteral === void 0) { allowStringLiteral = false; }
56
- if (!raw)
57
- return "";
58
- var trimmed = raw.trim();
59
- if (!trimmed)
60
- return "";
61
- if (trimmed.startsWith("=")) {
62
- return trimmed.slice(1);
63
- }
64
- if ((0, selection_1.checkIfStringIsReference)(trimmed)) {
65
- return trimmed;
66
- }
67
- if (NUMBER_LITERAL_PATTERN.test(trimmed) ||
68
- BOOLEAN_LITERAL_PATTERN.test(trimmed)) {
69
- return trimmed;
70
- }
71
- // Try parsing as locale-aware number
72
- if (locale) {
73
- var parsed = parseLocaleNumberLoose(trimmed, locale);
74
- if (!isNaN(parsed)) {
75
- return String(parsed);
76
- }
77
- }
78
- if (allowStringLiteral) {
79
- return "\"".concat(escapeFormulaText(trimmed), "\"");
80
- }
81
- return trimmed;
82
- };
83
29
  /**
84
30
  * Whether a data validation rule is evaluated via the calculator (formula path)
85
31
  * instead of the synchronous `checkBooleanRule` path used in
@@ -120,7 +66,29 @@ var isDataValidationFormulaRule = function (rule) {
120
66
  return Boolean((0, exports.buildDataValidationExpression)(rule, FORMULA_PREDICATE_BASE_CELL_REF));
121
67
  };
122
68
  exports.isDataValidationFormulaRule = isDataValidationFormulaRule;
69
+ /**
70
+ * Excel's *Whole number* validation kind rejects any non-integer (`5.5` fails
71
+ * "whole between 1 and 10"). An imported `type="whole"` rule carries a plain
72
+ * `NUMBER_*` comparison as its `condition` (the bounds) — which alone accepts
73
+ * `5.5` — so when the rule's `xlsxSource.type` is `whole` the comparison is
74
+ * wrapped in the same integer guard `buildExcelValidationRule` composes for
75
+ * an authored Whole-number rule: `AND(ISNUMBER(x), x=INT(x), <comparison>)`.
76
+ * Rules of other kinds, and non-`NUMBER_*` conditions, are returned as built.
77
+ */
123
78
  var buildDataValidationExpression = function (rule, baseCellRef, locale) {
79
+ var _a, _b, _c, _d;
80
+ var expression = buildDataValidationConditionExpression(rule, baseCellRef, locale);
81
+ if (!expression)
82
+ return undefined;
83
+ var isWholeSource = ((_b = (_a = rule === null || rule === void 0 ? void 0 : rule.xlsxSource) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.trim().toLowerCase()) === "whole";
84
+ var isNumberCondition = Boolean((_d = (_c = rule === null || rule === void 0 ? void 0 : rule.condition) === null || _c === void 0 ? void 0 : _c.type) === null || _d === void 0 ? void 0 : _d.startsWith("NUMBER_"));
85
+ if (!isWholeSource || !isNumberCondition)
86
+ return expression;
87
+ var body = expression.startsWith("=") ? expression.slice(1) : expression;
88
+ return "=AND(ISNUMBER(".concat(baseCellRef, "),").concat(baseCellRef, "=INT(").concat(baseCellRef, "),").concat(body, ")");
89
+ };
90
+ exports.buildDataValidationExpression = buildDataValidationExpression;
91
+ var buildDataValidationConditionExpression = function (rule, baseCellRef, locale) {
124
92
  var _a, _b, _c;
125
93
  var condition = rule === null || rule === void 0 ? void 0 : rule.condition;
126
94
  if (!(condition === null || condition === void 0 ? void 0 : condition.type))
@@ -135,8 +103,8 @@ var buildDataValidationExpression = function (rule, baseCellRef, locale) {
135
103
  return undefined;
136
104
  return trimmed.startsWith("=") ? trimmed : "=".concat(trimmed);
137
105
  }
138
- var fromExpr = normalizeConditionValue(fromRaw, true, locale);
139
- var toExpr = normalizeConditionValue(toRaw, true, locale);
106
+ var fromExpr = (0, condition_operand_1.normalizeConditionOperand)(fromRaw, condition.type, locale);
107
+ var toExpr = (0, condition_operand_1.normalizeConditionOperand)(toRaw, condition.type, locale);
140
108
  if (!fromExpr && !toExpr)
141
109
  return undefined;
142
110
  var comparisonOperatorMap = {
@@ -217,7 +185,7 @@ var buildDataValidationExpression = function (rule, baseCellRef, locale) {
217
185
  .flatMap(function (entry) {
218
186
  if (entry.startsWith("'")) {
219
187
  var stripped = (0, exports.stripDataValidationTextPrefix)(entry);
220
- var textCondition = "".concat(baseCellRef, "=\"").concat(escapeFormulaText(stripped), "\"");
188
+ var textCondition = "".concat(baseCellRef, "=\"").concat((0, condition_operand_1.escapeConditionFormulaText)(stripped), "\"");
221
189
  // The bare `'` entry means empty text, and a cell storing the lone
222
190
  // text-prefix apostrophe is equivalent to a blank cell — accept it too.
223
191
  return stripped === ""
@@ -225,7 +193,9 @@ var buildDataValidationExpression = function (rule, baseCellRef, locale) {
225
193
  : [textCondition];
226
194
  }
227
195
  return entry
228
- ? ["".concat(baseCellRef, "=").concat(normalizeConditionValue(entry, true, locale))]
196
+ ? [
197
+ "".concat(baseCellRef, "=").concat((0, condition_operand_1.normalizeConditionOperand)(entry, condition.type, locale)),
198
+ ]
229
199
  : [];
230
200
  })
231
201
  .filter(function (entry) { return Boolean(entry); });
@@ -246,4 +216,3 @@ var buildDataValidationExpression = function (rule, baseCellRef, locale) {
246
216
  }
247
217
  return undefined;
248
218
  };
249
- exports.buildDataValidationExpression = buildDataValidationExpression;
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Excel's 1900 date system counts a day that never happened: serial 60 is
3
+ * 1900-02-29 (Lotus 1-2-3 compatibility). 1900-01-01 is 1, 1900-02-28 is 59,
4
+ * 1900-03-01 is 61. Google Sheets keeps the same numbering.
5
+ */
6
+ export declare const EXCEL_LEAP_BUG_SERIAL = 60;
7
+ /** The calendar day Excel's serial 60 stands for, which no `Date` can hold. */
8
+ export declare const isExcelLeapDay: (year: number, month: number, day: number) => boolean;
1
9
  export type DateSerialMode = "local" | "excel-utc";
2
10
  /**
3
11
  * Convert date to serial with explicit time zone behavior.
@@ -6,6 +14,14 @@ export type DateSerialMode = "local" | "excel-utc";
6
14
  */
7
15
  export declare const toSerialWithMode: (date: Date, use1904?: boolean, mode?: DateSerialMode) => number;
8
16
  export declare const toSerial: (date: Date, use1904?: boolean) => number;
17
+ /**
18
+ * Serial for calendar parts the way a user typed them. Unlike
19
+ * `toSerial(new Date(y, m, d))`, this never goes through a `Date`, so the
20
+ * phantom 1900-02-29 stays serial 60 instead of rolling over to March 1
21
+ * (rowsncolumns/spreadsheet#1026). Every other date takes the same path as
22
+ * `toSerial` in "local" mode. `month` is 0-based like `Date`.
23
+ */
24
+ export declare const toSerialFromParts: (year: number, month: number, day: number, hour?: number, minute?: number, second?: number, use1904?: boolean) => number;
9
25
  /**
10
26
  * Convert serial to date
11
27
  * @param serial
@@ -1 +1 @@
1
- {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../date.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,WAAW,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,IAAI,EACV,iBAAe,EACf,OAAM,cAAwB,WAwB/B,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,MAAM,IAAI,EAAE,iBAAe,WAEnD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,iBAAe,SA+BrD,CAAC"}
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../date.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,+EAA+E;AAC/E,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,KAAK,MAAM,YAC3B,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,WAAW,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,IAAI,EACV,iBAAe,EACf,OAAM,cAAwB,WAwB/B,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,MAAM,IAAI,EAAE,iBAAe,WAEnD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,KAAK,MAAM,EACX,aAAQ,EACR,eAAU,EACV,eAAU,EACV,iBAAe,WAWhB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,iBAAe,SA+BrD,CAAC"}
package/dist/cjs/date.js CHANGED
@@ -1,8 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toDate = exports.toSerial = exports.toSerialWithMode = void 0;
3
+ exports.toDate = exports.toSerialFromParts = exports.toSerial = exports.toSerialWithMode = exports.isExcelLeapDay = exports.EXCEL_LEAP_BUG_SERIAL = void 0;
4
4
  var DAY_TO_MS = 24 * 60 * 60 * 1000;
5
- var EXCEL_LEAP_BUG_SERIAL = 60;
5
+ /**
6
+ * Excel's 1900 date system counts a day that never happened: serial 60 is
7
+ * 1900-02-29 (Lotus 1-2-3 compatibility). 1900-01-01 is 1, 1900-02-28 is 59,
8
+ * 1900-03-01 is 61. Google Sheets keeps the same numbering.
9
+ */
10
+ exports.EXCEL_LEAP_BUG_SERIAL = 60;
11
+ /** The calendar day Excel's serial 60 stands for, which no `Date` can hold. */
12
+ var isExcelLeapDay = function (year, month, day) {
13
+ return year === 1900 && month === 1 && day === 29;
14
+ };
15
+ exports.isExcelLeapDay = isExcelLeapDay;
6
16
  /**
7
17
  * Convert date to serial with explicit time zone behavior.
8
18
  * - local: interpret date components in local time (UI entry behavior).
@@ -31,6 +41,25 @@ var toSerial = function (date, use1904) {
31
41
  return (0, exports.toSerialWithMode)(date, use1904, "local");
32
42
  };
33
43
  exports.toSerial = toSerial;
44
+ /**
45
+ * Serial for calendar parts the way a user typed them. Unlike
46
+ * `toSerial(new Date(y, m, d))`, this never goes through a `Date`, so the
47
+ * phantom 1900-02-29 stays serial 60 instead of rolling over to March 1
48
+ * (rowsncolumns/spreadsheet#1026). Every other date takes the same path as
49
+ * `toSerial` in "local" mode. `month` is 0-based like `Date`.
50
+ */
51
+ var toSerialFromParts = function (year, month, day, hour, minute, second, use1904) {
52
+ if (hour === void 0) { hour = 0; }
53
+ if (minute === void 0) { minute = 0; }
54
+ if (second === void 0) { second = 0; }
55
+ if (use1904 === void 0) { use1904 = false; }
56
+ var timeFraction = (hour * 3600 + minute * 60 + second) / (24 * 60 * 60);
57
+ if (!use1904 && (0, exports.isExcelLeapDay)(year, month, day)) {
58
+ return exports.EXCEL_LEAP_BUG_SERIAL + timeFraction;
59
+ }
60
+ return (0, exports.toSerialWithMode)(new Date(year, month, day, hour, minute, second, 0), use1904, "local");
61
+ };
62
+ exports.toSerialFromParts = toSerialFromParts;
34
63
  /**
35
64
  * Convert serial to date
36
65
  * @param serial
@@ -44,11 +73,11 @@ var toDate = function (serial, use1904) {
44
73
  var utcDate_1 = new Date(utcMillis_1);
45
74
  return new Date(utcDate_1.getUTCFullYear(), utcDate_1.getUTCMonth(), utcDate_1.getUTCDate(), utcDate_1.getUTCHours(), utcDate_1.getUTCMinutes(), utcDate_1.getUTCSeconds(), utcDate_1.getUTCMilliseconds());
46
75
  }
47
- if (serial === EXCEL_LEAP_BUG_SERIAL) {
76
+ if (serial === exports.EXCEL_LEAP_BUG_SERIAL) {
48
77
  return new Date(1900, 1, 28);
49
78
  }
50
79
  var baseUtc = Date.UTC(1899, 11, 31);
51
- var dayCount = serial < EXCEL_LEAP_BUG_SERIAL ? serial : serial - 1;
80
+ var dayCount = serial < exports.EXCEL_LEAP_BUG_SERIAL ? serial : serial - 1;
52
81
  var utcMillis = baseUtc + dayCount * DAY_TO_MS;
53
82
  var utcDate = new Date(utcMillis);
54
83
  return new Date(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate(), utcDate.getUTCHours(), utcDate.getUTCMinutes(), utcDate.getUTCSeconds(), utcDate.getUTCMilliseconds());
@@ -18,6 +18,7 @@ export * from "./colors";
18
18
  export * from "./formula-refs";
19
19
  export * from "./sort";
20
20
  export * from "./table-styles";
21
+ export * from "./condition-operand";
21
22
  export * from "./conditional-format";
22
23
  export * from "./data-validation";
23
24
  export * from "./content-hash";
@@ -26,8 +27,11 @@ export * from "./keyboard";
26
27
  export * from "./sheet-span";
27
28
  export * from "./formula-locale";
28
29
  export * from "./table-names";
30
+ export * from "./sheet-names";
31
+ export * from "./sheet-protection";
29
32
  export * from "./table-totals";
30
33
  export * from "./sparkline-groups";
31
34
  export * from "./rich-text-html";
35
+ export * from "./clipboard-html-sanitize";
32
36
  export * from "./rich-text-links";
33
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC"}
package/dist/cjs/index.js CHANGED
@@ -21,6 +21,7 @@ tslib_1.__exportStar(require("./colors"), exports);
21
21
  tslib_1.__exportStar(require("./formula-refs"), exports);
22
22
  tslib_1.__exportStar(require("./sort"), exports);
23
23
  tslib_1.__exportStar(require("./table-styles"), exports);
24
+ tslib_1.__exportStar(require("./condition-operand"), exports);
24
25
  tslib_1.__exportStar(require("./conditional-format"), exports);
25
26
  tslib_1.__exportStar(require("./data-validation"), exports);
26
27
  tslib_1.__exportStar(require("./content-hash"), exports);
@@ -29,7 +30,10 @@ tslib_1.__exportStar(require("./keyboard"), exports);
29
30
  tslib_1.__exportStar(require("./sheet-span"), exports);
30
31
  tslib_1.__exportStar(require("./formula-locale"), exports);
31
32
  tslib_1.__exportStar(require("./table-names"), exports);
33
+ tslib_1.__exportStar(require("./sheet-names"), exports);
34
+ tslib_1.__exportStar(require("./sheet-protection"), exports);
32
35
  tslib_1.__exportStar(require("./table-totals"), exports);
33
36
  tslib_1.__exportStar(require("./sparkline-groups"), exports);
34
37
  tslib_1.__exportStar(require("./rich-text-html"), exports);
38
+ tslib_1.__exportStar(require("./clipboard-html-sanitize"), exports);
35
39
  tslib_1.__exportStar(require("./rich-text-links"), exports);
@@ -52,6 +52,15 @@ export type ParsedRichText = {
52
52
  * Parse an HTML clipboard payload into a hidden, mounted sandbox so
53
53
  * `getComputedStyle` resolves the payload's own `<style>` rules (Excel's
54
54
  * `.fontN` / `.xlNN` classes). Callers must `cleanup()` when done.
55
+ *
56
+ * The payload is untrusted. It is parsed with `DOMParser` (an inert document:
57
+ * no scripts run, no handlers fire, nothing loads), stripped by
58
+ * {@link sanitizeClipboardDocument} — scripts, frames, embeds, SVG/MathML,
59
+ * every `on*` handler, `javascript:`/`data:` links and network-reaching CSS —
60
+ * and only then are the surviving nodes imported into the live sandbox. The
61
+ * import is node-by-node (`importNode`), never a serialize + `innerHTML`
62
+ * round trip, so the parser cannot re-interpret the sanitized tree (mXSS).
63
+ * This sanitization is not optional and runs for every clipboard consumer.
55
64
  */
56
65
  export declare const mountClipboardHtml: (clipboardValue: string) => {
57
66
  root: HTMLDivElement;
@@ -1 +1 @@
1
- {"version":3,"file":"rich-text-html.d.ts","sourceRoot":"","sources":["../../rich-text-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAK5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;IAClC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAgGF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,gBAAgB,MAAM;;;CAmBxD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,GAAG,IAAI,GAAG,SAAS,KAC/B,MAAM,GAAG,SAkBX,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,eAAe,GAC1B,OAAO,MAAM,GAAG,IAAI,GAAG,SAAS,KAC/B,MAAM,GAAG,SAoBX,CAAC;AA+SF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,WAAW,KAAG,cA+DzD,CAAC;AAgBF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,WAAW,KAChB,WAAW,GAAG,SAShB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,MAAM,KACX,cAAc,GAAG,SAkBnB,CAAC"}
1
+ {"version":3,"file":"rich-text-html.d.ts","sourceRoot":"","sources":["../../rich-text-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAO5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;IAClC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAgGF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAAI,gBAAgB,MAAM;;;CA0BxD,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,GAAG,IAAI,GAAG,SAAS,KAC/B,MAAM,GAAG,SAkBX,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,eAAe,GAC1B,OAAO,MAAM,GAAG,IAAI,GAAG,SAAS,KAC/B,MAAM,GAAG,SAoBX,CAAC;AAiTF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,WAAW,KAAG,cA+DzD,CAAC;AAgBF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,WAAW,KAChB,WAAW,GAAG,SAShB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,MAAM,KACX,cAAc,GAAG,SAkBnB,CAAC"}
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.clipboardHtmlToRichText = exports.findSingleClipboardCell = exports.htmlElementToRichText = exports.cssFontSizeToPt = exports.cssColorToHex = exports.mountClipboardHtml = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var clipboard_html_sanitize_1 = require("./clipboard-html-sanitize");
5
6
  var color_1 = require("./color");
6
7
  var dom_1 = require("./dom");
8
+ var string_1 = require("./string");
7
9
  var BLOCK_TAGS = new Set([
8
10
  "p",
9
11
  "div",
@@ -90,17 +92,42 @@ var NON_COLORS = new Set([
90
92
  * Parse an HTML clipboard payload into a hidden, mounted sandbox so
91
93
  * `getComputedStyle` resolves the payload's own `<style>` rules (Excel's
92
94
  * `.fontN` / `.xlNN` classes). Callers must `cleanup()` when done.
95
+ *
96
+ * The payload is untrusted. It is parsed with `DOMParser` (an inert document:
97
+ * no scripts run, no handlers fire, nothing loads), stripped by
98
+ * {@link sanitizeClipboardDocument} — scripts, frames, embeds, SVG/MathML,
99
+ * every `on*` handler, `javascript:`/`data:` links and network-reaching CSS —
100
+ * and only then are the surviving nodes imported into the live sandbox. The
101
+ * import is node-by-node (`importNode`), never a serialize + `innerHTML`
102
+ * round trip, so the parser cannot re-interpret the sanitized tree (mXSS).
103
+ * This sanitization is not optional and runs for every clipboard consumer.
93
104
  */
94
105
  var mountClipboardHtml = function (clipboardValue) {
95
- var _a, _b, _c, _d;
106
+ var e_1, _a;
107
+ var _b, _c;
96
108
  var parser = new DOMParser();
97
- var doc = parser.parseFromString(clipboardValue, "text/html");
109
+ var doc = (0, clipboard_html_sanitize_1.sanitizeClipboardDocument)(parser.parseFromString(clipboardValue, "text/html"));
98
110
  var sandbox = document.createElement("div");
99
111
  sandbox.style.cssText =
100
112
  "position:fixed;left:-10000px;top:-10000px;width:0;height:0;overflow:hidden;opacity:0;pointer-events:none;font-size:10pt;";
101
- sandbox.innerHTML = (_b = (_a = doc.body) === null || _a === void 0 ? void 0 : _a.innerHTML) !== null && _b !== void 0 ? _b : "";
102
- var styles = (_d = (_c = doc.head) === null || _c === void 0 ? void 0 : _c.querySelectorAll("style")) !== null && _d !== void 0 ? _d : [];
103
- styles.forEach(function (style) { return sandbox.appendChild(style.cloneNode(true)); });
113
+ var bodyChildren = doc.body ? Array.from(doc.body.childNodes) : [];
114
+ try {
115
+ for (var bodyChildren_1 = tslib_1.__values(bodyChildren), bodyChildren_1_1 = bodyChildren_1.next(); !bodyChildren_1_1.done; bodyChildren_1_1 = bodyChildren_1.next()) {
116
+ var child = bodyChildren_1_1.value;
117
+ sandbox.appendChild(document.importNode(child, true));
118
+ }
119
+ }
120
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
121
+ finally {
122
+ try {
123
+ if (bodyChildren_1_1 && !bodyChildren_1_1.done && (_a = bodyChildren_1.return)) _a.call(bodyChildren_1);
124
+ }
125
+ finally { if (e_1) throw e_1.error; }
126
+ }
127
+ var styles = (_c = (_b = doc.head) === null || _b === void 0 ? void 0 : _b.querySelectorAll("style")) !== null && _c !== void 0 ? _c : [];
128
+ styles.forEach(function (style) {
129
+ return sandbox.appendChild(document.importNode(style, true));
130
+ });
104
131
  document.body.appendChild(sandbox);
105
132
  return {
106
133
  root: sandbox,
@@ -244,8 +271,10 @@ var readElementFormat = function (element, inherited) {
244
271
  break;
245
272
  }
246
273
  case "a": {
274
+ // The sanitizer already drops unsafe hrefs from clipboard payloads;
275
+ // this converter also serves non-clipboard callers, so re-check here.
247
276
  var href = element.getAttribute("href");
248
- if (href && href.trim()) {
277
+ if (href && href.trim() && (0, string_1.isSafeHyperlinkUri)(href)) {
249
278
  format.link = { uri: href.trim() };
250
279
  }
251
280
  break;
@@ -318,7 +347,7 @@ var isBlockElement = function (element) {
318
347
  return display === "block" || display === "list-item";
319
348
  };
320
349
  var collectSegments = function (node, inherited, segments) {
321
- var e_1, _a;
350
+ var e_2, _a;
322
351
  var _b;
323
352
  if (node.nodeType === Node.TEXT_NODE) {
324
353
  var text = normalizeWhitespace((_b = node.textContent) !== null && _b !== void 0 ? _b : "");
@@ -350,12 +379,12 @@ var collectSegments = function (node, inherited, segments) {
350
379
  collectSegments(child, format, segments);
351
380
  }
352
381
  }
353
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
382
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
354
383
  finally {
355
384
  try {
356
385
  if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
357
386
  }
358
- finally { if (e_1) throw e_1.error; }
387
+ finally { if (e_2) throw e_2.error; }
359
388
  }
360
389
  if (block && segments.length && !endsWithNewline(segments)) {
361
390
  segments.push({ text: "\n", format: inherited });
@@ -377,7 +406,7 @@ var TEXT_KEYS = [
377
406
  ];
378
407
  /** The properties of `format` that differ from `base` (the run's own contribution). */
379
408
  var diffFormat = function (format, base) {
380
- var e_2, _a;
409
+ var e_3, _a;
381
410
  var diff = {};
382
411
  try {
383
412
  for (var TEXT_KEYS_1 = tslib_1.__values(TEXT_KEYS), TEXT_KEYS_1_1 = TEXT_KEYS_1.next(); !TEXT_KEYS_1_1.done; TEXT_KEYS_1_1 = TEXT_KEYS_1.next()) {
@@ -407,17 +436,17 @@ var diffFormat = function (format, base) {
407
436
  diff[key] = normalizedValue;
408
437
  }
409
438
  }
410
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
439
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
411
440
  finally {
412
441
  try {
413
442
  if (TEXT_KEYS_1_1 && !TEXT_KEYS_1_1.done && (_a = TEXT_KEYS_1.return)) _a.call(TEXT_KEYS_1);
414
443
  }
415
- finally { if (e_2) throw e_2.error; }
444
+ finally { if (e_3) throw e_3.error; }
416
445
  }
417
446
  return diff;
418
447
  };
419
448
  var sameFormat = function (a, b) {
420
- var e_3, _a;
449
+ var e_4, _a;
421
450
  var keys = new Set(tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(Object.keys(a)), false), tslib_1.__read(Object.keys(b)), false));
422
451
  try {
423
452
  for (var keys_1 = tslib_1.__values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
@@ -435,12 +464,12 @@ var sameFormat = function (a, b) {
435
464
  }
436
465
  }
437
466
  }
438
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
467
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
439
468
  finally {
440
469
  try {
441
470
  if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
442
471
  }
443
- finally { if (e_3) throw e_3.error; }
472
+ finally { if (e_4) throw e_4.error; }
444
473
  }
445
474
  return true;
446
475
  };
@@ -452,7 +481,7 @@ var isEmptyFormat = function (format) {
452
481
  * table-less HTML) into the engine's rich-text shape. See the module doc.
453
482
  */
454
483
  var htmlElementToRichText = function (root) {
455
- var e_4, _a, e_5, _b;
484
+ var e_5, _a, e_6, _b;
456
485
  var _c, _d, _e;
457
486
  var baseFormat = normalizeBase(readElementFormat(root, {}));
458
487
  var segments = [];
@@ -462,12 +491,12 @@ var htmlElementToRichText = function (root) {
462
491
  collectSegments(child, baseFormat, segments);
463
492
  }
464
493
  }
465
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
494
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
466
495
  finally {
467
496
  try {
468
497
  if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
469
498
  }
470
- finally { if (e_4) throw e_4.error; }
499
+ finally { if (e_5) throw e_5.error; }
471
500
  }
472
501
  // Trim outer whitespace (leading/trailing spaces and line breaks) so the
473
502
  // text matches `extractTextContent`, shifting the segments with it.
@@ -512,12 +541,12 @@ var htmlElementToRichText = function (root) {
512
541
  runs.push({ startIndex: start, endIndex: end, format: format, nodeType: "text" });
513
542
  }
514
543
  }
515
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
544
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
516
545
  finally {
517
546
  try {
518
547
  if (segments_1_1 && !segments_1_1.done && (_b = segments_1.return)) _b.call(segments_1);
519
548
  }
520
- finally { if (e_5) throw e_5.error; }
549
+ finally { if (e_6) throw e_6.error; }
521
550
  }
522
551
  var wholeTextLink = links.find(function (link) { return link.startIndex === 0 && link.endIndex === text.length; });
523
552
  var hyperlink = (_d = wholeTextLink === null || wholeTextLink === void 0 ? void 0 : wholeTextLink.uri) !== null && _d !== void 0 ? _d : (_e = links[0]) === null || _e === void 0 ? void 0 : _e.uri;
@@ -534,7 +563,7 @@ exports.htmlElementToRichText = htmlElementToRichText;
534
563
  // The base drops the segment-only `link` key and `false`/`null` values — a
535
564
  // container can't be "not bold" more than the default already is.
536
565
  var normalizeBase = function (format) {
537
- var e_6, _a;
566
+ var e_7, _a;
538
567
  var base = {};
539
568
  try {
540
569
  for (var TEXT_KEYS_2 = tslib_1.__values(TEXT_KEYS), TEXT_KEYS_2_1 = TEXT_KEYS_2.next(); !TEXT_KEYS_2_1.done; TEXT_KEYS_2_1 = TEXT_KEYS_2.next()) {
@@ -546,12 +575,12 @@ var normalizeBase = function (format) {
546
575
  base[key] = value;
547
576
  }
548
577
  }
549
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
578
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
550
579
  finally {
551
580
  try {
552
581
  if (TEXT_KEYS_2_1 && !TEXT_KEYS_2_1.done && (_a = TEXT_KEYS_2.return)) _a.call(TEXT_KEYS_2);
553
582
  }
554
- finally { if (e_6) throw e_6.error; }
583
+ finally { if (e_7) throw e_7.error; }
555
584
  }
556
585
  return base;
557
586
  };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Excel compares worksheet names case-insensitively: `SHEET1` beside `Sheet1` is refused with
3
+ * "That name is already taken. Try a different one." The calc engine's sheet registry folds names
4
+ * the same way, so two sheets differing only by case would alias one engine sheet — every write to
5
+ * the second lands in the first and `=SHEET1!A1` resolves to whichever was registered first
6
+ * (Athena-Intel/demo-app-monorepo#37167 UI2-1). Both engines' rename / create / duplicate paths and
7
+ * the sheet tabs compare titles through these helpers (the rnc store mirrors them in Rust and
8
+ * surfaces the same message through its `rejections` channel).
9
+ */
10
+ export declare const SHEET_NAME_TAKEN_MESSAGE = "That name is already taken. Try a different one.";
11
+ /** The identity two worksheet titles are compared under: trimmed, Unicode-lowercased. */
12
+ export declare const sheetTitleKey: (title: string) => string;
13
+ /** Whether `a` and `b` name the same worksheet under Excel's comparison. */
14
+ export declare const isSameSheetTitle: (a: string, b: string) => boolean;
15
+ /**
16
+ * Whether another sheet (any but `exceptSheetId`) already holds `title`, case-insensitively. A
17
+ * sheet may always re-case its own title (`Sheet1` → `SHEET1` in place is not a collision).
18
+ */
19
+ export declare const isSheetTitleTaken: (title: string, sheets: Iterable<{
20
+ sheetId: number;
21
+ title: string;
22
+ }>, exceptSheetId?: number) => boolean;
23
+ /**
24
+ * `base` if no title in `existing` holds it (case-insensitively), else the first free
25
+ * `base 1`, `base 2`, … — the suffix scheme the JS engine uses for a new / duplicated sheet.
26
+ * Every candidate stays within `maxLength` (the suffix wins over the tail of a long base).
27
+ */
28
+ export declare const uniqueSheetTitle: (base: string, existing: Iterable<string>, maxLength?: number) => string;
29
+ /** Excel's ceiling for a worksheet name, in UTF-16 code units (what `String#length` counts). */
30
+ export declare const SHEET_NAME_MAX_LENGTH = 31;
31
+ /** The characters Excel never allows anywhere in a worksheet name: `\ / ? * [ ] :`. */
32
+ export declare const SHEET_NAME_ILLEGAL_CHARACTERS: readonly ["\\", "/", "?", "*", "[", "]", ":"];
33
+ /** Excel reserves this title for its change-history sheet (compared case-insensitively). */
34
+ export declare const SHEET_NAME_RESERVED_WORD = "History";
35
+ /**
36
+ * Excel 365's rename-refusal dialog, verbatim — one message for every rule except the duplicate
37
+ * title, which has its own ({@link SHEET_NAME_TAKEN_MESSAGE}).
38
+ */
39
+ export declare const SHEET_NAME_INVALID_MESSAGE: string;
40
+ /** Why a worksheet name was refused — a stable key hosts may branch on; `message` is the dialog text. */
41
+ export type SheetNameRejectionReason = "blank" | "too-long" | "illegal-character" | "apostrophe" | "reserved" | "taken";
42
+ export type SheetNameValidation = {
43
+ ok: true;
44
+ } | {
45
+ ok: false;
46
+ reason: SheetNameRejectionReason;
47
+ message: string;
48
+ };
49
+ /**
50
+ * Excel's worksheet-name rules, in the order its dialog lists them: not blank, at most 31 characters,
51
+ * none of `\ / ? * [ ] :`, no leading or trailing apostrophe, not `History`, and unique among
52
+ * `existing` compared case-insensitively (a sheet may always re-case its own title — pass its id as
53
+ * `exceptSheetId`). Both engines' rename / create paths and the sheet tabs validate through this one
54
+ * function (the rnc store mirrors it in Rust and surfaces the same messages via its `rejections`).
55
+ */
56
+ export declare const validateSheetName: (name: string, existing?: Iterable<{
57
+ sheetId: number;
58
+ title: string;
59
+ } | string>, exceptSheetId?: number) => SheetNameValidation;
60
+ //# sourceMappingURL=sheet-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheet-names.d.ts","sourceRoot":"","sources":["../../sheet-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,wBAAwB,qDACe,CAAC;AAErD,yFAAyF;AACzF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,MAClB,CAAC;AAE7B,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OACjB,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,MAAM,EACb,QAAQ,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACpD,gBAAgB,MAAM,KACrB,OAQF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,UAAU,QAAQ,CAAC,MAAM,CAAC,EAC1B,kBAAoC,KACnC,MAgBF,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,uFAAuF;AACvF,eAAO,MAAM,6BAA6B,+CAAgD,CAAC;AAG3F,4FAA4F;AAC5F,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAO3B,CAAC;AAEb,yGAAyG;AACzG,MAAM,MAAM,wBAAwB,GAChC,OAAO,GACP,UAAU,GACV,mBAAmB,GACnB,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,wBAAwB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,WAAU,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAM,EACpE,gBAAgB,MAAM,KACrB,mBAgCF,CAAC"}