Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
veneliniliev committed Jan 22, 2017
0 parents commit f1a6997
Show file tree
Hide file tree
Showing 6 changed files with 374 additions and 0 deletions.
22 changes: 22 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "provision/minifier",
"description": "ProVision Minifier",
"version": "0.0.1",
"license": "Apache License 2.0",
"authors": [
{
"name": "Venelin Iliev",
"homepage": "http://veneliniliev.com"
}
],
"type": "library",
"require": {
"php": ">5.6.4 || ^7.0",
"laravel/laravel": "5.3.*"
},
"autoload": {
"psr-4": {
"ProVision\\Minifier\\": "src/"
}
}
}
22 changes: 22 additions & 0 deletions config/provision_minifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
return [
/**
* Включване / изключване
*/
'enable' => true,

/**
* Автоматично добавя на middleware
*/
'autoload_middleware' => true,

/**
* Премахване на новите редове
*/
'remove_lines' => true,

/**
* Премахване на коментарите
*/
'remove_comments' => true
];
7 changes: 7 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ProVision/Minifier

HTML minifier for Laravel

## Documentation

https://veneliniliev.com/docs/provision-minifier/
165 changes: 165 additions & 0 deletions src/Middleware/MinifierMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php

/*
* ProVision Administration, http://ProVision.bg
* Author: Venelin Iliev, http://veneliniliev.com
*/

namespace ProVision\Minifier\Middleware;

use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Response;
use ProVision\Minifier\Minifier;

class MinifierMiddleware
{
/**
* The application implementation.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;

/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct(Application $app)
{
$this->app = $app;
}

/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);

if ($this->isAResponseObject($response) && $this->isAnHtmlResponse($response)) {
$output = $response->getContent();

$minifie = new Minifier($output);

$response->setContent($minifie->get());
}

return $response;
}

/**
* Check if the response is a usable response class.
*
* @param mixed $response
*
* @return bool
*/
protected function isAResponseObject($response)
{
return is_object($response) && $response instanceof Response;
}

/**
* Check if the content type header is html.
*
* @param \Illuminate\Http\Response $response
*
* @return bool
*/
protected function isAnHtmlResponse(Response $response)
{
$type = $response->headers->get('Content-Type');
return strtolower(strtok($type, ';')) === 'text/html';
}

function compress($buffer)
{
/**
* To remove useless whitespace from generated HTML, except for Javascript.
* [Regex Source]
* https://github.com/bcit-ci/codeigniter/wiki/compress-html-output
* http://stackoverflow.com/questions/5312349/minifying-final-html-output-using-regular-expressions-with-codeigniter
*/
$regexRemoveWhiteSpace = '%# Collapse ws everywhere but in blacklisted elements.
(?> # Match all whitespaces other than single space.
[^\S ]\s* # Either one [\t\r\n\f\v] and zero or more ws,
| \s{2,} # or two or more consecutive-any-whitespace.
) # Note: The remaining regex consumes no text at all...
(?= # Ensure we are not in a blacklist tag.
(?: # Begin (unnecessary) group.
(?: # Zero or more of...
[^<]++ # Either one or more non-"<"
| < # or a < starting a non-blacklist tag.
(?!/?(?:textarea|pre)\b)
)*+ # (This could be "unroll-the-loop"ified.)
) # End (unnecessary) group.
(?: # Begin alternation group.
< # Either a blacklist start tag.
(?>textarea|pre)\b
| \z # or end of file.
) # End alternation group.
) # If we made it here, we are not in a blacklist tag.
%ix';

$regexRemoveWhiteSpace = '%(?>[^\S ]\s*| \s{2,})(?=(?:(?:[^<]++| <(?!/?(?:textarea|pre)\b))*+)(?:<(?>textarea|pre)\b|\z))%ix';
$re = '%# Collapse whitespace everywhere but in blacklisted elements.
(?> # Match all whitespans other than single space.
[^\S ]\s* # Either one [\t\r\n\f\v] and zero or more ws,
| \s{2,} # or two or more consecutive-any-whitespace.
) # Note: The remaining regex consumes no text at all...
(?= # Ensure we are not in a blacklist tag.
[^<]*+ # Either zero or more non-"<" {normal*}
(?: # Begin {(special normal*)*} construct
< # or a < starting a non-blacklist tag.
(?!/?(?:textarea|pre|script)\b)
[^<]*+ # more non-"<" {normal*}
)*+ # Finish "unrolling-the-loop"
(?: # Begin alternation group.
< # Either a blacklist start tag.
(?>textarea|pre|script)\b
| \z # or end of file.
) # End alternation group.
) # If we made it here, we are not in a blacklist tag.
%Six';

// $new_buffer = preg_replace('/<!--(.*|\n)-->/Uis', " ", sanitize_output($buffer));
// $new_buffer = preg_replace('/\s+/', " ", sanitize_output($new_buffer));
$new_buffer = mb_ereg_replace($regexRemoveWhiteSpace, " ", $this->sanitize_output($buffer));

// We are going to check if processing has working
if ($new_buffer === null) {
$new_buffer = $buffer;
}

return $new_buffer;
}

function sanitize_output($buffer)
{
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s', // shorten multiple whitespace sequences
'!/\*.*?\*/!s', // Remove htmlcomment
'/\n\s*\n/'
); // Remove htmlcomment

$replace = array(
'>',
'<',
'\\1',
'',
''
);
$buffer = preg_replace($search, $replace, $buffer);
return $buffer;
}
}
129 changes: 129 additions & 0 deletions src/Minifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php


