Compress JPEG & PNG images - Version 2.1.0

Version Description

  • Compression of retina images generated by WP Retina 2x.
  • Solved a bug which caused the API key to be cleared on the settings page.
  • Fixed an error that occurred with some PHP 7 installations.
  • Fixed an fopen error when preserving metadata.
Download this release

Release Info

Developer TinyPNG
Plugin Icon 128x128 Compress JPEG & PNG images
Version 2.1.0
Comparing to
See all releases

Code changes from version 2.0.2 to 2.1.0

.travis.yml CHANGED
@@ -8,6 +8,10 @@ php:
8
  - hhvm
9
  matrix:
10
  include:
 
 
 
 
11
  - dist: trusty
12
  php: 7.0
13
  env: WORDPRESS_VERSION=45 INTEGRATION_TESTS=true
8
  - hhvm
9
  matrix:
10
  include:
11
+ - dist: trusty
12
+ php: 7.0
13
+ env: WORDPRESS_VERSION=46 INTEGRATION_TESTS=true
14
+ script: bin/integration-tests
15
  - dist: trusty
16
  php: 7.0
17
  env: WORDPRESS_VERSION=45 INTEGRATION_TESTS=true
composer.lock CHANGED
@@ -256,16 +256,16 @@
256
  },
257
  {
258
  "name": "mikey179/vfsStream",
259
- "version": "v1.6.3",
260
  "source": {
261
  "type": "git",
262
  "url": "https://github.com/mikey179/vfsStream.git",
263
- "reference": "c19925cd0390d3c436a0203ae859afa460d0474b"
264
  },
265
  "dist": {
266
  "type": "zip",
267
- "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/c19925cd0390d3c436a0203ae859afa460d0474b",
268
- "reference": "c19925cd0390d3c436a0203ae859afa460d0474b",
269
  "shasum": ""
270
  },
271
  "require": {
@@ -298,7 +298,7 @@
298
  ],
299
  "description": "Virtual file system to mock the real file system in unit tests.",
300
  "homepage": "http://vfs.bovigo.org/",
301
- "time": "2016-04-09 09:42:01"
302
  },
303
  {
304
  "name": "mockery/mockery",
@@ -721,16 +721,16 @@
721
  },
722
  {
723
  "name": "phpunit/phpunit",
724
- "version": "4.8.26",
725
  "source": {
726
  "type": "git",
727
  "url": "https://github.com/sebastianbergmann/phpunit.git",
728
- "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
729
  },
730
  "dist": {
731
  "type": "zip",
732
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
733
- "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
734
  "shasum": ""
735
  },
736
  "require": {
@@ -789,7 +789,7 @@
789
  "testing",
790
  "xunit"
791
  ],
792
- "time": "2016-05-17 03:09:28"
793
  },
794
  {
795
  "name": "phpunit/phpunit-mock-objects",
@@ -1299,16 +1299,16 @@
1299
  },
1300
  {
1301
  "name": "symfony/yaml",
1302
- "version": "v2.8.8",
1303
  "source": {
1304
  "type": "git",
1305
  "url": "https://github.com/symfony/yaml.git",
1306
- "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8"
1307
  },
1308
  "dist": {
1309
  "type": "zip",
1310
- "url": "https://api.github.com/repos/symfony/yaml/zipball/dba4bb5846798cd12f32e2d8f3f35d77045773c8",
1311
- "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8",
1312
  "shasum": ""
1313
  },
1314
  "require": {
@@ -1344,7 +1344,7 @@
1344
  ],
1345
  "description": "Symfony Yaml Component",
1346
  "homepage": "https://symfony.com",
1347
- "time": "2016-06-29 05:29:29"
1348
  },
1349
  {
1350
  "name": "tinify/tinify",
@@ -1352,12 +1352,12 @@
1352
  "source": {
1353
  "type": "git",
1354
  "url": "https://github.com/tinify/tinify-php.git",
1355
- "reference": "c369f9fd8ea1bae4654bac6f4d3ed4070fb75f03"
1356
  },
1357
  "dist": {
1358
  "type": "zip",
1359
- "url": "https://api.github.com/repos/tinify/tinify-php/zipball/c369f9fd8ea1bae4654bac6f4d3ed4070fb75f03",
1360
- "reference": "c369f9fd8ea1bae4654bac6f4d3ed4070fb75f03",
1361
  "shasum": ""
1362
  },
1363
  "require": {
@@ -1404,7 +1404,7 @@
1404
  "source": "https://github.com/tinify/tinify-php/tree/create-key",
1405
  "issues": "https://github.com/tinify/tinify-php/issues"
1406
  },
1407
- "time": "2016-06-22 11:58:28"
1408
  },
1409
  {
1410
  "name": "wp-coding-standards/wpcs",
256
  },
257
  {
258
  "name": "mikey179/vfsStream",
259
+ "version": "v1.6.4",
260
  "source": {
261
  "type": "git",
262
  "url": "https://github.com/mikey179/vfsStream.git",
263
+ "reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592"
264
  },
265
  "dist": {
266
  "type": "zip",
267
+ "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/0247f57b2245e8ad2e689d7cee754b45fbabd592",
268
+ "reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592",
269
  "shasum": ""
270
  },
271
  "require": {
298
  ],
299
  "description": "Virtual file system to mock the real file system in unit tests.",
300
  "homepage": "http://vfs.bovigo.org/",
301
+ "time": "2016-07-18 14:02:57"
302
  },
303
  {
304
  "name": "mockery/mockery",
721
  },
722
  {
723
  "name": "phpunit/phpunit",
724
+ "version": "4.8.27",
725
  "source": {
726
  "type": "git",
727
  "url": "https://github.com/sebastianbergmann/phpunit.git",
728
+ "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90"
729
  },
730
  "dist": {
731
  "type": "zip",
732
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90",
733
+ "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90",
734
  "shasum": ""
735
  },
736
  "require": {
789
  "testing",
790
  "xunit"
791
  ],
792
+ "time": "2016-07-21 06:48:14"
793
  },
