diff --git a/web/__tests__/check-i18n.test.ts b/web/__tests__/check-i18n.test.ts index 9f573bda10..de78ae997e 100644 --- a/web/__tests__/check-i18n.test.ts +++ b/web/__tests__/check-i18n.test.ts @@ -588,7 +588,7 @@ export default translation const trimmedKeyLine = keyLine.trim() // If key line ends with ":" (not complete value), it's likely multiline - if (trimmedKeyLine.endsWith(':') && !trimmedKeyLine.includes('{') && !trimmedKeyLine.match(/:\s*['"`]/)) { + if (trimmedKeyLine.endsWith(':') && !trimmedKeyLine.includes('{') && !/:\s*['"`]/.exec(trimmedKeyLine)) { // Find the value lines that belong to this key let currentLine = targetLineIndex + 1 let foundValue = false @@ -604,7 +604,7 @@ export default translation } // Check if this line starts a new key (indicates end of current value) - if (trimmed.match(/^\w+\s*:/)) + if (/^\w+\s*:/.exec(trimmed)) break // Check if this line is part of the value diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx index 919b7c355a..16cf9454ca 100644 --- a/web/app/components/app/configuration/index.tsx +++ b/web/app/components/app/configuration/index.tsx @@ -109,7 +109,7 @@ const Configuration: FC = () => { const [hasFetchedDetail, setHasFetchedDetail] = useState(false) const isLoading = !hasFetchedDetail const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) + const matched = /\/app\/([^/]+)/.exec(pathname) const appId = (matched?.length && matched[1]) ? matched[1] : '' const [mode, setMode] = useState(AppModeEnum.CHAT) const [publishedConfig, setPublishedConfig] = useState(null) diff --git a/web/app/components/base/block-input/index.tsx b/web/app/components/base/block-input/index.tsx index 75fe381c83..d9057eb737 100644 --- a/web/app/components/base/block-input/index.tsx +++ b/web/app/components/base/block-input/index.tsx @@ -70,7 +70,7 @@ const BlockInput: FC = ({ const renderSafeContent = (value: string) => { const parts = value.split(/(\{\{[^}]+\}\}|\n)/g) return parts.map((part, index) => { - const variableMatch = part.match(/^\{\{([^}]+)\}\}$/) + const variableMatch = /^\{\{([^}]+)\}\}$/.exec(part) if (variableMatch) { return ( { const outputVarRegex = /\{\{#\$output\.([^#]+)#\}\}/ - const match = str.match(outputVarRegex) + const match = outputVarRegex.exec(str) return match ? match[1] : '' } diff --git a/web/app/components/base/date-and-time-picker/utils/dayjs.ts b/web/app/components/base/date-and-time-picker/utils/dayjs.ts index 23307895a7..0d4474e8c4 100644 --- a/web/app/components/base/date-and-time-picker/utils/dayjs.ts +++ b/web/app/components/base/date-and-time-picker/utils/dayjs.ts @@ -111,7 +111,7 @@ export const convertTimezoneToOffsetStr = (timezone?: string) => { return DEFAULT_OFFSET_STR // Extract offset from name format like "-11:00 Niue Time" or "+05:30 India Time" // Name format is always "{offset}:{minutes} {timezone name}" - const offsetMatch = tzItem.name.match(/^([+-]?\d{1,2}):(\d{2})/) + const offsetMatch = /^([+-]?\d{1,2}):(\d{2})/.exec(tzItem.name) if (!offsetMatch) return DEFAULT_OFFSET_STR // Parse hours and minutes separately diff --git a/web/app/components/base/features/new-feature-panel/annotation-reply/index.tsx b/web/app/components/base/features/new-feature-panel/annotation-reply/index.tsx index e85e566a87..05bc5c638c 100644 --- a/web/app/components/base/features/new-feature-panel/annotation-reply/index.tsx +++ b/web/app/components/base/features/new-feature-panel/annotation-reply/index.tsx @@ -27,7 +27,7 @@ const AnnotationReply = ({ const { t } = useTranslation() const router = useRouter() const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) + const matched = /\/app\/([^/]+)/.exec(pathname) const appId = (matched?.length && matched[1]) ? matched[1] : '' const featuresStore = useFeaturesStore() const annotationReply = useFeatures(s => s.features.annotationReply) diff --git a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx index 7bc0c02c51..a17de2d151 100644 --- a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx +++ b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx @@ -29,7 +29,7 @@ const VoiceParamConfig = ({ }: VoiceParamConfigProps) => { const { t } = useTranslation() const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) + const matched = /\/app\/([^/]+)/.exec(pathname) const appId = (matched?.length && matched[1]) ? matched[1] : '' const text2speech = useFeatures(state => state.features.text2speech) const featuresStore = useFeaturesStore() diff --git a/web/app/components/base/ga/index.tsx b/web/app/components/base/ga/index.tsx index 95e4d3779f..6ad0363718 100644 --- a/web/app/components/base/ga/index.tsx +++ b/web/app/components/base/ga/index.tsx @@ -21,7 +21,7 @@ export type IGAProps = { const extractNonceFromCSP = (cspHeader: string | null): string | undefined => { if (!cspHeader) return undefined - const nonceMatch = cspHeader.match(/'nonce-([^']+)'/) + const nonceMatch = /'nonce-([^']+)'/.exec(cspHeader) return nonceMatch ? nonceMatch[1] : undefined } diff --git a/web/app/components/base/mermaid/index.tsx b/web/app/components/base/mermaid/index.tsx index d8db7f625e..35d37f83ee 100644 --- a/web/app/components/base/mermaid/index.tsx +++ b/web/app/components/base/mermaid/index.tsx @@ -239,7 +239,7 @@ const Flowchart = (props: FlowchartProps) => { .split('\n') .map((line) => { // Gantt charts have specific syntax needs. - const taskMatch = line.match(/^\s*([^:]+?)\s*:\s*(.*)/) + const taskMatch = /^\s*([^:]+?)\s*:\s*(.*)/.exec(line) if (!taskMatch) return line // Not a task line, return as is. diff --git a/web/app/components/base/mermaid/utils.ts b/web/app/components/base/mermaid/utils.ts index 17872e8345..c66858ac5b 100644 --- a/web/app/components/base/mermaid/utils.ts +++ b/web/app/components/base/mermaid/utils.ts @@ -185,7 +185,7 @@ export function isMermaidCodeComplete(code: string): boolean { const hasNoSyntaxErrors = !trimmedCode.includes('undefined') && !trimmedCode.includes('[object Object]') && trimmedCode.split('\n').every(line => - !(line.includes('-->') && !line.match(/\S+\s*-->\s*\S+/))) + !(line.includes('-->') && !/\S+\s*-->\s*\S+/.exec(line))) return hasValidStart && isBalanced && hasNoSyntaxErrors } diff --git a/web/app/components/billing/utils/index.ts b/web/app/components/billing/utils/index.ts index 39fc0cd7b5..6974f89c8b 100644 --- a/web/app/components/billing/utils/index.ts +++ b/web/app/components/billing/utils/index.ts @@ -7,7 +7,7 @@ import { ALL_PLANS, NUM_INFINITE } from '@/app/components/billing/config' * @example "50MB" -> 50, "5GB" -> 5120, "20GB" -> 20480 */ export const parseVectorSpaceToMB = (vectorSpace: string): number => { - const match = vectorSpace.match(/^(\d+)(MB|GB)$/i) + const match = /^(\d+)(MB|GB)$/i.exec(vectorSpace) if (!match) return 0 diff --git a/web/app/components/datasets/common/__tests__/credential-icon.spec.tsx b/web/app/components/datasets/common/__tests__/credential-icon.spec.tsx index 6b3ee7002e..e059f7c622 100644 --- a/web/app/components/datasets/common/__tests__/credential-icon.spec.tsx +++ b/web/app/components/datasets/common/__tests__/credential-icon.spec.tsx @@ -98,8 +98,8 @@ describe('CredentialIcon', () => { const classes1 = wrapper1.className const classes2 = wrapper2.className - const bgClass1 = classes1.match(/bg-components-icon-bg-\S+/)?.[0] - const bgClass2 = classes2.match(/bg-components-icon-bg-\S+/)?.[0] + const bgClass1 = /bg-components-icon-bg-\S+/.exec(classes1)?.[0] + const bgClass2 = /bg-components-icon-bg-\S+/.exec(classes2)?.[0] expect(bgClass1).toBe(bgClass2) }) @@ -112,8 +112,8 @@ describe('CredentialIcon', () => { const wrapper1 = container1.firstChild as HTMLElement const wrapper2 = container2.firstChild as HTMLElement - const bgClass1 = wrapper1.className.match(/bg-components-icon-bg-\S+/)?.[0] - const bgClass2 = wrapper2.className.match(/bg-components-icon-bg-\S+/)?.[0] + const bgClass1 = /bg-components-icon-bg-\S+/.exec(wrapper1.className)?.[0] + const bgClass2 = /bg-components-icon-bg-\S+/.exec(wrapper2.className)?.[0] expect(bgClass1).toBeDefined() expect(bgClass2).toBeDefined() diff --git a/web/app/components/tools/mcp/hooks/use-mcp-modal-form.ts b/web/app/components/tools/mcp/hooks/use-mcp-modal-form.ts index 286e2bf2e8..ec7c479b69 100644 --- a/web/app/components/tools/mcp/hooks/use-mcp-modal-form.ts +++ b/web/app/components/tools/mcp/hooks/use-mcp-modal-form.ts @@ -12,7 +12,7 @@ import { uploadRemoteFileInfo } from '@/service/common' const DEFAULT_ICON = { type: 'emoji', icon: '🔗', background: '#6366F1' } const extractFileId = (url: string) => { - const match = url.match(/files\/(.+?)\/file-preview/) + const match = /files\/(.+?)\/file-preview/.exec(url) return match ? match[1] : null } diff --git a/web/scripts/component-analyzer.js b/web/scripts/component-analyzer.js index 8bd3dc4409..4612981f82 100644 --- a/web/scripts/component-analyzer.js +++ b/web/scripts/component-analyzer.js @@ -140,7 +140,7 @@ export class ComponentAnalyzer { maxMessages.forEach((msg) => { if (msg.ruleId === 'sonarjs/cognitive-complexity') { - const match = msg.message.match(complexityPattern) + const match = complexityPattern.exec(msg.message) if (match && match[1]) max = Math.max(max, Number.parseInt(match[1], 10)) } diff --git a/web/scripts/gen-doc-paths.ts b/web/scripts/gen-doc-paths.ts index 03c3cdaddc..e5cf8aeb58 100644 --- a/web/scripts/gen-doc-paths.ts +++ b/web/scripts/gen-doc-paths.ts @@ -377,7 +377,7 @@ async function main(): Promise { for (const openapiPath of openApiPaths) { // Determine language from path - const langMatch = openapiPath.match(/^(en|zh|ja)\//) + const langMatch = /^(en|zh|ja)\//.exec(openapiPath) if (!langMatch) continue diff --git a/web/utils/error-parser.ts b/web/utils/error-parser.ts index 311505521f..f19bad3add 100644 --- a/web/utils/error-parser.ts +++ b/web/utils/error-parser.ts @@ -31,7 +31,7 @@ export const parsePluginErrorMessage = async (error: any): Promise => { // Try to extract nested JSON from PluginInvokeError // Use greedy match .+ to capture the complete JSON object with nested braces const pluginErrorPattern = /PluginInvokeError:\s*(\{.+\})/ - const match = rawMessage.match(pluginErrorPattern) + const match = pluginErrorPattern.exec(rawMessage) if (match) { try { diff --git a/web/utils/format.ts b/web/utils/format.ts index 04a8ba0b60..804a2c1180 100644 --- a/web/utils/format.ts +++ b/web/utils/format.ts @@ -39,7 +39,7 @@ export const formatNumber = (num: number | string) => { // Force fixed decimal for small numbers to avoid scientific notation if (Math.abs(n) < 0.001 && n !== 0) { const str = n.toString() - const match = str.match(/e-(\d+)$/) + const match = /e-(\d+)$/.exec(str) let precision: number if (match) { // Scientific notation: precision is exponent + decimal digits in mantissa diff --git a/web/utils/urlValidation.ts b/web/utils/urlValidation.ts index fcc5c4b5d8..e78639b15b 100644 --- a/web/utils/urlValidation.ts +++ b/web/utils/urlValidation.ts @@ -39,7 +39,7 @@ export function isPrivateOrLocalAddress(url: string): boolean { // Check for private IP ranges const ipv4Regex = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ - const ipv4Match = hostname.match(ipv4Regex) + const ipv4Match = ipv4Regex.exec(hostname) if (ipv4Match) { const [, a, b] = ipv4Match.map(Number) // 10.0.0.0/8