mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
feat(filters): improve RegexField validation (#803)
* make sure fields are validated on page load * make red border only show if useRegex enabled * ensure tooltips have higher z-index in RegexField removed z-index in customtooltip.tsx as its causing issues with tooltips in other components * improved regex validation return false for cases that are unsupported by Go * improved check for unsupported conditionals thanks nuxen
This commit is contained in:
parent
169863dded
commit
195b2929e0
2 changed files with 52 additions and 8 deletions
|
@ -1,8 +1,9 @@
|
|||
import { Field, FieldProps } from "formik";
|
||||
import { Field, FieldProps, useFormikContext } from "formik";
|
||||
import { classNames } from "../../utils";
|
||||
import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
||||
import { useToggle } from "../../hooks/hooks";
|
||||
import { CustomTooltip } from "../tooltips/CustomTooltip";
|
||||
import { useEffect } from "react";
|
||||
|
||||
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
|
||||
|
@ -100,16 +101,52 @@ export const RegexField = ({
|
|||
tooltip,
|
||||
disabled
|
||||
}: RegexFieldProps) => {
|
||||
const golangRegex = /^((\\\*|\\\?|\\[^\s\\])+|\(\?i\))(\|((\\\*|\\\?|\\[^\s\\])+|\(\?i\)))*$/;
|
||||
|
||||
const validRegex = (pattern: string) => {
|
||||
|
||||
// Check for unsupported lookahead and lookbehind assertions
|
||||
if (/\(\?<=|\(\?<!|\(\?=|\(\?!/.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported atomic groups
|
||||
if (/\(\?>/.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported recursive patterns
|
||||
if (/\(\?(R|0)\)/.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported possessive quantifiers
|
||||
if (/[*+?]{1}\+|\{[0-9]+,[0-9]*\}\+/.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported control verbs
|
||||
if (/\\g</.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported conditionals
|
||||
if (/\(\?\((\?[=!][^)]*)\)[^)]*\|?[^)]*\)/.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for unsupported backreferences
|
||||
if (/\\k</.test(pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the pattern is a valid regex
|
||||
try {
|
||||
new RegExp(golangRegex.source + pattern);
|
||||
new RegExp(pattern);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const validateRegexp = (val: string) => {
|
||||
let error = "";
|
||||
|
@ -121,6 +158,13 @@ export const RegexField = ({
|
|||
return error;
|
||||
};
|
||||
|
||||
const { validateForm } = useFormikContext();
|
||||
useEffect(() => {
|
||||
if (useRegex) {
|
||||
validateForm();
|
||||
}
|
||||
}, [useRegex]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
|
@ -135,7 +179,7 @@ export const RegexField = ({
|
|||
>
|
||||
<div className="flex">
|
||||
{label}
|
||||
{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}
|
||||
<span className="z-10">{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}</span>
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
|
@ -152,7 +196,7 @@ export const RegexField = ({
|
|||
defaultValue={defaultValue}
|
||||
autoComplete={autoComplete}
|
||||
className={classNames(
|
||||
meta.touched && meta.error
|
||||
useRegex && meta.error
|
||||
? "focus:ring-red-500 focus:border-red-500 border-red-500"
|
||||
: "focus:ring-blue-500 dark:focus:ring-blue-500 focus:border-blue-500 dark:focus:border-blue-500 border-gray-300 dark:border-gray-700",
|
||||
disabled
|
||||
|
@ -166,7 +210,7 @@ export const RegexField = ({
|
|||
{useRegex && (
|
||||
<div className="relative">
|
||||
<div className="flex float-right items-center">
|
||||
{meta.touched && !meta.error ? (
|
||||
{!meta.error ? (
|
||||
<CheckCircleIcon className="dark:bg-gray-800 bg-white h-8 w-8 mb-2.5 pl-1 text-green-500 right-2 absolute transform -translate-y-1/2" aria-hidden="true" style={{ overflow: "hidden" }} />
|
||||
) : (
|
||||
<XCircleIcon className="dark:bg-gray-800 bg-white h-8 w-8 mb-2.5 pl-1 text-red-500 right-2 absolute transform -translate-y-1/2" aria-hidden="true" style={{ overflow: "hidden" }} />
|
||||
|
|
|
@ -18,7 +18,7 @@ export const CustomTooltip = ({
|
|||
const id = `${anchorId}-tooltip`;
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<svg id={id} className="z-10 ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
|
||||
<svg id={id} className="ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
|
||||
<Tooltip style= {{ maxWidth: "350px", fontSize: "12px", textTransform: "none", fontWeight: "normal", borderRadius: "0.375rem", backgroundColor: "#34343A", color: "#fff", opacity: "1" }} delayShow={100} delayHide={150} place={place} anchorId={id} data-html={true} clickable={clickable}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue