PluginProbe
WP EXtra – One Click Optimize / trunk
WP EXtra – One Click Optimize vtrunk
8.7.1 8.6.8 8.7.0 trunk 5.9 8.0 8.5.0 8.5.4 8.5.5 8.6.0 8.6.1 8.6.2 8.6.3 8.6.5
wp-extra / src / Modules / Common / TOC / Assets.php

Assets.php in WP EXtra – One Click Optimize trunk, at src/Modules/Common/TOC/Assets.php

378 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * TOC Assets Module
4 *
5 * Handles script & style registration, enqueueing, localization, and dynamic inline CSS generation.
6 *
7 * @package WPEXtra\Modules\Common\TOC
8 */
9
10 namespace WPEXtra\Modules\Common\TOC;
11
12 use WPEXtra\Helper;
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 class Assets {
19
20 /**
21 * Initialize asset hooks.
22 */
23 public static function init() {
24 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'register_assets' ), 5 );
25 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_frontend_assets' ), 10 );
26 add_action( 'admin_head', array( __CLASS__, 'add_editor_button' ) );
27 }
28
29 /**
30 * Register core scripts and styles.
31 */
32 public static function register_assets() {
33 $ver = defined( 'WPEX_VERSION' ) ? WPEX_VERSION : '1.0.0';
34 $assets_url = defined( 'WPEX_URL' ) ? WPEX_URL . 'assets/' : plugins_url( 'assets/', dirname( dirname( __DIR__ ) ) );
35
36 // Register Styles
37 wp_register_style( 'wptoc', $assets_url . 'css/toc.min.css', array(), $ver );
38 wp_register_style( 'wptoc-sticky', $assets_url . 'css/toc-sticky.min.css', array(), $ver );
39 wp_register_style( 'wptoc-counter-decimal', $assets_url . 'css/toc-counter-decimal.min.css', array( 'wptoc' ), $ver );
40 wp_register_style( 'wptoc-counter-decimal-circle', $assets_url . 'css/toc-counter-decimal-circle.min.css', array( 'wptoc' ), $ver );
41 wp_register_style( 'wptoc-counter-disc', $assets_url . 'css/toc-counter-disc.min.css', array( 'wptoc' ), $ver );
42 wp_register_style( 'wptoc-counter-checkmark', $assets_url . 'css/toc-counter-checkmark.min.css', array( 'wptoc' ), $ver );
43 wp_register_style( 'wptoc-counter-none', $assets_url . 'css/toc-counter-none.min.css', array( 'wptoc' ), $ver );
44
45 // Register Scripts
46 wp_register_script( 'wptoc-sticky', $assets_url . 'js/toc-sticky.min.js', array( 'jquery' ), $ver, true );
47 wp_register_script( 'wptoc-js', $assets_url . 'js/toc.min.js', array( 'jquery' ), $ver, true );
48 wp_register_script( 'wptoc-scroll-scriptjs', $assets_url . 'js/toc-smooth-scroll.min.js', array( 'jquery' ), $ver, true );
49 wp_register_script( 'wptoc-anchor-fix', $assets_url . 'js/toc-anchor-fix.min.js', array(), $ver, true );
50
51 self::localize_scripts();
52 }
53
54 /**
55 * Localize variables for frontend scripts.
56 */
57 public static function localize_scripts() {
58 $scroll_offset = (int) Helper::get_option( 'smooth_scroll_offset', 30 );
59 if ( wp_is_mobile() ) {
60 $mobile_offset = Helper::get_option( 'mobile_smooth_scroll_offset', 0 );
61 if ( ! empty( $mobile_offset ) ) {
62 $scroll_offset = (int) $mobile_offset;
63 }
64 }
65
66 wp_localize_script(
67 'wptoc-js',
68 'wpTOC',
69 array(
70 'smooth_scroll' => (bool) Helper::get_option( 'smooth_scroll', true ),
71 'visibility_hide_by_default' => (bool) Helper::get_option( 'visibility_hide_by_default', false ),
72 'subheading_collapse_mode' => Helper::get_option( 'subheading_collapse_mode', 'open_first' ),
73 'scroll_offset' => $scroll_offset,
74 'fallbackIcon' => '<span class="wptoc-js-icon-con">' . Renderer::get_toggle_icon() . '</span>',
75 )
76 );
77
78 wp_localize_script(
79 'wptoc-scroll-scriptjs',
80 'wptoc_smooth_local',
81 array(
82 'drop_down' => Helper::get_option( 'heading-text-direction', 'ltr' ),
83 'scroll_offset' => $scroll_offset,
84 )
85 );
86
87 wp_localize_script(
88 'wptoc-sticky',
89 'wptoc_sticky_local',
90 array(
91 'position' => Helper::get_option( 'sticky-toggle-position', 'bottom-left' ),
92 'sticky_width' => Helper::get_option( 'sticky_width', 270 ),
93 'sticky_scale' => Helper::get_option( 'sticky_scale', '90' ),
94 )
95 );
96 }
97
98 /**
99 * Enqueue styles & scripts on eligible frontend requests.
100 */
101 public static function enqueue_frontend_assets() {
102 if ( is_admin() || is_feed() ) {
103 return;
104 }
105
106 if ( function_exists( 'wptoc_is_plugin_active' ) && wptoc_is_plugin_active( 'elementor/elementor.php' ) ) {
107 wp_enqueue_script( 'wptoc-anchor-fix' );
108 }
109
110 $enabled_post_types = (array) Helper::get_option( 'enabled_post_types', array( 'post' ) );
111 $current_post_type = get_post_type();
112
113 if ( is_singular() && in_array( $current_post_type, $enabled_post_types, true ) ) {
114 self::enqueue_toc_assets();
115 }
116 }
117
118 /**
119 * Force enqueue TOC assets (e.g. when shortcode is executed).
120 */
121 public static function enqueue_toc_assets() {
122 wp_enqueue_style( 'wptoc' );
123 self::enqueue_counter_style();
124
125 $dynamic_css = self::build_dynamic_css();
126 if ( ! empty( $dynamic_css ) ) {
127 wp_add_inline_style( 'wptoc', $dynamic_css );
128 }
129
130 if ( Helper::get_option( 'smooth_scroll', true ) ) {
131 wp_enqueue_script( 'wptoc-scroll-scriptjs' );
132 }
133 wp_enqueue_script( 'wptoc-js' );
134
135 if ( Helper::get_option( 'sticky-toggle', true ) ) {
136 wp_enqueue_style( 'wptoc-sticky' );
137 $sticky_css = self::build_sticky_inline_css();
138 if ( ! empty( $sticky_css ) ) {
139 wp_add_inline_style( 'wptoc-sticky', $sticky_css );
140 }
141 wp_enqueue_script( 'wptoc-sticky' );
142 }
143 }
144
145 /**
146 * Enqueue selected counter style stylesheet.
147 *
148 * @param string|null $counter_override
149 */
150 public static function enqueue_counter_style( $counter_override = null ) {
151 $counter = ! empty( $counter_override ) ? $counter_override : Helper::get_option( 'counter', 'none' );
152
153 switch ( $counter ) {
154 case 'decimal-circle':
155 wp_enqueue_style( 'wptoc-counter-decimal-circle' );
156 break;
157 case 'decimal':
158 case 'numeric':
159 wp_enqueue_style( 'wptoc-counter-decimal' );
160 break;
161 case 'disc':
162 wp_enqueue_style( 'wptoc-counter-disc' );
163 break;
164 case 'checkmark':
165 wp_enqueue_style( 'wptoc-counter-checkmark' );
166 break;
167 case 'none':
168 default:
169 wp_enqueue_style( 'wptoc-counter-none' );
170 break;
171 }
172 }
173
174 /**
175 * Build dynamic inline CSS from plugin customizer options.
176 *
177 * @return string
178 */
179 public static function build_dynamic_css() {
180 $css = '';
181
182 $title_font_size = Helper::get_option( 'title_font_size', 16 );
183 if ( ! empty( $title_font_size ) && is_numeric( $title_font_size ) ) {
184 $css .= 'div#wptoc-container .wptoc-title, div#wptoc-sticky-popup .wptoc-sticky-title { font-size: ' . esc_attr( intval( $title_font_size ) ) . 'px !important; }';
185 }
186
187 $font_size = Helper::get_option( 'font_size', 14 );
188 if ( ! empty( $font_size ) && is_numeric( $font_size ) ) {
189 $css .= 'div#wptoc-container ul.wptoc-list li a, div#wptoc-sticky-popup ul.wptoc-list li a { font-size: ' . esc_attr( intval( $font_size ) ) . 'px !important; }';
190 }
191
192 $child_font_size = Helper::get_option( 'child_font_size', 13 );
193 if ( ! empty( $child_font_size ) && is_numeric( $child_font_size ) ) {
194 $css .= 'div#wptoc-container ul.wptoc-list ul li a, div#wptoc-sticky-popup ul.wptoc-list ul li a, #wptoc-container li.wptoc-heading-level-3 a, #wptoc-sticky-popup li.wptoc-heading-level-3 a { font-size: ' . esc_attr( intval( $child_font_size ) ) . 'px !important; }';
195 }
196
197 $width_custom = Helper::get_option( 'width_custom' );
198 if ( ! empty( $width_custom ) && is_numeric( $width_custom ) ) {
199 $css .= 'div#wptoc-container { width: ' . esc_attr( intval( $width_custom ) ) . 'px !important; max-width: 100% !important; }';
200 }
201
202 $child_indent = Helper::get_option( 'child_indent', 40 );
203 $indent_val = ( '' !== $child_indent && is_numeric( $child_indent ) ) ? intval( $child_indent ) : 40;
204
205 if ( $indent_val <= 0 ) {
206 $css .= 'div#wptoc-container ul.wptoc-list ul, div#wptoc-sticky-popup ul.wptoc-list ul { padding-left: 0 !important; margin-left: 0 !important; }';
207 } else {
208 $css .= 'div#wptoc-container ul.wptoc-list ul > li > .wptoc-item-row > a, div#wptoc-sticky-popup ul.wptoc-list ul > li > .wptoc-item-row > a { padding-left: ' . esc_attr( $indent_val ) . 'px !important; }';
209 $css .= 'div#wptoc-container li.wptoc-heading-level-4 > .wptoc-item-row > a, div#wptoc-sticky-popup li.wptoc-heading-level-4 > .wptoc-item-row > a { padding-left: calc(' . esc_attr( $indent_val ) . 'px * 2) !important; }';
210 $css .= 'div#wptoc-container li.wptoc-heading-level-5 > .wptoc-item-row > a, div#wptoc-sticky-popup li.wptoc-heading-level-5 > .wptoc-item-row > a { padding-left: calc(' . esc_attr( $indent_val ) . 'px * 3) !important; }';
211 }
212
213 $theme_primary = '#2271b1';
214 $theme_text = '#334155';
215 if ( function_exists( 'get_theme_mod' ) ) {
216 $fp = get_theme_mod( 'color_primary', get_theme_mod( 'color_links' ) );
217 if ( ! empty( $fp ) ) {
218 $theme_primary = $fp;
219 }
220 $ft = get_theme_mod( 'type_texts_color' );
221 if ( ! empty( $ft ) ) {
222 $theme_text = $ft;
223 }
224 }
225
226 $custom_bg = Helper::get_option( 'custom_background_colour' );
227 $custom_header_bg = Helper::get_option( 'custom_header_background_colour' );
228 $custom_border = Helper::get_option( 'custom_border_colour' );
229 $custom_border_w = Helper::get_option( 'custom_border_width' );
230 $custom_border_s = Helper::get_option( 'custom_border_style', 'solid' );
231 $custom_border_r = Helper::get_option( 'custom_border_radius' );
232 $custom_title = Helper::get_option( 'custom_title_colour' );
233 $custom_link = Helper::get_option( 'custom_link_colour' );
234 $custom_hover = Helper::get_option( 'custom_link_hover_colour' );
235 $custom_counter = Helper::get_option( 'custom_counter_colour' );
236
237 $active_primary = ! empty( $custom_hover ) ? $custom_hover : $theme_primary;
238 $active_text = ! empty( $custom_link ) ? $custom_link : $theme_text;
239
240 $css .= ':root {';
241 $css .= '--wptoc-primary: ' . esc_attr( $active_primary ) . ' !important;';
242 $css .= '--wptoc-text: ' . esc_attr( $active_text ) . ' !important;';
243 if ( ! empty( $custom_counter ) ) {
244 $css .= '--wptoc-counter-color: ' . esc_attr( $custom_counter ) . ' !important;';
245 }
246 if ( ! empty( $custom_title ) ) {
247 $css .= '--wptoc-title-color: ' . esc_attr( $custom_title ) . ' !important;';
248 }
249 if ( ! empty( $custom_border ) ) {
250 $css .= '--wptoc-border: ' . esc_attr( $custom_border ) . ' !important;';
251 }
252 $css .= '}';
253
254 if ( ! empty( $custom_bg ) ) {
255 $css .= 'div#wptoc-container { background-color: ' . esc_attr( $custom_bg ) . ' !important; }';
256 }
257 if ( ! empty( $custom_header_bg ) ) {
258 $css .= 'div#wptoc-container .wptoc-title-container { background-color: ' . esc_attr( $custom_header_bg ) . ' !important; }';
259 }
260 if ( ! empty( $custom_border ) ) {
261 $css .= 'div#wptoc-container { border-color: ' . esc_attr( $custom_border ) . ' !important; }';
262 }
263 if ( ! empty( $custom_border_w ) && is_numeric( $custom_border_w ) ) {
264 $css .= 'div#wptoc-container { border-width: ' . esc_attr( intval( $custom_border_w ) ) . 'px !important; }';
265 }
266 if ( ! empty( $custom_border_s ) && 'solid' !== $custom_border_s ) {
267 $css .= 'div#wptoc-container { border-style: ' . esc_attr( $custom_border_s ) . ' !important; }';
268 }
269 if ( ! empty( $custom_border_r ) && is_numeric( $custom_border_r ) ) {
270 $css .= 'div#wptoc-container { border-radius: ' . esc_attr( intval( $custom_border_r ) ) . 'px !important; }';
271 }
272 if ( ! empty( $custom_title ) ) {
273 $css .= 'div#wptoc-container .wptoc-title { color: ' . esc_attr( $custom_title ) . ' !important; }';
274 }
275
276 $custom_title_icon = Helper::get_option( 'custom_title_icon_colour' );
277 if ( ! empty( $custom_title_icon ) ) {
278 $css .= 'div#wptoc-container .wptoc-title-icon svg { stroke: ' . esc_attr( $custom_title_icon ) . ' !important; }';
279 }
280
281 $container_padding = Helper::get_option( 'container_padding' );
282 if ( ! empty( $container_padding ) ) {
283 $pad_val = is_numeric( $container_padding ) ? intval( $container_padding ) . 'px' : esc_attr( trim( $container_padding ) );
284 $css .= 'div#wptoc-container { padding: ' . $pad_val . ' !important; }';
285 }
286
287 $nav_padding = Helper::get_option( 'nav_padding' );
288 if ( ! empty( $nav_padding ) ) {
289 $nav_pad_val = is_numeric( $nav_padding ) ? intval( $nav_padding ) . 'px' : esc_attr( trim( $nav_padding ) );
290 $css .= 'div#wptoc-container nav { padding: ' . $nav_pad_val . ' !important; }';
291 }
292
293 return apply_filters( 'wptoc_inline_css', $css );
294 }
295
296 /**
297 * Build Sticky TOC specific inline CSS.
298 *
299 * @return string
300 */
301 public static function build_sticky_inline_css() {
302 $css = '';
303
304 $sticky_width = Helper::get_option( 'sticky_width' );
305 if ( ! empty( $sticky_width ) && is_numeric( $sticky_width ) ) {
306 $css .= '#wptoc-sticky-popup { width: ' . esc_attr( intval( $sticky_width ) ) . 'px !important; }';
307 }
308
309 $sticky_height = Helper::get_option( 'sticky_height' );
310 if ( ! empty( $sticky_height ) && is_numeric( $sticky_height ) ) {
311 $s_height = intval( $sticky_height );
312 $css .= '#wptoc-sticky-popup { max-height: ' . esc_attr( $s_height ) . 'px !important; }';
313 $css .= '#wptoc-sticky-popup nav.wptoc-sidebar { max-height: ' . esc_attr( max( 100, $s_height - 50 ) ) . 'px !important; }';
314 }
315
316 $sticky_scale = Helper::get_option( 'sticky_scale', '90' );
317 if ( ! empty( $sticky_scale ) && is_numeric( $sticky_scale ) ) {
318 $scale_val = floatval( $sticky_scale );
319 $scale_float = ( $scale_val > 5 ) ? round( $scale_val / 100, 2 ) : $scale_val;
320 if ( $scale_float > 0 && 1 !== (int) $scale_float ) {
321 $css .= '#wptoc-sticky-popup.show { transform: scale(' . esc_attr( $scale_float ) . ') translateY(0) !important; }';
322 }
323 }
324
325 $sticky_highlight_bg = Helper::get_option( 'sticky_highlight_bg_colour' );
326 if ( ! empty( $sticky_highlight_bg ) ) {
327 $css .= '#wptoc-sticky-popup ul.wptoc-list li.active > .wptoc-item-row { background-color: ' . esc_attr( $sticky_highlight_bg ) . ' !important; }';
328 }
329
330 $sticky_highlight_title = Helper::get_option( 'sticky_highlight_title_colour' );
331 if ( ! empty( $sticky_highlight_title ) ) {
332 $css .= '#wptoc-sticky-popup ul.wptoc-list li.active > .wptoc-item-row > a { color: ' . esc_attr( $sticky_highlight_title ) . ' !important; }';
333 }
334
335 $sticky_mobile_width = Helper::get_option( 'sticky_mobile_width' );
336 $sticky_mobile_height = Helper::get_option( 'sticky_mobile_height' );
337 if ( ! empty( $sticky_mobile_width ) || ! empty( $sticky_mobile_height ) ) {
338 $css .= '@media screen and (max-width: 768px) {';
339 if ( ! empty( $sticky_mobile_width ) ) {
340 $m_w = is_numeric( $sticky_mobile_width ) ? intval( $sticky_mobile_width ) . 'px' : esc_attr( $sticky_mobile_width );
341 $css .= '#wptoc-sticky-popup { width: ' . $m_w . ' !important; max-width: calc(100vw - 32px) !important; }';
342 }
343 if ( ! empty( $sticky_mobile_height ) ) {
344 $m_h = is_numeric( $sticky_mobile_height ) ? intval( $sticky_mobile_height ) . 'px' : esc_attr( $sticky_mobile_height );
345 $css .= '#wptoc-sticky-popup { max-height: ' . $m_h . ' !important; }';
346 }
347 $css .= '}';
348 }
349
350 return apply_filters( 'wptoc_sticky_inline_css', $css );
351 }
352
353 /**
354 * Register TinyMCE Classic Editor button.
355 */
356 public static function add_editor_button() {
357 if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
358 return;
359 }
360
361 if ( 'true' === get_user_option( 'rich_editing' ) ) {
362 add_filter( 'mce_external_plugins', array( __CLASS__, 'toc_add_tinymce_plugin' ) );
363 add_filter( 'mce_buttons', array( __CLASS__, 'toc_register_mce_button' ) );
364 }
365 }
366
367 public static function toc_register_mce_button( $buttons ) {
368 array_push( $buttons, 'wptoc' );
369 return $buttons;
370 }
371
372 public static function toc_add_tinymce_plugin( $plugin_array ) {
373 $assets_url = defined( 'WPEX_URL' ) ? WPEX_URL . 'assets/' : plugins_url( 'assets/', dirname( dirname( __DIR__ ) ) );
374 $plugin_array['wptoc'] = $assets_url . 'tinymce/toc/plugin.min.js';
375 return $plugin_array;
376 }
377 }
378