diff --git a/src/components/keyword-highlighter.tsx b/src/components/keyword-highlighter.tsx new file mode 100644 index 0000000..9c2090c --- /dev/null +++ b/src/components/keyword-highlighter.tsx @@ -0,0 +1,35 @@ +"use client"; + +import React from "react"; + +interface KeywordHighlighterProps { + text: string; + keyword: string | null | undefined; +} + +export function KeywordHighlighter({ text, keyword }: KeywordHighlighterProps) { + if (!keyword || !text || keyword.trim() === "") { + return <>{text}; + } + + const escapedKeyword = keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + const regex = new RegExp(`(${escapedKeyword})`, "gi"); + const parts = text.split(regex); + + return ( + <> + {parts.map((part, i) => + regex.test(part) ? ( + + {part} + + ) : ( + part + ) + )} + + ); +} \ No newline at end of file diff --git a/src/components/meta-form.tsx b/src/components/meta-form.tsx index fcef515..2801f9e 100644 --- a/src/components/meta-form.tsx +++ b/src/components/meta-form.tsx @@ -29,6 +29,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { ImageAltDisplay } from "./image-alt-display"; import { TabIndicator } from "./tab-indicator"; import { getLengthIndicatorColor, type IndicatorColor } from "@/lib/analysis"; +import { KeywordHighlighter } from "./keyword-highlighter"; interface MetaData { title: string; @@ -259,6 +260,7 @@ export function MetaForm() { title={editableTitle} description={editableDescription} url={url} + keyword={metaData.keyword} /> {metaData.image && ( @@ -331,7 +333,14 @@ export function MetaForm() { /> ) : (

- {editableTitle || "Not found"} + {editableTitle ? ( + + ) : ( + "Not found" + )}

)} @@ -385,7 +394,14 @@ export function MetaForm() { /> ) : (

- {editableDescription || "Not found"} + {editableDescription ? ( + + ) : ( + "Not found" + )}

)} diff --git a/src/components/serp-preview.tsx b/src/components/serp-preview.tsx index 7d5967a..0a632f5 100644 --- a/src/components/serp-preview.tsx +++ b/src/components/serp-preview.tsx @@ -1,14 +1,21 @@ "use client"; import { Globe } from "lucide-react"; +import { KeywordHighlighter } from "./keyword-highlighter"; interface SerpPreviewProps { title: string; description: string; url: string; + keyword?: string | null; } -export function SerpPreview({ title, description, url }: SerpPreviewProps) { +export function SerpPreview({ + title, + description, + url, + keyword, +}: SerpPreviewProps) { const formatUrl = (fullUrl: string) => { try { let formattedUrl = fullUrl; @@ -18,7 +25,7 @@ export function SerpPreview({ title, description, url }: SerpPreviewProps) { const urlObject = new URL(formattedUrl); const path = urlObject.pathname === "/" ? "" : urlObject.pathname; // remove trailing slash - const displayPath = path.endsWith('/') ? path.slice(0, -1) : path; + const displayPath = path.endsWith("/") ? path.slice(0, -1) : path; return `${urlObject.hostname}${displayPath}`; } catch (error) { return fullUrl; @@ -41,11 +48,16 @@ export function SerpPreview({ title, description, url }: SerpPreviewProps) {

- {title || "Meta Title Preview"} +

- {description || - "This is where the meta description will be displayed. It provides a brief summary of the page's content for search engine users."} +

);