Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Custom Highlight API #4280

Open
4 tasks done
ghost opened this issue Oct 14, 2024 · 2 comments
Open
4 tasks done

CSS Custom Highlight API #4280

ghost opened this issue Oct 14, 2024 · 2 comments
Labels
enhancement New feature or request theme Related to the theme

Comments

@ghost
Copy link

ghost commented Oct 14, 2024

Is your feature request related to a problem? Please describe.

Highlighting search results keywords using string replacement is outdated

Describe the solution you'd like

Native API CSS.highlights
https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API

const query = document.getElementById("query");
const article = document.querySelector("article");

// Find all text nodes in the article. We'll search within
// these text nodes.
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
  allTextNodes.push(currentNode);
  currentNode = treeWalker.nextNode();
}

// Listen to the input event to run the search.
query.addEventListener("input", () => {
  // If the CSS Custom Highlight API is not supported,
  // display a message and bail-out.
  if (!CSS.highlights) {
    article.textContent = "CSS Custom Highlight API not supported.";
    return;
  }

  // Clear the HighlightRegistry to remove the
  // previous search results.
  CSS.highlights.clear();

  // Clean-up the search query and bail-out if
  // if it's empty.
  const str = query.value.trim().toLowerCase();
  if (!str) {
    return;
  }

  // Iterate over all text nodes and find matches.
  const ranges = allTextNodes
    .map((el) => {
      return { el, text: el.textContent.toLowerCase() };
    })
    .map(({ text, el }) => {
      const indices = [];
      let startPos = 0;
      while (startPos < text.length) {
        const index = text.indexOf(str, startPos);
        if (index === -1) break;
        indices.push(index);
        startPos = index + str.length;
      }

      // Create a range object for each instance of
      // str we found in the text node.
      return indices.map((index) => {
        const range = new Range();
        range.setStart(el, index);
        range.setEnd(el, index + str.length);
        return range;
      });
    });

  // Create a Highlight object for the ranges.
  const searchResultsHighlight = new Highlight(...ranges.flat());

  // Register the Highlight object in the registry.
  CSS.highlights.set("search-results", searchResultsHighlight);
});

css

::highlight(search-results) {
  background-color: #f06;
  color: white;
}

Describe alternatives you've considered

No response

Additional context

No response

Validations

@ghost
Copy link
Author

ghost commented Oct 14, 2024

Adding keyword highlighting to the search results page would be even better

@brc-dd brc-dd added enhancement New feature or request theme Related to the theme labels Oct 14, 2024
@brc-dd
Copy link
Member

brc-dd commented Oct 14, 2024

Very nice. But it currently doesn't match our browser support criteria (chrome/edge >= 88, firefox >= 78, safari >= 14). In future, we might replace mark.js with it 👀 Keeping this open for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request theme Related to the theme
Projects
None yet
Development

No branches or pull requests

1 participant