794
  {
795
  "name": "phpunit/phpunit-mock-objects",
1299
  },
1300
  {
1301
  "name": "symfony/yaml",
1302
+ "version": "v2.8.9",
1303
  "source": {
1304
  "type": "git",
1305
  "url": "https://github.com/symfony/yaml.git",
1306
+ "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d"
1307
  },
1308
  "dist": {
1309
  "type": "zip",
1310
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/0ceab136f43ed9d3e97b3eea32a7855dc50c121d",
1311
+ "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d",
1312
  "shasum": ""
1313
  },
1314
  "require": {
1344
  ],
1345
  "description": "Symfony Yaml Component",
1346
  "homepage": "https://symfony.com",
1347
+ "time": "2016-07-17 09:06:15"
1348
  },
1349
  {
1350
  "name": "tinify/tinify",
1352
  "source": {
1353
  "type": "git",
1354
  "url": "https://github.com/tinify/tinify-php.git",
1355
+ "reference": "8c1a4f123638204d409995e629d749c8655f4004"
1356
  },
1357
  "dist": {
1358
  "type": "zip",
1359
+ "url": "https://api.github.com/repos/tinify/tinify-php/zipball/8c1a4f123638204d409995e629d749c8655f4004",
1360
+ "reference": "8c1a4f123638204d409995e629d749c8655f4004",
1361
  "shasum": ""
1362
  },
1363
  "require": {
1404
  "source": "https://github.com/tinify/tinify-php/tree/create-key",
1405
  "issues": "https://github.com/tinify/tinify-php/issues"
1406
  },
1407
+ "time": "2016-08-10 07:21:14"
1408
  },
1409
  {
1410
  "name": "wp-coding-standards/wpcs",
config/Dockerfile-wordpress-46 ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM wordpress:4
2
+
3
+ ENV WORDPRESS_VERSION 4.6
4
+ ENV WORDPRESS_UPSTREAM_VERSION 4.6
5
+ ENV WORDPRESS_SHA1 830962689f350e43cd1a069f3a4f68a44c0339c8
6
+
7
+ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
+ RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
+ && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
+ && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
+ && rm wordpress.tar.gz \
12
+ && chown -R www-data:www-data /usr/src/wordpress
13
+
14
+ ENTRYPOINT ["/entrypoint.sh"]
15
+ CMD ["apache2-foreground"]
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://tinypng.com/
4
  Tags: optimize, compress, shrink, resize, faster, fit, scale, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, performance, panda, wordpress app
5
  Requires at least: 3.0.6
6
  Tested up to: 4.6
7
- Stable tag: 2.0.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -24,6 +24,7 @@ Make your website faster by optimizing your JPEG and PNG images. This plugin aut
24
  * Select which thumbnail sizes of an image may be optimized.
25
  * Multisite support with a single API key.
26
  * WooCommerce compatible.
 
27
  * See your usage from the media settings and during bulk optimization.
28
  * Color profiles are automatically translated to the standard RGB color space.
29
  * Convert CMYK to RGB to save more space and maximize compatibility.
@@ -107,6 +108,12 @@ A: Yes! After installing the plugin, go to *Media > Bulk Optimization*, and clic
107
 
108
  == Changelog ==
109
 
 
 
 
 
 
 
110
  = 2.0.2 =
111
  * Faster Bulk Optimization page with reduced memory usage (thanks to @esmus).
112
  * Fixed XML-RPC error (thanks @ironmanixs, @gingerdog, @quicoto and @isaumya).
4
  Tags: optimize, compress, shrink, resize, faster, fit, scale, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, performance, panda, wordpress app
5
  Requires at least: 3.0.6
6
  Tested up to: 4.6
7
+ Stable tag: 2.1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
24
  * Select which thumbnail sizes of an image may be optimized.
25
  * Multisite support with a single API key.
26
  * WooCommerce compatible.
27
+ * WP Retina 2x compatible.
28
  * See your usage from the media settings and during bulk optimization.
29
  * Color profiles are automatically translated to the standard RGB color space.
30
  * Convert CMYK to RGB to save more space and maximize compatibility.
108
 
109
  == Changelog ==
110
 
111
+ = 2.1.0 =
112
+ * Compression of retina images generated by WP Retina 2x.
113
+ * Solved a bug which caused the API key to be cleared on the settings page.
114
+ * Fixed an error that occurred with some PHP 7 installations.
115
+ * Fixed an fopen error when preserving metadata.
116
+
117
  = 2.0.2 =
118
  * Faster Bulk Optimization page with reduced memory usage (thanks to @esmus).
119
  * Fixed XML-RPC error (thanks @ironmanixs, @gingerdog, @quicoto and @isaumya).
src/class-tiny-compress-fopen.php CHANGED
@@ -193,12 +193,12 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
193
  return $res;
194
  }
195
 
