Version Description
| July 20th, 2022 =
* Added: Removed Google Webfonts Helper API and implemented a custom Web Font Loader. This adds/fixes:
* Added: full support for Variable Fonts
* Fixed: Proper (WOFF2) compression, so files generated by OMGF are no longer bigger than files downloaded from the Google Fonts API.
* Fixed: The (broken capital A) compression bug is fixed!
* Fixed: Changed logo in Help section to Daan.dev logo
* Fixed: Remove unused subsets from Optimized Fonts object to reduce db size
* Fixed: OMGF_Optimize class will bail earlier, if files and stylesheets already exist, to reduce execution time in the frontend.
* Fixed: Invalid Google Fonts API requests (e.g. without a family
parameter) are removed from the HTML.
* Fixed: A stricter regulax expression is used for matching stylesheet link
elements, to prevent backtracking.
* Added: Used Subset(s) option, which allows users to specify which subset(s) they'd like to use when generating stylesheets and down-/preloading (variable) font files.
Release Info
Developer | DaanvandenBergh |
Plugin | OMGF | GDPR/DSVGO Compliant, Faster Google Fonts. Easy. |
Version | 5.3.0 |
Comparing to | |
See all releases |
Code changes from version 5.2.2 to 5.3.0
- assets/css/omgf-admin.css +3 -0
- assets/css/omgf-admin.css.map +1 -1
- assets/css/omgf-admin.less +4 -0
- assets/images/logo-color.png +0 -0
- assets/images/logo.png +0 -0
- assets/js/omgf-admin.js +11 -14
- host-webfonts-local.php +2 -2
- includes/admin/class-optimize.php +1 -1
- includes/admin/class-settings.php +3 -9
- includes/admin/settings/class-advanced.php +1 -1
- includes/admin/settings/class-builder.php +1 -1
- includes/admin/settings/class-detection.php +3 -3
- includes/admin/settings/class-help.php +2 -2
- includes/admin/settings/class-optimize.php +31 -32
- includes/class-omgf.php +22 -5
- includes/class-optimize.php +267 -366
- includes/class-stylesheet-generator.php +3 -49
- includes/frontend/class-process.php +39 -119
- readme.md +3 -2
- readme.txt +16 -3
@@ -134,6 +134,9 @@
|
|
134 |
.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action {
|
135 |
font-size: 0.9em;
|
136 |
}
|
|
|
|
|
|
|
137 |
.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family {
|
138 |
padding: 0 10px 0;
|
139 |
font-weight: 600;
|
134 |
.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action {
|
135 |
font-size: 0.9em;
|
136 |
}
|
137 |
+
.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action:hover {
|
138 |
+
cursor: pointer;
|
139 |
+
}
|
140 |
.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family {
|
141 |
padding: 0 10px 0;
|
142 |
font-weight: 600;
|
@@ -1 +1 @@
|
|
1 |
-
{"version":3,"sources":["omgf-admin.less"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkBA,KACE;EACE,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAVF,eAUG;EACC,eAAA;EACA,mBAAA;EACA,WAAA;EACA,qBAAA;;;;;AAQN;EACE,oBAAA;;AADF,SAGE;EACE,eAAA;;AAJJ,SAOE,kBAAiB;EACf,oBAAA;EACA,mBAAA;;AAIJ,KAAM;EACJ,iBAAA;;AADF,KAAM,KAGJ;EACE,iBAAA;;AAJJ,KAAM,KAQJ,mBACE;EACE,eAAA;EACA,cAAA;;AAXN,KAAM,KAQJ,mBAME;EACE,eAAA;EACA,gBAAA;EACA,cAAA;EACA,eAAA;;AAlBN,KAAM,KAQJ,mBAME,GAME;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;;AAEA,KAzBF,KAQJ,mBAME,GAME,GAKG;EACC,aAAa,WAAb;EACA,eAAA;EACA,oBAAA;;AAGF,KA/BF,KAQJ,mBAME,GAME,GAWG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KApCF,KAQJ,mBAME,GAME,GAgBG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KAzCF,KAQJ,mBAME,GAME,GAqBG,UAAU;EACT,SAAS,OAAT;EACA,cAAA;;AAGF,KA9CF,KAQJ,mBAME,GAME,GA0BG,mBAAmB;EAClB,SAAS,OAAT;EACA,cAAA;;AAGF,KAnDF,KAQJ,mBAME,GAME,GA+BG,SAAS;EACR,SAAS,OAAT;EACA,cAAA;;AAOV;EACE,kBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,iBAAA;EACA,kBAAA;;AANF,8BAQE;EACE,kBAAA;EACA,YAAA;EACA,MAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAdJ,8BAiBE;EACE,gBAAA;EACA,aAAA;;AAnBJ,8BAsBE;EACE,gBAAA;;AAvBJ,8BAsBE,4BAGE;EACE,WAAA;EACA,yBAAA;;AA3BN,8BAsBE,4BAGE,MAIE,MACE;EACE,UAAA;;AA/BV,8BAsBE,4BAGE,MAUE;EACE,yBAAA;;AApCR,8BAsBE,4BAGE,MAUE,MAGE;EACE,qBAAA;EACA,UAAA;;AAxCV,8BAsBE,4BAGE,MAUE,MAQE;EACE,mBAAA;EACA,UAAA;;AA7CV,8BAsBE,4BAGE,MAUE,MAQE,GAIE;EACE,gBAAA;;
|
1 |
+
{"version":3,"sources":["omgf-admin.less"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkBA,KACE;EACE,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,mBAAA;EACA,4BAAA;;AAEA,KAVF,eAUG;EACC,eAAA;EACA,mBAAA;EACA,WAAA;EACA,qBAAA;;;;;AAQN;EACE,oBAAA;;AADF,SAGE;EACE,eAAA;;AAJJ,SAOE,kBAAiB;EACf,oBAAA;EACA,mBAAA;;AAIJ,KAAM;EACJ,iBAAA;;AADF,KAAM,KAGJ;EACE,iBAAA;;AAJJ,KAAM,KAQJ,mBACE;EACE,eAAA;EACA,cAAA;;AAXN,KAAM,KAQJ,mBAME;EACE,eAAA;EACA,gBAAA;EACA,cAAA;EACA,eAAA;;AAlBN,KAAM,KAQJ,mBAME,GAME;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;;AAEA,KAzBF,KAQJ,mBAME,GAME,GAKG;EACC,aAAa,WAAb;EACA,eAAA;EACA,oBAAA;;AAGF,KA/BF,KAQJ,mBAME,GAME,GAWG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KApCF,KAQJ,mBAME,GAME,GAgBG,MAAM;EACL,SAAS,OAAT;EACA,cAAA;;AAGF,KAzCF,KAQJ,mBAME,GAME,GAqBG,UAAU;EACT,SAAS,OAAT;EACA,cAAA;;AAGF,KA9CF,KAQJ,mBAME,GAME,GA0BG,mBAAmB;EAClB,SAAS,OAAT;EACA,cAAA;;AAGF,KAnDF,KAQJ,mBAME,GAME,GA+BG,SAAS;EACR,SAAS,OAAT;EACA,cAAA;;AAOV;EACE,kBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,iBAAA;EACA,kBAAA;;AANF,8BAQE;EACE,kBAAA;EACA,YAAA;EACA,MAAA;EACA,gBAAA;EACA,eAAA;EACA,cAAA;;AAdJ,8BAiBE;EACE,gBAAA;EACA,aAAA;;AAnBJ,8BAsBE;EACE,gBAAA;;AAvBJ,8BAsBE,4BAGE;EACE,WAAA;EACA,yBAAA;;AA3BN,8BAsBE,4BAGE,MAIE,MACE;EACE,UAAA;;AA/BV,8BAsBE,4BAGE,MAUE;EACE,yBAAA;;AApCR,8BAsBE,4BAGE,MAUE,MAGE;EACE,qBAAA;EACA,UAAA;;AAxCV,8BAsBE,4BAGE,MAUE,MAQE;EACE,mBAAA;EACA,UAAA;;AA7CV,8BAsBE,4BAGE,MAUE,MAQE,GAIE;EACE,gBAAA;;AAEA,8BA5BV,4BAGE,MAUE,MAQE,GAIE,oBAGG;EACC,eAAA;;AAnDd,8BAsBE,4BAGE,MAUE,MAQE,GAYE;EACE,iBAAA;EACA,gBAAA;;AAKF,8BAxCR,4BAGE,MAUE,MA0BE,GACG,WACC;EACE,oBAAA;;AAhEd,8BAwEE,iCACE;EACE,kBAAA;;AA1EN,8BAwEE,iCAKE;AA7EJ,8BAwEE,iCAME;EACE,gBAAA;EACA,UAAA;EACA,qBAAA;EACA,mBAAA;;AAlFN,8BAwEE,iCAKE,0BAOE,KAAI;AApFV,8BAwEE,iCAME,0BAME,KAAI;EACF,oBAAA;;AArFR,8BAwEE,iCAiBE;EACE,eAAA;EACA,iBAAA;;AA3FN,8BA+FE;EACE,mBAAA;;AAhGJ,8BAmGE;AAnGF,8BAoGE;EACE,mBAAA;;AAIJ;EACE,kBAAA;EACA,eAAA;EACA,iBAAA;EACA,YAAA;;AAJF,QAME;EACE,kBAAA;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,cAAA;EACA,qCAAA;EACA,gDAAgD,oDAAoD,4BAApG;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;;AApBJ,QAME,cAgBE;EACE,YAAA;;AAvBN,QAME,cAoBE;EACE,gBAAA;;AAIJ,QAAC,MAAO;EACN,mBAAA;;AAIJ,eACE;EACE,mBAAA;;AAFJ,eACE,SAGE;EACE,aAAA;EACA,mBAAA;EACA,8BAAA;;AAPN,eACE,SAGE,kBAKE,QACE,GACE;EACE,mBAAA;;AAEA,eAbV,SAGE,kBAKE,QACE,GACE,GAGG;EACC,mBAAA;;AAfd,eACE,SAGE,kBAKE,QACE,GACE,GAOE;EACE,qBAAA;EACA,iBAAA;;AAGE,eAtBd,SAGE,kBAKE,QACE,GACE,GAOE,EAIE,EACG;EACC,iBAAA;EACA,cAAA;;AAOV,eA/BN,SAGE,kBAKE,QAuBG;EACC,kBAAA;;AADF,eA/BN,SAGE,kBAKE,QAuBG,KAGC;EACE,kBAAA;;AAJJ,eA/BN,SAGE,kBAKE,QAuBG,KAGC,WAGE;EACE,cAAA;;AASd,wBAA0C;EACxC;IACE,cAAA;;EADF,8BAGE;IACE,kBAAA;IACA,aAAA;IACA,YAAA;;;;;;AAQN;EACE,eAAA;EACA,0CAAA;EACA,WAAA;EACA,YAAA;EACA,MAAA;EACA,kBAAA;;AANF,aAQE;EACE,QAAA;EACA,SAAA;EACA,kBAAA;EACA,eAAe,gBAAf;EACA,WAAW,gBAAX;;;;;AAOJ,gBACE;EACE,uBAAA;;AAIA,gBADF,WACG;EACC,sBAAA;;AAGF,gBALF,WAKG,WAAW;EACV,cAAA;;AAXN,gBAeE;EACE,WAAA"}
|
@@ -161,6 +161,10 @@
|
|
161 |
|
162 |
.unload-mass-action {
|
163 |
font-size: .9em;
|
|
|
|
|
|
|
|
|
164 |
}
|
165 |
|
166 |
.family {
|
161 |
|
162 |
.unload-mass-action {
|
163 |
font-size: .9em;
|
164 |
+
|
165 |
+
&:hover {
|
166 |
+
cursor: pointer;
|
167 |
+
}
|
168 |
}
|
169 |
|
170 |
.family {
|
Binary file
|
Binary file
|
@@ -226,14 +226,12 @@ jQuery(document).ready(function ($) {
|
|
226 |
/**
|
227 |
* Unload all fonts for current font family.
|
228 |
*/
|
229 |
-
unload_all: function (e) {
|
230 |
-
|
|
|
231 |
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
unloads.each(function (index, item) {
|
236 |
-
if (item.dataset.fontId == id && item.checked == false) {
|
237 |
item.click();
|
238 |
}
|
239 |
});
|
@@ -242,14 +240,12 @@ jQuery(document).ready(function ($) {
|
|
242 |
/**
|
243 |
* Uncheck all unload checkboxes for the current font family.
|
244 |
*/
|
245 |
-
load_all: function (
|
246 |
-
|
|
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
unloads.each(function (index, item) {
|
252 |
-
if (item.dataset.fontId == id && item.checked == true) {
|
253 |
item.click();
|
254 |
}
|
255 |
});
|
@@ -320,6 +316,7 @@ jQuery(document).ready(function ($) {
|
|
320 |
|
321 |
omgf_show_loader = omgf_admin.show_loader;
|
322 |
omgf_unload_all = omgf_admin.unload_all;
|
|
|
323 |
|
324 |
omgf_admin.init();
|
325 |
});
|
226 |
/**
|
227 |
* Unload all fonts for current font family.
|
228 |
*/
|
229 |
+
unload_all: function (e, self = this) {
|
230 |
+
var id = $(self).parents('.font-family').data('id'),
|
231 |
+
unloads = $('input.unload[data-font-id="' + id + '"]');
|
232 |
|
233 |
+
unloads.each(function (i, item) {
|
234 |
+
if (item.checked == false) {
|
|
|
|
|
|
|
235 |
item.click();
|
236 |
}
|
237 |
});
|
240 |
/**
|
241 |
* Uncheck all unload checkboxes for the current font family.
|
242 |
*/
|
243 |
+
load_all: function () {
|
244 |
+
var id = $(this).parents('.font-family').data('id'),
|
245 |
+
unloads = $('input.unload[data-font-id="' + id + '"]');
|
246 |
|
247 |
+
unloads.each(function (i, item) {
|
248 |
+
if (item.checked == true) {
|
|
|
|
|
|
|
249 |
item.click();
|
250 |
}
|
251 |
});
|
316 |
|
317 |
omgf_show_loader = omgf_admin.show_loader;
|
318 |
omgf_unload_all = omgf_admin.unload_all;
|
319 |
+
omgf_load_all = omgf_admin.load_all;
|
320 |
|
321 |
omgf_admin.init();
|
322 |
});
|
@@ -4,8 +4,8 @@
|
|
4 |
* Plugin Name: OMGF
|
5 |
* Plugin URI: https://daan.dev/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.
|
8 |
-
* Author: Daan from
|
9 |
* Author URI: https://daan.dev
|
10 |
* License: GPL2v2 or later
|
11 |
* Text Domain: host-webfonts-local
|
4 |
* Plugin Name: OMGF
|
5 |
* Plugin URI: https://daan.dev/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.3.0
|
8 |
+
* Author: Daan from Daan.dev
|
9 |
* Author URI: https://daan.dev
|
10 |
* License: GPL2v2 or later
|
11 |
* Text Domain: host-webfonts-local
|
@@ -74,7 +74,7 @@ class OMGF_Admin_Optimize
|
|
74 |
*/
|
75 |
public function verify_ssl($args)
|
76 |
{
|
77 |
-
$args['sslverify'] = strpos(
|
78 |
|
79 |
return $args;
|
80 |
}
|
74 |
*/
|
75 |
public function verify_ssl($args)
|
76 |
{
|
77 |
+
$args['sslverify'] = strpos(get_home_url(), 'https:') !== false;
|
78 |
|
79 |
return $args;
|
80 |
}
|
@@ -46,14 +46,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
|
|
46 |
'fallback' => 'Fallback',
|
47 |
'optional' => 'Optional'
|
48 |
];
|
49 |
-
const
|
50 |
-
'woff2' => 'Web Open Font Format 2.0 (WOFF2)',
|
51 |
-
'woff' => 'Web Open Font Format (WOFF)',
|
52 |
-
'eot' => 'Embedded OpenType (EOT)',
|
53 |
-
'ttf' => 'TrueType Font (TTF)',
|
54 |
-
'svg' => 'Scalable Vector Graphics (SVG)'
|
55 |
-
];
|
56 |
-
const OMGF_FORCE_SUBSETS_OPTIONS = [
|
57 |
'arabic' => 'Arabic',
|
58 |
'bengali' => 'Bengali',
|
59 |
'chinese-hongkong' => 'Chinese (Hong Kong)',
|
@@ -121,6 +114,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
|
|
121 |
* Optimize Fonts
|
122 |
*/
|
123 |
const OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION = 'omgf_display_option';
|
|
|
124 |
const OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS = 'omgf_optimized_fonts';
|
125 |
const OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS = 'omgf_preload_fonts';
|
126 |
const OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS = 'omgf_unload_fonts';
|
@@ -429,7 +423,7 @@ class OMGF_Admin_Settings extends OMGF_Admin
|
|
429 |
*/
|
430 |
public function footer_text_left()
|
431 |
{
|
432 |
-
$text = sprintf(__('Coded with %s in The Netherlands @ <strong>
|
433 |
|
434 |
return '<span id="footer-thankyou">' . $text . '</span>';
|
435 |
}
|
46 |
'fallback' => 'Fallback',
|
47 |
'optional' => 'Optional'
|
48 |
];
|
49 |
+
const OMGF_SUBSETS = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
'arabic' => 'Arabic',
|
51 |
'bengali' => 'Bengali',
|
52 |
'chinese-hongkong' => 'Chinese (Hong Kong)',
|
114 |
* Optimize Fonts
|
115 |
*/
|
116 |
const OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION = 'omgf_display_option';
|
117 |
+
const OMGF_OPTIMIZE_SETTING_SUBSETS = 'omgf_subsets';
|
118 |
const OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS = 'omgf_optimized_fonts';
|
119 |
const OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS = 'omgf_preload_fonts';
|
120 |
const OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS = 'omgf_unload_fonts';
|
423 |
*/
|
424 |
public function footer_text_left()
|
425 |
{
|
426 |
+
$text = sprintf(__('Coded with %s in The Netherlands @ <strong>Daan.dev</strong>.', $this->plugin_text_domain), '❤️');
|
427 |
|
428 |
return '<span id="footer-thankyou">' . $text . '</span>';
|
429 |
}
|
@@ -85,7 +85,7 @@ class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
|
|
85 |
__("Modify the <code>src</code> attribute for font files and stylesheets generated by OMGF Pro. This can be anything; from an absolute URL pointing to your CDN (e.g. <code>%s</code>) to an alternate relative URL (e.g. <code>/renamed-wp-content-dir/alternate/path/to/font-files</code>) to work with <em>security thru obscurity</em> plugins. Enter the full path to OMGF's files. Default: (empty)", $this->plugin_text_domain),
|
86 |
'https://your-cdn.com/wp-content/uploads/omgf'
|
87 |
) . ' ' . $this->promo,
|
88 |
-
|
89 |
);
|
90 |
}
|
91 |
|
85 |
__("Modify the <code>src</code> attribute for font files and stylesheets generated by OMGF Pro. This can be anything; from an absolute URL pointing to your CDN (e.g. <code>%s</code>) to an alternate relative URL (e.g. <code>/renamed-wp-content-dir/alternate/path/to/font-files</code>) to work with <em>security thru obscurity</em> plugins. Enter the full path to OMGF's files. Default: (empty)", $this->plugin_text_domain),
|
86 |
'https://your-cdn.com/wp-content/uploads/omgf'
|
87 |
) . ' ' . $this->promo,
|
88 |
+
!defined('OMGF_PRO_SOURCE_URL')
|
89 |
);
|
90 |
}
|
91 |
|
@@ -127,7 +127,7 @@ class OMGF_Admin_Settings_Builder
|
|
127 |
<?= apply_filters($name . '_setting_label', $label); ?>
|
128 |
</th>
|
129 |
<td>
|
130 |
-
<select name="<?= $name; ?><?= $is_multiselect ? '[]' : ''; ?>" class="<?= str_replace('_', '-', $name); ?>" <?= $is_multiselect ? 'size="
|
131 |
<?php
|
132 |
$options = apply_filters($name . '_setting_options', $options);
|
133 |
?>
|
127 |
<?= apply_filters($name . '_setting_label', $label); ?>
|
128 |
</th>
|
129 |
<td>
|
130 |
+
<select name="<?= $name; ?><?= $is_multiselect ? '[]' : ''; ?>" class="<?= str_replace('_', '-', $name); ?>" <?= $is_multiselect ? 'size="6" multiple="multiple"' : ''; ?> <?= apply_filters($name . '_setting_disabled', $disabled) ? 'disabled' : ''; ?>>
|
131 |
<?php
|
132 |
$options = apply_filters($name . '_setting_options', $options);
|
133 |
?>
|
@@ -31,7 +31,7 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
|
|
31 |
|
32 |
// Settings
|
33 |
add_filter('omgf_detection_settings_content', [$this, 'google_fonts_processing'], 30);
|
34 |
-
add_filter('omgf_detection_settings_content', [$this, '
|
35 |
|
36 |
// Close
|
37 |
add_filter('omgf_detection_settings_content', [$this, 'do_after'], 100);
|
@@ -69,7 +69,7 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
|
|
69 |
/**
|
70 |
*
|
71 |
*/
|
72 |
-
public function
|
73 |
{
|
74 |
?>
|
75 |
<tr>
|
@@ -79,7 +79,7 @@ class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
|
|
79 |
<?php foreach ($this->advanced_processing_pro_options() as $name => $data) : ?>
|
80 |
<?php
|
81 |
$checked = defined(strtoupper($name)) ? constant(strtoupper($name)) : false;
|
82 |
-
$disabled =
|
83 |
?>
|
84 |
<label for="<?= $name; ?>">
|
85 |
<input type="checkbox" name="<?= $name; ?>" id="<?= $name; ?>" <?= $checked ? 'checked="checked"' : ''; ?> <?= $disabled; ?> /><?= $data['label']; ?>
|
31 |
|
32 |
// Settings
|
33 |
add_filter('omgf_detection_settings_content', [$this, 'google_fonts_processing'], 30);
|
34 |
+
add_filter('omgf_detection_settings_content', [$this, 'promo_advanced_processing'], 60);
|
35 |
|
36 |
// Close
|
37 |
add_filter('omgf_detection_settings_content', [$this, 'do_after'], 100);
|
69 |
/**
|
70 |
*
|
71 |
*/
|
72 |
+
public function promo_advanced_processing()
|
73 |
{
|
74 |
?>
|
75 |
<tr>
|
79 |
<?php foreach ($this->advanced_processing_pro_options() as $name => $data) : ?>
|
80 |
<?php
|
81 |
$checked = defined(strtoupper($name)) ? constant(strtoupper($name)) : false;
|
82 |
+
$disabled = !defined(strtoupper($name)) ? 'disabled' : '';
|
83 |
?>
|
84 |
<label for="<?= $name; ?>">
|
85 |
<input type="checkbox" name="<?= $name; ?>" id="<?= $name; ?>" <?= $checked ? 'checked="checked"' : ''; ?> <?= $disabled; ?> /><?= $data['label']; ?>
|
@@ -65,9 +65,9 @@ class OMGF_Admin_Settings_Help extends OMGF_Admin_Settings_Builder
|
|
65 |
</ul>
|
66 |
</div>
|
67 |
<div class="column last">
|
68 |
-
<h3 class="signature"><?= sprintf(__('Coded with %s by', $this->plugin_text_domain), '
|
69 |
<p class="signature">
|
70 |
-
<a target="_blank" title="<?= __('Visit
|
71 |
</p>
|
72 |
</div>
|
73 |
</div>
|
65 |
</ul>
|
66 |
</div>
|
67 |
<div class="column last">
|
68 |
+
<h3 class="signature"><?= sprintf(__('Coded with %s by', $this->plugin_text_domain), '❤️'); ?> </h3>
|
69 |
<p class="signature">
|
70 |
+
<a target="_blank" title="<?= __('Visit Daan.dev', $this->plugin_text_domain); ?>" href="https://daan.dev/wordpress-plugins/"><img class="signature-image" alt="<?= __('Visit Daan.dev', $this->plugin_text_domain); ?>" src="<?= plugin_dir_url(OMGF_PLUGIN_FILE) . 'assets/images/logo.png'; ?>" /></a>
|
71 |
</p>
|
72 |
</div>
|
73 |
</div>
|
@@ -42,10 +42,10 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
42 |
add_filter('omgf_optimize_settings_content', [$this, 'close_task_manager'], 27);
|
43 |
|
44 |
add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 30);
|
45 |
-
add_filter('omgf_optimize_settings_content', [$this, 'do_display_option'],
|
46 |
-
add_filter('omgf_optimize_settings_content', [$this, '
|
47 |
-
add_filter('omgf_optimize_settings_content', [$this, '
|
48 |
-
add_filter('omgf_optimize_settings_content', [$this, '
|
49 |
add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 100);
|
50 |
|
51 |
add_filter('omgf_optimize_settings_content', [$this, 'do_optimize_fonts_container'], 200);
|
@@ -178,47 +178,46 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
178 |
/**
|
179 |
* Force Font-Display Option Site Wide
|
180 |
*/
|
181 |
-
public function
|
182 |
{
|
183 |
$this->do_checkbox(
|
184 |
-
__('
|
185 |
'omgf_pro_force_font_display',
|
186 |
defined('OMGF_PRO_FORCE_FONT_DISPLAY') ? OMGF_PRO_FORCE_FONT_DISPLAY : false,
|
187 |
-
__('
|
188 |
-
|
189 |
);
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
-
*
|
194 |
*
|
195 |
* @return void
|
196 |
*/
|
197 |
-
public function
|
198 |
{
|
199 |
-
$this->
|
200 |
-
__('
|
201 |
-
'
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
true,
|
206 |
-
true
|
207 |
);
|
208 |
}
|
209 |
|
210 |
/**
|
211 |
-
*
|
|
|
|
|
212 |
*/
|
213 |
-
public function
|
214 |
{
|
215 |
$this->do_select(
|
216 |
-
__('
|
217 |
-
|
218 |
-
OMGF_Admin_Settings::
|
219 |
-
|
220 |
-
__('
|
221 |
-
true,
|
222 |
true
|
223 |
);
|
224 |
}
|
@@ -292,15 +291,12 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
292 |
</tr>
|
293 |
<?php foreach ($fonts as $font) : ?>
|
294 |
<?php if (!is_object($font) || count((array) $font->variants) <= 0) continue; ?>
|
295 |
-
<?php
|
296 |
-
$aka = in_array($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS) ? array_search($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS) : '';
|
297 |
-
?>
|
298 |
<tr class="font-family" data-id="<?= $handle . '-' . $font->id; ?>">
|
299 |
<td colspan="5">
|
300 |
-
<span class="family"><em><?= rawurldecode($font->family);
|
301 |
</td>
|
302 |
<td class="fallback-font-stack">
|
303 |
-
<select data-handle="<?= $handle; ?>" <?=
|
304 |
<option value=''><?= __('None (default)', $this->plugin_text_domain); ?></option>
|
305 |
<?php foreach (OMGF_Admin_Settings::OMGF_FALLBACK_FONT_STACKS_OPTIONS as $value => $label) : ?>
|
306 |
<option <?= defined('OMGF_PRO_FALLBACK_FONT_STACK') && isset(OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id]) && OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id] == $value ? 'selected' : ''; ?> value="<?= $value; ?>"><?= $label; ?></option>
|
@@ -312,7 +308,7 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
312 |
$replace = defined('OMGF_PRO_REPLACE_FONT') && isset(OMGF_PRO_REPLACE_FONT[$handle][$font->id]) && OMGF_PRO_REPLACE_FONT[$handle][$font->id] == 'on' ? 'checked' : '';
|
313 |
$fallback = defined('OMGF_PRO_FALLBACK_FONT_STACK') && isset(OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id]) && OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id] !== '';
|
314 |
?>
|
315 |
-
<input autocomplete="off" type="checkbox" class="replace" <?= $replace; ?> <?= $fallback ? '' : 'disabled'; ?> <?=
|
316 |
</td>
|
317 |
</tr>
|
318 |
<?php $id = ''; ?>
|
@@ -325,6 +321,9 @@ class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
|
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 |
?>
|
42 |
add_filter('omgf_optimize_settings_content', [$this, 'close_task_manager'], 27);
|
43 |
|
44 |
add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 30);
|
45 |
+
add_filter('omgf_optimize_settings_content', [$this, 'do_display_option'], 40);
|
46 |
+
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_apply_font_display_globally'], 50);
|
47 |
+
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_remove_async_google_fonts'], 60);
|
48 |
+
add_filter('omgf_optimize_settings_content', [$this, 'do_use_subsets'], 70);
|
49 |
add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 100);
|
50 |
|
51 |
add_filter('omgf_optimize_settings_content', [$this, 'do_optimize_fonts_container'], 200);
|
178 |
/**
|
179 |
* Force Font-Display Option Site Wide
|
180 |
*/
|
181 |
+
public function do_promo_apply_font_display_globally()
|
182 |
{
|
183 |
$this->do_checkbox(
|
184 |
+
__('Apply Font-Display Option Globally (Pro)', $this->plugin_text_domain),
|
185 |
'omgf_pro_force_font_display',
|
186 |
defined('OMGF_PRO_FORCE_FONT_DISPLAY') ? OMGF_PRO_FORCE_FONT_DISPLAY : false,
|
187 |
+
__('Apply the above <code>font-display</code> attribute value to all <code>@font-face</code> statements found on your site to <strong>ensure text remains visible during webfont load</strong>.', $this->plugin_text_domain),
|
188 |
+
!defined('OMGF_PRO_FORCE_FONT_DISPLAY')
|
189 |
);
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
+
* Block Async Google Fonts option
|
194 |
*
|
195 |
* @return void
|
196 |
*/
|
197 |
+
public function do_promo_remove_async_google_fonts()
|
198 |
{
|
199 |
+
$this->do_checkbox(
|
200 |
+
__('Remove Async Google Fonts (Pro)', $this->plugin_text_domain),
|
201 |
+
'omgf_pro_remove_async_fonts',
|
202 |
+
defined('OMGF_PRO_REMOVE_ASYNC_FONTS') ? OMGF_PRO_REMOVE_ASYNC_FONTS : false,
|
203 |
+
sprintf(__('Remove Google Fonts loaded (asynchronously) by (3rd party) JavaScript libraries used by some themes/plugins. This won\'t work with embedded content (i.e. <code>iframe</code>). <strong>Warning!</strong> Make sure you load the Google Fonts, <a href="%s">either manually</a> or by using a plugin (like <a href="%s" target="_blank">Additional Fonts</a>) to prevent styling breaks.', $this->plugin_text_domain), 'https://daan.dev/docs/omgf-pro/remove-async-google-fonts/', 'https://daan.dev/wordpress/omgf-additional-fonts/'),
|
204 |
+
!defined('OMGF_PRO_REMOVE_ASYNC_FONTS')
|
|
|
|
|
205 |
);
|
206 |
}
|
207 |
|
208 |
/**
|
209 |
+
* Preload Subsets
|
210 |
+
*
|
211 |
+
* @return void
|
212 |
*/
|
213 |
+
public function do_use_subsets()
|
214 |
{
|
215 |
$this->do_select(
|
216 |
+
__('Used Subset(s)', $this->plugin_text_domain),
|
217 |
+
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_SUBSETS,
|
218 |
+
OMGF_Admin_Settings::OMGF_SUBSETS,
|
219 |
+
OMGF_SUBSETS,
|
220 |
+
__('Select which subset(s) sgould be used when generating stylesheets and preloads. Default: <code>latin</code>, <code>latin-ext</code>. Limit the selection to subsets your site actually uses. Selecting <u>too many</u> subsets can negatively impact performance! <em>Use CTRL + click to select multiple values.</em>', $this->plugin_text_domain),
|
|
|
221 |
true
|
222 |
);
|
223 |
}
|
291 |
</tr>
|
292 |
<?php foreach ($fonts as $font) : ?>
|
293 |
<?php if (!is_object($font) || count((array) $font->variants) <= 0) continue; ?>
|
|
|
|
|
|
|
294 |
<tr class="font-family" data-id="<?= $handle . '-' . $font->id; ?>">
|
295 |
<td colspan="5">
|
296 |
+
<span class="family"><em><?= rawurldecode($font->family); ?></em></span> <span class="unload-mass-action">(<a class="unload-italics"><?= __('Unload italics', $this->plugin_text_domain); ?></a> <span class="dashicons dashicons-info tooltip"><span class="tooltip-text"><?= __('In most situations you can safely unload all Italic font styles. Modern browsers are capable of mimicking Italic font styles.', $this->plugin_text_domain); ?></span></span> | <a class="unload-all"><?= __('Unload all', $this->plugin_text_domain); ?></a> | <a class="load-all"><?= __('Load all', $this->plugin_text_domain); ?></a>)</span>
|
297 |
</td>
|
298 |
<td class="fallback-font-stack">
|
299 |
+
<select data-handle="<?= $handle; ?>" <?= !defined('OMGF_PRO_FALLBACK_FONT_STACK') ? 'disabled' : ''; ?> name="omgf_pro_fallback_font_stack[<?= $handle; ?>][<?= $font->id; ?>]">
|
300 |
<option value=''><?= __('None (default)', $this->plugin_text_domain); ?></option>
|
301 |
<?php foreach (OMGF_Admin_Settings::OMGF_FALLBACK_FONT_STACKS_OPTIONS as $value => $label) : ?>
|
302 |
<option <?= defined('OMGF_PRO_FALLBACK_FONT_STACK') && isset(OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id]) && OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id] == $value ? 'selected' : ''; ?> value="<?= $value; ?>"><?= $label; ?></option>
|
308 |
$replace = defined('OMGF_PRO_REPLACE_FONT') && isset(OMGF_PRO_REPLACE_FONT[$handle][$font->id]) && OMGF_PRO_REPLACE_FONT[$handle][$font->id] == 'on' ? 'checked' : '';
|
309 |
$fallback = defined('OMGF_PRO_FALLBACK_FONT_STACK') && isset(OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id]) && OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id] !== '';
|
310 |
?>
|
311 |
+
<input autocomplete="off" type="checkbox" class="replace" <?= $replace; ?> <?= $fallback ? '' : 'disabled'; ?> <?= !defined('OMGF_PRO_REPLACE_FONT') ? 'disabled' : ''; ?> name="omgf_pro_replace_font[<?= $handle; ?>][<?= $font->id; ?>]" />
|
312 |
</td>
|
313 |
</tr>
|
314 |
<?php $id = ''; ?>
|
321 |
* This deals with the duplicate display of font styles. Which also
|
322 |
* means unloading and/or preloading will unload/preload all available
|
323 |
* subsets. It's a bit bloaty, but there's no alternative.
|
324 |
+
*
|
325 |
+
* To better deal with this, I've introduced the Used Subset(s) feature
|
326 |
+
* in this version.
|
327 |
*/
|
328 |
if ($id == $variant->fontWeight . $variant->fontStyle) continue;
|
329 |
?>
|
@@ -56,6 +56,7 @@ class OMGF
|
|
56 |
define('OMGF_CACHE_IS_STALE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CACHE_IS_STALE)));
|
57 |
define('OMGF_CURRENT_DB_VERSION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION)));
|
58 |
define('OMGF_DISPLAY_OPTION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION, 'swap')) ?: 'swap');
|
|
|
59 |
define('OMGF_UNLOAD_STYLESHEETS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, '')));
|
60 |
define('OMGF_CACHE_KEYS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, '')));
|
61 |
define('OMGF_TEST_MODE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_TEST_MODE)));
|
@@ -65,6 +66,22 @@ class OMGF
|
|
65 |
define('OMGF_UPLOAD_URL', apply_filters('omgf_upload_url', WP_CONTENT_URL . '/uploads/omgf'));
|
66 |
}
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
/**
|
69 |
* Needs to run before admin_menu and admin_init.
|
70 |
*
|
@@ -141,7 +158,7 @@ class OMGF
|
|
141 |
/**
|
142 |
* If the user entered https:// in the Home URL option, it's safe to assume that SSL is used.
|
143 |
*/
|
144 |
-
if (!is_ssl() && strpos(
|
145 |
$url = str_replace('http://', 'https://', $url);
|
146 |
}
|
147 |
|
@@ -191,7 +208,7 @@ class OMGF
|
|
191 |
*
|
192 |
* @return array
|
193 |
*/
|
194 |
-
public static function optimized_fonts($maybe_add = [])
|
195 |
{
|
196 |
/** @var array $optimized_fonts Cache layer */
|
197 |
static $optimized_fonts;
|
@@ -217,7 +234,7 @@ class OMGF
|
|
217 |
*
|
218 |
* @since v4.5.7
|
219 |
*/
|
220 |
-
if (!empty($maybe_add) && !isset($optimized_fonts[key($maybe_add)])) {
|
221 |
$optimized_fonts = array_merge($optimized_fonts, $maybe_add);
|
222 |
}
|
223 |
|
@@ -323,9 +340,9 @@ class OMGF
|
|
323 |
*
|
324 |
* @return string
|
325 |
*/
|
326 |
-
public static function generate_stylesheet($fonts, $
|
327 |
{
|
328 |
-
$generator = new OMGF_StylesheetGenerator($fonts, $
|
329 |
|
330 |
return $generator->generate();
|
331 |
}
|
56 |
define('OMGF_CACHE_IS_STALE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CACHE_IS_STALE)));
|
57 |
define('OMGF_CURRENT_DB_VERSION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION)));
|
58 |
define('OMGF_DISPLAY_OPTION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION, 'swap')) ?: 'swap');
|
59 |
+
define('OMGF_SUBSETS', $this->esc_array(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_SUBSETS, ['latin', 'latin-ext'])) ?: ['latin', 'latin-ext']);
|
60 |
define('OMGF_UNLOAD_STYLESHEETS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, '')));
|
61 |
define('OMGF_CACHE_KEYS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, '')));
|
62 |
define('OMGF_TEST_MODE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_TEST_MODE)));
|
66 |
define('OMGF_UPLOAD_URL', apply_filters('omgf_upload_url', WP_CONTENT_URL . '/uploads/omgf'));
|
67 |
}
|
68 |
|
69 |
+
/**
|
70 |
+
* Escape each value of an option array.
|
71 |
+
*/
|
72 |
+
private function esc_array($array)
|
73 |
+
{
|
74 |
+
if (!is_array($array)) {
|
75 |
+
return [];
|
76 |
+
}
|
77 |
+
|
78 |
+
foreach ($array as &$element) {
|
79 |
+
$element = esc_attr($element);
|
80 |
+
}
|
81 |
+
|
82 |
+
return $array;
|
83 |
+
}
|
84 |
+
|
85 |
/**
|
86 |
* Needs to run before admin_menu and admin_init.
|
87 |
*
|
158 |
/**
|
159 |
* If the user entered https:// in the Home URL option, it's safe to assume that SSL is used.
|
160 |
*/
|
161 |
+
if (!is_ssl() && strpos(get_home_url(), 'https://') !== false) {
|
162 |
$url = str_replace('http://', 'https://', $url);
|
163 |
}
|
164 |
|
208 |
*
|
209 |
* @return array
|
210 |
*/
|
211 |
+
public static function optimized_fonts($maybe_add = [], $force_add = false)
|
212 |
{
|
213 |
/** @var array $optimized_fonts Cache layer */
|
214 |
static $optimized_fonts;
|
234 |
*
|
235 |
* @since v4.5.7
|
236 |
*/
|
237 |
+
if (!empty($maybe_add) && (!isset($optimized_fonts[key($maybe_add)]) || $force_add)) {
|
238 |
$optimized_fonts = array_merge($optimized_fonts, $maybe_add);
|
239 |
}
|
240 |
|
340 |
*
|
341 |
* @return string
|
342 |
*/
|
343 |
+
public static function generate_stylesheet($fonts, $plugin = 'OMGF')
|
344 |
{
|
345 |
+
$generator = new OMGF_StylesheetGenerator($fonts, $plugin);
|
346 |
|
347 |
return $generator->generate();
|
348 |
}
|
@@ -18,34 +18,12 @@ defined('ABSPATH') || exit;
|
|
18 |
|
19 |
class OMGF_Optimize
|
20 |
{
|
21 |
-
const
|
22 |
-
|
23 |
-
const OMGF_USE_FALLBACK_API_TRANSIENT = 'omgf_use_fallback_api';
|
24 |
-
|
25 |
-
/**
|
26 |
-
* If a font changed names recently, this array will map the old name (key) to the new name (value).
|
27 |
-
*
|
28 |
-
* The key of an element should be dashed (no spaces) if necessary, e.g. open-sans.
|
29 |
-
*/
|
30 |
-
const OMGF_RENAMED_GOOGLE_FONTS = [
|
31 |
-
'crimson-text' => 'crimson-pro',
|
32 |
-
'ek-mukta' => 'mukta',
|
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 $
|
48 |
-
private $
|
49 |
|
50 |
/** @var string */
|
51 |
private $handle = '';
|
@@ -53,56 +31,51 @@ class OMGF_Optimize
|
|
53 |
/** @var string $original_handle */
|
54 |
private $original_handle = '';
|
55 |
|
56 |
-
/** @var string $subset */
|
57 |
-
private $subset = '';
|
58 |
-
|
59 |
/** @var string $return */
|
60 |
private $return = 'url';
|
61 |
|
|
|
|
|
|
|
62 |
/** @var string */
|
63 |
private $path = '';
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
/** @var string */
|
66 |
private $plugin_text_domain = 'host-webfonts-local';
|
67 |
|
68 |
/**
|
69 |
-
* @param string $
|
70 |
* @param string $handle The cache handle, generated using $handle + 5 random chars. Used for storing the fonts and stylesheet.
|
71 |
* @param string $original_handle The stylesheet handle, present in the ID attribute.
|
72 |
-
* @param string $subset Contents of "subset" parameter. If left empty, the downloaded files will support all subsets.
|
73 |
* @param string $return Valid values: 'url' | 'path' | 'object'.
|
74 |
-
*
|
75 |
-
*
|
76 |
-
*
|
77 |
-
* @throws SodiumException
|
78 |
-
* @throws SodiumException
|
79 |
-
* @throws TypeError
|
80 |
-
* @throws TypeError
|
81 |
-
* @throws TypeError
|
82 |
*/
|
83 |
public function __construct(
|
84 |
-
string $
|
85 |
string $handle,
|
86 |
string $original_handle,
|
87 |
-
string $
|
88 |
-
|
89 |
) {
|
90 |
-
$this->
|
91 |
$this->handle = sanitize_title_with_dashes($handle);
|
92 |
$this->original_handle = sanitize_title_with_dashes($original_handle);
|
93 |
-
$this->subset = $subset;
|
94 |
$this->path = OMGF_UPLOAD_DIR . '/' . $this->handle;
|
95 |
$this->return = $return;
|
|
|
96 |
}
|
97 |
|
98 |
/**
|
99 |
* @return string|array
|
100 |
-
*
|
101 |
-
* @throws SodiumException
|
102 |
-
* @throws SodiumException
|
103 |
-
* @throws TypeError
|
104 |
-
* @throws TypeError
|
105 |
-
* @throws TypeError
|
106 |
*/
|
107 |
public function process()
|
108 |
{
|
@@ -112,79 +85,38 @@ class OMGF_Optimize
|
|
112 |
return '';
|
113 |
}
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
$query['subsets'] = $this->subset;
|
121 |
-
}
|
122 |
-
|
123 |
-
foreach ($font_families as $key => $font_family) {
|
124 |
-
/**
|
125 |
-
* Prevent duplicate entries by generating a unique identifier, all lowercase,
|
126 |
-
* with (multiple) spaces replaced by dashes.
|
127 |
-
*
|
128 |
-
* @since v5.1.4
|
129 |
-
*/
|
130 |
-
$font_name = explode(':', $font_family)[0];
|
131 |
-
$font_id = strtolower(preg_replace("/[\s\+]+/", '-', $font_name));
|
132 |
-
|
133 |
-
$font_families[$font_id] = $font_family;
|
134 |
-
unset($font_families[$key]);
|
135 |
}
|
136 |
|
137 |
-
|
138 |
-
if (empty($font_family)) {
|
139 |
-
continue;
|
140 |
-
}
|
141 |
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
}
|
145 |
}
|
146 |
|
147 |
-
|
148 |
-
$
|
|
|
149 |
|
150 |
if (empty($fonts)) {
|
151 |
return '';
|
152 |
}
|
153 |
|
154 |
foreach ($fonts as $id => &$font) {
|
155 |
-
$fonts_request = $font_families[$id];
|
156 |
-
|
157 |
-
/**
|
158 |
-
* If no colon is found, @var string $requested_variants will be an empty string.
|
159 |
-
*
|
160 |
-
* @since v5.1.4
|
161 |
-
*/
|
162 |
-
list(, $requested_variants) = array_pad(explode(':', $fonts_request), 2, '');
|
163 |
-
|
164 |
-
$requested_variants = $this->parse_requested_variants($requested_variants, $font);
|
165 |
-
|
166 |
-
if ($unloaded_fonts = OMGF::unloaded_fonts()) {
|
167 |
-
$font_id = $font->id;
|
168 |
-
|
169 |
-
// Now we're sure we got 'em all. We can safely dequeue those we don't want.
|
170 |
-
if (isset($unloaded_fonts[$this->original_handle][$font_id])) {
|
171 |
-
$requested_variants = $this->dequeue_unloaded_variants($requested_variants, $unloaded_fonts[$this->original_handle], $font->id);
|
172 |
-
}
|
173 |
-
}
|
174 |
-
|
175 |
-
$font->variants = $this->process_unload_queue($font->id, $font->variants, $requested_variants, $this->original_handle);
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Which file types should we download and include in the stylesheet?
|
180 |
-
*
|
181 |
-
* @since v4.5
|
182 |
-
*/
|
183 |
-
$file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
|
184 |
-
|
185 |
-
foreach ($fonts as &$font) {
|
186 |
-
$font_id = $font->id;
|
187 |
-
|
188 |
/**
|
189 |
* Sanitize font family, because it may contain spaces.
|
190 |
*
|
@@ -192,8 +124,15 @@ class OMGF_Optimize
|
|
192 |
*/
|
193 |
$font->family = rawurlencode($font->family);
|
194 |
|
195 |
-
foreach ($font->variants as &$variant) {
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
|
198 |
/**
|
199 |
* Encode font family, because it may contain spaces.
|
@@ -202,16 +141,22 @@ class OMGF_Optimize
|
|
202 |
*/
|
203 |
$variant->fontFamily = rawurlencode($variant->fontFamily);
|
204 |
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
}
|
210 |
}
|
211 |
}
|
212 |
|
213 |
-
$
|
214 |
-
$stylesheet = OMGF::generate_stylesheet($fonts, $this->original_handle);
|
215 |
|
216 |
if (!file_exists($this->path)) {
|
217 |
wp_mkdir_p($this->path);
|
@@ -219,21 +164,15 @@ class OMGF_Optimize
|
|
219 |
|
220 |
file_put_contents($local_file, $stylesheet);
|
221 |
|
222 |
-
$
|
|
|
223 |
|
224 |
/**
|
225 |
* $current_stylesheet is added to temporary cache layer, if it isn't present in database.
|
226 |
*
|
227 |
* @since v4.5.7
|
228 |
*/
|
229 |
-
$optimized_fonts = OMGF::optimized_fonts($current_stylesheet);
|
230 |
-
|
231 |
-
/**
|
232 |
-
* When unload is used, this takes care of rewriting the font style URLs in the database.
|
233 |
-
*
|
234 |
-
* @since v4.5.7
|
235 |
-
*/
|
236 |
-
$optimized_fonts = $this->rewrite_variants($optimized_fonts, $current_stylesheet);
|
237 |
|
238 |
update_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts);
|
239 |
|
@@ -250,196 +189,49 @@ class OMGF_Optimize
|
|
250 |
}
|
251 |
|
252 |
/**
|
253 |
-
* @
|
254 |
-
*
|
255 |
-
* @param $
|
256 |
-
*
|
257 |
-
* @return array
|
258 |
-
*/
|
259 |
-
private function dequeue_unloaded_variants($variants, $unloaded_fonts, $font_id)
|
260 |
-
{
|
261 |
-
return array_filter(
|
262 |
-
$variants,
|
263 |
-
function ($variant) use ($unloaded_fonts, $font_id) {
|
264 |
-
if ($variant == '400') {
|
265 |
-
// Sometimes the font is defined as 'regular', so we need to check both.
|
266 |
-
return !in_array('regular', $unloaded_fonts[$font_id]) && !in_array($variant, $unloaded_fonts[$font_id]);
|
267 |
-
}
|
268 |
-
|
269 |
-
if ($variant == '400italic') {
|
270 |
-
// Sometimes the font is defined as 'italic', so we need to check both.
|
271 |
-
return !in_array('italic', $unloaded_fonts[$font_id]) && !in_array($variant, $unloaded_fonts[$font_id]);
|
272 |
-
}
|
273 |
-
|
274 |
-
return !in_array($variant, $unloaded_fonts[$font_id]);
|
275 |
-
}
|
276 |
-
);
|
277 |
-
}
|
278 |
-
|
279 |
-
/**
|
280 |
-
* @param $id Unique identifier for this Font Family, lowercase, dashes instead of spaces.
|
281 |
-
* @param $query
|
282 |
-
* @param $name The full name of the requested Font Family, e.g. Roboto Condensed, Open Sans or Roboto.
|
283 |
*
|
284 |
-
* @return
|
285 |
*/
|
286 |
-
private function
|
287 |
{
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
* an alternate API.
|
292 |
-
*/
|
293 |
-
$alternate_fonts = apply_filters('omgf_alternate_fonts', []);
|
294 |
-
$alternate_url = '';
|
295 |
-
$query_string = '';
|
296 |
-
|
297 |
-
if (in_array($id, array_keys($alternate_fonts))) {
|
298 |
-
$alternate_url = apply_filters('omgf_alternate_api_url', '', $id);
|
299 |
-
unset($query);
|
300 |
-
}
|
301 |
-
|
302 |
-
if (!empty($query)) {
|
303 |
-
$query_string = '?' . http_build_query($query);
|
304 |
-
}
|
305 |
-
|
306 |
-
/**
|
307 |
-
* If a font changed names recently, map their old name to the new name, before triggering the API request.
|
308 |
-
*/
|
309 |
-
if (in_array($id, array_keys(self::OMGF_RENAMED_GOOGLE_FONTS))) {
|
310 |
-
$id = self::OMGF_RENAMED_GOOGLE_FONTS[$id];
|
311 |
-
}
|
312 |
-
|
313 |
-
if (!$alternate_url) {
|
314 |
-
$response = $this->remote_get($id, $query_string);
|
315 |
-
} else {
|
316 |
-
$response = wp_remote_get(
|
317 |
-
sprintf($alternate_url . '%s', $id) . $query_string
|
318 |
-
);
|
319 |
-
}
|
320 |
-
|
321 |
-
if (is_wp_error($response)) {
|
322 |
-
OMGF_Admin_Notice::set_notice(sprintf(__('OMGF encountered an error while trying to fetch fonts: %s', $this->plugin_text_domain), $response->get_error_message()), $response->get_error_code(), 'error', 408);
|
323 |
-
}
|
324 |
-
|
325 |
-
/**
|
326 |
-
* If no subset was set, do a quick refresh to make sure all available subsets are included.
|
327 |
-
*/
|
328 |
-
if (!$query_string && !$alternate_url) {
|
329 |
-
$response_body = wp_remote_retrieve_body($response);
|
330 |
-
$body = json_decode($response_body);
|
331 |
-
$query_string = '?subsets=' . (isset($body->subsets) ? implode(',', $body->subsets) : 'latin,latin-ext');
|
332 |
-
$response = $this->remote_get($id, $query_string);
|
333 |
-
}
|
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);
|
347 |
-
$message = sprintf(__('OMGF couldn\'t find <strong>%s</strong> while parsing %s. The API returned the following error: %s.', $this->plugin_text_domain), $name, isset($_GET['omgf_optimize']) ? 'your homepage' : $_SERVER['REQUEST_URI'], is_wp_error($response) ? $response->get_error_message() : $error_message);
|
348 |
-
|
349 |
-
OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', 'error');
|
350 |
-
|
351 |
-
if ($error_message == 'Service Unavailable') {
|
352 |
-
$message = __('OMGF\'s Google Fonts API is currently unavailable. Try again later.', $this->plugin_text_domain);
|
353 |
-
|
354 |
-
OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', 'error', $response_code);
|
355 |
-
}
|
356 |
-
|
357 |
-
if ($error_body == 'Not found') {
|
358 |
-
$message = sprintf(__('Please verify that %s is available for free at Google Fonts by doing <a href="%s" target="_blank">a manual search</a>. Maybe it\'s a Premium font?', $this->plugin_text_domain), $name, 'https://fonts.google.com/?query=' . str_replace('-', '+', $id));
|
359 |
-
|
360 |
-
OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_not_found', 'info');
|
361 |
-
}
|
362 |
-
|
363 |
-
if ($error_body == 'Internal Server Error') {
|
364 |
-
$message = sprintf(__('Try using the Force Subsets option (available in OMGF Pro) to force loading %s in a subset in which it\'s actually available. Use the Language filter <a href="%s" target="_blank">here</a> to verify which subsets are available for %s.', $this->plugin_text_domain), $name, 'https://fonts.google.com/?query=' . str_replace('-', '+', $id), $name);
|
365 |
-
|
366 |
-
OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_internal_server_error', 'info');
|
367 |
-
}
|
368 |
-
|
369 |
-
return [];
|
370 |
-
}
|
371 |
|
372 |
-
|
373 |
-
}
|
374 |
|
375 |
-
|
376 |
-
|
377 |
-
*
|
378 |
-
* @param string $family
|
379 |
-
* @param string $query
|
380 |
-
*
|
381 |
-
* @return array|WP_Error
|
382 |
-
*/
|
383 |
-
private function remote_get($family, $query)
|
384 |
-
{
|
385 |
-
$response = wp_remote_get(
|
386 |
-
sprintf(self::OMGF_GOOGLE_FONTS_API_URL . '%s', $family) . $query
|
387 |
-
);
|
388 |
-
|
389 |
-
// Try with mirror, if first request failed.
|
390 |
-
if (is_wp_error($response) && $response->get_error_code() == 'http_request_failed') {
|
391 |
-
$response = wp_remote_get(
|
392 |
-
sprintf(self::OMGF_GOOGLE_FONTS_API_FALLBACK . '%s', $family) . $query
|
393 |
-
);
|
394 |
}
|
395 |
|
396 |
-
|
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 |
-
|
414 |
-
|
415 |
-
break;
|
416 |
-
}
|
417 |
}
|
418 |
|
419 |
-
$
|
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 |
-
|
428 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
}
|
430 |
|
431 |
-
|
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
|
@@ -448,27 +240,49 @@ class OMGF_Optimize
|
|
448 |
*/
|
449 |
private function parse_variants($stylesheet, $font_family)
|
450 |
{
|
451 |
-
|
|
|
|
|
|
|
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 |
-
|
471 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
}
|
473 |
|
474 |
return $font_object;
|
@@ -490,101 +304,188 @@ class OMGF_Optimize
|
|
490 |
}
|
491 |
|
492 |
/**
|
493 |
-
*
|
494 |
-
*
|
495 |
-
*
|
496 |
-
* @return
|
497 |
*/
|
498 |
-
private function
|
499 |
{
|
500 |
-
|
501 |
-
|
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 |
-
|
516 |
-
|
517 |
-
|
518 |
-
foreach ($font->variants as $variant) {
|
519 |
-
$requested_variants[] = $variant->id;
|
520 |
-
}
|
521 |
}
|
522 |
|
523 |
-
return $
|
524 |
}
|
525 |
|
526 |
/**
|
|
|
|
|
|
|
527 |
*
|
528 |
-
* @
|
529 |
-
* @param array $all_variants An array of all available font family variants.
|
530 |
-
* @param array $wanted_variants An array of requested variants in this font family request.
|
531 |
-
* @param string $stylesheet_handle
|
532 |
-
* @return mixed
|
533 |
*/
|
534 |
-
private function
|
535 |
{
|
536 |
-
|
537 |
-
* If $variants is empty and this is the first run, i.e. there are no unloaded fonts (yet)
|
538 |
-
* return all available variants.
|
539 |
-
*/
|
540 |
-
if (empty($wanted_variants) && !isset(OMGF::unloaded_fonts()[$stylesheet_handle][$font_id])) {
|
541 |
-
return $all_variants;
|
542 |
-
}
|
543 |
|
544 |
-
|
545 |
-
$
|
546 |
-
|
547 |
-
|
548 |
|
549 |
-
|
550 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
}
|
|
|
552 |
|
553 |
-
|
554 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
555 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
556 |
|
557 |
-
|
558 |
}
|
559 |
-
|
|
|
|
|
|
|
|
|
560 |
}
|
561 |
|
562 |
/**
|
563 |
* When unload is used, insert the cache key in the font URLs for the variants still in use.
|
564 |
*
|
565 |
-
* @param array $
|
566 |
-
* @param array $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
567 |
*
|
568 |
-
* @return
|
569 |
*/
|
570 |
-
private function rewrite_variants($
|
571 |
{
|
572 |
-
foreach ($
|
573 |
-
|
574 |
-
|
575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
}
|
577 |
|
578 |
-
|
579 |
-
$replace_variant = $current_stylesheet[$stylesheet][$index]->variants[$variant_index] ?? (object) [];
|
580 |
|
581 |
-
|
582 |
-
|
583 |
-
}
|
584 |
}
|
585 |
}
|
586 |
}
|
587 |
|
588 |
-
return $
|
589 |
}
|
590 |
}
|
18 |
|
19 |
class OMGF_Optimize
|
20 |
{
|
21 |
+
const USER_AGENT = [
|
22 |
+
'woff2' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
];
|
24 |
|
25 |
+
/** @var string $url */
|
26 |
+
private $url = '';
|
27 |
|
28 |
/** @var string */
|
29 |
private $handle = '';
|
31 |
/** @var string $original_handle */
|
32 |
private $original_handle = '';
|
33 |
|
|
|
|
|
|
|
34 |
/** @var string $return */
|
35 |
private $return = 'url';
|
36 |
|
37 |
+
/** @var bool $return_early */
|
38 |
+
private $return_early = false;
|
39 |
+
|
40 |
/** @var string */
|
41 |
private $path = '';
|
42 |
|
43 |
+
/**
|
44 |
+
* @var array $variable_fonts An array of font families in the current stylesheets that're Variable Fonts.
|
45 |
+
*
|
46 |
+
* @since v5.3.0
|
47 |
+
*/
|
48 |
+
private $variable_fonts = [];
|
49 |
+
|
50 |
/** @var string */
|
51 |
private $plugin_text_domain = 'host-webfonts-local';
|
52 |
|
53 |
/**
|
54 |
+
* @param string $url Google Fonts API URL, e.g. "fonts.googleapis.com/css?family="Lato:100,200,300,etc."
|
55 |
* @param string $handle The cache handle, generated using $handle + 5 random chars. Used for storing the fonts and stylesheet.
|
56 |
* @param string $original_handle The stylesheet handle, present in the ID attribute.
|
|
|
57 |
* @param string $return Valid values: 'url' | 'path' | 'object'.
|
58 |
+
* @param bool $return_early If this is set to true, the optimization will skip out early if the object already exists in the database.
|
59 |
+
*
|
60 |
+
* @return void
|
|
|
|
|
|
|
|
|
|
|
61 |
*/
|
62 |
public function __construct(
|
63 |
+
string $url,
|
64 |
string $handle,
|
65 |
string $original_handle,
|
66 |
+
string $return = 'url',
|
67 |
+
bool $return_early = false
|
68 |
) {
|
69 |
+
$this->url = apply_filters('omgf_optimize_url', $url);
|
70 |
$this->handle = sanitize_title_with_dashes($handle);
|
71 |
$this->original_handle = sanitize_title_with_dashes($original_handle);
|
|
|
72 |
$this->path = OMGF_UPLOAD_DIR . '/' . $this->handle;
|
73 |
$this->return = $return;
|
74 |
+
$this->return_early = $return_early;
|
75 |
}
|
76 |
|
77 |
/**
|
78 |
* @return string|array
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
*/
|
80 |
public function process()
|
81 |
{
|
85 |
return '';
|
86 |
}
|
87 |
|
88 |
+
/**
|
89 |
+
* Convert protocol relative URLs.
|
90 |
+
*/
|
91 |
+
if (strpos($this->url, '//') === 0) {
|
92 |
+
$this->url = 'https:' . $this->url;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
}
|
94 |
|
95 |
+
$local_file = $this->path . '/' . $this->handle . '.css';
|
|
|
|
|
|
|
96 |
|
97 |
+
/**
|
98 |
+
* @since v3.6.0 Allows us to bail early, if a fresh copy of files/stylesheets isn't necessary.
|
99 |
+
*/
|
100 |
+
if (file_exists($local_file) && $this->return_early) {
|
101 |
+
switch ($this->return) {
|
102 |
+
case 'path':
|
103 |
+
return $local_file;
|
104 |
+
case 'object':
|
105 |
+
return [$this->original_handle => OMGF::optimized_fonts()[$this->original_handle]];
|
106 |
+
default:
|
107 |
+
return str_replace(OMGF_UPLOAD_DIR, OMGF_UPLOAD_URL, $local_file);
|
108 |
}
|
109 |
}
|
110 |
|
111 |
+
$fonts_bak = $this->grab_fonts_object($this->url);
|
112 |
+
$url = $this->unload_variants($this->url);
|
113 |
+
$fonts = $this->grab_fonts_object($url);
|
114 |
|
115 |
if (empty($fonts)) {
|
116 |
return '';
|
117 |
}
|
118 |
|
119 |
foreach ($fonts as $id => &$font) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
/**
|
121 |
* Sanitize font family, because it may contain spaces.
|
122 |
*
|
124 |
*/
|
125 |
$font->family = rawurlencode($font->family);
|
126 |
|
127 |
+
foreach ($font->variants as $variant_id => &$variant) {
|
128 |
+
/**
|
129 |
+
* @since v5.3.0 Variable fonts use one filename for all font weights/styles. That's why we drop the weight from the filename.
|
130 |
+
*/
|
131 |
+
if (isset($this->variable_fonts[$id])) {
|
132 |
+
$filename = strtolower($id . '-' . $variant->fontStyle . '-' . (isset($variant->subset) ? $variant->subset : ''));
|
133 |
+
} else {
|
134 |
+
$filename = strtolower($id . '-' . $variant->fontStyle . '-' . (isset($variant->subset) ? $variant->subset . '-' : '') . $variant->fontWeight);
|
135 |
+
}
|
136 |
|
137 |
/**
|
138 |
* Encode font family, because it may contain spaces.
|
141 |
*/
|
142 |
$variant->fontFamily = rawurlencode($variant->fontFamily);
|
143 |
|
144 |
+
/**
|
145 |
+
* @since v5.3.0 No need to keep this if this variant belongs to a subset we don't need.
|
146 |
+
*/
|
147 |
+
if (isset($variant->subset) && !in_array($variant->subset, apply_filters('omgf_used_subsets', OMGF_SUBSETS))) {
|
148 |
+
unset($font->variants[$variant_id]);
|
149 |
+
|
150 |
+
continue;
|
151 |
+
}
|
152 |
+
|
153 |
+
if (isset($variant->woff2)) {
|
154 |
+
$variant->woff2 = OMGF::download($variant->woff2, $filename, 'woff2', $this->path);
|
155 |
}
|
156 |
}
|
157 |
}
|
158 |
|
159 |
+
$stylesheet = OMGF::generate_stylesheet($fonts);
|
|
|
160 |
|
161 |
if (!file_exists($this->path)) {
|
162 |
wp_mkdir_p($this->path);
|
164 |
|
165 |
file_put_contents($local_file, $stylesheet);
|
166 |
|
167 |
+
$fonts_bak = $this->rewrite_variants($fonts_bak, $fonts);
|
168 |
+
$current_stylesheet = [$this->original_handle => $fonts_bak];
|
169 |
|
170 |
/**
|
171 |
* $current_stylesheet is added to temporary cache layer, if it isn't present in database.
|
172 |
*
|
173 |
* @since v4.5.7
|
174 |
*/
|
175 |
+
$optimized_fonts = OMGF::optimized_fonts($current_stylesheet, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
update_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts);
|
178 |
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* @since v5.3.0 Parse the stylesheet and build it into a font object which OMGF can understand.
|
193 |
+
*
|
194 |
+
* @param $url Google Fonts API request, e.g. https://fonts.googleapis.com/css?family=Open+Sans:100,200,300,400italic
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
*
|
196 |
+
* @return stdClass
|
197 |
*/
|
198 |
+
private function grab_fonts_object($url)
|
199 |
{
|
200 |
+
$response = wp_remote_get($url, [
|
201 |
+
'user-agent' => self::USER_AGENT['woff2']
|
202 |
+
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
+
$code = wp_remote_retrieve_response_code($response);
|
|
|
205 |
|
206 |
+
if ($code !== 200) {
|
207 |
+
return new stdClass();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
}
|
209 |
|
210 |
+
$stylesheet = wp_remote_retrieve_body($response);
|
|
|
211 |
|
212 |
+
preg_match_all('/font-family:\s\'(.*?)\';/', $stylesheet, $font_families);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
+
if (!isset($font_families[1]) || empty($font_families[1])) {
|
215 |
+
return new stdClass();
|
|
|
|
|
216 |
}
|
217 |
|
218 |
+
$font_families = array_unique($font_families[1]);
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
+
foreach ($font_families as $font_family) {
|
221 |
+
$id = strtolower(str_replace(' ', '-', $font_family));
|
222 |
+
$object[$id] = (object) [
|
223 |
+
'id' => $id,
|
224 |
+
'family' => $font_family,
|
225 |
+
'variants' => apply_filters('omgf_optimize_fonts_object_variants', $this->parse_variants($stylesheet, $font_family), $stylesheet, $font_family, $this->url),
|
226 |
+
'subsets' => apply_filters('omgf_optimize_fonts_object_subsets', $this->parse_subsets($stylesheet, $font_family), $stylesheet, $font_family, $this->url)
|
227 |
+
];
|
228 |
}
|
229 |
|
230 |
+
return $object;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
|
233 |
/**
|
234 |
+
* Parse a stylesheet from Google Fonts' API into a valid Font Object.
|
235 |
*
|
236 |
* @param string $stylesheet
|
237 |
* @param string $font_family
|
240 |
*/
|
241 |
private function parse_variants($stylesheet, $font_family)
|
242 |
{
|
243 |
+
/**
|
244 |
+
* This also captures the commented Subset name.
|
245 |
+
*/
|
246 |
+
preg_match_all(apply_filters('omgf_optimize_parse_variants_regex', '/\/\*\s.*?}/s', $this->url), $stylesheet, $font_faces);
|
247 |
|
248 |
if (!isset($font_faces[0]) || empty($font_faces[0])) {
|
249 |
return [];
|
250 |
}
|
251 |
|
252 |
foreach ($font_faces[0] as $key => $font_face) {
|
253 |
+
if (strpos($font_face, $font_family) === false) {
|
254 |
+
continue;
|
255 |
+
}
|
256 |
+
|
257 |
preg_match('/font-style:\s(normal|italic);/', $font_face, $font_style);
|
258 |
preg_match('/font-weight:\s([0-9]+);/', $font_face, $font_weight);
|
259 |
preg_match('/src:\surl\((.*?woff2)\)/', $font_face, $font_src);
|
260 |
preg_match('/\/\*\s([a-z\-]+?)\s\*\//', $font_face, $subset);
|
261 |
preg_match('/unicode-range:\s(.*?);/', $font_face, $range);
|
262 |
|
263 |
+
$key = $subset[1] . '-' . $font_weight[1] . ($font_style[1] == 'normal' ? '' : '-' . $font_style[1]);
|
264 |
+
|
265 |
$font_object[$key] = new stdClass();
|
266 |
$font_object[$key]->id = $font_weight[1] . ($font_style[1] == 'normal' ? '' : $font_style[1]);
|
267 |
$font_object[$key]->fontFamily = $font_family;
|
268 |
$font_object[$key]->fontStyle = $font_style[1];
|
269 |
$font_object[$key]->fontWeight = $font_weight[1];
|
270 |
$font_object[$key]->woff2 = $font_src[1];
|
271 |
+
|
272 |
+
if (!empty($subset) && isset($subset[1])) {
|
273 |
+
$font_object[$key]->subset = $subset[1];
|
274 |
+
}
|
275 |
+
|
276 |
+
if (!empty($range) && isset($range[1])) {
|
277 |
+
$font_object[$key]->range = $range[1];
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* @since v5.3.0 Is this a variable font i.e. one font file for multiple font weights/styles?
|
282 |
+
*/
|
283 |
+
if (substr_count($stylesheet, $font_src[1]) > 1) {
|
284 |
+
$this->variable_fonts[strtolower(str_replace(' ', '-', $font_family))] = true;
|
285 |
+
}
|
286 |
}
|
287 |
|
288 |
return $font_object;
|
304 |
}
|
305 |
|
306 |
/**
|
307 |
+
* Modifies the URL to not include unloaded variants.
|
308 |
+
*
|
309 |
+
* @param mixed $url
|
310 |
+
* @return void
|
311 |
*/
|
312 |
+
private function unload_variants($url)
|
313 |
{
|
314 |
+
if (!isset(OMGF::unloaded_fonts()[$this->original_handle])) {
|
315 |
+
return $url;
|
316 |
+
}
|
|
|
317 |
|
318 |
+
$url = urldecode($url);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
|
320 |
+
if (strpos($url, '/css2') !== false) {
|
321 |
+
$url = $this->unload_css2($url);
|
322 |
+
} else {
|
323 |
+
$url = $this->unload_css($url);
|
|
|
|
|
|
|
324 |
}
|
325 |
|
326 |
+
return apply_filters('omgf_optimize_unload_variants_url', $url);
|
327 |
}
|
328 |
|
329 |
/**
|
330 |
+
* Process unload for Variable Fonts API requests.
|
331 |
+
*
|
332 |
+
* @param string $url full request to Variable Fonts API.
|
333 |
*
|
334 |
+
* @return string full requests (excluding unloaded variants)
|
|
|
|
|
|
|
|
|
335 |
*/
|
336 |
+
private function unload_css2($url)
|
337 |
{
|
338 |
+
$query = parse_url($url, PHP_URL_QUERY);
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
|
340 |
+
foreach ($font_families = explode('&', $query) as $key => $family) {
|
341 |
+
preg_match('/family=(?<name>[A-Za-z\s]+)[\:]?/', $family, $name);
|
342 |
+
preg_match('/:(?P<axes>[a-z,]+)@/', $family, $axes);
|
343 |
+
preg_match('/@(?P<tuples>[0-9,;]+)[&]?/', $family, $tuples);
|
344 |
|
345 |
+
if (!isset($name['name']) || empty($name['name'])) {
|
346 |
+
continue;
|
347 |
+
}
|
348 |
+
|
349 |
+
$name = $name['name'];
|
350 |
+
$id = str_replace(' ', '-', strtolower($name));
|
351 |
+
|
352 |
+
if (!isset(OMGF::unloaded_fonts()[$this->original_handle][$id])) {
|
353 |
+
continue;
|
354 |
+
}
|
355 |
+
|
356 |
+
if (!isset($axes['axes']) || empty($axes['axes'])) {
|
357 |
+
$axes = 'wght';
|
358 |
+
} else {
|
359 |
+
$axes = $axes['axes'];
|
360 |
+
}
|
361 |
+
|
362 |
+
if (!isset($tuples['tuples']) || empty($tuples['tuples'])) {
|
363 |
+
/**
|
364 |
+
* Variable Fonts API returns only regular (normal, 400) if no variations are defined.
|
365 |
+
*/
|
366 |
+
$tuples = ['400'];
|
367 |
+
} else {
|
368 |
+
$tuples = explode(';', $tuples['tuples']);
|
369 |
+
}
|
370 |
+
|
371 |
+
$unloaded_fonts = OMGF::unloaded_fonts()[$this->original_handle][$id];
|
372 |
+
$tuples = array_filter(
|
373 |
+
$tuples,
|
374 |
+
function ($tuple) use ($unloaded_fonts) {
|
375 |
+
return !in_array(preg_replace('/[0-9]+,/', '', $tuple), $unloaded_fonts);
|
376 |
}
|
377 |
+
);
|
378 |
|
379 |
+
/**
|
380 |
+
* The entire font-family appears to be unloaded, let's remove it.
|
381 |
+
*/
|
382 |
+
if (empty($tuples)) {
|
383 |
+
unset($font_families[$key]);
|
384 |
+
|
385 |
+
continue;
|
386 |
+
}
|
387 |
+
|
388 |
+
$font_families[$key] = 'family=' . $name . ':' . $axes . '@' . implode(';', $tuples);
|
389 |
+
}
|
390 |
+
|
391 |
+
return 'https://fonts.googleapis.com/css2?' . implode('&', $font_families);
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Process unload for Google Fonts API.
|
396 |
+
*
|
397 |
+
* @param string $url Full request to Google Fonts API.
|
398 |
+
*
|
399 |
+
* @return string Full request (excluding unloaded variants)
|
400 |
+
*/
|
401 |
+
private function unload_css($url)
|
402 |
+
{
|
403 |
+
$query = parse_url($url, PHP_URL_QUERY);
|
404 |
+
|
405 |
+
parse_str($query, $font_families);
|
406 |
+
|
407 |
+
foreach ($font_families = explode('|', $font_families['family']) as $key => $font_family) {
|
408 |
+
list($name, $tuples) = array_pad(explode(':', $font_family), 2, []);
|
409 |
+
|
410 |
+
$id = str_replace(' ', '-', strtolower($name));
|
411 |
+
|
412 |
+
if (!isset(OMGF::unloaded_fonts()[$this->original_handle][$id])) {
|
413 |
+
continue;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Google Fonts API returns 400 if no tuples are defined.
|
418 |
+
*/
|
419 |
+
if (empty($tuples)) {
|
420 |
+
$tuples = ['400'];
|
421 |
+
} else {
|
422 |
+
$tuples = explode(',', $tuples);
|
423 |
+
}
|
424 |
+
|
425 |
+
$unloaded_fonts = OMGF::unloaded_fonts()[$this->original_handle][$id];
|
426 |
+
$tuples = array_filter(
|
427 |
+
$tuples,
|
428 |
+
function ($tuple) use ($unloaded_fonts) {
|
429 |
+
return !in_array($tuple, $unloaded_fonts);
|
430 |
}
|
431 |
+
);
|
432 |
+
|
433 |
+
/**
|
434 |
+
* The entire font-family appears to be unloaded, let's remove it.
|
435 |
+
*/
|
436 |
+
if (empty($tuples)) {
|
437 |
+
unset($font_families[$key]);
|
438 |
|
439 |
+
continue;
|
440 |
}
|
441 |
+
|
442 |
+
$font_families[$key] = urlencode($name) . ':' . implode(',', $tuples);
|
443 |
+
}
|
444 |
+
|
445 |
+
return 'https://fonts.googleapis.com/css?family=' . implode('|', $font_families);
|
446 |
}
|
447 |
|
448 |
/**
|
449 |
* When unload is used, insert the cache key in the font URLs for the variants still in use.
|
450 |
*
|
451 |
+
* @param array $current Contains all font styles, loaded and unloaded.
|
452 |
+
* @param array $replacement Contains just the loaded font styles of current stylesheet.
|
453 |
+
*
|
454 |
+
* Both parameters follow this structure:
|
455 |
+
*
|
456 |
+
* (string) Font Family {
|
457 |
+
* (string) id, (string) family, (array) variants {
|
458 |
+
* (string) id => (object) {
|
459 |
+
* (string) id, (string) fontFamily, (string) fontStyle, (string) fontWeight, (string) woff2, (string) subset = null, (string) range
|
460 |
+
* }
|
461 |
+
* }
|
462 |
+
* }
|
463 |
*
|
464 |
+
* @return array
|
465 |
*/
|
466 |
+
private function rewrite_variants($current, $replacement)
|
467 |
{
|
468 |
+
foreach ($current as $font_family => &$properties) {
|
469 |
+
if (!isset($properties->variants) || empty($properties->variants)) {
|
470 |
+
continue;
|
471 |
+
}
|
472 |
+
|
473 |
+
foreach ($properties->variants as $id => &$variant) {
|
474 |
+
/**
|
475 |
+
* @since v5.3.0 Get rid of any subsets that aren't in use.
|
476 |
+
*/
|
477 |
+
if (isset($variant->subset) && !in_array($variant->subset, apply_filters('omgf_used_subsets', OMGF_SUBSETS))) {
|
478 |
+
unset($properties->variants[$id]);
|
479 |
}
|
480 |
|
481 |
+
$replacement_variant = $replacement[$font_family]->variants[$id] ?? '';
|
|
|
482 |
|
483 |
+
if ($replacement_variant && $replacement_variant != $variant) {
|
484 |
+
$variant = $replacement_variant;
|
|
|
485 |
}
|
486 |
}
|
487 |
}
|
488 |
|
489 |
+
return $current;
|
490 |
}
|
491 |
}
|
@@ -21,9 +21,6 @@ class OMGF_StylesheetGenerator
|
|
21 |
/** @var $fonts */
|
22 |
private $fonts;
|
23 |
|
24 |
-
/** @var string $handle */
|
25 |
-
private $handle;
|
26 |
-
|
27 |
/** @var string $plugin */
|
28 |
private $plugin;
|
29 |
|
@@ -32,11 +29,9 @@ class OMGF_StylesheetGenerator
|
|
32 |
*/
|
33 |
public function __construct(
|
34 |
$fonts,
|
35 |
-
string $handle,
|
36 |
string $plugin
|
37 |
) {
|
38 |
$this->fonts = $fonts;
|
39 |
-
$this->handle = $handle;
|
40 |
$this->plugin = $plugin;
|
41 |
}
|
42 |
|
@@ -47,66 +42,25 @@ class OMGF_StylesheetGenerator
|
|
47 |
*/
|
48 |
public function generate()
|
49 |
{
|
50 |
-
/**
|
51 |
-
* Which file types should we download and include in the stylesheet?
|
52 |
-
*
|
53 |
-
* @since v4.5
|
54 |
-
*/
|
55 |
-
$file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
|
56 |
$font_display = OMGF_DISPLAY_OPTION;
|
57 |
$stylesheet = "/**\n * Auto Generated by $this->plugin\n * @author: Daan van den Bergh\n * @url: https://daan.dev\n */\n\n";
|
58 |
|
59 |
foreach ($this->fonts as $font) {
|
60 |
-
/**
|
61 |
-
* If Font Family's name was recently renamed, the old name should be used so no manual changes have to be made
|
62 |
-
* to the stylesheet after processing.
|
63 |
-
*/
|
64 |
-
$renamed_font_family = in_array($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS)
|
65 |
-
? array_search($font->id, OMGF_Optimize::OMGF_RENAMED_GOOGLE_FONTS)
|
66 |
-
: '';
|
67 |
-
|
68 |
foreach ($font->variants as $variant) {
|
69 |
/**
|
70 |
* Filter font_family name.
|
71 |
*
|
72 |
* @since v4.5.1
|
73 |
*/
|
74 |
-
$font_family = apply_filters('omgf_generate_stylesheet_font_family',
|
75 |
$font_style = $variant->fontStyle;
|
76 |
$font_weight = $variant->fontWeight;
|
77 |
$stylesheet .= "@font-face {\n";
|
78 |
-
$stylesheet .= " font-family: $font_family;\n";
|
79 |
$stylesheet .= " font-style: $font_style;\n";
|
80 |
$stylesheet .= " font-weight: $font_weight;\n";
|
81 |
$stylesheet .= " font-display: $font_display;\n";
|
82 |
-
|
83 |
-
/**
|
84 |
-
* For IE compatibility, EOT is added before the local family name is defined.
|
85 |
-
*/
|
86 |
-
if (in_array('eot', $file_types)) {
|
87 |
-
$stylesheet .= " src: url('" . urldecode($variant->eot) . "');\n";
|
88 |
-
$eot_key = array_search('eot', $file_types);
|
89 |
-
unset($file_types[$eot_key]);
|
90 |
-
}
|
91 |
-
|
92 |
-
$local_src = '';
|
93 |
-
|
94 |
-
if (isset($variant->local) && is_array($variant->local)) {
|
95 |
-
foreach ($variant->local as $local) {
|
96 |
-
$local_src .= "local('$local'), ";
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
$stylesheet .= " src: $local_src\n";
|
101 |
-
$font_src_url = [];
|
102 |
-
|
103 |
-
foreach ($file_types as $file_type) {
|
104 |
-
if (isset($variant->$file_type)) {
|
105 |
-
$font_src_url = array_merge($font_src_url, [$file_type => urldecode($variant->$file_type)]);
|
106 |
-
}
|
107 |
-
}
|
108 |
-
|
109 |
-
$stylesheet .= $this->build_source_string($font_src_url);
|
110 |
|
111 |
if (isset($variant->range)) {
|
112 |
$stylesheet .= " unicode-range: $variant->range;\n";
|
21 |
/** @var $fonts */
|
22 |
private $fonts;
|
23 |
|
|
|
|
|
|
|
24 |
/** @var string $plugin */
|
25 |
private $plugin;
|
26 |
|
29 |
*/
|
30 |
public function __construct(
|
31 |
$fonts,
|
|
|
32 |
string $plugin
|
33 |
) {
|
34 |
$this->fonts = $fonts;
|
|
|
35 |
$this->plugin = $plugin;
|
36 |
}
|
37 |
|
42 |
*/
|
43 |
public function generate()
|
44 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
$font_display = OMGF_DISPLAY_OPTION;
|
46 |
$stylesheet = "/**\n * Auto Generated by $this->plugin\n * @author: Daan van den Bergh\n * @url: https://daan.dev\n */\n\n";
|
47 |
|
48 |
foreach ($this->fonts as $font) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
foreach ($font->variants as $variant) {
|
50 |
/**
|
51 |
* Filter font_family name.
|
52 |
*
|
53 |
* @since v4.5.1
|
54 |
*/
|
55 |
+
$font_family = apply_filters('omgf_generate_stylesheet_font_family', rawurldecode($variant->fontFamily));
|
56 |
$font_style = $variant->fontStyle;
|
57 |
$font_weight = $variant->fontWeight;
|
58 |
$stylesheet .= "@font-face {\n";
|
59 |
+
$stylesheet .= " font-family: '$font_family';\n";
|
60 |
$stylesheet .= " font-style: $font_style;\n";
|
61 |
$stylesheet .= " font-weight: $font_weight;\n";
|
62 |
$stylesheet .= " font-display: $font_display;\n";
|
63 |
+
$stylesheet .= " src: " . $this->build_source_string(['woff2' => $variant->woff2]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
if (isset($variant->range)) {
|
66 |
$stylesheet .= " unicode-range: $variant->range;\n";
|
@@ -79,7 +79,11 @@ class OMGF_Frontend_Process
|
|
79 |
add_action('wp_head', [$this, 'add_preloads'], 3);
|
80 |
add_action('template_redirect', [$this, 'maybe_buffer_output'], 3);
|
81 |
add_filter('omgf_buffer_output', [$this, 'remove_resource_hints'], 9);
|
82 |
-
|
|
|
|
|
|
|
|
|
83 |
|
84 |
/** Smart Slider 3 compatibility */
|
85 |
add_filter('wordpress_prepare_output', [$this, 'parse'], 11);
|
@@ -119,16 +123,23 @@ class OMGF_Frontend_Process
|
|
119 |
}
|
120 |
);
|
121 |
|
|
|
|
|
|
|
|
|
|
|
122 |
foreach ($preload_variants as $variant) {
|
123 |
$url = rawurldecode($variant->woff2);
|
124 |
|
125 |
/**
|
126 |
* @since v5.0.1 An extra check, because people tend to forget to flush their caches when changing fonts, etc.
|
127 |
*/
|
128 |
-
if (!file_exists(str_replace(OMGF_UPLOAD_URL, OMGF_UPLOAD_DIR, $url))) {
|
129 |
continue;
|
130 |
}
|
131 |
|
|
|
|
|
132 |
echo "<link id='omgf-preload-$i' rel='preload' href='$url' as='font' type='font/woff2' crossorigin />\n";
|
133 |
$i++;
|
134 |
}
|
@@ -193,7 +204,7 @@ class OMGF_Frontend_Process
|
|
193 |
* - Cache Enabler v1.8.7
|
194 |
* - Default Settings
|
195 |
* - Kinsta Cache (Same as Cache Enabler?)
|
196 |
-
* - Works on
|
197 |
* - LiteSpeed Cache
|
198 |
* - Don't know (Gal Baras tested it: @see https://wordpress.org/support/topic/completely-broke-wp-rocket-plugin/#post-15377538)
|
199 |
* - W3 Total Cache v2.2.1:
|
@@ -209,8 +220,8 @@ class OMGF_Frontend_Process
|
|
209 |
* - WP Super Cache v1.7.4
|
210 |
* - Page Cache: Enabled
|
211 |
*
|
212 |
-
*
|
213 |
-
*
|
214 |
*
|
215 |
* @return void
|
216 |
*/
|
@@ -253,7 +264,7 @@ class OMGF_Frontend_Process
|
|
253 |
* plugins (e.g. Asset Cleanup) also tend to include their own custom attributes,
|
254 |
* e.g. data-wpacu-to-be-preloaded
|
255 |
*
|
256 |
-
*
|
257 |
*/
|
258 |
foreach (self::RESOURCE_HINTS_URLS as $url) {
|
259 |
if (strpos($match, $url) !== false) {
|
@@ -294,7 +305,10 @@ class OMGF_Frontend_Process
|
|
294 |
return apply_filters('omgf_processed_html', $html, $this);
|
295 |
}
|
296 |
|
297 |
-
|
|
|
|
|
|
|
298 |
|
299 |
if (!isset($links[0]) || empty($links[0])) {
|
300 |
return apply_filters('omgf_processed_html', $html, $this);
|
@@ -371,7 +385,7 @@ class OMGF_Frontend_Process
|
|
371 |
* identifier to the string, to make sure we can make a difference between
|
372 |
* different Google Fonts configurations.
|
373 |
*
|
374 |
-
* @since v5.2.0 Allow Divi/Elementor
|
375 |
* many different Google Fonts stylesheets configured throughout their pages and
|
376 |
* blame OMGF for the fact that it detects all those different stylesheets. :-/
|
377 |
*/
|
@@ -391,6 +405,7 @@ class OMGF_Frontend_Process
|
|
391 |
$google_fonts[$key]['id'] = $id;
|
392 |
}
|
393 |
|
|
|
394 |
$google_fonts[$key]['href'] = $href['href'];
|
395 |
}
|
396 |
|
@@ -460,14 +475,18 @@ class OMGF_Frontend_Process
|
|
460 |
$replace = [];
|
461 |
|
462 |
foreach ($google_fonts as $key => $stack) {
|
463 |
-
|
|
|
|
|
|
|
|
|
464 |
|
465 |
/**
|
466 |
-
* If stylesheet with $handle is completely marked for unload, just
|
467 |
-
*
|
468 |
*/
|
469 |
if (OMGF::unloaded_stylesheets() && in_array($handle, OMGF::unloaded_stylesheets())) {
|
470 |
-
$search[$key] = $stack['
|
471 |
$replace[$key] = '';
|
472 |
|
473 |
continue;
|
@@ -492,16 +511,20 @@ class OMGF_Frontend_Process
|
|
492 |
continue;
|
493 |
}
|
494 |
|
495 |
-
$query =
|
|
|
496 |
|
497 |
/**
|
498 |
-
*
|
499 |
*/
|
500 |
-
if (!isset($query['family'])
|
|
|
|
|
|
|
501 |
continue;
|
502 |
}
|
503 |
|
504 |
-
$optimize = new OMGF_Optimize($
|
505 |
$cached_url = $optimize->process();
|
506 |
|
507 |
if (!$cached_url) {
|
@@ -515,109 +538,6 @@ class OMGF_Frontend_Process
|
|
515 |
return ['search' => $search, 'replace' => $replace];
|
516 |
}
|
517 |
|
518 |
-
/**
|
519 |
-
* The generated request URL includes all required parameters for OMGF's Download API.
|
520 |
-
*
|
521 |
-
* @param string $url e.g. https://fonts.googleapis.com/css?family=Open+Sans:100,200,300|Roboto:100,200,300 etc.
|
522 |
-
* @param string $updated_handle e.g. example-handle-xvfdo
|
523 |
-
* @param string $handle e.g. example-handle
|
524 |
-
*
|
525 |
-
* @return array [ 'family' => string, 'display' => string, 'handle' => string, 'original_handle' => string ]
|
526 |
-
*/
|
527 |
-
public function build_query($url, $updated_handle, $handle)
|
528 |
-
{
|
529 |
-
// Filter out HTML (&, etc) and URL encoded characters, so we can properly parse it.
|
530 |
-
$url = htmlspecialchars_decode(urldecode($url));
|
531 |
-
$parsed_url = parse_url($url);
|
532 |
-
$query = $parsed_url['query'] ?? '';
|
533 |
-
|
534 |
-
if ($parsed_url['path'] == '/css2') {
|
535 |
-
// Request to fonts.googleapis.com/css2?etc.
|
536 |
-
$original_query = $this->parse_css2($query);
|
537 |
-
} elseif (strpos($parsed_url['path'], 'earlyaccess') !== false) {
|
538 |
-
// Request to https://fonts.googleapis.com/earlyaccess/etc. should be left for OMGF Pro to deal with.
|
539 |
-
$original_query = ['family' => ''];
|
540 |
-
} else {
|
541 |
-
/**
|
542 |
-
* Request to fonts.googleapis.com/css?etc. (default)
|
543 |
-
*
|
544 |
-
* Decode, just to be sure.
|
545 |
-
*/
|
546 |
-
parse_str($query, $original_query);
|
547 |
-
}
|
548 |
-
|
549 |
-
$params = array_merge(
|
550 |
-
$original_query,
|
551 |
-
[
|
552 |
-
'handle' => $updated_handle,
|
553 |
-
'original_handle' => $handle,
|
554 |
-
]
|
555 |
-
);
|
556 |
-
|
557 |
-
return apply_filters('omgf_request_url', $params);
|
558 |
-
}
|
559 |
-
|
560 |
-
/**
|
561 |
-
* Convert CSS2 query to regular CSS API query.
|
562 |
-
*
|
563 |
-
* @param string $query
|
564 |
-
*
|
565 |
-
* @return array
|
566 |
-
*/
|
567 |
-
private function parse_css2($query)
|
568 |
-
{
|
569 |
-
// array_filter() removes empty elements.
|
570 |
-
$families = array_filter(explode('&', $query));
|
571 |
-
|
572 |
-
foreach ($families as $param) {
|
573 |
-
if (strpos($param, 'family') === false) {
|
574 |
-
continue;
|
575 |
-
}
|
576 |
-
|
577 |
-
parse_str($param, $parts);
|
578 |
-
|
579 |
-
$font_families[] = $parts['family'];
|
580 |
-
}
|
581 |
-
|
582 |
-
if (empty($font_families)) {
|
583 |
-
return $query;
|
584 |
-
}
|
585 |
-
|
586 |
-
$weights = '';
|
587 |
-
|
588 |
-
foreach ($font_families as $font_family) {
|
589 |
-
if (strpos($font_family, ':') !== false) {
|
590 |
-
list($family, $weights) = explode(':', $font_family);
|
591 |
-
} else {
|
592 |
-
$family = $font_family;
|
593 |
-
$weights = '';
|
594 |
-
}
|
595 |
-
|
596 |
-
/**
|
597 |
-
* @var string $weights [ '300', '400', '500', etc. ] || ''
|
598 |
-
*/
|
599 |
-
$weights = strpos($weights, ';') !== false ? explode(';', substr($weights, strpos($weights, '@') + 1)) : [substr($weights, strpos($weights, '@') + 1)];
|
600 |
-
|
601 |
-
if (!$weights) {
|
602 |
-
$fonts[] = $family;
|
603 |
-
|
604 |
-
continue;
|
605 |
-
}
|
606 |
-
|
607 |
-
/**
|
608 |
-
* @var array $weights Multiple weights, e.g. [ '300', '400', '500', '0,600', '1,700' ] || Single weight, e.g. [ '500' ] or [ '1,600' ]
|
609 |
-
*/
|
610 |
-
foreach ($weights as &$weight) {
|
611 |
-
$properties = explode(',', $weight);
|
612 |
-
$weight = $properties[0] == '1' && isset($properties[1]) ? $properties[1] . 'italic' : ($properties[0] != '0' ? $properties[0] : $properties[1]);
|
613 |
-
}
|
614 |
-
|
615 |
-
$fonts[] = $family . ':' . implode(',', $weights);
|
616 |
-
}
|
617 |
-
|
618 |
-
return ['family' => implode('|', $fonts)];
|
619 |
-
}
|
620 |
-
|
621 |
/**
|
622 |
* Because all great themes come packed with extra Cumulative Layout Shifting.
|
623 |
*
|
79 |
add_action('wp_head', [$this, 'add_preloads'], 3);
|
80 |
add_action('template_redirect', [$this, 'maybe_buffer_output'], 3);
|
81 |
add_filter('omgf_buffer_output', [$this, 'remove_resource_hints'], 9);
|
82 |
+
|
83 |
+
/** Only hook into our own filter if Smart Slider 3 isn't active, as it has its own filter. */
|
84 |
+
if (!function_exists('smart_slider_3_plugins_loaded')) {
|
85 |
+
add_filter('omgf_buffer_output', [$this, 'parse']);
|
86 |
+
}
|
87 |
|
88 |
/** Smart Slider 3 compatibility */
|
89 |
add_filter('wordpress_prepare_output', [$this, 'parse'], 11);
|
123 |
}
|
124 |
);
|
125 |
|
126 |
+
/**
|
127 |
+
* @since v5.3.0 Store all preloaded URLs temporarily, to make sure no duplicate files (Variable Fonts) are preloaded.
|
128 |
+
*/
|
129 |
+
$preloaded = [];
|
130 |
+
|
131 |
foreach ($preload_variants as $variant) {
|
132 |
$url = rawurldecode($variant->woff2);
|
133 |
|
134 |
/**
|
135 |
* @since v5.0.1 An extra check, because people tend to forget to flush their caches when changing fonts, etc.
|
136 |
*/
|
137 |
+
if (!file_exists(str_replace(OMGF_UPLOAD_URL, OMGF_UPLOAD_DIR, $url)) || in_array($url, $preloaded)) {
|
138 |
continue;
|
139 |
}
|
140 |
|
141 |
+
$preloaded[] = $url;
|
142 |
+
|
143 |
echo "<link id='omgf-preload-$i' rel='preload' href='$url' as='font' type='font/woff2' crossorigin />\n";
|
144 |
$i++;
|
145 |
}
|
204 |
* - Cache Enabler v1.8.7
|
205 |
* - Default Settings
|
206 |
* - Kinsta Cache (Same as Cache Enabler?)
|
207 |
+
* - Works on Daan.dev
|
208 |
* - LiteSpeed Cache
|
209 |
* - Don't know (Gal Baras tested it: @see https://wordpress.org/support/topic/completely-broke-wp-rocket-plugin/#post-15377538)
|
210 |
* - W3 Total Cache v2.2.1:
|
220 |
* - WP Super Cache v1.7.4
|
221 |
* - Page Cache: Enabled
|
222 |
*
|
223 |
+
* Not tested (yet):
|
224 |
+
* TODO: [OMGF-41] - Swift Performance
|
225 |
*
|
226 |
* @return void
|
227 |
*/
|
264 |
* plugins (e.g. Asset Cleanup) also tend to include their own custom attributes,
|
265 |
* e.g. data-wpacu-to-be-preloaded
|
266 |
*
|
267 |
+
* TODO: [OMGF-42] I think I should be able to use an array_filter here or something?
|
268 |
*/
|
269 |
foreach (self::RESOURCE_HINTS_URLS as $url) {
|
270 |
if (strpos($match, $url) !== false) {
|
305 |
return apply_filters('omgf_processed_html', $html, $this);
|
306 |
}
|
307 |
|
308 |
+
/**
|
309 |
+
* Use positive lookaround for stricter matching.
|
310 |
+
*/
|
311 |
+
preg_match_all('/(?=\<link).+?href=[\'"](https:)?\/\/fonts\.googleapis\.com\/css.+?[\'"].+?(?<=>)/', $html, $links);
|
312 |
|
313 |
if (!isset($links[0]) || empty($links[0])) {
|
314 |
return apply_filters('omgf_processed_html', $html, $this);
|
385 |
* identifier to the string, to make sure we can make a difference between
|
386 |
* different Google Fonts configurations.
|
387 |
*
|
388 |
+
* @since v5.2.0 Allow Divi/Elementor compatibility fixes to be disabled, for those who have too
|
389 |
* many different Google Fonts stylesheets configured throughout their pages and
|
390 |
* blame OMGF for the fact that it detects all those different stylesheets. :-/
|
391 |
*/
|
405 |
$google_fonts[$key]['id'] = $id;
|
406 |
}
|
407 |
|
408 |
+
$google_fonts[$key]['link'] = $link;
|
409 |
$google_fonts[$key]['href'] = $href['href'];
|
410 |
}
|
411 |
|
475 |
$replace = [];
|
476 |
|
477 |
foreach ($google_fonts as $key => $stack) {
|
478 |
+
/**
|
479 |
+
* Handles should be all lowercase to prevent duplication issues on some filesystems.
|
480 |
+
*/
|
481 |
+
$handle = strtolower($stack['id']);
|
482 |
+
$original_handle = $handle;
|
483 |
|
484 |
/**
|
485 |
+
* If stylesheet with $handle is completely marked for unload, just remove the element
|
486 |
+
* to prevent it from loading.
|
487 |
*/
|
488 |
if (OMGF::unloaded_stylesheets() && in_array($handle, OMGF::unloaded_stylesheets())) {
|
489 |
+
$search[$key] = $stack['link'];
|
490 |
$replace[$key] = '';
|
491 |
|
492 |
continue;
|
511 |
continue;
|
512 |
}
|
513 |
|
514 |
+
$query = parse_url($stack['href'], PHP_URL_QUERY);
|
515 |
+
parse_str($query, $query);
|
516 |
|
517 |
/**
|
518 |
+
* If required parameters aren't set, this request is most likely invalid. Let's just remove it.
|
519 |
*/
|
520 |
+
if (!isset($query['family'])) {
|
521 |
+
$search[$key] = $stack['link'];
|
522 |
+
$replace[$key] = '';
|
523 |
+
|
524 |
continue;
|
525 |
}
|
526 |
|
527 |
+
$optimize = new OMGF_Optimize($stack['href'], $handle, $original_handle);
|
528 |
$cached_url = $optimize->process();
|
529 |
|
530 |
if (!$cached_url) {
|
538 |
return ['search' => $search, 'replace' => $replace];
|
539 |
}
|
540 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
/**
|
542 |
* Because all great themes come packed with extra Cumulative Layout Shifting.
|
543 |
*
|
@@ -9,7 +9,7 @@ OMGF automagically caches the Google Fonts used by your theme/plugins locally. N
|
|
9 |
|
10 |
**Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
|
11 |
|
12 |
-
OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts
|
13 |
|
14 |
## How Does It Work?
|
15 |
|
@@ -24,10 +24,11 @@ All Google Fonts are listed in the **Manage Optimized Fonts** section of OMGF's
|
|
24 |
|
25 |
### Other Features include
|
26 |
|
|
|
|
|
27 |
- **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
|
28 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
|
29 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
|
30 |
-
- **Reduce the filesize** of your fonts and stylesheets, by using the *Force subset* and *Include File Types* feature (OMGF Pro required),
|
31 |
|
32 |
### Additional Features in OMGF Pro
|
33 |
- **Multisite** support,
|
9 |
|
10 |
**Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
|
11 |
|
12 |
+
OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
|
13 |
|
14 |
## How Does It Work?
|
15 |
|
24 |
|
25 |
### Other Features include
|
26 |
|
27 |
+
- **Variable Fonts** support,
|
28 |
+
- **Remove unused subsets** to reduce the size of the CSS stylesheet,
|
29 |
- **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
|
30 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
|
31 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
|
|
|
32 |
|
33 |
### Additional Features in OMGF Pro
|
34 |
- **Multisite** support,
|
@@ -3,7 +3,7 @@ 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.
|
7 |
Requires PHP: 7.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -17,7 +17,7 @@ OMGF automagically caches the Google Fonts used by your theme/plugins locally. N
|
|
17 |
|
18 |
**Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
|
19 |
|
20 |
-
OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts
|
21 |
|
22 |
= How Does It Work? =
|
23 |
|
@@ -32,10 +32,11 @@ All Google Fonts are listed in the **Manage Optimized Fonts** section of OMGF's
|
|
32 |
|
33 |
= Other Features include =
|
34 |
|
|
|
|
|
35 |
- **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
|
36 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
|
37 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
|
38 |
-
- **Reduce the file size** of your fonts and stylesheets, by using the *Force subset* and *Include File Types* feature (OMGF Pro required),
|
39 |
|
40 |
= Additional Features in OMGF Pro =
|
41 |
- **Multisite** support,
|
@@ -75,6 +76,18 @@ For the FAQ, [click here](https://daan.dev/docs/omgf-pro-faq/).
|
|
75 |
|
76 |
== Changelog ==
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
= 5.2.2 | June 28th, 2022 =
|
79 |
* Fixed: updated links from ffw.press to daan.dev after the migration.
|
80 |
|
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.3.0
|
7 |
Requires PHP: 7.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
17 |
|
18 |
**Leverage Browser Cache**, **reduce DNS lookups/requests**, **reduce Cumulative Layout Shift** and make your Google Fonts **100% GDPR compliant** with OMGF!
|
19 |
|
20 |
+
OMGF is written with performance and user-friendliness in mind. It uses the Google Fonts API to automatically cache the fonts your theme and plugins use to **minimize DNS requests** and speed up your WordPress website.
|
21 |
|
22 |
= How Does It Work? =
|
23 |
|
32 |
|
33 |
= Other Features include =
|
34 |
|
35 |
+
- **Variable Fonts** support,
|
36 |
+
- **Remove unused subsets** to reduce the size of the CSS stylesheet,
|
37 |
- **Remove Resource Hints** (preload, preconnect, dns-prefetch) pointing to `fonts.googleapis.com` or `fonts.gstatic.com`,
|
38 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to your Google Fonts,
|
39 |
- **Ensure text remains visible during webfont load** by forcing the *font-display* attribute to all your other fonts! (OMGF Pro required),
|
|
|
40 |
|
41 |
= Additional Features in OMGF Pro =
|
42 |
- **Multisite** support,
|
76 |
|
77 |
== Changelog ==
|
78 |
|
79 |
+
= 5.3.0 | July 20th, 2022 =
|
80 |
+
* Added: Removed Google Webfonts Helper API and implemented a custom Web Font Loader. This adds/fixes:
|
81 |
+
* Added: full support for Variable Fonts
|
82 |
+
* Fixed: Proper (WOFF2) compression, so files generated by OMGF are no longer bigger than files downloaded from the Google Fonts API.
|
83 |
+
* Fixed: The (broken capital A) compression bug is fixed!
|
84 |
+
* Fixed: Changed logo in Help section to Daan.dev logo
|
85 |
+
* Fixed: Remove unused subsets from Optimized Fonts object to reduce db size
|
86 |
+
* Fixed: OMGF_Optimize class will bail earlier, if files and stylesheets already exist, to reduce execution time in the frontend.
|
87 |
+
* Fixed: Invalid Google Fonts API requests (e.g. without a `family` parameter) are removed from the HTML.
|
88 |
+
* Fixed: A stricter regulax expression is used for matching stylesheet `link` elements, to prevent backtracking.
|
89 |
+
* Added: Used Subset(s) option, which allows users to specify which subset(s) they'd like to use when generating stylesheets and down-/preloading (variable) font files.
|
90 |
+
|
91 |
= 5.2.2 | June 28th, 2022 =
|
92 |
* Fixed: updated links from ffw.press to daan.dev after the migration.
|
93 |
|