{"id":315190,"date":"2026-06-03T19:29:18","date_gmt":"2026-06-03T19:29:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/perfect-image-resize\/"},"modified":"2026-06-04T23:25:45","modified_gmt":"2026-06-04T23:25:45","slug":"australcode-uniform-images","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/australcode-uniform-images\/","author":23459699,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.36.1","stable_tag":"0.36.1","tested":"7.0","requires":"6.5","requires_php":"8.2","requires_plugins":null,"header_name":"Australcode Uniform Images","header_author":"Australcode","header_description":"Uniforma im\u00e1genes de productos de WooCommerce sin recortar y las sirve en formatos modernos (AVIF\/WebP\/JPEG) usando &lt;picture&gt;.","assets_banners_color":"ffffff","last_updated":"2026-06-04 23:25:45","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/uniform-images.australcode.io","header_author_uri":"https:\/\/australcode.io","rating":0,"author_block_rating":0,"active_installs":0,"downloads":90,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.34.0":{"tag":"0.34.0","author":"australcode","date":"2026-06-03 19:28:51"},"0.36.1":{"tag":"0.36.1","author":"australcode","date":"2026-06-04 23:25:45"}},"upgrade_notice":{"0.36.1":"<p>Page-builder detection now also covers Beaver Builder and Oxygen. Run a Bulk Regenerate (&quot;All used images&quot; scope) to optimize images placed in their templates.<\/p>","0.36.0":"<p>Bulk regeneration now detects images placed in Bricks and Elementor templates (page-builder content). Run a Bulk Regenerate (&quot;All used images&quot; scope) to optimize them.<\/p>","0.35.0":"<p>New opt-in setting: auto-detect transparency. Off by default \u2014 existing sites are unaffected. Enabling it regenerates derivatives.<\/p>","0.34.1":"<p>The admin UI is now fully translatable (English bundle 100%). No behavior changes \u2014 safe in-place upgrade.<\/p>","0.33.1":"<p>WordPress.org compliance and listing fixes. No user-facing behavior changes. Safe in-place upgrade.<\/p>","0.23.9":"<p>Uniform-by-default for all image sizes. After upgrading, run a Bulk Regenerate (Australcode Image \u2192 Bulk regenerate) to rebuild derivatives with the new uniform default.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3559924,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3559924,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3559924,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3559924,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.34.0","0.36.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3559985,"resolution":"1","location":"assets","locale":"","width":2400,"height":1800},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3559985,"resolution":"2","location":"assets","locale":"","width":2400,"height":1800},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3561665,"resolution":"3","location":"assets","locale":"","width":2400,"height":1800},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3559985,"resolution":"4","location":"assets","locale":"","width":2400,"height":1800},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3559985,"resolution":"5","location":"assets","locale":"","width":2400,"height":1800},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3559985,"resolution":"6","location":"assets","locale":"","width":2400,"height":1800},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3559985,"resolution":"7","location":"assets","locale":"","width":2400,"height":1800},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3559985,"resolution":"8","location":"assets","locale":"","width":2400,"height":1800}},"screenshots":{"1":"<strong>Dashboard<\/strong> \u2014 catalog metrics: processed images, generated derivatives, storage used, % savings when serving AVIF vs original, active quality preset, current bulk run.","2":"<strong>Settings<\/strong> \u2014 4-tier quality preset, per-size override, visual canvas color picker, sticky save bar that appears when changes are detected.","3":"<strong>Bulk regenerate<\/strong> \u2014 scope dropdown with real-time count, dry-run with storage and time estimation, embedded sample test with before\/after grid.","4":"<strong>Health<\/strong> \u2014 full diagnostic: active engine + codec capabilities matrix, DB tables with row count, applied migrations, CDN edge (Cloudflare Polish\/Mirage + Image Transformations detection).","5":"<strong>Clean library<\/strong> (Pro) \u2014 orphan image audit with Bricks Builder + wp_termmeta + WooCommerce shortcodes detection. Trash mode with typed confirmation and audit log.","6":"<strong>Catalog Watch<\/strong> (Pro) \u2014 daily cron that detects ghost derivatives, orphan files, and products with broken images. Auto-heal with dry-run preview before applying.","7":"<strong>Multi-Site Manager<\/strong> (Agency \/ Network) \u2014 centralized dashboard to monitor up to 25 sites (Agency) or 1000 sites (Network) of clients. BYO Application Password, aggregated metrics + status badges.","8":"<strong>License management<\/strong> (Pro) \u2014 activate, validate, and deactivate your license; per-tier activation counter; one-click upgrade path to a higher tier."}},"plugin_section":[],"plugin_tags":[194661,14337,24716,2956,286],"plugin_category":[45,50],"plugin_contributors":[265691],"plugin_business_model":[],"class_list":["post-315190","plugin","type-plugin","status-publish","hentry","plugin_tags-avif","plugin_tags-image-resize","plugin_tags-product-images","plugin_tags-thumbnails","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_category-media","plugin_contributors-australcode","plugin_committers-australcode"],"banners":{"banner":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/banner-772x250.png?rev=3559924","banner_2x":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/banner-1544x500.png?rev=3559924","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/icon-128x128.png?rev=3559924","icon_2x":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/icon-256x256.png?rev=3559924","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-1.png?rev=3559985","caption":"<strong>Dashboard<\/strong> \u2014 catalog metrics: processed images, generated derivatives, storage used, % savings when serving AVIF vs original, active quality preset, current bulk run."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-2.png?rev=3559985","caption":"<strong>Settings<\/strong> \u2014 4-tier quality preset, per-size override, visual canvas color picker, sticky save bar that appears when changes are detected."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-3.png?rev=3561665","caption":"<strong>Bulk regenerate<\/strong> \u2014 scope dropdown with real-time count, dry-run with storage and time estimation, embedded sample test with before\/after grid."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-4.png?rev=3559985","caption":"<strong>Health<\/strong> \u2014 full diagnostic: active engine + codec capabilities matrix, DB tables with row count, applied migrations, CDN edge (Cloudflare Polish\/Mirage + Image Transformations detection)."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-5.png?rev=3559985","caption":"<strong>Clean library<\/strong> (Pro) \u2014 orphan image audit with Bricks Builder + wp_termmeta + WooCommerce shortcodes detection. Trash mode with typed confirmation and audit log."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-6.png?rev=3559985","caption":"<strong>Catalog Watch<\/strong> (Pro) \u2014 daily cron that detects ghost derivatives, orphan files, and products with broken images. Auto-heal with dry-run preview before applying."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-7.png?rev=3559985","caption":"<strong>Multi-Site Manager<\/strong> (Agency \/ Network) \u2014 centralized dashboard to monitor up to 25 sites (Agency) or 1000 sites (Network) of clients. BYO Application Password, aggregated metrics + status badges."},{"src":"https:\/\/ps.w.org\/australcode-uniform-images\/assets\/screenshot-8.png?rev=3559985","caption":"<strong>License management<\/strong> (Pro) \u2014 activate, validate, and deactivate your license; per-tier activation counter; one-click upgrade path to a higher tier."}],"raw_content":"<!--section=description-->\n<p><strong>Australcode Uniform Images<\/strong> solves the classic WooCommerce catalog problem: product photos with different proportions that the theme crops brutally to align the grid. This plugin makes them uniform without cropping \u2014 it adds smart padding over a colored canvas (white by default), optionally trims the uniform background first to normalize inconsistent margins, and delivers each thumbnail in AVIF + WebP + JPEG using the <code>&lt;picture&gt;<\/code> element.<\/p>\n\n<h4>Key differentiators<\/h4>\n\n<ul>\n<li><strong>No accidental crops<\/strong> \u2014 the entire product fits inside the thumbnail, always. Compare with \"smart crop\" plugins that guess the subject and sometimes fail on small or asymmetric products.<\/li>\n<li><strong>Real <code>&lt;picture&gt;<\/code> markup<\/strong> \u2014 multi-source with AVIF + WebP + JPEG fallback. <strong>Survives any page cache<\/strong> (LiteSpeed, WP Rocket, Cloudflare APO, W3 Total Cache) because it does not use <code>Vary: Accept<\/code>. The browser picks the optimal format; the cache serves HTML without negotiation.<\/li>\n<li><strong>4-tier quality preset<\/strong> \u2014 Maximum \/ High \/ Standard \/ Economy with per-format values calibrated (e.g. Standard = AVIF Q60, WebP Q82, JPEG Q85 \u2014 visually indistinguishable from the original at half the size).<\/li>\n<li><strong>HPOS-ready from day one<\/strong> \u2014 declares <code>custom_order_tables<\/code> and <code>cart_checkout_blocks<\/code> compatibility without any setup.<\/li>\n<li><strong>Cloudflare Image Transformations (CIT)<\/strong> \u2014 optional integration to serve via Cloudflare edge (<code>\/cdn-cgi\/image\/format=auto<\/code>) with automatic availability detection on your zone. If CIT is not enabled on your CF plan, the plugin keeps serving local derivatives without breaking anything.<\/li>\n<\/ul>\n\n<h4>Free (no license required)<\/h4>\n\n<ul>\n<li><strong>Bulk regenerate with Action Scheduler<\/strong> \u2014 async processing resumable after worker death, error classification (<code>oom<\/code>, <code>missing_original<\/code>, <code>engine_failed<\/code>, <code>fs_permission<\/code>), scope filters (<code>auto<\/code> = products only based on Settings; <code>all-used<\/code> = every image referenced in posts\/products\/Bricks templates\/terms).<\/li>\n<li><strong>Embedded sample test<\/strong> \u2014 processes 1-5 images on demand and shows the before\/after grid with bytes and % savings. Available on the <strong>Settings<\/strong> page (\"Quick preview\") and on <strong>Bulk regenerate<\/strong> (\"Generate sample\").<\/li>\n<li><strong>Health page with CDN detection<\/strong> \u2014 engine diagnostics, encoders, filesystem permissions, detected competing plugins (Smush\/EWWW\/ShortPixel\/Imagify), Cloudflare Polish status (alerts if active \u2014 incompatible with the plugin's AVIF\/WebP), Image Prioritizer (Performance Lab) status with automatic detection.<\/li>\n<li><strong>Basic WP-CLI<\/strong> \u2014 9 commands: <code>wp acimg health<\/code>, <code>wp acimg stats<\/code>, <code>wp acimg regenerate<\/code>, <code>wp acimg derivatives &lt;id&gt;<\/code>, <code>wp acimg purge-cache<\/code>, <code>wp acimg restore-originals<\/code>, <code>wp acimg migrate-from-sir<\/code>, <code>wp acimg reset<\/code>. <code>wp acimg doctor<\/code> requires a license.<\/li>\n<\/ul>\n\n<h4>Pro (license required)<\/h4>\n\n<ul>\n<li><strong>Cloudflare Image Transformations (CIT) delivery<\/strong> \u2014 emits <code>&lt;img&gt;<\/code> with CIT URLs (<code>\/cdn-cgi\/image\/format=auto<\/code>) instead of local derivatives when CIT is enabled on your zone. Defensive automatic fallback to the normal path if CIT is unavailable.<\/li>\n<li><strong>Media Library audit + cleanup<\/strong> \u2014 orphan image detector that understands <strong>Bricks Builder<\/strong> (PHP serialize), <code>wp_termmeta<\/code>, WooCommerce shortcodes, custom meta. Trash mode with typed confirmation, immutable audit log, and an <code>untrash<\/code> endpoint for rollback.<\/li>\n<li><strong>Image Health Monitor<\/strong> \u2014 weekly cron that scans for missing derivatives, stale derivatives, Cloudflare Polish conflicts, and storage usage. Email digest to the admin only when there are actionable findings.<\/li>\n<li><strong>AI Alt Text BYOK<\/strong> \u2014 alt text generation per attachment via OpenAI Vision (<code>gpt-4o-mini<\/code>) or Anthropic Vision (<code>claude-haiku-4-5<\/code>). Bring Your Own Key (no Merchant of Record over AI costs). Context enrichment with WooCommerce product title + category + brand.<\/li>\n<li><strong>Catalog Watch + Auto-Heal<\/strong> \u2014 daily cron that detects ghost derivatives (DB rows without files), orphan files (files without DB rows), products with broken thumbnails. Auto-heal with dry-run preview + strict path validation. Persistent admin notice when there are actionable issues.<\/li>\n<li><strong>Multi-Site Manager<\/strong> (Agency tier+) \u2014 centralized dashboard to monitor up to 25 client sites from a single wp-admin. BYO Application Password, aggregated metrics (derivatives + bytes + issues), automatic hourly sync + ad-hoc. No external services: direct wp-admin \u2194 wp-admin communication via native REST.<\/li>\n<li><strong>CIT Cost Analyzer<\/strong> \u2014 daily pull from Cloudflare GraphQL Analytics API. MTD cost + monthly projection + peak day to identify spikes. BYO API token (CF authenticates directly).<\/li>\n<\/ul>\n\n<h4>Integration with other plugins<\/h4>\n\n<ul>\n<li><strong>Image Prioritizer \/ Performance Lab<\/strong> \u2014 Australcode Uniform Images detects <code>fetchpriority=\"high\"<\/code> and propagates correct loading\/decoding to the final <code>&lt;picture&gt;<\/code>. Native LCP optimization.<\/li>\n<li><strong>Bricks Builder<\/strong> \u2014 supports <code>wp_get_attachment_image<\/code> and optional output buffer rewriter for themes\/page builders that bypass that filter.<\/li>\n<li><strong>WP Rocket \/ a3 Lazy Load<\/strong> \u2014 compatible with <code>data-src<\/code>\/<code>data-sizes<\/code> lazy loaders (reads both if present).<\/li>\n<\/ul>\n\n<h4>v1.0 non-goals<\/h4>\n\n<ul>\n<li><strong>Smart crop<\/strong> \u2014 would break the \"no cropping\" promise. If you need that, this plugin is not for you.<\/li>\n<li><strong>SaaS-only \/ phone home<\/strong> \u2014 the plugin is 100% local. All optimization happens on your own server.<\/li>\n<li><strong>JPEG XL<\/strong> \u2014 format still immature in browsers. We will reevaluate in 2027.<\/li>\n<\/ul>\n\n<h4>How it compares<\/h4>\n\n\n\n\n  Concern\n  Smush \/ ShortPixel \/ Imagify\n  Australcode Uniform Images\n\n\n\n\n  Product photo cropping\n  Smart crop (algorithm guesses)\n  None \u2014 pads to a uniform canvas, full product always visible\n\n\n  Modern formats\n  WebP \/ AVIF (Pro\/paid tiers)\n  AVIF + WebP + JPEG via <code>&lt;picture&gt;<\/code> element\n\n\n  Page cache\n  <code>Vary: Accept<\/code> (breaks LiteSpeed, WP Rocket, Cloudflare APO)\n  <code>&lt;picture&gt;<\/code> element (cache-safe by design)\n\n\n  Pricing model\n  $5-15\/month SaaS subscription\n  One-time license, no SaaS dependency\n\n\n  WooCommerce-specific\n  Generic optimizer\n  Built for product grids \u2014 reads <code>wp_get_registered_image_subsizes()<\/code>, respects WC thumbnail_cropping setting\n\n\n  Processing location\n  SaaS server (your images leave)\n  100% local on your server\n\n\n\n\n<p>The other plugins optimize <strong>any image<\/strong>. Australcode Uniform Images does <strong>one job extremely well<\/strong>: uniform product thumbnails for WooCommerce grids, served cache-safe. If you already have one of the big plugins active, you can run Australcode side-by-side \u2014 it only touches images on registered WooCommerce sizes.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to third-party services <strong>only when you explicitly enable\nthe corresponding optional feature<\/strong>. The free, core functionality (uniform\nimages, AVIF\/WebP\/JPEG <code>&lt;picture&gt;<\/code>, bulk regenerate, health) runs <strong>100% on your\nown server and contacts no external service<\/strong>.<\/p>\n\n<h4>Lemon Squeezy (license validation \u2014 Pro)<\/h4>\n\n<p>When you activate, validate, or deactivate a Pro license, the plugin sends your\n<strong>license key<\/strong> and your <strong>site domain<\/strong> to the Lemon Squeezy License API\n(host <code>api.lemonsqueezy.com<\/code>, path <code>\/v1\/licenses\/<\/code>). A background cron revalidates\nthe license roughly every 24 hours. This only happens if you enter a license\nkey. No data is sent in the free version.<\/p>\n\n<ul>\n<li>Terms of Service: https:\/\/www.lemonsqueezy.com\/terms<\/li>\n<li>Privacy Policy: https:\/\/www.lemonsqueezy.com\/privacy<\/li>\n<\/ul>\n\n<h4>OpenAI \/ Anthropic (AI Alt Text \u2014 Pro, Bring Your Own Key)<\/h4>\n\n<p>If you enable <strong>AI Alt Text<\/strong> and provide your own API key, the plugin sends the\n<strong>image<\/strong> (as a base64 data URI) plus the related <strong>WooCommerce product context<\/strong>\n(title, category, brand) to the provider you choose, to generate alt text:<\/p>\n\n<ul>\n<li>OpenAI Vision (<code>gpt-4o-mini<\/code>) \u2014 host <code>api.openai.com<\/code>, path <code>\/v1\/chat\/completions<\/code>\n\n<ul>\n<li>Terms: https:\/\/openai.com\/policies\/terms-of-use<\/li>\n<li>Privacy: https:\/\/openai.com\/policies\/privacy-policy<\/li>\n<\/ul><\/li>\n<li>Anthropic Vision (<code>claude-haiku-4-5<\/code>) \u2014 host <code>api.anthropic.com<\/code>, path <code>\/v1\/messages<\/code>\n\n<ul>\n<li>Terms: https:\/\/www.anthropic.com\/legal\/consumer-terms<\/li>\n<li>Privacy: https:\/\/www.anthropic.com\/legal\/privacy<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<p>This runs only when you trigger alt text generation and only with the key you\nsupply. The plugin is not a Merchant of Record for these AI costs (BYOK).<\/p>\n\n<h4>Cloudflare (Image Transformations + Cost Analyzer \u2014 Pro)<\/h4>\n\n<p>If you enable <strong>Cloudflare Image Transformations (CIT)<\/strong>, image URLs of your own\nsite are served through Cloudflare's edge (<code>\/cdn-cgi\/image\/...<\/code>) so Cloudflare can\ntransform them on-demand. If you enable the <strong>CIT Cost Analyzer<\/strong>, the plugin\nqueries the Cloudflare GraphQL Analytics API\n(host <code>api.cloudflare.com<\/code>, path <code>\/client\/v4\/graphql<\/code>) with the API token <strong>you provide<\/strong>\nand your zone identifier, to report usage and cost. The plugin also performs a\n    HEAD request to one of <strong>your own<\/strong> derivative URLs to detect whether CIT and\nCloudflare Polish are active on your zone (no third-party data is sent in that\ndetection).<\/p>\n\n<ul>\n<li>Terms of Service: https:\/\/www.cloudflare.com\/terms\/<\/li>\n<li>Privacy Policy: https:\/\/www.cloudflare.com\/privacypolicy\/<\/li>\n<\/ul>\n\n<!--section=installation-->\n<h4>Via WordPress Admin (recommended)<\/h4>\n\n<ol>\n<li>Go to <strong>Plugins \u2192 Add new<\/strong> in your WP admin, search for \"Australcode Uniform Images\" and click Install + Activate.<\/li>\n<li>Navigate to the new top-level menu <strong>Australcode Image \u2192 Settings<\/strong> and choose your quality preset (default Standard works well for most cases).<\/li>\n<li>Go to <strong>Australcode Image \u2192 Bulk regenerate<\/strong>, run a Sample Test with one product to validate visually, then click \"Start bulk\" to process the full catalog.<\/li>\n<\/ol>\n\n<h4>Via WP-CLI<\/h4>\n\n<pre><code>`\n<\/code><\/pre>\n\n<p>wp plugin install australcode-uniform-images --activate\nwp acimg health           # verify everything is OK\nwp acimg regenerate       # bulk dry-run\nwp acimg regenerate --start --yes   # starts bulk in the background\n    `<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20it%20compatible%20with%20woocommerce%20hpos%20%28high-performance%20order%20storage%29%3F\"><h3>Is it compatible with WooCommerce HPOS (High-Performance Order Storage)?<\/h3><\/dt>\n<dd><p>Yes. Compatibility with <code>custom_order_tables<\/code> and <code>cart_checkout_blocks<\/code> is declared from day one via <code>before_woocommerce_init<\/code>. No manual configuration required.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20cloudflare%3F\"><h3>Does it work with Cloudflare?<\/h3><\/dt>\n<dd><p>Yes, and well. The plugin emits <code>&lt;picture&gt;<\/code> with <code>&lt;source&gt;<\/code> per MIME type \u2014 <strong>it survives Cloudflare APO<\/strong> and any page cache perfectly because it does NOT use <code>Vary: Accept<\/code> (which would break caching).<\/p>\n\n<p>If you have <strong>Cloudflare Pro+<\/strong>, you can enable <strong>Image Transformations<\/strong> from Settings \u2192 CDN edge. The plugin automatically detects whether CIT is available on your zone and emits <code>\/cdn-cgi\/image\/<\/code> URLs that CF transforms on-demand with <code>format=auto<\/code>.<\/p>\n\n<p><strong>Caution with Cloudflare Polish<\/strong>: if active, it re-compresses the AVIF\/WebP that the plugin already optimized \u2014 double compression equals visual artifacts. The plugin detects this on the Health page and alerts you with an admin notice. Recommendation: disable Polish, keep APO.<\/p><\/dd>\n<dt id=\"which%20image%20engine%20does%20it%20use%3F\"><h3>Which image engine does it use?<\/h3><\/dt>\n<dd><p><strong>Imagick<\/strong> (preferred) with <code>libheif<\/code> for AVIF. <strong>GD<\/strong> as fallback. <strong>libvips<\/strong> is wired in the code but requires bundled binaries (not included in v0.x \u2014 future sprint). The active engine and its capabilities (read\/write per format) appear on <strong>Health \u2192 Image engines<\/strong>.<\/p><\/dd>\n<dt id=\"do%20i%20need%20anything%20special%20for%20avif%3F\"><h3>Do I need anything special for AVIF?<\/h3><\/dt>\n<dd><p>Imagick compiled with <code>libheif<\/code> (common on modern hosts: Kinsta, WP Engine, SiteGround, recent Cloudways). If Imagick does not support AVIF, the plugin still emits WebP + JPEG and the Health page reports the limitation. <strong>You do not get stuck without anything<\/strong> \u2014 you just lose the most efficient format.<\/p><\/dd>\n<dt id=\"how%20much%20storage%20does%20it%20use%3F\"><h3>How much storage does it use?<\/h3><\/dt>\n<dd><p>Estimate: ~700 KB of derivatives on average per original image at Standard preset (varies a lot by content type \u2014 product photos with a uniform background compress better). For a catalog of 1,000 products with one image each, that's ~700 MB of derivatives. The plugin <strong>NEVER touches the original<\/strong> on disk, so you need space for original + derivatives.<\/p><\/dd>\n<dt id=\"how%20do%20i%20regenerate%20after%20changing%20settings%3F\"><h3>How do I regenerate after changing settings?<\/h3><\/dt>\n<dd><p>Change settings on <strong>Australcode Image \u2192 Settings<\/strong>, save (the plugin shows a modal warning you that existing derivatives are invalidated), and then go to <strong>Bulk regenerate<\/strong> or run <code>wp acimg regenerate --start --yes<\/code>. The plugin keeps serving the old derivatives until regeneration completes \u2014 <strong>zero visual downtime<\/strong>.<\/p><\/dd>\n<dt id=\"conflicts%20with%20smush%20%2F%20ewww%20%2F%20shortpixel%20%2F%20imagify%3F\"><h3>Conflicts with Smush \/ EWWW \/ ShortPixel \/ Imagify?<\/h3><\/dt>\n<dd><p>Yes, <strong>disable those plugins<\/strong> before installing Australcode Uniform Images. The Health \u2192 Doctor page detects them and alerts you. The typical conflict is that those plugins also hook into <code>wp_get_attachment_image<\/code> and rewrite the HTML \u2014 the output ends up inconsistent.<\/p><\/dd>\n<dt id=\"does%20it%20have%20wp-cli%3F\"><h3>Does it have WP-CLI?<\/h3><\/dt>\n<dd><p>Yes, 9 commands under <code>wp acimg &lt;subcommand&gt;<\/code>: health (CI smoke test), stats, regenerate, derivatives , purge-cache, restore-originals, migrate-from-sir, reset (resets all persisted state without deactivating) \u2014 all available in the free version. <code>wp acimg doctor<\/code> (extended diagnostics) requires a Pro license. Each command supports <code>--format=json<\/code>. <code>wp help acimg<\/code> lists them all.<\/p><\/dd>\n<dt id=\"how%20do%20i%20report%20a%20bug%20or%20request%20a%20feature%3F\"><h3>How do I report a bug or request a feature?<\/h3><\/dt>\n<dd><p>Open a support thread in the WordPress.org plugin support forum (linked from the plugin page sidebar). For Pro license-related issues, contact support@australcode.io.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.36.1<\/h4>\n\n<ul>\n<li>Page-builder coverage extended to Beaver Builder (<code>_fl_builder_data<\/code>) and Oxygen (<code>ct_builder_shortcodes<\/code>). The detection now combines two strategies per builder: structured ID extraction (precise for Bricks\/Elementor) and a universal URL scan of the builder's stored markup (covers Beaver, Oxygen, and any builder that embeds the image URL). Divi\/WPBakery remain covered via <code>post_content<\/code>.<\/li>\n<\/ul>\n\n<h4>0.36.0<\/h4>\n\n<ul>\n<li>Page-builder coverage: Bulk Regenerate (\"All used images\" scope) now detects images placed directly in Bricks and Elementor templates \u2014 they live in the builder's own storage (<code>_bricks_page_content<\/code>, <code>_elementor_data<\/code>), outside <code>post_content<\/code>, so previous versions never found or optimized them. Divi was already covered (it stores in <code>post_content<\/code>). The frontend delivery already handled any <code>&lt;img&gt;<\/code> from any builder; this closes the generation side.<\/li>\n<li>Bulk runs now process exactly what the chosen scope selected: the \"All used images\" scope optimizes every used image (products and non-products alike), instead of silently skipping images whose post type isn't in the processing filter. The per-type filter still governs automatic processing on upload.<\/li>\n<\/ul>\n\n<h4>0.35.0<\/h4>\n\n<ul>\n<li>New (opt-in): auto-detect transparency. When enabled, images whose original has significant transparency (logos, cut-out products with shadows) keep their alpha channel \u2014 the plugin uses a transparent canvas and a PNG raster fallback instead of flattening onto the canvas color. WebP and AVIF already preserve transparency. Off by default, so existing sites are unaffected until you turn it on (which regenerates derivatives). Set it in Settings \u2192 Formats &amp; quality \u2192 Transparency.<\/li>\n<\/ul>\n\n<h4>0.34.1<\/h4>\n\n<ul>\n<li>Internationalization: the admin JavaScript layer is now fully translatable. All dynamic UI text in Bulk Regenerate and Clean Library (counters, confirmations, progress, summaries, error messages) \u2014 plus the previously localized Catalog Watch, Multi-Site, CIT Cost Analyzer and settings preview \u2014 now routes through WordPress translations instead of hardcoded strings.<\/li>\n<li>The English (en_US) translation bundle is now 100% complete.<\/li>\n<li>No behavior changes: every string keeps its original fallback until the site's active language provides a translation.<\/li>\n<\/ul>\n\n<h4>0.34.0<\/h4>\n\n<ul>\n<li>Pro: new per-aspect-ratio mode overrides. For each main WooCommerce size you can choose how each aspect ratio is processed (square 1:1, 4:3, 16:9, portrait, etc.): uniform with canvas, proportional without cropping, or skip. For example, keep square images on \"proportional\" while the rest of the size follows its base mode. Available on all paid plans.<\/li>\n<li>The per-aspect override is wired into the generation pipeline (upload and bulk regeneration) and into derivative invalidation, so changing it regenerates only what is needed.<\/li>\n<li>Visibility: the Dashboard now shows how many images were skipped by the context filter (not attached to a processable post type), with a shortcut to adjust the filter. Avoids the \"I uploaded an image and nothing happened\" confusion.<\/li>\n<\/ul>\n\n<h4>0.33.2<\/h4>\n\n<ul>\n<li>Security: REST endpoints that operate on attachments now verify the edit\/delete capability per attachment (current_user_can edit_post\/delete_post), in addition to the general manage_woocommerce gate.<\/li>\n<\/ul>\n\n<h4>0.33.1<\/h4>\n\n<p>WP.org re-submission compliance + listing polish. No user-facing behavior changes \u2014 safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>External services URLs no longer pingable as 404<\/strong> \u2014 the readme's \"External services\" section referenced API endpoints (<code>api.lemonsqueezy.com<\/code>, <code>api.openai.com<\/code>, <code>api.anthropic.com<\/code>, <code>api.cloudflare.com<\/code>) as full URLs. WP.org's review scanner pings every URL in the readme and flagged the Lemon Squeezy endpoint as a broken Terms\/Privacy URL. Endpoints are now declared as host + path (not full clickable URLs); Terms\/Privacy links remain and resolve.<\/li>\n<li><strong>Explicit output-buffer close<\/strong> \u2014 <code>OutputBufferHook<\/code> (opt-in feature, off by default) now closes its <code>ob_start()<\/code> buffer explicitly on <code>shutdown<\/code>, guarded by <code>ob_get_level()<\/code>. Same rewritten output, paired open\/close as WP.org guidelines expect. WP 6.5+ compatible.<\/li>\n<li><strong>Banners + branding<\/strong> \u2014 re-generated WP.org banners with the current name (Australcode Uniform Images) and version; renamed the last legacy global variable in the bootstrap file.<\/li>\n<li><strong>Listing polish<\/strong> \u2014 sharper short description and tags for the target niche, added Upgrade Notice, fixed screenshot #8 caption, aligned WP-CLI command count between Description and FAQ.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing.<\/p>\n\n<h4>0.33.0<\/h4>\n\n<p>Lote C \u2014 WP.org compliance fixes residuales para re-submission. Cierra los puntos del review WP.org del 20-May que no quedaron cubiertos por el rebrand inicial. Cero breaking changes a nivel de usuario.<\/p>\n\n<ul>\n<li><strong><code>league\/container<\/code> bumped 4.2.5 \u2192 5.2.0<\/strong> \u2014 la librer\u00eda de DI bumpea major sin breaking changes en la API que el plugin usa (<code>add<\/code>, <code>addShared<\/code>, <code>delegate(new ReflectionContainer(true))<\/code>, <code>get<\/code>). 296\/296 unit tests passing post-bump; runtime integraci\u00f3n validada en wp-sandbox-staging.<\/li>\n<li><strong>Removed GitHub URLs from readme.txt<\/strong> \u2014 la documentaci\u00f3n p\u00fablica del plugin (Installation, FAQ \"How do I report a bug?\", footer) apunta ahora exclusivamente a recursos accesibles p\u00fablicamente: WP.org plugin page para download\/install, support forum WP.org para reportes de issues free, support@australcode.io para Pro license issues. El repo de desarrollo es privado por dise\u00f1o; los users no necesitan acceso al c\u00f3digo fuente para usar el plugin (que viene con el ZIP del listing WP.org).<\/li>\n<li><strong>Internal repo rename<\/strong> \u2014 el repo de desarrollo se renombr\u00f3 a <code>australcode-uniform-images<\/code> para coherencia con el slug del plugin (era <code>conecta-image-resize<\/code> del codename interno legacy). Cambio invisible al usuario final; solo afecta workflow del autor.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.33.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido desde v0.23.14).<\/p>\n\n<h4>0.32.0<\/h4>\n\n<p>Lote B \u2014 fix de 4 hallazgos P1 de UX clarity de la prueba humana en drbrowns prod sobre v0.31.0. Cero breaking changes \u2014 solo correcciones de copy + tooltips. Safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Dashboard header \u2014 botones con contexto<\/strong> \u2014 los CTAs del header del Dashboard pasaron de etiquetas neutras (\"Generar muestra\" \/ \"Configuraci\u00f3n\") a etiquetas con flecha de navegaci\u00f3n + tooltip explicativo: \"Probar con muestra \u2192\" (con tooltip \"Probar el plugin con 1\u20135 im\u00e1genes antes de procesar el cat\u00e1logo completo\") y \"Configuraci\u00f3n \u2192\" (con tooltip \"Calidad, formatos, tama\u00f1os y delivery del plugin\"). La flecha indica que llevan a otra p\u00e1gina; el tooltip da el porqu\u00e9.<\/li>\n<li><strong>Settings \u2014 copy de heur\u00edstica sizes legible<\/strong> \u2014 el lede \"Por cada size, elige c\u00f3mo el plugin lo procesa. 'Auto' usa la heur\u00edstica por defecto (sizes con crop=true \u2192 uniforme; proporcional \u2192 proporcional; legacy\/plugins viejos \u2192 omitir)\" ahora habla en idioma de usuario: \"las im\u00e1genes pensadas para grilla (cuadradas) se uniforman; las pensadas para flujo (rectangulares) mantienen su proporci\u00f3n; las creadas por plugins antiguos que ya no usas se ignoran\". Misma l\u00f3gica, vocabulario no-t\u00e9cnico. Footer del table tambi\u00e9n re-escrito.<\/li>\n<li><strong>Bulk page \u2014 leds t\u00e9cnicos rewriteados estilo WP Rocket<\/strong> \u2014 los tres helpers principales (header lede, \"Generar muestra\" lede, \"Procesamiento masivo\" lede + helper de cantidad) pasaron de mencionar \"Action Scheduler\", \"background\", \"scope\", \"bypasea\", \"lotes de 5 cada 5 segundos\" a explicaciones orientadas a beneficios + caveats sin jargon: \"corre en segundo plano \u2014 puedes cerrar esta p\u00e1gina, el trabajo contin\u00faa solo\", \"ignora tus filtros de Configuraci\u00f3n a prop\u00f3sito\", \"Cada una toma unos 5\u201315 segundos en alta calidad\".<\/li>\n<li><strong>Catalog Watch \u2014 flujo 3-step expl\u00edcito + tooltips<\/strong> \u2014 los 3 botones \"Escanear ahora\" \/ \"Vista previa de reparaci\u00f3n\" \/ \"Aplicar reparaci\u00f3n\" ganaron tooltips per-bot\u00f3n explicando qu\u00e9 hace cada uno, y debajo del row hay un nuevo helper \"Flujo recomendado: 1) Escanear para detectar problemas. 2) Vista previa para ver qu\u00e9 se borrar\u00eda (no modifica nada). 3) Aplicar para ejecutar la limpieza cuando est\u00e9s conforme\". El usuario ya no tiene que adivinar qu\u00e9 hace \"vista previa\" vs \"aplicar\".<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.32.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido desde v0.23.14).<\/p>\n\n<h4>0.31.0<\/h4>\n\n<p>Lote A \u2014 fix de 3 hallazgos P0 visuales de la prueba humana en drbrowns prod sobre v0.30.0. Cero breaking changes \u2014 solo correcciones de layout y copy. Safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Notice positioning fix<\/strong> \u2014 agrega el marker <code>&lt;hr class=\"wp-header-end\" \/&gt;<\/code> despu\u00e9s del header de cada admin page (10 pages: Dashboard, Configuraci\u00f3n, Regenerar, Limpiar, Errores, Salud, Licencia, Multi-Site, CIT Cost, Catalog Watch). WordPress usa este marker para posicionar <code>admin_notices<\/code> correctamente; sin \u00e9l, los notices del plugin (ej. <code>CatalogIssuesNotice<\/code> con 80892 issues) quedaban atravesados visualmente entre el t\u00edtulo y los badges de versi\u00f3n\/estado.<\/li>\n<li><strong>WP Customizer path correcto<\/strong> \u2014 el copy del banner \"Para que tus productos se vean uniformes en la grilla\" ahora muestra la ruta completa <code>Apariencia \u2192 Personalizar \u2192 WooCommerce \u2192 Im\u00e1genes de producto \u2192 Cropping \u2192 1:1 (cuadrado)<\/code> en vez de la versi\u00f3n truncada anterior. Refleja la navegaci\u00f3n real de WP-Admin para que el usuario encuentre el setting al primer intento.<\/li>\n<li><strong>AI Alt Text section layout<\/strong> \u2014 la secci\u00f3n \"Alt text con IA\" (Pro) ahora sale del grid <code>acimg-settings-layout<\/code> (TOC sticky + form 1fr) y se renderiza como sibling <code>&lt;div class=\"acimg-settings-aux\"&gt;<\/code> debajo, con ancho completo y background blanco. Antes quedaba en el slot <code>__full<\/code> del grid pero el aside sticky de TOC la tapaba visualmente; tambi\u00e9n usaba clases hu\u00e9rfanas (<code>acimg-section<\/code>) que no existen en el CSS \u2014 ahora usa <code>acimg-surface<\/code> como el resto de cards de Settings, manteniendo coherencia visual.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.31.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido desde v0.23.14).<\/p>\n\n<h4>0.30.0<\/h4>\n\n<p>Final commercial-ready release \u2014 agrupa cierre del backlog perfeccionista post-audit 2026-05-25. Cero breaking changes acumulados entre v0.25 \u2192 v0.30, todos los bumps fueron polish + ADDs + transformations defensibles. Safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Re-capturados los 8 screenshots WP.org<\/strong> (1200\u00d7900) con todo el polish aplicado: icon SVG header branded + TOC lateral sticky en Settings + upgrade card en License + KPI \"Ahorro estimado\" + 9 commands WP-CLI + 4 Pro pages funcionales. Los screenshots muestran al usuario potencial el estado real del plugin con polish post-v0.25.<\/li>\n<li><strong>Skip jump v0.29.0<\/strong> \u2014 version skip intencional para reflejar el major polish accumulated (v0.25 \u2192 v0.30 incluye 5 bumps: v0.26 visual identity + v0.27 Settings TOC + v0.28 License upgrade + el cierre v0.30 con los screenshots updated + readme final).<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.30.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido desde v0.23.14, 6 meses estable).<\/p>\n\n<h4>0.28.0<\/h4>\n\n<p>License page upgrade path (Sprint T4 direct, T-003 audit 2026-05-25). Cero breaking changes \u2014 additions limpios.<\/p>\n\n<ul>\n<li><strong>License page \u2014 upgrade path card<\/strong> \u2014 converts the License page from \"pure information\" to \"information + contextual actions\". When the user has a tier below Network, a new card appears below the existing license info showing upgrade options: tier name + sites count + Pro badge + CTA \"Upgrade a X \u2192\" with direct deep link to the Lemon Squeezy upgrade flow per tier. Mapping: Single \u2192 Studio + Agency \/ Studio \u2192 Agency + Network \/ Agency \u2192 Network. Help text post-card explains \"Lemon Squeezy issues your new license key instantly; apply the upgrade from this same page by pasting the new key and activating\".<\/li>\n<li><strong>Network tier max state<\/strong> \u2014 when the user already has Network tier (top), the upgrade card is replaced by a \"Tier m\u00e1ximo activo\" card with <code>acimg-badge--pro<\/code> Network + thank-you message + \"\u2709 Contactar soporte priority\" CTA mailto link to support@australcode.io.<\/li>\n<li><strong>New utility CSS<\/strong> <code>.acimg-upgrade-grid<\/code> + <code>.acimg-upgrade-card<\/code> \u2014 responsive grid layout (auto-fit, minmax 220px) collapsing to 1 column on mobile. Each card uses existing DS tokens (<code>--bg-surface<\/code>, <code>--border-default<\/code>, <code>--radius-md<\/code>, <code>--fs-15<\/code>, etc).<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.28.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido).<\/p>\n\n<h4>0.27.0<\/h4>\n\n<p>Major UX upgrade for the Settings page (Sprint T1 mockup-first). Cero breaking changes \u2014 el HTML interno de cada section se preserva exacto. Safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Settings page \u2014 lateral sticky TOC + smooth scroll<\/strong> \u2014 the Configuration page used to be a 3500px linear scroll on mobile (10 sections back-to-back). Now there's a sticky lateral navigation (left sidebar 200px desktop \/ <code>&lt;select&gt;<\/code> dropdown mobile) with smooth-scroll on click and IntersectionObserver-driven active state highlighting (the section currently centered in viewport gets accent bg in the TOC). Deep links to specific sections via URL hash also work (e.g. <code>#acimg-anchor-ai-alt-text<\/code> lands the user directly on AI Alt Text section). The Dashboard CTA card \"Configurar ahora \u2192\" now lands precisely on the AI Alt Text section.<\/li>\n<li><strong>DS integration<\/strong> \u2014 the new layout uses tokens existing en <code>admin.css<\/code>: <code>--bg-surface<\/code>, <code>--border-default<\/code>, <code>--bg-selected<\/code>, <code>--accent-600<\/code>, <code>--radius-md<\/code>, <code>--radius-xs<\/code>. Sticky position with <code>top: 32px<\/code> offset for WordPress admin bar. Max-height <code>calc(100vh - 64px)<\/code> con <code>overflow-y: auto<\/code> para sections muy largas. Section anchors (<code>.acimg-section-anchor<\/code>) usan <code>scroll-margin-top: 64px<\/code> para que el hash navigation no quede oculto bajo el admin bar.<\/li>\n<li><strong>Mobile responsive<\/strong> \u2014 el TOC sticky collapsa a <code>&lt;select&gt;<\/code> dropdown con label \"Ir a secci\u00f3n\u2026\" cuando viewport \u2264 900px. Smooth scroll funciona igual.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.27.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido). 1 nuevo asset JS encolado en Settings page (<code>acimg-settings-toc<\/code>).<\/p>\n\n<h4>0.26.0<\/h4>\n\n<p>Visual identity boost (Sprint H1 cross-leverage Bsale patterns). Cero breaking changes, cero migrations \u2014 safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Branded icon SVG in admin page header<\/strong> \u2014 every admin page now displays the plugin's mark icon (Concept C \u2014 image inscribed in a canvas) on the left side of the title, with accent color and a subtle background. Applied via CSS pseudo-element so all 15+ page header occurrences benefit automatically without per-page changes. Cross-leverage pattern from <code>australcode-bsale<\/code> (audit familia 2026-05-26).<\/li>\n<li><strong>Highlighted CTA card for Pro features needing configuration<\/strong> \u2014 when the user has Pro license active but AI Alt Text is not configured, the Dashboard now shows a left-accent CTA card guiding them to \"Configurar ahora \u2192\" with a deep link to the Settings AI Alt Text section. Reduces silent friction where the user pays Pro and doesn't find how to activate the feature.<\/li>\n<li><strong>DashboardPage constructor<\/strong> \u2014 2 new deps autowired by <code>League\\Container<\/code>: <code>LicenseGate<\/code> + <code>AiConfigRepository<\/code> (both already registered in the container, zero migration impact).<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.26.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido).<\/p>\n\n<h4>0.25.0<\/h4>\n\n<p>Transformations ADDs (no breaking changes, no migrations) \u2014 Sprint E del backlog post-v0.24.0 audit 2026-05-25.<\/p>\n\n<ul>\n<li><strong>New (Dashboard) \u2014 KPI \"Ahorro estimado\" en hero<\/strong> \u2014 un 5to KPI card al lado de \"Ahorro al servir AVIF (%)\" ahora muestra el ahorro <strong>en bytes humanos<\/strong> (ej. \"50 MB\"). Heur\u00edstica: <code>sum(original_bytes - avif_bytes)<\/code> over all processed attachments, asume ~99.5% visitors compatibles con AVIF (default 2026). Convierte el dashboard de \"estado\" a \"valor demostrado\" \u2014 el usuario ve cu\u00e1nto le ahorr\u00f3 el plugin en cifras concretas, no solo en %.<\/li>\n<li><strong>Documented (Settings) \u2014 modal pre-save \"Esto invalidar\u00e1 N derivados\"<\/strong> \u2014 el modal ya exist\u00eda desde v0.23.x pero no estaba destacado en el listing. Ahora documentado: al click \"Guardar configuraci\u00f3n\" con cambios que afectan el <code>pipeline_hash<\/code> (padMode, padColor, trim, quality preset, AVIF speed, formats enabled, etc.), aparece dialog con: count de derivados a invalidar, bytes en storage, lista exacta de campos que cambiaron, link a \"Regenerar en lote\" para reconstruir, opciones \"Cancelar\" \/ \"Guardar de todos modos\". Cero sorpresa para el usuario al cambiar settings.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check sobre v0.25.0 esperado 0 errors \/ 155 warnings (baseline S3 mantenido). El m\u00e9todo privado <code>estimateSavings()<\/code> en <code>DashboardPage<\/code> retorna un campo nuevo <code>bytes_saved<\/code> adem\u00e1s de los existentes (sin breaking changes \u2014 campos viejos preservados).<\/p>\n\n<h4>0.24.1<\/h4>\n\n<p>Polish + DS coherence pass \u2014 no functional changes, no migrations, safe in-place upgrade.<\/p>\n\n<ul>\n<li><strong>Polish \u2014 status indicators<\/strong> \u2014 6 emoji occurrences in admin UI (white check, warning, red circle, lock) replaced with the canonical <code>.acimg-dot--*<\/code> color-coded indicators. Reasons: cross-OS rendering consistency, no impact on flex\/grid alignment, screen reader friendlier (no \"white heavy check mark\" noise). Affected: Settings flash notice, Catalog Watch issues empty state, Multi-Site issues column + help list.<\/li>\n<li><strong>Polish \u2014 admin copy es-CL canonical<\/strong> \u2014 8 strings switched from hybrid EN\/ES to neutral Chilean Spanish: \"Vista previa heal\" \u2192 \"Vista previa de reparaci\u00f3n\", \"Aplicar heal\" \u2192 \"Aplicar reparaci\u00f3n\", \"Auto-Heal\" \u2192 \"Auto-reparaci\u00f3n\", \"Sync all\" \u2192 \"Sincronizar todos\", \"Refresh ahora\" \u2192 \"Refrescar ahora\", \"Sample test\" \u2192 \"Generar muestra\" (3 occurrences in Dashboard).<\/li>\n<li><strong>Polish \u2014 voseo cleanup<\/strong> \u2014 <code>wp acimg purge-cache --all<\/code> confirmation prompt no longer uses Rioplatense \"CONFIRM\u00c1S\". Now says \"\u00bfConfirmas borrar TODOS los derivados?\".<\/li>\n<li><strong>DS \u2014 <code>.acimg-btn--loading<\/code> utility<\/strong> added in <code>assets\/css\/admin.css<\/code>. Spinner reusable for any AJAX button (reuses existing <code>@keyframes acimg-spin<\/code>). Companion helper <code>acimgWithLoading(btn, asyncFn)<\/code> exposed globally via the new <code>assets\/js\/btn-loading.js<\/code> (always enqueued on plugin pages).<\/li>\n<li><strong>DS \u2014 <code>surface<\/code> vs <code>card<\/code> convention<\/strong> documented inline in <code>admin.css<\/code> to prevent drift. <code>.acimg-surface<\/code> = main section with <code>&lt;h2&gt;<\/code> visible. <code>.acimg-card<\/code> = banner \/ sub-content \/ status panel without title.<\/li>\n<li><strong>CLI \u2014 <code>wp acimg purge-cache --dry-run<\/code> flag<\/strong> added as explicit alias of the safe default behavior (mutually exclusive with <code>--yes<\/code>). Aligns with standard WP-CLI convention for destructive commands.<\/li>\n<li><strong>Docs \u2014 readme accurately lists 9 WP-CLI commands<\/strong> (previously said 8, missing <code>wp acimg reset<\/code> which resets all persisted plugin state without deactivating). FAQ entry expanded with the same correction.<\/li>\n<\/ul>\n\n<p>Internal: 296\/296 unit tests passing. Plugin Check 0 errors, 155 warnings (S3 baseline maintained).<\/p>\n\n<h4>0.24.0<\/h4>\n\n<ul>\n<li><strong>New (Pro) \u2014 AI Alt Text admin UI<\/strong> \u2014 the BYOK alt text generation feature (OpenAI gpt-4o-mini \/ Anthropic claude-haiku-4-5) now has three dedicated UI surfaces:\n\n<ul>\n<li><strong>Settings \u2192 \"Alt text con IA\"<\/strong> section: provider select, masked API key field, language picker, \"Save\" + \"Generate test\" buttons that hit <code>\/alt-text\/generate\/&lt;lastAttachmentId&gt;<\/code> with <code>apply: false<\/code> for instant preview.<\/li>\n<li><strong>Attachment editor \u2192 \"Alt text con IA\"<\/strong> field: \"Generate with AI\" button next to the native Alt text field; preview before apply; one click fills the native field. Works in <code>post.php?action=edit<\/code> and the media modal.<\/li>\n<li><strong>Media library bulk action<\/strong>: \"Generate alt with AI\" entry in <code>upload.php?mode=list<\/code> bulk dropdown; processes selected attachments in batches of 5 with anti-rate-limit pacing (OpenAI 10rpm tier 1 \/ Anthropic 50rpm).<\/li>\n<\/ul><\/li>\n<li>All three surfaces are gated server-side (Pro license active + AI config present + <code>manage_woocommerce<\/code> capability) and gracefully hide for Free users.<\/li>\n<li><strong>Fix (P0 WP.org compliance)<\/strong> \u2014 <code>uninstall.php<\/code> cleanup query was matching the legacy <code>pir_<\/code> prefix instead of the current <code>acimg_<\/code> after the rebrand, leaving up to 8 options (including encrypted license key and AI API key) residual in the DB after uninstall. Now matches <code>acimg_%<\/code> correctly.<\/li>\n<li><strong>Fix (P0 mobile polish)<\/strong> \u2014 format chips (JPEG \/ WebP \/ AVIF) in the Dashboard \"Configuraci\u00f3n actual\" card were breaking across two lines on mobile (\"JPE G\" \/ \"WEB P\" \/ \"AVI F\") because <code>.acimg-chip<\/code> had no <code>white-space: nowrap<\/code>. Now chips stay on one line and wrap to a new row only if there isn't enough horizontal space.<\/li>\n<li><strong>Fix (CLI copy)<\/strong> \u2014 <code>wp acimg regenerate<\/code> dry-run success message used a Rioplatense Spanish conjugation (\"pas\u00e1\") instead of neutral Chilean Spanish (\"pasa\"). Corrected.<\/li>\n<li><strong>Fix (defensive)<\/strong> \u2014 <code>Dashboard::sumOriginalBytesProcessed()<\/code> now uses <code>unserialize($x, ['allowed_classes' =&gt; false])<\/code> for <code>_wp_attachment_metadata<\/code> parsing, matching the defensive pattern already in <code>SirMigrator<\/code> and <code>MediaAuditController<\/code> (regression: 1 of 7 occurrences was missing the guard).<\/li>\n<\/ul>\n\n<h4>0.23.17<\/h4>\n\n<ul>\n<li><strong>Fix (admin UI)<\/strong> \u2014 info bars and notices no longer render with their text glued to the edges. The <code>.acimg-card<\/code> callout had no padding defined, and the <code>.acimg-notice<\/code> component carried a leftover <code>::before<\/code> accent with negative margins that didn't match the padding. Both are now consistent (proper padding + a single clean left accent).<\/li>\n<\/ul>\n\n<h4>0.23.16<\/h4>\n\n<ul>\n<li><strong>Fix (Catalog Watch)<\/strong> \u2014 the \"Preview heal\" and \"Apply heal\" buttons always showed \"Error: desconocido\" even when the server responded successfully: the JavaScript read the success\/summary fields off the fetch wrapper object instead of the response body. Both handlers now unwrap the response correctly, so the preview\/apply report real counts. Scale-independent fix (affected every site).<\/li>\n<\/ul>\n\n<h4>0.23.15<\/h4>\n\n<ul>\n<li><strong>CLI\/UI polish<\/strong> \u2014 user-facing references to the CLI command corrected from the legacy <code>wp pir<\/code> to <code>wp acimg<\/code> across <code>wp help<\/code> output, admin hints, and inline docs (the command was already registered as <code>acimg<\/code>, so the old examples pointed at a non-existent command).<\/li>\n<li><strong>Fix<\/strong> \u2014 the first-run onboarding wizard derived its nonce and \"completed\" flag out of scope, which caused a 403 on the onboarding REST calls and made the wizard re-appear on every Settings visit; both are now derived within the section that renders the wizard.<\/li>\n<li><strong>i18n<\/strong> \u2014 translation catalog synced with the renamed CLI references.<\/li>\n<\/ul>\n\n<h4>0.23.14<\/h4>\n\n<ul>\n<li><strong>WordPress.org compliance (Plugin Check)<\/strong> \u2014 addressed the official Plugin Check errors: <code>Tested up to<\/code> bumped to 7.0; direct filesystem calls migrated to WordPress wrappers (<code>wp_delete_file<\/code>, <code>WP_Filesystem<\/code>, <code>wp_is_writable<\/code>); SQL queries hardened (<code>%i<\/code> for internal table identifiers, <code>LIKE<\/code> wildcards passed as prepared parameters with <code>esc_like<\/code>); <code>$_GET<\/code> input properly unslashed\/sanitized.<\/li>\n<li><strong>External services disclosure<\/strong> \u2014 added an \"External services\" section to the readme documenting Lemon Squeezy (license), OpenAI\/Anthropic (AI Alt Text, BYOK), and Cloudflare (Image Transformations + Analytics): what data is sent, when, and links to each provider's terms and privacy policy.<\/li>\n<li><strong>Branding consistency<\/strong> \u2014 user-facing references to the old menu name updated to \"Australcode Image\"; landing URLs unified to the canonical domain; <code>wp help acimg<\/code>.<\/li>\n<li><strong>Fix<\/strong> \u2014 uninstall now removes the plugin's Action Scheduler actions using the current <code>acimg_<\/code> hook prefix (previously used the old prefix and left orphan rows).<\/li>\n<\/ul>\n\n<h4>0.23.13<\/h4>\n\n<ul>\n<li><strong>WP.org compliance (enqueue)<\/strong> \u2014 all 12 inline <code>&lt;script&gt;<\/code>\/<code>&lt;style&gt;<\/code> blocks in admin pages and notices migrated to <code>wp_enqueue_script<\/code>\/<code>wp_enqueue_style<\/code> with <code>wp_localize_script<\/code> for dynamic data. No behavior change; assets now load through the WordPress Scripts\/Styles API. The HTML email <code>&lt;style&gt;<\/code> (HealthEmailFormatter) remains inline by necessity (email clients).<\/li>\n<\/ul>\n\n<h4>0.23.12<\/h4>\n\n<ul>\n<li><strong>UX\/UI deep audit follow-up<\/strong> \u2014 11 findings addressed (0 P0, 5 P1, 4 P2, 2 P3).<\/li>\n<li><strong>Human-readable durations<\/strong>: scan durations show \"12 min 7 s\" instead of raw \"726.896 s\". New <code>DurationFormatter<\/code>.<\/li>\n<li><strong>Async scan reassurance<\/strong>: Catalog Watch shows a banner during a running scan (\"runs in background, you can close this window\") with human status copy. Progress was always preserved server-side via Action Scheduler; now the UI says so.<\/li>\n<li><strong>Prominent cleanup CTA<\/strong>: Dashboard \"Storage recuperable\" clean-up is now a button with the amount in the label (\"Limpiar 3,19 GB \u2192\") instead of a tiny 11px link.<\/li>\n<li><strong>License badges fixed<\/strong>: status badges referenced 3 non-existent CSS classes (fell back to grey); added semantic aliases (<code>--success<\/code>\/<code>--danger<\/code>\/<code>--neutral<\/code>).<\/li>\n<li><strong>Voseo cleanup<\/strong>: removed the 10 remaining rioplatense conjugations the v0.23.7 pass missed.<\/li>\n<li><strong>Token migration<\/strong>: Media Cleanup's 40 hardcoded hex \u2192 design-system tokens (dark-mode-ready); Health cron timestamps in site timezone instead of raw GMT; status emojis in tables \u2192 semantic dots; remaining English labels translated (CIT Cost, Catalog Watch headers).<\/li>\n<\/ul>\n\n<h4>0.23.11<\/h4>\n\n<ul>\n<li><strong>Catalog Watch v2 + stale storage cleanup<\/strong>: new <code>StaleDerivative<\/code> detector finds rows in <code>wp_pir_derivatives<\/code> whose <code>pipeline_hash<\/code> no longer matches the current settings hash. Storage reclaimable is reported in Dashboard, Catalog Watch and Bulk Regen pages. Auto-Healer supports stale removal (Pro feature) \u2014 orphans\/ghosts remain Free as they are corruption repair, not storage optimization.<\/li>\n<li><strong>Dashboard \"Storage recuperable\" KPI<\/strong>: permanent card showing reclaimable GB\/MB + count of stale derivatives. If clean, shows \"Cat\u00e1logo limpio\" with success indicator. Links to Catalog Watch for cleanup action.<\/li>\n<li><strong>Catalog Watch scan now async<\/strong>: <code>\/catalog-watch\/scan<\/code> returns 202 + <code>job_id<\/code> and enqueues Action Scheduler. Frontend polls <code>\/scan-status<\/code>. Fixes timeout on sites with &gt;1000 attachments (Cloudflare 100s limit returned HTML 524 instead of JSON).<\/li>\n<li><strong>Health page Catalog Watch cron row<\/strong>: new row showing the next scheduled run + last completed time + status indicator. Helps diagnose if the daily cron is properly scheduled (Pro), failed last run, or wasn't scheduled at all.<\/li>\n<li><strong>License activation hook<\/strong>: when activating a license via REST <code>\/license\/activate<\/code>, the plugin now fires <code>do_action('pir_license_activated')<\/code> so other Pro features can initialize side-effects (like scheduling the Catalog Watch daily cron) without waiting for the next admin page load. Fixes the case where a fresh install with license activated later had the daily cron unscheduled.<\/li>\n<li><strong>WP-CLI gate refinement<\/strong>: <code>wp acimg purge-cache --orphans<\/code> is now Free (corruption repair). <code>--stale<\/code> and <code>--all<\/code> remain Pro (storage optimization).<\/li>\n<\/ul>\n\n<h4>0.23.10<\/h4>\n\n<ul>\n<li><strong>Onboarding wizard error handling<\/strong>: when the <code>\/onboarding\/apply<\/code> REST endpoint returns an error (expired nonce, missing capability, security plugin interception), the wizard now shows an inline red error message in step 2 and restores the button instead of silently jumping to the \"Configuration applied\" screen. Fixes a UX bug where users could see a success message even though the configuration was not saved.<\/li>\n<li><strong>JS API wrapper hardened<\/strong>: new <code>apiCheck()<\/code> helper validates HTTP status + parses JSON body + returns structured <code>{ ok, data, error }<\/code>. Replaces raw <code>fetch().then(r =&gt; r.json())<\/code> pattern that did not differentiate between success and error responses (fetch only throws on network errors, not on HTTP 4xx\/5xx).<\/li>\n<li><strong>Test coverage<\/strong>: new <code>OnboardingControllerTest<\/code> locks the WP_Error contract (code, message, data.status) that the wizard JS depends on. Future WP API changes that break the shape will be caught at test time.<\/li>\n<\/ul>\n\n<h4>0.23.9<\/h4>\n\n<ul>\n<li><strong>Uniform-by-default for all image sizes<\/strong>: Plugin now uniforms every registered size to its declared dimensions by default, regardless of the WP <code>crop<\/code> flag. Before 0.23.9, sizes with <code>crop=false<\/code> (<code>medium_large<\/code>, <code>woocommerce_single<\/code>, <code>large<\/code>) were left Proportional, producing rectangular derivatives that broke the \"uniform images without crop\" promise. Override per-size with <code>sizesConfig[&lt;size&gt;] = \"proportional\"<\/code>.<\/li>\n<li><strong>First-visit onboarding wizard<\/strong>: detects WooCommerce <code>thumbnail_cropping<\/code> + registered sizes and applies the recommended config (all uniform) in one click.<\/li>\n<li><strong>Health check<\/strong>: WooCommerce thumbnail cropping (1:1 \/ custom \/ uncropped) reported in Health page + dismissible notice when misaligned.<\/li>\n<li><strong>Content target default<\/strong> changed 100 \u2192 85 (15% breathing space, more premium). Existing installs keep their value.<\/li>\n<li><strong>Action required after upgrade<\/strong>: run a Bulk Regen to regenerate derivatives with the new uniform default.<\/li>\n<\/ul>\n\n<p>Full history of older versions (0.23.8 and earlier) is preserved in the project's archive \u2014 contact support@australcode.io if you need detail on a specific legacy version.<\/p>","raw_excerpt":"Make WooCommerce product images the same size without cropping. Smart padding plus AVIF\/WebP\/JPEG delivery that survives any page cache.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/315190","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=315190"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/australcode"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=315190"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=315190"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=315190"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=315190"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=315190"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=315190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}