Skip to content

Conversation

@frappe64
Copy link

@frappe64 frappe64 commented Aug 17, 2025

Hi Cache Enabler Team,

First off, thank you for creating and maintaining such a fantastic, fast, and easy-to-use caching plugin.

I've identified and fixed a critical bug in the HTML minification logic that can cause page corruption.

The Bug

When the setting Minify HTML in cached pages including inline CSS and JavaScript. is enabled, the page content can become corrupted if the source HTML contains a <script> tag with JSON content, such as type="speculationrules" or type="application/ld+json".

The minifier mistakenly identifies character sequences within JSON string values (e.g., \/*) as the beginning of a comment. It then removes everything until it finds the next closing comment tag (*/) in the document, which is often in a completely different <style> block, leading to a broken page.

Example Source HTML:

<script type="speculationrules">
{"prerender":[{"source":"document","where":{"and":[{"href_matches":"\/*"}, ... ]}}]}
</script>
...
<style id='bricks-dynamic-data-inline-css'>
/* TEMPLATE SHORTCODE CSS */
#brxe-blabla {flex-direction: row}
</style>

Broken Output (Before Fix):
The minifier removes the content between \/* in the script and */ in the style tag.

<script type="speculationrules">
{"prerender":[{"source":"document","where":{"and":[{"href_matches":"\ #brxe-blabla {flex-direction: row} </style>

The Root Cause

The core issue lies in applying a single, global regular expression to the entire HTML document to strip JS/CSS comments. This regex lacks context and cannot distinguish between a legitimate comment and a similar string pattern inside a JSON literal.

Proposed Solution

This pull request refactors the inline CSS/JS minification logic to be context-aware and safer.

Instead of running a single preg_replace on the entire HTML body, it now uses preg_replace_callback to find each <script> and <style> block individually.

Initial regex for stripping comments left unchanged.

This approach is more robust because:

  1. Isolation: The comment-stripping regex is now applied only to the content within each script or style tag, preventing cross-tag corruption.
  2. Safety: It includes a check to skip minification for non-executable script types that often contain JSON (speculationrules, application/ld+json). Since JSON does not officially support comments, attempting to strip them is both unnecessary and dangerous.
  3. Reliability: This change prevents data corruption and makes the powerful HTML minification feature much more reliable for all users.

How to Test

  1. Install and activate the Cache Enabler plugin.
  2. Go to Settings -> Cache Enabler and enable the option: Minify HTML in cached pages including inline CSS and JavaScript.
  3. Create a new page and add the following HTML block using the Custom HTML block editor:
    <script type="speculationrules">
    {"prerender":[{"source":"document","where":{"and":[{"href_matches":"\/*"},{"not":{"href_matches":["\/wp-*.php"]}}]}}]}
    </script>
    <style>
    /* This is a CSS comment */
    .test-class { color: blue; }
    </style>
  4. Save the page, then view it in an incognito window to ensure a cached version is served.
  5. View the page source. Without this PR, the source will be broken and show content missing between \/* and */.
  6. Apply the changes from this PR.
  7. Clear the site cache in Cache Enabler.
  8. View the page in an incognito window again and inspect the source. With this PR, the source code will be correctly minified, the speculationrules script will be intact, and the page will render correctly.

The inline JS/CSS minifier was using a global regex that incorrectly
identified `/*` inside JSON strings (e.g., in speculationrules or
ld+json scripts) as the start of a comment. This corrupted the page
by removing large chunks of HTML.

This commit refactors the minification to use a context-aware
`preg_replace_callback`. The logic now isolates each <script> and
<style> tag and explicitly skips minification for non-JS script
types like `application/ld+json` and `speculationrules`, resolving
the data corruption bug.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants