<?php
/**
 * Cache module — HTML minifier
 *
 * Trims insignificant whitespace and HTML comments without touching content
 * inside <pre>, <textarea>, <script>, <style> or `<!--[if IE]>` conditionals.
 *
 * Bench: ~3-8 ms per page on average WP themes; gain ~3-8 KB depending on
 * indentation. Negligible CPU compared to the disk write that follows.
 *
 * @package BlaminhorEssentials
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Blaminhor_Essentials_Cache_Html_Minifier {

	/**
	 * Minify a HTML document.
	 *
	 * @param string $html Full document.
	 * @return string Minified document, or original if minification cannot be
	 *                applied safely (regex failures, missing extensions).
	 */
	public static function minify( $html ) {
		if ( ! is_string( $html ) || '' === $html ) {
			return $html;
		}

		// 1. Stash content of preserved blocks so regex doesn't touch it.
		$preserved = array();
		$pattern   = '#<(pre|textarea|script|style)\b[^>]*>.*?</\1>#is';
		$stashed   = preg_replace_callback(
			$pattern,
			function ( $m ) use ( &$preserved ) {
				$key              = '@@BE_PRESERVED_' . count( $preserved ) . '@@';
				$preserved[ $key ] = $m[0];
				return $key;
			},
			$html
		);
		if ( null === $stashed ) {
			return $html;
		}

		// 2. Strip HTML comments — but keep IE conditionals (`<!--[if ...`).
		$step = preg_replace( '#<!--(?!\[if).*?-->#s', '', $stashed );
		if ( null === $step ) {
			return $html;
		}

		// 3. Collapse whitespace between tags.
		$step = preg_replace( '/>\s+</', '><', $step );
		if ( null === $step ) {
			return $html;
		}

		// 4. Collapse runs of whitespace within text nodes (but keep at least
		// one space because text spacing matters).
		$step = preg_replace( '/[ \t]{2,}/', ' ', $step );
		if ( null === $step ) {
			return $html;
		}
		$step = preg_replace( "/\r?\n[\r\n\t ]+/", "\n", $step );
		if ( null === $step ) {
			return $html;
		}

		// 5. Restore preserved blocks.
		if ( ! empty( $preserved ) ) {
			$step = strtr( $step, $preserved );
		}

		return $step;
	}
}