196
- private function request_options( $method, $body = null ) {
197
  return array(
198
  'http' => array(
199
  'method' => $method,
200
  'header' => array(
201
- 'Content-type: image/png',
202
  'Authorization: Basic ' . base64_encode( 'api:' . $this->api_key ),
203
  'User-Agent: ' . self::identifier(),
204
  ),
@@ -226,8 +226,7 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
226
  }
227
 
228
  if ( $resize_opts || $preserve_opts ) {
229
- $options['http']['header'][] = 'Content-Type: application/json';
230
- return $this->request_options( 'GET', json_encode( $body ) );
231
  } else {
232
  return $this->request_options( 'GET', null );
233
  }
193
  return $res;
194
  }
195
 
196
+ private function request_options( $method, $body = null, $content_type = 'image/png' ) {
197
  return array(
198
  'http' => array(
199
  'method' => $method,
200
  'header' => array(
201
+ 'Content-type: ' . $content_type,
202
  'Authorization: Basic ' . base64_encode( 'api:' . $this->api_key ),
203
  'User-Agent: ' . self::identifier(),
204
  ),
226
  }
227
 
228
  if ( $resize_opts || $preserve_opts ) {
229
+ return $this->request_options( 'GET', json_encode( $body ), 'application/json' );
 
230
  } else {
231
  return $this->request_options( 'GET', null );
232
  }
src/class-tiny-image.php CHANGED
@@ -114,7 +114,14 @@ class Tiny_Image {
114
  if ( $tiny_metadata ) {
115
  foreach ( $tiny_metadata as $size => $meta ) {
116
  if ( ! isset( $this->sizes[ $size ] ) ) {
117
- $this->sizes[ $size ] = new Tiny_Image_Size();
 
 
 
 
 
 
 
118
  }
119
  $this->sizes[ $size ]->meta = $meta;
120
  }
@@ -174,6 +181,43 @@ class Tiny_Image {
174
  return array( 'success' => $success, 'failed' => $failed );
175
  }
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  public function add_wp_metadata( $size_name, $size ) {
178
  if ( self::is_original( $size_name ) ) {
179
  if ( isset( $size->meta['output'] ) ) {
@@ -414,4 +458,8 @@ class Tiny_Image {
414
  public static function is_original( $size ) {
415
  return self::ORIGINAL === $size;
416
  }
 
 
 
 
417
  }
114
  if ( $tiny_metadata ) {
115
  foreach ( $tiny_metadata as $size => $meta ) {
116
  if ( ! isset( $this->sizes[ $size ] ) ) {
117
+ if ( self::is_retina( $size ) && Tiny_Settings::wr2x_active() ) {
118
+ $retina_path = wr2x_get_retina(
119
+ $this->sizes[ rtrim( $size, '_wr2x' ) ]->filename
120
+ );
121
+ $this->sizes[ $size ] = new Tiny_Image_Size( $retina_path );
122
+ } else {
123
+ $this->sizes[ $size ] = new Tiny_Image_Size();
124
+ }
125
  }
126
  $this->sizes[ $size ]->meta = $meta;
127
  }
181
  return array( 'success' => $success, 'failed' => $failed );
182
  }
183
 
184
+ public function compress_retina( $size_name, $path ) {
185
+ if ( $this->settings->get_compressor() === null || ! $this->file_type_allowed() ) {
186
+ return;
187
+ }
188
+
189
+ if ( ! isset( $this->sizes[ $size_name ] ) ) {
190
+ $this->sizes[ $size_name ] = new Tiny_Image_Size( $path );
191
+ }
192
+ $size = $this->sizes[ $size_name ];
193
+
194
+ if ( ! $size->has_been_compressed() ) {
195
+ $size->add_tiny_meta_start();
196
+ $this->update_tiny_post_meta();
197
+ $compressor = $this->settings->get_compressor();
198
+ $preserve = $this->settings->get_preserve_options( $size_name );
199
+
200
+ try {
201
+ $response = $compressor->compress_file( $path, false, $preserve );
202
+ $size->add_tiny_meta( $response );
203
+ } catch (Tiny_Exception $e) {
204
+ $size->add_tiny_meta_error( $e );
205
+ }
206
+ $this->update_tiny_post_meta();
207
+ }
208
+ }
209
+
210
+ public function remove_retina_metadata() {
211
+ // Remove metadata from all sizes, as this callback only fires when all
212
+ // retina sizes are deleted.
213
+ foreach ( $this->sizes as $size_name => $size ) {
214
+ if ( self::is_retina( $size_name ) ) {
215
+ unset( $this->sizes[ $size_name ] );
216
+ }
217
+ }
218
+ $this->update_tiny_post_meta();
219
+ }
220
+
221
  public function add_wp_metadata( $size_name, $size ) {
222
  if ( self::is_original( $size_name ) ) {
223
  if ( isset( $size->meta['output'] ) ) {
458
  public static function is_original( $size ) {
459
  return self::ORIGINAL === $size;
460
  }
461
+
462
+ public static function is_retina( $size ) {
463
+ return strrpos( $size, 'wr2x' ) === strlen( $size ) - strlen( 'wr2x' );
464
+ }
465
  }
src/class-tiny-plugin.php CHANGED
@@ -19,7 +19,7 @@
19
  */
20
 
21
  class Tiny_Plugin extends Tiny_WP_Base {
22
- const VERSION = '2.0.2';
23
  const MEDIA_COLUMN = self::NAME;
24
  const DATETIME_FORMAT = 'Y-m-d G:i:s';
25
 
@@ -113,6 +113,16 @@ class Tiny_Plugin extends Tiny_WP_Base {
113
  $this->get_method( 'add_plugin_links' )
114
  );
115
 
 
 
 
 
 
 
 
 
 
 
116
  add_thickbox();
117
  }
118
 
@@ -141,6 +151,18 @@ class Tiny_Plugin extends Tiny_WP_Base {
141
  return array_merge( $additional, $current_links );
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  public function enqueue_scripts( $hook ) {
145
  wp_enqueue_style( self::NAME .'_admin',
146
  plugins_url( '/css/admin.css', __FILE__ ),
@@ -436,6 +458,12 @@ class Tiny_Plugin extends Tiny_WP_Base {
436
  return $admin_colors;
437
  }
438
 
 
 
 
 
 
 
439
  private function get_ids_to_compress() {
440
  if ( empty( $_REQUEST['ids'] ) ) {
441
  return array();
19
  */
20
 
21
  class Tiny_Plugin extends Tiny_WP_Base {
22
+ const VERSION = '2.1.0';
23
  const MEDIA_COLUMN = self::NAME;
24
  const DATETIME_FORMAT = 'Y-m-d G:i:s';
25
 
113
  $this->get_method( 'add_plugin_links' )
114
  );
115
 
116
+ add_action( 'wr2x_retina_file_added',
117
+ $this->get_method( 'compress_retina_image' ),
118
+ 10, 3
119
+ );
120
+
121
+ add_action( 'wr2x_retina_file_removed',
122
+ $this->get_method( 'remove_retina_image' ),
123
+ 10, 2
124
+ );
125
+
126
  add_thickbox();
127
  }
128
 
151
  return array_merge( $additional, $current_links );
152
  }
153
 
154
+ public function compress_retina_image( $attachment_id, $path, $size_name ) {
155
+ if ( $this->settings->compress_wr2x_images() ) {
156
+ $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
157
+ $tiny_image->compress_retina( $size_name . '_wr2x', $path );
158
+ }
159
+ }
160
+
161
+ public function remove_retina_image( $attachment_id, $path ) {
162
+ $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
163
+ $tiny_image->remove_retina_metadata();
164
+ }
165
+
166
  public function enqueue_scripts( $hook ) {
167
  wp_enqueue_style( self::NAME .'_admin',
168
  plugins_url( '/css/admin.css', __FILE__ ),
458
  return $admin_colors;
459
  }
460
 
461
+ function friendly_user_name() {
462
+ $user = wp_get_current_user();
463
+ $name = ucfirst( empty( $user->first_name ) ? $user->display_name : $user->first_name );
464
+ return $name;
465
+ }
466
+
467
  private function get_ids_to_compress() {
468
  if ( empty( $_REQUEST['ids'] ) ) {
469
  return array();
src/class-tiny-settings.php CHANGED
@@ -166,9 +166,9 @@ class Tiny_Settings extends Tiny_WP_Base {
166
  public function image_sizes_notice() {
167
  $this->render_image_sizes_notice(
168
  $_GET['image_sizes_selected'],
169
- isset( $_GET['resize_original'] )
 
170
  );
171
-
172
  exit();
173
  }
174
 
@@ -356,12 +356,16 @@ class Tiny_Settings extends Tiny_WP_Base {
356
  foreach ( $this->get_sizes() as $size => $option ) {
357
  $this->render_size_checkbox( $size, $option );
358
  }
 
 
 
359
  echo '<br>';
360
  echo '<div id="tiny-image-sizes-notice">';
361
 
362
  $this->render_image_sizes_notice(
363
  count( self::get_active_tinify_sizes() ),
364
- self::get_resize_enabled()
 
365
  );
366
 
367
  echo '</div>';
@@ -374,6 +378,8 @@ class Tiny_Settings extends Tiny_WP_Base {
374
  if ( Tiny_Image::is_original( $size ) ) {
375
  $label = esc_html__( 'Original image', 'tiny-compress-images' ) . ' (' .
376
  esc_html__( 'overwritten by compressed image', 'tiny-compress-images' ) . ')';
 
 
377
  } else {
378
  $label = esc_html__( ucfirst( $size ) )
379
  . ' - ' . $option['width'] . 'x' . $option['height'];
@@ -385,11 +391,15 @@ class Tiny_Settings extends Tiny_WP_Base {
385
  echo '</p>';
386
  }
387
 
388
- public function render_image_sizes_notice( $active_sizes_count, $resize_original_enabled ) {
 
389
  echo '<p>';
390
  if ( $resize_original_enabled ) {
391
  $active_sizes_count++;
392
  }
 
 
 
393
 
394
  if ( $active_sizes_count < 1 ) {
395
  esc_html_e(
@@ -405,6 +415,20 @@ class Tiny_Settings extends Tiny_WP_Base {
405
  '<strong> at least %s images </strong> for free each month.',
406
  'tiny-compress-images'
407
  ), array( 'strong' => array() ) ), $free_images_per_month );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
408
  }
409
  echo '</p>';
410
  }
@@ -659,4 +683,22 @@ class Tiny_Settings extends Tiny_WP_Base {
659
  echo json_encode( $status );
660
  exit();
661
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  }
166
  public function image_sizes_notice() {
167
  $this->render_image_sizes_notice(
168
  $_GET['image_sizes_selected'],
169
+ isset( $_GET['resize_original'] ),
170
+ isset( $_GET['compress_wr2x'] )
171
  );
 
172
  exit();
173
  }
174
 
356
  foreach ( $this->get_sizes() as $size => $option ) {
357
  $this->render_size_checkbox( $size, $option );
358
  }
359
+ if ( self::wr2x_active() ) {
360
+ $this->render_size_checkbox( 'wr2x', $this->get_wr2x_option() );
361
+ }
362
  echo '<br>';
363
  echo '<div id="tiny-image-sizes-notice">';
364
 
365
  $this->render_image_sizes_notice(
366
  count( self::get_active_tinify_sizes() ),
367
+ self::get_resize_enabled(),
368
+ self::compress_wr2x_images()
369
  );
370
 
371
  echo '</div>';
378
  if ( Tiny_Image::is_original( $size ) ) {
379
  $label = esc_html__( 'Original image', 'tiny-compress-images' ) . ' (' .
380
  esc_html__( 'overwritten by compressed image', 'tiny-compress-images' ) . ')';
381
+ } else if ( Tiny_Image::is_retina( $size ) ) {
382
+ $label = esc_html__( 'WP Retina 2x sizes', 'tiny-compress-images' );
383
  } else {
384
  $label = esc_html__( ucfirst( $size ) )
385
  . ' - ' . $option['width'] . 'x' . $option['height'];
391
  echo '</p>';
392
  }
393
 
394
+ public function render_image_sizes_notice(
395
+ $active_sizes_count, $resize_original_enabled, $compress_wr2x ) {
396
  echo '<p>';
397
  if ( $resize_original_enabled ) {
398
  $active_sizes_count++;
399
  }
400
+ if ( $compress_wr2x ) {
401
+ $active_sizes_count *= 2;
402
+ }
403
 
404
  if ( $active_sizes_count < 1 ) {
405
  esc_html_e(
415
  '<strong> at least %s images </strong> for free each month.',
416
  'tiny-compress-images'
417
  ), array( 'strong' => array() ) ), $free_images_per_month );
418
+
419
+ if ( self::wr2x_active() ) {
420
+ echo '</p>';
421
+ echo '<p>';
422
+ esc_html_e(
423
+ 'If selected, retina sizes will be compressed when generated by WP Retina 2x',
424
+ 'tiny-compress-images'
425
+ );
426
+ echo '<br>';
427
+ esc_html_e(
428
+ 'Each retina size will count as an additional compression.',
429
+ 'tiny-compress-images'
430
+ );
431
+ }
432
  }
433
  echo '</p>';
434
  }
683
  echo json_encode( $status );
684
  exit();
685
  }
686
+
687
+ public static function wr2x_active() {
688
+ return is_plugin_active( 'wp-retina-2x/wp-retina-2x.php' );
689
+ }
690
+
691
+ public function get_wr2x_option() {
692
+ $setting = get_option( self::get_prefixed_name( 'sizes' ) );
693
+ return array(
694
+ 'width' => null,
695
+ 'height' => null,
696
+ 'tinify' => ( isset( $setting['wr2x'] ) && 'on' === $setting['wr2x'] ),
697
+ );
698
+ }
699
+
700
+ public function compress_wr2x_images() {
701
+ $option = $this->get_wr2x_option();
702
+ return self::wr2x_active() && $option['tinify'];
703
+ }
704
  }
src/css/bulk-optimization.css CHANGED
@@ -105,10 +105,6 @@ div.tiny-bulk-optimization div.available table.totals td.item div.tooltip div.ti
105
  text-align: left;
106
  }
107
 
108
- div.tiny-bulk-optimization div.available table.totals td.item div.tooltip:hover div.tip {
109
- display: block;
110
- }
111
-
112
  div.tiny-bulk-optimization div.available div.notes {
113
  display: table;
114
  }
@@ -265,6 +261,10 @@ div.tiny-bulk-optimization div.optimize div.progressbar div.progress {
265
  }
266
  }
267
 
 
 
 
 
268
  div.tiny-bulk-optimization div.optimize div.progressbar div.numbers {
269
  position: relative;
270
  z-index: 3;
105
  text-align: left;
106
  }
107
 
 
 
 
 
108
  div.tiny-bulk-optimization div.available div.notes {
109
  display: table;
110
  }
261
  }
262
  }
263
 
264
+ #tiny-bulk-optimization > div.dashboard > div.statistics td.item.costs > div.cost-currency {
265
+ display: inline-block;
266
+ }
267
+
268
  div.tiny-bulk-optimization div.optimize div.progressbar div.numbers {
269
  position: relative;
270
  z-index: 3;
src/js/admin.js CHANGED
@@ -208,10 +208,18 @@
208
  /* Unfortunately, we need some additional information to display
209
  the correct notice. */
210
  totalSelectedSizes = jQuery('input[name*=tinypng_sizes]:checked').length
 
 
 
 
 
211
  var image_count_url = ajaxurl + '?action=tiny_image_sizes_notice&image_sizes_selected=' + totalSelectedSizes
212
  if (propOf('#tinypng_resize_original_enabled', 'checked') && propOf('#tinypng_sizes_0', 'checked')) {
213
  image_count_url += '&resize_original=true'
214
  }
 
 
 
215
  jQuery('#tiny-image-sizes-notice').load(image_count_url)
216
  })
217
 
208
  /* Unfortunately, we need some additional information to display
209
  the correct notice. */
210
  totalSelectedSizes = jQuery('input[name*=tinypng_sizes]:checked').length
211
+ compressWr2x = propOf('#tinypng_sizes_wr2x', 'checked')
212
+ if (compressWr2x) {
213
+ totalSelectedSizes--;
214
+ }
215
+
216
  var image_count_url = ajaxurl + '?action=tiny_image_sizes_notice&image_sizes_selected=' + totalSelectedSizes
217
  if (propOf('#tinypng_resize_original_enabled', 'checked') && propOf('#tinypng_sizes_0', 'checked')) {
218
  image_count_url += '&resize_original=true'
219
  }
220
+ if (compressWr2x) {
221
+ image_count_url += '&compress_wr2x=true'
222
+ }
223
  jQuery('#tiny-image-sizes-notice').load(image_count_url)
224
  })
225
 
src/js/bulk-optimization.js CHANGED
@@ -211,6 +211,29 @@
211
  }
212
  });
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  window.bulkOptimizationAutorun = startBulkOptimization
215
  window.bulkOptimization = prepareBulkOptimization
216
 
211
  }
212
  });
213
 
214
+ function attachToolTipEventHandlers() {
215
+ var tooltip = '#tiny-bulk-optimization div.tooltip'
216
+ var tip = 'div.tip'
217
+ var toolTipTimeout = null
218
+ jQuery(tooltip).mouseleave(function(){
219
+ var that = this
220
+ toolTipTimeout = setTimeout(function() {
221
+ if (jQuery(that).find(tip).is(':visible')) {
222
+ jQuery(tooltip).find(tip).hide()
223
+ }
224
+ }, 100)
225
+ })
226
+ jQuery(tooltip).mouseenter(function(){
227
+ jQuery(this).find(tip).show()
228
+ clearTimeout(toolTipTimeout)
229
+ })
230
+ jQuery(tooltip).find(tip).mouseenter(function(){
231
+ clearTimeout(toolTipTimeout)
232
+ })
233
+ }
234
+
235
+ attachToolTipEventHandlers()
236
+
237
  window.bulkOptimizationAutorun = startBulkOptimization
238
  window.bulkOptimization = prepareBulkOptimization
239
 
src/vendor/tinify/Tinify/Client.php CHANGED
@@ -44,9 +44,12 @@ class Client {
44
 
45
  $url = strtolower(substr($url, 0, 6)) == "https:" ? $url : self::API_ENDPOINT . $url;
46
  curl_setopt($request, CURLOPT_URL, $url);
47
- curl_setopt($request, CURLOPT_HTTPHEADER, $header);
48
  curl_setopt($request, CURLOPT_CUSTOMREQUEST, strtoupper($method));
49
 
 
 
 
 
50
  if ($body) {
51
  curl_setopt($request, CURLOPT_POSTFIELDS, $body);
52
  }
44
 
45
  $url = strtolower(substr($url, 0, 6)) == "https:" ? $url : self::API_ENDPOINT . $url;
46
  curl_setopt($request, CURLOPT_URL, $url);
 
47
  curl_setopt($request, CURLOPT_CUSTOMREQUEST, strtoupper($method));
48
 
49
+ if (count($header) > 0) {
50
+ curl_setopt($request, CURLOPT_HTTPHEADER, $header);
51
+ }
52
+
53
  if ($body) {
54
  curl_setopt($request, CURLOPT_POSTFIELDS, $body);
55
  }
src/views/account-status-loading.php CHANGED
@@ -4,5 +4,9 @@
4
  'Retrieving account status',
5
  'tiny-compress-images'
6
  ); ?></p>
 
 
 
 
7
  </div>
8
  </div>
4
  'Retrieving account status',
5
  'tiny-compress-images'
6
  ); ?></p>
