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; + }); +}