mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-06 04:38:21 +01:00
Merge branch 'staging' into smol-tag-improvements
This commit is contained in:
commit
96f04a1c49
@ -220,7 +220,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.monospace {
|
.monospace {
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expander {
|
.expander {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
<link rel="preload" as="style" href="style.css">
|
<link rel="preload" as="style" href="style.css">
|
||||||
<link rel="manifest" crossorigin="use-credentials" href="manifest.json">
|
<link rel="manifest" crossorigin="use-credentials" href="manifest.json">
|
||||||
<link href="webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
<link href="webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
|
<link href="webfonts/NotoSansMono/stylesheet.css" rel="stylesheet">
|
||||||
<link href="css/fontawesome.min.css" rel="stylesheet">
|
<link href="css/fontawesome.min.css" rel="stylesheet">
|
||||||
<link href="css/solid.min.css" rel="stylesheet">
|
<link href="css/solid.min.css" rel="stylesheet">
|
||||||
<link href="css/brands.min.css" rel="stylesheet">
|
<link href="css/brands.min.css" rel="stylesheet">
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="css/login.css">
|
<link rel="stylesheet" type="text/css" href="css/login.css">
|
||||||
<link rel="manifest" crossorigin="use-credentials" href="manifest.json">
|
<link rel="manifest" crossorigin="use-credentials" href="manifest.json">
|
||||||
<link href="webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
<link href="webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
|
<link href="webfonts/NotoSansMono/stylesheet.css" rel="stylesheet">
|
||||||
<!-- fontawesome webfonts-->
|
<!-- fontawesome webfonts-->
|
||||||
<link href="css/fontawesome.min.css" rel="stylesheet">
|
<link href="css/fontawesome.min.css" rel="stylesheet">
|
||||||
<link href="css/solid.min.css" rel="stylesheet">
|
<link href="css/solid.min.css" rel="stylesheet">
|
||||||
|
@ -764,8 +764,19 @@ const per_page_default = 50;
|
|||||||
|
|
||||||
var is_advanced_char_open = false;
|
var is_advanced_char_open = false;
|
||||||
|
|
||||||
export let menu_type = ''; //what is selected in the menu
|
/**
|
||||||
|
* The type of the right menu
|
||||||
|
* @typedef {'characters' | 'character_edit' | 'create' | 'group_edit' | 'group_create' | '' } MenuType
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the right menu that is currently open
|
||||||
|
* @type {MenuType}
|
||||||
|
*/
|
||||||
|
export let menu_type = '';
|
||||||
|
|
||||||
export let selected_button = ''; //which button pressed
|
export let selected_button = ''; //which button pressed
|
||||||
|
|
||||||
//create pole save
|
//create pole save
|
||||||
let create_save = {
|
let create_save = {
|
||||||
name: '',
|
name: '',
|
||||||
@ -5432,8 +5443,14 @@ export function resetChatState() {
|
|||||||
characters.length = 0;
|
characters.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {'characters' | 'character_edit' | 'create' | 'group_edit' | 'group_create'} value
|
||||||
|
*/
|
||||||
export function setMenuType(value) {
|
export function setMenuType(value) {
|
||||||
menu_type = value;
|
menu_type = value;
|
||||||
|
// Allow custom CSS to see which menu type is active
|
||||||
|
document.getElementById('right-nav-panel').dataset.menuType = menu_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setExternalAbortController(controller) {
|
export function setExternalAbortController(controller) {
|
||||||
@ -6815,7 +6832,7 @@ export function select_selected_character(chid) {
|
|||||||
//character select
|
//character select
|
||||||
//console.log('select_selected_character() -- starting with input of -- ' + chid + ' (name:' + characters[chid].name + ')');
|
//console.log('select_selected_character() -- starting with input of -- ' + chid + ' (name:' + characters[chid].name + ')');
|
||||||
select_rm_create();
|
select_rm_create();
|
||||||
menu_type = 'character_edit';
|
setMenuType('character_edit');
|
||||||
$('#delete_button').css('display', 'flex');
|
$('#delete_button').css('display', 'flex');
|
||||||
$('#export_button').css('display', 'flex');
|
$('#export_button').css('display', 'flex');
|
||||||
var display_name = characters[chid].name;
|
var display_name = characters[chid].name;
|
||||||
@ -6891,7 +6908,7 @@ export function select_selected_character(chid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function select_rm_create() {
|
function select_rm_create() {
|
||||||
menu_type = 'create';
|
setMenuType('create');
|
||||||
|
|
||||||
//console.log('select_rm_Create() -- selected button: '+selected_button);
|
//console.log('select_rm_Create() -- selected button: '+selected_button);
|
||||||
if (selected_button == 'create') {
|
if (selected_button == 'create') {
|
||||||
@ -6952,7 +6969,7 @@ function select_rm_create() {
|
|||||||
|
|
||||||
function select_rm_characters() {
|
function select_rm_characters() {
|
||||||
const doFullRefresh = menu_type === 'characters';
|
const doFullRefresh = menu_type === 'characters';
|
||||||
menu_type = 'characters';
|
setMenuType('characters');
|
||||||
selectRightMenuWithAnimation('rm_characters_block');
|
selectRightMenuWithAnimation('rm_characters_block');
|
||||||
printCharacters(doFullRefresh);
|
printCharacters(doFullRefresh);
|
||||||
}
|
}
|
||||||
@ -8978,7 +8995,6 @@ jQuery(async function () {
|
|||||||
|
|
||||||
$('#rm_button_settings').click(function () {
|
$('#rm_button_settings').click(function () {
|
||||||
selected_button = 'settings';
|
selected_button = 'settings';
|
||||||
menu_type = 'settings';
|
|
||||||
selectRightMenuWithAnimation('rm_api_block');
|
selectRightMenuWithAnimation('rm_api_block');
|
||||||
});
|
});
|
||||||
$('#rm_button_characters').click(function () {
|
$('#rm_button_characters').click(function () {
|
||||||
|
@ -685,6 +685,23 @@ class PromptManager {
|
|||||||
this.log('Initialized');
|
this.log('Initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the scroll position of the prompt manager
|
||||||
|
* @returns {number} - Scroll position of the prompt manager
|
||||||
|
*/
|
||||||
|
#getScrollPosition() {
|
||||||
|
return document.getElementById(this.configuration.prefix + 'prompt_manager')?.closest('.scrollableInner')?.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scroll position of the prompt manager
|
||||||
|
* @param {number} scrollPosition - The scroll position to set
|
||||||
|
*/
|
||||||
|
#setScrollPosition(scrollPosition) {
|
||||||
|
if (scrollPosition === undefined || scrollPosition === null) return;
|
||||||
|
document.getElementById(this.configuration.prefix + 'prompt_manager')?.closest('.scrollableInner')?.scrollTo(0, scrollPosition);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main rendering function
|
* Main rendering function
|
||||||
*
|
*
|
||||||
@ -703,17 +720,21 @@ class PromptManager {
|
|||||||
this.tryGenerate().finally(async () => {
|
this.tryGenerate().finally(async () => {
|
||||||
this.profileEnd('filling context');
|
this.profileEnd('filling context');
|
||||||
this.profileStart('render');
|
this.profileStart('render');
|
||||||
|
const scrollPosition = this.#getScrollPosition();
|
||||||
await this.renderPromptManager();
|
await this.renderPromptManager();
|
||||||
await this.renderPromptManagerListItems();
|
await this.renderPromptManagerListItems();
|
||||||
this.makeDraggable();
|
this.makeDraggable();
|
||||||
|
this.#setScrollPosition(scrollPosition);
|
||||||
this.profileEnd('render');
|
this.profileEnd('render');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Executed during live communication
|
// Executed during live communication
|
||||||
this.profileStart('render');
|
this.profileStart('render');
|
||||||
|
const scrollPosition = this.#getScrollPosition();
|
||||||
await this.renderPromptManager();
|
await this.renderPromptManager();
|
||||||
await this.renderPromptManagerListItems();
|
await this.renderPromptManagerListItems();
|
||||||
this.makeDraggable();
|
this.makeDraggable();
|
||||||
|
this.#setScrollPosition(scrollPosition);
|
||||||
this.profileEnd('render');
|
this.profileEnd('render');
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
@ -482,8 +482,8 @@ export class AutoComplete {
|
|||||||
this.domWrap.style.setProperty('--leftOffset', `max(1vw, ${rect[power_user.stscript.autocomplete.width.left].left}px)`);
|
this.domWrap.style.setProperty('--leftOffset', `max(1vw, ${rect[power_user.stscript.autocomplete.width.left].left}px)`);
|
||||||
this.domWrap.style.setProperty('--rightOffset', `calc(100vw - min(99vw, ${rect[power_user.stscript.autocomplete.width.right].right}px)`);
|
this.domWrap.style.setProperty('--rightOffset', `calc(100vw - min(99vw, ${rect[power_user.stscript.autocomplete.width.right].right}px)`);
|
||||||
}
|
}
|
||||||
this.updateDetailsPosition();
|
|
||||||
}
|
}
|
||||||
|
this.updateDetailsPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,10 +29,14 @@
|
|||||||
<input type="checkbox" id="qr--modal-executeShortcut">
|
<input type="checkbox" id="qr--modal-executeShortcut">
|
||||||
<span>Ctrl+Enter to execute</span>
|
<span>Ctrl+Enter to execute</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="checkbox_label">
|
||||||
|
<input type="checkbox" id="qr--modal-syntax">
|
||||||
|
<span>Syntax highlight</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="qr--modal-messageHolder">
|
<div id="qr--modal-messageHolder">
|
||||||
<pre id="qr--modal-messageSyntax"><code id="qr--modal-messageSyntaxInner" class="hljs language-stscript"></code></pre>
|
<pre id="qr--modal-messageSyntax"><code id="qr--modal-messageSyntaxInner" class="hljs language-stscript"></code></pre>
|
||||||
<textarea class="monospace" id="qr--modal-message" spellcheck="false"></textarea>
|
<textarea id="qr--modal-message" spellcheck="false"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -264,6 +264,13 @@ export class QuickReply {
|
|||||||
const updateSyntax = ()=>{
|
const updateSyntax = ()=>{
|
||||||
messageSyntaxInner.innerHTML = hljs.highlight(`${message.value}${message.value.slice(-1) == '\n' ? ' ' : ''}`, { language:'stscript', ignoreIllegals:true })?.value;
|
messageSyntaxInner.innerHTML = hljs.highlight(`${message.value}${message.value.slice(-1) == '\n' ? ' ' : ''}`, { language:'stscript', ignoreIllegals:true })?.value;
|
||||||
};
|
};
|
||||||
|
const updateSyntaxEnabled = ()=>{
|
||||||
|
if (JSON.parse(localStorage.getItem('qr--syntax'))) {
|
||||||
|
dom.querySelector('#qr--modal-messageHolder').classList.remove('qr--noSyntax');
|
||||||
|
} else {
|
||||||
|
dom.querySelector('#qr--modal-messageHolder').classList.add('qr--noSyntax');
|
||||||
|
}
|
||||||
|
};
|
||||||
/**@type {HTMLInputElement}*/
|
/**@type {HTMLInputElement}*/
|
||||||
const tabSize = dom.querySelector('#qr--modal-tabSize');
|
const tabSize = dom.querySelector('#qr--modal-tabSize');
|
||||||
tabSize.value = JSON.parse(localStorage.getItem('qr--tabSize') ?? '4');
|
tabSize.value = JSON.parse(localStorage.getItem('qr--tabSize') ?? '4');
|
||||||
@ -282,6 +289,13 @@ export class QuickReply {
|
|||||||
executeShortcut.addEventListener('click', () => {
|
executeShortcut.addEventListener('click', () => {
|
||||||
localStorage.setItem('qr--executeShortcut', JSON.stringify(executeShortcut.checked));
|
localStorage.setItem('qr--executeShortcut', JSON.stringify(executeShortcut.checked));
|
||||||
});
|
});
|
||||||
|
/**@type {HTMLInputElement}*/
|
||||||
|
const syntax = dom.querySelector('#qr--modal-syntax');
|
||||||
|
syntax.checked = JSON.parse(localStorage.getItem('qr--syntax') ?? 'true');
|
||||||
|
syntax.addEventListener('click', () => {
|
||||||
|
localStorage.setItem('qr--syntax', JSON.stringify(syntax.checked));
|
||||||
|
updateSyntaxEnabled();
|
||||||
|
});
|
||||||
/**@type {HTMLTextAreaElement}*/
|
/**@type {HTMLTextAreaElement}*/
|
||||||
const message = dom.querySelector('#qr--modal-message');
|
const message = dom.querySelector('#qr--modal-message');
|
||||||
message.value = this.message;
|
message.value = this.message;
|
||||||
@ -352,8 +366,7 @@ export class QuickReply {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.addEventListener('resize', resizeListener);
|
window.addEventListener('resize', resizeListener);
|
||||||
message.style.color = 'transparent';
|
updateSyntaxEnabled();
|
||||||
message.style.background = 'transparent';
|
|
||||||
message.style.setProperty('text-shadow', 'none', 'important');
|
message.style.setProperty('text-shadow', 'none', 'important');
|
||||||
/**@type {HTMLElement}*/
|
/**@type {HTMLElement}*/
|
||||||
const messageSyntaxInner = dom.querySelector('#qr--modal-messageSyntaxInner');
|
const messageSyntaxInner = dom.querySelector('#qr--modal-messageSyntaxInner');
|
||||||
|
@ -301,6 +301,22 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder.qr--noSyntax > #qr--modal-messageSyntax {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder.qr--noSyntax > #qr--modal-message {
|
||||||
|
background-color: var(--ac-style-color-background);
|
||||||
|
color: var(--ac-style-color-text);
|
||||||
|
}
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder.qr--noSyntax > #qr--modal-message::selection {
|
||||||
|
color: unset;
|
||||||
|
background-color: rgba(108 171 251 / 0.25);
|
||||||
|
}
|
||||||
|
@supports (color: rgb(from white r g b / 0.25)) {
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder.qr--noSyntax > #qr--modal-message::selection {
|
||||||
|
background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax {
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
@ -315,18 +331,30 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message {
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message {
|
||||||
|
background-color: transparent;
|
||||||
|
color: transparent;
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
caret-color: white;
|
caret-color: var(--ac-style-color-text);
|
||||||
mix-blend-mode: difference;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar,
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar,
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar-thumb {
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar-thumb {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::selection {
|
||||||
|
color: transparent;
|
||||||
|
background-color: rgba(108 171 251 / 0.25);
|
||||||
|
}
|
||||||
|
@supports (color: rgb(from white r g b / 0.25)) {
|
||||||
|
.dialogue_popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::selection {
|
||||||
|
background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-message,
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-message,
|
||||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-messageSyntaxInner {
|
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-messageSyntaxInner {
|
||||||
|
font-family: var(--monoFontFamily);
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -322,6 +322,22 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
&.qr--noSyntax {
|
||||||
|
> #qr--modal-messageSyntax {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
> #qr--modal-message {
|
||||||
|
background-color: var(--ac-style-color-background);
|
||||||
|
color: var(--ac-style-color-text);
|
||||||
|
&::selection {
|
||||||
|
color: unset;
|
||||||
|
background-color: rgba(108 171 251 / 0.25);
|
||||||
|
@supports (color: rgb(from white r g b / 0.25)) {
|
||||||
|
background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
> #qr--modal-messageSyntax {
|
> #qr--modal-messageSyntax {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
@ -336,16 +352,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
> #qr--modal-message {
|
> #qr--modal-message {
|
||||||
|
background-color: transparent;
|
||||||
|
color: transparent;
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
caret-color: white;
|
caret-color: var(--ac-style-color-text);
|
||||||
mix-blend-mode: difference;
|
overflow: auto;
|
||||||
&::-webkit-scrollbar, &::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar, &::-webkit-scrollbar-thumb {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
&::selection {
|
||||||
|
color: transparent;
|
||||||
|
background-color: rgba(108 171 251 / 0.25);
|
||||||
|
@supports (color: rgb(from white r g b / 0.25)) {
|
||||||
|
background-color: rgb(from var(--ac-style-color-matchedText) r g b / 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#qr--modal-message, #qr--modal-messageSyntaxInner {
|
#qr--modal-message, #qr--modal-messageSyntaxInner {
|
||||||
|
font-family: var(--monoFontFamily);
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -16,6 +16,7 @@ import { SlashCommand } from '../../slash-commands/SlashCommand.js';
|
|||||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
|
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
|
||||||
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
||||||
import { splitRecursive } from '../../utils.js';
|
import { splitRecursive } from '../../utils.js';
|
||||||
|
import { renderTemplateAsync } from '../../templates.js';
|
||||||
|
|
||||||
export const autoModeOptions = {
|
export const autoModeOptions = {
|
||||||
NONE: 'none',
|
NONE: 'none',
|
||||||
@ -340,6 +341,34 @@ async function translateProviderBing(text, lang) {
|
|||||||
throw new Error(response.statusText);
|
throw new Error(response.statusText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates text using the Yandex Translate API
|
||||||
|
* @param {string} text Text to translate
|
||||||
|
* @param {string} lang Target language code
|
||||||
|
* @returns {Promise<string>} Translated text
|
||||||
|
*/
|
||||||
|
async function translateProviderYandex(text, lang) {
|
||||||
|
let chunks = [];
|
||||||
|
const chunkSize = 5000;
|
||||||
|
if (text.length <= chunkSize) {
|
||||||
|
chunks.push(text);
|
||||||
|
} else {
|
||||||
|
chunks = splitRecursive(text, chunkSize);
|
||||||
|
}
|
||||||
|
const response = await fetch('/api/translate/yandex', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: getRequestHeaders(),
|
||||||
|
body: JSON.stringify({ chunks: chunks, lang: lang }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result = await response.text();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(response.statusText);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits text into chunks and translates each chunk separately
|
* Splits text into chunks and translates each chunk separately
|
||||||
* @param {string} text Text to translate
|
* @param {string} text Text to translate
|
||||||
@ -389,6 +418,8 @@ async function translate(text, lang) {
|
|||||||
return await translateProviderOneRing(text, lang);
|
return await translateProviderOneRing(text, lang);
|
||||||
case 'bing':
|
case 'bing':
|
||||||
return await chunkedTranslate(text, lang, translateProviderBing, 1000);
|
return await chunkedTranslate(text, lang, translateProviderBing, 1000);
|
||||||
|
case 'yandex':
|
||||||
|
return await translateProviderYandex(text, lang);
|
||||||
default:
|
default:
|
||||||
console.error('Unknown translation provider', extension_settings.translate.provider);
|
console.error('Unknown translation provider', extension_settings.translate.provider);
|
||||||
return text;
|
return text;
|
||||||
@ -532,56 +563,10 @@ const handleMessageEdit = createEventHandler(translateMessageEdit, () => true);
|
|||||||
|
|
||||||
window['translate'] = translate;
|
window['translate'] = translate;
|
||||||
|
|
||||||
jQuery(() => {
|
jQuery(async() => {
|
||||||
const html = `
|
const html = await renderTemplateAsync('translateIndex');
|
||||||
<div class="translation_settings">
|
|
||||||
<div class="inline-drawer">
|
|
||||||
<div class="inline-drawer-toggle inline-drawer-header">
|
|
||||||
<b>Chat Translation</b>
|
|
||||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
|
||||||
</div>
|
|
||||||
<div class="inline-drawer-content">
|
|
||||||
<label for="translation_auto_mode" class="checkbox_label">Auto-mode</label>
|
|
||||||
<select id="translation_auto_mode">
|
|
||||||
<option value="none">None</option>
|
|
||||||
<option value="responses">Translate responses</option>
|
|
||||||
<option value="inputs">Translate inputs</option>
|
|
||||||
<option value="both">Translate both</option>
|
|
||||||
</select>
|
|
||||||
<label for="translation_provider">Provider</label>
|
|
||||||
<div class="flex-container gap5px flexnowrap marginBot5">
|
|
||||||
<select id="translation_provider" name="provider" class="margin0">
|
|
||||||
<option value="libre">Libre</option>
|
|
||||||
<option value="google">Google</option>
|
|
||||||
<option value="lingva">Lingva</option>
|
|
||||||
<option value="deepl">DeepL</option>
|
|
||||||
<option value="deeplx">DeepLX</option>
|
|
||||||
<option value="bing">Bing</option>
|
|
||||||
<option value="oneringtranslator">OneRingTranslator</option>
|
|
||||||
<select>
|
|
||||||
<div id="translate_key_button" class="menu_button fa-solid fa-key margin0"></div>
|
|
||||||
<div id="translate_url_button" class="menu_button fa-solid fa-link margin0"></div>
|
|
||||||
</div>
|
|
||||||
<label for="translation_target_language">Target Language</label>
|
|
||||||
<select id="translation_target_language" name="target_language"></select>
|
|
||||||
<div id="translation_clear" class="menu_button">
|
|
||||||
<i class="fa-solid fa-trash-can"></i>
|
|
||||||
<span>Clear Translations</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
const buttonHtml = `
|
const buttonHtml = await renderTemplateAsync('translateButtons');
|
||||||
<div id="translate_chat" class="list-group-item flex-container flexGap5">
|
|
||||||
<div class="fa-solid fa-language extensionsMenuExtensionButton" /></div>
|
|
||||||
Translate Chat
|
|
||||||
</div>
|
|
||||||
<div id="translate_input_message" class="list-group-item flex-container flexGap5">
|
|
||||||
<div class="fa-solid fa-keyboard extensionsMenuExtensionButton" /></div>
|
|
||||||
Translate Input
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
$('#extensionsMenu').append(buttonHtml);
|
$('#extensionsMenu').append(buttonHtml);
|
||||||
$('#extensions_settings2').append(html);
|
$('#extensions_settings2').append(html);
|
||||||
$('#translate_chat').on('click', onTranslateChatClick);
|
$('#translate_chat').on('click', onTranslateChatClick);
|
||||||
@ -624,7 +609,7 @@ jQuery(() => {
|
|||||||
'libre': 'http://127.0.0.1:5000/translate',
|
'libre': 'http://127.0.0.1:5000/translate',
|
||||||
'lingva': 'https://lingva.ml/api/v1',
|
'lingva': 'https://lingva.ml/api/v1',
|
||||||
'oneringtranslator': 'http://127.0.0.1:4990/translate',
|
'oneringtranslator': 'http://127.0.0.1:4990/translate',
|
||||||
'deeplx': 'http://127.0.0.1:1188/translate',
|
'deeplx': 'http://127.0.0.1:1188/translate'
|
||||||
};
|
};
|
||||||
const popupText = `<h3>${optionText} API URL</h3><i>Example: <tt>${String(exampleURLs[extension_settings.translate.provider])}</tt></i>`;
|
const popupText = `<h3>${optionText} API URL</h3><i>Example: <tt>${String(exampleURLs[extension_settings.translate.provider])}</tt></i>`;
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ class SBVits2TtsProvider {
|
|||||||
* @returns {string} Processed text
|
* @returns {string} Processed text
|
||||||
*/
|
*/
|
||||||
processText(text) {
|
processText(text) {
|
||||||
|
// backup for auto_split
|
||||||
|
text = text.replace(/\n+/g, '<br>');
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +278,8 @@ class SBVits2TtsProvider {
|
|||||||
|
|
||||||
const [model_id, speaker_id, style] = voiceId.split('-');
|
const [model_id, speaker_id, style] = voiceId.split('-');
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
// restore for auto_split
|
||||||
|
inputText = inputText.replaceAll('<br>', '\n');
|
||||||
params.append('text', inputText);
|
params.append('text', inputText);
|
||||||
params.append('model_id', model_id);
|
params.append('model_id', model_id);
|
||||||
params.append('speaker_id', speaker_id);
|
params.append('speaker_id', speaker_id);
|
||||||
|
@ -84,15 +84,21 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
|||||||
helpString: 'Get help on macros, chat formatting and commands.',
|
helpString: 'Get help on macros, chat formatting and commands.',
|
||||||
}));
|
}));
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'name',
|
name: 'persona',
|
||||||
callback: setNameCallback,
|
callback: setNameCallback,
|
||||||
unnamedArgumentList: [
|
namedArgumentList: [
|
||||||
new SlashCommandArgument(
|
new SlashCommandNamedArgument(
|
||||||
'persona', [ARGUMENT_TYPE.STRING], true,
|
'mode', 'The mode for persona selection. ("lookup" = search for existing persona, "temp" = create a temporary name, set a temporary name, "all" = allow both in the same command)',
|
||||||
|
[ARGUMENT_TYPE.STRING], false, false, 'all', ['lookup', 'temp', 'all'],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
helpString: 'Sets user name and persona avatar (if set).',
|
unnamedArgumentList: [
|
||||||
aliases: ['persona'],
|
new SlashCommandArgument(
|
||||||
|
'persona name', [ARGUMENT_TYPE.STRING], true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
helpString: 'Selects the given persona with its name and avatar (by name or avatar url). If no matching persona exists, applies a temporary name.',
|
||||||
|
aliases: ['name'],
|
||||||
}));
|
}));
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'sync',
|
name: 'sync',
|
||||||
@ -2372,26 +2378,44 @@ function setFlatModeCallback() {
|
|||||||
$('#chat_display').val(chat_styles.DEFAULT).trigger('change');
|
$('#chat_display').val(chat_styles.DEFAULT).trigger('change');
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNameCallback(_, name) {
|
/**
|
||||||
|
* Sets a persona name and optionally an avatar.
|
||||||
|
* @param {{mode: 'lookup' | 'temp' | 'all'}} namedArgs Named arguments
|
||||||
|
* @param {string} name Name to set
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function setNameCallback({ mode = 'all' }, name) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
toastr.warning('you must specify a name to change to');
|
toastr.warning('You must specify a name to change to');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!['lookup', 'temp', 'all'].includes(mode)) {
|
||||||
|
toastr.warning('Mode must be one of "lookup", "temp" or "all"');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = name.trim();
|
name = name.trim();
|
||||||
|
|
||||||
// If the name is a persona, auto-select it
|
// If the name matches a persona avatar, or a name, auto-select it
|
||||||
for (let persona of Object.values(power_user.personas)) {
|
if (['lookup', 'all'].includes(mode)) {
|
||||||
if (persona.toLowerCase() === name.toLowerCase()) {
|
let persona = Object.entries(power_user.personas).find(([avatar, _]) => avatar === name)?.[1];
|
||||||
autoSelectPersona(name);
|
if (!persona) persona = Object.entries(power_user.personas).find(([_, personaName]) => personaName.toLowerCase() === name.toLowerCase())?.[1];
|
||||||
|
if (persona) {
|
||||||
|
autoSelectPersona(persona);
|
||||||
retriggerFirstMessageOnEmptyChat();
|
retriggerFirstMessageOnEmptyChat();
|
||||||
return;
|
return;
|
||||||
|
} else if (mode === 'lookup') {
|
||||||
|
toastr.warning(`Persona ${name} not found`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, set just the name
|
if (['temp', 'all'].includes(mode)) {
|
||||||
setUserName(name); //this prevented quickReply usage
|
// Otherwise, set just the name
|
||||||
retriggerFirstMessageOnEmptyChat();
|
setUserName(name); //this prevented quickReply usage
|
||||||
|
retriggerFirstMessageOnEmptyChat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setNarratorName(_, text) {
|
async function setNarratorName(_, text) {
|
||||||
|
8
public/scripts/templates/translateButtons.html
Normal file
8
public/scripts/templates/translateButtons.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<div id="translate_chat" class="list-group-item flex-container flexGap5">
|
||||||
|
<div class="fa-solid fa-language extensionsMenuExtensionButton" /></div>
|
||||||
|
<span data-i18n="ext_translate_btn_chat">Translate Chat</span>
|
||||||
|
</div>
|
||||||
|
<div id="translate_input_message" class="list-group-item flex-container flexGap5">
|
||||||
|
<div class="fa-solid fa-keyboard extensionsMenuExtensionButton" /></div>
|
||||||
|
<span data-i18n="ext_translate_btn_input">Translate Input</span>
|
||||||
|
</div>
|
38
public/scripts/templates/translateIndex.html
Normal file
38
public/scripts/templates/translateIndex.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<div class="translation_settings">
|
||||||
|
<div class="inline-drawer">
|
||||||
|
<div class="inline-drawer-toggle inline-drawer-header">
|
||||||
|
<b data-i18n="Chat Translation">Chat Translation</b>
|
||||||
|
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inline-drawer-content">
|
||||||
|
<label for="translation_auto_mode" class="checkbox_label" data-i18n="ext_translate_auto_mode">Auto-mode</label>
|
||||||
|
<select id="translation_auto_mode">
|
||||||
|
<option data-i18n="ext_translate_mode_none" value="none">None</option>
|
||||||
|
<option data-i18n="ext_translate_mode_responses" value="responses">Translate responses</option>
|
||||||
|
<option data-i18n="ext_translate_mode_inputs" value="inputs">Translate inputs</option>
|
||||||
|
<option data-i18n="ext_translate_mode_both" value="both">Translate both</option>
|
||||||
|
</select>
|
||||||
|
<label data-i18n="ext_translate_mode_provider" for="translation_provider">Provider</label>
|
||||||
|
<div class="flex-container gap5px flexnowrap marginBot5">
|
||||||
|
<select id="translation_provider" name="provider" class="margin0">
|
||||||
|
<option value="libre">Libre</option>
|
||||||
|
<option value="google">Google</option>
|
||||||
|
<option value="lingva">Lingva</option>
|
||||||
|
<option value="deepl">DeepL</option>
|
||||||
|
<option value="deeplx">DeepLX</option>
|
||||||
|
<option value="bing">Bing</option>
|
||||||
|
<option value="oneringtranslator">OneRingTranslator</option>
|
||||||
|
<option value="yandex">Yandex</option>
|
||||||
|
<select>
|
||||||
|
<div id="translate_key_button" class="menu_button fa-solid fa-key margin0"></div>
|
||||||
|
<div id="translate_url_button" class="menu_button fa-solid fa-link margin0"></div>
|
||||||
|
</div>
|
||||||
|
<label data-i18n="ext_translate_target_lang" for="translation_target_language">Target Language</label>
|
||||||
|
<select id="translation_target_language" name="target_language"></select>
|
||||||
|
<div id="translation_clear" class="menu_button">
|
||||||
|
<i class="fa-solid fa-trash-can"></i>
|
||||||
|
<span data-i18n="ext_translate_clear">Clear Translations</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -495,14 +495,16 @@ export function trimToEndSentence(input, include_newline = false) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isEmoji = x => /(\p{Emoji_Presentation}|\p{Extended_Pictographic})/gu.test(x);
|
||||||
const punctuation = new Set(['.', '!', '?', '*', '"', ')', '}', '`', ']', '$', '。', '!', '?', '”', ')', '】', '’', '」', '_']); // extend this as you see fit
|
const punctuation = new Set(['.', '!', '?', '*', '"', ')', '}', '`', ']', '$', '。', '!', '?', '”', ')', '】', '’', '」', '_']); // extend this as you see fit
|
||||||
let last = -1;
|
let last = -1;
|
||||||
|
|
||||||
for (let i = input.length - 1; i >= 0; i--) {
|
const characters = Array.from(input);
|
||||||
const char = input[i];
|
for (let i = characters.length - 1; i >= 0; i--) {
|
||||||
|
const char = characters[i];
|
||||||
|
|
||||||
if (punctuation.has(char)) {
|
if (punctuation.has(char) || isEmoji(char)) {
|
||||||
if (i > 0 && /[\s\n]/.test(input[i - 1])) {
|
if (i > 0 && /[\s\n]/.test(characters[i - 1])) {
|
||||||
last = i - 1;
|
last = i - 1;
|
||||||
} else {
|
} else {
|
||||||
last = i;
|
last = i;
|
||||||
@ -520,7 +522,7 @@ export function trimToEndSentence(input, include_newline = false) {
|
|||||||
return input.trimEnd();
|
return input.trimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
return input.substring(0, last + 1).trimEnd();
|
return characters.slice(0, last + 1).join('').trimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trimToStartSentence(input) {
|
export function trimToStartSentence(input) {
|
||||||
@ -1275,6 +1277,9 @@ export async function waitUntilCondition(condition, timeout = 1000, interval = 1
|
|||||||
* uuidv4(); // '3e2fd9e1-0a7a-4f6d-9aaf-8a7a4babe7eb'
|
* uuidv4(); // '3e2fd9e1-0a7a-4f6d-9aaf-8a7a4babe7eb'
|
||||||
*/
|
*/
|
||||||
export function uuidv4() {
|
export function uuidv4() {
|
||||||
|
if ('randomUUID' in crypto) {
|
||||||
|
return crypto.randomUUID();
|
||||||
|
}
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
const r = Math.random() * 16 | 0;
|
const r = Math.random() * 16 | 0;
|
||||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
--fontScale: 1;
|
--fontScale: 1;
|
||||||
--mainFontSize: calc(var(--fontScale) * 15px);
|
--mainFontSize: calc(var(--fontScale) * 15px);
|
||||||
--mainFontFamily: "Noto Sans", "Noto Color Emoji", sans-serif;
|
--mainFontFamily: "Noto Sans", "Noto Color Emoji", sans-serif;
|
||||||
|
--monoFontFamily: 'Noto Sans Mono', 'Courier New', Consolas, monospace;
|
||||||
|
|
||||||
/* base variable for blur strength slider calculations */
|
/* base variable for blur strength slider calculations */
|
||||||
--blurStrength: 10;
|
--blurStrength: 10;
|
||||||
@ -444,7 +445,7 @@ small {
|
|||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: Consolas, monospace;
|
font-family: var(--monoFontFamily);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
/* word-wrap: break-word; */
|
/* word-wrap: break-word; */
|
||||||
border: 1px solid var(--SmartThemeBorderColor);
|
border: 1px solid var(--SmartThemeBorderColor);
|
||||||
@ -1248,6 +1249,7 @@ select {
|
|||||||
left: var(--leftOffset);
|
left: var(--leftOffset);
|
||||||
right: var(--rightOffset);
|
right: var(--rightOffset);
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
|
||||||
&.isFloating {
|
&.isFloating {
|
||||||
@ -1656,7 +1658,7 @@ body[data-stscript-style] .hljs.language-stscript {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
/* opacity: 0.6; */
|
/* opacity: 0.6; */
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
line-height: calc(1.2em / 0.8);
|
line-height: calc(1.2em / 0.8);
|
||||||
/* &:before { content: "["; }
|
/* &:before { content: "["; }
|
||||||
&:after { content: "]"; } */
|
&:after { content: "]"; } */
|
||||||
@ -1824,7 +1826,7 @@ body[data-stscript-style] .hljs.language-stscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
>.alias {
|
>.alias {
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
|
|
||||||
&+.alias:before {
|
&+.alias:before {
|
||||||
content: ', ';
|
content: ', ';
|
||||||
@ -1844,7 +1846,7 @@ body[data-stscript-style] .hljs.language-stscript {
|
|||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
|
|
||||||
>.name {
|
>.name {
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
/* color: var(--ac-color-text); */
|
/* color: var(--ac-color-text); */
|
||||||
}
|
}
|
||||||
@ -1853,7 +1855,7 @@ body[data-stscript-style] .hljs.language-stscript {
|
|||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
>.arguments {
|
>.arguments {
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
|
|
||||||
.argument {
|
.argument {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -1943,7 +1945,7 @@ body[data-stscript-style] .hljs.language-stscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
>.returns {
|
>.returns {
|
||||||
font-family: monospace;
|
font-family: var(--monoFontFamily);
|
||||||
color: var(--ac-color-text);
|
color: var(--ac-color-text);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-100.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-100.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-200.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-200.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-300.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-300.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-500.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-500.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-600.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-600.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-700.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-700.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-800.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-800.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-900.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-900.woff2
Normal file
Binary file not shown.
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-regular.woff2
Normal file
BIN
public/webfonts/NotoSansMono/noto-sans-mono-v30-regular.woff2
Normal file
Binary file not shown.
89
public/webfonts/NotoSansMono/stylesheet.css
Normal file
89
public/webfonts/NotoSansMono/stylesheet.css
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* noto-sans-mono-100 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
src: url('noto-sans-mono-v30-100.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-200 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 200;
|
||||||
|
src: url('noto-sans-mono-v30-200.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-300 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
src: url('noto-sans-mono-v30-300.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-regular - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('noto-sans-mono-v30-regular.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-500 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
src: url('noto-sans-mono-v30-500.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-600 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
src: url('noto-sans-mono-v30-600.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-700 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: url('noto-sans-mono-v30-700.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-800 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 800;
|
||||||
|
src: url('noto-sans-mono-v30-800.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* noto-sans-mono-900 - cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Noto Sans Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
src: url('noto-sans-mono-v30-900.woff2') format('woff2');
|
||||||
|
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
@ -2,7 +2,7 @@ const fetch = require('node-fetch').default;
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { readSecret, SECRET_KEYS } = require('./secrets');
|
const { readSecret, SECRET_KEYS } = require('./secrets');
|
||||||
const { getConfigValue } = require('../util');
|
const { getConfigValue, uuidv4 } = require('../util');
|
||||||
const { jsonParser } = require('../express-common');
|
const { jsonParser } = require('../express-common');
|
||||||
|
|
||||||
const DEEPLX_URL_DEFAULT = 'http://127.0.0.1:1188/translate';
|
const DEEPLX_URL_DEFAULT = 'http://127.0.0.1:1188/translate';
|
||||||
@ -102,6 +102,54 @@ router.post('/google', jsonParser, async (request, response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/yandex', jsonParser, async (request, response) => {
|
||||||
|
const chunks = request.body.chunks;
|
||||||
|
const lang = request.body.lang;
|
||||||
|
|
||||||
|
if (!chunks || !lang) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reconstruct original text to log
|
||||||
|
let inputText = '';
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
params.append('text', chunk);
|
||||||
|
inputText += chunk;
|
||||||
|
}
|
||||||
|
params.append('lang', lang);
|
||||||
|
const ucid = uuidv4().replaceAll('-', '');
|
||||||
|
|
||||||
|
console.log('Input text: ' + inputText);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: params,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
timeout: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
const error = await result.text();
|
||||||
|
console.log('Yandex error: ', result.statusText, error);
|
||||||
|
return response.sendStatus(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = await result.json();
|
||||||
|
const translated = json.text.join();
|
||||||
|
console.log('Translated text: ' + translated);
|
||||||
|
|
||||||
|
return response.send(translated);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Translation error: ' + error.message);
|
||||||
|
return response.sendStatus(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.post('/lingva', jsonParser, async (request, response) => {
|
router.post('/lingva', jsonParser, async (request, response) => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = readSecret(request.user.directories, SECRET_KEYS.LINGVA_URL);
|
const baseUrl = readSecret(request.user.directories, SECRET_KEYS.LINGVA_URL);
|
||||||
|
@ -293,7 +293,14 @@ const color = {
|
|||||||
white: (mess) => color.byNum(mess, 37),
|
white: (mess) => color.byNum(mess, 37),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a random UUIDv4 string.
|
||||||
|
* @returns {string} A UUIDv4 string
|
||||||
|
*/
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
|
if ('randomUUID' in crypto) {
|
||||||
|
return crypto.randomUUID();
|
||||||
|
}
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
const r = Math.random() * 16 | 0;
|
const r = Math.random() * 16 | 0;
|
||||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user