Search code examples
regexintellij-ideasearch

Intellij HTML Tags Find usage with filter


I would like to find all usages of a certain html tag and filter the results via attributes.

<tag attribute1="'text123'" />

<tag attribute2="'true'" 
     attribute1="'text1'"/>

<tag attribute2="'true'"/>

=> Find all tags "tag" with attribute1 set => 3rd example is ignored

Searching could be an alternative, but should respect multilines.

Any help would be appreciated


Solution

  • We could have a quick go with this simple pattern:

    <tag\b[^>]*?attribute1\s*=\s*"([^"]*)"[^>]*>
    

    But it's not 100% correct.

    Explanation and improvements

    • <tag\b will search for the opening tag, with \b as word boundary, to avoid matching "<tagada />", or something starting with "tag". We can improve it by replacing it by <\s*tag\b as it is allowed to have space chars before the tag name.

    • [^>]*? will match any chars not being ">", in an un-greedy way, because we want the search engine to try matching attribute1 after the optional preceding attributes.

    • attribute1\s*=\s*"([^"]*)" will find attribute1 with its value, captured in the group n°1. We could be more precise by adding \b in front of attribute1 just to be sure not to match another attribute which could be called myattribute1. But unfortunately, this will not totally work, because HTML attributes can contain hyphens, such as the common data-* attributes, so in our case, we could have my-attribute1="...", which would not work by using the preceding \b. But this can be solved by using a positive lookbehind, searching for a space char before it, leading to (?<=\s)attribute1\s*=\s*"([^"]*)".

    • The last part [^>]*> is optional, as it matches the attributes after attribute1 and the closing ">". We don't really need it, but this depends on what you would like to do with your search results.

    Adding the improvements, we get this pattern:

    <\s*tag\b[^>]*?(?<=\s)attribute1\s*=\s*"([^"]*)"[^>]*>
    

    According to IntelliJ IDEA's documentation, the search engine uses Java's regular expression flavour, so it should also work with this search pattern.

    Test it live with Java's regex flavour: https://regex101.com/r/spZG7c/2

    Live demo using JavaScript:

    const pattern = /<\s*tag\b[^>]*?(?<=\s)attribute1\s*=\s*"([^"]*)"[^>]*>/giu;
    
    // When the document is ready, attach the event handlers.
    document.addEventListener("DOMContentLoaded", function () {
      const input = document.getElementById("input");
      const searchButton = document.getElementById("search");
     
      searchButton.addEventListener('click', (event) => {
        console.log([...input.value.matchAll(pattern)]);
        event.preventDefault();
        return false;
      });
    });
    *, *::before, *::after { box-sizing: border-box; }
    
    form {
      /* Display the form in two columns. */
      display: flex;
      flex-direction: row;
      column-gap: 1em;
    }
    
    form > div:first-child {
      width: calc(100% - 6em); /* 100% - gap - right column. */
      min-width: 20em; /* Enough for the textarea content. */
    }
    
    form > div:last-child {
      width: 5em; /* Enough for the button. */
    }
    
    textarea {
      width: 100%; /* Override cols="80". */
      font-size: .85em;
    }
    
    .as-console-row-code {
      font-size: .85em !important; /* Instead of 13px. */
    }
    <form action="#">
      <div>
        <textarea name="input" id="input" cols="80" rows="13"
                  placeholder="Enter your HTML here">&lt;tag attribute1=&quot;'text123'&quot; /&gt;
    &lt;TAG attribute2=&quot;'true'&quot; attribute1=&quot;'text1'&quot;/&gt;
    &lt;tag attribute2=&quot;'true'&quot;/&gt;
    &lt; tag type=&quot;apple&quot; title=&quot;Golden apple&quot;
      ATTRIBUTE1=&quot;value&quot; /&gt;
    &lt;tagger attribute1=&quot;something&quot;&gt;
       &lt;tag data-id=&quot;6735&quot;
            attribute1=&quot;'some more text'&quot;
            required &gt;
          Whatever in here
       &lt;/tag&gt;
    &lt;/tagger&gt;
    &lt;tag matching=&quot;false&quot; data-attribute1=&quot;&quot; /&gt;</textarea>
      </div>
      <div>
        <button id="search"
           title="Search for &lt;tag ... attribute1 ...&gt;">
           Search
        </button>
      </div>
    </form>