1/**
2 * Copyright (c) 2024, The Linux Foundation.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6function filterSamples(input) {
7  const searchQuery = input.value.toLowerCase();
8  const container = input.closest(".code-sample-listing");
9
10  function removeHighlights(element) {
11    const marks = element.querySelectorAll("mark");
12    marks.forEach((mark) => {
13      const parent = mark.parentNode;
14      while (mark.firstChild) {
15        parent.insertBefore(mark.firstChild, mark);
16      }
17      parent.removeChild(mark);
18      parent.normalize(); // Merge adjacent text nodes
19    });
20  }
21
22  function highlightMatches(node, query) {
23    if (node.nodeType === Node.TEXT_NODE) {
24      const text = node.textContent;
25      const index = text.toLowerCase().indexOf(query);
26      if (index !== -1 && query.length > 0) {
27        const highlightedFragment = document.createDocumentFragment();
28
29        const before = document.createTextNode(text.substring(0, index));
30        const highlight = document.createElement("mark");
31        highlight.textContent = text.substring(index, index + query.length);
32        const after = document.createTextNode(text.substring(index + query.length));
33
34        highlightedFragment.appendChild(before);
35        highlightedFragment.appendChild(highlight);
36        highlightedFragment.appendChild(after);
37
38        node.parentNode.replaceChild(highlightedFragment, node);
39      }
40    } else if (node.nodeType === Node.ELEMENT_NODE) {
41      node.childNodes.forEach((child) => highlightMatches(child, query));
42    }
43  }
44
45  function processSection(section) {
46    let sectionVisible = false;
47    const lists = section.querySelectorAll(":scope > ul.code-sample-list");
48    const childSections = section.querySelectorAll(":scope > section");
49
50    // Process lists directly under this section
51    lists.forEach((list) => {
52      let listVisible = false;
53      const items = list.querySelectorAll("li");
54
55      items.forEach((item) => {
56        const nameElement = item.querySelector(".code-sample-name");
57        const descElement = item.querySelector(".code-sample-description");
58
59        removeHighlights(nameElement);
60        removeHighlights(descElement);
61
62        const sampleName = nameElement.textContent.toLowerCase();
63        const sampleDescription = descElement.textContent.toLowerCase();
64
65        if (
66          sampleName.includes(searchQuery) ||
67          sampleDescription.includes(searchQuery)
68        ) {
69          if (searchQuery) {
70            highlightMatches(nameElement, searchQuery);
71            highlightMatches(descElement, searchQuery);
72          }
73
74          item.style.display = "";
75          listVisible = true;
76          sectionVisible = true;
77        } else {
78          item.style.display = "none";
79        }
80      });
81
82      // Show or hide the list based on whether any items are visible
83      list.style.display = listVisible ? "" : "none";
84    });
85
86    // Recursively process child sections
87    childSections.forEach((childSection) => {
88      const childVisible = processSection(childSection);
89      if (childVisible) {
90        sectionVisible = true;
91      }
92    });
93
94    // Show or hide the section heading based on visibility
95    const heading = section.querySelector(
96      ":scope > h2, :scope > h3, :scope > h4, :scope > h5, :scope > h6"
97    );
98    if (sectionVisible) {
99      if (heading) heading.style.display = "";
100      section.style.display = "";
101    } else {
102      if (heading) heading.style.display = "none";
103      section.style.display = "none";
104    }
105
106    return sectionVisible;
107  }
108
109  // Start processing from the container
110  processSection(container);
111
112  // Ensure the input and its container are always visible
113  input.style.display = "";
114  container.style.display = "";
115}
116