Add CodeMirror based Highlighted editor

This commit is contained in:
ModMapper
2024-03-23 18:41:36 +09:00
parent 2fe9ca2704
commit 580cd3e1a7
10 changed files with 187 additions and 2 deletions

View File

@@ -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",

View File

@@ -403,4 +403,5 @@ export const languageChinese = {
"appendNameNAI": "在NAI上附加名称", "appendNameNAI": "在NAI上附加名称",
module: "模块", module: "模块",
modules: "模块", modules: "模块",
useAdvancedEditor: "使用高级编辑器",
} }

View File

@@ -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",
} }

View File

@@ -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",
} }

View File

@@ -432,4 +432,5 @@ export const languageKorean = {
largePersonaPortrait: "페르소나 세로 이미지", largePersonaPortrait: "페르소나 세로 이미지",
module: "모듈", module: "모듈",
modules: "모듈", modules: "모듈",
useAdvancedEditor: "고급 에디터 사용",
} }

View File

@@ -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",
} }

View 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>

View File

@@ -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,9 +427,16 @@
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}
<div <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}> 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}> <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 /> 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 />

View File

@@ -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={() => {

View File

@@ -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{