@knime/utils 1.11.1 → 1.12.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/CHANGELOG.md +16 -0
- package/README.md +67 -14
- package/dist/globals.d.ts +8 -0
- package/dist/index.js +751 -0
- package/dist/index.js.map +1 -0
- package/dist/src/capitalize.d.ts +20 -0
- package/dist/src/capitalize.d.ts.map +1 -0
- package/dist/src/dateMinMaxCheck.d.ts +19 -0
- package/dist/src/dateMinMaxCheck.d.ts.map +1 -0
- package/dist/src/debounce.d.ts +4 -0
- package/dist/src/debounce.d.ts.map +1 -0
- package/dist/src/fileExtensions.d.ts +33 -0
- package/dist/src/fileExtensions.d.ts.map +1 -0
- package/dist/src/filters.d.ts +13 -0
- package/dist/src/filters.d.ts.map +1 -0
- package/dist/src/format.d.ts +39 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/getDeepActiveElement.d.ts +3 -0
- package/dist/src/getDeepActiveElement.d.ts.map +1 -0
- package/{src/getWrappedAroundIndex.ts → dist/src/getWrappedAroundIndex.d.ts} +3 -2
- package/dist/src/getWrappedAroundIndex.d.ts.map +1 -0
- package/dist/src/hotkeys/enums.d.ts +11 -0
- package/dist/src/hotkeys/enums.d.ts.map +1 -0
- package/dist/src/hotkeys/format.d.ts +15 -0
- package/dist/src/hotkeys/format.d.ts.map +1 -0
- package/dist/src/hotkeys/index.d.ts +19 -0
- package/dist/src/hotkeys/index.d.ts.map +1 -0
- package/dist/src/hotkeys/match.d.ts +12 -0
- package/dist/src/hotkeys/match.d.ts.map +1 -0
- package/dist/src/hotkeys/modifiers.d.ts +18 -0
- package/dist/src/hotkeys/modifiers.d.ts.map +1 -0
- package/dist/src/hotkeys/types.d.ts +10 -0
- package/dist/src/hotkeys/types.d.ts.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/intervalUtils.d.ts +114 -0
- package/dist/src/intervalUtils.d.ts.map +1 -0
- package/{src/localTimezone.ts → dist/src/localTimezone.d.ts} +3 -2
- package/dist/src/localTimezone.d.ts.map +1 -0
- package/{src/numIntegerDigits.ts → dist/src/numIntegerDigits.d.ts} +3 -2
- package/dist/src/numIntegerDigits.d.ts.map +1 -0
- package/dist/src/platform/index.d.ts +2 -0
- package/dist/src/platform/index.d.ts.map +1 -0
- package/dist/src/platform/navigator.d.ts +11 -0
- package/dist/src/platform/navigator.d.ts.map +1 -0
- package/dist/src/promise/createAbortablePromise.d.ts +32 -0
- package/dist/src/promise/createAbortablePromise.d.ts.map +1 -0
- package/dist/src/promise/createUnwrappedPromise.d.ts +7 -0
- package/dist/src/promise/createUnwrappedPromise.d.ts.map +1 -0
- package/dist/src/promise/index.d.ts +4 -0
- package/dist/src/promise/index.d.ts.map +1 -0
- package/dist/src/promise/retryPromise.d.ts +16 -0
- package/dist/src/promise/retryPromise.d.ts.map +1 -0
- package/dist/src/sanitization.d.ts +8 -0
- package/dist/src/sanitization.d.ts.map +1 -0
- package/dist/src/sleep.d.ts +5 -0
- package/dist/src/sleep.d.ts.map +1 -0
- package/dist/src/truncateString.d.ts +3 -0
- package/dist/src/truncateString.d.ts.map +1 -0
- package/dist/src/updateDate.d.ts +11 -0
- package/dist/src/updateDate.d.ts.map +1 -0
- package/{src/updateTime.ts → dist/src/updateTime.d.ts} +3 -11
- package/dist/src/updateTime.d.ts.map +1 -0
- package/dist/test-utils/index.d.ts +3 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +40 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/muteConsole.d.ts +8 -0
- package/dist/test-utils/muteConsole.d.ts.map +1 -0
- package/package.json +51 -33
- package/src/capitalize.ts +0 -45
- package/src/dateMinMaxCheck.ts +0 -68
- package/src/debounce.ts +0 -28
- package/src/fileExtensions.ts +0 -87
- package/src/filters.ts +0 -114
- package/src/format.ts +0 -113
- package/src/formatHotkeys.ts +0 -98
- package/src/getDeepActiveElement.ts +0 -9
- package/src/hotkeys.ts +0 -32
- package/src/index.ts +0 -76
- package/src/intervalUtils.ts +0 -434
- package/src/navigator.ts +0 -13
- package/src/promise/createAbortablePromise.ts +0 -56
- package/src/promise/createUnwrappedPromise.ts +0 -17
- package/src/promise/index.ts +0 -3
- package/src/promise/retryPromise.ts +0 -45
- package/src/sanitization.ts +0 -72
- package/src/sleep.ts +0 -6
- package/src/truncateString.ts +0 -7
- package/src/updateDate.ts +0 -23
- package/src/uploadManager/index.ts +0 -370
- package/test-utils/index.ts +0 -3
- package/test-utils/muteConsole.ts +0 -54
- /package/{src/audit → audit}/README.md +0 -0
- /package/{src/audit → audit}/bulkAudit.js +0 -0
- /package/{src/audit → audit}/cli.js +0 -0
- /package/{src/config/globals.d.ts → globals.d.ts} +0 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
import { isValid, set, getDate, getMonth, getYear, isAfter, isBefore } from 'date-fns';
|
|
2
|
+
import prettyBytes from 'pretty-bytes';
|
|
3
|
+
import DomPurify from 'dompurify';
|
|
4
|
+
|
|
5
|
+
const capitalize = (input) => input.charAt(0).toUpperCase() + input.substring(1);
|
|
6
|
+
const formats = {
|
|
7
|
+
customFormat: (input, delimiter) => capitalize(input.replace(delimiter, " ").toLowerCase()),
|
|
8
|
+
kebabFormat: (input) => formats.customFormat(input, "-"),
|
|
9
|
+
snakeFormat: (input) => formats.customFormat(input, "_"),
|
|
10
|
+
camelPascalCase: (input) => capitalize(
|
|
11
|
+
(input.match(/([A-Z]?[^A-Z]*)/g) ?? []).slice(0, -1).join(" ").toLowerCase()
|
|
12
|
+
)
|
|
13
|
+
};
|
|
14
|
+
const caseFormatter = ({
|
|
15
|
+
string,
|
|
16
|
+
delimiter,
|
|
17
|
+
format
|
|
18
|
+
}) => {
|
|
19
|
+
if (delimiter) {
|
|
20
|
+
return formats.customFormat(string, delimiter);
|
|
21
|
+
}
|
|
22
|
+
if (format) {
|
|
23
|
+
return formats[format](string, delimiter ?? "");
|
|
24
|
+
}
|
|
25
|
+
return capitalize(string);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const updateDate = (base, date) => {
|
|
29
|
+
if (date) {
|
|
30
|
+
base = isValid(base) ? base : new Date(Date.UTC(0, 0));
|
|
31
|
+
return set(base, {
|
|
32
|
+
year: getYear(date),
|
|
33
|
+
month: getMonth(date),
|
|
34
|
+
date: getDate(date)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return base;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const updateTime = (base, date) => {
|
|
41
|
+
const d = new Date(base);
|
|
42
|
+
if (date) {
|
|
43
|
+
d.setHours(date.getHours());
|
|
44
|
+
d.setMinutes(date.getMinutes());
|
|
45
|
+
d.setSeconds(date.getSeconds());
|
|
46
|
+
d.setMilliseconds(date.getMilliseconds());
|
|
47
|
+
}
|
|
48
|
+
return d;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const isBeforeMinDate = (date, min, checkDate, checkTime) => {
|
|
52
|
+
if (min) {
|
|
53
|
+
if (checkTime && checkDate) {
|
|
54
|
+
return isBefore(date, min);
|
|
55
|
+
}
|
|
56
|
+
if (checkTime) {
|
|
57
|
+
const base = /* @__PURE__ */ new Date(0);
|
|
58
|
+
return isBefore(updateTime(base, date), updateTime(base, min));
|
|
59
|
+
}
|
|
60
|
+
if (checkDate) {
|
|
61
|
+
const base = /* @__PURE__ */ new Date(0);
|
|
62
|
+
return isBefore(updateDate(base, date), updateDate(base, min));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
};
|
|
67
|
+
const isAfterMaxDate = (date, max, checkDate, checkTime) => {
|
|
68
|
+
if (max) {
|
|
69
|
+
if (checkTime && checkDate) {
|
|
70
|
+
return isAfter(date, max);
|
|
71
|
+
}
|
|
72
|
+
if (checkTime) {
|
|
73
|
+
const base = /* @__PURE__ */ new Date(0);
|
|
74
|
+
return isAfter(updateTime(base, date), updateTime(base, max));
|
|
75
|
+
}
|
|
76
|
+
if (checkDate) {
|
|
77
|
+
const base = /* @__PURE__ */ new Date(0);
|
|
78
|
+
return isAfter(updateDate(base, date), updateDate(base, max));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const debounce = (callback, wait) => {
|
|
85
|
+
let timer;
|
|
86
|
+
let lastCall = 0;
|
|
87
|
+
return (...args) => {
|
|
88
|
+
const [value, index] = args;
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const timeFromLastCall = now - lastCall;
|
|
92
|
+
if (timeFromLastCall > wait) {
|
|
93
|
+
lastCall = now;
|
|
94
|
+
callback(value, index);
|
|
95
|
+
} else {
|
|
96
|
+
timer = setTimeout(() => {
|
|
97
|
+
lastCall = now;
|
|
98
|
+
callback(value, index);
|
|
99
|
+
}, wait);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const modeDefinitions = [
|
|
105
|
+
{
|
|
106
|
+
id: "search",
|
|
107
|
+
normalize(searchTerm, caseSensitiveSearch) {
|
|
108
|
+
return caseSensitiveSearch ? searchTerm : searchTerm.toLowerCase();
|
|
109
|
+
},
|
|
110
|
+
test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {
|
|
111
|
+
const testText = caseSensitiveSearch ? text : text.toLowerCase();
|
|
112
|
+
const matches = testText.includes(normalizedSearchTerm);
|
|
113
|
+
return inverseSearch ? !matches : matches;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "wildcard",
|
|
118
|
+
normalize(searchTerm, caseSensitiveSearch) {
|
|
119
|
+
if (searchTerm.length > 0) {
|
|
120
|
+
const escapedSearchTerm = searchTerm.replace(
|
|
121
|
+
/[-[\]{}()+.,\\^$|#\s]/g,
|
|
122
|
+
"\\$&"
|
|
123
|
+
);
|
|
124
|
+
const wildcardSearchTerm = escapedSearchTerm.replace(/\*/g, ".*").replace(/\?/g, ".?");
|
|
125
|
+
searchTerm = `^${wildcardSearchTerm}$`;
|
|
126
|
+
} else {
|
|
127
|
+
return { test: () => false };
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const flags = caseSensitiveSearch ? "" : "i";
|
|
131
|
+
return new RegExp(searchTerm, flags);
|
|
132
|
+
} catch (_error) {
|
|
133
|
+
return /$^/;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {
|
|
137
|
+
const matches = normalizedSearchTerm.test(text);
|
|
138
|
+
return inverseSearch ? !matches : matches;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "regex",
|
|
143
|
+
normalize(searchTerm, caseSensitiveSearch) {
|
|
144
|
+
try {
|
|
145
|
+
const flags = caseSensitiveSearch ? "" : "i";
|
|
146
|
+
return new RegExp(`^(${searchTerm})$`, flags);
|
|
147
|
+
} catch (_error) {
|
|
148
|
+
return /$^/;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {
|
|
152
|
+
const matches = normalizedSearchTerm.test(text);
|
|
153
|
+
return inverseSearch ? !matches : matches;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "type",
|
|
158
|
+
normalize(selectedTypes) {
|
|
159
|
+
return { test: (type) => selectedTypes.includes(type) };
|
|
160
|
+
},
|
|
161
|
+
test(type, normalizedSearchTerm) {
|
|
162
|
+
if (typeof type === "undefined") {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return normalizedSearchTerm.test(type);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
];
|
|
169
|
+
const filters = Object.assign({}, ...modeDefinitions.map((obj) => ({ [obj.id]: obj })));
|
|
170
|
+
|
|
171
|
+
const getLocalTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
172
|
+
|
|
173
|
+
const formatDateString = (dateString, useTimeZone = false) => {
|
|
174
|
+
const date = new Date(dateString);
|
|
175
|
+
if (isNaN(date)) {
|
|
176
|
+
throw Error("Invalid Date format");
|
|
177
|
+
}
|
|
178
|
+
const baseDateOptions = {
|
|
179
|
+
day: "numeric",
|
|
180
|
+
month: "short",
|
|
181
|
+
year: "numeric"
|
|
182
|
+
};
|
|
183
|
+
const dateOptions = useTimeZone ? { ...baseDateOptions, timeZone: getLocalTimeZone() } : baseDateOptions;
|
|
184
|
+
return date.toLocaleDateString("en-US", dateOptions);
|
|
185
|
+
};
|
|
186
|
+
const formatTimeString = (timeString, useTimeZone = false) => {
|
|
187
|
+
const time = new Date(timeString);
|
|
188
|
+
if (isNaN(time)) {
|
|
189
|
+
throw Error("Invalid Date format");
|
|
190
|
+
}
|
|
191
|
+
const baseTimeOptions = {
|
|
192
|
+
hour: "numeric",
|
|
193
|
+
minute: "2-digit"
|
|
194
|
+
};
|
|
195
|
+
const timeOptions = useTimeZone ? { ...baseTimeOptions, timeZone: getLocalTimeZone() } : baseTimeOptions;
|
|
196
|
+
return time.toLocaleTimeString("en-US", timeOptions);
|
|
197
|
+
};
|
|
198
|
+
const formatDateTimeString = (dateTimeString, useTimeZone = false) => {
|
|
199
|
+
return `${formatDateString(dateTimeString, useTimeZone)} ${formatTimeString(
|
|
200
|
+
dateTimeString,
|
|
201
|
+
useTimeZone
|
|
202
|
+
)}`;
|
|
203
|
+
};
|
|
204
|
+
const formatLocalDateTimeString = (date, showTime) => showTime ? formatDateTimeString(date, true) : formatDateString(date, true);
|
|
205
|
+
const formatFileSize = (bytes) => {
|
|
206
|
+
const safeBytes = Number.isFinite(bytes) && bytes >= 0 ? bytes : 0;
|
|
207
|
+
return prettyBytes(safeBytes);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const getDeepActiveElement = () => {
|
|
211
|
+
let element = document?.activeElement;
|
|
212
|
+
while (element?.shadowRoot) {
|
|
213
|
+
element = element?.shadowRoot?.activeElement;
|
|
214
|
+
}
|
|
215
|
+
return element;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const getWrappedAroundIndex = (index, length) => (index % length + length) % length;
|
|
219
|
+
|
|
220
|
+
const extractPeriodFromRegexMatch = (negative, match) => {
|
|
221
|
+
return {
|
|
222
|
+
negative,
|
|
223
|
+
years: parseInt(match[1] ?? "0", 10),
|
|
224
|
+
months: parseInt(match[2] ?? "0", 10),
|
|
225
|
+
weeks: parseInt(match[3] ?? "0", 10),
|
|
226
|
+
days: parseInt(match[4] ?? "0", 10)
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
const extractDurationFromRegexMatch = (negative, match) => {
|
|
230
|
+
const milliseconds = parseInt(match[4]?.padEnd(3, "0") ?? "0", 10);
|
|
231
|
+
return {
|
|
232
|
+
negative,
|
|
233
|
+
hours: parseInt(match[1] ?? "0", 10),
|
|
234
|
+
minutes: parseInt(match[2] ?? "0", 10),
|
|
235
|
+
seconds: parseInt(match[3] ?? "0", 10),
|
|
236
|
+
milliseconds
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
const isZero = (interval) => {
|
|
240
|
+
if (interval.type === "DATE") {
|
|
241
|
+
return interval.interval.years === 0 && interval.interval.months === 0 && interval.interval.weeks === 0 && interval.interval.days === 0;
|
|
242
|
+
} else {
|
|
243
|
+
return interval.interval.hours === 0 && interval.interval.minutes === 0 && interval.interval.seconds === 0 && interval.interval.milliseconds === 0;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const formatIntervalToISOIntervalString = (toFormat) => {
|
|
247
|
+
let output = "P";
|
|
248
|
+
if (toFormat.type === "DATE") {
|
|
249
|
+
output += `${toFormat.interval.years}Y${toFormat.interval.months}M${toFormat.interval.weeks}W${toFormat.interval.days}D`;
|
|
250
|
+
} else {
|
|
251
|
+
output += `T${toFormat.interval.hours}H${toFormat.interval.minutes}M${toFormat.interval.seconds}.${toFormat.interval.milliseconds.toString().padStart(3, "0")}S`;
|
|
252
|
+
}
|
|
253
|
+
if (toFormat.interval.negative) {
|
|
254
|
+
output = `-${output}`;
|
|
255
|
+
}
|
|
256
|
+
return output;
|
|
257
|
+
};
|
|
258
|
+
const formatIntervalToHumanReadableIntervalString = (toFormat) => {
|
|
259
|
+
const formatPart = (value, unit) => {
|
|
260
|
+
if (value === 0) {
|
|
261
|
+
return "";
|
|
262
|
+
} else if (value === 1) {
|
|
263
|
+
return `${value} ${unit} `;
|
|
264
|
+
} else {
|
|
265
|
+
return `${value} ${unit}s `;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
let output = "";
|
|
269
|
+
if (toFormat.type === "DATE") {
|
|
270
|
+
if (isZero(toFormat)) {
|
|
271
|
+
return "0 days";
|
|
272
|
+
}
|
|
273
|
+
output += formatPart(toFormat.interval.years, "year");
|
|
274
|
+
output += formatPart(toFormat.interval.months, "month");
|
|
275
|
+
output += formatPart(toFormat.interval.weeks, "week");
|
|
276
|
+
output += formatPart(toFormat.interval.days, "day");
|
|
277
|
+
} else {
|
|
278
|
+
if (isZero(toFormat)) {
|
|
279
|
+
return "0 seconds";
|
|
280
|
+
}
|
|
281
|
+
output += formatPart(toFormat.interval.hours, "hour");
|
|
282
|
+
output += formatPart(toFormat.interval.minutes, "minute");
|
|
283
|
+
const milliSecondsZero = toFormat.interval.milliseconds === 0;
|
|
284
|
+
if (toFormat.interval.seconds !== 0 || !milliSecondsZero) {
|
|
285
|
+
if (milliSecondsZero) {
|
|
286
|
+
output += formatPart(toFormat.interval.seconds, "second");
|
|
287
|
+
} else {
|
|
288
|
+
output += `${toFormat.interval.seconds}.${toFormat.interval.milliseconds.toString().padStart(3, "0")} seconds `;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (toFormat.interval.negative) {
|
|
293
|
+
output = `-(${output.trim()})`;
|
|
294
|
+
}
|
|
295
|
+
return output.trim();
|
|
296
|
+
};
|
|
297
|
+
const yearsPart = "(\\d+)\\s*y(?:ears?)?";
|
|
298
|
+
const monthsPart = "(\\d+)\\s*m(?:o(?:nths?)?)?";
|
|
299
|
+
const weeksPart = "(\\d+)\\s*w(?:eeks?)?";
|
|
300
|
+
const daysPart = "(\\d+)\\s*d(?:ays?)?";
|
|
301
|
+
const hoursPart = "(\\d+)\\s*h(?:ours?)?";
|
|
302
|
+
const minutesPart = "(\\d+)\\s*m(?:in(?:s|utes?)?)?";
|
|
303
|
+
const secondsPart = "(\\d+)(?:[,.](\\d{1,3}))?\\s*s(?:ec(?:s|onds?)?)?";
|
|
304
|
+
const humanReadablePeriodRegex = new RegExp(
|
|
305
|
+
`^(?:${yearsPart})?\\s*(?:${monthsPart})?\\s*(?:${weeksPart})?\\s*(?:${daysPart})?\\s*$`,
|
|
306
|
+
"i"
|
|
307
|
+
);
|
|
308
|
+
const humanReadableDurationRegex = new RegExp(
|
|
309
|
+
`^(?:${hoursPart})?\\s*(?:${minutesPart})?\\s*(?:${secondsPart})?$`,
|
|
310
|
+
"i"
|
|
311
|
+
);
|
|
312
|
+
const negativeHumanReadablePeriodRegex = new RegExp(
|
|
313
|
+
`^\\s*-\\s*\\(\\s*${humanReadablePeriodRegex.source.replace(/[$^]/g, "")}\\s*\\)\\s*$`,
|
|
314
|
+
"i"
|
|
315
|
+
);
|
|
316
|
+
const negativeHumanReadablePeriodRegexWithSingleField = new RegExp(
|
|
317
|
+
`^\\s*-\\s*(?:\\s*${yearsPart}|${monthsPart}|${weeksPart}|${daysPart})\\s*$`,
|
|
318
|
+
"i"
|
|
319
|
+
);
|
|
320
|
+
const negativeHumanReadableDurationRegex = new RegExp(
|
|
321
|
+
`^\\s*-\\s*\\(\\s*${humanReadableDurationRegex.source.replace(/[$^]/g, "")}\\s*\\)\\s*$`,
|
|
322
|
+
"i"
|
|
323
|
+
);
|
|
324
|
+
const negativeHumanReadableDurationRegexWithSingleField = new RegExp(
|
|
325
|
+
`^\\s*-\\s*(?:\\s*${hoursPart}|${minutesPart}|${secondsPart})\\s*$`,
|
|
326
|
+
"i"
|
|
327
|
+
);
|
|
328
|
+
const parseHumanReadableIntervalString = (intervalString) => {
|
|
329
|
+
intervalString = intervalString?.trim();
|
|
330
|
+
if (!intervalString) {
|
|
331
|
+
throw new Error("Empty interval string");
|
|
332
|
+
}
|
|
333
|
+
const matchPositivePeriod = humanReadablePeriodRegex.exec(intervalString);
|
|
334
|
+
const matchNegativePeriod = negativeHumanReadablePeriodRegex.exec(intervalString) ?? negativeHumanReadablePeriodRegexWithSingleField.exec(intervalString);
|
|
335
|
+
const matchPositiveDuration = humanReadableDurationRegex.exec(intervalString);
|
|
336
|
+
const matchNegativeDuration = negativeHumanReadableDurationRegex.exec(intervalString) ?? negativeHumanReadableDurationRegexWithSingleField.exec(intervalString);
|
|
337
|
+
const matchPeriod = matchPositivePeriod ?? matchNegativePeriod;
|
|
338
|
+
const matchDuration = matchPositiveDuration ?? matchNegativeDuration;
|
|
339
|
+
const negative = (matchNegativePeriod ?? matchNegativeDuration) !== null;
|
|
340
|
+
if (matchDuration && matchPeriod) {
|
|
341
|
+
throw new Error("Ambiguous time format");
|
|
342
|
+
}
|
|
343
|
+
if (matchPeriod) {
|
|
344
|
+
return {
|
|
345
|
+
type: "DATE",
|
|
346
|
+
interval: extractPeriodFromRegexMatch(negative, matchPeriod)
|
|
347
|
+
};
|
|
348
|
+
} else if (matchDuration) {
|
|
349
|
+
return {
|
|
350
|
+
type: "TIME",
|
|
351
|
+
interval: extractDurationFromRegexMatch(negative, matchDuration)
|
|
352
|
+
};
|
|
353
|
+
} else {
|
|
354
|
+
throw new Error(`Invalid human readable time: ${intervalString}`);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
const isValidHumanReadableIntervalString = (time, expectedType) => {
|
|
358
|
+
try {
|
|
359
|
+
const validationResult = parseHumanReadableIntervalString(time);
|
|
360
|
+
const actualType = validationResult.type;
|
|
361
|
+
const negative = validationResult.interval.negative;
|
|
362
|
+
if (actualType === expectedType || expectedType === "DATE_OR_TIME") {
|
|
363
|
+
return {
|
|
364
|
+
valid: true,
|
|
365
|
+
type: actualType,
|
|
366
|
+
negative
|
|
367
|
+
};
|
|
368
|
+
} else {
|
|
369
|
+
return { valid: false };
|
|
370
|
+
}
|
|
371
|
+
} catch (_e) {
|
|
372
|
+
return { valid: false };
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
const parseISOIntervalString = (isoString) => {
|
|
376
|
+
isoString = isoString?.trim();
|
|
377
|
+
if (["", "P", "PT", "-", "-P", "-PT"].includes(isoString)) {
|
|
378
|
+
throw new Error("Empty ISO duration");
|
|
379
|
+
}
|
|
380
|
+
const periodRegex = /^-?P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?$/;
|
|
381
|
+
const durationRegex = /^-?PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:[,.](\d{1,3}))?S)?$/;
|
|
382
|
+
const matchPeriod = periodRegex.exec(isoString);
|
|
383
|
+
const matchDuration = durationRegex.exec(isoString);
|
|
384
|
+
if (matchPeriod) {
|
|
385
|
+
return {
|
|
386
|
+
type: "DATE",
|
|
387
|
+
interval: extractPeriodFromRegexMatch(
|
|
388
|
+
isoString.startsWith("-"),
|
|
389
|
+
matchPeriod
|
|
390
|
+
)
|
|
391
|
+
};
|
|
392
|
+
} else if (matchDuration) {
|
|
393
|
+
return {
|
|
394
|
+
type: "TIME",
|
|
395
|
+
interval: extractDurationFromRegexMatch(
|
|
396
|
+
isoString.startsWith("-"),
|
|
397
|
+
matchDuration
|
|
398
|
+
)
|
|
399
|
+
};
|
|
400
|
+
} else {
|
|
401
|
+
throw new Error(`Invalid ISO duration: ${isoString}`);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const isValidISOIntervalString = (isoString, type) => {
|
|
405
|
+
try {
|
|
406
|
+
const validationResult = parseISOIntervalString(isoString);
|
|
407
|
+
const actualType = validationResult.type;
|
|
408
|
+
const negative = validationResult.interval.negative;
|
|
409
|
+
if (actualType === type || type === "DATE_OR_TIME") {
|
|
410
|
+
return {
|
|
411
|
+
valid: true,
|
|
412
|
+
type: actualType,
|
|
413
|
+
negative
|
|
414
|
+
};
|
|
415
|
+
} else {
|
|
416
|
+
return { valid: false };
|
|
417
|
+
}
|
|
418
|
+
} catch (_e) {
|
|
419
|
+
return { valid: false };
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
const parseGenericIntervalString = (time) => {
|
|
423
|
+
const validISO = isValidISOIntervalString(time, "DATE_OR_TIME");
|
|
424
|
+
const validHumanReadable = isValidHumanReadableIntervalString(
|
|
425
|
+
time,
|
|
426
|
+
"DATE_OR_TIME"
|
|
427
|
+
);
|
|
428
|
+
if (validISO.valid) {
|
|
429
|
+
return parseISOIntervalString(time);
|
|
430
|
+
} else if (validHumanReadable.valid) {
|
|
431
|
+
return parseHumanReadableIntervalString(time);
|
|
432
|
+
} else {
|
|
433
|
+
throw new Error(`Invalid interval string: ${time}`);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
const isValidIntervalString = (time, type) => {
|
|
437
|
+
const validISO = isValidISOIntervalString(time, type);
|
|
438
|
+
const validHumanReadable = isValidHumanReadableIntervalString(time, type);
|
|
439
|
+
if (validISO.valid) {
|
|
440
|
+
return validISO;
|
|
441
|
+
} else if (validHumanReadable.valid) {
|
|
442
|
+
return validHumanReadable;
|
|
443
|
+
} else {
|
|
444
|
+
return { valid: false };
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const intervalUtils = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
449
|
+
__proto__: null,
|
|
450
|
+
formatIntervalToHumanReadableIntervalString,
|
|
451
|
+
formatIntervalToISOIntervalString,
|
|
452
|
+
isValidHumanReadableIntervalString,
|
|
453
|
+
isValidISOIntervalString,
|
|
454
|
+
isValidIntervalString,
|
|
455
|
+
isZero,
|
|
456
|
+
parseGenericIntervalString,
|
|
457
|
+
parseHumanReadableIntervalString,
|
|
458
|
+
parseISOIntervalString
|
|
459
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
460
|
+
|
|
461
|
+
const numIntegerDigits = (input) => Math.max(Math.floor(Math.log10(Math.abs(input))), 0) + 1;
|
|
462
|
+
|
|
463
|
+
class AbortError extends Error {
|
|
464
|
+
}
|
|
465
|
+
const createAbortablePromise = () => {
|
|
466
|
+
const abortController = new AbortController();
|
|
467
|
+
const runAbortablePromise = (request) => {
|
|
468
|
+
return new Promise((resolve, reject) => {
|
|
469
|
+
const abortListener = ({ target }) => {
|
|
470
|
+
abortController.signal.removeEventListener("abort", abortListener);
|
|
471
|
+
const reason = target.reason;
|
|
472
|
+
reject(reason instanceof AbortError ? reason : new AbortError(reason));
|
|
473
|
+
};
|
|
474
|
+
request().then(resolve).catch((error) => {
|
|
475
|
+
if (error instanceof AbortError) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
reject(error);
|
|
479
|
+
});
|
|
480
|
+
abortController.signal.addEventListener("abort", abortListener);
|
|
481
|
+
});
|
|
482
|
+
};
|
|
483
|
+
return { abortController, runAbortablePromise };
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const createUnwrappedPromise = () => {
|
|
487
|
+
let resolve = () => {
|
|
488
|
+
};
|
|
489
|
+
let reject = () => {
|
|
490
|
+
};
|
|
491
|
+
const promise = new Promise((res, rej) => {
|
|
492
|
+
resolve = res;
|
|
493
|
+
reject = rej;
|
|
494
|
+
});
|
|
495
|
+
return { resolve, reject, promise };
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
function sleep(ms) {
|
|
499
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const DEFAULT_RETRY_DELAY_MS = 0;
|
|
503
|
+
const DEFAULT_RETRY_COUNT = 5;
|
|
504
|
+
async function retryPromise({
|
|
505
|
+
fn,
|
|
506
|
+
retryCount = DEFAULT_RETRY_COUNT,
|
|
507
|
+
retryDelayMS = DEFAULT_RETRY_DELAY_MS,
|
|
508
|
+
excludeError
|
|
509
|
+
}) {
|
|
510
|
+
try {
|
|
511
|
+
return await fn();
|
|
512
|
+
} catch (error) {
|
|
513
|
+
if (excludeError?.(error)) {
|
|
514
|
+
throw error;
|
|
515
|
+
}
|
|
516
|
+
if (retryCount > 0) {
|
|
517
|
+
await sleep(retryDelayMS);
|
|
518
|
+
return await retryPromise({
|
|
519
|
+
fn,
|
|
520
|
+
retryCount: retryCount - 1,
|
|
521
|
+
retryDelayMS,
|
|
522
|
+
excludeError
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
throw error;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const index = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
530
|
+
__proto__: null,
|
|
531
|
+
AbortError,
|
|
532
|
+
DEFAULT_RETRY_COUNT,
|
|
533
|
+
DEFAULT_RETRY_DELAY_MS,
|
|
534
|
+
createAbortablePromise,
|
|
535
|
+
createUnwrappedPromise,
|
|
536
|
+
retryPromise
|
|
537
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
538
|
+
|
|
539
|
+
const ALLOWED_TAGS = [
|
|
540
|
+
"p",
|
|
541
|
+
"div",
|
|
542
|
+
"h1",
|
|
543
|
+
"h2",
|
|
544
|
+
"h3",
|
|
545
|
+
"h4",
|
|
546
|
+
"h5",
|
|
547
|
+
"h6",
|
|
548
|
+
"ul",
|
|
549
|
+
"ol",
|
|
550
|
+
"li",
|
|
551
|
+
"blockquote",
|
|
552
|
+
"b",
|
|
553
|
+
"i",
|
|
554
|
+
"s",
|
|
555
|
+
"u",
|
|
556
|
+
"sup",
|
|
557
|
+
"sub",
|
|
558
|
+
"ins",
|
|
559
|
+
"del",
|
|
560
|
+
"strong",
|
|
561
|
+
"strike",
|
|
562
|
+
"tt",
|
|
563
|
+
"code",
|
|
564
|
+
"big",
|
|
565
|
+
"small",
|
|
566
|
+
"br",
|
|
567
|
+
"span",
|
|
568
|
+
"em"
|
|
569
|
+
];
|
|
570
|
+
const sanitizeHTML = (rawHTML, options = {
|
|
571
|
+
allowStyleAttribute: false,
|
|
572
|
+
allowHyperlinks: false
|
|
573
|
+
}) => {
|
|
574
|
+
const { allowStyleAttribute, allowHyperlinks } = options;
|
|
575
|
+
const ALLOWED_ATTR = [
|
|
576
|
+
...allowStyleAttribute ? ["style"] : [],
|
|
577
|
+
...allowHyperlinks ? ["href"] : []
|
|
578
|
+
];
|
|
579
|
+
const allowedTags = allowHyperlinks ? [...ALLOWED_TAGS, "a"] : ALLOWED_TAGS;
|
|
580
|
+
return DomPurify.sanitize(rawHTML, {
|
|
581
|
+
ALLOWED_TAGS: allowedTags,
|
|
582
|
+
ALLOWED_ATTR
|
|
583
|
+
});
|
|
584
|
+
};
|
|
585
|
+
const stripHTML = (rawHTML) => {
|
|
586
|
+
return DomPurify.sanitize(rawHTML, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
|
|
587
|
+
};
|
|
588
|
+
const sanitization = { sanitizeHTML, stripHTML };
|
|
589
|
+
|
|
590
|
+
const defaultMaxLength = 160;
|
|
591
|
+
const truncateString = (string = "", maxLength = defaultMaxLength) => {
|
|
592
|
+
const dots = string.length > maxLength ? "…" : "";
|
|
593
|
+
return `${string.substring(0, maxLength - 1)}${dots}`;
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const getFileExtension = (nameOrPath) => {
|
|
597
|
+
const basename = nameOrPath.split(/[\\/]/).pop() ?? "";
|
|
598
|
+
const parts = basename.split(".");
|
|
599
|
+
if (basename === "" || parts.length === 1) {
|
|
600
|
+
return "";
|
|
601
|
+
}
|
|
602
|
+
return parts.at(-1) ?? "";
|
|
603
|
+
};
|
|
604
|
+
const KNAR = Object.freeze({
|
|
605
|
+
extension: "knar",
|
|
606
|
+
mimeType: "application/vnd.knime.workflow-group+zip",
|
|
607
|
+
matches(file) {
|
|
608
|
+
const extension = getFileExtension(file.name);
|
|
609
|
+
return extension === this.extension;
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
const KNWF = Object.freeze({
|
|
613
|
+
extension: "knwf",
|
|
614
|
+
mimeType: "application/vnd.knime.workflow+zip",
|
|
615
|
+
matches(file) {
|
|
616
|
+
const extension = getFileExtension(file.name);
|
|
617
|
+
return extension === this.extension;
|
|
618
|
+
},
|
|
619
|
+
/**
|
|
620
|
+
* Gets the name of a .knwf file without the extension. If the file is not
|
|
621
|
+
* matched as a .knwf file then this function will return the default value,
|
|
622
|
+
* which is empty string ("") if param is not provided
|
|
623
|
+
*/
|
|
624
|
+
getNameOrDefault(file, defaultValue = "") {
|
|
625
|
+
if (!this.matches(file)) {
|
|
626
|
+
return defaultValue;
|
|
627
|
+
}
|
|
628
|
+
return file.name.replace(`.${this.extension}`, "");
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
const knimeFileFormats = { KNAR, KNWF };
|
|
632
|
+
const getFileMimeType = (file) => {
|
|
633
|
+
const DEFAULT_MIMETYPE = "application/octet-stream";
|
|
634
|
+
const extension = getFileExtension(file.name);
|
|
635
|
+
if (!extension) {
|
|
636
|
+
return DEFAULT_MIMETYPE;
|
|
637
|
+
}
|
|
638
|
+
if (KNWF.matches(file)) {
|
|
639
|
+
return KNWF.mimeType;
|
|
640
|
+
}
|
|
641
|
+
if (KNAR.matches(file)) {
|
|
642
|
+
return KNAR.mimeType;
|
|
643
|
+
}
|
|
644
|
+
if (!file.type) {
|
|
645
|
+
return DEFAULT_MIMETYPE;
|
|
646
|
+
}
|
|
647
|
+
return file.type;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
const hotkeyPlatform = {
|
|
651
|
+
MAC_OS: "macOS",
|
|
652
|
+
OTHER: "other"
|
|
653
|
+
};
|
|
654
|
+
Object.values(hotkeyPlatform);
|
|
655
|
+
|
|
656
|
+
const isMac = () => navigator?.userAgent?.toLowerCase()?.includes("mac");
|
|
657
|
+
const isWindows = () => navigator?.userAgent?.toLowerCase()?.includes("windows");
|
|
658
|
+
|
|
659
|
+
const navigator$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
660
|
+
__proto__: null,
|
|
661
|
+
isMac,
|
|
662
|
+
isWindows
|
|
663
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
664
|
+
|
|
665
|
+
const globalKeyMap = {
|
|
666
|
+
ArrowUp: "↑",
|
|
667
|
+
ArrowDown: "↓",
|
|
668
|
+
ArrowLeft: "←",
|
|
669
|
+
ArrowRight: "→",
|
|
670
|
+
Enter: "↵",
|
|
671
|
+
" ": "Space",
|
|
672
|
+
// we use event.key and there space is an actual space not the code "Space"
|
|
673
|
+
CtrlOrCmd: "Ctrl"
|
|
674
|
+
};
|
|
675
|
+
const MacOSkeyMap = {
|
|
676
|
+
Shift: "⇧",
|
|
677
|
+
Delete: "⌫",
|
|
678
|
+
CtrlOrCmd: "⌘",
|
|
679
|
+
Ctrl: "⌃",
|
|
680
|
+
Alt: "⌥",
|
|
681
|
+
Enter: "↩"
|
|
682
|
+
};
|
|
683
|
+
const formatHotkey = (hotkey, platform) => {
|
|
684
|
+
const mapSymbols = (formatMap) => (key) => formatMap[key] ?? key;
|
|
685
|
+
const pipe = (...fns) => fns.reduce(
|
|
686
|
+
(f, g) => (arg) => g(f(arg)),
|
|
687
|
+
(arg) => arg
|
|
688
|
+
);
|
|
689
|
+
const macKeyFormatter = pipe(
|
|
690
|
+
mapSymbols(MacOSkeyMap),
|
|
691
|
+
mapSymbols(globalKeyMap)
|
|
692
|
+
);
|
|
693
|
+
const generalKeyFormatter = mapSymbols(globalKeyMap);
|
|
694
|
+
const useMacFormatter = platform === void 0 ? isMac() : platform === hotkeyPlatform.MAC_OS;
|
|
695
|
+
return useMacFormatter ? macKeyFormatter(hotkey) : generalKeyFormatter(hotkey);
|
|
696
|
+
};
|
|
697
|
+
const getDefaultSeparator = () => isMac() ? " " : "+";
|
|
698
|
+
const formatHotkeys = (hotkeys, getSeparator = getDefaultSeparator) => hotkeys.map((hotkey) => formatHotkey(hotkey)).join(getSeparator());
|
|
699
|
+
|
|
700
|
+
const isDigitKeyInRange = (keyCode, hotkey) => {
|
|
701
|
+
const digitRangeLength = 3;
|
|
702
|
+
if (hotkey.length !== digitRangeLength || !keyCode?.startsWith("Digit")) {
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
const keyNumber = Number(keyCode.slice("Digit".length));
|
|
706
|
+
const [lower, upper] = hotkey.split("-");
|
|
707
|
+
return Boolean(lower) && Boolean(upper) && Number.parseInt(lower, 10) <= keyNumber && keyNumber <= Number.parseInt(upper, 10);
|
|
708
|
+
};
|
|
709
|
+
const match = (event, hotkeys) => {
|
|
710
|
+
const { key, code, metaKey, ctrlKey, shiftKey, altKey } = event;
|
|
711
|
+
const modifiers = hotkeys.slice();
|
|
712
|
+
const character = modifiers.pop() ?? "";
|
|
713
|
+
const ctrlOrMeta = isMac() ? "Meta" : "Ctrl";
|
|
714
|
+
const platformModifiers = new Set(
|
|
715
|
+
modifiers.map(
|
|
716
|
+
(modifier) => modifier === "CtrlOrCmd" ? ctrlOrMeta : modifier
|
|
717
|
+
)
|
|
718
|
+
);
|
|
719
|
+
const metaMatches = Boolean(metaKey) === platformModifiers.has("Meta");
|
|
720
|
+
const ctrlMatches = Boolean(ctrlKey) === platformModifiers.has("Ctrl");
|
|
721
|
+
const shiftMatches = Boolean(shiftKey) === platformModifiers.has("Shift");
|
|
722
|
+
const altMatches = Boolean(altKey) === platformModifiers.has("Alt");
|
|
723
|
+
const keysMatch = (
|
|
724
|
+
// keys are matched case insensitively
|
|
725
|
+
key.toUpperCase() === character.toUpperCase() || character.includes("-") && isDigitKeyInRange(code, character) || // on mac 'backspace' can be used instead of delete
|
|
726
|
+
isMac() && character === "Delete" && key === "Backspace"
|
|
727
|
+
);
|
|
728
|
+
return metaMatches && ctrlMatches && shiftMatches && altMatches && keysMatch;
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
const isModifierKeyPressed = (event) => {
|
|
732
|
+
return event.ctrlKey || event.metaKey || event.altKey || event.shiftKey;
|
|
733
|
+
};
|
|
734
|
+
const isKeyWithoutModifiers = (event, keys) => {
|
|
735
|
+
const keyList = Array.isArray(keys) ? keys : [keys];
|
|
736
|
+
return keyList.includes(event.key) && !isModifierKeyPressed(event);
|
|
737
|
+
};
|
|
738
|
+
const getMetaOrCtrlKey = () => {
|
|
739
|
+
return isMac() ? "metaKey" : "ctrlKey";
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
const hotkeys = {
|
|
743
|
+
formatHotkeys,
|
|
744
|
+
formatHotkey,
|
|
745
|
+
getDefaultSeparator,
|
|
746
|
+
hotkeyPlatform,
|
|
747
|
+
match
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
export { capitalize, caseFormatter, debounce, filters, formatDateString, formatDateTimeString, formatFileSize, formatLocalDateTimeString, formatTimeString, getDeepActiveElement, getFileExtension, getFileMimeType, getLocalTimeZone, getMetaOrCtrlKey, getWrappedAroundIndex, hotkeys, intervalUtils, isAfterMaxDate, isBeforeMinDate, isKeyWithoutModifiers, isModifierKeyPressed, knimeFileFormats, match, navigator$1 as navigatorUtils, numIntegerDigits, index as promise, sanitization, sleep, truncateString, updateDate, updateTime };
|
|
751
|
+
//# sourceMappingURL=index.js.map
|