A trigger->replacement library (core/shortcuts.py, a close port of v4's apply_prompt_shortcuts/resolve_variables), a Settings section to manage it, autocomplete on the real prompt textarea (composer.autocomplete.default, so it outranks the Constructor modal it lives inside), and a stateless /api/prompt/expand that combines anchor + shortcuts + $variables + postfix at the moment a run is queued -- scene.text itself stays exactly what was typed. Project gained anchor/postfix/variables editing UI on its own tab. Along the way: a real layout bug in the Properties column (every composer stack can flex-shrink below its own content, and once the Project tab grew past a couple of rows the column started squeezing its own children's content into each other and, at the outer level, into the sibling Generation section below) -- fixed with flex-shrink:0 at each level that needs it, caught by a Playwright regression test.
56 lines
2.2 KiB
Python
56 lines
2.2 KiB
Python
"""build(): anchor + scene text + postfix, shortcuts expanded across the
|
|
whole combined string, then $variables resolved last. Order is what makes a
|
|
shortcut trigger spanning the anchor/scene boundary still match, and a
|
|
variable's value able to contain another variable or a shortcut trigger.
|
|
"""
|
|
|
|
from core import prompt_build, shortcuts
|
|
|
|
|
|
def _sc(triggers, replacements):
|
|
return shortcuts.Shortcut(name=triggers[0], triggers=triggers, replacements=replacements)
|
|
|
|
|
|
def test_anchor_and_postfix_wrap_the_scene_text():
|
|
out = prompt_build.build("a fox runs", anchor="cinematic", postfix="4k")
|
|
assert out == "cinematic a fox runs 4k"
|
|
|
|
|
|
def test_postfix_is_dropped_when_disabled():
|
|
out = prompt_build.build("a fox runs", anchor="cinematic", postfix="4k", postfix_enabled=False)
|
|
assert out == "cinematic a fox runs"
|
|
|
|
|
|
def test_empty_anchor_and_postfix_leave_only_the_scene_text():
|
|
assert prompt_build.build("a fox runs") == "a fox runs"
|
|
|
|
|
|
def test_a_shortcut_expands_inside_the_combined_string():
|
|
out = prompt_build.build("a fox runs", anchor="", postfix="",
|
|
shortcuts=[_sc(["fox"], ["red fox"])])
|
|
assert out == "a red fox runs"
|
|
|
|
|
|
def test_a_shortcut_can_span_the_anchor_and_scene_boundary():
|
|
out = prompt_build.build("hour scene", anchor="golden",
|
|
shortcuts=[_sc(["golden hour"], ["warm light"])])
|
|
assert out == "warm light scene"
|
|
|
|
|
|
def test_variables_resolve_after_shortcuts_expand():
|
|
out = prompt_build.build("a $animal runs", shortcuts=[_sc(["runs"], ["runs fast"])],
|
|
variables=[{"name": "animal", "value": "fox"}])
|
|
assert out == "a fox runs fast"
|
|
|
|
|
|
def test_a_variables_own_text_is_not_rescanned_for_shortcut_triggers():
|
|
# variables resolve AFTER shortcut expansion, so a $var's own text is not
|
|
# re-scanned for shortcut triggers -- only the scene/anchor/postfix text is.
|
|
out = prompt_build.build("$style", shortcuts=[_sc(["fox"], ["red fox"])],
|
|
variables=[{"name": "style", "value": "a fox runs"}])
|
|
assert out == "a fox runs"
|
|
|
|
|
|
def test_whitespace_only_scene_text_with_no_anchor_or_postfix_is_empty():
|
|
assert prompt_build.build(" ") == ""
|