mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Slash command output for sys and sendas commands were being formatted, but add the ability for user placement to also apply to slash command invocations. Some slash commands will require an output hook, so add exclusions inside the code itself. Signed-off-by: kingbri <bdashore3@proton.me>
241 lines
9.2 KiB
JavaScript
241 lines
9.2 KiB
JavaScript
import { callPopup, eventSource, event_types, getCurrentChatId, reloadCurrentChat, saveSettingsDebounced } from "../../../script.js";
|
|
import { extension_settings } from "../../extensions.js";
|
|
import { uuidv4, waitUntilCondition } from "../../utils.js";
|
|
import { regex_placement } from "./engine.js";
|
|
|
|
async function saveRegexScript(regexScript, existingScriptIndex) {
|
|
// If not editing
|
|
if (existingScriptIndex === -1) {
|
|
// Is the script name undefined?
|
|
if (!regexScript.scriptName) {
|
|
toastr.error(`Could not save regex script: The script name was undefined or empty!`);
|
|
return;
|
|
}
|
|
|
|
// Does the script name already exist?
|
|
if (extension_settings.regex.find((e) => e.scriptName === regexScript.scriptName)) {
|
|
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
|
|
return;
|
|
}
|
|
} else {
|
|
// Does the script name already exist somewhere else?
|
|
// (If this fails, make it a .filter().map() to index array)
|
|
const foundIndex = extension_settings.regex.findIndex((e) => e.scriptName === regexScript.scriptName);
|
|
if (foundIndex !== existingScriptIndex && foundIndex !== -1) {
|
|
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Is a find regex present?
|
|
if (regexScript.findRegex.length === 0) {
|
|
toastr.error(`Could not save regex script: A find regex is required!`);
|
|
return;
|
|
}
|
|
|
|
// Is there someplace to place results?
|
|
if (regexScript.placement.length === 0) {
|
|
toastr.error(`Could not save regex script: One placement checkbox must be selected!`);
|
|
return;
|
|
}
|
|
|
|
if (existingScriptIndex !== -1) {
|
|
extension_settings.regex[existingScriptIndex] = regexScript;
|
|
} else {
|
|
extension_settings.regex.push(regexScript);
|
|
}
|
|
|
|
saveSettingsDebounced();
|
|
await loadRegexScripts();
|
|
|
|
// Reload the current chat to undo previous markdown
|
|
const currentChatId = getCurrentChatId();
|
|
if (currentChatId !== undefined && currentChatId !== null) {
|
|
await reloadCurrentChat();
|
|
}
|
|
}
|
|
|
|
async function deleteRegexScript({ existingId }) {
|
|
let scriptName = $(`#${existingId}`).find('.regex_script_name').text();
|
|
|
|
const existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === scriptName);
|
|
if (!existingScriptIndex || existingScriptIndex !== -1) {
|
|
extension_settings.regex.splice(existingScriptIndex, 1);
|
|
|
|
saveSettingsDebounced();
|
|
await loadRegexScripts();
|
|
}
|
|
}
|
|
|
|
async function loadRegexScripts() {
|
|
$("#saved_regex_scripts").empty();
|
|
|
|
const scriptTemplate = $(await $.get("scripts/extensions/regex/scriptTemplate.html"));
|
|
|
|
extension_settings.regex.forEach((script) => {
|
|
// Have to clone here
|
|
const scriptHtml = scriptTemplate.clone();
|
|
scriptHtml.attr('id', uuidv4());
|
|
scriptHtml.find('.regex_script_name').text(script.scriptName);
|
|
scriptHtml.find('.edit_existing_regex').on('click', async function() {
|
|
await onRegexEditorOpenClick(scriptHtml.attr("id"));
|
|
});
|
|
scriptHtml.find('.delete_regex').on('click', async function() {
|
|
await deleteRegexScript({ existingId: scriptHtml.attr("id") });
|
|
});
|
|
|
|
$("#saved_regex_scripts").append(scriptHtml);
|
|
});
|
|
}
|
|
|
|
async function onRegexEditorOpenClick(existingId) {
|
|
const editorHtml = $(await $.get("scripts/extensions/regex/editor.html"));
|
|
|
|
// If an ID exists, fill in all the values
|
|
let existingScriptIndex = -1;
|
|
if (existingId) {
|
|
const existingScriptName = $(`#${existingId}`).find('.regex_script_name').text();
|
|
existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === existingScriptName);
|
|
if (existingScriptIndex !== -1) {
|
|
const existingScript = extension_settings.regex[existingScriptIndex];
|
|
if (existingScript.scriptName) {
|
|
editorHtml.find(`.regex_script_name`).val(existingScript.scriptName);
|
|
} else {
|
|
toastr.error("This script doesn't have a name! Please delete it.")
|
|
return;
|
|
}
|
|
|
|
editorHtml.find(`.find_regex`).val(existingScript.findRegex || "");
|
|
editorHtml.find(`.regex_replace_string`).val(existingScript.replaceString || "");
|
|
editorHtml.find(`.regex_trim_strings`).val(existingScript.trimStrings?.join("\n") || []);
|
|
editorHtml
|
|
.find(`input[name="disabled"]`)
|
|
.prop("checked", existingScript.disabled ?? false);
|
|
editorHtml
|
|
.find(`input[name="only_format_display"]`)
|
|
.prop("checked", existingScript.markdownOnly ?? false);
|
|
editorHtml
|
|
.find(`input[name="run_on_edit"]`)
|
|
.prop("checked", existingScript.runOnEdit ?? false);
|
|
editorHtml
|
|
.find(`input[name="substitute_regex"]`)
|
|
.prop("checked", existingScript.substituteRegex ?? false);
|
|
editorHtml
|
|
.find(`select[name="replace_strategy_select"]`)
|
|
.val(existingScript.replaceStrategy ?? 0);
|
|
|
|
existingScript.placement.forEach((element) => {
|
|
editorHtml
|
|
.find(`input[name="replace_position"][value="${element}"]`)
|
|
.prop("checked", true);
|
|
});
|
|
}
|
|
} else {
|
|
editorHtml
|
|
.find(`input[name="only_format_display"]`)
|
|
.prop("checked", true);
|
|
|
|
editorHtml
|
|
.find(`input[name="run_on_edit"]`)
|
|
.prop("checked", true);
|
|
|
|
editorHtml
|
|
.find(`input[name="replace_position"][value="0"]`)
|
|
.prop("checked", true);
|
|
}
|
|
|
|
const popupResult = await callPopup(editorHtml, "confirm", undefined, { okButton: "Save" });
|
|
if (popupResult) {
|
|
const newRegexScript = {
|
|
scriptName: editorHtml.find(".regex_script_name").val(),
|
|
findRegex: editorHtml.find(".find_regex").val(),
|
|
replaceString: editorHtml.find(".regex_replace_string").val(),
|
|
trimStrings: editorHtml.find(".regex_trim_strings").val().split("\n").filter((e) => e.length !== 0) || [],
|
|
placement:
|
|
editorHtml
|
|
.find(`input[name="replace_position"]`)
|
|
.filter(":checked")
|
|
.map(function() { return parseInt($(this).val()) })
|
|
.get()
|
|
.filter((e) => e !== NaN) || [],
|
|
disabled:
|
|
editorHtml
|
|
.find(`input[name="disabled"]`)
|
|
.prop("checked"),
|
|
markdownOnly:
|
|
editorHtml
|
|
.find(`input[name="only_format_display"]`)
|
|
.prop("checked"),
|
|
runOnEdit:
|
|
editorHtml
|
|
.find(`input[name="run_on_edit"]`)
|
|
.prop("checked"),
|
|
substituteRegex:
|
|
editorHtml
|
|
.find(`input[name="substitute_regex"]`)
|
|
.prop("checked"),
|
|
replaceStrategy:
|
|
parseInt(editorHtml
|
|
.find(`select[name="replace_strategy_select"]`)
|
|
.find(`:selected`)
|
|
.val()) ?? 0
|
|
};
|
|
|
|
saveRegexScript(newRegexScript, existingScriptIndex);
|
|
}
|
|
}
|
|
|
|
// Common settings migration function. Some parts will eventually be removed
|
|
// TODO: Maybe migrate placement to strings?
|
|
function migrateSettings() {
|
|
let performSave = false;
|
|
|
|
// Current: If MD Display is present in placement, remove it and add new placements/MD option
|
|
extension_settings.regex.forEach((script) => {
|
|
if (script.placement.includes(regex_placement.MD_DISPLAY)) {
|
|
script.placement = script.placement.length === 1 ?
|
|
Object.values(regex_placement).filter((e) => e !== regex_placement.MD_DISPLAY) :
|
|
script.placement = script.placement.filter((e) => e !== regex_placement.MD_DISPLAY);
|
|
|
|
script.markdownOnly = true
|
|
|
|
performSave = true;
|
|
}
|
|
|
|
// Old system and sendas placement migration
|
|
// 4 - sendAs
|
|
if (script.placement.includes(4)) {
|
|
script.placement = script.placement.length === 1 ?
|
|
[regex_placement.SLASH_COMMAND] :
|
|
script.placement = script.placement.filter((e) => e !== 4);
|
|
|
|
performSave = true;
|
|
}
|
|
});
|
|
|
|
if (performSave) {
|
|
saveSettingsDebounced();
|
|
}
|
|
}
|
|
|
|
// Workaround for loading in sequence with other extensions
|
|
// NOTE: Always puts extension at the top of the list, but this is fine since it's static
|
|
jQuery(async () => {
|
|
if (extension_settings.regex) {
|
|
migrateSettings();
|
|
}
|
|
|
|
// Manually disable the extension since static imports auto-import the JS file
|
|
if (extension_settings.disabledExtensions.includes("regex")) {
|
|
return;
|
|
}
|
|
|
|
const settingsHtml = await $.get("scripts/extensions/regex/dropdown.html");
|
|
$("#extensions_settings2").append(settingsHtml);
|
|
$("#open_regex_editor").on("click", function() {
|
|
onRegexEditorOpenClick(false);
|
|
});
|
|
|
|
await loadRegexScripts();
|
|
});
|