Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
1.6 kB ยท 59 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960"use client";
import { useSearchParams } from "next/navigation";import { useEffect, useRef } from "react";
import { buildHighlightRegex } from "./utils/search-match";
function escapeHtml(input: string) { return input.replace(/[&<>]/g, (c) => c === "&" ? "&" : c === "<" ? "<" : ">", );}
function highlight(root: HTMLElement, query: string) { const regex = buildHighlightRegex(query); if (!regex) return;
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
const textNodes: Text[] = []; let node = walker.nextNode();
while (node) { if (node instanceof Text) { textNodes.push(node); } node = walker.nextNode(); }
for (const textNode of textNodes) { const nodeValue = textNode.nodeValue; // `g`-flag .test is stateful โ reset so a hit in one node can't skip the next. regex.lastIndex = 0; if (!nodeValue || !regex.test(nodeValue)) continue;
const span = document.createElement("span"); // Escape first โ the text node's value must not parse as HTML. span.innerHTML = escapeHtml(nodeValue).replace( regex, (match) => `<mark>${match}</mark>`, );
textNode.parentNode?.replaceChild(span, textNode); }}
export function HighlightText({ children }: { children: React.ReactNode }) { const ref = useRef<HTMLDivElement>(null); const searchParams = useSearchParams(); const q = searchParams.get("q");
useEffect(() => { if (ref.current && q) { highlight(ref.current, q); } }, [q]);
return <div ref={ref}>{children}</div>;}