mirror of
https://github.com/langgenius/dify.git
synced 2026-02-19 09:24:42 +08:00
refactor(web): replace String.match() with RegExp.exec() for non-global regex (#32386)
Some checks are pending
autofix.ci / autofix (push) Waiting to run
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/amd64, build-api-amd64) (push) Waiting to run
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/arm64, build-api-arm64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/amd64, build-web-amd64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/arm64, build-web-arm64) (push) Waiting to run
Build and Push API & Web / create-manifest (api, DIFY_API_IMAGE_NAME, merge-api-images) (push) Blocked by required conditions
Build and Push API & Web / create-manifest (web, DIFY_WEB_IMAGE_NAME, merge-web-images) (push) Blocked by required conditions
Main CI Pipeline / Check Changed Files (push) Waiting to run
Main CI Pipeline / API Tests (push) Blocked by required conditions
Main CI Pipeline / Web Tests (push) Blocked by required conditions
Main CI Pipeline / Style Check (push) Waiting to run
Main CI Pipeline / VDB Tests (push) Blocked by required conditions
Main CI Pipeline / DB Migration Test (push) Blocked by required conditions
Some checks are pending
autofix.ci / autofix (push) Waiting to run
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/amd64, build-api-amd64) (push) Waiting to run
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/arm64, build-api-arm64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/amd64, build-web-amd64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/arm64, build-web-arm64) (push) Waiting to run
Build and Push API & Web / create-manifest (api, DIFY_API_IMAGE_NAME, merge-api-images) (push) Blocked by required conditions
Build and Push API & Web / create-manifest (web, DIFY_WEB_IMAGE_NAME, merge-web-images) (push) Blocked by required conditions
Main CI Pipeline / Check Changed Files (push) Waiting to run
Main CI Pipeline / API Tests (push) Blocked by required conditions
Main CI Pipeline / Web Tests (push) Blocked by required conditions
Main CI Pipeline / Style Check (push) Waiting to run
Main CI Pipeline / VDB Tests (push) Blocked by required conditions
Main CI Pipeline / DB Migration Test (push) Blocked by required conditions
This commit is contained in:
parent
41a4a57d2e
commit
00591a592c
@ -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
|
||||
|
||||
@ -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>(AppModeEnum.CHAT)
|
||||
const [publishedConfig, setPublishedConfig] = useState<PublishConfig | null>(null)
|
||||
|
||||
@ -70,7 +70,7 @@ const BlockInput: FC<IBlockInputProps> = ({
|
||||
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 (
|
||||
<VarHighlight
|
||||
|
||||
@ -17,7 +17,7 @@ const ContentItem = ({
|
||||
|
||||
const extractFieldName = (str: string): string => {
|
||||
const outputVarRegex = /\{\{#\$output\.([^#]+)#\}\}/
|
||||
const match = str.match(outputVarRegex)
|
||||
const match = outputVarRegex.exec(str)
|
||||
return match ? match[1] : ''
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ async function main(): Promise<void> {
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ export const parsePluginErrorMessage = async (error: any): Promise<string> => {
|
||||
// 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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user