Changeset 3721511
- Timestamp:
- 09/30/2026 02:54:33 PM (3 weeks ago)
- Location:
- host-webfonts-local
- Files:
-
- 44 edited
- 1 copied
-
tags/6.3.12 (copied) (copied from host-webfonts-local/trunk )
-
tags/6.3.12/assets/css/omgf-admin.css (modified) (1 diff)
-
tags/6.3.12/assets/css/omgf-admin.min.css (modified) (1 diff)
-
tags/6.3.12/assets/css/omgf-frontend.css (modified) (1 diff)
-
tags/6.3.12/assets/css/omgf-frontend.min.css (modified) (1 diff)
-
tags/6.3.12/assets/js/omgf-admin.js (modified) (2 diffs)
-
tags/6.3.12/assets/js/omgf-admin.min.js (modified) (1 diff)
-
tags/6.3.12/assets/js/omgf-frontend.js (modified) (8 diffs)
-
tags/6.3.12/assets/js/omgf-frontend.min.js (modified) (1 diff)
-
tags/6.3.12/host-webfonts-local.php (modified) (1 diff)
-
tags/6.3.12/readme.txt (modified) (2 diffs)
-
tags/6.3.12/src/API/AdminbarMenu.php (modified) (3 diffs)
-
tags/6.3.12/src/API/Dashboard.php (modified) (3 diffs)
-
tags/6.3.12/src/Admin/Actions.php (modified) (2 diffs)
-
tags/6.3.12/src/Admin/Dashboard.php (modified) (3 diffs)
-
tags/6.3.12/src/Admin/Notice.php (modified) (1 diff)
-
tags/6.3.12/src/Admin/Settings.php (modified) (1 diff)
-
tags/6.3.12/src/Admin/Settings/Optimize.php (modified) (2 diffs)
-
tags/6.3.12/src/Download.php (modified) (6 diffs)
-
tags/6.3.12/src/Filters.php (modified) (1 diff)
-
tags/6.3.12/src/Frontend/Process.php (modified) (3 diffs)
-
tags/6.3.12/src/Helper.php (modified) (5 diffs)
-
tags/6.3.12/src/Optimize.php (modified) (1 diff)
-
trunk/assets/css/omgf-admin.css (modified) (1 diff)
-
trunk/assets/css/omgf-admin.min.css (modified) (1 diff)
-
trunk/assets/css/omgf-frontend.css (modified) (1 diff)
-
trunk/assets/css/omgf-frontend.min.css (modified) (1 diff)
-
trunk/assets/js/omgf-admin.js (modified) (2 diffs)
-
trunk/assets/js/omgf-admin.min.js (modified) (1 diff)
-
trunk/assets/js/omgf-frontend.js (modified) (8 diffs)
-
trunk/assets/js/omgf-frontend.min.js (modified) (1 diff)
-
trunk/host-webfonts-local.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/src/API/AdminbarMenu.php (modified) (3 diffs)
-
trunk/src/API/Dashboard.php (modified) (3 diffs)
-
trunk/src/Admin/Actions.php (modified) (2 diffs)
-
trunk/src/Admin/Dashboard.php (modified) (3 diffs)
-
trunk/src/Admin/Notice.php (modified) (1 diff)
-
trunk/src/Admin/Settings.php (modified) (1 diff)
-
trunk/src/Admin/Settings/Optimize.php (modified) (2 diffs)
-
trunk/src/Download.php (modified) (6 diffs)
-
trunk/src/Filters.php (modified) (1 diff)
-
trunk/src/Frontend/Process.php (modified) (3 diffs)
-
trunk/src/Helper.php (modified) (5 diffs)
-
trunk/src/Optimize.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
host-webfonts-local/tags/6.3.12/assets/css/omgf-admin.css
r3489128 r3721511 563 563 width: 96px; 564 564 } 565 566 /* Font files which couldn't be downloaded correctly. */ 567 .omgf form .omgf-task-manager #omgf-download-failures-notice ul { 568 margin-left: 0; 569 } 570 571 .omgf form .omgf-task-manager #omgf-download-failures-notice ul li { 572 text-indent: 0; 573 margin-bottom: 0.5em; 574 } -
host-webfonts-local/tags/6.3.12/assets/css/omgf-admin.min.css
r3489128 r3721511 1 @import url(omgf-admin-google-fonts.min.css);#wpwrap{background-color:rgb(248 250 252 / 1)}.omgf{font-family:"Public Sans",Arial,sans-serif;max-width:1350px}.omgf h1 .pro{background-color:#00adda;padding:0 5px 0 6px;border-radius:5px;text-transform:uppercase;color:#fff}.omgf h1{font-family:Poppins,Verdana,sans-serif;font-weight:800}.omgf h2,.omgf h3,.omgf h4,.omgf h5,.omgf h6{font-family:Poppins,Verdana,sans-serif;font-weight:500}.omgf .button{font-family:Poppins,Verdana,sans-serif;border-radius:10px;font-weight:500}.omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;white-space:nowrap}.omgf .button-cancel.omgf-refresh{color:#ff851b}.omgf .button-cancel.omgf-empty,.omgf .button-cancel.omgf-refresh{padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf .button-cancel:hover#omgf-refresh{color:#fff;background:#ff851b;border-color:#ff851b}.omgf #submit{background:#00adda;border:0;padding:7px 20px}.omgf #submit:hover{background-color:#09c}.omgf h2.omgf-nav{border-bottom:0;padding-bottom:3px}.omgf h2.omgf-nav a{border:0;background-color:transparent;font-weight:600}.omgf h2.omgf-nav .nav-tab{color:#000}.omgf h2.omgf-nav .nav-tab:last-child{float:right}.omgf h2.omgf-nav .nav-tab-active,.omgf h2.omgf-nav .nav-tab:hover{color:#00adda}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-task-manager{padding:5px 25px;margin-bottom:30px;box-shadow:0 10px 20px 1px #ccc;border:0;border-top:4px solid #00adda;border-radius:10px}.omgf form .omgf-task-manager .form-table{margin-bottom:1em}.omgf form .omgf-task-manager th.omgf-align-row-header{padding:.5em 0}.omgf form .omgf-task-manager .task-manager-row{padding:0;line-height:1.33}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:18px 12px;border:1px solid #ececec;border-left:4px solid #ececec;border-radius:3px;margin-bottom:1em}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:10px 18px 2px}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item{display:grid;grid-template-columns:1.5rem 9rem auto}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item .omgf-cache-legend-item-title{font-weight:700}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice ol{margin-left:1.5em;margin-bottom:0;overflow-wrap:anywhere}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.warning,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{border:1px solid #ffdc00;border-left:4px solid #ffdc00;background-color:#fffbdf}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.success{border:1px solid #2ecc40;border-left:4px solid #2ecc40;background-color:#ddf7e0}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.alert{border:1px solid #ff4136;border-left:4px solid #ff4136;background-color:#ff41362B}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice h4{margin-top:0}.omgf form .omgf-task-manager ul{margin-top:5px;list-style:none;margin-left:.5em;padding-left:0}.omgf form .omgf-task-manager ul li{padding-left:0;text-indent:-.5em;line-height:1.5em}.omgf form .omgf-task-manager ul li:before{font-family:dashicons,sans-serif;font-size:16px;vertical-align:-3px}.omgf form .omgf-task-manager ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-task-manager ul li.found:before{content:"\f15e";color:#2ecc40}.omgf form .omgf-task-manager ul li.not-found:before{content:"\f223";color:#00adda}.omgf form .omgf-task-manager ul li.stale-cache-notice:before{content:"\f348";color:#00adda}.omgf form .omgf-task-manager ul li.unloaded:before{content:"\f460";color:#0074d9}.omgf form .advanced-processing-notice,.omgf form .used-subsets-notice{display:block;padding:18px 12px;margin-bottom:.5em;border:1px solid #ececec;border-left:4px solid #ececec}.omgf form .advanced-processing-notice.info,.omgf form .used-subsets-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf-optimize-fonts-container{padding:5px 25px 50px;margin:2.5em auto 2em;overflow:visible;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}.omgf-optimize-fonts-container .form-table tr{position:relative}.omgf-optimize-fonts-container .form-table tr td{padding:20px 0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{margin-top:1.5em;text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning{position:fixed;top:50%;left:33%;width:33%;padding:20px 40px;background-color:#fff5b5;border:2px solid #ffdc00;border-radius:4px;box-shadow:1px 1px 333px #333;z-index:1000}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning .omgf-optimize-preload-warning-close{float:right;font-size:2em;line-height:.45;cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%;padding:4px 0 9px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border-top:4px solid #00adda}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{font-family:Poppins,sans-serif;font-weight:600;padding:9px 0 6px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action:hover{cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{margin:0 0 30px}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip ul li{line-height:1.5em}.omgf-help-section .about,.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul,.omgf-task-manager p{text-align:justify;font-size:14px}.tooltip{position:relative;font-size:16px;line-height:16px;height:12px}.tooltip.omgf-save-optimize{vertical-align:middle}.tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:"Public Sans",Arial,sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:20px;margin-left:-125px;border-radius:10px}.tooltip .tooltip-text a{color:#fff}.tooltip .tooltip-text .illustration{margin-top:10px}.tooltip:hover .tooltip-text{visibility:visible}.omgf-warning{color:red;font-weight:600}#omgf-advanced-settings-form{background-color:#fff;border-radius:10px;padding:0 20px 20px;border-top:4px solid #00adda;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox{padding:5px 25px 10px;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:0}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}#omgf-help-form .postbox .column-container .column.last .signature .signature-image{width:185px}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#wpfooter{font-family:"Public Sans",Arial,sans-serif}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px} 1 @import url(omgf-admin-google-fonts.min.css);#wpwrap{background-color:rgb(248 250 252 / 1)}.omgf{font-family:"Public Sans",Arial,sans-serif;max-width:1350px}.omgf h1 .pro{background-color:#00adda;padding:0 5px 0 6px;border-radius:5px;text-transform:uppercase;color:#fff}.omgf h1{font-family:Poppins,Verdana,sans-serif;font-weight:800}.omgf h2,.omgf h3,.omgf h4,.omgf h5,.omgf h6{font-family:Poppins,Verdana,sans-serif;font-weight:500}.omgf .button{font-family:Poppins,Verdana,sans-serif;border-radius:10px;font-weight:500}.omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;white-space:nowrap}.omgf .button-cancel.omgf-refresh{color:#ff851b}.omgf .button-cancel.omgf-empty,.omgf .button-cancel.omgf-refresh{padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf .button-cancel:hover#omgf-refresh{color:#fff;background:#ff851b;border-color:#ff851b}.omgf #submit{background:#00adda;border:0;padding:7px 20px}.omgf #submit:hover{background-color:#09c}.omgf h2.omgf-nav{border-bottom:0;padding-bottom:3px}.omgf h2.omgf-nav a{border:0;background-color:transparent;font-weight:600}.omgf h2.omgf-nav .nav-tab{color:#000}.omgf h2.omgf-nav .nav-tab:last-child{float:right}.omgf h2.omgf-nav .nav-tab-active,.omgf h2.omgf-nav .nav-tab:hover{color:#00adda}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-task-manager{padding:5px 25px;margin-bottom:30px;box-shadow:0 10px 20px 1px #ccc;border:0;border-top:4px solid #00adda;border-radius:10px}.omgf form .omgf-task-manager .form-table{margin-bottom:1em}.omgf form .omgf-task-manager th.omgf-align-row-header{padding:.5em 0}.omgf form .omgf-task-manager .task-manager-row{padding:0;line-height:1.33}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:18px 12px;border:1px solid #ececec;border-left:4px solid #ececec;border-radius:3px;margin-bottom:1em}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:10px 18px 2px}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item{display:grid;grid-template-columns:1.5rem 9rem auto}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item .omgf-cache-legend-item-title{font-weight:700}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice ol{margin-left:1.5em;margin-bottom:0;overflow-wrap:anywhere}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.warning,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{border:1px solid #ffdc00;border-left:4px solid #ffdc00;background-color:#fffbdf}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.success{border:1px solid #2ecc40;border-left:4px solid #2ecc40;background-color:#ddf7e0}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.alert{border:1px solid #ff4136;border-left:4px solid #ff4136;background-color:#ff41362B}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice h4{margin-top:0}.omgf form .omgf-task-manager ul{margin-top:5px;list-style:none;margin-left:.5em;padding-left:0}.omgf form .omgf-task-manager ul li{padding-left:0;text-indent:-.5em;line-height:1.5em}.omgf form .omgf-task-manager ul li:before{font-family:dashicons,sans-serif;font-size:16px;vertical-align:-3px}.omgf form .omgf-task-manager ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-task-manager ul li.found:before{content:"\f15e";color:#2ecc40}.omgf form .omgf-task-manager ul li.not-found:before{content:"\f223";color:#00adda}.omgf form .omgf-task-manager ul li.stale-cache-notice:before{content:"\f348";color:#00adda}.omgf form .omgf-task-manager ul li.unloaded:before{content:"\f460";color:#0074d9}.omgf form .advanced-processing-notice,.omgf form .used-subsets-notice{display:block;padding:18px 12px;margin-bottom:.5em;border:1px solid #ececec;border-left:4px solid #ececec}.omgf form .advanced-processing-notice.info,.omgf form .used-subsets-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf-optimize-fonts-container{padding:5px 25px 50px;margin:2.5em auto 2em;overflow:visible;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}.omgf-optimize-fonts-container .form-table tr{position:relative}.omgf-optimize-fonts-container .form-table tr td{padding:20px 0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{margin-top:1.5em;text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning{position:fixed;top:50%;left:33%;width:33%;padding:20px 40px;background-color:#fff5b5;border:2px solid #ffdc00;border-radius:4px;box-shadow:1px 1px 333px #333;z-index:1000}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning .omgf-optimize-preload-warning-close{float:right;font-size:2em;line-height:.45;cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%;padding:4px 0 9px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border-top:4px solid #00adda}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{font-family:Poppins,sans-serif;font-weight:600;padding:9px 0 6px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action:hover{cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{margin:0 0 30px}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip ul li{line-height:1.5em}.omgf-help-section .about,.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul,.omgf-task-manager p{text-align:justify;font-size:14px}.tooltip{position:relative;font-size:16px;line-height:16px;height:12px}.tooltip.omgf-save-optimize{vertical-align:middle}.tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:"Public Sans",Arial,sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:20px;margin-left:-125px;border-radius:10px}.tooltip .tooltip-text a{color:#fff}.tooltip .tooltip-text .illustration{margin-top:10px}.tooltip:hover .tooltip-text{visibility:visible}.omgf-warning{color:red;font-weight:600}#omgf-advanced-settings-form{background-color:#fff;border-radius:10px;padding:0 20px 20px;border-top:4px solid #00adda;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox{padding:5px 25px 10px;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:0}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}#omgf-help-form .postbox .column-container .column.last .signature .signature-image{width:185px}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#wpfooter{font-family:"Public Sans",Arial,sans-serif}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px}.omgf form .omgf-task-manager #omgf-download-failures-notice ul{margin-left:0}.omgf form .omgf-task-manager #omgf-download-failures-notice ul li{text-indent:0;margin-bottom:.5em} -
host-webfonts-local/tags/6.3.12/assets/css/omgf-frontend.css
r3489128 r3721511 132 132 color: white !important; 133 133 } 134 135 #wp-admin-bar-omgf .alert { 136 background-color: #FF4136 !important; 137 } 138 139 #wp-admin-bar-omgf .alert .ab-item { 140 color: white !important; 141 } -
host-webfonts-local/tags/6.3.12/assets/css/omgf-frontend.min.css
r3489128 r3721511 1 #wp-admin-bar-omgf.dot>.ab-item:after{content:"";width:10px;height:10px;margin-left:5px;border-radius:50%;background-color:grey;display:inline-block;-webkit-animation:2.5s infinite waiting;-moz-animation:2.5s infinite waiting;-o-animation:2.5s infinite waiting;animation:2.5s infinite waiting}@keyframes waiting{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:grey}}#wp-admin-bar-omgf-info>.ab-item{color:#fff!important}#wp-admin-bar-omgf.dot.success>.ab-item:after{background-color:#2ecc40;animation:none}#wp-admin-bar-omgf.dot.alert>.ab-item:after{background-color:#ff4136;-webkit-animation:2.5s blinking-alert;-moz-animation:2.5s blinking-alert;-o-animation:2.5s blinking-alert;animation:2.5s blinking-alert}@keyframes blinking-alert{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff4136}}#wp-admin-bar-omgf.dot.warning>.ab-item:after{background-color:#ff851b;-webkit-animation:2.5s blinking-warning;-moz-animation:2.5s blinking-warning;-o-animation:2.5s blinking-warning;animation:2.5s blinking-warning}@keyframes blinking-warning{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff851b}}#wp-admin-bar-omgf.dot.notice>.ab-item:after{background-color:#ffdc00;-webkit-animation:2.5s blinking-notice;-moz-animation:2.5s blinking-notice;-o-animation:2.5s blinking-notice;animation:2.5s blinking-notice}@keyframes blinking-notice{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ffdc00}}#wp-admin-bar-omgf.dot.info>.ab-item:after{background-color:#0074d9;-webkit-animation:2.5s blinking-info;-moz-animation:2.5s blinking-info;-o-animation:2.5s blinking-info;animation:2.5s blinking-info}@keyframes blinking-info{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#0074d9}}#wp-admin-bar-omgf.alert #wp-admin-bar-omgf-info{background-color:#ff4136!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info{background-color:#ffdc00!important}#wp-admin-bar-omgf.info #wp-admin-bar-omgf-first-run,#wp-admin-bar-omgf.info #wp-admin-bar-omgf-info{background-color:#0074d9!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info .ab-item{color:#000!important}#wp-admin-bar-omgf .info{background-color:#0074d9!important}#wp-admin-bar-omgf .info .ab-item{color:#fff!important} 1 #wp-admin-bar-omgf.dot>.ab-item:after{content:"";width:10px;height:10px;margin-left:5px;border-radius:50%;background-color:grey;display:inline-block;-webkit-animation:2.5s infinite waiting;-moz-animation:2.5s infinite waiting;-o-animation:2.5s infinite waiting;animation:2.5s infinite waiting}@keyframes waiting{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:grey}}#wp-admin-bar-omgf-info>.ab-item{color:#fff!important}#wp-admin-bar-omgf.dot.success>.ab-item:after{background-color:#2ecc40;animation:none}#wp-admin-bar-omgf.dot.alert>.ab-item:after{background-color:#ff4136;-webkit-animation:2.5s blinking-alert;-moz-animation:2.5s blinking-alert;-o-animation:2.5s blinking-alert;animation:2.5s blinking-alert}@keyframes blinking-alert{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff4136}}#wp-admin-bar-omgf.dot.warning>.ab-item:after{background-color:#ff851b;-webkit-animation:2.5s blinking-warning;-moz-animation:2.5s blinking-warning;-o-animation:2.5s blinking-warning;animation:2.5s blinking-warning}@keyframes blinking-warning{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff851b}}#wp-admin-bar-omgf.dot.notice>.ab-item:after{background-color:#ffdc00;-webkit-animation:2.5s blinking-notice;-moz-animation:2.5s blinking-notice;-o-animation:2.5s blinking-notice;animation:2.5s blinking-notice}@keyframes blinking-notice{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ffdc00}}#wp-admin-bar-omgf.dot.info>.ab-item:after{background-color:#0074d9;-webkit-animation:2.5s blinking-info;-moz-animation:2.5s blinking-info;-o-animation:2.5s blinking-info;animation:2.5s blinking-info}@keyframes blinking-info{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#0074d9}}#wp-admin-bar-omgf.alert #wp-admin-bar-omgf-info{background-color:#ff4136!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info{background-color:#ffdc00!important}#wp-admin-bar-omgf.info #wp-admin-bar-omgf-first-run,#wp-admin-bar-omgf.info #wp-admin-bar-omgf-info{background-color:#0074d9!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info .ab-item{color:#000!important}#wp-admin-bar-omgf .info{background-color:#0074d9!important}#wp-admin-bar-omgf .info .ab-item{color:#fff!important}#wp-admin-bar-omgf .alert{background-color:#ff4136!important}#wp-admin-bar-omgf .alert .ab-item{color:#fff!important} -
host-webfonts-local/tags/6.3.12/assets/js/omgf-admin.js
r3503345 r3721511 54 54 $('.omgf-optimize-forbidden').on('click', this.wait_for_page_reload); 55 55 $(document).on('click', '#omgf-dismiss-performance-checker-notice', this.dismiss_performance_checker_notice); 56 $(document).on('click', '#omgf-dismiss-download-failures', this.dismiss_download_failures); 56 57 // Ticker 57 58 setInterval(this.loop_ticker_items, 4000); … … 480 481 481 482 /** 483 * Dismiss the font files which couldn't be downloaded correctly. 484 */ 485 dismiss_download_failures: function (e) { 486 e.preventDefault(); 487 488 $.ajax({ 489 type: 'POST', 490 url: omgf_admin_i18n.rest_url + '/dashboard/dismiss-download-failures', 491 beforeSend: function (xhr) { 492 xhr.setRequestHeader('X-WP-Nonce', omgf_admin_i18n.nonce); 493 omgf_admin.show_loader(); 494 }, 495 complete: function (result) { 496 if (result.responseJSON !== undefined && result.responseJSON.success) { 497 $('#omgf-download-failures-notice').fadeOut(300, function () { 498 $(this).remove(); 499 }); 500 } 501 502 omgf_admin.hide_loader(); 503 } 504 }); 505 }, 506 507 /** 482 508 * 483 509 */ -
host-webfonts-local/tags/6.3.12/assets/js/omgf-admin.min.js
r3503345 r3721511 1 jQuery(document).ready(function(d){var r={ticker_items:document.querySelectorAll(".ticker-item"),ticker_index:0,empty_cache_directory_xhr:!1,optimize_xhr:!1,cache_prefix:"-mod-",flush_action_init:d(".omgf-empty").data("init"),empty_action_nonce:d(".omgf-empty").data("nonce"),delete_log_xhr:!1,delete_action_nonce:d("#omgf-delete-log").data("nonce"),init:function(){d(".omgf-subsets").on("change",this.maybe_select_latin),d(".omgf-optimize-fonts-manage .unload").on("change",this.maybe_unload_stylesheets),d(".omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select").on("change",this.generate_cache_key),d(".omgf-optimize-fonts-manage .unload").on("change",this.toggle_preload),d(".omgf-optimize-fonts-manage .preload").on("change",this.toggle_unload),d(".omgf-optimize-fonts-manage .preload").on("change",this.maybe_show_preload_warning),d(".omgf-optimize-fonts-manage .unload-italics").on("click",this.unload_italics),d(".omgf-optimize-fonts-manage .unload-all").on("click",this.unload_all),d(".omgf-optimize-fonts-manage .load-all").on("click",this.load_all),d("#omgf-save-optimize, #omgf-optimize-again").on("click",function(){d("#omgf-optimize-settings-form #submit").click()}),d(document).on("click","a[id^=omgf-hide-notice-]",this.hide_notice),d(".omgf-remove-stylesheet").on("click",this.remove_stylesheet_from_db),d(".omgf-refresh, #omgf-cache-refresh").on("click",this.refresh_cache),d(".omgf-empty, #omgf-cache-flush").on("click",this.empty_cache_directory),d("#omgf-optimize-settings-form").on("submit",this.show_loader_before_submit),d("#omgf-delete-log").on("click",this.delete_log),d(".omgf-optimize-preload-warning-close").on("click",this.hide_preload_warning),d(".omgf-optimize-forbidden").on("click",this.wait_for_page_reload),d(document).on("click","#omgf-dismiss-performance-checker-notice",this.dismiss_performance_checker_notice),setInterval(this.loop_ticker_items,4e3)},maybe_select_latin:function(e){let o=this.value,t=e.target,n=t.className,a=["latin","latin-ext"];"latin-ext"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0}),a=["latin","vietnamese"],"vietnamese"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0})},loop_ticker_items:function(){r.ticker_items.forEach(function(e,o){o==r.ticker_index?d(e).fadeIn(500):d(e).hide(0)}),r.ticker_index++,r.ticker_index===r.ticker_items.length&&(r.ticker_index=0)},hide_notice:function(){var e=d(this).data("warning-id"),o=d(this).data("nonce");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_hide_notice",warning_id:e,nonce:o},beforeSend:function(){r.show_loader()},complete:function(e){void 0!==e.responseJSON&&void 0!==e.responseJSON.data&&d("#task-manager-notice-row").replaceWith(e.responseJSON.data),r.hide_loader()}})},remove_stylesheet_from_db:function(){var e=d(this).data("handle");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_remove_stylesheet_from_db",handle:e,nonce:r.empty_action_nonce},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},refresh_cache:function(){d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_refresh_cache",nonce:r.empty_action_nonce},beforeSend:function(){d(".omgf-optimize-fonts-manage table tbody").each(function(e,o){r.generate_cache_key(o)})},complete:function(){d("#submit").click()}})},maybe_unload_stylesheets:function(){var e=d(this).closest("tbody")[0].id;d("tbody#"+e+" input.unload:checked").length===d("tbody#"+e+" input.unload").length?r.unload_stylesheet(e):r.load_stylesheet(e)},unload_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");-1===t.indexOf(e)&&t.push(e),t.join(),o.val(t)},load_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");~(position=t.indexOf(e))&&t.splice(position,1),o.val(t)},generate_cache_key:function(e=null){t=void 0===e.target?d(e).attr("id"):d(this).data("handle");var t,o,e=d("#cache_keys"),n=e.val().split(","),a=d("#"+t+" input.unload:checked").length,i=d("#"+t+" input.unload").length,c=n.findIndex((e,o)=>{if(-1!==e.indexOf(t))return!0}),l=!1;"SELECT"===this.nodeName||0!==a&&a!==i||(n[c]=t,l=!0),!0!==l&&-1!==c&&(a=n[c],i=r.cache_prefix+Math.random().toString(36).substring(2,7),-1!==a.indexOf(r.cache_prefix)&&((l=a.split(r.cache_prefix))[o=r.get_last_element_index(l)]=Math.random().toString(36).substring(2,7),a=l[0],i=r.cache_prefix+l[o]),n[c]=a+i),e.val(n.join())},toggle_preload:function(){r.toggle(this,"preload")},toggle_unload:function(){r.toggle(this,"unload")},maybe_show_preload_warning:function(){5===d("."+this.className+":checked").length&&d("#omgf-optimize-preload-warning").fadeIn("300")},hide_preload_warning:function(){d("#omgf-optimize-preload-warning").fadeOut("100")},wait_for_page_reload:function(e){e.preventDefault(),r.show_loader();var o=window.setInterval(function(){document.hasFocus()&&(window.location.reload(),window.clearInterval(o))},500);window.open(this.href,"_blank")},unload_italics:function(e){e.preventDefault();var t=d(this).parents(".font-family").data("id");d(".unload").each(function(e,o){o.value.includes("italic")&&o.dataset.fontId===t&&!1===o.checked&&o.click()})},unload_all:function(e,o=this){o=d(o).parents(".font-family").data("id");d('input.unload[data-font-id="'+o+'"]').each(function(e,o){!1===o.checked&&o.click()})},load_all:function(){var e=d(this).parents(".font-family").data("id");d('input.unload[data-font-id="'+e+'"]').each(function(e,o){!0===o.checked&&o.click()})},toggle:function(e,o){var t=d(e),t=d("."+o+"-"+t.data("font-id")+"-"+t.val()+" ."+o);e.checked?t.attr("disabled",!0):t.attr("disabled",!1)},get_last_element_index:function(e){return e.length-1},empty_cache_directory:function(){r.empty_cache_directory_xhr&&r.empty_cache_directory_xhr.abort(),r.empty_cache_directory_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_empty_dir",nonce:r.empty_action_nonce,init:r.flush_action_init},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},delete_log:function(){r.delete_log_xhr&&r.delete_log_xhr.abort(),r.delete_log_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_delete_log",nonce:r.delete_action_nonce},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},show_loader_before_submit:function(){r.show_loader()},hide_loader:function(){d(".omgf-loading").fadeOut(300,function(){d(".omgf-loading").remove()})},dismiss_performance_checker_notice:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-notice",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),r.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-performance-checker-notice").fadeOut(300,function(){d(this).remove()}),r.hide_loader()}})},show_loader:function(){d("#wpwrap").append('<div class="omgf-loading"><span class="spinner is-active"></span></div>')}};omgf_show_loader=r.show_loader,omgf_hide_loader=r.hide_loader,omgf_unload_all=r.unload_all,omgf_load_all=r.load_all,omgf_unload_stylesheet=r.unload_stylesheet,omgf_load_stylesheet=r.load_stylesheet,r.init()});1 jQuery(document).ready(function(d){var s={ticker_items:document.querySelectorAll(".ticker-item"),ticker_index:0,empty_cache_directory_xhr:!1,optimize_xhr:!1,cache_prefix:"-mod-",flush_action_init:d(".omgf-empty").data("init"),empty_action_nonce:d(".omgf-empty").data("nonce"),delete_log_xhr:!1,delete_action_nonce:d("#omgf-delete-log").data("nonce"),init:function(){d(".omgf-subsets").on("change",this.maybe_select_latin),d(".omgf-optimize-fonts-manage .unload").on("change",this.maybe_unload_stylesheets),d(".omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select").on("change",this.generate_cache_key),d(".omgf-optimize-fonts-manage .unload").on("change",this.toggle_preload),d(".omgf-optimize-fonts-manage .preload").on("change",this.toggle_unload),d(".omgf-optimize-fonts-manage .preload").on("change",this.maybe_show_preload_warning),d(".omgf-optimize-fonts-manage .unload-italics").on("click",this.unload_italics),d(".omgf-optimize-fonts-manage .unload-all").on("click",this.unload_all),d(".omgf-optimize-fonts-manage .load-all").on("click",this.load_all),d("#omgf-save-optimize, #omgf-optimize-again").on("click",function(){d("#omgf-optimize-settings-form #submit").click()}),d(document).on("click","a[id^=omgf-hide-notice-]",this.hide_notice),d(".omgf-remove-stylesheet").on("click",this.remove_stylesheet_from_db),d(".omgf-refresh, #omgf-cache-refresh").on("click",this.refresh_cache),d(".omgf-empty, #omgf-cache-flush").on("click",this.empty_cache_directory),d("#omgf-optimize-settings-form").on("submit",this.show_loader_before_submit),d("#omgf-delete-log").on("click",this.delete_log),d(".omgf-optimize-preload-warning-close").on("click",this.hide_preload_warning),d(".omgf-optimize-forbidden").on("click",this.wait_for_page_reload),d(document).on("click","#omgf-dismiss-performance-checker-notice",this.dismiss_performance_checker_notice),d(document).on("click","#omgf-dismiss-download-failures",this.dismiss_download_failures),setInterval(this.loop_ticker_items,4e3)},maybe_select_latin:function(e){let o=this.value,t=e.target,n=t.className,a=["latin","latin-ext"];"latin-ext"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0}),a=["latin","vietnamese"],"vietnamese"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0})},loop_ticker_items:function(){s.ticker_items.forEach(function(e,o){o==s.ticker_index?d(e).fadeIn(500):d(e).hide(0)}),s.ticker_index++,s.ticker_index===s.ticker_items.length&&(s.ticker_index=0)},hide_notice:function(){var e=d(this).data("warning-id"),o=d(this).data("nonce");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_hide_notice",warning_id:e,nonce:o},beforeSend:function(){s.show_loader()},complete:function(e){void 0!==e.responseJSON&&void 0!==e.responseJSON.data&&d("#task-manager-notice-row").replaceWith(e.responseJSON.data),s.hide_loader()}})},remove_stylesheet_from_db:function(){var e=d(this).data("handle");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_remove_stylesheet_from_db",handle:e,nonce:s.empty_action_nonce},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},refresh_cache:function(){d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_refresh_cache",nonce:s.empty_action_nonce},beforeSend:function(){d(".omgf-optimize-fonts-manage table tbody").each(function(e,o){s.generate_cache_key(o)})},complete:function(){d("#submit").click()}})},maybe_unload_stylesheets:function(){var e=d(this).closest("tbody")[0].id;d("tbody#"+e+" input.unload:checked").length===d("tbody#"+e+" input.unload").length?s.unload_stylesheet(e):s.load_stylesheet(e)},unload_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");-1===t.indexOf(e)&&t.push(e),t.join(),o.val(t)},load_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");~(position=t.indexOf(e))&&t.splice(position,1),o.val(t)},generate_cache_key:function(e=null){t=void 0===e.target?d(e).attr("id"):d(this).data("handle");var t,o,e=d("#cache_keys"),n=e.val().split(","),a=d("#"+t+" input.unload:checked").length,i=d("#"+t+" input.unload").length,c=n.findIndex((e,o)=>{if(-1!==e.indexOf(t))return!0}),l=!1;"SELECT"===this.nodeName||0!==a&&a!==i||(n[c]=t,l=!0),!0!==l&&-1!==c&&(a=n[c],i=s.cache_prefix+Math.random().toString(36).substring(2,7),-1!==a.indexOf(s.cache_prefix)&&((l=a.split(s.cache_prefix))[o=s.get_last_element_index(l)]=Math.random().toString(36).substring(2,7),a=l[0],i=s.cache_prefix+l[o]),n[c]=a+i),e.val(n.join())},toggle_preload:function(){s.toggle(this,"preload")},toggle_unload:function(){s.toggle(this,"unload")},maybe_show_preload_warning:function(){5===d("."+this.className+":checked").length&&d("#omgf-optimize-preload-warning").fadeIn("300")},hide_preload_warning:function(){d("#omgf-optimize-preload-warning").fadeOut("100")},wait_for_page_reload:function(e){e.preventDefault(),s.show_loader();var o=window.setInterval(function(){document.hasFocus()&&(window.location.reload(),window.clearInterval(o))},500);window.open(this.href,"_blank")},unload_italics:function(e){e.preventDefault();var t=d(this).parents(".font-family").data("id");d(".unload").each(function(e,o){o.value.includes("italic")&&o.dataset.fontId===t&&!1===o.checked&&o.click()})},unload_all:function(e,o=this){o=d(o).parents(".font-family").data("id");d('input.unload[data-font-id="'+o+'"]').each(function(e,o){!1===o.checked&&o.click()})},load_all:function(){var e=d(this).parents(".font-family").data("id");d('input.unload[data-font-id="'+e+'"]').each(function(e,o){!0===o.checked&&o.click()})},toggle:function(e,o){var t=d(e),t=d("."+o+"-"+t.data("font-id")+"-"+t.val()+" ."+o);e.checked?t.attr("disabled",!0):t.attr("disabled",!1)},get_last_element_index:function(e){return e.length-1},empty_cache_directory:function(){s.empty_cache_directory_xhr&&s.empty_cache_directory_xhr.abort(),s.empty_cache_directory_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_empty_dir",nonce:s.empty_action_nonce,init:s.flush_action_init},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},delete_log:function(){s.delete_log_xhr&&s.delete_log_xhr.abort(),s.delete_log_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_delete_log",nonce:s.delete_action_nonce},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},show_loader_before_submit:function(){s.show_loader()},hide_loader:function(){d(".omgf-loading").fadeOut(300,function(){d(".omgf-loading").remove()})},dismiss_performance_checker_notice:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-notice",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),s.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-performance-checker-notice").fadeOut(300,function(){d(this).remove()}),s.hide_loader()}})},dismiss_download_failures:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-download-failures",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),s.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-download-failures-notice").fadeOut(300,function(){d(this).remove()}),s.hide_loader()}})},show_loader:function(){d("#wpwrap").append('<div class="omgf-loading"><span class="spinner is-active"></span></div>')}};omgf_show_loader=s.show_loader,omgf_hide_loader=s.hide_loader,omgf_unload_all=s.unload_all,omgf_load_all=s.load_all,omgf_unload_stylesheet=s.unload_stylesheet,omgf_load_stylesheet=s.load_stylesheet,s.init()}); -
host-webfonts-local/tags/6.3.12/assets/js/omgf-frontend.js
r3641590 r3721511 87 87 } 88 88 89 if ((status !== 'success' && status !== 'warning')) { 89 // If the alert is only caused by failed downloads, the Google Fonts Checker's alert text doesn't apply. 90 let download_failures_only = status === 'alert' && response.download_failures && !response.google_fonts_checker_alert; 91 92 if (status !== 'success' && status !== 'warning' && !download_failures_only) { 90 93 this.addInfoBox(status); 94 } 95 96 if (response.download_failures) { 97 this.addInfoBox('download_failures', response); 91 98 } 92 99 … … 188 195 189 196 /** 197 * Normalizes a font-weight to the numeric value computed styles use, e.g. 'normal' => '400' and 'bold' => '700'. 198 * Ranges (e.g. '100 900' for variable fonts) are returned as-is. 199 * 200 * @param {string} weight 201 * @returns {string} 202 */ 203 normalizeFontWeight: function (weight) { 204 weight = String(weight || '400').trim().toLowerCase(); 205 206 if (weight === 'normal') { 207 return '400'; 208 } 209 210 if (weight === 'bold') { 211 return '700'; 212 } 213 214 return weight; 215 }, 216 217 /** 218 * Checks if a font face is in a set of face IDs collected from computed styles (which always have a single, 219 * numeric weight). A font face with a weight range (i.e. a variable font) is used if any weight within the range is. 220 * 221 * @param {Set} face_ids 222 * @param {string} family 223 * @param {string} weight Normalized font-weight. 224 * @param {string} style 225 * @returns {boolean} 226 */ 227 isFaceUsed: function (face_ids, family, weight, style) { 228 if (face_ids.has(`${family}-${weight}-${style}`.toLowerCase())) { 229 return true; 230 } 231 232 let range = weight.split(/\s+/).map(Number); 233 234 if (range.length !== 2 || range.some(isNaN)) { 235 return false; 236 } 237 238 for (let face_id of face_ids) { 239 let prefix = `${family}-`.toLowerCase(); 240 let suffix = `-${style}`.toLowerCase(); 241 242 if (!face_id.startsWith(prefix) || !face_id.endsWith(suffix)) { 243 continue; 244 } 245 246 let used_weight = Number(face_id.slice(prefix.length, face_id.length - suffix.length)); 247 248 if (used_weight >= range[0] && used_weight <= range[1]) { 249 return true; 250 } 251 } 252 253 return false; 254 }, 255 256 /** 257 * The rules of cross-origin stylesheets can't be read, unless they were loaded with the crossorigin attribute. Most 258 * font CDNs send CORS headers though, so these stylesheets are fetched again (usually from the browser's cache) 259 * and parsed separately to find their @font-face rules. 260 * 261 * @param {string[]} hrefs 262 * @param {Map} font_face_url_map 263 * @param {Set} loaded_font_urls 264 * @returns {Promise<void>} 265 */ 266 extractCrossOriginFontFaceRules: async function (hrefs, font_face_url_map, loaded_font_urls) { 267 if (typeof CSSStyleSheet === 'undefined' || typeof CSSStyleSheet.prototype.replaceSync !== 'function') { 268 return; 269 } 270 271 // Keep the analysis bounded. 272 const max_sheets = 10; 273 const timeout_ms = 3000; 274 275 let unique_hrefs = [...new Set(hrefs)].slice(0, max_sheets); 276 277 await Promise.all(unique_hrefs.map(async (href) => { 278 let controller = typeof AbortController !== 'undefined' ? new AbortController() : null; 279 let timeout = controller ? setTimeout(() => controller.abort(), timeout_ms) : null; 280 281 try { 282 let response = await fetch(href, { 283 mode: 'cors', 284 credentials: 'omit', 285 signal: controller ? controller.signal : undefined 286 }); 287 288 if (!response.ok) { 289 return; 290 } 291 292 let sheet = new CSSStyleSheet(); 293 294 // @import rules aren't supported (and ignored) in constructed stylesheets. 295 sheet.replaceSync(await response.text()); 296 297 this.extractFontFaceRules(sheet.cssRules, { href: href }, font_face_url_map, loaded_font_urls); 298 } catch (e) { 299 // No CORS headers, a network error or a timeout: nothing we can do. 300 } finally { 301 if (timeout) { 302 clearTimeout(timeout); 303 } 304 } 305 })); 306 }, 307 308 /** 190 309 * Helper to get property value from a CSSRule, with fallback for Firefox. 191 310 * … … 230 349 let rule_style = this.getFontFaceProperty(rule, 'font-style') || 'normal'; 231 350 232 if (rule_weight === 'normal') rule_weight = '400'; 233 if (rule_weight === 'bold') rule_weight = '700'; 351 rule_weight = this.normalizeFontWeight(rule_weight); 234 352 235 353 let src = rule.style.getPropertyValue('src') || rule.style.src; … … 356 474 let font_face_url_map = new Map(); 357 475 476 let cross_origin_sheets = []; 477 358 478 for (let i = 0; i < document.styleSheets.length; i++) { 479 let sheet = document.styleSheets[i]; 480 359 481 try { 360 let sheet = document.styleSheets[i];361 482 let rules = sheet.cssRules || sheet.rules; 362 483 if (!rules) continue; … … 364 485 this.extractFontFaceRules(rules, sheet, font_face_url_map, loaded_font_urls); 365 486 } catch (e) { 366 // Ignore cross-origin stylesheet errors. 367 } 368 } 487 // The rules of cross-origin stylesheets (loaded without the crossorigin attribute) can't be read. 488 if (sheet.href) { 489 cross_origin_sheets.push(sheet.href); 490 } 491 } 492 } 493 494 await this.extractCrossOriginFontFaceRules(cross_origin_sheets, font_face_url_map, loaded_font_urls); 369 495 370 496 document.fonts.forEach((font) => { 371 497 let family = font.family.replace(/["']/g, ''); 372 let weight = font.weight; 498 // Font faces often define keywords (e.g. icon fonts use 'normal'), while computed styles are always numeric. 499 let weight = this.normalizeFontWeight(font.weight); 373 500 let style = font.style; 374 501 let face_id = `${family}-${weight}-${style}`.toLowerCase(); … … 381 508 * Check if any loaded fonts that are used above the fold are not preloaded. 382 509 */ 383 if (font.status === 'loaded' && font_url && used_faces_above_the_fold.has(face_id)) {510 if (font.status === 'loaded' && font_url && this.isFaceUsed(used_faces_above_the_fold, family, weight, style)) { 384 511 let is_preloaded = preloaded_fonts.some((url) => { 385 512 // If we have the actual font URL, use it for exact matching. … … 416 543 * elements that aren't rendered yet (e.g. tabs, accordions and modals) would be unloaded. 417 544 */ 418 if (font.status === 'unloaded' && ! used_faces_not_rendered.has(face_id) && font_url) {545 if (font.status === 'unloaded' && !this.isFaceUsed(used_faces_not_rendered, family, weight, style) && font_url) { 419 546 unused_fonts.push({ 420 547 family: family, … … 711 838 let text = omgf_frontend.sprintf(omgf_frontend_i18n.info_box_preload_text, count || 0, data.potential_delay_ms || 0, data.impact || omgf_frontend_i18n.info_box_impact_low); 712 839 info_box.innerHTML = `<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${text}</a>`; 840 } 841 842 if (status === 'download_failures') { 843 info_box.id = 'wp-admin-bar-omgf-download-failures'; 844 info_box.classList.add('alert'); 845 846 let link = document.createElement('a'); 847 link.className = 'ab-item'; 848 link.href = omgf_frontend_i18n.info_box_admin_url; 849 link.textContent = data.download_failures_text || ''; 850 info_box.appendChild(link); 713 851 } 714 852 -
host-webfonts-local/tags/6.3.12/assets/js/omgf-frontend.min.js
r3641590 r3721511 1 let omgf_font_cls=0,omgf_fonts_ready=!1,omgf_dom_content_loaded="loading"!==document.readyState,omgf_dom_content_loaded_time=omgf_dom_content_loaded?performance.now():0,omgf_cls_supported=!1;omgf_dom_content_loaded||document.addEventListener("DOMContentLoaded",()=>{omgf_dom_content_loaded=!0,omgf_dom_content_loaded_time=performance.now()});try{let e=new PerformanceObserver(()=>{});e.observe({type:"layout-shift",buffered:!1}),e.disconnect(),omgf_cls_supported=!0}catch(e){}if(omgf_cls_supported&&void 0!==document.fonts&&void 0!==document.fonts.ready)try{let e=new PerformanceObserver(e=>{e.getEntries().forEach(e=>{!e.hadRecentInput&&omgf_dom_content_loaded&&!omgf_fonts_ready&&e.startTime>=omgf_dom_content_loaded_time&&(omgf_font_cls+=e.value)})});e.observe({type:"layout-shift",buffered:!0}),document.fonts.ready.then(()=>{omgf_fonts_ready=!0,e.disconnect()})}catch(e){}window.addEventListener("load",()=>{let _={menu_item:document.getElementById("wp-admin-bar-omgf"),sub_menu:document.getElementById("wp-admin-bar-omgf-default"),skip_results:omgf_frontend_results.skip||!1,init:async function(){let e=[],t=[],n=null;try{var o,a=this.filterGoogleFonts(),i=(o=await this.getStatus(a)).unused_fonts_analysis||{},r=(t=o.unused_fonts||[],o.preload_analysis||{}),s=(e=o.missing_preloads||[],o.cls_analysis||{});if(n=o.status||null,null!==this.menu_item&&(this.menu_item.classList.add("dot"),n)&&this.menu_item.classList.add(n),"success"!==n&&"warning"!==n&&this.addInfoBox(n),!_.skip_results){if(omgf_frontend_i18n.multilang_plugin_used){var l=omgf_frontend_i18n.subsets_count;if(1<l){let e=omgf_frontend_i18n.info_box_impact_low;3===l?e=omgf_frontend_i18n.info_box_impact_medium:3<l&&(e=omgf_frontend_i18n.info_box_impact_high);var f={name:omgf_frontend_i18n.multilang_plugin_name,subsets_count:l,impact:e};this.addInfoBox("multilang_plugin",f)}}i&&i.count&&this.addInfoBox("unload_notice",i),r&&0<r.potential_delay_ms&&0<e.length&&this.addInfoBox("preload_notice",r,e.length),s&&.01<=s.cls&&this.addInfoBox("cls_notice",s)}}catch(e){console.error("OMGF - Error running Google Fonts Checker:",e)}finally{document.dispatchEvent(new CustomEvent("omgf_frontend_loaded",{detail:{missing_preloads:e,unused_fonts:t,status:n}}))}},filterGoogleFonts:()=>{var e=window.performance.getEntries().filter(e=>{var t,n=0<e.name.indexOf("/fonts.googleapis.com/css")||0<e.name.indexOf("/fonts.googleapis.com/icon");let o=0<e.name.indexOf("/fonts.gstatic.com/");return o&&(t=/\.(woff2|woff|ttf|otf)(\?.*)?$/i.test(e.name),e=!e.initiatorType||["css","link","other"].includes(e.initiatorType),o=t&&e),n||o});if(0===e.length)return[];console.log("OMGF has found the following Google Fonts API calls:");let t=[];return e.forEach(e=>{t.push(e.name),console.log(" - "+e.name)}),t},getFontFaceProperty:function(e,t){var n=e.style.getPropertyValue(t);return n?n.replace(/["']/g,"").trim():(n=e.cssText.match(new RegExp(t+"\\s*:\\s*([^;]+)","i")))?n[1].replace(/["']/g,"").trim():null},extractFontFaceRules:function(t,o,a,i){for(let e=0;e<t.length;e++){var r=t[e];if(r.type===CSSRule.IMPORT_RULE&&r.styleSheet&&(s=r.styleSheet.cssRules||r.styleSheet.rules)&&this.extractFontFaceRules(s,r.styleSheet,a,i),"CSSFontFaceRule"===r.constructor.name||r.type===CSSRule.FONT_FACE_RULE){var s=this.getFontFaceProperty(r,"font-family");let e=this.getFontFaceProperty(r,"font-weight")||"400";var l,f=this.getFontFaceProperty(r,"font-style")||"normal";"bold"===(e="normal"===e?"400":e)&&(e="700");let t=r.style.getPropertyValue("src")||r.style.src,n=(t=t||this.getFontFaceProperty(r,"src"))?t.match(/url\(["']?([^"')]+\.woff2[^"')]*?)["']?\)/):null;(n=n||(t?t.match(/url\(["']?([^"')]+)["']?\)/):null))&&(l=new URL(n[1],o.href||document.baseURI).href,r=r.style.getPropertyValue("unicode-range")||"",f=(`${s}-${e}-`+f+(r?"-"+r:"")).toLowerCase(),a.has(f)||a.set(f,l),i.has(l))&&a.set(f,l)}}},getStatus:async function(e){var t=new URLSearchParams(window.location.search),t=Object.fromEntries(t.entries());let d=[],m=[];if(void 0!==document.fonts&&void 0!==document.fonts.ready){await document.fonts.ready;let s=[];document.head.querySelectorAll('link[rel="preload"][as="font"]').forEach(e=>{s.push(e.href)});let l=new Set,f=new Set;var o=document.querySelectorAll("body *:not(#wpadminbar):not(#wpadminbar *)");for(let e=0;e<o.length&&e<1500;e++){let a=o[e];var c=a.getBoundingClientRect(),u=window.getComputedStyle(a),g=u.fontFamily.replace(/["']/g,"");let t=u.fontWeight,n=u.fontStyle,i=c.top<window.innerHeight&&0<c.bottom&&c.left<window.innerWidth&&0<c.right,r=0<c.width||0<c.height;g.split(",").forEach(e=>{e=(`${e=e.trim()}-${t}-`+n).toLowerCase();i&&l.add(e),r||f.add(e)}),["::before","::after"].forEach(e=>{var e=window.getComputedStyle(a,e),t=e.fontFamily.replace(/["']/g,"");let n=e.fontWeight,o=e.fontStyle;t.split(",").forEach(e=>{e=(`${e=e.trim()}-${n}-`+o).toLowerCase();i&&l.add(e),r||f.add(e)})})}var n=new Set(window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff2?|ttf|otf)(\?.*)?$/i)).map(e=>e.name));let _=new Map;for(let e=0;e<document.styleSheets.length;e++)try{var a=document.styleSheets[e],i=a.cssRules||a.rules;i&&this.extractFontFaceRules(i,a,_,n)}catch(e){}document.fonts.forEach(e=>{let n=e.family.replace(/["']/g,"");var t=e.weight,o=e.style,a=(n+`-${t}-`+o).toLowerCase(),i=(a+"-"+(e.unicodeRange||"")).toLowerCase();let r=_.get(i)||_.get(a);"loaded"===e.status&&r&&l.has(a)&&(s.some(e=>{var t;return!(!r||e!==r)||(t=n.toLowerCase().replace(/\s/g,"-"),e=e.toLowerCase(),new RegExp("(^|[/_-])"+t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|$)","i").test(e))})||d.some(e=>e.family===n&&e.url===r)||d.push({family:n,weight:t,style:o,url:r})),"unloaded"===e.status&&!f.has(a)&&r&&m.push({family:n,weight:t,style:o,url:r,unicode_range:e.unicodeRange})})}let r=this.analyzeUnusedFonts(m),s=await this.analyzePreloadImpact(d),l=this.analyzeCLS(omgf_font_cls);var f=new FormData;return f.append("path",document.location.pathname),f.append("urls",JSON.stringify(e)),f.append("params",JSON.stringify(t)),f.append("unused_fonts_analysis",JSON.stringify(r)),f.append("preload_analysis",JSON.stringify(s)),f.append("cls_analysis",JSON.stringify(l)),_.ajax(f).then(e=>(e&&(e.unused_fonts_analysis=r,e.unused_fonts=m,e.preload_analysis=s,e.missing_preloads=d,e.cls_analysis=l),e))},forEachMatchingResources:function(e,n,o){e.forEach(i=>{let t=i.family,r=i.url,s=t.toLowerCase().replace(/\s/g,"-");n.filter(e=>{var t=e.name.toLowerCase();if(r&&e.name===r)return!0;if(!new RegExp("(^|[/_-])"+s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|\\.|$)","i").test(t))return!1;if(void 0===i.weight)return!0;let n=i.weight;var e=i.style,o=("bold"===(n="normal"===n?"400":n)&&(n="700"),new RegExp(`[./_-]${n}([./_-]|\\.|$)`,"i"));let a=!0;return"italic"===e?a=t.includes("italic")||/[._-]i\.(woff|woff2|ttf|otf)/.test(t)||/\d{3}i\.(woff|woff2|ttf|otf)/.test(t):"normal"===e&&(a=!t.includes("italic")),o.test(t)&&a}).forEach(e=>{o(e,t)})})},getFontResources:function(){return window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i))},analyzeUnusedFonts:function(e){if(0===e.length)return{};e=e.length;let t=omgf_frontend_i18n.info_box_impact_low;return 6<e?t=omgf_frontend_i18n.info_box_impact_high:3<=e&&(t=omgf_frontend_i18n.info_box_impact_medium),{count:e,impact:t}},analyzeCLS:function(e){let t=omgf_frontend_i18n.info_box_impact_low;e=Math.round(1e3*e)/1e3;return e<.01?{}:(.1<e&&(t=omgf_frontend_i18n.info_box_impact_medium),{cls:e,impact:t=.25<e?omgf_frontend_i18n.info_box_impact_high:t})},analyzePreloadImpact:async function(n){if(0===n.length)return{};let o={affects_lcp:!1,potential_delay_ms:0,impact:omgf_frontend_i18n.info_box_impact_low};try{var a=await new Promise(t=>{let n=new PerformanceObserver(e=>{e=e.getEntries(),e=e[e.length-1];n.disconnect(),t(e)});n.observe({type:"largest-contentful-paint",buffered:!0}),setTimeout(()=>{n.disconnect(),t(null)},2e3)});if(!a)return o;var i=a.element;let e=!1;if(!(e=i?"string"==typeof i.innerText&&0<i.innerText.trim().length||"string"==typeof i.textContent&&0<i.textContent.trim().length:e))return o;var r=this.getFontResources();let t=0;if(this.forEachMatchingResources(n,r,e=>{e=e.responseEnd-e.startTime;0<e&&(o.affects_lcp=!0,e>t)&&(t=e)}),o.potential_delay_ms=Math.round(t),o.potential_delay_ms<=5)return{};100<o.potential_delay_ms?o.impact=omgf_frontend_i18n.info_box_impact_high:20<o.potential_delay_ms&&(o.impact=omgf_frontend_i18n.info_box_impact_medium)}catch(e){return console.warn("OMGF - Error analyzing preload impact:",e),{}}return o},ajax:function(e){return fetch(omgf_frontend_i18n.api_url,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":omgf_frontend_i18n.nonce},body:e}).then(e=>!!e.ok&&e.json())},addInfoBox:function(e,t,n){var o,a=document.createElement("li");a.id="wp-admin-bar-omgf-info","alert"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_alert_text}</a>`),"notice"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_notice_text}</a>`),"multilang_plugin"===e&&(a.id="wp-admin-bar-omgf-multilang-info",o=_.sprintf(omgf_frontend_i18n.info_box_multilang_plugin_text,omgf_frontend_i18n.multilang_plugin_name,t.subsets_count,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"unload_notice"===e&&(a.id="wp-admin-bar-omgf-unload-info",o=_.sprintf(omgf_frontend_i18n.info_box_unload_text,t.count||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"preload_notice"===e&&(a.id="wp-admin-bar-omgf-preload-info",o=_.sprintf(omgf_frontend_i18n.info_box_preload_text,n||0,t.potential_delay_ms||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"cls_notice"===e&&(a.id="wp-admin-bar-omgf-cls-info",n=_.sprintf(omgf_frontend_i18n.info_box_cls_text,t.cls,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${n}</a>`),"cls_notice"!==e&&"unload_notice"!==e&&"preload_notice"!==e&&"multilang_plugin"!==e||a.classList.add("info"),"info"===e&&omgf_frontend_i18n.first_run&&document.getElementById("wp-admin-bar-omgf-optimize-this")?.classList.add("info"),_.sub_menu&&_.sub_menu.prepend(a)},sprintf:function(e){let a=arguments,i=1;return e.replace(/%(s|d|0\d+d)/g,function(e,t){var n=a[i++];switch(t){case"s":return n;case"d":return parseInt(n,10);default:var n=String(parseInt(n,10)),o=Number(t.slice(1,-1));return"0".repeat(o).slice(n.length)+n}})}},e=window.performance.getEntries(),t=0,n=setInterval(()=>{t++,((e=e.length<window.performance.getEntries().length?window.performance.getEntries():e).length===window.performance.getEntries().length||20<=t)&&(clearInterval(n),_.init())},500)});1 let omgf_font_cls=0,omgf_fonts_ready=!1,omgf_dom_content_loaded="loading"!==document.readyState,omgf_dom_content_loaded_time=omgf_dom_content_loaded?performance.now():0,omgf_cls_supported=!1;omgf_dom_content_loaded||document.addEventListener("DOMContentLoaded",()=>{omgf_dom_content_loaded=!0,omgf_dom_content_loaded_time=performance.now()});try{let e=new PerformanceObserver(()=>{});e.observe({type:"layout-shift",buffered:!1}),e.disconnect(),omgf_cls_supported=!0}catch(e){}if(omgf_cls_supported&&void 0!==document.fonts&&void 0!==document.fonts.ready)try{let e=new PerformanceObserver(e=>{e.getEntries().forEach(e=>{!e.hadRecentInput&&omgf_dom_content_loaded&&!omgf_fonts_ready&&e.startTime>=omgf_dom_content_loaded_time&&(omgf_font_cls+=e.value)})});e.observe({type:"layout-shift",buffered:!0}),document.fonts.ready.then(()=>{omgf_fonts_ready=!0,e.disconnect()})}catch(e){}window.addEventListener("load",()=>{let p={menu_item:document.getElementById("wp-admin-bar-omgf"),sub_menu:document.getElementById("wp-admin-bar-omgf-default"),skip_results:omgf_frontend_results.skip||!1,init:async function(){let e=[],t=[],n=null;try{var o,a=this.filterGoogleFonts(),i=(o=await this.getStatus(a)).unused_fonts_analysis||{},r=(t=o.unused_fonts||[],o.preload_analysis||{}),s=(e=o.missing_preloads||[],o.cls_analysis||{}),l=(n=o.status||null,null!==this.menu_item&&(this.menu_item.classList.add("dot"),n)&&this.menu_item.classList.add(n),"alert"===n&&o.download_failures&&!o.google_fonts_checker_alert);if("success"===n||"warning"===n||l||this.addInfoBox(n),o.download_failures&&this.addInfoBox("download_failures",o),!p.skip_results){if(omgf_frontend_i18n.multilang_plugin_used){var f=omgf_frontend_i18n.subsets_count;if(1<f){let e=omgf_frontend_i18n.info_box_impact_low;3===f?e=omgf_frontend_i18n.info_box_impact_medium:3<f&&(e=omgf_frontend_i18n.info_box_impact_high);var d={name:omgf_frontend_i18n.multilang_plugin_name,subsets_count:f,impact:e};this.addInfoBox("multilang_plugin",d)}}i&&i.count&&this.addInfoBox("unload_notice",i),r&&0<r.potential_delay_ms&&0<e.length&&this.addInfoBox("preload_notice",r,e.length),s&&.01<=s.cls&&this.addInfoBox("cls_notice",s)}}catch(e){console.error("OMGF - Error running Google Fonts Checker:",e)}finally{document.dispatchEvent(new CustomEvent("omgf_frontend_loaded",{detail:{missing_preloads:e,unused_fonts:t,status:n}}))}},filterGoogleFonts:()=>{var e=window.performance.getEntries().filter(e=>{var t,n=0<e.name.indexOf("/fonts.googleapis.com/css")||0<e.name.indexOf("/fonts.googleapis.com/icon");let o=0<e.name.indexOf("/fonts.gstatic.com/");return o&&(t=/\.(woff2|woff|ttf|otf)(\?.*)?$/i.test(e.name),e=!e.initiatorType||["css","link","other"].includes(e.initiatorType),o=t&&e),n||o});if(0===e.length)return[];console.log("OMGF has found the following Google Fonts API calls:");let t=[];return e.forEach(e=>{t.push(e.name),console.log(" - "+e.name)}),t},normalizeFontWeight:function(e){return"normal"===(e=String(e||"400").trim().toLowerCase())?"400":"bold"===e?"700":e},isFaceUsed:function(e,t,n,o){if(e.has((t+`-${n}-`+o).toLowerCase()))return!0;var a=n.split(/\s+/).map(Number);if(2===a.length&&!a.some(isNaN))for(var i of e){var r=(t+"-").toLowerCase(),s=("-"+o).toLowerCase();if(i.startsWith(r)&&i.endsWith(s)){r=Number(i.slice(r.length,i.length-s.length));if(r>=a[0]&&r<=a[1])return!0}}return!1},extractCrossOriginFontFaceRules:async function(e,i,r){if("undefined"!=typeof CSSStyleSheet&&"function"==typeof CSSStyleSheet.prototype.replaceSync){e=[...new Set(e)].slice(0,10);await Promise.all(e.map(async e=>{let t="undefined"!=typeof AbortController?new AbortController:null;var n=t?setTimeout(()=>t.abort(),3e3):null;try{var o,a=await fetch(e,{mode:"cors",credentials:"omit",signal:t?t.signal:void 0});a.ok&&((o=new CSSStyleSheet).replaceSync(await a.text()),this.extractFontFaceRules(o.cssRules,{href:e},i,r))}catch(e){}finally{n&&clearTimeout(n)}}))}},getFontFaceProperty:function(e,t){var n=e.style.getPropertyValue(t);return n?n.replace(/["']/g,"").trim():(n=e.cssText.match(new RegExp(t+"\\s*:\\s*([^;]+)","i")))?n[1].replace(/["']/g,"").trim():null},extractFontFaceRules:function(t,n,o,a){for(let e=0;e<t.length;e++){var i=t[e];if(i.type===CSSRule.IMPORT_RULE&&i.styleSheet&&(s=i.styleSheet.cssRules||i.styleSheet.rules)&&this.extractFontFaceRules(s,i.styleSheet,o,a),"CSSFontFaceRule"===i.constructor.name||i.type===CSSRule.FONT_FACE_RULE){var r,s=this.getFontFaceProperty(i,"font-family"),l=this.getFontFaceProperty(i,"font-weight")||"400",f=this.getFontFaceProperty(i,"font-style")||"normal",l=this.normalizeFontWeight(l);let e=i.style.getPropertyValue("src")||i.style.src,t=(e=e||this.getFontFaceProperty(i,"src"))?e.match(/url\(["']?([^"')]+\.woff2[^"')]*?)["']?\)/):null;(t=t||(e?e.match(/url\(["']?([^"')]+)["']?\)/):null))&&(r=new URL(t[1],n.href||document.baseURI).href,f=(s+`-${l}-`+f+((l=i.style.getPropertyValue("unicode-range")||"")?"-"+l:"")).toLowerCase(),o.has(f)||o.set(f,r),a.has(r))&&o.set(f,r)}}},getStatus:async function(e){var t=new URLSearchParams(window.location.search),t=Object.fromEntries(t.entries());let _=[],c=[];if(void 0!==document.fonts&&void 0!==document.fonts.ready){await document.fonts.ready;let s=[];document.head.querySelectorAll('link[rel="preload"][as="font"]').forEach(e=>{s.push(e.href)});let l=new Set,f=new Set;var o=document.querySelectorAll("body *:not(#wpadminbar):not(#wpadminbar *)");for(let e=0;e<o.length&&e<1500;e++){let a=o[e];var m=a.getBoundingClientRect(),u=window.getComputedStyle(a),g=u.fontFamily.replace(/["']/g,"");let t=u.fontWeight,n=u.fontStyle,i=m.top<window.innerHeight&&0<m.bottom&&m.left<window.innerWidth&&0<m.right,r=0<m.width||0<m.height;g.split(",").forEach(e=>{e=(`${e=e.trim()}-${t}-`+n).toLowerCase();i&&l.add(e),r||f.add(e)}),["::before","::after"].forEach(e=>{var e=window.getComputedStyle(a,e),t=e.fontFamily.replace(/["']/g,"");let n=e.fontWeight,o=e.fontStyle;t.split(",").forEach(e=>{e=(`${e=e.trim()}-${n}-`+o).toLowerCase();i&&l.add(e),r||f.add(e)})})}var n=new Set(window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff2?|ttf|otf)(\?.*)?$/i)).map(e=>e.name));let d=new Map;var a=[];for(let e=0;e<document.styleSheets.length;e++){var i=document.styleSheets[e];try{var r=i.cssRules||i.rules;r&&this.extractFontFaceRules(r,i,d,n)}catch(e){i.href&&a.push(i.href)}}await this.extractCrossOriginFontFaceRules(a,d,n),document.fonts.forEach(e=>{let n=e.family.replace(/["']/g,"");var t=this.normalizeFontWeight(e.weight),o=e.style,a=(n+`-${t}-`+o).toLowerCase(),i=(a+"-"+(e.unicodeRange||"")).toLowerCase();let r=d.get(i)||d.get(a);"loaded"===e.status&&r&&this.isFaceUsed(l,n,t,o)&&(s.some(e=>{var t;return!(!r||e!==r)||(t=n.toLowerCase().replace(/\s/g,"-"),e=e.toLowerCase(),new RegExp("(^|[/_-])"+t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|$)","i").test(e))})||_.some(e=>e.family===n&&e.url===r)||_.push({family:n,weight:t,style:o,url:r})),"unloaded"===e.status&&!this.isFaceUsed(f,n,t,o)&&r&&c.push({family:n,weight:t,style:o,url:r,unicode_range:e.unicodeRange})})}let s=this.analyzeUnusedFonts(c),l=await this.analyzePreloadImpact(_),f=this.analyzeCLS(omgf_font_cls);var d=new FormData;return d.append("path",document.location.pathname),d.append("urls",JSON.stringify(e)),d.append("params",JSON.stringify(t)),d.append("unused_fonts_analysis",JSON.stringify(s)),d.append("preload_analysis",JSON.stringify(l)),d.append("cls_analysis",JSON.stringify(f)),p.ajax(d).then(e=>(e&&(e.unused_fonts_analysis=s,e.unused_fonts=c,e.preload_analysis=l,e.missing_preloads=_,e.cls_analysis=f),e))},forEachMatchingResources:function(e,n,o){e.forEach(i=>{let t=i.family,r=i.url,s=t.toLowerCase().replace(/\s/g,"-");n.filter(e=>{var t=e.name.toLowerCase();if(r&&e.name===r)return!0;if(!new RegExp("(^|[/_-])"+s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|\\.|$)","i").test(t))return!1;if(void 0===i.weight)return!0;let n=i.weight;var e=i.style,o=("bold"===(n="normal"===n?"400":n)&&(n="700"),new RegExp(`[./_-]${n}([./_-]|\\.|$)`,"i"));let a=!0;return"italic"===e?a=t.includes("italic")||/[._-]i\.(woff|woff2|ttf|otf)/.test(t)||/\d{3}i\.(woff|woff2|ttf|otf)/.test(t):"normal"===e&&(a=!t.includes("italic")),o.test(t)&&a}).forEach(e=>{o(e,t)})})},getFontResources:function(){return window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i))},analyzeUnusedFonts:function(e){if(0===e.length)return{};e=e.length;let t=omgf_frontend_i18n.info_box_impact_low;return 6<e?t=omgf_frontend_i18n.info_box_impact_high:3<=e&&(t=omgf_frontend_i18n.info_box_impact_medium),{count:e,impact:t}},analyzeCLS:function(e){let t=omgf_frontend_i18n.info_box_impact_low;e=Math.round(1e3*e)/1e3;return e<.01?{}:(.1<e&&(t=omgf_frontend_i18n.info_box_impact_medium),{cls:e,impact:t=.25<e?omgf_frontend_i18n.info_box_impact_high:t})},analyzePreloadImpact:async function(n){if(0===n.length)return{};let o={affects_lcp:!1,potential_delay_ms:0,impact:omgf_frontend_i18n.info_box_impact_low};try{var a=await new Promise(t=>{let n=new PerformanceObserver(e=>{e=e.getEntries(),e=e[e.length-1];n.disconnect(),t(e)});n.observe({type:"largest-contentful-paint",buffered:!0}),setTimeout(()=>{n.disconnect(),t(null)},2e3)});if(!a)return o;var i=a.element;let e=!1;if(!(e=i?"string"==typeof i.innerText&&0<i.innerText.trim().length||"string"==typeof i.textContent&&0<i.textContent.trim().length:e))return o;var r=this.getFontResources();let t=0;if(this.forEachMatchingResources(n,r,e=>{e=e.responseEnd-e.startTime;0<e&&(o.affects_lcp=!0,e>t)&&(t=e)}),o.potential_delay_ms=Math.round(t),o.potential_delay_ms<=5)return{};100<o.potential_delay_ms?o.impact=omgf_frontend_i18n.info_box_impact_high:20<o.potential_delay_ms&&(o.impact=omgf_frontend_i18n.info_box_impact_medium)}catch(e){return console.warn("OMGF - Error analyzing preload impact:",e),{}}return o},ajax:function(e){return fetch(omgf_frontend_i18n.api_url,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":omgf_frontend_i18n.nonce},body:e}).then(e=>!!e.ok&&e.json())},addInfoBox:function(e,t,n){var o,a=document.createElement("li");a.id="wp-admin-bar-omgf-info","alert"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_alert_text}</a>`),"notice"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_notice_text}</a>`),"multilang_plugin"===e&&(a.id="wp-admin-bar-omgf-multilang-info",o=p.sprintf(omgf_frontend_i18n.info_box_multilang_plugin_text,omgf_frontend_i18n.multilang_plugin_name,t.subsets_count,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"unload_notice"===e&&(a.id="wp-admin-bar-omgf-unload-info",o=p.sprintf(omgf_frontend_i18n.info_box_unload_text,t.count||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"preload_notice"===e&&(a.id="wp-admin-bar-omgf-preload-info",o=p.sprintf(omgf_frontend_i18n.info_box_preload_text,n||0,t.potential_delay_ms||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"download_failures"===e&&(a.id="wp-admin-bar-omgf-download-failures",a.classList.add("alert"),(n=document.createElement("a")).className="ab-item",n.href=omgf_frontend_i18n.info_box_admin_url,n.textContent=t.download_failures_text||"",a.appendChild(n)),"cls_notice"===e&&(a.id="wp-admin-bar-omgf-cls-info",o=p.sprintf(omgf_frontend_i18n.info_box_cls_text,t.cls,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"cls_notice"!==e&&"unload_notice"!==e&&"preload_notice"!==e&&"multilang_plugin"!==e||a.classList.add("info"),"info"===e&&omgf_frontend_i18n.first_run&&document.getElementById("wp-admin-bar-omgf-optimize-this")?.classList.add("info"),p.sub_menu&&p.sub_menu.prepend(a)},sprintf:function(e){let a=arguments,i=1;return e.replace(/%(s|d|0\d+d)/g,function(e,t){var n=a[i++];switch(t){case"s":return n;case"d":return parseInt(n,10);default:var n=String(parseInt(n,10)),o=Number(t.slice(1,-1));return"0".repeat(o).slice(n.length)+n}})}},e=window.performance.getEntries(),t=0,n=setInterval(()=>{t++,((e=e.length<window.performance.getEntries().length?window.performance.getEntries():e).length===window.performance.getEntries().length||20<=t)&&(clearInterval(n),p.init())},500)}); -
host-webfonts-local/tags/6.3.12/host-webfonts-local.php
r3707539 r3721511 4 4 * Plugin URI: https://daan.dev/wordpress/omgf/ 5 5 * Description: Increase GDPR/DSGVO compliance and leverage browser cache by automatically self-hosting Google Fonts. 6 * Version: 6.3.1 16 * Version: 6.3.12 7 7 * Author: Daan from Daan.dev 8 8 * Author URI: https://daan.dev -
host-webfonts-local/tags/6.3.12/readme.txt
r3707539 r3721511 3 3 Tags: google, fonts, gdpr, dsgvo, cache 4 4 Requires at least: 5.9 5 Tested up to: 7. 06 Stable tag: 6.3.1 15 Tested up to: 7.1 6 Stable tag: 6.3.12 7 7 Requires PHP: 7.3 8 8 License: GPLv2 or later … … 87 87 88 88 == Changelog == 89 90 = 6.3.12 = 91 * Security: hardened the handling of Google Fonts stylesheet requests. 92 * Security: hardened the handling of downloaded font files. 93 * Security: admin notices are escaped on output. 94 * Security: the redirect after saving settings is restricted to the site's own host. 95 * Security: the stylesheet handle is escaped on the Optimize Fonts screen. 96 * Improved: removed a legacy, hidden option from the settings form. 97 * Security: only administrators can store results or trigger processing through the Admin Bar Menu's status endpoint, even when its permission is widened by a filter. URLs are validated before they're processed. 98 * Security: downloaded font files are now validated before they're stored. 99 * Fixed: the Font Performance Checker didn't detect fonts which should be preloaded if their @font-face statement used a keyword (e.g. font-weight: normal, which most icon fonts use) or a weight range (i.e. variable fonts). 100 * Improved: the Font Performance Checker now also detects fonts which should be preloaded in cross-origin stylesheets loaded without the crossorigin attribute, if the stylesheet's host allows it (most font CDNs do). 101 * Tested with WP 7.1. 89 102 90 103 = 6.3.11 = -
host-webfonts-local/tags/6.3.12/src/API/AdminbarMenu.php
r3503345 r3721511 19 19 use OMGF\Admin\Dashboard; 20 20 use OMGF\Admin\Settings; 21 use OMGF\Download; 21 22 use OMGF\Helper as OMGF; 22 23 … … 55 56 public function get_admin_bar_status( $request ) { 56 57 $params = $this->clean( $request->get_params() ); 57 $stored_results = $this->update_google_fonts_checker_results( $params );58 58 $unused_fonts_analysis = $this->decode_json_array( $params['unused_fonts_analysis'] ?? [] ); 59 59 $preload_analysis = $this->decode_json_array( $params['preload_analysis'] ?? [] ); 60 60 $cls_analysis = $this->decode_json_array( $params['cls_analysis'] ?? [] ); 61 61 62 $this->update_perf_metrics( $params, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 62 /** 63 * @since v6.3.12 The permission for this endpoint can be widened with the omgf_api_adminbar_menu_permission 64 * filter (e.g., to allow visitors to request the status), but only administrators may store 65 * results or trigger any processing through it. Everyone else gets a read-only status. 66 */ 67 if ( current_user_can( 'manage_options' ) ) { 68 $stored_results = $this->update_google_fonts_checker_results( $params ); 69 70 $this->update_perf_metrics( $params, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 71 } else { 72 $stored_results = get_option( Settings::OMGF_DB_GOOGLE_FONTS_CHECKER_RESULTS, [] ); 73 $stored_results = is_array( $stored_results ) ? $stored_results : []; 74 } 63 75 64 76 $status = $this->calculate_status( $stored_results, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 65 77 66 return [ 'status' => apply_filters( 'omgf_ajax_admin_bar_status', $status ) ]; 78 /** 79 * @since v6.3.12 Font files which couldn't be downloaded correctly are reported to administrators only, because 80 * visitors requesting the status (e.g. for Smart Optimize) need the regular status. 81 */ 82 $download_failures = current_user_can( 'manage_options' ) ? count( Download::get_failures() ) : 0; 83 84 if ( $download_failures > 0 ) { 85 $status = 'alert'; 86 } 87 88 $response = [ 'status' => apply_filters( 'omgf_ajax_admin_bar_status', $status ) ]; 89 90 if ( $download_failures > 0 ) { 91 $response['download_failures'] = $download_failures; 92 $response['download_failures_text'] = sprintf( 93 /* translators: %d: number of font files */ 94 _n( 95 '%d font file couldn\'t be downloaded correctly', 96 '%d font files couldn\'t be downloaded correctly', 97 $download_failures, 98 'host-webfonts-local' 99 ), 100 $download_failures 101 ); 102 $response['google_fonts_checker_alert'] = ! empty( $stored_results ); 103 } 104 105 return $response; 67 106 } 68 107 … … 135 174 $urls = []; 136 175 } 176 177 /** 178 * @since v6.3.12 Validate the URLs before they're passed to any filter. 179 */ 180 $urls = array_filter( 181 $urls, 182 function ( $url ) { 183 return is_string( $url ) && filter_var( $url, FILTER_VALIDATE_URL ); 184 } 185 ); 137 186 138 187 $urls = apply_filters( 'omgf_ajax_results', $urls, $params, $path ); -
host-webfonts-local/tags/6.3.12/src/API/Dashboard.php
r3489128 r3721511 18 18 19 19 use OMGF\Admin\Settings; 20 use OMGF\Download; 20 21 21 22 class Dashboard { … … 67 68 ] 68 69 ); 70 71 register_rest_route( 72 $this->namespace, 73 '/' . $this->base . '/dismiss-download-failures', 74 [ 75 [ 76 'methods' => 'POST', 77 'callback' => [ $this, 'dismiss_download_failures' ], 78 'permission_callback' => [ $this, 'get_permission' ], 79 ], 80 'schema' => null, 81 ] 82 ); 69 83 } 70 84 … … 90 104 return new \WP_REST_Response( [ 'success' => true ] ); 91 105 } 106 107 /** 108 * Dismiss the font files which couldn't be downloaded correctly. 109 * 110 * @since v6.3.12 111 * 112 * @return \WP_REST_Response 113 */ 114 public function dismiss_download_failures() { 115 Download::clear_failures(); 116 117 return new \WP_REST_Response( [ 'success' => true ] ); 118 } 92 119 } -
host-webfonts-local/tags/6.3.12/src/Admin/Actions.php
r3707539 r3721511 202 202 ); 203 203 204 /** 205 * @since v6.3.12 These options are generated by OMGF and should never be updated using the settings form. 206 */ 207 $read_only_options = [ 208 Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, 209 Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS_FRONTEND, 210 ]; 211 204 212 foreach ( $updated_settings as $option_name => $option_value ) { 205 213 if ( ! str_starts_with( $option_name, 'omgf_' ) || ( empty( $option_value ) && $option_value !== '0' ) ) { 214 continue; 215 } 216 217 if ( in_array( $option_name, $read_only_options, true ) ) { 206 218 continue; 207 219 } … … 258 270 259 271 if ( ! defined( 'DAAN_DOING_TESTS' ) ) { 260 wp_ redirect( $goback ); // @codeCoverageIgnore272 wp_safe_redirect( $goback ); // @codeCoverageIgnore 261 273 exit; // @codeCoverageIgnore 262 274 } -
host-webfonts-local/tags/6.3.12/src/Admin/Dashboard.php
r3628684 r3721511 17 17 namespace OMGF\Admin; 18 18 19 use OMGF\Download; 19 20 use OMGF\Helper as OMGF; 20 21 … … 101 102 102 103 return ob_get_clean(); 104 } 105 106 /** 107 * Renders the font files which couldn't be downloaded correctly. 108 * 109 * @since v6.3.12 110 * 111 * @return void 112 */ 113 public static function render_download_failures() { 114 $failures = Download::get_failures(); 115 116 if ( empty( $failures ) ) { 117 return; 118 } 119 ?> 120 <div class="task-manager-notice alert" id="omgf-download-failures-notice"> 121 <h4><?php echo wp_kses_post( 122 sprintf( 123 /* translators: %1$s: plugin name, %2$d: number of font files */ 124 _n( 125 '%1$s couldn\'t download %2$d font file correctly.', 126 '%1$s couldn\'t download %2$d font files correctly.', 127 count( $failures ), 128 'host-webfonts-local' 129 ), 130 apply_filters( 'omgf_settings_page_title', 'OMGF' ), 131 count( $failures ) 132 ) 133 ); ?></h4> 134 <ul> 135 <?php foreach ( $failures as $url => $failure ) : ?> 136 <li> 137 <strong><?php echo esc_html( $url ); ?></strong><br/> 138 <?php echo esc_html( Download::get_failure_message( $failure['reason'] ) ); ?> 139 </li> 140 <?php endforeach; ?> 141 </ul> 142 <p> 143 [ <a href="#" id="omgf-dismiss-download-failures"><?php echo esc_html__( 'Dismiss', 'host-webfonts-local' ); ?></a> ] 144 </p> 145 </div> 146 <?php 103 147 } 104 148 … … 141 185 unset( $warnings['google_fonts_checker'] ); 142 186 } 187 188 self::render_download_failures(); 143 189 ?> 144 190 <?php if ( ! empty( $google_fonts_checker_results ) ): ?> -
host-webfonts-local/tags/6.3.12/src/Admin/Notice.php
r3494741 r3721511 41 41 foreach ( $notice as $type => $message ) { 42 42 ?> 43 <div id="message" class="notice notice-<?php echo $type; ?> is-dismissible">43 <div id="message" class="notice notice-<?php echo esc_attr( $type ); ?> is-dismissible"> 44 44 <?php foreach ( $message as $line ) : ?> 45 <p><strong><?php echo $line; ?></strong></p>45 <p><strong><?php echo wp_kses_post( $line ); ?></strong></p> 46 46 <?php endforeach; ?> 47 47 </div> -
host-webfonts-local/tags/6.3.12/src/Admin/Settings.php
r3503345 r3721511 35 35 36 36 const OMGF_DB_PERF_CHECK = 'omgf_perf_check'; 37 38 const OMGF_DB_DOWNLOAD_FAILURES = 'omgf_download_failures'; 37 39 38 40 const OMGF_DB_CACHE_TIMESTAMP = 'omgf_cache_timestamp'; -
host-webfonts-local/tags/6.3.12/src/Admin/Settings/Optimize.php
r3531267 r3721511 269 269 } 270 270 ?> 271 <tbody class="stylesheet" id="<?php echo $handle; ?>">271 <tbody class="stylesheet" id="<?php echo esc_attr( $handle ); ?>"> 272 272 <tr> 273 273 <th colspan="6"><?php echo sprintf( 274 274 __( 'Stylesheet handle: %s', 'host-webfonts-local' ), 275 $handle275 esc_html( $handle ) 276 276 ); ?></th> 277 277 </tr> … … 390 390 <?php endforeach; ?> 391 391 </table> 392 <input type="hidden" name="<?php echo Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS; ?>"393 value="<?php echo base64_encode( serialize( $this->optimized_fonts ) ); ?>"/>394 392 <input id="<?php echo Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" type="hidden" 395 393 name="omgf_settings[<?php echo Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>]" -
host-webfonts-local/tags/6.3.12/src/Download.php
r3707539 r3721511 19 19 use OMGF\Helper as OMGF; 20 20 use OMGF\Admin\Notice; 21 use OMGF\Admin\Settings; 21 22 22 23 class Download { … … 39 40 ]; 40 41 42 /** 43 * Default maximum size (in bytes) of a downloaded font file. 44 * 45 * @since v6.3.12 46 */ 47 const MAX_FILE_SIZE = 25 * MB_IN_BYTES; 48 49 /** 50 * Maximum number of failed downloads reported on the Dashboard. 51 * 52 * @since v6.3.12 53 */ 54 const MAX_FAILURES = 20; 55 56 /** 57 * Reasons why a downloaded file was discarded. 58 */ 59 const FAILURE_EMPTY = 'empty'; 60 61 const FAILURE_TOO_LARGE = 'too_large'; 62 63 const FAILURE_INVALID = 'invalid'; 64 41 65 42 66 /** @var string $url */ … … 57 81 string $path 58 82 ) { 59 $this->url = $url; 60 $this->filename = $filename; 83 $this->url = $url; 84 /** 85 * @since v6.3.12 Sanitize the filename so a font family (which it's partly built from) can't contain a 86 * path separator and write the downloaded file outside of $path. 87 */ 88 $this->filename = sanitize_file_name( $filename ); 61 89 $this->path = $path; 62 90 } … … 82 110 $temp_filename = $this->path . '/' . $this->filename . '-' . wp_generate_password( 12, false ) . '.tmp'; 83 111 84 $response = wp_safe_remote_get( 112 $max_file_size = self::get_max_file_size(); 113 $response = wp_safe_remote_get( 85 114 $this->url, 86 115 [ 87 'timeout' => 300, 88 'stream' => true, 89 'filename' => $temp_filename, 116 'timeout' => 300, 117 'stream' => true, 118 'filename' => $temp_filename, 119 /** 120 * @since v6.3.12 Stop downloading once the file exceeds the maximum size. One extra byte is requested, so 121 * a file which was cut off can be told apart from a file of exactly the maximum size. 122 */ 123 'limit_response_size' => $max_file_size + 1, 90 124 ] 91 125 ); … … 161 195 } 162 196 197 /** 198 * @since v6.3.12 Validate the downloaded file before it's stored. 199 */ 200 $reason = $this->validate_file( $temp_filename, $max_file_size ); 201 202 if ( $reason ) { 203 $this->delete_temp_file( $temp_filename ); 204 205 /** 206 * Reported on the Dashboard (and in the Admin Bar), because downloads often run during a visitor's request. 207 * 208 * @see \OMGF\Admin\Dashboard::render_download_failures() 209 */ 210 self::add_failure( $this->url, $reason ); 211 212 return ''; 213 } 214 163 215 if ( file_exists( $temp_filename ) ) { 164 216 $final_path = $this->path . '/' . $this->filename . '.' . $extension; … … 179 231 } 180 232 233 self::remove_failure( $this->url ); 234 181 235 return OMGF_UPLOAD_URL . str_replace( OMGF_UPLOAD_DIR, '', $this->path ) . '/' . $this->filename . '.' . $extension; 236 } 237 238 /** 239 * Maximum size (in bytes) of a downloaded font file. 240 * 241 * @since v6.3.12 242 * @filter omgf_download_max_file_size 243 * 244 * @return int 245 */ 246 public static function get_max_file_size() { 247 return max( 1, (int) apply_filters( 'omgf_download_max_file_size', self::MAX_FILE_SIZE ) ); 248 } 249 250 /** 251 * Checks if $file is a complete font file, i.e. not empty, not cut off because it exceeds the maximum size, and 252 * starting with the signature of a font format. 253 * 254 * @since v6.3.12 255 * 256 * @param string $file 257 * @param int $max_file_size 258 * 259 * @return string An error message if the file is invalid, an empty string if it's valid. 260 */ 261 private function validate_file( $file, $max_file_size ) { 262 $size = file_exists( $file ) ? filesize( $file ) : 0; 263 264 if ( ! $size ) { 265 return self::FAILURE_EMPTY; 266 } 267 268 if ( $size > $max_file_size ) { 269 return self::FAILURE_TOO_LARGE; 270 } 271 272 if ( ! self::is_font_file( $file ) ) { 273 return self::FAILURE_INVALID; 274 } 275 276 return ''; 277 } 278 279 /** 280 * Failed downloads, most recent first. 281 * 282 * @since v6.3.12 283 * 284 * @return array [ url => [ 'reason' => string, 'time' => int ] ] 285 */ 286 public static function get_failures() { 287 return self::normalize_failures( get_option( Settings::OMGF_DB_DOWNLOAD_FAILURES, [] ) ); 288 } 289 290 /** 291 * Removes invalid entries and sorts the failed downloads, most recent first. 292 * 293 * @since v6.3.12 294 * 295 * @param mixed $failures 296 * 297 * @return array 298 */ 299 private static function normalize_failures( $failures ) { 300 if ( ! is_array( $failures ) ) { 301 return []; // @codeCoverageIgnore 302 } 303 304 $failures = array_filter( 305 $failures, 306 function ( $failure, $url ) { 307 return is_string( $url ) && is_array( $failure ) && in_array( $failure['reason'] ?? '', self::get_failure_reasons(), true ); 308 }, 309 ARRAY_FILTER_USE_BOTH 310 ); 311 312 uasort( 313 $failures, 314 function ( $a, $b ) { 315 return ( $b['time'] ?? 0 ) <=> ( $a['time'] ?? 0 ); 316 } 317 ); 318 319 return $failures; 320 } 321 322 /** 323 * Stores a failed download, keeping at most MAX_FAILURES (the most recent ones). 324 * 325 * @since v6.3.12 326 * 327 * @param string $url 328 * @param string $reason One of the FAILURE_* constants. 329 * 330 * @return void 331 */ 332 public static function add_failure( $url, $reason ) { 333 self::update_failures( 334 function ( $failures ) use ( $url, $reason ) { 335 unset( $failures[ $url ] ); 336 337 return array_slice( [ $url => [ 'reason' => $reason, 'time' => time() ] ] + $failures, 0, self::MAX_FAILURES, true ); 338 } 339 ); 340 } 341 342 /** 343 * Removes a failed download, e.g. once it succeeds. 344 * 345 * @since v6.3.12 346 * 347 * @param string $url 348 * 349 * @return void 350 */ 351 public static function remove_failure( $url ) { 352 /** 353 * This runs after every successful download, so only lock when there's something to remove. The check reads the 354 * database, because a cached copy might not contain a failure stored by another request. 355 */ 356 if ( ! isset( self::read_stored_failures()[ $url ] ) ) { 357 return; 358 } 359 360 self::update_failures( 361 function ( $failures ) use ( $url ) { 362 unset( $failures[ $url ] ); 363 364 return $failures; 365 } 366 ); 367 } 368 369 /** 370 * Removes all failed downloads, i.e. when they're dismissed. 371 * 372 * @since v6.3.12 373 * 374 * @return void 375 */ 376 public static function clear_failures() { 377 self::update_failures( 378 function () { 379 return []; 380 } 381 ); 382 } 383 384 /** 385 * Reads the failed downloads from the database, instead of a (possibly outdated) cached copy. 386 * 387 * @since v6.3.12 388 * 389 * @return array 390 */ 391 private static function read_stored_failures() { 392 global $wpdb; 393 394 $stored = $wpdb->get_var( 395 $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", Settings::OMGF_DB_DOWNLOAD_FAILURES ) 396 ); 397 398 return self::normalize_failures( $stored === null ? [] : maybe_unserialize( $stored ) ); 399 } 400 401 /** 402 * Updates the failed downloads while holding a (MySQL) lock, based on the value currently stored in the database, 403 * so concurrent downloads can't overwrite each other's changes. 404 * 405 * @since v6.3.12 406 * 407 * @param callable $callback Receives the current failed downloads and returns the new ones. 408 * 409 * @return void 410 */ 411 private static function update_failures( $callback ) { 412 global $wpdb; 413 414 $lock_name = $wpdb->prefix . Settings::OMGF_DB_DOWNLOAD_FAILURES; 415 // Databases which don't support locks (e.g. SQLite) return null, in which case we proceed without one. 416 $locked = (bool) $wpdb->get_var( $wpdb->prepare( 'SELECT GET_LOCK(%s, %d)', $lock_name, 5 ) ); 417 418 try { 419 $failures = $callback( self::read_stored_failures() ); 420 421 wp_cache_delete( Settings::OMGF_DB_DOWNLOAD_FAILURES, 'options' ); 422 wp_cache_delete( 'notoptions', 'options' ); 423 424 if ( empty( $failures ) ) { 425 delete_option( Settings::OMGF_DB_DOWNLOAD_FAILURES ); 426 } else { 427 update_option( Settings::OMGF_DB_DOWNLOAD_FAILURES, $failures, false ); 428 } 429 } finally { 430 if ( $locked ) { 431 $wpdb->query( $wpdb->prepare( 'SELECT RELEASE_LOCK(%s)', $lock_name ) ); 432 } 433 } 434 } 435 436 /** 437 * @since v6.3.12 438 * 439 * @return string[] 440 */ 441 private static function get_failure_reasons() { 442 return [ self::FAILURE_EMPTY, self::FAILURE_TOO_LARGE, self::FAILURE_INVALID ]; 443 } 444 445 /** 446 * A human-readable description of why a download failed, and what the user can do about it. 447 * 448 * @since v6.3.12 449 * 450 * @param string $reason One of the FAILURE_* constants. 451 * 452 * @return string 453 */ 454 public static function get_failure_message( $reason ) { 455 switch ( $reason ) { 456 case self::FAILURE_TOO_LARGE: 457 return sprintf( 458 /* translators: %s: maximum file size, e.g. 25 MB */ 459 __( 'The file exceeds the maximum file size of %s, so it isn\'t used and a fallback font is shown instead.', 'host-webfonts-local' ), 460 size_format( self::get_max_file_size() ) 461 ); 462 case self::FAILURE_INVALID: 463 return __( 'The downloaded file isn\'t a font file (e.g. an error page), so a fallback font is shown until it\'s downloaded successfully. Click Save & Optimize to try again.', 'host-webfonts-local' ); 464 default: 465 return __( 'The downloaded file was empty, so a fallback font is shown until it\'s downloaded successfully. Click Save & Optimize to try again.', 'host-webfonts-local' ); 466 } 467 } 468 469 /** 470 * Checks if $file starts with the signature (magic bytes) of a WOFF2, WOFF, TrueType, OpenType or EOT file. 471 * 472 * @since v6.3.12 473 * 474 * @param string $file 475 * 476 * @return bool 477 */ 478 public static function is_font_file( $file ) { 479 $handle = @fopen( $file, 'rb' ); // phpcs:ignore 480 481 if ( ! $handle ) { 482 return false; // @codeCoverageIgnore 483 } 484 485 $header = (string) fread( $handle, 36 ); 486 487 fclose( $handle ); 488 489 // WOFF2, WOFF, OpenType (CFF), TrueType, TrueType (Apple), TrueType Collection. 490 if ( in_array( substr( $header, 0, 4 ), [ 'wOF2', 'wOFF', 'OTTO', "\x00\x01\x00\x00", 'true', 'ttcf' ], true ) ) { 491 return true; 492 } 493 494 // EOT: magic number 0x504C at offset 34. 495 return strlen( $header ) >= 36 && substr( $header, 34, 2 ) === 'LP'; 182 496 } 183 497 -
host-webfonts-local/tags/6.3.12/src/Filters.php
r3531267 r3721511 28 28 add_filter( 'home_url', [ $this, 'force_ssl' ], 1000, 2 ); 29 29 add_filter( 'omgf_optimize_user_agent', [ $this, 'maybe_do_legacy_mode' ] ); 30 add_filter( 'pre_update_option_omgf_optimized_fonts', [ $this, 'base64_decode_optimized_fonts' ] );31 30 add_filter( 'omgf_do_not_load_frontend_css', [ $this, 'maybe_load_frontend_assets' ] ); 32 }33 34 /**35 * @since v5.0.5 omgf_optimized_fonts is base64_encoded in the frontend, to bypass firewall restrictions on36 * some servers.37 *38 * @param $old_value39 * @param $value40 *41 * @return bool|array42 */43 public function base64_decode_optimized_fonts( $value ) {44 if ( is_string( $value ) && base64_encode( base64_decode( $value, true ) ) === $value ) {45 return base64_decode( $value );46 }47 48 return $value;49 31 } 50 32 -
host-webfonts-local/tags/6.3.12/src/Frontend/Process.php
r3707539 r3721511 629 629 * just fine. Using a negated character class (instead of adding the /s modifier) makes 630 630 * sure the match can never run past a quote character. 631 */ 632 preg_match( '/href=([\'"])(?P<href>[^\'"]*)\1/', $link, $href ); 631 * @since v6.3.12 Only match the href attribute when it starts a new attribute (after whitespace or the 632 * tag opener), so an attribute whose name ends in "href" (e.g. data-href, x:href, 633 * x.href) isn't captured as the href. 634 */ 635 preg_match( '/(?:^|[\s<])href=([\'"])(?P<href>[^\'"]*)\1/', $link, $href ); 633 636 634 637 /** … … 734 737 735 738 /** 739 * @since v6.3.12 Only process (and request) stylesheets whose URL is actually hosted on the Google 740 * Fonts API (or a compatible endpoint). The element was kept because one of its 741 * attribute values points at the API (see get_element_urls()), but the href used 742 * here could point at a different — e.g. internal — host. Checking here, before the 743 * branches below, leaves a non-API link untouched (not removed, not swapped for a 744 * cached file) and makes sure it's never requested, which prevents SSRF. 745 */ 746 if ( ! $this->is_font_api_url( $url ) ) { 747 continue; 748 } 749 750 /** 736 751 * If the stylesheet with $handle is completely marked for unloading, just remove the element 737 752 * to prevent it from loading. … … 795 810 796 811 $search[ $key ] = $stack['href']; 797 $replace[ $key ] = $cached_url ? $cached_url . '?ver=' . $this->timestamp : ''; 812 /** 813 * @since v6.3.12 If optimization produced no URL (e.g. the request was blocked or redirected, the 814 * fetch failed, or the response wasn't a stylesheet), leave the original link 815 * untouched instead of removing it, so the fonts keep loading. 816 */ 817 $replace[ $key ] = $cached_url ? $cached_url . '?ver=' . $this->timestamp : $stack['href']; 798 818 } 799 819 -
host-webfonts-local/tags/6.3.12/src/Helper.php
r3707539 r3721511 133 133 134 134 /** 135 * Unserializes $value if it's serialized, like maybe_unserialize(), but only allows stdClass objects, because 136 * OMGF never stores any other objects. 137 * 138 * @since v6.3.12 139 * 140 * @param mixed $value 141 * 142 * @return mixed 143 */ 144 public static function maybe_unserialize( $value ) { 145 if ( ! is_string( $value ) || ! is_serialized( $value ) ) { 146 return $value; 147 } 148 149 return @unserialize( trim( $value ), [ 'allowed_classes' => [ 'stdClass' ] ] ); // phpcs:ignore 150 } 151 152 /** 135 153 * Method to retrieve OMGF's settings from database. 136 154 * WARNING: DO NOT ATTEMPT TO RETRIEVE WP CORE SETTINGS USING THIS METHOD. IT WILL FAIL. … … 151 169 // get_option() should take care of this, but sometimes it doesn't. 152 170 if ( is_string( $value ) ) { 153 $value = maybe_unserialize( $value );171 $value = self::maybe_unserialize( $value ); 154 172 } 155 173 … … 292 310 } 293 311 312 /** 313 * @since v6.3.12 A font family is used to build the filename its files are stored under, so reject any 314 * path separator to make sure a crafted name can't traverse out of the fonts directory. 315 * Dots are left alone: a font family can legitimately contain them, and without a 316 * separator they can't traverse (the download filename is sanitized regardless). 317 */ 318 if ( preg_match( '#[/\\\\]#', $family ) ) { 319 return false; // @codeCoverageIgnore 320 } 321 294 322 // A CSS custom property, e.g. --wp--preset--font-family--foo. 295 323 if ( str_starts_with( $family, '--' ) ) { … … 534 562 */ 535 563 if ( is_string( self::$admin_optimized_fonts ) && self::$admin_optimized_fonts !== '' ) { 536 self::$admin_optimized_fonts = maybe_unserialize( self::$admin_optimized_fonts ); // @codeCoverageIgnore564 self::$admin_optimized_fonts = self::maybe_unserialize( self::$admin_optimized_fonts ); // @codeCoverageIgnore 537 565 } 538 566 … … 698 726 */ 699 727 if ( is_string( self::$optimized_fonts ) && self::$optimized_fonts !== '' ) { 700 self::$optimized_fonts = maybe_unserialize( self::$optimized_fonts ); // @codeCoverageIgnore728 self::$optimized_fonts = self::maybe_unserialize( self::$optimized_fonts ); // @codeCoverageIgnore 701 729 } 702 730 -
host-webfonts-local/tags/6.3.12/src/Optimize.php
r3707539 r3721511 298 298 /** @codeCoverageIgnoreEnd */ 299 299 300 $response = wp_remote_get( 300 /** 301 * @since v6.3.12 Use wp_safe_remote_get() so internal/private hosts are rejected even if the host 302 * allow-list is ever bypassed. Belt-and-braces against SSRF. 303 */ 304 $response = wp_safe_remote_get( 301 305 $url, 302 306 [ 307 /** 308 * @since v6.3.12 Never follow redirects: the Google Fonts API (and compatible CDNs) serve the 309 * stylesheet directly, so a redirect would only point the request somewhere else. 310 */ 311 'redirection' => 0, 303 312 /** 304 313 * Allow WP devs to use a different User-Agent, e.g. for compatibility with older browsers/OSes. -
host-webfonts-local/trunk/assets/css/omgf-admin.css
r3489128 r3721511 563 563 width: 96px; 564 564 } 565 566 /* Font files which couldn't be downloaded correctly. */ 567 .omgf form .omgf-task-manager #omgf-download-failures-notice ul { 568 margin-left: 0; 569 } 570 571 .omgf form .omgf-task-manager #omgf-download-failures-notice ul li { 572 text-indent: 0; 573 margin-bottom: 0.5em; 574 } -
host-webfonts-local/trunk/assets/css/omgf-admin.min.css
r3489128 r3721511 1 @import url(omgf-admin-google-fonts.min.css);#wpwrap{background-color:rgb(248 250 252 / 1)}.omgf{font-family:"Public Sans",Arial,sans-serif;max-width:1350px}.omgf h1 .pro{background-color:#00adda;padding:0 5px 0 6px;border-radius:5px;text-transform:uppercase;color:#fff}.omgf h1{font-family:Poppins,Verdana,sans-serif;font-weight:800}.omgf h2,.omgf h3,.omgf h4,.omgf h5,.omgf h6{font-family:Poppins,Verdana,sans-serif;font-weight:500}.omgf .button{font-family:Poppins,Verdana,sans-serif;border-radius:10px;font-weight:500}.omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;white-space:nowrap}.omgf .button-cancel.omgf-refresh{color:#ff851b}.omgf .button-cancel.omgf-empty,.omgf .button-cancel.omgf-refresh{padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf .button-cancel:hover#omgf-refresh{color:#fff;background:#ff851b;border-color:#ff851b}.omgf #submit{background:#00adda;border:0;padding:7px 20px}.omgf #submit:hover{background-color:#09c}.omgf h2.omgf-nav{border-bottom:0;padding-bottom:3px}.omgf h2.omgf-nav a{border:0;background-color:transparent;font-weight:600}.omgf h2.omgf-nav .nav-tab{color:#000}.omgf h2.omgf-nav .nav-tab:last-child{float:right}.omgf h2.omgf-nav .nav-tab-active,.omgf h2.omgf-nav .nav-tab:hover{color:#00adda}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-task-manager{padding:5px 25px;margin-bottom:30px;box-shadow:0 10px 20px 1px #ccc;border:0;border-top:4px solid #00adda;border-radius:10px}.omgf form .omgf-task-manager .form-table{margin-bottom:1em}.omgf form .omgf-task-manager th.omgf-align-row-header{padding:.5em 0}.omgf form .omgf-task-manager .task-manager-row{padding:0;line-height:1.33}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:18px 12px;border:1px solid #ececec;border-left:4px solid #ececec;border-radius:3px;margin-bottom:1em}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:10px 18px 2px}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item{display:grid;grid-template-columns:1.5rem 9rem auto}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item .omgf-cache-legend-item-title{font-weight:700}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice ol{margin-left:1.5em;margin-bottom:0;overflow-wrap:anywhere}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.warning,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{border:1px solid #ffdc00;border-left:4px solid #ffdc00;background-color:#fffbdf}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.success{border:1px solid #2ecc40;border-left:4px solid #2ecc40;background-color:#ddf7e0}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.alert{border:1px solid #ff4136;border-left:4px solid #ff4136;background-color:#ff41362B}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice h4{margin-top:0}.omgf form .omgf-task-manager ul{margin-top:5px;list-style:none;margin-left:.5em;padding-left:0}.omgf form .omgf-task-manager ul li{padding-left:0;text-indent:-.5em;line-height:1.5em}.omgf form .omgf-task-manager ul li:before{font-family:dashicons,sans-serif;font-size:16px;vertical-align:-3px}.omgf form .omgf-task-manager ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-task-manager ul li.found:before{content:"\f15e";color:#2ecc40}.omgf form .omgf-task-manager ul li.not-found:before{content:"\f223";color:#00adda}.omgf form .omgf-task-manager ul li.stale-cache-notice:before{content:"\f348";color:#00adda}.omgf form .omgf-task-manager ul li.unloaded:before{content:"\f460";color:#0074d9}.omgf form .advanced-processing-notice,.omgf form .used-subsets-notice{display:block;padding:18px 12px;margin-bottom:.5em;border:1px solid #ececec;border-left:4px solid #ececec}.omgf form .advanced-processing-notice.info,.omgf form .used-subsets-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf-optimize-fonts-container{padding:5px 25px 50px;margin:2.5em auto 2em;overflow:visible;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}.omgf-optimize-fonts-container .form-table tr{position:relative}.omgf-optimize-fonts-container .form-table tr td{padding:20px 0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{margin-top:1.5em;text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning{position:fixed;top:50%;left:33%;width:33%;padding:20px 40px;background-color:#fff5b5;border:2px solid #ffdc00;border-radius:4px;box-shadow:1px 1px 333px #333;z-index:1000}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning .omgf-optimize-preload-warning-close{float:right;font-size:2em;line-height:.45;cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%;padding:4px 0 9px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border-top:4px solid #00adda}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{font-family:Poppins,sans-serif;font-weight:600;padding:9px 0 6px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action:hover{cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{margin:0 0 30px}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip ul li{line-height:1.5em}.omgf-help-section .about,.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul,.omgf-task-manager p{text-align:justify;font-size:14px}.tooltip{position:relative;font-size:16px;line-height:16px;height:12px}.tooltip.omgf-save-optimize{vertical-align:middle}.tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:"Public Sans",Arial,sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:20px;margin-left:-125px;border-radius:10px}.tooltip .tooltip-text a{color:#fff}.tooltip .tooltip-text .illustration{margin-top:10px}.tooltip:hover .tooltip-text{visibility:visible}.omgf-warning{color:red;font-weight:600}#omgf-advanced-settings-form{background-color:#fff;border-radius:10px;padding:0 20px 20px;border-top:4px solid #00adda;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox{padding:5px 25px 10px;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:0}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}#omgf-help-form .postbox .column-container .column.last .signature .signature-image{width:185px}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#wpfooter{font-family:"Public Sans",Arial,sans-serif}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px} 1 @import url(omgf-admin-google-fonts.min.css);#wpwrap{background-color:rgb(248 250 252 / 1)}.omgf{font-family:"Public Sans",Arial,sans-serif;max-width:1350px}.omgf h1 .pro{background-color:#00adda;padding:0 5px 0 6px;border-radius:5px;text-transform:uppercase;color:#fff}.omgf h1{font-family:Poppins,Verdana,sans-serif;font-weight:800}.omgf h2,.omgf h3,.omgf h4,.omgf h5,.omgf h6{font-family:Poppins,Verdana,sans-serif;font-weight:500}.omgf .button{font-family:Poppins,Verdana,sans-serif;border-radius:10px;font-weight:500}.omgf .button-cancel{color:#a00;text-decoration:none;border-color:transparent;box-shadow:none;background:0 0;white-space:nowrap}.omgf .button-cancel.omgf-refresh{color:#ff851b}.omgf .button-cancel.omgf-empty,.omgf .button-cancel.omgf-refresh{padding:1px 10px!important}.omgf .button-cancel:hover{cursor:pointer;background:#d54e21;color:#fff;border-color:#d54e21}.omgf .button-cancel:hover#omgf-refresh{color:#fff;background:#ff851b;border-color:#ff851b}.omgf #submit{background:#00adda;border:0;padding:7px 20px}.omgf #submit:hover{background-color:#09c}.omgf h2.omgf-nav{border-bottom:0;padding-bottom:3px}.omgf h2.omgf-nav a{border:0;background-color:transparent;font-weight:600}.omgf h2.omgf-nav .nav-tab{color:#000}.omgf h2.omgf-nav .nav-tab:last-child{float:right}.omgf h2.omgf-nav .nav-tab-active,.omgf h2.omgf-nav .nav-tab:hover{color:#00adda}.omgf-nav .dashicons-before:before{margin-right:.25em;line-height:1.15em}.omgf form{max-width:1350px}.omgf form .dashicons{line-height:15px}.omgf form .omgf-task-manager{padding:5px 25px;margin-bottom:30px;box-shadow:0 10px 20px 1px #ccc;border:0;border-top:4px solid #00adda;border-radius:10px}.omgf form .omgf-task-manager .form-table{margin-bottom:1em}.omgf form .omgf-task-manager th.omgf-align-row-header{padding:.5em 0}.omgf form .omgf-task-manager .task-manager-row{padding:0;line-height:1.33}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:18px 12px;border:1px solid #ececec;border-left:4px solid #ececec;border-radius:3px;margin-bottom:1em}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{padding:10px 18px 2px}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item{display:grid;grid-template-columns:1.5rem 9rem auto}.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend .omgf-cache-legend-item .omgf-cache-legend-item-title{font-weight:700}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice ol{margin-left:1.5em;margin-bottom:0;overflow-wrap:anywhere}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.warning,.omgf form .omgf-task-manager .task-manager-row.omgf-cache-legend{border:1px solid #ffdc00;border-left:4px solid #ffdc00;background-color:#fffbdf}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.success{border:1px solid #2ecc40;border-left:4px solid #2ecc40;background-color:#ddf7e0}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice.alert{border:1px solid #ff4136;border-left:4px solid #ff4136;background-color:#ff41362B}.omgf form .omgf-task-manager .task-manager-row .task-manager-notice h4{margin-top:0}.omgf form .omgf-task-manager ul{margin-top:5px;list-style:none;margin-left:.5em;padding-left:0}.omgf form .omgf-task-manager ul li{padding-left:0;text-indent:-.5em;line-height:1.5em}.omgf form .omgf-task-manager ul li:before{font-family:dashicons,sans-serif;font-size:16px;vertical-align:-3px}.omgf form .omgf-task-manager ul li.stale:before{content:"\f534";color:#ff851b}.omgf form .omgf-task-manager ul li.found:before{content:"\f15e";color:#2ecc40}.omgf form .omgf-task-manager ul li.not-found:before{content:"\f223";color:#00adda}.omgf form .omgf-task-manager ul li.stale-cache-notice:before{content:"\f348";color:#00adda}.omgf form .omgf-task-manager ul li.unloaded:before{content:"\f460";color:#0074d9}.omgf form .advanced-processing-notice,.omgf form .used-subsets-notice{display:block;padding:18px 12px;margin-bottom:.5em;border:1px solid #ececec;border-left:4px solid #ececec}.omgf form .advanced-processing-notice.info,.omgf form .used-subsets-notice.info{border:1px solid #00adda;border-left:4px solid #00adda;background-color:#e0edf3}.omgf-optimize-fonts-container{padding:5px 25px 50px;margin:2.5em auto 2em;overflow:visible;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}.omgf-optimize-fonts-container .form-table tr{position:relative}.omgf-optimize-fonts-container .form-table tr td{padding:20px 0}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage{margin-top:1.5em;text-align:left}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning{position:fixed;top:50%;left:33%;width:33%;padding:20px 40px;background-color:#fff5b5;border:2px solid #ffdc00;border-radius:4px;box-shadow:1px 1px 333px #333;z-index:1000}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage #omgf-optimize-preload-warning .omgf-optimize-preload-warning-close{float:right;font-size:2em;line-height:.45;cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table{width:100%;border-collapse:collapse}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table thead th{width:13%;padding:4px 0 9px}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody{border-top:4px solid #00adda}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody th{font-family:Poppins,sans-serif;font-weight:600;padding:9px 0 6px;width:40%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td{padding-bottom:5px;width:13%}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action{font-size:.9em}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .unload-mass-action:hover{cursor:pointer}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody td .family{font-weight:600}.omgf-optimize-fonts-container .omgf-optimize-fonts-manage table tbody tr:last-child td{padding-bottom:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{margin-right:10px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros{text-align:left;width:48%;display:inline-block;vertical-align:top}.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-cons span:before,.omgf-optimize-fonts-container .omgf-optimize-fonts-description .omgf-optimize-fonts-pros span:before{vertical-align:-4px}.omgf-optimize-fonts-container .omgf-optimize-fonts-description label{font-size:18px;font-weight:700}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip{margin:0 0 30px}.omgf-optimize-fonts-container .omgf-optimize-fonts-tooltip ul li{line-height:1.5em}.omgf-help-section .about,.omgf-optimize-fonts-container p,.omgf-optimize-fonts-container ul,.omgf-task-manager p{text-align:justify;font-size:14px}.tooltip{position:relative;font-size:16px;line-height:16px;height:12px}.tooltip.omgf-save-optimize{vertical-align:middle}.tooltip .tooltip-text{visibility:hidden;position:absolute;top:100%;left:100%;z-index:10000;background-color:rgba(0,0,0,.75);font-family:"Public Sans",Arial,sans-serif;font-size:.8em;color:#fff;line-height:1.5;width:250px;padding:20px;margin-left:-125px;border-radius:10px}.tooltip .tooltip-text a{color:#fff}.tooltip .tooltip-text .illustration{margin-top:10px}.tooltip:hover .tooltip-text{visibility:visible}.omgf-warning{color:red;font-weight:600}#omgf-advanced-settings-form{background-color:#fff;border-radius:10px;padding:0 20px 20px;border-top:4px solid #00adda;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox{padding:5px 25px 10px;border:0;border-top:4px solid #00adda;border-radius:10px;box-shadow:0 10px 20px 1px #ccc}#omgf-help-form .postbox .column-container{display:flex;flex-flow:row wrap;justify-content:space-between}#omgf-help-form .postbox .column-container .column ul li{margin-bottom:10px}#omgf-help-form .postbox .column-container .column ul li:last-child{margin-bottom:0}#omgf-help-form .postbox .column-container .column ul li a{text-decoration:none;line-height:1.45}#omgf-help-form .postbox .column-container .column ul li a i.dashicons{margin-right:5px;color:#646970}#omgf-help-form .postbox .column-container .column.last{margin-right:45px}#omgf-help-form .postbox .column-container .column.last .signature{text-align:center}#omgf-help-form .postbox .column-container .column.last .signature .dashicons-heart{color:#ff4136}#omgf-help-form .postbox .column-container .column.last .signature .signature-image{width:185px}@media only screen and (max-width:782px){.omgf-optimize-fonts-container{margin:20px 0}.omgf-optimize-fonts-container .option-title{position:relative;left:initial;top:initial}}.omgf-loading{position:fixed;background-color:rgba(255,255,255,.6);width:100%;height:100%;top:0;text-align:center}.omgf-loading .spinner{top:50%;left:50%;position:absolute;-ms-transform:translateX(-50%);transform:translateX(-50%)}#wpfooter{font-family:"Public Sans",Arial,sans-serif}#footer-thankyou a{vertical-align:-.65em}#footer-thankyou .dashicons.ffwp-heart{vertical-align:middle}#footer-thankyou .dashicons.ffwp-heart:before{color:#ff4136}#footer-thankyou .signature-image{width:96px}.omgf form .omgf-task-manager #omgf-download-failures-notice ul{margin-left:0}.omgf form .omgf-task-manager #omgf-download-failures-notice ul li{text-indent:0;margin-bottom:.5em} -
host-webfonts-local/trunk/assets/css/omgf-frontend.css
r3489128 r3721511 132 132 color: white !important; 133 133 } 134 135 #wp-admin-bar-omgf .alert { 136 background-color: #FF4136 !important; 137 } 138 139 #wp-admin-bar-omgf .alert .ab-item { 140 color: white !important; 141 } -
host-webfonts-local/trunk/assets/css/omgf-frontend.min.css
r3489128 r3721511 1 #wp-admin-bar-omgf.dot>.ab-item:after{content:"";width:10px;height:10px;margin-left:5px;border-radius:50%;background-color:grey;display:inline-block;-webkit-animation:2.5s infinite waiting;-moz-animation:2.5s infinite waiting;-o-animation:2.5s infinite waiting;animation:2.5s infinite waiting}@keyframes waiting{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:grey}}#wp-admin-bar-omgf-info>.ab-item{color:#fff!important}#wp-admin-bar-omgf.dot.success>.ab-item:after{background-color:#2ecc40;animation:none}#wp-admin-bar-omgf.dot.alert>.ab-item:after{background-color:#ff4136;-webkit-animation:2.5s blinking-alert;-moz-animation:2.5s blinking-alert;-o-animation:2.5s blinking-alert;animation:2.5s blinking-alert}@keyframes blinking-alert{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff4136}}#wp-admin-bar-omgf.dot.warning>.ab-item:after{background-color:#ff851b;-webkit-animation:2.5s blinking-warning;-moz-animation:2.5s blinking-warning;-o-animation:2.5s blinking-warning;animation:2.5s blinking-warning}@keyframes blinking-warning{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff851b}}#wp-admin-bar-omgf.dot.notice>.ab-item:after{background-color:#ffdc00;-webkit-animation:2.5s blinking-notice;-moz-animation:2.5s blinking-notice;-o-animation:2.5s blinking-notice;animation:2.5s blinking-notice}@keyframes blinking-notice{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ffdc00}}#wp-admin-bar-omgf.dot.info>.ab-item:after{background-color:#0074d9;-webkit-animation:2.5s blinking-info;-moz-animation:2.5s blinking-info;-o-animation:2.5s blinking-info;animation:2.5s blinking-info}@keyframes blinking-info{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#0074d9}}#wp-admin-bar-omgf.alert #wp-admin-bar-omgf-info{background-color:#ff4136!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info{background-color:#ffdc00!important}#wp-admin-bar-omgf.info #wp-admin-bar-omgf-first-run,#wp-admin-bar-omgf.info #wp-admin-bar-omgf-info{background-color:#0074d9!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info .ab-item{color:#000!important}#wp-admin-bar-omgf .info{background-color:#0074d9!important}#wp-admin-bar-omgf .info .ab-item{color:#fff!important} 1 #wp-admin-bar-omgf.dot>.ab-item:after{content:"";width:10px;height:10px;margin-left:5px;border-radius:50%;background-color:grey;display:inline-block;-webkit-animation:2.5s infinite waiting;-moz-animation:2.5s infinite waiting;-o-animation:2.5s infinite waiting;animation:2.5s infinite waiting}@keyframes waiting{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:grey}}#wp-admin-bar-omgf-info>.ab-item{color:#fff!important}#wp-admin-bar-omgf.dot.success>.ab-item:after{background-color:#2ecc40;animation:none}#wp-admin-bar-omgf.dot.alert>.ab-item:after{background-color:#ff4136;-webkit-animation:2.5s blinking-alert;-moz-animation:2.5s blinking-alert;-o-animation:2.5s blinking-alert;animation:2.5s blinking-alert}@keyframes blinking-alert{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff4136}}#wp-admin-bar-omgf.dot.warning>.ab-item:after{background-color:#ff851b;-webkit-animation:2.5s blinking-warning;-moz-animation:2.5s blinking-warning;-o-animation:2.5s blinking-warning;animation:2.5s blinking-warning}@keyframes blinking-warning{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ff851b}}#wp-admin-bar-omgf.dot.notice>.ab-item:after{background-color:#ffdc00;-webkit-animation:2.5s blinking-notice;-moz-animation:2.5s blinking-notice;-o-animation:2.5s blinking-notice;animation:2.5s blinking-notice}@keyframes blinking-notice{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#ffdc00}}#wp-admin-bar-omgf.dot.info>.ab-item:after{background-color:#0074d9;-webkit-animation:2.5s blinking-info;-moz-animation:2.5s blinking-info;-o-animation:2.5s blinking-info;animation:2.5s blinking-info}@keyframes blinking-info{12.5%,37.5%,67.5%,87.5%{background-color:transparent}0%,100%,25%,50%,75%{background-color:#0074d9}}#wp-admin-bar-omgf.alert #wp-admin-bar-omgf-info{background-color:#ff4136!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info{background-color:#ffdc00!important}#wp-admin-bar-omgf.info #wp-admin-bar-omgf-first-run,#wp-admin-bar-omgf.info #wp-admin-bar-omgf-info{background-color:#0074d9!important}#wp-admin-bar-omgf.notice #wp-admin-bar-omgf-info .ab-item{color:#000!important}#wp-admin-bar-omgf .info{background-color:#0074d9!important}#wp-admin-bar-omgf .info .ab-item{color:#fff!important}#wp-admin-bar-omgf .alert{background-color:#ff4136!important}#wp-admin-bar-omgf .alert .ab-item{color:#fff!important} -
host-webfonts-local/trunk/assets/js/omgf-admin.js
r3503345 r3721511 54 54 $('.omgf-optimize-forbidden').on('click', this.wait_for_page_reload); 55 55 $(document).on('click', '#omgf-dismiss-performance-checker-notice', this.dismiss_performance_checker_notice); 56 $(document).on('click', '#omgf-dismiss-download-failures', this.dismiss_download_failures); 56 57 // Ticker 57 58 setInterval(this.loop_ticker_items, 4000); … … 480 481 481 482 /** 483 * Dismiss the font files which couldn't be downloaded correctly. 484 */ 485 dismiss_download_failures: function (e) { 486 e.preventDefault(); 487 488 $.ajax({ 489 type: 'POST', 490 url: omgf_admin_i18n.rest_url + '/dashboard/dismiss-download-failures', 491 beforeSend: function (xhr) { 492 xhr.setRequestHeader('X-WP-Nonce', omgf_admin_i18n.nonce); 493 omgf_admin.show_loader(); 494 }, 495 complete: function (result) { 496 if (result.responseJSON !== undefined && result.responseJSON.success) { 497 $('#omgf-download-failures-notice').fadeOut(300, function () { 498 $(this).remove(); 499 }); 500 } 501 502 omgf_admin.hide_loader(); 503 } 504 }); 505 }, 506 507 /** 482 508 * 483 509 */ -
host-webfonts-local/trunk/assets/js/omgf-admin.min.js
r3503345 r3721511 1 jQuery(document).ready(function(d){var r={ticker_items:document.querySelectorAll(".ticker-item"),ticker_index:0,empty_cache_directory_xhr:!1,optimize_xhr:!1,cache_prefix:"-mod-",flush_action_init:d(".omgf-empty").data("init"),empty_action_nonce:d(".omgf-empty").data("nonce"),delete_log_xhr:!1,delete_action_nonce:d("#omgf-delete-log").data("nonce"),init:function(){d(".omgf-subsets").on("change",this.maybe_select_latin),d(".omgf-optimize-fonts-manage .unload").on("change",this.maybe_unload_stylesheets),d(".omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select").on("change",this.generate_cache_key),d(".omgf-optimize-fonts-manage .unload").on("change",this.toggle_preload),d(".omgf-optimize-fonts-manage .preload").on("change",this.toggle_unload),d(".omgf-optimize-fonts-manage .preload").on("change",this.maybe_show_preload_warning),d(".omgf-optimize-fonts-manage .unload-italics").on("click",this.unload_italics),d(".omgf-optimize-fonts-manage .unload-all").on("click",this.unload_all),d(".omgf-optimize-fonts-manage .load-all").on("click",this.load_all),d("#omgf-save-optimize, #omgf-optimize-again").on("click",function(){d("#omgf-optimize-settings-form #submit").click()}),d(document).on("click","a[id^=omgf-hide-notice-]",this.hide_notice),d(".omgf-remove-stylesheet").on("click",this.remove_stylesheet_from_db),d(".omgf-refresh, #omgf-cache-refresh").on("click",this.refresh_cache),d(".omgf-empty, #omgf-cache-flush").on("click",this.empty_cache_directory),d("#omgf-optimize-settings-form").on("submit",this.show_loader_before_submit),d("#omgf-delete-log").on("click",this.delete_log),d(".omgf-optimize-preload-warning-close").on("click",this.hide_preload_warning),d(".omgf-optimize-forbidden").on("click",this.wait_for_page_reload),d(document).on("click","#omgf-dismiss-performance-checker-notice",this.dismiss_performance_checker_notice),setInterval(this.loop_ticker_items,4e3)},maybe_select_latin:function(e){let o=this.value,t=e.target,n=t.className,a=["latin","latin-ext"];"latin-ext"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0}),a=["latin","vietnamese"],"vietnamese"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0})},loop_ticker_items:function(){r.ticker_items.forEach(function(e,o){o==r.ticker_index?d(e).fadeIn(500):d(e).hide(0)}),r.ticker_index++,r.ticker_index===r.ticker_items.length&&(r.ticker_index=0)},hide_notice:function(){var e=d(this).data("warning-id"),o=d(this).data("nonce");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_hide_notice",warning_id:e,nonce:o},beforeSend:function(){r.show_loader()},complete:function(e){void 0!==e.responseJSON&&void 0!==e.responseJSON.data&&d("#task-manager-notice-row").replaceWith(e.responseJSON.data),r.hide_loader()}})},remove_stylesheet_from_db:function(){var e=d(this).data("handle");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_remove_stylesheet_from_db",handle:e,nonce:r.empty_action_nonce},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},refresh_cache:function(){d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_refresh_cache",nonce:r.empty_action_nonce},beforeSend:function(){d(".omgf-optimize-fonts-manage table tbody").each(function(e,o){r.generate_cache_key(o)})},complete:function(){d("#submit").click()}})},maybe_unload_stylesheets:function(){var e=d(this).closest("tbody")[0].id;d("tbody#"+e+" input.unload:checked").length===d("tbody#"+e+" input.unload").length?r.unload_stylesheet(e):r.load_stylesheet(e)},unload_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");-1===t.indexOf(e)&&t.push(e),t.join(),o.val(t)},load_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");~(position=t.indexOf(e))&&t.splice(position,1),o.val(t)},generate_cache_key:function(e=null){t=void 0===e.target?d(e).attr("id"):d(this).data("handle");var t,o,e=d("#cache_keys"),n=e.val().split(","),a=d("#"+t+" input.unload:checked").length,i=d("#"+t+" input.unload").length,c=n.findIndex((e,o)=>{if(-1!==e.indexOf(t))return!0}),l=!1;"SELECT"===this.nodeName||0!==a&&a!==i||(n[c]=t,l=!0),!0!==l&&-1!==c&&(a=n[c],i=r.cache_prefix+Math.random().toString(36).substring(2,7),-1!==a.indexOf(r.cache_prefix)&&((l=a.split(r.cache_prefix))[o=r.get_last_element_index(l)]=Math.random().toString(36).substring(2,7),a=l[0],i=r.cache_prefix+l[o]),n[c]=a+i),e.val(n.join())},toggle_preload:function(){r.toggle(this,"preload")},toggle_unload:function(){r.toggle(this,"unload")},maybe_show_preload_warning:function(){5===d("."+this.className+":checked").length&&d("#omgf-optimize-preload-warning").fadeIn("300")},hide_preload_warning:function(){d("#omgf-optimize-preload-warning").fadeOut("100")},wait_for_page_reload:function(e){e.preventDefault(),r.show_loader();var o=window.setInterval(function(){document.hasFocus()&&(window.location.reload(),window.clearInterval(o))},500);window.open(this.href,"_blank")},unload_italics:function(e){e.preventDefault();var t=d(this).parents(".font-family").data("id");d(".unload").each(function(e,o){o.value.includes("italic")&&o.dataset.fontId===t&&!1===o.checked&&o.click()})},unload_all:function(e,o=this){o=d(o).parents(".font-family").data("id");d('input.unload[data-font-id="'+o+'"]').each(function(e,o){!1===o.checked&&o.click()})},load_all:function(){var e=d(this).parents(".font-family").data("id");d('input.unload[data-font-id="'+e+'"]').each(function(e,o){!0===o.checked&&o.click()})},toggle:function(e,o){var t=d(e),t=d("."+o+"-"+t.data("font-id")+"-"+t.val()+" ."+o);e.checked?t.attr("disabled",!0):t.attr("disabled",!1)},get_last_element_index:function(e){return e.length-1},empty_cache_directory:function(){r.empty_cache_directory_xhr&&r.empty_cache_directory_xhr.abort(),r.empty_cache_directory_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_empty_dir",nonce:r.empty_action_nonce,init:r.flush_action_init},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},delete_log:function(){r.delete_log_xhr&&r.delete_log_xhr.abort(),r.delete_log_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_delete_log",nonce:r.delete_action_nonce},beforeSend:function(){r.show_loader()},complete:function(){location.reload()}})},show_loader_before_submit:function(){r.show_loader()},hide_loader:function(){d(".omgf-loading").fadeOut(300,function(){d(".omgf-loading").remove()})},dismiss_performance_checker_notice:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-notice",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),r.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-performance-checker-notice").fadeOut(300,function(){d(this).remove()}),r.hide_loader()}})},show_loader:function(){d("#wpwrap").append('<div class="omgf-loading"><span class="spinner is-active"></span></div>')}};omgf_show_loader=r.show_loader,omgf_hide_loader=r.hide_loader,omgf_unload_all=r.unload_all,omgf_load_all=r.load_all,omgf_unload_stylesheet=r.unload_stylesheet,omgf_load_stylesheet=r.load_stylesheet,r.init()});1 jQuery(document).ready(function(d){var s={ticker_items:document.querySelectorAll(".ticker-item"),ticker_index:0,empty_cache_directory_xhr:!1,optimize_xhr:!1,cache_prefix:"-mod-",flush_action_init:d(".omgf-empty").data("init"),empty_action_nonce:d(".omgf-empty").data("nonce"),delete_log_xhr:!1,delete_action_nonce:d("#omgf-delete-log").data("nonce"),init:function(){d(".omgf-subsets").on("change",this.maybe_select_latin),d(".omgf-optimize-fonts-manage .unload").on("change",this.maybe_unload_stylesheets),d(".omgf-optimize-fonts-manage .unload, .omgf-optimize-fonts-manage .fallback-font-stack select").on("change",this.generate_cache_key),d(".omgf-optimize-fonts-manage .unload").on("change",this.toggle_preload),d(".omgf-optimize-fonts-manage .preload").on("change",this.toggle_unload),d(".omgf-optimize-fonts-manage .preload").on("change",this.maybe_show_preload_warning),d(".omgf-optimize-fonts-manage .unload-italics").on("click",this.unload_italics),d(".omgf-optimize-fonts-manage .unload-all").on("click",this.unload_all),d(".omgf-optimize-fonts-manage .load-all").on("click",this.load_all),d("#omgf-save-optimize, #omgf-optimize-again").on("click",function(){d("#omgf-optimize-settings-form #submit").click()}),d(document).on("click","a[id^=omgf-hide-notice-]",this.hide_notice),d(".omgf-remove-stylesheet").on("click",this.remove_stylesheet_from_db),d(".omgf-refresh, #omgf-cache-refresh").on("click",this.refresh_cache),d(".omgf-empty, #omgf-cache-flush").on("click",this.empty_cache_directory),d("#omgf-optimize-settings-form").on("submit",this.show_loader_before_submit),d("#omgf-delete-log").on("click",this.delete_log),d(".omgf-optimize-preload-warning-close").on("click",this.hide_preload_warning),d(".omgf-optimize-forbidden").on("click",this.wait_for_page_reload),d(document).on("click","#omgf-dismiss-performance-checker-notice",this.dismiss_performance_checker_notice),d(document).on("click","#omgf-dismiss-download-failures",this.dismiss_download_failures),setInterval(this.loop_ticker_items,4e3)},maybe_select_latin:function(e){let o=this.value,t=e.target,n=t.className,a=["latin","latin-ext"];"latin-ext"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0}),a=["latin","vietnamese"],"vietnamese"===o&&a.forEach(function(e){document.querySelector("."+n+" option[value="+e+"]").selected=!0})},loop_ticker_items:function(){s.ticker_items.forEach(function(e,o){o==s.ticker_index?d(e).fadeIn(500):d(e).hide(0)}),s.ticker_index++,s.ticker_index===s.ticker_items.length&&(s.ticker_index=0)},hide_notice:function(){var e=d(this).data("warning-id"),o=d(this).data("nonce");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_hide_notice",warning_id:e,nonce:o},beforeSend:function(){s.show_loader()},complete:function(e){void 0!==e.responseJSON&&void 0!==e.responseJSON.data&&d("#task-manager-notice-row").replaceWith(e.responseJSON.data),s.hide_loader()}})},remove_stylesheet_from_db:function(){var e=d(this).data("handle");d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_remove_stylesheet_from_db",handle:e,nonce:s.empty_action_nonce},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},refresh_cache:function(){d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_refresh_cache",nonce:s.empty_action_nonce},beforeSend:function(){d(".omgf-optimize-fonts-manage table tbody").each(function(e,o){s.generate_cache_key(o)})},complete:function(){d("#submit").click()}})},maybe_unload_stylesheets:function(){var e=d(this).closest("tbody")[0].id;d("tbody#"+e+" input.unload:checked").length===d("tbody#"+e+" input.unload").length?s.unload_stylesheet(e):s.load_stylesheet(e)},unload_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");-1===t.indexOf(e)&&t.push(e),t.join(),o.val(t)},load_stylesheet:function(e){var o=d("#unload_stylesheets"),t=o.val().split(",");~(position=t.indexOf(e))&&t.splice(position,1),o.val(t)},generate_cache_key:function(e=null){t=void 0===e.target?d(e).attr("id"):d(this).data("handle");var t,o,e=d("#cache_keys"),n=e.val().split(","),a=d("#"+t+" input.unload:checked").length,i=d("#"+t+" input.unload").length,c=n.findIndex((e,o)=>{if(-1!==e.indexOf(t))return!0}),l=!1;"SELECT"===this.nodeName||0!==a&&a!==i||(n[c]=t,l=!0),!0!==l&&-1!==c&&(a=n[c],i=s.cache_prefix+Math.random().toString(36).substring(2,7),-1!==a.indexOf(s.cache_prefix)&&((l=a.split(s.cache_prefix))[o=s.get_last_element_index(l)]=Math.random().toString(36).substring(2,7),a=l[0],i=s.cache_prefix+l[o]),n[c]=a+i),e.val(n.join())},toggle_preload:function(){s.toggle(this,"preload")},toggle_unload:function(){s.toggle(this,"unload")},maybe_show_preload_warning:function(){5===d("."+this.className+":checked").length&&d("#omgf-optimize-preload-warning").fadeIn("300")},hide_preload_warning:function(){d("#omgf-optimize-preload-warning").fadeOut("100")},wait_for_page_reload:function(e){e.preventDefault(),s.show_loader();var o=window.setInterval(function(){document.hasFocus()&&(window.location.reload(),window.clearInterval(o))},500);window.open(this.href,"_blank")},unload_italics:function(e){e.preventDefault();var t=d(this).parents(".font-family").data("id");d(".unload").each(function(e,o){o.value.includes("italic")&&o.dataset.fontId===t&&!1===o.checked&&o.click()})},unload_all:function(e,o=this){o=d(o).parents(".font-family").data("id");d('input.unload[data-font-id="'+o+'"]').each(function(e,o){!1===o.checked&&o.click()})},load_all:function(){var e=d(this).parents(".font-family").data("id");d('input.unload[data-font-id="'+e+'"]').each(function(e,o){!0===o.checked&&o.click()})},toggle:function(e,o){var t=d(e),t=d("."+o+"-"+t.data("font-id")+"-"+t.val()+" ."+o);e.checked?t.attr("disabled",!0):t.attr("disabled",!1)},get_last_element_index:function(e){return e.length-1},empty_cache_directory:function(){s.empty_cache_directory_xhr&&s.empty_cache_directory_xhr.abort(),s.empty_cache_directory_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_empty_dir",nonce:s.empty_action_nonce,init:s.flush_action_init},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},delete_log:function(){s.delete_log_xhr&&s.delete_log_xhr.abort(),s.delete_log_xhr=d.ajax({type:"POST",url:ajaxurl,data:{action:"omgf_delete_log",nonce:s.delete_action_nonce},beforeSend:function(){s.show_loader()},complete:function(){location.reload()}})},show_loader_before_submit:function(){s.show_loader()},hide_loader:function(){d(".omgf-loading").fadeOut(300,function(){d(".omgf-loading").remove()})},dismiss_performance_checker_notice:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-notice",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),s.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-performance-checker-notice").fadeOut(300,function(){d(this).remove()}),s.hide_loader()}})},dismiss_download_failures:function(e){e.preventDefault(),d.ajax({type:"POST",url:omgf_admin_i18n.rest_url+"/dashboard/dismiss-download-failures",beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",omgf_admin_i18n.nonce),s.show_loader()},complete:function(e){void 0!==e.responseJSON&&e.responseJSON.success&&d("#omgf-download-failures-notice").fadeOut(300,function(){d(this).remove()}),s.hide_loader()}})},show_loader:function(){d("#wpwrap").append('<div class="omgf-loading"><span class="spinner is-active"></span></div>')}};omgf_show_loader=s.show_loader,omgf_hide_loader=s.hide_loader,omgf_unload_all=s.unload_all,omgf_load_all=s.load_all,omgf_unload_stylesheet=s.unload_stylesheet,omgf_load_stylesheet=s.load_stylesheet,s.init()}); -
host-webfonts-local/trunk/assets/js/omgf-frontend.js
r3641590 r3721511 87 87 } 88 88 89 if ((status !== 'success' && status !== 'warning')) { 89 // If the alert is only caused by failed downloads, the Google Fonts Checker's alert text doesn't apply. 90 let download_failures_only = status === 'alert' && response.download_failures && !response.google_fonts_checker_alert; 91 92 if (status !== 'success' && status !== 'warning' && !download_failures_only) { 90 93 this.addInfoBox(status); 94 } 95 96 if (response.download_failures) { 97 this.addInfoBox('download_failures', response); 91 98 } 92 99 … … 188 195 189 196 /** 197 * Normalizes a font-weight to the numeric value computed styles use, e.g. 'normal' => '400' and 'bold' => '700'. 198 * Ranges (e.g. '100 900' for variable fonts) are returned as-is. 199 * 200 * @param {string} weight 201 * @returns {string} 202 */ 203 normalizeFontWeight: function (weight) { 204 weight = String(weight || '400').trim().toLowerCase(); 205 206 if (weight === 'normal') { 207 return '400'; 208 } 209 210 if (weight === 'bold') { 211 return '700'; 212 } 213 214 return weight; 215 }, 216 217 /** 218 * Checks if a font face is in a set of face IDs collected from computed styles (which always have a single, 219 * numeric weight). A font face with a weight range (i.e. a variable font) is used if any weight within the range is. 220 * 221 * @param {Set} face_ids 222 * @param {string} family 223 * @param {string} weight Normalized font-weight. 224 * @param {string} style 225 * @returns {boolean} 226 */ 227 isFaceUsed: function (face_ids, family, weight, style) { 228 if (face_ids.has(`${family}-${weight}-${style}`.toLowerCase())) { 229 return true; 230 } 231 232 let range = weight.split(/\s+/).map(Number); 233 234 if (range.length !== 2 || range.some(isNaN)) { 235 return false; 236 } 237 238 for (let face_id of face_ids) { 239 let prefix = `${family}-`.toLowerCase(); 240 let suffix = `-${style}`.toLowerCase(); 241 242 if (!face_id.startsWith(prefix) || !face_id.endsWith(suffix)) { 243 continue; 244 } 245 246 let used_weight = Number(face_id.slice(prefix.length, face_id.length - suffix.length)); 247 248 if (used_weight >= range[0] && used_weight <= range[1]) { 249 return true; 250 } 251 } 252 253 return false; 254 }, 255 256 /** 257 * The rules of cross-origin stylesheets can't be read, unless they were loaded with the crossorigin attribute. Most 258 * font CDNs send CORS headers though, so these stylesheets are fetched again (usually from the browser's cache) 259 * and parsed separately to find their @font-face rules. 260 * 261 * @param {string[]} hrefs 262 * @param {Map} font_face_url_map 263 * @param {Set} loaded_font_urls 264 * @returns {Promise<void>} 265 */ 266 extractCrossOriginFontFaceRules: async function (hrefs, font_face_url_map, loaded_font_urls) { 267 if (typeof CSSStyleSheet === 'undefined' || typeof CSSStyleSheet.prototype.replaceSync !== 'function') { 268 return; 269 } 270 271 // Keep the analysis bounded. 272 const max_sheets = 10; 273 const timeout_ms = 3000; 274 275 let unique_hrefs = [...new Set(hrefs)].slice(0, max_sheets); 276 277 await Promise.all(unique_hrefs.map(async (href) => { 278 let controller = typeof AbortController !== 'undefined' ? new AbortController() : null; 279 let timeout = controller ? setTimeout(() => controller.abort(), timeout_ms) : null; 280 281 try { 282 let response = await fetch(href, { 283 mode: 'cors', 284 credentials: 'omit', 285 signal: controller ? controller.signal : undefined 286 }); 287 288 if (!response.ok) { 289 return; 290 } 291 292 let sheet = new CSSStyleSheet(); 293 294 // @import rules aren't supported (and ignored) in constructed stylesheets. 295 sheet.replaceSync(await response.text()); 296 297 this.extractFontFaceRules(sheet.cssRules, { href: href }, font_face_url_map, loaded_font_urls); 298 } catch (e) { 299 // No CORS headers, a network error or a timeout: nothing we can do. 300 } finally { 301 if (timeout) { 302 clearTimeout(timeout); 303 } 304 } 305 })); 306 }, 307 308 /** 190 309 * Helper to get property value from a CSSRule, with fallback for Firefox. 191 310 * … … 230 349 let rule_style = this.getFontFaceProperty(rule, 'font-style') || 'normal'; 231 350 232 if (rule_weight === 'normal') rule_weight = '400'; 233 if (rule_weight === 'bold') rule_weight = '700'; 351 rule_weight = this.normalizeFontWeight(rule_weight); 234 352 235 353 let src = rule.style.getPropertyValue('src') || rule.style.src; … … 356 474 let font_face_url_map = new Map(); 357 475 476 let cross_origin_sheets = []; 477 358 478 for (let i = 0; i < document.styleSheets.length; i++) { 479 let sheet = document.styleSheets[i]; 480 359 481 try { 360 let sheet = document.styleSheets[i];361 482 let rules = sheet.cssRules || sheet.rules; 362 483 if (!rules) continue; … … 364 485 this.extractFontFaceRules(rules, sheet, font_face_url_map, loaded_font_urls); 365 486 } catch (e) { 366 // Ignore cross-origin stylesheet errors. 367 } 368 } 487 // The rules of cross-origin stylesheets (loaded without the crossorigin attribute) can't be read. 488 if (sheet.href) { 489 cross_origin_sheets.push(sheet.href); 490 } 491 } 492 } 493 494 await this.extractCrossOriginFontFaceRules(cross_origin_sheets, font_face_url_map, loaded_font_urls); 369 495 370 496 document.fonts.forEach((font) => { 371 497 let family = font.family.replace(/["']/g, ''); 372 let weight = font.weight; 498 // Font faces often define keywords (e.g. icon fonts use 'normal'), while computed styles are always numeric. 499 let weight = this.normalizeFontWeight(font.weight); 373 500 let style = font.style; 374 501 let face_id = `${family}-${weight}-${style}`.toLowerCase(); … … 381 508 * Check if any loaded fonts that are used above the fold are not preloaded. 382 509 */ 383 if (font.status === 'loaded' && font_url && used_faces_above_the_fold.has(face_id)) {510 if (font.status === 'loaded' && font_url && this.isFaceUsed(used_faces_above_the_fold, family, weight, style)) { 384 511 let is_preloaded = preloaded_fonts.some((url) => { 385 512 // If we have the actual font URL, use it for exact matching. … … 416 543 * elements that aren't rendered yet (e.g. tabs, accordions and modals) would be unloaded. 417 544 */ 418 if (font.status === 'unloaded' && ! used_faces_not_rendered.has(face_id) && font_url) {545 if (font.status === 'unloaded' && !this.isFaceUsed(used_faces_not_rendered, family, weight, style) && font_url) { 419 546 unused_fonts.push({ 420 547 family: family, … … 711 838 let text = omgf_frontend.sprintf(omgf_frontend_i18n.info_box_preload_text, count || 0, data.potential_delay_ms || 0, data.impact || omgf_frontend_i18n.info_box_impact_low); 712 839 info_box.innerHTML = `<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${text}</a>`; 840 } 841 842 if (status === 'download_failures') { 843 info_box.id = 'wp-admin-bar-omgf-download-failures'; 844 info_box.classList.add('alert'); 845 846 let link = document.createElement('a'); 847 link.className = 'ab-item'; 848 link.href = omgf_frontend_i18n.info_box_admin_url; 849 link.textContent = data.download_failures_text || ''; 850 info_box.appendChild(link); 713 851 } 714 852 -
host-webfonts-local/trunk/assets/js/omgf-frontend.min.js
r3641590 r3721511 1 let omgf_font_cls=0,omgf_fonts_ready=!1,omgf_dom_content_loaded="loading"!==document.readyState,omgf_dom_content_loaded_time=omgf_dom_content_loaded?performance.now():0,omgf_cls_supported=!1;omgf_dom_content_loaded||document.addEventListener("DOMContentLoaded",()=>{omgf_dom_content_loaded=!0,omgf_dom_content_loaded_time=performance.now()});try{let e=new PerformanceObserver(()=>{});e.observe({type:"layout-shift",buffered:!1}),e.disconnect(),omgf_cls_supported=!0}catch(e){}if(omgf_cls_supported&&void 0!==document.fonts&&void 0!==document.fonts.ready)try{let e=new PerformanceObserver(e=>{e.getEntries().forEach(e=>{!e.hadRecentInput&&omgf_dom_content_loaded&&!omgf_fonts_ready&&e.startTime>=omgf_dom_content_loaded_time&&(omgf_font_cls+=e.value)})});e.observe({type:"layout-shift",buffered:!0}),document.fonts.ready.then(()=>{omgf_fonts_ready=!0,e.disconnect()})}catch(e){}window.addEventListener("load",()=>{let _={menu_item:document.getElementById("wp-admin-bar-omgf"),sub_menu:document.getElementById("wp-admin-bar-omgf-default"),skip_results:omgf_frontend_results.skip||!1,init:async function(){let e=[],t=[],n=null;try{var o,a=this.filterGoogleFonts(),i=(o=await this.getStatus(a)).unused_fonts_analysis||{},r=(t=o.unused_fonts||[],o.preload_analysis||{}),s=(e=o.missing_preloads||[],o.cls_analysis||{});if(n=o.status||null,null!==this.menu_item&&(this.menu_item.classList.add("dot"),n)&&this.menu_item.classList.add(n),"success"!==n&&"warning"!==n&&this.addInfoBox(n),!_.skip_results){if(omgf_frontend_i18n.multilang_plugin_used){var l=omgf_frontend_i18n.subsets_count;if(1<l){let e=omgf_frontend_i18n.info_box_impact_low;3===l?e=omgf_frontend_i18n.info_box_impact_medium:3<l&&(e=omgf_frontend_i18n.info_box_impact_high);var f={name:omgf_frontend_i18n.multilang_plugin_name,subsets_count:l,impact:e};this.addInfoBox("multilang_plugin",f)}}i&&i.count&&this.addInfoBox("unload_notice",i),r&&0<r.potential_delay_ms&&0<e.length&&this.addInfoBox("preload_notice",r,e.length),s&&.01<=s.cls&&this.addInfoBox("cls_notice",s)}}catch(e){console.error("OMGF - Error running Google Fonts Checker:",e)}finally{document.dispatchEvent(new CustomEvent("omgf_frontend_loaded",{detail:{missing_preloads:e,unused_fonts:t,status:n}}))}},filterGoogleFonts:()=>{var e=window.performance.getEntries().filter(e=>{var t,n=0<e.name.indexOf("/fonts.googleapis.com/css")||0<e.name.indexOf("/fonts.googleapis.com/icon");let o=0<e.name.indexOf("/fonts.gstatic.com/");return o&&(t=/\.(woff2|woff|ttf|otf)(\?.*)?$/i.test(e.name),e=!e.initiatorType||["css","link","other"].includes(e.initiatorType),o=t&&e),n||o});if(0===e.length)return[];console.log("OMGF has found the following Google Fonts API calls:");let t=[];return e.forEach(e=>{t.push(e.name),console.log(" - "+e.name)}),t},getFontFaceProperty:function(e,t){var n=e.style.getPropertyValue(t);return n?n.replace(/["']/g,"").trim():(n=e.cssText.match(new RegExp(t+"\\s*:\\s*([^;]+)","i")))?n[1].replace(/["']/g,"").trim():null},extractFontFaceRules:function(t,o,a,i){for(let e=0;e<t.length;e++){var r=t[e];if(r.type===CSSRule.IMPORT_RULE&&r.styleSheet&&(s=r.styleSheet.cssRules||r.styleSheet.rules)&&this.extractFontFaceRules(s,r.styleSheet,a,i),"CSSFontFaceRule"===r.constructor.name||r.type===CSSRule.FONT_FACE_RULE){var s=this.getFontFaceProperty(r,"font-family");let e=this.getFontFaceProperty(r,"font-weight")||"400";var l,f=this.getFontFaceProperty(r,"font-style")||"normal";"bold"===(e="normal"===e?"400":e)&&(e="700");let t=r.style.getPropertyValue("src")||r.style.src,n=(t=t||this.getFontFaceProperty(r,"src"))?t.match(/url\(["']?([^"')]+\.woff2[^"')]*?)["']?\)/):null;(n=n||(t?t.match(/url\(["']?([^"')]+)["']?\)/):null))&&(l=new URL(n[1],o.href||document.baseURI).href,r=r.style.getPropertyValue("unicode-range")||"",f=(`${s}-${e}-`+f+(r?"-"+r:"")).toLowerCase(),a.has(f)||a.set(f,l),i.has(l))&&a.set(f,l)}}},getStatus:async function(e){var t=new URLSearchParams(window.location.search),t=Object.fromEntries(t.entries());let d=[],m=[];if(void 0!==document.fonts&&void 0!==document.fonts.ready){await document.fonts.ready;let s=[];document.head.querySelectorAll('link[rel="preload"][as="font"]').forEach(e=>{s.push(e.href)});let l=new Set,f=new Set;var o=document.querySelectorAll("body *:not(#wpadminbar):not(#wpadminbar *)");for(let e=0;e<o.length&&e<1500;e++){let a=o[e];var c=a.getBoundingClientRect(),u=window.getComputedStyle(a),g=u.fontFamily.replace(/["']/g,"");let t=u.fontWeight,n=u.fontStyle,i=c.top<window.innerHeight&&0<c.bottom&&c.left<window.innerWidth&&0<c.right,r=0<c.width||0<c.height;g.split(",").forEach(e=>{e=(`${e=e.trim()}-${t}-`+n).toLowerCase();i&&l.add(e),r||f.add(e)}),["::before","::after"].forEach(e=>{var e=window.getComputedStyle(a,e),t=e.fontFamily.replace(/["']/g,"");let n=e.fontWeight,o=e.fontStyle;t.split(",").forEach(e=>{e=(`${e=e.trim()}-${n}-`+o).toLowerCase();i&&l.add(e),r||f.add(e)})})}var n=new Set(window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff2?|ttf|otf)(\?.*)?$/i)).map(e=>e.name));let _=new Map;for(let e=0;e<document.styleSheets.length;e++)try{var a=document.styleSheets[e],i=a.cssRules||a.rules;i&&this.extractFontFaceRules(i,a,_,n)}catch(e){}document.fonts.forEach(e=>{let n=e.family.replace(/["']/g,"");var t=e.weight,o=e.style,a=(n+`-${t}-`+o).toLowerCase(),i=(a+"-"+(e.unicodeRange||"")).toLowerCase();let r=_.get(i)||_.get(a);"loaded"===e.status&&r&&l.has(a)&&(s.some(e=>{var t;return!(!r||e!==r)||(t=n.toLowerCase().replace(/\s/g,"-"),e=e.toLowerCase(),new RegExp("(^|[/_-])"+t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|$)","i").test(e))})||d.some(e=>e.family===n&&e.url===r)||d.push({family:n,weight:t,style:o,url:r})),"unloaded"===e.status&&!f.has(a)&&r&&m.push({family:n,weight:t,style:o,url:r,unicode_range:e.unicodeRange})})}let r=this.analyzeUnusedFonts(m),s=await this.analyzePreloadImpact(d),l=this.analyzeCLS(omgf_font_cls);var f=new FormData;return f.append("path",document.location.pathname),f.append("urls",JSON.stringify(e)),f.append("params",JSON.stringify(t)),f.append("unused_fonts_analysis",JSON.stringify(r)),f.append("preload_analysis",JSON.stringify(s)),f.append("cls_analysis",JSON.stringify(l)),_.ajax(f).then(e=>(e&&(e.unused_fonts_analysis=r,e.unused_fonts=m,e.preload_analysis=s,e.missing_preloads=d,e.cls_analysis=l),e))},forEachMatchingResources:function(e,n,o){e.forEach(i=>{let t=i.family,r=i.url,s=t.toLowerCase().replace(/\s/g,"-");n.filter(e=>{var t=e.name.toLowerCase();if(r&&e.name===r)return!0;if(!new RegExp("(^|[/_-])"+s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|\\.|$)","i").test(t))return!1;if(void 0===i.weight)return!0;let n=i.weight;var e=i.style,o=("bold"===(n="normal"===n?"400":n)&&(n="700"),new RegExp(`[./_-]${n}([./_-]|\\.|$)`,"i"));let a=!0;return"italic"===e?a=t.includes("italic")||/[._-]i\.(woff|woff2|ttf|otf)/.test(t)||/\d{3}i\.(woff|woff2|ttf|otf)/.test(t):"normal"===e&&(a=!t.includes("italic")),o.test(t)&&a}).forEach(e=>{o(e,t)})})},getFontResources:function(){return window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i))},analyzeUnusedFonts:function(e){if(0===e.length)return{};e=e.length;let t=omgf_frontend_i18n.info_box_impact_low;return 6<e?t=omgf_frontend_i18n.info_box_impact_high:3<=e&&(t=omgf_frontend_i18n.info_box_impact_medium),{count:e,impact:t}},analyzeCLS:function(e){let t=omgf_frontend_i18n.info_box_impact_low;e=Math.round(1e3*e)/1e3;return e<.01?{}:(.1<e&&(t=omgf_frontend_i18n.info_box_impact_medium),{cls:e,impact:t=.25<e?omgf_frontend_i18n.info_box_impact_high:t})},analyzePreloadImpact:async function(n){if(0===n.length)return{};let o={affects_lcp:!1,potential_delay_ms:0,impact:omgf_frontend_i18n.info_box_impact_low};try{var a=await new Promise(t=>{let n=new PerformanceObserver(e=>{e=e.getEntries(),e=e[e.length-1];n.disconnect(),t(e)});n.observe({type:"largest-contentful-paint",buffered:!0}),setTimeout(()=>{n.disconnect(),t(null)},2e3)});if(!a)return o;var i=a.element;let e=!1;if(!(e=i?"string"==typeof i.innerText&&0<i.innerText.trim().length||"string"==typeof i.textContent&&0<i.textContent.trim().length:e))return o;var r=this.getFontResources();let t=0;if(this.forEachMatchingResources(n,r,e=>{e=e.responseEnd-e.startTime;0<e&&(o.affects_lcp=!0,e>t)&&(t=e)}),o.potential_delay_ms=Math.round(t),o.potential_delay_ms<=5)return{};100<o.potential_delay_ms?o.impact=omgf_frontend_i18n.info_box_impact_high:20<o.potential_delay_ms&&(o.impact=omgf_frontend_i18n.info_box_impact_medium)}catch(e){return console.warn("OMGF - Error analyzing preload impact:",e),{}}return o},ajax:function(e){return fetch(omgf_frontend_i18n.api_url,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":omgf_frontend_i18n.nonce},body:e}).then(e=>!!e.ok&&e.json())},addInfoBox:function(e,t,n){var o,a=document.createElement("li");a.id="wp-admin-bar-omgf-info","alert"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_alert_text}</a>`),"notice"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_notice_text}</a>`),"multilang_plugin"===e&&(a.id="wp-admin-bar-omgf-multilang-info",o=_.sprintf(omgf_frontend_i18n.info_box_multilang_plugin_text,omgf_frontend_i18n.multilang_plugin_name,t.subsets_count,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"unload_notice"===e&&(a.id="wp-admin-bar-omgf-unload-info",o=_.sprintf(omgf_frontend_i18n.info_box_unload_text,t.count||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"preload_notice"===e&&(a.id="wp-admin-bar-omgf-preload-info",o=_.sprintf(omgf_frontend_i18n.info_box_preload_text,n||0,t.potential_delay_ms||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"cls_notice"===e&&(a.id="wp-admin-bar-omgf-cls-info",n=_.sprintf(omgf_frontend_i18n.info_box_cls_text,t.cls,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${n}</a>`),"cls_notice"!==e&&"unload_notice"!==e&&"preload_notice"!==e&&"multilang_plugin"!==e||a.classList.add("info"),"info"===e&&omgf_frontend_i18n.first_run&&document.getElementById("wp-admin-bar-omgf-optimize-this")?.classList.add("info"),_.sub_menu&&_.sub_menu.prepend(a)},sprintf:function(e){let a=arguments,i=1;return e.replace(/%(s|d|0\d+d)/g,function(e,t){var n=a[i++];switch(t){case"s":return n;case"d":return parseInt(n,10);default:var n=String(parseInt(n,10)),o=Number(t.slice(1,-1));return"0".repeat(o).slice(n.length)+n}})}},e=window.performance.getEntries(),t=0,n=setInterval(()=>{t++,((e=e.length<window.performance.getEntries().length?window.performance.getEntries():e).length===window.performance.getEntries().length||20<=t)&&(clearInterval(n),_.init())},500)});1 let omgf_font_cls=0,omgf_fonts_ready=!1,omgf_dom_content_loaded="loading"!==document.readyState,omgf_dom_content_loaded_time=omgf_dom_content_loaded?performance.now():0,omgf_cls_supported=!1;omgf_dom_content_loaded||document.addEventListener("DOMContentLoaded",()=>{omgf_dom_content_loaded=!0,omgf_dom_content_loaded_time=performance.now()});try{let e=new PerformanceObserver(()=>{});e.observe({type:"layout-shift",buffered:!1}),e.disconnect(),omgf_cls_supported=!0}catch(e){}if(omgf_cls_supported&&void 0!==document.fonts&&void 0!==document.fonts.ready)try{let e=new PerformanceObserver(e=>{e.getEntries().forEach(e=>{!e.hadRecentInput&&omgf_dom_content_loaded&&!omgf_fonts_ready&&e.startTime>=omgf_dom_content_loaded_time&&(omgf_font_cls+=e.value)})});e.observe({type:"layout-shift",buffered:!0}),document.fonts.ready.then(()=>{omgf_fonts_ready=!0,e.disconnect()})}catch(e){}window.addEventListener("load",()=>{let p={menu_item:document.getElementById("wp-admin-bar-omgf"),sub_menu:document.getElementById("wp-admin-bar-omgf-default"),skip_results:omgf_frontend_results.skip||!1,init:async function(){let e=[],t=[],n=null;try{var o,a=this.filterGoogleFonts(),i=(o=await this.getStatus(a)).unused_fonts_analysis||{},r=(t=o.unused_fonts||[],o.preload_analysis||{}),s=(e=o.missing_preloads||[],o.cls_analysis||{}),l=(n=o.status||null,null!==this.menu_item&&(this.menu_item.classList.add("dot"),n)&&this.menu_item.classList.add(n),"alert"===n&&o.download_failures&&!o.google_fonts_checker_alert);if("success"===n||"warning"===n||l||this.addInfoBox(n),o.download_failures&&this.addInfoBox("download_failures",o),!p.skip_results){if(omgf_frontend_i18n.multilang_plugin_used){var f=omgf_frontend_i18n.subsets_count;if(1<f){let e=omgf_frontend_i18n.info_box_impact_low;3===f?e=omgf_frontend_i18n.info_box_impact_medium:3<f&&(e=omgf_frontend_i18n.info_box_impact_high);var d={name:omgf_frontend_i18n.multilang_plugin_name,subsets_count:f,impact:e};this.addInfoBox("multilang_plugin",d)}}i&&i.count&&this.addInfoBox("unload_notice",i),r&&0<r.potential_delay_ms&&0<e.length&&this.addInfoBox("preload_notice",r,e.length),s&&.01<=s.cls&&this.addInfoBox("cls_notice",s)}}catch(e){console.error("OMGF - Error running Google Fonts Checker:",e)}finally{document.dispatchEvent(new CustomEvent("omgf_frontend_loaded",{detail:{missing_preloads:e,unused_fonts:t,status:n}}))}},filterGoogleFonts:()=>{var e=window.performance.getEntries().filter(e=>{var t,n=0<e.name.indexOf("/fonts.googleapis.com/css")||0<e.name.indexOf("/fonts.googleapis.com/icon");let o=0<e.name.indexOf("/fonts.gstatic.com/");return o&&(t=/\.(woff2|woff|ttf|otf)(\?.*)?$/i.test(e.name),e=!e.initiatorType||["css","link","other"].includes(e.initiatorType),o=t&&e),n||o});if(0===e.length)return[];console.log("OMGF has found the following Google Fonts API calls:");let t=[];return e.forEach(e=>{t.push(e.name),console.log(" - "+e.name)}),t},normalizeFontWeight:function(e){return"normal"===(e=String(e||"400").trim().toLowerCase())?"400":"bold"===e?"700":e},isFaceUsed:function(e,t,n,o){if(e.has((t+`-${n}-`+o).toLowerCase()))return!0;var a=n.split(/\s+/).map(Number);if(2===a.length&&!a.some(isNaN))for(var i of e){var r=(t+"-").toLowerCase(),s=("-"+o).toLowerCase();if(i.startsWith(r)&&i.endsWith(s)){r=Number(i.slice(r.length,i.length-s.length));if(r>=a[0]&&r<=a[1])return!0}}return!1},extractCrossOriginFontFaceRules:async function(e,i,r){if("undefined"!=typeof CSSStyleSheet&&"function"==typeof CSSStyleSheet.prototype.replaceSync){e=[...new Set(e)].slice(0,10);await Promise.all(e.map(async e=>{let t="undefined"!=typeof AbortController?new AbortController:null;var n=t?setTimeout(()=>t.abort(),3e3):null;try{var o,a=await fetch(e,{mode:"cors",credentials:"omit",signal:t?t.signal:void 0});a.ok&&((o=new CSSStyleSheet).replaceSync(await a.text()),this.extractFontFaceRules(o.cssRules,{href:e},i,r))}catch(e){}finally{n&&clearTimeout(n)}}))}},getFontFaceProperty:function(e,t){var n=e.style.getPropertyValue(t);return n?n.replace(/["']/g,"").trim():(n=e.cssText.match(new RegExp(t+"\\s*:\\s*([^;]+)","i")))?n[1].replace(/["']/g,"").trim():null},extractFontFaceRules:function(t,n,o,a){for(let e=0;e<t.length;e++){var i=t[e];if(i.type===CSSRule.IMPORT_RULE&&i.styleSheet&&(s=i.styleSheet.cssRules||i.styleSheet.rules)&&this.extractFontFaceRules(s,i.styleSheet,o,a),"CSSFontFaceRule"===i.constructor.name||i.type===CSSRule.FONT_FACE_RULE){var r,s=this.getFontFaceProperty(i,"font-family"),l=this.getFontFaceProperty(i,"font-weight")||"400",f=this.getFontFaceProperty(i,"font-style")||"normal",l=this.normalizeFontWeight(l);let e=i.style.getPropertyValue("src")||i.style.src,t=(e=e||this.getFontFaceProperty(i,"src"))?e.match(/url\(["']?([^"')]+\.woff2[^"')]*?)["']?\)/):null;(t=t||(e?e.match(/url\(["']?([^"')]+)["']?\)/):null))&&(r=new URL(t[1],n.href||document.baseURI).href,f=(s+`-${l}-`+f+((l=i.style.getPropertyValue("unicode-range")||"")?"-"+l:"")).toLowerCase(),o.has(f)||o.set(f,r),a.has(r))&&o.set(f,r)}}},getStatus:async function(e){var t=new URLSearchParams(window.location.search),t=Object.fromEntries(t.entries());let _=[],c=[];if(void 0!==document.fonts&&void 0!==document.fonts.ready){await document.fonts.ready;let s=[];document.head.querySelectorAll('link[rel="preload"][as="font"]').forEach(e=>{s.push(e.href)});let l=new Set,f=new Set;var o=document.querySelectorAll("body *:not(#wpadminbar):not(#wpadminbar *)");for(let e=0;e<o.length&&e<1500;e++){let a=o[e];var m=a.getBoundingClientRect(),u=window.getComputedStyle(a),g=u.fontFamily.replace(/["']/g,"");let t=u.fontWeight,n=u.fontStyle,i=m.top<window.innerHeight&&0<m.bottom&&m.left<window.innerWidth&&0<m.right,r=0<m.width||0<m.height;g.split(",").forEach(e=>{e=(`${e=e.trim()}-${t}-`+n).toLowerCase();i&&l.add(e),r||f.add(e)}),["::before","::after"].forEach(e=>{var e=window.getComputedStyle(a,e),t=e.fontFamily.replace(/["']/g,"");let n=e.fontWeight,o=e.fontStyle;t.split(",").forEach(e=>{e=(`${e=e.trim()}-${n}-`+o).toLowerCase();i&&l.add(e),r||f.add(e)})})}var n=new Set(window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff2?|ttf|otf)(\?.*)?$/i)).map(e=>e.name));let d=new Map;var a=[];for(let e=0;e<document.styleSheets.length;e++){var i=document.styleSheets[e];try{var r=i.cssRules||i.rules;r&&this.extractFontFaceRules(r,i,d,n)}catch(e){i.href&&a.push(i.href)}}await this.extractCrossOriginFontFaceRules(a,d,n),document.fonts.forEach(e=>{let n=e.family.replace(/["']/g,"");var t=this.normalizeFontWeight(e.weight),o=e.style,a=(n+`-${t}-`+o).toLowerCase(),i=(a+"-"+(e.unicodeRange||"")).toLowerCase();let r=d.get(i)||d.get(a);"loaded"===e.status&&r&&this.isFaceUsed(l,n,t,o)&&(s.some(e=>{var t;return!(!r||e!==r)||(t=n.toLowerCase().replace(/\s/g,"-"),e=e.toLowerCase(),new RegExp("(^|[/_-])"+t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|$)","i").test(e))})||_.some(e=>e.family===n&&e.url===r)||_.push({family:n,weight:t,style:o,url:r})),"unloaded"===e.status&&!this.isFaceUsed(f,n,t,o)&&r&&c.push({family:n,weight:t,style:o,url:r,unicode_range:e.unicodeRange})})}let s=this.analyzeUnusedFonts(c),l=await this.analyzePreloadImpact(_),f=this.analyzeCLS(omgf_font_cls);var d=new FormData;return d.append("path",document.location.pathname),d.append("urls",JSON.stringify(e)),d.append("params",JSON.stringify(t)),d.append("unused_fonts_analysis",JSON.stringify(s)),d.append("preload_analysis",JSON.stringify(l)),d.append("cls_analysis",JSON.stringify(f)),p.ajax(d).then(e=>(e&&(e.unused_fonts_analysis=s,e.unused_fonts=c,e.preload_analysis=l,e.missing_preloads=_,e.cls_analysis=f),e))},forEachMatchingResources:function(e,n,o){e.forEach(i=>{let t=i.family,r=i.url,s=t.toLowerCase().replace(/\s/g,"-");n.filter(e=>{var t=e.name.toLowerCase();if(r&&e.name===r)return!0;if(!new RegExp("(^|[/_-])"+s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"([./_-]|\\.|$)","i").test(t))return!1;if(void 0===i.weight)return!0;let n=i.weight;var e=i.style,o=("bold"===(n="normal"===n?"400":n)&&(n="700"),new RegExp(`[./_-]${n}([./_-]|\\.|$)`,"i"));let a=!0;return"italic"===e?a=t.includes("italic")||/[._-]i\.(woff|woff2|ttf|otf)/.test(t)||/\d{3}i\.(woff|woff2|ttf|otf)/.test(t):"normal"===e&&(a=!t.includes("italic")),o.test(t)&&a}).forEach(e=>{o(e,t)})})},getFontResources:function(){return window.performance.getEntriesByType("resource").filter(e=>e.name.match(/\.(woff|woff2|ttf|otf)(\?.*)?$/i))},analyzeUnusedFonts:function(e){if(0===e.length)return{};e=e.length;let t=omgf_frontend_i18n.info_box_impact_low;return 6<e?t=omgf_frontend_i18n.info_box_impact_high:3<=e&&(t=omgf_frontend_i18n.info_box_impact_medium),{count:e,impact:t}},analyzeCLS:function(e){let t=omgf_frontend_i18n.info_box_impact_low;e=Math.round(1e3*e)/1e3;return e<.01?{}:(.1<e&&(t=omgf_frontend_i18n.info_box_impact_medium),{cls:e,impact:t=.25<e?omgf_frontend_i18n.info_box_impact_high:t})},analyzePreloadImpact:async function(n){if(0===n.length)return{};let o={affects_lcp:!1,potential_delay_ms:0,impact:omgf_frontend_i18n.info_box_impact_low};try{var a=await new Promise(t=>{let n=new PerformanceObserver(e=>{e=e.getEntries(),e=e[e.length-1];n.disconnect(),t(e)});n.observe({type:"largest-contentful-paint",buffered:!0}),setTimeout(()=>{n.disconnect(),t(null)},2e3)});if(!a)return o;var i=a.element;let e=!1;if(!(e=i?"string"==typeof i.innerText&&0<i.innerText.trim().length||"string"==typeof i.textContent&&0<i.textContent.trim().length:e))return o;var r=this.getFontResources();let t=0;if(this.forEachMatchingResources(n,r,e=>{e=e.responseEnd-e.startTime;0<e&&(o.affects_lcp=!0,e>t)&&(t=e)}),o.potential_delay_ms=Math.round(t),o.potential_delay_ms<=5)return{};100<o.potential_delay_ms?o.impact=omgf_frontend_i18n.info_box_impact_high:20<o.potential_delay_ms&&(o.impact=omgf_frontend_i18n.info_box_impact_medium)}catch(e){return console.warn("OMGF - Error analyzing preload impact:",e),{}}return o},ajax:function(e){return fetch(omgf_frontend_i18n.api_url,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":omgf_frontend_i18n.nonce},body:e}).then(e=>!!e.ok&&e.json())},addInfoBox:function(e,t,n){var o,a=document.createElement("li");a.id="wp-admin-bar-omgf-info","alert"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_alert_text}</a>`),"notice"===e&&(a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${omgf_frontend_i18n.info_box_notice_text}</a>`),"multilang_plugin"===e&&(a.id="wp-admin-bar-omgf-multilang-info",o=p.sprintf(omgf_frontend_i18n.info_box_multilang_plugin_text,omgf_frontend_i18n.multilang_plugin_name,t.subsets_count,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"unload_notice"===e&&(a.id="wp-admin-bar-omgf-unload-info",o=p.sprintf(omgf_frontend_i18n.info_box_unload_text,t.count||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"preload_notice"===e&&(a.id="wp-admin-bar-omgf-preload-info",o=p.sprintf(omgf_frontend_i18n.info_box_preload_text,n||0,t.potential_delay_ms||0,t.impact||omgf_frontend_i18n.info_box_impact_low),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"download_failures"===e&&(a.id="wp-admin-bar-omgf-download-failures",a.classList.add("alert"),(n=document.createElement("a")).className="ab-item",n.href=omgf_frontend_i18n.info_box_admin_url,n.textContent=t.download_failures_text||"",a.appendChild(n)),"cls_notice"===e&&(a.id="wp-admin-bar-omgf-cls-info",o=p.sprintf(omgf_frontend_i18n.info_box_cls_text,t.cls,t.impact),a.innerHTML=`<a class="ab-item" href="${omgf_frontend_i18n.info_box_admin_url}">${o}</a>`),"cls_notice"!==e&&"unload_notice"!==e&&"preload_notice"!==e&&"multilang_plugin"!==e||a.classList.add("info"),"info"===e&&omgf_frontend_i18n.first_run&&document.getElementById("wp-admin-bar-omgf-optimize-this")?.classList.add("info"),p.sub_menu&&p.sub_menu.prepend(a)},sprintf:function(e){let a=arguments,i=1;return e.replace(/%(s|d|0\d+d)/g,function(e,t){var n=a[i++];switch(t){case"s":return n;case"d":return parseInt(n,10);default:var n=String(parseInt(n,10)),o=Number(t.slice(1,-1));return"0".repeat(o).slice(n.length)+n}})}},e=window.performance.getEntries(),t=0,n=setInterval(()=>{t++,((e=e.length<window.performance.getEntries().length?window.performance.getEntries():e).length===window.performance.getEntries().length||20<=t)&&(clearInterval(n),p.init())},500)}); -
host-webfonts-local/trunk/host-webfonts-local.php
r3707539 r3721511 4 4 * Plugin URI: https://daan.dev/wordpress/omgf/ 5 5 * Description: Increase GDPR/DSGVO compliance and leverage browser cache by automatically self-hosting Google Fonts. 6 * Version: 6.3.1 16 * Version: 6.3.12 7 7 * Author: Daan from Daan.dev 8 8 * Author URI: https://daan.dev -
host-webfonts-local/trunk/readme.txt
r3707539 r3721511 3 3 Tags: google, fonts, gdpr, dsgvo, cache 4 4 Requires at least: 5.9 5 Tested up to: 7. 06 Stable tag: 6.3.1 15 Tested up to: 7.1 6 Stable tag: 6.3.12 7 7 Requires PHP: 7.3 8 8 License: GPLv2 or later … … 87 87 88 88 == Changelog == 89 90 = 6.3.12 = 91 * Security: hardened the handling of Google Fonts stylesheet requests. 92 * Security: hardened the handling of downloaded font files. 93 * Security: admin notices are escaped on output. 94 * Security: the redirect after saving settings is restricted to the site's own host. 95 * Security: the stylesheet handle is escaped on the Optimize Fonts screen. 96 * Improved: removed a legacy, hidden option from the settings form. 97 * Security: only administrators can store results or trigger processing through the Admin Bar Menu's status endpoint, even when its permission is widened by a filter. URLs are validated before they're processed. 98 * Security: downloaded font files are now validated before they're stored. 99 * Fixed: the Font Performance Checker didn't detect fonts which should be preloaded if their @font-face statement used a keyword (e.g. font-weight: normal, which most icon fonts use) or a weight range (i.e. variable fonts). 100 * Improved: the Font Performance Checker now also detects fonts which should be preloaded in cross-origin stylesheets loaded without the crossorigin attribute, if the stylesheet's host allows it (most font CDNs do). 101 * Tested with WP 7.1. 89 102 90 103 = 6.3.11 = -
host-webfonts-local/trunk/src/API/AdminbarMenu.php
r3503345 r3721511 19 19 use OMGF\Admin\Dashboard; 20 20 use OMGF\Admin\Settings; 21 use OMGF\Download; 21 22 use OMGF\Helper as OMGF; 22 23 … … 55 56 public function get_admin_bar_status( $request ) { 56 57 $params = $this->clean( $request->get_params() ); 57 $stored_results = $this->update_google_fonts_checker_results( $params );58 58 $unused_fonts_analysis = $this->decode_json_array( $params['unused_fonts_analysis'] ?? [] ); 59 59 $preload_analysis = $this->decode_json_array( $params['preload_analysis'] ?? [] ); 60 60 $cls_analysis = $this->decode_json_array( $params['cls_analysis'] ?? [] ); 61 61 62 $this->update_perf_metrics( $params, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 62 /** 63 * @since v6.3.12 The permission for this endpoint can be widened with the omgf_api_adminbar_menu_permission 64 * filter (e.g., to allow visitors to request the status), but only administrators may store 65 * results or trigger any processing through it. Everyone else gets a read-only status. 66 */ 67 if ( current_user_can( 'manage_options' ) ) { 68 $stored_results = $this->update_google_fonts_checker_results( $params ); 69 70 $this->update_perf_metrics( $params, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 71 } else { 72 $stored_results = get_option( Settings::OMGF_DB_GOOGLE_FONTS_CHECKER_RESULTS, [] ); 73 $stored_results = is_array( $stored_results ) ? $stored_results : []; 74 } 63 75 64 76 $status = $this->calculate_status( $stored_results, $unused_fonts_analysis, $preload_analysis, $cls_analysis ); 65 77 66 return [ 'status' => apply_filters( 'omgf_ajax_admin_bar_status', $status ) ]; 78 /** 79 * @since v6.3.12 Font files which couldn't be downloaded correctly are reported to administrators only, because 80 * visitors requesting the status (e.g. for Smart Optimize) need the regular status. 81 */ 82 $download_failures = current_user_can( 'manage_options' ) ? count( Download::get_failures() ) : 0; 83 84 if ( $download_failures > 0 ) { 85 $status = 'alert'; 86 } 87 88 $response = [ 'status' => apply_filters( 'omgf_ajax_admin_bar_status', $status ) ]; 89 90 if ( $download_failures > 0 ) { 91 $response['download_failures'] = $download_failures; 92 $response['download_failures_text'] = sprintf( 93 /* translators: %d: number of font files */ 94 _n( 95 '%d font file couldn\'t be downloaded correctly', 96 '%d font files couldn\'t be downloaded correctly', 97 $download_failures, 98 'host-webfonts-local' 99 ), 100 $download_failures 101 ); 102 $response['google_fonts_checker_alert'] = ! empty( $stored_results ); 103 } 104 105 return $response; 67 106 } 68 107 … … 135 174 $urls = []; 136 175 } 176 177 /** 178 * @since v6.3.12 Validate the URLs before they're passed to any filter. 179 */ 180 $urls = array_filter( 181 $urls, 182 function ( $url ) { 183 return is_string( $url ) && filter_var( $url, FILTER_VALIDATE_URL ); 184 } 185 ); 137 186 138 187 $urls = apply_filters( 'omgf_ajax_results', $urls, $params, $path ); -
host-webfonts-local/trunk/src/API/Dashboard.php
r3489128 r3721511 18 18 19 19 use OMGF\Admin\Settings; 20 use OMGF\Download; 20 21 21 22 class Dashboard { … … 67 68 ] 68 69 ); 70 71 register_rest_route( 72 $this->namespace, 73 '/' . $this->base . '/dismiss-download-failures', 74 [ 75 [ 76 'methods' => 'POST', 77 'callback' => [ $this, 'dismiss_download_failures' ], 78 'permission_callback' => [ $this, 'get_permission' ], 79 ], 80 'schema' => null, 81 ] 82 ); 69 83 } 70 84 … … 90 104 return new \WP_REST_Response( [ 'success' => true ] ); 91 105 } 106 107 /** 108 * Dismiss the font files which couldn't be downloaded correctly. 109 * 110 * @since v6.3.12 111 * 112 * @return \WP_REST_Response 113 */ 114 public function dismiss_download_failures() { 115 Download::clear_failures(); 116 117 return new \WP_REST_Response( [ 'success' => true ] ); 118 } 92 119 } -
host-webfonts-local/trunk/src/Admin/Actions.php
r3707539 r3721511 202 202 ); 203 203 204 /** 205 * @since v6.3.12 These options are generated by OMGF and should never be updated using the settings form. 206 */ 207 $read_only_options = [ 208 Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, 209 Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS_FRONTEND, 210 ]; 211 204 212 foreach ( $updated_settings as $option_name => $option_value ) { 205 213 if ( ! str_starts_with( $option_name, 'omgf_' ) || ( empty( $option_value ) && $option_value !== '0' ) ) { 214 continue; 215 } 216 217 if ( in_array( $option_name, $read_only_options, true ) ) { 206 218 continue; 207 219 } … … 258 270 259 271 if ( ! defined( 'DAAN_DOING_TESTS' ) ) { 260 wp_ redirect( $goback ); // @codeCoverageIgnore272 wp_safe_redirect( $goback ); // @codeCoverageIgnore 261 273 exit; // @codeCoverageIgnore 262 274 } -
host-webfonts-local/trunk/src/Admin/Dashboard.php
r3628684 r3721511 17 17 namespace OMGF\Admin; 18 18 19 use OMGF\Download; 19 20 use OMGF\Helper as OMGF; 20 21 … … 101 102 102 103 return ob_get_clean(); 104 } 105 106 /** 107 * Renders the font files which couldn't be downloaded correctly. 108 * 109 * @since v6.3.12 110 * 111 * @return void 112 */ 113 public static function render_download_failures() { 114 $failures = Download::get_failures(); 115 116 if ( empty( $failures ) ) { 117 return; 118 } 119 ?> 120 <div class="task-manager-notice alert" id="omgf-download-failures-notice"> 121 <h4><?php echo wp_kses_post( 122 sprintf( 123 /* translators: %1$s: plugin name, %2$d: number of font files */ 124 _n( 125 '%1$s couldn\'t download %2$d font file correctly.', 126 '%1$s couldn\'t download %2$d font files correctly.', 127 count( $failures ), 128 'host-webfonts-local' 129 ), 130 apply_filters( 'omgf_settings_page_title', 'OMGF' ), 131 count( $failures ) 132 ) 133 ); ?></h4> 134 <ul> 135 <?php foreach ( $failures as $url => $failure ) : ?> 136 <li> 137 <strong><?php echo esc_html( $url ); ?></strong><br/> 138 <?php echo esc_html( Download::get_failure_message( $failure['reason'] ) ); ?> 139 </li> 140 <?php endforeach; ?> 141 </ul> 142 <p> 143 [ <a href="#" id="omgf-dismiss-download-failures"><?php echo esc_html__( 'Dismiss', 'host-webfonts-local' ); ?></a> ] 144 </p> 145 </div> 146 <?php 103 147 } 104 148 … … 141 185 unset( $warnings['google_fonts_checker'] ); 142 186 } 187 188 self::render_download_failures(); 143 189 ?> 144 190 <?php if ( ! empty( $google_fonts_checker_results ) ): ?> -
host-webfonts-local/trunk/src/Admin/Notice.php
r3494741 r3721511 41 41 foreach ( $notice as $type => $message ) { 42 42 ?> 43 <div id="message" class="notice notice-<?php echo $type; ?> is-dismissible">43 <div id="message" class="notice notice-<?php echo esc_attr( $type ); ?> is-dismissible"> 44 44 <?php foreach ( $message as $line ) : ?> 45 <p><strong><?php echo $line; ?></strong></p>45 <p><strong><?php echo wp_kses_post( $line ); ?></strong></p> 46 46 <?php endforeach; ?> 47 47 </div> -
host-webfonts-local/trunk/src/Admin/Settings.php
r3503345 r3721511 35 35 36 36 const OMGF_DB_PERF_CHECK = 'omgf_perf_check'; 37 38 const OMGF_DB_DOWNLOAD_FAILURES = 'omgf_download_failures'; 37 39 38 40 const OMGF_DB_CACHE_TIMESTAMP = 'omgf_cache_timestamp'; -
host-webfonts-local/trunk/src/Admin/Settings/Optimize.php
r3531267 r3721511 269 269 } 270 270 ?> 271 <tbody class="stylesheet" id="<?php echo $handle; ?>">271 <tbody class="stylesheet" id="<?php echo esc_attr( $handle ); ?>"> 272 272 <tr> 273 273 <th colspan="6"><?php echo sprintf( 274 274 __( 'Stylesheet handle: %s', 'host-webfonts-local' ), 275 $handle275 esc_html( $handle ) 276 276 ); ?></th> 277 277 </tr> … … 390 390 <?php endforeach; ?> 391 391 </table> 392 <input type="hidden" name="<?php echo Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS; ?>"393 value="<?php echo base64_encode( serialize( $this->optimized_fonts ) ); ?>"/>394 392 <input id="<?php echo Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" type="hidden" 395 393 name="omgf_settings[<?php echo Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>]" -
host-webfonts-local/trunk/src/Download.php
r3707539 r3721511 19 19 use OMGF\Helper as OMGF; 20 20 use OMGF\Admin\Notice; 21 use OMGF\Admin\Settings; 21 22 22 23 class Download { … … 39 40 ]; 40 41 42 /** 43 * Default maximum size (in bytes) of a downloaded font file. 44 * 45 * @since v6.3.12 46 */ 47 const MAX_FILE_SIZE = 25 * MB_IN_BYTES; 48 49 /** 50 * Maximum number of failed downloads reported on the Dashboard. 51 * 52 * @since v6.3.12 53 */ 54 const MAX_FAILURES = 20; 55 56 /** 57 * Reasons why a downloaded file was discarded. 58 */ 59 const FAILURE_EMPTY = 'empty'; 60 61 const FAILURE_TOO_LARGE = 'too_large'; 62 63 const FAILURE_INVALID = 'invalid'; 64 41 65 42 66 /** @var string $url */ … … 57 81 string $path 58 82 ) { 59 $this->url = $url; 60 $this->filename = $filename; 83 $this->url = $url; 84 /** 85 * @since v6.3.12 Sanitize the filename so a font family (which it's partly built from) can't contain a 86 * path separator and write the downloaded file outside of $path. 87 */ 88 $this->filename = sanitize_file_name( $filename ); 61 89 $this->path = $path; 62 90 } … … 82 110 $temp_filename = $this->path . '/' . $this->filename . '-' . wp_generate_password( 12, false ) . '.tmp'; 83 111 84 $response = wp_safe_remote_get( 112 $max_file_size = self::get_max_file_size(); 113 $response = wp_safe_remote_get( 85 114 $this->url, 86 115 [ 87 'timeout' => 300, 88 'stream' => true, 89 'filename' => $temp_filename, 116 'timeout' => 300, 117 'stream' => true, 118 'filename' => $temp_filename, 119 /** 120 * @since v6.3.12 Stop downloading once the file exceeds the maximum size. One extra byte is requested, so 121 * a file which was cut off can be told apart from a file of exactly the maximum size. 122 */ 123 'limit_response_size' => $max_file_size + 1, 90 124 ] 91 125 ); … … 161 195 } 162 196 197 /** 198 * @since v6.3.12 Validate the downloaded file before it's stored. 199 */ 200 $reason = $this->validate_file( $temp_filename, $max_file_size ); 201 202 if ( $reason ) { 203 $this->delete_temp_file( $temp_filename ); 204 205 /** 206 * Reported on the Dashboard (and in the Admin Bar), because downloads often run during a visitor's request. 207 * 208 * @see \OMGF\Admin\Dashboard::render_download_failures() 209 */ 210 self::add_failure( $this->url, $reason ); 211 212 return ''; 213 } 214 163 215 if ( file_exists( $temp_filename ) ) { 164 216 $final_path = $this->path . '/' . $this->filename . '.' . $extension; … … 179 231 } 180 232 233 self::remove_failure( $this->url ); 234 181 235 return OMGF_UPLOAD_URL . str_replace( OMGF_UPLOAD_DIR, '', $this->path ) . '/' . $this->filename . '.' . $extension; 236 } 237 238 /** 239 * Maximum size (in bytes) of a downloaded font file. 240 * 241 * @since v6.3.12 242 * @filter omgf_download_max_file_size 243 * 244 * @return int 245 */ 246 public static function get_max_file_size() { 247 return max( 1, (int) apply_filters( 'omgf_download_max_file_size', self::MAX_FILE_SIZE ) ); 248 } 249 250 /** 251 * Checks if $file is a complete font file, i.e. not empty, not cut off because it exceeds the maximum size, and 252 * starting with the signature of a font format. 253 * 254 * @since v6.3.12 255 * 256 * @param string $file 257 * @param int $max_file_size 258 * 259 * @return string An error message if the file is invalid, an empty string if it's valid. 260 */ 261 private function validate_file( $file, $max_file_size ) { 262 $size = file_exists( $file ) ? filesize( $file ) : 0; 263 264 if ( ! $size ) { 265 return self::FAILURE_EMPTY; 266 } 267 268 if ( $size > $max_file_size ) { 269 return self::FAILURE_TOO_LARGE; 270 } 271 272 if ( ! self::is_font_file( $file ) ) { 273 return self::FAILURE_INVALID; 274 } 275 276 return ''; 277 } 278 279 /** 280 * Failed downloads, most recent first. 281 * 282 * @since v6.3.12 283 * 284 * @return array [ url => [ 'reason' => string, 'time' => int ] ] 285 */ 286 public static function get_failures() { 287 return self::normalize_failures( get_option( Settings::OMGF_DB_DOWNLOAD_FAILURES, [] ) ); 288 } 289 290 /** 291 * Removes invalid entries and sorts the failed downloads, most recent first. 292 * 293 * @since v6.3.12 294 * 295 * @param mixed $failures 296 * 297 * @return array 298 */ 299 private static function normalize_failures( $failures ) { 300 if ( ! is_array( $failures ) ) { 301 return []; // @codeCoverageIgnore 302 } 303 304 $failures = array_filter( 305 $failures, 306 function ( $failure, $url ) { 307 return is_string( $url ) && is_array( $failure ) && in_array( $failure['reason'] ?? '', self::get_failure_reasons(), true ); 308 }, 309 ARRAY_FILTER_USE_BOTH 310 ); 311 312 uasort( 313 $failures, 314 function ( $a, $b ) { 315 return ( $b['time'] ?? 0 ) <=> ( $a['time'] ?? 0 ); 316 } 317 ); 318 319 return $failures; 320 } 321 322 /** 323 * Stores a failed download, keeping at most MAX_FAILURES (the most recent ones). 324 * 325 * @since v6.3.12 326 * 327 * @param string $url 328 * @param string $reason One of the FAILURE_* constants. 329 * 330 * @return void 331 */ 332 public static function add_failure( $url, $reason ) { 333 self::update_failures( 334 function ( $failures ) use ( $url, $reason ) { 335 unset( $failures[ $url ] ); 336 337 return array_slice( [ $url => [ 'reason' => $reason, 'time' => time() ] ] + $failures, 0, self::MAX_FAILURES, true ); 338 } 339 ); 340 } 341 342 /** 343 * Removes a failed download, e.g. once it succeeds. 344 * 345 * @since v6.3.12 346 * 347 * @param string $url 348 * 349 * @return void 350 */ 351 public static function remove_failure( $url ) { 352 /** 353 * This runs after every successful download, so only lock when there's something to remove. The check reads the 354 * database, because a cached copy might not contain a failure stored by another request. 355 */ 356 if ( ! isset( self::read_stored_failures()[ $url ] ) ) { 357 return; 358 } 359 360 self::update_failures( 361 function ( $failures ) use ( $url ) { 362 unset( $failures[ $url ] ); 363 364 return $failures; 365 } 366 ); 367 } 368 369 /** 370 * Removes all failed downloads, i.e. when they're dismissed. 371 * 372 * @since v6.3.12 373 * 374 * @return void 375 */ 376 public static function clear_failures() { 377 self::update_failures( 378 function () { 379 return []; 380 } 381 ); 382 } 383 384 /** 385 * Reads the failed downloads from the database, instead of a (possibly outdated) cached copy. 386 * 387 * @since v6.3.12 388 * 389 * @return array 390 */ 391 private static function read_stored_failures() { 392 global $wpdb; 393 394 $stored = $wpdb->get_var( 395 $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", Settings::OMGF_DB_DOWNLOAD_FAILURES ) 396 ); 397 398 return self::normalize_failures( $stored === null ? [] : maybe_unserialize( $stored ) ); 399 } 400 401 /** 402 * Updates the failed downloads while holding a (MySQL) lock, based on the value currently stored in the database, 403 * so concurrent downloads can't overwrite each other's changes. 404 * 405 * @since v6.3.12 406 * 407 * @param callable $callback Receives the current failed downloads and returns the new ones. 408 * 409 * @return void 410 */ 411 private static function update_failures( $callback ) { 412 global $wpdb; 413 414 $lock_name = $wpdb->prefix . Settings::OMGF_DB_DOWNLOAD_FAILURES; 415 // Databases which don't support locks (e.g. SQLite) return null, in which case we proceed without one. 416 $locked = (bool) $wpdb->get_var( $wpdb->prepare( 'SELECT GET_LOCK(%s, %d)', $lock_name, 5 ) ); 417 418 try { 419 $failures = $callback( self::read_stored_failures() ); 420 421 wp_cache_delete( Settings::OMGF_DB_DOWNLOAD_FAILURES, 'options' ); 422 wp_cache_delete( 'notoptions', 'options' ); 423 424 if ( empty( $failures ) ) { 425 delete_option( Settings::OMGF_DB_DOWNLOAD_FAILURES ); 426 } else { 427 update_option( Settings::OMGF_DB_DOWNLOAD_FAILURES, $failures, false ); 428 } 429 } finally { 430 if ( $locked ) { 431 $wpdb->query( $wpdb->prepare( 'SELECT RELEASE_LOCK(%s)', $lock_name ) ); 432 } 433 } 434 } 435 436 /** 437 * @since v6.3.12 438 * 439 * @return string[] 440 */ 441 private static function get_failure_reasons() { 442 return [ self::FAILURE_EMPTY, self::FAILURE_TOO_LARGE, self::FAILURE_INVALID ]; 443 } 444 445 /** 446 * A human-readable description of why a download failed, and what the user can do about it. 447 * 448 * @since v6.3.12 449 * 450 * @param string $reason One of the FAILURE_* constants. 451 * 452 * @return string 453 */ 454 public static function get_failure_message( $reason ) { 455 switch ( $reason ) { 456 case self::FAILURE_TOO_LARGE: 457 return sprintf( 458 /* translators: %s: maximum file size, e.g. 25 MB */ 459 __( 'The file exceeds the maximum file size of %s, so it isn\'t used and a fallback font is shown instead.', 'host-webfonts-local' ), 460 size_format( self::get_max_file_size() ) 461 ); 462 case self::FAILURE_INVALID: 463 return __( 'The downloaded file isn\'t a font file (e.g. an error page), so a fallback font is shown until it\'s downloaded successfully. Click Save & Optimize to try again.', 'host-webfonts-local' ); 464 default: 465 return __( 'The downloaded file was empty, so a fallback font is shown until it\'s downloaded successfully. Click Save & Optimize to try again.', 'host-webfonts-local' ); 466 } 467 } 468 469 /** 470 * Checks if $file starts with the signature (magic bytes) of a WOFF2, WOFF, TrueType, OpenType or EOT file. 471 * 472 * @since v6.3.12 473 * 474 * @param string $file 475 * 476 * @return bool 477 */ 478 public static function is_font_file( $file ) { 479 $handle = @fopen( $file, 'rb' ); // phpcs:ignore 480 481 if ( ! $handle ) { 482 return false; // @codeCoverageIgnore 483 } 484 485 $header = (string) fread( $handle, 36 ); 486 487 fclose( $handle ); 488 489 // WOFF2, WOFF, OpenType (CFF), TrueType, TrueType (Apple), TrueType Collection. 490 if ( in_array( substr( $header, 0, 4 ), [ 'wOF2', 'wOFF', 'OTTO', "\x00\x01\x00\x00", 'true', 'ttcf' ], true ) ) { 491 return true; 492 } 493 494 // EOT: magic number 0x504C at offset 34. 495 return strlen( $header ) >= 36 && substr( $header, 34, 2 ) === 'LP'; 182 496 } 183 497 -
host-webfonts-local/trunk/src/Filters.php
r3531267 r3721511 28 28 add_filter( 'home_url', [ $this, 'force_ssl' ], 1000, 2 ); 29 29 add_filter( 'omgf_optimize_user_agent', [ $this, 'maybe_do_legacy_mode' ] ); 30 add_filter( 'pre_update_option_omgf_optimized_fonts', [ $this, 'base64_decode_optimized_fonts' ] );31 30 add_filter( 'omgf_do_not_load_frontend_css', [ $this, 'maybe_load_frontend_assets' ] ); 32 }33 34 /**35 * @since v5.0.5 omgf_optimized_fonts is base64_encoded in the frontend, to bypass firewall restrictions on36 * some servers.37 *38 * @param $old_value39 * @param $value40 *41 * @return bool|array42 */43 public function base64_decode_optimized_fonts( $value ) {44 if ( is_string( $value ) && base64_encode( base64_decode( $value, true ) ) === $value ) {45 return base64_decode( $value );46 }47 48 return $value;49 31 } 50 32 -
host-webfonts-local/trunk/src/Frontend/Process.php
r3707539 r3721511 629 629 * just fine. Using a negated character class (instead of adding the /s modifier) makes 630 630 * sure the match can never run past a quote character. 631 */ 632 preg_match( '/href=([\'"])(?P<href>[^\'"]*)\1/', $link, $href ); 631 * @since v6.3.12 Only match the href attribute when it starts a new attribute (after whitespace or the 632 * tag opener), so an attribute whose name ends in "href" (e.g. data-href, x:href, 633 * x.href) isn't captured as the href. 634 */ 635 preg_match( '/(?:^|[\s<])href=([\'"])(?P<href>[^\'"]*)\1/', $link, $href ); 633 636 634 637 /** … … 734 737 735 738 /** 739 * @since v6.3.12 Only process (and request) stylesheets whose URL is actually hosted on the Google 740 * Fonts API (or a compatible endpoint). The element was kept because one of its 741 * attribute values points at the API (see get_element_urls()), but the href used 742 * here could point at a different — e.g. internal — host. Checking here, before the 743 * branches below, leaves a non-API link untouched (not removed, not swapped for a 744 * cached file) and makes sure it's never requested, which prevents SSRF. 745 */ 746 if ( ! $this->is_font_api_url( $url ) ) { 747 continue; 748 } 749 750 /** 736 751 * If the stylesheet with $handle is completely marked for unloading, just remove the element 737 752 * to prevent it from loading. … … 795 810 796 811 $search[ $key ] = $stack['href']; 797 $replace[ $key ] = $cached_url ? $cached_url . '?ver=' . $this->timestamp : ''; 812 /** 813 * @since v6.3.12 If optimization produced no URL (e.g. the request was blocked or redirected, the 814 * fetch failed, or the response wasn't a stylesheet), leave the original link 815 * untouched instead of removing it, so the fonts keep loading. 816 */ 817 $replace[ $key ] = $cached_url ? $cached_url . '?ver=' . $this->timestamp : $stack['href']; 798 818 } 799 819 -
host-webfonts-local/trunk/src/Helper.php
r3707539 r3721511 133 133 134 134 /** 135 * Unserializes $value if it's serialized, like maybe_unserialize(), but only allows stdClass objects, because 136 * OMGF never stores any other objects. 137 * 138 * @since v6.3.12 139 * 140 * @param mixed $value 141 * 142 * @return mixed 143 */ 144 public static function maybe_unserialize( $value ) { 145 if ( ! is_string( $value ) || ! is_serialized( $value ) ) { 146 return $value; 147 } 148 149 return @unserialize( trim( $value ), [ 'allowed_classes' => [ 'stdClass' ] ] ); // phpcs:ignore 150 } 151 152 /** 135 153 * Method to retrieve OMGF's settings from database. 136 154 * WARNING: DO NOT ATTEMPT TO RETRIEVE WP CORE SETTINGS USING THIS METHOD. IT WILL FAIL. … … 151 169 // get_option() should take care of this, but sometimes it doesn't. 152 170 if ( is_string( $value ) ) { 153 $value = maybe_unserialize( $value );171 $value = self::maybe_unserialize( $value ); 154 172 } 155 173 … … 292 310 } 293 311 312 /** 313 * @since v6.3.12 A font family is used to build the filename its files are stored under, so reject any 314 * path separator to make sure a crafted name can't traverse out of the fonts directory. 315 * Dots are left alone: a font family can legitimately contain them, and without a 316 * separator they can't traverse (the download filename is sanitized regardless). 317 */ 318 if ( preg_match( '#[/\\\\]#', $family ) ) { 319 return false; // @codeCoverageIgnore 320 } 321 294 322 // A CSS custom property, e.g. --wp--preset--font-family--foo. 295 323 if ( str_starts_with( $family, '--' ) ) { … … 534 562 */ 535 563 if ( is_string( self::$admin_optimized_fonts ) && self::$admin_optimized_fonts !== '' ) { 536 self::$admin_optimized_fonts = maybe_unserialize( self::$admin_optimized_fonts ); // @codeCoverageIgnore564 self::$admin_optimized_fonts = self::maybe_unserialize( self::$admin_optimized_fonts ); // @codeCoverageIgnore 537 565 } 538 566 … … 698 726 */ 699 727 if ( is_string( self::$optimized_fonts ) && self::$optimized_fonts !== '' ) { 700 self::$optimized_fonts = maybe_unserialize( self::$optimized_fonts ); // @codeCoverageIgnore728 self::$optimized_fonts = self::maybe_unserialize( self::$optimized_fonts ); // @codeCoverageIgnore 701 729 } 702 730 -
host-webfonts-local/trunk/src/Optimize.php
r3707539 r3721511 298 298 /** @codeCoverageIgnoreEnd */ 299 299 300 $response = wp_remote_get( 300 /** 301 * @since v6.3.12 Use wp_safe_remote_get() so internal/private hosts are rejected even if the host 302 * allow-list is ever bypassed. Belt-and-braces against SSRF. 303 */ 304 $response = wp_safe_remote_get( 301 305 $url, 302 306 [ 307 /** 308 * @since v6.3.12 Never follow redirects: the Google Fonts API (and compatible CDNs) serve the 309 * stylesheet directly, so a redirect would only point the request somewhere else. 310 */ 311 'redirection' => 0, 303 312 /** 304 313 * Allow WP devs to use a different User-Agent, e.g. for compatibility with older browsers/OSes.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)