7
+
8
+ <input type="hidden" id="<?php echo esc_attr( self::get_prefixed_name( 'api_key' ) ); ?>"
9
+ name="<?php echo esc_attr( self::get_prefixed_name( 'api_key' ) ); ?>" size="35" spellcheck="false"
10
+ value="<?php echo esc_attr( $key ); ?>">
11
  </div>
12
  </div>
src/views/account-status-update.php CHANGED
@@ -15,8 +15,8 @@
15
  ), $link );
16
  ?></p>
17
 
18
- <input type="text" id="tinypng_api_key"
19
- name="tinypng_api_key" size="35" spellcheck="false"
20
  value="<?php echo esc_attr( $key ); ?>">
21
 
22
  <button class="button button-primary" data-tiny-action="update-key"><?php
15
  ), $link );
16
  ?></p>
17
 
18
+ <input type="text" id="<?php echo esc_attr( self::get_prefixed_name( 'api_key' ) ); ?>"
19
+ name="<?php echo esc_attr( self::get_prefixed_name( 'api_key' ) ); ?>" size="35" spellcheck="false"
20
  value="<?php echo esc_attr( $key ); ?>">
21
 
22
  <button class="button button-primary" data-tiny-action="update-key"><?php
src/views/bulk-optimization.php CHANGED
@@ -51,9 +51,13 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
51
  } elseif ( 0 == sizeof( $active_tinify_sizes ) ) {
52
  esc_html_e( 'Based on your current settings, nothing will be optimized. There are no active sizes selected for optimization.' );
53
  } elseif ( 0 == $stats['available-unoptimised-sizes'] ) {
54
- esc_html_e( 'Great! Your entire library is optimimized!' );
55
  } elseif ( $stats['optimized-image-sizes'] > 0 ) {
56
- ( $percentage_of_files > 75 ) ? esc_html_e( 'You are doing great!', 'tiny-compress-images' ) : esc_html_e( 'You are doing good.', 'tiny-compress-images' );
 
 
 
 
57
  echo ' ';
58
  printf( esc_html__( '%d%% of your image library is optimized.', 'tiny-compress-images' ), $percentage_of_files );
59
  echo ' ';
@@ -63,6 +67,13 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
63
  }
