From 7c21ddefa87bf3d9999c0e790b48c004c078304d Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Thu, 10 Oct 2024 16:12:22 +0200 Subject: [PATCH] fix(InputMenu/SelectMenu): escape regexp before search --- src/runtime/components/InputMenu.vue | 7 ++++--- src/runtime/components/SelectMenu.vue | 7 ++++--- src/runtime/utils/index.ts | 4 ++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/runtime/components/InputMenu.vue b/src/runtime/components/InputMenu.vue index b4d689fc..3633bc2f 100644 --- a/src/runtime/components/InputMenu.vue +++ b/src/runtime/components/InputMenu.vue @@ -127,7 +127,7 @@ import { useFormField } from '../composables/useFormField' import UIcon from './Icon.vue' import UAvatar from './Avatar.vue' import UChip from './Chip.vue' -import { get } from '../utils' +import { get, escapeRegExp } from '../utils' defineOptions({ inheritAttrs: false }) @@ -175,16 +175,17 @@ function filterFunction(items: ArrayOrWrapped, searchTerm: stri } const fields = Array.isArray(props.filter) ? props.filter : ['label'] + const escapedSearchTerm = escapeRegExp(searchTerm) return items.filter((item) => { if (typeof item !== 'object') { - return String(item).search(new RegExp(searchTerm, 'i')) !== -1 + return String(item).search(new RegExp(escapedSearchTerm, 'i')) !== -1 } return fields.some((field) => { const child = get(item, field) - return child !== null && child !== undefined && String(child).search(new RegExp(searchTerm, 'i')) !== -1 + return child !== null && child !== undefined && String(child).search(new RegExp(escapedSearchTerm, 'i')) !== -1 }) }) as ArrayOrWrapped } diff --git a/src/runtime/components/SelectMenu.vue b/src/runtime/components/SelectMenu.vue index 81f38ae5..55583077 100644 --- a/src/runtime/components/SelectMenu.vue +++ b/src/runtime/components/SelectMenu.vue @@ -117,7 +117,7 @@ import { useFormField } from '../composables/useFormField' import UIcon from './Icon.vue' import UAvatar from './Avatar.vue' import UChip from './Chip.vue' -import { get } from '../utils' +import { get, escapeRegExp } from '../utils' const props = withDefaults(defineProps>(), { search: true, @@ -167,16 +167,17 @@ function filterFunction(items: ArrayOrWrapped, searchTerm: stri } const fields = Array.isArray(props.filter) ? props.filter : ['label'] + const escapedSearchTerm = escapeRegExp(searchTerm) return items.filter((item) => { if (typeof item !== 'object') { - return String(item).search(new RegExp(searchTerm, 'i')) !== -1 + return String(item).search(new RegExp(escapedSearchTerm, 'i')) !== -1 } return fields.some((field) => { const child = get(item, field) - return child !== null && child !== undefined && String(child).search(new RegExp(searchTerm, 'i')) !== -1 + return child !== null && child !== undefined && String(child).search(new RegExp(escapedSearchTerm, 'i')) !== -1 }) }) as ArrayOrWrapped } diff --git a/src/runtime/utils/index.ts b/src/runtime/utils/index.ts index e598e93f..f8d3a525 100644 --- a/src/runtime/utils/index.ts +++ b/src/runtime/utils/index.ts @@ -59,3 +59,7 @@ export function looseToNumber(val: any): any { const n = Number.parseFloat(val) return Number.isNaN(n) ? val : n } + +export function escapeRegExp(string: string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +}