- svg-sanitize.ts: strip each dangerous element repeatedly until stable with
whitespace-tolerant end tags, defeating nested/overlapping tags (closes 5
incomplete-multi-character-sanitization + 1 bad-tag-filter; the prior
single-pass regex could leave a residual <script>/<iframe>).
- file-preview.ts: add a resolve()+containment barrier (the path-traversal
guard CodeQL recognizes) on top of the id charset check (closes 9
path-injection).
- metadata.ts: bound the XMP namespace:name key segments so parseXmp cannot
backtrack polynomially (closes js/polynomial-redos).
- analytics-disabled.spec.ts: match analytics by URL host, not substring
(closes 4 incomplete-url-substring-sanitization).
typecheck + lint green; svg (119), preview (22), metadata (164) tests pass.
Extends the platform to handle 7 new image format families alongside
the existing AVIF support gap-fill. Uses the established HEIC decoder
pattern (CLI decode → PNG → Sharp) for formats Sharp can't handle
natively: Camera RAW via dcraw_emu/LibRaw, PSD/TGA/EXR/HDR via
ImageMagick. JXL and ICO are Sharp-native. Adds server-side preview
for non-browser-displayable formats and JXL as a new convert output
target. All 27 validateImageBuffer callers updated with filename for
extension-based format detection.
Move sanitizeValue, parseExif, parseGps, parseXmp into the shared
image-engine package so both strip-metadata and edit-metadata can
reuse them. Includes 13 unit tests covering all four functions.