64
  ?>
65
  </p>
 
 
 
 
 
 
 
66
  <table class="totals">
67
  <tr>
68
  <td class="item">
@@ -110,6 +121,16 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
110
  }
111
  ?>
112
  </p>
 
 
 
 
 
 
 
 
 
 
113
  </div>
114
  </div>
115
  </td>
@@ -118,7 +139,23 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
118
  <?php echo wp_kses( __( 'Estimated <br> cost', 'tiny-compress-images' ), array( 'br' => array() ) ) ?>
119
  </h3>
120
  <span id="estimated-cost">$ <?php echo number_format( $estimated_costs, 2 ) ?></span>
121
- USD
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  </td>
123
  </tr>
124
  </table>
@@ -171,18 +208,16 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
171
  </div>
172
  </div>
173
  <div class="optimize">
174
- <?php if ( true ) { ?>
175
- <div class="progressbar" id="compression-progress-bar" data-number-to-optimize="<?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?>" data-amount-optimized="0">
176
- <div id="progress-size" class="progress">
177
- </div>
178
- <div class="numbers" >
179
- <span id="optimized-so-far"><?php echo $stats['optimized-image-sizes'] ?></span>
180
- /
181
- <span><?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?></span>
182
- <span id="percentage"></span>
183
- </div>
184
  </div>
185
- <?php } ?>
186
  <?php
