Add CodeMirror based Highlighted editor (#325)
# PR Checklist - [ ] Did you check if it works normally in all models? *ignore this when it dosen't uses models* - [ ] Did you check if it works normally in all of web, local and node hosted versions? if it dosen't, did you blocked it in those versions? - [ ] Did you added a type def? # Description  I have added an editor and settings that highlight asterisks, quotes, and backticks, similar to AutoMark, using a CodeMirror-based editor. 1. Added the CodeMirror5 package 2. Added language and settings for "useAdvancedEditor" 3. Wrote AdvancedChatEditor.svelte Thank you for your hard work on the project.
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
"blueimp-md5": "^2.19.0",
|
"blueimp-md5": "^2.19.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
"codemirror": "^5.65.16",
|
||||||
"core-js": "^3.35.0",
|
"core-js": "^3.35.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"crc": "^4.3.2",
|
"crc": "^4.3.2",
|
||||||
|
|||||||
@@ -403,4 +403,5 @@ export const languageChinese = {
|
|||||||
"appendNameNAI": "在NAI上附加名称",
|
"appendNameNAI": "在NAI上附加名称",
|
||||||
module: "模块",
|
module: "模块",
|
||||||
modules: "模块",
|
modules: "模块",
|
||||||
|
useAdvancedEditor: "使用高级编辑器",
|
||||||
}
|
}
|
||||||
@@ -432,4 +432,5 @@ export const languageGerman = {
|
|||||||
textAdventureNAI: "Als Textabenteuer ausführen",
|
textAdventureNAI: "Als Textabenteuer ausführen",
|
||||||
appendNameNAI: "Namen an NAI anhängen",
|
appendNameNAI: "Namen an NAI anhängen",
|
||||||
customStopWords: "Benutzerdefinierte Stoppwörter",
|
customStopWords: "Benutzerdefinierte Stoppwörter",
|
||||||
|
useAdvancedEditor: "Erweiterten Editor verwenden",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,4 +551,5 @@ export const languageEnglish = {
|
|||||||
popularityLevelDesc: "Popularity increases with downloads, etc. to estimate, 3.7 popularity is about 1 downloads.",
|
popularityLevelDesc: "Popularity increases with downloads, etc. to estimate, 3.7 popularity is about 1 downloads.",
|
||||||
additionalParams: "Additional Parameters",
|
additionalParams: "Additional Parameters",
|
||||||
heightMode: "Height Mode",
|
heightMode: "Height Mode",
|
||||||
|
useAdvancedEditor: "Use Advanced Editor",
|
||||||
}
|
}
|
||||||
@@ -432,4 +432,5 @@ export const languageKorean = {
|
|||||||
largePersonaPortrait: "페르소나 세로 이미지",
|
largePersonaPortrait: "페르소나 세로 이미지",
|
||||||
module: "모듈",
|
module: "모듈",
|
||||||
modules: "모듈",
|
modules: "모듈",
|
||||||
|
useAdvancedEditor: "고급 에디터 사용",
|
||||||
}
|
}
|
||||||
@@ -406,4 +406,5 @@ export const LanguageVietnamese = {
|
|||||||
"defaultPrompt": "Lời nhắc mặc định",
|
"defaultPrompt": "Lời nhắc mặc định",
|
||||||
module: "Mô-đun",
|
module: "Mô-đun",
|
||||||
modules: "Mô-đun",
|
modules: "Mô-đun",
|
||||||
|
useAdvancedEditor: "Sử dụng trình biên tập nâng cao",
|
||||||
}
|
}
|
||||||
163
src/lib/ChatScreens/AdvancedChatEditor.svelte
Normal file
163
src/lib/ChatScreens/AdvancedChatEditor.svelte
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<script>
|
||||||
|
import { onMount, createEventDispatcher } from 'svelte';
|
||||||
|
import { EditIcon, LanguagesIcon } from "lucide-svelte";
|
||||||
|
import { DataBase } from "../../ts/storage/database";
|
||||||
|
import CodeMirror from 'codemirror';
|
||||||
|
import 'codemirror/lib/codemirror.css';
|
||||||
|
|
||||||
|
export let value, translate;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
let toggleTranslate = !$DataBase.useAutoTranslateInput;
|
||||||
|
let velement, veditor;
|
||||||
|
let telement, teditor;
|
||||||
|
let _value = value;
|
||||||
|
let _translate = translate;
|
||||||
|
|
||||||
|
const markdowns = [
|
||||||
|
{
|
||||||
|
regex: /["“”](.*?)(["“”]|$)/gs,
|
||||||
|
className: "ci-quote",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regex: /`([^`]+)`/gs,
|
||||||
|
className: "ci-backtick",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regex: /\*\*\*([^*]+)(\*\*\*|$)/gs,
|
||||||
|
className: "ci-asterisk3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regex: /(?<!\*)\*\*([^*]+)(\*\*(?!\*)|$)/gs,
|
||||||
|
className: "ci-asterisk2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regex: /(?<!\*)\*([^*]+)(\*(?!\*)|$)/gs,
|
||||||
|
className: "ci-asterisk1",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
veditor = initEditor(velement, value);
|
||||||
|
teditor = initEditor(telement, translate);
|
||||||
|
veditor.on('change', (_, evt) => {
|
||||||
|
if(evt.origin != 'setValue' && !toggleTranslate) {
|
||||||
|
const input = veditor.getValue('\r\n');
|
||||||
|
if(input != value) {
|
||||||
|
value = _value = input;
|
||||||
|
dispatch('change', { translate: false, value: input });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
teditor.on('change', (_, evt) => {
|
||||||
|
if(evt.origin != 'setValue' && toggleTranslate) {
|
||||||
|
const input = teditor.getValue('\r\n');
|
||||||
|
if(input != translate) {
|
||||||
|
translate = _translate = input;
|
||||||
|
dispatch('change', { translate: true, value: input });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
toggleTranslateText();
|
||||||
|
});
|
||||||
|
|
||||||
|
$: if(value != _value) {
|
||||||
|
veditor.setValue(_value = value);
|
||||||
|
}
|
||||||
|
$: if(translate != _translate) {
|
||||||
|
teditor.setValue(_translate = translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTranslateText() {
|
||||||
|
toggleTranslate = !toggleTranslate;
|
||||||
|
if(toggleTranslate) {
|
||||||
|
velement.style.display = "none";
|
||||||
|
telement.style.display = null;
|
||||||
|
teditor.refresh();
|
||||||
|
} else {
|
||||||
|
velement.style.display = null;
|
||||||
|
telement.style.display = "none";
|
||||||
|
veditor.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditor(element, value) {
|
||||||
|
const editor = CodeMirror(element, {
|
||||||
|
lineNumbers: true,
|
||||||
|
value: value,
|
||||||
|
});
|
||||||
|
editor.on('change', (sender) => updateMarks(sender.doc));
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMarks(doc) {
|
||||||
|
const text = doc.getValue();
|
||||||
|
for (const mark of doc.getAllMarks()) {
|
||||||
|
mark.clear();
|
||||||
|
}
|
||||||
|
for(const markdown of markdowns) {
|
||||||
|
for (const match of text.matchAll(markdown.regex)) {
|
||||||
|
const start = doc.posFromIndex(match.index);
|
||||||
|
const end = doc.posFromIndex(match.index + match[0].length);
|
||||||
|
doc.markText(start, end, { className: markdown.className });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-1 items-end ml-2 mr-2">
|
||||||
|
{#if $DataBase.useAutoTranslateInput}
|
||||||
|
<button
|
||||||
|
on:click={toggleTranslateText}
|
||||||
|
class="mr-2 bg-textcolor2 flex justify-center items-center text-gray-100 w-12 h-12 rounded-md hover:bg-green-500 transition-colors">
|
||||||
|
{#if toggleTranslate}
|
||||||
|
<LanguagesIcon />
|
||||||
|
{:else}
|
||||||
|
<EditIcon />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="chatEditor" bind:this={velement}></div>
|
||||||
|
<div class="chatEditor" hidden bind:this={telement}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
.chatEditor {
|
||||||
|
display: table;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.CodeMirror) {
|
||||||
|
min-height: 2em;
|
||||||
|
height: auto;
|
||||||
|
background-color: var(--risu-theme-bgcolor);
|
||||||
|
color: #DD0;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.CodeMirror:focus-within) {
|
||||||
|
background-color: var(--risu-theme-textcolor2);
|
||||||
|
}
|
||||||
|
.chatEditor :global(.CodeMirror-gutters) {
|
||||||
|
background-color: var(--risu-theme-selected);
|
||||||
|
border-left-color: var(--risu-theme-borderc);
|
||||||
|
}
|
||||||
|
.chatEditor :global(.ci-quote) {
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.ci-backtick) {
|
||||||
|
color: #6AC;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.ci-asterisk3) {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
color: #E22;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.ci-asterisk2) {
|
||||||
|
font-style: italic;
|
||||||
|
color: #E84;
|
||||||
|
}
|
||||||
|
.chatEditor :global(.ci-asterisk1) {
|
||||||
|
font-style: italic;
|
||||||
|
color: #990;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Suggestion from './Suggestion.svelte';
|
import Suggestion from './Suggestion.svelte';
|
||||||
|
import AdvancedChatEditor from './AdvancedChatEditor.svelte';
|
||||||
import { CameraIcon, DatabaseIcon, DicesIcon, GlobeIcon, ImagePlusIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, PackageIcon, RefreshCcwIcon, ReplyIcon, Send, StepForwardIcon } from "lucide-svelte";
|
import { CameraIcon, DatabaseIcon, DicesIcon, GlobeIcon, ImagePlusIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, PackageIcon, RefreshCcwIcon, ReplyIcon, Send, StepForwardIcon } from "lucide-svelte";
|
||||||
import { CurrentCharacter, CurrentChat, CurrentUsername, selectedCharID, CurrentUserIcon, CurrentShowMemoryLimit,CurrentSimpleCharacter } from "../../ts/stores";
|
import { CurrentCharacter, CurrentChat, CurrentUsername, selectedCharID, CurrentUserIcon, CurrentShowMemoryLimit,CurrentSimpleCharacter } from "../../ts/stores";
|
||||||
import Chat from "./Chat.svelte";
|
import Chat from "./Chat.svelte";
|
||||||
@@ -385,6 +386,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div class="w-full h-full" style={customStyle} on:click={() => {
|
<div class="w-full h-full" style={customStyle} on:click={() => {
|
||||||
openMenu = false
|
openMenu = false
|
||||||
}}>
|
}}>
|
||||||
@@ -405,6 +407,8 @@
|
|||||||
<Laugh/>
|
<Laugh/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if !$DataBase.useAdvancedEditor}
|
||||||
<textarea class="text-textcolor p-2 min-w-0 bg-transparent input-text text-xl flex-grow ml-4 mr-2 border-darkbutton resize-none focus:bg-selected overflow-y-hidden overflow-x-hidden max-w-full"
|
<textarea class="text-textcolor p-2 min-w-0 bg-transparent input-text text-xl flex-grow ml-4 mr-2 border-darkbutton resize-none focus:bg-selected overflow-y-hidden overflow-x-hidden max-w-full"
|
||||||
bind:value={messageInput}
|
bind:value={messageInput}
|
||||||
bind:this={inputEle}
|
bind:this={inputEle}
|
||||||
@@ -423,6 +427,13 @@
|
|||||||
on:input={()=>{updateInputSizeAll();updateInputTransateMessage(false)}}
|
on:input={()=>{updateInputSizeAll();updateInputTransateMessage(false)}}
|
||||||
style:height={inputHeight}
|
style:height={inputHeight}
|
||||||
/>
|
/>
|
||||||
|
{:else}
|
||||||
|
<AdvancedChatEditor
|
||||||
|
bind:value={messageInput}
|
||||||
|
bind:translate={messageInputTranslate}
|
||||||
|
on:change={(e) => { updateInputTransateMessage(e.detail.translate);}}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
{#if $doingChat || doingChatInputTranslate}
|
{#if $doingChat || doingChatInputTranslate}
|
||||||
@@ -443,7 +454,7 @@
|
|||||||
class="mr-2 bg-textcolor2 flex justify-center items-center text-gray-100 w-12 h-12 rounded-md hover:bg-green-500 transition-colors"><MenuIcon />
|
class="mr-2 bg-textcolor2 flex justify-center items-center text-gray-100 w-12 h-12 rounded-md hover:bg-green-500 transition-colors"><MenuIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if $DataBase.useAutoTranslateInput}
|
{#if $DataBase.useAutoTranslateInput && !$DataBase.useAdvancedEditor}
|
||||||
<div class="flex items-center mt-2 mb-2">
|
<div class="flex items-center mt-2 mb-2">
|
||||||
<label for='messageInputTranslate' class="text-textcolor ml-4">
|
<label for='messageInputTranslate' class="text-textcolor ml-4">
|
||||||
<LanguagesIcon />
|
<LanguagesIcon />
|
||||||
|
|||||||
@@ -192,6 +192,10 @@
|
|||||||
<Check bind:check={$DataBase.roundIcons} name={language.roundIcons}/>
|
<Check bind:check={$DataBase.roundIcons} name={language.roundIcons}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center mt-2">
|
||||||
|
<Check bind:check={$DataBase.useAdvancedEditor} name={language.useAdvancedEditor}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if $DataBase.textScreenColor}
|
{#if $DataBase.textScreenColor}
|
||||||
<div class="flex items-center mt-2">
|
<div class="flex items-center mt-2">
|
||||||
<Check check={true} onChange={() => {
|
<Check check={true} onChange={() => {
|
||||||
|
|||||||
@@ -604,6 +604,7 @@ export interface Database{
|
|||||||
requestInfoInsideChat?:boolean
|
requestInfoInsideChat?:boolean
|
||||||
additionalParams:[string, string][]
|
additionalParams:[string, string][]
|
||||||
heightMode:string
|
heightMode:string
|
||||||
|
useAdvancedEditor:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface customscript{
|
export interface customscript{
|
||||||
|
|||||||
Reference in New Issue
Block a user