From e30abd209f16fd8640dc9be7238bb421eca269e0 Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:04:16 -0400 Subject: [PATCH 1/6] Preserve whitespace in the editor (cherry picked from commit 793d788706a7a35adb53fb0d22c6b629a9c1d215) --- static/custom.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/custom.css b/static/custom.css index 640cb8db..2b6db54d 100644 --- a/static/custom.css +++ b/static/custom.css @@ -4,6 +4,7 @@ body { chunk { color: #ffffff; + white-space: pre-wrap; } #gametext.adventure action { From 2a4d37ce6024a0b4cc5f8544757185fd40f6d79f Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:04:36 -0400 Subject: [PATCH 2/6] Clean up whitespace at the end of actions when loading story Specifically, we merge blank actions into the next action and we move whitespace at the end of non-blank actions to the beginning of the next action. (cherry picked from commit 4b16600e49a24f9d43c16d9517eb0acfc9539313) --- aiserver.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/aiserver.py b/aiserver.py index 08046290..57eac4e4 100644 --- a/aiserver.py +++ b/aiserver.py @@ -5090,7 +5090,8 @@ def loadRequest(loadpath, filename=None): for text in js['actions']: vars.actions_metadata[i] = {'Selected Text': text, 'Alternative Text': []} i+=1 - + + footer = "" if(len(vars.prompt.strip()) == 0): while(len(actions)): @@ -5100,9 +5101,25 @@ def loadRequest(loadpath, filename=None): break else: vars.gamestarted = False + vars.prompt = vars.prompt.lstrip() + ln = len(vars.prompt.rstrip()) + footer += vars.prompt[ln:] + vars.prompt = vars.prompt[:ln] if(vars.gamestarted): for s in actions: - vars.actions.append(s) + if(len(s.strip()) == 0): + # If this action only contains whitespace, we merge it with the next action + footer += s + continue + vars.actions.append(footer + s) + footer = "" + # If there is trailing whitespace at the end of an action, we move that whitespace to the beginning of the next action + ln = len(vars.actions[vars.actions.get_last_key()].rstrip()) + footer += vars.actions[vars.actions.get_last_key()][ln:] + vars.actions[vars.actions.get_last_key()] = vars.actions[vars.actions.get_last_key()][:ln] + if(len(vars.actions) == 0): + vars.gamestarted = False + # Try not to break older save files if("authorsnote" in js): From 9d09ae5feada79e61b7db45655bcb600daa95ac3 Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:05:04 -0400 Subject: [PATCH 3/6] Clean up whitespace in the editor as well (cherry picked from commit 6e138db1c0be03768e1c1297668260614011b9e1) --- static/application.js | 45 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/static/application.js b/static/application.js index 3cddea87..7ae7aee1 100644 --- a/static/application.js +++ b/static/application.js @@ -1609,7 +1609,7 @@ function applyChunkDeltas(nodes) { var selected_chunks = buildChunkSetFromNodeArray(getSelectedNodes()); for(var i = 0; i < chunks.length; i++) { var chunk = document.getElementById("n" + chunks[i]); - if(chunk && formatChunkInnerText(chunk).length != 0 && chunks[i] != '0') { + if(chunk && formatChunkInnerText(chunk).trim().length != 0 && chunks[i] != '0') { if(!selected_chunks.has(chunks[i])) { modified_chunks.delete(chunks[i]); socket.send({'cmd': 'inlineedit', 'chunk': chunks[i], 'data': formatChunkInnerText(chunk)}); @@ -1618,7 +1618,7 @@ function applyChunkDeltas(nodes) { } else { if(!selected_chunks.has(chunks[i])) { modified_chunks.delete(chunks[i]); - socket.send({'cmd': 'inlineedit', 'chunk': chunks[i], 'data': ''}); + socket.send({'cmd': 'inlineedit', 'chunk': chunks[i], 'data': formatChunkInnerText(chunk)}); } empty_chunks.add(chunks[i]); } @@ -1750,6 +1750,46 @@ function highlightEditingChunks() { } } +function cleanupChunkWhitespace() { + // Merge empty chunks with the next chunk + var chunks = Array.from(empty_chunks); + chunks.sort(function(e) {parseInt(e)}); + for(var i = 0; i < chunks.length; i++) { + var original_chunk = document.getElementById("n" + chunks[i]); + original_chunk.innerText = footer + original_chunk.innerText; + footer = ""; + var chunk = original_chunk.nextSibling; + while(chunk) { + if(chunk.tagName === "CHUNK") { + break; + } + chunk = chunk.nextSibling; + } + if(chunk) { + chunk.innerText = original_chunk.innerText + chunk.innerText; + } + original_chunk.innerText = ""; + } + // Move whitespace at the end of non-empty chunks into the beginning of the next non-empty chunk + var chunks = Array.from(modified_chunks); + chunks.sort(function(e) {parseInt(e)}); + for(var i = 0; i < chunks.length; i++) { + var original_chunk = document.getElementById("n" + chunks[i]); + var chunk = original_chunk.nextSibling; + while(chunk) { + if(chunk.tagName === "CHUNK" && !empty_chunks.has(chunk.getAttribute("n"))) { + break; + } + chunk = chunk.nextSibling; + } + var ln = original_chunk.innerText.trimEnd().length; + if (chunk) { + chunk.innerText = original_chunk.innerText.substring(ln) + chunk.innerText; + } + original_chunk.innerText = original_chunk.innerText.substring(0, ln); + } +} + // This gets run every time the text in a chunk is edited // or a chunk is deleted function chunkOnDOMMutate(mutations, observer) { @@ -1828,6 +1868,7 @@ function chunkOnFocusOut(event) { if(document.activeElement === game_text[0] || game_text[0].contains(document.activeElement)) { return; } + cleanupChunkWhitespace(); syncAllModifiedChunks(true); setTimeout(function() { var blurred = game_text[0] !== document.activeElement; From 6ba7429eead8a3f882b5fb7949ffb7157949cf37 Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:06:18 -0400 Subject: [PATCH 4/6] Don't add sentence spacing if submission is empty When you retry, it actually sends an empty submission, so if you have add sentence spacing on, retrying could add an extra action with a single space. (cherry picked from commit 151407a001651c70f49a0c659957d80a36ec2a8a) --- utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils.py b/utils.py index 96606269..e6d7d12b 100644 --- a/utils.py +++ b/utils.py @@ -91,6 +91,9 @@ def removespecialchars(txt, vars=None): # If the next action follows a sentence closure, add a space #==================================================================# def addsentencespacing(txt, vars): + # Don't add sentence spacing if submission is empty or starts with whitespace + if(len(txt) == 0 or len(txt) != len(txt.lstrip())): + return txt # Get last character of last action if(len(vars.actions) > 0): if(len(vars.actions[vars.actions.get_last_key()]) > 0): From ebba79fed6ce957d1d3079b400eb301b7f49d078 Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:06:34 -0400 Subject: [PATCH 5/6] Remove trailing whitespace from submissions (cherry picked from commit b99d1449c942286113df3c98ba7dd99137fcae64) --- aiserver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aiserver.py b/aiserver.py index 57eac4e4..728f8201 100644 --- a/aiserver.py +++ b/aiserver.py @@ -3110,6 +3110,7 @@ def actionsubmit(data, actionmode=0, force_submit=False, force_prompt_gen=False, if(not vars.gamestarted): vars.submission = data execute_inmod() + vars.submission = re.sub(r"[^\S\r\n]*([\r\n]*)$", r"\1", vars.submission) # Remove trailing whitespace, excluding newlines data = vars.submission if(not force_submit and len(data.strip()) == 0): assert False @@ -3168,6 +3169,7 @@ def actionsubmit(data, actionmode=0, force_submit=False, force_prompt_gen=False, data = applyinputformatting(data) vars.submission = data execute_inmod() + vars.submission = re.sub(r"[^\S\r\n]*([\r\n]*)$", r"\1", vars.submission) # Remove trailing whitespace, excluding newlines data = vars.submission # Dont append submission if it's a blank/continue action if(data != ""): From 6576f5c01df693a561da12eede7ec8a7fc2b26ba Mon Sep 17 00:00:00 2001 From: vfbd Date: Sun, 26 Jun 2022 14:06:57 -0400 Subject: [PATCH 6/6] Make sure editor changes are applied before submitting (cherry picked from commit ae41ad298cc54a1ef9972cef57dd25455b07f9fe) --- static/application.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/application.js b/static/application.js index 7ae7aee1..4faf3922 100644 --- a/static/application.js +++ b/static/application.js @@ -881,6 +881,7 @@ function dosubmit(disallow_abort) { if((disallow_abort || gamestate !== "wait") && !memorymode && !gamestarted && ((!adventure || !action_mode) && txt.trim().length == 0)) { return; } + chunkOnFocusOut("override"); input_text.val(""); hideMessage(); hidegenseqs(); @@ -1861,7 +1862,7 @@ function chunkOnKeyDownSelectionChange(event) { // This gets run when you defocus the editor by clicking // outside of the editor or by pressing escape or tab function chunkOnFocusOut(event) { - if(!gametext_bound || !allowedit || event.target !== game_text[0]) { + if(event !== "override" && (!gametext_bound || !allowedit || event.target !== game_text[0])) { return; } setTimeout(function() {