├── LICENSE
├── README.md
├── composer.json
├── config
└── laravel-html-minifier.php
├── example-output
├── after.jpg
└── before.jpg
└── src
├── HtmlMinifierServiceProvider.php
└── Middleware
├── Minifier.php
├── MinifyCss.php
├── MinifyHtml.php
└── MinifyJavascript.php
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 :D
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | # Laravel Html Minifier
9 |
10 | Adalah Paket simpel untuk minify HTML, Css Style, dan Javascript sebelum dirender ke browser untuk aplikasi Laravel anda.
11 |
12 | Alat ini hanya bekerja jika output yang diberikan adalah bentuk struktur html yang valid meliputi tag html, head dan body. contohnya
13 |
14 | - Html yang valid (akan diproses dan diminify)
15 |
16 | ```html
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ```
26 |
27 | - Html yang tidak valid (tidak diminify)
28 |
29 | ```html
30 | < html>
31 |
32 |
33 |
34 |
35 |
36 |
37 | html>
38 |
39 | atau
40 |
41 |
42 |
43 |
44 |
45 |
46 | ```
47 |
48 | ## Contoh Hasilnya :
49 |
50 | 
51 |
52 | 
53 |
54 | ## Installasi
55 |
56 | > **Membutuhkan:**
57 | - **[PHP 7.2.5+](https://php.net/releases/)**
58 | - **[Laravel 6.0+](https://github.com/laravel/laravel)**
59 |
60 | ## Tahap pertama anda bisa menginstall paket ini dengan [Composer 2x](https://getcomposer.org/download/)
61 |
62 | ```sh
63 | composer require dz-id/laravel-html-minifier
64 | ```
65 |
66 | ## Publish konfigurasi file
67 |
68 | ```sh
69 | php artisan vendor:publish --provider="DzId\LaravelHtmlMinifier\HtmlMinifierServiceProvider"
70 | ```
71 |
72 | ## Jangan lupa untuk mendaftarkan ke Global Middleware
73 |
74 | [\DzId\LaravelHtmlMinifier\Middleware\MinifyHtml::class](src/Middleware/MinifyHtml.php) dan Middleware lainnya harus didaftarkan ke kernel jika diperlukan, contoh :
75 |
76 | ```php
77 |
78 | // file : app/Http/Karnel.php
79 |
80 | protected $middleware = [
81 | ....
82 | \DzId\LaravelHtmlMinifier\Middleware\MinifyHtml::class, // middleware untuk minify html
83 | \DzId\LaravelHtmlMinifier\Middleware\MinifyCss::class, // middleware untuk minify css style
84 | \DzId\LaravelHtmlMinifier\Middleware\MinifyJavascript::class, // middleware untuk minify kode javascript
85 | ];
86 | ```
87 |
88 | ## Informasi Middleware
89 |
90 | ##### [\DzId\LaravelHtmlMinifier\Middleware\MinifyHtml::class](src/Middleware/MinifyHtml.php)
91 |
92 | ```MinifyHtml::class``` fungsinya adalah untuk minify html menghapus blank spasi dan juga baris baru menjadi satu baris.
93 |
94 | Contoh Hasil :
95 |
96 | - Sebelum diminify
97 | ```html
98 |
99 |
100 | Laravel Html Minifier
101 |
102 |
103 | Laravel Html Minifier
104 |
105 |
106 | ```
107 |
108 | - Sesudah diminify
109 | ```html
110 | Laravel Html MinifierLaravel Html Minifier
111 | ```
112 |
113 | ##### [\DzId\LaravelHtmlMinifier\Middleware\MinifyCss::class](src/Middleware/MinifyCss.php)
114 |
115 | ```MinifyCss::class``` fungsinya adalah untuk minify css style menghapus blank spasi dan juga baris baru menjadi satu baris.
116 |
117 | Contoh Hasil :
118 |
119 | - Sebelum diminify
120 | ```css
121 | body {
122 | background-color: salmon;
123 | width: 100%;
124 | height: 100%;
125 | }
126 | ```
127 |
128 | - Sesudah diminify
129 | ```css
130 | body{background-color:salmon;width:100%;height:100%}
131 | ```
132 |
133 | ##### [\DzId\LaravelHtmlMinifier\Middleware\MinifyJavascript::class](src/Middleware/MinifyJavascript.php)
134 |
135 | ```MinifyJavascript::class``` fungsinya adalah untuk minify kode javascript menghapus blank spasi dan juga baris baru menjadi satu baris.
136 |
137 | Catatan: jangan menggunakan kode tanpa kurung kurawal (```{}```) untuk if, elseif, else, while, for, dll. ini akan menyebebkan kode anda error, contohnya
138 |
139 | - kode yang disarankan
140 | ```javascript
141 | for (let i = 0; i < 10; i++) {
142 | console.log('hello dunia');
143 | }
144 | ```
145 |
146 | - kode yang tidak disarankan, tanpa kurung kurawal biasanya akan menyebabkan error jika menggunakan ```MinifyJavascript::class```
147 | ```javascript
148 | for (let i = 0; i < 10; i++) // tanpa
149 | console.log('hello dunia'); // kurung kurawal
150 | ```
151 |
152 | - sesudah diminify
153 | ```javascript
154 | for (let i = 0; i < 10; i++){console.log('hello dunia')}
155 | ```
156 |
157 | kamu juga bisa mengaburkan kode javascript dengan menyetel ke ```true``` bagian ```"obfuscate_javascript"``` dalam file : [config/laravel-html-minifier.php](config/laravel-html-minifier.php)
158 |
159 | ## File Konfigurasi
160 |
161 | Setelah menginstall paket anda mungkin perlu mengkonfigurasi beberapa opsi
162 | Silahkan masuk ke file [config/laravel-html-minifier.php](config/laravel-html-minifier.php) untuk mengubah konfigurasi
163 |
164 | ##### Nonaktifkan Layanan
165 |
166 | Anda cukup menyetel ke ```false``` untuk menonaktifkan Layanan.
167 |
168 | ```php
169 |
170 | // file: config/laravel-html-minifier.php
171 |
172 | // setel bagian ini ke false untuk menonaktifkan layanan minify Laravel.
173 | "enable" => env("LARAVEL_HTML_MINIFIER_ENABLE", true),
174 | ```
175 |
176 | ##### Otomatis Menambahkan Semicolon Atau Titik Koma Diakhir kode Pada CSS
177 |
178 | Jika kode css anda mengalami bug saat menggunakan ```MinifyCss::class``` silahkan setel bidang ini ke ```false```.
179 |
180 | ```php
181 |
182 | // file: config/laravel-html-minifier.php
183 |
184 | "css_automatic_insert_semicolon" => env("LARAVEL_HTML_MINIFIER_CSS_AUTOMATIC_INSERT_SEMICOLON", true),
185 | ```
186 |
187 | ##### Otomatis Menambahkan Semicolon Atau Titik Koma Diakhir kode Pada Javascript
188 |
189 | Catatan: Jangan menggunakan jeda baris untuk while, do while, for, if, elseif, else, return, dll. ataupun kode tanpa kurung kurawal (```{}```). contohnya
190 |
191 | - kode yang disarankan
192 | ```javascript
193 | var log = function(log) {
194 | return console.log(log);
195 | }
196 |
197 | let i = 0;
198 |
199 | do {
200 | if (i == 5) {
201 | break;
202 | }
203 | i++;
204 | log("hello dunia");
205 | } while (true);
206 | ```
207 |
208 | - kode yang tidak disarankan, akan menyebabkan error jika mengaktifkan "js_automatic_insert_semicolon"
209 | ```javascript
210 | var log = function(log) {
211 | return // jeda
212 | console.log(log); // baris
213 | }
214 |
215 | let i = 0;
216 |
217 | do
218 | // jeda baris
219 | {
220 | if (i == 5) // tanpa
221 | break; // kurung kurawal
222 | i++;
223 | log("hello dunia");
224 | }
225 | // jeda baris
226 | while (true);
227 | ```
228 |
229 | mungkin aja jika mengaktifkan bidang ini kode anda akan menjadi bug karena suatu kondisi yang salah
230 | dalam hal ini jika itu terjadi anda cukup menyetel bidang ini ke ```false```
231 |
232 | jangan lupa untuk selalu menggunakan titik koma pada kode javascript jika bidang ini disetel ke ```false```
233 |
234 | fungsi ini hanya berlaku jika menggunakan ```MinifyJavascript::class```
235 |
236 | ```php
237 |
238 | // file: config/laravel-html-minifier.php
239 |
240 | "js_automatic_insert_semicolon" => env("LARAVEL_HTML_MINIFIER_JS_AUTOMATIC_INSERT_SEMICOLON", true),
241 | ```
242 |
243 | ##### Menghapus Komentar HTML
244 |
245 | Cukup setel ke ```true``` untuk mengaktifkan dan setel ke ```false``` untuk menonaktifkan.
246 |
247 | Fungsi ini hanya berlaku jika menggunakan Middleware ```MinifyHtml::class```
248 |
249 | ```php
250 |
251 | // file: config/laravel-html-minifier.php
252 |
253 | // setel bidang ini ke false untuk mematikan
254 | "remove_comments" => env("LARAVEL_HTML_MINIFIER_REMOVE_COMMENTS", true),
255 | ```
256 |
257 | ##### Kaburkan Kode Javascript (Obfuscate)
258 |
259 | Catatan : jika ada mengaktifkan fungsi ini mungkin kode javascript anda akan menjadi panjang,
260 | Fungsi ini akan mengubah satu per satu dari setiap string / text ke ```chr()``` fungsi PHP dan didecode dengan ```String.fromCharCode()``` fungsi javascript.
261 |
262 | Fungsi ini hanya berlaku jika kamu menggunakan Middleware ```MinifyJavascript::class``` jika bidang ini disetel ke ```false``` kode javascript hanya diminify tidak dikaburkan/Obfuscate
263 |
264 | Contoh Hasil :
265 |
266 | - Sebelum dikaburkan
267 | ```javascript
268 | alert(1);
269 | ```
270 |
271 | - Sesudah dikaburkan
272 | ```javascript
273 | eval(((_,__,___,____,_____,______,_______)=>{______[___](x=>_______[__](String[____](x)));return _______[_](_____)})('join','push','forEach','fromCharCode','',[97,108,101,114,116,40,49,41,59],[]))
274 | ```
275 |
276 | Dalam kasus ini kamu cukup menyetelnya ke ```false``` untuk menonaktifkan dan menyetelnya ke ```true``` untuk mengaktifkan
277 |
278 | ```php
279 |
280 | // file : config/laravel-html-minifier.php
281 |
282 | // setel ke true untuk mengaktifkan
283 | "obfuscate_javascript" => env("LARAVEL_HTML_MINIFIER_OBFUSCATE_JS", false),
284 | ```
285 |
286 | ##### Ignore / Abaikan Route
287 |
288 | Anda mungkin ingin mengonfigurasi paket untuk melewati beberapa rute.
289 |
290 | ```php
291 |
292 | // file : config/laravel-html-minifier.php
293 |
294 | "ignore" => [
295 | "*/download/*", // Abaikan semua route yang mengandung download
296 | "admin/*", // Abaikan semua route dengan awalan admin,
297 | "*/user" // Abaikan route dengan akhiran user
298 | ]
299 | ```
300 |
301 | ## Skip / Lewati dengan menambahkan attribute ignore--minify
302 |
303 | Kamu cukup menambahkan attribute ```ignore--minify``` dalam tag script / style untuk melewati proses minify.
304 |
305 | Contoh :
306 |
307 | ```html
308 |
309 |
312 |
313 |
316 | ```
317 |
318 | Setiap tag style/script yang memiliki attribute ```ignore--minify``` akan dilewati tidak diminify.
319 |
320 | ## Skip / Lewati View dengan menambahkan data "ignore_minify" ke dalam view
321 |
322 | Kamu juga bisa melewati minify dengan memasukan data ```"ignore_minify"``` kedalam view
323 |
324 | Contoh :
325 |
326 | ```php
327 |
328 | // View ini tidak diminify akan di skip.
329 | return view("welcome", ["ignore_minify" => true]);
330 | ```
331 |
332 | ## Lisensi
333 |
334 | [MIT](LICENSE) (MIT)
335 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dz-id/laravel-html-minifier",
3 | "description": "Html Minifier adalah paket simpel untuk minify output Html, Css style, dan Javascript sebelum dirender ke browser untuk aplikasi Laravel anda.",
4 | "keywords": [
5 | "laravel",
6 | "Laravel Html Minifier",
7 | "Laravel-Html-Minifier",
8 | "Html Minify",
9 | "Minify"
10 | ],
11 | "authors": [
12 | {
13 | "name": "DulLah",
14 | "email": "dulah755@gmail.com"
15 | }
16 | ],
17 | "require": {
18 | "php": "^7.2.5 || ^8.0",
19 | "illuminate/support": "^6.0 || ^7.0 || ^8.0",
20 | "illuminate/http": "^6.0 || ^7.0 || ^8.0",
21 | "illuminate/view": "^6.0 || ^7.0 || ^8.0"
22 | },
23 | "license": "MIT",
24 | "autoload": {
25 | "psr-4": {
26 | "DzId\\LaravelHtmlMinifier\\": "src/"
27 | }
28 | },
29 | "minimum-stability": "dev",
30 | "extra": {
31 | "laravel": {
32 | "providers": [
33 | "DzId\\LaravelHtmlMinifier\\HtmlMinifierServiceProvider"
34 | ]
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/config/laravel-html-minifier.php:
--------------------------------------------------------------------------------
1 | env("LARAVEL_HTML_MINIFIER_ENABLE", true),
13 |
14 | /*
15 | |--------------------------------------------------------------------------
16 | | Otomatis menambahkan semicolon diakhir kode untuk CSS
17 | |--------------------------------------------------------------------------
18 | |
19 | | Silahkan setel bidang ini ke false
20 | | jika kode CSS anda mengalami bug atau tidak berfungi
21 | | setelah menggunakan MinifyCss::class
22 | |
23 | */
24 | "css_automatic_insert_semicolon" => env("LARAVEL_HTML_MINIFIER_CSS_AUTOMATIC_INSERT_SEMICOLON", true),
25 |
26 | /*
27 | |--------------------------------------------------------------------------
28 | | Otomatis menambahkan semicolon diakhir kode untuk Javascript
29 | |--------------------------------------------------------------------------
30 | |
31 | | Silahkan setel bidang ini ke false
32 | | jika kode Javascript anda mengalami bug atau tidak berfungi
33 | | setelah menggunakan MinifyJavascript::class
34 | |
35 | | Dan jangan lupa untuk selalu mengakhiri dengan semicolon
36 | | jika bidang ini disetel ke false.
37 | */
38 | "js_automatic_insert_semicolon" => env("LARAVEL_HTML_MINIFIER_JS_AUTOMATIC_INSERT_SEMICOLON", true),
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Aktifkan penghapusan komentar pada HTML
43 | |--------------------------------------------------------------------------
44 | |
45 | | Setel bagian ini ke false jika komentar HTML tidak ingin dihapus
46 | |
47 | | Catatan: Pengaturan ini akan berlaku jika menggunakan Middleware MinifyHtml::class
48 | |
49 | */
50 | "remove_comments" => env("LARAVEL_HTML_MINIFIER_REMOVE_COMMENTS", true),
51 |
52 | /*
53 | |--------------------------------------------------------------------------
54 | | Kaburkan Kode Javascript
55 | |--------------------------------------------------------------------------
56 | |
57 | | Pengaturan ini akan berlaku jika menggunakan MinifyJavascript::class
58 | |
59 | | Jika di setel ke true maka kode javascript akan dikaburkan,
60 | | Akan mentranslate kode js ke ord() fungsi php
61 | | Dan akan didecode dengan String.fromCharCode() Fungsi javascript
62 | |
63 | | Catatan: Mungkin fungsi ini akan membuat kode Anda menjadi panjang.
64 | |
65 | */
66 | "obfuscate_javascript" => env("LARAVEL_HTML_MINIFIER_OBFUSCATE_JS", false),
67 |
68 | /*
69 | |--------------------------------------------------------------------------
70 | | Abaikan Routes
71 | |--------------------------------------------------------------------------
72 | |
73 | | Dalam pengecekan akan menggunakan fungsi request()->is(),
74 | | Dan jika route cocok maka akan diabaikan / Tidak diminify.
75 | | Anda dapat menggunakan * sebagai wildcard.
76 | |
77 | */
78 |
79 | "ignore" => [
80 | // "*/download/*", // Abaikan semua route yang mengandung download
81 | // "admin/*", // Abaikan semua route dengan awalan admin,
82 | // "*/user" // Abaikan route dengan akhiran user
83 | ],
84 | ];
85 |
--------------------------------------------------------------------------------
/example-output/after.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dz-id/laravel-html-minifier/0f016d1a7b6ec8b2d7a8696e26c2b8ecf4dac0ac/example-output/after.jpg
--------------------------------------------------------------------------------
/example-output/before.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dz-id/laravel-html-minifier/0f016d1a7b6ec8b2d7a8696e26c2b8ecf4dac0ac/example-output/before.jpg
--------------------------------------------------------------------------------
/src/HtmlMinifierServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
22 | __DIR__."/../config/laravel-html-minifier.php" => config_path("laravel-html-minifier.php"),
23 | ]);
24 | }
25 |
26 | /**
27 | * Register the service provider.
28 | */
29 | public function register()
30 | {
31 | $this->mergeConfigFrom(__DIR__."/../config/laravel-html-minifier.php", "laravel-html-minifier.php");
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Middleware/Minifier.php:
--------------------------------------------------------------------------------
1 | ]*>.*]*>.*<\/head[^>]*>.*]*>.*<\/body[^>]*>.*<\/html[^>]*>/is";
23 |
24 | abstract protected function apply();
25 |
26 | /**
27 | * Handle an incoming request.
28 | *
29 | * @param \Illuminate\Http\Request $request
30 | * @param \Closure $next
31 | * @return mixed
32 | */
33 | public function handle(Request $request, Closure $next)
34 | {
35 | $response = $next($request);
36 |
37 | /* Apakah boleh menjalankan minify? */
38 | if (!$this->shouldProcessMinify($request, $response))
39 | {
40 | if (!(static::$dom instanceof DOMDocument))
41 | {
42 | return $response;
43 | }
44 | }
45 |
46 | $html = $response->getContent();
47 |
48 | $this->loadDom($html);
49 |
50 | return $response->setContent($this->apply());
51 | }
52 |
53 | protected function shouldProcessMinify($request, $response) : bool
54 | {
55 | /* Apakah fungsi laravel-html-minifier.enable dimatikan? */
56 | if (!$this->isEnable())
57 | {
58 | return false;
59 | }
60 |
61 | /* Apakah responnya adalah json? */
62 | if ($response instanceof JsonResponse)
63 | {
64 | return false;
65 | }
66 |
67 | /* Apakah responnya adalah binnary? */
68 | if ($response instanceof BinaryFileResponse)
69 | {
70 | return false;
71 | }
72 |
73 | /* Apakah responsenya adalah stream? */
74 | if ($response instanceof StreamedResponse)
75 | {
76 | return false;
77 | }
78 |
79 | /* Apakah responnya dari view() fungsi laravel? */
80 | if ($response->original instanceof View)
81 | {
82 | $data = $response->original->getData();
83 | /* Apakah ada data ignore_minify di view() dan isinya true? */
84 | if (isset($data["ignore_minify"]) && $data["ignore_minify"] === true)
85 | {
86 | return false;
87 | }
88 | }
89 |
90 | foreach ($this->ignore() as $route)
91 | {
92 | /* Apakah route yang sedang diakses cocok dengan yang ada di laravel-html-minifier.ignore? */
93 | if ($request->is($route))
94 | {
95 | return false;
96 | }
97 | }
98 |
99 | $response = $response->getContent();
100 |
101 | /* Apakah responnya kosong atau NULL? */
102 | if (empty($response) or !is_string($response) or $this->isEmpty($response))
103 | {
104 | return false;
105 | }
106 |
107 | /*
108 | * $result = true;
109 | *
110 | * foreach (["html", "body"] as $name)
111 | * {
112 | * $result = $result && !is_null($this->matchHtmlTag($response, $name));
113 | * }
114 | *
115 | * return $result;
116 | */
117 |
118 | /* Apakah responnya adalah bentuk syntax html yang valid? */
119 | return $this->validHtml($response);
120 | }
121 |
122 | protected function isEmpty(string $value) : bool
123 | {
124 | return (bool) preg_match("/^\s*$/", $value);
125 | }
126 |
127 | protected function validHtml(string $value) : bool
128 | {
129 | return (bool) preg_match(self::REGEX_VALID_HTML, $value);
130 | }
131 |
132 | protected function isEnable() : bool
133 | {
134 | /* Apakah laravel-html-minifier.enable belum dipanggil? */
135 | if (is_null(static::$isEnable))
136 | {
137 | static::$isEnable = (bool) config("laravel-html-minifier.enable", true);
138 | }
139 |
140 | return static::$isEnable;
141 | }
142 |
143 | protected function ignore() : array
144 | {
145 | /* Apakah laravel-html-minifier.enable belum dipanggil? */
146 | if (is_null(static::$ignore))
147 | {
148 | static::$ignore = (array) config("laravel-html-minifier.ignore", []);
149 | }
150 |
151 | return static::$ignore;
152 | }
153 |
154 | protected function matchHtmlTag(string $value, string $tags)
155 | {
156 | if (!preg_match_all("/<" . $tags . "[^>]*>(.*?)<\/" . $tags . "[^>]*>/is", $value, $matches))
157 | {
158 | return null;
159 | }
160 |
161 | return $matches;
162 | }
163 |
164 | protected function loadDom(string $html, bool $force = false)
165 | {
166 | /* Apakah dom sudah diload? */
167 | if ((static::$dom instanceof DOMDocument))
168 | {
169 | /* Apakah dipaksa untuk meload dom lagi? */
170 | if ($force)
171 | {
172 |
173 | }
174 | else
175 | {
176 | return;
177 | }
178 | }
179 |
180 | static::$dom = new DOMDocument;
181 | @static::$dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_SCHEMA_CREATE);
182 | }
183 |
184 | protected function getByTag(string $tags) : array
185 | {
186 | $result = [];
187 | $element = static::$dom->getElementsByTagName($tags);
188 |
189 | foreach ($element as $el)
190 | {
191 | $value = $el->nodeValue;
192 |
193 | /* Apakah isinya kosong? */
194 | if ($this->isEmpty($value))
195 | {
196 | continue;
197 | }
198 |
199 | /* Apakah memiliki attribute ignore--minify? */
200 | if ($el->hasAttribute("ignore--minify"))
201 | {
202 | continue;
203 | }
204 |
205 | $result[] = $el;
206 | }
207 |
208 | return $result;
209 | }
210 |
211 | protected function getByTagOnlyIgnored(string $tags) : array
212 | {
213 | $result = [];
214 | $element = static::$dom->getElementsByTagName($tags);
215 |
216 | foreach ($element as $el)
217 | {
218 | $value = $el->nodeValue;
219 |
220 | /* Apakah isinya kosong? */
221 | if ($this->isEmpty($value))
222 | {
223 | continue;
224 | }
225 |
226 | /* Apakah tidak memiliki attribute ignore--minify? */
227 | if (!$el->hasAttribute("ignore--minify"))
228 | {
229 | continue;
230 | }
231 |
232 | $result[] = $el;
233 | }
234 |
235 | return $result;
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/src/Middleware/MinifyCss.php:
--------------------------------------------------------------------------------
1 | getByTag("style") as $el)
16 | {
17 | $value = $this->replace($el->nodeValue);
18 |
19 | $el->nodeValue = "";
20 | $el->appendChild(static::$dom->createTextNode($value));
21 | }
22 |
23 | return static::$dom->saveHtml();
24 | }
25 |
26 | protected function insertSemicolon($value)
27 | {
28 | return preg_replace([
29 | // otomatis menambahkan semicolon atau titik koma (;) diakhir kode
30 | // kecuali yang diakhiri dengan braces ({}) ataupun dengan semicolon (;)
31 | '#^[A-Za-z\s\-]+:.+(?insertSemicolon($value);
45 | }
46 |
47 | return trim(preg_replace([
48 | // Remove comment(s)
49 | '#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|\/\*(?!\!)(?>.*?\*\/)|^\s*|\s*$#s',
50 | // Remove unused white-space(s)
51 | '#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/))|\s*+;\s*+(})\s*+|\s*+([*$~^|]?+=|[{};,>~]|\s(?![0-9\.])|!important\b)\s*+|([[(:])\s++|\s++([])])|\s++(:)\s*+(?!(?>[^{}"\']++|"(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')*+{)|^\s++|\s++\z|(\s)\s+#si',
52 | // Replace `0(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)` with `0`
53 | '#(?<=[\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)#si',
54 | // Replace `:0 0 0 0` with `:0`
55 | '#:(0\s+0|0\s+0\s+0\s+0)(?=[;\}]|\!important)#i',
56 | // Replace `background-position:0` with `background-position:0 0`
57 | '#(background-position):0(?=[;\}])#si',
58 | // Replace `0.6` with `.6`, but only when preceded by `:`, `,`, `-` or a white-space
59 | '#(?<=[\s:,\-])0+\.(\d+)#s',
60 | // Minify string value
61 | '#(\/\*(?>.*?\*\/))|(?.*?\*\/))|(\burl\()([\'"])([^\s]+?)\3(\))#si',
63 | // Minify HEX color code
64 | '#(?<=[\s:,\-]\#)([a-f0-6]+)\1([a-f0-6]+)\2([a-f0-6]+)\3#i',
65 | // Replace `(border|outline):none` with `(border|outline):0`
66 | '#(?<=[\{;])(border|outline):none(?=[;\}\!])#',
67 | // Remove empty selector(s)
68 | '#(\/\*(?>.*?\*\/))|(^|[\{\}])(?:[^\s\{\}]+)\{\}#s' //
69 | ],[
70 | '$1',
71 | '$1$2$3$4$5$6$7',
72 | '$1',
73 | ':0',
74 | '$1:0 0',
75 | '.$1',
76 | '$1$3',
77 | '$1$2$4$5',
78 | '$1$2$3',
79 | '$1:0',
80 | '$1$2'
81 | ], $value));
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Middleware/MinifyHtml.php:
--------------------------------------------------------------------------------
1 | \s*|(?)\n+(?=\<[^!])#s";
8 |
9 | protected function apply()
10 | {
11 | // simpan css dan javascript yang belum di minify dan yang ada attribute ignored--minify nya
12 | $ignoredCss = $this->getByTagOnlyIgnored("style");
13 | $ignoredJs = $this->getByTagOnlyIgnored("script");
14 |
15 | if (static::$minifyCssHasBeenUsed && static::$minifyJavascriptHasBeenUsed)
16 | {
17 | $html = $this->replace(static::$dom->saveHtml());
18 |
19 | if (empty($ignoredCss) || empty($ignoredCss))
20 | {
21 | return $html;
22 | }
23 |
24 | $this->loadDom($html, true);
25 | }
26 | else
27 | {
28 | if (!static::$minifyCssHasBeenUsed)
29 | {
30 | $css = $this->getByTag("style");
31 | }
32 |
33 | if (!static::$minifyJavascriptHasBeenUsed)
34 | {
35 | $js = $this->getByTag("script");
36 | }
37 |
38 | $html = $this->replace(static::$dom->saveHtml());
39 |
40 | $this->loadDom($html, true);
41 |
42 | if (isset($css)) {
43 | $this->append("getByTag", "style", $css);
44 | }
45 | if (isset($js)) {
46 | $this->append("getByTag", "script", $js);
47 | }
48 | }
49 |
50 | if (!empty($ignoredCss))
51 | {
52 | $this->append("getByTagOnlyIgnored", "style", $ignoredCss);
53 | }
54 | if (!empty($ignoredJs))
55 | {
56 | $this->append("getByTagOnlyIgnored", "script", $ignoredJs);
57 | }
58 |
59 | return trim(static::$dom->saveHtml());
60 | }
61 |
62 | protected function append(string $function, string $tags, array $backup)
63 | {
64 | $index = 0;
65 | foreach ($this->{$function}($tags) as $el)
66 | {
67 | $el->nodeValue = "";
68 | $el->appendChild(static::$dom->createTextNode($backup[$index]->nodeValue));
69 | $index++;
70 | }
71 | }
72 |
73 | protected function removeComment($value)
74 | {
75 | return preg_replace(self::REGEX_REMOVE_COMMENT, "", $value);
76 | }
77 |
78 | protected function replace($value)
79 | {
80 | $value = trim(preg_replace([
81 | // t = text
82 | // o = tag open
83 | // c = tag close
84 | // Keep important white-space(s) after self-closing HTML tag(s)
85 | '#<(img|input)(>| .*?>)#s',
86 | // Remove a line break and two or more white-space(s) between tag(s)
87 | '#()|(>)(?:\n*|\s{2,})(<)|^\s*|\s*$#s',
88 | '#()|(?)\s+(<\/.*?>)|(<[^\/]*?>)\s+(?!\<)#s',
89 | // t+c || o+t
90 | '#()|(<[^\/]*?>)\s+(<[^\/]*?>)|(<\/.*?>)\s+(<\/.*?>)#s',
91 | // o+o || c+c
92 | '#()|(<\/.*?>)\s+(\s)(?!\<)|(?)\s+(\s)(<[^\/]*?\/?>)|(<[^\/]*?\/?>)\s+(\s)(?!\<)#s',
93 | // c+t || t+o || o+t -- separated by long white-space(s)
94 | '#()|(<[^\/]*?>)\s+(<\/.*?>)#s',
95 | // empty tag
96 | '#<(img|input)(>| .*?>)<\/\1>#s',
97 | // reset previous fix
98 | '#( ) (?![<\s])#',
99 | // clean up ...
100 | '#(?<=\>)( )(?=\<)#',
101 | // --ibid
102 | '/\s+/',
103 | ],[
104 | '<$1$2$1>',
105 | '$1$2$3',
106 | '$1$2$3',
107 | '$1$2$3$4$5',
108 | '$1$2$3$4$5$6$7',
109 | '$1$2$3',
110 | '<$1$2',
111 | '$1 ',
112 | '$1',
113 | " ",
114 | ], $value));
115 |
116 | $allowRemoveComments = (bool) config("laravel-html-minifier.remove_comments", true);
117 |
118 | return $allowRemoveComments == false
119 | ? $value
120 | : $this->removeComment($value);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Middleware/MinifyJavascript.php:
--------------------------------------------------------------------------------
1 | getByTag("script") as $el)
18 | {
19 | $value = $this->replace($el->nodeValue);
20 |
21 | /* Apakah fungsi obfuscate diaktifkan? */
22 | if ($obfuscate)
23 | {
24 | $value = $this->obfuscate($value);
25 | }
26 | $el->nodeValue = "";
27 | $el->appendChild(static::$dom->createTextNode($value));
28 | }
29 |
30 | return static::$dom->saveHtml();
31 | }
32 |
33 | protected function insertSemicolon($value)
34 | {
35 | /**
36 | * menghapus semua komentar
37 | */
38 | $value = preg_replace('/(?:(?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:(?, :, ?, .
62 | '#(?:({|\[|\(|,|;|=>|\:|\?|\.))$#',
63 | // temukan blank spasi
64 | '#^\s*$#',
65 | // temukan string pertama dan terakhir do, else
66 | '#^(do|else)$#'
67 | ];
68 |
69 | $loop = 0;
70 |
71 | foreach ($code as $line)
72 | {
73 | $loop++;
74 | $insert = false;
75 | $shouldInsert = true;
76 |
77 | foreach ($patternRegex as $pattern)
78 | {
79 | // jika pattern tidak cocok artinya boleh ditambahkan semicolon
80 | $match = preg_match($pattern, trim($line));
81 | $shouldInsert = $shouldInsert && (bool) !$match;
82 | }
83 |
84 | if ($shouldInsert)
85 | {
86 | $i = $loop;
87 |
88 | while (true)
89 | {
90 | if ($i >= count($code))
91 | {
92 | $insert = true;
93 | break;
94 | }
95 |
96 | $c = trim($code[$i]);
97 | $i++;
98 |
99 | if (!$c)
100 | {
101 | continue;
102 | }
103 |
104 | $insert = true;
105 | $regex = ['#^(\?|\:|,|\.|{|}|\)|\])#'];
106 |
107 | foreach ($regex as $r)
108 | {
109 | $insert = $insert && (bool) !preg_match($r, $c);
110 | }
111 |
112 | if ($insert)
113 | {
114 | if (preg_match("#(?:\\})$#", trim($line)) && preg_match("#^(else|elseif|else\s*if|catch)#", $c))
115 | {
116 | $insert = false;
117 | }
118 | }
119 |
120 | break;
121 | }
122 | }
123 |
124 | if ($insert)
125 | {
126 | $result[] = sprintf("%s;", $line);
127 | }
128 | else
129 | {
130 | $result[] = $line;
131 | }
132 |
133 | }
134 |
135 | return join("\n", $result);
136 | }
137 |
138 | protected function replace($value)
139 | {
140 | if (static::$allowInsertSemicolon)
141 | {
142 | $value = $this->insertSemicolon($value);
143 | }
144 |
145 | return trim(preg_replace([
146 | '#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s',
149 | // Remove the last semicolon
150 | '#;+\}#',
151 | // Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}`
152 | '#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i',
153 | // --ibid. From `foo['bar']` to `foo.bar`
154 | '#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i'
155 | ],[
156 | '$1',
157 | '$1$2',
158 | '}',
159 | '$1$3',
160 | '$1.$3'
161 | ], $value));
162 | }
163 |
164 | protected function obfuscate($value)
165 | {
166 | $ords = [];
167 |
168 | for ($i = 0; $i < strlen($value); $i++)
169 | {
170 | $ords[] = ord($value[$i]);
171 | }
172 |
173 | $template = sprintf("
174 | eval(((_, __, ___, ____, _____, ______, _______) => {
175 | ______[___](x => _______[__](String[____](x)));
176 | return _______[_](_____)
177 | })('join', 'push', 'forEach', 'fromCharCode', '', %s, []))
178 |
179 | ", json_encode($ords));
180 |
181 | return $this->replace($template);
182 | }
183 | }
184 |
--------------------------------------------------------------------------------