mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-16 20:02:20 +02:00
feat(photo-editor): Ajax Image Editor client (Photoshop-parity tools)
Photoshop-parity editor client: layers, selection/masking, brushes,
smart filters, LUT import, Quick Edit, mobile gestures, workspaces,
batch operations, and the service-worker versioning (v978->v1006).
Source: vendor/photocraft (ad1cff44) photo-editor client files, merged
onto upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/A_conflicts.md; editor files taken from vendor/photocraft
(upstream's editor is an earlier snapshot of the same feature).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c74f475679
commit
5fac693c1c
@@ -0,0 +1,50 @@
|
||||
"""Quick Edit support for Photoshop's Type ▸ Warp ("warp the text").
|
||||
|
||||
The editor already had a full retained-text warp pipeline (static/js/editor/
|
||||
text-layer.js `warpCanvas`, and `warp`/`warpAmount` on the text data), but the
|
||||
Quick Edit client fast path never routed a warp request, so "warp the text"
|
||||
fell through to "No built-in quick action matched". These tests pin the new
|
||||
deterministic branch in galleryEditor.js `_executeQuickEditLocal`.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
EDITOR = (ROOT / "static" / "js" / "galleryEditor.js").read_text(encoding="utf-8")
|
||||
TEXT_LAYER = (ROOT / "static" / "js" / "editor" / "text-layer.js").read_text(encoding="utf-8")
|
||||
COVERAGE = (ROOT / "docs" / "QUICKEDIT_COVERAGE.md").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_warp_branch_applies_style_and_amount():
|
||||
assert "// --- Type ▸ Warp (deterministic) ---" in EDITOR
|
||||
assert "const _warpWord = /\\bwarp(?:ed)?\\b/.test(p);" in EDITOR
|
||||
assert "const _warpTextWord = /\\b(?:text|title|caption|heading|word|lettering|type)\\b/.test(p);" in EDITOR
|
||||
assert "_rerenderTextLayer(_wLayer, { ..._wLayer.text, warp: style, warpAmount: _wAmount });" in EDITOR
|
||||
assert "_saveState('Warp text');" in EDITOR
|
||||
assert "_setAiCommandStatus(style === 'none' ? 'Removed the text warp.' : `Warped the text (${style}).`, 'done');" in EDITOR
|
||||
|
||||
|
||||
def test_warp_maps_every_photoshop_style():
|
||||
for style in ("arc", "arch", "bulge", "inflate", "squeeze", "fisheye", "wave", "rise", "twist", "flag"):
|
||||
assert f"style = '{style}'" in EDITOR, style
|
||||
assert "style = 'none'" in EDITOR
|
||||
assert "const _wAm = p.match(/\\b(?:by|amount|to)\\s*(-?\\d{1,3})\\b/);" in EDITOR
|
||||
assert "Math.max(-100, Math.min(100, Math.round(Number(_wAm[1])))) : 50" in EDITOR
|
||||
|
||||
|
||||
def test_warp_runs_before_generic_text_edit():
|
||||
warp_idx = EDITOR.index("// --- Type ▸ Warp (deterministic) ---")
|
||||
text_idx = EDITOR.index("// --- Text edit (deterministic) ---")
|
||||
assert warp_idx < text_idx
|
||||
|
||||
|
||||
def test_warp_infrastructure_exists():
|
||||
assert "export function warpCanvas(base, style, amount)" in TEXT_LAYER
|
||||
assert "export const WARP_STYLES" in TEXT_LAYER
|
||||
assert "warp: WARP_STYLES.includes(value.warp) ? value.warp : 'none'," in TEXT_LAYER
|
||||
assert "warpAmount: finite(value.warpAmount, DEFAULT_TEXT_DATA.warpAmount, -100, 100)," in TEXT_LAYER
|
||||
assert "function _rerenderTextLayer(layer, nextText, preserveCenter = true)" in EDITOR
|
||||
|
||||
|
||||
def test_coverage_row_marked_ok():
|
||||
assert "| Type → Warp | \"warp the text\" | `_rerenderTextLayer` (warp) | ✔ | ✔ | ✔ | OK |" in COVERAGE
|
||||
Reference in New Issue
Block a user