Asset CleanUp: Page Speed Booster - Version 1.3.3.7

Version Description

  • New Feature: Google Fonts Optimization: Option to preload Google Font Files
  • New Feature: Local Fonts Optimization: Option to preload Local Font Files
  • Extra Compatibility with the latest version of SG Optimiser
Download this release

Release Info

Developer gabelivan
Plugin Icon 128x128 Asset CleanUp: Page Speed Booster
Version 1.3.3.7
Comparing to
See all releases

Code changes from version 1.3.3.6 to 1.3.3.7

assets/style.min.css CHANGED
@@ -1 +1 @@
1
- #wpacu-pages-info-area{width:98%}#wpacu-top-area{margin:15px 0;padding:0 10px}#wpacu-quick-actions{color:#74777b;float:right;width:auto;margin-right:30px;background:rgba(40,44,42,.05);border-radius:10px;padding:6px 12px}#wpacu-quick-actions .wpacu-actions-title{font-weight:200;letter-spacing:.5px}#wpacu-quick-actions a{color:#004567;text-decoration:none}#wpacu-quick-actions a:hover{color:#0073aa}#wpacu-logo-wrap{width:auto;display:inline-block;position:relative}#wpacu-logo-wrap a{display:block}#wpacu-logo-wrap img{width:352px;height:79px}#wpacu-logo-wrap .wpacu-pro-sign{position:absolute;height:auto;font-family:FiraSans-Medium,proxima-nova-1,Montserrat,Helvetica,sans-serif;font-size:13px;font-weight:600;letter-spacing:1px;padding:5px 11px;border-radius:15px;right:-60px;top:30px;width:auto;display:inline-block;text-align:center}#wpacu-logo-wrap .wpacu-pro-sign.wpacu-lite{color:#74777b;background:rgba(40,44,42,.05)}#wpacu-logo-wrap .wpacu-pro-sign.wpacu-pro{color:#004567;background-color:rgba(40,44,42,.05)}#wpacu_meta_box_content .dashicons.dashicons-warning,.wpacu-tabs nav ul li span.extra-info.license-status.inactive{color:#c00}.wpacu-tabs{position:relative;overflow:hidden;margin:0 auto 20px;width:100%;font-weight:300;font-size:20px}.wpacu-tabs nav{text-align:center}.wpacu-tabs nav ul{position:relative;display:-ms-flexbox;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:flex;margin:0 auto;padding:0;max-width:1200px;list-style:none;-ms-box-orient:horizontal;-ms-box-pack:center;-webkit-flex-flow:row wrap;-moz-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center}.wpacu-tabs nav ul li{position:relative;z-index:1;display:block;margin:0;text-align:center;-webkit-flex:1;-moz-flex:1;-ms-flex:1;flex:1}.wpacu-tabs nav ul li span.extra-info{position:absolute;font-size:12px;left:0;right:50%;bottom:12px;-webkit-transform:translate(50%,50%);transform:translate(50%,50%)}.wpacu-tabs nav ul li span.extra-info .dashicons{font-size:16px;margin-right:-3px;margin-top:1px}.wpacu-tabs nav ul li span.extra-info.license-status.active{color:green}.wpacu-tabs nav ul li span.extra-info.assets-unloaded-false{color:#004567}.wpacu-license-area .notice .dashicons,.wpacu-settings-area .notice .dashicons,.wpacu-tabs nav ul li span.extra-info.assets-unloaded-true,.wpacu-tabs nav ul li span.extra-info.bulk-unloads-true{color:green}.wpacu-tabs nav a{position:relative;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:2.5}.wpacu-tabs nav a span{vertical-align:middle;font-size:14px}.wpacu-tabs nav li.wpacu-tab-current a{color:#74777b}.wpacu-tabs nav a:focus{outline:0}.wpacu-tabs .dashicons{font-size:20px}.no-js .wpacu-content-wrap section{display:block;padding-bottom:2em;border-bottom:1px solid rgba(255,255,255,.6)}.no-flexbox nav ul{display:block}.no-flexbox nav ul li{min-width:15%;display:inline-block}@media screen and (max-width:58em){.wpacu-tabs nav a.icon span{display:none}.wpacu-tabs nav a:before{margin-right:0}}.wpacu-tabs-style-underline nav{background:#fff}.wpacu-tabs-style-underline nav a{color:#74777b;font-size:18px;text-transform:uppercase;text-decoration:none;padding:.25em 0 .5em;border-left:1px solid #e7ecea;-webkit-transition:color .2s;transition:color .2s}.wpacu-tabs-style-underline nav li:last-child a{border-right:1px solid #e7ecea}.wpacu-tabs-style-underline nav li a::after{position:absolute;bottom:0;left:0;width:100%;height:6px;background:#2CC185;content:'';-webkit-transition:-webkit-transform .3s;transition:transform .3s;-webkit-transform:translate3d(0,150%,0);transform:translate3d(0,150%,0)}.wpacu-tabs-style-underline nav li.wpacu-tab-current a::after{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.wpacu-tabs-style-underline nav a span{font-weight:700}.wpacu-tabs-style-topline{max-width:1200px;margin:20px auto 30px 0;width:100%;font-weight:300;text-decoration:none}.wpacu-tabs-style-topline nav li{border:1px solid rgba(40,44,42,.1)}.wpacu-tabs-style-topline nav li:not(:last-child){border-right:none}.wpacu-tabs-style-topline nav li.wpacu-tab-current{border-top-color:#008f9c;border-bottom:none}.wpacu-tabs-style-topline nav a{padding:20px 18px;background:rgba(40,44,42,.05);color:#74777b;line-height:1;-webkit-transition:color .2s;transition:color .2s;text-decoration:none}.wpacu-tabs-style-topline nav a:focus,.wpacu-tabs-style-topline nav a:hover{background:0 0;color:#008f9c}.wpacu-tabs-style-topline nav li.wpacu-tab-current a{background:0 0;box-shadow:inset 0 3px 0 #008f9c;color:#008f9c}.wpacu-tabs-style-topline nav li.wpacu-tab-current a span:not(.dashicons){font-weight:600}.wpacu-tabs-style-topline nav a span{text-transform:uppercase;font-weight:400}.wpacu-tab-nav-wrapper{border-bottom:none!important}.wpacu-tab-nav-wrapper .nav-tab.nav-tab-active{background:#fff;position:relative}.wpacu-tab-nav-wrapper .nav-tab.nav-tab-active:after{content:'';width:100%;bottom:-2px;left:0;position:absolute;border-bottom:2px solid #fff}.wpacu-script-attributes-area{margin:20px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings{padding:5px 7px!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings.wpacu-first{margin:0 28px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings label{margin:0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li{margin:0 16px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li:first-child{margin:0 10px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li:last-child{margin:0 2px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings{background:#fff!important;border:1px solid #eee!important;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:5px 10px!important;list-style:none;display:inline-block;margin:0}.wpacu-script-attributes-area .wpacu-script-attributes-settings input[type=radio]{width:auto;padding:0;margin:0 5px 0 0}.wpacu-script-attributes-area .wpacu-script-attributes-settings.wpacu-first{margin:0 34px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings li{float:left;margin:0 17px 0 0}.wpacu-script-attributes-area .wpacu-script-attributes-settings li:first-child{margin:0 10px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings li:last-child{margin:0}.wpacu-script-attributes-area .wpacu-script-attributes-settings:hover{background:#f2faf2}tr.wpacu_location_changed>td{border-left:#004567 4px solid}tr.wpacu_not_load td,tr.wpacu_not_load th{background:#FFE1E1!important}tr.wpacu_not_load td .wpacu-assets-inline-code-wrap,tr.wpacu_not_load td .wpacu-script-attributes-area,tr.wpacu_not_load th .wpacu-assets-inline-code-wrap,tr.wpacu_not_load th .wpacu-script-attributes-area{filter:alpha(opacity=45);opacity:.45}.dashicons-wpacu{width:17px;height:17px;margin:2px 0 0;font-size:16px;text-decoration:none}#wpacu_meta_box_content,.wpacu_widefat{width:99%}.wpacu_widefat .check-column.wpacu_check{padding:10px}body[class*=wpassetcleanup] #footer-left{border-left:2px solid green;padding-left:10px}#wpassetcleanup_asset_list small{width:auto;float:none;display:inline}#wpacu_meta_box_content .emoji{font-size:18px}#wpacu_meta_box_content h3{margin-left:0;padding-left:0}#wpacu_meta_box_content div.wpacu_note{padding:10px;background-color:#f5f5f5}#wpacu_meta_box_content .wpacu_verified{padding:10px;background-color:#f5f5f5;border-left:1px solid #ddd}#wpacu_meta_box_content .wpacu_verified span{color:#0073aa;font-weight:700}#wpacu_meta_box_content div.wpacu_warning{border:1px solid #c00}#wpacu_meta_box_content ul.wpacu_asset_options{margin:0;padding:0}#wpacu_meta_box_content ul.wpacu_asset_options li{list-style:none;display:inline-block}#wpacu_meta_box_content ul.wpacu_asset_options label{font-weight:400;margin-right:5px;margin-top:5px;margin-bottom:5px}.wpacu-updated-frontend{font-weight:400;background-color:#fff;border-left:4px solid #46b450;border-top:1px solid #46b450;border-right:1px solid #46b450;border-bottom:1px solid #46b450;padding:9px 14px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu-updated-frontend span.dashicons-yes{color:#46b450;font-size:26px}#wpacu-update-front-settings-area{margin:10px 0;display:inline-block;position:relative}#wpacu-updating-front-settings{display:none;position:absolute;top:5px;right:-35px}#wpacu_wrap_assets{color:#000!important;text-align:left!important;clear:both!important;width:90%!important;padding:20px!important;margin:30px 0 0 15px!important;border:1px solid #cdcdcd;z-index:10000!important;position:relative!important;background-color:#fff!important}#wpacu_wrap_assets div.wpacu_warning{border:1px solid #c00;padding:5px 10px}#wpacu_wrap_assets small{display:inline!important;margin:0!important;letter-spacing:normal!important}#wpacu_wrap_assets input[type=checkbox]{width:auto!important;margin-right:4px!important}#wpacu_wrap_assets img:not(.wpacu-ajax-loader){display:inline-block!important}#wpacu_wrap_assets p{line-height:22px!important;margin:10px 0!important;text-align:left!important;font-weight:400!important}#wpacu_wrap_assets p:first-child,.wpacu_verified{margin:0 0 10px!important}#wpacu_wrap_assets h1{margin:0 0 20px!important;font-size:160%!important;text-align:left!important}#wpacu_wrap_assets h3{margin:20px 0;font-size:130%}.wpacu_asset_row:first-child td{border-top:1px solid #cdcdcd}.wpacu_asset_row td{border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd;border-bottom:1px solid #cdcdcd}.wpacu_asset_row.wpacu_notice_row td{position:relative;padding:5px;border-bottom:1px solid transparent}.wpacu_asset_row.wpacu_notice_row td div.wpacu-warning{width:auto;margin:5px;font-style:italic}.wpacu_asset_row:not(.wpacu_notice_row) td{padding:18px!important;position:relative}.wpacu_asset_row:not(.wpacu_notice_row) td.selected,.wpacu_asset_row:not(.wpacu_notice_row) td:hover{-moz-box-shadow:inset 0 0 12px #cdcdcd;-webkit-box-shadow:inset 0 0 12px #cdcdcd;box-shadow:inset 0 0 12px #cdcdcd}.wpacu_asset_row:not(.wpacu_notice_row) td p{padding:0!important;margin-bottom:10px!important;word-wrap:break-word!important;-ms-word-break:break-all;word-break:break-word}.wpacu_asset_row:not(.wpacu_notice_row) td label{width:auto!important;margin:0!important;cursor:pointer!important;display:inline-block!important;font-size:100%!important;font-weight:400!important}.wpacu_asset_row:not(.wpacu_notice_row) td label span:not(.dashicons){font-size:100%!important}.wpacu_asset_row:not(.wpacu_notice_row) td.wpacu_check{width:50px!important}.asset-table-extra-info td{padding:5px!important}body.wp-admin .wpacu_asset_row td.wpacu_check{width:25px!important}.wpacu_asset_row .dashicons-warning{color:red!important}label.wpacu_add_global{cursor:pointer!important}label.wpacu_input_load_checked{font-weight:700;color:#d54e21}label.wpacu_global_unload_exception{font-weight:700!important}tr.wpacu_global_rule_row.selected{background:#e7e7e7}.nav-tab-wrapper{border-bottom:1px solid #ccc;width:95%}.nav-tab-wrapper.nav-assets-manager .nav-tab{font-size:13px;font-weight:500;padding:6px 10px}.nav-tab-wrapper.nav-assets-manager .nav-tab.for-pro{padding:6px 8px 6px 3px}ul.wpacu_asset_options{margin:0 10px 0 0;padding:0}ul.wpacu_asset_options li{margin:0 10px 0 0;list-style:none;display:inline-block;line-height:normal}ul.wpacu_asset_options li.remove_rule label{font-weight:700}ul.wpacu_asset_options label{margin-right:20px;font-weight:400}ul.wpacu_asset_options label input{margin-right:4px}.wpacu_list_table,.wpacu_list_table div,.wpacu_list_table li,.wpacu_list_table p{font-weight:400}.wpacu_striped>tbody>:nth-child(even),ul.wpacu_striped>:nth-child(even){background-color:#fff!important}.wpacu_striped>tbody>:nth-child(odd),ul.wpacu_striped>:nth-child(odd){background-color:#f9f9f9!important}.wpacu_update_btn{-moz-box-shadow:inset 0 1px 0 0 #54a3f7!important;-webkit-box-shadow:inset 0 1px 0 0 #54a3f7!important;box-shadow:inset 0 1px 0 0 #54a3f7!important;background:-webkit-gradient(linear,left top,left bottom,color-stop(.05,#007dc1),color-stop(1,#0061a7))!important;background:-moz-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-webkit-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-o-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-ms-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:linear-gradient(to bottom,#007dc1 5%,#0061a7 100%)!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#007dc1', endColorstr='#0061a7', GradientType=0)!important;background-color:#007dc1!important;-moz-border-radius:3px!important;-webkit-border-radius:3px!important;border-radius:3px!important;border:1px solid #124d77!important;display:inline-block!important;cursor:pointer!important;color:#fff!important;font-size:15px!important;padding:10px 24px!important;text-decoration:none!important;text-shadow:0 1px 0 #154682!important;height:auto!important;line-height:normal!important}.wpacu-btns .btn:focus,.wpacu-btns .btn:hover,.wpacu-btns a{text-decoration:none}.wpacu_update_btn.wpacu_submitting,.wpacu_update_btn:hover{background:-webkit-gradient(linear,left top,left bottom,color-stop(.05,#0061a7),color-stop(1,#007dc1))!important;background:-moz-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-webkit-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-o-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-ms-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:linear-gradient(to bottom,#0061a7 5%,#007dc1 100%)!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0061a7', endColorstr='#007dc1', GradientType=0)!important;background-color:#0061a7!important}.wpacu_update_btn.wpacu_submitting{cursor:default!important}.wpacu_update_btn:active{position:relative!important;top:1px!important}.wpacu-btns .btn{display:inline-block;font-weight:400;line-height:1.25;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem 1rem;font-size:1rem;-webkit-border-radius:.25rem;-moz-border-radius:.25rem;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wpacu-btns .btn.focus,.wpacu-btns .btn:focus{outline:0;-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.25);box-shadow:0 0 0 2px rgba(2,117,216,.25)}.wpacu-btns .btn.disabled,.wpacu-btns .btn:disabled{cursor:not-allowed;opacity:.65}.wpacu-btns .btn.active,.wpacu-btns .btn:active{background-image:none}.wpacu-btns a.btn.disabled,.wpacu-btns fieldset[disabled] a.btn{pointer-events:none}.wpacu-btns .btn-primary{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-primary:hover{color:#fff;background-color:#025aa5;border-color:#01549b}.wpacu-btns .btn-primary.focus,.wpacu-btns .btn-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.wpacu-btns .btn-primary.disabled,.wpacu-btns .btn-primary:disabled{background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-primary.active,.wpacu-btns .btn-primary:active,.wpacu-btns .show>.btn-primary.dropdown-toggle{color:#fff;background-color:#025aa5;background-image:none;border-color:#01549b}.wpacu-btns .btn-secondary{color:#292b2c;background-color:#fff;border-color:#ccc}.wpacu-btns .btn-secondary:hover{color:#292b2c;background-color:#e6e6e6;border-color:#adadad}.wpacu-btns .btn-secondary.focus,.wpacu-btns .btn-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.wpacu-btns .btn-secondary.disabled,.wpacu-btns .btn-secondary:disabled{background-color:#fff;border-color:#ccc}.wpacu-btns .btn-secondary.active,.wpacu-btns .btn-secondary:active,.wpacu-btns .show>.btn-secondary.dropdown-toggle{color:#292b2c;background-color:#e6e6e6;background-image:none;border-color:#adadad}.wpacu-btns .btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.wpacu-btns .btn-info.focus,.wpacu-btns .btn-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.wpacu-btns .btn-info.disabled,.wpacu-btns .btn-info:disabled{background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-info.active,.wpacu-btns .btn-info:active,.wpacu-btns .show>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;background-image:none;border-color:#2aabd2}.wpacu-btns .btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-success:hover{color:#fff;background-color:#449d44;border-color:#419641}.wpacu-btns .btn-success.focus,.wpacu-btns .btn-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.wpacu-btns .btn-success.disabled,.wpacu-btns .btn-success:disabled{background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-success.active,.wpacu-btns .btn-success:active,.wpacu-btns .show>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;background-image:none;border-color:#419641}.wpacu-btns .btn-warning{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#eb9316}.wpacu-btns .btn-warning.focus,.wpacu-btns .btn-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.wpacu-btns .btn-warning.disabled,.wpacu-btns .btn-warning:disabled{background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-warning.active,.wpacu-btns .btn-warning:active,.wpacu-btns .show>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;background-image:none;border-color:#eb9316}.wpacu-btns .btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#c12e2a}.wpacu-btns .btn-danger.focus,.wpacu-btns .btn-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.wpacu-btns .btn-danger.disabled,.wpacu-btns .btn-danger:disabled{background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-danger.active,.wpacu-btns .btn-danger:active,.wpacu-btns .show>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;background-image:none;border-color:#c12e2a}.wpacu-btns .btn-outline-primary{color:#0275d8;background-image:none;background-color:transparent;border-color:#0275d8}.wpacu-btns .btn-outline-primary:hover{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-outline-primary.focus,.wpacu-btns .btn-outline-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.wpacu-btns .btn-outline-primary.disabled,.wpacu-btns .btn-outline-primary:disabled{color:#0275d8;background-color:transparent}.wpacu-btns .btn-outline-primary.active,.wpacu-btns .btn-outline-primary:active,.wpacu-btns .show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-outline-secondary{color:#ccc;background-image:none;background-color:transparent;border-color:#ccc}.wpacu-btns .btn-outline-secondary:hover{color:#fff;background-color:#ccc;border-color:#ccc}.wpacu-btns .btn-outline-secondary.focus,.wpacu-btns .btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.wpacu-btns .btn-outline-secondary.disabled,.wpacu-btns .btn-outline-secondary:disabled{color:#ccc;background-color:transparent}.wpacu-btns .btn-outline-secondary.active,.wpacu-btns .btn-outline-secondary:active,.wpacu-btns .show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ccc;border-color:#ccc}.wpacu-btns .btn-outline-info{color:#5bc0de;background-image:none;background-color:transparent;border-color:#5bc0de}.wpacu-btns .btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-outline-info.focus,.wpacu-btns .btn-outline-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.wpacu-btns .btn-outline-info.disabled,.wpacu-btns .btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.wpacu-btns .btn-outline-info.active,.wpacu-btns .btn-outline-info:active,.wpacu-btns .show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-outline-success{color:#5cb85c;background-image:none;background-color:transparent;border-color:#5cb85c}.wpacu-btns .btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-outline-success.focus,.wpacu-btns .btn-outline-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.wpacu-btns .btn-outline-success.disabled,.wpacu-btns .btn-outline-success:disabled{color:#5cb85c;background-color:transparent}.wpacu-btns .btn-outline-success.active,.wpacu-btns .btn-outline-success:active,.wpacu-btns .show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-outline-warning{color:#f0ad4e;background-image:none;background-color:transparent;border-color:#f0ad4e}.wpacu-btns .btn-outline-warning:hover{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-outline-warning.focus,.wpacu-btns .btn-outline-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.wpacu-btns .btn-outline-warning.disabled,.wpacu-btns .btn-outline-warning:disabled{color:#f0ad4e;background-color:transparent}.wpacu-btns .btn-outline-warning.active,.wpacu-btns .btn-outline-warning:active,.wpacu-btns .show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-outline-danger{color:#d9534f;background-image:none;background-color:transparent;border-color:#d9534f}.wpacu-btns .btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-outline-danger.focus,.wpacu-btns .btn-outline-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.wpacu-btns .btn-outline-danger.disabled,.wpacu-btns .btn-outline-danger:disabled{color:#d9534f;background-color:transparent}.wpacu-btns .btn-outline-danger.active,.wpacu-btns .btn-outline-danger:active,.wpacu-btns .show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-link{font-weight:400;color:#0275d8;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.wpacu-btns .btn-link,.wpacu-btns .btn-link.active,.wpacu-btns .btn-link:active,.wpacu-btns .btn-link:disabled{background-color:transparent}.wpacu-btns .btn-link,.wpacu-btns .btn-link:active,.wpacu-btns .btn-link:focus,.wpacu-btns .btn-link:hover{border-color:transparent}.wpacu-btns .btn-link:focus,.wpacu-btns .btn-link:hover{color:#014c8c;text-decoration:underline;background-color:transparent}.wpacu-btns .btn-link:disabled{color:#636c72}.wpacu-btns .btn-link:disabled:focus,.wpacu-btns .btn-link:disabled:hover{text-decoration:none}.wpacu-btns .btn-group-lg>.btn,.wpacu-btns .btn-lg{padding:.75rem 1.5rem;font-size:1.25rem;-webkit-border-radius:.3rem;-moz-border-radius:.3rem;border-radius:.3rem}.wpacu-btns .btn-group-sm>.btn,.wpacu-btns .btn-sm{padding:.25rem .5rem;font-size:.875rem;-webkit-border-radius:.2rem;-moz-border-radius:.2rem;border-radius:.2rem}.wpacu-btns .btn-block{display:block;width:100%}.go-pro-button,.go-pro-link-no-style,.wordpress-core-file{display:inline-block;text-decoration:none}.wpacu-btns .btn-block+.btn-block{margin-top:.5rem}.wpacu-btns input[type=reset].btn-block,.wpacu-btns input[type=button].btn-block,.wpacu-btns input[type=submit].btn-block{width:100%}.wpacu-btns .fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.go-pro-button{background-color:#4CAF50;border:2px solid #4CAF50;color:#fff;padding:12px 18px;text-align:center;font-size:16px;margin:4px 2px;cursor:pointer;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-transition-duration:.4s;transition-duration:.4s}.go-pro-button:hover{background-color:#fff;color:#000;border:2px solid #4CAF50;text-decoration:none}.wpacu-restore-pos-btn{font-size:14px!important;line-height:normal!important;height:42px!important;padding:0 18px!important;margin-top:10px!important}body.wp-admin .wpacu_asset_row .go-pro-link-no-style .wpacu-tooltip{padding:8px 2px}body.wp-admin .go-pro-link-no-style .wpacu-tooltip{text-shadow:none;font-weight:400;font-size:12px;line-height:16px;padding:8px 11px}.go-pro-link-no-style{position:relative;color:inherit}.go-pro-link-no-style:not(.nav-tab){font-style:italic}.go-pro-link-no-style.no-transition .wpacu-tooltip{-webkit-transition:0s all ease;transition:0s all ease;-webkit-transition-delay:0s;transition-delay:0s}.go-pro-link-no-style>img{max-width:20px;max-height:20px}.go-pro-link-no-style .wpacu-tooltip{font-size:14px;line-height:18px;position:absolute;z-index:1;visibility:hidden;width:160px;background-color:#00a7a7;color:#fff;text-align:center;padding:8px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;bottom:100%;bottom:calc(100% + 15px);left:50%;margin-left:-65px;-webkit-transition:.1s all ease;transition:.1s all ease;-webkit-transition-delay:0s;transition-delay:0s}.go-pro-link-no-style .wpacu-tooltip:after{content:"";position:absolute;border-width:10px;border-style:solid;top:100%;left:50%;left:calc(50% - 10px);border-color:#00a7a7 transparent transparent}.go-pro-link-no-style .wpacu-tooltip.wpacu-on-pages-btn{cursor:pointer;margin-left:-77px;width:130px}.go-pro-link-no-style .wpacu-tooltip.wpacu-larger{width:240px}.go-pro-link-no-style:hover .wpacu-tooltip{visibility:visible}.wpacu_list_table tr:first-child .wordpress-core-file .wpacu-tooltip{bottom:-40px;left:120px;margin-left:-86px}.wpacu_list_table tr:first-child .wordpress-core-file .wpacu-tooltip:after{top:41px;left:-20px;border-color:transparent #c00 transparent transparent}.wordpress-core-file{position:relative;font-style:normal;color:inherit}.wordpress-core-file .wpacu-tooltip{font-size:14px;line-height:18px;position:absolute;z-index:1;visibility:hidden;width:160px;background-color:#c00;color:#fff;text-align:center;padding:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;bottom:100%;bottom:calc(100% + 15px);left:50%;margin-left:-86px;-webkit-transition:.1s all ease;transition:.1s all ease;-webkit-transition-delay:0s;transition-delay:0s}.wordpress-core-file .wpacu-tooltip:after{content:"";position:absolute;border-width:10px;border-style:solid;top:100%;left:50%;left:calc(50% - 10px);border-color:#c00 transparent transparent}.wordpress-core-file:hover .wpacu-tooltip{visibility:visible}.ajax-direct-call-error-area{background:#fff;padding:10px;border:1px solid #c00;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px}.ajax-direct-call-error-area td{padding:6px}.ajax-direct-call-error-area .note{margin-top:0;padding-top:0}.ajax-direct-call-error-area .error-code{color:#c00;font-weight:700}.ajax-wp-remote-post-call-error-area{background:#fff;padding:20px}.ajax-wp-remote-post-call-error-area .table-data{background:0 0;border:1px solid #c66;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.ajax-wp-remote-post-call-error-area .table-data td{padding:10px}.wrap-upgrade-info{background:#fff;padding:0 15px;border:1px solid #cdcdcd;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-notice{margin:20px 20px 0 0!important}.wpacu-notice p{font-weight:600!important;font-style:italic}.wpacu-notice .dashicons{font-weight:inherit!important;color:#46b450!important;margin-right:4px;vertical-align:text-bottom;font-size:27px}.wpacu-notice-info{padding:12px 12px 12px 16px;background:#fff;border-left:4px solid #008f9c}.wpacu-notice-info p{margin-top:8px}.wpacu-notice-info p:first-child{margin-top:0}.wpacu-notice-info p:last-child{margin-bottom:0}.wpacu-warning{font-size:15px;padding:10px;background:#fffcec;border:1px solid #fdd5c9;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;margin:0 0 5px;width:100%}.pro-page-unlock-notice{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;padding:10px;background:#f2faf2;border:1px solid #c0e8c0;width:auto;display:block}.wpacu-license-area .notice,.wpacu-settings-area .notice{margin-left:0;padding:10px!important;width:97%;box-sizing:border-box;font-weight:600;font-style:italic}#wpacu-dom-get-type-selections,.wpacu-radio-selections{float:none;clear:both;width:auto;display:inline-block;margin-bottom:0;margin-top:0}#wpacu-dom-get-type-selections.wpacu-vertical,.wpacu-radio-selections.wpacu-vertical{display:block;margin-top:15px;margin-bottom:18px}#wpacu-dom-get-type-selections.wpacu-vertical li,.wpacu-radio-selections.wpacu-vertical li{float:none;margin-bottom:12px}#wpacu-dom-get-type-selections.wpacu-vertical li:last-child,.wpacu-radio-selections.wpacu-vertical li:last-child{margin-bottom:0}#wpacu-dom-get-type-selections li,.wpacu-radio-selections li{margin-right:30px;float:left;margin-bottom:0}#wpacu-dom-get-type-selections li:first-child,.wpacu-radio-selections li:first-child{margin-right:15px}#wpacu-dom-get-type-selections li:last-child,.wpacu-radio-selections li:last-child{margin-right:0}.wpacu_combine_loaded_js_level_area{display:none;background:0 0;border-left:2px solid #008f9c;padding-top:8px;padding-bottom:8px;padding-right:10px;padding-left:10px;margin:20px 0 15px}.wpacu_combine_loaded_js_level_area.wpacu_active{display:block}#wpacu-dom-get-type-infos{margin-bottom:0}#wpacu-dom-get-type-infos li{margin-bottom:0;line-height:20px}.wpacu-wrap li,.wpacu-wrap p,.wpacu-wrap td{font-weight:400}.wpacu-wrap small{width:auto;float:none;display:inline}.wpacu-wrap.wpacu-settings-show-all .wpacu-settings-tab-content{display:block;width:100%}.wpacu-wrap.wpacu-settings-show-all .wpacu-settings-area-title{color:#004567;padding:16px 15px;background:#f8f8f8;border-left:5px solid #004567b0;border-top:1px solid #e7e7e7;border-right:1px solid #e7e7e7;border-bottom:1px solid #e7e7e7;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;font-size:1.45em;font-weight:500}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider.wpacu_round,.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch .wpacu_slider.wpacu_round{border-radius:29px}.wpacu-wrap.wpacu-settings-show-all #wpacu-update-button-area{margin:0}.wpacu-wrap.wpacu-settings-show-all #wpacu-update-button-area .button{padding:11px 28px;height:auto;font-size:18px}.wpacu-wrap.wpacu-settings-show-all #wpacu-updating-settings{margin-left:224px;top:25px}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch{width:auto;height:auto}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch input,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch input{display:block}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch input[type=checkbox],.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch input[type=checkbox]{margin:0 0 3px}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch .wpacu_slider,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch .wpacu_slider{display:none}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch{position:relative;display:inline-block;width:52px;height:29px}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input{display:none}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch:not(.wpacu_switch_standard) .wpacu_slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.2s;transition:.2s}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch:not(.wpacu_switch_standard) .wpacu_slider:before{position:absolute;content:'';height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.2s;transition:.2s}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:checked+.wpacu_slider{background-color:#52af00}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:focus+.wpacu_slider{box-shadow:0 0 1px #52af00}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:checked+.wpacu_slider:before{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch .wpacu_slider.wpacu_round:before{border-radius:50%}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_disabled,.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_locked_for_pro{opacity:.3}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_disabled:before{content:"\f160";font-family:Dashicons,Arial,"Times New Roman","Bitstream Charter",Times,serif;position:absolute;font-size:23px;top:5px;right:2px;z-index:1000}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle{margin-top:4px;line-height:1.4}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle em,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle em{font-weight:200}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_read_more,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_read_more{margin-top:-10px;font-style:italic;font-size:12px}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices{list-style:none;margin:0}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices li,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices li{float:left;margin-right:30px}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li:last-child,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li:last-child,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices li:last-child{margin-right:0}#wpacu-assets-list-by-location-selected{background:0 0;border:1px solid #e7e7e7;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:8px;clear:both}.notice.notice-success+.wpacu-wrap.wpacu-settings-area{margin-top:20px}.wpacu-form-table th{vertical-align:top;text-align:left;padding:5px 20px 20px 0;width:200px;line-height:1.3;font-weight:600}.wpacu-form-table th label{color:#23282d;font-weight:600;font-size:14px;text-shadow:none;vertical-align:middle;cursor:pointer}.wpacu-form-table td{padding-bottom:25px}.wpacu-form-table td:last-child p:last-child{margin:0}.wpacu-form-table label input[type=checkbox]{height:19px;width:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.wpacu-form-table label input[type=checkbox]:checked,.wpacu-form-table label input[type=checkbox]:hover{border:1px solid green}.wpacu-form-table label input[type=checkbox]:checked:before{color:#52af00;font:400 24px/1 dashicons}#wpacu-settings-vertical-tab-wrap{display:table;width:100%}#wpacu-settings-vertical-tab-wrap *{box-sizing:border-box}.wpacu-settings-tab{display:table-cell;width:19%;height:100%;vertical-align:top}.wpacu-settings-tab a{text-decoration:none;border-left:3px solid transparent;display:block;background-color:#f1f1f1;color:#004567;padding:17px 16px;width:100%;outline:0;text-align:left;cursor:pointer;font-size:14px;font-weight:600;border-bottom:1px solid #ccc}.wpacu-settings-tab a:first-child{border-top:1px solid transparent!important}.wpacu-settings-tab a:last-child{border-bottom:1px solid transparent!important}.wpacu-settings-tab a:hover{background-color:#fff;border-left:3px solid #004567;position:relative}.wpacu-settings-tab a.active{color:#004567;background-color:#fff;border-left:3px solid #004567;position:relative;border-bottom:1px solid #ccc}.wpacu-settings-tab a.active:after{content:'';position:absolute;height:100%;width:1px;top:0;right:-1px;background-color:#fff}.wpacu-settings-tab-content{background-color:#fff;display:none;padding:12px 18px;width:79%;border-left:none;height:100%;border-top-right-radius:10px;border-bottom-right-radius:10px}.wpacu-settings-tab-content h2{padding:0 0 15px;border-bottom:1px solid #e7e7e7}.wpacu-settings-tab-content.active{display:table-cell}#wpacu_minify_css_exceptions_area,#wpacu_minify_js_exceptions_area{margin:16px 0 0}#wpacu-update-button-area{position:relative;margin-left:19%}#wpacu-update-button-area.no-left-margin{margin-left:0}#wpacu-update-button-area p{margin-top:10px}#wpacu-update-button-area .button{padding:5px 18px;height:38px;font-size:15px}#wpacu-updating-settings{position:absolute;margin-left:183px;top:19px;display:none}#combine_loaded_js_info_area{position:relative}#combine_loaded_js_info_area.locked-for-pro:before{position:absolute;content:'';height:100%;width:100%;background:#fff;opacity:.5;z-index:10000}body.wp-admin .wpacu-handle-notes{margin-top:10px!important}body.wp-admin .wpacu-handle-notes p{margin-top:0!important}body.wp-admin .wpacu-handle-notes p a{font-size:inherit}body.wp-admin .wpacu-handle-notes p a span.dashicons{font-size:19px;width:19px;height:19px;vertical-align:bottom;text-decoration:none}.wpacu-handle-notes{margin-top:12px!important;padding-top:5px;border-top:1px solid #e7e7e7}.wpacu-handle-notes .wpacu-handle-notes-field{display:none}.wpacu-handle-notes .wpacu-handle-notes-field>textarea{font-size:85%;padding:6px;width:320px;max-width:100%}.wpacu-handle-notes p{margin:10px 0 0!important}.wpacu-handle-notes p a.wpacu-add-handle-note{text-decoration:none;font-size:80%;display:inline-block;color:inherit}.wpacu-handle-notes p a.wpacu-add-handle-note span.dashicons{font-size:18px;width:18px;height:18px}.wrap_bulk_unload_options{width:auto;display:inline-flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.wrap_bulk_unload_options .wpacu_asset_options_wrap{flex-grow:1;margin:5px 10px 14px 0!important;padding:8px 10px 2px!important}.wrap_bulk_unload_options .wpacu_asset_options_wrap .wpacu_slider_text{position:relative!important;vertical-align:top;left:inherit!important;top:inherit!important}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch{position:relative;display:inline-block;min-width:52px;width:52px;height:29px;margin-right:5px!important}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input{display:none}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.15s;transition:.15s}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider:before{position:absolute;content:'';height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.15s;transition:.15s}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:checked+.wpacu_slider{background-color:#C00}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:focus+.wpacu_slider{box-shadow:0 0 1px #C00}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:checked+.wpacu_slider:before{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider.wpacu_round:before{border-radius:50%}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_slider_text{position:absolute;left:62px;top:3px}.editor-post-saved-state.is-wpacu-reloading{animation:edit-post__loading-fade-animation .5s infinite}body.wp-admin .wpacu_asset_row.wpacu-loading{position:relative}body.wp-admin .wpacu_asset_row.wpacu-loading .wpacu-ajax-loader{display:block!important}body.wp-admin .wpacu_asset_row .wpacu-ajax-loader{display:none;width:58px;height:58px;position:absolute;bottom:0;right:0;opacity:.75}.wpacu_asset_row input{width:auto;height:auto;min-height:16px}.wpacu_asset_row .tip{background:inherit;border-left:4px solid #e7e7e7;margin:5px 0;padding:7px;font-style:italic;font-size:small;line-height:1.4}.wpacu_asset_row td{width:100%;text-align:left}.wpacu_asset_row td p:last-child{margin-bottom:0!important}.wpacu_asset_row td .wpacu_asset_options_wrap{padding:8px 10px;margin:15px 0;background:#fff;border:1px solid #eee;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu_asset_row td .wpacu_asset_options_wrap p:first-child{margin-top:0;margin-bottom:8px!important}.wpacu_asset_row p.wpacu_handle{margin-top:0}.wpacu_asset_row li.wpacu_unload_this_page{display:block!important;position:relative}.wpacu-clearfix:after,.wpacu-clearfix:before{display:table;content:''}.wpacu-contract-expand-area{width:100%;margin:20px 0 0}.wpacu-contract-expand-area .col-left{float:left}.wpacu-contract-expand-area .col-left h4{margin-bottom:0}.wpacu-contract-expand-area .col-right{float:right}.wpacu-clearfix:after{clear:both}.wpacu-wp-button{color:#555;border-color:#ccc;background:#f7f7f7;box-shadow:0 1px 0 #ccc;vertical-align:top}body.wp-admin .wpacu-wp-button{font-size:13px;line-height:26px;height:28px}.wpacu-wp-button.wpacu-wp-button-secondary{display:inline-block;text-decoration:none;height:auto;margin:0 5px 0 0;padding:0 10px 1px;cursor:pointer;border-width:1px;border-style:solid;-webkit-appearance:none;border-radius:3px;white-space:nowrap;box-sizing:border-box}.wpacu-wp-button:hover{background:#fafafa;border-color:#999;color:#23282d}.distinguish-asset-list{list-style:none;margin-left:0;margin-bottom:5px;display:inline-block}.distinguish-asset-list li{float:left;margin-right:20px}.distinguish-asset-list li:last-child{margin-right:0}body[class*=asset-cleanup-pro] a.wpacu-plugin-contracted-wrap-link{padding:16px 6px 16px 41px!important}body[class*=asset-cleanup-pro] .wpacu-area-open .wpacu-plugin-toggle-all{font-size:12px!important;width:calc(100% - 26px)!important}body.wp-admin .wpacu-area-expanded .wpacu-plugin-toggle-all{top:5px}body.wp-admin .wpacu-area-expanded .wpacu-plugin-toggle-all ul li{font-size:12px!important}.wpacu-assets-collapsible-wrap{border:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location{margin-bottom:15px}.wpacu-assets-collapsible-wrap.wpacu-wrap-all{margin-top:20px}.wpacu-assets-collapsible-wrap.wpacu-wrap-area{margin-top:10px}.wpacu-assets-collapsible-wrap.wpacu-by-location>a.wpacu-assets-collapsible{padding:15px 15px 15px 43px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu_list_table{border-width:0;margin:0;border-spacing:inherit;width:100%;box-shadow:3px 3px 2px #ddd;border-bottom-right-radius:5px;border-top-right-radius:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location span.wpacu-child-location-name{font-weight:600}.wpacu-assets-collapsible-wrap.wpacu-by-location span.wpacu-child-location-version{font-weight:200}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area[data-wpacu-plugin=oxygen] .icon-area{border-radius:50%}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all{display:inline-block;padding:0;font-size:13px;width:100%;width:calc(100% + 46px);min-width:250px;position:absolute;left:100%;left:calc(100% + 6px);margin:0;top:4px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul{display:inline-block;margin:0;list-style:none;padding-left:13px;padding-top:0}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul li{padding:0;margin:0;line-height:normal;font-size:14px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul li:first-child{font-style:italic;margin-bottom:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content>table:last-child{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{display:inline;position:relative;z-index:1}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title:after{content:'';position:absolute;width:100%;left:0;bottom:0;height:1px;background-color:#fdfdfd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap{padding:0 0 10px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap.wpacu-area-open .wpacu-plugin-toggle-all{display:inline-block;padding:7px 12px 16px;font-size:14px;width:100%;text-align:left;border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap.wpacu-area-open.wpacu-plugin-assets-last{margin-bottom:18px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link{color:inherit;text-decoration:none;font-weight:inherit;font-style:inherit;font-size:105%;line-height:initial;height:auto;margin:14px 0 0;padding:13px 6px 14px 39px;position:relative;display:block}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:after{position:absolute;font-size:18px;font-family:Dashicons;right:12px;top:14px;content:"\f132"}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-open:after{content:"\f460"}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-closed{border:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:hover{border:1px solid #878787;background:#f9f9f9}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:hover.wpacu-link-closed{box-shadow:3px 3px 2px #ddd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-open{border-top:1px solid #cdcdcd;border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd;border-bottom:none}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-closed.wpacu-last-wrap-link{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default{top:10px;left:10px;width:30px;height:30px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default .icon-area{width:30px;height:30px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default .icon-area:before{font-size:22px;line-height:22px;top:4px;left:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .wpacu-area-title{position:relative;padding:17px 10px 16px 46px;z-index:1}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .wpacu-area-title:after{content:'';position:absolute;width:100%;left:0;bottom:0;height:1px;background-color:#fdfdfd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-area-last{margin-bottom:18px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-area-open{padding:0;max-height:100%}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-area-closed{padding:0;overflow:hidden;max-height:0}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content>table:last-child{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{margin-top:0;margin-bottom:-1px;padding:14px 10px 16px 12px!important}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title.wpacu-theme-has-icon{padding:18px 10px 16px 58px!important}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area{margin-top:22px;margin-bottom:-1px;font-size:110%;line-height:initial}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area.wpacu-location-child-area-first{margin-top:2px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area.wpacu-area-expanded .wpacu-area-title{display:inline-block;z-index:1;padding:17px 10px 16px 46px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{display:inline;border-top-right-radius:8px;border-top-left-radius:8px;background-color:#f9f9f9;border-left:1px solid #cdcdcd;border-top:1px solid #cdcdcd;border-bottom:1px solid transparent;border-right:1px solid #cdcdcd;position:relative}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default{position:absolute;padding:0;top:10px;left:10px;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default:not(.has-icon){color:#b4b9be;background-color:#eee;box-shadow:inset 0 0 10px rgba(160,165,170,.15);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default:not(.has-icon) .icon-area:before{content:"\f106";font-family:Dashicons;position:absolute;font-size:28px;line-height:28px;top:5px;left:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default .icon-area{position:relative;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-theme{position:absolute;padding:0;top:10px;left:10px;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-theme .icon-area{position:relative;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-wp_core{border:1px solid #c00}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content{padding:0}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table{width:100%;margin:0}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row td,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row td{border-left:hidden;border-right:hidden;border-bottom:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child{margin-bottom:0!important}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child td:last-child,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child td:last-child{border-bottom:hidden}a.wpacu-assets-collapsible{color:#000;font-size:20px;text-decoration:none;display:block;position:relative;background-color:#f1f3f8;cursor:pointer;padding:15px 15px 15px 36px;width:auto;border:none;text-align:left;outline:0}a.wpacu-assets-collapsible>span.dashicons{font-size:25px;line-height:normal;position:absolute;top:15px;top:calc(50% - 21px);left:22px;-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}a.wpacu-assets-collapsible:hover{background-color:#f1f3f8;text-decoration:none}a.wpacu-assets-collapsible:after{position:absolute;font-size:22px;font-family:Dashicons;right:14px;top:16px}a.wpacu-assets-collapsible:not(.wpacu-assets-collapsible-active):after{content:"\f132"}a.wpacu-assets-collapsible.wpacu-assets-collapsible-active{background-color:#f1f3f8}a.wpacu-assets-collapsible.wpacu-assets-collapsible-active:after{content:"\f460"}.wpacu-assets-collapsible-content{padding:0 16px;max-height:0;overflow:hidden;background-color:#fbfbfb8c}.wpacu-assets-collapsible-content .wpacu-assets-note{margin:0;padding:15px 15px 10px}.wpacu-assets-collapsible-content>div:not(.wpacu-assets-table-list-wrap){padding:16px 0 0}.wpacu-assets-collapsible-content>div>p:first-child{margin-top:0}.wpacu-assets-collapsible-content.wpacu-open{max-height:100%}a.wpacu-assets-inline-code-collapsible{color:inherit;font-size:14px;text-decoration:none;display:inline-block;position:relative;cursor:pointer;width:auto;outline:0;background:#f1f3f8;border:1px solid #cdcdcd;padding:4px 21px 4px 8px;margin:0 0 0 6px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}a.wpacu-assets-inline-code-collapsible:hover{border:1px solid #5c5c5c}a.wpacu-assets-inline-code-collapsible:after{position:absolute;font-size:15px;font-family:Dashicons;right:-3px;top:-1px;width:14px;height:14px;-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}a.wpacu-assets-inline-code-collapsible:not(.wpacu-assets-inline-code-collapsible-active):after{content:"\f132"}a.wpacu-assets-inline-code-collapsible.wpacu-assets-inline-code-collapsible-active:after{content:"\f460"}.wpacu-assets-inline-code-collapsible-content{font-size:80%;padding:0 8px;max-height:0;overflow:hidden;background-color:#fbfbfb8c}.wpacu-assets-inline-code-collapsible-content>div{padding:7px 8px 0}.wpacu-assets-inline-code-collapsible-content>div>p{line-height:normal!important}.wpacu-assets-inline-code-collapsible-content>div>p:first-child{margin-top:0}.wpacu-assets-inline-code-collapsible-content.wpacu-open{max-height:100%}.wpacu_asset_row p div.select{display:inline-block}.wpacu-wrap-choose-position{display:inline}.wpacu-wrap-choose-position>div{display:inline-block}.wpacu-wrap-choose-position select{width:auto;font-size:inherit;display:inline;margin-left:6px;margin-right:4px}.wpacu-wrap-choose-position>.select>.select{display:inline}.wpacu-wrap-choose-position>.select>.select select{padding-right:30px}.wpacu-wrap-choose-position>.select>.select:after{right:15px;top:-4px}.wpacu_table_wrap{margin:20px 0 0}.wpacu_table_wrap>table{border:1px solid #cdcdcd}.wpacu_table_wrap .table{width:100%;max-width:100%;margin-bottom:1rem;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu_table_wrap .table td,.wpacu_table_wrap .table th{padding:.75rem;vertical-align:top;border-top:1px solid #eceeef}.wpacu_table_wrap .table thead th{vertical-align:bottom;border-bottom:2px solid #eceeef}.wpacu_table_wrap .table tbody+tbody{border-top:2px solid #eceeef}.wpacu_table_wrap .table .table{background-color:#fff}.wpacu_table_wrap .table-sm td,.wpacu_table_wrap .table-sm th{padding:.3rem}.wpacu_table_wrap .table-bordered,.wpacu_table_wrap .table-bordered td,.wpacu_table_wrap .table-bordered th{border:1px solid #eceeef}.wpacu_table_wrap .table-bordered thead td,.wpacu_table_wrap .table-bordered thead th{border-bottom-width:2px}.wpacu_table_wrap .table-striped tbody tr:nth-of-type(even){background-color:#f9f9f9}.wpacu_table_wrap .table-striped tbody tr:nth-of-type(odd){background-color:#fff}.wpacu_table_wrap .table-active,.wpacu_table_wrap .table-active>td,.wpacu_table_wrap .table-active>th,.wpacu_table_wrap .table-hover .table-active:hover,.wpacu_table_wrap .table-hover .table-active:hover>td,.wpacu_table_wrap .table-hover .table-active:hover>th,.wpacu_table_wrap .table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.wpacu_table_wrap .table-success,.wpacu_table_wrap .table-success>td,.wpacu_table_wrap .table-success>th{background-color:#dff0d8}.wpacu_table_wrap .table-hover .table-success:hover,.wpacu_table_wrap .table-hover .table-success:hover>td,.wpacu_table_wrap .table-hover .table-success:hover>th{background-color:#d0e9c6}.wpacu_table_wrap .table-info,.wpacu_table_wrap .table-info>td,.wpacu_table_wrap .table-info>th{background-color:#d9edf7}.wpacu_table_wrap .table-hover .table-info:hover,.wpacu_table_wrap .table-hover .table-info:hover>td,.wpacu_table_wrap .table-hover .table-info:hover>th{background-color:#c4e3f3}.wpacu_table_wrap .table-warning,.wpacu_table_wrap .table-warning>td,.wpacu_table_wrap .table-warning>th{background-color:#fcf8e3}.wpacu_table_wrap .table-hover .table-warning:hover,.wpacu_table_wrap .table-hover .table-warning:hover>td,.wpacu_table_wrap .table-hover .table-warning:hover>th{background-color:#faf2cc}.wpacu_table_wrap .table-danger,.wpacu_table_wrap .table-danger>td,.wpacu_table_wrap .table-danger>th{background-color:#f2dede}.wpacu_table_wrap .table-hover .table-danger:hover,.wpacu_table_wrap .table-hover .table-danger:hover>td,.wpacu_table_wrap .table-hover .table-danger:hover>th{background-color:#ebcccc}.wpacu_table_wrap .thead-inverse th{color:#fff;background-color:#292b2c}.wpacu_table_wrap .thead-default th{color:#464a4c;background-color:#eceeef}.wpacu_table_wrap .table-inverse{color:#fff;background-color:#292b2c}.wpacu_table_wrap .table-inverse td,.wpacu_table_wrap .table-inverse th,.wpacu_table_wrap .table-inverse thead th{border-color:#fff}.wpacu_table_wrap .table-inverse.table-bordered,.wpacu_table_wrap .table-responsive.table-bordered{border:0}.wpacu_table_wrap .table-responsive{display:block;width:100%;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.wp-list-table .wpacu_remove_global_attr_row.wpacu_selected,.wp-list-table .wpacu_restore_position_row.wpacu_selected{background:#e7e7e7}ul.hire-reasons{margin-bottom:20px}ul.hire-reasons li{font-size:14px;line-height:22px;margin-bottom:12px}ul.hire-reasons li .dashicons{font-size:23px;line-height:23px}ul.hire-reasons li .dashicons.dashicons-yes{color:green}ol.getting-started li{font-size:14px;line-height:22px;margin-bottom:8px}.wpacu-get-help-wrap p{font-size:14px}.wpacu-get-help-wrap .help-content-wrap{margin:20px 0 25px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-moz-flex;display:-webkit-flex;display:flex;width:100%}@media only screen and (min-width:768px){.wpacu-get-help-wrap .help-content-wrap{-webkit-box-align:start;-ms-flex-align:start;-ms-grid-row-align:flex-start;align-items:flex-start}}@media only screen and (max-width:767px){.wpacu-get-help-wrap .help-content-wrap{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.wpacu-get-help-wrap .help-content-wrap .help-content{padding:15px;background:#fff;border:1px solid #E0E0E0;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;box-shadow:2px 3px 8px 0 #231f2038;flex:1 1 50%;margin-bottom:10px}.wpacu-get-help-wrap .help-content-wrap .help-content .content-title{margin:5px 0 15px}.wpacu-get-help-wrap .help-content-wrap .help-content .cols-wrap{width:100%;margin:0 auto;display:table}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area{margin:5px 0 0;position:relative}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.col-left{float:left;width:48%}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.col-right{float:right;width:48%}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.activate-plugin img{max-width:280px}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area img{width:99%;margin:8px 0;border:1px solid #cdcdcd;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-get-help-wrap .help-content-wrap .help-content.upgrade-help{order:2}@media only screen and (min-width:768px){.wpacu-get-help-wrap .help-content-wrap .help-content{margin-right:24px}.wpacu-get-help-wrap .help-content-wrap .help-content.upgrade-help{margin-right:0}}.wpacu-get-help-wrap .help-content-wrap .help-content.tech-help{order:1}@media only screen and (max-width:767px){.wpacu-get-help-wrap .help-content-wrap .help-content.tech-help{margin-bottom:30px}}.wpacu-get-help-wrap .help-content-wrap .help-content ul{list-style:none;padding-left:0}.wpacu-get-help-wrap .help-content-wrap .help-content ul li{font-size:14px;line-height:22px;margin-bottom:15px}.wpacu-get-help-wrap .help-content-wrap .help-content p:last-child,.wpacu-get-help-wrap .help-content-wrap .help-content ul li:last-child{margin-bottom:0}#wpacu-license-data-remove-area{display:none;margin:10px 0 25px}#wpacu-license-data-remove-area.wpacu-visible{display:block}span#wpacu-license-data-removed-msg{display:block;padding-left:26px}#wpacu-warning-read{display:none;margin:10px 0}#wpacu-warning-read span.dashicons-warning{color:#c00}#wpacu-warning-read.wpacu-visible{display:block}#wpacu-reset-submit-area{margin:10px 0;clear:both}#wpacu-reset-submit-btn{margin:10px 0 0}.wpacu-tools-area{margin:10px 20px 0 2px}.wpacu-tools-area .wpacu-tools-container{background:#fff;padding:15px;border:1px solid #cdcdcd;width:96%}.wpacu-tools-area .wpacu-tools-container form>div:first-child{margin:0 0 10px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning{display:none;box-sizing:border-box;margin-top:10px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning p{margin:0 0 10px;line-height:22px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning p:only-child{margin:0}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning ul{font-size:13px;list-style-type:disc;padding-left:30px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning.wpacu-visible{display:block}.wpacu-tools-area .wpacu-export-import-area{padding:10px}.wpacu-tools-area .wpacu-export-import-area form>p:first-of-type{margin-top:0}.wpacu-tools-area .wpacu-export-import-area form>p:last-of-type{margin-bottom:0}.wpacu-tools-area .wpacu-export-import-area:hover{background:rgba(40,44,42,.05);box-shadow:inset 0 0 10px rgba(160,165,170,.15)}.wpacu-tools-area .wpacu-export-import-area+hr{display:block;height:1px;border:0;border-top:1px solid #cdcdcd;margin:10px 0;padding:0}#wpacu-import-form button.wpacu-importing img.wpacu-spinner{display:inline-block}#wpacu-import-form button img.wpacu-spinner{display:none;margin:0 0 0 5px;height:16px;width:16px;vertical-align:middle}.wpacu-about-wrap .wpacu-about-text img{width:auto;height:150px;position:absolute;top:20px;right:-20px}@media only screen and (max-width:767px){.wpacu-about-wrap h1{margin:20px}.wpacu-about-wrap .wpacu-about-text img{display:none}.wpacu-about-wrap .wpacu-about-text{margin:20px}}.wpacu-about-wrap .about-wrap-content .area-title{font-size:19px;line-height:19px;margin-bottom:0}.wpacu-about-wrap hr{margin:10px 0}.wpacu-lite-vs-pro-wrap ul{display:flex;top:0;z-index:10;padding-bottom:14px}.wpacu-lite-vs-pro-wrap li{list-style:none;flex:1}.wpacu-lite-vs-pro-wrap li:last-child{border-right:1px solid #DDD}.wpacu-lite-vs-pro-wrap button{width:100%;border:1px solid #DDD;border-right:0;border-top:0;padding:10px;background:#FFF;font-size:14px;font-weight:700;height:60px;color:#999}.wpacu-lite-vs-pro-wrap li.active button{background:#F5F5F5;color:#000}.wpacu-lite-vs-pro-wrap table{border-collapse:collapse;table-layout:fixed;width:100%}.wpacu-lite-vs-pro-wrap th{background:inherit}.wpacu-lite-vs-pro-wrap tr.first{background:inherit;font-size:18px}.wpacu-lite-vs-pro-wrap tr.first .bg-lite{border-top:4px solid #6d6e70;background:#fff;color:#6d6e70}.wpacu-lite-vs-pro-wrap tr.first .bg-pro{border-top:4px solid green;background:#fff;color:green}.wpacu-lite-vs-pro-wrap tr:not(.first){background:#fff}.wpacu-lite-vs-pro-wrap tr:not(:last-child):hover{background:#f8f8f8}.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{height:53px;border:1px solid #DDD;padding:10px 16px;empty-cells:show;text-align:left}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{font-size:14px}}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{text-align:center;display:none}.wpacu-lite-vs-pro-wrap td.default{display:table-cell}.wpacu-lite-vs-pro-wrap .txt-l{font-size:28px;font-weight:700}.wpacu-lite-vs-pro-wrap .txt-top{position:relative;top:-9px;left:-2px}.wpacu-lite-vs-pro-wrap svg{width:18px;height:18px}.wpacu-lite-vs-pro-wrap svg path{fill:green}.wpacu-lite-vs-pro-wrap .tick{color:#2CA01C}.wpacu-lite-vs-pro-wrap .tick img{fill:#2CA01C}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap .txt-l{font-size:20px}.wpacu-lite-vs-pro-wrap .tick{font-size:15px}}.wpacu-lite-vs-pro-wrap .na{font-size:18px;opacity:.3;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"}.wpacu-lite-vs-pro-wrap .hide{border:0;background:0 0}.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{display:table-cell!important;width:auto}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{width:130px}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap .na{font-size:15px}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{width:42px}}@media only screen and (min-width:768px){.wpacu-lite-vs-pro-wrap td .button{font-size:16px!important}}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap td .button{font-size:14px!important;padding:0 20px!important}.wpacu-lite-vs-pro-wrap td .button.button-primary{margin-top:6px;margin-bottom:14px}}@media only screen and (min-width:768px){.wpacu-lite-vs-pro-wrap{margin-bottom:40px;clear:both}}.wpacu-video-areas>div{padding:20px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-video-areas>div:nth-child(odd){background:#fff}.wpacu-video-areas>div:nth-child(even){background:inherit}@media only screen and (min-width:1200px){.wpacu-video-areas .wpacu-video-area-wrapper{margin:0 0 15px;display:flex}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right{padding:0 20px 0 25px}}@media only screen and (min-width:992px) and (max-width:1199px){.wpacu-video-areas .wpacu-video-area-wrapper{margin:0 0 40px}}.wpacu-video-areas .wpacu-video-area-wrapper ol{font-size:14px}.wpacu-video-areas .wpacu-video-area-wrapper ul{font-size:14px;list-style:disc;margin-left:22px}@media only screen and (min-width:1200px){.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right p:first-child{margin-top:0}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right p:last-child{margin-bottom:0}}@media only screen and (max-width:1199px){.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-video-wrapper{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-video-wrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}}#wpassetcleanup_asset_list.postbox h2{padding-left:52px!important;position:relative}#wpassetcleanup_asset_list.postbox h2:before{content:'';position:absolute;background-image:url(images/wpacu-logo-transparent-bg-v1.png);background-size:cover;top:6px;left:13px;width:33px;height:26px;opacity:.8;-webkit-filter:grayscale(100%);filter:grayscale(100%)}body.wp-admin .wpacu-modal{display:none;position:fixed;z-index:1000000;padding-top:15%;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.4)}body.wp-admin .wpacu-modal-content{background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888;width:80%;max-width:600px;border-radius:10px}body.wp-admin .wpacu-close{color:#aaa;float:right;font-size:28px;font-weight:700}body.wp-admin .wpacu-close:focus,body.wp-admin .wpacu-close:hover{color:#000;text-decoration:none;cursor:pointer}.wpacu-bulk-changes-tabs{display:table;position:relative;overflow:hidden;margin:0;width:100%}.wpacu-bulk-changes-tabs li{border-top:1px solid rgba(40,44,42,.1);border-left:1px solid rgba(40,44,42,.1);border-bottom:1px solid rgba(40,44,42,.1);float:left;line-height:38px;padding:0;position:relative;margin-bottom:12px}.wpacu-bulk-changes-tabs li:last-child{border-right:1px solid rgba(40,44,42,.1)}.wpacu-bulk-changes-tabs a{position:relative;background:rgba(40,44,42,.05);color:#004567;font-size:14px;font-weight:500;display:block;letter-spacing:0;outline:0;padding:6px 20px;text-decoration:none;border-top:3px solid transparent}.wpacu-bulk-changes-tabs a:hover{background:#f1f1f1;border-top:3px solid transparent}.wpacu-bulk-changes-tabs .current a{background:#fff;border-top:3px solid #004567}.wpacu-bulk-changes-tabs .current a:hover{background:#fff}.wpacu-bulk-changes-tabs .current a:after,.wpacu-bulk-changes-tabs .current a:before{top:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.wpacu-bulk-changes-tabs .current a:after{border-color:rgba(136,183,213,0);border-top-color:#fff;border-width:12px;margin-left:-12px}.wpacu-bulk-changes-tabs .current a:before{border-color:rgba(194,225,245,0);border-top-color:rgba(40,44,42,.1);border-width:13px;margin-left:-13px}
1
+ #wpacu-pages-info-area{width:98%}#wpacu-top-area{margin:15px 0;padding:0 10px}#wpacu-quick-actions{color:#74777b;float:right;width:auto;margin-right:30px;background:rgba(40,44,42,.05);border-radius:10px;padding:6px 12px}#wpacu-quick-actions .wpacu-actions-title{font-weight:200;letter-spacing:.5px}#wpacu-quick-actions a{color:#004567;text-decoration:none}#wpacu-quick-actions a:hover{color:#0073aa}#wpacu-logo-wrap{width:auto;display:inline-block;position:relative}#wpacu-logo-wrap a{display:block}#wpacu-logo-wrap img{width:352px;height:79px}#wpacu-logo-wrap .wpacu-pro-sign{position:absolute;height:auto;font-family:FiraSans-Medium,proxima-nova-1,Montserrat,Helvetica,sans-serif;font-size:13px;font-weight:600;letter-spacing:1px;padding:5px 11px;border-radius:15px;right:-60px;top:30px;width:auto;display:inline-block;text-align:center}#wpacu-logo-wrap .wpacu-pro-sign.wpacu-lite{color:#74777b;background:rgba(40,44,42,.05)}#wpacu-logo-wrap .wpacu-pro-sign.wpacu-pro{color:#004567;background-color:rgba(40,44,42,.05)}#wpacu_meta_box_content .dashicons.dashicons-warning,.wpacu-tabs nav ul li span.extra-info.license-status.inactive{color:#c00}.wpacu-tabs{position:relative;overflow:hidden;margin:0 auto 20px;width:100%;font-weight:300;font-size:20px}.wpacu-tabs nav{text-align:center}.wpacu-tabs nav ul{position:relative;display:-ms-flexbox;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:flex;margin:0 auto;padding:0;max-width:1200px;list-style:none;-ms-box-orient:horizontal;-ms-box-pack:center;-webkit-flex-flow:row wrap;-moz-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center}.wpacu-tabs nav ul li{position:relative;z-index:1;display:block;margin:0;text-align:center;-webkit-flex:1;-moz-flex:1;-ms-flex:1;flex:1}.wpacu-tabs nav ul li span.extra-info{position:absolute;font-size:12px;left:0;right:50%;bottom:12px;-webkit-transform:translate(50%,50%);transform:translate(50%,50%)}.wpacu-tabs nav ul li span.extra-info .dashicons{font-size:16px;margin-right:-3px;margin-top:1px}.wpacu-tabs nav ul li span.extra-info.license-status.active{color:green}.wpacu-tabs nav ul li span.extra-info.assets-unloaded-false{color:#004567}.wpacu-license-area .notice .dashicons,.wpacu-settings-area .notice .dashicons,.wpacu-tabs nav ul li span.extra-info.assets-unloaded-true,.wpacu-tabs nav ul li span.extra-info.bulk-unloads-true{color:green}.wpacu-tabs nav a{position:relative;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:2.5}.wpacu-tabs nav a span{vertical-align:middle;font-size:14px}.wpacu-tabs nav li.wpacu-tab-current a{color:#74777b}.wpacu-tabs nav a:focus{outline:0}.wpacu-tabs .dashicons{font-size:20px}.no-js .wpacu-content-wrap section{display:block;padding-bottom:2em;border-bottom:1px solid rgba(255,255,255,.6)}.no-flexbox nav ul{display:block}.no-flexbox nav ul li{min-width:15%;display:inline-block}@media screen and (max-width:58em){.wpacu-tabs nav a.icon span{display:none}.wpacu-tabs nav a:before{margin-right:0}}.wpacu-tabs-style-underline nav{background:#fff}.wpacu-tabs-style-underline nav a{color:#74777b;font-size:18px;text-transform:uppercase;text-decoration:none;padding:.25em 0 .5em;border-left:1px solid #e7ecea;-webkit-transition:color .2s;transition:color .2s}.wpacu-tabs-style-underline nav li:last-child a{border-right:1px solid #e7ecea}.wpacu-tabs-style-underline nav li a::after{position:absolute;bottom:0;left:0;width:100%;height:6px;background:#2CC185;content:'';-webkit-transition:-webkit-transform .3s;transition:transform .3s;-webkit-transform:translate3d(0,150%,0);transform:translate3d(0,150%,0)}.wpacu-tabs-style-underline nav li.wpacu-tab-current a::after{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.wpacu-tabs-style-underline nav a span{font-weight:700}.wpacu-tabs-style-topline{max-width:1200px;margin:20px auto 30px 0;width:100%;font-weight:300;text-decoration:none}.wpacu-tabs-style-topline nav li{border:1px solid rgba(40,44,42,.1)}.wpacu-tabs-style-topline nav li:not(:last-child){border-right:none}.wpacu-tabs-style-topline nav li.wpacu-tab-current{border-top-color:#008f9c;border-bottom:none}.wpacu-tabs-style-topline nav a{padding:20px 18px;background:rgba(40,44,42,.05);color:#74777b;line-height:1;-webkit-transition:color .2s;transition:color .2s;text-decoration:none}.wpacu-tabs-style-topline nav a:focus,.wpacu-tabs-style-topline nav a:hover{background:0 0;color:#008f9c}.wpacu-tabs-style-topline nav li.wpacu-tab-current a{background:0 0;box-shadow:inset 0 3px 0 #008f9c;color:#008f9c}.wpacu-tabs-style-topline nav li.wpacu-tab-current a span:not(.dashicons){font-weight:600}.wpacu-tabs-style-topline nav a span{text-transform:uppercase;font-weight:400}.wpacu-tab-nav-wrapper{border-bottom:none!important}.wpacu-tab-nav-wrapper .nav-tab.nav-tab-active{background:#fff;position:relative}.wpacu-tab-nav-wrapper .nav-tab.nav-tab-active:after{content:'';width:100%;bottom:-2px;left:0;position:absolute;border-bottom:2px solid #fff}.wpacu-script-attributes-area{margin:20px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings{padding:5px 7px!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings.wpacu-first{margin:0 28px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings label{margin:0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li{margin:0 16px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li:first-child{margin:0 10px 0 0!important}.wpacu-script-attributes-area.wpacu-lite ul.wpacu-script-attributes-settings li:last-child{margin:0 2px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings{background:#fff!important;border:1px solid #eee!important;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:5px 10px!important;list-style:none;display:inline-block;margin:0}.wpacu-script-attributes-area .wpacu-script-attributes-settings input[type=radio]{width:auto;padding:0;margin:0 5px 0 0}.wpacu-script-attributes-area .wpacu-script-attributes-settings.wpacu-first{margin:0 34px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings li{float:left;margin:0 17px 0 0}.wpacu-script-attributes-area .wpacu-script-attributes-settings li:first-child{margin:0 10px 0 0!important}.wpacu-script-attributes-area .wpacu-script-attributes-settings li:last-child{margin:0}.wpacu-script-attributes-area .wpacu-script-attributes-settings:hover{background:#f2faf2}tr.wpacu_location_changed>td{border-left:#004567 4px solid}tr.wpacu_not_load td,tr.wpacu_not_load th{background:#FFE1E1!important}tr.wpacu_not_load td .wpacu-assets-inline-code-wrap,tr.wpacu_not_load td .wpacu-script-attributes-area,tr.wpacu_not_load th .wpacu-assets-inline-code-wrap,tr.wpacu_not_load th .wpacu-script-attributes-area{filter:alpha(opacity=45);opacity:.45}.dashicons-wpacu{width:17px;height:17px;margin:2px 0 0;font-size:16px;text-decoration:none}#wpacu_meta_box_content,.wpacu_widefat{width:99%}.wpacu_widefat .check-column.wpacu_check{padding:10px}body[class*=wpassetcleanup] #footer-left{border-left:2px solid green;padding-left:10px}#wpassetcleanup_asset_list small{width:auto;float:none;display:inline}#wpacu_meta_box_content .emoji{font-size:18px}#wpacu_meta_box_content h3{margin-left:0;padding-left:0}#wpacu_meta_box_content div.wpacu_note{padding:10px;background-color:#f5f5f5}#wpacu_meta_box_content .wpacu_verified{padding:10px;background-color:#f5f5f5;border-left:1px solid #ddd}#wpacu_meta_box_content .wpacu_verified span{color:#0073aa;font-weight:700}#wpacu_meta_box_content div.wpacu_warning{border:1px solid #c00}#wpacu_meta_box_content ul.wpacu_asset_options{margin:0;padding:0}#wpacu_meta_box_content ul.wpacu_asset_options li{list-style:none;display:inline-block}#wpacu_meta_box_content ul.wpacu_asset_options label{font-weight:400;margin-right:5px;margin-top:5px;margin-bottom:5px}.wpacu-updated-frontend{font-weight:400;background-color:#fff;border-left:4px solid #46b450;border-top:1px solid #46b450;border-right:1px solid #46b450;border-bottom:1px solid #46b450;padding:9px 14px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu-updated-frontend span.dashicons-yes{color:#46b450;font-size:26px}#wpacu-update-front-settings-area{margin:10px 0;display:inline-block;position:relative}#wpacu-updating-front-settings{display:none;position:absolute;top:5px;right:-35px}#wpacu_wrap_assets{color:#000!important;text-align:left!important;clear:both!important;width:90%!important;padding:20px!important;margin:30px 0 0 15px!important;border:1px solid #cdcdcd;z-index:10000!important;position:relative!important;background-color:#fff!important}#wpacu_wrap_assets div.wpacu_warning{border:1px solid #c00;padding:5px 10px}#wpacu_wrap_assets small{display:inline!important;margin:0!important;letter-spacing:normal!important}#wpacu_wrap_assets input[type=checkbox]{width:auto!important;margin-right:4px!important}#wpacu_wrap_assets img:not(.wpacu-ajax-loader){display:inline-block!important}#wpacu_wrap_assets p{line-height:22px!important;margin:10px 0!important;text-align:left!important;font-weight:400!important}#wpacu_wrap_assets p:first-child,.wpacu_verified{margin:0 0 10px!important}#wpacu_wrap_assets h1{margin:0 0 20px!important;font-size:160%!important;text-align:left!important}#wpacu_wrap_assets h3{margin:20px 0;font-size:130%}.wpacu_asset_row:first-child td{border-top:1px solid #cdcdcd}.wpacu_asset_row td{border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd;border-bottom:1px solid #cdcdcd}.wpacu_asset_row.wpacu_notice_row td{position:relative;padding:5px;border-bottom:1px solid transparent}.wpacu_asset_row.wpacu_notice_row td div.wpacu-warning{width:auto;margin:5px;font-style:italic}.wpacu_asset_row:not(.wpacu_notice_row) td{padding:18px!important;position:relative}.wpacu_asset_row:not(.wpacu_notice_row) td.selected,.wpacu_asset_row:not(.wpacu_notice_row) td:hover{-moz-box-shadow:inset 0 0 12px #cdcdcd;-webkit-box-shadow:inset 0 0 12px #cdcdcd;box-shadow:inset 0 0 12px #cdcdcd}.wpacu_asset_row:not(.wpacu_notice_row) td p{padding:0!important;margin-bottom:10px!important;word-wrap:break-word!important;-ms-word-break:break-all;word-break:break-word}.wpacu_asset_row:not(.wpacu_notice_row) td label{width:auto!important;margin:0!important;cursor:pointer!important;display:inline-block!important;font-size:100%!important;font-weight:400!important}.wpacu_asset_row:not(.wpacu_notice_row) td label span:not(.dashicons){font-size:100%!important}.wpacu_asset_row:not(.wpacu_notice_row) td.wpacu_check{width:50px!important}.asset-table-extra-info td{padding:5px!important}body.wp-admin .wpacu_asset_row td.wpacu_check{width:25px!important}.wpacu_asset_row .dashicons-warning{color:red!important}label.wpacu_add_global{cursor:pointer!important}label.wpacu_input_load_checked{font-weight:700;color:#d54e21}label.wpacu_global_unload_exception{font-weight:700!important}tr.wpacu_global_rule_row.selected{background:#e7e7e7}.nav-tab-wrapper{border-bottom:1px solid #ccc;width:95%}.nav-tab-wrapper.nav-assets-manager .nav-tab{font-size:13px;font-weight:500;padding:6px 10px}.nav-tab-wrapper.nav-assets-manager .nav-tab.for-pro{padding:6px 8px 6px 3px}ul.wpacu_asset_options{margin:0 10px 0 0;padding:0}ul.wpacu_asset_options li{margin:0 10px 0 0;list-style:none;display:inline-block;line-height:normal}ul.wpacu_asset_options li.remove_rule label{font-weight:700}ul.wpacu_asset_options label{margin-right:20px;font-weight:400}ul.wpacu_asset_options label input{margin-right:4px}.wpacu_list_table,.wpacu_list_table div,.wpacu_list_table li,.wpacu_list_table p{font-weight:400}.wpacu_striped>tbody>:nth-child(even),ul.wpacu_striped>:nth-child(even){background-color:#fff!important}.wpacu_striped>tbody>:nth-child(odd),ul.wpacu_striped>:nth-child(odd){background-color:#f9f9f9!important}.wpacu_update_btn{-moz-box-shadow:inset 0 1px 0 0 #54a3f7!important;-webkit-box-shadow:inset 0 1px 0 0 #54a3f7!important;box-shadow:inset 0 1px 0 0 #54a3f7!important;background:-webkit-gradient(linear,left top,left bottom,color-stop(.05,#007dc1),color-stop(1,#0061a7))!important;background:-moz-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-webkit-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-o-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:-ms-linear-gradient(top,#007dc1 5%,#0061a7 100%)!important;background:linear-gradient(to bottom,#007dc1 5%,#0061a7 100%)!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#007dc1', endColorstr='#0061a7', GradientType=0)!important;background-color:#007dc1!important;-moz-border-radius:3px!important;-webkit-border-radius:3px!important;border-radius:3px!important;border:1px solid #124d77!important;display:inline-block!important;cursor:pointer!important;color:#fff!important;font-size:15px!important;padding:10px 24px!important;text-decoration:none!important;text-shadow:0 1px 0 #154682!important;height:auto!important;line-height:normal!important}.wpacu-btns .btn:focus,.wpacu-btns .btn:hover,.wpacu-btns a{text-decoration:none}.wpacu_update_btn.wpacu_submitting,.wpacu_update_btn:hover{background:-webkit-gradient(linear,left top,left bottom,color-stop(.05,#0061a7),color-stop(1,#007dc1))!important;background:-moz-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-webkit-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-o-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:-ms-linear-gradient(top,#0061a7 5%,#007dc1 100%)!important;background:linear-gradient(to bottom,#0061a7 5%,#007dc1 100%)!important;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0061a7', endColorstr='#007dc1', GradientType=0)!important;background-color:#0061a7!important}.wpacu_update_btn.wpacu_submitting{cursor:default!important}.wpacu_update_btn:active{position:relative!important;top:1px!important}.wpacu-btns .btn{display:inline-block;font-weight:400;line-height:1.25;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem 1rem;font-size:1rem;-webkit-border-radius:.25rem;-moz-border-radius:.25rem;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wpacu-btns .btn.focus,.wpacu-btns .btn:focus{outline:0;-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.25);box-shadow:0 0 0 2px rgba(2,117,216,.25)}.wpacu-btns .btn.disabled,.wpacu-btns .btn:disabled{cursor:not-allowed;opacity:.65}.wpacu-btns .btn.active,.wpacu-btns .btn:active{background-image:none}.wpacu-btns a.btn.disabled,.wpacu-btns fieldset[disabled] a.btn{pointer-events:none}.wpacu-btns .btn-primary{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-primary:hover{color:#fff;background-color:#025aa5;border-color:#01549b}.wpacu-btns .btn-primary.focus,.wpacu-btns .btn-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.wpacu-btns .btn-primary.disabled,.wpacu-btns .btn-primary:disabled{background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-primary.active,.wpacu-btns .btn-primary:active,.wpacu-btns .show>.btn-primary.dropdown-toggle{color:#fff;background-color:#025aa5;background-image:none;border-color:#01549b}.wpacu-btns .btn-secondary{color:#292b2c;background-color:#fff;border-color:#ccc}.wpacu-btns .btn-secondary:hover{color:#292b2c;background-color:#e6e6e6;border-color:#adadad}.wpacu-btns .btn-secondary.focus,.wpacu-btns .btn-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.wpacu-btns .btn-secondary.disabled,.wpacu-btns .btn-secondary:disabled{background-color:#fff;border-color:#ccc}.wpacu-btns .btn-secondary.active,.wpacu-btns .btn-secondary:active,.wpacu-btns .show>.btn-secondary.dropdown-toggle{color:#292b2c;background-color:#e6e6e6;background-image:none;border-color:#adadad}.wpacu-btns .btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.wpacu-btns .btn-info.focus,.wpacu-btns .btn-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.wpacu-btns .btn-info.disabled,.wpacu-btns .btn-info:disabled{background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-info.active,.wpacu-btns .btn-info:active,.wpacu-btns .show>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;background-image:none;border-color:#2aabd2}.wpacu-btns .btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-success:hover{color:#fff;background-color:#449d44;border-color:#419641}.wpacu-btns .btn-success.focus,.wpacu-btns .btn-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.wpacu-btns .btn-success.disabled,.wpacu-btns .btn-success:disabled{background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-success.active,.wpacu-btns .btn-success:active,.wpacu-btns .show>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;background-image:none;border-color:#419641}.wpacu-btns .btn-warning{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#eb9316}.wpacu-btns .btn-warning.focus,.wpacu-btns .btn-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.wpacu-btns .btn-warning.disabled,.wpacu-btns .btn-warning:disabled{background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-warning.active,.wpacu-btns .btn-warning:active,.wpacu-btns .show>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;background-image:none;border-color:#eb9316}.wpacu-btns .btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#c12e2a}.wpacu-btns .btn-danger.focus,.wpacu-btns .btn-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.wpacu-btns .btn-danger.disabled,.wpacu-btns .btn-danger:disabled{background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-danger.active,.wpacu-btns .btn-danger:active,.wpacu-btns .show>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;background-image:none;border-color:#c12e2a}.wpacu-btns .btn-outline-primary{color:#0275d8;background-image:none;background-color:transparent;border-color:#0275d8}.wpacu-btns .btn-outline-primary:hover{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-outline-primary.focus,.wpacu-btns .btn-outline-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.wpacu-btns .btn-outline-primary.disabled,.wpacu-btns .btn-outline-primary:disabled{color:#0275d8;background-color:transparent}.wpacu-btns .btn-outline-primary.active,.wpacu-btns .btn-outline-primary:active,.wpacu-btns .show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#0275d8;border-color:#0275d8}.wpacu-btns .btn-outline-secondary{color:#ccc;background-image:none;background-color:transparent;border-color:#ccc}.wpacu-btns .btn-outline-secondary:hover{color:#fff;background-color:#ccc;border-color:#ccc}.wpacu-btns .btn-outline-secondary.focus,.wpacu-btns .btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.wpacu-btns .btn-outline-secondary.disabled,.wpacu-btns .btn-outline-secondary:disabled{color:#ccc;background-color:transparent}.wpacu-btns .btn-outline-secondary.active,.wpacu-btns .btn-outline-secondary:active,.wpacu-btns .show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ccc;border-color:#ccc}.wpacu-btns .btn-outline-info{color:#5bc0de;background-image:none;background-color:transparent;border-color:#5bc0de}.wpacu-btns .btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-outline-info.focus,.wpacu-btns .btn-outline-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.wpacu-btns .btn-outline-info.disabled,.wpacu-btns .btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.wpacu-btns .btn-outline-info.active,.wpacu-btns .btn-outline-info:active,.wpacu-btns .show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.wpacu-btns .btn-outline-success{color:#5cb85c;background-image:none;background-color:transparent;border-color:#5cb85c}.wpacu-btns .btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-outline-success.focus,.wpacu-btns .btn-outline-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.wpacu-btns .btn-outline-success.disabled,.wpacu-btns .btn-outline-success:disabled{color:#5cb85c;background-color:transparent}.wpacu-btns .btn-outline-success.active,.wpacu-btns .btn-outline-success:active,.wpacu-btns .show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.wpacu-btns .btn-outline-warning{color:#f0ad4e;background-image:none;background-color:transparent;border-color:#f0ad4e}.wpacu-btns .btn-outline-warning:hover{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-outline-warning.focus,.wpacu-btns .btn-outline-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.wpacu-btns .btn-outline-warning.disabled,.wpacu-btns .btn-outline-warning:disabled{color:#f0ad4e;background-color:transparent}.wpacu-btns .btn-outline-warning.active,.wpacu-btns .btn-outline-warning:active,.wpacu-btns .show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.wpacu-btns .btn-outline-danger{color:#d9534f;background-image:none;background-color:transparent;border-color:#d9534f}.wpacu-btns .btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-outline-danger.focus,.wpacu-btns .btn-outline-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.wpacu-btns .btn-outline-danger.disabled,.wpacu-btns .btn-outline-danger:disabled{color:#d9534f;background-color:transparent}.wpacu-btns .btn-outline-danger.active,.wpacu-btns .btn-outline-danger:active,.wpacu-btns .show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#d9534f;border-color:#d9534f}.wpacu-btns .btn-link{font-weight:400;color:#0275d8;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.wpacu-btns .btn-link,.wpacu-btns .btn-link.active,.wpacu-btns .btn-link:active,.wpacu-btns .btn-link:disabled{background-color:transparent}.wpacu-btns .btn-link,.wpacu-btns .btn-link:active,.wpacu-btns .btn-link:focus,.wpacu-btns .btn-link:hover{border-color:transparent}.wpacu-btns .btn-link:focus,.wpacu-btns .btn-link:hover{color:#014c8c;text-decoration:underline;background-color:transparent}.wpacu-btns .btn-link:disabled{color:#636c72}.wpacu-btns .btn-link:disabled:focus,.wpacu-btns .btn-link:disabled:hover{text-decoration:none}.wpacu-btns .btn-group-lg>.btn,.wpacu-btns .btn-lg{padding:.75rem 1.5rem;font-size:1.25rem;-webkit-border-radius:.3rem;-moz-border-radius:.3rem;border-radius:.3rem}.wpacu-btns .btn-group-sm>.btn,.wpacu-btns .btn-sm{padding:.25rem .5rem;font-size:.875rem;-webkit-border-radius:.2rem;-moz-border-radius:.2rem;border-radius:.2rem}.wpacu-btns .btn-block{display:block;width:100%}.go-pro-button,.go-pro-link-no-style,.wordpress-core-file{display:inline-block;text-decoration:none}.wpacu-btns .btn-block+.btn-block{margin-top:.5rem}.wpacu-btns input[type=reset].btn-block,.wpacu-btns input[type=button].btn-block,.wpacu-btns input[type=submit].btn-block{width:100%}.wpacu-btns .fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.go-pro-button{background-color:#4CAF50;border:2px solid #4CAF50;color:#fff;padding:12px 18px;text-align:center;font-size:16px;margin:4px 2px;cursor:pointer;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-transition-duration:.4s;transition-duration:.4s}.go-pro-button:hover{background-color:#fff;color:#000;border:2px solid #4CAF50;text-decoration:none}.wpacu-restore-pos-btn{font-size:14px!important;line-height:normal!important;height:42px!important;padding:0 18px!important;margin-top:10px!important}body.wp-admin .wpacu_asset_row .go-pro-link-no-style .wpacu-tooltip{padding:8px 2px}body.wp-admin .go-pro-link-no-style .wpacu-tooltip{text-shadow:none;font-weight:400;font-size:12px;line-height:16px;padding:8px 11px}.go-pro-link-no-style{position:relative;color:inherit}.go-pro-link-no-style:not(.nav-tab){font-style:italic}.go-pro-link-no-style.no-transition .wpacu-tooltip{-webkit-transition:0s all ease;transition:0s all ease;-webkit-transition-delay:0s;transition-delay:0s}.go-pro-link-no-style>img{max-width:20px;max-height:20px}.go-pro-link-no-style .wpacu-tooltip{font-size:14px;line-height:18px;position:absolute;z-index:1;visibility:hidden;width:160px;background-color:#00a7a7;color:#fff;text-align:center;padding:8px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;bottom:100%;bottom:calc(100% + 15px);left:50%;margin-left:-65px;-webkit-transition:.1s all ease;transition:.1s all ease;-webkit-transition-delay:0s;transition-delay:0s}.go-pro-link-no-style .wpacu-tooltip:after{content:"";position:absolute;border-width:10px;border-style:solid;top:100%;left:50%;left:calc(50% - 10px);border-color:#00a7a7 transparent transparent}.go-pro-link-no-style .wpacu-tooltip.wpacu-on-pages-btn{cursor:pointer;margin-left:-77px;width:130px}.go-pro-link-no-style .wpacu-tooltip.wpacu-larger{width:240px}.go-pro-link-no-style:hover .wpacu-tooltip{visibility:visible}.wpacu_list_table tr:first-child .wordpress-core-file .wpacu-tooltip{bottom:-40px;left:120px;margin-left:-86px}.wpacu_list_table tr:first-child .wordpress-core-file .wpacu-tooltip:after{top:41px;left:-20px;border-color:transparent #c00 transparent transparent}.wordpress-core-file{position:relative;font-style:normal;color:inherit}.wordpress-core-file .wpacu-tooltip{font-size:14px;line-height:18px;position:absolute;z-index:1;visibility:hidden;width:160px;background-color:#c00;color:#fff;text-align:center;padding:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;bottom:100%;bottom:calc(100% + 15px);left:50%;margin-left:-86px;-webkit-transition:.1s all ease;transition:.1s all ease;-webkit-transition-delay:0s;transition-delay:0s}.wordpress-core-file .wpacu-tooltip:after{content:"";position:absolute;border-width:10px;border-style:solid;top:100%;left:50%;left:calc(50% - 10px);border-color:#c00 transparent transparent}.wordpress-core-file:hover .wpacu-tooltip{visibility:visible}.ajax-direct-call-error-area{background:#fff;padding:10px;border:1px solid #c00;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px}.ajax-direct-call-error-area td{padding:6px}.ajax-direct-call-error-area .note{margin-top:0;padding-top:0}.ajax-direct-call-error-area .error-code{color:#c00;font-weight:700}.ajax-wp-remote-post-call-error-area{background:#fff;padding:20px}.ajax-wp-remote-post-call-error-area .table-data{background:0 0;border:1px solid #c66;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.ajax-wp-remote-post-call-error-area .table-data td{padding:10px}.wrap-upgrade-info{background:#fff;padding:0 15px;border:1px solid #cdcdcd;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-notice{margin:20px 20px 0 0!important}.wpacu-notice p{font-weight:600!important;font-style:italic}.wpacu-notice .dashicons{font-weight:inherit!important;color:#46b450!important;margin-right:4px;vertical-align:text-bottom;font-size:27px}.wpacu-notice-info{padding:12px 12px 12px 16px;background:#fff;border-left:4px solid #008f9c}.wpacu-notice-info p{margin-top:8px}.wpacu-notice-info p:first-child{margin-top:0}.wpacu-notice-info p:last-child{margin-bottom:0}.wpacu-warning{font-size:15px;padding:10px;background:#fffcec;border:1px solid #fdd5c9;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;margin:0 0 5px;width:100%}.pro-page-unlock-notice{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;padding:10px;background:#f2faf2;border:1px solid #c0e8c0;width:auto;display:block}.wpacu-license-area .notice,.wpacu-settings-area .notice{margin-left:0;padding:10px!important;width:97%;box-sizing:border-box;font-weight:600;font-style:italic}#wpacu-dom-get-type-selections,.wpacu-radio-selections{float:none;clear:both;width:auto;display:inline-block;margin-bottom:0;margin-top:0}#wpacu-dom-get-type-selections.wpacu-vertical,.wpacu-radio-selections.wpacu-vertical{display:block;margin-top:15px;margin-bottom:18px}#wpacu-dom-get-type-selections.wpacu-vertical li,.wpacu-radio-selections.wpacu-vertical li{float:none;margin-bottom:12px}#wpacu-dom-get-type-selections.wpacu-vertical li:last-child,.wpacu-radio-selections.wpacu-vertical li:last-child{margin-bottom:0}#wpacu-dom-get-type-selections li,.wpacu-radio-selections li{margin-right:30px;float:left;margin-bottom:0}#wpacu-dom-get-type-selections li:first-child,.wpacu-radio-selections li:first-child{margin-right:15px}#wpacu-dom-get-type-selections li:last-child,.wpacu-radio-selections li:last-child{margin-right:0}.wpacu_combine_loaded_js_level_area{display:none;background:0 0;border-left:2px solid #008f9c;padding-top:8px;padding-bottom:8px;padding-right:10px;padding-left:10px;margin:20px 0 15px}.wpacu_combine_loaded_js_level_area.wpacu_active{display:block}#wpacu-dom-get-type-infos{margin-bottom:0}#wpacu-dom-get-type-infos li{margin-bottom:0;line-height:20px}.wpacu-wrap li,.wpacu-wrap p,.wpacu-wrap td{font-weight:400}.wpacu-wrap small{width:auto;float:none;display:inline}.wpacu-wrap.wpacu-settings-show-all .wpacu-settings-tab-content{display:block;width:100%}.wpacu-wrap.wpacu-settings-show-all .wpacu-settings-area-title{color:#004567;padding:16px 15px;background:#f8f8f8;border-left:5px solid #004567b0;border-top:1px solid #e7e7e7;border-right:1px solid #e7e7e7;border-bottom:1px solid #e7e7e7;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;font-size:1.45em;font-weight:500}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider.wpacu_round,.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch .wpacu_slider.wpacu_round{border-radius:29px}.wpacu-wrap.wpacu-settings-show-all #wpacu-update-button-area{margin:0}.wpacu-wrap.wpacu-settings-show-all #wpacu-update-button-area .button{padding:11px 28px;height:auto;font-size:18px}.wpacu-wrap.wpacu-settings-show-all #wpacu-updating-settings{margin-left:224px;top:25px}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch{width:auto;height:auto}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch input,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch input{display:block}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch input[type=checkbox],.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch input[type=checkbox]{margin:0 0 3px}.wpacu-wrap.wpacu-switch-standard .asset-cleanup-pro_page_wpassetcleanup_settings .wpacu_switch .wpacu_slider,.wpacu-wrap.wpacu-switch-standard .asset-cleanup_page_wpassetcleanup_settings .wpacu_switch .wpacu_slider{display:none}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch{position:relative;display:inline-block;width:52px;height:29px}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input{display:none}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch:not(.wpacu_switch_standard) .wpacu_slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.2s;transition:.2s}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch:not(.wpacu_switch_standard) .wpacu_slider:before{position:absolute;content:'';height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.2s;transition:.2s}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:checked+.wpacu_slider{background-color:#52af00}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:focus+.wpacu_slider{box-shadow:0 0 1px #52af00}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch input:checked+.wpacu_slider:before{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch .wpacu_slider.wpacu_round:before{border-radius:50%}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_disabled,.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_locked_for_pro{opacity:.3}.wpacu-wrap.wpacu-switch-enhanced .wpacu_switch.wpacu_disabled:before{content:"\f160";font-family:Dashicons,Arial,"Times New Roman","Bitstream Charter",Times,serif;position:absolute;font-size:23px;top:5px;right:2px;z-index:1000}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle{margin-top:4px;line-height:1.4}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle em,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_subtitle em{font-weight:200}.asset-cleanup-pro_page_wpassetcleanup_settings .setting_title p.wpacu_read_more,.asset-cleanup_page_wpassetcleanup_settings .setting_title p.wpacu_read_more{margin-top:-10px;font-style:italic;font-size:12px}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices{list-style:none;margin:0}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices li,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices li{float:left;margin-right:30px}.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li:last-child,.asset-cleanup-pro_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li:last-child,.asset-cleanup-pro_page_wpassetcleanup_settings .input_style_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .assets_list_inline_code_status_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .assets_list_layout_areas_status_choices li:last-child,.asset-cleanup_page_wpassetcleanup_settings .input_style_choices li:last-child{margin-right:0}#wpacu-assets-list-by-location-selected{background:0 0;border:1px solid #e7e7e7;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:8px;clear:both}.notice.notice-success+.wpacu-wrap.wpacu-settings-area{margin-top:20px}.wpacu-form-table th{vertical-align:top;text-align:left;padding:5px 20px 20px 0;width:200px;line-height:1.3;font-weight:600}.wpacu-form-table th label{color:#23282d;font-weight:600;font-size:14px;text-shadow:none;vertical-align:middle;cursor:pointer}.wpacu-form-table td{padding-bottom:25px}.wpacu-form-table td:last-child p:last-child{margin:0}.wpacu-form-table label input[type=checkbox]{height:19px;width:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.wpacu-form-table label input[type=checkbox]:checked,.wpacu-form-table label input[type=checkbox]:hover{border:1px solid green}.wpacu-form-table label input[type=checkbox]:checked:before{color:#52af00;font:400 24px/1 dashicons}#wpacu-settings-vertical-tab-wrap{display:table;width:100%}#wpacu-settings-vertical-tab-wrap *{box-sizing:border-box}.wpacu-settings-tab{display:table-cell;width:20%;height:100%;vertical-align:top}.wpacu-settings-tab a{text-decoration:none;border-left:3px solid transparent;display:block;background-color:#f1f1f1;color:#004567;padding:17px 16px;width:100%;outline:0;text-align:left;cursor:pointer;font-size:14px;font-weight:600;border-bottom:1px solid #ccc}.wpacu-settings-tab a:first-child{border-top:1px solid transparent!important}.wpacu-settings-tab a:last-child{border-bottom:1px solid transparent!important}.wpacu-settings-tab a:hover{background-color:#fff;border-left:3px solid #004567;position:relative}.wpacu-settings-tab a.active{color:#004567;background-color:#fff;border-left:3px solid #004567;position:relative;border-bottom:1px solid #ccc}.wpacu-settings-tab a.active:after{content:'';position:absolute;height:100%;width:1px;top:0;right:-1px;background-color:#fff}.wpacu-settings-tab-content{background-color:#fff;display:none;padding:12px 18px;width:79%;border-left:none;height:100%;border-top-right-radius:10px;border-bottom-right-radius:10px}.wpacu-settings-tab-content h2{padding:0 0 15px;border-bottom:1px solid #e7e7e7}.wpacu-settings-tab-content.active{display:table-cell}#wpacu_minify_css_exceptions_area,#wpacu_minify_js_exceptions_area{margin:16px 0 0}#wpacu-update-button-area{position:relative;margin-left:19%}#wpacu-update-button-area.no-left-margin{margin-left:0}#wpacu-update-button-area p{margin-top:10px}#wpacu-update-button-area .button{padding:5px 18px;height:38px;font-size:15px}#wpacu-updating-settings{position:absolute;margin-left:183px;top:19px;display:none}#combine_loaded_js_info_area{position:relative}#combine_loaded_js_info_area.locked-for-pro:before{position:absolute;content:'';height:100%;width:100%;background:#fff;opacity:.5;z-index:10000}body.wp-admin .wpacu-handle-notes{margin-top:10px!important}body.wp-admin .wpacu-handle-notes p{margin-top:0!important}body.wp-admin .wpacu-handle-notes p a{font-size:inherit}body.wp-admin .wpacu-handle-notes p a span.dashicons{font-size:19px;width:19px;height:19px;vertical-align:bottom;text-decoration:none}.wpacu-handle-notes{margin-top:12px!important;padding-top:5px;border-top:1px solid #e7e7e7}.wpacu-handle-notes .wpacu-handle-notes-field{display:none}.wpacu-handle-notes .wpacu-handle-notes-field>textarea{font-size:85%;padding:6px;width:320px;max-width:100%}.wpacu-handle-notes p{margin:10px 0 0!important}.wpacu-handle-notes p a.wpacu-add-handle-note{text-decoration:none;font-size:80%;display:inline-block;color:inherit}.wpacu-handle-notes p a.wpacu-add-handle-note span.dashicons{font-size:18px;width:18px;height:18px}.wrap_bulk_unload_options{width:auto;display:inline-flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.wrap_bulk_unload_options .wpacu_asset_options_wrap{flex-grow:1;margin:5px 10px 14px 0!important;padding:8px 10px 2px!important}.wrap_bulk_unload_options .wpacu_asset_options_wrap .wpacu_slider_text{position:relative!important;vertical-align:top;left:inherit!important;top:inherit!important}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch{position:relative;display:inline-block;min-width:52px;width:52px;height:29px;margin-right:5px!important}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input{display:none}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.15s;transition:.15s}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider:before{position:absolute;content:'';height:22px;width:22px;left:4px;bottom:4px;background-color:#fff;-webkit-transition:.15s;transition:.15s}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:checked+.wpacu_slider{background-color:#C00}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:focus+.wpacu_slider{box-shadow:0 0 1px #C00}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch input:checked+.wpacu_slider:before{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_switch .wpacu_slider.wpacu_round:before{border-radius:50%}.wpacu-switch-enhanced .wpacu_asset_row .wpacu_slider_text{position:absolute;left:62px;top:3px}.editor-post-saved-state.is-wpacu-reloading{animation:edit-post__loading-fade-animation .5s infinite}body.wp-admin .wpacu_asset_row.wpacu-loading{position:relative}body.wp-admin .wpacu_asset_row.wpacu-loading .wpacu-ajax-loader{display:block!important}body.wp-admin .wpacu_asset_row .wpacu-ajax-loader{display:none;width:58px;height:58px;position:absolute;bottom:0;right:0;opacity:.75}.wpacu_asset_row input{width:auto;height:auto;min-height:16px}.wpacu_asset_row .tip{background:inherit;border-left:4px solid #e7e7e7;margin:5px 0;padding:7px;font-style:italic;font-size:small;line-height:1.4}.wpacu_asset_row td{width:100%;text-align:left}.wpacu_asset_row td p:last-child{margin-bottom:0!important}.wpacu_asset_row td .wpacu_asset_options_wrap{padding:8px 10px;margin:15px 0;background:#fff;border:1px solid #eee;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu_asset_row td .wpacu_asset_options_wrap p:first-child{margin-top:0;margin-bottom:8px!important}.wpacu_asset_row p.wpacu_handle{margin-top:0}.wpacu_asset_row li.wpacu_unload_this_page{display:block!important;position:relative}.wpacu-clearfix:after,.wpacu-clearfix:before{display:table;content:''}.wpacu-contract-expand-area{width:100%;margin:20px 0 0}.wpacu-contract-expand-area .col-left{float:left}.wpacu-contract-expand-area .col-left h4{margin-bottom:0}.wpacu-contract-expand-area .col-right{float:right}.wpacu-clearfix:after{clear:both}.wpacu-wp-button{color:#555;border-color:#ccc;background:#f7f7f7;box-shadow:0 1px 0 #ccc;vertical-align:top}body.wp-admin .wpacu-wp-button{font-size:13px;line-height:26px;height:28px}.wpacu-wp-button.wpacu-wp-button-secondary{display:inline-block;text-decoration:none;height:auto;margin:0 5px 0 0;padding:0 10px 1px;cursor:pointer;border-width:1px;border-style:solid;-webkit-appearance:none;border-radius:3px;white-space:nowrap;box-sizing:border-box}.wpacu-wp-button:hover{background:#fafafa;border-color:#999;color:#23282d}.distinguish-asset-list{list-style:none;margin-left:0;margin-bottom:5px;display:inline-block}.distinguish-asset-list li{float:left;margin-right:20px}.distinguish-asset-list li:last-child{margin-right:0}body[class*=asset-cleanup-pro] a.wpacu-plugin-contracted-wrap-link{padding:16px 6px 16px 41px!important}body[class*=asset-cleanup-pro] .wpacu-area-open .wpacu-plugin-toggle-all{font-size:12px!important;width:calc(100% - 26px)!important}body.wp-admin .wpacu-area-expanded .wpacu-plugin-toggle-all{top:5px}body.wp-admin .wpacu-area-expanded .wpacu-plugin-toggle-all ul li{font-size:12px!important}.wpacu-assets-collapsible-wrap{border:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location{margin-bottom:15px}.wpacu-assets-collapsible-wrap.wpacu-wrap-all{margin-top:20px}.wpacu-assets-collapsible-wrap.wpacu-wrap-area{margin-top:10px}.wpacu-assets-collapsible-wrap.wpacu-by-location>a.wpacu-assets-collapsible{padding:15px 15px 15px 43px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu_list_table{border-width:0;margin:0;border-spacing:inherit;width:100%;box-shadow:3px 3px 2px #ddd;border-bottom-right-radius:5px;border-top-right-radius:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location span.wpacu-child-location-name{font-weight:600}.wpacu-assets-collapsible-wrap.wpacu-by-location span.wpacu-child-location-version{font-weight:200}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area[data-wpacu-plugin=oxygen] .icon-area{border-radius:50%}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all{display:inline-block;padding:0;font-size:13px;width:100%;width:calc(100% + 46px);min-width:250px;position:absolute;left:100%;left:calc(100% + 6px);margin:0;top:4px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul{display:inline-block;margin:0;list-style:none;padding-left:13px;padding-top:0}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul li{padding:0;margin:0;line-height:normal;font-size:14px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-location-child-area .wpacu-plugin-toggle-all ul li:first-child{font-style:italic;margin-bottom:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content>table:last-child{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{display:inline;position:relative;z-index:1}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title:after{content:'';position:absolute;width:100%;left:0;bottom:0;height:1px;background-color:#fdfdfd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap{padding:0 0 10px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap.wpacu-area-open .wpacu-plugin-toggle-all{display:inline-block;padding:7px 12px 16px;font-size:14px;width:100%;text-align:left;border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-plugin-assets-wrap.wpacu-area-open.wpacu-plugin-assets-last{margin-bottom:18px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link{color:inherit;text-decoration:none;font-weight:inherit;font-style:inherit;font-size:105%;line-height:initial;height:auto;margin:14px 0 0;padding:13px 6px 14px 39px;position:relative;display:block}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:after{position:absolute;font-size:18px;font-family:Dashicons;right:12px;top:14px;content:"\f132"}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-open:after{content:"\f460"}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-closed{border:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:hover{border:1px solid #878787;background:#f9f9f9}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link:hover.wpacu-link-closed{box-shadow:3px 3px 2px #ddd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-open{border-top:1px solid #cdcdcd;border-left:1px solid #cdcdcd;border-right:1px solid #cdcdcd;border-bottom:none}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-link-closed.wpacu-last-wrap-link{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default{top:10px;left:10px;width:30px;height:30px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default .icon-area{width:30px;height:30px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .icon-plugin-default .icon-area:before{font-size:22px;line-height:22px;top:4px;left:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .wpacu-area-title{position:relative;padding:17px 10px 16px 46px;z-index:1}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link .wpacu-area-title:after{content:'';position:absolute;width:100%;left:0;bottom:0;height:1px;background-color:#fdfdfd}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content a.wpacu-plugin-contracted-wrap-link.wpacu-area-last{margin-bottom:18px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-area-open{padding:0;max-height:100%}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content .wpacu-area-closed{padding:0;overflow:hidden;max-height:0}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-plugins .wpacu-assets-collapsible-content>table:last-child{margin-bottom:20px}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{margin-top:0;margin-bottom:-1px;padding:14px 10px 16px 12px!important}.wpacu-assets-collapsible-wrap.wpacu-by-location.wpacu-themes .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title.wpacu-theme-has-icon{padding:18px 10px 16px 58px!important}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area{margin-top:22px;margin-bottom:-1px;font-size:110%;line-height:initial}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area.wpacu-location-child-area-first{margin-top:2px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area.wpacu-area-expanded .wpacu-area-title{display:inline-block;z-index:1;padding:17px 10px 16px 46px}.wpacu-assets-collapsible-wrap.wpacu-by-location .wpacu-assets-collapsible-content .wpacu-location-child-area .wpacu-area-title{display:inline;border-top-right-radius:8px;border-top-left-radius:8px;background-color:#f9f9f9;border-left:1px solid #cdcdcd;border-top:1px solid #cdcdcd;border-bottom:1px solid transparent;border-right:1px solid #cdcdcd;position:relative}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default{position:absolute;padding:0;top:10px;left:10px;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default:not(.has-icon){color:#b4b9be;background-color:#eee;box-shadow:inset 0 0 10px rgba(160,165,170,.15);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default:not(.has-icon) .icon-area:before{content:"\f106";font-family:Dashicons;position:absolute;font-size:28px;line-height:28px;top:5px;left:5px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-plugin-default .icon-area{position:relative;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-theme{position:absolute;padding:0;top:10px;left:10px;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-by-location .icon-theme .icon-area{position:relative;width:37px;height:37px}.wpacu-assets-collapsible-wrap.wpacu-wp_core{border:1px solid #c00}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content{padding:0}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table{width:100%;margin:0}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row td,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row td{border-left:hidden;border-right:hidden;border-bottom:1px solid #cdcdcd}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child{margin-bottom:0!important}.wpacu-assets-collapsible-wrap.wpacu-external .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child td:last-child,.wpacu-assets-collapsible-wrap.wpacu-wp_core .wpacu-assets-collapsible-content .wpacu_list_table .wpacu_asset_row:last-child td:last-child{border-bottom:hidden}a.wpacu-assets-collapsible{color:#000;font-size:20px;text-decoration:none;display:block;position:relative;background-color:#f1f3f8;cursor:pointer;padding:15px 15px 15px 36px;width:auto;border:none;text-align:left;outline:0}a.wpacu-assets-collapsible>span.dashicons{font-size:25px;line-height:normal;position:absolute;top:15px;top:calc(50% - 21px);left:22px;-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}a.wpacu-assets-collapsible:hover{background-color:#f1f3f8;text-decoration:none}a.wpacu-assets-collapsible:after{position:absolute;font-size:22px;font-family:Dashicons;right:14px;top:16px}a.wpacu-assets-collapsible:not(.wpacu-assets-collapsible-active):after{content:"\f132"}a.wpacu-assets-collapsible.wpacu-assets-collapsible-active{background-color:#f1f3f8}a.wpacu-assets-collapsible.wpacu-assets-collapsible-active:after{content:"\f460"}.wpacu-assets-collapsible-content{padding:0 16px;max-height:0;overflow:hidden;background-color:#fbfbfb8c}.wpacu-assets-collapsible-content .wpacu-assets-note{margin:0;padding:15px 15px 10px}.wpacu-assets-collapsible-content>div:not(.wpacu-assets-table-list-wrap){padding:16px 0 0}.wpacu-assets-collapsible-content>div>p:first-child{margin-top:0}.wpacu-assets-collapsible-content.wpacu-open{max-height:100%}a.wpacu-assets-inline-code-collapsible{color:inherit;font-size:14px;text-decoration:none;display:inline-block;position:relative;cursor:pointer;width:auto;outline:0;background:#f1f3f8;border:1px solid #cdcdcd;padding:4px 21px 4px 8px;margin:0 0 0 6px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}a.wpacu-assets-inline-code-collapsible:hover{border:1px solid #5c5c5c}a.wpacu-assets-inline-code-collapsible:after{position:absolute;font-size:15px;font-family:Dashicons;right:-3px;top:-1px;width:14px;height:14px;-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}a.wpacu-assets-inline-code-collapsible:not(.wpacu-assets-inline-code-collapsible-active):after{content:"\f132"}a.wpacu-assets-inline-code-collapsible.wpacu-assets-inline-code-collapsible-active:after{content:"\f460"}.wpacu-assets-inline-code-collapsible-content{font-size:80%;padding:0 8px;max-height:0;overflow:hidden;background-color:#fbfbfb8c}.wpacu-assets-inline-code-collapsible-content>div{padding:7px 8px 0}.wpacu-assets-inline-code-collapsible-content>div>p{line-height:normal!important}.wpacu-assets-inline-code-collapsible-content>div>p:first-child{margin-top:0}.wpacu-assets-inline-code-collapsible-content.wpacu-open{max-height:100%}.wpacu_asset_row p div.select{display:inline-block}.wpacu-wrap-choose-position{display:inline}.wpacu-wrap-choose-position>div{display:inline-block}.wpacu-wrap-choose-position select{width:auto;font-size:inherit;display:inline;margin-left:6px;margin-right:4px}.wpacu-wrap-choose-position>.select>.select{display:inline}.wpacu-wrap-choose-position>.select>.select select{padding-right:30px}.wpacu-wrap-choose-position>.select>.select:after{right:15px;top:-4px}.wpacu_table_wrap{margin:20px 0 0}.wpacu_table_wrap>table{border:1px solid #cdcdcd}.wpacu_table_wrap .table{width:100%;max-width:100%;margin-bottom:1rem;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu_table_wrap .table td,.wpacu_table_wrap .table th{padding:.75rem;vertical-align:top;border-top:1px solid #eceeef}.wpacu_table_wrap .table thead th{vertical-align:bottom;border-bottom:2px solid #eceeef}.wpacu_table_wrap .table tbody+tbody{border-top:2px solid #eceeef}.wpacu_table_wrap .table .table{background-color:#fff}.wpacu_table_wrap .table-sm td,.wpacu_table_wrap .table-sm th{padding:.3rem}.wpacu_table_wrap .table-bordered,.wpacu_table_wrap .table-bordered td,.wpacu_table_wrap .table-bordered th{border:1px solid #eceeef}.wpacu_table_wrap .table-bordered thead td,.wpacu_table_wrap .table-bordered thead th{border-bottom-width:2px}.wpacu_table_wrap .table-striped tbody tr:nth-of-type(even){background-color:#f9f9f9}.wpacu_table_wrap .table-striped tbody tr:nth-of-type(odd){background-color:#fff}.wpacu_table_wrap .table-active,.wpacu_table_wrap .table-active>td,.wpacu_table_wrap .table-active>th,.wpacu_table_wrap .table-hover .table-active:hover,.wpacu_table_wrap .table-hover .table-active:hover>td,.wpacu_table_wrap .table-hover .table-active:hover>th,.wpacu_table_wrap .table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.wpacu_table_wrap .table-success,.wpacu_table_wrap .table-success>td,.wpacu_table_wrap .table-success>th{background-color:#dff0d8}.wpacu_table_wrap .table-hover .table-success:hover,.wpacu_table_wrap .table-hover .table-success:hover>td,.wpacu_table_wrap .table-hover .table-success:hover>th{background-color:#d0e9c6}.wpacu_table_wrap .table-info,.wpacu_table_wrap .table-info>td,.wpacu_table_wrap .table-info>th{background-color:#d9edf7}.wpacu_table_wrap .table-hover .table-info:hover,.wpacu_table_wrap .table-hover .table-info:hover>td,.wpacu_table_wrap .table-hover .table-info:hover>th{background-color:#c4e3f3}.wpacu_table_wrap .table-warning,.wpacu_table_wrap .table-warning>td,.wpacu_table_wrap .table-warning>th{background-color:#fcf8e3}.wpacu_table_wrap .table-hover .table-warning:hover,.wpacu_table_wrap .table-hover .table-warning:hover>td,.wpacu_table_wrap .table-hover .table-warning:hover>th{background-color:#faf2cc}.wpacu_table_wrap .table-danger,.wpacu_table_wrap .table-danger>td,.wpacu_table_wrap .table-danger>th{background-color:#f2dede}.wpacu_table_wrap .table-hover .table-danger:hover,.wpacu_table_wrap .table-hover .table-danger:hover>td,.wpacu_table_wrap .table-hover .table-danger:hover>th{background-color:#ebcccc}.wpacu_table_wrap .thead-inverse th{color:#fff;background-color:#292b2c}.wpacu_table_wrap .thead-default th{color:#464a4c;background-color:#eceeef}.wpacu_table_wrap .table-inverse{color:#fff;background-color:#292b2c}.wpacu_table_wrap .table-inverse td,.wpacu_table_wrap .table-inverse th,.wpacu_table_wrap .table-inverse thead th{border-color:#fff}.wpacu_table_wrap .table-inverse.table-bordered,.wpacu_table_wrap .table-responsive.table-bordered{border:0}.wpacu_table_wrap .table-responsive{display:block;width:100%;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.wp-list-table .wpacu_remove_global_attr_row.wpacu_selected,.wp-list-table .wpacu_restore_position_row.wpacu_selected{background:#e7e7e7}ul.hire-reasons{margin-bottom:20px}ul.hire-reasons li{font-size:14px;line-height:22px;margin-bottom:12px}ul.hire-reasons li .dashicons{font-size:23px;line-height:23px}ul.hire-reasons li .dashicons.dashicons-yes{color:green}ol.getting-started li{font-size:14px;line-height:22px;margin-bottom:8px}.wpacu-get-help-wrap p{font-size:14px}.wpacu-get-help-wrap .help-content-wrap{margin:20px 0 25px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-moz-flex;display:-webkit-flex;display:flex;width:100%}@media only screen and (min-width:768px){.wpacu-get-help-wrap .help-content-wrap{-webkit-box-align:start;-ms-flex-align:start;-ms-grid-row-align:flex-start;align-items:flex-start}}@media only screen and (max-width:767px){.wpacu-get-help-wrap .help-content-wrap{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.wpacu-get-help-wrap .help-content-wrap .help-content{padding:15px;background:#fff;border:1px solid #E0E0E0;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;box-shadow:2px 3px 8px 0 #231f2038;flex:1 1 50%;margin-bottom:10px}.wpacu-get-help-wrap .help-content-wrap .help-content .content-title{margin:5px 0 15px}.wpacu-get-help-wrap .help-content-wrap .help-content .cols-wrap{width:100%;margin:0 auto;display:table}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area{margin:5px 0 0;position:relative}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.col-left{float:left;width:48%}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.col-right{float:right;width:48%}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area.activate-plugin img{max-width:280px}.wpacu-get-help-wrap .help-content-wrap .help-content .wpacu-image-area img{width:99%;margin:8px 0;border:1px solid #cdcdcd;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-get-help-wrap .help-content-wrap .help-content.upgrade-help{order:2}@media only screen and (min-width:768px){.wpacu-get-help-wrap .help-content-wrap .help-content{margin-right:24px}.wpacu-get-help-wrap .help-content-wrap .help-content.upgrade-help{margin-right:0}}.wpacu-get-help-wrap .help-content-wrap .help-content.tech-help{order:1}@media only screen and (max-width:767px){.wpacu-get-help-wrap .help-content-wrap .help-content.tech-help{margin-bottom:30px}}.wpacu-get-help-wrap .help-content-wrap .help-content ul{list-style:none;padding-left:0}.wpacu-get-help-wrap .help-content-wrap .help-content ul li{font-size:14px;line-height:22px;margin-bottom:15px}.wpacu-get-help-wrap .help-content-wrap .help-content p:last-child,.wpacu-get-help-wrap .help-content-wrap .help-content ul li:last-child{margin-bottom:0}#wpacu-license-data-remove-area{display:none;margin:10px 0 25px}#wpacu-license-data-remove-area.wpacu-visible{display:block}span#wpacu-license-data-removed-msg{display:block;padding-left:26px}#wpacu-warning-read{display:none;margin:10px 0}#wpacu-warning-read span.dashicons-warning{color:#c00}#wpacu-warning-read.wpacu-visible{display:block}#wpacu-reset-submit-area{margin:10px 0;clear:both}#wpacu-reset-submit-btn{margin:10px 0 0}.wpacu-tools-area{margin:10px 20px 0 2px}.wpacu-tools-area .wpacu-tools-container{background:#fff;padding:15px;border:1px solid #cdcdcd;width:96%}.wpacu-tools-area .wpacu-tools-container form>div:first-child{margin:0 0 10px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning{display:none;box-sizing:border-box;margin-top:10px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning p{margin:0 0 10px;line-height:22px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning p:only-child{margin:0}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning ul{font-size:13px;list-style-type:disc;padding-left:30px}.wpacu-tools-area .wpacu-tools-container form .wpacu-warning.wpacu-visible{display:block}.wpacu-tools-area .wpacu-export-import-area{padding:10px}.wpacu-tools-area .wpacu-export-import-area form>p:first-of-type{margin-top:0}.wpacu-tools-area .wpacu-export-import-area form>p:last-of-type{margin-bottom:0}.wpacu-tools-area .wpacu-export-import-area:hover{background:rgba(40,44,42,.05);box-shadow:inset 0 0 10px rgba(160,165,170,.15)}.wpacu-tools-area .wpacu-export-import-area+hr{display:block;height:1px;border:0;border-top:1px solid #cdcdcd;margin:10px 0;padding:0}#wpacu-import-form button.wpacu-importing img.wpacu-spinner{display:inline-block}#wpacu-import-form button img.wpacu-spinner{display:none;margin:0 0 0 5px;height:16px;width:16px;vertical-align:middle}.wpacu-about-wrap .wpacu-about-text img{width:auto;height:150px;position:absolute;top:20px;right:-20px}@media only screen and (max-width:767px){.wpacu-about-wrap h1{margin:20px}.wpacu-about-wrap .wpacu-about-text img{display:none}.wpacu-about-wrap .wpacu-about-text{margin:20px}}.wpacu-about-wrap .about-wrap-content .area-title{font-size:19px;line-height:19px;margin-bottom:0}.wpacu-about-wrap hr{margin:10px 0}.wpacu-lite-vs-pro-wrap ul{display:flex;top:0;z-index:10;padding-bottom:14px}.wpacu-lite-vs-pro-wrap li{list-style:none;flex:1}.wpacu-lite-vs-pro-wrap li:last-child{border-right:1px solid #DDD}.wpacu-lite-vs-pro-wrap button{width:100%;border:1px solid #DDD;border-right:0;border-top:0;padding:10px;background:#FFF;font-size:14px;font-weight:700;height:60px;color:#999}.wpacu-lite-vs-pro-wrap li.active button{background:#F5F5F5;color:#000}.wpacu-lite-vs-pro-wrap table{border-collapse:collapse;table-layout:fixed;width:100%}.wpacu-lite-vs-pro-wrap th{background:inherit}.wpacu-lite-vs-pro-wrap tr.first{background:inherit;font-size:18px}.wpacu-lite-vs-pro-wrap tr.first .bg-lite{border-top:4px solid #6d6e70;background:#fff;color:#6d6e70}.wpacu-lite-vs-pro-wrap tr.first .bg-pro{border-top:4px solid green;background:#fff;color:green}.wpacu-lite-vs-pro-wrap tr:not(.first){background:#fff}.wpacu-lite-vs-pro-wrap tr:not(:last-child):hover{background:#f8f8f8}.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{height:53px;border:1px solid #DDD;padding:10px 16px;empty-cells:show;text-align:left}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{font-size:14px}}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{text-align:center;display:none}.wpacu-lite-vs-pro-wrap td.default{display:table-cell}.wpacu-lite-vs-pro-wrap .txt-l{font-size:28px;font-weight:700}.wpacu-lite-vs-pro-wrap .txt-top{position:relative;top:-9px;left:-2px}.wpacu-lite-vs-pro-wrap svg{width:18px;height:18px}.wpacu-lite-vs-pro-wrap svg path{fill:green}.wpacu-lite-vs-pro-wrap .tick{color:#2CA01C}.wpacu-lite-vs-pro-wrap .tick img{fill:#2CA01C}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap .txt-l{font-size:20px}.wpacu-lite-vs-pro-wrap .tick{font-size:15px}}.wpacu-lite-vs-pro-wrap .na{font-size:18px;opacity:.3;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"}.wpacu-lite-vs-pro-wrap .hide{border:0;background:0 0}.wpacu-lite-vs-pro-wrap td,.wpacu-lite-vs-pro-wrap th{display:table-cell!important;width:auto}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{width:130px}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap .na{font-size:15px}.wpacu-lite-vs-pro-wrap td+td,.wpacu-lite-vs-pro-wrap th+th{width:42px}}@media only screen and (min-width:768px){.wpacu-lite-vs-pro-wrap td .button{font-size:16px!important}}@media only screen and (max-width:767px){.wpacu-lite-vs-pro-wrap td .button{font-size:14px!important;padding:0 20px!important}.wpacu-lite-vs-pro-wrap td .button.button-primary{margin-top:6px;margin-bottom:14px}}@media only screen and (min-width:768px){.wpacu-lite-vs-pro-wrap{margin-bottom:40px;clear:both}}.wpacu-video-areas>div{padding:20px;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.wpacu-video-areas>div:nth-child(odd){background:#fff}.wpacu-video-areas>div:nth-child(even){background:inherit}@media only screen and (min-width:1200px){.wpacu-video-areas .wpacu-video-area-wrapper{margin:0 0 15px;display:flex}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right{padding:0 20px 0 25px}}@media only screen and (min-width:992px) and (max-width:1199px){.wpacu-video-areas .wpacu-video-area-wrapper{margin:0 0 40px}}.wpacu-video-areas .wpacu-video-area-wrapper ol{font-size:14px}.wpacu-video-areas .wpacu-video-area-wrapper ul{font-size:14px;list-style:disc;margin-left:22px}@media only screen and (min-width:1200px){.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right p:first-child{margin-top:0}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-col-right p:last-child{margin-bottom:0}}@media only screen and (max-width:1199px){.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-video-wrapper{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}.wpacu-video-areas .wpacu-video-area-wrapper .wpacu-video-wrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}}#wpassetcleanup_asset_list.postbox h2{padding-left:52px!important;position:relative}#wpassetcleanup_asset_list.postbox h2:before{content:'';position:absolute;background-image:url(images/wpacu-logo-transparent-bg-v1.png);background-size:cover;top:6px;left:13px;width:33px;height:26px;opacity:.8;-webkit-filter:grayscale(100%);filter:grayscale(100%)}body.wp-admin .wpacu-modal{display:none;position:fixed;z-index:1000000;padding-top:15%;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.4)}body.wp-admin .wpacu-modal-content{background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888;width:80%;max-width:600px;border-radius:10px}body.wp-admin .wpacu-close{color:#aaa;float:right;font-size:28px;font-weight:700}body.wp-admin .wpacu-close:focus,body.wp-admin .wpacu-close:hover{color:#000;text-decoration:none;cursor:pointer}.wpacu-bulk-changes-tabs{display:table;position:relative;overflow:hidden;margin:0;width:100%}.wpacu-bulk-changes-tabs li{border-top:1px solid rgba(40,44,42,.1);border-left:1px solid rgba(40,44,42,.1);border-bottom:1px solid rgba(40,44,42,.1);float:left;line-height:38px;padding:0;position:relative;margin-bottom:12px}.wpacu-bulk-changes-tabs li:last-child{border-right:1px solid rgba(40,44,42,.1)}.wpacu-bulk-changes-tabs a{position:relative;background:rgba(40,44,42,.05);color:#004567;font-size:14px;font-weight:500;display:block;letter-spacing:0;outline:0;padding:6px 20px;text-decoration:none;border-top:3px solid transparent}.wpacu-bulk-changes-tabs a:hover{background:#f1f1f1;border-top:3px solid transparent}.wpacu-bulk-changes-tabs .current a{background:#fff;border-top:3px solid #004567}.wpacu-bulk-changes-tabs .current a:hover{background:#fff}.wpacu-bulk-changes-tabs .current a:after,.wpacu-bulk-changes-tabs .current a:before{top:100%;left:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.wpacu-bulk-changes-tabs .current a:after{border-color:rgba(136,183,213,0);border-top-color:#fff;border-width:12px;margin-left:-12px}.wpacu-bulk-changes-tabs .current a:before{border-color:rgba(194,225,245,0);border-top-color:rgba(40,44,42,.1);border-width:13px;margin-left:-13px}
classes/CleanUp.php CHANGED
@@ -12,17 +12,10 @@ class CleanUp
12
  */
13
  public function init()
14
  {
15
- add_action('init', function() {
16
- // Is "Test Mode" enabled and the page is viewed by a regular visitor (non-admin)?
17
- // Stop here as the script will NOT PREVENT any of the elements below to load
18
- // They will load as they used to for the regular visitor while the admin debugs the website
19
- if (Main::instance()->preventAssetsSettings()) {
20
- return;
21
- }
22
-
23
- // Perform the cleaning
24
- CleanUp::doClean();
25
- }, 12);
26
  }
27
 
28
  /**
@@ -30,6 +23,10 @@ class CleanUp
30
  */
31
  public function doClean()
32
  {
 
 
 
 
33
  $settings = Main::instance()->settings;
34
 
35
  // Remove "Really Simple Discovery (RSD)" link?
@@ -88,8 +85,8 @@ class CleanUp
88
 
89
  // Remove "WordPress version" and all other "generator" meta tags?
90
  if ($settings['remove_generator_tag']) {
91
- add_action('wp_loaded', function () {
92
- ob_start(function ($htmlSource) {
93
  return self::removeMetaGenerators($htmlSource);
94
  });
95
  }, PHP_INT_MAX);
@@ -97,8 +94,8 @@ class CleanUp
97
 
98
  // Remove valid HTML Comments
99
  if ($settings['remove_html_comments']) {
100
- add_action('wp_loaded', function () {
101
- ob_start(function ($htmlSource) {
102
  return self::removeHtmlComments($htmlSource);
103
  });
104
  }, PHP_INT_MAX);
@@ -115,8 +112,8 @@ class CleanUp
115
  }
116
 
117
  // Also clean it up from the <head>
118
- add_action('wp_loaded', function() {
119
- ob_start(function ($htmlSource) {
120
  $pingBackUrl = get_bloginfo('pingback_url');
121
 
122
  $matchRegExps = array(
@@ -140,13 +137,13 @@ class CleanUp
140
  public function disableXmlRpcPingback()
141
  {
142
  // Disable Pingback method
143
- add_filter('xmlrpc_methods', function ($methods) {
144
  unset($methods['pingback.ping'], $methods['pingback.extensions.getPingbacks']);
145
  return $methods;
146
  } );
147
 
148
  // Remove X-Pingback HTTP header
149
- add_filter('wp_headers', function ($headers) {
150
  unset($headers['X-Pingback']);
151
  return $headers;
152
  });
@@ -239,8 +236,8 @@ class CleanUp
239
  }
240
 
241
  if (! (function_exists('libxml_use_internal_errors')
242
- && function_exists('libxml_clear_errors')
243
- && class_exists('DOMDocument')))
244
  {
245
  return $htmlSource;
246
  }
@@ -293,7 +290,7 @@ class CleanUp
293
  // Do not strip MSIE conditional comments
294
  if (strpos($entireComment, '<!--<![endif]-->') !== false ||
295
  preg_match('#<!--\[if(.*?)]>(.*?)<!-->#si', $entireComment) ||
296
- preg_match('#<!--\[if(.*?)\[endif\]-->#si', $entireComment)) {
297
  continue;
298
  }
299
 
@@ -439,7 +436,7 @@ class CleanUp
439
  */
440
  public function doDisableOembed()
441
  {
442
- add_action('init', function() {
443
  // Remove the REST API endpoint.
444
  remove_action('rest_api_init', 'wp_oembed_register_route');
445
 
@@ -447,7 +444,7 @@ class CleanUp
447
  add_filter('embed_oembed_discover', '__return_false');
448
 
449
  // Don't filter oEmbed results.
450
- remove_filter('oembed_dataparse', 'wp_filter_oembed_result', 10);
451
 
452
  // Remove oEmbed discovery links.
453
  remove_action('wp_head', 'wp_oembed_add_discovery_links');
@@ -455,12 +452,12 @@ class CleanUp
455
  // Remove oEmbed-specific JavaScript from the front-end and back-end.
456
  remove_action('wp_head', 'wp_oembed_add_host_js');
457
 
458
- add_filter('tiny_mce_plugins', function ($plugins) {
459
  return array_diff($plugins, array('wpembed'));
460
  });
461
 
462
  // Remove all embeds rewrite rules.
463
- add_filter('rewrite_rules_array', function ($rules) {
464
  foreach($rules as $rule => $rewrite) {
465
  if (false !== strpos($rewrite, 'embed=true')) {
466
  unset($rules[$rule]);
@@ -470,7 +467,7 @@ class CleanUp
470
  });
471
 
472
  // Remove filter of the oEmbed result before any HTTP requests are made.
473
- remove_filter('pre_oembed_result', 'wp_filter_pre_oembed_result', 10);
474
  }, 9999 );
475
  }
476
 
@@ -523,7 +520,7 @@ class CleanUp
523
  add_filter('sgo_js_minify_exclude', array($this, 'allJsHandles'));
524
  add_filter('sgo_js_async_exclude', array($this, 'allJsHandles'));
525
 
526
- add_filter('sgo_html_minify_exclude_params', function ($excludeParams) {
527
  $excludeParams[] = WPACU_LOAD_ASSETS_REQ_KEY;
528
  return $excludeParams;
529
  });
12
  */
13
  public function init()
14
  {
15
+ // Is "Test Mode" is enabled and the page is viewed by a regular visitor (not administrator with plugin activation privileges)?
16
+ // Stop here as the script will NOT PREVENT any of the elements below to load
17
+ // They will load as they used to for the regular visitor while the admin debugs the website
18
+ add_action('init', array($this, 'doClean'), 12);
 
 
 
 
 
 
 
19
  }
20
 
21
  /**
23
  */
24
  public function doClean()
25
  {
26
+ if (Main::instance()->preventAssetsSettings()) {
27
+ return;
28
+ }
29
+
30
  $settings = Main::instance()->settings;
31
 
32
  // Remove "Really Simple Discovery (RSD)" link?
85
 
86
  // Remove "WordPress version" and all other "generator" meta tags?
87
  if ($settings['remove_generator_tag']) {
88
+ add_action('wp_loaded', static function () {
89
+ ob_start(static function ($htmlSource) {
90
  return self::removeMetaGenerators($htmlSource);
91
  });
92
  }, PHP_INT_MAX);
94
 
95
  // Remove valid HTML Comments
96
  if ($settings['remove_html_comments']) {
97
+ add_action('wp_loaded', static function () {
98
+ ob_start(static function ($htmlSource) {
99
  return self::removeHtmlComments($htmlSource);
100
  });
101
  }, PHP_INT_MAX);
112
  }
113
 
114
  // Also clean it up from the <head>
115
+ add_action('wp_loaded', static function() {
116
+ ob_start(static function ($htmlSource) {
117
  $pingBackUrl = get_bloginfo('pingback_url');
118
 
119
  $matchRegExps = array(
137
  public function disableXmlRpcPingback()
138
  {
139
  // Disable Pingback method
140
+ add_filter('xmlrpc_methods', static function ($methods) {
141
  unset($methods['pingback.ping'], $methods['pingback.extensions.getPingbacks']);
142
  return $methods;
143
  } );
144
 
145
  // Remove X-Pingback HTTP header
146
+ add_filter('wp_headers', static function ($headers) {
147
  unset($headers['X-Pingback']);
148
  return $headers;
149
  });
236
  }
237
 
238
  if (! (function_exists('libxml_use_internal_errors')
239
+ && function_exists('libxml_clear_errors')
240
+ && class_exists('DOMDocument')))
241
  {
242
  return $htmlSource;
243
  }
290
  // Do not strip MSIE conditional comments
291
  if (strpos($entireComment, '<!--<![endif]-->') !== false ||
292
  preg_match('#<!--\[if(.*?)]>(.*?)<!-->#si', $entireComment) ||
293
+ preg_match('#<!--\[if(.*?)\[endif]-->#si', $entireComment)) {
294
  continue;
295
  }
296
 
436
  */
437
  public function doDisableOembed()
438
  {
439
+ add_action('init', static function() {
440
  // Remove the REST API endpoint.
441
  remove_action('rest_api_init', 'wp_oembed_register_route');
442
 
444
  add_filter('embed_oembed_discover', '__return_false');
445
 
446
  // Don't filter oEmbed results.
447
+ remove_filter('oembed_dataparse', 'wp_filter_oembed_result');
448
 
449
  // Remove oEmbed discovery links.
450
  remove_action('wp_head', 'wp_oembed_add_discovery_links');
452
  // Remove oEmbed-specific JavaScript from the front-end and back-end.
453
  remove_action('wp_head', 'wp_oembed_add_host_js');
454
 
455
+ add_filter('tiny_mce_plugins', static function ($plugins) {
456
  return array_diff($plugins, array('wpembed'));
457
  });
458
 
459
  // Remove all embeds rewrite rules.
460
+ add_filter('rewrite_rules_array', static function ($rules) {
461
  foreach($rules as $rule => $rewrite) {
462
  if (false !== strpos($rewrite, 'embed=true')) {
463
  unset($rules[$rule]);
467
  });
468
 
469
  // Remove filter of the oEmbed result before any HTTP requests are made.
470
+ remove_filter('pre_oembed_result', 'wp_filter_pre_oembed_result');
471
  }, 9999 );
472
  }
473
 
520
  add_filter('sgo_js_minify_exclude', array($this, 'allJsHandles'));
521
  add_filter('sgo_js_async_exclude', array($this, 'allJsHandles'));
522
 
523
+ add_filter('sgo_html_minify_exclude_params', static function ($excludeParams) {
524
  $excludeParams[] = WPACU_LOAD_ASSETS_REQ_KEY;
525
  return $excludeParams;
526
  });
classes/Lite.php CHANGED
@@ -26,7 +26,7 @@ class Lite
26
  $current_screen = \get_current_screen();
27
 
28
  if ($current_screen->base === 'term' && isset($current_screen->taxonomy) && $current_screen->taxonomy != '') {
29
- add_action ($current_screen->taxonomy . '_edit_form_fields', function ($tag) {
30
  ?>
31
  <tr class="form-field">
32
  <th scope="row" valign="top"><label for="wpassetcleanup_list"><?php echo WPACU_PLUGIN_TITLE; ?> <?php _e('CSS &amp; JavaScript Load Manager', 'wp-asset-clean-up'); ?></label></th>
26
  $current_screen = \get_current_screen();
27
 
28
  if ($current_screen->base === 'term' && isset($current_screen->taxonomy) && $current_screen->taxonomy != '') {
29
+ add_action ($current_screen->taxonomy . '_edit_form_fields', static function ($tag) {
30
  ?>
31
  <tr class="form-field">
32
  <th scope="row" valign="top"><label for="wpassetcleanup_list"><?php echo WPACU_PLUGIN_TITLE; ?> <?php _e('CSS &amp; JavaScript Load Manager', 'wp-asset-clean-up'); ?></label></th>
classes/Main.php CHANGED
@@ -109,20 +109,6 @@ class Main
109
  */
110
  public $ignoreChildrenHandlesOnTheFly = array();
111
 
112
- /**
113
- * @var int
114
- */
115
- /*
116
- public $lastScriptPos = 1;
117
- */
118
-
119
- /**
120
- * @var int
121
- */
122
- /*
123
- public $lastStylePos = 1;
124
- */
125
-
126
  /**
127
  * @var int
128
  */
@@ -189,7 +175,8 @@ class Main
189
  'autoptimize-toolbar',
190
  'query-monitor',
191
  'wp-fastest-cache-toolbar', // WP Fastest Cache plugin toolbar CSS
192
- 'litespeed-cache' // LiteSpeed toolbar
 
193
  );
194
 
195
  $this->skipAssets['scripts'] = array(
@@ -1102,9 +1089,7 @@ class Main
1102
 
1103
  $list = array();
1104
 
1105
- $currentUnloadedAll = $currentUnloaded = (array)json_decode(
1106
- $this->getAssetsUnloaded($this->getCurrentPostId())
1107
- );
1108
 
1109
  // Append global unloaded assets to current (one by one) unloaded ones
1110
  if (! empty($this->globalUnloaded['styles'])) {
@@ -1302,8 +1287,6 @@ class Main
1302
  $data['all'] = Sorting::sortListByAlpha($data['all']);
1303
  }
1304
 
1305
- //echo '<pre>'; print_r($data['all']);
1306
-
1307
  $this->fetchUrl = Misc::getPageUrl($this->getCurrentPostId());
1308
 
1309
  $data['fetch_url'] = $this->fetchUrl;
@@ -1920,14 +1903,6 @@ class Main
1920
  }
1921
 
1922
  /**
1923
- * @return bool
1924
- */
1925
- public static function isSettingsPage()
1926
- {
1927
- return (Misc::getVar('get', 'page') === WPACU_PLUGIN_ID . '_settings');
1928
- }
1929
-
1930
- /**
1931
  * @return bool
1932
  */
1933
  public static function isWpDefaultSearchPage()
109
  */
110
  public $ignoreChildrenHandlesOnTheFly = array();
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  /**
113
  * @var int
114
  */
175
  'autoptimize-toolbar',
176
  'query-monitor',
177
  'wp-fastest-cache-toolbar', // WP Fastest Cache plugin toolbar CSS
178
+ 'litespeed-cache', // LiteSpeed toolbar
179
+ 'siteground-optimizer-combined-styles-header' // Combine CSS in SG Optimiser (irrelevant as it made from the combined handles)
180
  );
181
 
182
  $this->skipAssets['scripts'] = array(
1089
 
1090
  $list = array();
1091
 
1092
+ $currentUnloadedAll = $currentUnloaded = json_decode($this->getAssetsUnloaded($this->getCurrentPostId()), ARRAY_A);
 
 
1093
 
1094
  // Append global unloaded assets to current (one by one) unloaded ones
1095
  if (! empty($this->globalUnloaded['styles'])) {
1287
  $data['all'] = Sorting::sortListByAlpha($data['all']);
1288
  }
1289
 
 
 
1290
  $this->fetchUrl = Misc::getPageUrl($this->getCurrentPostId());
1291
 
1292
  $data['fetch_url'] = $this->fetchUrl;
1903
  }
1904
 
1905
  /**
 
 
 
 
 
 
 
 
1906
  * @return bool
1907
  */
1908
  public static function isWpDefaultSearchPage()
classes/Misc.php CHANGED
@@ -1135,7 +1135,7 @@ SQL;
1135
  }
1136
 
1137
  $result = round(
1138
- // 1024 ** ($base - $floorBase) is available only from PHP 5.6+
1139
  pow(1024, ($base - $floorBase)),
1140
  $precision
1141
  );
1135
  }
1136
 
1137
  $result = round(
1138
+ // 1024 ** ($base - $floorBase) is available only from PHP 5.6+
1139
  pow(1024, ($base - $floorBase)),
1140
  $precision
1141
  );
classes/OptimiseAssets/CombineCss.php ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WpAssetCleanUp\OptimiseAssets;
3
+
4
+ use WpAssetCleanUp\Main;
5
+ use WpAssetCleanUp\Menu;
6
+ use WpAssetCleanUp\FileSystem;
7
+
8
+ /**
9
+ * Class CombineCss
10
+ * @package WpAssetCleanUp\OptimiseAssets
11
+ */
12
+ class CombineCss
13
+ {
14
+ /**
15
+ * @var string
16
+ */
17
+ public static $jsonStorageFile = 'css-combined{maybe-extra-info}.json';
18
+
19
+ /**
20
+ * @param $htmlSource
21
+ *
22
+ * @return mixed
23
+ */
24
+ public static function doCombine($htmlSource)
25
+ {
26
+ $useDom = function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument');
27
+
28
+ if (! $useDom) {
29
+ return $htmlSource;
30
+ }
31
+
32
+ if ( array_key_exists('wpacu_no_css_combine', $_GET) || // not on query string request (debugging purposes)
33
+ ! self::proceedWithCssCombine() ) {
34
+ return $htmlSource;
35
+ }
36
+
37
+ // Speed up processing by getting the already existing final CSS file URI
38
+ // This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
39
+ $storageJsonContents = OptimizeCommon::getAssetCachedData(self::$jsonStorageFile, OptimizeCss::getRelPathCssCacheDir(), 'css');
40
+
41
+ // $uriToFinalCssFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathCssCacheDir()
42
+ // which is usually "wp-content/cache/asset-cleanup/css/"
43
+
44
+ if (empty($storageJsonContents)) {
45
+ $storageJsonContentsToSave = array();
46
+
47
+ /*
48
+ * NO CACHING? Parse the DOM
49
+ */
50
+ // Nothing in the database records or the retrieved cached file does not exist?
51
+ OptimizeCommon::clearAssetCachedData( self::$jsonStorageFile );
52
+
53
+ // Fetch the DOM, and then set a new transient
54
+ $documentForCSS = new \DOMDocument();
55
+
56
+ libxml_use_internal_errors(true);
57
+
58
+ // Fore some reason, <noscript> is not recognised by DOMDocument as a tag belonging to HEAD
59
+ $htmlSourceAlt = str_replace(array('<noscript>', '</noscript>'), array('<!--', '-->'), $htmlSource);
60
+
61
+ $documentForCSS->loadHTML($htmlSourceAlt);
62
+
63
+ $storageJsonContents = array();
64
+
65
+ foreach ( array( 'head', 'body' ) as $docLocationTag ) {
66
+ $combinedUriPaths = $localAssetsPaths = $linkHrefs = array();
67
+
68
+ $docLocationElements = $documentForCSS->getElementsByTagName( $docLocationTag )->item( 0 );
69
+ $linkTags = $docLocationElements->getElementsByTagName( 'link' );
70
+
71
+ if ( $linkTags === null ) {
72
+ continue;
73
+ }
74
+
75
+ foreach ( $linkTags as $tagObject ) {
76
+ if ( ! $tagObject->hasAttributes() ) {
77
+ continue;
78
+ }
79
+
80
+ $linkAttributes = array();
81
+
82
+ foreach ( $tagObject->attributes as $attrObj ) {
83
+ $linkAttributes[ $attrObj->nodeName ] = trim( $attrObj->nodeValue );
84
+ }
85
+
86
+ // The attribute's value was fetched for verification, thus the attribute is not relevant anymore
87
+ if (isset($linkAttributes['data-wpacu-link-href-before']) && $linkAttributes['data-wpacu-link-href-before']) {
88
+ $htmlSource = str_replace('<link data-wpacu-link-href-before="'.$linkAttributes['data-wpacu-link-href-before'].'" ', '<link ', $htmlSource);
89
+ }
90
+
91
+ // Only rel="stylesheet" (with no rel="preload" associated with it) gets prepared for combining as links with rel="preload" (if any) are never combined into a standard render-blocking CSS file
92
+ // rel="preload" is there for a reason to make sure the CSS code is made available earlier prior to the one from rel="stylesheet" which is render-blocking
93
+ if (isset($linkAttributes['rel'], $linkAttributes['href']) && $linkAttributes['href']) {
94
+ // Make sure that tag value is checked and it's matched against the value from the HTML source code
95
+ //$htmlSource .= $attrObj->nodeValue."\n";
96
+ $href = (string) $linkAttributes['href'];
97
+
98
+ // 1) Check if there is any rel="preload" connected to the rel="stylesheet"
99
+ // making sure the file is not added to the final CSS combined file
100
+
101
+ // 2) Only combine media "all", "screen" and the ones with no media
102
+ // Do not combine media='only screen and (max-width: 768px)' etc.
103
+ if ( $linkAttributes['rel'] === 'preload' ) {
104
+ continue;
105
+ }
106
+
107
+ if (isset($linkAttributes['data-wpacu-to-be-preloaded-basic']) && $linkAttributes['data-wpacu-to-be-preloaded-basic']) {
108
+ continue;
109
+ }
110
+
111
+ if (array_key_exists( 'media', $linkAttributes ) && ! in_array( $linkAttributes['media'], array( 'all', 'screen' ) ) ) {
112
+ continue;
113
+ }
114
+
115
+ if (self::skipCombine( $linkAttributes['href'] ) ) {
116
+ continue;
117
+ }
118
+
119
+ // Was it optimized and has the URL updated? Check the Source URL
120
+ if (isset($linkAttributes['data-wpacu-link-href-before']) && $linkAttributes['data-wpacu-link-href-before'] && self::skipCombine($linkAttributes['data-wpacu-link-href-before'])) {
121
+ continue;
122
+ }
123
+
124
+ $localAssetPath = OptimizeCommon::getLocalAssetPath( $href, 'css' );
125
+
126
+ // It will skip external stylesheets (from a different domain)
127
+ if ( $localAssetPath ) {
128
+ $combinedUriPaths[] = OptimizeCommon::getHrefRelPath( $href );
129
+ $localAssetsPaths[ $href ] = $localAssetPath;
130
+ $linkHrefs[] = $href;
131
+ }
132
+ }
133
+ }
134
+
135
+ // No Link Tags? Continue
136
+ if ( empty( $linkHrefs ) ) {
137
+ continue;
138
+ }
139
+
140
+ $maybeDoCssCombine = self::maybeDoCssCombine( sha1( implode( '', $combinedUriPaths ) ), $localAssetsPaths, $linkHrefs, $docLocationTag );
141
+
142
+ // Local path to combined CSS file
143
+ $localFinalCssFile = $maybeDoCssCombine['local_final_css_file'];
144
+
145
+ // URI (e.g. /wp-content/cache/asset-cleanup/[file-name-here.css]) to the combined CSS file
146
+ $uriToFinalCssFile = $maybeDoCssCombine['uri_final_css_file'];
147
+
148
+ // Any link hrefs removed perhaps if the file wasn't combined?
149
+ $linkHrefs = $maybeDoCssCombine['link_hrefs'];
150
+
151
+ if ( file_exists( $localFinalCssFile ) ) {
152
+ $storageJsonContents[$docLocationTag] = array(
153
+ 'uri_to_final_css_file' => $uriToFinalCssFile,
154
+ 'link_hrefs' => array_map( static function ( $href ) {
155
+ return str_replace( '{site_url}', site_url(), $href );
156
+ }, $linkHrefs )
157
+ );
158
+
159
+ $storageJsonContentsToSave[$docLocationTag] = array(
160
+ 'uri_to_final_css_file' => $uriToFinalCssFile,
161
+ 'link_hrefs' => array_map( static function ( $href ) {
162
+ return str_replace( site_url(), '{site_url}', $href );
163
+ }, $linkHrefs )
164
+ );
165
+ }
166
+ }
167
+
168
+ libxml_clear_errors();
169
+
170
+ OptimizeCommon::setAssetCachedData(
171
+ self::$jsonStorageFile,
172
+ OptimizeCss::getRelPathCssCacheDir(),
173
+ json_encode($storageJsonContentsToSave)
174
+ );
175
+ }
176
+
177
+ if ( ! empty($storageJsonContents) ) {
178
+ foreach ($storageJsonContents as $locationTag => $storageJsonContentLocation) {
179
+ if (! isset($storageJsonContentLocation['link_hrefs'][0])) {
180
+ continue;
181
+ }
182
+
183
+ $storageJsonContentLocation['link_hrefs'] = array_map( static function ( $href ) {
184
+ return str_replace( '{site_url}', site_url(), $href );
185
+ }, $storageJsonContentLocation['link_hrefs'] );
186
+
187
+ $finalTagUrl = OptimizeCommon::filterWpContentUrl() . OptimizeCss::getRelPathCssCacheDir() . $storageJsonContentLocation['uri_to_final_css_file'];
188
+
189
+ $finalCssTag = <<<HTML
190
+ <link id='wpacu-combined-css-{$locationTag}' rel='stylesheet' href='{$finalTagUrl}' type='text/css' media='all' />
191
+ HTML;
192
+ $htmlSourceBeforeAnyLinkTagReplacement = $htmlSource;
193
+
194
+ // Detect first LINK tag from the <$locationTag> and replace it with the final combined LINK tag
195
+ $firstLinkTag = OptimizeCss::getFirstLinkTag($storageJsonContentLocation['link_hrefs'][0], $htmlSource);
196
+
197
+ if ($firstLinkTag) {
198
+ $htmlSource = str_replace( $firstLinkTag, $finalCssTag, $htmlSource );
199
+ }
200
+
201
+ if ($htmlSource !== $htmlSourceBeforeAnyLinkTagReplacement) {
202
+ $htmlSource = OptimizeCommon::stripJustCombinedFileTags( $storageJsonContentLocation['link_hrefs'], $htmlSource, 'css' ); // Strip the combined files to avoid duplicate code
203
+
204
+ // There should be at least two replacements made
205
+ if ($htmlSource === 'do_not_combine') {
206
+ $htmlSource = $htmlSourceBeforeAnyLinkTagReplacement;
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ return $htmlSource;
213
+ }
214
+
215
+ /**
216
+ * @param $href
217
+ *
218
+ * @return bool
219
+ */
220
+ public static function skipCombine($href)
221
+ {
222
+ $regExps = array();
223
+
224
+ if (Main::instance()->settings['combine_loaded_css_exceptions'] !== '') {
225
+ $loadedCssExceptionsPatterns = trim(Main::instance()->settings['combine_loaded_css_exceptions']);
226
+
227
+ if (strpos($loadedCssExceptionsPatterns, "\n")) {
228
+ // Multiple values (one per line)
229
+ foreach (explode("\n", $loadedCssExceptionsPatterns) as $loadedCssExceptionPattern) {
230
+ $regExps[] = '#'.trim($loadedCssExceptionPattern).'#';
231
+ }
232
+ } else {
233
+ // Only one value?
234
+ $regExps[] = '#'.trim($loadedCssExceptionsPatterns).'#';
235
+ }
236
+ }
237
+
238
+ // No exceptions set? Do not skip combination
239
+ if (empty($regExps)) {
240
+ return false;
241
+ }
242
+
243
+ foreach ($regExps as $regExp) {
244
+ if ( preg_match( $regExp, $href ) ) {
245
+ // Skip combination
246
+ return true;
247
+ }
248
+ }
249
+
250
+ return false;
251
+ }
252
+
253
+ /**
254
+ * @param $shaOneCombinedUriPaths
255
+ * @param $localAssetsPaths
256
+ * @param $linkHrefs
257
+ * @param $docLocationTag
258
+ *
259
+ * @return array
260
+ */
261
+ public static function maybeDoCssCombine($shaOneCombinedUriPaths, $localAssetsPaths, $linkHrefs, $docLocationTag)
262
+ {
263
+ $current_user = wp_get_current_user();
264
+ $dirToUserCachedFile = ((isset($current_user->ID) && $current_user->ID > 0) ? 'logged-in/'.$current_user->ID.'/' : '');
265
+
266
+ $uriToFinalCssFile = $dirToUserCachedFile . $docLocationTag . '-' .$shaOneCombinedUriPaths . '.css';
267
+ $localFinalCssFile = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $uriToFinalCssFile;
268
+
269
+ $localDirForCssFile = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $dirToUserCachedFile;
270
+
271
+ // Only combine if $shaOneCombinedUriPaths.css does not exist
272
+ // If "?ver" value changes on any of the assets or the asset list changes in any way
273
+ // then $shaOneCombinedUriPaths will change too and a new CSS file will be generated and loaded
274
+
275
+ $skipIfFileExists = true;
276
+
277
+ if ($skipIfFileExists || ! file_exists($localFinalCssFile)) {
278
+ // Change $assetsContents as paths to fonts and images that are relative (e.g. ../, ../../) have to be updated
279
+ $finalAssetsContents = '';
280
+
281
+ foreach ($localAssetsPaths as $assetHref => $localAssetsPath) {
282
+ $posLastSlash = strrpos($assetHref, '/');
283
+ $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
284
+
285
+ $parseUrl = parse_url($pathToAssetDir);
286
+
287
+ if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
288
+ $pathToAssetDir = str_replace(
289
+ array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
290
+ '',
291
+ $pathToAssetDir
292
+ );
293
+ } elseif (strpos($pathToAssetDir, '//') === 0) {
294
+ $pathToAssetDir = str_replace(
295
+ array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
296
+ '',
297
+ $pathToAssetDir
298
+ );
299
+ }
300
+
301
+ $cssContent = FileSystem::file_get_contents($localAssetsPath);
302
+
303
+ if ($cssContent) {
304
+ // Do not combine it if it contains "@import"
305
+ if (stripos($cssContent, '@import') !== false) {
306
+ unset($localAssetsPaths[$assetHref]);
307
+ $linkHrefKey = array_search($assetHref, $linkHrefs);
308
+ unset($linkHrefs[$linkHrefKey]);
309
+ continue;
310
+ }
311
+
312
+ // Does it have a source map? Strip it
313
+ if (strpos($cssContent, 'sourceMappingURL') !== false) {
314
+ $cssContent = OptimizeCommon::stripSourceMap($cssContent);
315
+ }
316
+
317
+ $finalAssetsContents .= '/*** Source: '.str_replace(ABSPATH, '/', $localAssetsPath)." ***/\n";
318
+ $finalAssetsContents .= OptimizeCss::maybeFixCssBackgroundUrls($cssContent, $pathToAssetDir . '/') . "\n\n";
319
+ }
320
+ }
321
+
322
+ $finalAssetsContents = trim($finalAssetsContents);
323
+
324
+ if ($finalAssetsContents) {
325
+ if ($dirToUserCachedFile !== '' && isset($current_user->ID) && $current_user->ID > 0 && ! is_dir($localDirForCssFile)) {
326
+ $makeLocalDirForCss = @mkdir($localDirForCssFile);
327
+
328
+ if (! $makeLocalDirForCss) {
329
+ return array('uri_final_css_file' => '', 'local_final_css_file' => '');
330
+ }
331
+ }
332
+
333
+ FileSystem::file_put_contents($localFinalCssFile, $finalAssetsContents);
334
+ }
335
+ }
336
+
337
+ return array(
338
+ 'uri_final_css_file' => $uriToFinalCssFile,
339
+ 'local_final_css_file' => $localFinalCssFile,
340
+ 'link_hrefs' => $linkHrefs
341
+ );
342
+ }
343
+
344
+ /**
345
+ * @return bool
346
+ */
347
+ public static function proceedWithCssCombine()
348
+ {
349
+ // No CSS files are combined in the Dashboard
350
+ // Always in the front-end view
351
+ // Do not combine if there's a POST request as there could be assets loading conditionally
352
+ // that might not be needed when the page is accessed without POST, making the final CSS file larger
353
+ if (! empty($_POST) || is_admin()) {
354
+ return false; // Do not combine
355
+ }
356
+
357
+ // Only clean request URIs allowed (with Exceptions)
358
+ // Exceptions
359
+ if ((strpos($_SERVER['REQUEST_URI'], '?') !== false) && ! OptimizeCommon::loadOptimizedAssetsIfQueryStrings()) {
360
+ return false;
361
+ }
362
+
363
+ if (! OptimizeCommon::doCombineIsRegularPage()) {
364
+ return false;
365
+ }
366
+
367
+ $pluginSettings = Main::instance()->settings;
368
+
369
+ if ($pluginSettings['test_mode'] && ! Menu::userCanManageAssets()) {
370
+ return false; // Do not combine anything if "Test Mode" is ON and the user is in guest mode (not logged-in)
371
+ }
372
+
373
+ if ($pluginSettings['combine_loaded_css'] === '') {
374
+ return false; // Do not combine
375
+ }
376
+
377
+ if (OptimizeCss::isOptimizeCssEnabledByOtherParty('if_enabled')) {
378
+ return false; // Do not combine (it's already enabled in other plugin)
379
+ }
380
+
381
+ if ( ($pluginSettings['combine_loaded_css'] === 'for_admin'
382
+ || $pluginSettings['combine_loaded_css_for_admin_only'] == 1)
383
+ && Menu::userCanManageAssets()) {
384
+ return true; // Do combine
385
+ }
386
+
387
+ if ( $pluginSettings['combine_loaded_css_for_admin_only'] === ''
388
+ && in_array($pluginSettings['combine_loaded_css'], array('for_all', 1)) ) {
389
+ return true; // Do combine
390
+ }
391
+
392
+ // Finally, return false as none of the checks above matched
393
+ return false;
394
+ }
395
+ }
classes/OptimiseAssets/CombineJs.php ADDED
@@ -0,0 +1,486 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WpAssetCleanUp\OptimiseAssets;
3
+
4
+ use WpAssetCleanUp\Main;
5
+ use WpAssetCleanUp\Menu;
6
+ use WpAssetCleanUp\FileSystem;
7
+
8
+ /**
9
+ * Class CombineJs
10
+ * @package WpAssetCleanUp\OptimiseAssets
11
+ */
12
+ class CombineJs
13
+ {
14
+ /**
15
+ * @var string
16
+ */
17
+ public static $jsonStorageFile = 'js-combined{maybe-extra-info}.json';
18
+
19
+ /**
20
+ * @param $htmlSource
21
+ *
22
+ * @return mixed
23
+ */
24
+ public static function doCombine($htmlSource)
25
+ {
26
+ if ( array_key_exists('wpacu_no_js_combine', $_GET) || // not on query string request (debugging purposes)
27
+ ! self::proceedWithJsCombine() ) {
28
+ return $htmlSource;
29
+ }
30
+
31
+ $useDom = function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument');
32
+
33
+ if (! $useDom) {
34
+ return $htmlSource;
35
+ }
36
+
37
+ $combineLevel = 2;
38
+
39
+ // Speed up processing by getting the already existing final CSS file URI
40
+ // This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
41
+ $finalCacheList = OptimizeCommon::getAssetCachedData(self::$jsonStorageFile, OptimizeJs::getRelPathJsCacheDir(), 'js');
42
+
43
+ // $uriToFinalJsFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathJsCacheDir()
44
+ // which is usually "wp-content/cache/asset-cleanup/js/"
45
+
46
+ // "false" would make it avoid checking the cache and always use the DOM Parser / RegExp
47
+ // for DEV purposes ONLY as it uses more resources
48
+ if (empty($finalCacheList)) {
49
+ /*
50
+ * NO CACHING TRANSIENT; Parse the DOM
51
+ */
52
+ // Nothing in the database records or the retrieved cached file does not exist?
53
+ OptimizeCommon::clearAssetCachedData(self::$jsonStorageFile);
54
+
55
+ $regExpPattern = '#<script[^>]*>.*?</script>#is';
56
+
57
+ preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
58
+
59
+ // No <script> tag found? Do not continue
60
+ if (empty($matchesSourcesFromTags)) {
61
+ return $htmlSource;
62
+ }
63
+
64
+ if ($combineLevel === 2) {
65
+ $matchesSourcesFromTags = OptimizeJs::clearInlineScriptTags($matchesSourcesFromTags);
66
+ }
67
+
68
+ if (empty($matchesSourcesFromTags)) {
69
+ return $htmlSource;
70
+ }
71
+
72
+ $combinableList = $bodyGroupIndexes = array();
73
+
74
+ $groupIndex = 1;
75
+ $jQueryAndMigrateGroup = 0;
76
+
77
+ $jQueryGroupIndex = $loadsLocaljQuery = $loadsLocaljQueryMigrate = false;
78
+
79
+ $lastScriptSrcFromHead = OptimizeJs::lastScriptSrcFromHead($htmlSource);
80
+
81
+ $reachedBody = false;
82
+
83
+ $domTag = new \DOMDocument();
84
+
85
+ libxml_use_internal_errors( true );
86
+
87
+ // Only keep combinable JS files
88
+ foreach ($matchesSourcesFromTags as $matchSourceFromTag) {
89
+ $matchedSourceFromTag = trim( $matchSourceFromTag[0] );
90
+
91
+ $domTag->loadHTML($matchedSourceFromTag);
92
+
93
+ $scriptNotCombinable = $scriptPreloaded = $src = false;
94
+
95
+ foreach ($domTag->getElementsByTagName( 'script' ) as $tagObject) {
96
+ if (! $tagObject->hasAttributes()) {
97
+ continue;
98
+ }
99
+
100
+ $scriptAttributes = array();
101
+
102
+ foreach ( $tagObject->attributes as $attrObj ) {
103
+ $scriptAttributes[ $attrObj->nodeName ] = trim($attrObj->nodeValue);
104
+ }
105
+
106
+ // The attribute's value was fetched for verification, thus the attribute is not relevant anymore
107
+ if (isset($scriptAttributes['data-wpacu-script-src-before']) && $scriptAttributes['data-wpacu-script-src-before']) {
108
+ $beforeAfterReps = array('<script data-wpacu-script-src-before="'.$scriptAttributes['data-wpacu-script-src-before'].'" ' => '<script ');
109
+ $matchedSourceFromTag = str_replace(array_keys($beforeAfterReps), array_values($beforeAfterReps), $matchedSourceFromTag);
110
+ $htmlSource = str_replace(array_keys($beforeAfterReps), array_values($beforeAfterReps), $htmlSource);
111
+ }
112
+
113
+ if (isset($scriptAttributes['src']) && $scriptAttributes['src']) {
114
+ $src = (string) $scriptAttributes['src'];
115
+
116
+ $scriptNotCombinable = false;
117
+
118
+ if (self::skipCombine($src)) {
119
+ $scriptNotCombinable = true;
120
+ }
121
+
122
+ // Do not add it to the combination list if it has "async" or "defer" attributes
123
+ if (in_array($scriptAttributes, array('async', 'defer'))) {
124
+ $scriptNotCombinable = true;
125
+ }
126
+
127
+ if (isset($scriptAttributes['data-wpacu-to-be-preloaded-basic']) && $scriptAttributes['data-wpacu-to-be-preloaded-basic']) {
128
+ $scriptNotCombinable = $scriptPreloaded = true;
129
+ }
130
+
131
+ // Was it optimized and has the URL updated? Check the Source URL
132
+ if (! $scriptNotCombinable && isset($scriptAttributes['data-wpacu-script-src-before']) && $scriptAttributes['data-wpacu-script-src-before'] && self::skipCombine($scriptAttributes['data-wpacu-script-src-before'])) {
133
+ $scriptNotCombinable = true;
134
+ }
135
+ }
136
+
137
+ }
138
+
139
+ if ( $src && ! $scriptNotCombinable ) {
140
+ $localAssetPath = OptimizeCommon::getLocalAssetPath( $src, 'js' );
141
+
142
+ if ( $localAssetPath ) {
143
+ $combinableList[ $groupIndex ][] = array(
144
+ 'src' => $src,
145
+ 'local' => $localAssetPath,
146
+ 'html' => $matchedSourceFromTag
147
+ );
148
+
149
+ if ( strpos( $localAssetPath, '/wp-includes/js/jquery/jquery.js' ) !== false ) {
150
+ $loadsLocaljQuery = true;
151
+ $jQueryGroupIndex = $groupIndex;
152
+
153
+ $jQueryArrayGroupKeys = array_keys( $combinableList[ $groupIndex ] );
154
+ $jQueryScriptIndex = array_pop( $jQueryArrayGroupKeys );
155
+
156
+ $jQueryAndMigrateGroup ++;
157
+ } elseif ( strpos( $localAssetPath,
158
+ '/wp-includes/js/jquery/jquery-migrate.' ) !== false ) {
159
+ $loadsLocaljQueryMigrate = true;
160
+ $jQueryAndMigrateGroup ++;
161
+ }
162
+ }
163
+
164
+ // We'll check the current group
165
+ // If we have jQuery and jQuery migrate, we will consider the group completed
166
+ // and we will move on to the next group
167
+ if ( $jQueryAndMigrateGroup > 1 ) {
168
+ $groupIndex ++;
169
+ $jQueryAndMigrateGroup = 0; // reset it to avoid having one file per group!
170
+ }
171
+
172
+ // Have we passed <head> and stumbled upon the first script tag from the <body>
173
+ // Then consider the group completed
174
+ if ($lastScriptSrcFromHead && ($src === $lastScriptSrcFromHead)) {
175
+ $groupIndex++;
176
+ $reachedBody = true;
177
+ }
178
+ } elseif (! $scriptPreloaded) {
179
+ $groupIndex ++;
180
+ }
181
+
182
+ if ($reachedBody) {
183
+ $bodyGroupIndexes[] = $groupIndex;
184
+ }
185
+ }
186
+
187
+ // Is the page loading local jQuery but not local jQuery Migrate?
188
+ // Keep jQuery as standalone file (not in the combinable list)
189
+ if ( $loadsLocaljQuery && ! $loadsLocaljQueryMigrate && isset($jQueryScriptIndex) ) {
190
+ unset($combinableList[$jQueryGroupIndex][$jQueryScriptIndex]);
191
+ }
192
+
193
+ // Could be pages such as maintenance mode with no external JavaScript files
194
+ if (empty($combinableList)) {
195
+ return $htmlSource;
196
+ }
197
+
198
+ $groupNo = 1;
199
+
200
+ $finalCacheList = array();
201
+
202
+ foreach ($combinableList as $groupIndex => $groupFiles) {
203
+ // Any groups having one file? Then it's not really a group and the file should load on its own
204
+ // Could be one extra file besides the jQuery & jQuery Migrate group or the only JS file called within the HEAD
205
+ if (count($groupFiles) < 2) {
206
+ continue;
207
+ }
208
+
209
+ $combinedUriPaths = $localAssetsPaths = $groupScriptTags = $groupScriptSrcs = array();
210
+
211
+ foreach ( $groupFiles as $groupFileData ) {
212
+ $src = $groupFileData['src'];
213
+ $groupScriptSrcs[] = $src;
214
+ $combinedUriPaths[] = OptimizeCommon::getHrefRelPath( $src );
215
+ $localAssetsPaths[ $src ] = $groupFileData['local'];
216
+ $groupScriptTags[] = $groupFileData['html'];
217
+ }
218
+
219
+ // <head> or <body>
220
+ $docLocationScript = in_array($groupIndex, $bodyGroupIndexes) ? 'body' : 'head';
221
+
222
+ $maybeDoJsCombine = self::maybeDoJsCombine(
223
+ sha1( implode( '', $combinedUriPaths ) ) . '-' . $groupNo,
224
+ $localAssetsPaths,
225
+ $docLocationScript
226
+ );
227
+
228
+ // Local path to combined CSS file
229
+ $localFinalJsFile = $maybeDoJsCombine['local_final_js_file'];
230
+
231
+ // URI (e.g. /wp-content/cache/asset-cleanup/[file-name-here.js]) to the combined JS file
232
+ $uriToFinalJsFile = $maybeDoJsCombine['uri_final_js_file'];
233
+
234
+ if ( ! file_exists( $localFinalJsFile ) ) {
235
+ return $htmlSource; // something is not right as the file wasn't created, we will return the original HTML source
236
+ }
237
+
238
+ $groupScriptSrcsFilter = array_map( function ( $src ) {
239
+ return str_replace( site_url(), '{site_url}', $src );
240
+ }, $groupScriptSrcs );
241
+
242
+ $groupScriptTagsFilter = array_map( function ( $scriptTag ) {
243
+ return str_replace( site_url(), '{site_url}', $scriptTag );
244
+ }, $groupScriptTags );
245
+
246
+ $finalCacheList[ $groupNo ] = array(
247
+ 'uri_to_final_js_file' => $uriToFinalJsFile,
248
+ 'script_srcs' => $groupScriptSrcsFilter,
249
+ 'script_tags' => $groupScriptTagsFilter
250
+ );
251
+
252
+ if (Main::instance()->settings['combine_loaded_js_defer_body'] && in_array($groupIndex, $bodyGroupIndexes)) {
253
+ $finalCacheList[ $groupNo ]['extras'][] = 'defer';
254
+ }
255
+
256
+ $groupNo++;
257
+ }
258
+
259
+ OptimizeCommon::setAssetCachedData(self::$jsonStorageFile, OptimizeJs::getRelPathJsCacheDir(), json_encode($finalCacheList));
260
+ }
261
+
262
+ if (! empty($finalCacheList)) {
263
+ foreach ( $finalCacheList as $groupNo => $cachedValues ) {
264
+ $htmlSourceBeforeGroupReplacement = $htmlSource;
265
+
266
+ $uriToFinalJsFile = $cachedValues['uri_to_final_js_file'];
267
+
268
+ // Basic Combining (1) -> replace "first" tag with the final combination tag (there would be most likely multiple groups)
269
+ // Enhanced Combining (2) -> replace "last" tag with the final combination tag (most likely one group)
270
+ $indexReplacement = ($combineLevel === 2) ? (count($cachedValues['script_tags']) - 1) : 0;
271
+
272
+ $finalTagUrl = OptimizeCommon::filterWpContentUrl() . OptimizeJs::getRelPathJsCacheDir() . $uriToFinalJsFile;
273
+
274
+ $deferAttr = (isset($cachedValues['extras']) && in_array('defer', $cachedValues['extras'])) ? 'defer="defer"' : '';
275
+
276
+ $finalJsTag = <<<HTML
277
+ <script {$deferAttr} id='wpacu-combined-js-group-{$groupNo}' type='text/javascript' src='{$finalTagUrl}'></script>
278
+ HTML;
279
+ $tagsStripped = 0;
280
+
281
+ foreach ( $cachedValues['script_tags'] as $groupScriptTagIndex => $scriptTag ) {
282
+ $scriptTag = str_replace( '{site_url}', site_url(), $scriptTag );
283
+
284
+ if ( $groupScriptTagIndex === $indexReplacement ) {
285
+ $htmlSourceBeforeTagReplacement = $htmlSource;
286
+ $htmlSource = OptimizeJs::strReplaceOnce( $scriptTag, $finalJsTag, $htmlSource );
287
+ } else {
288
+ $htmlSourceBeforeTagReplacement = $htmlSource;
289
+ $htmlSource = OptimizeJs::strReplaceOnce( $scriptTag, '', $htmlSource );
290
+ }
291
+
292
+ if ($htmlSource !== $htmlSourceBeforeTagReplacement) {
293
+ $tagsStripped++;
294
+ }
295
+ }
296
+
297
+ // At least two tags has have be stripped from the group to consider doing the group replacement
298
+ // If the tags weren't replaced it's likely there were changes to their structure after they were cached for the group merging
299
+ if ($tagsStripped < 2) {
300
+ $htmlSource = $htmlSourceBeforeGroupReplacement;
301
+ }
302
+ }
303
+ }
304
+
305
+ return $htmlSource;
306
+ }
307
+
308
+ /**
309
+ * @param $src
310
+ *
311
+ * @return bool
312
+ */
313
+ public static function skipCombine($src)
314
+ {
315
+ $regExps = array();
316
+
317
+ if (Main::instance()->settings['combine_loaded_js_exceptions'] !== '') {
318
+ $loadedCssExceptionsPatterns = trim(Main::instance()->settings['combine_loaded_js_exceptions']);
319
+
320
+ if (strpos($loadedCssExceptionsPatterns, "\n")) {
321
+ // Multiple values (one per line)
322
+ foreach (explode("\n", $loadedCssExceptionsPatterns) as $loadedCssExceptionPattern) {
323
+ $regExps[] = '#'.trim($loadedCssExceptionPattern).'#';
324
+ }
325
+ } else {
326
+ // Only one value?
327
+ $regExps[] = '#'.trim($loadedCssExceptionsPatterns).'#';
328
+ }
329
+ }
330
+
331
+ // No exceptions set? Do not skip combination
332
+ if (empty($regExps)) {
333
+ return false;
334
+ }
335
+
336
+ foreach ($regExps as $regExp) {
337
+ if ( preg_match( $regExp, $src ) ) {
338
+ // Skip combination
339
+ return true;
340
+ }
341
+ }
342
+
343
+ return false;
344
+ }
345
+
346
+ /**
347
+ * @param $shaOneCombinedUriPaths
348
+ * @param $localAssetsPaths
349
+ * @param $docLocationScript
350
+ *
351
+ * @return array
352
+ */
353
+ public static function maybeDoJsCombine($shaOneCombinedUriPaths, $localAssetsPaths, $docLocationScript)
354
+ {
355
+ $current_user = wp_get_current_user();
356
+ $dirToUserCachedFile = ((isset($current_user->ID) && $current_user->ID > 0) ? 'logged-in/'.$current_user->ID.'/' : '');
357
+
358
+ $uriToFinalJsFile = $dirToUserCachedFile . $docLocationScript . '-' . $shaOneCombinedUriPaths . '.js';
359
+
360
+ $localFinalJsFile = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $uriToFinalJsFile;
361
+ $localDirForJsFile = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $dirToUserCachedFile;
362
+
363
+ // Only combine if $shaOneCombinedUriPaths.js does not exist
364
+ // If "?ver" value changes on any of the assets or the asset list changes in any way
365
+ // then $shaOneCombinedUriPaths will change too and a new JS file will be generated and loaded
366
+
367
+ $skipIfFileExists = true;
368
+
369
+ if ($skipIfFileExists || ! file_exists($localFinalJsFile)) {
370
+ // Change $assetsContents as paths to fonts and images that are relative (e.g. ../, ../../) have to be updated
371
+ $finalJsContentsGroupsArray = array();
372
+
373
+ foreach ($localAssetsPaths as $assetHref => $localAssetsPath) {
374
+ $posLastSlash = strrpos($assetHref, '/');
375
+ $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
376
+
377
+ $parseUrl = parse_url($pathToAssetDir);
378
+
379
+ if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
380
+ $pathToAssetDir = str_replace(
381
+ array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
382
+ '',
383
+ $pathToAssetDir
384
+ );
385
+ } elseif (strpos($pathToAssetDir, '//') === 0) {
386
+ $pathToAssetDir = str_replace(
387
+ array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
388
+ '',
389
+ $pathToAssetDir
390
+ );
391
+ }
392
+
393
+ $jsContent = FileSystem::file_get_contents($localAssetsPath);
394
+
395
+ if ($jsContent) {
396
+ // Does it have a source map? Strip it
397
+ if (strpos($jsContent, 'sourceMappingURL') !== false) {
398
+ $jsContent = OptimizeCommon::stripSourceMap($jsContent);
399
+ }
400
+
401
+ $finalJsContentsIndex = 1;
402
+
403
+ $finalJsContentsGroupsArray[$finalJsContentsIndex][] = '/*** Source: '.str_replace(ABSPATH, '/', $localAssetsPath)." ***/\n" . OptimizeJs::maybeDoJsFixes($jsContent, $pathToAssetDir . '/') . "\n\n";
404
+ }
405
+ }
406
+
407
+ if (! empty($finalJsContentsGroupsArray)) {
408
+ $contentsOne = isset($finalJsContentsGroupsArray[1]) && ! empty($finalJsContentsGroupsArray[1]) ? implode ('', $finalJsContentsGroupsArray[1]) : '';
409
+ $contentsTwo = isset($finalJsContentsGroupsArray[2]) && ! empty($finalJsContentsGroupsArray[2]) ? implode ('', $finalJsContentsGroupsArray[2]) : '';
410
+
411
+ $finalJsContents = $contentsOne . $contentsTwo;
412
+
413
+ if ( $dirToUserCachedFile !== '' && isset( $current_user->ID ) && $current_user->ID > 0) {
414
+ if (! is_dir( $localDirForJsFile)) {
415
+ $makeLocalDirForJs = @mkdir($localDirForJsFile);
416
+
417
+ if (! $makeLocalDirForJs) {
418
+ return array('uri_final_js_file' => '', 'local_final_js_file' => '');
419
+ }
420
+ }
421
+ }
422
+
423
+ @file_put_contents( $localFinalJsFile, $finalJsContents );
424
+ }
425
+ }
426
+
427
+ return array(
428
+ 'uri_final_js_file' => $uriToFinalJsFile,
429
+ 'local_final_js_file' => $localFinalJsFile
430
+ );
431
+ }
432
+
433
+ /**
434
+ * @return bool
435
+ */
436
+ public static function proceedWithJsCombine()
437
+ {
438
+ // No JS files are combined in the Dashboard
439
+ // Always in the front-end view
440
+ // Do not combine if there's a POST request as there could be assets loading conditionally
441
+ // that might not be needed when the page is accessed without POST, making the final JS file larger
442
+ if (! empty($_POST) || is_admin()) {
443
+ return false; // Do not combine
444
+ }
445
+
446
+ // Only clean request URIs allowed (with few exceptions)
447
+ if (strpos($_SERVER['REQUEST_URI'], '?') !== false) {
448
+ // Exceptions
449
+ if (! OptimizeCommon::loadOptimizedAssetsIfQueryStrings()) {
450
+ return false;
451
+ }
452
+ }
453
+
454
+ if (! OptimizeCommon::doCombineIsRegularPage()) {
455
+ return false;
456
+ }
457
+
458
+ $pluginSettings = Main::instance()->settings;
459
+
460
+ if ($pluginSettings['test_mode'] && ! Menu::userCanManageAssets()) {
461
+ return false; // Do not combine anything if "Test Mode" is ON
462
+ }
463
+
464
+ if ($pluginSettings['combine_loaded_js'] === '') {
465
+ return false; // Do not combine
466
+ }
467
+
468
+ if (OptimizeJs::isOptimizeJsEnabledByOtherParty('if_enabled')) {
469
+ return false; // Do not combine (it's already enabled in other plugin)
470
+ }
471
+
472
+ if ( ($pluginSettings['combine_loaded_js'] === 'for_admin'
473
+ || $pluginSettings['combine_loaded_js_for_admin_only'] == 1)
474
+ && Menu::userCanManageAssets() ) {
475
+ return true; // Do combine
476
+ }
477
+
478
+ if ( $pluginSettings['combine_loaded_js_for_admin_only'] === ''
479
+ && in_array($pluginSettings['combine_loaded_js'], array('for_all', 1)) ) {
480
+ return true; // Do combine
481
+ }
482
+
483
+ // Finally, return false as none of the checks above matched
484
+ return false;
485
+ }
486
+ }
classes/OptimiseAssets/{GoogleFonts.php → FontsGoogle.php} RENAMED
@@ -4,10 +4,10 @@ namespace WpAssetCleanUp\OptimiseAssets;
4
  use WpAssetCleanUp\Main;
5
 
6
  /**
7
- * Class GoogleFonts
8
  * @package WpAssetCleanUp\OptimiseAssets
9
  */
10
- class GoogleFonts
11
  {
12
  /**
13
  * @var string
@@ -24,6 +24,10 @@ class GoogleFonts
24
  */
25
  public function init()
26
  {
 
 
 
 
27
  add_action('init', function() {
28
  // don't apply any changes if not in the front-end view (e.g. Dashboard view)
29
  // or test mode is enabled and a guest user is accessing the page
@@ -34,79 +38,151 @@ class GoogleFonts
34
  add_filter('style_loader_src', array($this, 'alterGoogleFontLink'));
35
  }, 20);
36
 
37
- add_action('wp_loaded', function() {
38
- // don't apply any changes if not in the front-end view (e.g. Dashboard view)
39
- // or test mode is enabled and a guest user is accessing the page
40
- if (is_admin() || Main::instance()->preventAssetsSettings()) {
41
- return;
42
- }
43
 
44
- ob_start(function($htmlSource) {
45
- // Cleaner HTML Source
46
- $altHtmlSource = preg_replace('#<noscript>(.*?)</noscript>#si', '', $htmlSource);
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- // Do not continue if there is no single reference to the string we look for in the clean HTML source
49
- if (stripos($altHtmlSource, self::$containsStr) === false) {
50
- return $htmlSource;
 
 
 
 
 
 
 
 
 
 
 
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- // Get all valid LINKs that have the $string within them
54
- $strContainsFormat = preg_quote(self::$containsStr, '/');
55
- $regExpPattern = '#<link[^>]*' . $strContainsFormat . '.*(>)#Usmi';
 
 
 
56
 
57
- preg_match_all($regExpPattern, $altHtmlSource, $matchesFromLinkTags, PREG_SET_ORDER);
 
 
 
58
 
59
- // Needs to match at least one to carry on with the replacements
60
- if (isset($matchesFromLinkTags[0]) && ! empty($matchesFromLinkTags[0])) {
61
- $finalCombinableLinks = $preloadedLinks = array();
62
 
63
- foreach ($matchesFromLinkTags as $linkIndex => $linkTagArray) {
64
- $linkTag = $finalLinkTag = trim(trim($linkTagArray[0], '"\''));
65
- preg_match_all('#href=("|\')' . '(.*)' . '("|\')#Usmi', $linkTag, $outputMatches);
66
- $linkHrefOriginal = $finalLinkHref = trim($outputMatches[2][0], '"\'');
67
 
68
- // If anything is set apart from '[none set]', proceed
69
- if (Main::instance()->settings['google_fonts_display']) {
70
- $newLinkHref = $finalLinkHref = self::alterGoogleFontLink($linkHrefOriginal);
71
 
72
- if ($newLinkHref !== $linkHrefOriginal) {
73
- $finalLinkTag = str_replace($linkHrefOriginal, $newLinkHref, $linkTag);
74
 
75
- // Finally, alter the HTML source
76
- $htmlSource = str_replace($linkTag, $finalLinkTag, $htmlSource);
77
- }
78
- }
 
 
79
 
80
- if (preg_match('/rel=("\')preload("\')/i', $finalLinkTag)
81
- || strpos($finalLinkTag, 'data-wpacu-to-be-preloaded-basic')) {
82
- $preloadedLinks[] = $finalLinkHref;
83
- }
 
 
84
 
85
- $finalCombinableLinks[] = array('href' => $finalLinkHref, 'tag' => $finalLinkTag);
 
 
86
  }
 
 
 
 
 
87
 
88
- $preloadedLinks = array_unique($preloadedLinks);
 
89
 
90
- // Remove data for preloaded LINKs
91
- if (! empty($preloadedLinks)) {
92
- foreach ($finalCombinableLinks as $fclIndex => $combinableLinkData) {
93
- if (in_array($combinableLinkData['href'], $preloadedLinks)) {
94
- unset($finalCombinableLinks[$fclIndex]);
95
- }
96
  }
97
  }
98
 
99
- // Only proceed with the combine if there's obviously at least 2 combinable URL requests to Google Fonts
100
- if (count($finalCombinableLinks) > 1 && Main::instance()->settings['google_fonts_combine']) {
101
- $htmlSource = self::combineGoogleFontLinks($finalCombinableLinks, $htmlSource);
102
  }
 
 
103
  }
104
 
105
- $htmlSource = self::alterGoogleFontUrlFromInlineStyleTags($htmlSource);
106
 
107
- return $htmlSource;
108
- });
109
- }, PHP_INT_MAX);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
 
112
  /**
@@ -192,7 +268,7 @@ class GoogleFonts
192
  */
193
  public static function alterGoogleFontUrlFromCssContent($cssContent)
194
  {
195
- if (stripos($cssContent, 'fonts.googleapis.com') === false) {
196
  return $cssContent;
197
  }
198
 
4
  use WpAssetCleanUp\Main;
5
 
6
  /**
7
+ * Class FontsGoogle
8
  * @package WpAssetCleanUp\OptimiseAssets
9
  */
10
+ class FontsGoogle
11
  {
12
  /**
13
  * @var string
24
  */
25
  public function init()
26
  {
27
+ add_filter('wp_resource_hints', array($this, 'resourceHints'), 10, 2);
28
+
29
+ add_action('wp_head', array($this, 'preloadFontFiles'), 1);
30
+
31
  add_action('init', function() {
32
  // don't apply any changes if not in the front-end view (e.g. Dashboard view)
33
  // or test mode is enabled and a guest user is accessing the page
38
  add_filter('style_loader_src', array($this, 'alterGoogleFontLink'));
39
  }, 20);
40
 
41
+ add_action('wp_loaded', array($this, 'alterHtmlSource'), PHP_INT_MAX);
42
+ }
 
 
 
 
43
 
44
+ /**
45
+ * @param $urls
46
+ * @param $relationType
47
+ *
48
+ * @return array
49
+ */
50
+ public function resourceHints($urls, $relationType)
51
+ {
52
+ if ('preconnect' === $relationType && Main::instance()->settings['google_fonts_preconnect']) {
53
+ $urls[] = array(
54
+ 'href' => 'https://fonts.gstatic.com/',
55
+ 'crossorigin'
56
+ );
57
+ }
58
 
59
+ return $urls;
60
+ }
61
+
62
+ /**
63
+ *
64
+ */
65
+ public function preloadFontFiles()
66
+ {
67
+ if ($preloadFontFiles = Main::instance()->settings['google_fonts_preload_files']) {
68
+ $preloadFontFilesArray = array();
69
+
70
+ if (strpos($preloadFontFiles, "\n") !== false) {
71
+ foreach (explode("\n", $preloadFontFiles) as $preloadFontFile) {
72
+ $preloadFontFilesArray[] = trim($preloadFontFile);
73
  }
74
+ } else {
75
+ $preloadFontFilesArray[] = trim($preloadFontFiles);
76
+ }
77
+
78
+ $preloadFontFilesOutput = '';
79
+
80
+ // Finally, go through the list
81
+ foreach ($preloadFontFilesArray as $preloadFontFile) {
82
+ $preloadFontFilesOutput .= '<link rel="preload" as="font" href="'.esc_attr($preloadFontFile).'" data-wpacu-preload-font="1" crossorigin>'."\n";
83
+ }
84
+
85
+ echo apply_filters('wpacu_preload_google_font_files_output', $preloadFontFilesOutput);
86
+ }
87
+ }
88
+
89
+ /**
90
+ *
91
+ */
92
+ public function alterHtmlSource()
93
+ {
94
+ // don't apply any changes if not in the front-end view (e.g. Dashboard view)
95
+ // or test mode is enabled and a guest user is accessing the page
96
+ if (is_admin() || Main::instance()->preventAssetsSettings()) {
97
+ return;
98
+ }
99
 
100
+ ob_start(static function($htmlSource) {
101
+ // Cleaner HTML Source
102
+ $altHtmlSource = preg_replace('#<noscript(.*?)</noscript>#si', '', $htmlSource);
103
+ $altHtmlSource = preg_replace('#<!--(.*?)-->#s', '', $altHtmlSource);
104
+ $altHtmlSource = preg_replace('#<style(.*?)</style>#si', '', $altHtmlSource);
105
+ $altHtmlSource = preg_replace('#<script(.*?)</script>#si', '', $altHtmlSource);
106
 
107
+ // Do not continue if there is no single reference to the string we look for in the clean HTML source
108
+ if (stripos($altHtmlSource, self::$containsStr) === false) {
109
+ return $htmlSource;
110
+ }
111
 
112
+ // Get all valid LINKs that have the $string within them
113
+ $strContainsFormat = preg_quote(self::$containsStr, '/');
114
+ $regExpPattern = '#<link[^>]*' . $strContainsFormat . '.*(>)#Usmi';
115
 
116
+ preg_match_all($regExpPattern, $altHtmlSource, $matchesFromLinkTags, PREG_SET_ORDER);
 
 
 
117
 
118
+ // Needs to match at least one to carry on with the replacements
119
+ if (isset($matchesFromLinkTags[0]) && ! empty($matchesFromLinkTags[0])) {
120
+ $finalCombinableLinks = $preloadedLinks = array();
121
 
122
+ foreach ($matchesFromLinkTags as $linkIndex => $linkTagArray) {
123
+ $linkTag = $finalLinkTag = trim(trim($linkTagArray[0], '"\''));
124
 
125
+ // Extra checks to make sure it's a valid LINK tag
126
+ if ( (strpos($linkTag, "'") !== false && (substr_count($linkTag, "'") % 2))
127
+ || (strpos($linkTag, '"') !== false && (substr_count($linkTag, '"') % 2))
128
+ || (trim(strip_tags($linkTag)) !== '')) {
129
+ continue;
130
+ }
131
 
132
+ preg_match_all('#href=(["\'])' . '(.*)' . '(["\'])#Usmi', $linkTag, $outputMatches);
133
+ $linkHrefOriginal = $finalLinkHref = trim($outputMatches[2][0], '"\'');
134
+
135
+ // [START] Remove invalid requests with no font family
136
+ $urlParse = parse_url(str_replace('&amp;', '&', $linkHrefOriginal), PHP_URL_QUERY);
137
+ parse_str($urlParse, $qStr);
138
 
139
+ if (isset($qStr['family']) && ! $qStr['family']) {
140
+ $htmlSource = str_replace($linkTag, '', $htmlSource);
141
+ continue;
142
  }
143
+ // [END] Remove invalid requests with no font family
144
+
145
+ // If anything is set apart from '[none set]', proceed
146
+ if (Main::instance()->settings['google_fonts_display']) {
147
+ $newLinkHref = $finalLinkHref = self::alterGoogleFontLink($linkHrefOriginal);
148
 
149
+ if ($newLinkHref !== $linkHrefOriginal) {
150
+ $finalLinkTag = str_replace($linkHrefOriginal, $newLinkHref, $linkTag);
151
 
152
+ // Finally, alter the HTML source
153
+ $htmlSource = str_replace($linkTag, $finalLinkTag, $htmlSource);
 
 
 
 
154
  }
155
  }
156
 
157
+ if (preg_match('/rel=(["\'])preload(["\'])/i', $finalLinkTag)
158
+ || strpos($finalLinkTag, 'data-wpacu-to-be-preloaded-basic')) {
159
+ $preloadedLinks[] = $finalLinkHref;
160
  }
161
+
162
+ $finalCombinableLinks[] = array('href' => $finalLinkHref, 'tag' => $finalLinkTag);
163
  }
164
 
165
+ $preloadedLinks = array_unique($preloadedLinks);
166
 
167
+ // Remove data for preloaded LINKs
168
+ if (! empty($preloadedLinks)) {
169
+ foreach ($finalCombinableLinks as $fclIndex => $combinableLinkData) {
170
+ if (in_array($combinableLinkData['href'], $preloadedLinks)) {
171
+ unset($finalCombinableLinks[$fclIndex]);
172
+ }
173
+ }
174
+ }
175
+
176
+ // Only proceed with the combine if there's obviously at least 2 combinable URL requests to Google Fonts
177
+ if (count($finalCombinableLinks) > 1 && Main::instance()->settings['google_fonts_combine']) {
178
+ $htmlSource = self::combineGoogleFontLinks($finalCombinableLinks, $htmlSource);
179
+ }
180
+ }
181
+
182
+ $htmlSource = self::alterGoogleFontUrlFromInlineStyleTags($htmlSource);
183
+
184
+ return $htmlSource;
185
+ });
186
  }
187
 
188
  /**
268
  */
269
  public static function alterGoogleFontUrlFromCssContent($cssContent)
270
  {
271
+ if (stripos($cssContent, 'fonts.googleapis.com') === false || ! Main::instance()->settings['google_fonts_display']) {
272
  return $cssContent;
273
  }
274
 
classes/OptimiseAssets/FontsLocal.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WpAssetCleanUp\OptimiseAssets;
3
+
4
+ use WpAssetCleanUp\Main;
5
+
6
+ /**
7
+ * Class LocalFonts
8
+ * @package WpAssetCleanUp\OptimiseAssets
9
+ */
10
+ class FontsLocal
11
+ {
12
+ /**
13
+ *
14
+ */
15
+ public function init()
16
+ {
17
+ add_action('wp_head', array($this, 'preloadFontFiles'), 1);
18
+ }
19
+
20
+ /**
21
+ *
22
+ */
23
+ public function preloadFontFiles()
24
+ {
25
+ if ($preloadFontFiles = Main::instance()->settings['local_fonts_preload_files']) {
26
+ $preloadFontFilesArray = array();
27
+
28
+ if (strpos($preloadFontFiles, "\n") !== false) {
29
+ foreach (explode("\n", $preloadFontFiles) as $preloadFontFile) {
30
+ $preloadFontFilesArray[] = trim($preloadFontFile);
31
+ }
32
+ } else {
33
+ $preloadFontFilesArray[] = trim($preloadFontFiles);
34
+ }
35
+
36
+ $preloadFontFilesOutput = '';
37
+
38
+ // Finally, go through the list
39
+ foreach ($preloadFontFilesArray as $preloadFontFile) {
40
+ $preloadFontFilesOutput .= '<link rel="preload" as="font" href="'.esc_attr($preloadFontFile).'" data-wpacu-preload-font="1" crossorigin>'."\n";
41
+ }
42
+
43
+ echo apply_filters('wpacu_preload_local_font_files_output', $preloadFontFilesOutput);
44
+ }
45
+ }
46
+ }
classes/OptimiseAssets/MinifyCss.php CHANGED
@@ -1,10 +1,8 @@
1
  <?php
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
4
- use WpAssetCleanUp\FileSystem;
5
  use WpAssetCleanUp\Main;
6
  use WpAssetCleanUp\Menu;
7
- use WpAssetCleanUp\Misc;
8
  use WpAssetCleanUp\MetaBoxes;
9
 
10
  /**
@@ -13,317 +11,6 @@ use WpAssetCleanUp\MetaBoxes;
13
  */
14
  class MinifyCss
15
  {
16
- /**
17
- *
18
- */
19
- public function init()
20
- {
21
- add_action('wp_footer', function() {
22
- // Do not continue if "Minify CSS" is not enabled (in "Settings" or on the fly)
23
- if (! self::isMinifyCssEnabled()) {
24
- return;
25
- }
26
-
27
- global $wp_styles;
28
-
29
- $allStylesHandles = wp_cache_get('wpacu_all_styles_handles');
30
-
31
- if (empty($allStylesHandles)) {
32
- return;
33
- }
34
-
35
- $cssMinifyList = array();
36
-
37
- // [Start] Collect for caching
38
- $wpStylesDone = $wp_styles->done;
39
- $wpStylesRegistered = $wp_styles->registered;
40
-
41
- foreach ($wpStylesDone as $handle) {
42
- if (isset($wpStylesRegistered[$handle])) {
43
- $value = $wpStylesRegistered[$handle];
44
-
45
- $minifyValues = $this->maybeMinifyIt($value);
46
-
47
- if (! empty($minifyValues)) {
48
- $cssMinifyList[] = $minifyValues;
49
- }
50
- }
51
- }
52
-
53
- if (empty($cssMinifyList)) {
54
- return;
55
- }
56
-
57
- wp_cache_add('wpacu_css_minify_list', $cssMinifyList);
58
- // [End] Collect for caching
59
- }, PHP_INT_MAX);
60
- }
61
-
62
- /**
63
- * Next: Alter the HTML source by updating the original link URLs with the just cached ones
64
- *
65
- * @param $htmlSource
66
- *
67
- * @return mixed
68
- */
69
- public static function updateHtmlSourceOriginalToMinCss($htmlSource)
70
- {
71
- $cssMinifyList = wp_cache_get('wpacu_css_minify_list');
72
-
73
- // This will be taken from the transient
74
- if (empty($cssMinifyList)) {
75
- return $htmlSource;
76
- }
77
-
78
- $regExpPattern = '#<link[^>]*(stylesheet|preload)[^>]*(>)#Usmi';
79
-
80
- preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
81
-
82
- if (empty($matchesSourcesFromTags)) {
83
- return $htmlSource;
84
- }
85
-
86
- foreach ($matchesSourcesFromTags as $matches) {
87
- $linkSourceTag = $matches[0];
88
-
89
- if (strip_tags($linkSourceTag) !== '') {
90
- // Hmm? Not a valid tag... Skip it...
91
- continue;
92
- }
93
-
94
- foreach ($cssMinifyList as $listValues) {
95
- // If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
96
- // do not replace the CSS file path to avoid breaking the website
97
- if (! file_exists(rtrim(ABSPATH, '/') . $listValues[1])) {
98
- continue;
99
- }
100
-
101
- $sourceUrl = site_url() . $listValues[0];
102
- $minUrl = site_url() . $listValues[1];
103
-
104
- if ($linkSourceTag !== str_ireplace($sourceUrl, $minUrl, $linkSourceTag)) {
105
- $newLinkSourceTag = self::updateOriginalToMinifiedTag($linkSourceTag, $sourceUrl, $minUrl);
106
- $htmlSource = str_replace($linkSourceTag, $newLinkSourceTag, $htmlSource);
107
- break;
108
- }
109
- }
110
-
111
- }
112
-
113
- return $htmlSource;
114
- }
115
-
116
- /**
117
- * @param $linkSourceTag
118
- * @param $sourceUrl
119
- * @param $minUrl
120
- *
121
- * @return mixed
122
- */
123
- public static function updateOriginalToMinifiedTag($linkSourceTag, $sourceUrl, $minUrl)
124
- {
125
- $newLinkSourceTag = str_replace($sourceUrl, $minUrl, $linkSourceTag);
126
-
127
- // Strip ?ver=
128
- $newLinkSourceTag = str_replace('&#038;ver=', '?ver=', $newLinkSourceTag);
129
- $toStrip = Misc::extractBetween($newLinkSourceTag, '?ver=', ' ');
130
-
131
- if (in_array(substr($toStrip, -1), array('"', "'"))) {
132
- $toStrip = '?ver='. trim(trim($toStrip, '"'), "'");
133
- $newLinkSourceTag = str_replace($toStrip, '', $newLinkSourceTag);
134
- }
135
-
136
- return $newLinkSourceTag;
137
- }
138
-
139
- /**
140
- * @param $value
141
- *
142
- * @return array
143
- */
144
- public function maybeMinifyIt($value)
145
- {
146
- global $wp_version;
147
-
148
- $src = isset($value->src) ? $value->src : false;
149
-
150
- if (! $src || $this->skipMinify($src, $value->handle)) {
151
- return array();
152
- }
153
-
154
- $handleDbStr = md5($value->handle);
155
-
156
- $transientName = 'wpacu_css_minify_'.$handleDbStr;
157
-
158
- $savedValues = get_transient( $transientName );
159
-
160
- if ( $savedValues ) {
161
- $savedValuesArray = json_decode( $savedValues, ARRAY_A );
162
-
163
- if ( $savedValuesArray['ver'] !== $value->ver ) {
164
- // New File Version? Delete transient as it will be re-added to the database with the new version
165
- delete_transient( $transientName );
166
- } else {
167
- $localPathToCssMin = str_replace( '//', '/', ABSPATH . $savedValuesArray['min_uri'] );
168
-
169
- if ( isset( $savedValuesArray['source_uri'] ) && file_exists( $localPathToCssMin ) ) {
170
- return array(
171
- $savedValuesArray['source_uri'],
172
- $savedValuesArray['min_uri'],
173
- );
174
- }
175
- }
176
- }
177
-
178
- if (strpos($src, '/wp-includes/') === 0) {
179
- $src = site_url() . $src;
180
- }
181
-
182
- if ($value->handle === 'sccss_style' && in_array('simple-custom-css/simple-custom-css.php', apply_filters('active_plugins', get_option('active_plugins')))) {
183
- /*
184
- * Special Case: "Simple Custom CSS" Plugin
185
- *
186
- * /?sccss=1
187
- *
188
- * As it is (no minification or optimization), it adds extra load time to the page
189
- * as the CSS is read via PHP and all the WP environment is loading
190
- */
191
- $pathToAssetDir = '';
192
- $sourceBeforeMin = $value->src;
193
-
194
- $cssContent = Misc::getSimpleCustomCss();
195
-
196
- $newLocalSrc = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . 'sccss_style.css';
197
-
198
- // Append CSS content to make it cacheable (exception)
199
- $cssContent = '/*! Simple Custom CSS */' ."\n". $cssContent;
200
-
201
- if (! FileSystem::file_put_contents($newLocalSrc, $cssContent)) {
202
- return array();
203
- }
204
- // strpos($src, '.css?ver=') === false
205
- } elseif (strpos($src, '/?custom-css=') !== false) {
206
- /*
207
- * JetPack Custom CSS
208
- * /?custom-css
209
- */
210
- global $wp_version;
211
-
212
- $pathToAssetDir = '';
213
- $sourceBeforeMin = $value->src;
214
-
215
- if (! OptimizeCommon::isSourceFromSameHost($sourceBeforeMin)) {
216
- return array();
217
- }
218
-
219
- $response = wp_remote_get($sourceBeforeMin);
220
- $responseCode = wp_remote_retrieve_response_code($response);
221
-
222
- if ($responseCode !== 200) {
223
- return array();
224
- }
225
-
226
- $cssContent = wp_remote_retrieve_body($response);
227
-
228
- $listSrcAfterSlash = str_replace('/?', '', strrchr($src, '/?'));
229
-
230
- parse_str($listSrcAfterSlash, $outputSrcParse);
231
-
232
- $customCssVersion = isset($outputSrcParse['custom-css']) ? $outputSrcParse['custom-css'] : $wp_version;
233
- $extraVersion = isset($value->ver) ? '_'.$value->ver : '';
234
-
235
- $newLocalSrc = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . 'custom_css_' . $customCssVersion . $extraVersion . '.css';
236
-
237
- // Append CSS content to make it cacheable (exception)
238
- $cssContent = '/*! JetPack Custom CSS */' ."\n". $cssContent;
239
-
240
- if (! FileSystem::file_put_contents($newLocalSrc, $cssContent)) {
241
- return array();
242
- }
243
- } else {
244
- /*
245
- * All the CSS that exists as a .css file within the plugins/theme
246
- */
247
- $localAssetPath = OptimizeCommon::getLocalAssetPath($src, 'css');
248
-
249
- if (! file_exists($localAssetPath)) {
250
- return array();
251
- }
252
-
253
- $assetHref = $src;
254
-
255
- $posLastSlash = strrpos($assetHref, '/');
256
- $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
257
-
258
- $parseUrl = parse_url($pathToAssetDir);
259
-
260
- if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
261
- $pathToAssetDir = str_replace(
262
- array('http://' . $parseUrl['host'], 'https://' . $parseUrl['host']),
263
- '',
264
- $pathToAssetDir
265
- );
266
- } elseif (strpos($pathToAssetDir, '//') === 0) {
267
- $pathToAssetDir = str_replace(
268
- array('//' . $parseUrl['host'], '//' . $parseUrl['host']),
269
- '',
270
- $pathToAssetDir
271
- );
272
- }
273
-
274
- $cssContent = FileSystem::file_get_contents($localAssetPath);
275
-
276
- $sourceBeforeMin = str_replace(ABSPATH, '/', $localAssetPath);
277
- }
278
-
279
- $cssContent = OptimizeCss::maybeFixCssBackgroundUrls($cssContent, $pathToAssetDir . '/'); // Minify it and save it to /wp-content/cache/css/min/
280
-
281
- // Any "font-display" enabled in "Settings" - "Google Fonts"?
282
- $cssContent = GoogleFonts::alterGoogleFontUrlFromCssContent($cssContent);
283
-
284
- $cssContent = self::applyMinification($cssContent);
285
-
286
- // Relative path to the new file
287
- $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
288
-
289
- $newFilePathUri = OptimizeCss::getRelPathCssCacheDir() . 'min/' . $value->handle . '-v' . $ver;
290
-
291
- $sha1File = @sha1_file($localAssetPath);
292
-
293
- if ($sha1File) {
294
- $newFilePathUri .= '-'.$sha1File;
295
- }
296
-
297
- $newFilePathUri .= '.css';
298
-
299
- $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
300
- $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
301
-
302
- if ($cssContent) {
303
- $cssContent = '/*** Source (before minification): ' . $sourceBeforeMin . ' ***/' . "\n" . $cssContent;
304
- }
305
-
306
- $saveFile = FileSystem::file_put_contents($newLocalPath, $cssContent);
307
-
308
- if (! $saveFile && ! $cssContent) {
309
- return array();
310
- }
311
-
312
- $saveValues = array(
313
- 'source_uri' => OptimizeCommon::getHrefRelPath($src),
314
- 'min_uri' => OptimizeCommon::getHrefRelPath($newLocalPathUrl),
315
- 'ver' => $ver
316
- );
317
-
318
- // Add / Re-add (with new version) transient
319
- set_transient($transientName, json_encode($saveValues));
320
-
321
- return array(
322
- OptimizeCommon::getHrefRelPath($src),
323
- OptimizeCommon::getHrefRelPath($newLocalPathUrl),
324
- );
325
- }
326
-
327
  /**
328
  * @param $cssContent
329
  *
@@ -372,7 +59,7 @@ class MinifyCss
372
  *
373
  * @return bool
374
  */
375
- public function skipMinify($src, $handle = '')
376
  {
377
  // Things like WP Fastest Cache Toolbar CSS shouldn't be minified and take up space on the server
378
  if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['styles'])) {
@@ -456,7 +143,7 @@ class MinifyCss
456
  }
457
  }
458
 
459
- if (Misc::isOptimizeCssEnabledByOtherParty('if_enabled')) {
460
  return false;
461
  }
462
 
1
  <?php
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
 
4
  use WpAssetCleanUp\Main;
5
  use WpAssetCleanUp\Menu;
 
6
  use WpAssetCleanUp\MetaBoxes;
7
 
8
  /**
11
  */
12
  class MinifyCss
13
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
  * @param $cssContent
16
  *
59
  *
60
  * @return bool
61
  */
62
+ public static function skipMinify($src, $handle = '')
63
  {
64
  // Things like WP Fastest Cache Toolbar CSS shouldn't be minified and take up space on the server
65
  if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['styles'])) {
143
  }
144
  }
145
 
146
+ if (OptimizeCss::isOptimizeCssEnabledByOtherParty('if_enabled')) {
147
  return false;
148
  }
149
 
classes/OptimiseAssets/MinifyJs.php CHANGED
@@ -1,10 +1,8 @@
1
  <?php
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
4
- use WpAssetCleanUp\FileSystem;
5
  use WpAssetCleanUp\Main;
6
  use WpAssetCleanUp\Menu;
7
- use WpAssetCleanUp\Misc;
8
  use WpAssetCleanUp\MetaBoxes;
9
 
10
  /**
@@ -13,231 +11,6 @@ use WpAssetCleanUp\MetaBoxes;
13
  */
14
  class MinifyJs
15
  {
16
- /**
17
- * MinifyJs constructor.
18
- */
19
- public function __construct()
20
- {
21
- /*
22
- * #minifying
23
- * STEP 1: Prepare minify-able caching list
24
- */
25
- add_action('wp_print_footer_scripts', function() {
26
- // Do not continue if "Minify JS" is not enabled (in "Settings" or on the fly)
27
- if (! self::isMinifyJsEnabled()) {
28
- return;
29
- }
30
-
31
- global $wp_scripts;
32
-
33
- $jsMinifyList = array();
34
-
35
- $wpScriptsList = array_unique(array_merge($wp_scripts->done, $wp_scripts->queue));
36
-
37
- // [Start] Collect for caching
38
- foreach ($wpScriptsList as $handle) {
39
- if (isset($wp_scripts->registered[$handle])) {
40
- $value = $wp_scripts->registered[$handle];
41
- $minifyValues = $this->maybeMinifyIt( $value );
42
-
43
- if ( ! empty( $minifyValues ) ) {
44
- $jsMinifyList[] = $minifyValues;
45
- }
46
- }
47
- }
48
-
49
- wp_cache_add('wpacu_js_minify_list', $jsMinifyList);
50
- // [End] Collect for caching
51
- }, PHP_INT_MAX);
52
- }
53
-
54
- /**
55
- * @param $htmlSource
56
- *
57
- * @return mixed
58
- */
59
- public static function updateHtmlSourceOriginalToMinJs($htmlSource)
60
- {
61
- $jsMinifyList = wp_cache_get('wpacu_js_minify_list');
62
-
63
- if (empty($jsMinifyList)) {
64
- return $htmlSource;
65
- }
66
-
67
- $regExpPattern = '#<script[^>]*src(|\s+)=(|\s+)[^>]*(>)#Usmi';
68
-
69
- preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
70
-
71
- foreach ($matchesSourcesFromTags as $matches) {
72
- $scriptSourceTag = $matches[0];
73
-
74
- if (strip_tags($scriptSourceTag) !== '') {
75
- // Hmm? Not a valid tag... Skip it...
76
- continue;
77
- }
78
-
79
- foreach ($jsMinifyList as $listValues) {
80
- // If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
81
- // do not replace the JS file path to avoid breaking the website
82
- if (! file_exists(rtrim(ABSPATH, '/') . $listValues[1])) {
83
- continue;
84
- }
85
-
86
- $sourceUrl = site_url() . $listValues[0];
87
- $minUrl = site_url() . $listValues[1];
88
-
89
- if ($scriptSourceTag !== str_ireplace($sourceUrl, $minUrl, $scriptSourceTag)) {
90
- $newLinkSourceTag = self::updateOriginalToMinifiedTag($scriptSourceTag, $sourceUrl, $minUrl);
91
- $htmlSource = str_replace($scriptSourceTag, $newLinkSourceTag, $htmlSource);
92
- break;
93
- }
94
- }
95
- }
96
-
97
- return $htmlSource;
98
- }
99
-
100
- /**
101
- * @param $scriptSourceTag
102
- * @param $sourceUrl
103
- * @param $minUrl
104
- *
105
- * @return mixed
106
- */
107
- public static function updateOriginalToMinifiedTag($scriptSourceTag, $sourceUrl, $minUrl)
108
- {
109
- $newScriptSourceTag = str_replace($sourceUrl, $minUrl, $scriptSourceTag);
110
-
111
- // Strip ?ver=
112
- $toStrip = Misc::extractBetween($newScriptSourceTag, '?ver=', '>');
113
-
114
- if (in_array(substr($toStrip, -1), array('"', "'"))) {
115
- $toStrip = '?ver='. trim(trim($toStrip, '"'), "'");
116
- $newScriptSourceTag = str_replace($toStrip, '', $newScriptSourceTag);
117
- }
118
-
119
- return $newScriptSourceTag;
120
- }
121
-
122
- /**
123
- * @param $value
124
- *
125
- * @return array
126
- */
127
- public function maybeMinifyIt($value)
128
- {
129
- global $wp_version;
130
-
131
- $src = isset($value->src) ? $value->src : false;
132
-
133
- if (! $src || $this->skipMinify($src, $value->handle)) {
134
- return array();
135
- }
136
-
137
- $handleDbStr = md5($value->handle);
138
-
139
- $transientName = 'wpacu_js_minify_'.$handleDbStr;
140
-
141
- $savedValues = get_transient( $transientName );
142
-
143
- if ( $savedValues ) {
144
- $savedValuesArray = json_decode( $savedValues, ARRAY_A );
145
-
146
- if ( $savedValuesArray['ver'] !== $value->ver ) {
147
- // New File Version? Delete transient as it will be re-added to the database with the new version
148
- delete_transient( $transientName );
149
- } else {
150
- $localPathToJsMin = str_replace( '//', '/', ABSPATH . $savedValuesArray['min_uri'] );
151
-
152
- // Do not load any minified JS file (from the database transient cache) if it doesn't exist
153
- // It will fallback to the original JS file
154
- if ( isset( $savedValuesArray['source_uri'] ) && file_exists( $localPathToJsMin ) ) {
155
- return array(
156
- $savedValuesArray['source_uri'],
157
- $savedValuesArray['min_uri'],
158
- );
159
- }
160
- }
161
- }
162
-
163
- if (strpos($src, '/wp-includes/') === 0) {
164
- $src = site_url() . $src;
165
- }
166
-
167
- $localAssetPath = OptimizeCommon::getLocalAssetPath($src, 'js');
168
-
169
- if (! file_exists($localAssetPath)) {
170
- return array();
171
- }
172
-
173
- $assetHref = $value->src;
174
-
175
- $posLastSlash = strrpos($assetHref, '/');
176
- $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
177
-
178
- $parseUrl = parse_url($pathToAssetDir);
179
-
180
- if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
181
- $pathToAssetDir = str_replace(
182
- array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
183
- '',
184
- $pathToAssetDir
185
- );
186
- } elseif (strpos($pathToAssetDir, '//') === 0) {
187
- $pathToAssetDir = str_replace(
188
- array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
189
- '',
190
- $pathToAssetDir
191
- );
192
- }
193
-
194
- $jsContent = FileSystem::file_get_contents($localAssetPath);
195
- $jsContent = OptimizeJs::maybeDoJsFixes($jsContent, $pathToAssetDir . '/'); // Minify it and save it to /wp-content/cache/js/min/
196
-
197
- $jsContent = self::applyMinification($jsContent);
198
-
199
- // Relative path to the new file
200
- $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
201
-
202
- $newFilePathUri = OptimizeJs::getRelPathJsCacheDir() . 'min/' . $value->handle . '-v' . $ver;
203
-
204
- $sha1File = @sha1_file($localAssetPath);
205
-
206
- if ($sha1File) {
207
- $newFilePathUri .= '-'.$sha1File;
208
- }
209
-
210
- $newFilePathUri .= '.js';
211
-
212
- $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
213
- $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
214
-
215
- if ($jsContent) {
216
- $jsContent = '/*** Source (before minification): ' . str_replace(ABSPATH, '/', $localAssetPath) . ' ***/' . "\n" . $jsContent;
217
- }
218
-
219
- $saveFile = @file_put_contents($newLocalPath, $jsContent);
220
-
221
- if (! $saveFile || ! $jsContent) {
222
- // Fallback to the original JS if the minified version can't be created or updated
223
- return array();
224
- }
225
-
226
- $saveValues = array(
227
- 'source_uri' => OptimizeCommon::getHrefRelPath($value->src),
228
- 'min_uri' => OptimizeCommon::getHrefRelPath($newLocalPathUrl),
229
- 'ver' => $ver
230
- );
231
-
232
- // Add / Re-add (with new version) transient
233
- set_transient($transientName, json_encode($saveValues));
234
-
235
- return array(
236
- OptimizeCommon::getHrefRelPath($value->src),
237
- OptimizeCommon::getHrefRelPath($newLocalPathUrl),
238
- );
239
- }
240
-
241
  /**
242
  * @param $jsContent
243
  *
@@ -305,7 +78,7 @@ class MinifyJs
305
  $regex = array(
306
  "`^([\t\s]+)`sm" => '',
307
  "`^\/\*(.*?)\*\/`sm" => '',
308
- "`([\n\A;]+)\/\*(.+?)\*\/`ism" => '$1',
309
  "`([\n\A;\s]+)//(.+?)[\n\r]`ism" => "$1\n",
310
  "`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n",
311
 
@@ -412,7 +185,7 @@ class MinifyJs
412
  *
413
  * @return bool
414
  */
415
- public function skipMinify($src, $handle = '')
416
  {
417
  // Things like WP Fastest Cache Toolbar JS shouldn't be minified and take up space on the server
418
  if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['scripts'])) {
@@ -493,7 +266,7 @@ class MinifyJs
493
  }
494
  }
495
 
496
- if (Misc::isOptimizeJsEnabledByOtherParty('if_enabled')) {
497
  return false;
498
  }
499
 
1
  <?php
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
 
4
  use WpAssetCleanUp\Main;
5
  use WpAssetCleanUp\Menu;
 
6
  use WpAssetCleanUp\MetaBoxes;
7
 
8
  /**
11
  */
12
  class MinifyJs
13
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
  * @param $jsContent
16
  *
78
  $regex = array(
79
  "`^([\t\s]+)`sm" => '',
80
  "`^\/\*(.*?)\*\/`sm" => '',
81
+ "`([\n\A;]+)\/\*(.+?)\*\/`ism" => "$1",
82
  "`([\n\A;\s]+)//(.+?)[\n\r]`ism" => "$1\n",
83
  "`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n",
84
 
185
  *
186
  * @return bool
187
  */
188
+ public static function skipMinify($src, $handle = '')
189
  {
190
  // Things like WP Fastest Cache Toolbar JS shouldn't be minified and take up space on the server
191
  if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['scripts'])) {
266
  }
267
  }
268
 
269
+ if (OptimizeJs::isOptimizeJsEnabledByOtherParty('if_enabled')) {
270
  return false;
271
  }
272
 
classes/OptimiseAssets/OptimizeCommon.php CHANGED
@@ -18,6 +18,11 @@ class OptimizeCommon
18
  */
19
  public static $relPathPluginCacheDirDefault = '/cache/asset-cleanup/'; // keep forward slash at the end
20
 
 
 
 
 
 
21
  /**
22
  *
23
  */
@@ -455,7 +460,7 @@ class OptimizeCommon
455
  }
456
  } elseif (is_dir($item) && (strpos($item, '/css/logged-in/') !== false || strpos($item, '/js/logged-in/') !== false)) {
457
  $userIdDirs[] = $item;
458
- } elseif (strpos($item, $storageDir) !== false && $item != $storageDir) {
459
  $storageEmptyDirs[] = $item;
460
  }
461
  }
@@ -495,7 +500,7 @@ class OptimizeCommon
495
 
496
  $sqlGetCacheTransients = <<<SQL
497
  SELECT option_value FROM `{$wpdb->options}`
498
- WHERE `option_name` LIKE '%transient_wpacu_js_minify%' OR `option_name` LIKE '%transient_wpacu_css_minify%'
499
  SQL;
500
  $cacheTransients = $wpdb->get_col($sqlGetCacheTransients);
501
 
@@ -503,8 +508,8 @@ SQL;
503
  foreach ($cacheTransients as $optionValue) {
504
  $jsonValueArray = @json_decode($optionValue, ARRAY_A);
505
 
506
- if (isset($jsonValueArray['min_uri'])) {
507
- $allAssetsToKeep[] = rtrim(ABSPATH, '/') . $jsonValueArray['min_uri'];
508
  }
509
  }
510
  }
@@ -529,6 +534,12 @@ SQL;
529
  }
530
  }
531
 
 
 
 
 
 
 
532
  /*
533
  * STEP 2: Remove all transients related to the Minify CSS/JS files feature
534
  */
18
  */
19
  public static $relPathPluginCacheDirDefault = '/cache/asset-cleanup/'; // keep forward slash at the end
20
 
21
+ /**
22
+ * @var string
23
+ */
24
+ public static $optimizedSingleFilesDir = 'item';
25
+
26
  /**
27
  *
28
  */
460
  }
461
  } elseif (is_dir($item) && (strpos($item, '/css/logged-in/') !== false || strpos($item, '/js/logged-in/') !== false)) {
462
  $userIdDirs[] = $item;
463
+ } elseif ($item != $storageDir && strpos($item, $storageDir) !== false) {
464
  $storageEmptyDirs[] = $item;
465
  }
466
  }
500
 
501
  $sqlGetCacheTransients = <<<SQL
502
  SELECT option_value FROM `{$wpdb->options}`
503
+ WHERE `option_name` LIKE '%transient_wpacu_css_optimize%' OR `option_name` LIKE '%transient_wpacu_js_optimize%'
504
  SQL;
505
  $cacheTransients = $wpdb->get_col($sqlGetCacheTransients);
506
 
508
  foreach ($cacheTransients as $optionValue) {
509
  $jsonValueArray = @json_decode($optionValue, ARRAY_A);
510
 
511
+ if (isset($jsonValueArray['optimize_uri'])) {
512
+ $allAssetsToKeep[] = rtrim(ABSPATH, '/') . $jsonValueArray['optimize_uri'];
513
  }
514
  }
515
  }
534
  }
535
  }
536
 
537
+ // Remove "min" and "one" directories (created with Lite Version < 1.3.3.7) if they are empty
538
+ @rmdir(WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir().'min');
539
+ @rmdir(WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir().'min');
540
+ @rmdir(WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir().'one');
541
+ @rmdir(WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir().'one');
542
+
543
  /*
544
  * STEP 2: Remove all transients related to the Minify CSS/JS files feature
545
  */
classes/OptimiseAssets/OptimizeCss.php CHANGED
@@ -21,248 +21,331 @@ class OptimizeCss
21
  public static $cachedCssAssetsFileExpiresIn = 28800; // 8 hours in seconds (60 * 60 * 8)
22
 
23
  /**
24
- * @var string
25
  */
26
- public $jsonStorageFile = 'css-combined{maybe-extra-info}.json';
 
 
 
 
27
 
28
  /**
29
  *
30
  */
31
- public function init()
32
  {
33
- add_action('wp_loaded', function() {
34
- if (is_admin()) { // don't apply any changes if not in the front-end view (e.g. Dashboard view)
35
- return;
36
- }
37
 
38
- ob_start(function ($htmlSource) {
39
- // Do not do any optimization if "Test Mode" is Enabled
40
- if (! Menu::userCanManageAssets() && Main::instance()->settings['test_mode']) {
41
- return $htmlSource;
42
- }
43
 
44
- // There has to be at least one "<link", otherwise, it could be a feed request or something similar (not page, post, homepage etc.)
45
- if (stripos($htmlSource, '<link') === false) {
46
- return $htmlSource;
47
- }
48
 
49
- // Are there any assets unloaded where their "children" are ignored?
50
- // Since they weren't dequeued the WP way (to avoid unloading the "children"), they will be stripped here
51
- if (! Main::instance()->preventAssetsSettings()) {
52
- $ignoreChild = Main::instance()->getIgnoreChildren();
53
 
54
- if (isset($ignoreChild['styles']) && ! empty($ignoreChild['styles'])) {
55
- foreach ($ignoreChild['styles'] as $styleSrc) {
56
- $htmlSource = CleanUp::cleanLinkTagFromHtmlSource($styleSrc, $htmlSource);
57
- }
58
- }
59
- }
60
 
61
- if (MinifyCss::isMinifyCssEnabled()) {
62
- // 'wpacu_css_minify_list' caching list is also checked; if it's empty, no minification is made
63
- $htmlSource = MinifyCss::updateHtmlSourceOriginalToMinCss($htmlSource);
64
- }
65
 
66
- if (! Main::instance()->preventAssetsSettings()) {
67
- $htmlSource = Preloads::instance()->doChanges($htmlSource);
68
- }
69
 
70
- if ( array_key_exists('wpacu_no_css_combine', $_GET) || // not on query string request (debugging purposes)
71
- ! $this->doCssCombine() ) {
72
- return $htmlSource;
73
  }
 
 
 
 
 
 
74
 
75
- // If "Do not combine CSS on this page" is checked in "Asset CleanUp: Options" side meta box
76
- // Works for posts, pages and custom post types
77
- if (defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0) {
78
- $pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID );
79
 
80
- if ( isset( $pageOptions['no_css_optimize'] ) && $pageOptions['no_css_optimize'] ) {
81
- return $htmlSource;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
  }
 
84
 
85
- $useDom = function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument');
 
 
86
 
87
- if (! $useDom) {
88
- return $htmlSource;
89
- }
90
 
91
- // Speed up processing by getting the already existing final CSS file URI
92
- // This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
93
- $storageJsonContents = OptimizeCommon::getAssetCachedData($this->jsonStorageFile, self::getRelPathCssCacheDir(), 'css');
 
 
 
 
 
 
 
 
94
 
95
- // $uriToFinalCssFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathCssCacheDir()
96
- // which is usually "wp-content/cache/asset-cleanup/css/"
97
 
98
- if (empty($storageJsonContents)) {
99
- $storageJsonContentsToSave = array();
100
 
101
- /*
102
- * NO CACHING? Parse the DOM
103
- */
104
- // Nothing in the database records or the retrieved cached file does not exist?
105
- OptimizeCommon::clearAssetCachedData( $this->jsonStorageFile );
106
 
107
- // Fetch the DOM, and then set a new transient
108
- $documentForCSS = new \DOMDocument();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
- libxml_use_internal_errors(true);
 
111
 
112
- // Fore some reason, <noscript> is not recognised by DOMDocument as a tag belonging to HEAD
113
- $htmlSourceAlt = str_replace(array('<noscript>', '</noscript>'), array('<!--', '-->'), $htmlSource);
 
114
 
115
- $documentForCSS->loadHTML( $htmlSourceAlt );
116
 
117
- $storageJsonContents = array();
118
 
119
- foreach ( array( 'head', 'body' ) as $docLocationTag ) {
120
- $combinedUriPaths = $localAssetsPaths = $linkHrefs = array();
121
 
122
- $docLocationElements = $documentForCSS->getElementsByTagName( $docLocationTag )->item( 0 );
123
- $linkTags = $docLocationElements->getElementsByTagName( 'link' );
124
 
125
- if ( $linkTags === null ) {
126
- continue;
127
- }
128
 
129
- foreach ( $linkTags as $tagObject ) {
130
- if ( ! $tagObject->hasAttributes() ) {
131
- continue;
132
- }
133
 
134
- $linkAttributes = array();
 
 
 
 
 
 
 
 
 
 
 
135
 
136
- foreach ( $tagObject->attributes as $attrObj ) {
137
- $linkAttributes[ $attrObj->nodeName ] = trim( $attrObj->nodeValue );
138
- }
139
 
140
- // Only rel="stylesheet" (with no rel="preload" associated with it) gets prepared for combining as links with rel="preload" (if any) are never combined into a standard render-blocking CSS file
141
- // rel="preload" is there for a reason to make sure the CSS code is made available earlier prior to the one from rel="stylesheet" which is render-blocking
142
- if (isset($linkAttributes['rel'], $linkAttributes['href']) && $linkAttributes['href']) {
143
- // Make sure that tag value is checked and it's matched against the value from the HTML source code
144
- //$htmlSource .= $attrObj->nodeValue."\n";
145
- $href = (string) $linkAttributes['href'];
146
 
147
- $cssNotCombinable = false;
 
148
 
149
- // 1) Check if there is any rel="preload" connected to the rel="stylesheet"
150
- // making sure the file is not added to the final CSS combined file
151
 
152
- // 2) Only combine media "all", "screen" and the ones with no media
153
- // Do not combine media='only screen and (max-width: 768px)' etc.
154
- if ($linkAttributes['rel'] === 'preload') {
155
- $cssNotCombinable = true;
156
- }
 
 
 
 
 
 
 
 
157
 
158
- if (isset($linkAttributes['data-wpacu-to-be-preloaded-basic']) && $linkAttributes['data-wpacu-to-be-preloaded-basic']) {
159
- $cssNotCombinable = true;
160
- }
161
 
162
- if ( array_key_exists( 'media', $linkAttributes ) && ! in_array( $linkAttributes['media'], array( 'all', 'screen' ) ) ) {
163
- $cssNotCombinable = true;
164
- }
165
 
166
- if ( $this->skipCombine( $linkAttributes['href']) ) {
167
- $cssNotCombinable = true;
168
- }
 
 
169
 
170
- if ( $cssNotCombinable ) {
171
- continue;
172
- }
 
173
 
174
- $localAssetPath = OptimizeCommon::getLocalAssetPath( $href, 'css' );
 
 
 
175
 
176
- // It will skip external stylesheets (from a different domain)
177
- if ( $localAssetPath ) {
178
- $combinedUriPaths[] = OptimizeCommon::getHrefRelPath( $href );
179
- $localAssetsPaths[ $href ] = $localAssetPath;
180
- $linkHrefs[] = $href;
181
- }
182
- }
183
- }
184
 
185
- // No Link Tags? Continue
186
- if ( empty( $linkHrefs ) ) {
187
- continue;
188
- }
189
 
190
- $maybeDoCssCombine = $this->maybeDoCssCombine( sha1( implode( '', $combinedUriPaths ) ), $localAssetsPaths, $linkHrefs, $docLocationTag );
 
191
 
192
- // Local path to combined CSS file
193
- $localFinalCssFile = $maybeDoCssCombine['local_final_css_file'];
194
 
195
- // URI (e.g. /wp-content/cache/asset-cleanup/[file-name-here.css]) to the combined CSS file
196
- $uriToFinalCssFile = $maybeDoCssCombine['uri_final_css_file'];
197
 
198
- // Any link hrefs removed perhaps if the file wasn't combined?
199
- $linkHrefs = $maybeDoCssCombine['link_hrefs'];
 
200
 
201
- if ( file_exists( $localFinalCssFile ) ) {
202
- $storageJsonContents[$docLocationTag] = array(
203
- 'uri_to_final_css_file' => $uriToFinalCssFile,
204
- 'link_hrefs' => array_map( function ( $href ) {
205
- return str_replace( '{site_url}', site_url(), $href );
206
- }, $linkHrefs )
207
- );
208
 
209
- $storageJsonContentsToSave[$docLocationTag] = array(
210
- 'uri_to_final_css_file' => $uriToFinalCssFile,
211
- 'link_hrefs' => array_map( function ( $href ) {
212
- return str_replace( site_url(), '{site_url}', $href );
213
- }, $linkHrefs )
214
- );
215
- }
216
- }
217
 
218
- libxml_clear_errors();
 
 
219
 
220
- OptimizeCommon::setAssetCachedData(
221
- $this->jsonStorageFile,
222
- self::getRelPathCssCacheDir(),
223
- json_encode($storageJsonContentsToSave)
224
- );
225
- }
226
 
227
- if ( ! empty($storageJsonContents) ) {
228
- foreach ($storageJsonContents as $locationTag => $storageJsonContentLocation) {
229
- if (! isset($storageJsonContentLocation['link_hrefs'][0])) {
230
- continue;
231
- }
232
 
233
- $storageJsonContentLocation['link_hrefs'] = array_map( function ( $href ) {
234
- return str_replace( '{site_url}', site_url(), $href );
235
- }, $storageJsonContentLocation['link_hrefs'] );
 
 
236
 
237
- $finalTagUrl = OptimizeCommon::filterWpContentUrl() . self::getRelPathCssCacheDir() . $storageJsonContentLocation['uri_to_final_css_file'];
 
238
 
239
- $finalCssTag = <<<HTML
240
- <link id='wpacu-combined-css-{$locationTag}' rel='stylesheet' href='{$finalTagUrl}' type='text/css' media='all' />
241
- HTML;
 
 
242
 
243
- $htmlSourceBeforeAnyLinkTagReplacement = $htmlSource;
 
 
 
 
 
 
 
244
 
245
- // Detect first LINK tag from the <$locationTag> and replace it with the final combined LINK tag
246
- $firstLinkTag = $this->getFirstLinkTag($storageJsonContentLocation['link_hrefs'][0], $htmlSource);
 
 
 
247
 
248
- if ($firstLinkTag) {
249
- $htmlSource = str_replace( $firstLinkTag, $finalCssTag, $htmlSource );
250
- }
 
251
 
252
- if ($htmlSource !== $htmlSourceBeforeAnyLinkTagReplacement) {
253
- $htmlSource = OptimizeCommon::stripJustCombinedFileTags( $storageJsonContentLocation['link_hrefs'], $htmlSource, 'css' ); // Strip the combined files to avoid duplicate code
 
 
254
 
255
- // There should be at least two replacements made
256
- if ($htmlSource === 'do_not_combine') {
257
- $htmlSource = $htmlSourceBeforeAnyLinkTagReplacement;
258
- }
259
- }
260
  }
261
  }
 
262
 
263
- return $htmlSource;
264
- });
265
- }, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  }
267
 
268
  /**
@@ -279,7 +362,7 @@ HTML;
279
  *
280
  * @return string
281
  */
282
- public function getFirstLinkTag($firstLinkHref, $htmlSource)
283
  {
284
  $regExpPattern = '#<link[^>]*stylesheet[^>]*(>)#Usmi';
285
 
@@ -293,99 +376,6 @@ HTML;
293
  return '';
294
  }
295
 
296
- /**
297
- * @param $shaOneCombinedUriPaths
298
- * @param $localAssetsPaths
299
- * @param $linkHrefs
300
- * @param $docLocationTag
301
- *
302
- * @return array
303
- */
304
- public function maybeDoCssCombine($shaOneCombinedUriPaths, $localAssetsPaths, $linkHrefs, $docLocationTag)
305
- {
306
- $current_user = wp_get_current_user();
307
- $dirToUserCachedFile = ((isset($current_user->ID) && $current_user->ID > 0) ? 'logged-in/'.$current_user->ID.'/' : '');
308
-
309
- $uriToFinalCssFile = $dirToUserCachedFile . $docLocationTag . '-' .$shaOneCombinedUriPaths . '.css';
310
- $localFinalCssFile = WP_CONTENT_DIR . self::getRelPathCssCacheDir() . $uriToFinalCssFile;
311
-
312
- $localDirForCssFile = WP_CONTENT_DIR . self::getRelPathCssCacheDir() . $dirToUserCachedFile;
313
-
314
- // Only combine if $shaOneCombinedUriPaths.css does not exist
315
- // If "?ver" value changes on any of the assets or the asset list changes in any way
316
- // then $shaOneCombinedUriPaths will change too and a new CSS file will be generated and loaded
317
-
318
- $skipIfFileExists = true;
319
-
320
- if ($skipIfFileExists || ! file_exists($localFinalCssFile)) {
321
- // Change $assetsContents as paths to fonts and images that are relative (e.g. ../, ../../) have to be updated
322
- $finalAssetsContents = '';
323
-
324
- foreach ($localAssetsPaths as $assetHref => $localAssetsPath) {
325
- $posLastSlash = strrpos($assetHref, '/');
326
- $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
327
-
328
- $parseUrl = parse_url($pathToAssetDir);
329
-
330
- if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
331
- $pathToAssetDir = str_replace(
332
- array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
333
- '',
334
- $pathToAssetDir
335
- );
336
- } elseif (strpos($pathToAssetDir, '//') === 0) {
337
- $pathToAssetDir = str_replace(
338
- array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
339
- '',
340
- $pathToAssetDir
341
- );
342
- }
343
-
344
- $cssContent = FileSystem::file_get_contents($localAssetsPath);
345
-
346
- if ($cssContent) {
347
- // Do not combine it if it contains "@import"
348
- if (stripos($cssContent, '@import') !== false) {
349
- unset($localAssetsPaths[$assetHref]);
350
- $linkHrefKey = array_search($assetHref, $linkHrefs);
351
- unset($linkHrefs[$linkHrefKey]);
352
- continue;
353
- }
354
-
355
- // Does it have a source map? Strip it
356
- if (strpos($cssContent, 'sourceMappingURL') !== false) {
357
- $cssContent = OptimizeCommon::stripSourceMap($cssContent);
358
- }
359
-
360
- $finalAssetsContents .= '/*** Source: '.str_replace(ABSPATH, '/', $localAssetsPath)." ***/\n";
361
- $finalAssetsContents .= self::maybeFixCssBackgroundUrls($cssContent, $pathToAssetDir . '/') . "\n\n";
362
- }
363
- }
364
-
365
- $finalAssetsContents = trim($finalAssetsContents);
366
-
367
- if ($finalAssetsContents) {
368
- if ($dirToUserCachedFile !== '' && isset($current_user->ID) && $current_user->ID > 0) {
369
- if (! is_dir($localDirForCssFile)) {
370
- $makeLocalDirForCss = @mkdir($localDirForCssFile);
371
-
372
- if (! $makeLocalDirForCss) {
373
- return array('uri_final_css_file' => '', 'local_final_css_file' => '');
374
- }
375
- }
376
- }
377
-
378
- FileSystem::file_put_contents($localFinalCssFile, $finalAssetsContents);
379
- }
380
- }
381
-
382
- return array(
383
- 'uri_final_css_file' => $uriToFinalCssFile,
384
- 'local_final_css_file' => $localFinalCssFile,
385
- 'link_hrefs' => $linkHrefs
386
- );
387
- }
388
-
389
  /**
390
  * @param $cssContent
391
  * @param $appendBefore
@@ -449,94 +439,212 @@ HTML;
449
  }
450
 
451
  /**
452
- * @param $href
453
  *
454
- * @return bool
 
 
455
  */
456
- public function skipCombine($href)
457
  {
458
- $regExps = array();
 
 
 
 
 
 
 
 
 
459
 
460
- if (Main::instance()->settings['combine_loaded_css_exceptions'] !== '') {
461
- $loadedCssExceptionsPatterns = trim(Main::instance()->settings['combine_loaded_css_exceptions']);
 
 
 
 
 
 
 
 
 
462
 
463
- if (strpos($loadedCssExceptionsPatterns, "\n")) {
464
- // Multiple values (one per line)
465
- foreach (explode("\n", $loadedCssExceptionsPatterns) as $loadedCssExceptionPattern) {
466
- $regExps[] = '#'.trim($loadedCssExceptionPattern).'#';
 
 
 
 
 
 
 
 
 
 
467
  }
468
- } else {
469
- // Only one value?
470
- $regExps[] = '#'.trim($loadedCssExceptionsPatterns).'#';
471
  }
472
- }
473
 
474
- // No exceptions set? Do not skip combination
475
- if (empty($regExps)) {
476
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  }
478
 
479
- foreach ($regExps as $regExp) {
480
- if ( preg_match( $regExp, $href ) ) {
481
- // Skip combination
482
- return true;
483
- }
 
 
484
  }
485
 
486
- return false;
487
  }
488
 
489
  /**
490
- * @return bool
 
 
491
  */
492
- public function doCssCombine()
493
  {
494
- // No CSS files are combined in the Dashboard
495
- // Always in the front-end view
496
- // Do not combine if there's a POST request as there could be assets loading conditionally
497
- // that might not be needed when the page is accessed without POST, making the final CSS file larger
498
- if (! empty($_POST) || is_admin()) {
499
- return false; // Do not combine
500
- }
 
 
 
 
 
501
 
502
- // Only clean request URIs allowed
503
- if (strpos($_SERVER['REQUEST_URI'], '?') !== false) {
504
- // Exceptions
505
- if (! OptimizeCommon::loadOptimizedAssetsIfQueryStrings()) {
506
- return false;
 
507
  }
508
- }
509
 
510
- if (! OptimizeCommon::doCombineIsRegularPage()) {
511
- return false;
512
- }
 
 
 
 
 
 
 
513
 
514
- $pluginSettings = Main::instance()->settings;
 
515
 
516
- if ($pluginSettings['test_mode'] && ! Menu::userCanManageAssets()) {
517
- return false; // Do not combine anything if "Test Mode" is ON and the user is in guest mode (not logged-in)
518
- }
519
 
520
- if ($pluginSettings['combine_loaded_css'] === '') {
521
- return false; // Do not combine
522
- }
 
523
 
524
- if (Misc::isOptimizeCssEnabledByOtherParty('if_enabled')) {
525
- return false; // Do not combine (it's already enabled in other plugin)
526
- }
 
 
 
 
 
 
 
 
 
 
 
527
 
528
- if ( ($pluginSettings['combine_loaded_css'] === 'for_admin'
529
- || $pluginSettings['combine_loaded_css_for_admin_only'] == 1)
530
- && Menu::userCanManageAssets()) {
531
- return true; // Do combine
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
532
  }
533
 
534
- if ( $pluginSettings['combine_loaded_css_for_admin_only'] === ''
535
- && in_array($pluginSettings['combine_loaded_css'], array('for_all', 1)) ) {
536
- return true; // Do combine
 
 
 
 
 
 
 
 
 
 
 
537
  }
538
 
539
- // Finally, return false as none of the checks above matched
540
  return false;
541
  }
542
 
21
  public static $cachedCssAssetsFileExpiresIn = 28800; // 8 hours in seconds (60 * 60 * 8)
22
 
23
  /**
24
+ *
25
  */
26
+ public function init()
27
+ {
28
+ add_action('wp_footer', array($this, 'prepareOptimizeList'), PHP_INT_MAX);
29
+ add_action('wp_loaded', array($this, 'alterHtmlSource'), 1);
30
+ }
31
 
32
  /**
33
  *
34
  */
35
+ public function prepareOptimizeList()
36
  {
37
+ global $wp_styles;
 
 
 
38
 
39
+ $allStylesHandles = wp_cache_get('wpacu_all_styles_handles');
 
 
 
 
40
 
41
+ if (empty($allStylesHandles)) {
42
+ return;
43
+ }
 
44
 
45
+ $cssOptimizeList = array();
 
 
 
46
 
47
+ // [Start] Collect for caching
48
+ $wpStylesDone = $wp_styles->done;
49
+ $wpStylesRegistered = $wp_styles->registered;
 
 
 
50
 
51
+ foreach ($wpStylesDone as $handle) {
52
+ if (isset($wpStylesRegistered[$handle])) {
53
+ $value = $wpStylesRegistered[$handle];
 
54
 
55
+ $optimizeValues = $this->maybeOptimizeIt($value);
 
 
56
 
57
+ if (! empty($optimizeValues)) {
58
+ $cssOptimizeList[] = $optimizeValues;
 
59
  }
60
+ }
61
+ }
62
+
63
+ if (empty($cssOptimizeList)) {
64
+ return;
65
+ }
66
 
67
+ wp_cache_add('wpacu_css_optimize_list', $cssOptimizeList);
68
+ // [End] Collect for caching
69
+ }
 
70
 
71
+ /**
72
+ * @param $value
73
+ *
74
+ * @return mixed
75
+ */
76
+ public function maybeOptimizeIt($value)
77
+ {
78
+ global $wp_version;
79
+
80
+ $src = isset($value->src) ? $value->src : false;
81
+
82
+ if (! $src) {
83
+ return array();
84
+ }
85
+
86
+ $doFileMinify = true;
87
+
88
+ if (! MinifyCss::isMinifyCssEnabled()) {
89
+ $doFileMinify = false;
90
+ } elseif(MinifyCss::skipMinify($src, $value->handle)) {
91
+ $doFileMinify = false;
92
+ }
93
+
94
+ $handleDbStr = md5($value->handle);
95
+
96
+ $transientName = 'wpacu_css_optimize_'.$handleDbStr;
97
+
98
+ $savedValues = get_transient( $transientName );
99
+
100
+ if ( $savedValues ) {
101
+ $savedValuesArray = json_decode( $savedValues, ARRAY_A );
102
+
103
+ if ( $savedValuesArray['ver'] !== $value->ver ) {
104
+ // New File Version? Delete transient as it will be re-added to the database with the new version
105
+ delete_transient( $transientName );
106
+ } else {
107
+ $localPathToCssOptimized = str_replace( '//', '/', ABSPATH . $savedValuesArray['optimize_uri'] );
108
+
109
+ if ( isset( $savedValuesArray['source_uri'] ) && file_exists( $localPathToCssOptimized ) ) {
110
+ return array(
111
+ $savedValuesArray['source_uri'],
112
+ $savedValuesArray['optimize_uri'],
113
+ );
114
  }
115
  }
116
+ }
117
 
118
+ if (strpos($src, '/wp-includes/') === 0) {
119
+ $src = site_url() . $src;
120
+ }
121
 
122
+ $isCssFile = false;
 
 
123
 
124
+ if ($value->handle === 'sccss_style' && in_array('simple-custom-css/simple-custom-css.php', apply_filters('active_plugins', get_option('active_plugins')))) {
125
+ /*
126
+ * Special Case: "Simple Custom CSS" Plugin
127
+ *
128
+ * /?sccss=1
129
+ *
130
+ * As it is (no minification or optimization), it adds extra load time to the page
131
+ * as the CSS is read via PHP and all the WP environment is loading
132
+ */
133
+ $pathToAssetDir = '';
134
+ $sourceBeforeOptimization = $value->src;
135
 
136
+ $cssContent = Misc::getSimpleCustomCss();
 
137
 
138
+ $newLocalSrc = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . 'sccss_style.css';
 
139
 
140
+ // Append CSS content to make it cacheable (exception)
141
+ $cssContent = '/*! Simple Custom CSS */' ."\n". $cssContent;
 
 
 
142
 
143
+ if (! FileSystem::file_put_contents($newLocalSrc, $cssContent)) {
144
+ return array();
145
+ }
146
+ // strpos($src, '.css?ver=') === false
147
+ } elseif (strpos($src, '/?custom-css=') !== false) {
148
+ /*
149
+ * JetPack Custom CSS
150
+ * /?custom-css
151
+ */
152
+ global $wp_version;
153
+
154
+ $pathToAssetDir = '';
155
+ $sourceBeforeOptimization = $value->src;
156
+
157
+ if (! OptimizeCommon::isSourceFromSameHost($sourceBeforeOptimization)) {
158
+ return array();
159
+ }
160
 
161
+ $response = wp_remote_get($sourceBeforeOptimization);
162
+ $responseCode = wp_remote_retrieve_response_code($response);
163
 
164
+ if ($responseCode !== 200) {
165
+ return array();
166
+ }
167
 
168
+ $cssContent = wp_remote_retrieve_body($response);
169
 
170
+ $listSrcAfterSlash = str_replace('/?', '', strrchr($src, '/?'));
171
 
172
+ parse_str($listSrcAfterSlash, $outputSrcParse);
 
173
 
174
+ $customCssVersion = isset($outputSrcParse['custom-css']) ? $outputSrcParse['custom-css'] : $wp_version;
175
+ $extraVersion = isset($value->ver) ? '_'.$value->ver : '';
176
 
177
+ $newLocalSrc = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . 'custom_css_' . $customCssVersion . $extraVersion . '.css';
 
 
178
 
179
+ // Append CSS content to make it cacheable (exception)
180
+ $cssContent = '/*! JetPack Custom CSS */' ."\n". $cssContent;
 
 
181
 
182
+ if (! FileSystem::file_put_contents($newLocalSrc, $cssContent)) {
183
+ return array();
184
+ }
185
+ } else {
186
+ /*
187
+ * All the CSS that exists as a .css file within the plugins/theme
188
+ */
189
+ $localAssetPath = OptimizeCommon::getLocalAssetPath($src, 'css');
190
+
191
+ if (! file_exists($localAssetPath)) {
192
+ return array();
193
+ }
194
 
195
+ $isCssFile = true;
 
 
196
 
197
+ $assetHref = $src;
 
 
 
 
 
198
 
199
+ $posLastSlash = strrpos($assetHref, '/');
200
+ $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
201
 
202
+ $parseUrl = parse_url($pathToAssetDir);
 
203
 
204
+ if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
205
+ $pathToAssetDir = str_replace(
206
+ array('http://' . $parseUrl['host'], 'https://' . $parseUrl['host']),
207
+ '',
208
+ $pathToAssetDir
209
+ );
210
+ } elseif (strpos($pathToAssetDir, '//') === 0) {
211
+ $pathToAssetDir = str_replace(
212
+ array('//' . $parseUrl['host'], '//' . $parseUrl['host']),
213
+ '',
214
+ $pathToAssetDir
215
+ );
216
+ }
217
 
218
+ $cssContent = FileSystem::file_get_contents($localAssetPath);
 
 
219
 
220
+ $sourceBeforeOptimization = str_replace(ABSPATH, '/', $localAssetPath);
221
+ }
 
222
 
223
+ /*
224
+ * [START] CSS Content Optimization
225
+ */
226
+ // If there are no changes from this point, do not optimize (keep the file where it is)
227
+ $cssContentBefore = $cssContent;
228
 
229
+ if (Main::instance()->settings['google_fonts_display']) {
230
+ // Any "font-display" enabled in "Settings" - "Google Fonts"?
231
+ $cssContent = FontsGoogle::alterGoogleFontUrlFromCssContent($cssContent);
232
+ }
233
 
234
+ if ($doFileMinify) {
235
+ // Minify this file?
236
+ $cssContent = MinifyCss::applyMinification($cssContent);
237
+ }
238
 
239
+ if ($isCssFile && $cssContentBefore === $cssContent) {
240
+ // No changes were made, thus, there's no point in changing the original file location
241
+ return array();
242
+ }
 
 
 
 
243
 
244
+ $cssContent = OptimizeCss::maybeFixCssBackgroundUrls($cssContent, $pathToAssetDir . '/');
245
+ /*
246
+ * [END] CSS Content Optimization
247
+ */
248
 
249
+ // Relative path to the new file
250
+ $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
251
 
252
+ // Save it to /wp-content/cache/css/{OptimizeCommon::$optimizedSingleFilesDir}/
253
+ $newFilePathUri = OptimizeCss::getRelPathCssCacheDir() . OptimizeCommon::$optimizedSingleFilesDir . '/' . $value->handle . '-v' . $ver;
254
 
255
+ $sha1File = @sha1_file($localAssetPath);
 
256
 
257
+ if ($sha1File) {
258
+ $newFilePathUri .= '-'.$sha1File;
259
+ }
260
 
261
+ $newFilePathUri .= '.css';
 
 
 
 
 
 
262
 
263
+ $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
264
+ $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
 
 
 
 
 
 
265
 
266
+ if ($cssContent) {
267
+ $cssContent = '/*** Source (before optimization): ' . $sourceBeforeOptimization . ' ***/' . "\n" . $cssContent;
268
+ }
269
 
270
+ $saveFile = FileSystem::file_put_contents($newLocalPath, $cssContent);
 
 
 
 
 
271
 
272
+ if (! $saveFile && ! $cssContent) {
273
+ return array();
274
+ }
 
 
275
 
276
+ $saveValues = array(
277
+ 'source_uri' => OptimizeCommon::getHrefRelPath($src),
278
+ 'optimize_uri' => OptimizeCommon::getHrefRelPath($newLocalPathUrl),
279
+ 'ver' => $ver
280
+ );
281
 
282
+ // Add / Re-add (with new version) transient
283
+ set_transient($transientName, json_encode($saveValues));
284
 
285
+ return array(
286
+ OptimizeCommon::getHrefRelPath($src),
287
+ OptimizeCommon::getHrefRelPath($newLocalPathUrl),
288
+ );
289
+ }
290
 
291
+ /**
292
+ *
293
+ */
294
+ public function alterHtmlSource()
295
+ {
296
+ if (is_admin()) { // don't apply any changes if not in the front-end view (e.g. Dashboard view)
297
+ return;
298
+ }
299
 
300
+ ob_start(static function ($htmlSource) {
301
+ // Do not do any optimization if "Test Mode" is Enabled
302
+ if (! Menu::userCanManageAssets() && Main::instance()->settings['test_mode']) {
303
+ return $htmlSource;
304
+ }
305
 
306
+ // There has to be at least one "<link", otherwise, it could be a feed request or something similar (not page, post, homepage etc.)
307
+ if (stripos($htmlSource, '<link') === false) {
308
+ return $htmlSource;
309
+ }
310
 
311
+ // Are there any assets unloaded where their "children" are ignored?
312
+ // Since they weren't dequeued the WP way (to avoid unloading the "children"), they will be stripped here
313
+ if (! Main::instance()->preventAssetsSettings()) {
314
+ $ignoreChild = Main::instance()->getIgnoreChildren();
315
 
316
+ if (isset($ignoreChild['styles']) && ! empty($ignoreChild['styles'])) {
317
+ foreach ($ignoreChild['styles'] as $styleSrc) {
318
+ $htmlSource = CleanUp::cleanLinkTagFromHtmlSource($styleSrc, $htmlSource);
 
 
319
  }
320
  }
321
+ }
322
 
323
+ // 'wpacu_css_optimize_list' caching list is also checked; if it's empty, no minification is made
324
+ $htmlSource = self::updateHtmlSourceOriginalToOptimizedCss($htmlSource);
325
+
326
+ if (! Main::instance()->preventAssetsSettings()) {
327
+ $htmlSource = Preloads::instance()->doChanges($htmlSource);
328
+ }
329
+
330
+ $proceedWithCombineOnThisPage = true;
331
+
332
+ // If "Do not combine CSS on this page" is checked in "Asset CleanUp: Options" side meta box
333
+ // Works for posts, pages and custom post types
334
+ if (defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0) {
335
+ $pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID );
336
+
337
+ // 'no_css_optimize' refers to avoid the combination of CSS files
338
+ if ( isset( $pageOptions['no_css_optimize'] ) && $pageOptions['no_css_optimize'] ) {
339
+ $proceedWithCombineOnThisPage = false;
340
+ }
341
+ }
342
+
343
+ if ($proceedWithCombineOnThisPage) {
344
+ $htmlSource = CombineCss::doCombine($htmlSource);
345
+ }
346
+
347
+ return $htmlSource;
348
+ });
349
  }
350
 
351
  /**
362
  *
363
  * @return string
364
  */
365
+ public static function getFirstLinkTag($firstLinkHref, $htmlSource)
366
  {
367
  $regExpPattern = '#<link[^>]*stylesheet[^>]*(>)#Usmi';
368
 
376
  return '';
377
  }
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  /**
380
  * @param $cssContent
381
  * @param $appendBefore
439
  }
440
 
441
  /**
442
+ * Next: Alter the HTML source by updating the original link URLs with the just cached ones
443
  *
444
+ * @param $htmlSource
445
+ *
446
+ * @return mixed
447
  */
448
+ public static function updateHtmlSourceOriginalToOptimizedCss($htmlSource)
449
  {
450
+ $cssOptimizeList = wp_cache_get('wpacu_css_optimize_list');
451
+
452
+ // This will be taken from the transient
453
+ if (empty($cssOptimizeList)) {
454
+ return $htmlSource;
455
+ }
456
+
457
+ $regExpPattern = '#<link[^>]*(stylesheet|preload)[^>]*(>)#Usmi';
458
+
459
+ preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
460
 
461
+ if (empty($matchesSourcesFromTags)) {
462
+ return $htmlSource;
463
+ }
464
+
465
+ foreach ($matchesSourcesFromTags as $matches) {
466
+ $linkSourceTag = $matches[0];
467
+
468
+ if (strip_tags($linkSourceTag) !== '') {
469
+ // Hmm? Not a valid tag... Skip it...
470
+ continue;
471
+ }
472
 
473
+ foreach ($cssOptimizeList as $listValues) {
474
+ // If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
475
+ // do not replace the CSS file path to avoid breaking the website
476
+ if (! file_exists(rtrim(ABSPATH, '/') . $listValues[1])) {
477
+ continue;
478
+ }
479
+
480
+ $sourceUrl = site_url() . $listValues[0];
481
+ $optimizeUrl = site_url() . $listValues[1];
482
+
483
+ if ($linkSourceTag !== str_ireplace($sourceUrl, $optimizeUrl, $linkSourceTag)) {
484
+ $newLinkSourceTag = self::updateOriginalToOptimizedTag($linkSourceTag, $sourceUrl, $optimizeUrl);
485
+ $htmlSource = str_replace($linkSourceTag, $newLinkSourceTag, $htmlSource);
486
+ break;
487
  }
 
 
 
488
  }
 
489
 
490
+ }
491
+
492
+ return $htmlSource;
493
+ }
494
+
495
+ /**
496
+ * @param $linkSourceTag
497
+ * @param $sourceUrl
498
+ * @param $optimizeUrl
499
+ *
500
+ * @return mixed
501
+ */
502
+ public static function updateOriginalToOptimizedTag($linkSourceTag, $sourceUrl, $optimizeUrl)
503
+ {
504
+ $newLinkSourceTag = str_replace($sourceUrl, $optimizeUrl, $linkSourceTag);
505
+
506
+ // Needed in case it's added to the Combine CSS exceptions list
507
+ if (CombineCss::proceedWithCssCombine()) {
508
+ $newLinkSourceTag = str_ireplace('<link ', '<link data-wpacu-link-href-before="' . $sourceUrl . '" ', $newLinkSourceTag);
509
  }
510
 
511
+ // Strip ?ver=
512
+ $newLinkSourceTag = str_replace('.css&#038;ver=', '.css?ver=', $newLinkSourceTag);
513
+ $toStrip = Misc::extractBetween($newLinkSourceTag, '?ver=', ' ');
514
+
515
+ if (in_array(substr($toStrip, -1), array('"', "'"))) {
516
+ $toStrip = '?ver='. trim(trim($toStrip, '"'), "'");
517
+ $newLinkSourceTag = str_replace($toStrip, '', $newLinkSourceTag);
518
  }
519
 
520
+ return $newLinkSourceTag;
521
  }
522
 
523
  /**
524
+ * @param string $returnType
525
+ *
526
+ * @return array|bool
527
  */
528
+ public static function isOptimizeCssEnabledByOtherParty($returnType = 'list')
529
  {
530
+ $pluginsToCheck = array(
531
+ 'autoptimize/autoptimize.php' => 'Autoptimize',
532
+ 'wp-rocket/wp-rocket.php' => 'WP Rocket',
533
+ 'wp-fastest-cache/wpFastestCache.php' => 'WP Fastest Cache',
534
+ 'w3-total-cache/w3-total-cache.php' => 'W3 Total Cache',
535
+ 'sg-cachepress/sg-cachepress.php' => 'SG Optimizer',
536
+ 'fast-velocity-minify/fvm.php' => 'Fast Velocity Minify',
537
+ 'litespeed-cache/litespeed-cache.php' => 'LiteSpeed Cache',
538
+ 'swift-performance-lite/performance.php' => 'Swift Performance Lite'
539
+ );
540
+
541
+ $cssOptimizeEnabledIn = array();
542
 
543
+ foreach ($pluginsToCheck as $plugin => $pluginTitle) {
544
+ // "Autoptimize" check
545
+ if ($plugin === 'autoptimize/autoptimize.php' && Misc::isPluginActive($plugin) && get_option('autoptimize_css')) {
546
+ $cssOptimizeEnabledIn[] = $pluginTitle;
547
+
548
+ if ($returnType === 'if_enabled') { return true; }
549
  }
 
550
 
551
+ // "WP Rocket" check
552
+ if ($plugin === 'wp-rocket/wp-rocket.php' && Misc::isPluginActive($plugin)) {
553
+ if (function_exists('get_rocket_option')) {
554
+ $wpRocketMinifyCss = get_rocket_option('minify_css');
555
+ $wpRocketMinifyConcatenateCss = get_rocket_option('minify_concatenate_css');
556
+ } else {
557
+ $wpRocketSettings = get_option('wp_rocket_settings');
558
+ $wpRocketMinifyCss = isset($wpRocketSettings['minify_css']) ? $wpRocketSettings['minify_css'] : false;
559
+ $wpRocketMinifyConcatenateCss = isset($wpRocketSettings['minify_concatenate_css']) ? $wpRocketSettings['minify_concatenate_css'] : false;
560
+ }
561
 
562
+ if ($wpRocketMinifyCss || $wpRocketMinifyConcatenateCss) {
563
+ $cssOptimizeEnabledIn[] = $pluginTitle;
564
 
565
+ if ($returnType === 'if_enabled') { return true; }
566
+ }
567
+ }
568
 
569
+ // "WP Fastest Cache" check
570
+ if ($plugin === 'wp-fastest-cache/wpFastestCache.php' && Misc::isPluginActive($plugin)) {
571
+ $wpfcOptionsJson = get_option('WpFastestCache');
572
+ $wpfcOptions = @json_decode($wpfcOptionsJson, ARRAY_A);
573
 
574
+ if (isset($wpfcOptions['wpFastestCacheMinifyCss']) || isset($wpfcOptions['wpFastestCacheCombineCss'])) {
575
+ $cssOptimizeEnabledIn[] = $pluginTitle;
576
+
577
+ if ($returnType === 'if_enabled') { return true; }
578
+ }
579
+ }
580
+
581
+ // "W3 Total Cache" check
582
+ if ($plugin === 'w3-total-cache/w3-total-cache.php' && Misc::isPluginActive($plugin)) {
583
+ $w3tcConfigMaster = Misc::getW3tcMasterConfig();
584
+ $w3tcEnableCss = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.css.enable":', ','), '" ');
585
+
586
+ if ($w3tcEnableCss === 1) {
587
+ $cssOptimizeEnabledIn[] = $pluginTitle;
588
 
589
+ if ($returnType === 'if_enabled') { return true; }
590
+ }
591
+ }
592
+
593
+ // "SG Optimizer" check
594
+ if ($plugin === 'sg-cachepress/sg-cachepress.php' && Misc::isPluginActive($plugin)) {
595
+ if (class_exists('\SiteGround_Optimizer\Options\Options')
596
+ && method_exists('\SiteGround_Optimizer\Options\Options', 'is_enabled')
597
+ && @\SiteGround_Optimizer\Options\Options::is_enabled('siteground_optimizer_combine_css')) {
598
+ $cssOptimizeEnabledIn[] = $pluginTitle;
599
+ if ($returnType === 'if_enabled') { return true; }
600
+ }
601
+ }
602
+
603
+ // "Fast Velocity Minify" check
604
+ if ($plugin === 'fast-velocity-minify/fvm.php' && Misc::isPluginActive($plugin)) {
605
+ // It's enough if it's active due to its configuration
606
+ $cssOptimizeEnabledIn[] = $pluginTitle;
607
+
608
+ if ($returnType === 'if_enabled') { return true; }
609
+ }
610
+
611
+ // "LiteSpeed Cache" check
612
+ if ($plugin === 'litespeed-cache/litespeed-cache.php' && Misc::isPluginActive($plugin) && ($liteSpeedCacheConf = apply_filters('litespeed_cache_get_options', get_option('litespeed-cache-conf')))) {
613
+ if ( (isset($liteSpeedCacheConf['css_minify']) && $liteSpeedCacheConf['css_minify'])
614
+ || (isset($liteSpeedCacheConf['css_combine']) && $liteSpeedCacheConf['css_combine']) ) {
615
+ $cssOptimizeEnabledIn[] = $pluginTitle;
616
+
617
+ if ($returnType === 'if_enabled') { return true; }
618
+ }
619
+ }
620
+
621
+ // "Swift Performance Lite" check
622
+ if ($plugin === 'swift-performance-lite/performance.php' && Misc::isPluginActive($plugin)
623
+ && class_exists('Swift_Performance_Lite') && method_exists('Swift_Performance_Lite', 'check_option')) {
624
+ if ( @\Swift_Performance_Lite::check_option('merge-styles', 1) ) {
625
+ $cssOptimizeEnabledIn[] = $pluginTitle;
626
+ }
627
+
628
+ if ($returnType === 'if_enabled') { return true; }
629
+ }
630
  }
631
 
632
+ return $cssOptimizeEnabledIn;
633
+ }
634
+
635
+ /**
636
+ * @return bool
637
+ */
638
+ public static function wpfcMinifyCssEnabledOnly()
639
+ {
640
+ if (Misc::isPluginActive('wp-fastest-cache/wpFastestCache.php')) {
641
+ $wpfcOptionsJson = get_option('WpFastestCache');
642
+ $wpfcOptions = @json_decode($wpfcOptionsJson, ARRAY_A);
643
+
644
+ // "Minify CSS" is enabled, "Combine CSS" is disabled
645
+ return isset($wpfcOptions['wpFastestCacheMinifyCss']) && ! isset($wpfcOptions['wpFastestCacheCombineCss']);
646
  }
647
 
 
648
  return false;
649
  }
650
 
classes/OptimiseAssets/OptimizeJs.php CHANGED
@@ -16,347 +16,331 @@ use WpAssetCleanUp\Preloads;
16
  class OptimizeJs
17
  {
18
  /**
19
- * @var float|int
20
  */
21
- public static $cachedJsAssetsFileExpiresIn = 28800; // 8 hours in seconds (60 * 60 * 8)
22
 
23
  /**
24
- * @var string
25
  */
26
- public $jsonStorageFile = 'js-combined{maybe-extra-info}.json';
27
 
28
  /**
29
  *
30
  */
31
  public function init()
32
  {
33
- add_action('wp_loaded', function() {
34
- if (is_admin()) { // don't apply any changes if not in the front-end view (e.g. Dashboard view)
35
- return;
36
- }
37
-
38
- ob_start(function($htmlSource) {
39
- // Do not do any optimization if "Test Mode" is Enabled
40
- if (! Menu::userCanManageAssets() && Main::instance()->settings['test_mode']) {
41
- return $htmlSource;
42
- }
43
-
44
- // There has to be at least one "<script", otherwise, it could be a feed request or something similar (not page, post, homepage etc.)
45
- if (stripos($htmlSource, '<script') === false) {
46
- return $htmlSource;
47
- }
48
-
49
- // Are there any assets unloaded where their "children" are ignored?
50
- // Since they weren't dequeued the WP way (to avoid unloading the "children"), they will be stripped here
51
- if (! Main::instance()->preventAssetsSettings()) {
52
- $ignoreChild = Main::instance()->getIgnoreChildren();
53
-
54
- if (isset($ignoreChild['scripts']) && ! empty($ignoreChild['scripts'])) {
55
- foreach ($ignoreChild['scripts'] as $scriptSrc) {
56
- $htmlSource = CleanUp::cleanScriptTagFromHtmlSource($scriptSrc, $htmlSource);
57
- }
58
- }
59
- }
60
-
61
- /*
62
- * #minifying
63
- * STEP 2: Load minify-able caching list and replace the original source URLs with the new cached ones
64
- */
65
- if (MinifyJs::isMinifyJsEnabled()) {
66
- // 'wpacu_js_minify_list' caching list is also checked; if it's empty, no minification is made
67
- $htmlSource = MinifyJs::updateHtmlSourceOriginalToMinJs($htmlSource);
68
- }
69
-
70
- if (! Main::instance()->preventAssetsSettings()) {
71
- $preloads = Preloads::instance()->getPreloads();
72
 
73
- if (isset($preloads['scripts']) && ! empty($preloads['scripts'])) {
74
- $htmlSource = Preloads::appendPreloadsForScriptsToHead($htmlSource);
75
- }
 
 
 
 
 
 
76
 
77
- $htmlSource = str_replace(Preloads::DEL_SCRIPTS_PRELOADS, '', $htmlSource);
78
- }
 
 
 
 
 
 
 
79
 
80
- if ( array_key_exists('wpacu_no_js_combine', $_GET) || // not on query string request (debugging purposes)
81
- ! $this->doJsCombine() ) {
82
- return $htmlSource;
83
- }
84
 
85
- // If "Do not combine JS on this page" is checked in "Asset CleanUp Options" side meta box
86
- // Works for posts, pages and custom post types
87
- if (defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0) {
88
- $pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID );
89
 
90
- if ( isset( $pageOptions['no_js_optimize'] ) && $pageOptions['no_js_optimize'] ) {
91
- return $htmlSource;
92
- }
93
- }
94
 
95
- $useDom = function_exists('libxml_use_internal_errors') && function_exists('libxml_clear_errors') && class_exists('DOMDocument');
 
 
 
 
96
 
97
- if (! $useDom) {
98
- return $htmlSource;
99
  }
 
 
100
 
101
- $combineLevel = 2;
 
 
102
 
103
- // Speed up processing by getting the already existing final CSS file URI
104
- // This will avoid parsing the HTML DOM and determine the combined URI paths for all the CSS files
105
- $finalCacheList = OptimizeCommon::getAssetCachedData($this->jsonStorageFile, self::getRelPathJsCacheDir(), 'js');
 
 
 
 
 
106
 
107
- // $uriToFinalJsFile will always be relative ONLY within WP_CONTENT_DIR . self::getRelPathJsCacheDir()
108
- // which is usually "wp-content/cache/asset-cleanup/js/"
109
 
110
- // "false" would make it avoid checking the cache and always use the DOM Parser / RegExp
111
- // for DEV purposes ONLY as it uses more resources
112
- if (empty($finalCacheList)) {
113
- /*
114
- * NO CACHING TRANSIENT; Parse the DOM
115
- */
116
- // Nothing in the database records or the retrieved cached file does not exist?
117
- OptimizeCommon::clearAssetCachedData($this->jsonStorageFile);
118
 
119
- $regExpPattern = '#<script[^>]*>.*?</script>#is';
120
 
121
- preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
122
 
123
- // No <script> tag found? Do not continue
124
- if (empty($matchesSourcesFromTags)) {
125
- return $htmlSource;
126
- }
127
 
128
- if ($combineLevel === 2) {
129
- $matchesSourcesFromTags = $this->clearInlineScriptTags($matchesSourcesFromTags);
130
- }
131
 
132
- if (empty($matchesSourcesFromTags)) {
133
- return $htmlSource;
 
 
 
 
 
 
 
 
 
 
 
134
  }
 
 
135
 
136
- $combinableList = $bodyGroupIndexes = array();
137
-
138
- $groupIndex = 1;
139
- $jQueryAndMigrateGroup = 0;
140
-
141
- $jQueryGroupIndex = $loadsLocaljQuery = $loadsLocaljQueryMigrate = false;
142
-
143
- $lastScriptSrcFromHead = $this->lastScriptSrcFromHead($htmlSource);
144
-
145
- $reachedBody = false;
146
 
147
- $domTag = new \DOMDocument();
148
 
149
- libxml_use_internal_errors( true );
 
 
150
 
151
- // Only keep combinable JS files
152
- foreach ($matchesSourcesFromTags as $matchSourceFromTag) {
153
- $matchedSourceFromTag = trim( $matchSourceFromTag[0] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
- $domTag->loadHTML($matchedSourceFromTag);
 
156
 
157
- $scriptNotCombinable = $scriptPreloaded = $src = false;
158
 
159
- foreach ($domTag->getElementsByTagName( 'script' ) as $tagObject) {
160
- if (! $tagObject->hasAttributes()) {
161
- continue;
162
- }
163
 
164
- $scriptAttributes = array();
 
165
 
166
- foreach ( $tagObject->attributes as $attrObj ) {
167
- $scriptAttributes[ $attrObj->nodeName ] = trim($attrObj->nodeValue);
168
- }
169
 
170
- if (isset($scriptAttributes['src']) && $scriptAttributes['src']) {
171
- $src = (string) $scriptAttributes['src'];
 
172
 
173
- $scriptNotCombinable = false;
174
 
175
- if ($this->skipCombine($src)) {
176
- $scriptNotCombinable = true;
177
- }
178
 
179
- // Do not add it to the combination list if it has "async" or "defer" attributes
180
- if (in_array($scriptAttributes, array('async', 'defer'))) {
181
- $scriptNotCombinable = true;
182
- }
183
 
184
- if (isset($scriptAttributes['data-wpacu-to-be-preloaded']) && $scriptAttributes['data-wpacu-to-be-preloaded']) {
185
- $scriptNotCombinable = $scriptPreloaded = true;
186
- }
187
- }
188
 
189
- }
 
 
 
190
 
191
- if ( $src && ! $scriptNotCombinable ) {
192
- $localAssetPath = OptimizeCommon::getLocalAssetPath( $src, 'js' );
 
 
 
193
 
194
- if ( $localAssetPath ) {
195
- $combinableList[ $groupIndex ][] = array(
196
- 'src' => $src,
197
- 'local' => $localAssetPath,
198
- 'html' => $matchedSourceFromTag
199
- );
200
 
201
- if ( strpos( $localAssetPath, '/wp-includes/js/jquery/jquery.js' ) !== false ) {
202
- $loadsLocaljQuery = true;
203
- $jQueryGroupIndex = $groupIndex;
 
 
204
 
205
- $jQueryArrayGroupKeys = array_keys( $combinableList[ $groupIndex ] );
206
- $jQueryScriptIndex = array_pop( $jQueryArrayGroupKeys );
 
 
 
 
 
 
207
 
208
- $jQueryAndMigrateGroup ++;
209
- } elseif ( strpos( $localAssetPath,
210
- '/wp-includes/js/jquery/jquery-migrate.' ) !== false ) {
211
- $loadsLocaljQueryMigrate = true;
212
- $jQueryAndMigrateGroup ++;
213
- }
214
- }
215
 
216
- // We'll check the current group
217
- // If we have jQuery and jQuery migrate, we will consider the group completed
218
- // and we will move on to the next group
219
- if ( $jQueryAndMigrateGroup > 1 ) {
220
- $groupIndex ++;
221
- $jQueryAndMigrateGroup = 0; // reset it to avoid having one file per group!
222
- }
223
 
224
- // Have we passed <head> and stumbled upon the first script tag from the <body>
225
- // Then consider the group completed
226
- if ($lastScriptSrcFromHead && ($src === $lastScriptSrcFromHead)) {
227
- $groupIndex++;
228
- $reachedBody = true;
229
- }
230
- } elseif (! $scriptPreloaded) {
231
- $groupIndex ++;
232
- }
233
 
234
- if ($reachedBody) {
235
- $bodyGroupIndexes[] = $groupIndex;
236
- }
237
- }
238
 
239
- // Is the page loading local jQuery but not local jQuery Migrate?
240
- // Keep jQuery as standalone file (not in the combinable list)
241
- if ( $loadsLocaljQuery && ! $loadsLocaljQueryMigrate && isset($jQueryScriptIndex) ) {
242
- unset($combinableList[$jQueryGroupIndex][$jQueryScriptIndex]);
243
- }
244
 
245
- // Could be pages such as maintenance mode with no external JavaScript files
246
- if (empty($combinableList)) {
247
- return $htmlSource;
248
- }
 
 
249
 
250
- $groupNo = 1;
 
251
 
252
- $finalCacheList = array();
 
 
 
 
 
 
253
 
254
- foreach ($combinableList as $groupIndex => $groupFiles) {
255
- // Any groups having one file? Then it's not really a group and the file should load on its own
256
- // Could be one extra file besides the jQuery & jQuery Migrate group or the only JS file called within the HEAD
257
- if (count($groupFiles) < 2) {
258
- continue;
259
- }
260
 
261
- $combinedUriPaths = $localAssetsPaths = $groupScriptTags = $groupScriptSrcs = array();
 
 
 
 
 
 
 
 
 
262
 
263
- foreach ( $groupFiles as $groupFileData ) {
264
- $src = $groupFileData['src'];
265
- $groupScriptSrcs[] = $src;
266
- $combinedUriPaths[] = OptimizeCommon::getHrefRelPath( $src );
267
- $localAssetsPaths[ $src ] = $groupFileData['local'];
268
- $groupScriptTags[] = $groupFileData['html'];
269
- }
270
 
271
- // <head> or <body>
272
- $docLocationScript = in_array($groupIndex, $bodyGroupIndexes) ? 'body' : 'head';
273
 
274
- $maybeDoJsCombine = $this->maybeDoJsCombine(
275
- sha1( implode( '', $combinedUriPaths ) ) . '-' . $groupNo,
276
- $localAssetsPaths,
277
- $docLocationScript
278
- );
279
 
280
- // Local path to combined CSS file
281
- $localFinalJsFile = $maybeDoJsCombine['local_final_js_file'];
282
 
283
- // URI (e.g. /wp-content/cache/asset-cleanup/[file-name-here.js]) to the combined JS file
284
- $uriToFinalJsFile = $maybeDoJsCombine['uri_final_js_file'];
285
 
286
- if ( ! file_exists( $localFinalJsFile ) ) {
287
- return $htmlSource; // something is not right as the file wasn't created, we will return the original HTML source
288
- }
289
 
290
- $groupScriptSrcsFilter = array_map( function ( $src ) {
291
- return str_replace( site_url(), '{site_url}', $src );
292
- }, $groupScriptSrcs );
 
 
 
 
 
293
 
294
- $groupScriptTagsFilter = array_map( function ( $scriptTag ) {
295
- return str_replace( site_url(), '{site_url}', $scriptTag );
296
- }, $groupScriptTags );
 
 
297
 
298
- $finalCacheList[ $groupNo ] = array(
299
- 'uri_to_final_js_file' => $uriToFinalJsFile,
300
- 'script_srcs' => $groupScriptSrcsFilter,
301
- 'script_tags' => $groupScriptTagsFilter
302
- );
303
 
304
- if (Main::instance()->settings['combine_loaded_js_defer_body'] && in_array($groupIndex, $bodyGroupIndexes)) {
305
- $finalCacheList[ $groupNo ]['extras'][] = 'defer';
306
- }
 
307
 
308
- $groupNo++;
 
 
309
  }
310
-
311
- OptimizeCommon::setAssetCachedData($this->jsonStorageFile, self::getRelPathJsCacheDir(), json_encode($finalCacheList));
312
  }
 
313
 
314
- if (! empty($finalCacheList)) {
315
- foreach ( $finalCacheList as $groupNo => $cachedValues ) {
316
- $htmlSourceBeforeGroupReplacement = $htmlSource;
317
-
318
- $uriToFinalJsFile = $cachedValues['uri_to_final_js_file'];
319
-
320
- // Basic Combining (1) -> replace "first" tag with the final combination tag (there would be most likely multiple groups)
321
- // Enhanced Combining (2) -> replace "last" tag with the final combination tag (most likely one group)
322
- $indexReplacement = ($combineLevel === 2) ? (count($cachedValues['script_tags']) - 1) : 0;
323
-
324
- $finalTagUrl = OptimizeCommon::filterWpContentUrl() . self::getRelPathJsCacheDir() . $uriToFinalJsFile;
325
-
326
- $deferAttr = (isset($cachedValues['extras']) && in_array('defer', $cachedValues['extras'])) ? 'defer="defer"' : '';
327
 
328
- $finalJsTag = <<<HTML
329
- <script {$deferAttr} id='wpacu-combined-js-group-{$groupNo}' type='text/javascript' src='{$finalTagUrl}'></script>
330
- HTML;
331
- $tagsStripped = 0;
332
 
333
- foreach ( $cachedValues['script_tags'] as $groupScriptTagIndex => $scriptTag ) {
334
- $scriptTag = str_replace( '{site_url}', site_url(), $scriptTag );
 
335
 
336
- if ( $groupScriptTagIndex === $indexReplacement ) {
337
- $htmlSourceBeforeTagReplacement = $htmlSource;
338
- $htmlSource = $this->strReplaceOnce( $scriptTag, $finalJsTag, $htmlSource );
339
- } else {
340
- $htmlSourceBeforeTagReplacement = $htmlSource;
341
- $htmlSource = $this->strReplaceOnce( $scriptTag, '', $htmlSource );
342
- }
343
 
344
- if ($htmlSource !== $htmlSourceBeforeTagReplacement) {
345
- $tagsStripped++;
346
- }
347
- }
348
 
349
- // At least two tags has have be stripped from the group to consider doing the group replacement
350
- // If the tags weren't replaced it's likely there were changes to their structure after they were cached for the group merging
351
- if ($tagsStripped < 2) {
352
- $htmlSource = $htmlSourceBeforeGroupReplacement;
353
- }
354
- }
355
  }
 
356
 
357
- return $htmlSource;
358
- });
359
- }, 1);
 
360
  }
361
 
362
  /**
@@ -372,7 +356,7 @@ HTML;
372
  *
373
  * @return mixed
374
  */
375
- public function clearInlineScriptTags($matchesSourcesFromTags)
376
  {
377
  $domTag = new \DOMDocument();
378
 
@@ -413,7 +397,7 @@ HTML;
413
  *
414
  * @return string
415
  */
416
- public function lastScriptSrcFromHead($htmlSource)
417
  {
418
  // Do not check MSIE conditional comments as they are not combined
419
  $htmlSource = OptimizeCommon::cleanerHtmlSource($htmlSource);
@@ -454,90 +438,20 @@ HTML;
454
  }
455
 
456
  /**
457
- * @param $shaOneCombinedUriPaths
458
- * @param $localAssetsPaths
459
- * @param $doclocationScript
460
  *
461
- * @return array
462
  */
463
- public function maybeDoJsCombine($shaOneCombinedUriPaths, $localAssetsPaths, $docLocationScript)
464
  {
465
- $current_user = wp_get_current_user();
466
- $dirToUserCachedFile = ((isset($current_user->ID) && $current_user->ID > 0) ? 'logged-in/'.$current_user->ID.'/' : '');
467
-
468
- $uriToFinalJsFile = $dirToUserCachedFile . $docLocationScript . '-' . $shaOneCombinedUriPaths . '.js';
469
-
470
- $localFinalJsFile = WP_CONTENT_DIR . self::getRelPathJsCacheDir() . $uriToFinalJsFile;
471
- $localDirForJsFile = WP_CONTENT_DIR . self::getRelPathJsCacheDir() . $dirToUserCachedFile;
472
-
473
- // Only combine if $shaOneCombinedUriPaths.js does not exist
474
- // If "?ver" value changes on any of the assets or the asset list changes in any way
475
- // then $shaOneCombinedUriPaths will change too and a new JS file will be generated and loaded
476
-
477
- $skipIfFileExists = true;
478
-
479
- if ($skipIfFileExists || ! file_exists($localFinalJsFile)) {
480
- // Change $assetsContents as paths to fonts and images that are relative (e.g. ../, ../../) have to be updated
481
- $finalJsContentsGroupsArray = array();
482
-
483
- foreach ($localAssetsPaths as $assetHref => $localAssetsPath) {
484
- $posLastSlash = strrpos($assetHref, '/');
485
- $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
486
-
487
- $parseUrl = parse_url($pathToAssetDir);
488
-
489
- if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
490
- $pathToAssetDir = str_replace(
491
- array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
492
- '',
493
- $pathToAssetDir
494
- );
495
- } elseif (strpos($pathToAssetDir, '//') === 0) {
496
- $pathToAssetDir = str_replace(
497
- array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
498
- '',
499
- $pathToAssetDir
500
- );
501
- }
502
-
503
- $jsContent = FileSystem::file_get_contents($localAssetsPath);
504
-
505
- if ($jsContent) {
506
- // Does it have a source map? Strip it
507
- if (strpos($jsContent, 'sourceMappingURL') !== false) {
508
- $jsContent = OptimizeCommon::stripSourceMap($jsContent);
509
- }
510
-
511
- $finalJsContentsIndex = 1;
512
-
513
- $finalJsContentsGroupsArray[$finalJsContentsIndex][] = '/*** Source: '.str_replace(ABSPATH, '/', $localAssetsPath)." ***/\n" . self::maybeDoJsFixes($jsContent, $pathToAssetDir . '/') . "\n\n";
514
- }
515
- }
516
-
517
- if (! empty($finalJsContentsGroupsArray)) {
518
- $contentsOne = isset($finalJsContentsGroupsArray[1]) && ! empty($finalJsContentsGroupsArray[1]) ? implode ('', $finalJsContentsGroupsArray[1]) : '';
519
- $contentsTwo = isset($finalJsContentsGroupsArray[2]) && ! empty($finalJsContentsGroupsArray[2]) ? implode ('', $finalJsContentsGroupsArray[2]) : '';
520
-
521
- $finalJsContents = $contentsOne . $contentsTwo;
522
-
523
- if ( $dirToUserCachedFile !== '' && isset( $current_user->ID ) && $current_user->ID > 0) {
524
- if (! is_dir( $localDirForJsFile)) {
525
- $makeLocalDirForJs = @mkdir($localDirForJsFile);
526
-
527
- if (! $makeLocalDirForJs) {
528
- return array('uri_final_js_file' => '', 'local_final_js_file' => '');
529
- }
530
- }
531
- }
532
-
533
- @file_put_contents( $localFinalJsFile, $finalJsContents );
534
- }
535
  }
536
 
537
- return array(
538
- 'uri_final_js_file' => $uriToFinalJsFile,
539
- 'local_final_js_file' => $localFinalJsFile
540
- );
541
  }
542
 
543
  /**
@@ -566,112 +480,120 @@ HTML;
566
  }
567
 
568
  /**
569
- * @param $src
570
- *
571
- * @return bool
 
572
  */
573
- public function skipCombine($src)
574
  {
575
- $regExps = array();
 
 
 
 
 
 
 
 
 
576
 
577
- if (Main::instance()->settings['combine_loaded_js_exceptions'] !== '') {
578
- $loadedCssExceptionsPatterns = trim(Main::instance()->settings['combine_loaded_js_exceptions']);
579
 
580
- if (strpos($loadedCssExceptionsPatterns, "\n")) {
581
- // Multiple values (one per line)
582
- foreach (explode("\n", $loadedCssExceptionsPatterns) as $loadedCssExceptionPattern) {
583
- $regExps[] = '#'.trim($loadedCssExceptionPattern).'#';
584
- }
585
- } else {
586
- // Only one value?
587
- $regExps[] = '#'.trim($loadedCssExceptionsPatterns).'#';
588
  }
589
- }
590
 
591
- // No exceptions set? Do not skip combination
592
- if (empty($regExps)) {
593
- return false;
594
- }
 
 
 
 
 
 
 
 
 
595
 
596
- foreach ($regExps as $regExp) {
597
- if ( preg_match( $regExp, $src ) ) {
598
- // Skip combination
599
- return true;
600
  }
601
- }
602
 
603
- return false;
604
- }
 
 
605
 
606
- /**
607
- * @return bool
608
- */
609
- public function doJsCombine()
610
- {
611
- // No JS files are combined in the Dashboard
612
- // Always in the front-end view
613
- // Do not combine if there's a POST request as there could be assets loading conditionally
614
- // that might not be needed when the page is accessed without POST, making the final JS file larger
615
- if (! empty($_POST) || is_admin()) {
616
- return false; // Do not combine
617
- }
618
 
619
- // Only clean request URIs allowed (with few exceptions)
620
- if (strpos($_SERVER['REQUEST_URI'], '?') !== false) {
621
- // Exceptions
622
- if (! OptimizeCommon::loadOptimizedAssetsIfQueryStrings()) {
623
- return false;
624
  }
625
- }
626
 
627
- if (! OptimizeCommon::doCombineIsRegularPage()) {
628
- return false;
629
- }
 
630
 
631
- $pluginSettings = Main::instance()->settings;
 
632
 
633
- if ($pluginSettings['test_mode'] && ! Menu::userCanManageAssets()) {
634
- return false; // Do not combine anything if "Test Mode" is ON
635
- }
636
 
637
- if ($pluginSettings['combine_loaded_js'] === '') {
638
- return false; // Do not combine
639
- }
 
 
640
 
641
- if (Misc::isOptimizeJsEnabledByOtherParty('if_enabled')) {
642
- return false; // Do not combine (it's already enabled in another plugin)
643
- }
 
644
 
645
- if ( ($pluginSettings['combine_loaded_js'] === 'for_admin'
646
- || $pluginSettings['combine_loaded_js_for_admin_only'] == 1)
647
- && Menu::userCanManageAssets() ) {
648
- return true; // Do combine
649
- }
650
 
651
- if ( $pluginSettings['combine_loaded_js_for_admin_only'] === ''
652
- && in_array($pluginSettings['combine_loaded_js'], array('for_all', 1)) ) {
653
- return true; // Do combine
654
- }
655
 
656
- // Finally, return false as none of the checks above matched
657
- return false;
658
- }
 
 
659
 
660
- /**
661
- * @param $strFind
662
- * @param $strReplaceWith
663
- * @param $string
664
- *
665
- * @return mixed
666
- */
667
- public static function strReplaceOnce($strFind, $strReplaceWith, $string)
668
- {
669
- if ( strpos($string, $strFind) === false ) {
670
- return $string;
 
 
 
671
  }
672
 
673
- $occurrence = strpos($string, $strFind);
674
- return substr_replace($string, $strReplaceWith, $occurrence, strlen($strFind));
 
675
  }
676
 
677
  }
16
  class OptimizeJs
17
  {
18
  /**
19
+ * @var array
20
  */
21
+ public $optimizeList = array();
22
 
23
  /**
24
+ * @var float|int
25
  */
26
+ public static $cachedJsAssetsFileExpiresIn = 28800; // 8 hours in seconds (60 * 60 * 8)
27
 
28
  /**
29
  *
30
  */
31
  public function init()
32
  {
33
+ add_action('init', array($this, 'whatToOptimize'), 20);
34
+ add_action('wp_print_footer_scripts', array($this, 'prepareOptimizeList'), PHP_INT_MAX);
35
+ add_action('wp_loaded', array($this, 'alterHtmlSource'), 1);
36
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ /**
39
+ *
40
+ */
41
+ public function whatToOptimize()
42
+ {
43
+ if (MinifyJs::isMinifyJsEnabled()) {
44
+ $this->optimizeList[] = 'minify_js';
45
+ }
46
+ }
47
 
48
+ /**
49
+ *
50
+ */
51
+ public function prepareOptimizeList()
52
+ {
53
+ // At this time, the only optimization for JS files is minification
54
+ if (! in_array('minify_js', $this->optimizeList)) {
55
+ return;
56
+ }
57
 
58
+ global $wp_scripts;
 
 
 
59
 
60
+ $jsOptimizeList = array();
 
 
 
61
 
62
+ $wpScriptsList = array_unique(array_merge($wp_scripts->done, $wp_scripts->queue));
 
 
 
63
 
64
+ // [Start] Collect for caching
65
+ foreach ($wpScriptsList as $handle) {
66
+ if (isset($wp_scripts->registered[$handle])) {
67
+ $value = $wp_scripts->registered[$handle];
68
+ $optimizeValues = $this->maybeOptimizeIt($value);
69
 
70
+ if ( ! empty( $optimizeValues ) ) {
71
+ $jsOptimizeList[] = $optimizeValues;
72
  }
73
+ }
74
+ }
75
 
76
+ wp_cache_add('wpacu_js_optimize_list', $jsOptimizeList);
77
+ // [End] Collect for caching
78
+ }
79
 
80
+ /**
81
+ * @param $value
82
+ *
83
+ * @return array
84
+ */
85
+ public function maybeOptimizeIt($value)
86
+ {
87
+ global $wp_version;
88
 
89
+ $src = isset($value->src) ? $value->src : false;
 
90
 
91
+ if (! $src || MinifyJs::skipMinify($src, $value->handle)) {
92
+ return array();
93
+ }
 
 
 
 
 
94
 
95
+ $handleDbStr = md5($value->handle);
96
 
97
+ $transientName = 'wpacu_js_optimize_'.$handleDbStr;
98
 
99
+ $savedValues = get_transient( $transientName );
 
 
 
100
 
101
+ if ( $savedValues ) {
102
+ $savedValuesArray = json_decode( $savedValues, ARRAY_A );
 
103
 
104
+ if ( $savedValuesArray['ver'] !== $value->ver ) {
105
+ // New File Version? Delete transient as it will be re-added to the database with the new version
106
+ delete_transient( $transientName );
107
+ } else {
108
+ $localPathToJsOptimized = str_replace( '//', '/', ABSPATH . $savedValuesArray['optimize_uri'] );
109
+
110
+ // Do not load any minified JS file (from the database transient cache) if it doesn't exist
111
+ // It will fallback to the original JS file
112
+ if ( isset( $savedValuesArray['source_uri'] ) && file_exists( $localPathToJsOptimized ) ) {
113
+ return array(
114
+ $savedValuesArray['source_uri'],
115
+ $savedValuesArray['optimize_uri'],
116
+ );
117
  }
118
+ }
119
+ }
120
 
121
+ if (strpos($src, '/wp-includes/') === 0) {
122
+ $src = site_url() . $src;
123
+ }
 
 
 
 
 
 
 
124
 
125
+ $localAssetPath = OptimizeCommon::getLocalAssetPath($src, 'js');
126
 
127
+ if (! file_exists($localAssetPath)) {
128
+ return array();
129
+ }
130
 
131
+ $assetHref = $value->src;
132
+
133
+ $posLastSlash = strrpos($assetHref, '/');
134
+ $pathToAssetDir = substr($assetHref, 0, $posLastSlash);
135
+
136
+ $parseUrl = parse_url($pathToAssetDir);
137
+
138
+ if (isset($parseUrl['scheme']) && $parseUrl['scheme'] !== '') {
139
+ $pathToAssetDir = str_replace(
140
+ array('http://'.$parseUrl['host'], 'https://'.$parseUrl['host']),
141
+ '',
142
+ $pathToAssetDir
143
+ );
144
+ } elseif (strpos($pathToAssetDir, '//') === 0) {
145
+ $pathToAssetDir = str_replace(
146
+ array('//'.$parseUrl['host'], '//'.$parseUrl['host']),
147
+ '',
148
+ $pathToAssetDir
149
+ );
150
+ }
151
 
152
+ $jsContent = FileSystem::file_get_contents($localAssetPath);
153
+ $jsContent = OptimizeJs::maybeDoJsFixes($jsContent, $pathToAssetDir . '/'); // Minify it and save it to /wp-content/cache/js/min/
154
 
155
+ $jsContent = MinifyJs::applyMinification($jsContent);
156
 
157
+ // Relative path to the new file
158
+ $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
 
 
159
 
160
+ // Save it to /wp-content/cache/js/{OptimizeCommon::$optimizedSingleFilesDir}/
161
+ $newFilePathUri = OptimizeJs::getRelPathJsCacheDir() . OptimizeCommon::$optimizedSingleFilesDir . '/' . $value->handle . '-v' . $ver;
162
 
163
+ $sha1File = @sha1_file($localAssetPath);
 
 
164
 
165
+ if ($sha1File) {
166
+ $newFilePathUri .= '-'.$sha1File;
167
+ }
168
 
169
+ $newFilePathUri .= '.js';
170
 
171
+ $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
172
+ $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
 
173
 
174
+ if ($jsContent) {
175
+ $jsContent = '/*** Source (before minification): ' . str_replace(ABSPATH, '/', $localAssetPath) . ' ***/' . "\n" . $jsContent;
176
+ }
 
177
 
178
+ $saveFile = @file_put_contents($newLocalPath, $jsContent);
 
 
 
179
 
180
+ if (! $saveFile || ! $jsContent) {
181
+ // Fallback to the original JS if the minified version can't be created or updated
182
+ return array();
183
+ }
184
 
185
+ $saveValues = array(
186
+ 'source_uri' => OptimizeCommon::getHrefRelPath($value->src),
187
+ 'optimize_uri' => OptimizeCommon::getHrefRelPath($newLocalPathUrl),
188
+ 'ver' => $ver
189
+ );
190
 
191
+ // Add / Re-add (with new version) transient
192
+ set_transient($transientName, json_encode($saveValues));
 
 
 
 
193
 
194
+ return array(
195
+ OptimizeCommon::getHrefRelPath($value->src),
196
+ OptimizeCommon::getHrefRelPath($newLocalPathUrl),
197
+ );
198
+ }
199
 
200
+ /**
201
+ * @param $htmlSource
202
+ *
203
+ * @return mixed
204
+ */
205
+ public static function updateHtmlSourceOriginalToOptimizedJs($htmlSource)
206
+ {
207
+ $jsOptimizeList = wp_cache_get('wpacu_js_optimize_list');
208
 
209
+ if (empty($jsOptimizeList)) {
210
+ return $htmlSource;
211
+ }
 
 
 
 
212
 
213
+ $regExpPattern = '#<script[^>]*src(|\s+)=(|\s+)[^>]*(>)#Usmi';
 
 
 
 
 
 
214
 
215
+ preg_match_all($regExpPattern, OptimizeCommon::cleanerHtmlSource($htmlSource), $matchesSourcesFromTags, PREG_SET_ORDER);
 
 
 
 
 
 
 
 
216
 
217
+ foreach ($matchesSourcesFromTags as $matches) {
218
+ $scriptSourceTag = $matches[0];
 
 
219
 
220
+ if (strip_tags($scriptSourceTag) !== '') {
221
+ // Hmm? Not a valid tag... Skip it...
222
+ continue;
223
+ }
 
224
 
225
+ foreach ($jsOptimizeList as $listValues) {
226
+ // If the minified files are deleted (e.g. /wp-content/cache/ is cleared)
227
+ // do not replace the JS file path to avoid breaking the website
228
+ if (! file_exists(rtrim(ABSPATH, '/') . $listValues[1])) {
229
+ continue;
230
+ }
231
 
232
+ $sourceUrl = site_url() . $listValues[0];
233
+ $optimizeUrl = site_url() . $listValues[1];
234
 
235
+ if ($scriptSourceTag !== str_ireplace($sourceUrl, $optimizeUrl, $scriptSourceTag)) {
236
+ $newLinkSourceTag = self::updateOriginalToOptimizedTag($scriptSourceTag, $sourceUrl, $optimizeUrl);
237
+ $htmlSource = str_replace($scriptSourceTag, $newLinkSourceTag, $htmlSource);
238
+ break;
239
+ }
240
+ }
241
+ }
242
 
243
+ return $htmlSource;
244
+ }
 
 
 
 
245
 
246
+ /**
247
+ * @param $scriptSourceTag
248
+ * @param $sourceUrl
249
+ * @param $optimizeUrl
250
+ *
251
+ * @return mixed
252
+ */
253
+ public static function updateOriginalToOptimizedTag($scriptSourceTag, $sourceUrl, $optimizeUrl)
254
+ {
255
+ $newScriptSourceTag = str_replace($sourceUrl, $optimizeUrl, $scriptSourceTag);
256
 
257
+ // Needed in case it's added to the Combine CSS exceptions list
258
+ if (CombineJs::proceedWithJsCombine()) {
259
+ $newScriptSourceTag = str_ireplace('<script ', '<script data-wpacu-script-src-before="' . $sourceUrl . '" ', $newScriptSourceTag);
260
+ }
 
 
 
261
 
262
+ // Strip ?ver=
263
+ $toStrip = Misc::extractBetween($newScriptSourceTag, '?ver=', '>');
264
 
265
+ if (in_array(substr($toStrip, -1), array('"', "'"))) {
266
+ $toStrip = '?ver='. trim(trim($toStrip, '"'), "'");
267
+ $newScriptSourceTag = str_replace($toStrip, '', $newScriptSourceTag);
268
+ }
 
269
 
270
+ global $wp_version;
 
271
 
272
+ $newScriptSourceTag = str_replace('.js&#038;ver='.$wp_version, '.js', $newScriptSourceTag);
273
+ $newScriptSourceTag = str_replace('.js&#038;ver=', '.js?ver=', $newScriptSourceTag);
274
 
275
+ return $newScriptSourceTag;
276
+ }
 
277
 
278
+ /**
279
+ *
280
+ */
281
+ public function alterHtmlSource()
282
+ {
283
+ if (is_admin()) { // don't apply any changes if not in the front-end view (e.g. Dashboard view)
284
+ return;
285
+ }
286
 
287
+ ob_start(function($htmlSource) {
288
+ // Do not do any optimization if "Test Mode" is Enabled
289
+ if (! Menu::userCanManageAssets() && Main::instance()->settings['test_mode']) {
290
+ return $htmlSource;
291
+ }
292
 
293
+ // There has to be at least one "<script", otherwise, it could be a feed request or something similar (not page, post, homepage etc.)
294
+ if (stripos($htmlSource, '<script') === false) {
295
+ return $htmlSource;
296
+ }
 
297
 
298
+ // Are there any assets unloaded where their "children" are ignored?
299
+ // Since they weren't dequeued the WP way (to avoid unloading the "children"), they will be stripped here
300
+ if (! Main::instance()->preventAssetsSettings()) {
301
+ $ignoreChild = Main::instance()->getIgnoreChildren();
302
 
303
+ if (isset($ignoreChild['scripts']) && ! empty($ignoreChild['scripts'])) {
304
+ foreach ($ignoreChild['scripts'] as $scriptSrc) {
305
+ $htmlSource = CleanUp::cleanScriptTagFromHtmlSource($scriptSrc, $htmlSource);
306
  }
 
 
307
  }
308
+ }
309
 
310
+ /*
311
+ * #minifying
312
+ * STEP 2: Load minify-able caching list and replace the original source URLs with the new cached ones
313
+ */
314
+ if (MinifyJs::isMinifyJsEnabled()) {
315
+ // 'wpacu_js_optimize_list' caching list is also checked; if it's empty, no minification is made
316
+ $htmlSource = self::updateHtmlSourceOriginalToOptimizedJs($htmlSource);
317
+ }
 
 
 
 
 
318
 
319
+ if (! Main::instance()->preventAssetsSettings()) {
320
+ $preloads = Preloads::instance()->getPreloads();
 
 
321
 
322
+ if (isset($preloads['scripts']) && ! empty($preloads['scripts'])) {
323
+ $htmlSource = Preloads::appendPreloadsForScriptsToHead($htmlSource);
324
+ }
325
 
326
+ $htmlSource = str_replace(Preloads::DEL_SCRIPTS_PRELOADS, '', $htmlSource);
327
+ }
 
 
 
 
 
328
 
329
+ // If "Do not combine JS on this page" is checked in "Asset CleanUp Options" side meta box
330
+ // Works for posts, pages and custom post types
331
+ if (defined('WPACU_CURRENT_PAGE_ID') && WPACU_CURRENT_PAGE_ID > 0) {
332
+ $pageOptions = MetaBoxes::getPageOptions( WPACU_CURRENT_PAGE_ID );
333
 
334
+ // 'no_js_optimize' refers to avoid the combination of JS files
335
+ if ( isset( $pageOptions['no_js_optimize'] ) && $pageOptions['no_js_optimize'] ) {
336
+ return $htmlSource;
 
 
 
337
  }
338
+ }
339
 
340
+ $htmlSource = CombineJs::doCombine($htmlSource);
341
+
342
+ return $htmlSource;
343
+ });
344
  }
345
 
346
  /**
356
  *
357
  * @return mixed
358
  */
359
+ public static function clearInlineScriptTags($matchesSourcesFromTags)
360
  {
361
  $domTag = new \DOMDocument();
362
 
397
  *
398
  * @return string
399
  */
400
+ public static function lastScriptSrcFromHead($htmlSource)
401
  {
402
  // Do not check MSIE conditional comments as they are not combined
403
  $htmlSource = OptimizeCommon::cleanerHtmlSource($htmlSource);
438
  }
439
 
440
  /**
441
+ * @param $strFind
442
+ * @param $strReplaceWith
443
+ * @param $string
444
  *
445
+ * @return mixed
446
  */
447
+ public static function strReplaceOnce($strFind, $strReplaceWith, $string)
448
  {
449
+ if ( strpos($string, $strFind) === false ) {
450
+ return $string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  }
452
 
453
+ $occurrence = strpos($string, $strFind);
454
+ return substr_replace($string, $strReplaceWith, $occurrence, strlen($strFind));
 
 
455
  }
456
 
457
  /**
480
  }
481
 
482
  /**
483
+ * @param string $returnType
484
+ * 'list' - will return the list of plugins that have JS optimization enabled
485
+ * 'if_enabled' - will stop when it finds the first one (any order) and return true
486
+ * @return array|bool
487
  */
488
+ public static function isOptimizeJsEnabledByOtherParty($returnType = 'list')
489
  {
490
+ $pluginsToCheck = array(
491
+ 'autoptimize/autoptimize.php' => 'Autoptimize',
492
+ 'wp-rocket/wp-rocket.php' => 'WP Rocket',
493
+ 'wp-fastest-cache/wpFastestCache.php' => 'WP Fastest Cache',
494
+ 'w3-total-cache/w3-total-cache.php' => 'W3 Total Cache',
495
+ 'sg-cachepress/sg-cachepress.php' => 'SG Optimizer',
496
+ 'fast-velocity-minify/fvm.php' => 'Fast Velocity Minify',
497
+ 'litespeed-cache/litespeed-cache.php' => 'LiteSpeed Cache',
498
+ 'swift-performance-lite/performance.php' => 'Swift Performance Lite'
499
+ );
500
 
501
+ $jsOptimizeEnabledIn = array();
 
502
 
503
+ foreach ($pluginsToCheck as $plugin => $pluginTitle) {
504
+ // "Autoptimize" check
505
+ if ($plugin === 'autoptimize/autoptimize.php' && Misc::isPluginActive($plugin) && get_option('autoptimize_js')) {
506
+ $jsOptimizeEnabledIn[] = $pluginTitle;
507
+
508
+ if ($returnType === 'if_enabled') { return true; }
 
 
509
  }
 
510
 
511
+ // "WP Rocket" check
512
+ if ($plugin === 'wp-rocket/wp-rocket.php' && Misc::isPluginActive($plugin)) {
513
+ if (function_exists('get_rocket_option')) {
514
+ $wpRocketMinifyJs = get_rocket_option('minify_js');
515
+ $wpRocketMinifyConcatenateJs = get_rocket_option('minify_concatenate_js');
516
+ } else {
517
+ $wpRocketSettings = get_option('wp_rocket_settings');
518
+ $wpRocketMinifyJs = isset($wpRocketSettings['minify_js']) ? $wpRocketSettings['minify_js'] : false;
519
+ $wpRocketMinifyConcatenateJs = isset($wpRocketSettings['minify_concatenate_js']) ? $wpRocketSettings['minify_concatenate_js'] : false;
520
+ }
521
+
522
+ if ($wpRocketMinifyJs || $wpRocketMinifyConcatenateJs) {
523
+ $jsOptimizeEnabledIn[] = $pluginTitle;
524
 
525
+ if ($returnType === 'if_enabled') { return true; }
526
+ }
 
 
527
  }
 
528
 
529
+ // "WP Fastest Cache" check
530
+ if ($plugin === 'wp-fastest-cache/wpFastestCache.php' && Misc::isPluginActive($plugin)) {
531
+ $wpfcOptionsJson = get_option('WpFastestCache');
532
+ $wpfcOptions = @json_decode($wpfcOptionsJson, ARRAY_A);
533
 
534
+ if (isset($wpfcOptions['wpFastestCacheMinifyJs']) || isset($wpfcOptions['wpFastestCacheCombineJs'])) {
535
+ $jsOptimizeEnabledIn[] = $pluginTitle;
 
 
 
 
 
 
 
 
 
 
536
 
537
+ if ($returnType === 'if_enabled') { return true; }
538
+ }
 
 
 
539
  }
 
540
 
541
+ // "W3 Total Cache" check
542
+ if ($plugin === 'w3-total-cache/w3-total-cache.php' && Misc::isPluginActive($plugin)) {
543
+ $w3tcConfigMaster = Misc::getW3tcMasterConfig();
544
+ $w3tcEnableJs = (int)trim(Misc::extractBetween($w3tcConfigMaster, '"minify.js.enable":', ','), '" ');
545
 
546
+ if ($w3tcEnableJs === 1) {
547
+ $jsOptimizeEnabledIn[] = $pluginTitle;
548
 
549
+ if ($returnType === 'if_enabled') { return true; }
550
+ }
551
+ }
552
 
553
+ // "SG Optimizer" check
554
+ if ($plugin === 'sg-cachepress/sg-cachepress.php' && Misc::isPluginActive($plugin)) {
555
+ if (class_exists('\SiteGround_Optimizer\Options\Options') && method_exists('\SiteGround_Optimizer\Options\Options', 'is_enabled')) {
556
+ if (@\SiteGround_Optimizer\Options\Options::is_enabled( 'siteground_optimizer_optimize_javascript')) {
557
+ $jsOptimizeEnabledIn[] = $pluginTitle;
558
 
559
+ if ($returnType === 'if_enabled') { return true; }
560
+ }
561
+ }
562
+ }
563
 
564
+ // "Fast Velocity Minify" check
565
+ if ($plugin === 'fast-velocity-minify/fvm.php' && Misc::isPluginActive($plugin)) {
566
+ // It's enough if it's active due to its configuration
567
+ $jsOptimizeEnabledIn[] = $pluginTitle;
 
568
 
569
+ if ($returnType === 'if_enabled') { return true; }
570
+ }
 
 
571
 
572
+ // "LiteSpeed Cache" check
573
+ if ($plugin === 'litespeed-cache/litespeed-cache.php' && Misc::isPluginActive($plugin) && ($liteSpeedCacheConf = apply_filters('litespeed_cache_get_options', get_option('litespeed-cache-conf')))) {
574
+ if ( (isset($liteSpeedCacheConf['js_minify']) && $liteSpeedCacheConf['js_minify'])
575
+ || (isset($liteSpeedCacheConf['js_combine']) && $liteSpeedCacheConf['js_combine']) ) {
576
+ $jsOptimizeEnabledIn[] = $pluginTitle;
577
 
578
+ if ($returnType === 'if_enabled') { return true; }
579
+ }
580
+ }
581
+
582
+ // "Swift Performance Lite" check
583
+ if ($plugin === 'swift-performance-lite/performance.php' && Misc::isPluginActive($plugin)
584
+ && class_exists('Swift_Performance_Lite') && method_exists('Swift_Performance_Lite',
585
+ 'check_option')) {
586
+ if ( @\Swift_Performance_Lite::check_option('merge-scripts', 1) ) {
587
+ $jsOptimizeEnabledIn[] = $pluginTitle;
588
+ }
589
+
590
+ if ($returnType === 'if_enabled') { return true; }
591
+ }
592
  }
593
 
594
+ if ($returnType === 'if_enabled') { return false; }
595
+
596
+ return $jsOptimizeEnabledIn;
597
  }
598
 
599
  }
classes/Plugin.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  namespace WpAssetCleanUp;
3
 
 
 
4
  /**
5
  * Class Plugin
6
  * @package WpAssetCleanUp
@@ -96,13 +98,17 @@ class Plugin
96
  * /wp-content/cache/asset-cleanup/.htaccess
97
  *
98
  * /wp-content/cache/asset-cleanup/css/
 
99
  * /wp-content/cache/asset-cleanup/css/index.php
100
- *
101
  * /wp-content/cache/asset-cleanup/css/logged-in/
102
  * /wp-content/cache/asset-cleanup/css/logged-in/index.php
103
- *
104
- * /wp-content/cache/asset-cleanup/css/min/
105
- * /wp-content/cache/asset-cleanup/css/min/index.php
 
 
 
 
106
  */
107
  self::createCacheFoldersFiles(array('css','js'));
108
 
@@ -127,14 +133,14 @@ class Plugin
127
  */
128
  public static function createCacheFoldersFiles($assetTypes)
129
  {
130
- foreach ($assetTypes as $assetType) {
131
- if ($assetType === 'css') {
132
- $cacheDir = WP_CONTENT_DIR . OptimiseAssets\OptimizeCss::getRelPathCssCacheDir();
133
- } elseif ($assetType === 'js') {
134
- $cacheDir = WP_CONTENT_DIR . OptimiseAssets\OptimizeJs::getRelPathJsCacheDir();
135
- } else {
136
- return;
137
- }
138
 
139
  $emptyPhpFileContents = <<<TEXT
140
  <?php
@@ -160,8 +166,8 @@ HTACCESS;
160
  @mkdir( $cacheDir . 'logged-in', 0755 );
161
  }
162
 
163
- if ( ! is_dir( $cacheDir . 'min' ) ) {
164
- @mkdir( $cacheDir . 'min', 0755 );
165
  }
166
 
167
  if ( ! is_file( $cacheDir . 'logged-in/index.php' ) ) {
1
  <?php
2
  namespace WpAssetCleanUp;
3
 
4
+ use WpAssetCleanUp\OptimiseAssets\OptimizeCommon;
5
+
6
  /**
7
  * Class Plugin
8
  * @package WpAssetCleanUp
98
  * /wp-content/cache/asset-cleanup/.htaccess
99
  *
100
  * /wp-content/cache/asset-cleanup/css/
101
+ * /wp-content/cache/asset-cleanup/css/item/
102
  * /wp-content/cache/asset-cleanup/css/index.php
 
103
  * /wp-content/cache/asset-cleanup/css/logged-in/
104
  * /wp-content/cache/asset-cleanup/css/logged-in/index.php
105
+
106
+ * /wp-content/cache/asset-cleanup/js/
107
+ * /wp-content/cache/asset-cleanup/js/item/
108
+ * /wp-content/cache/asset-cleanup/js/index.php
109
+ * /wp-content/cache/asset-cleanup/js/logged-in/
110
+ * /wp-content/cache/asset-cleanup/js/logged-in/index.php
111
+ *
112
  */
113
  self::createCacheFoldersFiles(array('css','js'));
114
 
133
  */
134
  public static function createCacheFoldersFiles($assetTypes)
135
  {
136
+ foreach ($assetTypes as $assetType) {
137
+ if ($assetType === 'css') {
138
+ $cacheDir = WP_CONTENT_DIR . OptimiseAssets\OptimizeCss::getRelPathCssCacheDir();
139
+ } elseif ($assetType === 'js') {
140
+ $cacheDir = WP_CONTENT_DIR . OptimiseAssets\OptimizeJs::getRelPathJsCacheDir();
141
+ } else {
142
+ return;
143
+ }
144
 
145
  $emptyPhpFileContents = <<<TEXT
146
  <?php
166
  @mkdir( $cacheDir . 'logged-in', 0755 );
167
  }
168
 
169
+ if ( ! is_dir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir ) ) {
170
+ @mkdir( $cacheDir . OptimizeCommon::$optimizedSingleFilesDir, 0755 );
171
  }
172
 
173
  if ( ! is_file( $cacheDir . 'logged-in/index.php' ) ) {
classes/Preloads.php CHANGED
@@ -1,21 +1,23 @@
1
  <?php
2
  namespace WpAssetCleanUp;
3
 
 
 
4
  /**
5
  * Class Preloads
6
  * @package WpAssetCleanUp
7
  */
8
  class Preloads
9
  {
10
- /**
11
- *
12
- */
13
- const DEL_STYLES_PRELOADS = '<meta name="wpacu-generator" content="ASSET CLEANUP STYLES PRELOADS">';
14
 
15
- /**
16
- *
17
- */
18
- const DEL_SCRIPTS_PRELOADS = '<meta name="wpacu-generator" content="ASSET CLEANUP SCRIPTS PRELOADS">';
19
 
20
  /**
21
  * @var array
@@ -46,7 +48,7 @@ class Preloads
46
  {
47
  $this->preloads = $this->getPreloads();
48
 
49
- add_filter('wpfc_buffer_callback_filter', function ($buffer) {
50
  $buffer = str_replace('rel=\'preload\' data-from-rel=\'stylesheet\'', 'rel=\'preload\'', $buffer);
51
  return $buffer;
52
  });
@@ -248,10 +250,39 @@ class Preloads
248
  */
249
  public static function appendPreloadsForStylesToHead($htmlSource)
250
  {
251
- $strContainsFormat = preg_quote('data-wpacu-to-be-preloaded-basic=\'1\'', '/');
252
- $regExpPattern = $regExpPattern = '#<link[^>]'.$strContainsFormat.'[^>]*' . 'href=(\'|")(.*)(\'|")' . '.*(>)#Usmi';
 
 
 
 
 
 
 
253
 
254
- preg_match_all($regExpPattern, $htmlSource, $matchesSourcesFromLinkTags, PREG_SET_ORDER);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  foreach ($matchesSourcesFromLinkTags as $linkTagArray) {
257
  $linkHref = isset($linkTagArray[2]) ? $linkTagArray[2] : false;
@@ -275,7 +306,7 @@ class Preloads
275
  */
276
  public static function linkPreloadCssFormat($linkHref)
277
  {
278
- if (Misc::wpfcMinifyCssEnabledOnly()) {
279
  // [wpacu_lite]
280
  return '<link rel=\'preload\' data-from-rel=\'stylesheet\' as=\'style\' href=\'' . $linkHref . '\' data-wpacu-preload-css-basic=\'1\' />' . "\n";
281
  // [/wpacu_lite]
1
  <?php
2
  namespace WpAssetCleanUp;
3
 
4
+ use WpAssetCleanUp\OptimiseAssets\OptimizeCss;
5
+
6
  /**
7
  * Class Preloads
8
  * @package WpAssetCleanUp
9
  */
10
  class Preloads
11
  {
12
+ /**
13
+ *
14
+ */
15
+ const DEL_STYLES_PRELOADS = '<meta name="wpacu-generator" content="ASSET CLEANUP STYLES PRELOADS">';
16
 
17
+ /**
18
+ *
19
+ */
20
+ const DEL_SCRIPTS_PRELOADS = '<meta name="wpacu-generator" content="ASSET CLEANUP SCRIPTS PRELOADS">';
21
 
22
  /**
23
  * @var array
48
  {
49
  $this->preloads = $this->getPreloads();
50
 
51
+ add_filter('wpfc_buffer_callback_filter', static function ($buffer) {
52
  $buffer = str_replace('rel=\'preload\' data-from-rel=\'stylesheet\'', 'rel=\'preload\'', $buffer);
53
  return $buffer;
54
  });
250
  */
251
  public static function appendPreloadsForStylesToHead($htmlSource)
252
  {
253
+ $useDom = function_exists('libxml_use_internal_errors')
254
+ && function_exists('libxml_clear_errors')
255
+ && class_exists('DOMDocument');
256
+
257
+ // Highest accuracy
258
+ if ($useDom) {
259
+ $documentForCSS = new \DOMDocument();
260
+ $documentForCSS->loadHTML($htmlSource);
261
+ $linkTags = $documentForCSS->getElementsByTagName( 'link' );
262
 
263
+ $matchesSourcesFromLinkTags = array();
264
+
265
+ foreach ( $linkTags as $tagObject ) {
266
+ if (! $tagObject->hasAttributes()) {
267
+ continue;
268
+ }
269
+
270
+ $linkAttributes = array();
271
+
272
+ foreach ($tagObject->attributes as $attrObj) {
273
+ $linkAttributes[$attrObj->nodeName] = trim($attrObj->nodeValue);
274
+ }
275
+
276
+ if (isset($linkAttributes['data-wpacu-to-be-preloaded-basic'], $linkAttributes['href'])) {
277
+ $matchesSourcesFromLinkTags[][2] = $linkAttributes['href'];
278
+ }
279
+ }
280
+ } else { // RegExp Fallback
281
+ $strContainsFormat = preg_quote('data-wpacu-to-be-preloaded-basic=\'1\'', '/');
282
+ $regExpPattern = $regExpPattern = '#<link[^>]'.$strContainsFormat.'[^>]*' . 'href=(\'|")(.*)(\'|")' . '.*(>)#Usmi';
283
+
284
+ preg_match_all($regExpPattern, $htmlSource, $matchesSourcesFromLinkTags, PREG_SET_ORDER);
285
+ }
286
 
287
  foreach ($matchesSourcesFromLinkTags as $linkTagArray) {
288
  $linkHref = isset($linkTagArray[2]) ? $linkTagArray[2] : false;
306
  */
307
  public static function linkPreloadCssFormat($linkHref)
308
  {
309
+ if (OptimizeCss::wpfcMinifyCssEnabledOnly()) {
310
  // [wpacu_lite]
311
  return '<link rel=\'preload\' data-from-rel=\'stylesheet\' as=\'style\' href=\'' . $linkHref . '\' data-wpacu-preload-css-basic=\'1\' />' . "\n";
312
  // [/wpacu_lite]
classes/Settings.php CHANGED
@@ -94,11 +94,23 @@ class Settings
94
  // Clear Cached CSS/JS files after (x) days
95
  'clear_cached_files_after',
96
 
 
 
 
 
 
 
97
  // Google Fonts: Combine Into One Request
98
  'google_fonts_combine',
99
 
100
- // Google Fonts: "display" CSS property
101
- 'google_fonts_display'
 
 
 
 
 
 
102
  );
103
 
104
  /**
@@ -413,6 +425,10 @@ class Settings
413
  'jquery_migrate' => $disableJQueryMigrate,
414
  'comment_reply' => $disableCommentReply
415
  ));
 
 
 
 
416
  }
417
 
418
  Misc::addUpdateOption(WPACU_PLUGIN_ID . '_settings', json_encode($settings));
94
  // Clear Cached CSS/JS files after (x) days
95
  'clear_cached_files_after',
96
 
97
+ // Local Fonts: "font-display" CSS property (Pro feature)
98
+ 'local_fonts_display',
99
+
100
+ // Local Fonts: Preload Files
101
+ 'local_fonts_preload_files',
102
+
103
  // Google Fonts: Combine Into One Request
104
  'google_fonts_combine',
105
 
106
+ // Google Fonts: "font-display" CSS property
107
+ 'google_fonts_display',
108
+
109
+ // Google Fonts: preconnect hint
110
+ 'google_fonts_preconnect',
111
+
112
+ // Google Fonts: Preload Files
113
+ 'google_fonts_preload_files'
114
  );
115
 
116
  /**
425
  'jquery_migrate' => $disableJQueryMigrate,
426
  'comment_reply' => $disableCommentReply
427
  ));
428
+
429
+ // Some validation
430
+ $settings['local_fonts_preload_files'] = strip_tags($settings['local_fonts_preload_files']);
431
+ $settings['google_fonts_preload_files'] = strip_tags($settings['google_fonts_preload_files']);
432
  }
433
 
434
  Misc::addUpdateOption(WPACU_PLUGIN_ID . '_settings', json_encode($settings));
early-triggers.php CHANGED
@@ -98,6 +98,12 @@ if (! function_exists('assetCleanUpNoLoad')) {
98
  return true;
99
  }
100
 
 
 
 
 
 
 
101
  // WordPress Customise Mode
102
  if ((isset($_GET['customize_changeset_uuid'], $_GET['customize_theme']) && $_GET['customize_changeset_uuid'] && $_GET['customize_theme'])
103
  || (strpos($_SERVER['REQUEST_URI'],
98
  return true;
99
  }
100
 
101
+ // Custom CSS Pro: Editor
102
+ if ((isset($_GET['page']) && $_GET['page'] === 'ccp-editor')
103
+ || (isset($_GET['ccp-iframe']) && $_GET['ccp-iframe'] === 'true')) {
104
+ return true;
105
+ }
106
+
107
  // WordPress Customise Mode
108
  if ((isset($_GET['customize_changeset_uuid'], $_GET['customize_theme']) && $_GET['customize_changeset_uuid'] && $_GET['customize_theme'])
109
  || (strpos($_SERVER['REQUEST_URI'],
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: pagespeed, page speed, dequeue, minify css, performance
4
  Donate link: https://gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
5
  Requires at least: 4.4
6
  Tested up to: 5.2.2
7
- Stable tag: 1.3.3.6
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl.html
10
 
@@ -24,9 +24,14 @@ For instance, you might use a plugin that generates contact forms and it loads i
24
  The plugin works best in combination with a cache plugin such as [WP Rocket](https://gabelivan.com/visit/wp-rocket).
25
 
26
  = Main plugin's benefits include =
27
- * Decreases the number of HTTP requests loaded (important for faster page load) by unloading useless CSS/JS
28
- * Preload CSS/JS to instruct the browser to download the chosen assets as soon as possible
29
  * Minify/Combine remaining loaded CSS/JavaScript files
 
 
 
 
 
30
  * Reduces the HTML code of the actual page (that's even better if GZIP compression is enabled)
31
  * Makes source code easier to scan in case you're a developer and want to search for something
32
  * Remove possible conflicts between plugins/theme (e.g. 2 JavaScript files that are loading from different plugins and they interfere one with another)
@@ -43,9 +48,10 @@ The plugin works best in combination with a cache plugin such as [WP Rocket](htt
43
  * WordPress version meta tag (also good for security reasons)
44
  * All "generator" meta tags (also good for security reasons)
45
  * RSS Feed Link Tags (usually they are not needed if your website is not used for blogging purposes)
 
46
  * Valid HTML Comments (exceptions from stripping can be added and Internet Explorer conditional comments are preserved)
47
 
48
- Each that was just mentioned can be turned on/off depending on your needs. Instructions about each of them are given in the plugin's settings page.
49
 
50
  = Disable partially or completely XML-RPC protocol =
51
  This is an API service used by WordPress for 3rd party applications, such as mobile apps, communication between blogs and plugins such as Jetpack. If you use or are planning to use a remote system to post content to your website, you can keep this feature enabled (which it is by default). Many users do not use this function at all and if you’re one of them, you can disable it.
@@ -63,6 +69,7 @@ People that have tested the plugin are so far happy with it and I want to keep a
63
  * Defer loading CSS by appending it to the BODY to load it asynchronously (Render blocking CSS delays a web page from being visible in a timely manner)
64
  * Move JavaScript files from HEAD to BODY and vice-versa (CSS files moved to the BODY are automatically deferred)
65
  * Async & Defer attributes for JavaScript files
 
66
  * Get File Size of the Loaded CSS/JS
67
  * Premium support and updates within the Dashboard
68
 
@@ -157,6 +164,11 @@ With the recently released "Test Mode" feature, you can safely unload assets on
157
  4. Homepage CSS & JS Management (List sorted by location)
158
 
159
  == Changelog ==
 
 
 
 
 
160
  = 1.3.3.6 =
161
  * New Feature: Google Fonts Optimization: Combine multiple font requests into fewer requests; Option to add "font-display" CSS property (PageSpeed Insights Reference: "Ensure text remains visible during webfont load")
162
 
4
  Donate link: https://gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
5
  Requires at least: 4.4
6
  Tested up to: 5.2.2
7
+ Stable tag: 1.3.3.7
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl.html
10
 
24
  The plugin works best in combination with a cache plugin such as [WP Rocket](https://gabelivan.com/visit/wp-rocket).
25
 
26
  = Main plugin's benefits include =
27
+ * Decreases the number of HTTP requests loaded and eliminate render-blocking resources (important for faster page load) by unloading useless CSS/JS
28
+ * Preload CSS/JS, Local Fonts & Google Fonts files to instruct the browser to download the chosen assets as soon as possible
29
  * Minify/Combine remaining loaded CSS/JavaScript files
30
+ * Defer combined JavaScript files by applying "defer" attribute to the SCRIPT tags
31
+ * Combine all Google Font requests into fewer (usually one) requests, saving one round trip to the server for each additional font requested
32
+ * Apply "font-display" CSS property to all loaded Google Font requests
33
+ * Enable preconnect resource hint for fonts.gstatic.com in case you use Google Fonts; don't let the browser wait until it fetches the CSS for loading the font files before it begins DNS/TCP/TLS
34
+ * Easily site-wide removal for Emojis, Dashicons for guest users and Comment Reply styles & scripts if not needed
35
  * Reduces the HTML code of the actual page (that's even better if GZIP compression is enabled)
36
  * Makes source code easier to scan in case you're a developer and want to search for something
37
  * Remove possible conflicts between plugins/theme (e.g. 2 JavaScript files that are loading from different plugins and they interfere one with another)
48
  * WordPress version meta tag (also good for security reasons)
49
  * All "generator" meta tags (also good for security reasons)
50
  * RSS Feed Link Tags (usually they are not needed if your website is not used for blogging purposes)
51
+ * oEmbeds, if you do not need to embed videos (e.g. YouTube), tweets and audios
52
  * Valid HTML Comments (exceptions from stripping can be added and Internet Explorer conditional comments are preserved)
53
 
54
+ Each option can be turned on/off depending on your needs. Instructions about each of them are given in the plugin's settings page.
55
 
56
  = Disable partially or completely XML-RPC protocol =
57
  This is an API service used by WordPress for 3rd party applications, such as mobile apps, communication between blogs and plugins such as Jetpack. If you use or are planning to use a remote system to post content to your website, you can keep this feature enabled (which it is by default). Many users do not use this function at all and if you’re one of them, you can disable it.
69
  * Defer loading CSS by appending it to the BODY to load it asynchronously (Render blocking CSS delays a web page from being visible in a timely manner)
70
  * Move JavaScript files from HEAD to BODY and vice-versa (CSS files moved to the BODY are automatically deferred)
71
  * Async & Defer attributes for JavaScript files
72
+ * Apply "font-display:" CSS property to @font-face from existing local files to improve the PageSpeed score for "Ensure text remains visible during webfont load"
73
  * Get File Size of the Loaded CSS/JS
74
  * Premium support and updates within the Dashboard
75
 
164
  4. Homepage CSS & JS Management (List sorted by location)
165
 
166
  == Changelog ==
167
+ = 1.3.3.7 =
168
+ * New Feature: Google Fonts Optimization: Option to preload Google Font Files
169
+ * New Feature: Local Fonts Optimization: Option to preload Local Font Files
170
+ * Extra Compatibility with the latest version of SG Optimiser
171
+
172
  = 1.3.3.6 =
173
  * New Feature: Google Fonts Optimization: Combine multiple font requests into fewer requests; Option to add "font-display" CSS property (PageSpeed Insights Reference: "Ensure text remains visible during webfont load")
174
 
templates/_admin-page-settings-plugin-areas/_combine-loaded-files.php CHANGED
@@ -13,8 +13,8 @@ if (! defined('WPACU_USE_MODAL_BOX')) {
13
  $tabIdArea = 'wpacu-setting-combine-loaded-files';
14
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
15
 
16
- $isOptimizeCssEnabledByOtherParty = \WpAssetCleanUp\Misc::isOptimizeCssEnabledByOtherParty();
17
- $isOptimizeJsEnabledByOtherParty = \WpAssetCleanUp\Misc::isOptimizeJsEnabledByOtherParty();
18
  ?>
19
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
20
  <h2 class="wpacu-settings-area-title"><?php echo __('Combine loaded CSS &amp; JavaScript files into fewer files', 'wp-asset-clean-up'); ?></h2>
13
  $tabIdArea = 'wpacu-setting-combine-loaded-files';
14
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
15
 
16
+ $isOptimizeCssEnabledByOtherParty = \WpAssetCleanUp\OptimiseAssets\OptimizeCss::isOptimizeCssEnabledByOtherParty();
17
+ $isOptimizeJsEnabledByOtherParty = \WpAssetCleanUp\OptimiseAssets\OptimizeJs::isOptimizeJsEnabledByOtherParty();
18
  ?>
19
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
20
  <h2 class="wpacu-settings-area-title"><?php echo __('Combine loaded CSS &amp; JavaScript files into fewer files', 'wp-asset-clean-up'); ?></h2>
templates/_admin-page-settings-plugin-areas/{_google-fonts.php → _fonts-google.php} RENAMED
@@ -46,7 +46,7 @@ $ddOptions = array(
46
  </ul>
47
  <hr />
48
  <ul>
49
- <li><code>&lt;link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Tangerine:italic|Inconsolata:bold|Roboto+Mono"&gt;</code></li>
50
  </ul>
51
 
52
  <p><strong>Result:</strong> This simple feature saves one round trip to the server for each additional font requested (reducing the number of HTTP requests), and also protects against blocking on older browsers which only have 2 connections open per domain at a time.</p>
@@ -58,7 +58,7 @@ $ddOptions = array(
58
  </th>
59
  <td>
60
  <select name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[google_fonts_display]">
61
- <option value="">[none set]</option>
62
  <?php
63
  foreach ($ddOptions as $ddOptionValue => $ddOptionText) {
64
  $selectedOption = ($data['google_fonts_display'] === $ddOptionValue) ? 'selected="selected"' : '';
@@ -71,20 +71,66 @@ $ddOptions = array(
71
  <?php _e('This will result in printing of "font-display" CSS property within @font-face.', 'wp-asset-clean-up'); ?>
72
  <span style="color: #0073aa;" class="dashicons dashicons-info"></span> <a id="wpacu-google-fonts-display-info-target" href="#wpacu-google-fonts-display-info"><?php _e('Read more', 'wp-asset-clean-up'); ?></a>
73
 
 
 
 
 
 
74
  <hr />
75
 
76
  <p><?php echo __('Deciding the behavior for a web font as it is loading can be an important performance tuning technique. If applied, this option ensures text remains visible during webfont load.', 'wp-asset-clean-up'); ?> <?php _e('The <code>font-display</code> CSS property defines how font files are loaded and display by the browser.', 'wp-asset-clean-up'); ?></p>
77
 
78
  <strong>Read more about this:</strong>
79
- <ul style="margin-top: 5px;">
80
- <li>- <a target="_blank" href="https://css-tricks.com/hey-hey-font-display/">Hey hey `font-display`</a></li>
81
- <li>- <a target="_blank" href="https://css-tricks.com/font-display-masses/">`font-display` for the Masses</a></li>
82
- <li>- <a target="_blank" href="https://developers.google.com/web/updates/2016/02/font-display">Controlling Font Performance with font-display</a></li>
83
- <li>- <a target="_blank" href="https://font-display.glitch.me/">https://font-display.glitch.me/</a></li>
84
- <li>- <a target="_blank" href="https://vimeo.com/241111413">Video: Fontastic Web Performance</a></li>
85
- </ul>
86
  </td>
87
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  </table>
89
  </div>
90
 
46
  </ul>
47
  <hr />
48
  <ul>
49
+ <li><code>&lt;link rel="stylesheet" id="wpacu-combined-google-fonts-css" href="https://fonts.googleapis.com/css?family=Tangerine:italic|Inconsolata:bold|Roboto+Mono"&gt;</code></li>
50
  </ul>
51
 
52
  <p><strong>Result:</strong> This simple feature saves one round trip to the server for each additional font requested (reducing the number of HTTP requests), and also protects against blocking on older browsers which only have 2 connections open per domain at a time.</p>
58
  </th>
59
  <td>
60
  <select name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[google_fonts_display]">
61
+ <option value="">Do not apply (default)</option>
62
  <?php
63
  foreach ($ddOptions as $ddOptionValue => $ddOptionText) {
64
  $selectedOption = ($data['google_fonts_display'] === $ddOptionValue) ? 'selected="selected"' : '';
71
  <?php _e('This will result in printing of "font-display" CSS property within @font-face.', 'wp-asset-clean-up'); ?>
72
  <span style="color: #0073aa;" class="dashicons dashicons-info"></span> <a id="wpacu-google-fonts-display-info-target" href="#wpacu-google-fonts-display-info"><?php _e('Read more', 'wp-asset-clean-up'); ?></a>
73
 
74
+ <hr />
75
+ <ul>
76
+ <li><code>&lt;link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono<strong>&amp;display=swap</strong>"&gt;</code></li>
77
+ <li><code>&lt;link rel="stylesheet" id="wpacu-combined-google-fonts-css" href="https://fonts.googleapis.com/css?family=Tangerine:italic|Inconsolata:bold|Roboto+Mono<strong>&amp;display=swap</strong>"&gt;</code></li>
78
+ </ul>
79
  <hr />
80
 
81
  <p><?php echo __('Deciding the behavior for a web font as it is loading can be an important performance tuning technique. If applied, this option ensures text remains visible during webfont load.', 'wp-asset-clean-up'); ?> <?php _e('The <code>font-display</code> CSS property defines how font files are loaded and display by the browser.', 'wp-asset-clean-up'); ?></p>
82
 
83
  <strong>Read more about this:</strong>
84
+ <a target="_blank" href="https://css-tricks.com/hey-hey-font-display/">Hey hey `font-display`</a> &nbsp;|&nbsp;
85
+ <a target="_blank" href="https://css-tricks.com/font-display-masses/">`font-display` for the Masses</a> &nbsp;|&nbsp;
86
+ <a target="_blank" href="https://developers.google.com/web/updates/2016/02/font-display">Controlling Font Performance with font-display</a> &nbsp;|&nbsp;
87
+ <a target="_blank" href="https://font-display.glitch.me/">https://font-display.glitch.me/</a> &nbsp;|&nbsp;
88
+ <a target="_blank" href="https://vimeo.com/241111413">Video: Fontastic Web Performance</a>
 
 
89
  </td>
90
  </tr>
91
+ <tr valign="top">
92
+ <th scope="row" class="setting_title">
93
+ <?php _e('Preconnect?', 'wp-asset-clean-up'); ?>
94
+ <p class="wpacu_subtitle"><small><em><?php _e('Don\'t let the browser wait until it sees the CSS call font files before it begins DNS/TCP/TLS', 'wp-asset-clean-up'); ?></em></small></p>
95
+ </th>
96
+ <td>
97
+ <label class="wpacu_switch">
98
+ <input id="wpacu_google_fonts_preconnect"
99
+ type="checkbox"
100
+ <?php echo (($data['google_fonts_preconnect'] == 1) ? 'checked="checked"' : ''); ?>
101
+ name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[google_fonts_preconnect]"
102
+ value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
103
+ &nbsp;If you know your website requests resources from Google Fonts (fonts.gstatic.com), then adding the preconnect resource hint will instruct the browser to preconnect to Google Fonts while it is loading the CSS, saving load time.
104
+ <hr />
105
+ <p style="margin-bottom: 5px;">This will generate the following output within <code>&lt;HEAD&gt;</code> and <code>&lt;/HEAD&gt;</code>:</p>
106
+ <code>&lt;link href='https://fonts.gstatic.com' crossorigin rel='preconnect' /&gt;</code>
107
+ </td>
108
+ </tr>
109
+ <tr valign="top">
110
+ <th scope="row" class="setting_title">
111
+ <?php _e('Preload Google Font Files', 'wp-asset-clean-up'); ?>
112
+ <p class="wpacu_subtitle"><small><em><?php _e('One per line', 'wp-asset-clean-up'); ?>, only external Google Font Files are allowed</em></small></p>
113
+ </th>
114
+ <td>
115
+ <div style="margin: 0 0 6px;"><?php _e('If you wish to preload any of the Google Font Files (e.g. ending in .woff2), you can add their URL here (one per line)', 'wp-asset-clean-up'); ?>:</div>
116
+ <textarea style="width:100%;"
117
+ rows="5"
118
+ name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[google_fonts_preload_files]"><?php echo $data['google_fonts_preload_files']; ?></textarea>
119
+ <hr />
120
+ <p>To get the URL to the actual font file, you have to open the Google Fonts Link (e.g. https://fonts.googleapis.com/css?family=Open+Sans:bold), locate the actual @font-face (or all of them, depends on the circumstances), and then copy the value of the <code>url</code> within the 'src:' property.</p>
121
+ <strong>Examples:</strong>
122
+ <div style="margin-top: 5px;">
123
+ <div><code>https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2</code></div>
124
+ <div><code>https://fonts.gstatic.com/s/robotomono/v7/L0x5DF4xlVMF-BfR8bXMIjhFq3-cXbKDO1w.woff2</code></div>
125
+ </div>
126
+ <hr />
127
+ <strong>Generated Output</strong>, printed within <code>&lt;HEAD&gt;</code> and <code>&lt;/HEAD&gt;</code>
128
+ <div style="margin-top: 5px;">
129
+ <div style="margin-bottom: 8px;"><code>&lt;link rel="preload" as="font" href="https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2" data-wpacu-preload-font="1" crossorigin&gt;</code></div>
130
+ <div style="margin-bottom: 8px;"><code>&lt;link rel="preload" as="font" href="https://fonts.gstatic.com/l/font?kit=HTxtL2QoJDuBh5RMHcDgpoTZGQ&skey=9d22fae1754942f6&v=v9" data-wpacu-preload-font="1" crossorigin&gt;</code></div>
131
+ </div>
132
+ </td>
133
+ </tr>
134
  </table>
135
  </div>
136
 
templates/_admin-page-settings-plugin-areas/_fonts-local.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * No direct access to this file
4
+ */
5
+ if (! isset($data)) {
6
+ exit;
7
+ }
8
+
9
+ $tabIdArea = 'wpacu-setting-local-fonts';
10
+ $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
11
+
12
+ $ddOptions = array(
13
+ 'swap' => 'swap (most used)',
14
+ 'auto' => 'auto',
15
+ 'block' => 'block',
16
+ 'fallback' => 'fallback',
17
+ 'optional' => 'optional'
18
+ );
19
+
20
+ // [wpacu_lite]
21
+ $availableForPro = '<a class="go-pro-link-no-style" target="_blank" href="' . WPACU_PLUGIN_GO_PRO_URL . '?utm_source=plugin_usage_settings&utm_medium=assets_list_layout"><span class="wpacu-tooltip" style="width: 186px;">'.__('This is a feature available in the Pro version! Unlock it!', 'wp-asset-clean-up').'</span> <img style="opacity: 0.6;" width="20" height="20" src="'.WPACU_PLUGIN_URL.'/assets/icons/icon-lock.svg" valign="top" alt="" /></a>';
22
+ // [/wpacu_lite]
23
+ ?>
24
+ <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
25
+ <h2 class="wpacu-settings-area-title"><?php _e('Local Fonts Optimization', 'wp-asset-clean-up'); ?></h2>
26
+ <table class="wpacu-form-table">
27
+ <tr valign="top">
28
+ <th scope="row" class="setting_title">
29
+ <?php echo sprintf(__('Apply %s CSS property value', 'wp-asset-clean-up'), '<span style="background: #f5f5f5; padding: 4px;">font-display:</span>'); ?>
30
+ </th>
31
+ <td>
32
+ <?php echo $availableForPro; ?>&nbsp;
33
+ &nbsp;<select
34
+ <?php /* [wpacu_lite] */ ?>
35
+ style="opacity: 0.5;"
36
+ <?php /* [/wpacu_lite] */ ?>
37
+ name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[local_fonts_display]">
38
+ <option value="">Do not apply (default)</option>
39
+ <?php
40
+ foreach ($ddOptions as $ddOptionValue => $ddOptionText) {
41
+ $selectedOption = ($data['local_fonts_display'] === $ddOptionValue) ? 'selected="selected"' : '';
42
+ echo '<option '.$selectedOption.' value="'.$ddOptionValue.'">'.$ddOptionText.'</option>'."\n";
43
+ }
44
+ ?>
45
+ </select>
46
+ &nbsp;
47
+ <?php _e('This feature applies site-wide "font-display:" property (if none set already in the file) within @font-face in every loaded CSS file.', 'wp-asset-clean-up'); ?> &nbsp; <span style="color: #0073aa;" class="dashicons dashicons-info"></span>&nbsp;<a id="wpacu-local-fonts-display-info-target" href="#wpacu-local-fonts-display-info"><?php _e('Read more', 'wp-asset-clean-up'); ?></a>
48
+ <p><?php echo sprintf(__('The new generated CSS files will be loaded from <code>%s</code>, as the existing files from plugins/themes will not be altered in any way.', 'wp-asset-clean-up'), \WpAssetCleanUp\OptimiseAssets\OptimizeCommon::getRelPathPluginCacheDir()); ?></p>
49
+
50
+ <hr />
51
+
52
+ <p><?php echo __('Deciding the behavior for a web font as it is loading can be an important performance tuning technique. If applied, this option ensures text remains visible during webfont load.', 'wp-asset-clean-up'); ?> <?php _e('The <code>font-display</code> CSS property defines how font files are loaded and display by the browser.', 'wp-asset-clean-up'); ?></p>
53
+
54
+ <strong>Read more about this:</strong>
55
+ <a target="_blank" href="https://css-tricks.com/hey-hey-font-display/">Hey hey `font-display`</a> &nbsp;|&nbsp;
56
+ <a target="_blank" href="https://css-tricks.com/font-display-masses/">`font-display` for the Masses</a> &nbsp;|&nbsp;
57
+ <a target="_blank" href="https://developers.google.com/web/updates/2016/02/font-display">Controlling Font Performance with font-display</a> &nbsp;|&nbsp;
58
+ <a target="_blank" href="https://font-display.glitch.me/">https://font-display.glitch.me/</a> &nbsp;|&nbsp;
59
+ <a target="_blank" href="https://vimeo.com/241111413">Video: Fontastic Web Performance</a>
60
+ </td>
61
+ </tr>
62
+ <tr valign="top">
63
+ <th scope="row" class="setting_title">
64
+ <?php _e('Preload Local Font Files', 'wp-asset-clean-up'); ?>
65
+ <p class="wpacu_subtitle"><small><em><?php _e('One per line', 'wp-asset-clean-up'); ?></em></small></p>
66
+ </th>
67
+ <td>
68
+ <div style="margin: 0 0 6px;"><?php _e('If you wish to preload any of the Local Font Files (ending in .woff, .woff2, .ttf etc.), you can add their URI here like in the examples below (one per line)', 'wp-asset-clean-up'); ?>:</div>
69
+ <textarea style="width:100%;"
70
+ rows="5"
71
+ name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[local_fonts_preload_files]"><?php echo $data['local_fonts_preload_files']; ?></textarea>
72
+ <hr />
73
+ <strong>Examples:</strong>
74
+ <div style="margin-top: 5px;">
75
+ <div><code>/wp-content/themes/your-theme-dir/fonts/lato.woff</code></div>
76
+ <div><code>/wp-content/plugins/plugin-title-here/fonts/fontawesome-webfont.ttf?v=4.5.0</code></div>
77
+ </div>
78
+ <hr />
79
+ <strong>Generated Output</strong>, printed within <code>&lt;HEAD&gt;</code> and <code>&lt;/HEAD&gt;</code>
80
+ <div style="margin-top: 5px;">
81
+ <div style="margin-bottom: 8px;"><code>&lt;link rel="preload" as="font" href="/wp-content/themes/your-theme-dir/fonts/lato.woff" data-wpacu-preload-font="1" crossorigin&gt;</code></div>
82
+ <div style="margin-bottom: 8px;"><code>&lt;link rel="preload" as="font" href="/wp-content/plugins/plugin-title-here/fonts/fontawesome-webfont.ttf?v=4.5.0" data-wpacu-preload-font="1" crossorigin&gt;</code></div>
83
+ </div>
84
+ </td>
85
+ </tr>
86
+ </table>
87
+ </div>
88
+
89
+ <div id="wpacu-local-fonts-display-info" class="wpacu-modal" style="padding-top: 60px;">
90
+ <div class="wpacu-modal-content" style="max-width: 800px;">
91
+ <span class="wpacu-close">&times;</span>
92
+ <h3 style="margin-top: 2px; margin-bottom: 4px;">font-display: <span style="background: #f2faf2;">swap</span></h3>
93
+ <p style="margin-top: 0; margin-bottom: 22px;">The text is shown immediately (without any block period, no invisible text) in the fallback font until the custom font loads, then it's swapped with the custom font. You get a <strong>FOUT</strong> (<em>flash of unstyled text</em>).</p>
94
+
95
+ <h3 style="margin-bottom: 4px;">font-display: <span style="background: #f2faf2;">block</span></h3>
96
+ <p style="margin-top: 0; margin-bottom: 22px;">The text blocks (is invisible) for a short period. Then, if the custom font hasn't been downloaded yet, the browser swaps (renders the text in the fallback font), for however long it takes the custom font to be downloaded, and then re-renders the text in the custom font. You get a <strong>FOIT</strong> (<em>flash of invisible text</em>).</p>
97
+
98
+ <h3 style="margin-bottom: 4px;">font-display: <span style="background: #f2faf2;">fallback</span></h3>
99
+ <p style="margin-top: 0; margin-bottom: 22px;">This is somewhere in between block and swap. The text is invisible for a short period of time (100ms). Then if the custom font hasn't downloaded, the text is shown in a fallback font (for about 3s), then swapped after the custom font loads.</p>
100
+
101
+ <h3 style="margin-bottom: 4px;">font-display: <span style="background: #f2faf2;">optional</span></h3>
102
+ <p style="margin-top: 0; margin-bottom: 22px;">This behaves just like fallback, only the browser can decide to not use the custom font at all, based on the user's connection speed (if you're on a slow 3G or less, it will take forever to download the custom font and then swapping to it will be too late and extremely annoying)</p>
103
+
104
+ <h3 style="margin-bottom: 4px;">font-display: <span style="background: #f2faf2;">auto</span></h3>
105
+ <p style="margin-top: 0; margin-bottom: 0;">The default. Typical browser font loading behavior will take place. This behavior may be FOIT, or FOIT with a relatively long invisibility period. This may change as browser vendors decide on better default behaviors.</p>
106
+
107
+ <h3 style="margin-bottom: 4px;">Example of a @font-face CSS output</h3>
108
+ <code>@font-face{font-family:'proxima-nova-1';src:url("/wp-content/themes/my-theme-dir/fonts/proxima-nova-light.woff2") format("woff2"),url("/wp-content/themes/my-theme-dir/fonts/proxima-nova-light.woff") format("woff");font-weight:300;font-style:normal;font-stretch:normal;<span style="background: #f2faf2;">font-display:swap</span>}</code>
109
+ </div>
110
+ </div>
templates/_admin-page-settings-plugin-areas/_minify-loaded-files.php CHANGED
@@ -9,8 +9,8 @@ if (! isset($data)) {
9
  $tabIdArea = 'wpacu-setting-minify-loaded-files';
10
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
11
 
12
- $isOptimizeCssEnabledByOtherParty = \WpAssetCleanUp\Misc::isOptimizeCssEnabledByOtherParty();
13
- $isOptimizeJsEnabledByOtherParty = \WpAssetCleanUp\Misc::isOptimizeJsEnabledByOtherParty();
14
  ?>
15
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
16
  <h2 class="wpacu-settings-area-title"><?php _e('Minify loaded CSS &amp; JavaScript files to reduce total page size', 'wp-asset-clean-up'); ?></h2>
9
  $tabIdArea = 'wpacu-setting-minify-loaded-files';
10
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
11
 
12
+ $isOptimizeCssEnabledByOtherParty = \WpAssetCleanUp\OptimiseAssets\OptimizeCss::isOptimizeCssEnabledByOtherParty();
13
+ $isOptimizeJsEnabledByOtherParty = \WpAssetCleanUp\OptimiseAssets\OptimizeJs::isOptimizeJsEnabledByOtherParty();
14
  ?>
15
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
16
  <h2 class="wpacu-settings-area-title"><?php _e('Minify loaded CSS &amp; JavaScript files to reduce total page size', 'wp-asset-clean-up'); ?></h2>
templates/_admin-page-settings-plugin-areas/_plugin-usage-settings.php CHANGED
@@ -8,10 +8,6 @@ if (! isset($data)) {
8
 
9
  $tabIdArea = 'wpacu-setting-plugin-usage-settings';
10
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
11
-
12
- // [wpacu_lite]
13
- $availableForPro = '<a class="go-pro-link-no-style" target="_blank" href="' . WPACU_PLUGIN_GO_PRO_URL . '?utm_source=plugin_usage_settings&utm_medium=assets_list_layout"><span class="wpacu-tooltip" style="width: 154px;">'.__('Click here to unlock it', 'wp-asset-clean-up').'!</span> <img style="opacity: 0.6;" width="20" height="20" src="'.WPACU_PLUGIN_URL.'/assets/icons/icon-lock.svg" valign="top" alt="" /></a>';
14
- // [/wpacu_lite]
15
  ?>
16
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
17
  <h2 class="wpacu-settings-area-title"><?php _e('General &amp; Files Management', 'wp-asset-clean-up'); ?></h2>
8
 
9
  $tabIdArea = 'wpacu-setting-plugin-usage-settings';
10
  $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-cell;"' : '';
 
 
 
 
11
  ?>
12
  <div id="<?php echo $tabIdArea; ?>" class="wpacu-settings-tab-content" <?php echo $styleTabContent; ?>>
13
  <h2 class="wpacu-settings-area-title"><?php _e('General &amp; Files Management', 'wp-asset-clean-up'); ?></h2>
templates/_admin-page-settings-plugin-areas/_strip-the-fat.php CHANGED
@@ -36,5 +36,5 @@ $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-ce
36
  <?php echo (($data['wiki_read'] == 1) ? 'checked="checked"' : ''); ?>
37
  name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[wiki_read]"
38
  value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
39
- <?php echo sprintf(__('I understand how the plugin works and I will make sure to make proper tests (via "%s" if necessary) after the changes I\'m making.', 'wp-asset-clean-up'), __('Test Mode', 'wp-asset-clean-up')); ?> <?php _e('I\'m aware that unloading the wrong CSS/JS files can break the layout and front-end functionality of the pages I\'m optimising.', 'wp-asset-clean-up'); ?>
40
  </div>
36
  <?php echo (($data['wiki_read'] == 1) ? 'checked="checked"' : ''); ?>
37
  name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[wiki_read]"
38
  value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
39
+ &nbsp;<?php echo sprintf(__('I understand how the plugin works and I will make sure to make proper tests (via "%s" if necessary) after the changes I\'m making.', 'wp-asset-clean-up'), __('Test Mode', 'wp-asset-clean-up')); ?> <?php _e('I\'m aware that unloading the wrong CSS/JS files can break the layout and front-end functionality of the pages I\'m optimising.', 'wp-asset-clean-up'); ?>
40
  </div>
templates/admin-page-settings-plugin.php CHANGED
@@ -30,6 +30,7 @@ if ($showSettingsType === 'tabs') {
30
  'wpacu-setting-combine-loaded-files' => __( 'Combine CSS &amp; JS Files', 'wp-asset-clean-up' ),
31
  'wpacu-setting-common-files-unload' => __( 'Site-Wide Common Unloads', 'wp-asset-clean-up' ),
32
  'wpacu-setting-html-source-cleanup' => __( 'HTML Source CleanUp', 'wp-asset-clean-up' ),
 
33
  'wpacu-setting-google-fonts' => __( 'Google Fonts', 'wp-asset-clean-up' ),
34
  'wpacu-setting-disable-xml-rpc' => __( 'Disable XML-RPC', 'wp-asset-clean-up' ),
35
  );
@@ -75,7 +76,8 @@ if ($showSettingsType === 'tabs') {
75
  include_once '_admin-page-settings-plugin-areas/_combine-loaded-files.php';
76
  include_once '_admin-page-settings-plugin-areas/_common-files-unload.php';
77
  include_once '_admin-page-settings-plugin-areas/_html-source-cleanup.php';
78
- include_once '_admin-page-settings-plugin-areas/_google-fonts.php';
 
79
  include_once '_admin-page-settings-plugin-areas/_disable-xml-rpc-protocol.php';
80
  ?>
81
 
30
  'wpacu-setting-combine-loaded-files' => __( 'Combine CSS &amp; JS Files', 'wp-asset-clean-up' ),
31
  'wpacu-setting-common-files-unload' => __( 'Site-Wide Common Unloads', 'wp-asset-clean-up' ),
32
  'wpacu-setting-html-source-cleanup' => __( 'HTML Source CleanUp', 'wp-asset-clean-up' ),
33
+ 'wpacu-setting-local-fonts' => __( 'Local Fonts', 'wp-asset-clean-up' ),
34
  'wpacu-setting-google-fonts' => __( 'Google Fonts', 'wp-asset-clean-up' ),
35
  'wpacu-setting-disable-xml-rpc' => __( 'Disable XML-RPC', 'wp-asset-clean-up' ),
36
  );
76
  include_once '_admin-page-settings-plugin-areas/_combine-loaded-files.php';
77
  include_once '_admin-page-settings-plugin-areas/_common-files-unload.php';
78
  include_once '_admin-page-settings-plugin-areas/_html-source-cleanup.php';
79
+ include_once '_admin-page-settings-plugin-areas/_fonts-local.php';
80
+ include_once '_admin-page-settings-plugin-areas/_fonts-google.php';
81
  include_once '_admin-page-settings-plugin-areas/_disable-xml-rpc-protocol.php';
82
  ?>
83
 
templates/meta-box-loaded-assets/_asset-style-single-row.php CHANGED
@@ -54,12 +54,20 @@ sort($childHandles);
54
  $ver = (isset($data['row']['obj']->ver) && trim($data['row']['obj']->ver)) ? $data['row']['obj']->ver : $data['wp_version'];
55
  $data['row']['obj']->preload_status = 'not_preloaded'; // default
56
 
 
 
57
  if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row']['obj']->src && $data['row']['obj']->srcHref) {
 
 
 
 
58
  // Formatting for Google Fonts
59
- $data['row']['obj']->src = urldecode(\WpAssetCleanUp\OptimiseAssets\GoogleFonts::alterGoogleFontLink($data['row']['obj']->src));
60
- $data['row']['obj']->src = str_replace(' ', '+', $data['row']['obj']->src);
 
 
61
 
62
- $data['row']['obj']->srcHref = urldecode(\WpAssetCleanUp\OptimiseAssets\GoogleFonts::alterGoogleFontLink($data['row']['obj']->srcHref));
63
  $data['row']['obj']->srcHref = str_replace(' ', '+', $data['row']['obj']->srcHref);
64
 
65
  $relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
@@ -72,7 +80,12 @@ sort($childHandles);
72
  $toUnderline = 'display='.$data['plugin_settings']['google_fonts_display'];
73
  $relSrc = str_replace($toUnderline, '<u style="background: #f2faf2;">'.$toUnderline.'</u>', $relSrc);
74
 
75
- $appendAfterSrcHref = (strpos($data['row']['obj']->srcHref, '?') === false) ? '?' : '&';
 
 
 
 
 
76
 
77
  $isCssPreload = (isset($data['preloads']['styles'][$data['row']['obj']->handle]) && $data['preloads']['styles'][$data['row']['obj']->handle])
78
  ? $data['preloads']['styles'][$data['row']['obj']->handle]
@@ -83,7 +96,7 @@ sort($childHandles);
83
  }
84
  ?>
85
  <p>
86
- <?php _e('Source:', 'wp-asset-clean-up'); ?> <a target="_blank" style="color: green;" href="<?php echo $data['row']['obj']->srcHref . $appendAfterSrcHref . 'ver='.$ver; ?>"><?php echo $relSrc; ?></a>
87
  &nbsp;&#10230;&nbsp;
88
  Preload (if kept loaded)?
89
  &nbsp;<select style="display: inline-block;"
@@ -126,8 +139,16 @@ sort($childHandles);
126
 
127
  $extraInfo[] = __('Version:', 'wp-asset-clean-up').' '.$ver;
128
 
129
- if (isset($data['row']['obj']->position) && $data['row']['obj']->position !== '') {
130
  $extraInfo[] = __('Position:', 'wp-asset-clean-up') . ' ' . (( $data['row']['obj']->position === 'head') ? 'HEAD' : 'BODY') . '<a class="go-pro-link-no-style" href="' . WPACU_PLUGIN_GO_PRO_URL . '?utm_source=manage_asset&utm_medium=change_css_position"><span class="wpacu-tooltip" style="width: 300px; margin-left: -146px;">Upgrade to Pro and change the location<br />of the CSS file (e.g. to BODY to reduce render-blocking or to HEAD for very early triggering)</span><img width="20" height="20" src="' . WPACU_PLUGIN_URL . '/assets/icons/icon-lock.svg" valign="top" alt="" /> Change it?</a>';
 
 
 
 
 
 
 
 
131
  }
132
 
133
  // [wpacu_lite]
54
  $ver = (isset($data['row']['obj']->ver) && trim($data['row']['obj']->ver)) ? $data['row']['obj']->ver : $data['wp_version'];
55
  $data['row']['obj']->preload_status = 'not_preloaded'; // default
56
 
57
+ $styleHandleHasSrc = false;
58
+
59
  if (isset($data['row']['obj']->src, $data['row']['obj']->srcHref) && $data['row']['obj']->src && $data['row']['obj']->srcHref) {
60
+ $styleHandleHasSrc = true;
61
+
62
+ $isGoogleFontLink = stripos($data['row']['obj']->srcHref, 'fonts.googleapis.com') === false;
63
+
64
  // Formatting for Google Fonts
65
+ if ($isGoogleFontLink) {
66
+ $data['row']['obj']->src = urldecode(\WpAssetCleanUp\OptimiseAssets\FontsGoogle::alterGoogleFontLink($data['row']['obj']->src));
67
+ $data['row']['obj']->srcHref = urldecode(\WpAssetCleanUp\OptimiseAssets\FontsGoogle::alterGoogleFontLink($data['row']['obj']->srcHref));
68
+ }
69
 
70
+ $data['row']['obj']->src = str_replace(' ', '+', $data['row']['obj']->src);
71
  $data['row']['obj']->srcHref = str_replace(' ', '+', $data['row']['obj']->srcHref);
72
 
73
  $relSrc = str_replace(site_url(), '', $data['row']['obj']->src);
80
  $toUnderline = 'display='.$data['plugin_settings']['google_fonts_display'];
81
  $relSrc = str_replace($toUnderline, '<u style="background: #f2faf2;">'.$toUnderline.'</u>', $relSrc);
82
 
83
+ $appendAfterSrcHref = '';
84
+
85
+ if ($isGoogleFontLink) {
86
+ $appendAfterSrcHref .= (strpos($data['row']['obj']->srcHref, '?') === false) ? '?' : '&';
87
+ $appendAfterSrcHref .= 'ver=' . $ver;
88
+ }
89
 
90
  $isCssPreload = (isset($data['preloads']['styles'][$data['row']['obj']->handle]) && $data['preloads']['styles'][$data['row']['obj']->handle])
91
  ? $data['preloads']['styles'][$data['row']['obj']->handle]
96
  }
97
  ?>
98
  <p>
99
+ <?php _e('Source:', 'wp-asset-clean-up'); ?> <a target="_blank" style="color: green;" href="<?php echo $data['row']['obj']->srcHref . $appendAfterSrcHref; ?>"><?php echo $relSrc; ?></a>
100
  &nbsp;&#10230;&nbsp;
101
  Preload (if kept loaded)?
102
  &nbsp;<select style="display: inline-block;"
139
 
140
  $extraInfo[] = __('Version:', 'wp-asset-clean-up').' '.$ver;
141
 
142
+ if ($styleHandleHasSrc && isset($data['row']['obj']->position) && $data['row']['obj']->position !== '') {
143
  $extraInfo[] = __('Position:', 'wp-asset-clean-up') . ' ' . (( $data['row']['obj']->position === 'head') ? 'HEAD' : 'BODY') . '<a class="go-pro-link-no-style" href="' . WPACU_PLUGIN_GO_PRO_URL . '?utm_source=manage_asset&utm_medium=change_css_position"><span class="wpacu-tooltip" style="width: 300px; margin-left: -146px;">Upgrade to Pro and change the location<br />of the CSS file (e.g. to BODY to reduce render-blocking or to HEAD for very early triggering)</span><img width="20" height="20" src="' . WPACU_PLUGIN_URL . '/assets/icons/icon-lock.svg" valign="top" alt="" /> Change it?</a>';
144
+ } elseif (! $styleHandleHasSrc) {
145
+ if ($data['row']['obj']->handle === 'woocommerce-inline') {
146
+ $noSrcLoadedIn = __('Inline CSS Loaded In:', 'wp-asset-clean-up');
147
+ } else {
148
+ $noSrcLoadedIn = __('This handle is not for external stylesheet (most likely inline CSS) and it is loaded in:', 'wp-asset-clean-up');
149
+ }
150
+
151
+ $extraInfo[] = $noSrcLoadedIn . ' '. (($data['row']['obj']->position === 'head') ? 'HEAD' : 'BODY');
152
  }
153
 
154
  // [wpacu_lite]
wpacu-load.php CHANGED
@@ -62,7 +62,7 @@ new \WpAssetCleanUp\AdminBar();
62
  new \WpAssetCleanUp\Info();
63
 
64
  // Common functions for both CSS & JS combinations
65
- // Clear cache functionality
66
  $wpacuOptimizeCommon = new \WpAssetCleanUp\OptimiseAssets\OptimizeCommon();
67
  $wpacuOptimizeCommon->init();
68
 
@@ -76,13 +76,9 @@ if (\WpAssetCleanUp\Misc::triggerFrontendOptimization()) {
76
  $wpacuOptimizeCss = new \WpAssetCleanUp\OptimiseAssets\OptimizeCss();
77
  $wpacuOptimizeCss->init();
78
 
79
- $wpacuMinifyCss = new \WpAssetCleanUp\OptimiseAssets\MinifyCss();
80
- $wpacuMinifyCss->init();
81
-
82
  // Combine/Minify JS Files Setup
83
  $wpacuOptimizeJs = new \WpAssetCleanUp\OptimiseAssets\OptimizeJs();
84
  $wpacuOptimizeJs->init();
85
- new \WpAssetCleanUp\OptimiseAssets\MinifyJs();
86
  }
87
 
88
  if (is_admin()) {
@@ -106,6 +102,9 @@ if (is_admin()) {
106
  $wpacuCleanUp = new \WpAssetCleanUp\CleanUp();
107
  $wpacuCleanUp->init();
108
 
109
- $wpacuGoogleFonts = new \WpAssetCleanUp\OptimiseAssets\GoogleFonts();
110
- $wpacuGoogleFonts->init();
 
 
 
111
  }
62
  new \WpAssetCleanUp\Info();
63
 
64
  // Common functions for both CSS & JS combinations
65
+ // Clear CSS/JS caching functionality
66
  $wpacuOptimizeCommon = new \WpAssetCleanUp\OptimiseAssets\OptimizeCommon();
67
  $wpacuOptimizeCommon->init();
68
 
76
  $wpacuOptimizeCss = new \WpAssetCleanUp\OptimiseAssets\OptimizeCss();
77
  $wpacuOptimizeCss->init();
78
 
 
 
 
79
  // Combine/Minify JS Files Setup
80
  $wpacuOptimizeJs = new \WpAssetCleanUp\OptimiseAssets\OptimizeJs();
81
  $wpacuOptimizeJs->init();
 
82
  }
83
 
84
  if (is_admin()) {
102
  $wpacuCleanUp = new \WpAssetCleanUp\CleanUp();
103
  $wpacuCleanUp->init();
104
 
105
+ $wpacuFontsLocal = new \WpAssetCleanUp\OptimiseAssets\FontsLocal();
106
+ $wpacuFontsLocal->init();
107
+
108
+ $wpacuFontsGoogle = new \WpAssetCleanUp\OptimiseAssets\FontsGoogle();
109
+ $wpacuFontsGoogle->init();
110
  }
wpacu.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  * Plugin Name: Asset CleanUp: Page Speed Booster
4
  * Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
5
- * Version: 1.3.3.6
6
  * Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
7
  * Author: Gabriel Livan
8
  * Author URI: http://gabelivan.com/
@@ -12,7 +12,7 @@
12
 
13
  // Is the Pro version triggered before the Lite one and are both plugins active?
14
  if (! defined('WPACU_PLUGIN_VERSION')) {
15
- define('WPACU_PLUGIN_VERSION', '1.3.3.6');
16
  }
17
 
18
  // Exit if accessed directly
2
  /*
3
  * Plugin Name: Asset CleanUp: Page Speed Booster
4
  * Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
5
+ * Version: 1.3.3.7
6
  * Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
7
  * Author: Gabriel Livan
8
  * Author URI: http://gabelivan.com/
12
 
13
  // Is the Pro version triggered before the Lite one and are both plugins active?
14
  if (! defined('WPACU_PLUGIN_VERSION')) {
15
+ define('WPACU_PLUGIN_VERSION', '1.3.3.7');
16
  }
17
 
18
  // Exit if accessed directly