From e5543fc7f2f1c13bdffd773a8f62b00cb1667c8c Mon Sep 17 00:00:00 2001 From: OrionDesign Date: Mon, 20 Oct 2025 23:25:59 -0300 Subject: [PATCH] Escape special characters in Monaco tokens and fix black screen in application An escapeRegex utility has been added and applied to all locations where command tokens are used to generate regex patterns in Monaco's token providers. This ensures that tokens containing special regex characters (such as *) do not cause errors. Additionally, this fix prevents the application from displaying a black screen when accessed. --- .../ui/src/utils/monaco/monacoRedisMonarchTokensProvider.ts | 6 ++++-- .../utils/monaco/monarchTokens/redisearchTokensTemplates.ts | 5 ++++- redisinsight/ui/src/utils/monaco/redisearch/utils.ts | 6 ++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/redisinsight/ui/src/utils/monaco/monacoRedisMonarchTokensProvider.ts b/redisinsight/ui/src/utils/monaco/monacoRedisMonarchTokensProvider.ts index 44f342766e..68eef4c6db 100644 --- a/redisinsight/ui/src/utils/monaco/monacoRedisMonarchTokensProvider.ts +++ b/redisinsight/ui/src/utils/monaco/monacoRedisMonarchTokensProvider.ts @@ -5,6 +5,8 @@ import { IRedisCommand } from 'uiSrc/constants' const STRING_DOUBLE = 'string.double' +const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + export const getRedisMonarchTokensProvider = ( commands: IRedisCommand[], ): monacoEditor.languages.IMonarchLanguage => { @@ -12,8 +14,8 @@ export const getRedisMonarchTokensProvider = ( const searchCommands = remove(commandRedisCommands, ({ token }) => token?.startsWith(ModuleCommandPrefix.RediSearch), ) - const COMMON_COMMANDS_REGEX = `^\\s*(\\d+\\s+)?(${commandRedisCommands.map(({ token }) => token).join('|')})\\b` - const SEARCH_COMMANDS_REGEX = `^\\s*(\\d+\\s+)?(${searchCommands.map(({ token }) => token).join('|')})\\b` + const COMMON_COMMANDS_REGEX = `^\\s*(\\d+\\s+)?(${commandRedisCommands.map(({ token }) => escapeRegex(token || '')).join('|')})\\b` + const SEARCH_COMMANDS_REGEX = `^\\s*(\\d+\\s+)?(${searchCommands.map(({ token }) => escapeRegex(token || '')).join('|')})\\b` return { defaultToken: '', diff --git a/redisinsight/ui/src/utils/monaco/monarchTokens/redisearchTokensTemplates.ts b/redisinsight/ui/src/utils/monaco/monarchTokens/redisearchTokensTemplates.ts index e2311ee5ba..538c8c8b12 100644 --- a/redisinsight/ui/src/utils/monaco/monarchTokens/redisearchTokensTemplates.ts +++ b/redisinsight/ui/src/utils/monaco/monarchTokens/redisearchTokensTemplates.ts @@ -3,6 +3,9 @@ import { curryRight } from 'lodash' import { Maybe } from 'uiSrc/utils' import { IRedisCommand } from 'uiSrc/constants' +// Escape special regex characters in tokens +const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const appendToken = (token: string, name: Maybe) => name ? `${token}.${name}` : token export const generateQuery = ( @@ -17,7 +20,7 @@ export const generateQuery = ( ): languages.IMonarchLanguageRule => args?.length ? [ - `(${args?.map(({ token }) => token).join('|')})\\b`, + `(${args?.map(({ token }) => escapeRegex(token || '')).join('|')})\\b`, { token: 'function', next: appendTokenName(tokenName) }, ] : [/_/, ''] diff --git a/redisinsight/ui/src/utils/monaco/redisearch/utils.ts b/redisinsight/ui/src/utils/monaco/redisearch/utils.ts index b7419fcadf..6a1d9164de 100644 --- a/redisinsight/ui/src/utils/monaco/redisearch/utils.ts +++ b/redisinsight/ui/src/utils/monaco/redisearch/utils.ts @@ -5,6 +5,8 @@ import { generateQuery } from 'uiSrc/utils/monaco/monarchTokens/redisearchTokens import { ICommandTokenType, IRedisCommand } from 'uiSrc/constants' import { DefinedArgumentName } from 'uiSrc/pages/workbench/constants' +const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + export const generateKeywords = (commands: IRedisCommand[]) => commands.map(({ name }) => name) export const generateTokens = ( @@ -153,7 +155,7 @@ export const getBlockTokens = ( if (tokensWithNextExpression.length) { result.push([ - `(${tokensWithNextExpression.map(({ token }) => token).join('|')})\\b`, + `(${tokensWithNextExpression.map(({ token }) => escapeRegex(token || '')).join('|')})\\b`, { token: `argument.block.${lvl}.${name}`, next: '@query', @@ -163,7 +165,7 @@ export const getBlockTokens = ( if (restTokens.length) { result.push([ - `(${restTokens.map(({ token }) => token).join('|')})\\b`, + `(${restTokens.map(({ token }) => escapeRegex(token || '')).join('|')})\\b`, { token: `argument.block.${lvl}.${name}`, next: '@root' }, ]) }