From b6fe63a924bf7c819940310abb183b9eb3b3a45c Mon Sep 17 00:00:00 2001
From: Lionel Duboeuf <lduboeuf@ouvaton.org>
Date: Fri, 29 Nov 2024 12:15:07 +0100
Subject: [PATCH] fix ":is(" not supported css selector

---
 src/Morph/Web/MorphWebView.qml           | 20 ++++---
 src/Morph/Web/queryselector_overrides.js | 66 ++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 6 deletions(-)
 create mode 100644 src/Morph/Web/queryselector_overrides.js

diff --git a/src/Morph/Web/MorphWebView.qml b/src/Morph/Web/MorphWebView.qml
index 01f5d52b2..d68dd8766 100644
--- a/src/Morph/Web/MorphWebView.qml
+++ b/src/Morph/Web/MorphWebView.qml
@@ -75,12 +75,20 @@ WebEngineView {
         return (request.type === JavaScriptDialogRequest.DialogTypePrompt && request.message==='XX-MORPH-SELECT-OVERRIDE-XX')
     }
 
-    userScripts: WebEngineScript {
-        runOnSubframes: true
-        sourceUrl: enableSelectOverride && (screenDiagonal > 0 && screenDiagonal < 190)  ? Qt.resolvedUrl("select_overrides.js") : ""
-        injectionPoint: WebEngineScript.DocumentCreation
-        worldId: WebEngineScript.MainWorld
-    }
+    userScripts: [
+        WebEngineScript {
+            runOnSubframes: true
+            sourceUrl: enableSelectOverride && (screenDiagonal > 0 && screenDiagonal < 190)  ? Qt.resolvedUrl("select_overrides.js") : ""
+            injectionPoint: WebEngineScript.DocumentCreation
+            worldId: WebEngineScript.MainWorld
+        },
+         WebEngineScript {
+            //runOnSubframes: true
+            sourceUrl: Qt.resolvedUrl("queryselector_overrides.js")
+            injectionPoint: WebEngineScript.DocumentCreation
+            worldId: WebEngineScript.MainWorld
+         }
+    ]
 
     onJavaScriptDialogRequested: function(request) {
 
diff --git a/src/Morph/Web/queryselector_overrides.js b/src/Morph/Web/queryselector_overrides.js
new file mode 100644
index 000000000..95634367f
--- /dev/null
+++ b/src/Morph/Web/queryselector_overrides.js
@@ -0,0 +1,66 @@
+(function() {
+    // Backup original methods
+    const originalElementQuerySelector = Element.prototype.querySelector;
+    const originalElementQuerySelectorAll = Element.prototype.querySelectorAll;
+    const originalDocumentQuerySelector = Document.prototype.querySelector;
+    const originalDocumentQuerySelectorAll = Document.prototype.querySelectorAll;
+
+    function emulateIs(selector, context) {
+        const isRegex = /:is\(([^)]+)\)/;
+
+        if (!isRegex.test(selector)) {
+            return selector;
+        }
+
+        let transformedSelector = selector;
+        const matchedElements = new Set();
+
+        let match;
+        while ((match = isRegex.exec(transformedSelector)) !== null) {
+            const options = match[1].split(',').map(s => s.trim());
+
+            const [beforeIs, afterIs] = transformedSelector.split(match[0]);
+
+            const baseSelector = beforeIs.trim() || '*';
+            const nodeList = context.querySelectorAll(baseSelector);
+
+            nodeList.forEach(element => {
+                if (options.some(option => {
+                    return element.matches(option);
+                })) {
+                    matchedElements.add(element);
+                }
+            });
+
+            transformedSelector = afterIs.trim();
+        }
+
+        return Array.from(matchedElements);
+    }
+
+    Document.prototype.querySelector = Element.prototype.querySelector = function(selector) {
+        const context = this;
+        const transformed = emulateIs(selector, context);
+        console.log('querySelector', selector, transformed)
+        if (typeof transformed === 'string') {
+            return (this instanceof Document)
+                ? originalDocumentQuerySelector.call(this, transformed)
+                : originalElementQuerySelector.call(this, transformed);
+        }
+        return transformed[0] || null;
+    };
+
+    Document.prototype.querySelectorAll = Element.prototype.querySelectorAll = function(selector) {
+        const context = this;
+        const transformed = emulateIs(selector, context);
+        console.log('querySelectorAll', selector, transformed)
+        if (typeof transformed === 'string') {
+            return (this instanceof Document)
+                ? originalDocumentQuerySelectorAll.call(this, transformed)
+                : originalElementQuerySelectorAll.call(this, transformed);
+        }
+        return transformed;
+    };
+
+    console.log('querySelector and querySelectorAll have been overridden');
+})();
-- 
GitLab
