feat(editor-v2): wire data-editor-language attrs into three textareas
Templates:
- blueprint_detail.html:52 — config textarea gets
data-editor-language="srccfg".
- overlay_detail.html:25 — script textarea gets
data-editor-language="bash".
- overlay_detail.html files-modal — content textarea gets
data-editor-language="auto"; new <select data-editor-language-select>
(auto / srccfg / bash / plain); filename input gets
data-editor-filename.
- Both templates {% include "_editor_assets.html" %} before
{% endblock %}.
Tests (TDD red-green):
- test_blueprint_get_includes_editor_markup pins srccfg + bundle + glue
in blueprint detail GET.
- test_script_overlay_detail_carries_editor_markup pins bash + bundle
+ glue in script overlay GET.
- Files-modal markup verified end-to-end in Task 14 Playwright (its
pytest fixtures are heavyweight; not worth duplicating for a static
markup assertion).
Fast suite stays at 564 passed (no regressions).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9ca0e789f4
commit
59446bc105
4 changed files with 44 additions and 4 deletions
|
|
@ -49,7 +49,7 @@
|
|||
<pre class="config-preview" aria-label="Auto-loaded overlay configs">{% for o in exposed %}exec {{ o.name }}.cfg
|
||||
{% endfor %}</pre>
|
||||
{% endif %}
|
||||
<textarea name="config" rows="8" spellcheck="false">{{ config_lines | join('\n') }}</textarea>
|
||||
<textarea name="config" rows="8" spellcheck="false" data-editor-language="srccfg">{{ config_lines | join('\n') }}</textarea>
|
||||
</div>
|
||||
</label>
|
||||
<button type="submit">Save blueprint</button>
|
||||
|
|
@ -92,4 +92,5 @@
|
|||
</div>
|
||||
</dialog>
|
||||
<script src="{{ url_for('static', filename='js/blueprint-overlay-picker.js') }}" defer></script>
|
||||
{% include "_editor_assets.html" %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
<form method="post" action="/overlays/{{ overlay.id }}/script" class="stack">
|
||||
<input type="hidden" name="csrf_token" value="{{ session.get('csrf_token', '') }}">
|
||||
<label>Bash script
|
||||
<textarea name="script" rows="20" spellcheck="false">{{ overlay.script or "" }}</textarea>
|
||||
<textarea name="script" rows="20" spellcheck="false" data-editor-language="bash">{{ overlay.script or "" }}</textarea>
|
||||
</label>
|
||||
<p class="muted">Runs sandboxed against the overlay directory mounted at <code>/overlay</code>.</p>
|
||||
{% if not latest_build_is_running %}
|
||||
|
|
@ -168,14 +168,23 @@
|
|||
<div class="modal-body">
|
||||
<label class="files-editor-field">
|
||||
<span class="files-field-label">Filename</span>
|
||||
<input type="text" class="files-editor-filename" autocomplete="off" spellcheck="false">
|
||||
<input type="text" class="files-editor-filename" data-editor-filename autocomplete="off" spellcheck="false">
|
||||
</label>
|
||||
<p class="files-editor-rename-hint" hidden>↻ Save will rename <code class="files-rename-from"></code> → <code class="files-rename-to"></code>.</p>
|
||||
|
||||
<div class="files-editor-text">
|
||||
<label class="files-editor-field files-editor-language-field">
|
||||
<span class="files-field-label">Language</span>
|
||||
<select data-editor-language-select aria-label="Editor language">
|
||||
<option value="auto">auto (from filename)</option>
|
||||
<option value="srccfg">srccfg (.cfg)</option>
|
||||
<option value="bash">bash (.sh)</option>
|
||||
<option value="plain">plain</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="files-editor-field">
|
||||
<span class="files-field-label">Content</span>
|
||||
<textarea class="files-editor-content" rows="14" spellcheck="false"></textarea>
|
||||
<textarea class="files-editor-content" rows="14" spellcheck="false" data-editor-language="auto"></textarea>
|
||||
</label>
|
||||
<div class="files-editor-meta muted">
|
||||
<span class="files-editor-byte-count">UTF-8 · 0 bytes</span>
|
||||
|
|
@ -273,4 +282,5 @@
|
|||
|
||||
<script src="{{ url_for('static', filename='js/files-overlay.js') }}" defer></script>
|
||||
{% endif %}
|
||||
{% include "_editor_assets.html" %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -453,3 +453,19 @@ def test_blueprint_config_form_post_round_trip(user_client) -> None:
|
|||
# line round-tripped into the rendered textarea.
|
||||
for line in ("// pinned by form-contract test", "sv_cheats 0", "exec server.cfg"):
|
||||
assert line in body, f"line not found in rendered page: {line!r}"
|
||||
|
||||
|
||||
def test_blueprint_get_includes_editor_markup(user_client) -> None:
|
||||
"""Blueprint detail page must carry the editor opt-in attribute and
|
||||
the editor asset partial — the v2 CodeMirror 6 wiring contract."""
|
||||
create = user_client.post(
|
||||
"/blueprints",
|
||||
data={"name": "editor-attrs", "arguments": "", "config": "", "overlay_ids": []},
|
||||
headers={"X-CSRF-Token": "test-token"},
|
||||
)
|
||||
assert create.status_code == 302
|
||||
page = user_client.get(create.headers["Location"])
|
||||
body = page.get_data(as_text=True)
|
||||
assert 'data-editor-language="srccfg"' in body
|
||||
assert "vendor/editor.bundle.js" in body
|
||||
assert "js/editor.js" in body
|
||||
|
|
|
|||
|
|
@ -277,3 +277,16 @@ def test_permissions_admin_can_edit_any(app, alice_id, admin_id) -> None:
|
|||
with session_scope() as s:
|
||||
overlay = s.query(Overlay).filter_by(id=overlay_id).one()
|
||||
assert overlay.script == "echo admin"
|
||||
|
||||
|
||||
def test_script_overlay_detail_carries_editor_markup(app, alice_id) -> None:
|
||||
"""Script overlay detail page must carry the editor opt-in attribute
|
||||
and the editor asset partial — the v2 CodeMirror 6 wiring contract."""
|
||||
overlay_id = _create_script_overlay(app, alice_id)
|
||||
client = _client_for(app, alice_id)
|
||||
response = client.get(f"/overlays/{overlay_id}")
|
||||
assert response.status_code == 200
|
||||
body = response.get_data(as_text=True)
|
||||
assert 'data-editor-language="bash"' in body
|
||||
assert "vendor/editor.bundle.js" in body
|
||||
assert "js/editor.js" in body
|
||||
|
|
|
|||
Loading…
Reference in a new issue