187
  if ( $stats['available-unoptimised-sizes'] > 0 ) {
188
  require_once dirname( __FILE__ ) . '/bulk-optimization-form.php';
51
  } elseif ( 0 == sizeof( $active_tinify_sizes ) ) {
52
  esc_html_e( 'Based on your current settings, nothing will be optimized. There are no active sizes selected for optimization.' );
53
  } elseif ( 0 == $stats['available-unoptimised-sizes'] ) {
54
+ printf( esc_html__( '%s, this is great! Your entire library is optimized!' ), $this->friendly_user_name() );
55
  } elseif ( $stats['optimized-image-sizes'] > 0 ) {
56
+ if ( $percentage_of_files > 75 ) {
57
+ printf( esc_html__( '%s, you are doing great!', 'tiny-compress-images' ), $this->friendly_user_name() );
58
+ } else {
59
+ printf( esc_html__( '%s, you are doing good.', 'tiny-compress-images' ), $this->friendly_user_name() );
60
+ }
61
  echo ' ';
62
  printf( esc_html__( '%d%% of your image library is optimized.', 'tiny-compress-images' ), $percentage_of_files );
63
  echo ' ';
67
  }
68
  ?>
69
  </p>
70
+ <p>
71
+ <?php
72
+ if ( Tiny_Settings::wr2x_active() ) {
73
+ esc_html_e( 'Notice that the WP Retina 2x sizes will not be compressed using this page. You will need to bulk generate the retina sizes separately from the WP Retina 2x page.', 'tiny-compress-images' );
74
+ }
75
+ ?>
76
+ </p>
77
  <table class="totals">
