Version Description
| June 25th, 2022 = * Fixed: shorthand syntax (r,i,b,bi) is now parsed correctly. * Added: Basic Variable Fonts support (full support coming in 5.3.0!) * Fixed: "preload" attributes added by 3rd party plugins would somehow be misunderstood as preload resource hints. * Deprecated: Force Subsets (Pro) and Include File Types (Pro) are marked as deprecated in preparation for the upcoming release which includes full Variable Fonts support, rendering these options useless.
Download this release
Release Info
Developer | DaanvandenBergh |
Plugin | OMGF | GDPR/DSVGO Compliant, Faster Google Fonts. Easy. |
Version | 5.2.1 |
Comparing to | |
See all releases |
Code changes from version 5.2.0 to 5.2.1
- host-webfonts-local.php +1 -1
- includes/admin/settings/class-optimize.php +15 -2
- includes/class-optimize.php +121 -1
- includes/class-stylesheet-generator.php +5 -0
- includes/frontend/class-process.php +4 -1
- readme.md +1 -1
- readme.txt +8 -2
host-webfonts-local.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
* Plugin Name: OMGF
|
5 |
* Plugin URI: https://ffw.press/wordpress/omgf/
|
6 |
* Description: Increase GDPR compliance, reduce DNS requests and leverage browser cache by automatically downloading Google Fonts to your server.
|
7 |
-
* Version: 5.2.
|
8 |
* Author: Daan from FFW.Press
|
9 |
* Author URI: https://ffw.press
|
10 |
* License: GPL2v2 or later
|
4 |
* Plugin Name: OMGF
|
5 |
* Plugin URI: https://ffw.press/wordpress/omgf/
|
6 |
* Description: Increase GDPR compliance, reduce DNS requests and leverage browser cache by automatically downloading Google Fonts to your server.
|
7 |
+
* Version: 5.2.1
|
8 |
* Author: Daan from FFW.Press
|
9 |
* Author URI: https://ffw.press
|
10 |
* License: GPL2v2 or later
|
includes/admin/settings/class-optimize.php
CHANGED
@@ -197,7 +197,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
197 |
public function do_promo_include_file_types()
|
198 |
{
|
199 |
$this->do_select(
|
200 |
-
__('Include File Types (Pro)', $this->plugin_text_domain),
|
201 |
'omgf_pro_file_types',
|
202 |
OMGF_Admin_Settings::OMGF_FILE_TYPES_OPTIONS,
|
203 |
defined('OMGF_PRO_FILE_TYPES') ? OMGF_PRO_FILE_TYPES : [],
|
@@ -213,7 +213,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
213 |
public function do_promo_force_subsets()
|
214 |
{
|
215 |
$this->do_select(
|
216 |
-
__('Force Subsets (Pro)', $this->plugin_text_domain),
|
217 |
'omgf_pro_force_subsets',
|
218 |
OMGF_Admin_Settings::OMGF_FORCE_SUBSETS_OPTIONS,
|
219 |
defined('OMGF_PRO_FORCE_SUBSETS') ? OMGF_PRO_FORCE_SUBSETS : [],
|
@@ -315,7 +315,20 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
315 |
<input autocomplete="off" type="checkbox" class="replace" <?= $replace; ?> <?= $fallback ? '' : 'disabled'; ?> <?= apply_filters('omgf_pro_replace_font_setting_disabled', true) ? 'disabled' : ''; ?> name="omgf_pro_replace_font[<?= $handle; ?>][<?= $font->id; ?>]" />
|
316 |
</td>
|
317 |
</tr>
|
|
|
318 |
<?php foreach ($font->variants as $variant) : ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
<tr>
|
320 |
<td></td>
|
321 |
<?php
|
197 |
public function do_promo_include_file_types()
|
198 |
{
|
199 |
$this->do_select(
|
200 |
+
__('Include File Types (Pro) (Deprecated)', $this->plugin_text_domain),
|
201 |
'omgf_pro_file_types',
|
202 |
OMGF_Admin_Settings::OMGF_FILE_TYPES_OPTIONS,
|
203 |
defined('OMGF_PRO_FILE_TYPES') ? OMGF_PRO_FILE_TYPES : [],
|
213 |
public function do_promo_force_subsets()
|
214 |
{
|
215 |
$this->do_select(
|
216 |
+
__('Force Subsets (Pro) (Deprecated)', $this->plugin_text_domain),
|
217 |
'omgf_pro_force_subsets',
|
218 |
OMGF_Admin_Settings::OMGF_FORCE_SUBSETS_OPTIONS,
|
219 |
defined('OMGF_PRO_FORCE_SUBSETS') ? OMGF_PRO_FORCE_SUBSETS : [],
|
315 |
<input autocomplete="off" type="checkbox" class="replace" <?= $replace; ?> <?= $fallback ? '' : 'disabled'; ?> <?= apply_filters('omgf_pro_replace_font_setting_disabled', true) ? 'disabled' : ''; ?> name="omgf_pro_replace_font[<?= $handle; ?>][<?= $font->id; ?>]" />
|
316 |
</td>
|
317 |
</tr>
|
318 |
+
<?php $id = ''; ?>
|
319 |
<?php foreach ($font->variants as $variant) : ?>
|
320 |
+
<?php
|
321 |
+
/**
|
322 |
+
* @since v5.3.0: Variable Fonts are pulled directly from the Google Fonts API,
|
323 |
+
* which creates @font-face statements for each separate subset.
|
324 |
+
*
|
325 |
+
* This deals with the duplicate display of font styles. Which also
|
326 |
+
* means unloading and/or preloading will unload/preload all available
|
327 |
+
* subsets. It's a bit bloaty, but there's no alternative.
|
328 |
+
*/
|
329 |
+
if ($id == $variant->fontWeight . $variant->fontStyle) continue;
|
330 |
+
?>
|
331 |
+
<?php $id = $variant->fontWeight . $variant->fontStyle; ?>
|
332 |
<tr>
|
333 |
<td></td>
|
334 |
<?php
|
includes/class-optimize.php
CHANGED
@@ -33,6 +33,17 @@ class OMGF_Optimize
|
|
33 |
'muli' => 'mulish'
|
34 |
];
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/** @var string $family */
|
37 |
private $family = '';
|
38 |
|
@@ -182,7 +193,7 @@ class OMGF_Optimize
|
|
182 |
$font->family = rawurlencode($font->family);
|
183 |
|
184 |
foreach ($font->variants as &$variant) {
|
185 |
-
$filename = strtolower($font_id . '-' . $variant->fontStyle . '-' . $variant->fontWeight);
|
186 |
|
187 |
/**
|
188 |
* Encode font family, because it may contain spaces.
|
@@ -323,6 +334,13 @@ class OMGF_Optimize
|
|
323 |
|
324 |
$response_code = wp_remote_retrieve_response_code($response);
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
if ($response_code != 200) {
|
327 |
$error_body = wp_remote_retrieve_body($response);
|
328 |
$error_message = wp_remote_retrieve_response_message($response);
|
@@ -378,6 +396,99 @@ class OMGF_Optimize
|
|
378 |
return $response;
|
379 |
}
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
/**
|
382 |
* @param $request
|
383 |
* @param $font
|
@@ -391,6 +502,15 @@ class OMGF_Optimize
|
|
391 |
*/
|
392 |
$requested_variants = array_filter(explode(',', $request));
|
393 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
/**
|
395 |
* This means by default all fonts are requested, so we need to fill up the queue, before unloading the unwanted variants.
|
396 |
*/
|
33 |
'muli' => 'mulish'
|
34 |
];
|
35 |
|
36 |
+
/**
|
37 |
+
* @since 5.2.1 Use this map to convert shorthands (r(egular), i(talic), b(old) and b(old)i(talic)) to
|
38 |
+
* to human readable font style values.
|
39 |
+
*/
|
40 |
+
const OMGF_FONT_STYLES_MAP = [
|
41 |
+
'r' => '400',
|
42 |
+
'i' => '400italic',
|
43 |
+
'b' => '700',
|
44 |
+
'bi' => '700italic'
|
45 |
+
];
|
46 |
+
|
47 |
/** @var string $family */
|
48 |
private $family = '';
|
49 |
|
193 |
$font->family = rawurlencode($font->family);
|
194 |
|
195 |
foreach ($font->variants as &$variant) {
|
196 |
+
$filename = strtolower($font_id . '-' . $variant->fontStyle . '-' . (isset($variant->subset) ? $variant->subset . '-' : '') . $variant->fontWeight);
|
197 |
|
198 |
/**
|
199 |
* Encode font family, because it may contain spaces.
|
334 |
|
335 |
$response_code = wp_remote_retrieve_response_code($response);
|
336 |
|
337 |
+
/**
|
338 |
+
* Let's try and parse the stylesheet if it wasn't found on the API.
|
339 |
+
*/
|
340 |
+
if ($response_code == 404) {
|
341 |
+
return $this->parse_stylesheet($this->family, $id, $name);
|
342 |
+
}
|
343 |
+
|
344 |
if ($response_code != 200) {
|
345 |
$error_body = wp_remote_retrieve_body($response);
|
346 |
$error_message = wp_remote_retrieve_response_message($response);
|
396 |
return $response;
|
397 |
}
|
398 |
|
399 |
+
/**
|
400 |
+
* A workaround for font families which are not available on the Helper API, but are still
|
401 |
+
* served from the Google Fonts API (e.g. Open Sans Condensed)
|
402 |
+
*
|
403 |
+
* @param string $request The full request
|
404 |
+
* @param string $id Unique identifier for this font family
|
405 |
+
* @param string $font_family The full name of font family not available on the Helper API.
|
406 |
+
* @return array An empty array (if request to Google Fonts API returns a 404) or a
|
407 |
+
* valid Font Object: { }
|
408 |
+
*/
|
409 |
+
public function parse_stylesheet($request, $id, $font_family)
|
410 |
+
{
|
411 |
+
$requested_families = explode('|', $request);
|
412 |
+
|
413 |
+
foreach ($requested_families as $requested_family) {
|
414 |
+
if (strpos($requested_family, $font_family)) {
|
415 |
+
break;
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
$url = 'https://fonts.googleapis.com/css?family=' . urlencode($requested_family);
|
420 |
+
$response = wp_remote_get($url, [
|
421 |
+
// Retrieve WOFF2 files only.
|
422 |
+
'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0'
|
423 |
+
]);
|
424 |
+
|
425 |
+
$code = wp_remote_retrieve_response_code($response);
|
426 |
+
|
427 |
+
if ($code !== 200) {
|
428 |
+
return [];
|
429 |
+
}
|
430 |
+
|
431 |
+
$stylesheet = wp_remote_retrieve_body($response);
|
432 |
+
|
433 |
+
return (object) [
|
434 |
+
'id' => $id,
|
435 |
+
'family' => $font_family,
|
436 |
+
'variants' => $this->parse_variants($stylesheet, $font_family),
|
437 |
+
'subsets' => $this->parse_subsets($stylesheet, $font_family)
|
438 |
+
];
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Parse a stylesheet from Google Fonts' API into
|
443 |
+
*
|
444 |
+
* @param string $stylesheet
|
445 |
+
* @param string $font_family
|
446 |
+
*
|
447 |
+
* @return array
|
448 |
+
*/
|
449 |
+
private function parse_variants($stylesheet, $font_family)
|
450 |
+
{
|
451 |
+
preg_match_all('/\/\*\s.*?}/s', $stylesheet, $font_faces);
|
452 |
+
|
453 |
+
if (!isset($font_faces[0]) || empty($font_faces[0])) {
|
454 |
+
return [];
|
455 |
+
}
|
456 |
+
|
457 |
+
foreach ($font_faces[0] as $key => $font_face) {
|
458 |
+
preg_match('/font-style:\s(normal|italic);/', $font_face, $font_style);
|
459 |
+
preg_match('/font-weight:\s([0-9]+);/', $font_face, $font_weight);
|
460 |
+
preg_match('/src:\surl\((.*?woff2)\)/', $font_face, $font_src);
|
461 |
+
preg_match('/\/\*\s([a-z\-]+?)\s\*\//', $font_face, $subset);
|
462 |
+
preg_match('/unicode-range:\s(.*?);/', $font_face, $range);
|
463 |
+
|
464 |
+
$font_object[$key] = new stdClass();
|
465 |
+
$font_object[$key]->id = $font_weight[1] . ($font_style[1] == 'normal' ? '' : $font_style[1]);
|
466 |
+
$font_object[$key]->fontFamily = $font_family;
|
467 |
+
$font_object[$key]->fontStyle = $font_style[1];
|
468 |
+
$font_object[$key]->fontWeight = $font_weight[1];
|
469 |
+
$font_object[$key]->woff2 = $font_src[1];
|
470 |
+
$font_object[$key]->subset = $subset[1];
|
471 |
+
$font_object[$key]->range = $range[1];
|
472 |
+
}
|
473 |
+
|
474 |
+
return $font_object;
|
475 |
+
}
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Parse stylesheets for subsets, which in Google Fonts stylesheets are always
|
479 |
+
* included, commented above each @font-face statements, e.g. /* latin-ext */ /*
|
480 |
+
*/
|
481 |
+
private function parse_subsets($stylesheet)
|
482 |
+
{
|
483 |
+
preg_match_all('/\/\*\s([a-z\-]+?)\s\*\//', $stylesheet, $subsets);
|
484 |
+
|
485 |
+
if (!isset($subsets[1]) || empty($subsets[1])) {
|
486 |
+
return [];
|
487 |
+
}
|
488 |
+
|
489 |
+
return array_unique($subsets[1]);
|
490 |
+
}
|
491 |
+
|
492 |
/**
|
493 |
* @param $request
|
494 |
* @param $font
|
502 |
*/
|
503 |
$requested_variants = array_filter(explode(',', $request));
|
504 |
|
505 |
+
/**
|
506 |
+
* @since v5.2.1 Run a quick to see if shorthands (e.g. r,i,b,bi) are used in this request. And if so,
|
507 |
+
* convert them to human readable values (e.g. 400, 400italic)
|
508 |
+
*/
|
509 |
+
$replacements = self::OMGF_FONT_STYLES_MAP;
|
510 |
+
$requested_variants = array_map(function ($value) use ($replacements) {
|
511 |
+
return isset($replacements[$value]) ? $replacements[$value] : $value;
|
512 |
+
}, $requested_variants);
|
513 |
+
|
514 |
/**
|
515 |
* This means by default all fonts are requested, so we need to fill up the queue, before unloading the unwanted variants.
|
516 |
*/
|
includes/class-stylesheet-generator.php
CHANGED
@@ -107,6 +107,11 @@ class OMGF_StylesheetGenerator
|
|
107 |
}
|
108 |
|
109 |
$stylesheet .= $this->build_source_string($font_src_url);
|
|
|
|
|
|
|
|
|
|
|
110 |
$stylesheet .= "}\n";
|
111 |
}
|
112 |
}
|
107 |
}
|
108 |
|
109 |
$stylesheet .= $this->build_source_string($font_src_url);
|
110 |
+
|
111 |
+
if (isset($variant->range)) {
|
112 |
+
$stylesheet .= " unicode-range: $variant->range;\n";
|
113 |
+
}
|
114 |
+
|
115 |
$stylesheet .= "}\n";
|
116 |
}
|
117 |
}
|
includes/frontend/class-process.php
CHANGED
@@ -249,13 +249,16 @@ class OMGF_Frontend_Process
|
|
249 |
foreach ($resource_hints[0] as $key => $match) {
|
250 |
/**
|
251 |
* @since v5.1.5 Filter out any resource hints with a href pointing to Google Fonts' APIs.
|
|
|
|
|
|
|
252 |
*
|
253 |
* @todo: I think I should be able to use an array_filter here or something?
|
254 |
*/
|
255 |
foreach (self::RESOURCE_HINTS_URLS as $url) {
|
256 |
if (strpos($match, $url) !== false) {
|
257 |
foreach (self::RESOURCE_HINTS_ATTR as $attr) {
|
258 |
-
if (
|
259 |
$search[] = $match;
|
260 |
}
|
261 |
}
|
249 |
foreach ($resource_hints[0] as $key => $match) {
|
250 |
/**
|
251 |
* @since v5.1.5 Filter out any resource hints with a href pointing to Google Fonts' APIs.
|
252 |
+
* @since v5.2.1 Use preg_match() to exactly match an element's attribute, since 3rd party
|
253 |
+
* plugins (e.g. Asset Cleanup) also tend to include their own custom attributes,
|
254 |
+
* e.g. data-wpacu-to-be-preloaded
|
255 |
*
|
256 |
* @todo: I think I should be able to use an array_filter here or something?
|
257 |
*/
|
258 |
foreach (self::RESOURCE_HINTS_URLS as $url) {
|
259 |
if (strpos($match, $url) !== false) {
|
260 |
foreach (self::RESOURCE_HINTS_ATTR as $attr) {
|
261 |
+
if (preg_match("/['\"]{$attr}['\"]/", $match) === 1) {
|
262 |
$search[] = $match;
|
263 |
}
|
264 |
}
|
readme.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
# OMGF |
|
2 |
|
3 |
OMGF automagically caches the Google Fonts used by your theme/plugins locally. No configuration (or brains) required!
|
4 |
|
1 |
+
# OMGF | GDPR Compliant, Faster Google Fonts. Easy.
|
2 |
|
3 |
OMGF automagically caches the Google Fonts used by your theme/plugins locally. No configuration (or brains) required!
|
4 |
|
readme.txt
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
-
=== OMGF |
|
2 |
Contributors: DaanvandenBergh
|
3 |
Tags: google, fonts, gdpr, cache, speed, preload, font-display, webfonts, subsets, remove, minimize, external, requests
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 6.0
|
6 |
-
Stable tag: 5.2.
|
7 |
Requires PHP: 7.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -75,6 +75,12 @@ For the FAQ, [click here](https://ffw.press/docs/omgf-pro-faq/).
|
|
75 |
|
76 |
== Changelog ==
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
= 5.2.0 | June 14th, 2022 =
|
79 |
* Added: toggle to disable Elementor/Divi compatibility fixes.
|
80 |
* Fixed: when resource hints (e.g. preloads) were located in unusual places (e.g. Themify Builder places its preloads above the `<title>` element) this would cause other elements (e.g. stylesheets) to be removed as well.
|
1 |
+
=== OMGF | GDPR Compliant, Faster Google Fonts. Easy. ===
|
2 |
Contributors: DaanvandenBergh
|
3 |
Tags: google, fonts, gdpr, cache, speed, preload, font-display, webfonts, subsets, remove, minimize, external, requests
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 6.0
|
6 |
+
Stable tag: 5.2.1
|
7 |
Requires PHP: 7.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
75 |
|
76 |
== Changelog ==
|
77 |
|
78 |
+
= 5.2.1 | June 25th, 2022 =
|
79 |
+
* Fixed: shorthand syntax (r,i,b,bi) is now parsed correctly.
|
80 |
+
* Added: Basic Variable Fonts support (full support coming in 5.3.0!)
|
81 |
+
* Fixed: "preload" attributes added by 3rd party plugins would somehow be misunderstood as preload resource hints.
|
82 |
+
* Deprecated: Force Subsets (Pro) and Include File Types (Pro) are marked as deprecated in preparation for the upcoming release which includes full Variable Fonts support, rendering these options useless.
|
83 |
+
|
84 |
= 5.2.0 | June 14th, 2022 =
|
85 |
* Added: toggle to disable Elementor/Divi compatibility fixes.
|
86 |
* Fixed: when resource hints (e.g. preloads) were located in unusual places (e.g. Themify Builder places its preloads above the `<title>` element) this would cause other elements (e.g. stylesheets) to be removed as well.
|