Allow blockquotes with encoded tags (#4662) * Allow blockquotes with encoded tags Fixes #4634 * Cache canUseNegativeLookbehind result * Optimize regex allocation

d08f3a2eef34959307270b485c6c4d92e725ab43

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +23 -11Ignore whitespace
public/script.js+4 -1
@@ -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';
183import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js';184import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids } from './scripts/constants.js';
184185
@@ -1598,7 +1599,9 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san
1598 }1599 }
15991600
1600 if (!isSystem && power_user.encode_tags) {1601 if (!isSystem && power_user.encode_tags) {
1601 mes = mes.replaceAll('<', '&lt;').replaceAll('>', '&gt;');1602 mes = canUseNegativeLookbehind()
1603 ? mes.replaceAll('<', '&lt;').replace(new RegExp('(?<!^|\\n\\s*)>', 'g'), '&gt;')
1604 : mes.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
1602 }1605 }
16031606
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 ">"
public/scripts/slash-commands.js+1 -10
@@ -1,5 +1,5 @@
1import { Fuse, DOMPurify } from '../lib.js';1import { Fuse, DOMPurify } from '../lib.js';
2import { copyText, flashHighlight } from './utils.js';2import { canUseNegativeLookbehind, copyText, flashHighlight } from './utils.js';
33
4import {4import {
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 */
5545export async function setSlashCommandAutoComplete(textarea, isFloating = false) {5545export 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;
public/scripts/utils.js+18 -0
@@ -35,6 +35,24 @@ export const localizePagination = function(container) {
35};35};
3636
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 */
41export 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 size57 * @param {number} pageSize Page size
40 * @param {number[]} sizeChangerOptions Array of page size options58 * @param {number[]} sizeChangerOptions Array of page size options