Skip to content

Commit d9dfb7b

Browse files
committed
experimental contenteditable wildcard editor
1 parent 7367fc6 commit d9dfb7b

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

src/Pages/_Generate/GenTabModals.cshtml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@
166166
<div class="modal-body">
167167
<p class="translate">Wildcards are lists of random prompt segments. One entry per line. Prompt sub-syntax is allowed (eg you can link another wildcard, or use <code>&lt;random:...&gt;</code>, or <code>&lt;preset:...&gt;</code> or anything else you want).</p>
168168
<p class="translate">Prefix a line with <code>#</code> to make it a comment (ie won't be counted as an option).</p>
169-
Options: <textarea class="auto-text auto-text-block" id="edit_wildcard_contents" rows="15" placeholder="Wildcard options (1 per line)"></textarea>
169+
<p>Use Experimental Editor? <input type="checkbox" id="edit_wildcard_experimental_editor" onchange="wildcardHelpers.toggleExperimentalEditor()" /></p>
170+
<div id="edit_wildcard_editor_spot"></div>
170171
<div id="edit_wildcard_image_block"></div>
171172
</div>
172173
<div class="modal-footer">

src/wwwroot/js/genpage/gentab/wildcards.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ class WildcardHelpers {
88
this.wildcardNameCheck = {};
99
this.wildcardDataCache = {};
1010
this.nameElem = getRequiredElementById('edit_wildcard_name');
11-
this.contentsElem = getRequiredElementById('edit_wildcard_contents');
11+
this.experimentalEditorElem = getRequiredElementById('edit_wildcard_experimental_editor');
12+
this.experimentalEditorSpotElem = getRequiredElementById('edit_wildcard_editor_spot');
13+
this.toggleExperimentalEditor();
1214
this.imageBlockElem = getRequiredElementById('edit_wildcard_image_block');
1315
let imageHtml = makeImageInput(null, 'edit_wildcard_image', null, 'Image', 'Image', true, false);
1416
this.imageBlockElem.innerHTML = imageHtml;
@@ -21,9 +23,6 @@ class WildcardHelpers {
2123
this.nameElem.addEventListener('input', () => {
2224
this.modalMayClose = false;
2325
});
24-
this.contentsElem.addEventListener('input', () => {
25-
this.modalMayClose = false;
26-
});
2726
setTimeout(() => {
2827
$(this.modalElem).modal({backdrop: 'static', keyboard: false});
2928
}, 1);
@@ -39,6 +38,32 @@ class WildcardHelpers {
3938
this.enableImageElem = getRequiredElementById('edit_wildcard_image_toggle');
4039
}
4140

41+
/** Toggles the experimental editor. */
42+
toggleExperimentalEditor() {
43+
let content = null;
44+
if (this.contentsElem) {
45+
content = getTextContent(this.contentsElem);
46+
}
47+
if (this.experimentalEditorElem.checked) {
48+
this.experimentalEditorSpotElem.innerHTML = '<div class="editable-textbox" id="edit_wildcard_contents" style="min-height: 15lh" contenteditable="true"></div>';
49+
this.contentsElem = getRequiredElementById('edit_wildcard_contents');
50+
this.contentsElem.addEventListener('input', () => {
51+
this.processContents();
52+
});
53+
}
54+
else {
55+
this.experimentalEditorSpotElem.innerHTML = '<textarea class="auto-text auto-text-block" id="edit_wildcard_contents" rows="15" placeholder="Wildcard options (1 per line)"></textarea>';
56+
this.contentsElem = getRequiredElementById('edit_wildcard_contents');
57+
}
58+
if (content) {
59+
setTextContent(this.contentsElem, content);
60+
}
61+
this.contentsElem.addEventListener('input', () => {
62+
this.modalMayClose = false;
63+
});
64+
this.processContents();
65+
}
66+
4267
/** Applies a new wildcard list from the server. */
4368
newWildcardList(cards) {
4469
this.allWildcards = cards;
@@ -97,6 +122,31 @@ class WildcardHelpers {
97122
this.editWildcard(card);
98123
}
99124

125+
/** Processes the contents of the wildcard contents edit box, reapplying syntax highlighting. */
126+
processContents() {
127+
if (this.contentsElem.tagName == 'TEXTAREA') {
128+
return;
129+
}
130+
let [start, end] = getTextSelRange(this.contentsElem);
131+
let contents = getTextContent(this.contentsElem);
132+
let lines = contents.split('\n');
133+
let html = '';
134+
for (let i = 0; i < lines.length; i++) {
135+
let line = lines[i];
136+
let trimLine = line.trim();
137+
let clazz = `wc_line_${i % 2}`;
138+
if (trimLine.startsWith('#')) {
139+
clazz += ' wc_line_comment';
140+
}
141+
html += `<span class="${clazz}">${line}</span>`;
142+
if (i < lines.length - 1) {
143+
html += '<br>';
144+
}
145+
}
146+
this.contentsElem.innerHTML = html;
147+
setTextSelRange(this.contentsElem, start, end);
148+
}
149+
100150
/** Edit a wildcard, opening the wildcard edit modal. This can also open the editor for new wildcards. */
101151
editWildcard(card) {
102152
if (card == null) {
@@ -107,7 +157,8 @@ class WildcardHelpers {
107157
this.enableImageElem.checked = false;
108158
let curImg = document.getElementById('current_image_img');
109159
this.nameElem.value = card.name;
110-
this.contentsElem.value = card.raw;
160+
setTextContent(this.contentsElem, card.raw);
161+
this.processContents();
111162
this.errorBoxElem.innerText = '';
112163
this.modalMayClose = true;
113164
let run = () => {
@@ -147,7 +198,7 @@ class WildcardHelpers {
147198
this.wildcardModalError('Cannot save a wildcard as a folder, give it a filename, or remove the trailing slash');
148199
return;
149200
}
150-
let content = this.contentsElem.value.trim();
201+
let content = getTextContent(this.contentsElem).trim();
151202
if (content == '') {
152203
this.wildcardModalError('At least one entry is required');
153204
return;

0 commit comments

Comments
 (0)