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:
@@ -403,4 +403,5 @@ export const languageChinese = {
|
||||
"appendNameNAI": "在NAI上附加名称",
|
||||
module: "模块",
|
||||
modules: "模块",
|
||||
useAdvancedEditor: "使用高级编辑器",
|
||||
}
|
||||
@@ -432,4 +432,5 @@ export const languageGerman = {
|
||||
textAdventureNAI: "Als Textabenteuer ausführen",
|
||||
appendNameNAI: "Namen an NAI anhängen",
|
||||
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.",
|
||||
additionalParams: "Additional Parameters",
|
||||
heightMode: "Height Mode",
|
||||
useAdvancedEditor: "Use Advanced Editor",
|
||||
}
|
||||
@@ -432,4 +432,5 @@ export const languageKorean = {
|
||||
largePersonaPortrait: "페르소나 세로 이미지",
|
||||
module: "모듈",
|
||||
modules: "모듈",
|
||||
useAdvancedEditor: "고급 에디터 사용",
|
||||
}
|
||||
@@ -406,4 +406,5 @@ export const LanguageVietnamese = {
|
||||
"defaultPrompt": "Lời nhắc mặc định",
|
||||
module: "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">
|
||||
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 { CurrentCharacter, CurrentChat, CurrentUsername, selectedCharID, CurrentUserIcon, CurrentShowMemoryLimit,CurrentSimpleCharacter } from "../../ts/stores";
|
||||
import Chat from "./Chat.svelte";
|
||||
@@ -385,6 +386,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- 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={() => {
|
||||
openMenu = false
|
||||
}}>
|
||||
@@ -405,6 +407,8 @@
|
||||
<Laugh/>
|
||||
</div>
|
||||
{/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"
|
||||
bind:value={messageInput}
|
||||
bind:this={inputEle}
|
||||
@@ -423,9 +427,16 @@
|
||||
on:input={()=>{updateInputSizeAll();updateInputTransateMessage(false)}}
|
||||
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}
|
||||
<div
|
||||
class="mr-2 bg-selected flex justify-center items-center text-gray-100 w-12 h-12 rounded-md hover:bg-green-500 transition-colors" on:click={abortChat}>
|
||||
<div class="loadmove" class:autoload={autoMode}>
|
||||
@@ -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 />
|
||||
</div>
|
||||
</div>
|
||||
{#if $DataBase.useAutoTranslateInput}
|
||||
{#if $DataBase.useAutoTranslateInput && !$DataBase.useAdvancedEditor}
|
||||
<div class="flex items-center mt-2 mb-2">
|
||||
<label for='messageInputTranslate' class="text-textcolor ml-4">
|
||||
<LanguagesIcon />
|
||||
|
||||
@@ -192,6 +192,10 @@
|
||||
<Check bind:check={$DataBase.roundIcons} name={language.roundIcons}/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mt-2">
|
||||
<Check bind:check={$DataBase.useAdvancedEditor} name={language.useAdvancedEditor}/>
|
||||
</div>
|
||||
|
||||
{#if $DataBase.textScreenColor}
|
||||
<div class="flex items-center mt-2">
|
||||
<Check check={true} onChange={() => {
|
||||
|
||||
@@ -604,6 +604,7 @@ export interface Database{
|
||||
requestInfoInsideChat?:boolean
|
||||
additionalParams:[string, string][]
|
||||
heightMode:string
|
||||
useAdvancedEditor:boolean
|
||||
}
|
||||
|
||||
export interface customscript{
|
||||
|
||||
Reference in New Issue
Block a user