- Add language field to balance topup and landing purchase requests
- Cap news article featured image height with max-h-96
Cherry-picked from PR #362 (without favicon change — files don't exist)
- Register DOMPurify hooks at module init (not per sanitizeHtml call)
- Always set iframe allow attribute (not conditional on existing)
- Add AbortController to featured image upload for unmount cleanup
- Check defaultPrevented in React onDrop to prevent double upload with TipTap
- Remove explicit Content-Type header on upload (axios auto-sets boundary)
- Use DOMPurify(window) to avoid global hook pollution
- Fix controls default from boolean to empty string (HTML attribute semantics)
- Remove redundant non-null assertion on featured_image_url
TipTap didn't recognize <video> tags without a custom node extension,
serializing them as escaped text. Also revert video src to allow HTTP
since request.base_url returns http:// behind reverse proxy.
- uploadCount: always decrement in finally (prevent permanent uploading state)
- AbortSignal: pass to actual HTTP request (cancel network, not just UI)
- Concurrent uploads: use Set<AbortController> instead of single ref
- DOMPurify hooks: scope inside sanitizeHtml() to avoid global pollution
- Video src: restrict to HTTPS only (was allowing HTTP)
- GIF: remove from accept attributes (backend rejects GIF)
- Ref mutation: move handleMediaUploadRef update to useEffect