Files
pixa/internal/templates/generator.html
T
clawbot a225560248
check / check (push) Canceled after 0s
Serve and accept JPEG XL as an image format (part of #222)
A JPEG XL source, a bare codestream or one in its container, is
fetched, detected and decoded, and orig of one is JPEG XL. The format
jxl works in plain and encrypted URLs and on the generator page,
served as image/jxl, and auto chooses it first when Accept names
image/jxl.

govips sends libvips a JPEG XL distance with every save, and libvips
then ignores the quality, so q is turned into a distance with libvips'
formula, keeping 100 lossy. govips cannot have libvips strip metadata
from JPEG XL, so it is removed from the image before saving; the
conversion to sRGB moved ahead of the format switch to run first.

Model: opus-5-5
2026-10-08 04:38:18 +00:00

162 lines
6.4 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 eq .FormFormat "jxl"}}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>