78
  <tr>
79
  <td class="item">
121
  }
122
  ?>
123
  </p>
124
+ <p>
125
+ <?php esc_html_e( 'For each uploaded image, ', 'tiny-compress-images' ) ?>
126
+ <strong>
127
+ <?php echo sizeof( $active_tinify_sizes ) ?>
128
+ <?php sizeof( $active_tinify_sizes ) > 1 ? esc_html_e( 'sizes', 'tiny-compress-images' ) : esc_html_e( 'size', 'tiny-compress-images' ) ?>
129
+ </strong>
130
+ <?php sizeof( $active_tinify_sizes ) > 1 ? esc_html_e( 'are compressed.', 'tiny-compress-images' ) : esc_html_e( 'is compressed.', 'tiny-compress-images' ) ?>
131
+ <?php esc_html_e( 'You can changed these settings', 'tiny-compress-images' ) ?>
132
+ <a href="/wp-admin/options-media.php#tiny-compress-images"><?php esc_html_e( 'here', 'tiny-compress-images' )?></a>.
133
+ </p>
134
  </div>
135
  </div>
136
  </td>
139
  <?php echo wp_kses( __( 'Estimated <br> cost', 'tiny-compress-images' ), array( 'br' => array() ) ) ?>
140
  </h3>
141
  <span id="estimated-cost">$ <?php echo number_format( $estimated_costs, 2 ) ?></span>
142
+ <div class="cost-currency">USD</div>
143
+ <?php if ( $estimated_costs > 0 ) { ?>
144
+ <div class="tooltip">
145
+ <span class="dashicons dashicons-info"></span>
146
+ <div class="tip">
147
+ <p>
148
+ <?php esc_html_e( 'If you wish to compress more than ', 'tiny-compress-images' ) ?>
149
+ <strong>
150
+ <?php echo Tiny_Config::MONTHLY_FREE_COMPRESSIONS ?>
151
+ <?php esc_html_e( 'image sizes', 'tiny-compress-images' ) ?>
152
+ </strong>
153
+ <?php esc_html_e( 'a month and you are still on a free account', 'tiny-compress-images' ) ?>
154
+ <a href="https://tinypng.com/developers"><?php esc_html_e( 'upgrade here.', 'tiny-compress-images' ) ?></a>
155
+ </p>
156
+ </div>
157
+ </div>
158
+ <?php } ?>
159
  </td>
160
  </tr>
161
  </table>
208
  </div>
209
  </div>
210
  <div class="optimize">
211
+ <div class="progressbar" id="compression-progress-bar" data-number-to-optimize="<?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?>" data-amount-optimized="0">
212
+ <div id="progress-size" class="progress">
213
+ </div>
214
+ <div class="numbers" >
215
+ <span id="optimized-so-far"><?php echo $stats['optimized-image-sizes'] ?></span>
216
+ /
217
+ <span><?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?></span>
218
+ <span id="percentage"></span>
 
 
219
  </div>
220
+ </div>
221
  <?php
