=== Flexa Cache ===
Contributors: flexatech
Tags: cache, page cache, performance, speed, optimization
Requires at least: 5.9
Tested up to: 7.0
Requires PHP: 8.2
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A fast page-cache and front-end optimization plugin: static HTML served before WordPress boots, 23 performance toggles, zero configuration required.

== Description ==

Flexa Cache is a full-featured WordPress page-cache and front-end optimization plugin. It installs a self-contained `advanced-cache.php` drop-in that serves compressed static HTML files before WordPress even loads — the same technique used by WP Fastest Cache and W3 Total Cache — giving you maximum TTFB improvement on both Apache and nginx hosts.

**Page Cache**

* Static HTML cache served by a pre-WordPress drop-in (no PHP/MySQL on cache hits)
* Gzip pre-compressed `.gz` files served natively
* Separate mobile cache variant (`index-mobile.html`) when Mobile Theme is enabled
* Smart invalidation: purge on new post, updated post, comments, theme/menu/widget changes, and WooCommerce product/stock updates
* Per-URL cache purge from the admin UI, WP-CLI, or REST API
* Cache preloader via Action Scheduler (or WP-Cron fallback) with start/cancel/status controls
* Widget output cache with O(1) versioned-key invalidation

**Front-End Optimization**

* Minify HTML (whitespace collapse) and Minify HTML Plus (inline CSS/JS trim)
* Minify CSS and Minify CSS Plus (deeper punctuation squeeze)
* Combine CSS — adjacency-only buffer fusion preserving cascade order
* Combine JS / Combine JS Plus — concatenate header and footer scripts
* Gzip — mod_deflate `.htaccess` block for dynamic (non-cached) responses
* Browser Caching — Expires/Cache-Control `.htaccess` block
* Disable Emojis — remove WordPress emoji scripts, styles, and DNS prefetch
* Lazy Load — native `loading="lazy"` + `decoding="async"` on images and iframes
* Render Blocking JS — add `defer` to render-blocking scripts
* Google Fonts Async — rewrite Google Fonts `<link>` to preload + `onload` swap with `<noscript>` fallback
* Delay JS — neutralise non-critical external scripts until first user interaction or 7-second idle fallback

**Developer-Friendly**

* WP-CLI: `wp flexa-cache clear [--url=<url>]`, `wp flexa-cache status`, `wp flexa-cache preload [start|status|cancel]`
* REST API: `/flexa-cache/v1/cache/purge`, `/cache/stats`, `/cache/preload`
* Filterable hooks: `flexa_cache/engine/is_cacheable`, `flexa_cache/engine/buffer`, `flexa_cache/store/dir`, `flexa_cache/purged`, `flexa_cache/settings/languages`, and more
* Kill switch: `?flexa_cache_optimize=0` disables optimization for a single admin request
* Exclusion lists for URLs, cookies, user agents, CSS handles, and JS handles

**Source code for compiled JavaScript and CSS**

The plugin ships with a compiled admin UI (`assets/dist/`). The human-readable source code is **publicly available** at:

https://github.com/flexatech/flexa-cache

== Installation ==

1. Upload the plugin files to `/wp-content/plugins/flexa-cache`, or install through the WordPress **Plugins** screen.
2. Activate the plugin through the **Plugins** screen.
3. Open **Flexa Cache** from the admin sidebar (located below Settings).
4. Enable the **Cache System** toggle and click **Save Settings**.

**After a plugin update:** deactivate and reactivate Flexa Cache once so the `advanced-cache.php` drop-in is refreshed. This step is only needed after an update that changes the drop-in — the release notes will say so when it applies.

== Frequently Asked Questions ==

= How does the page cache work? =
On activation, Flexa Cache installs an `advanced-cache.php` drop-in into `wp-content/` and adds `define('WP_CACHE', true)` to `wp-config.php`. On the next uncached request, the plugin generates a static HTML file. Every subsequent request for that URL is served directly from the file — no PHP execution, no database query.

= Does Flexa Cache work with WooCommerce? =
Yes. Cart, checkout, and account pages are automatically excluded from the cache. The cache is also purged when a product's stock level or price changes.

= Does it work on nginx? =
The static file cache works on any server (the drop-in uses PHP `readfile()`). The Gzip and Browser Caching toggles write Apache `.htaccess` rules; the plugin's class docblocks include the nginx equivalent snippets for hosts that need them.

= How do I clear the cache? =
Click **Delete Cache** in the Flexa Cache settings page, use `wp flexa-cache clear` from the command line, or call `POST /wp-json/flexa-cache/v1/cache/purge`. To clear a single URL, use the per-URL input in the Cache Stats panel or `wp flexa-cache clear --url=https://example.com/page/`.

= What does "Minify JS" do? =
The Minify JS toggle is a documented safe no-op when used alone. JavaScript is only ever concatenated (via Combine JS), never minified in isolation — the plugin ships no JS parser. If you want JS minification, enable Combine JS together with Minify JS.

= Will it conflict with other caching plugins? =
Flexa Cache checks for a foreign `advanced-cache.php` on activation and refuses to overwrite it. If you already have a caching plugin installed, deactivate it and remove its drop-in before activating Flexa Cache.

= Where are the plugin settings? =
In the WordPress admin sidebar, click **Flexa Cache** (located below Settings). Settings are organised into five sections: Cache, Invalidation, Performance, Exclusions, and Danger Zone.

== Changelog ==

= 1.0.2 =
* Fix: CSS minify (aggressive HTML minify and CSS combine) no longer strips whitespace around `:`, which previously fused descendant combinators into compound selectors before a pseudo-class (`:root :where(…)` → `:root:where(…)`) and silently dropped WordPress global-styles rules — most visibly Gutenberg button styles. Whitespace around `{ } ; ,` is still collapsed.

= 1.0.1 =
* Security: cache purge, stats, and preload REST endpoints now require the `manage_options` capability instead of `upload_files`, so only administrators can trigger site-wide cache operations.
* Hardening: cached widget output is now passed through `wp_kses_post()` before it is echoed.
* Cleanup: removed a dead pre-WordPress-5.7 raw `<script>` fallback in the delay-JS loader; the core `wp_print_inline_script_tag()` helper is now always used.
* CSS/JS combine and minify now rewrite the URL of the stylesheet/script tag WordPress already enqueued and printed, instead of emitting a freshly-built tag — preserving the original tag attributes.

= 1.0.0 =
* Initial release: page cache drop-in, 23 optimization toggles, WP-CLI, REST API, cache preloader, widget cache, mobile theme cache, i18n-ready.