namespace ProVision\Minifier;


use Illuminate\Support\Facades\Config;

class Minifier
{
private $html;

function __construct($html)
{

if (!Config::get('provision_minifier.enable', false)) {
return $html;
}

$this->html = $html;

if (Config::get('provision_minifier.remove_comments', false)) {
$this->removeComments();
}

if (Config::get('provision_minifier.remove_lines', false)) {
$this->html = $this->removeLines($this->html);
}
}

public function get()
{
return $this->html;
}

/**
* Remove comments
*/
private function removeComments()
{

// Remove htmlcomments
$additionaly = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
'/(?:(?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:(?<!\:|\\\|\\\' | ")\/\/.*))/' => '',
);

$this->html = preg_replace(array_keys($additionaly), array_values($additionaly), $this->html);
}

/**
* Remove lines
*/
private function removeLines($buffer)
{
/**
* To remove useless whitespace from generated HTML, except for Javascript.
* [Regex Source]
* https://github.com/bcit-ci/codeigniter/wiki/compress-html-output
* http://stackoverflow.com/questions/5312349/minifying-final-html-output-using-regular-expressions-with-codeigniter
*/
$regexRemoveWhiteSpace = '%# Collapse ws everywhere but in blacklisted elements.
(?> # Match all whitespaces other than single space.
[^\S ]\s* # Either one [\t\r\n\f\v] and zero or more ws,
| \s{2,} # or two or more consecutive-any-whitespace.
) # Note: The remaining regex consumes no text at all...
(?= # Ensure we are not in a blacklist tag.
(?: # Begin (unnecessary) group.
(?: # Zero or more of...
[^<]++ # Either one or more non-"<"
| < # or a < starting a non-blacklist tag.
(?!/?(?:textarea|pre)\b)
)*+ # (This could be "unroll-the-loop"ified.)
) # End (unnecessary) group.
(?: # Begin alternation group.
< # Either a blacklist start tag.
(?>textarea|pre)\b
| \z # or end of file.
) # End alternation group.
) # If we made it here, we are not in a blacklist tag.
%ix';
$regexRemoveWhiteSpace = '%(?>[^\S ]\s*| \s{2,})(?=(?:(?:[^<]++| <(?!/?(?:textarea|pre)\b))*+)(?:<(?>textarea|pre)\b|\z))%ix';
$re = '%# Collapse whitespace everywhere but in blacklisted elements.
(?> # Match all whitespans other than single space.
[^\S ]\s* # Either one [\t\r\n\f\v] and zero or more ws,
| \s{2,} # or two or more consecutive-any-whitespace.
) # Note: The remaining regex consumes no text at all...
(?= # Ensure we are not in a blacklist tag.
[^<]*+ # Either zero or more non-"<" {normal*}
(?: # Begin {(special normal*)*} construct
< # or a < starting a non-blacklist tag.
(?!/?(?:textarea|pre|script)\b)
[^<]*+ # more non-"<" {normal*}
)*+ # Finish "unrolling-the-loop"
(?: # Begin alternation group.
< # Either a blacklist start tag.
(?>textarea|pre|script)\b
| \z # or end of file.
) # End alternation group.
) # If we made it here, we are not in a blacklist tag.
%Six';
// $new_buffer = preg_replace('/<!--(.*|\n)-->/Uis', " ", sanitize_output($buffer));
// $new_buffer = preg_replace('/\s+/', " ", sanitize_output($new_buffer));
$new_buffer = mb_ereg_replace($regexRemoveWhiteSpace, " ", $this->sanitize_output($buffer));
// We are going to check if processing has working
if ($new_buffer === null) {
$new_buffer = $buffer;
}

return str_ireplace('> <', '><', $new_buffer);

}

private function sanitize_output($buffer)
{
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s', // shorten multiple whitespace sequences
);
$replace = array(
'>',
'<',
'\\1'
);
$buffer = preg_replace($search, $replace, $buffer);
return $buffer;
}
}
29 changes: 29 additions & 0 deletions src/Providers/MinifierProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace ProVision\Minifier\Providers;

use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;

class MinifierProvider extends ServiceProvider
{

public function boot()
{
$this->publishes([
__DIR__ . '/../../config/provision_minifier.php' => config_path('provision_minifier.php'),
], 'config');
}

public function register()
{
$this->mergeConfigFrom(
__DIR__ . '/../../config/provision_minifier.php', 'provision_minifier'
);

if (Config::get('provision_minifier.autoload_middleware')) {
$this->app['router']->pushMiddlewareToGroup('web', \ProVision\Minifier\Middleware\MinifierMiddleware::class);
}

}
}

0 comments on commit f1a6997

Please sign in to comment.