From f19efc7ba7bef0a79850cef044a201460ba68de8 Mon Sep 17 00:00:00 2001 From: Vita Chumakova Date: Sat, 27 Jun 2026 14:35:34 +0400 Subject: [PATCH 1/5] feat: parse interpolated localized strings --- script.py | 28 ++++++++++++++++------------ static/main.css | 3 +++ static/script.css | 25 +++++++++++++++++++++++++ templates/highlight/text.html | 2 +- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/script.py b/script.py index f8df625a..3f563854 100755 --- a/script.py +++ b/script.py @@ -5,6 +5,7 @@ import sys from pathlib import Path from typing import Dict, List +from html import escape from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -18,7 +19,7 @@ ) -def parse_text(text: str) -> str: +def parse_text(text: str, is_format: bool) -> str: # Parse Undertale codes the same as Deltarune text = re.sub(r'\\\\', r'\\', text) # General text codes @@ -42,6 +43,13 @@ def parse_text(text: str) -> str: 'Close Message', text, ) + if is_format: + # '~[x]': interpolated argument + text = re.sub( + r'~([1-9])', + r'Argument №\1\1', + text, + ) # '\E[x]': emotion # '\M[x]': special, typically emotion on overworld sprite text = re.sub( @@ -97,7 +105,7 @@ def highlight_text(matches: re.Match[str]) -> str: before_var='"', variable=matches[2], after_var=matches[3], - parsed_text=parse_text(matches[2]), + parsed_text=parse_text(matches[2], 'subloc' in matches[1]), ) @@ -106,7 +114,7 @@ def highlight_text_ch1(matches: re.Match[str], data: Data) -> str: before_var=matches[1], variable=matches[2], after_var=matches[3], - parsed_text=parse_text(data.get_localized_string_ch1(matches[2])), + parsed_text=parse_text(data.get_localized_string_ch1(matches[2]), False), ) @@ -232,21 +240,17 @@ def process_line( ) -> str: # Escape dangerous HTML characters. # This preserves strings like "THE LEGEND OF THIS WORLD.#" - line = re.sub( - r'(&|<)', - lambda matches: {'&': '&', '<': '<'}[matches[1]], - line, - ) + line = escape(line, quote=False) # Highlight localized strings line = re.sub( - r'([A-Za-z0-9_]+loc\((?:\d+, )?)"((?:[^"\\]|\\.)+)(", "[a-z0-9_-]+")\)', # noqa: E501 + r'([a-z0-9_]+loc\((?:\d+, )?)"((?:[^"\\]|\\.)+)(", (?:.+?, )?"[a-z0-9_-]+")\)', # noqa: E501 lambda matches: matches[1] + highlight_text(matches) + ')', line, flags=re.IGNORECASE, ) line = re.sub( - r'(scr_(?:84_get_lang_string(?:_ch1)?|gettext)\(")([a-zA-Z0-9_-]+)("\))', # noqa: E501 + r'(scr_(?:84_get_lang_string(?:_ch1)?|gettext)\(")([a-z0-9_-]+)("\))', # noqa: E501 lambda matches: highlight_text_ch1(matches, data), line, flags=re.IGNORECASE, @@ -259,7 +263,7 @@ def process_line( flags=re.IGNORECASE, ) line = re.sub( - r'(room_goto\()([A-Za-z0-9_]+)', + r'(room_goto\()([a-z0-9_]+)', lambda matches: highlight_room(matches, data), line, flags=re.IGNORECASE, @@ -272,7 +276,7 @@ def process_line( ) # Link to functions and alarms line = re.sub( - r'(\b)(s?cr?_[a-zA-Z0-9_]+)\(', + r'(\b)(s?cr?_[a-z0-9_]+)\(', lambda matches: highlight_function( matches, script_name, text, data, resolve_references ), diff --git a/static/main.css b/static/main.css index 89722fef..e69c9cc1 100644 --- a/static/main.css +++ b/static/main.css @@ -23,6 +23,9 @@ --close-text-color: #fff; --face-background-color: #252; --face-text-color: #8c8; + --arg-background-color: #707; + --arg-text-color: #fff; + --arg-collapsed-text-color: #aaa; --flag-not-found-text-color: #ec6; --flag-found-text-color: #fd8; --flag-found-background-color: black; diff --git a/static/script.css b/static/script.css index 450bab58..1091d0ec 100644 --- a/static/script.css +++ b/static/script.css @@ -111,6 +111,27 @@ pre:not(.funcCode), code, .hljs { user-select: none; } +.cc-arg { + background: var(--arg-background-color); + color: var(--arg-text-color); + user-select: none; +} + +.cc-arg > span { + position: absolute; + right: 0; + bottom: 0.1em; + display: inline-block; + font-size: 70%; + color: var(--arg-collapsed-text-color); + text-indent: 0; + font-style: italic; +} + +.cc-arg:hover > span { + display: none; +} + .cc-delay:before { content: '\231b'; margin-right: 0.2em; @@ -124,6 +145,10 @@ pre:not(.funcCode), code, .hljs { content: '\239a'; } +.cc-arg:before { + content: '\2386'; +} + .cc-color { color: white; } diff --git a/templates/highlight/text.html b/templates/highlight/text.html index c61dfd78..4fd2c5e5 100644 --- a/templates/highlight/text.html +++ b/templates/highlight/text.html @@ -1 +1 @@ -
{{ parsed_text | safe }}
{{ before_var }}{{ variable | safe }}{{ after_var }}
+
{{ parsed_text | safe }}
{{ before_var | safe }}{{ variable | safe }}{{ after_var | safe }}
From a0202f4980e9420dea0c2c8e1b99710bbb65b1c2 Mon Sep 17 00:00:00 2001 From: Vita Chumakova Date: Sat, 27 Jun 2026 14:35:52 +0400 Subject: [PATCH 2/5] build: add vscode config --- .vscode/launch.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..a6ed804b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Build the Deltarune site", + "type": "debugpy", + "request": "launch", + "program": "build.py", + "console": "integratedTerminal", + "args": "deltarune" + } + ] +} \ No newline at end of file From b2fce1533e6bb0b62ba5ffecb5755c962439700a Mon Sep 17 00:00:00 2001 From: Vita Chumakova Date: Sat, 27 Jun 2026 14:36:29 +0400 Subject: [PATCH 3/5] chore: ignore mac resource files --- .gitignore | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index ff68d765..f0738211 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -.venv -__pycache__ -decompiled-* -out +.venv/ +__pycache__/ +decompiled-*/ +out/ +.DS_Store From 7b37c6f96cce3cd902ad2aaee74a7c92414b8e7d Mon Sep 17 00:00:00 2001 From: Vita Chumakova Date: Sat, 27 Jun 2026 15:33:12 +0400 Subject: [PATCH 4/5] fix: use greedy matching due to nested func calls --- script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.py b/script.py index 3f563854..3cb7a3b3 100755 --- a/script.py +++ b/script.py @@ -244,7 +244,7 @@ def process_line( # Highlight localized strings line = re.sub( - r'([a-z0-9_]+loc\((?:\d+, )?)"((?:[^"\\]|\\.)+)(", (?:.+?, )?"[a-z0-9_-]+")\)', # noqa: E501 + r'([a-z0-9_]+loc\((?:\d+, )?)"((?:[^"\\]|\\.)+)(", (?:.+, )?"[a-z0-9_-]+")\)', # noqa: E501 lambda matches: matches[1] + highlight_text(matches) + ')', line, flags=re.IGNORECASE, From 917c1166c33aeed824a2d5e0581b651a2372b803 Mon Sep 17 00:00:00 2001 From: Vita Chumakova Date: Sat, 27 Jun 2026 16:38:02 +0400 Subject: [PATCH 5/5] style: fix warnings --- script.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/script.py b/script.py index 3cb7a3b3..c17cef83 100755 --- a/script.py +++ b/script.py @@ -1,11 +1,11 @@ #!/usr/bin/env python import argparse +import html import os import re import sys from pathlib import Path from typing import Dict, List -from html import escape from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -114,7 +114,9 @@ def highlight_text_ch1(matches: re.Match[str], data: Data) -> str: before_var=matches[1], variable=matches[2], after_var=matches[3], - parsed_text=parse_text(data.get_localized_string_ch1(matches[2]), False), + parsed_text=parse_text( + data.get_localized_string_ch1(matches[2]), + False), ) @@ -240,7 +242,7 @@ def process_line( ) -> str: # Escape dangerous HTML characters. # This preserves strings like "THE LEGEND OF THIS WORLD.#" - line = escape(line, quote=False) + line = html.escape(line, quote=False) # Highlight localized strings line = re.sub(