Forráskód Böngészése

Merge pull request #16718 from Haoming02/bracket-checker-order

[Bracket Checker] Also check for the order of brackets
w-e-w 8 hónapja
szülő
commit
e8c3b1f2a0

+ 55 - 22
extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js

@@ -1,36 +1,69 @@
-// Stable Diffusion WebUI - Bracket checker
-// By Hingashi no Florin/Bwin4L & @akx
+// Stable Diffusion WebUI - Bracket Checker
+// By @Bwin4L, @akx, @w-e-w, @Haoming02
 // Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
 // Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
-// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
+// If there's a mismatch, the keyword counter turns red, and if you hover on it, a tooltip tells you what's wrong.
+
+function checkBrackets(textArea, counterElem) {
+    const pairs = [
+        ['(', ')', 'round brackets'],
+        ['[', ']', 'square brackets'],
+        ['{', '}', 'curly brackets']
+    ];
 
 
-function checkBrackets(textArea, counterElt) {
     const counts = {};
     const counts = {};
-    textArea.value.matchAll(/(?<!\\)(?:\\\\)*?([(){}[\]])/g).forEach(bracket => {
-        counts[bracket[1]] = (counts[bracket[1]] || 0) + 1;
-    });
-    const errors = [];
-
-    function checkPair(open, close, kind) {
-        if (counts[open] !== counts[close]) {
-            errors.push(
-                `${open}...${close} - Detected ${counts[open] || 0} opening and ${counts[close] || 0} closing ${kind}.`
-            );
+    const errors = new Set();
+    let i = 0;
+
+    while (i < textArea.value.length) {
+        let char = textArea.value[i];
+        let escaped = false;
+        while (char === '\\' && i + 1 < textArea.value.length) {
+            escaped = !escaped;
+            i++;
+            char = textArea.value[i];
+        }
+
+        if (escaped) {
+            i++;
+            continue;
+        }
+
+        for (const [open, close, label] of pairs) {
+            if (char === open) {
+                counts[label] = (counts[label] || 0) + 1;
+            } else if (char === close) {
+                counts[label] = (counts[label] || 0) - 1;
+                if (counts[label] < 0) {
+                    errors.add(`Incorrect order of ${label}.`);
+                }
+            }
+        }
+
+        i++;
+    }
+
+    for (const [open, close, label] of pairs) {
+        if (counts[label] == undefined) {
+            continue;
+        }
+
+        if (counts[label] > 0) {
+            errors.add(`${open} ... ${close} - Detected ${counts[label]} more opening than closing ${label}.`);
+        } else if (counts[label] < 0) {
+            errors.add(`${open} ... ${close} - Detected ${-counts[label]} more closing than opening ${label}.`);
         }
         }
     }
     }
 
 
-    checkPair('(', ')', 'round brackets');
-    checkPair('[', ']', 'square brackets');
-    checkPair('{', '}', 'curly brackets');
-    counterElt.title = errors.join('\n');
-    counterElt.classList.toggle('error', errors.length !== 0);
+    counterElem.title = [...errors].join('\n');
+    counterElem.classList.toggle('error', errors.size !== 0);
 }
 }
 
 
 function setupBracketChecking(id_prompt, id_counter) {
 function setupBracketChecking(id_prompt, id_counter) {
-    var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
-    var counter = gradioApp().getElementById(id_counter);
+    const textarea = gradioApp().querySelector(`#${id_prompt} > label > textarea`);
+    const counter = gradioApp().getElementById(id_counter);
 
 
     if (textarea && counter) {
     if (textarea && counter) {
-        textarea.addEventListener("input", () => checkBrackets(textarea, counter));
+        onEdit(`${id_prompt}_BracketChecking`, textarea, 400, () => checkBrackets(textarea, counter));
     }
     }
 }
 }