Allow blockquotes with encoded tags (#4662) * Allow blockquotes with encoded tags Fixes #4634 * Cache canUseNegativeLookbehind result * Optimize regex allocation
Signed| @@ -179,6 +179,7 @@ import { | |||
| 179 | importFromExternalUrl, | 179 | importFromExternalUrl, |
| 180 | shiftUpByOne, | 180 | shiftUpByOne, |
| 181 | shiftDownByOne, | 181 | shiftDownByOne, |
| 182 | canUseNegativeLookbehind, | ||
| 182 | } from './scripts/utils.js'; | 183 | } from './scripts/utils.js'; |
| 183 | import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js'; | 184 | import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js'; |
| 184 | 185 | ||
| @@ -1598,7 +1599,9 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san | |||
| 1598 | } | 1599 | } |
| 1599 | 1600 | ||
| 1600 | if (!isSystem && power_user.encode_tags) { | 1601 | if (!isSystem && power_user.encode_tags) { |
| 1601 | mes = mes.replaceAll('<', '<').replaceAll('>', '>'); | 1602 | mes = canUseNegativeLookbehind() |
| 1603 | ? mes.replaceAll('<', '<').replace(new RegExp('(?<!^|\\n\\s*)>', 'g'), '>') | ||
| 1604 | : mes.replaceAll('<', '<').replaceAll('>', '>'); | ||
| 1602 | } | 1605 | } |
| 1603 | 1606 | ||
| 1604 | // Make sure reasoning strings are always shown, even if they include "<" or ">" | 1607 | // Make sure reasoning strings are always shown, even if they include "<" or ">" |
| @@ -1,5 +1,5 @@ | |||
| 1 | import { Fuse, DOMPurify } from '../lib.js'; | 1 | import { Fuse, DOMPurify } from '../lib.js'; |
| 2 | import { copyText, flashHighlight } from './utils.js'; | 2 | import { canUseNegativeLookbehind, copyText, flashHighlight } from './utils.js'; |
| 3 | 3 | ||
| 4 | import { | 4 | import { |
| 5 | Generate, | 5 | Generate, |
| @@ -5543,15 +5543,6 @@ async function executeSlashCommands(text, handleParserErrors = true, scope = nul | |||
| 5543 | * @returns {Promise<AutoComplete>} | 5543 | * @returns {Promise<AutoComplete>} |
| 5544 | */ | 5544 | */ |
| 5545 | export async function setSlashCommandAutoComplete(textarea, isFloating = false) { | 5545 | export async function setSlashCommandAutoComplete(textarea, isFloating = false) { |
| 5546 | function canUseNegativeLookbehind() { | ||
| 5547 | try { | ||
| 5548 | new RegExp('(?<!_)'); | ||
| 5549 | return true; | ||
| 5550 | } catch (e) { | ||
| 5551 | return false; | ||
| 5552 | } | ||
| 5553 | } | ||
| 5554 | |||
| 5555 | if (!canUseNegativeLookbehind()) { | 5546 | if (!canUseNegativeLookbehind()) { |
| 5556 | console.warn('Cannot use negative lookbehind in this browser'); | 5547 | console.warn('Cannot use negative lookbehind in this browser'); |
| 5557 | return; | 5548 | return; |
| @@ -35,6 +35,24 @@ export const localizePagination = function(container) { | |||
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | /** | 37 | /** |
| 38 | * Checks if the current environment supports negative lookbehind in regular expressions. | ||
| 39 | * @returns {boolean} True if negative lookbehind is supported, false otherwise. | ||
| 40 | */ | ||
| 41 | export function canUseNegativeLookbehind() { | ||
| 42 | let result = canUseNegativeLookbehind['result']; | ||
| 43 | if (typeof result !== 'boolean') { | ||
| 44 | try { | ||
| 45 | new RegExp('(?<!_)'); | ||
| 46 | result = true; | ||
| 47 | } catch (e) { | ||
| 48 | result = false; | ||
| 49 | } | ||
| 50 | canUseNegativeLookbehind['result'] = result; | ||
| 51 | } | ||
| 52 | return result; | ||
| 53 | } | ||
| 54 | |||
| 55 | /** | ||
| 38 | * Renders a dropdown for selecting page size in pagination. | 56 | * Renders a dropdown for selecting page size in pagination. |
| 39 | * @param {number} pageSize Page size | 57 | * @param {number} pageSize Page size |
| 40 | * @param {number[]} sizeChangerOptions Array of page size options | 58 | * @param {number[]} sizeChangerOptions Array of page size options |