import { useState } from "react"; // ============================================= // Sample articles to search through (DO NOT MODIFY) // ============================================= interface Article { id: number; title: string; body: string; } const ARTICLES: Article[] = [ { id: 1, title: "Getting Started with React", body: "React is a JavaScript library for building user interfaces. It lets you compose complex UIs from small, isolated pieces of code called components. React has been designed from the start for gradual adoption, and you can use as little or as much React as you need.", }, { id: 2, title: "Understanding JavaScript Closures", body: "A closure is the combination of a function bundled together with references to its surrounding state. In JavaScript, closures are created every time a function is created, at function creation time. Closures are useful because they let you associate data with a function that operates on that data.", }, { id: 3, title: "CSS Grid Layout Guide", body: "CSS Grid Layout is a two-dimensional layout system for the web. It lets you lay content out in rows and columns. Grid layout gives us a method of creating grid structures that are described in CSS and not in HTML.", }, { id: 4, title: "Introduction to TypeScript", body: "TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale. TypeScript adds additional syntax to JavaScript to support a tighter integration with your editor.", }, { id: 5, title: "Web Performance Optimization", body: "Web performance refers to how quickly site content loads and renders in a web browser. Performance optimization includes reducing load times, making the site interactive sooner, and ensuring smooth scrolling and responsive interactions.", }, { id: 6, title: "Node.js Event Loop Explained", body: "The event loop is what allows Node.js to perform non-blocking operations despite JavaScript being single-threaded. It works by offloading operations to the system kernel whenever possible.", }, ]; // ============================================= // TODO: Implement highlightText function // ============================================= // // This is a FUNCTION-BASED approach — you write a function that // takes a plain string and a query, and returns JSX with matches // wrapped in <mark> tags. // // Signature: // function highlightText(text: string, query: string): React.ReactNode // // Requirements: // 1. If query is empty/whitespace, return the text as-is // 2. Escape special regex characters in the query // 3. Split the text around matches using a capturing group regex: // text.split(new RegExp(`(${escapedQuery})`, "gi")) // This gives alternating [non-match, match, non-match, ...] // 4. Map over the parts — if a part matches the query (case-insensitive), // wrap it in a <mark> with highlight styles // 5. Return the array of JSX elements // // Hints: // - Escape regex special chars: str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") // - Compare with part.toLowerCase() === query.toLowerCase() // - Use index as key since parts are derived from a single string function highlightText(text: string, query: string) { // TODO: Your implementation here // For now, just return the text with no highlighting return text; } export default function App() { const [searchText, setSearchText] = useState(""); // ============================================= // TODO: Filter articles based on search query // ============================================= // Filter ARTICLES where the title OR body contains // the search text (case-insensitive). // If searchText is empty, show all articles. // // Hint: use .filter() with .toLowerCase().includes() const filteredList = ARTICLES; // ← replace with filtered version return ( <div style={{ maxWidth: 640, margin: "0 auto", padding: 24, fontFamily: "system-ui" }}> <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 4 }}> Search with Highlighting </h2> <p style={{ fontSize: 14, color: "#666", marginBottom: 24 }}> Build a search that filters articles and highlights all occurrences of the query in both titles and body text. Implement the{" "} <code>highlightText</code> function and the filtering logic. </p> {/* Search input */} <div style={{ marginBottom: 16 }}> <input type="text" placeholder="Search articles..." value={searchText} onChange={(e) => setSearchText(e.target.value)} style={{ width: "100%", padding: "10px 14px", border: "1px solid #d1d5db", borderRadius: 8, fontSize: 14, outline: "none", boxSizing: "border-box", }} /> </div> {/* Results count */} <div style={{ marginBottom: 16, fontSize: 13, color: "#999" }}> Showing {filteredList.length} of {ARTICLES.length} articles </div> {/* Article list */} <div style={{ display: "flex", flexDirection: "column", gap: 12 }}> {filteredList.map((article) => ( <div key={article.id} style={{ border: "1px solid #e5e7eb", borderRadius: 8, padding: 16, }} > {/* TODO: Use highlightText() on the title and body */} <h3 style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}> {highlightText(article.title, searchText)} </h3> <p style={{ fontSize: 13, color: "#666", lineHeight: 1.6, margin: 0 }}> {highlightText(article.body, searchText)} </p> </div> ))} {filteredList.length === 0 && ( <div style={{ textAlign: "center", color: "#999", fontSize: 14, padding: "40px 0" }}> No articles match your search. </div> )} </div> {/* Hint */} <div style={{ marginTop: 24, padding: 16, background: "#f9fafb", borderLeft: "4px solid #111", borderRadius: "0 8px 8px 0", fontSize: 13, color: "#555", }}> <strong>Approach:</strong> Split text around matches using a capturing group regex: <code style={{ background: "#f3f4f6", padding: "2px 6px", borderRadius: 4, fontSize: 12 }}> text.split(new RegExp(`(${"\{"}escaped{"\}"})`, "gi")) </code> — this gives alternating non-match and match segments. Map over them and wrap matches in a <code><mark></code> tag. <ul style={{ margin: "8px 0 0 16px", padding: 0, lineHeight: 1.8 }}> <li>Escape special regex characters in the query first</li> <li>Compare <code>part.toLowerCase() === query.toLowerCase()</code> to identify matches</li> <li>Also implement the article filtering with <code>.filter()</code></li> </ul> </div> </div> ); }