diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index ad4de0868a4..af6b52cf87d 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -1299,11 +1299,6 @@ "count": 2 } }, - "web/app/components/base/image-uploader/image-link-input.tsx": { - "regexp/no-unused-capturing-group": { - "count": 1 - } - }, "web/app/components/base/image-uploader/image-preview.tsx": { "jsx-a11y/no-static-element-interactions": { "count": 1 @@ -1337,11 +1332,6 @@ "count": 9 } }, - "web/app/components/base/markdown-blocks/form.tsx": { - "prefer-regex-literals": { - "count": 1 - } - }, "web/app/components/base/markdown-blocks/index.ts": { "no-barrel-files/no-barrel-files": { "count": 10 @@ -1390,11 +1380,6 @@ "count": 3 } }, - "web/app/components/base/markdown/markdown-utils.ts": { - "regexp/no-unused-capturing-group": { - "count": 1 - } - }, "web/app/components/base/mermaid/index.tsx": { "eslint-react/set-state-in-effect": { "count": 4 @@ -1416,9 +1401,6 @@ } }, "web/app/components/base/mermaid/utils.ts": { - "regexp/no-unused-capturing-group": { - "count": 1 - }, "typescript/no-explicit-any": { "count": 4 } @@ -3537,9 +3519,6 @@ "eslint-react/set-state-in-effect": { "count": 2 }, - "regexp/no-useless-assertions": { - "count": 2 - }, "typescript/no-explicit-any": { "count": 6 } @@ -4081,9 +4060,6 @@ "dify/require-disable-directive-description": { "count": 1 }, - "regexp/no-unused-capturing-group": { - "count": 2 - }, "typescript/no-explicit-any": { "count": 4 } @@ -4175,11 +4151,6 @@ "count": 1 } }, - "web/app/components/workflow/note-node/note-editor/utils.ts": { - "regexp/no-useless-quantifier": { - "count": 1 - } - }, "web/app/components/workflow/operator/hooks.ts": { "typescript/no-explicit-any": { "count": 1 @@ -4615,12 +4586,6 @@ "eslint-react/set-state-in-effect": { "count": 5 }, - "regexp/no-super-linear-backtracking": { - "count": 1 - }, - "regexp/no-unused-capturing-group": { - "count": 2 - }, "typescript/no-explicit-any": { "count": 5 } @@ -4775,9 +4740,6 @@ } }, "web/hooks/use-format-time-from-now.spec.ts": { - "regexp/no-dupe-disjunctions": { - "count": 5 - }, "typescript/no-explicit-any": { "count": 1 } diff --git a/web/app/components/base/image-uploader/image-link-input.tsx b/web/app/components/base/image-uploader/image-link-input.tsx index 3e7cbd2c2c0..513b10a1041 100644 --- a/web/app/components/base/image-uploader/image-link-input.tsx +++ b/web/app/components/base/image-uploader/image-link-input.tsx @@ -9,7 +9,7 @@ type ImageLinkInputProps = { onUpload: (imageFile: ImageFile) => void disabled?: boolean } -const regex = /^(https?|ftp):\/\// +const regex = /^(?:https?|ftp):\/\// const ImageLinkInput: FC = ({ onUpload, disabled }) => { const { t } = useTranslation() const [imageLink, setImageLink] = useState('') diff --git a/web/app/components/base/markdown-blocks/form.tsx b/web/app/components/base/markdown-blocks/form.tsx index 079d6b19186..563e69df372 100644 --- a/web/app/components/base/markdown-blocks/form.tsx +++ b/web/app/components/base/markdown-blocks/form.tsx @@ -54,14 +54,7 @@ type SupportedType = (typeof SUPPORTED_TYPES)[keyof typeof SUPPORTED_TYPES] const SUPPORTED_TYPES_SET = new Set(Object.values(SUPPORTED_TYPES)) -const SAFE_NAME_RE = (() => { - try { - return new RegExp('^\\p{L}[\\p{L}\\p{M}\\p{N}_-]*$', 'u') - } catch { - // Fallback for browsers without Unicode property escape support. - return /^[a-z][\w-]*$/i - } -})() +const SAFE_NAME_RE = /^\p{L}[\p{L}\p{M}\p{N}_-]*$/u // Treat operator-provided characters literally instead of interpolating them into a regular expression. const EXTRA_SAFE_NAME_CHARS = new Set(MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS) const PROTOTYPE_POISON_KEYS = new Set(['__proto__', 'constructor', 'prototype']) diff --git a/web/app/components/base/markdown/markdown-utils.ts b/web/app/components/base/markdown/markdown-utils.ts index 8a619434669..eb4a212300c 100644 --- a/web/app/components/base/markdown/markdown-utils.ts +++ b/web/app/components/base/markdown/markdown-utils.ts @@ -106,7 +106,7 @@ export const preprocessThinkTag = (content: string) => { * signal that the URI should be removed/disallowed by react-markdown. */ export const customUrlTransform = (uri: string): string | undefined => { - const PERMITTED_SCHEME_REGEX = /^(https?|ircs?|mailto|xmpp|abbr):$/i + const PERMITTED_SCHEME_REGEX = /^(?:https?|ircs?|mailto|xmpp|abbr):$/i if (uri.startsWith('#')) return uri diff --git a/web/app/components/base/mermaid/utils.ts b/web/app/components/base/mermaid/utils.ts index 8acf5c71d25..bce7cdd7974 100644 --- a/web/app/components/base/mermaid/utils.ts +++ b/web/app/components/base/mermaid/utils.ts @@ -184,7 +184,7 @@ export function isMermaidCodeComplete(code: string): boolean { // Check for basic syntax structure const hasValidStart = - /^(graph|flowchart|sequenceDiagram|classDiagram|classDef|class|stateDiagram|gantt|pie|er|journey|requirementDiagram|mindmap)/.test( + /^(?:graph|flowchart|sequenceDiagram|classDiagram|classDef|class|stateDiagram|gantt|pie|er|journey|requirementDiagram|mindmap)/.test( trimmedCode, ) diff --git a/web/app/components/workflow/nodes/code/use-config.ts b/web/app/components/workflow/nodes/code/use-config.ts index 60d070a7ba1..fd6187a3849 100644 --- a/web/app/components/workflow/nodes/code/use-config.ts +++ b/web/app/components/workflow/nodes/code/use-config.ts @@ -119,13 +119,13 @@ const useConfig = (id: string, payload: CodeNodeType) => { let mainDefRe let newMainDef if (inputs.code_language === CodeLanguage.javascript) { - mainDefRe = /function\s+main\b\s*\([\s\S]*?\)/g + mainDefRe = /function\s+main\s*\([\s\S]*?\)/g newMainDef = 'function main({{var_list}})' let param_list = inputs.variables?.map((item) => item.variable).join(', ') || '' param_list = param_list ? `{${param_list}}` : '' newMainDef = newMainDef.replace('{{var_list}}', param_list) } else if (inputs.code_language === CodeLanguage.python3) { - mainDefRe = /def\s+main\b\s*\([\s\S]*?\)/g + mainDefRe = /def\s+main\s*\([\s\S]*?\)/g const param_list = [] for (const item of inputs.variables) { let param = item.variable diff --git a/web/app/components/workflow/nodes/trigger-schedule/default.ts b/web/app/components/workflow/nodes/trigger-schedule/default.ts index 57c9e69734b..2f7979e53a6 100644 --- a/web/app/components/workflow/nodes/trigger-schedule/default.ts +++ b/web/app/components/workflow/nodes/trigger-schedule/default.ts @@ -8,7 +8,7 @@ import { isValidCronExpression } from './utils/cron-parser' import { getNextExecutionTimes } from './utils/execution-time-calculator' const isValidTimeFormat = (time: string): boolean => { - const timeRegex = /^(0?\d|1[0-2]):[0-5]\d (AM|PM)$/ + const timeRegex = /^(?:0?\d|1[0-2]):[0-5]\d (?:AM|PM)$/ if (!timeRegex.test(time)) return false const [timePart, period] = time.split(' ') diff --git a/web/app/components/workflow/note-node/note-editor/utils.ts b/web/app/components/workflow/note-node/note-editor/utils.ts index 7bd7a4b6516..ebede7d9a76 100644 --- a/web/app/components/workflow/note-node/note-editor/utils.ts +++ b/web/app/components/workflow/note-node/note-editor/utils.ts @@ -14,4 +14,4 @@ export function getSelectedNode(selection: RangeSelection): TextNode | ElementNo } export const urlRegExp = - /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-]*)?\??[-+=&;%@.\w]*#?\w*)?)/ + /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-]*)?\??[-+=&;%@.\w]*#?\w*))/ diff --git a/web/app/components/workflow/variable-inspect/value-content.tsx b/web/app/components/workflow/variable-inspect/value-content.tsx index eedc6495a80..fe396acfc0b 100644 --- a/web/app/components/workflow/variable-inspect/value-content.tsx +++ b/web/app/components/workflow/variable-inspect/value-content.tsx @@ -69,7 +69,7 @@ const ValueContent = ({ currentVar, handleValueChange, isTruncated }: Props) => if (currentVar.value_type === 'string') setValue(value) if (currentVar.value_type === 'number') { - if (/^-?\d+(\.)?(\d+)?$/.test(value)) setValue(Number.parseFloat(value)) + if (/^-?\d+(?:\.\d*)?$/.test(value)) setValue(Number.parseFloat(value)) } const newValue = currentVar.value_type === 'number' ? Number.parseFloat(value) : value debounceValueChange(currentVar.id, newValue) diff --git a/web/hooks/use-format-time-from-now.spec.ts b/web/hooks/use-format-time-from-now.spec.ts index adb0ad9f7e5..8e2a0996e57 100644 --- a/web/hooks/use-format-time-from-now.spec.ts +++ b/web/hooks/use-format-time-from-now.spec.ts @@ -55,7 +55,7 @@ describe('useFormatTimeFromNow', () => { const formatted = result.current.formatTimeFromNow(oneHourAgo) // Should contain "hour" or "hours" and "ago" - expect(formatted).toMatch(/hour|hours/) + expect(formatted).toMatch(/hour/) expect(formatted).toMatch(/ago/) }) @@ -72,7 +72,7 @@ describe('useFormatTimeFromNow', () => { const fiveSecondsAgo = now - 5 * 1000 const formatted = result.current.formatTimeFromNow(fiveSecondsAgo) - expect(formatted).toMatch(/second|seconds|few seconds/) + expect(formatted).toMatch(/second/) }) /** @@ -88,7 +88,7 @@ describe('useFormatTimeFromNow', () => { const threeDaysAgo = now - 3 * 24 * 60 * 60 * 1000 const formatted = result.current.formatTimeFromNow(threeDaysAgo) - expect(formatted).toMatch(/day|days/) + expect(formatted).toMatch(/day/) expect(formatted).toMatch(/ago/) }) @@ -106,7 +106,7 @@ describe('useFormatTimeFromNow', () => { const formatted = result.current.formatTimeFromNow(twoHoursFromNow) expect(formatted).toMatch(/in/) - expect(formatted).toMatch(/hour|hours/) + expect(formatted).toMatch(/hour/) }) }) @@ -229,7 +229,7 @@ describe('useFormatTimeFromNow', () => { expect(typeof formatted).toBe('string') expect(formatted.length).toBeGreaterThan(0) - expect(formatted).toMatch(/year|years/) + expect(formatted).toMatch(/year/) }) /**