mirror of
https://github.com/langgenius/dify.git
synced 2026-05-01 14:16:40 +08:00
refactor(web): replace String.match() with RegExp.exec() for non-global regex (#32386)
This commit is contained in:
parent
41a4a57d2e
commit
00591a592c
@ -588,7 +588,7 @@ export default translation
|
|||||||
const trimmedKeyLine = keyLine.trim()
|
const trimmedKeyLine = keyLine.trim()
|
||||||
|
|
||||||
// If key line ends with ":" (not complete value), it's likely multiline
|
// 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
|
// Find the value lines that belong to this key
|
||||||
let currentLine = targetLineIndex + 1
|
let currentLine = targetLineIndex + 1
|
||||||
let foundValue = false
|
let foundValue = false
|
||||||
@ -604,7 +604,7 @@ export default translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if this line starts a new key (indicates end of current value)
|
// Check if this line starts a new key (indicates end of current value)
|
||||||
if (trimmed.match(/^\w+\s*:/))
|
if (/^\w+\s*:/.exec(trimmed))
|
||||||
break
|
break
|
||||||
|
|
||||||
// Check if this line is part of the value
|
// Check if this line is part of the value
|
||||||
|
|||||||
@ -109,7 +109,7 @@ const Configuration: FC = () => {
|
|||||||
const [hasFetchedDetail, setHasFetchedDetail] = useState(false)
|
const [hasFetchedDetail, setHasFetchedDetail] = useState(false)
|
||||||
const isLoading = !hasFetchedDetail
|
const isLoading = !hasFetchedDetail
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const matched = pathname.match(/\/app\/([^/]+)/)
|
const matched = /\/app\/([^/]+)/.exec(pathname)
|
||||||
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
||||||
const [mode, setMode] = useState<AppModeEnum>(AppModeEnum.CHAT)
|
const [mode, setMode] = useState<AppModeEnum>(AppModeEnum.CHAT)
|
||||||
const [publishedConfig, setPublishedConfig] = useState<PublishConfig | null>(null)
|
const [publishedConfig, setPublishedConfig] = useState<PublishConfig | null>(null)
|
||||||
|
|||||||
@ -70,7 +70,7 @@ const BlockInput: FC<IBlockInputProps> = ({
|
|||||||
const renderSafeContent = (value: string) => {
|
const renderSafeContent = (value: string) => {
|
||||||
const parts = value.split(/(\{\{[^}]+\}\}|\n)/g)
|
const parts = value.split(/(\{\{[^}]+\}\}|\n)/g)
|
||||||
return parts.map((part, index) => {
|
return parts.map((part, index) => {
|
||||||
const variableMatch = part.match(/^\{\{([^}]+)\}\}$/)
|
const variableMatch = /^\{\{([^}]+)\}\}$/.exec(part)
|
||||||
if (variableMatch) {
|
if (variableMatch) {
|
||||||
return (
|
return (
|
||||||
<VarHighlight
|
<VarHighlight
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const ContentItem = ({
|
|||||||
|
|
||||||
const extractFieldName = (str: string): string => {
|
const extractFieldName = (str: string): string => {
|
||||||
const outputVarRegex = /\{\{#\$output\.([^#]+)#\}\}/
|
const outputVarRegex = /\{\{#\$output\.([^#]+)#\}\}/
|
||||||
const match = str.match(outputVarRegex)
|
const match = outputVarRegex.exec(str)
|
||||||
return match ? match[1] : ''
|
return match ? match[1] : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,7 +111,7 @@ export const convertTimezoneToOffsetStr = (timezone?: string) => {
|
|||||||
return DEFAULT_OFFSET_STR
|
return DEFAULT_OFFSET_STR
|
||||||
// Extract offset from name format like "-11:00 Niue Time" or "+05:30 India Time"
|
// Extract offset from name format like "-11:00 Niue Time" or "+05:30 India Time"
|
||||||
// Name format is always "{offset}:{minutes} {timezone name}"
|
// 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)
|
if (!offsetMatch)
|
||||||
return DEFAULT_OFFSET_STR
|
return DEFAULT_OFFSET_STR
|
||||||
// Parse hours and minutes separately
|
// Parse hours and minutes separately
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const AnnotationReply = ({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const matched = pathname.match(/\/app\/([^/]+)/)
|
const matched = /\/app\/([^/]+)/.exec(pathname)
|
||||||
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
||||||
const featuresStore = useFeaturesStore()
|
const featuresStore = useFeaturesStore()
|
||||||
const annotationReply = useFeatures(s => s.features.annotationReply)
|
const annotationReply = useFeatures(s => s.features.annotationReply)
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const VoiceParamConfig = ({
|
|||||||
}: VoiceParamConfigProps) => {
|
}: VoiceParamConfigProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const matched = pathname.match(/\/app\/([^/]+)/)
|
const matched = /\/app\/([^/]+)/.exec(pathname)
|
||||||
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
const appId = (matched?.length && matched[1]) ? matched[1] : ''
|
||||||
const text2speech = useFeatures(state => state.features.text2speech)
|
const text2speech = useFeatures(state => state.features.text2speech)
|
||||||
const featuresStore = useFeaturesStore()
|
const featuresStore = useFeaturesStore()
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export type IGAProps = {
|
|||||||
const extractNonceFromCSP = (cspHeader: string | null): string | undefined => {
|
const extractNonceFromCSP = (cspHeader: string | null): string | undefined => {
|
||||||
if (!cspHeader)
|
if (!cspHeader)
|
||||||
return undefined
|
return undefined
|
||||||
const nonceMatch = cspHeader.match(/'nonce-([^']+)'/)
|
const nonceMatch = /'nonce-([^']+)'/.exec(cspHeader)
|
||||||
return nonceMatch ? nonceMatch[1] : undefined
|
return nonceMatch ? nonceMatch[1] : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -239,7 +239,7 @@ const Flowchart = (props: FlowchartProps) => {
|
|||||||
.split('\n')
|
.split('\n')
|
||||||
.map((line) => {
|
.map((line) => {
|
||||||
// Gantt charts have specific syntax needs.
|
// Gantt charts have specific syntax needs.
|
||||||
const taskMatch = line.match(/^\s*([^:]+?)\s*:\s*(.*)/)
|
const taskMatch = /^\s*([^:]+?)\s*:\s*(.*)/.exec(line)
|
||||||
if (!taskMatch)
|
if (!taskMatch)
|
||||||
return line // Not a task line, return as is.
|
return line // Not a task line, return as is.
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,7 @@ export function isMermaidCodeComplete(code: string): boolean {
|
|||||||
const hasNoSyntaxErrors = !trimmedCode.includes('undefined')
|
const hasNoSyntaxErrors = !trimmedCode.includes('undefined')
|
||||||
&& !trimmedCode.includes('[object Object]')
|
&& !trimmedCode.includes('[object Object]')
|
||||||
&& trimmedCode.split('\n').every(line =>
|
&& 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
|
return hasValidStart && isBalanced && hasNoSyntaxErrors
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { ALL_PLANS, NUM_INFINITE } from '@/app/components/billing/config'
|
|||||||
* @example "50MB" -> 50, "5GB" -> 5120, "20GB" -> 20480
|
* @example "50MB" -> 50, "5GB" -> 5120, "20GB" -> 20480
|
||||||
*/
|
*/
|
||||||
export const parseVectorSpaceToMB = (vectorSpace: string): number => {
|
export const parseVectorSpaceToMB = (vectorSpace: string): number => {
|
||||||
const match = vectorSpace.match(/^(\d+)(MB|GB)$/i)
|
const match = /^(\d+)(MB|GB)$/i.exec(vectorSpace)
|
||||||
if (!match)
|
if (!match)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@ -98,8 +98,8 @@ describe('CredentialIcon', () => {
|
|||||||
const classes1 = wrapper1.className
|
const classes1 = wrapper1.className
|
||||||
const classes2 = wrapper2.className
|
const classes2 = wrapper2.className
|
||||||
|
|
||||||
const bgClass1 = classes1.match(/bg-components-icon-bg-\S+/)?.[0]
|
const bgClass1 = /bg-components-icon-bg-\S+/.exec(classes1)?.[0]
|
||||||
const bgClass2 = classes2.match(/bg-components-icon-bg-\S+/)?.[0]
|
const bgClass2 = /bg-components-icon-bg-\S+/.exec(classes2)?.[0]
|
||||||
|
|
||||||
expect(bgClass1).toBe(bgClass2)
|
expect(bgClass1).toBe(bgClass2)
|
||||||
})
|
})
|
||||||
@ -112,8 +112,8 @@ describe('CredentialIcon', () => {
|
|||||||
const wrapper1 = container1.firstChild as HTMLElement
|
const wrapper1 = container1.firstChild as HTMLElement
|
||||||
const wrapper2 = container2.firstChild as HTMLElement
|
const wrapper2 = container2.firstChild as HTMLElement
|
||||||
|
|
||||||
const bgClass1 = wrapper1.className.match(/bg-components-icon-bg-\S+/)?.[0]
|
const bgClass1 = /bg-components-icon-bg-\S+/.exec(wrapper1.className)?.[0]
|
||||||
const bgClass2 = wrapper2.className.match(/bg-components-icon-bg-\S+/)?.[0]
|
const bgClass2 = /bg-components-icon-bg-\S+/.exec(wrapper2.className)?.[0]
|
||||||
|
|
||||||
expect(bgClass1).toBeDefined()
|
expect(bgClass1).toBeDefined()
|
||||||
expect(bgClass2).toBeDefined()
|
expect(bgClass2).toBeDefined()
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { uploadRemoteFileInfo } from '@/service/common'
|
|||||||
const DEFAULT_ICON = { type: 'emoji', icon: '🔗', background: '#6366F1' }
|
const DEFAULT_ICON = { type: 'emoji', icon: '🔗', background: '#6366F1' }
|
||||||
|
|
||||||
const extractFileId = (url: string) => {
|
const extractFileId = (url: string) => {
|
||||||
const match = url.match(/files\/(.+?)\/file-preview/)
|
const match = /files\/(.+?)\/file-preview/.exec(url)
|
||||||
return match ? match[1] : null
|
return match ? match[1] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -140,7 +140,7 @@ export class ComponentAnalyzer {
|
|||||||
|
|
||||||
maxMessages.forEach((msg) => {
|
maxMessages.forEach((msg) => {
|
||||||
if (msg.ruleId === 'sonarjs/cognitive-complexity') {
|
if (msg.ruleId === 'sonarjs/cognitive-complexity') {
|
||||||
const match = msg.message.match(complexityPattern)
|
const match = complexityPattern.exec(msg.message)
|
||||||
if (match && match[1])
|
if (match && match[1])
|
||||||
max = Math.max(max, Number.parseInt(match[1], 10))
|
max = Math.max(max, Number.parseInt(match[1], 10))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -377,7 +377,7 @@ async function main(): Promise<void> {
|
|||||||
|
|
||||||
for (const openapiPath of openApiPaths) {
|
for (const openapiPath of openApiPaths) {
|
||||||
// Determine language from path
|
// Determine language from path
|
||||||
const langMatch = openapiPath.match(/^(en|zh|ja)\//)
|
const langMatch = /^(en|zh|ja)\//.exec(openapiPath)
|
||||||
if (!langMatch)
|
if (!langMatch)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export const parsePluginErrorMessage = async (error: any): Promise<string> => {
|
|||||||
// Try to extract nested JSON from PluginInvokeError
|
// Try to extract nested JSON from PluginInvokeError
|
||||||
// Use greedy match .+ to capture the complete JSON object with nested braces
|
// Use greedy match .+ to capture the complete JSON object with nested braces
|
||||||
const pluginErrorPattern = /PluginInvokeError:\s*(\{.+\})/
|
const pluginErrorPattern = /PluginInvokeError:\s*(\{.+\})/
|
||||||
const match = rawMessage.match(pluginErrorPattern)
|
const match = pluginErrorPattern.exec(rawMessage)
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export const formatNumber = (num: number | string) => {
|
|||||||
// Force fixed decimal for small numbers to avoid scientific notation
|
// Force fixed decimal for small numbers to avoid scientific notation
|
||||||
if (Math.abs(n) < 0.001 && n !== 0) {
|
if (Math.abs(n) < 0.001 && n !== 0) {
|
||||||
const str = n.toString()
|
const str = n.toString()
|
||||||
const match = str.match(/e-(\d+)$/)
|
const match = /e-(\d+)$/.exec(str)
|
||||||
let precision: number
|
let precision: number
|
||||||
if (match) {
|
if (match) {
|
||||||
// Scientific notation: precision is exponent + decimal digits in mantissa
|
// Scientific notation: precision is exponent + decimal digits in mantissa
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export function isPrivateOrLocalAddress(url: string): boolean {
|
|||||||
|
|
||||||
// Check for private IP ranges
|
// Check for private IP ranges
|
||||||
const ipv4Regex = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
|
const ipv4Regex = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
|
||||||
const ipv4Match = hostname.match(ipv4Regex)
|
const ipv4Match = ipv4Regex.exec(hostname)
|
||||||
if (ipv4Match) {
|
if (ipv4Match) {
|
||||||
const [, a, b] = ipv4Match.map(Number)
|
const [, a, b] = ipv4Match.map(Number)
|
||||||
// 10.0.0.0/8
|
// 10.0.0.0/8
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user