diff --git a/components/utils/regex-tester.utils.test.ts b/components/utils/regex-tester.utils.test.ts index e3bde85..14ffa7a 100644 --- a/components/utils/regex-tester.utils.test.ts +++ b/components/utils/regex-tester.utils.test.ts @@ -1,4 +1,26 @@ -import { createRegex } from "./regex-tester.utils"; +import { createRegex, escapeRegexPattern } from "./regex-tester.utils"; + +describe("escapeRegexPattern", () => { + test("should escape special regex characters", () => { + expect(escapeRegexPattern("hello.world")).toBe("hello\\.world"); + expect(escapeRegexPattern("a*b+c?")).toBe("a\\*b\\+c\\?"); + expect(escapeRegexPattern("(test)")).toBe("\\(test\\)"); + expect(escapeRegexPattern("[abc]")).toBe("\\[abc\\]"); + expect(escapeRegexPattern("a{1,2}")).toBe("a\\{1,2\\}"); + expect(escapeRegexPattern("a|b")).toBe("a\\|b"); + expect(escapeRegexPattern("^start$end")).toBe("\\^start\\$end"); + expect(escapeRegexPattern("back\\slash")).toBe("back\\\\slash"); + }); + + test("should return plain text unchanged", () => { + expect(escapeRegexPattern("hello world")).toBe("hello world"); + expect(escapeRegexPattern("abc123")).toBe("abc123"); + }); + + test("should handle empty string", () => { + expect(escapeRegexPattern("")).toBe(""); + }); +}); describe("createRegex", () => { test("should create regex from simple pattern without flags and delimiters", () => { diff --git a/components/utils/regex-tester.utils.ts b/components/utils/regex-tester.utils.ts index ef73a5f..697d9b9 100644 --- a/components/utils/regex-tester.utils.ts +++ b/components/utils/regex-tester.utils.ts @@ -1,3 +1,7 @@ +export const escapeRegexPattern = (text: string): string => { + return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +}; + export const createRegex = (pattern: string): RegExp => { if (typeof pattern !== "string" || pattern.trim() === "") { throw new Error("Pattern must be a non-empty string"); diff --git a/pages/utilities/regex-tester.tsx b/pages/utilities/regex-tester.tsx index c32a13d..ca49e13 100644 --- a/pages/utilities/regex-tester.tsx +++ b/pages/utilities/regex-tester.tsx @@ -2,12 +2,16 @@ import { useState, useEffect, useCallback } from "react"; import { Textarea } from "@/components/ds/TextareaComponent"; import PageHeader from "@/components/PageHeader"; import { Card } from "@/components/ds/CardComponent"; +import { Button } from "@/components/ds/ButtonComponent"; import { Label } from "@/components/ds/LabelComponent"; import Header from "@/components/Header"; import { CMDK } from "@/components/CMDK"; import Meta from "@/components/Meta"; import RegexHighlightText from "@/components/RegexHighlightText"; -import { createRegex } from "@/components/utils/regex-tester.utils"; +import { + createRegex, + escapeRegexPattern, +} from "@/components/utils/regex-tester.utils"; import CallToActionGrid from "@/components/CallToActionGrid"; import GitHubContribution from "@/components/GitHubContribution"; @@ -17,6 +21,14 @@ export default function RegexTester() { const [result, setResult] = useState("Please fill out"); const [matches, setMatches] = useState(null); + const handleFixPattern = useCallback(() => { + if (!testString.trim()) { + return; + } + const escapedPattern = escapeRegexPattern(testString); + setPattern(escapedPattern); + }, [testString]); + const handleTest = useCallback(() => { try { const regex = createRegex(pattern); @@ -81,9 +93,17 @@ export default function RegexTester() { rows={1} placeholder="Enter regex pattern here (e.g., /pattern/g)" onChange={(event) => setPattern(event.target.value)} - className="mb-6 min-h-0" + className="mb-4 min-h-0" value={pattern} /> +