@schukai/monster 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -73,7 +73,7 @@ We do try to work around some browser bugs, but on the whole we don't use polyfi
73
73
  However, many functions can be mapped via [polyfill.io](https://polyfill.io/) and thus the compatibility can be increased.
74
74
 
75
75
  ```html
76
- <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getOwnPropertySymbols,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
76
+ <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
77
77
  crossorigin="anonymous"
78
78
  referrerpolicy="no-referrer"></script>
79
79
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "2.2.0",
3
+ "version": "3.0.0",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -24,7 +24,7 @@ export {Datasource}
24
24
  * @license AGPLv3
25
25
  * @since 1.24.0
26
26
  */
27
- const internalDataSymbol = Symbol.for('@schukai/monster/data/datasource/data');
27
+ const internalDataSymbol = Symbol.for('@schukai/monster/data/datasource/@@data');
28
28
 
29
29
  /**
30
30
  * The datasource class is the basis for dealing with different data sources.
@@ -59,6 +59,7 @@ export {
59
59
  ATTRIBUTE_EXPORTPARTS,
60
60
  ATTRIBUTE_HIDDEN,
61
61
  objectUpdaterLinkSymbol,
62
+ customElementUpdaterLinkSymbol
62
63
 
63
64
  }
64
65
 
@@ -223,6 +224,14 @@ const ATTRIBUTE_ERRORMESSAGE = ATTRIBUTE_PREFIX + 'error';
223
224
  */
224
225
  const objectUpdaterLinkSymbol = Symbol.for('@schukai/monster/dom/@@object-updater-link');
225
226
 
227
+ /**
228
+ * @memberOf Monster.DOM
229
+ * @type {symbol}
230
+ * @license AGPLv3
231
+ * @since 1.24.0
232
+ */
233
+ const customElementUpdaterLinkSymbol = Symbol.for('@schukai/monster/dom/custom-element@@options-updater-link');
234
+
226
235
  /**
227
236
  * @memberOf Monster.DOM
228
237
  * @type {string}
@@ -22,13 +22,20 @@ import {
22
22
  ATTRIBUTE_ERRORMESSAGE,
23
23
  ATTRIBUTE_OPTIONS,
24
24
  ATTRIBUTE_OPTIONS_SELECTOR,
25
- objectUpdaterLinkSymbol
25
+ customElementUpdaterLinkSymbol
26
26
  } from "./constants.mjs";
27
27
  import {findDocumentTemplate, Template} from "./template.mjs";
28
- import {Updater} from "./updater.mjs";
28
+ import {addObjectWithUpdaterToElement} from "./updater.mjs";
29
29
  import {instanceSymbol} from '../constants.mjs';
30
30
 
31
- export {CustomElement, initMethodSymbol, assembleMethodSymbol, attributeObserverSymbol, registerCustomElement, assignUpdaterToElement, getSlottedElements}
31
+ export {
32
+ CustomElement,
33
+ initMethodSymbol,
34
+ assembleMethodSymbol,
35
+ attributeObserverSymbol,
36
+ registerCustomElement,
37
+ getSlottedElements
38
+ }
32
39
 
33
40
  /**
34
41
  * @memberOf Monster.DOM
@@ -460,7 +467,8 @@ class CustomElement extends HTMLElement {
460
467
  nodeList = elements
461
468
  }
462
469
 
463
- assignUpdaterToElement.call(self, nodeList, clone(self[internalSymbol].getRealSubject()['options']));
470
+ addObjectWithUpdaterToElement.call(self, nodeList, customElementUpdaterLinkSymbol, clone(self[internalSymbol].getRealSubject()['options']))
471
+ //assignUpdaterToElement.call(self, nodeList, clone(self[internalSymbol].getRealSubject()['options']));
464
472
  return self;
465
473
  }
466
474
 
@@ -473,7 +481,7 @@ class CustomElement extends HTMLElement {
473
481
  */
474
482
  connectedCallback() {
475
483
  let self = this;
476
- if (!hasObjectLink(self, objectUpdaterLinkSymbol)) {
484
+ if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
477
485
  self[assembleMethodSymbol]()
478
486
  }
479
487
  }
@@ -673,11 +681,11 @@ function initOptionObserver() {
673
681
  self.attachObserver(new Observer(function () {
674
682
 
675
683
  // not initialised
676
- if (!hasObjectLink(self, objectUpdaterLinkSymbol)) {
684
+ if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
677
685
  return;
678
686
  }
679
687
  // inform every element
680
- const updaters = getLinkedObjects(self, objectUpdaterLinkSymbol);
688
+ const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
681
689
 
682
690
  for (const list of updaters) {
683
691
  for (const updater of list) {
@@ -935,44 +943,3 @@ function registerCustomElement(element) {
935
943
  getGlobalObject('customElements').define(element.getTag(), element);
936
944
  }
937
945
 
938
-
939
- /**
940
- *
941
- * @param element
942
- * @param object
943
- * @return {Promise[]}
944
- * @license AGPLv3
945
- * @since 1.23.0
946
- * @memberOf Monster.DOM
947
- */
948
- function assignUpdaterToElement(elements, object) {
949
-
950
- const updaters = new Set;
951
-
952
- if (elements instanceof NodeList) {
953
- elements = new Set([
954
- ...elements
955
- ])
956
- }
957
-
958
- let result = [];
959
-
960
- elements.forEach((element) => {
961
- if (!(element instanceof HTMLElement)) return;
962
- if ((element instanceof HTMLTemplateElement)) return;
963
-
964
- const u = new Updater(element, object)
965
- updaters.add(u);
966
-
967
- result.push(u.run().then(() => {
968
- return u.enableEventProcessing();
969
- }));
970
-
971
- });
972
-
973
- if (updaters.size > 0) {
974
- addToObjectLink(this, objectUpdaterLinkSymbol, updaters);
975
- }
976
-
977
- return result;
978
- }
@@ -17,7 +17,7 @@ import {
17
17
  ATTRIBUTE_UPDATER_INSERT_REFERENCE,
18
18
  ATTRIBUTE_UPDATER_REMOVE,
19
19
  ATTRIBUTE_UPDATER_REPLACE,
20
- ATTRIBUTE_UPDATER_SELECT_THIS
20
+ ATTRIBUTE_UPDATER_SELECT_THIS, customElementUpdaterLinkSymbol
21
21
  } from "../dom/constants.mjs";
22
22
 
23
23
  import {Base} from "../types/base.mjs";
@@ -27,11 +27,12 @@ import {ProxyObserver} from "../types/proxyobserver.mjs";
27
27
  import {validateArray, validateInstance} from "../types/validate.mjs";
28
28
  import {clone} from "../util/clone.mjs";
29
29
  import {trimSpaces} from "../util/trimspaces.mjs";
30
+ import {addToObjectLink} from "./attributes.mjs";
30
31
  import {findTargetElementFromEvent} from "./events.mjs";
31
32
  import {findDocumentTemplate} from "./template.mjs";
32
33
  import {getDocument} from "./util.mjs";
33
34
 
34
- export {Updater}
35
+ export {Updater, addObjectWithUpdaterToElement}
35
36
 
36
37
  /**
37
38
  * The updater class connects an object with the dom. In this way, structures and contents in the DOM can be programmatically adapted via attributes.
@@ -252,7 +253,7 @@ function getCheckStateCallback() {
252
253
  /**
253
254
  * @private
254
255
  */
255
- const symbol = Symbol('EventHandler');
256
+ const symbol = Symbol('@schukai/monster/updater@@EventHandler');
256
257
 
257
258
  /**
258
259
  * @private
@@ -308,7 +309,7 @@ function retrieveAndSetValue(element) {
308
309
  throw new Error('the bind argument must start as a value with a path');
309
310
  }
310
311
 
311
- path = path.substr(5);
312
+ path = path.substring(5);
312
313
 
313
314
  let value;
314
315
 
@@ -372,7 +373,7 @@ function retrieveFromBindings() {
372
373
  const self = this;
373
374
 
374
375
  if (self[internalSymbol].element.matches('[' + ATTRIBUTE_UPDATER_BIND + ']')) {
375
- retrieveAndSetValue.call(self, element)
376
+ retrieveAndSetValue.call(self, self[internalSymbol].element)
376
377
  }
377
378
 
378
379
  for (const [, element] of self[internalSymbol].element.querySelectorAll('[' + ATTRIBUTE_UPDATER_BIND + ']').entries()) {
@@ -525,8 +526,6 @@ function insertElement(change) {
525
526
  }
526
527
 
527
528
  }
528
-
529
-
530
529
  }
531
530
 
532
531
  /**
@@ -608,8 +607,6 @@ function updateContent(change) {
608
607
  }
609
608
  }
610
609
  }
611
-
612
-
613
610
  }
614
611
 
615
612
  /**
@@ -869,3 +866,64 @@ function handleInputControlAttributeUpdate(element, name, value) {
869
866
  }
870
867
 
871
868
  }
869
+
870
+
871
+
872
+ /**
873
+ * @param {NodeList|HTMLElement|Set<HTMLElement>} elements
874
+ * @param {Symbol} symbol
875
+ * @param {object} object
876
+ * @return {Promise[]}
877
+ * @license AGPLv3
878
+ * @since 1.23.0
879
+ * @memberOf Monster.DOM
880
+ * @throws {TypeError} elements is not an instance of NodeList, HTMLElement or Set
881
+ * @throws {TypeError} the context of the function is not an instance of HTMLElement
882
+ * @throws {TypeError} symbol must be an instance of Symbol
883
+ */
884
+ function addObjectWithUpdaterToElement (elements,symbol, object) {
885
+ const self = this;
886
+ if (!(self instanceof HTMLElement)) {
887
+ throw new TypeError('the context of this function must be an instance of HTMLElement');
888
+ }
889
+
890
+ if (!(typeof symbol === 'symbol')) {
891
+ throw new TypeError('symbol must be an instance of Symbol');
892
+ }
893
+
894
+ const updaters = new Set;
895
+
896
+ if (elements instanceof NodeList) {
897
+ elements = new Set([
898
+ ...elements
899
+ ])
900
+ } else if (elements instanceof HTMLElement) {
901
+ elements = new Set([
902
+ elements
903
+ ])
904
+ } else if (elements instanceof Set) {
905
+ } else {
906
+ throw new TypeError('elements is not a valid type. (actual: ' + typeof elements + ')');
907
+ }
908
+
909
+ let result = [];
910
+
911
+ elements.forEach((element) => {
912
+ if (!(element instanceof HTMLElement)) return;
913
+ if ((element instanceof HTMLTemplateElement)) return;
914
+
915
+ const u = new Updater(element, object)
916
+ updaters.add(u);
917
+
918
+ result.push(u.run().then(() => {
919
+ return u.enableEventProcessing();
920
+ }));
921
+
922
+ });
923
+
924
+ if (updaters.size > 0) {
925
+ addToObjectLink(self, symbol, updaters);
926
+ }
927
+
928
+ return result;
929
+ }
@@ -99,7 +99,6 @@ export {
99
99
  assembleMethodSymbol,
100
100
  attributeObserverSymbol,
101
101
  registerCustomElement,
102
- assignUpdaterToElement,
103
102
  getSlottedElements
104
103
  } from "./dom/customelement.mjs"
105
104
  export {
@@ -149,7 +149,7 @@ function getMonsterVersion() {
149
149
  }
150
150
 
151
151
  /** don't touch, replaced by make with package.json version */
152
- monsterVersion = new Version('2.2.0')
152
+ monsterVersion = new Version('3.0.0')
153
153
 
154
154
  return monsterVersion;
155
155
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  import chai from "chai"
4
4
  import {internalSymbol} from "../../../../application/source/constants.mjs";
5
- import {ATTRIBUTE_OPTIONS} from "../../../../application/source/dom/constants.mjs";
5
+ import {ATTRIBUTE_OPTIONS, customElementUpdaterLinkSymbol} from "../../../../application/source/dom/constants.mjs";
6
6
  import {getDocument} from "../../../../application/source/dom/util.mjs";
7
+ import {ProxyObserver} from "../../../../application/source/types/proxyobserver.mjs";
8
+ import {addObjectWithUpdaterToElement} from "../../../../application/source/dom/updater.mjs";
7
9
  import {chaiDom} from "../../util/chai-dom.mjs";
8
10
  import {initJSDOM} from "../../util/jsdom.mjs";
9
11
 
@@ -16,10 +18,164 @@ let html1 = `
16
18
  </div>
17
19
  `;
18
20
 
21
+ let html2 = `
22
+ <input data-monster-bind="path:a" id="test2" data-monster-attributes="value path:a">
23
+ `;
24
+
25
+ // defined in constants.mjs
26
+ const updaterSymbolKey = "@schukai/monster/dom/custom-element@@options-updater-link"
27
+ const updaterSymbolSymbol = Symbol.for(updaterSymbolKey);
28
+
29
+
19
30
 
20
31
  describe('DOM', function () {
21
32
 
22
- let CustomElement, registerCustomElement, TestComponent, document, TestComponent2;
33
+ let CustomElement, registerCustomElement, TestComponent, document, TestComponent2,assignUpdaterToElement;
34
+
35
+ // This allows us to inspect the addEventListener calls
36
+
37
+ // let addEventListener = EventTarget.prototype.addEventListener;
38
+ // let removeEventListener = EventTarget.prototype.removeEventListener;
39
+ //
40
+ // before(function (done) {
41
+ // initJSDOM().then(() => {
42
+ //
43
+ // EventTarget.prototype.addEventListener = function (type, callback, options) {
44
+ // /* store args and then… */
45
+ // // callback = (e) => {
46
+ // // console.log("event fired" + e);
47
+ // // callback(e);
48
+ // // };
49
+ //
50
+ // addEventListener.call(this, type, callback, options);
51
+ // };
52
+ //
53
+ // EventTarget.prototype.removeEventListener = function (type, callback, options) {
54
+ // /* remove from stored args and then… */
55
+ // removeEventListener.call(this, type, callback, options);
56
+ // };
57
+ //
58
+ // done(e);
59
+ //
60
+ //
61
+ // });
62
+ //
63
+ //
64
+ // })
65
+ //
66
+ // after(function () {
67
+ // EventTarget.prototype.addEventListener = addEventListener;
68
+ // EventTarget.prototype.removeEventListener = removeEventListener;
69
+ // });
70
+
71
+
72
+ describe("assignUpdaterToElement", function () {
73
+
74
+ before(function (done) {
75
+ initJSDOM().then(() => {
76
+ import("../../../../application/source/dom/customelement.mjs").then((m) => {
77
+ try {
78
+ CustomElement = m['CustomElement'];
79
+ assignUpdaterToElement= function (elements, object) {
80
+ return addObjectWithUpdaterToElement.call(this, elements, updaterSymbolSymbol, object);
81
+ }
82
+
83
+
84
+ document = getDocument();
85
+
86
+ done()
87
+ } catch (e) {
88
+ done(e);
89
+ }
90
+
91
+
92
+ });
93
+
94
+ });
95
+ })
96
+
97
+ beforeEach(() => {
98
+ let mocks = document.getElementById('mocks');
99
+ mocks.innerHTML = html2;
100
+ })
101
+
102
+ afterEach(() => {
103
+ let mocks = document.getElementById('mocks');
104
+ mocks.innerHTML = "";
105
+ })
106
+
107
+ /**
108
+ * this test try to simulate the bug that was found in the assignUpdaterToElement function.
109
+ * The bug was that the updater was not assigned to the element when the element was created.
110
+ *
111
+ * unfortunately, this test does not reproduce the bug.
112
+ */
113
+ it("should assign an updater to an element", function (done) {
114
+ let element = document.getElementById('test2');
115
+
116
+ expect(document.getElementById("mocks").innerHTML).to.equal(html2);
117
+
118
+ const a = {a: 1};
119
+ const b = {b: 2};
120
+
121
+ const ap = new ProxyObserver(a);
122
+ const bp = new ProxyObserver(b);
123
+
124
+ const x = ap.getSubject()
125
+ const y = bp.getSubject()
126
+
127
+ const set = new Set();
128
+ set.add(element);
129
+
130
+ assignUpdaterToElement.call(element, set, ap);
131
+ assignUpdaterToElement.call(element, set, bp);
132
+
133
+ expect(JSON.stringify(x)).to.equal('{"a":1}');
134
+ expect(JSON.stringify(y)).to.equal('{"b":2}');
135
+
136
+ const sy = updaterSymbolSymbol;
137
+
138
+ let v = element.getAttribute("data-monster-objectlink");
139
+ expect(v).to.equal('Symbol('+updaterSymbolKey+')');
140
+
141
+ const updater = element[sy];
142
+
143
+ for (const v of updater) {
144
+ for (const u of v) {
145
+ u.run().then(() => {
146
+ u.enableEventProcessing();
147
+ });
148
+ }
149
+ }
150
+
151
+ expect(updater).to.be.an.instanceof(Set);
152
+ expect(updater).to.be.a("Set");
153
+
154
+ x.a = 3;
155
+ bp.getSubject().b = 4;
156
+
157
+ setTimeout(() => {
158
+
159
+ let mockHTML = document.getElementById("mocks");
160
+
161
+ // html expexted:
162
+ // <input data-monster-bind="path:a" id="test2" data-monster-attributes="value path:a" data-monster-objectlink="Symbol(@schukai/monster/dom/@@object-updater-link)" value="3">
163
+
164
+ expect(mockHTML.querySelector("#test2")).to.have.value('3')
165
+ expect(mockHTML.querySelector("#test2")).to.have.attribute('data-monster-objectlink', 'Symbol('+updaterSymbolKey+')')
166
+ //expect(mockHTML).to.have.html(resultHTML);
167
+
168
+ expect(element.value).to.equal("3");
169
+
170
+ expect(JSON.stringify(ap.getRealSubject())).to.equal('{"a":3}');
171
+ expect(JSON.stringify(bp.getRealSubject())).to.equal('{"b":4}');
172
+ done()
173
+ }, 10)
174
+
175
+ })
176
+
177
+ })
178
+
23
179
 
24
180
  describe('CustomElement()', function () {
25
181
 
@@ -102,7 +258,7 @@ describe('DOM', function () {
102
258
 
103
259
  let monster = document.getElementById('thisisatest');
104
260
  expect(monster.getOption('demotest')).is.eql(1425);
105
-
261
+
106
262
  });
107
263
  });
108
264
 
@@ -133,7 +289,7 @@ describe('DOM', function () {
133
289
  try {
134
290
  expect(document.getElementsByTagName('monster-testclass2').length).is.equal(1);
135
291
  expect(document.getElementsByTagName('monster-testclass2').item(0).shadowRoot.innerHTML).is.equal('<h1></h1><article><p>test</p><div id="container"></div></article>');
136
- expect(document.getElementById('test1')).contain.html('<monster-testclass2 data-monster-objectlink="Symbol(@schukai/monster/dom/@@object-updater-link)"></monster-testclass2>');
292
+ expect(document.getElementById('test1')).contain.html('<monster-testclass2 data-monster-objectlink="Symbol('+updaterSymbolKey+')"></monster-testclass2>');
137
293
  return done();
138
294
  } catch (e) {
139
295
  done(e);
@@ -514,6 +670,4 @@ describe('DOM', function () {
514
670
  })
515
671
 
516
672
  });
517
- });
518
-
519
-
673
+ })
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version('2.2.0')
10
+ monsterVersion = new Version('3.0.0')
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -54,6 +54,7 @@ function initJSDOM(options) {
54
54
  'Document',
55
55
  'Node',
56
56
  'ShadowRoot',
57
+ 'EventTarget',
57
58
  'Event',
58
59
  'CustomEvent',
59
60
  'Element',
@@ -62,6 +63,7 @@ function initJSDOM(options) {
62
63
  'customElements',
63
64
  'DocumentFragment',
64
65
  'DOMParser',
66
+ 'KeyboardEvent',
65
67
  'CSSStyleSheet',
66
68
  'HTMLScriptElement',
67
69
  'MutationObserver',
@@ -14,6 +14,7 @@ import "../cases/dom/updater.mjs";
14
14
  import "../cases/dom/customcontrol.mjs";
15
15
  import "../cases/dom/locale.mjs";
16
16
  import "../cases/dom/theme.mjs";
17
+ import "../cases/dom/resource.mjs";
17
18
  import "../cases/dom/resourcemanager.mjs";
18
19
  import "../cases/dom/util.mjs";
19
20
  import "../cases/dom/customelement.mjs";
@@ -58,6 +59,7 @@ import "../cases/constraint/invalid.mjs";
58
59
  import "../cases/constraint/andoperator.mjs";
59
60
  import "../cases/constraint/oroperator.mjs";
60
61
  import "../cases/constraint/isarray.mjs";
62
+ import "../cases/constraint/abstractoperator.mjs";
61
63
  import "../cases/constraint/valid.mjs";
62
64
  import "../cases/util/trimspaces.mjs";
63
65
  import "../cases/util/deadmansswitch.mjs";
@@ -5,7 +5,7 @@
5
5
  <title>Mocha Monster</title>
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
7
  <link rel="stylesheet" href="mocha.css"/>
8
- <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getOwnPropertySymbols,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
8
+ <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
9
9
  src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,DataView,document,DocumentFragment,Element,Event,globalThis,HTMLDocument,HTMLTemplateElement,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.getOwnPropertyDescriptor,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.iterator,WeakMap,WeakSet"
10
10
  crossorigin="anonymous"
11
11
  referrerpolicy="no-referrer"></script>
@@ -14,8 +14,8 @@
14
14
  </head>
15
15
  <body>
16
16
  <div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
17
- <h1 style='margin-bottom: 0.1em;'>Monster 2.0.16</h1>
18
- <div id="lastupdate" style='font-size:0.7em'>last update Do 29. Dez 14:29:19 CET 2022</div>
17
+ <h1 style='margin-bottom: 0.1em;'>Monster 2.2.1</h1>
18
+ <div id="lastupdate" style='font-size:0.7em'>last update Mi 4. Jan 15:51:44 CET 2023</div>
19
19
  </div>
20
20
  <div id="mocks"></div>
21
21
  <div id="mocha"></div>