Repository: exadel-inc/esl
Pull request #1129 (2022-08-02 01:04:02)

chore: squash fix for #1120
Tech PR to merge #1120 properly


Patch:
diff --git a/src/modules/esl-traversing-query/core/esl-traversing-query.ts b/src/modules/esl-traversing-query/core/esl-traversing-query.ts
index 8b2f5a1a2..b34818567 100644
--- a/src/modules/esl-traversing-query/core/esl-traversing-query.ts
+++ b/src/modules/esl-traversing-query/core/esl-traversing-query.ts
@@ -95,8 +95,35 @@ export class TraversingQuery {
     }
     return uniq(result);
   }
+  /** Split multiple queries separated by comma (respects query brackets) */
+  // This can be solved by RegEx /(?<!\([^\)]*),(?![^\(]*\))/g)/, when the WebKit browser implements this feature
+  public static splitQueries(str: string): string[] {
+    let last = 0;
+    let stack = 0;
+    const result = [];
+    for (let i = 0; i < str.length; i++) {
+      if (str[i] === '(') stack++;
+      if (str[i] === ')') stack = Math.max(0, stack - 1);
+      if (str[i] === ',' && !stack) {
+        result.push(str.substring(last, i).trim());
+        last = i + 1;
+      }
+    }
+    result.push(str.substring(last).trim());
+    return result;
+  }
+
+  protected static traverse(query: string, findFirst: boolean, base?: Element | null, scope: Element | Document = document): Element[] {
+    const found: Element[] = [];
+    for (const part of TraversingQuery.splitQueries(query)) {
+      const els = this.traverseQuery(part, findFirst, base, scope);
+      if (findFirst && els.length) return [els[0]];
+      found.push(...els);
+    }
+    return found;
+  }
 
-  static traverse(query: string, findFirst: boolean, base?: Element | null, scope: Element | Document = document): Element[] {
+  protected static traverseQuery(query: string, findFirst: boolean, base?: Element | null, scope: Element | Document = document): Element[] {
     const parts = query.split(this.PROCESSORS_REGEX).map((term) => term.trim());
     const rootSel = parts.shift();
     const baseCollection = base ? [base] : [];


Test patch:
diff --git a/src/modules/esl-traversing-query/test/esl-traversing-query.test.ts b/src/modules/esl-traversing-query/test/esl-traversing-query.test.ts
index efd755e06..7681f65f4 100644
--- a/src/modules/esl-traversing-query/test/esl-traversing-query.test.ts
+++ b/src/modules/esl-traversing-query/test/esl-traversing-query.test.ts
@@ -169,4 +169,31 @@ describe('Traversing Query tests', () => {
         .toEqual(expectedCollection);
     });
   });
+  describe('TraversingQuery should support multiple queries separated by comma', () => {
+    test.each([
+      ['::parent,::next', btn1, [row1, btn2]],
+      ['::next,  ::parent', btn1, [btn2, row1]],
+      ['::parent  ,::next', btn2, [row1, btn3]],
+      ['::find(button, article)::filter(:first-child)', row1, [btn1]],
+    ])('TraversingQuery.all/one, Sel: %s, Base: %p.', traversingQueryWrap);
+  });
+
+  describe('TraversingQuery.splitQueries split string with query syntax in mind', () => {
+    test.each([
+      ['', ['']],
+      ['(,)', ['(,)']],
+      ['((,)', ['((,)']],
+      ['()),(,)', ['())', '(,)']],
+      ['))(),((),)', ['))()', '((),)']],
+      ['a,b', ['a', 'b']],
+      ['a, b', ['a', 'b']],
+      ['a,b ,c ', ['a', 'b', 'c']],
+      ['a,(b),c', ['a', '(b)', 'c']],
+      ['a,(b, b),c', ['a', '(b, b)', 'c']],
+      ['(a,b),c', ['(a,b)', 'c']],
+    ])('%s -> %p', (inp: string, out: string[]) =>
+    {
+      expect(TraversingQuery.splitQueries(inp)).toEqual(out);
+    });
+  });
 });