@paulirish/trace_engine 0.0.10 → 0.0.11
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/analyze-trace.mjs +1 -1
- package/core/platform/DevToolsPath.d.ts +4 -13
- package/core/platform/DevToolsPath.js +7 -4
- package/core/platform/DevToolsPath.js.map +1 -7
- package/core/platform/MimeType.d.ts +27 -0
- package/core/platform/MimeType.js +119 -86
- package/core/platform/MimeType.js.map +1 -7
- package/core/platform/Timing.d.ts +7 -0
- package/core/platform/Timing.js +7 -4
- package/core/platform/Timing.js.map +1 -7
- package/core/platform/UIString.d.ts +2 -5
- package/core/platform/UIString.js +5 -2
- package/core/platform/UIString.js.map +1 -7
- package/core/platform/UserVisibleError.js +19 -10
- package/core/platform/UserVisibleError.js.map +1 -7
- package/core/platform/array-utilities.d.ts +48 -10
- package/core/platform/array-utilities.js +160 -124
- package/core/platform/array-utilities.js.map +1 -7
- package/core/platform/brand.d.ts +14 -0
- package/core/platform/brand.js +5 -1
- package/core/platform/brand.js.map +1 -7
- package/core/platform/date-utilities.js +10 -6
- package/core/platform/date-utilities.js.map +1 -7
- package/core/platform/dom-utilities.d.ts +3 -1
- package/core/platform/dom-utilities.js +94 -83
- package/core/platform/dom-utilities.js.map +1 -7
- package/core/platform/keyboard-utilities.d.ts +2 -0
- package/core/platform/keyboard-utilities.js +15 -24
- package/core/platform/keyboard-utilities.js.map +1 -7
- package/core/platform/map-utilities.d.ts +4 -0
- package/core/platform/map-utilities.js +66 -60
- package/core/platform/map-utilities.js.map +1 -7
- package/core/platform/number-utilities.js +66 -55
- package/core/platform/number-utilities.js.map +1 -7
- package/core/platform/platform.d.ts +5 -1
- package/core/platform/platform.js +54 -37
- package/core/platform/platform.js.map +1 -7
- package/core/platform/promise-utilities.d.ts +10 -0
- package/core/platform/promise-utilities.js +16 -8
- package/core/platform/promise-utilities.js.map +1 -7
- package/core/platform/set-utilities.js +20 -17
- package/core/platform/set-utilities.js.map +1 -7
- package/core/platform/string-utilities.d.ts +32 -1
- package/core/platform/string-utilities.js +453 -379
- package/core/platform/string-utilities.js.map +1 -7
- package/core/platform/typescript-utilities.d.ts +5 -5
- package/core/platform/typescript-utilities.js +19 -7
- package/core/platform/typescript-utilities.js.map +1 -7
- package/generated/protocol.d.ts +2081 -347
- package/generated/protocol.js +5 -2230
- package/models/cpu_profile/CPUProfileDataModel.d.ts +77 -0
- package/models/cpu_profile/CPUProfileDataModel.js +492 -359
- package/models/cpu_profile/CPUProfileDataModel.js.map +1 -7
- package/models/cpu_profile/ProfileTreeModel.d.ts +29 -0
- package/models/cpu_profile/ProfileTreeModel.js +87 -82
- package/models/cpu_profile/ProfileTreeModel.js.map +1 -7
- package/models/cpu_profile/cpu_profile.d.ts +3 -0
- package/models/cpu_profile/cpu_profile.js +7 -7
- package/models/cpu_profile/cpu_profile.js.map +1 -7
- package/models/trace/EntriesFilter.d.ts +55 -0
- package/models/trace/EntriesFilter.js +227 -166
- package/models/trace/EntriesFilter.js.map +1 -7
- package/models/trace/LegacyTracingModel.js.map +1 -7
- package/models/trace/ModelImpl.d.ts +110 -0
- package/models/trace/ModelImpl.js +161 -102
- package/models/trace/ModelImpl.js.map +1 -7
- package/models/trace/Processor.d.ts +36 -0
- package/models/trace/Processor.js +197 -163
- package/models/trace/Processor.js.map +1 -7
- package/models/trace/TracingManager.js.map +1 -7
- package/models/trace/extras/FetchNodes.d.ts +46 -0
- package/models/trace/extras/FetchNodes.js +132 -91
- package/models/trace/extras/FetchNodes.js.map +1 -7
- package/models/trace/extras/FilmStrip.d.ts +19 -0
- package/models/trace/extras/FilmStrip.js +38 -31
- package/models/trace/extras/FilmStrip.js.map +1 -7
- package/models/trace/extras/MainThreadActivity.d.ts +2 -0
- package/models/trace/extras/MainThreadActivity.js +72 -56
- package/models/trace/extras/MainThreadActivity.js.map +1 -7
- package/models/trace/extras/Metadata.d.ts +2 -0
- package/models/trace/extras/Metadata.js +42 -26
- package/models/trace/extras/Metadata.js.map +1 -7
- package/models/trace/extras/extras.js.map +1 -7
- package/models/trace/handlers/AnimationHandler.d.ts +8 -0
- package/models/trace/handlers/AnimationHandler.js +22 -20
- package/models/trace/handlers/AnimationHandler.js.map +1 -7
- package/models/trace/handlers/AuctionWorkletsHandler.d.ts +8 -0
- package/models/trace/handlers/AuctionWorkletsHandler.js +143 -89
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -7
- package/models/trace/handlers/FramesHandler.d.ts +76 -0
- package/models/trace/handlers/FramesHandler.js +424 -355
- package/models/trace/handlers/FramesHandler.js.map +1 -7
- package/models/trace/handlers/GPUHandler.d.ts +11 -0
- package/models/trace/handlers/GPUHandler.js +41 -37
- package/models/trace/handlers/GPUHandler.js.map +1 -7
- package/models/trace/handlers/InitiatorsHandler.d.ts +10 -0
- package/models/trace/handlers/InitiatorsHandler.js +164 -113
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -7
- package/models/trace/handlers/InvalidationsHandler.d.ts +10 -0
- package/models/trace/handlers/InvalidationsHandler.js +101 -79
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -7
- package/models/trace/handlers/LargestImagePaintHandler.d.ts +5 -0
- package/models/trace/handlers/LargestImagePaintHandler.js +32 -12
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -7
- package/models/trace/handlers/LargestTextPaintHandler.d.ts +5 -0
- package/models/trace/handlers/LargestTextPaintHandler.js +20 -12
- package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -7
- package/models/trace/handlers/LayerTreeHandler.d.ts +13 -0
- package/models/trace/handlers/LayerTreeHandler.js +96 -70
- package/models/trace/handlers/LayerTreeHandler.js.map +1 -7
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +44 -0
- package/models/trace/handlers/LayoutShiftsHandler.js +304 -227
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -7
- package/models/trace/handlers/MemoryHandler.d.ts +7 -0
- package/models/trace/handlers/MemoryHandler.js +14 -11
- package/models/trace/handlers/MemoryHandler.js.map +1 -7
- package/models/trace/handlers/MetaHandler.d.ts +37 -0
- package/models/trace/handlers/MetaHandler.js +314 -226
- package/models/trace/handlers/MetaHandler.js.map +1 -7
- package/models/trace/handlers/ModelHandlers.d.ts +21 -0
- package/models/trace/handlers/ModelHandlers.js +25 -22
- package/models/trace/handlers/ModelHandlers.js.map +1 -7
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +17 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +342 -218
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -7
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +67 -0
- package/models/trace/handlers/PageLoadMetricsHandler.js +357 -284
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -7
- package/models/trace/handlers/RendererHandler.d.ts +101 -0
- package/models/trace/handlers/RendererHandler.js +295 -191
- package/models/trace/handlers/RendererHandler.js.map +1 -7
- package/models/trace/handlers/SamplesHandler.d.ts +46 -0
- package/models/trace/handlers/SamplesHandler.js +195 -158
- package/models/trace/handlers/SamplesHandler.js.map +1 -7
- package/models/trace/handlers/ScreenshotsHandler.d.ts +7 -0
- package/models/trace/handlers/ScreenshotsHandler.js +63 -41
- package/models/trace/handlers/ScreenshotsHandler.js.map +1 -7
- package/models/trace/handlers/Threads.d.ts +33 -0
- package/models/trace/handlers/Threads.js +85 -67
- package/models/trace/handlers/Threads.js.map +1 -7
- package/models/trace/handlers/UserInteractionsHandler.d.ts +57 -0
- package/models/trace/handlers/UserInteractionsHandler.js +240 -141
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -7
- package/models/trace/handlers/UserTimingsHandler.d.ts +28 -0
- package/models/trace/handlers/UserTimingsHandler.js +91 -80
- package/models/trace/handlers/UserTimingsHandler.js.map +1 -7
- package/models/trace/handlers/WarningsHandler.d.ts +14 -0
- package/models/trace/handlers/WarningsHandler.js +100 -62
- package/models/trace/handlers/WarningsHandler.js.map +1 -7
- package/models/trace/handlers/WorkersHandler.d.ts +11 -0
- package/models/trace/handlers/WorkersHandler.js +40 -38
- package/models/trace/handlers/WorkersHandler.js.map +1 -7
- package/models/trace/handlers/handlers.d.ts +3 -0
- package/models/trace/handlers/handlers.js +7 -4
- package/models/trace/handlers/handlers.js.map +1 -7
- package/models/trace/handlers/types.d.ts +45 -0
- package/models/trace/handlers/types.js +15 -15
- package/models/trace/handlers/types.js.map +1 -7
- package/models/trace/helpers/SamplesIntegrator.d.ts +49 -0
- package/models/trace/helpers/SamplesIntegrator.js +381 -204
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -7
- package/models/trace/helpers/Timing.d.ts +26 -0
- package/models/trace/helpers/Timing.js +131 -110
- package/models/trace/helpers/Timing.js.map +1 -7
- package/models/trace/helpers/Trace.d.ts +37 -0
- package/models/trace/helpers/Trace.js +200 -166
- package/models/trace/helpers/Trace.js.map +1 -7
- package/models/trace/helpers/TreeHelpers.d.ts +90 -0
- package/models/trace/helpers/TreeHelpers.js +203 -100
- package/models/trace/helpers/TreeHelpers.js.map +1 -7
- package/models/trace/helpers/helpers.d.ts +4 -0
- package/models/trace/helpers/helpers.js +8 -5
- package/models/trace/helpers/helpers.js.map +1 -7
- package/models/trace/root-causes/LayoutShift.d.ts +119 -0
- package/models/trace/root-causes/LayoutShift.js +470 -323
- package/models/trace/root-causes/LayoutShift.js.map +1 -7
- package/models/trace/root-causes/RootCauses.d.ts +14 -0
- package/models/trace/root-causes/RootCauses.js +9 -6
- package/models/trace/root-causes/RootCauses.js.map +1 -7
- package/models/trace/root-causes/root-causes.d.ts +1 -0
- package/models/trace/root-causes/root-causes.js +5 -2
- package/models/trace/root-causes/root-causes.js.map +1 -7
- package/models/trace/trace.d.ts +11 -0
- package/models/trace/trace.js +17 -23
- package/models/trace/trace.js.map +1 -7
- package/models/trace/types/Configuration.d.ts +33 -0
- package/models/trace/types/Configuration.js +25 -14
- package/models/trace/types/Configuration.js.map +1 -7
- package/models/trace/types/File.d.ts +23 -0
- package/models/trace/types/File.js +5 -6
- package/models/trace/types/File.js.map +1 -7
- package/models/trace/types/Timing.d.ts +25 -0
- package/models/trace/types/Timing.js +10 -11
- package/models/trace/types/Timing.js.map +1 -7
- package/models/trace/types/TraceEvents.d.ts +1571 -0
- package/models/trace/types/TraceEvents.js +174 -381
- package/models/trace/types/TraceEvents.js.map +1 -7
- package/models/trace/types/types.d.ts +4 -0
- package/models/trace/types/types.js +8 -5
- package/models/trace/types/types.js.map +1 -7
- package/package.json +1 -1
- package/TracingManager.js +0 -0
- package/extras/extras.js +0 -0
- package/trace.mjs +0 -6980
- package/trace.mjs.map +0 -8
|
@@ -1,439 +1,513 @@
|
|
|
1
|
+
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
1
4
|
export const escapeCharacters = (inputString, charsToEscape) => {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
let foundChar = false;
|
|
6
|
+
for (let i = 0; i < charsToEscape.length; ++i) {
|
|
7
|
+
if (inputString.indexOf(charsToEscape.charAt(i)) !== -1) {
|
|
8
|
+
foundChar = true;
|
|
9
|
+
break;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
if (!foundChar) {
|
|
13
|
+
return String(inputString);
|
|
14
|
+
}
|
|
15
|
+
let result = '';
|
|
16
|
+
for (let i = 0; i < inputString.length; ++i) {
|
|
17
|
+
if (charsToEscape.indexOf(inputString.charAt(i)) !== -1) {
|
|
18
|
+
result += '\\';
|
|
19
|
+
}
|
|
20
|
+
result += inputString.charAt(i);
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
20
23
|
};
|
|
21
24
|
const toHexadecimal = (charCode, padToLength) => {
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
return charCode.toString(16).toUpperCase().padStart(padToLength, '0');
|
|
26
|
+
};
|
|
27
|
+
// Remember to update the third group in the regexps patternsToEscape and
|
|
28
|
+
// patternsToEscapePlusSingleQuote when adding new entries in this map.
|
|
29
|
+
const escapedReplacements = new Map([
|
|
30
|
+
['\b', '\\b'],
|
|
31
|
+
['\f', '\\f'],
|
|
32
|
+
['\n', '\\n'],
|
|
33
|
+
['\r', '\\r'],
|
|
34
|
+
['\t', '\\t'],
|
|
35
|
+
['\v', '\\v'],
|
|
36
|
+
['\'', '\\\''],
|
|
37
|
+
['\\', '\\\\'],
|
|
38
|
+
['<!--', '\\x3C!--'],
|
|
39
|
+
['<script', '\\x3Cscript'],
|
|
40
|
+
['</script', '\\x3C/script'],
|
|
36
41
|
]);
|
|
37
42
|
export const formatAsJSLiteral = (content) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
escapedContent = content.replaceAll(patternsToEscape, escapePattern);
|
|
68
|
-
} else {
|
|
69
|
-
quote = "'";
|
|
70
|
-
escapedContent = content.replaceAll(patternsToEscapePlusSingleQuote, escapePattern);
|
|
71
|
-
}
|
|
72
|
-
return `${quote}${escapedContent}${quote}`;
|
|
73
|
-
};
|
|
74
|
-
export const sprintf = (fmt, ...args) => {
|
|
75
|
-
let argIndex = 0;
|
|
76
|
-
const RE = /%(?:(\d+)\$)?(?:\.(\d*))?([%dfs])/g;
|
|
77
|
-
return fmt.replaceAll(RE, (_, index, precision, specifier) => {
|
|
78
|
-
if (specifier === "%") {
|
|
79
|
-
return "%";
|
|
43
|
+
const patternsToEscape = /(\\|<(?:!--|\/?script))|(\p{Control})|(\p{Surrogate})/gu;
|
|
44
|
+
const patternsToEscapePlusSingleQuote = /(\\|'|<(?:!--|\/?script))|(\p{Control})|(\p{Surrogate})/gu;
|
|
45
|
+
const escapePattern = (match, pattern, controlChar, loneSurrogate) => {
|
|
46
|
+
if (controlChar) {
|
|
47
|
+
if (escapedReplacements.has(controlChar)) {
|
|
48
|
+
// @ts-ignore https://github.com/microsoft/TypeScript/issues/13086
|
|
49
|
+
return escapedReplacements.get(controlChar);
|
|
50
|
+
}
|
|
51
|
+
const twoDigitHex = toHexadecimal(controlChar.charCodeAt(0), 2);
|
|
52
|
+
return '\\x' + twoDigitHex;
|
|
53
|
+
}
|
|
54
|
+
if (loneSurrogate) {
|
|
55
|
+
const fourDigitHex = toHexadecimal(loneSurrogate.charCodeAt(0), 4);
|
|
56
|
+
return '\\u' + fourDigitHex;
|
|
57
|
+
}
|
|
58
|
+
if (pattern) {
|
|
59
|
+
return escapedReplacements.get(pattern) || '';
|
|
60
|
+
}
|
|
61
|
+
return match;
|
|
62
|
+
};
|
|
63
|
+
let escapedContent = '';
|
|
64
|
+
let quote = '';
|
|
65
|
+
if (!content.includes('\'')) {
|
|
66
|
+
quote = '\'';
|
|
67
|
+
escapedContent = content.replaceAll(patternsToEscape, escapePattern);
|
|
68
|
+
}
|
|
69
|
+
else if (!content.includes('"')) {
|
|
70
|
+
quote = '"';
|
|
71
|
+
escapedContent = content.replaceAll(patternsToEscape, escapePattern);
|
|
80
72
|
}
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
throw new RangeError(`Invalid parameter index ${argIndex + 1}`);
|
|
85
|
-
}
|
|
73
|
+
else if (!content.includes('`') && !content.includes('${')) {
|
|
74
|
+
quote = '`';
|
|
75
|
+
escapedContent = content.replaceAll(patternsToEscape, escapePattern);
|
|
86
76
|
}
|
|
87
|
-
|
|
88
|
-
|
|
77
|
+
else {
|
|
78
|
+
quote = '\'';
|
|
79
|
+
escapedContent = content.replaceAll(patternsToEscapePlusSingleQuote, escapePattern);
|
|
80
|
+
}
|
|
81
|
+
return `${quote}${escapedContent}${quote}`;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* This implements a subset of the sprintf() function described in the Single UNIX
|
|
85
|
+
* Specification. It supports the %s, %f, %d, and %% formatting specifiers, and
|
|
86
|
+
* understands the %m$d notation to select the m-th parameter for this substitution,
|
|
87
|
+
* as well as the optional precision for %s, %f, and %d.
|
|
88
|
+
*
|
|
89
|
+
* @param fmt format string.
|
|
90
|
+
* @param args parameters to the format string.
|
|
91
|
+
* @returns the formatted output string.
|
|
92
|
+
*/
|
|
93
|
+
export const sprintf = (fmt, ...args) => {
|
|
94
|
+
let argIndex = 0;
|
|
95
|
+
const RE = /%(?:(\d+)\$)?(?:\.(\d*))?([%dfs])/g;
|
|
96
|
+
return fmt.replaceAll(RE, (_, index, precision, specifier) => {
|
|
97
|
+
if (specifier === '%') {
|
|
98
|
+
return '%';
|
|
99
|
+
}
|
|
100
|
+
if (index !== undefined) {
|
|
101
|
+
argIndex = parseInt(index, 10) - 1;
|
|
102
|
+
if (argIndex < 0) {
|
|
103
|
+
throw new RangeError(`Invalid parameter index ${argIndex + 1}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (argIndex >= args.length) {
|
|
107
|
+
throw new RangeError(`Expected at least ${argIndex + 1} format parameters, but only ${args.length} where given.`);
|
|
108
|
+
}
|
|
109
|
+
if (specifier === 's') {
|
|
110
|
+
const argValue = String(args[argIndex++]);
|
|
111
|
+
if (precision !== undefined) {
|
|
112
|
+
return argValue.substring(0, Number(precision));
|
|
113
|
+
}
|
|
114
|
+
return argValue;
|
|
115
|
+
}
|
|
116
|
+
let argValue = Number(args[argIndex++]);
|
|
117
|
+
if (isNaN(argValue)) {
|
|
118
|
+
argValue = 0;
|
|
119
|
+
}
|
|
120
|
+
if (specifier === 'd') {
|
|
121
|
+
return String(Math.floor(argValue)).padStart(Number(precision), '0');
|
|
122
|
+
}
|
|
123
|
+
if (precision !== undefined) {
|
|
124
|
+
return argValue.toFixed(Number(precision));
|
|
125
|
+
}
|
|
126
|
+
return String(argValue);
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
export const toBase64 = (inputString) => {
|
|
130
|
+
/* note to the reader: we can't use btoa here because we need to
|
|
131
|
+
* support Unicode correctly. See the test cases for this function and
|
|
132
|
+
* also
|
|
133
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem
|
|
134
|
+
*/
|
|
135
|
+
function encodeBits(b) {
|
|
136
|
+
return b < 26 ? b + 65 : b < 52 ? b + 71 : b < 62 ? b - 4 : b === 62 ? 43 : b === 63 ? 47 : 65;
|
|
89
137
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
138
|
+
const encoder = new TextEncoder();
|
|
139
|
+
const data = encoder.encode(inputString.toString());
|
|
140
|
+
const n = data.length;
|
|
141
|
+
let encoded = '';
|
|
142
|
+
if (n === 0) {
|
|
143
|
+
return encoded;
|
|
96
144
|
}
|
|
97
|
-
let
|
|
98
|
-
|
|
99
|
-
|
|
145
|
+
let shift;
|
|
146
|
+
let v = 0;
|
|
147
|
+
for (let i = 0; i < n; i++) {
|
|
148
|
+
shift = i % 3;
|
|
149
|
+
v |= data[i] << (16 >>> shift & 24);
|
|
150
|
+
if (shift === 2) {
|
|
151
|
+
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), encodeBits(v >>> 6 & 63), encodeBits(v & 63));
|
|
152
|
+
v = 0;
|
|
153
|
+
}
|
|
100
154
|
}
|
|
101
|
-
if (
|
|
102
|
-
|
|
155
|
+
if (shift === 0) {
|
|
156
|
+
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), 61, 61);
|
|
103
157
|
}
|
|
104
|
-
if (
|
|
105
|
-
|
|
158
|
+
else if (shift === 1) {
|
|
159
|
+
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), encodeBits(v >>> 6 & 63), 61);
|
|
106
160
|
}
|
|
107
|
-
return String(argValue);
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
export const toBase64 = (inputString) => {
|
|
111
|
-
function encodeBits(b) {
|
|
112
|
-
return b < 26 ? b + 65 : b < 52 ? b + 71 : b < 62 ? b - 4 : b === 62 ? 43 : b === 63 ? 47 : 65;
|
|
113
|
-
}
|
|
114
|
-
const encoder = new TextEncoder();
|
|
115
|
-
const data = encoder.encode(inputString.toString());
|
|
116
|
-
const n = data.length;
|
|
117
|
-
let encoded = "";
|
|
118
|
-
if (n === 0) {
|
|
119
161
|
return encoded;
|
|
120
|
-
}
|
|
121
|
-
let shift;
|
|
122
|
-
let v = 0;
|
|
123
|
-
for (let i = 0; i < n; i++) {
|
|
124
|
-
shift = i % 3;
|
|
125
|
-
v |= data[i] << (16 >>> shift & 24);
|
|
126
|
-
if (shift === 2) {
|
|
127
|
-
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), encodeBits(v >>> 6 & 63), encodeBits(v & 63));
|
|
128
|
-
v = 0;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
if (shift === 0) {
|
|
132
|
-
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), 61, 61);
|
|
133
|
-
} else if (shift === 1) {
|
|
134
|
-
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), encodeBits(v >>> 6 & 63), 61);
|
|
135
|
-
}
|
|
136
|
-
return encoded;
|
|
137
162
|
};
|
|
138
163
|
export const findIndexesOfSubString = (inputString, searchString) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
164
|
+
const matches = [];
|
|
165
|
+
let i = inputString.indexOf(searchString);
|
|
166
|
+
while (i !== -1) {
|
|
167
|
+
matches.push(i);
|
|
168
|
+
i = inputString.indexOf(searchString, i + searchString.length);
|
|
169
|
+
}
|
|
170
|
+
return matches;
|
|
146
171
|
};
|
|
147
172
|
export const findLineEndingIndexes = (inputString) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
173
|
+
const endings = findIndexesOfSubString(inputString, '\n');
|
|
174
|
+
endings.push(inputString.length);
|
|
175
|
+
return endings;
|
|
151
176
|
};
|
|
152
177
|
export const isWhitespace = (inputString) => {
|
|
153
|
-
|
|
178
|
+
return /^\s*$/.test(inputString);
|
|
154
179
|
};
|
|
155
180
|
export const trimURL = (url, baseURLDomain) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
181
|
+
let result = url.replace(/^(https|http|file):\/\//i, '');
|
|
182
|
+
if (baseURLDomain) {
|
|
183
|
+
if (result.toLowerCase().startsWith(baseURLDomain.toLowerCase())) {
|
|
184
|
+
result = result.substr(baseURLDomain.length);
|
|
185
|
+
}
|
|
160
186
|
}
|
|
161
|
-
|
|
162
|
-
return result;
|
|
187
|
+
return result;
|
|
163
188
|
};
|
|
164
189
|
export const collapseWhitespace = (inputString) => {
|
|
165
|
-
|
|
190
|
+
return inputString.replace(/[\s\xA0]+/g, ' ');
|
|
166
191
|
};
|
|
167
192
|
export const reverse = (inputString) => {
|
|
168
|
-
|
|
193
|
+
return inputString.split('').reverse().join('');
|
|
169
194
|
};
|
|
170
195
|
export const replaceControlCharacters = (inputString) => {
|
|
171
|
-
|
|
196
|
+
// Replace C0 and C1 control character sets with replacement character.
|
|
197
|
+
// Do not replace '\t', \n' and '\r'.
|
|
198
|
+
return inputString.replace(/[\0-\x08\x0B\f\x0E-\x1F\x80-\x9F]/g, '\uFFFD');
|
|
172
199
|
};
|
|
173
200
|
export const countWtf8Bytes = (inputString) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
201
|
+
let count = 0;
|
|
202
|
+
for (let i = 0; i < inputString.length; i++) {
|
|
203
|
+
const c = inputString.charCodeAt(i);
|
|
204
|
+
if (c <= 0x7F) {
|
|
205
|
+
count++;
|
|
206
|
+
}
|
|
207
|
+
else if (c <= 0x07FF) {
|
|
208
|
+
count += 2;
|
|
209
|
+
}
|
|
210
|
+
else if (c < 0xD800 || 0xDFFF < c) {
|
|
211
|
+
count += 3;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
if (c <= 0xDBFF && i + 1 < inputString.length) {
|
|
215
|
+
// The current character is a leading surrogate, and there is a
|
|
216
|
+
// next character.
|
|
217
|
+
const next = inputString.charCodeAt(i + 1);
|
|
218
|
+
if (0xDC00 <= next && next <= 0xDFFF) {
|
|
219
|
+
// The next character is a trailing surrogate, meaning this
|
|
220
|
+
// is a surrogate pair.
|
|
221
|
+
count += 4;
|
|
222
|
+
i++;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
count += 3;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return count;
|
|
196
230
|
};
|
|
197
231
|
export const stripLineBreaks = (inputStr) => {
|
|
198
|
-
|
|
232
|
+
return inputStr.replace(/(\r)?\n/g, '');
|
|
199
233
|
};
|
|
200
234
|
const EXTENDED_KEBAB_CASE_REGEXP = /^([a-z0-9]+(?:-[a-z0-9]+)*\.)*[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
235
|
+
/**
|
|
236
|
+
* Tests if the `inputStr` is following the extended Kebab Case naming convetion,
|
|
237
|
+
* where words are separated with either a dash (`-`) or a dot (`.`), and all
|
|
238
|
+
* characters must be lower-case alphanumeric.
|
|
239
|
+
*
|
|
240
|
+
* For example, it will yield `true` for `'my.amazing-string.literal'`, but `false`
|
|
241
|
+
* for `'Another.AmazingLiteral'` or '`another_amazing_literal'`.
|
|
242
|
+
*
|
|
243
|
+
* @param inputStr the input string to test.
|
|
244
|
+
* @return `true` if the `inputStr` follows the extended Kebab Case convention.
|
|
245
|
+
*/
|
|
201
246
|
export const isExtendedKebabCase = (inputStr) => {
|
|
202
|
-
|
|
247
|
+
return EXTENDED_KEBAB_CASE_REGEXP.test(inputStr);
|
|
203
248
|
};
|
|
204
249
|
export const toTitleCase = (inputStr) => {
|
|
205
|
-
|
|
250
|
+
return inputStr.substring(0, 1).toUpperCase() + inputStr.substring(1);
|
|
206
251
|
};
|
|
207
252
|
export const removeURLFragment = (inputStr) => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
};
|
|
212
|
-
const SPECIAL_REGEX_CHARACTERS =
|
|
213
|
-
export const regexSpecialCharacters = function() {
|
|
214
|
-
|
|
215
|
-
};
|
|
216
|
-
export const filterRegex = function(query) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
};
|
|
227
|
-
export const createSearchRegex = function(query, caseSensitive, isRegex, matchWholeWord = false) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
a = a.toUpperCase();
|
|
246
|
-
b = b.toUpperCase();
|
|
247
|
-
if (a === b) {
|
|
248
|
-
return 0;
|
|
249
|
-
}
|
|
250
|
-
return a > b ? 1 : -1;
|
|
253
|
+
const url = new URL(inputStr);
|
|
254
|
+
url.hash = '';
|
|
255
|
+
return url.toString();
|
|
256
|
+
};
|
|
257
|
+
const SPECIAL_REGEX_CHARACTERS = '^[]{}()\\.^$*+?|-,';
|
|
258
|
+
export const regexSpecialCharacters = function () {
|
|
259
|
+
return SPECIAL_REGEX_CHARACTERS;
|
|
260
|
+
};
|
|
261
|
+
export const filterRegex = function (query) {
|
|
262
|
+
let regexString = '^(?:.*\\0)?'; // Start from beginning or after a \0
|
|
263
|
+
for (let i = 0; i < query.length; ++i) {
|
|
264
|
+
let c = query.charAt(i);
|
|
265
|
+
if (SPECIAL_REGEX_CHARACTERS.indexOf(c) !== -1) {
|
|
266
|
+
c = '\\' + c;
|
|
267
|
+
}
|
|
268
|
+
regexString += '[^\\0' + c + ']*' + c;
|
|
269
|
+
}
|
|
270
|
+
return new RegExp(regexString, 'i');
|
|
271
|
+
};
|
|
272
|
+
export const createSearchRegex = function (query, caseSensitive, isRegex, matchWholeWord = false) {
|
|
273
|
+
const regexFlags = caseSensitive ? 'g' : 'gi';
|
|
274
|
+
let regexObject;
|
|
275
|
+
if (isRegex) {
|
|
276
|
+
try {
|
|
277
|
+
regexObject = new RegExp(query, regexFlags);
|
|
278
|
+
}
|
|
279
|
+
catch (e) {
|
|
280
|
+
// Silent catch.
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!regexObject) {
|
|
284
|
+
regexObject = createPlainTextSearchRegex(query, regexFlags);
|
|
285
|
+
}
|
|
286
|
+
if (matchWholeWord && regexObject) {
|
|
287
|
+
regexObject = new RegExp(`\\b${regexObject.source}\\b`, regexFlags);
|
|
288
|
+
}
|
|
289
|
+
return regexObject;
|
|
251
290
|
};
|
|
252
|
-
export const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
291
|
+
export const caseInsensetiveComparator = function (a, b) {
|
|
292
|
+
a = a.toUpperCase();
|
|
293
|
+
b = b.toUpperCase();
|
|
294
|
+
if (a === b) {
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
return a > b ? 1 : -1;
|
|
298
|
+
};
|
|
299
|
+
export const hashCode = function (string) {
|
|
300
|
+
if (!string) {
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
// Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in
|
|
304
|
+
// eingeschränkten Branchingprogrammmodellen" by Woelfe.
|
|
305
|
+
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
|
|
306
|
+
const p = ((1 << 30) * 4 - 5); // prime: 2^32 - 5
|
|
307
|
+
const z = 0x5033d967; // 32 bits from random.org
|
|
308
|
+
const z2 = 0x59d2f15d; // random odd 32 bit number
|
|
309
|
+
let s = 0;
|
|
310
|
+
let zi = 1;
|
|
311
|
+
for (let i = 0; i < string.length; i++) {
|
|
312
|
+
const xi = string.charCodeAt(i) * z2;
|
|
313
|
+
s = (s + zi * xi) % p;
|
|
314
|
+
zi = (zi * z) % p;
|
|
315
|
+
}
|
|
316
|
+
s = (s + zi * (p - 1)) % p;
|
|
317
|
+
return Math.abs(s | 0);
|
|
268
318
|
};
|
|
269
319
|
export const compare = (a, b) => {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
320
|
+
if (a > b) {
|
|
321
|
+
return 1;
|
|
322
|
+
}
|
|
323
|
+
if (a < b) {
|
|
324
|
+
return -1;
|
|
325
|
+
}
|
|
326
|
+
return 0;
|
|
277
327
|
};
|
|
278
328
|
export const trimMiddle = (str, maxLength) => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
329
|
+
if (str.length <= maxLength) {
|
|
330
|
+
return String(str);
|
|
331
|
+
}
|
|
332
|
+
let leftHalf = maxLength >> 1;
|
|
333
|
+
let rightHalf = maxLength - leftHalf - 1;
|
|
334
|
+
if (str.codePointAt(str.length - rightHalf - 1) >= 0x10000) {
|
|
335
|
+
--rightHalf;
|
|
336
|
+
++leftHalf;
|
|
337
|
+
}
|
|
338
|
+
if (leftHalf > 0 && str.codePointAt(leftHalf - 1) >= 0x10000) {
|
|
339
|
+
--leftHalf;
|
|
340
|
+
}
|
|
341
|
+
return str.substr(0, leftHalf) + '…' + str.substr(str.length - rightHalf, rightHalf);
|
|
292
342
|
};
|
|
293
343
|
export const trimEndWithMaxLength = (str, maxLength) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
344
|
+
if (str.length <= maxLength) {
|
|
345
|
+
return String(str);
|
|
346
|
+
}
|
|
347
|
+
return str.substr(0, maxLength - 1) + '…';
|
|
298
348
|
};
|
|
299
349
|
export const escapeForRegExp = (str) => {
|
|
300
|
-
|
|
350
|
+
return escapeCharacters(str, SPECIAL_REGEX_CHARACTERS);
|
|
301
351
|
};
|
|
302
352
|
export const naturalOrderComparator = (a, b) => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
size
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
|
|
353
|
+
const chunk = /^\d+|^\D+/;
|
|
354
|
+
let chunka, chunkb, anum, bnum;
|
|
355
|
+
while (true) {
|
|
356
|
+
if (a) {
|
|
357
|
+
if (!b) {
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
if (b) {
|
|
363
|
+
return -1;
|
|
364
|
+
}
|
|
365
|
+
return 0;
|
|
366
|
+
}
|
|
367
|
+
chunka = a.match(chunk)[0];
|
|
368
|
+
chunkb = b.match(chunk)[0];
|
|
369
|
+
anum = !Number.isNaN(Number(chunka));
|
|
370
|
+
bnum = !Number.isNaN(Number(chunkb));
|
|
371
|
+
if (anum && !bnum) {
|
|
372
|
+
return -1;
|
|
373
|
+
}
|
|
374
|
+
if (bnum && !anum) {
|
|
375
|
+
return 1;
|
|
376
|
+
}
|
|
377
|
+
if (anum && bnum) {
|
|
378
|
+
const diff = Number(chunka) - Number(chunkb);
|
|
379
|
+
if (diff) {
|
|
380
|
+
return diff;
|
|
381
|
+
}
|
|
382
|
+
if (chunka.length !== chunkb.length) {
|
|
383
|
+
if (!Number(chunka) && !Number(chunkb)) { // chunks are strings of all 0s (special case)
|
|
384
|
+
return chunka.length - chunkb.length;
|
|
385
|
+
}
|
|
386
|
+
return chunkb.length - chunka.length;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else if (chunka !== chunkb) {
|
|
390
|
+
return (chunka < chunkb) ? -1 : 1;
|
|
391
|
+
}
|
|
392
|
+
a = a.substring(chunka.length);
|
|
393
|
+
b = b.substring(chunkb.length);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
export const base64ToSize = function (content) {
|
|
397
|
+
if (!content) {
|
|
398
|
+
return 0;
|
|
399
|
+
}
|
|
400
|
+
let size = content.length * 3 / 4;
|
|
401
|
+
if (content[content.length - 1] === '=') {
|
|
402
|
+
size--;
|
|
403
|
+
}
|
|
404
|
+
if (content.length > 1 && content[content.length - 2] === '=') {
|
|
405
|
+
size--;
|
|
406
|
+
}
|
|
407
|
+
return size;
|
|
408
|
+
};
|
|
409
|
+
export const SINGLE_QUOTE = '\'';
|
|
358
410
|
export const DOUBLE_QUOTE = '"';
|
|
359
|
-
const BACKSLASH =
|
|
360
|
-
export const findUnclosedCssQuote = function(str) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
411
|
+
const BACKSLASH = '\\';
|
|
412
|
+
export const findUnclosedCssQuote = function (str) {
|
|
413
|
+
let unmatchedQuote = '';
|
|
414
|
+
for (let i = 0; i < str.length; ++i) {
|
|
415
|
+
const char = str[i];
|
|
416
|
+
if (char === BACKSLASH) {
|
|
417
|
+
i++;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE) {
|
|
421
|
+
if (unmatchedQuote === char) {
|
|
422
|
+
unmatchedQuote = '';
|
|
423
|
+
}
|
|
424
|
+
else if (unmatchedQuote === '') {
|
|
425
|
+
unmatchedQuote = char;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return unmatchedQuote;
|
|
377
430
|
};
|
|
378
431
|
export const countUnmatchedLeftParentheses = (str) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
432
|
+
let unmatchedCount = 0;
|
|
433
|
+
for (const c of str) {
|
|
434
|
+
if (c === '(') {
|
|
435
|
+
unmatchedCount++;
|
|
436
|
+
}
|
|
437
|
+
else if (c === ')' && unmatchedCount > 0) {
|
|
438
|
+
unmatchedCount--;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return unmatchedCount;
|
|
442
|
+
};
|
|
443
|
+
export const createPlainTextSearchRegex = function (query, flags) {
|
|
444
|
+
// This should be kept the same as the one in StringUtil.cpp.
|
|
445
|
+
let regex = '';
|
|
446
|
+
for (let i = 0; i < query.length; ++i) {
|
|
447
|
+
const c = query.charAt(i);
|
|
448
|
+
if (regexSpecialCharacters().indexOf(c) !== -1) {
|
|
449
|
+
regex += '\\';
|
|
450
|
+
}
|
|
451
|
+
regex += c;
|
|
452
|
+
}
|
|
453
|
+
return new RegExp(regex, flags || '');
|
|
399
454
|
};
|
|
400
455
|
class LowerCaseStringTag {
|
|
401
|
-
|
|
456
|
+
lowerCaseStringTag;
|
|
402
457
|
}
|
|
403
|
-
export const toLowerCaseString = function(input) {
|
|
404
|
-
|
|
458
|
+
export const toLowerCaseString = function (input) {
|
|
459
|
+
return input.toLowerCase();
|
|
405
460
|
};
|
|
406
461
|
const WORD = /[A-Z]{2,}(?=[A-Z0-9][a-z0-9]+|\b)|[A-Za-z][0-9]+[a-z]|[A-Z]?[a-z]+|[0-9][A-Za-z]+|[A-Z]|[0-9]+|[.]/g;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
462
|
+
// <---1---><-----------2----------> <--------3--------> <-----4----> <------5-----> <-----6----> <7>
|
|
463
|
+
// 1: two or more consecutive uppercase letters. This is useful for identifying acronyms
|
|
464
|
+
// 2: lookahead assertion that matches a word boundary
|
|
465
|
+
// 3: numeronym: single letter followed by number and another letter
|
|
466
|
+
// 4: word starting with an optional uppercase letter
|
|
467
|
+
// 5: single digit followed by word to handle '3D' or '2px' (this might be controverial)
|
|
468
|
+
// 6: single uppercase letter or number
|
|
469
|
+
// 7: a dot character. We extract it into a separate word and remove dashes around it later.
|
|
470
|
+
// This is makes more sense conceptually and allows accounting for all possible word variants.
|
|
471
|
+
// Making dot a part of a word prevent us from handling acronyms or numeronyms after the word
|
|
472
|
+
// correctly without making the RegExp prohibitively complicated.
|
|
473
|
+
// https://regex101.com/r/LtFugp/1
|
|
474
|
+
export const toKebabCase = function (input) {
|
|
475
|
+
return (input.match?.(WORD)?.map(w => w.toLowerCase()).join('-').replaceAll('-.-', '.') || input);
|
|
476
|
+
};
|
|
477
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
410
478
|
export function toKebabCaseKeys(settingValue) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
479
|
+
const result = {};
|
|
480
|
+
for (const [key, value] of Object.entries(settingValue)) {
|
|
481
|
+
result[toKebabCase(key)] = value;
|
|
482
|
+
}
|
|
483
|
+
return result;
|
|
416
484
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
485
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
486
|
+
// Replaces the last ocurrence of parameter `search` with parameter `replacement` in `input`
|
|
487
|
+
export const replaceLast = function (input, search, replacement) {
|
|
488
|
+
const replacementStartIndex = input.lastIndexOf(search);
|
|
489
|
+
if (replacementStartIndex === -1) {
|
|
490
|
+
return input;
|
|
491
|
+
}
|
|
492
|
+
return input.slice(0, replacementStartIndex) + input.slice(replacementStartIndex).replace(search, replacement);
|
|
493
|
+
};
|
|
494
|
+
export const stringifyWithPrecision = function stringifyWithPrecision(s, precision = 2) {
|
|
495
|
+
if (precision === 0) {
|
|
496
|
+
return s.toFixed(0);
|
|
497
|
+
}
|
|
498
|
+
const string = s.toFixed(precision).replace(/\.?0*$/, '');
|
|
499
|
+
return string === '-0' ? '0' : string;
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* Somewhat efficiently concatenates 2 base64 encoded strings.
|
|
503
|
+
*/
|
|
504
|
+
export const concatBase64 = function (lhs, rhs) {
|
|
505
|
+
if (lhs.length === 0 || !lhs.endsWith('=')) {
|
|
506
|
+
// Empty string or no padding, we can straight-up concatenate.
|
|
507
|
+
return lhs + rhs;
|
|
508
|
+
}
|
|
509
|
+
const lhsLeaveAsIs = lhs.substring(0, lhs.length - 4);
|
|
510
|
+
const lhsToDecode = lhs.substring(lhs.length - 4);
|
|
511
|
+
return lhsLeaveAsIs + window.btoa(window.atob(lhsToDecode) + window.atob(rhs));
|
|
512
|
+
};
|
|
513
|
+
//# sourceMappingURL=string-utilities.js.map
|