PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow / trunk
WDesignKit – AI Templates, Widget Builder & MCP Workflow vtrunk
2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.4.0 2.3.3 2.3.2 2.3.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 All 128 releases
← All changes | includes/admin/class-wdkit-enqueue.php +186 -31 2.4.0trunk View file →
@@ -83,9 +83,21 @@
83 83 *
84 84 * @since 1.0.0
85 85 * @return void
86 86 */
87 - public function wdkit_enqueue_styles_library() {
87 + public function wdkit_enqueue_styles_library( $hook = '' ) {
88 + // Hooked on admin_enqueue_scripts with no screen check at all, so this loaded the icon
89 + // font on every wp-admin screen (ClickUp 86d41cnze). admin_enqueue_scripts passes the
90 + // screen hook as its first argument, so the same guard wdkit_admin_scripts() uses can
91 + // apply here. Kept as a separate handle from 'wdkit-library-preview' — both point at the
92 + // same stylesheet, and deduplicating the handles is a separate change.
93 + $is_nexter_page = isset( $_GET['page'] ) && sanitize_key( wp_unslash( $_GET['page'] ) ) === 'nxt_code_snippets';
94 + $is_theme_builder_page = ( isset( $_GET['post_type'] ) && sanitize_key( wp_unslash( $_GET['post_type'] ) ) === 'nxt_builder' ) || ( isset( $_GET['page'] ) && sanitize_key( wp_unslash( $_GET['page'] ) ) === 'nxt_builder' );
95 +
96 + if ( ! in_array( $hook, array( 'toplevel_page_wdesign-kit', 'elementor', 'post-new.php', 'post.php' ), true ) && ! $is_nexter_page && ! $is_theme_builder_page ) {
97 + return;
98 + }
99 +
88 100 wp_enqueue_style( 'wdkit-library', WDKIT_URL . 'assets/fonts/style.css', array(), WDKIT_VERSION, false );
89 101 }
90 102
91 103 /**
@@ -173,8 +185,9 @@
173 185 public function wdkit_bricks_editor_style() {
174 186 // Only load in Bricks editor
175 187 if ( function_exists( 'bricks_is_builder' ) && bricks_is_builder() ) {
176 188 wp_enqueue_style( 'wdkit-bricks-editor-css', WDKIT_URL . 'assets/css/bricks/wdkit_enqueue_editor_styles.css', array(), WDKIT_VERSION );
189 + // Cross-domain copy/paste for Bricks is marked "Coming Soon" — do not enqueue yet.
177 190
178 191 // Hide WDesignKit logo icon when white label is enabled
179 192 $white_label = get_option( 'wkit_white_label', false );
180 193 if ( ! empty( $white_label['help_link'] ) ) {
@@ -187,8 +200,9 @@
187 200 * Gutenberg Editor Panel Style Loaded
188 201 */
189 202 public function wdkit_gutenberg_editor_style() {
190 203 wp_enqueue_style( 'wdkit-gutenberg-editor-css', WDKIT_URL . 'assets/css/gutenberg/wdkit_enqueue_editor_styles.css', array(), WDKIT_VERSION );
204 + $this->wdkit_cross_copy_paste_script( 'gutenberg' );
191 205
192 206 // Hide WDesignKit logo icon + Need Help panel when white label is enabled
193 207 $white_label = get_option( 'wkit_white_label', false );
194 208 if ( ! empty( $white_label['help_link'] ) ) {
@@ -213,9 +227,13 @@
213 227 * @param string $hook use for check page type.
214 228 */
215 229 public function wdkit_admin_scripts( $hook ) {
216 230
217 - wp_enqueue_style( 'wdkit-library-preview', WDKIT_URL . 'assets/fonts/style.css', array(), WDKIT_VERSION, false );
231 + // Deliberately BEFORE the screen guard below: this 1.4 KB stylesheet contains nothing but
232 + // #adminmenu rules for the WDesignKit menu item, and the admin menu is rendered on every
233 + // admin screen. Gating it to WDesignKit's own screens leaves the menu icon unstyled
234 + // everywhere else — the masked-SVG ::before never applies, so the raw <img> shows through.
235 + // Do not "optimise" this into the guard (ClickUp 86d41cnze).
218 236 wp_enqueue_style( 'wdkit-out-dashborad', WDKIT_URL . 'assets/css/dashborad/wdkit-dashborad.css', array(), WDKIT_VERSION, false );
219 237
220 238 $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
221 239 $ptype = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : '';
@@ -224,15 +242,21 @@
224 242 $is_nexter_page = isset( $_GET['page'] ) && sanitize_key( wp_unslash( $_GET['page'] ) ) === 'nxt_code_snippets';
225 243
226 244 // Check if we're on a Theme Builder page (via post_type or page parameter)
227 245 $is_theme_builder_page = ( isset( $_GET['post_type'] ) && sanitize_key( wp_unslash( $_GET['post_type'] ) ) === 'nxt_builder' ) || ( isset( $_GET['page'] ) && sanitize_key( wp_unslash( $_GET['page'] ) ) === 'nxt_builder' );
228 -
246 +
229 247 if ( ! in_array( $hook, array( 'toplevel_page_wdesign-kit', 'elementor', 'post-new.php', 'post.php' ), true ) && !$is_nexter_page && !$is_theme_builder_page ) {
230 248 return;
231 249 }
232 250
233 - wp_enqueue_media();
251 + // Moved BELOW the screen guard: this is the 9 KB WDesignKit icon font, used only by
252 + // WDesignKit's own UI (no #adminmenu rules in it), yet it was enqueued on every wp-admin
253 + // screen — dashboard, posts list, media library, plugins page (ClickUp 86d41cnze).
254 + // The admin-menu stylesheet is NOT gated here; see the note at the top of this method.
255 + wp_enqueue_style( 'wdkit-library-preview', WDKIT_URL . 'assets/fonts/style.css', array(), WDKIT_VERSION, false );
234 256
257 + wp_enqueue_media();
258 +
235 259 $this->wdkit_enqueue_scripts( $hook );
236 260 $this->wdkit_enqueue_styles();
237 261 }
238 262
@@ -242,8 +266,16 @@
242 266 * @since 1.0.0
243 267 */
244 268 public function wdkit_enqueue_styles() {
245 269 wp_enqueue_style( 'wdkit-editor-css', WDKIT_URL . 'build/index.css', array(), WDKIT_VERSION );
270 +
271 + /**
272 + * The build emits a right-to-left stylesheet (build/index-rtl.css) because the
273 + * source CSS uses physical left/right properties. WordPress does not auto-load
274 + * the -rtl variant; registering it here makes core swap in index-rtl.css on RTL
275 + * locales (Arabic, Hebrew, Farsi, Urdu) so the admin layout mirrors correctly.
276 + */
277 + wp_style_add_data( 'wdkit-editor-css', 'rtl', 'replace' );
246 278 }
247 279
248 280 /**
249 281 * Register the JavaScript for the admin area.
@@ -251,11 +283,32 @@
251 283 * @param string $hook give builder name.
252 284 * @since 1.0.0
253 285 */
254 286 public function wdkit_enqueue_scripts( $hook ) {
255 - $asset_file = WDKIT_PATH . 'build/index.asset.php';
287 + $asset_file = WDKIT_PATH . 'build/index.min.asset.php';
256 288 $asset = file_exists( $asset_file ) ? require $asset_file : array( 'dependencies' => array( 'wp-i18n', 'wp-element', 'wp-components' ), 'version' => WDKIT_VERSION );
257 - wp_enqueue_script( 'wdkit-editor-js', WDKIT_URL . 'build/index.js', $asset['dependencies'], $asset['version'], true );
289 +
290 + /**
291 + * JS translations catalog.
292 + *
293 + * The app ships as a large minified bundle (build/index.min.js) which
294 + * `wp i18n make-pot` skips (all *.min.js are skipped) and could not parse
295 + * within WordPress.org's budget anyway. build/wdk-i18n-strings.js is a
296 + * small, readable catalog of every translatable JS string (generated from
297 + * src/ by bin/generate-i18n-strings.js). WordPress.org extracts strings
298 + * from it and builds the per-locale JSON keyed to this handle; loading it
299 + * here populates the shared wp.i18n store so the whole React app is
300 + * translated. It is a dependency of the app bundle so it (and its inline
301 + * translation data) load first.
302 + */
303 + $script_deps = $asset['dependencies'];
304 + if ( file_exists( WDKIT_PATH . 'build/wdk-i18n-strings.js' ) ) {
305 + wp_enqueue_script( 'wdkit-editor-i18n', WDKIT_URL . 'build/wdk-i18n-strings.js', array( 'wp-i18n' ), $asset['version'], array( 'in_footer' => true, 'strategy' => 'defer' ) );
306 + wp_set_script_translations( 'wdkit-editor-i18n', 'wdesignkit' );
307 + $script_deps = array_merge( $script_deps, array( 'wdkit-editor-i18n' ) );
308 + }
309 +
310 + wp_enqueue_script( 'wdkit-editor-js', WDKIT_URL . 'build/index.min.js', $script_deps, $asset['version'], array( 'in_footer' => true, 'strategy' => 'defer' ) );
258 311 wp_set_script_translations( 'wdkit-editor-js', 'wdesignkit' );
259 312
260 313 $onbording_end = get_option( $this->wdkit_onbording_end );
261 314 $white_label = get_option( 'wkit_white_label', false );
@@ -264,44 +317,146 @@
264 317 wp_localize_script(
265 318 'wdkit-editor-js',
266 319 'wdkitData',
267 320 array(
268 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
269 - 'WDKIT_URL' => WDKIT_URL,
270 - 'WDKIT_ASSETS' => WDKIT_ASSETS,
271 - 'wdkit_server_url' => WDKIT_SERVER_SITE_URL,
272 - 'wdkit_site_api_url' => WDKIT_SERVER_API_URL,
273 - 'wdkit_wp_version' => get_bloginfo( 'version' ),
274 - 'home_url' => esc_url( home_url( '/' ) ),
275 - 'kit_nonce' => wp_create_nonce( 'wdkit_nonce' ),
276 - 'post_id' => get_the_ID(),
277 - 'post_type' => get_post_type(),
278 - 'text_domain' => WDKIT_TEXT_DOMAIN,
279 - 'use_editor' => $this->wdkit_use_editor(),
280 - 'post_type_list' => $this->wdkit_get_post_type_list(),
281 - 'WDKIT_onbording_end' => $onbording_end,
282 - 'wdkit_white_label' => $white_label,
283 - 'WDKIT_dark_mode' => $dark_mode,
321 + 'ajax_url' => admin_url( 'admin-ajax.php' ),
322 + 'WDKIT_URL' => WDKIT_URL,
323 + 'WDKIT_ASSETS' => WDKIT_ASSETS,
324 + 'wdkit_server_url' => WDKIT_SERVER_SITE_URL,
325 + 'wdkit_site_api_url' => WDKIT_SERVER_API_URL,
326 + 'wdkit_wp_version' => get_bloginfo( 'version' ),
327 + 'home_url' => esc_url( home_url( '/' ) ),
328 + 'kit_nonce' => wp_create_nonce( 'wdkit_nonce' ),
329 + 'post_id' => get_the_ID(),
330 + 'post_type' => get_post_type(),
331 + 'text_domain' => WDKIT_TEXT_DOMAIN,
332 + 'use_editor' => $this->wdkit_use_editor(),
333 + 'post_type_list' => $this->wdkit_get_post_type_list(),
334 + 'WDKIT_onbording_end' => $onbording_end,
335 + 'wdkit_white_label' => $white_label,
336 + 'WDKIT_dark_mode' => $dark_mode,
284 337 /** Widget Builder — public URL only, no server filesystem paths */
285 - 'WDKIT_SITE_URL' => WDKIT_GET_SITE_URL,
286 - 'WDKIT_DOC_URL' => WDKIT_DOCUMENT,
287 - 'WDKIT_SERVER_PATH' => WDKIT_SERVER_PATH,
288 - 'WDKIT_VERSION' => WDKIT_VERSION,
338 + 'WDKIT_SITE_URL' => WDKIT_GET_SITE_URL,
339 + 'WDKIT_DOC_URL' => WDKIT_DOCUMENT,
340 + 'WDKIT_SERVER_PATH' => WDKIT_SERVER_PATH,
341 + 'WDKIT_VERSION' => WDKIT_VERSION,
289 342
290 - 'gutenberg_template' => Wdkit_Wdesignkit::wdkit_is_compatible( 'gutenberg_template', 'template' )
343 + 'gutenberg_template' => Wdkit_Wdesignkit::wdkit_is_compatible( 'gutenberg_template', 'template' ),
344 +
345 + /**
346 + * Data Sharing switcher, Settings panel.
347 + *
348 + * Read as a SITE option — the consent is one answer per install, not per blog. The
349 + * class guard matches the one in wdesignkit.php: on a white-labelled install, or when
350 + * a sibling POSIMYTH plugin's SDK copy won the loader, the tracker class is never
351 + * declared and the constant reference would fatal.
352 + *
353 + * Both references are root-namespaced. This file lives in wdkit\WdKit_enqueue while
354 + * the SDK class is declared in the global namespace: a string class name is always
355 + * global so the guard passed either way, but an unprefixed `Posimyth_Tracker_WDK::`
356 + * resolves against THIS namespace and fatals on every admin page load.
357 + */
358 + 'wdkit_data_sharing' => class_exists( '\Posimyth_Tracker_WDK' ) ? (bool) get_site_option( \Posimyth_Tracker_WDK::OPT_IN_OPTION, false ) : false,
359 + 'wdkit_consent_nonce' => wp_create_nonce( 'posimyth_consent_wdk' ),
360 +
361 + /**
362 + * Whether the Data Sharing card may be shown at all.
363 + *
364 + * Tracks the tracker class rather than the white-label flag: a rebranded install now
365 + * keeps the feature (see wdesignkit.php), so this is false only when the SDK genuinely
366 + * failed to load — a sibling POSIMYTH plugin winning the loader with a diverged copy.
367 + * Rendering a switch in that case would offer a save with no handler behind it.
368 + *
369 + * Separate from wdkit_data_sharing on purpose: that one is false both when sharing is
370 + * off and when the feature is absent, which cannot tell the two apart.
371 + */
372 + 'wdkit_data_sharing_available' => class_exists( '\Posimyth_Tracker_WDK' ),
373 +
374 + /**
375 + * Reseller's product name, for the Data Sharing copy that would otherwise say
376 + * "WDesignKit" on a plugin they have rebranded as their own.
377 + */
378 + 'wdkit_data_sharing_name' => ! empty( $white_label['plugin_name'] ) ? $white_label['plugin_name'] : 'WDesignKit',
379 +
380 + /** help_link is the reseller's "hide POSIMYTH documentation links" switch. */
381 + 'wdkit_data_sharing_docs' => empty( $white_label['help_link'] ) ? WDKIT_DOCUMENT . 'data-sharing/' : ''
291 382 )
292 383 );
293 384
294 385 /**Ace Editor files for Widget-builder */
295 386 if ( 'toplevel_page_wdesign-kit' === $hook && Wdkit_Wdesignkit::wdkit_is_compatible( 'builder', 'widget' ) ) {
296 - wp_enqueue_script( 'widgetBuilder-script-editor-js', WDKIT_URL . 'assets/js/extra/ace.min.js', array( 'wp-element' ), WDKIT_VERSION, true );
297 - wp_enqueue_script( 'widgetBuilder-script-editor-cobalt', WDKIT_URL . 'assets/js/extra/theme-cobalt.js', array( 'wp-element' ), WDKIT_VERSION, true );
298 - wp_enqueue_script( 'widgetBuilder-script-editor-html', WDKIT_URL . 'assets/js/extra/mode-html.js', array( 'wp-element' ), WDKIT_VERSION, true );
387 + wp_enqueue_script( 'widgetBuilder-script-editor-js', WDKIT_URL . 'assets/js/extra/ace.min.js', array( 'wp-element' ), WDKIT_VERSION, array( 'in_footer' => true, 'strategy' => 'defer' ) );
388 + wp_enqueue_script( 'widgetBuilder-script-editor-cobalt', WDKIT_URL . 'assets/js/extra/theme-cobalt.js', array( 'wp-element' ), WDKIT_VERSION, array( 'in_footer' => true, 'strategy' => 'defer' ) );
389 + wp_enqueue_script( 'widgetBuilder-script-editor-html', WDKIT_URL . 'assets/js/extra/mode-html.js', array( 'wp-element' ), WDKIT_VERSION, array( 'in_footer' => true, 'strategy' => 'defer' ) );
299 390 }
300 391
301 392 if ( 'elementor' === $hook && Wdkit_Wdesignkit::wdkit_is_compatible( 'elementor_template', 'template' ) ) {
302 - wp_enqueue_script( 'wdkit-frontend-editor', WDKIT_ASSETS . '/js/main/elementor/elementor-editor.js', array( 'jquery', 'wp-i18n' ), WDKIT_VERSION, true );
393 + wp_enqueue_script( 'wdkit-frontend-editor', WDKIT_ASSETS . 'js/main/elementor/elementor-editor.js', array( 'jquery', 'wp-i18n' ), WDKIT_VERSION, array( 'in_footer' => true, 'strategy' => 'defer' ) );
394 + wp_set_script_translations( 'wdkit-frontend-editor', 'wdesignkit' );
395 + $this->wdkit_cross_copy_paste_script( 'elementor' );
303 396 }
397 + }
398 +
399 + /**
400 + * Enqueue cross-domain copy/paste support for active builders.
401 + *
402 + * @since 1.0.0
403 + */
404 + public function wdkit_cross_copy_paste_script( $builder = '' ) {
405 + $settings = get_option( 'wkit_settings_panel', array() );
406 + $enabled = array(
407 + 'elementor' => ! empty( $settings['cross_copy_paste_elementor'] ) || ! empty( $settings['cross_copy_paste'] ),
408 + 'gutenberg' => ! empty( $settings['cross_copy_paste_gutenberg'] ) || ! empty( $settings['cross_copy_paste'] ),
409 + // Bricks support is "Coming Soon" — force-disabled regardless of saved setting.
410 + 'bricks' => false,
411 + );
412 +
413 + if ( empty( array_filter( $enabled ) ) ) {
414 + return;
415 + }
416 +
417 + if ( ! empty( $builder ) && empty( $enabled[ $builder ] ) ) {
418 + return;
419 + }
420 +
421 + if ( wp_script_is( 'wdkit-cross-copy-paste', 'enqueued' ) ) {
422 + return;
423 + }
424 +
425 + $deps = array( 'wp-i18n' );
426 + // Gutenberg SlotFill needs these so the block toolbar's
427 + // "Options" menu can host our "WDesignKit Copy / Paste" items.
428 + if ( ! empty( $enabled['gutenberg'] ) ) {
429 + $deps[] = 'wp-plugins';
430 + $deps[] = 'wp-element';
431 + $deps[] = 'wp-components';
432 + $deps[] = 'wp-block-editor';
433 + $deps[] = 'wp-data';
434 + $deps[] = 'wp-blocks';
435 + $deps[] = 'wp-dom-ready';
436 + }
437 +
438 + wp_enqueue_script( 'wdkit-cross-copy-paste', WDKIT_ASSETS . 'js/main/wdkit-cross-copy-paste.js', $deps, WDKIT_VERSION, array( 'in_footer' => true, 'strategy' => 'defer' ) );
439 + wp_set_script_translations( 'wdkit-cross-copy-paste', 'wdesignkit' );
440 + wp_localize_script(
441 + 'wdkit-cross-copy-paste',
442 + 'wdkitCrossCopyPaste',
443 + array(
444 + 'enabled' => true,
445 + 'version' => WDKIT_VERSION,
446 + 'site' => esc_url( home_url( '/' ) ),
447 + 'builders' => $enabled,
448 + // Direct AJAX access — the editor pages don't always
449 + // load the dashboard wdkitData global. Needed for the
450 + // wdkit_cp_check_widgets endpoint.
451 + 'ajax_url' => admin_url( 'admin-ajax.php' ),
452 + // WDesignKit dashboard (hash-router) page. Missing widgets
453 + // are installed by loading its /create/widget/:w_unique
454 + // route inside a hidden iframe.
455 + 'dashboard_url' => admin_url( 'admin.php?page=wdesign-kit' ),
456 + 'kit_nonce' => wp_create_nonce( 'wdkit_nonce' ),
457 + )
458 + );
304 459 }
305 460
306 461 /**
307 462 * Add Menu Page WdKit.