@schukai/monster 4.11.1 → 4.13.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 +26 -0
- package/package.json +1 -1
- package/source/components/content/camera-capture.mjs +389 -387
- package/source/components/data/metric-graph.mjs +3 -3
- package/source/components/data/metric.mjs +1 -1
- package/source/components/datatable/filter.mjs +22 -0
- package/source/components/form/message-state-button.mjs +26 -22
- package/source/components/layout/popper.mjs +75 -68
- package/source/dom/customelement.mjs +27 -3
- package/source/i18n/util.mjs +41 -0
- package/source/text/generate-range-comparison-expression.mjs +109 -39
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/cases/text/generate-range-comparison-expression.mjs +94 -0
- package/test/cases/text/util.mjs +3 -3
- package/test/web/import.js +1 -0
- package/test/web/test.html +2 -2
- package/test/web/tests.js +238 -104
@@ -15,7 +15,7 @@
|
|
15
15
|
export { generateRangeComparisonExpression };
|
16
16
|
|
17
17
|
/**
|
18
|
-
* The `generateRangeComparisonExpression()` function is function that generates a string representation
|
18
|
+
* The `generateRangeComparisonExpression()` function is a function that generates a string representation
|
19
19
|
* of a comparison expression based on a range of values. It takes three arguments:
|
20
20
|
*
|
21
21
|
* - expression (required): a string representation of a range of values in the format of start1-end1,start2-end2,value3....
|
@@ -33,6 +33,8 @@ export { generateRangeComparisonExpression };
|
|
33
33
|
* eqOp (string, default: '=='): the equality operator to use in the expression.
|
34
34
|
* geOp (string, default: '>='): the greater than or equal to operator to use in the expression.
|
35
35
|
* leOp (string, default: '<='): the less than or equal to operator to use in the expression.
|
36
|
+
* gtOp (string, default: '>'): the greater than operator to use in the expression.
|
37
|
+
* ltOp (string, default: '<'): the less than operator to use in the expression.
|
36
38
|
*
|
37
39
|
* Examples
|
38
40
|
*
|
@@ -58,10 +60,16 @@ export { generateRangeComparisonExpression };
|
|
58
60
|
* @param {string} [options.eqOp='=='] - The comparison operator for equality to use.
|
59
61
|
* @param {string} [options.geOp='>='] - The comparison operator for greater than or equal to to use.
|
60
62
|
* @param {string} [options.leOp='<='] - The comparison operator for less than or equal to to use.
|
63
|
+
* @param {string} [options.gtOp='>'] - The comparison operator for greater than to use.
|
64
|
+
* @param {string} [options.ltOp='<'] - The comparison operator for less than to use.
|
61
65
|
* @return {string} The generated comparison expression.
|
62
66
|
* @throws {Error} If the input is invalid.
|
63
67
|
* @summary Generates a comparison expression based on a range of values.
|
64
68
|
*/
|
69
|
+
/**
|
70
|
+
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
|
71
|
+
* SPDX-License-Identifier: AGPL-3.0
|
72
|
+
*/
|
65
73
|
function generateRangeComparisonExpression(
|
66
74
|
expression,
|
67
75
|
valueName,
|
@@ -74,48 +82,110 @@ function generateRangeComparisonExpression(
|
|
74
82
|
eqOp = "==",
|
75
83
|
geOp = ">=",
|
76
84
|
leOp = "<=",
|
85
|
+
gtOp = ">",
|
86
|
+
ltOp = "<",
|
77
87
|
} = options;
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
88
|
+
|
89
|
+
if (
|
90
|
+
typeof expression !== "string" ||
|
91
|
+
typeof valueName !== "string" ||
|
92
|
+
!expression.trim()
|
93
|
+
) {
|
94
|
+
throw new Error("Invalid input");
|
95
|
+
}
|
96
|
+
|
97
|
+
const encode = (s) => (urlEncode ? encodeURIComponent(s) : s);
|
98
|
+
const and = encode(andOp);
|
99
|
+
const or = encode(orOp);
|
100
|
+
const space = urlEncode ? "%20" : " ";
|
101
|
+
|
102
|
+
function parseRange(range) {
|
103
|
+
range = range.trim();
|
104
|
+
if (!range) throw new Error("Empty range");
|
105
|
+
|
106
|
+
// Sonderfall: nur Bindestriche wie "--"
|
107
|
+
if (/^-+$/.test(range)) {
|
83
108
|
throw new Error(`Invalid range '${range}'`);
|
84
|
-
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
const compStart =
|
95
|
-
start !== null
|
96
|
-
? `${valueName}${urlEncode ? encodeURIComponent(geOp) : geOp}${start}`
|
97
|
-
: "";
|
98
|
-
const compEnd =
|
99
|
-
end !== null
|
100
|
-
? `${valueName}${urlEncode ? encodeURIComponent(leOp) : leOp}${end}`
|
101
|
-
: "";
|
102
|
-
const compRange = `${compStart}${
|
103
|
-
compStart && compEnd ? ` ${andOp} ` : ""
|
104
|
-
}${compEnd}`;
|
105
|
-
comparison += ranges.length > 1 ? `(${compRange})` : compRange;
|
106
|
-
} else {
|
107
|
-
const value = parseFloat(range);
|
108
|
-
if (isNaN(value)) {
|
109
|
+
}
|
110
|
+
|
111
|
+
// Bereich: z.B. -10--5, 4-6
|
112
|
+
const rangeMatch = range.match(
|
113
|
+
/^(-?\d+(?:\.\d+)?)\s*-\s*(-?\d+(?:\.\d+)?)/,
|
114
|
+
);
|
115
|
+
if (rangeMatch) {
|
116
|
+
const sNum = parseFloat(rangeMatch[1]);
|
117
|
+
const eNum = parseFloat(rangeMatch[2]);
|
118
|
+
if (isNaN(sNum) || isNaN(eNum))
|
109
119
|
throw new Error(`Invalid value '${range}'`);
|
110
|
-
}
|
111
|
-
|
112
|
-
urlEncode ? encodeURIComponent(eqOp) : eqOp
|
113
|
-
}${value}`;
|
114
|
-
comparison += ranges.length > 1 ? `(${compValue})` : compValue;
|
120
|
+
if (sNum > eNum) throw new Error(`Invalid range '${range}'`);
|
121
|
+
return `${valueName}${encode(geOp)}${sNum}${space}${and}${space}${valueName}${encode(leOp)}${eNum}`;
|
115
122
|
}
|
116
|
-
|
117
|
-
|
123
|
+
|
124
|
+
// Exklusiver Bereich: 4~6 → x>4 && x<6
|
125
|
+
const exclMatch = range.match(/^(-?\d+(?:\.\d+)?)\s*~\s*(-?\d+(?:\.\d+)?)/);
|
126
|
+
if (exclMatch) {
|
127
|
+
const sNum = parseFloat(exclMatch[1]);
|
128
|
+
const eNum = parseFloat(exclMatch[2]);
|
129
|
+
if (isNaN(sNum) || isNaN(eNum))
|
130
|
+
throw new Error(`Invalid value '${range}'`);
|
131
|
+
return `${valueName}${encode(gtOp)}${sNum}${space}${and}${space}${valueName}${encode(ltOp)}${eNum}`;
|
118
132
|
}
|
133
|
+
|
134
|
+
// Offene Intervalle exklusiv: 4~ → x>4, ~6 → x<6
|
135
|
+
const openRightExclMatch = range.match(/^(-?\d+(?:\.\d+)?)~$/);
|
136
|
+
if (openRightExclMatch) {
|
137
|
+
const sNum = parseFloat(openRightExclMatch[1]);
|
138
|
+
if (isNaN(sNum)) throw new Error(`Invalid value in '${range}'`);
|
139
|
+
return `${valueName}${encode(gtOp)}${sNum}`;
|
140
|
+
}
|
141
|
+
const openLeftExclMatch = range.match(/^~(-?\d+(?:\.\d+)?)$/);
|
142
|
+
if (openLeftExclMatch) {
|
143
|
+
const eNum = parseFloat(openLeftExclMatch[1]);
|
144
|
+
if (isNaN(eNum)) throw new Error(`Invalid value in '${range}'`);
|
145
|
+
return `${valueName}${encode(ltOp)}${eNum}`;
|
146
|
+
}
|
147
|
+
|
148
|
+
// Offene Intervalle inklusiv: 4- → x>=4, -6 → x<=6
|
149
|
+
const openRightInclMatch = range.match(/^(-?\d+(?:\.\d+)?)\-$/);
|
150
|
+
if (openRightInclMatch) {
|
151
|
+
const sNum = parseFloat(openRightInclMatch[1]);
|
152
|
+
if (isNaN(sNum)) throw new Error(`Invalid value in '${range}'`);
|
153
|
+
return `${valueName}${encode(geOp)}${sNum}`;
|
154
|
+
}
|
155
|
+
const openLeftInclMatch = range.match(/^\-(-?\d+(?:\.\d+)?)$/);
|
156
|
+
if (openLeftInclMatch) {
|
157
|
+
const eNum = parseFloat(openLeftInclMatch[1]);
|
158
|
+
if (isNaN(eNum)) throw new Error(`Invalid value in '${range}'`);
|
159
|
+
return `${valueName}${encode(leOp)}${eNum}`;
|
160
|
+
}
|
161
|
+
|
162
|
+
// <n oder >n
|
163
|
+
if (range.startsWith("<")) {
|
164
|
+
const n = parseFloat(range.slice(1));
|
165
|
+
if (isNaN(n)) throw new Error(`Invalid value in '${range}'`);
|
166
|
+
return `${valueName}${encode(ltOp)}${n}`;
|
167
|
+
}
|
168
|
+
if (range.startsWith(">")) {
|
169
|
+
const n = parseFloat(range.slice(1));
|
170
|
+
if (isNaN(n)) throw new Error(`Invalid value in '${range}'`);
|
171
|
+
return `${valueName}${encode(gtOp)}${n}`;
|
172
|
+
}
|
173
|
+
|
174
|
+
// Einzelwert NUR, wenn wirklich reine Zahl
|
175
|
+
if (/^-?\d+(\.\d+)?$/.test(range)) {
|
176
|
+
const value = parseFloat(range);
|
177
|
+
return `${valueName}${encode(eqOp)}${value}`;
|
178
|
+
}
|
179
|
+
|
180
|
+
throw new Error(`Invalid value '${range}'`);
|
119
181
|
}
|
120
|
-
|
182
|
+
|
183
|
+
const parts = expression
|
184
|
+
.split(",")
|
185
|
+
.map((r) => r.trim())
|
186
|
+
.filter(Boolean)
|
187
|
+
.map(parseRange);
|
188
|
+
|
189
|
+
const sep = space + or + space;
|
190
|
+
return parts.length > 1 ? parts.map((p) => `(${p})`).join(sep) : parts[0];
|
121
191
|
}
|
package/source/types/version.mjs
CHANGED
package/test/cases/monster.mjs
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
import { expect } from "chai";
|
2
|
+
import { generateRangeComparisonExpression } from "../../../source/text/generate-range-comparison-expression.mjs";
|
3
|
+
|
4
|
+
describe('generateRangeComparisonExpression', function () {
|
5
|
+
|
6
|
+
it('soll Einzelwerte korrekt behandeln', function () {
|
7
|
+
expect(generateRangeComparisonExpression("5", "x")).to.equal("x==5");
|
8
|
+
expect(generateRangeComparisonExpression("0", "age")).to.equal("age==0");
|
9
|
+
expect(generateRangeComparisonExpression("-3", "score")).to.equal("score<=3");
|
10
|
+
expect(generateRangeComparisonExpression("7.5", "n")).to.equal("n==7.5");
|
11
|
+
});
|
12
|
+
|
13
|
+
it('soll einfache inklusive Ranges korrekt behandeln', function () {
|
14
|
+
expect(generateRangeComparisonExpression("4-6", "x")).to.equal("x>=4 && x<=6");
|
15
|
+
expect(generateRangeComparisonExpression("10-15", "a")).to.equal("a>=10 && a<=15");
|
16
|
+
expect(generateRangeComparisonExpression("-5-5", "y")).to.equal("y>=-5 && y<=5");
|
17
|
+
expect(generateRangeComparisonExpression("4.1-6.2", "x")).to.equal("x>=4.1 && x<=6.2");
|
18
|
+
});
|
19
|
+
|
20
|
+
it('soll exklusive Ranges (mit ~) korrekt behandeln', function () {
|
21
|
+
expect(generateRangeComparisonExpression("4~6", "x")).to.equal("x>4 && x<6");
|
22
|
+
expect(generateRangeComparisonExpression("10~15", "a")).to.equal("a>10 && a<15");
|
23
|
+
expect(generateRangeComparisonExpression("-4~4", "y")).to.equal("y>-4 && y<4");
|
24
|
+
});
|
25
|
+
|
26
|
+
it('soll offene Intervalle links korrekt behandeln', function () {
|
27
|
+
expect(generateRangeComparisonExpression("-6", "x")).to.equal("x<=6");
|
28
|
+
expect(generateRangeComparisonExpression("-2", "y")).to.equal("y<=2");
|
29
|
+
expect(generateRangeComparisonExpression(" -3 ", "z")).to.equal("z<=3");
|
30
|
+
});
|
31
|
+
|
32
|
+
it('soll offene Intervalle rechts korrekt behandeln', function () {
|
33
|
+
expect(generateRangeComparisonExpression("4-", "x")).to.equal("x>=4");
|
34
|
+
expect(generateRangeComparisonExpression("10-", "z")).to.equal("z>=10");
|
35
|
+
expect(generateRangeComparisonExpression(" -5- ", "y")).to.equal("y>=-5");
|
36
|
+
});
|
37
|
+
|
38
|
+
it('soll die Operatoren < und > korrekt behandeln', function () {
|
39
|
+
expect(generateRangeComparisonExpression(">4", "x")).to.equal("x>4");
|
40
|
+
expect(generateRangeComparisonExpression("<6", "x")).to.equal("x<6");
|
41
|
+
expect(generateRangeComparisonExpression(">-4.2", "n")).to.equal("n>-4.2");
|
42
|
+
expect(generateRangeComparisonExpression("--2", "x")).to.equal("x<=-2");
|
43
|
+
});
|
44
|
+
|
45
|
+
it('soll mehrere Bedingungen per Komma ODER-verknüpfen', function () {
|
46
|
+
expect(generateRangeComparisonExpression("4-6,10,20~25", "x"))
|
47
|
+
.to.equal("(x>=4 && x<=6) || (x==10) || (x>20 && x<25)");
|
48
|
+
expect(generateRangeComparisonExpression("0,5-10", "y"))
|
49
|
+
.to.equal("(y==0) || (y>=5 && y<=10)");
|
50
|
+
expect(generateRangeComparisonExpression(">1,<3", "z"))
|
51
|
+
.to.equal("(z>1) || (z<3)");
|
52
|
+
});
|
53
|
+
|
54
|
+
it('soll urlEncode korrekt unterstützen', function () {
|
55
|
+
expect(generateRangeComparisonExpression("4-6", "x", { urlEncode: true }))
|
56
|
+
.to.equal("x%3E%3D4%20%26%26%20x%3C%3D6");
|
57
|
+
expect(generateRangeComparisonExpression("10", "n", { urlEncode: true }))
|
58
|
+
.to.equal("n%3D%3D10");
|
59
|
+
});
|
60
|
+
|
61
|
+
it('soll Fehler werfen bei falschen Eingaben', function () {
|
62
|
+
expect(() => generateRangeComparisonExpression("", "x")).to.throw("Invalid input");
|
63
|
+
expect(() => generateRangeComparisonExpression("abc", "x")).to.throw("Invalid value 'abc'");
|
64
|
+
expect(() => generateRangeComparisonExpression("4-3", "x")).to.throw("Invalid range '4-3'");
|
65
|
+
expect(() => generateRangeComparisonExpression("4-foo", "x")).to.throw("Invalid value '4-foo'");
|
66
|
+
expect(() => generateRangeComparisonExpression("4~foo", "x")).to.throw("Invalid value '4~foo'");
|
67
|
+
expect(() => generateRangeComparisonExpression(">", "x")).to.throw("Invalid value in '>'");
|
68
|
+
expect(() => generateRangeComparisonExpression("<", "x")).to.throw("Invalid value in '<'");
|
69
|
+
expect(() => generateRangeComparisonExpression("--", "x")).to.throw("Invalid range '--'");
|
70
|
+
expect(() => generateRangeComparisonExpression("-foo", "x")).to.throw("Invalid value '-foo'");
|
71
|
+
expect(() => generateRangeComparisonExpression("foo-", "x")).to.throw("Invalid value 'foo-'");
|
72
|
+
expect(() => generateRangeComparisonExpression("5~", "x")).to.not.throw();
|
73
|
+
expect(() => generateRangeComparisonExpression("~5", "x")).to.not.throw();
|
74
|
+
expect(() => generateRangeComparisonExpression(">", "")).to.throw("Invalid value in '>'");
|
75
|
+
expect(() => generateRangeComparisonExpression("1,,2", "x")).not.to.throw();
|
76
|
+
expect(() => generateRangeComparisonExpression(",", "x")).to.not.throw();
|
77
|
+
});
|
78
|
+
|
79
|
+
it('soll Leerzeichen robust behandeln', function () {
|
80
|
+
expect(generateRangeComparisonExpression(" 4 - 6 , 8 ", "x"))
|
81
|
+
.to.equal("(x>=4 && x<=6) || (x==8)");
|
82
|
+
expect(generateRangeComparisonExpression(" -10--5 ", "temp"))
|
83
|
+
.to.equal("temp>=-10 && temp<=-5");
|
84
|
+
});
|
85
|
+
|
86
|
+
it('soll negative Werte korrekt behandeln', function () {
|
87
|
+
expect(generateRangeComparisonExpression("-10--5", "temp"))
|
88
|
+
.to.equal("temp>=-10 && temp<=-5");
|
89
|
+
expect(generateRangeComparisonExpression("> -3", "z")).to.equal("z>-3");
|
90
|
+
expect(generateRangeComparisonExpression(" -4~4 ", "y")).to.equal("y>-4 && y<4");
|
91
|
+
expect(generateRangeComparisonExpression("-5", "x")).to.equal("x<=5");
|
92
|
+
|
93
|
+
});
|
94
|
+
});
|
package/test/cases/text/util.mjs
CHANGED
@@ -55,7 +55,7 @@ describe('generateRangeComparisonExpression', () => {
|
|
55
55
|
{
|
56
56
|
expression: '1,3,5',
|
57
57
|
valueName: 'x',
|
58
|
-
expected: '(x%3D%3D1)
|
58
|
+
expected: '(x%3D%3D1)%20%7C%7C%20(x%3D%3D3)%20%7C%7C%20(x%3D%3D5)',
|
59
59
|
},
|
60
60
|
{
|
61
61
|
expression: '-10',
|
@@ -70,12 +70,12 @@ describe('generateRangeComparisonExpression', () => {
|
|
70
70
|
{
|
71
71
|
expression: '1-3,6-8',
|
72
72
|
valueName: 'y',
|
73
|
-
expected: '(y%3E%3D1
|
73
|
+
expected: '(y%3E%3D1%20%26%26%20y%3C%3D3)%20%7C%7C%20(y%3E%3D6%20%26%26%20y%3C%3D8)',
|
74
74
|
},
|
75
75
|
{
|
76
76
|
expression: '1-3,5,7-9',
|
77
77
|
valueName: 'z',
|
78
|
-
expected: '(z%3E%3D1
|
78
|
+
expected: '(z%3E%3D1%20%26%26%20z%3C%3D3)%20%7C%7C%20(z%3D%3D5)%20%7C%7C%20(z%3E%3D7%20%26%26%20z%3C%3D9)',
|
79
79
|
},
|
80
80
|
];
|
81
81
|
|
package/test/web/import.js
CHANGED
@@ -19,6 +19,7 @@ import "../cases/components/host/overlay.mjs";
|
|
19
19
|
import "../cases/components/host/util.mjs";
|
20
20
|
import "../cases/components/host/details.mjs";
|
21
21
|
import "../cases/text/formatter.mjs";
|
22
|
+
import "../cases/text/generate-range-comparison-expression.mjs";
|
22
23
|
import "../cases/text/util.mjs";
|
23
24
|
import "../cases/text/bracketed-key-value-hash.mjs";
|
24
25
|
import "../cases/math/random.mjs";
|
package/test/web/test.html
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
</head>
|
10
10
|
<body>
|
11
11
|
<div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
|
12
|
-
<h1 style='margin-bottom: 0.1em;'>Monster 4.11.
|
13
|
-
<div id="lastupdate" style='font-size:0.7em'>last update
|
12
|
+
<h1 style='margin-bottom: 0.1em;'>Monster 4.11.1</h1>
|
13
|
+
<div id="lastupdate" style='font-size:0.7em'>last update Do 29. Mai 13:24:01 CEST 2025</div>
|
14
14
|
</div>
|
15
15
|
<div id="mocha-errors"
|
16
16
|
style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>
|