Files
pixa/internal/templates/generator.html
T
clawbot 847bd36087
check / check (push) Waiting to run
Serve JPEG XL when a request names no format (closes #222)
A /v1/image/ URL whose last segment is a size with no format, such as
800x600 or orig, is served as JPEG XL and signed as jxl, so it shares
the signature of the same URL ending in .jxl. An encrypted URL whose
token holds no format is served as JPEG XL, as encurl.DefaultFormat is
now jxl. The generator page selects JPEG XL by default, and a form
with an empty format, or none, makes a URL whose name ends in .jxl.

The image processor no longer takes an empty format as orig: both
routes give every request a format, so it refuses a request with none
instead of keeping a second default. auto still ends with JPEG.

Model: opus-5-5
2026-10-08 10:12:30 +00:00

162 lines
6.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pixa - URL Generator</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="page">
<header>
<h1>Pixa URL Generator</h1>
<a href="/logout">
Logout
</a>
</header>
{{if .GeneratedURL}}
<div class="result">
<h2>Generated URL</h2>
<div>
<input
type="text"
readonly
value="{{.GeneratedURL}}"
id="generated-url"
>
<button id="copy-url">
Copy
</button>
</div>
<p>
Expires: {{.ExpiresAt}}
</p>
</div>
{{end}}
{{if .Error}}
<div class="error">
{{.Error}}
</div>
{{end}}
<form method="POST" action="/generate" class="card">
{{ .CSRFField }}
<div>
<label for="url">
Source URL
</label>
<input
type="url"
id="url"
name="url"
required
placeholder="https://example.com/image.jpg"
value="{{.FormURL}}"
>
</div>
<div class="columns">
<div>
<label for="width">
Width
</label>
<input
type="number"
id="width"
name="width"
min="0"
max="8192"
value="{{if .FormWidth}}{{.FormWidth}}{{else}}0{{end}}"
placeholder="0 = original"
>
</div>
<div>
<label for="height">
Height
</label>
<input
type="number"
id="height"
name="height"
min="0"
max="8192"
value="{{if .FormHeight}}{{.FormHeight}}{{else}}0{{end}}"
placeholder="0 = original"
>
</div>
</div>
<div class="columns">
<div>
<label for="format">
Format
</label>
<select id="format" name="format">
<option value="orig" {{if eq .FormFormat "orig"}}selected{{end}}>Original</option>
<option value="auto" {{if eq .FormFormat "auto"}}selected{{end}}>Auto (JPEG XL, AVIF, WebP or JPEG)</option>
<option value="jpeg" {{if eq .FormFormat "jpeg"}}selected{{end}}>JPEG</option>
<option value="png" {{if eq .FormFormat "png"}}selected{{end}}>PNG</option>
<option value="webp" {{if eq .FormFormat "webp"}}selected{{end}}>WebP</option>
<option value="avif" {{if eq .FormFormat "avif"}}selected{{end}}>AVIF</option>
<option value="jxl" {{if or (eq .FormFormat "jxl") (eq .FormFormat "")}}selected{{end}}>JPEG XL</option>
<option value="gif" {{if eq .FormFormat "gif"}}selected{{end}}>GIF</option>
</select>
</div>
<div>
<label for="quality">
Quality
</label>
<select id="quality" name="quality">
<option value="25" {{if eq .FormQuality "25"}}selected{{end}}>Potato</option>
<option value="50" {{if eq .FormQuality "50"}}selected{{end}}>Low</option>
<option value="70" {{if eq .FormQuality "70"}}selected{{end}}>Medium</option>
<option value="85" {{if or (eq .FormQuality "85") (eq .FormQuality "")}}selected{{end}}>High</option>
<option value="100" {{if eq .FormQuality "100"}}selected{{end}}>Ultra</option>
</select>
</div>
</div>
<div class="columns">
<div>
<label for="fit">
Fit Mode
</label>
<select id="fit" name="fit">
<option value="cover" {{if eq .FormFit "cover"}}selected{{end}}>Cover</option>
<option value="contain" {{if eq .FormFit "contain"}}selected{{end}}>Contain</option>
<option value="fill" {{if eq .FormFit "fill"}}selected{{end}}>Fill</option>
<option value="inside" {{if eq .FormFit "inside"}}selected{{end}}>Inside</option>
<option value="outside" {{if eq .FormFit "outside"}}selected{{end}}>Outside</option>
</select>
</div>
<div>
<label for="ttl">
Expires In
</label>
<select id="ttl" name="ttl">
<option value="0" {{if or (eq .FormTTL "0") (eq .FormTTL "")}}selected{{end}}>Never</option>
<option value="60" {{if eq .FormTTL "60"}}selected{{end}}>1 minute</option>
<option value="3600" {{if eq .FormTTL "3600"}}selected{{end}}>1 hour</option>
<option value="86400" {{if eq .FormTTL "86400"}}selected{{end}}>1 day</option>
<option value="604800" {{if eq .FormTTL "604800"}}selected{{end}}>1 week</option>
<option value="2592000" {{if eq .FormTTL "2592000"}}selected{{end}}>30 days</option>
<option value="31536000" {{if eq .FormTTL "31536000"}}selected{{end}}>1 year</option>
</select>
</div>
</div>
<button type="submit">
Generate Encrypted URL
</button>
</form>
<p class="note">
Generated URLs are encrypted and cannot be modified. They will expire at the specified time.
</p>
</div>
<script src="/static/generator.js"></script>
</body>
</html>