unvendor: Replace DOMPurify

3387fe4bd6a3f9ddb7227f69453317e0096a2607

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

20 files changed, +67 -31Showing whitespace changes
.eslintrc.cjs+0 -1
@@ -50,7 +50,6 @@ module.exports = {
5050 },
5151 // These scripts are loaded in HTML; tell ESLint not to complain about them being undefined
5252 globals: {
53- DOMPurify: 'readonly',
5453 droll: 'readonly',
5554 Handlebars: 'readonly',
5655 hljs: 'readonly',
package-lock.json+7 -18
@@ -22,6 +22,7 @@
2222 "cookie-session": "^2.1.0",
2323 "cors": "^2.8.5",
2424 "csrf-csrf": "^2.2.3",
25+ "dompurify": "^3.1.7",
2526 "express": "^4.21.0",
2627 "form-data": "^4.0.0",
2728 "fuse.js": "^7.0.0",
@@ -68,7 +69,6 @@
6869 "@types/cookie-parser": "^1.4.7",
6970 "@types/cookie-session": "^2.0.49",
7071 "@types/cors": "^2.8.17",
71- "@types/dompurify": "^3.0.5",
7272 "@types/express": "^4.17.21",
7373 "@types/jquery": "^3.5.29",
7474 "@types/lodash": "^4.17.10",
@@ -1174,16 +1174,6 @@
11741174 "@types/node": "*"
11751175 }
11761176 },
1177- "node_modules/@types/dompurify": {
1178- "version": "3.0.5",
1179- "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz",
1180- "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==",
1181- "dev": true,
1182- "license": "MIT",
1183- "dependencies": {
1184- "@types/trusted-types": "*"
1185- }
1186- },
11871177 "node_modules/@types/estree": {
11881178 "version": "1.0.6",
11891179 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@@ -1427,13 +1417,6 @@
14271417 "@types/jquery": "*"
14281418 }
14291419 },
1430- "node_modules/@types/trusted-types": {
1431- "version": "2.0.7",
1432- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
1433- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
1434- "dev": true,
1435- "license": "MIT"
1436- },
14371420 "node_modules/@types/write-file-atomic": {
14381421 "version": "4.0.3",
14391422 "resolved": "https://registry.npmjs.org/@types/write-file-atomic/-/write-file-atomic-4.0.3.tgz",
@@ -3221,6 +3204,12 @@
32213204 "url": "https://github.com/fb55/domhandler?sponsor=1"
32223205 }
32233206 },
3207+ "node_modules/dompurify": {
3208+ "version": "3.1.7",
3209+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
3210+ "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==",
3211+ "license": "(MPL-2.0 OR Apache-2.0)"
3212+ },
32243213 "node_modules/domutils": {
32253214 "version": "3.1.0",
32263215 "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
package.json+1 -1
@@ -12,6 +12,7 @@
1212 "cookie-session": "^2.1.0",
1313 "cors": "^2.8.5",
1414 "csrf-csrf": "^2.2.3",
15+ "dompurify": "^3.1.7",
1516 "express": "^4.21.0",
1617 "form-data": "^4.0.0",
1718 "fuse.js": "^7.0.0",
@@ -94,7 +95,6 @@
9495 "@types/cookie-parser": "^1.4.7",
9596 "@types/cookie-session": "^2.0.49",
9697 "@types/cors": "^2.8.17",
97- "@types/dompurify": "^3.0.5",
9898 "@types/express": "^4.17.21",
9999 "@types/jquery": "^3.5.29",
100100 "@types/lodash": "^4.17.10",
public/global.d.ts+1 -0
@@ -16,6 +16,7 @@ declare var ai;
1616declare var SillyTavern: {
1717 getContext(): any;
1818 llm: any;
19+ libs: any;
1920};
2021
2122// Jquery plugins
public/lib.js+26 -0
@@ -3,7 +3,33 @@
33 * They are bundled and exposed by Webpack in the /lib.js file.
44 */
55import Fuse from 'fuse.js';
6+import DOMPurify from 'dompurify';
7+
8+/**
9+ * Expose the libraries to the 'window' object.
10+ * Needed for compatibility with old extensions.
11+ * Note: New extensions are encouraged to import the libraries directly from lib.js.
12+ */
13+export function initLibraryShims() {
14+ if (!window) {
15+ return;
16+ }
17+ if (!('Fuse' in window)) {
18+ // @ts-ignore
19+ window.Fuse = Fuse;
20+ }
21+ if (!('DOMPurify' in window)) {
22+ // @ts-ignore
23+ window.DOMPurify = DOMPurify;
24+ }
25+}
26+
27+export default {
28+ Fuse,
29+ DOMPurify,
30+};
631
732export {
833 Fuse,
34+ DOMPurify,
935};
public/script.js+12 -3
@@ -1,4 +1,4 @@
11import { Fuse, DOMPurify, initLibraryShims, default as libs } from './lib.js';
22
33import { humanizedDateTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, initRossMods, shouldSendOnEnter, addSafariPatch } from './scripts/RossAscends-mods.js';
44import { userStatsHandler, statMesProcess, initStats } from './scripts/stats.js';
@@ -410,6 +410,7 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => {
410410
411411// API OBJECT FOR EXTERNAL WIRING
412412window['SillyTavern'] = {};
413+window['SillyTavern'].libs = libs;
413414
414415// Event source init
415416export const event_types = {
@@ -940,6 +941,7 @@ async function firstLoadInit() {
940941 throw new Error('Initialization failed');
941942 }
942943
944+ initLibraryShims();
943945 addSafariPatch();
944946 await getClientVersion();
945947 await readSecretState();
@@ -2058,8 +2060,15 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san
20582060 mes = mes.replace(new RegExp(`(^|\n)${escapeRegex(ch_name)}:`, 'g'), '$1');
20592061 }
20602062
20612063 /** @type {anyimport('dompurify').Config & { RETURN_DOM_FRAGMENT: false; RETURN_DOM: false }} */
2062- const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'], ...sanitizerOverrides };
2064+ const config = {
2065+ RETURN_DOM: false,
2066+ RETURN_DOM_FRAGMENT: false,
2067+ RETURN_TRUSTED_TYPE: false,
2068+ MESSAGE_SANITIZE: true,
2069+ ADD_TAGS: ['custom-style'],
2070+ ...sanitizerOverrides,
2071+ };
20632072 mes = encodeStyleTags(mes);
20642073 mes = DOMPurify.sanitize(mes, config);
20652074 mes = decodeStyleTags(mes);
public/scripts/PromptManager.js+2 -0
@@ -1,5 +1,7 @@
11'use strict';
22
3+import { DOMPurify } from '../lib.js';
4+
35import { event_types, eventSource, is_send_press, main_api, substituteParams } from '../script.js';
46import { is_group_generating } from './group-chats.js';
57import { Message, TokenHandler } from './openai.js';
public/scripts/RossAscends-mods.js+2 -0
@@ -1,3 +1,5 @@
1+import { DOMPurify } from '../lib.js';
2+
13import {
24 characters,
35 online_status,
public/scripts/extensions.js+2 -0
@@ -1,3 +1,5 @@
1+import { DOMPurify } from '../lib.js';
2+
13import { eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, animation_duration } from '../script.js';
24import { showLoader } from './loader.js';
35import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
public/scripts/extensions/assets/index.js+1 -0
@@ -3,6 +3,7 @@ TODO:
33*/
44//const DEBUG_TONY_SAMA_FORK_MODE = true
55
6+import { DOMPurify } from '../../../lib.js';
67import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from '../../../script.js';
78import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js';
89import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';
public/scripts/openai.js+1 -1
@@ -3,7 +3,7 @@
33* By CncAnon (@CncAnon1)
44* https://github.com/CncAnon1/TavernAITurbo
55*/
66import { Fuse, DOMPurify } from '../lib.js';
77
88import {
99 abortStatusCheck,
public/scripts/secrets.js+1 -0
@@ -1,3 +1,4 @@
1+import { DOMPurify } from '../lib.js';
12import { callPopup, getRequestHeaders } from '../script.js';
23
34export const SECRET_KEYS = {
public/scripts/slash-commands.js+1 -1
@@ -1,4 +1,4 @@
11import { Fuse, DOMPurify } from '../lib.js';
22
33import {
44 Generate,
public/scripts/slash-commands/SlashCommandReturnHelper.js+1 -0
@@ -1,3 +1,4 @@
1+import { DOMPurify } from '../../lib.js';
12import { sendSystemMessage, system_message_types } from '../../script.js';
23import { callGenericPopup, POPUP_TYPE } from '../popup.js';
34import { escapeHtml } from '../utils.js';
public/scripts/tags.js+2 -0
@@ -1,3 +1,5 @@
1+import { DOMPurify } from '../lib.js';
2+
13import {
24 characters,
35 saveSettingsDebounced,
public/scripts/templates.js+1 -0
@@ -1,3 +1,4 @@
1+import { DOMPurify } from '../lib.js';
12import { applyLocale } from './i18n.js';
23
34/**
public/scripts/textgen-models.js+1 -0
@@ -1,3 +1,4 @@
1+import { DOMPurify } from '../lib.js';
12import { isMobile } from './RossAscends-mods.js';
23import { amount_gen, callPopup, eventSource, event_types, getRequestHeaders, max_context, online_status, setGenerationParamsFromPreset } from '../script.js';
34import { textgenerationwebui_settings as textgen_settings, textgen_types } from './textgen-settings.js';
public/scripts/tool-calling.js+2 -0
@@ -1,3 +1,5 @@
1+import { DOMPurify } from '../lib.js';
2+
13import { addOneMessage, chat, event_types, eventSource, main_api, saveChatConditional, system_avatar, systemUserName } from '../script.js';
24import { chat_completion_sources, oai_settings } from './openai.js';
35import { Popup } from './popup.js';
public/scripts/utils.js+2 -0
@@ -1,3 +1,5 @@
1+import { DOMPurify } from '../lib.js';
2+
13import { getContext } from './extensions.js';
24import { characters, getRequestHeaders, this_chid } from '../script.js';
35import { isMobile } from './RossAscends-mods.js';
webpack.config.js+1 -6
@@ -4,12 +4,7 @@ export const publicLibConfig = {
44 entry: './public/lib.js',
55 cache: true,
66 devtool: 'source-map',
77 module: {},
8- rules: [{
9- test: /\.js$/,
10- exclude: /node_modules/,
11- }],
12- },
138 experiments: {
149 outputModule: true,
1510 },