From 02b0000117e6b9136ed9014d9eb2c1655ccb7761 Mon Sep 17 00:00:00 2001 From: ceruleandeep Date: Sat, 5 Oct 2024 17:26:28 +1000 Subject: [PATCH 1/7] Add clickable buttons in Welcome chat message. Add bool `uses_system_ui` on system messages to override sanitizer for buttons when set Modify uponSanitizeAttribute DOMPurify hook to allow unmangled class names on attributes in some cases Add event listener for .drawer-opener to open a navbar drawer --- public/script.js | 192 ++++++++++++++++---------- public/scripts/templates/welcome.html | 124 ++++++++++------- public/style.css | 5 +- 3 files changed, 200 insertions(+), 121 deletions(-) diff --git a/public/script.js b/public/script.js index 68cd86ed3..d82373400 100644 --- a/public/script.js +++ b/public/script.js @@ -293,10 +293,17 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) { } }); -DOMPurify.addHook('uponSanitizeAttribute', (_, data, config) => { +DOMPurify.addHook('uponSanitizeAttribute', (node, data, config) => { if (!config['MESSAGE_SANITIZE']) { return; } + + /* Retain the classes on UI elements of messages that interact with the main UI */ + const permittedNodeTypes = ['BUTTON', 'DIV']; + if (config['MESSAGE_ALLOW_SYSTEM_UI'] && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) { + return; + } + switch (data.attrName) { case 'class': { if (data.attrValue) { @@ -650,7 +657,8 @@ async function getSystemMessages() { force_avatar: system_avatar, is_user: false, is_system: true, - mes: await renderTemplateAsync('welcome', { displayVersion }), + uses_system_ui: true, + mes: await renderTemplateAsync('welcome', { displayVersion } ), }, group: { name: systemUserName, @@ -1916,9 +1924,10 @@ export async function sendTextareaMessage() { * @param {boolean} isSystem If the message was sent by the system * @param {boolean} isUser If the message was sent by the user * @param {number} messageId Message index in chat array + * @param {object} [sanitizerOverrides] DOMPurify sanitizer option overrides * @returns {string} HTML string */ -export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) { +export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, sanitizerOverrides = {}) { if (!mes) { return ''; } @@ -2029,7 +2038,7 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) { } /** @type {any} */ - const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'] }; + const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'], ...sanitizerOverrides }; mes = encodeStyleTags(mes); mes = DOMPurify.sanitize(mes, config); mes = decodeStyleTags(mes); @@ -2234,6 +2243,18 @@ export function addCopyToCodeBlocks(messageElement) { } +/** + * Adds a single message to the chat. + * @param {object} mes Message object + * @param {object} [options] Options + * @param {string} [options.type='normal'] Message type + * @param {number} [options.insertAfter=null] Message ID to insert the new message after + * @param {boolean} [options.scroll=true] Whether to scroll to the new message + * @param {number} [options.insertBefore=null] Message ID to insert the new message before + * @param {number} [options.forceId=null] Force the message ID + * @param {boolean} [options.showSwipes=true] Whether to show swipe buttons + * @returns {void} + */ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) { let messageText = mes['mes']; const momentDate = timestampToMoment(mes.send_date); @@ -2262,7 +2283,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll } else if (this_chid === undefined) { avatarImg = system_avatar; } else { - if (characters[this_chid].avatar != 'none') { + if (characters[this_chid].avatar !== 'none') { avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar); } else { avatarImg = default_avatar; @@ -2277,12 +2298,16 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll avatarImg = mes['force_avatar']; } + // if mes.uses_system_ui is true, set an override on the sanitizer options + const sanitizerOverrides = mes.uses_system_ui ? { MESSAGE_ALLOW_SYSTEM_UI: true } : {}; + messageText = messageFormatting( messageText, mes.name, isSystem, mes.is_user, chat.indexOf(mes), + sanitizerOverrides, ); const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1); let bookmarkLink = mes?.extra?.bookmark_link ?? ''; @@ -2330,7 +2355,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll } //shows or hides the Prompt display button - let mesIdToFind = type == 'swipe' ? params.mesId - 1 : params.mesId; //Number(newMessage.attr('mesId')); + let mesIdToFind = type === 'swipe' ? params.mesId - 1 : params.mesId; //Number(newMessage.attr('mesId')); //if we have itemized messages, and the array isn't null.. if (params.isUser === false && Array.isArray(itemizedPrompts) && itemizedPrompts.length > 0) { @@ -2651,7 +2676,7 @@ export function sendSystemMessage(type, text, extra = {}) { newMessage.mes = text; } - if (type == system_message_types.SLASH_COMMANDS) { + if (type === system_message_types.SLASH_COMMANDS) { newMessage.mes = getSlashCommandsHelp(); } @@ -2665,7 +2690,7 @@ export function sendSystemMessage(type, text, extra = {}) { chat.push(newMessage); addOneMessage(newMessage); is_send_press = false; - if (type == system_message_types.SLASH_COMMANDS) { + if (type === system_message_types.SLASH_COMMANDS) { const browser = new SlashCommandBrowser(); const spinner = document.querySelector('#chat .last_mes .custom-slashHelp'); const parent = spinner.parentElement; @@ -7854,7 +7879,7 @@ function openAlternateGreetings() { if (menu_type !== 'create') { await createOrEditCharacter(); } - } + }, }); for (let index = 0; index < getArray().length; index++) { @@ -9070,6 +9095,90 @@ function doTogglePanels() { return ''; } +/** + * Event handler to open a navbar drawer when a drawer open button is clicked. + * Handles click events on .drawer-opener elements. + * Opens the drawer associated with the clicked button according to the data-target attribute. + * @returns {void} + */ +function doDrawerOpenClick() { + const targetDrawerID = $(this).attr('data-target'); + const drawer = $(`#${targetDrawerID}`); + const drawerToggle = drawer.find('.drawer-toggle'); + const drawerWasOpenAlready = drawerToggle.parent().find('.drawer-content').hasClass('openDrawer'); + if (drawerWasOpenAlready || drawer.hasClass('resizing') ) { return; } + doNavbarIconClick.call(drawerToggle); +} + +/** + * Event handler to open or close a navbar drawer when a navbar icon is clicked. + * Handles click events on .drawer-toggle elements. + * @returns {void} + */ +function doNavbarIconClick() { + var icon = $(this).find('.drawer-icon'); + var drawer = $(this).parent().find('.drawer-content'); + if (drawer.hasClass('resizing')) { return; } + var drawerWasOpenAlready = $(this).parent().find('.drawer-content').hasClass('openDrawer'); + let targetDrawerID = $(this).parent().find('.drawer-content').attr('id'); + const pinnedDrawerClicked = drawer.hasClass('pinnedOpen'); + + if (!drawerWasOpenAlready) { //to open the drawer + $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { + await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); + }); + $('.openIcon').toggleClass('closedIcon openIcon'); + $('.openDrawer').not('.pinnedOpen').toggleClass('closedDrawer openDrawer'); + icon.toggleClass('openIcon closedIcon'); + drawer.toggleClass('openDrawer closedDrawer'); + + //console.log(targetDrawerID); + if (targetDrawerID === 'right-nav-panel') { + $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle({ + duration: 200, + easing: 'swing', + start: function () { + jQuery(this).css('display', 'flex'); //flex needed to make charlist scroll + }, + complete: async function () { + favsToHotswap(); + await delay(50); + $(this).closest('.drawer-content').removeClass('resizing'); + $('#rm_print_characters_block').trigger('scroll'); + }, + }); + } else { + $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle(200, 'swing', async function () { + await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); + }); + } + + // Set the height of "autoSetHeight" textareas within the drawer to their scroll height + if (!CSS.supports('field-sizing', 'content')) { + $(this).closest('.drawer').find('.drawer-content textarea.autoSetHeight').each(async function () { + await resetScrollHeight($(this)); + return; + }); + } + + } else if (drawerWasOpenAlready) { //to close manually + icon.toggleClass('closedIcon openIcon'); + + if (pinnedDrawerClicked) { + $(drawer).addClass('resizing').slideToggle(200, 'swing', async function () { + await delay(50); $(this).removeClass('resizing'); + }); + } + else { + $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { + await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); + }); + } + + drawer.toggleClass('closedDrawer openDrawer'); + } +} + function addDebugFunctions() { const doBackfill = async () => { for (const message of chat) { @@ -10659,69 +10768,8 @@ jQuery(async function () { stopScriptExecution(); }); - $('.drawer-toggle').on('click', function () { - var icon = $(this).find('.drawer-icon'); - var drawer = $(this).parent().find('.drawer-content'); - if (drawer.hasClass('resizing')) { return; } - var drawerWasOpenAlready = $(this).parent().find('.drawer-content').hasClass('openDrawer'); - let targetDrawerID = $(this).parent().find('.drawer-content').attr('id'); - const pinnedDrawerClicked = drawer.hasClass('pinnedOpen'); - - if (!drawerWasOpenAlready) { //to open the drawer - $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { - await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); - }); - $('.openIcon').not('.drawerPinnedOpen').toggleClass('closedIcon openIcon'); - $('.openDrawer').not('.pinnedOpen').toggleClass('closedDrawer openDrawer'); - icon.toggleClass('openIcon closedIcon'); - drawer.toggleClass('openDrawer closedDrawer'); - - //console.log(targetDrawerID); - if (targetDrawerID === 'right-nav-panel') { - $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle({ - duration: 200, - easing: 'swing', - start: function () { - jQuery(this).css('display', 'flex'); //flex needed to make charlist scroll - }, - complete: async function () { - favsToHotswap(); - await delay(50); - $(this).closest('.drawer-content').removeClass('resizing'); - $('#rm_print_characters_block').trigger('scroll'); - }, - }); - } else { - $(this).closest('.drawer').find('.drawer-content').addClass('resizing').slideToggle(200, 'swing', async function () { - await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); - }); - } - - // Set the height of "autoSetHeight" textareas within the drawer to their scroll height - if (!CSS.supports('field-sizing', 'content')) { - $(this).closest('.drawer').find('.drawer-content textarea.autoSetHeight').each(async function () { - await resetScrollHeight($(this)); - return; - }); - } - - } else if (drawerWasOpenAlready) { //to close manually - icon.toggleClass('closedIcon openIcon'); - - if (pinnedDrawerClicked) { - $(drawer).addClass('resizing').slideToggle(200, 'swing', async function () { - await delay(50); $(this).removeClass('resizing'); - }); - } - else { - $('.openDrawer').not('.pinnedOpen').addClass('resizing').slideToggle(200, 'swing', async function () { - await delay(50); $(this).closest('.drawer-content').removeClass('resizing'); - }); - } - - drawer.toggleClass('closedDrawer openDrawer'); - } - }); + $(document).on('click', '.drawer-opener', doDrawerOpenClick); + $('.drawer-toggle').on('click', doNavbarIconClick); $('html').on('touchstart mousedown', function (e) { var clickTarget = $(e.target); diff --git a/public/scripts/templates/welcome.html b/public/scripts/templates/welcome.html index 82eb07097..df887c3ad 100644 --- a/public/scripts/templates/welcome.html +++ b/public/scripts/templates/welcome.html @@ -1,65 +1,95 @@

- {{displayVersion}} + {{displayVersion}}

- Want to update? + Want to update?

How to start chatting?

    -
  1. - Click and select a Chat API. -
  2. -
  3. - Click and pick a character. -
  4. +
  5. + Click + + and select a + + + Chat API. +
  6. +
  7. + Click + + and pick a character. +
-
- - You can browse a list of bundled characters in the - - - Download Extensions & Assets - - - menu within - - - . -
+ +

+ You can add more + + or + + from other websites. + + Go to the + + Download Extensions & Assets + menu within + + + + to install additional features. +

+

Confused or lost?


Still have questions?

diff --git a/public/style.css b/public/style.css index 01a49ab9f..6ee4f6d60 100644 --- a/public/style.css +++ b/public/style.css @@ -1208,8 +1208,9 @@ textarea.autoSetHeight { } input, -select { - font-family: var(--mainFontFamily); +select, +button { + font-family: var(--mainFontFamily), sans-serif; font-size: var(--mainFontSize); color: var(--SmartThemeBodyColor); } From ebe2929dfd8ad3f83975ad1fa8ecba37f66cc311 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 5 Oct 2024 17:07:17 +0300 Subject: [PATCH 2/7] Localize chat timestamps --- public/index.html | 2 +- public/lib/moment-with-locales.min.js | 2 ++ public/lib/moment-with-locales.min.js.map | 1 + public/lib/moment.min.js | 2 -- public/lib/moment.min.js.map | 1 - public/scripts/i18n.js | 1 + 6 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 public/lib/moment-with-locales.min.js create mode 100644 public/lib/moment-with-locales.min.js.map delete mode 100644 public/lib/moment.min.js delete mode 100644 public/lib/moment.min.js.map diff --git a/public/index.html b/public/index.html index 132d4d4bf..9a71ba897 100644 --- a/public/index.html +++ b/public/index.html @@ -6636,7 +6636,7 @@ - + diff --git a/public/lib/moment-with-locales.min.js b/public/lib/moment-with-locales.min.js new file mode 100644 index 000000000..8a6c9b475 --- /dev/null +++ b/public/lib/moment-with-locales.min.js @@ -0,0 +1,2 @@ +!function(e,a){"object"==typeof exports&&"undefined"!=typeof module?module.exports=a():"function"==typeof define&&define.amd?define(a):e.moment=a()}(this,function(){"use strict";var E;function c(){return E.apply(null,arguments)}function F(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function z(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e,a){return Object.prototype.hasOwnProperty.call(e,a)}function N(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;for(var a in e)if(l(e,a))return;return 1}function L(e){return void 0===e}function J(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function R(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function C(e,a){for(var t=[],s=e.length,n=0;n>>0,s=0;sFe(e)?(r=e+1,a-Fe(e)):(r=e,a);return{year:r,dayOfYear:t}}function aa(e,a,t){var s,n,r=Xe(e.year(),a,t),r=Math.floor((e.dayOfYear()-r-1)/7)+1;return r<1?s=r+ta(n=e.year()-1,a,t):r>ta(e.year(),a,t)?(s=r-ta(e.year(),a,t),n=e.year()+1):(n=e.year(),s=r),{week:s,year:n}}function ta(e,a,t){var s=Xe(e,a,t),a=Xe(e+1,a,t);return(Fe(e)-s+a)/7}s("w",["ww",2],"wo","week"),s("W",["WW",2],"Wo","isoWeek"),h("w",r,u),h("ww",r,a),h("W",r,u),h("WW",r,a),Se(["w","ww","W","WW"],function(e,a,t,s){a[s.substr(0,1)]=f(e)});function sa(e,a){return e.slice(a,7).concat(e.slice(0,a))}s("d",0,"do","day"),s("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),s("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),s("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),s("e",0,0,"weekday"),s("E",0,0,"isoWeekday"),h("d",r),h("e",r),h("E",r),h("dd",function(e,a){return a.weekdaysMinRegex(e)}),h("ddd",function(e,a){return a.weekdaysShortRegex(e)}),h("dddd",function(e,a){return a.weekdaysRegex(e)}),Se(["dd","ddd","dddd"],function(e,a,t,s){s=t._locale.weekdaysParse(e,s,t._strict);null!=s?a.d=s:Y(t).invalidWeekday=e}),Se(["d","e","E"],function(e,a,t,s){a[s]=f(e)});var na="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ra="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),da="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),_a=m,ia=m,oa=m;function ma(){function e(e,a){return a.length-e.length}for(var a,t,s,n=[],r=[],d=[],_=[],i=0;i<7;i++)s=U([2e3,1]).day(i),a=we(this.weekdaysMin(s,"")),t=we(this.weekdaysShort(s,"")),s=we(this.weekdays(s,"")),n.push(a),r.push(t),d.push(s),_.push(a),_.push(t),_.push(s);n.sort(e),r.sort(e),d.sort(e),_.sort(e),this._weekdaysRegex=new RegExp("^("+_.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+n.join("|")+")","i")}function ua(){return this.hours()%12||12}function la(e,a){s(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}function Ma(e,a){return a._meridiemParse}s("H",["HH",2],0,"hour"),s("h",["hh",2],0,ua),s("k",["kk",2],0,function(){return this.hours()||24}),s("hmm",0,0,function(){return""+ua.apply(this)+de(this.minutes(),2)}),s("hmmss",0,0,function(){return""+ua.apply(this)+de(this.minutes(),2)+de(this.seconds(),2)}),s("Hmm",0,0,function(){return""+this.hours()+de(this.minutes(),2)}),s("Hmmss",0,0,function(){return""+this.hours()+de(this.minutes(),2)+de(this.seconds(),2)}),la("a",!0),la("A",!1),h("a",Ma),h("A",Ma),h("H",r,M),h("h",r,u),h("k",r,u),h("HH",r,a),h("hh",r,a),h("kk",r,a),h("hmm",ye),h("hmmss",_),h("Hmm",ye),h("Hmmss",_),k(["H","HH"],D),k(["k","kk"],function(e,a,t){e=f(e);a[D]=24===e?0:e}),k(["a","A"],function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e}),k(["h","hh"],function(e,a,t){a[D]=f(e),Y(t).bigHour=!0}),k("hmm",function(e,a,t){var s=e.length-2;a[D]=f(e.substr(0,s)),a[Pe]=f(e.substr(s)),Y(t).bigHour=!0}),k("hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[D]=f(e.substr(0,s)),a[Pe]=f(e.substr(s,2)),a[Oe]=f(e.substr(n)),Y(t).bigHour=!0}),k("Hmm",function(e,a,t){var s=e.length-2;a[D]=f(e.substr(0,s)),a[Pe]=f(e.substr(s))}),k("Hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[D]=f(e.substr(0,s)),a[Pe]=f(e.substr(s,2)),a[Oe]=f(e.substr(n))});m=Ne("Hours",!0);var ha,ca={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ie,monthsShort:Ue,week:{dow:0,doy:6},weekdays:na,weekdaysMin:da,weekdaysShort:ra,meridiemParse:/[ap]\.?m?\.?/i},g={},La={};function Ya(e){return e&&e.toLowerCase().replace("_","-")}function ya(e){for(var a,t,s,n,r=0;r=a&&function(e,a){for(var t=Math.min(e.length,a.length),s=0;s=a-1)break;a--}r++}return ha}function fa(a){var e,t;if(void 0===g[a]&&"undefined"!=typeof module&&module&&module.exports&&(t=a)&&t.match("^[^/\\\\]*$"))try{e=ha._abbr,require("./locale/"+a),ka(e)}catch(e){g[a]=null}return g[a]}function ka(e,a){return e&&((a=L(a)?Da(e):pa(e,a))?ha=a:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),ha._abbr}function pa(e,a){if(null===a)return delete g[e],null;var t,s=ca;if(a.abbr=e,null!=g[e])ae("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=g[e]._config;else if(null!=a.parentLocale)if(null!=g[a.parentLocale])s=g[a.parentLocale]._config;else{if(null==(t=fa(a.parentLocale)))return La[a.parentLocale]||(La[a.parentLocale]=[]),La[a.parentLocale].push({name:e,config:a}),null;s=t._config}return g[e]=new ne(se(s,a)),La[e]&&La[e].forEach(function(e){pa(e.name,e.config)}),ka(e),g[e]}function Da(e){var a;if(!(e=e&&e._locale&&e._locale._abbr?e._locale._abbr:e))return ha;if(!F(e)){if(a=fa(e))return a;e=[e]}return ya(e)}function Ta(e){var a=e._a;return a&&-2===Y(e).overflow&&(a=a[je]<0||11Ce(a[p],a[je])?xe:a[D]<0||24ta(r,i,o)?Y(s)._overflowWeeks=!0:null!=m?Y(s)._overflowWeekday=!0:(u=ea(r,d,_,i,o),s._a[p]=u.year,s._dayOfYear=u.dayOfYear)),null!=e._dayOfYear&&(n=Aa(e._a[p],t[p]),(e._dayOfYear>Fe(n)||0===e._dayOfYear)&&(Y(e)._overflowDayOfYear=!0),m=Qe(n,0,e._dayOfYear),e._a[je]=m.getUTCMonth(),e._a[xe]=m.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=l[a]=t[a];for(;a<7;a++)e._a[a]=l[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[D]&&0===e._a[Pe]&&0===e._a[Oe]&&0===e._a[We]&&(e._nextDay=!0,e._a[D]=0),e._d=(e._useUTC?Qe:$e).apply(null,l),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[D]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(Y(e).weekdayMismatch=!0)}}function Fa(e){if(e._f===c.ISO_8601)Pa(e);else if(e._f===c.RFC_2822)Wa(e);else{e._a=[],Y(e).empty=!0;for(var a,t,s,n,r,d=""+e._i,_=d.length,i=0,o=le(e._f,e._locale).match(_e)||[],m=o.length,u=0;ue.valueOf():e.valueOf()"}),u.toJSON=function(){return this.isValid()?this.toISOString():null},u.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},u.unix=function(){return Math.floor(this.valueOf()/1e3)},u.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},u.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},u.eraName=function(){for(var e,a=this.localeData().eras(),t=0,s=a.length;tthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},u.isLocal=function(){return!!this.isValid()&&!this._isUTC},u.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},u.isUtc=Za,u.isUTC=Za,u.zoneAbbr=function(){return this._isUTC?"UTC":""},u.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},u.dates=e("dates accessor is deprecated. Use date instead.",i),u.months=e("months accessor is deprecated. Use month instead",Ke),u.years=e("years accessor is deprecated. Use year instead",ze),u.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,a){return null!=e?(this.utcOffset(e="string"!=typeof e?-e:e,a),this):-this.utcOffset()}),u.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){var e,a;return L(this._isDSTShifted)&&(Z(e={},this),(e=za(e))._a?(a=(e._isUTC?U:w)(e._a),this._isDSTShifted=this.isValid()&&0>>0,s=0;sAe(e)?(r=e+1,t-Ae(e)):(r=e,t);return{year:r,dayOfYear:n}}function qe(e,t,n){var s,i,r=ze(e.year(),t,n),r=Math.floor((e.dayOfYear()-r-1)/7)+1;return r<1?s=r+P(i=e.year()-1,t,n):r>P(e.year(),t,n)?(s=r-P(e.year(),t,n),i=e.year()+1):(i=e.year(),s=r),{week:s,year:i}}function P(e,t,n){var s=ze(e,t,n),t=ze(e+1,t,n);return(Ae(e)-s+t)/7}s("w",["ww",2],"wo","week"),s("W",["WW",2],"Wo","isoWeek"),t("week","w"),t("isoWeek","W"),n("week",5),n("isoWeek",5),v("w",p),v("ww",p,w),v("W",p),v("WW",p,w),Te(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=g(e)});function Be(e,t){return e.slice(t,7).concat(e.slice(0,t))}s("d",0,"do","day"),s("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),s("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),s("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),s("e",0,0,"weekday"),s("E",0,0,"isoWeekday"),t("day","d"),t("weekday","e"),t("isoWeekday","E"),n("day",11),n("weekday",11),n("isoWeekday",11),v("d",p),v("e",p),v("E",p),v("dd",function(e,t){return t.weekdaysMinRegex(e)}),v("ddd",function(e,t){return t.weekdaysShortRegex(e)}),v("dddd",function(e,t){return t.weekdaysRegex(e)}),Te(["dd","ddd","dddd"],function(e,t,n,s){s=n._locale.weekdaysParse(e,s,n._strict);null!=s?t.d=s:m(n).invalidWeekday=e}),Te(["d","e","E"],function(e,t,n,s){t[s]=g(e)});var Je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Qe="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Xe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Ke=k,et=k,tt=k;function nt(){function e(e,t){return t.length-e.length}for(var t,n,s,i=[],r=[],a=[],o=[],u=0;u<7;u++)s=l([2e3,1]).day(u),t=M(this.weekdaysMin(s,"")),n=M(this.weekdaysShort(s,"")),s=M(this.weekdays(s,"")),i.push(t),r.push(n),a.push(s),o.push(t),o.push(n),o.push(s);i.sort(e),r.sort(e),a.sort(e),o.sort(e),this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function st(){return this.hours()%12||12}function it(e,t){s(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function rt(e,t){return t._meridiemParse}s("H",["HH",2],0,"hour"),s("h",["hh",2],0,st),s("k",["kk",2],0,function(){return this.hours()||24}),s("hmm",0,0,function(){return""+st.apply(this)+r(this.minutes(),2)}),s("hmmss",0,0,function(){return""+st.apply(this)+r(this.minutes(),2)+r(this.seconds(),2)}),s("Hmm",0,0,function(){return""+this.hours()+r(this.minutes(),2)}),s("Hmmss",0,0,function(){return""+this.hours()+r(this.minutes(),2)+r(this.seconds(),2)}),it("a",!0),it("A",!1),t("hour","h"),n("hour",13),v("a",rt),v("A",rt),v("H",p),v("h",p),v("k",p),v("HH",p,w),v("hh",p,w),v("kk",p,w),v("hmm",ge),v("hmmss",we),v("Hmm",ge),v("Hmmss",we),D(["H","HH"],x),D(["k","kk"],function(e,t,n){e=g(e);t[x]=24===e?0:e}),D(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),D(["h","hh"],function(e,t,n){t[x]=g(e),m(n).bigHour=!0}),D("hmm",function(e,t,n){var s=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s)),m(n).bigHour=!0}),D("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s,2)),t[N]=g(e.substr(i)),m(n).bigHour=!0}),D("Hmm",function(e,t,n){var s=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s))}),D("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s,2)),t[N]=g(e.substr(i))});k=de("Hours",!0);var at,ot={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:Ue,week:{dow:0,doy:6},weekdays:Je,weekdaysMin:Xe,weekdaysShort:Qe,meridiemParse:/[ap]\.?m?\.?/i},R={},ut={};function lt(e){return e&&e.toLowerCase().replace("_","-")}function ht(e){for(var t,n,s,i,r=0;r=t&&function(e,t){for(var n=Math.min(e.length,t.length),s=0;s=t-1)break;t--}r++}return at}function dt(t){var e;if(void 0===R[t]&&"undefined"!=typeof module&&module&&module.exports&&null!=t.match("^[^/\\\\]*$"))try{e=at._abbr,require("./locale/"+t),ct(e)}catch(e){R[t]=null}return R[t]}function ct(e,t){return e&&((t=o(t)?mt(e):ft(e,t))?at=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),at._abbr}function ft(e,t){if(null===t)return delete R[e],null;var n,s=ot;if(t.abbr=e,null!=R[e])Q("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=R[e]._config;else if(null!=t.parentLocale)if(null!=R[t.parentLocale])s=R[t.parentLocale]._config;else{if(null==(n=dt(t.parentLocale)))return ut[t.parentLocale]||(ut[t.parentLocale]=[]),ut[t.parentLocale].push({name:e,config:t}),null;s=n._config}return R[e]=new K(X(s,t)),ut[e]&&ut[e].forEach(function(e){ft(e.name,e.config)}),ct(e),R[e]}function mt(e){var t;if(!(e=e&&e._locale&&e._locale._abbr?e._locale._abbr:e))return at;if(!a(e)){if(t=dt(e))return t;e=[e]}return ht(e)}function _t(e){var t=e._a;return t&&-2===m(e).overflow&&(t=t[O]<0||11We(t[Y],t[O])?b:t[x]<0||24P(r,u,l)?m(s)._overflowWeeks=!0:null!=h?m(s)._overflowWeekday=!0:(d=$e(r,a,o,u,l),s._a[Y]=d.year,s._dayOfYear=d.dayOfYear)),null!=e._dayOfYear&&(i=bt(e._a[Y],n[Y]),(e._dayOfYear>Ae(i)||0===e._dayOfYear)&&(m(e)._overflowDayOfYear=!0),h=Ze(i,0,e._dayOfYear),e._a[O]=h.getUTCMonth(),e._a[b]=h.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=c[t]=n[t];for(;t<7;t++)e._a[t]=c[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[x]&&0===e._a[T]&&0===e._a[N]&&0===e._a[Ne]&&(e._nextDay=!0,e._a[x]=0),e._d=(e._useUTC?Ze:je).apply(null,c),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[x]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(m(e).weekdayMismatch=!0)}}function Tt(e){if(e._f===f.ISO_8601)St(e);else if(e._f===f.RFC_2822)Ot(e);else{e._a=[],m(e).empty=!0;for(var t,n,s,i,r,a=""+e._i,o=a.length,u=0,l=ae(e._f,e._locale).match(te)||[],h=l.length,d=0;de.valueOf():e.valueOf()"}),i.toJSON=function(){return this.isValid()?this.toISOString():null},i.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},i.unix=function(){return Math.floor(this.valueOf()/1e3)},i.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},i.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},i.eraName=function(){for(var e,t=this.localeData().eras(),n=0,s=t.length;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},i.isLocal=function(){return!!this.isValid()&&!this._isUTC},i.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},i.isUtc=At,i.isUTC=At,i.zoneAbbr=function(){return this._isUTC?"UTC":""},i.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},i.dates=e("dates accessor is deprecated. Use date instead.",ke),i.months=e("months accessor is deprecated. Use month instead",Ge),i.years=e("years accessor is deprecated. Use year instead",Ie),i.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?(this.utcOffset(e="string"!=typeof e?-e:e,t),this):-this.utcOffset()}),i.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var e,t={};return $(t,this),(t=Nt(t))._a?(e=(t._isUTC?l:W)(t._a),this._isDSTShifted=this.isValid()&&0 response.json()); localeData = await getLocaleData(localeFile); applyLocale(); From 60fef3ee99705be644c25e578b666344af8af81d Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 5 Oct 2024 19:45:41 +0300 Subject: [PATCH 3/7] Restyle welcome --- public/script.js | 4 +- public/scripts/templates/welcome.html | 149 +++++++++++++------------- public/style.css | 6 ++ 3 files changed, 81 insertions(+), 78 deletions(-) diff --git a/public/script.js b/public/script.js index d82373400..7651cf3fd 100644 --- a/public/script.js +++ b/public/script.js @@ -658,7 +658,7 @@ async function getSystemMessages() { is_user: false, is_system: true, uses_system_ui: true, - mes: await renderTemplateAsync('welcome', { displayVersion } ), + mes: await renderTemplateAsync('welcome', { displayVersion }), }, group: { name: systemUserName, @@ -9106,7 +9106,7 @@ function doDrawerOpenClick() { const drawer = $(`#${targetDrawerID}`); const drawerToggle = drawer.find('.drawer-toggle'); const drawerWasOpenAlready = drawerToggle.parent().find('.drawer-content').hasClass('openDrawer'); - if (drawerWasOpenAlready || drawer.hasClass('resizing') ) { return; } + if (drawerWasOpenAlready || drawer.hasClass('resizing')) { return; } doNavbarIconClick.call(drawerToggle); } diff --git a/public/scripts/templates/welcome.html b/public/scripts/templates/welcome.html index df887c3ad..eaf49b986 100644 --- a/public/scripts/templates/welcome.html +++ b/public/scripts/templates/welcome.html @@ -1,95 +1,92 @@

- {{displayVersion}} + {{displayVersion}}

- Want to update? + Want to update? -

How to start chatting?

    -
  1. - Click - - and select a - - - Chat API. -
  2. -
  3. - Click - - and pick a character. -
  4. +
  5. + Click + + and connect to an + + + API. +
  6. +
  7. + Click + + and pick a character. +
-

- You can add more - - or - - from other websites. +

+ You can add more + + or + + from other websites. +
+
+ Go to the - Go to the + Download Extensions & Assets + menu within - Download Extensions & Assets - menu within + - + to install additional features. +
- to install additional features. -

- -

Confused or lost?

-

Still have questions?

- diff --git a/public/style.css b/public/style.css index 6ee4f6d60..8bb8d5809 100644 --- a/public/style.css +++ b/public/style.css @@ -314,6 +314,12 @@ input[type='checkbox']:focus-visible { display: inline-block; } +.mes_text ol, +.mes_text ul { + margin-top: 5px; + margin-bottom: 5px; +} + .mes_text br, .mes_bias br { content: ' '; From 24300642dd6cdf678b9da03bf2b88874f0d00ac2 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 5 Oct 2024 19:48:20 +0300 Subject: [PATCH 4/7] Cleaner HTML Diff --- public/scripts/templates/welcome.html | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/public/scripts/templates/welcome.html b/public/scripts/templates/welcome.html index eaf49b986..202609012 100644 --- a/public/scripts/templates/welcome.html +++ b/public/scripts/templates/welcome.html @@ -57,9 +57,7 @@

Confused or lost?

  • - - click these - icons! + - click these icons!
  • Enter /? in the chat bar @@ -84,8 +82,7 @@
  • - + Contact the developers
  • From 1055f2e1b74c2f91afe3aa84d473010174d9a939 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 5 Oct 2024 20:09:54 +0300 Subject: [PATCH 5/7] Support more pairs of international quotes --- public/script.js | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/public/script.js b/public/script.js index 872932e63..6077b0b7c 100644 --- a/public/script.js +++ b/public/script.js @@ -2002,15 +2002,33 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san }); } - mes = mes.replace(/```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(".+?")|(\u201C.+?\u201D)/gm, function (match, p1, p2) { - if (p1) { - return '"' + p1.replace(/"/g, '') + '"'; - } else if (p2) { - return '“' + p2.replace(/\u201C|\u201D/g, '') + '”'; - } else { - return match; + mes = mes.replace( + /```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(".*?")|(\u201C.*?\u201D)|(\u00AB.*?\u00BB)|(\u300C.*?\u300D)|(\u300E.*?\u300F)|(\uFF02.*?\uFF02)/gm, + function (match, p1, p2, p3, p4, p5, p6) { + if (p1) { + // English double quotes + return `"${p1.slice(1, -1)}"`; + } else if (p2) { + // Curly double quotes “ ” + return `“${p2.slice(1, -1)}”`; + } else if (p3) { + // Guillemets « » + return `«${p3.slice(1, -1)}»`; + } else if (p4) { + // Corner brackets 「 」 + return `「${p4.slice(1, -1)}」`; + } else if (p5) { + // White corner brackets 『 』 + return `『${p5.slice(1, -1)}』`; + } else if (p6) { + // Fullwidth quotes " " + return `"${p6.slice(1, -1)}"`; + } else { + // Return the original match if no quotes are found + return match; + } } - }); + ); // Restore double quotes in tags if (!power_user.encode_tags) { From a5be8898527c2ded026fb1faa0f33c181050a457 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 5 Oct 2024 20:14:07 +0300 Subject: [PATCH 6/7] Extend quote list for TTS --- public/scripts/extensions/tts/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/extensions/tts/index.js b/public/scripts/extensions/tts/index.js index 802d51f9c..4c5314af0 100644 --- a/public/scripts/extensions/tts/index.js +++ b/public/scripts/extensions/tts/index.js @@ -474,7 +474,7 @@ async function processTtsQueue() { } if (extension_settings.tts.narrate_quoted_only) { - const special_quotes = /[“”«»]/g; // Extend this regex to include other special quotes + const special_quotes = /[“”«»「」『』""]/g; // Extend this regex to include other special quotes text = text.replace(special_quotes, '"'); const matches = text.match(/".*?"/g); // Matches text inside double quotes, non-greedily const partJoiner = (ttsProvider?.separator || ' ... '); From 912525fdd9c546b57a1b818fa56744d999b2fa3e Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:13:01 +0300 Subject: [PATCH 7/7] Add missing import --- public/scripts/group-chats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index aebf565f6..237cd4021 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -70,12 +70,12 @@ import { animation_duration, depth_prompt_role_default, shouldAutoContinue, - this_chid, } from '../script.js'; import { printTagList, createTagMapFromList, applyTagsOnCharacterSelect, tag_map, applyTagsOnGroupSelect } from './tags.js'; import { FILTER_TYPES, FilterHelper } from './filters.js'; import { isExternalMediaAllowed } from './chats.js'; import { POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; +import { t } from './i18n.js'; export { selected_group,