1
+ <script >
2
+ import { onMount , createEventDispatcher } from ' svelte' ;
3
+ import { EditIcon , LanguagesIcon } from " lucide-svelte" ;
4
+ import { DataBase } from " ../../ts/storage/database" ;
5
+ import CodeMirror from ' codemirror' ;
6
+ import ' codemirror/lib/codemirror.css' ;
7
+
8
+ export let value, translate;
9
+
10
+ const dispatch = createEventDispatcher ();
11
+ let toggleTranslate = ! $DataBase .useAutoTranslateInput ;
12
+ let velement, veditor;
13
+ let telement, teditor;
14
+ let _value = value;
15
+ let _translate = translate;
16
+
17
+ const markdowns = [
18
+ {
19
+ regex: / ["“”] (. *? )(["“”] | $ )/ gs ,
20
+ className: " ci-quote" ,
21
+ },
22
+ {
23
+ regex: / `([^ `] + )`/ gs ,
24
+ className: " ci-backtick" ,
25
+ },
26
+ {
27
+ regex: / \*\*\* ([^ *] + )(\*\*\* | $ )/ gs ,
28
+ className: " ci-asterisk3" ,
29
+ },
30
+ {
31
+ regex: / (?<!\* )\*\* ([^ *] + )(\*\* (?!\* )| $ )/ gs ,
32
+ className: " ci-asterisk2" ,
33
+ },
34
+ {
35
+ regex: / (?<!\* )\* ([^ *] + )(\* (?!\* )| $ )/ gs ,
36
+ className: " ci-asterisk1" ,
37
+ },
38
+ ];
39
+
40
+ onMount (() => {
41
+ veditor = initEditor (velement, value);
42
+ teditor = initEditor (telement, translate);
43
+ veditor .on (' change' , (_ , evt ) => {
44
+ if (evt .origin != ' setValue' && ! toggleTranslate) {
45
+ const input = veditor .getValue (' \r\n ' );
46
+ if (input != value) {
47
+ value = _value = input;
48
+ dispatch (' change' , { translate: false , value: input });
49
+ }
50
+ }
51
+ });
52
+ teditor .on (' change' , (_ , evt ) => {
53
+ if (evt .origin != ' setValue' && toggleTranslate) {
54
+ const input = teditor .getValue (' \r\n ' );
55
+ if (input != translate) {
56
+ translate = _translate = input;
57
+ dispatch (' change' , { translate: true , value: input });
58
+ }
59
+ }
60
+ });
61
+ toggleTranslateText ();
62
+ });
63
+
64
+ $: if (value != _value) {
65
+ veditor .setValue (_value = value);
66
+ }
67
+ $: if (translate != _translate) {
68
+ teditor .setValue (_translate = translate);
69
+ }
70
+
71
+ function toggleTranslateText () {
72
+ toggleTranslate = ! toggleTranslate;
73
+ if (toggleTranslate) {
74
+ velement .style .display = " none" ;
75
+ telement .style .display = null ;
76
+ teditor .refresh ();
77
+ } else {
78
+ velement .style .display = null ;
79
+ telement .style .display = " none" ;
80
+ veditor .refresh ();
81
+ }
82
+ }
83
+
84
+ function initEditor (element , value ) {
85
+ const editor = CodeMirror (element, {
86
+ lineNumbers: true ,
87
+ value: value,
88
+ });
89
+ editor .on (' change' , (sender ) => updateMarks (sender .doc ));
90
+ return editor;
91
+ }
92
+
93
+ function updateMarks (doc ) {
94
+ const text = doc .getValue ();
95
+ for (const mark of doc .getAllMarks ()) {
96
+ mark .clear ();
97
+ }
98
+ for (const markdown of markdowns) {
99
+ for (const match of text .matchAll (markdown .regex )) {
100
+ const start = doc .posFromIndex (match .index );
101
+ const end = doc .posFromIndex (match .index + match[0 ].length );
102
+ doc .markText (start, end, { className: markdown .className });
103
+ }
104
+ }
105
+ }
106
+ </script >
107
+
108
+ <div class =" flex flex-1 items-end ml-2 mr-2" >
109
+ {#if $DataBase .useAutoTranslateInput }
110
+ <button
111
+ on:click ={toggleTranslateText }
112
+ 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" >
113
+ {#if toggleTranslate }
114
+ <LanguagesIcon />
115
+ {:else }
116
+ <EditIcon />
117
+ {/if }
118
+ </button >
119
+ {/if }
120
+ <div class =" flex-1" >
121
+ <div class ="chatEditor" bind:this ={velement }></div >
122
+ <div class ="chatEditor" hidden bind:this ={telement }></div >
123
+ </div >
124
+ </div >
125
+ <style >
126
+ .chatEditor {
127
+ display : table ;
128
+ table-layout : fixed ;
129
+ width : 100% ;
130
+ }
131
+ .chatEditor :global(.CodeMirror ) {
132
+ min-height : 2em ;
133
+ height : auto ;
134
+ background-color : var (--risu-theme-bgcolor );
135
+ color : #DD0 ;
136
+ }
137
+ .chatEditor :global(.CodeMirror :focus-within ) {
138
+ background-color : var (--risu-theme-textcolor2 );
139
+ }
140
+ .chatEditor :global(.CodeMirror-gutters ) {
141
+ background-color : var (--risu-theme-selected );
142
+ border-left-color : var (--risu-theme-borderc );
143
+ }
144
+ .chatEditor :global(.ci-quote ) {
145
+ color : #FFF ;
146
+ }
147
+ .chatEditor :global(.ci-backtick ) {
148
+ color : #6AC ;
149
+ }
150
+ .chatEditor :global(.ci-asterisk3 ) {
151
+ font-weight : bold ;
152
+ font-style : italic ;
153
+ color : #E22 ;
154
+ }
155
+ .chatEditor :global(.ci-asterisk2 ) {
156
+ font-style : italic ;
157
+ color : #E84 ;
158
+ }
159
+ .chatEditor :global(.ci-asterisk1 ) {
160
+ font-style : italic ;
161
+ color : #990 ;
162
+ }
163
+ </style >
0 commit comments