222
  if ( $stats['available-unoptimised-sizes'] > 0 ) {
223
  require_once dirname( __FILE__ ) . '/bulk-optimization-form.php';
src/views/compress-details.php CHANGED
@@ -87,14 +87,16 @@ ksort( $size_exists );
87
  <tr class="<?php echo ( 0 == $i % 2 ) ? 'even' : 'odd' ?>">
88
  <?php
89
  echo '<td>';
90
- echo ( Tiny_Image::is_original( $size_name ) ? esc_html__( 'Original', 'tiny-compress-images' ) : esc_html__( ucfirst( $size_name ) ) );
91
  echo ' ';
92
- if ( ! array_key_exists( $size_name, $active_sizes ) ) {
93
  echo '<em>' . esc_html__( '(not in use)', 'tiny-compress-images' ) . '</em>';
94
- } else if ( $size->missing() ) {
95
  echo '<em>' . esc_html__( '(file removed)', 'tiny-compress-images' ) . '</em>';
96
  } else if ( $size->modified() ) {
97
  echo '<em>' . esc_html__( '(modified after compression)', 'tiny-compress-images' ) . '</em>';
 
 
98
  } else if ( $size->resized() ) {
99
  printf( '<em>' . esc_html__( '(resized to %dx%d)', 'tiny-compress-images' ) . '</em>', $size->meta['output']['width'], $size->meta['output']['height'] );
100
  }
@@ -110,7 +112,7 @@ ksort( $size_exists );
110
  } else if ( ! $size->exists() ) {
111
  echo '<td>-</td>';
112
  echo '<td colspan=2><em>' . esc_html__( 'Not present', 'tiny-compress-images' ) . '</em></td>';
113
- } else if ( isset( $size_active[ $size_name ] ) ) {
114
  echo '<td>' . size_format( $size->filesize(), 1 ) . '</td>';
115
  echo '<td colspan=2><em>' . esc_html__( 'Not compressed', 'tiny-compress-images' ) . '</em></td>';
116
  } else if ( isset( $size_exists[ $size_name ] ) ) {
87
  <tr class="<?php echo ( 0 == $i % 2 ) ? 'even' : 'odd' ?>">
88
  <?php
89
  echo '<td>';
90
+ echo ( Tiny_Image::is_original( $size_name ) ? esc_html__( 'Original', 'tiny-compress-images' ) : esc_html__( ucfirst( rtrim( $size_name, '_wr2x' ) ) ) );
91
  echo ' ';
92
+ if ( ! array_key_exists( $size_name, $active_sizes ) && ! Tiny_Image::is_retina( $size_name ) ) {
93
  echo '<em>' . esc_html__( '(not in use)', 'tiny-compress-images' ) . '</em>';
94
+ } else if ( $size->missing() && ( Tiny_Settings::wr2x_active() || ! Tiny_Image::is_retina( $size_name ) ) ) {
95
  echo '<em>' . esc_html__( '(file removed)', 'tiny-compress-images' ) . '</em>';
96
  } else if ( $size->modified() ) {
97
  echo '<em>' . esc_html__( '(modified after compression)', 'tiny-compress-images' ) . '</em>';
98
+ } else if ( Tiny_Image::is_retina( $size_name ) ) {
99
+ echo '<em>' . esc_html__( '(WP Retina 2x)', 'tiny-compress-images' ) . '</em>';
100
  } else if ( $size->resized() ) {
101
  printf( '<em>' . esc_html__( '(resized to %dx%d)', 'tiny-compress-images' ) . '</em>', $size->meta['output']['width'], $size->meta['output']['height'] );
102
  }
112
  } else if ( ! $size->exists() ) {
113
  echo '<td>-</td>';
114
  echo '<td colspan=2><em>' . esc_html__( 'Not present', 'tiny-compress-images' ) . '</em></td>';
115
+ } else if ( isset( $size_active[ $size_name ] ) || Tiny_Image::is_retina( $size_name ) ) {
116
  echo '<td>' . size_format( $size->filesize(), 1 ) . '</td>';
117
  echo '<td colspan=2><em>' . esc_html__( 'Not compressed', 'tiny-compress-images' ) . '</em></td>';
118
  } else if ( isset( $size_exists[ $size_name ] ) ) {
test/helpers/setup.php CHANGED
@@ -40,16 +40,18 @@ function restore_wordpress() {
40
  }
41
  }
42
 
43
- function mysql_dump_file() {
 
 
44
  return dirname( __FILE__ ) . '/../../tmp/mysqldump_' . getenv( 'WORDPRESS_DATABASE' ) . '.sql.gz';
45
  }
46
 
47
  function restore_wordpress_site() {
48
- shell_exec( 'gunzip -c < ' . mysql_dump_file() . ' | mysql -h ' . getenv( 'HOST' ) . ' -u root ' . getenv( 'WORDPRESS_DATABASE' ) );
49
  }
50
 
51
  function backup_wordpress_site() {
52
- shell_exec( 'mysqldump -h ' . getenv( 'HOST' ) . ' -u root ' . getenv( 'WORDPRESS_DATABASE' ) . ' | gzip -c > ' . mysql_dump_file() );
53
  }
54
 
55
  function set_siteurl( $site_url ) {
40
  }
41
  }
42
 
43
+ // Renamed this function to mysqldump_file without underscore
44
+ // for compatibility with WP Engine PHP Compatibility Checker
45
+ function mysqldump_file() {
46
  return dirname( __FILE__ ) . '/../../tmp/mysqldump_' . getenv( 'WORDPRESS_DATABASE' ) . '.sql.gz';
47
  }
48
 
49
  function restore_wordpress_site() {
50
+ shell_exec( 'gunzip -c < ' . mysqldump_file() . ' | mysql -h ' . getenv( 'HOST' ) . ' -u root ' . getenv( 'WORDPRESS_DATABASE' ) );
51
  }
52
 
53
  function backup_wordpress_site() {
54
+ shell_exec( 'mysqldump -h ' . getenv( 'HOST' ) . ' -u root ' . getenv( 'WORDPRESS_DATABASE' ) . ' | gzip -c > ' . mysqldump_file() );
55
  }
56
 
57
  function set_siteurl( $site_url ) {
test/integration/BulkOptimizationIntegrationTest.php CHANGED
@@ -77,4 +77,8 @@ class BulkOptimizationIntegrationTest extends IntegrationTestCase {
77
 
78
  $this->assertEquals( '9 / 9 (100%)', $this->find( '#compression-progress-bar' )->getText() );
79
  }
 
 
 
 
80
  }
77
 
78
  $this->assertEquals( '9 / 9 (100%)', $this->find( '#compression-progress-bar' )->getText() );
79
  }
80
+
81
+ public function test_should_display_tooltips() {
82
+ $this->assertGreaterThanOrEqual( '1', sizeof($this->find_all( 'div.tip' )));
83
+ }
84
  }
test/unit/TinyImageTest.php CHANGED
@@ -121,4 +121,16 @@ class Tiny_Image_Test extends Tiny_TestCase {
121
  Tiny_Image::get_optimization_statistics( new Tiny_Settings(), $wpdb_results )
122
  );
123
  }
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
121
  Tiny_Image::get_optimization_statistics( new Tiny_Settings(), $wpdb_results )
122
  );
123
  }
124
+
125
+ public function test_is_retina_for_retina_size() {
126
+ $this->assertEquals( true, Tiny_Image::is_retina( 'small_wr2x' ) );
127
+ }
128
+
129
+ public function test_is_retina_for_non_retina_size() {
130
+ $this->assertEquals( false, Tiny_Image::is_retina( 'small' ) );
131
+ }
132
+
133
+ public function test_is_retina_for_non_retina_size_with_short_name() {
134
+ $this->assertEquals( false, Tiny_Image::is_retina( 'file' ) );
135
+ }
136
  }
tiny-compress-images.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
- * Version: 2.0.2
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * Text Domain: tiny-compress-images
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
+ * Version: 2.1.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * Text Domain: tiny-compress-images