@schukai/monster 4.143.4 → 4.143.6
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/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.143.
|
|
1
|
+
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.143.6"}
|
|
@@ -155,6 +155,18 @@ const debounceSizeSymbol = Symbol("debounceSize");
|
|
|
155
155
|
*/
|
|
156
156
|
const hashChangeSymbol = Symbol("hashChange");
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* @private
|
|
160
|
+
* @type {symbol}
|
|
161
|
+
*/
|
|
162
|
+
const pendingConfigWriteSymbol = Symbol("pendingConfigWrite");
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @private
|
|
166
|
+
* @type {symbol}
|
|
167
|
+
*/
|
|
168
|
+
const configWritePromiseSymbol = Symbol("configWritePromise");
|
|
169
|
+
|
|
158
170
|
/**
|
|
159
171
|
* The Filter component is used to show and handle the filter values.
|
|
160
172
|
*
|
|
@@ -1089,6 +1101,10 @@ function initTabEvents() {
|
|
|
1089
1101
|
return host.getConfig(configKey);
|
|
1090
1102
|
})
|
|
1091
1103
|
.then((config) => {
|
|
1104
|
+
if (!isObject(config)) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1092
1108
|
for (const [name, query] of Object.entries(config)) {
|
|
1093
1109
|
if (labels.includes(name)) {
|
|
1094
1110
|
continue;
|
|
@@ -1130,6 +1146,10 @@ function updateFilterTabs() {
|
|
|
1130
1146
|
return host.getConfig(configKey);
|
|
1131
1147
|
})
|
|
1132
1148
|
.then((config) => {
|
|
1149
|
+
if (!isObject(config)) {
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1133
1153
|
for (const [name, query] of Object.entries(config)) {
|
|
1134
1154
|
const found = element.querySelector(
|
|
1135
1155
|
`[data-monster-button-label="${name}"]`,
|
|
@@ -1629,12 +1649,51 @@ function updateConfig() {
|
|
|
1629
1649
|
if (!(host && hasConfigIdentity.call(this))) {
|
|
1630
1650
|
return;
|
|
1631
1651
|
}
|
|
1652
|
+
|
|
1632
1653
|
const configKey = getFilterConfigKey.call(this);
|
|
1654
|
+
this[pendingConfigWriteSymbol] = {
|
|
1655
|
+
key: configKey,
|
|
1656
|
+
value: this[settingsSymbol].getOptions(),
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
if (this[configWritePromiseSymbol]) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
writePendingConfig.call(this, host);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
/**
|
|
1667
|
+
* @private
|
|
1668
|
+
* @param {Host} host
|
|
1669
|
+
*/
|
|
1670
|
+
function writePendingConfig(host) {
|
|
1671
|
+
const pending = this[pendingConfigWriteSymbol];
|
|
1672
|
+
delete this[pendingConfigWriteSymbol];
|
|
1673
|
+
|
|
1674
|
+
if (!pending) {
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1633
1677
|
|
|
1634
1678
|
try {
|
|
1635
|
-
|
|
1679
|
+
this[configWritePromiseSymbol] = Promise.resolve(
|
|
1680
|
+
host.setConfig(pending.key, pending.value),
|
|
1681
|
+
)
|
|
1682
|
+
.catch((error) => {
|
|
1683
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
|
|
1684
|
+
})
|
|
1685
|
+
.finally(() => {
|
|
1686
|
+
delete this[configWritePromiseSymbol];
|
|
1687
|
+
if (this[pendingConfigWriteSymbol]) {
|
|
1688
|
+
writePendingConfig.call(this, host);
|
|
1689
|
+
}
|
|
1690
|
+
});
|
|
1636
1691
|
} catch (error) {
|
|
1692
|
+
delete this[configWritePromiseSymbol];
|
|
1637
1693
|
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
|
|
1694
|
+
if (this[pendingConfigWriteSymbol]) {
|
|
1695
|
+
writePendingConfig.call(this, host);
|
|
1696
|
+
}
|
|
1638
1697
|
}
|
|
1639
1698
|
}
|
|
1640
1699
|
|
|
@@ -82,6 +82,8 @@ function parseBracketedKeyValueHash(hashString) {
|
|
|
82
82
|
let inSelector = true;
|
|
83
83
|
let escaped = false;
|
|
84
84
|
let quotedValueStartChar = "";
|
|
85
|
+
let valueParenthesisDepth = 0;
|
|
86
|
+
let valueClosedByParenthesis = false;
|
|
85
87
|
|
|
86
88
|
for (let i = 0; i < cleanedHashString.length; i++) {
|
|
87
89
|
const c = cleanedHashString[i];
|
|
@@ -166,6 +168,19 @@ function parseBracketedKeyValueHash(hashString) {
|
|
|
166
168
|
continue;
|
|
167
169
|
}
|
|
168
170
|
|
|
171
|
+
if (c === "(") {
|
|
172
|
+
valueParenthesisDepth++;
|
|
173
|
+
currentValue += c;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (c === ")" && valueParenthesisDepth > 0) {
|
|
178
|
+
valueParenthesisDepth--;
|
|
179
|
+
currentValue += c;
|
|
180
|
+
valueClosedByParenthesis = valueParenthesisDepth === 0;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
169
184
|
if (c === ",") {
|
|
170
185
|
inValue = false;
|
|
171
186
|
inKey = true;
|
|
@@ -173,6 +188,8 @@ function parseBracketedKeyValueHash(hashString) {
|
|
|
173
188
|
addToResult(currentKey, decodedCurrentValue);
|
|
174
189
|
currentKey = "";
|
|
175
190
|
currentValue = "";
|
|
191
|
+
valueParenthesisDepth = 0;
|
|
192
|
+
valueClosedByParenthesis = false;
|
|
176
193
|
continue;
|
|
177
194
|
}
|
|
178
195
|
|
|
@@ -186,6 +203,8 @@ function parseBracketedKeyValueHash(hashString) {
|
|
|
186
203
|
currentKey = "";
|
|
187
204
|
currentValue = "";
|
|
188
205
|
currentSelector = "";
|
|
206
|
+
valueParenthesisDepth = 0;
|
|
207
|
+
valueClosedByParenthesis = false;
|
|
189
208
|
continue;
|
|
190
209
|
}
|
|
191
210
|
|
|
@@ -199,6 +218,12 @@ function parseBracketedKeyValueHash(hashString) {
|
|
|
199
218
|
return selectors;
|
|
200
219
|
}
|
|
201
220
|
|
|
221
|
+
if (inValue && valueParenthesisDepth === 0 && valueClosedByParenthesis) {
|
|
222
|
+
const decodedCurrentValue = decodeURIComponent(currentValue);
|
|
223
|
+
addToResult(currentKey, decodedCurrentValue);
|
|
224
|
+
return selectors;
|
|
225
|
+
}
|
|
226
|
+
|
|
202
227
|
return {};
|
|
203
228
|
}
|
|
204
229
|
|
|
@@ -106,6 +106,16 @@ describe("parseBracketedKeyValueHash", () => {
|
|
|
106
106
|
expect(result).to.deep.equal({selector: {key1: 'value,1', key2: 'value,2'}});
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
it('should keep unencoded parentheses inside a percent-encoded filter expression', () => {
|
|
110
|
+
const hashString = '#list-filter-nucleus-pim-product-variants-list(tags=tags%20IN%20(%22gustav-varianten%22)';
|
|
111
|
+
const result = parseBracketedKeyValueHash(hashString);
|
|
112
|
+
expect(result).to.deep.equal({
|
|
113
|
+
'list-filter-nucleus-pim-product-variants-list': {
|
|
114
|
+
tags: 'tags IN ("gustav-varianten")'
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
109
119
|
it('should ignore leading hash symbol (#)', () => {
|
|
110
120
|
const hashString = 'selector(key=value)';
|
|
111
121
|
const result = parseBracketedKeyValueHash(hashString);
|
|
@@ -195,6 +205,18 @@ describe("parseBracketedKeyValueHash", () => {
|
|
|
195
205
|
const result = createBracketedKeyValueHash(input, true);
|
|
196
206
|
expect(result).to.deep.equal("#.example(color=r%22ed,font-size=14px);.other(background=blue)");
|
|
197
207
|
});
|
|
208
|
+
|
|
209
|
+
it('should round-trip a filter expression with quotes and parentheses', () => {
|
|
210
|
+
const input = {
|
|
211
|
+
'list-filter-nucleus-pim-product-variants-list': {
|
|
212
|
+
tags: 'tags IN ("gustav-varianten")'
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const hashString = createBracketedKeyValueHash(input, true);
|
|
217
|
+
const result = parseBracketedKeyValueHash(hashString);
|
|
218
|
+
expect(result).to.deep.equal(input);
|
|
219
|
+
});
|
|
198
220
|
|
|
199
221
|
it('should return an empty string for an empty object', () => {
|
|
200
222
|
const input = {};
|