<?php
/*
 * Copyright (c) 2017-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 * Copyright (c) 2015-2017 Aimy Extensions, Lingua-Systems Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); abstract class AimySpeedOptimizationMinifyHTML { static public function minify_by_dom( &$dom ) { return self::get_minified_html( $dom ); } static private function get_minified_html( &$dom ) { $html = '<!DOCTYPE html>'; $e = & $dom->documentElement; $html .= '<' . $e->nodeName . self::format_element_attributes( $e ) . '>'; $html .= self::get_element_html( $e ); $html .= '</' . $e->nodeName . '>'; return $html; } static private function get_element_html( &$node ) { $html = ''; $es = $node->childNodes; foreach ( $es as $e ) { switch ( $e->nodeType ) { case XML_CDATA_SECTION_NODE: { $html .= trim( $e->nodeValue ); break; } case XML_TEXT_NODE: { if ( ! empty( $e->nodeValue ) ) { $par = $e->parentNode; if ( self::has_pre_parent( $par ) ) { $html .= htmlspecialchars( $e->nodeValue, ENT_NOQUOTES ); } else if ( is_object( $par ) && ! empty( $par->nodeName ) && ( $par->nodeName == 'script' || $par->nodeName == 'style' ) ) { $html .= $e->nodeValue; } else { $v = htmlspecialchars( self::normalize_space( $e->nodeValue, false ), ENT_NOQUOTES ); if ( is_object( $par ) && $par->nodeName == 'head' ) { } else { $html .= $v; } } } break; } case XML_COMMENT_NODE: { if ( strpos( $e->nodeValue, '[' ) === 0 ) { $html .= '<!--' . self::normalize_space( $e->nodeValue ) . '-->'; } break; } case XML_ELEMENT_NODE: { $html .= '<' . $e->nodeName . self::format_element_attributes( $e ); if ( $e->hasChildNodes() ) { $html .= '>'; $html .= self::get_element_html( $e ); $html .= '</' . $e->nodeName . '>'; } else { if ( self::is_void_element( $e->nodeName ) ) { $html .= ( $e->hasAttributes() ? ' ' : '' ) . '/>'; } else { $html .= '></' . $e->nodeName . '>'; } } break; } } } return $html; } static private function is_void_element( $t ) { static $ts = array( 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' ); return in_array( $t, $ts ); } static private function has_pre_parent( &$e ) { if ( ! $e || ! $e->nodeName ) { return false; } if ( $e->nodeName == 'pre' ) { return true; } if ( $e->parentNode ) { return self::has_pre_parent( $e->parentNode ); } return false; } static private function normalize_space( $s, $do_trim = true ) { return preg_replace( '#\s+#', ' ', ( $do_trim ? trim( $s ) : $s ) ); } static private function format_element_attributes( &$e ) { if ( ! $e->hasAttributes() ) { return ''; } $html = ''; foreach ( $e->attributes as $attr ) { $v = htmlspecialchars( self::normalize_space( $attr->nodeValue ) ); $html .= ' ' . $attr->nodeName; if ( $v === '' ) { continue; } $html .= '='; if ( strpos( $v, ' ' ) === false && strpos( $v, "\t" ) === false && strpos( $v, "\n" ) === false && strpos( $v, "\f" ) === false && strpos( $v, "\r" ) === false && strpos( $v, '?' ) === false && strpos( $v, '&' ) === false && strpos( $v, '=' ) === false && strpos( $v, "'" ) === false ) { $html .= $v; } else { $html .= '"' . $v . '"'; } } return $html; } } 
