@schukai/monster 3.35.4 → 3.36.0

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "3.35.4",
3
+ "version": "3.36.0",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -8,7 +8,7 @@
8
8
  import { getGlobal } from "../types/global.mjs";
9
9
  import { validateString } from "../types/validate.mjs";
10
10
 
11
- export { getDocument, getWindow, getDocumentFragmentFromString, findElementWithIdUpwards };
11
+ export { getDocument, getWindow, getDocumentFragmentFromString, findElementWithIdUpwards,getContainingDocument };
12
12
 
13
13
  /**
14
14
  * This method fetches the document object
@@ -199,3 +199,48 @@ function findElementWithIdUpwards(element, targetId) {
199
199
  // Otherwise, search the current element's parent
200
200
  return findElementWithIdUpwards(element.parentElement, targetId);
201
201
  }
202
+
203
+ /**
204
+ * @private
205
+ * @param {HTMLElement} element
206
+ * @returns {HTMLElement|null}
207
+ */
208
+ function traverseShadowRoots(element) {
209
+ let currentRoot = element.shadowRoot;
210
+ let currentParent = element.parentNode;
211
+
212
+ while (currentParent && currentParent.nodeType !== Node.DOCUMENT_NODE && currentParent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
213
+ if (currentRoot && currentRoot.parentNode) {
214
+ currentParent = currentRoot.parentNode;
215
+ currentRoot = currentParent.shadowRoot;
216
+ } else if (currentParent.parentNode) {
217
+ currentParent = currentParent.parentNode;
218
+ currentRoot = null;
219
+ } else if (currentRoot && currentRoot.host && currentRoot.host.nodeType === Node.DOCUMENT_NODE) {
220
+ currentParent = currentRoot.host;
221
+ currentRoot = null;
222
+ } else {
223
+ currentParent = null;
224
+ currentRoot = null;
225
+ }
226
+ }
227
+
228
+ return currentParent;
229
+ }
230
+
231
+ /**
232
+ * Recursively searches upwards from a given element to find an ancestor element
233
+ *
234
+ * @param {HTMLElement} element
235
+ * @returns {*}
236
+ * @throws {Error} Invalid argument. Expected an HTMLElement.
237
+ * @memberOf Monster.DOM
238
+ * @since 3.36.0
239
+ */
240
+ function getContainingDocument(element) {
241
+ if (!element || !(element instanceof HTMLElement || element instanceof element.ownerDocument.defaultView.HTMLElement)) {
242
+ throw new Error('Invalid argument. Expected an HTMLElement.');
243
+ }
244
+
245
+ return traverseShadowRoots(element) || null;
246
+ }
@@ -142,7 +142,7 @@ function getMonsterVersion() {
142
142
  }
143
143
 
144
144
  /** don't touch, replaced by make with package.json version */
145
- monsterVersion = new Version("3.35.4");
145
+ monsterVersion = new Version("3.36.0");
146
146
 
147
147
  return monsterVersion;
148
148
  }
@@ -2,6 +2,7 @@ import {
2
2
  getDocument, getWindow, getDocumentFragmentFromString
3
3
  } from "../../../../application/source/dom/util.mjs";
4
4
 
5
+ import {getContainingDocument} from "../../../../application/source/dom/util.mjs";
5
6
 
6
7
  import {initJSDOM} from "../../util/jsdom.mjs";
7
8
 
@@ -52,4 +53,63 @@ describe('DOM', function () {
52
53
  });
53
54
 
54
55
  });
56
+
57
+
58
+ describe('getContainingDocument', () => {
59
+ let jsDomDocument;
60
+
61
+ beforeEach(() => {
62
+ jsDomDocument = getDocument();
63
+ });
64
+ //
65
+ // afterEach(() => {
66
+ // dom.window.close();
67
+ // });
68
+
69
+ it('should throw an error when called with an invalid argument', () => {
70
+ expect(() => getContainingDocument(null)).to.throw('Invalid argument. Expected an HTMLElement.');
71
+ });
72
+
73
+ it('should return the correct containing document for an element in the main document', () => {
74
+ const element = jsDomDocument.createElement('div');
75
+ const containingDocument = getContainingDocument(element);
76
+
77
+ expect(containingDocument).to.null;
78
+ });
79
+
80
+ it('should return the correct containing document for an element inside a shadow root', () => {
81
+ const host = jsDomDocument.createElement('div');
82
+ const shadowRoot = host.attachShadow({ mode: 'open' });
83
+ const element = jsDomDocument.createElement('span');
84
+ shadowRoot.appendChild(element);
85
+
86
+ const containingDocument = getContainingDocument(element);
87
+ expect(containingDocument).to.not.null;
88
+ });
89
+
90
+ it('should return the correct containing document for an element inside a nested shadow root', () => {
91
+ const outerHost = jsDomDocument.createElement('div');
92
+ const outerShadowRoot = outerHost.attachShadow({ mode: 'open' });
93
+
94
+ const innerHost = jsDomDocument.createElement('div');
95
+ outerShadowRoot.appendChild(innerHost);
96
+
97
+ const innerShadowRoot = innerHost.attachShadow({ mode: 'open' });
98
+
99
+ const element = jsDomDocument.createElement('span');
100
+ innerShadowRoot.appendChild(element);
101
+
102
+ const containingDocument = getContainingDocument(element);
103
+ expect(containingDocument).to.not.null;
104
+ });
105
+
106
+ it('should return null when the element is not attached to any document', () => {
107
+ const detachedElement = jsDomDocument.createElement('div');
108
+ detachedElement.remove();
109
+
110
+ const containingDocument = getContainingDocument(detachedElement);
111
+ expect(containingDocument).to.be.null;
112
+ });
113
+ });
114
+
55
115
  });
@@ -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("3.35.4")
10
+ monsterVersion = new Version("3.36.0")
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -87,5 +87,5 @@ function initJSDOM(options) {
87
87
  });
88
88
  }
89
89
 
90
- export {initJSDOM,JSDOMExport}
90
+ export {initJSDOM, JSDOMExport}
91
91
 
@@ -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 3.33.0</h1>
18
- <div id="lastupdate" style='font-size:0.7em'>last update Mo 27. Mär 18:10:51 CEST 2023</div>
17
+ <h1 style='margin-bottom: 0.1em;'>Monster 3.35.4</h1>
18
+ <div id="lastupdate" style='font-size:0.7em'>last update Sa 1. Apr 17:29:43 CEST 2023</div>
19
19
  </div>
20
20
  <div id="mocks"></div>
21
21
  <div id="mocha"></div>