diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index ba25403e4..3cf7d03b5 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -53,7 +53,6 @@ module.exports = {
droll: 'readonly',
moment: 'readonly',
Popper: 'readonly',
- showdown: 'readonly',
showdownKatex: 'readonly',
toastr: 'readonly',
isProbablyReaderable: 'readonly',
diff --git a/package-lock.json b/package-lock.json
index 9a65df674..6d563d99e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -56,6 +56,7 @@
"rate-limiter-flexible": "^5.0.0",
"response-time": "^2.3.2",
"sanitize-filename": "^1.6.3",
+ "showdown": "^2.1.0",
"sillytavern-transformers": "2.14.6",
"simple-git": "^3.19.1",
"tiktoken": "^1.0.16",
@@ -7137,6 +7138,31 @@
"node": ">=8"
}
},
+ "node_modules/showdown": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
+ "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^9.0.0"
+ },
+ "bin": {
+ "showdown": "bin/showdown.js"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://www.paypal.me/tiviesantos"
+ }
+ },
+ "node_modules/showdown/node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
diff --git a/package.json b/package.json
index 1e6ce680d..7cbb5c490 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"rate-limiter-flexible": "^5.0.0",
"response-time": "^2.3.2",
"sanitize-filename": "^1.6.3",
+ "showdown": "^2.1.0",
"sillytavern-transformers": "2.14.6",
"simple-git": "^3.19.1",
"tiktoken": "^1.0.16",
diff --git a/public/global.d.ts b/public/global.d.ts
index 13b6d8547..ef6f0426a 100644
--- a/public/global.d.ts
+++ b/public/global.d.ts
@@ -1,7 +1,6 @@
// Global namespace modules
declare var droll;
declare var Popper;
-declare var showdown;
declare var showdownKatex;
declare var ai;
diff --git a/public/index.html b/public/index.html
index b62ced43f..82f6d643a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -6745,8 +6745,6 @@
-
-
diff --git a/public/jsconfig.json b/public/jsconfig.json
index 75a5ff04c..3e89dfd52 100644
--- a/public/jsconfig.json
+++ b/public/jsconfig.json
@@ -18,7 +18,6 @@
"typeAcquisition": {
"include": [
"@popperjs/core",
- "showdown",
"seedrandom",
"showdown-katex",
"droll"
diff --git a/public/lib.js b/public/lib.js
index fc67f665c..05a32e2e0 100644
--- a/public/lib.js
+++ b/public/lib.js
@@ -15,6 +15,7 @@ import * as pdfjsLib from 'pdfjs-dist/webpack.mjs';
import DiffMatchPatch from 'diff-match-patch';
import { isProbablyReaderable, Readability } from '@mozilla/readability';
import SVGInject from '@iconfu/svg-inject';
+import showdown from 'showdown';
/**
* Expose the libraries to the 'window' object.
@@ -53,6 +54,10 @@ export function initLibraryShims() {
// @ts-ignore
window.SVGInject = SVGInject;
}
+ if (!('showdown' in window)) {
+ // @ts-ignore
+ window.showdown = showdown;
+ }
}
export default {
@@ -70,6 +75,7 @@ export default {
Readability,
isProbablyReaderable,
SVGInject,
+ showdown,
};
export {
@@ -87,4 +93,5 @@ export {
Readability,
isProbablyReaderable,
SVGInject,
+ showdown,
};
diff --git a/public/lib/showdown-patch.js b/public/lib/showdown-patch.js
deleted file mode 100644
index 312a9f923..000000000
--- a/public/lib/showdown-patch.js
+++ /dev/null
@@ -1,24 +0,0 @@
-showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
- 'use strict';
- text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
-
- for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
- var repText = globals.gHtmlSpans[i],
- // limiter to prevent infinite loop (assume 10 as limit for recurse)
- limit = 0;
-
- while (/¨C(\d+)C/.test(repText)) {
- var num = RegExp.$1;
- repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
- if (limit === 10000) {
- console.error('maximum nesting of 10000 spans reached!!!');
- break;
- }
- ++limit;
- }
- text = text.replace('¨C' + i + 'C', repText);
- }
-
- text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
- return text;
-});
diff --git a/public/script.js b/public/script.js
index 4fa189544..290089ea4 100644
--- a/public/script.js
+++ b/public/script.js
@@ -1,4 +1,5 @@
import {
+ showdown,
Fuse,
DOMPurify,
hljs,
@@ -259,6 +260,7 @@ import { AbortReason } from './scripts/util/AbortReason.js';
import { initSystemPrompts } from './scripts/sysprompt.js';
import { registerExtensionSlashCommands as initExtensionSlashCommands } from './scripts/extensions-slashcommands.js';
import { ToolManager } from './scripts/tool-calling.js';
+import { addShowdownPatch } from './scripts/util/showdown-patch.js';
//exporting functions and vars for mods
export {
@@ -502,6 +504,7 @@ console.debug('Character context menu initialized', characterContextMenu);
// Markdown converter
export let mesForShowdownParse; //intended to be used as a context to compare showdown strings against
+/** @type {import('showdown').Converter} */
let converter;
reloadMarkdownProcessor();
@@ -952,6 +955,7 @@ async function firstLoadInit() {
}
initLibraryShims();
+ addShowdownPatch(showdown);
addSafariPatch();
await getClientVersion();
await readSecretState();
diff --git a/public/scripts/slash-commands/SlashCommandReturnHelper.js b/public/scripts/slash-commands/SlashCommandReturnHelper.js
index c26729ac5..7b8da1a80 100644
--- a/public/scripts/slash-commands/SlashCommandReturnHelper.js
+++ b/public/scripts/slash-commands/SlashCommandReturnHelper.js
@@ -1,4 +1,4 @@
-import { DOMPurify } from '../../lib.js';
+import { DOMPurify, showdown } from '../../lib.js';
import { sendSystemMessage, system_message_types } from '../../script.js';
import { callGenericPopup, POPUP_TYPE } from '../popup.js';
import { escapeHtml } from '../utils.js';
diff --git a/public/scripts/util/showdown-patch.js b/public/scripts/util/showdown-patch.js
new file mode 100644
index 000000000..d11ce5723
--- /dev/null
+++ b/public/scripts/util/showdown-patch.js
@@ -0,0 +1,30 @@
+/**
+ * Patches showdown to unrestrictedly unhash HTML spans.
+ * @param {import('showdown')} showdown The showdown object to patch
+ */
+export function addShowdownPatch(showdown) {
+ showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
+ 'use strict';
+ text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
+
+ for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
+ var repText = globals.gHtmlSpans[i],
+ // limiter to prevent infinite loop (assume 10 as limit for recurse)
+ limit = 0;
+
+ while (/¨C(\d+)C/.test(repText)) {
+ var num = RegExp.$1;
+ repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
+ if (limit === 10000) {
+ console.error('maximum nesting of 10000 spans reached!!!');
+ break;
+ }
+ ++limit;
+ }
+ text = text.replace('¨C' + i + 'C', repText);
+ }
+
+ text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
+ return text;
+ });
+}