validate_css( $content ); } if ( 'js' === $type ) { return $this->validate_js( $content ); } if ( 'html' === $type ) { return $this->validate_html( $content ); } return null; } /** * Normalize line endings to LF. * * @param string $content Content. * @return string */ private function normalize_line_endings( string $content ): string { return str_replace( [ "\r\n", "\r" ], "\n", $content ); } /** * Get a human-readable label for a code type. * * @param string $type Type slug. * @return string Label. */ private function get_type_label( string $type ): string { $labels = [ 'css' => 'CSS', 'js' => 'JavaScript', 'html' => 'HTML', ]; return $labels[ $type ] ?? strtoupper( $type ); } /** * Validate CSS by checking that curly braces are balanced. * String literals and url() tokens are stripped first to avoid false positives. * * @param string $content Raw CSS content. * @return string|null Error message, or null if valid. */ private function validate_css( string $content ): ?string { // Remove string literals ("..." and '...') so braces inside them are ignored. $stripped = preg_replace( '/([\'"])(?:\\\\.|(?!\1).)*\1/s', '', $content ); // Remove url(...) tokens (may contain data URIs with braces). $stripped = preg_replace( '/url\s*\([^)]*\)/i', 'url()', $stripped ); $open = substr_count( $stripped, '{' ); $close = substr_count( $stripped, '}' ); if ( $open !== $close ) { return sprintf( /* translators: 1: opening brace count 2: closing brace count */ __( 'CSS has unbalanced braces: %1$d opening { vs %2$d closing }.', 'admin-optimizer' ), $open, $close ); } return null; } /** * Validate JS: checks that a