The SEO Framework - Version 2.9.3

Version Description

A highly recommended update that fixes "Home Page as Blog" query issues.

Download this release

Release Info

Developer Cybr
Plugin Icon 128x128 The SEO Framework
Version 2.9.3
Comparing to
See all releases

Code changes from version 2.9.2 to 2.9.3

autodescription.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: The SEO Framework
4
  * Plugin URI: https://theseoframework.com/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for any WordPress website.
6
- * Version: 2.9.2
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
@@ -31,15 +31,15 @@ defined( 'ABSPATH' ) or die;
31
  */
32
 
33
  //* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
- //add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
- //if ( is_admin() ) {
36
- //define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
- //define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
- //define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
- //update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
- //add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
- //}
42
- //}},0);
43
 
44
  /**
45
  * The plugin version.
@@ -51,7 +51,7 @@ defined( 'ABSPATH' ) or die;
51
  *
52
  * @since 1.0.0
53
  */
54
- define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.2' );
55
 
56
  /**
57
  * The plugin Database version.
@@ -90,11 +90,17 @@ define( 'THE_SEO_FRAMEWORK_NETWORK_OPTIONS', (string) apply_filters( 'the_seo_fr
90
  define( 'THE_SEO_FRAMEWORK_TERM_OPTIONS', (string) apply_filters( 'the_seo_framework_term_options', 'autodescription-term-settings' ) );
91
 
92
  /**
93
- * Plugin term options filter.
94
  * @since 2.7.0
95
  */
96
  define( 'THE_SEO_FRAMEWORK_USER_OPTIONS', (string) apply_filters( 'the_seo_framework_user_options', 'autodescription-user-settings' ) );
97
 
 
 
 
 
 
 
98
  /**
99
  * The plugin map url.
100
  * Used for calling browser files.
3
  * Plugin Name: The SEO Framework
4
  * Plugin URI: https://theseoframework.com/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for any WordPress website.
6
+ * Version: 2.9.3
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
31
  */
32
 
33
  //* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
+ // add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
+ // if ( is_admin() ) {
36
+ // define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
+ // define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
+ // define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
+ // update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
+ // add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
+ // }
42
+ // }},0);
43
 
44
  /**
45
  * The plugin version.
51
  *
52
  * @since 1.0.0
53
  */
54
+ define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.3' );
55
 
56
  /**
57
  * The plugin Database version.
90
  define( 'THE_SEO_FRAMEWORK_TERM_OPTIONS', (string) apply_filters( 'the_seo_framework_term_options', 'autodescription-term-settings' ) );
91
 
92
  /**
93
+ * Plugin user term options filter.
94
  * @since 2.7.0
95
  */
96
  define( 'THE_SEO_FRAMEWORK_USER_OPTIONS', (string) apply_filters( 'the_seo_framework_user_options', 'autodescription-user-settings' ) );
97
 
98
+ /**
99
+ * Plugin updates cache database name.
100
+ * @since 2.9.3
101
+ */
102
+ define( 'THE_SEO_FRAMEWORK_UPDATES_CACHE', (string) apply_filters( 'the_seo_framework_updates_cache', 'autodescription-updates-cache' ) );
103
+
104
  /**
105
  * The plugin map url.
106
  * Used for calling browser files.
inc/classes/admin-init.class.php CHANGED
@@ -524,6 +524,8 @@ class Admin_Init extends Init {
524
  *
525
  * @since 2.2.2
526
  * @since 2.9.2 : Added user-friendly exception handling.
 
 
527
  *
528
  * @param string $page Menu slug.
529
  * @param array $query_args Optional. Associative array of query string arguments
@@ -543,7 +545,7 @@ class Admin_Init extends Init {
543
  }
544
 
545
  $target = \add_query_arg( $query_args, $url );
546
- $target = \esc_url_raw( $url );
547
 
548
  //* Predict white screen:
549
  $headers_sent = headers_sent();
@@ -593,7 +595,8 @@ class Admin_Init extends Init {
593
  \esc_html__( 'There has been an error redirecting. Refresh the page or follow [this link](%s).', 'autodescription' ),
594
  $target
595
  ),
596
- array( 'a' )
 
597
  )
598
  );
599
  }
524
  *
525
  * @since 2.2.2
526
  * @since 2.9.2 : Added user-friendly exception handling.
527
+ * @since 2.9.3 : 1. Query arguments work again (regression 2.9.2).
528
+ * 2. Now only accepts http and https protocols.
529
  *
530
  * @param string $page Menu slug.
531
  * @param array $query_args Optional. Associative array of query string arguments
545
  }
546
 
547
  $target = \add_query_arg( $query_args, $url );
548
+ $target = \esc_url_raw( $target, array( 'http', 'https' ) );
549
 
550
  //* Predict white screen:
551
  $headers_sent = headers_sent();
595
  \esc_html__( 'There has been an error redirecting. Refresh the page or follow [this link](%s).', 'autodescription' ),
596
  $target
597
  ),
598
+ array( 'a' ),
599
+ array( 'a_internal' => true )
600
  )
601
  );
602
  }
inc/classes/admin-pages.class.php CHANGED
@@ -403,7 +403,7 @@ class Admin_Pages extends Inpost {
403
  * Display notices on the save or reset of settings.
404
  *
405
  * @since 2.2.2
406
- * @todo convert the "request" into secure "error_notice" option. See TSF Extension Manager.
407
  *
408
  * @return void
409
  */
@@ -412,18 +412,18 @@ class Admin_Pages extends Inpost {
412
  if ( false === $this->is_seo_settings_page( true ) )
413
  return;
414
 
415
- $request = isset( $_REQUEST ) ? $_REQUEST : null;
416
 
417
- if ( null === $request )
418
  return;
419
 
420
- if ( isset( $request['settings-updated'] ) && 'true' === $request['settings-updated'] ) :
421
  $this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
422
- elseif ( isset( $request['tsf-settings-reset'] ) && 'true' === $request['tsf-settings-reset'] ) :
423
  $this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
424
- elseif ( isset( $request['error'] ) && 'true' === $request['error'] ) :
425
  $this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
426
- elseif ( isset( $request['tsf-settings-updated'] ) && 'true' === $request['tsf-settings-updated'] ) :
427
  $this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
428
  endif;
429
  }
@@ -629,7 +629,7 @@ class Admin_Pages extends Inpost {
629
  public function make_info( $description = '', $link = '', $echo = true ) {
630
 
631
  if ( $link ) {
632
- $output = '<a href="' . \esc_url( $link ) . '" target="_blank" title="' . \esc_attr( $description ) . '">[?]</a>';
633
  } else {
634
  $output = '<span title="' . \esc_attr( $description ) . '">[?]</span>';
635
  }
403
  * Display notices on the save or reset of settings.
404
  *
405
  * @since 2.2.2
406
+ * @todo convert the "get" into secure "error_notice" option. See TSF Extension Manager.
407
  *
408
  * @return void
409
  */
412
  if ( false === $this->is_seo_settings_page( true ) )
413
  return;
414
 
415
+ $get = empty( $_GET ) ? null : $_GET;
416
 
417
+ if ( null === $get )
418
  return;
419
 
420
+ if ( isset( $get['settings-updated'] ) && 'true' === $get['settings-updated'] ) :
421
  $this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
422
+ elseif ( isset( $get['tsf-settings-reset'] ) && 'true' === $get['tsf-settings-reset'] ) :
423
  $this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
424
+ elseif ( isset( $get['error'] ) && 'true' === $get['error'] ) :
425
  $this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
426
+ elseif ( isset( $get['tsf-settings-updated'] ) && 'true' === $get['tsf-settings-updated'] ) :
427
  $this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
428
  endif;
429
  }
629
  public function make_info( $description = '', $link = '', $echo = true ) {
630
 
631
  if ( $link ) {
632
+ $output = '<a href="' . \esc_url( $link, array( 'http', 'https' ) ) . '" target="_blank" title="' . \esc_attr( $description ) . '">[?]</a>';
633
  } else {
634
  $output = '<span title="' . \esc_attr( $description ) . '">[?]</span>';
635
  }
inc/classes/cache.class.php CHANGED
@@ -218,6 +218,7 @@ class Cache extends Sitemaps {
218
  * Main cache deletion function handler.
219
  *
220
  * @since 2.8.0
 
221
  *
222
  * @param string $type The type
223
  * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
@@ -235,6 +236,7 @@ class Cache extends Sitemaps {
235
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
236
  $this->delete_auto_description_transient( $front_id, '', 'frontpage' );
237
  $this->delete_ld_json_transient( $front_id, '', 'frontpage' );
 
238
  break;
239
 
240
  case 'post' :
@@ -561,7 +563,7 @@ class Cache extends Sitemaps {
561
 
562
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
563
 
564
- $revision = '3';
565
 
566
  /**
567
  * Change key based on options.
@@ -627,54 +629,6 @@ class Cache extends Sitemaps {
627
 
628
  if ( $this->is_404() ) {
629
  $the_id = '_404_';
630
- } elseif ( ( $this->is_real_front_page() || $this->is_front_page_by_id( $page_id ) ) || ( $this->is_admin() && $this->is_seo_settings_page( true ) ) ) {
631
- //* Front/HomePage.
632
- $the_id = $this->generate_front_page_cache_key();
633
- } elseif ( $this->is_blog_page( $page_id ) ) {
634
- $the_id = 'blog_' . $page_id;
635
- } elseif ( $this->is_singular() ) {
636
-
637
- $post_type = \get_post_type( $page_id );
638
-
639
- switch ( $post_type ) :
640
- case 'page' :
641
- $the_id = 'page_' . $page_id;
642
- break;
643
-
644
- case 'post' :
645
- $the_id = 'post_' . $page_id;
646
- break;
647
-
648
- case 'attachment' :
649
- $the_id = 'attach_' . $page_id;
650
- break;
651
-
652
- default :
653
- $the_id = 'singular_' . $page_id;
654
- break;
655
- endswitch;
656
- } elseif ( $this->is_search() ) {
657
- $query = '';
658
-
659
- //* TODO figure out why this check is here... admin compat maybe?
660
- if ( function_exists( 'get_search_query' ) ) {
661
- $search_query = \get_search_query( $_escaped = true );
662
-
663
- if ( $search_query )
664
- $query = str_replace( ' ', '', $search_query );
665
-
666
- //* Limit to 10 chars.
667
- if ( mb_strlen( $query ) > 10 )
668
- $query = mb_substr( $query, 0, 10 );
669
-
670
- $query = \esc_sql( $query );
671
- }
672
-
673
- //* Temporarily disable caches to prevent database spam.
674
- $this->the_seo_framework_use_transients = false;
675
- $this->use_object_cache = false;
676
-
677
- $the_id = $page_id . '_s_' . $query;
678
  } elseif ( $this->is_archive() ) {
679
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
680
 
@@ -685,7 +639,7 @@ class Cache extends Sitemaps {
685
  $t = $o->taxonomy;
686
  }
687
 
688
- $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
689
 
690
  if ( $this->is_tax() )
691
  $the_id = 'archives_' . $the_id;
@@ -724,7 +678,7 @@ class Cache extends Sitemaps {
724
  $the_id = 'unix_' . $unix;
725
  }
726
  } else {
727
- //* Other taxonomial archives.
728
 
729
  if ( empty( $t ) ) {
730
  $post_type = \get_query_var( 'post_type' );
@@ -743,10 +697,58 @@ class Cache extends Sitemaps {
743
  if ( empty( $t ) )
744
  $t = \get_query_var( 'taxonomy' );
745
 
746
- $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
747
 
748
  $the_id = 'archives_' . $the_id;
749
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  }
751
 
752
  /**
@@ -802,7 +804,7 @@ class Cache extends Sitemaps {
802
  return $this->add_cache_key_suffix( 'singular_' . $page_id );
803
  break;
804
  case 'term' :
805
- return $this->add_cache_key_suffix( $this->generate_taxonomial_cache_key( $page_id, $taxonomy ) );
806
  break;
807
  default :
808
  $this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
@@ -858,16 +860,16 @@ class Cache extends Sitemaps {
858
  }
859
 
860
  /**
861
- * Generates Cache key for taxonomial archives.
862
  *
863
  * @since 2.6.0
864
  *
865
  * @param int $page_id The taxonomy or page ID.
866
  * @param string $taxonomy The taxonomy name.
867
  *
868
- * @return string The Taxonomial Archive cache key.
869
  */
870
- protected function generate_taxonomial_cache_key( $page_id = '', $taxonomy = '' ) {
871
 
872
  $the_id = '';
873
 
218
  * Main cache deletion function handler.
219
  *
220
  * @since 2.8.0
221
+ * @since 2.9.3 $type = 'front' now also returns true.
222
  *
223
  * @param string $type The type
224
  * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
236
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
237
  $this->delete_auto_description_transient( $front_id, '', 'frontpage' );
238
  $this->delete_ld_json_transient( $front_id, '', 'frontpage' );
239
+ return true;
240
  break;
241
 
242
  case 'post' :
563
 
564
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
565
 
566
+ $revision = '5';
567
 
568
  /**
569
  * Change key based on options.
629
 
630
  if ( $this->is_404() ) {
631
  $the_id = '_404_';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632
  } elseif ( $this->is_archive() ) {
633
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
634
 
639
  $t = $o->taxonomy;
640
  }
641
 
642
+ $the_id = $this->generate_taxonomical_cache_key( $page_id, $t );
643
 
644
  if ( $this->is_tax() )
645
  $the_id = 'archives_' . $the_id;
678
  $the_id = 'unix_' . $unix;
679
  }
680
  } else {
681
+ //* Other taxonomical archives.
682
 
683
  if ( empty( $t ) ) {
684
  $post_type = \get_query_var( 'post_type' );
697
  if ( empty( $t ) )
698
  $t = \get_query_var( 'taxonomy' );
699
 
700
+ $the_id = $this->generate_taxonomical_cache_key( $page_id, $t );
701
 
702
  $the_id = 'archives_' . $the_id;
703
  }
704
+ } elseif ( ( $this->is_real_front_page() || $this->is_front_page_by_id( $page_id ) ) || ( $this->is_admin() && $this->is_seo_settings_page( true ) ) ) {
705
+ //* Front/HomePage.
706
+ $the_id = $this->generate_front_page_cache_key();
707
+ } elseif ( $this->is_blog_page( $page_id ) ) {
708
+ $the_id = 'blog_' . $page_id;
709
+ } elseif ( $this->is_singular() ) {
710
+
711
+ $post_type = \get_post_type( $page_id );
712
+
713
+ switch ( $post_type ) :
714
+ case 'page' :
715
+ $the_id = 'page_' . $page_id;
716
+ break;
717
+
718
+ case 'post' :
719
+ $the_id = 'post_' . $page_id;
720
+ break;
721
+
722
+ case 'attachment' :
723
+ $the_id = 'attach_' . $page_id;
724
+ break;
725
+
726
+ default :
727
+ $the_id = 'singular_' . $page_id;
728
+ break;
729
+ endswitch;
730
+ } elseif ( $this->is_search() ) {
731
+ $query = '';
732
+
733
+ //* TODO figure out why this check is here... admin compat maybe?
734
+ if ( function_exists( 'get_search_query' ) ) {
735
+ $search_query = \get_search_query( $_escaped = true );
736
+
737
+ if ( $search_query )
738
+ $query = str_replace( ' ', '', $search_query );
739
+
740
+ //* Limit to 10 chars.
741
+ if ( mb_strlen( $query ) > 10 )
742
+ $query = mb_substr( $query, 0, 10 );
743
+
744
+ $query = \esc_sql( $query );
745
+ }
746
+
747
+ //* Temporarily disable caches to prevent database spam.
748
+ $this->the_seo_framework_use_transients = false;
749
+ $this->use_object_cache = false;
750
+
751
+ $the_id = $page_id . '_s_' . $query;
752
  }
753
 
754
  /**
804
  return $this->add_cache_key_suffix( 'singular_' . $page_id );
805
  break;
806
  case 'term' :
807
+ return $this->add_cache_key_suffix( $this->generate_taxonomical_cache_key( $page_id, $taxonomy ) );
808
  break;
809
  default :
810
  $this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
860
  }
861
 
862
  /**
863
+ * Generates Cache key for taxonomical archives.
864
  *
865
  * @since 2.6.0
866
  *
867
  * @param int $page_id The taxonomy or page ID.
868
  * @param string $taxonomy The taxonomy name.
869
  *
870
+ * @return string The Taxonomical Archive cache key.
871
  */
872
+ protected function generate_taxonomical_cache_key( $page_id = '', $taxonomy = '' ) {
873
 
874
  $the_id = '';
875
 
inc/classes/core.class.php CHANGED
@@ -313,7 +313,7 @@ class Core {
313
  $a11y = $a11y ? 'tsf-show-icon' : '';
314
 
315
  $notice = '<div class="notice ' . \esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
316
- $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . \esc_attr__( 'Dismiss', 'AutoDescription' ) . '"></a>';
317
  $notice .= '<strong>' . $message . '</strong>';
318
  $notice .= '</p></div>';
319
 
@@ -334,6 +334,52 @@ class Core {
334
  echo $this->generate_dismissible_notice( $message, $type, (bool) $a11y, (bool) $escape );
335
  }
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  /**
338
  * Mark up content with code tags.
339
  * Escapes all HTML, so `<` gets changed to `&lt;` and displays correctly.
@@ -552,7 +598,7 @@ class Core {
552
 
553
  $url = html_entity_decode( \menu_page_url( $this->seo_settings_page_slug, false ) );
554
 
555
- return \esc_url( $url );
556
  }
557
 
558
  return '';
@@ -805,14 +851,17 @@ class Core {
805
  * @since 2.9.0 : 1. Removed word boundary requirement for strong.
806
  * 2. Now accepts regex count their numeric values in string.
807
  * 3. Fixed header 1~6 calculation.
 
 
808
  * @link https://wordpress.org/plugins/about/readme.txt
809
  *
810
  * @param string $text The text that might contain markdown. Expected to be escaped.
811
  * @param array $convert The markdown style types wished to be converted.
812
- * If left empty, it will convert all.
 
813
  * @return string The markdown converted text.
814
  */
815
- public function convert_markdown( $text, $convert = array() ) {
816
 
817
  preprocess : {
818
  $text = str_replace( "\r\n", "\n", $text );
@@ -823,6 +872,11 @@ class Core {
823
  if ( '' === $text )
824
  return '';
825
 
 
 
 
 
 
826
  /**
827
  * The conversion list's keys are per reference only.
828
  */
@@ -902,10 +956,12 @@ class Core {
902
  case 'a' :
903
  $count = preg_match_all( '/(?:(?:\[{1})([^\]{1}]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
904
 
 
 
905
  for ( $i = 0; $i < $count; $i++ ) {
906
  $text = str_replace(
907
  $matches[0][ $i ],
908
- sprintf( '<a href="%s" rel="nofollow noreferrer noopener">%s</a>', \esc_url( $matches[2][ $i ] ), \esc_html( $matches[1][ $i ] ) ),
909
  $text
910
  );
911
  }
313
  $a11y = $a11y ? 'tsf-show-icon' : '';
314
 
315
  $notice = '<div class="notice ' . \esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
316
+ $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . \esc_attr__( 'Dismiss', 'autodescription' ) . '"></a>';
317
  $notice .= '<strong>' . $message . '</strong>';
318
  $notice .= '</p></div>';
319
 
334
  echo $this->generate_dismissible_notice( $message, $type, (bool) $a11y, (bool) $escape );
335
  }
336
 
337
+ /**
338
+ * Generates dismissible notice that stick until the user dismisses it.
339
+ * Also loads scripts and styles if out of The SEO Framework's context.
340
+ *
341
+ * @since 2.9.3
342
+ * @see $this->do_dismissible_sticky_notice()
343
+ * @uses THE_SEO_FRAMEWORK_UPDATES_CACHE
344
+ * @todo make this do something.
345
+ * NOTE: This method is a placeholder.
346
+ *
347
+ * @param string $message The notice message. Expected to be escaped if $escape is false.
348
+ * @param string $key The notice key. Must be unique and tied to the stored updates cache option.
349
+ * @param array $args : {
350
+ * 'type' => string Optional. The notification type. Default 'updated'.
351
+ * 'a11y' => bool Optional. Whether to enable accessibility. Default true.
352
+ * 'escape' => bool Optional. Whether to escape the $message. Default true.
353
+ * 'color' => string Optional. If filled in, it will output the selected color. Default ''.
354
+ * 'icon' => string Optional. If filled in, it will output the selected icon. Default ''.
355
+ * }
356
+ * @return string The dismissible error notice.
357
+ */
358
+ public function generate_dismissible_sticky_notice( $message, $key, $args = array() ) {
359
+ return '';
360
+ }
361
+
362
+ /**
363
+ * Echos generated dismissible sticky notice.
364
+ *
365
+ * @since 2.9.3
366
+ * @uses $this->generate_dismissible_sticky_notice()
367
+ *
368
+ * @param string $message The notice message. Expected to be escaped if $escape is false.
369
+ * @param string $key The notice key. Must be unique and tied to the stored updates cache option.
370
+ * @param array $args : {
371
+ * 'type' => string Optional. The notification type. Default 'updated'.
372
+ * 'a11y' => bool Optional. Whether to enable accessibility. Default true.
373
+ * 'escape' => bool Optional. Whether to escape the $message. Default true.
374
+ * 'color' => string Optional. If filled in, it will output the selected color. Default ''.
375
+ * 'icon' => string Optional. If filled in, it will output the selected icon. Default ''.
376
+ * }
377
+ * @return string The dismissible error notice.
378
+ */
379
+ public function do_dismissible_sticky_notice( $message, $key, $args = array() ) {
380
+ echo $this->generate_dismissible_sticky_notice( $message, $key, $args );
381
+ }
382
+
383
  /**
384
  * Mark up content with code tags.
385
  * Escapes all HTML, so `<` gets changed to `&lt;` and displays correctly.
598
 
599
  $url = html_entity_decode( \menu_page_url( $this->seo_settings_page_slug, false ) );
600
 
601
+ return \esc_url( $url, array( 'http', 'https' ) );
602
  }
603
 
604
  return '';
851
  * @since 2.9.0 : 1. Removed word boundary requirement for strong.
852
  * 2. Now accepts regex count their numeric values in string.
853
  * 3. Fixed header 1~6 calculation.
854
+ * @since 2.9.3 : 1. Added $args parameter.
855
+ * 2. TODO It now uses substr_replace instead of str_replace to prevent duplicated replacements.
856
  * @link https://wordpress.org/plugins/about/readme.txt
857
  *
858
  * @param string $text The text that might contain markdown. Expected to be escaped.
859
  * @param array $convert The markdown style types wished to be converted.
860
+ * If left empty, it will convert all.
861
+ * @param array $args The function arguments.
862
  * @return string The markdown converted text.
863
  */
864
+ public function convert_markdown( $text, $convert = array(), $args = array() ) {
865
 
866
  preprocess : {
867
  $text = str_replace( "\r\n", "\n", $text );
872
  if ( '' === $text )
873
  return '';
874
 
875
+ $defaults = array(
876
+ 'a_internal' => false,
877
+ );
878
+ $args = array_merge( $defaults, $args );
879
+
880
  /**
881
  * The conversion list's keys are per reference only.
882
  */
956
  case 'a' :
957
  $count = preg_match_all( '/(?:(?:\[{1})([^\]{1}]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
958
 
959
+ $_string = $args['a_internal'] ? '<a href="%s">%s</a>' : '<a href="%s" target="_blank" rel="nofollow noreferrer noopener">%s</a>';
960
+
961
  for ( $i = 0; $i < $count; $i++ ) {
962
  $text = str_replace(
963
  $matches[0][ $i ],
964
+ sprintf( $_string, \esc_url( $matches[2][ $i ], array( 'http', 'https' ) ), \esc_html( $matches[1][ $i ] ) ),
965
  $text
966
  );
967
  }
inc/classes/deprecated.class.php CHANGED
@@ -647,12 +647,13 @@ final class Deprecated {
647
 
648
  /**
649
  * Fetches image from post thumbnail.
650
- * Resizes the image between 1500px if bigger. Then it saves the image and
651
  * Keeps dimensions relative.
652
  *
653
  * @since 2.3.0
654
  * @since 2.9.0 Changed parameters.
655
  * @since 2.9.0 Deprecated.
 
656
  * @deprecated
657
  *
658
  * @param array $args The image args.
@@ -741,4 +742,549 @@ final class Deprecated {
741
 
742
  return $is_front_page;
743
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744
  }
647
 
648
  /**
649
  * Fetches image from post thumbnail.
650
+ * Resizes the image between 4096px if bigger. Then it saves the image and
651
  * Keeps dimensions relative.
652
  *
653
  * @since 2.3.0
654
  * @since 2.9.0 Changed parameters.
655
  * @since 2.9.0 Deprecated.
656
+ * @since 2.9.3 Now supports 4K, rather than 1500px.
657
  * @deprecated
658
  *
659
  * @param array $args The image args.
742
 
743
  return $is_front_page;
744
  }
745
+
746
+ /**
747
+ * Returns http://schema.org json encoded context URL.
748
+ *
749
+ * @staticvar string $context
750
+ * @since 2.6.0
751
+ * @since 2.9.3 Deprecated.
752
+ * @deprecated
753
+ *
754
+ * @return string The json encoded context url.
755
+ */
756
+ public function schema_context() {
757
+
758
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_context()', '2.9.3' );
759
+
760
+ static $context;
761
+
762
+ if ( isset( $context ) )
763
+ return $context;
764
+
765
+ return $context = json_encode( 'http://schema.org' );
766
+ }
767
+
768
+
769
+ /**
770
+ * Returns 'WebSite' json encoded type name.
771
+ *
772
+ * @staticvar string $context
773
+ * @since 2.6.0
774
+ * @since 2.9.3 Deprecated.
775
+ * @deprecated
776
+ *
777
+ * @return string The json encoded type name.
778
+ */
779
+ public function schema_type() {
780
+
781
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_type()', '2.9.3' );
782
+
783
+ static $type;
784
+
785
+ if ( isset( $type ) )
786
+ return $type;
787
+
788
+ return $type = json_encode( 'WebSite' );
789
+ }
790
+
791
+ /**
792
+ * Returns json encoded home url.
793
+ *
794
+ * @staticvar string $url
795
+ * @since 2.6.0
796
+ * @since 2.9.3 Deprecated.
797
+ * @deprecated
798
+ *
799
+ * @return string The json encoded home url.
800
+ */
801
+ public function schema_home_url() {
802
+
803
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_home_url()', '2.9.3' );
804
+
805
+ static $type;
806
+
807
+ if ( isset( $type ) )
808
+ return $type;
809
+
810
+ return $type = json_encode( \the_seo_framework()->the_home_url_from_cache() );
811
+ }
812
+
813
+ /**
814
+ * Returns json encoded blogname.
815
+ *
816
+ * @staticvar string $name
817
+ * @since 2.6.0
818
+ * @since 2.9.3 Deprecated.
819
+ * @deprecated
820
+ *
821
+ * @return string The json encoded blogname.
822
+ */
823
+ public function schema_blog_name() {
824
+
825
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_blog_name()', '2.9.3' );
826
+
827
+ static $name;
828
+
829
+ if ( isset( $name ) )
830
+ return $name;
831
+
832
+ return $name = json_encode( \the_seo_framework()->get_blogname() );
833
+ }
834
+
835
+ /**
836
+ * Returns 'BreadcrumbList' json encoded type name.
837
+ *
838
+ * @staticvar string $crumblist
839
+ * @since 2.6.0
840
+ * @since 2.9.3 Deprecated.
841
+ * @deprecated
842
+ *
843
+ * @return string The json encoded 'BreadcrumbList'.
844
+ */
845
+ public function schema_breadcrumblist() {
846
+
847
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_breadcrumblist()', '2.9.3' );
848
+
849
+ static $crumblist;
850
+
851
+ if ( isset( $crumblist ) )
852
+ return $crumblist;
853
+
854
+ return $crumblist = json_encode( 'BreadcrumbList' );
855
+ }
856
+
857
+ /**
858
+ * Returns 'ListItem' json encoded type name.
859
+ *
860
+ * @staticvar string $listitem
861
+ * @since 2.6.0
862
+ * @since 2.9.3 Deprecated.
863
+ * @deprecated
864
+ *
865
+ * @return string The json encoded 'ListItem'.
866
+ */
867
+ public function schema_listitem() {
868
+
869
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_listitem()', '2.9.3' );
870
+
871
+ static $listitem;
872
+
873
+ if ( isset( $listitem ) )
874
+ return $listitem;
875
+
876
+ return $listitem = json_encode( 'ListItem' );
877
+ }
878
+
879
+ /**
880
+ * Returns 'image' json encoded value.
881
+ *
882
+ * @staticvar array $images
883
+ * @since 2.7.0
884
+ * @since 2.9.0 : 1. No longer uses image from cache, instead: it skips fallback images.
885
+ * 2. Can now fetch home-page as blog set image.
886
+ * @since 2.9.3 Deprecated.
887
+ * @deprecated
888
+ *
889
+ * @param int|string $id The page, post, product or term ID.
890
+ * @param bool $singular Whether the ID is singular.
891
+ */
892
+ public function schema_image( $id = 0, $singular = false ) {
893
+
894
+ $tsf = \the_seo_framework();
895
+
896
+ $tsf->_deprecated_function( 'the_seo_framework()->schema_image()', '2.9.3' );
897
+
898
+ static $images = array();
899
+
900
+ $id = (int) $id;
901
+
902
+ if ( isset( $images[ $id ][ $singular ] ) )
903
+ return $images[ $id ][ $singular ];
904
+
905
+ $image = '';
906
+
907
+ if ( $singular ) {
908
+ if ( $id === $tsf->get_the_front_page_ID() ) {
909
+ if ( $tsf->has_page_on_front() ) {
910
+ $image_args = array(
911
+ 'post_id' => $id,
912
+ 'skip_fallback' => true,
913
+ );
914
+ } else {
915
+ $image_args = array(
916
+ 'post_id' => $id,
917
+ 'skip_fallback' => true,
918
+ 'disallowed' => array(
919
+ 'postmeta',
920
+ 'featured',
921
+ ),
922
+ );
923
+ }
924
+ } else {
925
+ $image_args = array(
926
+ 'post_id' => $id,
927
+ 'skip_fallback' => true,
928
+ 'disallowed' => array(
929
+ 'homemeta'
930
+ ),
931
+ );
932
+ }
933
+ $image = $tsf->get_social_image( $image_args );
934
+ } else {
935
+ //* Placeholder.
936
+ $image = '';
937
+ }
938
+
939
+ /**
940
+ * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
941
+ * @since 2.7.0
942
+ * @param string $image The current image.
943
+ * @param int $id The page, post, product or term ID.
944
+ * @param bool $singular Whether the ID is singular.
945
+ */
946
+ $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
947
+
948
+ return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
949
+ }
950
+
951
+ /**
952
+ * Generate LD+Json search helper.
953
+ *
954
+ * @since 2.2.8
955
+ * @since 2.9.3 Deprecated.
956
+ * @deprecated
957
+ *
958
+ * @return escaped LD+json search helper string.
959
+ */
960
+ public function ld_json_search() {
961
+
962
+ $tsf = \the_seo_framework();
963
+
964
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_search()', '2.9.3' );
965
+
966
+ if ( false === $tsf->enable_ld_json_searchbox() )
967
+ return '';
968
+
969
+ $context = $this->schema_context();
970
+ $webtype = $this->schema_type();
971
+ $url = $this->schema_home_url();
972
+ $name = $this->schema_blog_name();
973
+ $actiontype = json_encode( 'SearchAction' );
974
+
975
+ /**
976
+ * Applies filters 'the_seo_framework_ld_json_search_url' : string
977
+ * @since 2.7.0
978
+ * @param string $search_url The default WordPress search URL without query parameters.
979
+ */
980
+ $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $tsf->the_home_url_from_cache( true ) . '?s=' );
981
+
982
+ // Remove trailing quote and add it back.
983
+ $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
984
+
985
+ $queryaction = json_encode( 'required name=search_term_string' );
986
+
987
+ $json = sprintf( '{"@context":%s,"@type":%s,"url":%s,"name":%s,"potentialAction":{"@type":%s,"target":%s,"query-input":%s}}', $context, $webtype, $url, $name, $actiontype, $target, $queryaction );
988
+
989
+ $output = '';
990
+
991
+ if ( $json )
992
+ $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
993
+
994
+ return $output;
995
+ }
996
+
997
+ /**
998
+ * Generate Site Name LD+Json script.
999
+ *
1000
+ * @since 2.6.0
1001
+ * @since 2.9.3 Deprecated.
1002
+ * @deprecated
1003
+ *
1004
+ * @return string The LD+JSon Site Name script.
1005
+ */
1006
+ public function ld_json_name() {
1007
+
1008
+ $tsf = \the_seo_framework();
1009
+
1010
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3' );
1011
+
1012
+ if ( false === $tsf->enable_ld_json_sitename() )
1013
+ return '';
1014
+
1015
+ $context = $this->schema_context();
1016
+ $webtype = $this->schema_type();
1017
+ $url = $this->schema_home_url();
1018
+ $name = $this->schema_blog_name();
1019
+ $alternate = '';
1020
+
1021
+ $blogname = $tsf->get_blogname();
1022
+ $knowledge_name = $tsf->get_option( 'knowledge_name' );
1023
+
1024
+ if ( $knowledge_name && $knowledge_name !== $blogname ) {
1025
+ $alternate = json_encode( \esc_html( $knowledge_name ) );
1026
+ }
1027
+
1028
+ if ( $alternate ) {
1029
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"alternateName":%s,"url":%s}', $context, $webtype, $name, $alternate, $url );
1030
+ } else {
1031
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s}', $context, $webtype, $name, $url );
1032
+ }
1033
+
1034
+ $output = '';
1035
+ if ( $json )
1036
+ $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1037
+
1038
+ return $output;
1039
+ }
1040
+
1041
+ /**
1042
+ * Return LD+Json Knowledge Graph helper.
1043
+ *
1044
+ * @since 2.2.8
1045
+ * @since 2.9.2 : Now grabs home URL from cache.
1046
+ * @since 2.9.3 Deprecated.
1047
+ * @deprecated
1048
+ *
1049
+ * @return string LD+json Knowledge Graph helper.
1050
+ */
1051
+ public function ld_json_knowledge() {
1052
+
1053
+ $tsf = \the_seo_framework();
1054
+
1055
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3', 'the_seo_framework()->get_ld_json_links()' );
1056
+
1057
+ return $tsf->get_ld_json_links();
1058
+ }
1059
+
1060
+ /**
1061
+ * Generate LD+Json breadcrumb helper.
1062
+ *
1063
+ * @since 2.4.2
1064
+ * @since 2.9.3 Deprecated.
1065
+ * @deprecated
1066
+ *
1067
+ * @return escaped LD+json search helper string.
1068
+ */
1069
+ public function ld_json_breadcrumbs() {
1070
+
1071
+ $tsf = \the_seo_framework();
1072
+
1073
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs()' );
1074
+
1075
+ return $tsf->get_ld_json_breadcrumbs();
1076
+ }
1077
+
1078
+ /**
1079
+ * Generate post breadcrumb.
1080
+ *
1081
+ * @since 2.6.0
1082
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1083
+ * @since 2.9.3 Deprecated.
1084
+ * @deprecated
1085
+ *
1086
+ * @return string $output The breadcrumb script.
1087
+ */
1088
+ public function ld_json_breadcrumbs_post() {
1089
+
1090
+ $tsf = \the_seo_framework();
1091
+
1092
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_post()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_post()' );
1093
+
1094
+ return $tsf->get_ld_json_breadcrumbs_post();
1095
+ }
1096
+
1097
+ /**
1098
+ * Generate page breadcrumb.
1099
+ *
1100
+ * @since 2.6.0
1101
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1102
+ * @since 2.9.3 Deprecated.
1103
+ * @deprecated
1104
+ *
1105
+ * @return string $output The breadcrumb script.
1106
+ */
1107
+ public function ld_json_breadcrumbs_page() {
1108
+
1109
+ $tsf = \the_seo_framework();
1110
+
1111
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_page()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_page()' );
1112
+
1113
+ return $tsf->get_ld_json_breadcrumbs_page();
1114
+ }
1115
+
1116
+ /**
1117
+ * Return home page item for LD Json Breadcrumbs.
1118
+ *
1119
+ * @since 2.4.2
1120
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1121
+ * @since 2.9.3 Deprecated.
1122
+ * @deprecated
1123
+ * @staticvar string $first_item.
1124
+ *
1125
+ * @param string|null $item_type the breadcrumb item type.
1126
+ * @return string Home Breadcrumb item
1127
+ */
1128
+ public function ld_json_breadcrumb_first( $item_type = null ) {
1129
+
1130
+ $tsf = \the_seo_framework();
1131
+
1132
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_first()', '2.9.3' );
1133
+
1134
+ static $first_item = null;
1135
+
1136
+ if ( isset( $first_item ) )
1137
+ return $first_item;
1138
+
1139
+ if ( is_null( $item_type ) )
1140
+ $item_type = json_encode( 'ListItem' );
1141
+
1142
+ $id = json_encode( $tsf->the_home_url_from_cache() );
1143
+
1144
+ if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1145
+
1146
+ $home_title = $tsf->get_option( 'homepage_title' );
1147
+
1148
+ if ( $home_title ) {
1149
+ $custom_name = $home_title;
1150
+ } elseif ( $tsf->has_page_on_front() ) {
1151
+ $home_id = (int) \get_option( 'page_on_front' );
1152
+
1153
+ $custom_name = $tsf->get_custom_field( '_genesis_title', $home_id ) ?: $tsf->get_blogname();
1154
+ } else {
1155
+ $custom_name = $tsf->get_blogname();
1156
+ }
1157
+ } else {
1158
+ $custom_name = $tsf->get_blogname();
1159
+ }
1160
+
1161
+ $custom_name = json_encode( $custom_name );
1162
+ $image = $this->schema_image( $tsf->get_the_front_page_ID(), true );
1163
+
1164
+ $breadcrumb = array(
1165
+ 'type' => $item_type,
1166
+ 'pos' => '1',
1167
+ 'id' => $id,
1168
+ 'name' => $custom_name,
1169
+ 'image' => $image,
1170
+ );
1171
+
1172
+ return $first_item = $tsf->make_breadcrumb( $breadcrumb, true );
1173
+ }
1174
+
1175
+ /**
1176
+ * Return current page item for LD Json Breadcrumbs.
1177
+ *
1178
+ * @since 2.4.2
1179
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1180
+ * @since 2.9.3 Deprecated.
1181
+ * @deprecated
1182
+ * @staticvar string $last_item.
1183
+ * @staticvar string $type The breadcrumb item type.
1184
+ * @staticvar string $id The current post/page/archive url.
1185
+ * @staticvar string $name The current post/page/archive title.
1186
+ *
1187
+ * @param string $item_type the breadcrumb item type.
1188
+ * @param int $pos Last known position.
1189
+ * @param int $post_id The current Post ID
1190
+ * @return string Last Breadcrumb item
1191
+ */
1192
+ public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
1193
+
1194
+ $tsf = \the_seo_framework();
1195
+
1196
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_last()', '2.9.3' );
1197
+
1198
+ /**
1199
+ * 2 (becomes 3) holds mostly true for single term items.
1200
+ * This shouldn't run anyway. Pos should always be provided.
1201
+ */
1202
+ if ( is_null( $pos ) )
1203
+ $pos = 2;
1204
+
1205
+ //* Add current page.
1206
+ $pos = $pos + 1;
1207
+
1208
+ if ( is_null( $item_type ) ) {
1209
+ static $type = null;
1210
+
1211
+ if ( ! isset( $type ) )
1212
+ $type = json_encode( 'ListItem' );
1213
+
1214
+ $item_type = $type;
1215
+ }
1216
+
1217
+ if ( empty( $post_id ) )
1218
+ $post_id = $tsf->get_the_real_ID();
1219
+
1220
+ static $id = null;
1221
+ static $name = null;
1222
+
1223
+ if ( ! isset( $id ) )
1224
+ $id = json_encode( $tsf->the_url_from_cache() );
1225
+
1226
+ $title_args = array(
1227
+ 'term_id' => $post_id,
1228
+ 'placeholder' => true,
1229
+ 'meta' => true,
1230
+ 'notagline' => true,
1231
+ 'description_title' => true,
1232
+ 'get_custom_field' => false,
1233
+ );
1234
+
1235
+ if ( ! isset( $name ) ) {
1236
+ if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1237
+ $name = $tsf->get_custom_field( '_genesis_title', $post_id ) ?: $tsf->title( '', '', '', $title_args );
1238
+ } else {
1239
+ $name = $tsf->title( '', '', '', $title_args );
1240
+ }
1241
+ $name = json_encode( $name );
1242
+ }
1243
+
1244
+ $image = $this->schema_image( $post_id, true );
1245
+
1246
+ $breadcrumb = array(
1247
+ 'type' => $item_type,
1248
+ 'pos' => (string) $pos,
1249
+ 'id' => $id,
1250
+ 'name' => $name,
1251
+ 'image' => $image,
1252
+ );
1253
+
1254
+ return $this->make_breadcrumb( $breadcrumb, false );
1255
+ }
1256
+
1257
+ /**
1258
+ * Builds a breadcrumb.
1259
+ *
1260
+ * @since 2.6.0
1261
+ * @since 2.9.0 : No longer outputs image if it's not present.
1262
+ * @since 2.9.3 Deprecated.
1263
+ * @deprecated
1264
+ *
1265
+ * @param array $item : {
1266
+ * 'type',
1267
+ * 'pos',
1268
+ * 'id',
1269
+ * 'name'
1270
+ * }
1271
+ * @param bool $comma Whether to add a trailing comma.
1272
+ * @return string The LD+Json breadcrumb.
1273
+ */
1274
+ public function make_breadcrumb( $item, $comma = true ) {
1275
+
1276
+ $tsf = \the_seo_framework();
1277
+
1278
+ $tsf->_deprecated_function( 'the_seo_framework()->make_breadcrumb()', '2.9.3' );
1279
+
1280
+ $comma = $comma ? ',' : '';
1281
+
1282
+ if ( $item['image'] && '""' !== $item['image'] ) {
1283
+ $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
1284
+ } else {
1285
+ $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $comma );
1286
+ }
1287
+
1288
+ return $retval;
1289
+ }
1290
  }
inc/classes/detect.class.php CHANGED
@@ -520,6 +520,7 @@ class Detect extends Render {
520
  * @since 2.8.0 Added check_option parameter.
521
  * @since 2.9.0 Now also checks for subdirectory installations.
522
  * @since 2.9.2 Now also checks for permalinks.
 
523
  *
524
  * @param bool $check_option Whether to check for sitemap option.
525
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
@@ -536,7 +537,7 @@ class Detect extends Render {
536
  return false;
537
 
538
  if ( $check_option ) {
539
- if ( ! $this->is_option_checked( 'sitemaps_output' ) )
540
  return false;
541
  }
542
 
@@ -914,10 +915,12 @@ class Detect extends Render {
914
  }
915
 
916
  /**
917
- * Checks (current) Post Type for if this plugin may use it.
918
  *
919
  * @since 2.6.0
920
- * @staticvar string $cache
 
 
921
  *
922
  * @param bool $public Whether to only get Public Post types.
923
  * @param string $post_type Optional. The post type to check.
@@ -925,6 +928,11 @@ class Detect extends Render {
925
  */
926
  public function get_supported_post_type( $public = true, $post_type = '' ) {
927
 
 
 
 
 
 
928
  if ( empty( $post_type ) ) {
929
  global $current_screen;
930
 
@@ -937,11 +945,6 @@ class Detect extends Render {
937
 
938
  $post_type_evaluated = $post_type;
939
 
940
- static $cache = array();
941
-
942
- if ( isset( $cache[ $public ][ $post_type ] ) )
943
- return $cache[ $public ][ $post_type ];
944
-
945
  $object = \get_post_type_object( $post_type );
946
 
947
  //* Check if rewrite is enabled. Bypass builtin post types.
@@ -970,6 +973,39 @@ class Detect extends Render {
970
  return $cache[ $public ][ $post_type ] = $post_type;
971
  }
972
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  /**
974
  * Determines whether the theme is outputting the title correctly based on transient.
975
  *
520
  * @since 2.8.0 Added check_option parameter.
521
  * @since 2.9.0 Now also checks for subdirectory installations.
522
  * @since 2.9.2 Now also checks for permalinks.
523
+ * @since 2.9.3 Now also checks for sitemap_robots option.
524
  *
525
  * @param bool $check_option Whether to check for sitemap option.
526
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
537
  return false;
538
 
539
  if ( $check_option ) {
540
+ if ( ! $this->is_option_checked( 'sitemaps_output' ) || ! $this->is_option_checked( 'sitemaps_robots' ) )
541
  return false;
542
  }
543
 
915
  }
916
 
917
  /**
918
+ * Checks (current) Post Type for if this plugin may use it for customizable SEO.
919
  *
920
  * @since 2.6.0
921
+ * @since 2.9.3 : Improved caching structure. i.e. it's faster now when no $post_type is supplied.
922
+ * @staticvar array $cache
923
+ * @global object $current_screen
924
  *
925
  * @param bool $public Whether to only get Public Post types.
926
  * @param string $post_type Optional. The post type to check.
928
  */
929
  public function get_supported_post_type( $public = true, $post_type = '' ) {
930
 
931
+ static $cache = array();
932
+
933
+ if ( isset( $cache[ $public ][ $post_type ] ) )
934
+ return $cache[ $public ][ $post_type ];
935
+
936
  if ( empty( $post_type ) ) {
937
  global $current_screen;
938
 
945
 
946
  $post_type_evaluated = $post_type;
947
 
 
 
 
 
 
948
  $object = \get_post_type_object( $post_type );
949
 
950
  //* Check if rewrite is enabled. Bypass builtin post types.
973
  return $cache[ $public ][ $post_type ] = $post_type;
974
  }
975
 
976
+ /**
977
+ * Checks (current) Post Type for taxonomical archives.
978
+ *
979
+ * @since 2.9.3
980
+ * @staticvar array $cache
981
+ * @global object $current_screen
982
+ *
983
+ * @param string $post_type Optional. The post type to check.
984
+ * @return bool True when the post type has taxonomies.
985
+ */
986
+ public function post_type_supports_taxonomies( $post_type = '' ) {
987
+
988
+ static $cache = array();
989
+
990
+ if ( isset( $cache[ $post_type ] ) )
991
+ return $cache[ $post_type ];
992
+
993
+ if ( empty( $post_type ) ) {
994
+ global $current_screen;
995
+
996
+ if ( isset( $current_screen->post_type ) ) {
997
+ $post_type = $current_screen->post_type;
998
+ } else {
999
+ return false;
1000
+ }
1001
+ }
1002
+
1003
+ if ( \get_object_taxonomies( $post_type, 'names' ) )
1004
+ return $cache[ $post_type ] = true;
1005
+
1006
+ return $cache[ $post_type ] = false;
1007
+ }
1008
+
1009
  /**
1010
  * Determines whether the theme is outputting the title correctly based on transient.
1011
  *
inc/classes/doing-it-right.class.php CHANGED
@@ -76,10 +76,14 @@ class Doing_It_Right extends Generate_Ldjson {
76
  $post_id = isset( $post->ID ) ? $post->ID : false;
77
 
78
  if ( $post_id ) {
79
- $searchexclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
 
80
 
81
- if ( $searchexclude )
82
  $states[] = \esc_html__( 'No Search', 'autodescription' );
 
 
 
83
  }
84
 
85
  return $states;
76
  $post_id = isset( $post->ID ) ? $post->ID : false;
77
 
78
  if ( $post_id ) {
79
+ $search_exclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
80
+ $archive_exclude = (bool) $this->get_custom_field( 'exclude_from_archive', $post_id );
81
 
82
+ if ( $search_exclude )
83
  $states[] = \esc_html__( 'No Search', 'autodescription' );
84
+
85
+ if ( $archive_exclude )
86
+ $states[] = \esc_html__( 'No Archive', 'autodescription' );
87
  }
88
 
89
  return $states;
inc/classes/generate-image.class.php CHANGED
@@ -48,6 +48,85 @@ class Generate_Image extends Generate_Url {
48
  parent::__construct();
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  /**
52
  * Returns social image URL and sets $this->image_dimensions.
53
  *
@@ -343,10 +422,11 @@ class Generate_Image extends Generate_Url {
343
  /**
344
  * Fetches image from post thumbnail.
345
  *
346
- * Resizes the image between 1500px if bigger. Then it saves the image and
347
  * Keeps dimensions relative.
348
  *
349
  * @since 2.9.0
 
350
  *
351
  * @param int $id The post ID. Required.
352
  * @param array $args The image args.
@@ -404,9 +484,11 @@ class Generate_Image extends Generate_Url {
404
  * @since 2.8.0 : 1. Removed staticvar.
405
  * 2. Now adds ID call to OG image called listener.
406
  * @since 2.9.0 : Added $set_og_dimension parameter
 
407
  *
408
  * @todo create formula to fetch transient.
409
  * @priority high 2.7.0
 
410
  *
411
  * @param int $id The attachment ID.
412
  * @param array $args The image args
@@ -428,19 +510,22 @@ class Generate_Image extends Generate_Url {
428
  $w = $src[1]; // Width
429
  $h = $src[2]; // Height
430
 
431
- //* Preferred 1500px, resize it
432
- if ( $w > 1500 || $h > 1500 ) :
 
 
 
433
 
434
  if ( $w === $h ) {
435
  //* Square
436
- $w = 1500;
437
- $h = 1500;
438
  } elseif ( $w > $h ) {
439
- //* Landscape, set $w to 1500.
440
- $h = $this->proportionate_dimensions( $h, $w, $w = 1500 );
441
  } elseif ( $h > $w ) {
442
- //* Portrait, set $h to 1500.
443
- $w = $this->proportionate_dimensions( $w, $h, $h = 1500 );
444
  }
445
 
446
  //* Get path of image and load it into the wp_get_image_editor
48
  parent::__construct();
49
  }
50
 
51
+ /**
52
+ * Returns image URL suitable for Schema items.
53
+ *
54
+ * These are images that are strictly assigned to the Post or Page.
55
+ * Themes should compliment these. If not, then Open Graph should at least
56
+ * compliment these.
57
+ * If that's not even true, then I don't know what happens. But then you're
58
+ * in a grey area... @TODO make images optional for Schema?
59
+ *
60
+ * @since 2.9.3
61
+ * @uses $this->get_social_image()
62
+ * @staticvar array $images
63
+ *
64
+ * @TODO support Terms.
65
+ *
66
+ * @param int|string $id The page, post, product or term ID.
67
+ * @param bool $singular Whether the ID is singular or archival.
68
+ * @return string $url The Schema.org safe image.
69
+ */
70
+ public function get_schema_image( $id = 0, $singular = false ) {
71
+
72
+ //= TODO remove this when term images are introduced.
73
+ if ( ! $singular )
74
+ return '';
75
+
76
+ static $images = array();
77
+
78
+ $id = (int) $id;
79
+
80
+ if ( isset( $images[ $id ][ $singular ] ) )
81
+ return $images[ $id ][ $singular ];
82
+
83
+ if ( $singular ) {
84
+ if ( $id === $this->get_the_front_page_ID() ) {
85
+ if ( $this->has_page_on_front() ) {
86
+ $image_args = array(
87
+ 'post_id' => $id,
88
+ 'skip_fallback' => true,
89
+ 'escape' => false,
90
+ );
91
+ } else {
92
+ $image_args = array(
93
+ 'post_id' => $id,
94
+ 'skip_fallback' => true,
95
+ 'disallowed' => array(
96
+ 'postmeta',
97
+ 'featured',
98
+ ),
99
+ 'escape' => false,
100
+ );
101
+ }
102
+ } else {
103
+ $image_args = array(
104
+ 'post_id' => $id,
105
+ 'skip_fallback' => true,
106
+ 'disallowed' => array(
107
+ 'homemeta',
108
+ ),
109
+ 'escape' => false,
110
+ );
111
+ }
112
+ $url = $this->get_social_image( $image_args, false );
113
+ } else {
114
+ //* Placeholder for when Terms get image uploads.
115
+ $url = '';
116
+ }
117
+
118
+ /**
119
+ * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
120
+ * @since 2.7.0
121
+ * @param string $image The current image.
122
+ * @param int $id The page, post, product or term ID.
123
+ * @param bool $singular Whether the ID is singular.
124
+ */
125
+ $url = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $url, $id, $singular );
126
+
127
+ return $images[ $id ][ $singular ] = \esc_url_raw( $url );
128
+ }
129
+
130
  /**
131
  * Returns social image URL and sets $this->image_dimensions.
132
  *
422
  /**
423
  * Fetches image from post thumbnail.
424
  *
425
+ * Resizes the image between 4096px if bigger. Then it saves the image and
426
  * Keeps dimensions relative.
427
  *
428
  * @since 2.9.0
429
+ * @since 2.9.3 Now supports 4K.
430
  *
431
  * @param int $id The post ID. Required.
432
  * @param array $args The image args.
484
  * @since 2.8.0 : 1. Removed staticvar.
485
  * 2. Now adds ID call to OG image called listener.
486
  * @since 2.9.0 : Added $set_og_dimension parameter
487
+ * @since 2.9.3 : 4k baby.
488
  *
489
  * @todo create formula to fetch transient.
490
  * @priority high 2.7.0
491
+ * @prioerity lowered with 4K @ 2.9.3
492
  *
493
  * @param int $id The attachment ID.
494
  * @param array $args The image args
510
  $w = $src[1]; // Width
511
  $h = $src[2]; // Height
512
 
513
+ //* @TODO add filter that can lower it?
514
+ $_size = 4096;
515
+
516
+ //* Preferred 4096px, resize it
517
+ if ( $w > $_size || $h > $_size ) :
518
 
519
  if ( $w === $h ) {
520
  //* Square
521
+ $w = $_size;
522
+ $h = $_size;
523
  } elseif ( $w > $h ) {
524
+ //* Landscape, set $w to 4096.
525
+ $h = $this->proportionate_dimensions( $h, $w, $w = $_size );
526
  } elseif ( $h > $w ) {
527
+ //* Portrait, set $h to 4096.
528
+ $w = $this->proportionate_dimensions( $w, $h, $h = $_size );
529
  }
530
 
531
  //* Get path of image and load it into the wp_get_image_editor
inc/classes/generate-ldjson.class.php CHANGED
@@ -40,11 +40,110 @@ class Generate_Ldjson extends Generate_Image {
40
  }
41
 
42
  /**
43
- * Render the LD+Json scripts.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  *
45
  * @since 2.6.0
46
  *
47
- * @return string The LD+Json scripts.
48
  */
49
  public function render_ld_json_scripts() {
50
 
@@ -53,39 +152,21 @@ class Generate_Ldjson extends Generate_Image {
53
 
54
  $this->setup_ld_json_transient( $this->get_the_real_ID() );
55
 
56
- $this->the_seo_framework_debug and $this->debug_init( __METHOD__, false, $debug_key = microtime( true ), array( 'LD Json transient' => $this->ld_json_transient, 'Output from transient' => false !== $this->get_transient( $this->ld_json_transient ) ) );
57
 
58
  $use_cache = $this->is_option_checked( 'cache_meta_schema' );
59
 
60
  $output = $use_cache ? $this->get_transient( $this->ld_json_transient ) : false;
61
  if ( false === $output ) :
62
-
63
- $output = '';
64
-
65
- //* Only display search helper and knowledge graph on front page.
66
  if ( $this->is_real_front_page() ) {
 
 
67
 
68
- $sitename = $this->ld_json_name();
69
- $sitelinks = $this->ld_json_search();
70
- $knowledgegraph = $this->ld_json_knowledge();
71
-
72
- if ( $sitename )
73
- $output .= $sitename;
74
-
75
- if ( $sitelinks )
76
- $output .= $sitelinks;
77
-
78
- if ( $knowledgegraph )
79
- $output .= $knowledgegraph;
80
-
81
  } else {
82
- $breadcrumbhelper = $this->ld_json_breadcrumbs();
83
-
84
- //* No wrapper, is done within script generator.
85
- if ( $breadcrumbhelper ) {
86
- $output .= $breadcrumbhelper;
87
- $output .= $this->ld_json_name();
88
- }
89
  }
90
 
91
  if ( $use_cache ) {
@@ -105,265 +186,231 @@ class Generate_Ldjson extends Generate_Image {
105
  }
106
 
107
  /**
108
- * Returns http://schema.org json encoded context URL.
109
  *
110
- * @staticvar string $context
111
- * @since 2.6.0
112
  *
113
- * @return string The json encoded context url.
114
  */
115
- public function schema_context() {
116
-
117
- static $context;
118
 
119
- if ( isset( $context ) )
120
- return $context;
121
 
122
- return $context = json_encode( 'http://schema.org' );
123
- }
124
 
125
- /**
126
- * Returns 'WebSite' json encoded type name.
127
- *
128
- * @staticvar string $context
129
- * @since 2.6.0
130
- *
131
- * @return string The json encoded type name.
132
- */
133
- public function schema_type() {
134
 
135
- static $type;
 
 
136
 
137
- if ( isset( $type ) )
138
- return $type;
139
 
140
- return $type = json_encode( 'WebSite' );
141
- }
 
 
 
142
 
143
- /**
144
- * Returns json encoded home url.
145
- *
146
- * @staticvar string $url
147
- * @since 2.6.0
148
- *
149
- * @return string The json encoded home url.
150
- */
151
- public function schema_home_url() {
 
 
 
 
 
 
 
 
152
 
153
- static $type;
 
 
154
 
155
- if ( isset( $type ) )
156
- return $type;
157
 
158
- return $type = json_encode( $this->the_home_url_from_cache() );
159
  }
160
 
161
  /**
162
- * Returns json encoded blogname.
163
  *
164
- * @staticvar string $name
165
- * @since 2.6.0
166
  *
167
- * @return string The json encoded blogname.
168
  */
169
- public function schema_blog_name() {
170
-
171
- static $name;
172
 
173
- if ( isset( $name ) )
174
- return $name;
175
 
176
- return $name = json_encode( $this->get_blogname() );
177
- }
178
 
179
- /**
180
- * Returns 'BreadcrumbList' json encoded type name.
181
- *
182
- * @staticvar string $crumblist
183
- * @since 2.6.0
184
- *
185
- * @return string The json encoded 'BreadcrumbList'.
186
- */
187
- public function schema_breadcrumblist() {
188
 
189
- static $crumblist;
 
 
 
 
 
190
 
191
- if ( isset( $crumblist ) )
192
- return $crumblist;
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
194
- return $crumblist = json_encode( 'BreadcrumbList' );
195
- }
 
 
 
 
 
196
 
197
- /**
198
- * Returns 'ListItem' json encoded type name.
199
- *
200
- * @staticvar string $listitem
201
- * @since 2.6.0
202
- *
203
- * @return string The json encoded 'ListItem'.
204
- */
205
- public function schema_listitem() {
206
 
207
- static $listitem;
 
 
208
 
209
- if ( isset( $listitem ) )
210
- return $listitem;
211
 
212
- return $listitem = json_encode( 'ListItem' );
213
  }
214
 
215
  /**
216
- * Returns 'image' json encoded value.
217
  *
218
- * @staticvar array $images
219
- * @since 2.7.0
220
- * @since 2.9.0 : 1. No longer uses image from cache, instead: it skips fallback images.
221
- * 2. Can now fetch home-page as blog set image.
222
  *
223
- * @param int|string $id The page, post, product or term ID.
224
- * @param bool $singular Whether the ID is singular.
225
  */
226
- public function schema_image( $id = 0, $singular = false ) {
227
-
228
- static $images = array();
229
 
230
- $id = (int) $id;
231
-
232
- if ( isset( $images[ $id ][ $singular ] ) )
233
- return $images[ $id ][ $singular ];
234
 
235
- $image = '';
 
236
 
237
- if ( $singular ) {
238
- if ( $id === $this->get_the_front_page_ID() ) {
239
- if ( $this->has_page_on_front() ) {
240
- $image_args = array(
241
- 'post_id' => $id,
242
- 'skip_fallback' => true,
243
- );
244
- } else {
245
- $image_args = array(
246
- 'post_id' => $id,
247
- 'skip_fallback' => true,
248
- 'disallowed' => array(
249
- 'postmeta',
250
- 'featured',
251
- ),
252
- );
253
- }
254
- } else {
255
- $image_args = array(
256
- 'post_id' => $id,
257
- 'skip_fallback' => true,
258
- 'disallowed' => array(
259
- 'homemeta'
260
- ),
261
- );
262
- }
263
- $image = $this->get_social_image( $image_args );
264
- } else {
265
- //* Placeholder.
266
- $image = '';
267
  }
268
 
269
- /**
270
- * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
271
- * @since 2.7.0
272
- * @param string $image The current image.
273
- * @param int $id The page, post, product or term ID.
274
- * @param bool $singular Whether the ID is singular.
275
- */
276
- $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
277
-
278
- return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
279
  }
280
 
281
  /**
282
- * Generate LD+Json search helper.
283
  *
284
- * @since 2.2.8
285
  *
286
- * @return escaped LD+json search helper string.
287
  */
288
- public function ld_json_search() {
289
-
290
- if ( false === $this->enable_ld_json_searchbox() )
291
- return '';
292
 
293
- $context = $this->schema_context();
294
- $webtype = $this->schema_type();
295
- $url = $this->schema_home_url();
296
- $name = $this->schema_blog_name();
297
- $actiontype = json_encode( 'SearchAction' );
298
-
299
- /**
300
- * Applies filters 'the_seo_framework_ld_json_search_url' : string
301
- * @since 2.7.0
302
- * @param string $search_url The default WordPress search URL without query parameters.
303
- */
304
- $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $this->the_home_url_from_cache( true ) . '?s=' );
305
 
306
- // Remove trailing quote and add it back.
307
- $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
308
 
309
- $queryaction = json_encode( 'required name=search_term_string' );
 
 
310
 
311
- $json = sprintf( '{"@context":%s,"@type":%s,"url":%s,"name":%s,"potentialAction":{"@type":%s,"target":%s,"query-input":%s}}', $context, $webtype, $url, $name, $actiontype, $target, $queryaction );
312
 
313
- $output = '';
314
- if ( $json )
315
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
 
 
316
 
317
- return $output;
318
- }
319
 
320
- /**
321
- * Generate LD+Json breadcrumb helper.
322
- *
323
- * @since 2.4.2
324
- *
325
- * @return escaped LD+json search helper string.
326
- */
327
- public function ld_json_breadcrumbs() {
328
 
329
- if ( false === $this->enable_ld_json_breadcrumbs() )
330
- return '';
331
 
332
- //* Used to count ancestors and categories.
333
- $output = '';
334
 
335
- if ( $this->is_single() || $this->is_wc_product() ) {
336
- $output = $this->ld_json_breadcrumbs_post();
337
- } elseif ( false === $this->is_real_front_page() && $this->is_page() ) {
338
- $output = $this->ld_json_breadcrumbs_page();
339
  }
340
 
341
  return $output;
342
  }
343
 
344
  /**
345
- * Generate post breadcrumb.
346
  *
347
- * @since 2.6.0
348
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
349
  *
350
- * @return string $output The breadcrumb script.
351
  */
352
- public function ld_json_breadcrumbs_post() {
353
 
354
  $output = '';
355
 
356
  $post_id = $this->get_the_real_ID();
357
 
358
- $cat_type = 'category';
359
-
360
  //* WooCommerce support.
361
- if ( $this->is_wc_product() )
362
- $cat_type = 'product_cat';
363
 
364
  //* Test categories.
365
  $r = \is_object_in_term( $post_id, $cat_type, '' );
366
-
367
  if ( ! $r || \is_wp_error( $r ) )
368
  return '';
369
 
@@ -371,8 +418,8 @@ class Generate_Ldjson extends Generate_Image {
371
  * Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
372
  * @since 2.8.0
373
  *
374
- * @param array $cats The LD+Json terms that are being used
375
- * @param int $post_id The current Post ID.
376
  * @param string $cat_type The current taxonomy (either category or product_cat).
377
  */
378
  $cats = (array) \apply_filters_ref_array( 'the_seo_framework_ld_json_breadcrumb_terms', array( \get_the_terms( $post_id, $cat_type ), $post_id, $cat_type ) );
@@ -390,23 +437,37 @@ class Generate_Ldjson extends Generate_Image {
390
 
391
  //* Fetch cats children id's, if any.
392
  foreach ( $cats as $term_id => $parent_id ) :
393
- //* Warning: This makes database calls...
394
- if ( ! \term_exists( $term_id, $cat_type, $parent_id ) )
395
- continue;
396
 
397
- //* Store to filter unused Cat ID's from the post.
 
398
  $assigned_ids[] = $term_id;
399
 
400
- // Check if they have kittens.
401
  $children = \get_term_children( $term_id, $cat_type );
402
- $ancestors = \get_ancestors( $term_id, $cat_type );
 
 
 
 
 
 
 
 
 
403
 
404
- //* Save children id's as kittens.
405
- $kittens[ $term_id ] = $children;
406
- $parents[ $term_id ] = $ancestors;
 
 
 
407
  endforeach;
 
408
  unset( $cats );
409
 
 
 
 
410
  foreach ( $kittens as $kit_id => $child_id ) :
411
  foreach ( $child_id as $ckey => $cid ) :
412
 
@@ -414,7 +475,7 @@ class Generate_Ldjson extends Generate_Image {
414
  * Seed out children that aren't assigned.
415
  * (from levels too deep as get_term_children gets them all).
416
  */
417
- if ( $cid && false === in_array( $cid, $assigned_ids, true ) )
418
  unset( $kittens[ $kit_id ][ $ckey ] );
419
 
420
  /**
@@ -444,7 +505,7 @@ class Generate_Ldjson extends Generate_Image {
444
  /**
445
  * Build category ID trees for kittens.
446
  */
447
- $trees = $this->build_breadcrumb_trees( $kittens );
448
 
449
  //* Empty parents.
450
  $parents = array();
@@ -468,235 +529,170 @@ class Generate_Ldjson extends Generate_Image {
468
  //* Temporarily array.
469
  $kitten[ $pid ] = $parents_ids;
470
 
471
- $trees = $this->build_breadcrumb_trees( $kitten, $trees );
472
  } else {
473
  //* Parents are reversed children. Let's fix that.
474
  $parents_ids = array_reverse( $parents_ids );
475
 
476
- $trees = $this->build_breadcrumb_trees( $parents_ids, $trees );
477
  }
478
  }
479
  endif;
480
 
 
 
 
481
  /**
482
  * Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
483
  */
484
  if ( count( $trees ) > 1 ) :
485
- /**
486
- * Applies filter 'the_seo_framework_breadcrumb_post_sorting_callback' : string|array
487
- * @since 2.8.0
488
- *
489
- * @param mixed $function The method or function callback. Default false.
490
- * @param array $trees The current tree list.
491
- */
492
- $callback_filter = \apply_filters_ref_array( 'the_seo_framework_breadcrumb_post_sorting_callback', array( false, $trees ) );
493
- if ( $callback_filter ) {
 
 
 
 
494
  $trees = $this->call_function( $callback_filter, '2.8.0', $trees );
495
  } else {
496
  array_multisort( array_map( 'count', $trees ), SORT_DESC, SORT_REGULAR, $trees );
497
  }
498
  endif;
499
 
500
- $item_type = $this->schema_listitem();
 
501
 
502
  //* For each of the tree items, create a separated script.
503
- if ( $trees ) :
504
- foreach ( $trees as $tree_ids ) :
505
-
506
- if ( is_array( $tree_ids ) ) {
507
- //* Term has assigned children.
508
-
509
- /**
510
- * @staticvar int $item_cache : Used to prevent duplicated item re-generation.
511
- */
512
- static $item_cache = array();
513
-
514
- $items = '';
515
-
516
- //* Put the children in the right order.
517
- $tree_ids = array_reverse( $tree_ids, false );
518
-
519
- foreach ( $tree_ids as $position => $child_id ) :
520
- if ( in_array( $child_id, $assigned_ids, true ) ) :
521
- //* Cat has been assigned, continue.
522
-
523
- //* Fetch item from cache if available.
524
- if ( isset( $item_cache[ $child_id ] ) ) {
525
- $pos = $position + 2;
526
- $item_cache[ $child_id ]['pos'] = $pos;
527
- $items .= $this->make_breadcrumb( $item_cache[ $child_id ], true );
528
- } else {
529
- $pos = $position + 2;
530
-
531
- $cat = \get_term_by( 'id', $child_id, $cat_type, OBJECT, 'raw' );
532
- $data = $this->get_term_data( $cat, $child_id );
533
-
534
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'is_term' => true, 'term' => $cat ) ) );
535
-
536
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
537
- //* Note: WordPress Core translation.
538
- $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
539
- } else {
540
- //* Note: WordPress Core translation.
541
- $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
542
- }
543
- $name = json_encode( $cat_name );
544
-
545
- $image = $this->schema_image( $child_id );
546
-
547
- //* Store in cache.
548
- $item_cache[ $child_id ] = array(
549
- 'type' => $item_type,
550
- 'pos' => (string) $pos,
551
- 'id' => $id,
552
- 'name' => $name,
553
- 'image' => $image,
554
- );
555
-
556
- $items .= $this->make_breadcrumb( $item_cache[ $child_id ], true );
557
- }
558
- endif;
559
- endforeach;
560
-
561
- if ( $items ) {
562
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $post_id );
563
- $output .= $this->make_breadcrumb_script( $items );
564
- }
565
- } else {
566
- //* No assigned children, single term item.
567
 
568
- //* The position of the current item is always static here.
569
- $pos = '2';
570
 
571
- $image = $this->schema_image( $tree_ids );
 
 
 
 
 
 
572
 
573
- //* $tree_ids is a single ID here.
574
- $cat = \get_term_by( 'id', $tree_ids, $cat_type, OBJECT, 'raw' );
575
- $data = $this->get_term_data( $cat, $tree_ids );
576
 
577
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
578
 
579
  if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
580
  //* Note: WordPress Core translation.
 
581
  $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
582
  } else {
583
  //* Note: WordPress Core translation.
584
  $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
585
  }
586
- $name = json_encode( $cat_name );
587
-
588
- $item = array(
589
- 'type' => $item_type,
590
- 'pos' => (string) $pos,
591
- 'id' => $id,
592
- 'name' => $name,
593
- 'image' => $image,
594
- );
595
 
596
- $items = $this->make_breadcrumb( $item, true );
 
 
 
 
 
 
 
 
 
597
 
598
- if ( $items ) {
599
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $post_id );
600
- $output .= $this->make_breadcrumb_script( $items );
601
- }
602
  }
603
  endforeach;
604
- endif;
 
 
 
 
 
 
605
 
606
  return $output;
607
  }
608
 
609
  /**
610
- * Generate page breadcrumb.
611
  *
612
- * @since 2.6.0
613
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
614
  *
615
- * @return string $output The breadcrumb script.
 
 
616
  */
617
- public function ld_json_breadcrumbs_page() {
618
-
619
- $output = '';
620
 
621
- $page_id = $this->get_the_real_ID();
622
-
623
- //* Get ancestors.
624
- $parents = \get_post_ancestors( $page_id );
625
-
626
- if ( $parents ) :
627
-
628
- $item_type = $this->schema_listitem();
629
-
630
- $items = '';
631
-
632
- $parents = array_reverse( $parents );
633
-
634
- foreach ( $parents as $position => $parent_id ) {
635
- $pos = $position + 2;
636
-
637
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ) );
638
-
639
- $title_args = array(
640
- 'term_id' => $parent_id,
641
- 'meta' => true,
642
- 'placeholder' => true,
643
- 'notagline' => true,
644
- 'description_title' => true,
645
- 'get_custom_field' => false,
646
- );
647
 
648
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
649
- $parent_name = $this->get_custom_field( '_genesis_title', $parent_id ) ?: $this->title( '', '', '', $title_args );
 
 
 
 
 
 
650
  } else {
651
- $parent_name = $this->title( '', '', '', $title_args );
652
- }
653
-
654
- $name = json_encode( $parent_name );
655
- $image = $this->schema_image( $parent_id, true );
656
-
657
- $breadcrumb = array(
658
- 'type' => $item_type,
659
- 'pos' => (string) $pos,
660
- 'id' => $id,
661
- 'name' => $name,
662
- 'image' => $image,
663
- );
664
 
665
- $items .= $this->make_breadcrumb( $breadcrumb, true );
666
- }
 
 
 
667
 
668
- if ( $items ) {
 
669
 
670
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $page_id );
671
- $output = $this->make_breadcrumb_script( $items );
672
  }
673
- endif;
674
 
675
- return $output;
676
  }
677
 
678
  /**
679
- * Return home page item for LD Json Breadcrumbs.
680
  *
681
- * @since 2.4.2
682
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
683
- * @staticvar string $first_item.
684
  *
685
- * @param string|null $item_type the breadcrumb item type.
686
- * @return string Home Breadcrumb item
687
  */
688
- public function ld_json_breadcrumb_first( $item_type = null ) {
689
 
690
- static $first_item = null;
691
 
692
- if ( isset( $first_item ) )
693
- return $first_item;
694
 
695
- if ( is_null( $item_type ) )
696
- $item_type = json_encode( 'ListItem' );
697
-
698
- $id = json_encode( $this->the_home_url_from_cache() );
699
 
 
700
  if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
701
 
702
  $home_title = $this->get_option( 'homepage_title' );
@@ -704,201 +700,110 @@ class Generate_Ldjson extends Generate_Image {
704
  if ( $home_title ) {
705
  $custom_name = $home_title;
706
  } elseif ( $this->has_page_on_front() ) {
707
- $home_id = (int) \get_option( 'page_on_front' );
708
-
709
- $custom_name = $this->get_custom_field( '_genesis_title', $home_id ) ?: $this->get_blogname();
710
- } else {
711
- $custom_name = $this->get_blogname();
712
  }
713
- } else {
714
- $custom_name = $this->get_blogname();
715
  }
716
 
717
- $custom_name = json_encode( $custom_name );
718
- $image = $this->schema_image( $this->get_the_front_page_ID(), true );
719
 
720
- $breadcrumb = array(
721
- 'type' => $item_type,
722
- 'pos' => '1',
723
- 'id' => $id,
724
- 'name' => $custom_name,
725
- 'image' => $image,
 
726
  );
727
 
728
- return $first_item = $this->make_breadcrumb( $breadcrumb, true );
 
 
 
729
  }
730
 
731
  /**
732
- * Return current page item for LD Json Breadcrumbs.
733
  *
734
- * @since 2.4.2
735
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
736
- * @staticvar string $last_item.
737
- * @staticvar string $type The breadcrumb item type.
738
- * @staticvar string $id The current post/page/archive url.
739
- * @staticvar string $name The current post/page/archive title.
740
  *
741
- * @param string $item_type the breadcrumb item type.
742
- * @param int $pos Last known position.
743
- * @param int $post_id The current Post ID
744
- * @return string Last Breadcrumb item
745
  */
746
- public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
747
 
748
- /**
749
- * 2 (becomes 3) holds mostly true for single term items.
750
- * This shouldn't run anyway. Pos should always be provided.
751
- */
752
- if ( is_null( $pos ) )
753
- $pos = 2;
754
 
755
- //* Add current page.
756
- $pos = $pos + 1;
757
 
758
- if ( is_null( $item_type ) ) {
759
- static $type = null;
760
-
761
- if ( ! isset( $type ) )
762
- $type = json_encode( 'ListItem' );
763
-
764
- $item_type = $type;
765
  }
766
 
767
- if ( empty( $post_id ) )
768
- $post_id = $this->get_the_real_ID();
769
-
770
- static $id = null;
771
- static $name = null;
772
-
773
- if ( ! isset( $id ) )
774
- $id = json_encode( $this->the_url_from_cache() );
775
-
776
- $title_args = array(
777
- 'term_id' => $post_id,
778
- 'placeholder' => true,
779
- 'meta' => true,
780
- 'notagline' => true,
781
- 'description_title' => true,
782
- 'get_custom_field' => false,
783
- );
784
 
785
- if ( ! isset( $name ) ) {
786
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
787
- $name = $this->get_custom_field( '_genesis_title', $post_id ) ?: $this->title( '', '', '', $title_args );
788
- } else {
789
- $name = $this->title( '', '', '', $title_args );
790
- }
791
- $name = json_encode( $name );
792
  }
793
 
794
- $image = $this->schema_image( $post_id, true );
795
-
796
- $breadcrumb = array(
797
- 'type' => $item_type,
798
- 'pos' => (string) $pos,
799
- 'id' => $id,
800
- 'name' => $name,
801
- 'image' => $image,
802
  );
803
 
804
- return $this->make_breadcrumb( $breadcrumb, false );
805
- }
806
 
807
- /**
808
- * Builds a breadcrumb.
809
- *
810
- * @since 2.6.0
811
- * @since 2.9.0 : No longer outputs image if it's not present.
812
- * @param array $item : {
813
- * 'type',
814
- * 'pos',
815
- * 'id',
816
- * 'name'
817
- * }
818
- * @param bool $comma Whether to add a trailing comma.
819
- * @return string The LD+Json breadcrumb.
820
- */
821
- public function make_breadcrumb( $item, $comma = true ) {
822
-
823
- $comma = $comma ? ',' : '';
824
-
825
- if ( $item['image'] && '""' !== $item['image'] ) {
826
- $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
827
- } else {
828
- $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $comma );
829
- }
830
-
831
- return $retval;
832
  }
833
 
834
  /**
835
- * Puts breadcrumb items in script wrapper.
836
  *
837
  * @since 2.9.0
 
 
838
  *
839
- * @param string $items The breadcrumb items
840
- * @return string The breadcrumb script tag.
841
  */
842
- protected function make_breadcrumb_script( $items = '' ) {
843
-
844
- if ( $items ) {
845
- $context = $this->schema_context();
846
- $context_type = $this->schema_breadcrumblist();
847
-
848
- //* Put it all together.
849
- $breadcrumbhelper = sprintf( '{"@context":%s,"@type":%s,"itemListElement":[%s]}', $context, $context_type, $items );
850
- return '<script type="application/ld+json">' . $breadcrumbhelper . '</script>' . "\r\n";
851
- }
852
 
853
- return '';
854
- }
855
 
856
- /**
857
- * Builds breadcrumb trees.
858
- *
859
- * @since 2.6.0
860
- *
861
- * @param array $kittens The breadcrumb trees, with the key as parent.
862
- * @param array $previous_tree A previous set tree to compare to, if set.
863
- * @return array Trees in order.
864
- */
865
- protected function build_breadcrumb_trees( $kittens, array $previous_tree = array() ) {
866
 
867
- $trees = $previous_tree;
868
 
869
- foreach ( $kittens as $parent => $kitten ) {
870
- if ( empty( $kitten ) ) {
871
- //* Final cat.
872
- $trees[] = $parent;
873
- } else {
874
- if ( 1 === count( $kitten ) ) {
875
- //* Single tree.
876
- $trees[] = array( reset( $kitten ), $parent );
877
- } else {
878
- //* Nested categories.
879
- $add = array();
880
 
881
- foreach ( $kitten as $kit_id => $child_id ) {
882
- //* Only add if non-existent in $trees.
883
- if ( ! in_array( $child_id, $trees, true ) )
884
- $add[] = $child_id;
885
- }
886
 
887
- //* Put children in right order.
888
- $add = array_reverse( $add );
889
 
890
- $trees[] = array_merge( $add, array( $parent ) );
891
- }
892
- }
893
- }
894
 
895
- return $trees;
896
  }
897
 
898
  /**
899
  * Determines whether to use the SEO title or only the fallback page title.
900
  *
901
- * Does not affect cache.
902
  *
903
  * @since 2.9.0
904
  * @staticvar bool $cache
@@ -915,137 +820,12 @@ class Generate_Ldjson extends Generate_Image {
915
  * Determines whether to use the SEO title or only the fallback page title
916
  * in breadcrumbs.
917
  *
918
- * @param $retval bool
 
919
  */
920
  return isset( $cache ) ? $cache : $cache = (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true );
921
  }
922
 
923
- /**
924
- * Return LD+Json Knowledge Graph helper.
925
- *
926
- * @since 2.2.8
927
- * @since 2.9.2 : Now grabs home URL from cache.
928
- *
929
- * @return string LD+json Knowledge Graph helper.
930
- */
931
- public function ld_json_knowledge() {
932
-
933
- if ( false === $this->enable_ld_json_knowledge() )
934
- return '';
935
-
936
- $knowledge_type = $this->get_option( 'knowledge_type' );
937
-
938
- /**
939
- * Forgot to add this.
940
- * @since 2.4.3
941
- */
942
- $knowledge_name = $this->get_option( 'knowledge_name' ) ?: $this->get_blogname();
943
-
944
- $context = $this->schema_context();
945
- $type = json_encode( ucfirst( $knowledge_type ) );
946
- $name = json_encode( $knowledge_name );
947
- $url = $this->schema_home_url();
948
-
949
- $logo = '';
950
-
951
- if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
952
- $_logo = $this->get_site_logo() ?: $this->get_site_icon();
953
-
954
- if ( $_logo ) {
955
- $logourl = \esc_url_raw( $_logo );
956
-
957
- //* Add trailing comma
958
- $logo = '"logo":' . json_encode( $logourl );
959
- }
960
- }
961
-
962
- /**
963
- * Applies filters 'the_seo_framework_json_options' : array The option names
964
- * @since ???
965
- * @todo Document.
966
- */
967
- $options = (array) \apply_filters( 'the_seo_framework_json_options', array(
968
- 'knowledge_facebook',
969
- 'knowledge_twitter',
970
- 'knowledge_gplus',
971
- 'knowledge_instagram',
972
- 'knowledge_youtube',
973
- 'knowledge_linkedin',
974
- 'knowledge_pinterest',
975
- 'knowledge_soundcloud',
976
- 'knowledge_tumblr',
977
- ) );
978
-
979
- $sameurls = '';
980
- $comma = ',';
981
-
982
- //* Put the urls together from the options.
983
- if ( is_array( $options ) ) {
984
- foreach ( $options as $option ) {
985
- $the_option = $this->get_option( $option );
986
-
987
- if ( '' !== $the_option )
988
- $sameurls .= json_encode( $the_option ) . $comma;
989
- }
990
- }
991
-
992
- //* Remove trailing comma
993
- $sameurls = rtrim( $sameurls, $comma );
994
- $json = '';
995
-
996
- $logo = $logo ? ',' . $logo : '';
997
-
998
- if ( $sameurls ) {
999
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s,"sameAs":[%s]}', $context, $type, $name, $url, $logo, $sameurls );
1000
- } else {
1001
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s}', $context, $type, $name, $url, $logo );
1002
- }
1003
-
1004
- $output = '';
1005
- if ( $json )
1006
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1007
-
1008
- return $output;
1009
- }
1010
-
1011
- /**
1012
- * Generate Site Name LD+Json script.
1013
- *
1014
- * @since 2.6.0
1015
- *
1016
- * @return string The LD+JSon Site Name script.
1017
- */
1018
- public function ld_json_name() {
1019
-
1020
- if ( false === $this->enable_ld_json_sitename() )
1021
- return '';
1022
-
1023
- $context = $this->schema_context();
1024
- $webtype = $this->schema_type();
1025
- $url = $this->schema_home_url();
1026
- $name = $this->schema_blog_name();
1027
- $alternate = '';
1028
-
1029
- $blogname = $this->get_blogname();
1030
- $knowledge_name = $this->get_option( 'knowledge_name' );
1031
-
1032
- if ( $knowledge_name && $knowledge_name !== $blogname ) {
1033
- $alternate = json_encode( \esc_html( $knowledge_name ) );
1034
- }
1035
-
1036
- if ( $alternate ) {
1037
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"alternateName":%s,"url":%s}', $context, $webtype, $name, $alternate, $url );
1038
- } else {
1039
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s}', $context, $webtype, $name, $url );
1040
- }
1041
-
1042
- $output = '';
1043
- if ( $json )
1044
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1045
-
1046
- return $output;
1047
- }
1048
-
1049
  /**
1050
  * Determines if breadcrumbs scripts are enabled.
1051
  *
40
  }
41
 
42
  /**
43
+ * Builds up JSON data.
44
+ *
45
+ * NOTE: Array indexes with falsy values will be stripped.
46
+ * `[ 'key' => (string) 'false' ]` will pass.
47
+ * `[ 'key' => '0' ]` will not pass.
48
+ *
49
+ * @since 2.9.3
50
+ * @see $this->receive_json_data()
51
+ * @uses $this->build_json_data_cache()
52
+ *
53
+ * @param string $key The JSON data key.
54
+ * @param array $data The JSON data.
55
+ */
56
+ public function build_json_data( $key, array $data ) {
57
+
58
+ $key = \sanitize_key( $key );
59
+ $data = array_filter( $data );
60
+
61
+ foreach ( $data as $k => $v ) {
62
+ $thing = array( $k => $v );
63
+ $this->build_json_data_cache( $key, $thing );
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Returns built JSON data.
69
+ *
70
+ * May return empty values if data is invalid.
71
+ *
72
+ * @since 2.9.3
73
+ * @see $this->build_json_data()
74
+ * @uses $this->cache_json_data()
75
+ *
76
+ * @param string $key The JSON data key.
77
+ * @param bool $encode Whether to JSON encode the output.
78
+ * @return array|string The JSON data for $key. Array if $encode is false, string otherwise.
79
+ */
80
+ public function receive_json_data( $key, $encode = true ) {
81
+
82
+ $key = \sanitize_key( $key );
83
+ $data = $this->cache_json_data( true, $key );
84
+
85
+ if ( \has_filter( 'the_seo_framework_receive_json_data' ) ) {
86
+ /**
87
+ * Applies filters 'the_seo_framework_recieve_json_data'
88
+ *
89
+ * @since 2.9.3
90
+ *
91
+ * @param array $data The LD-JSON data.
92
+ * @param string $key The data key.
93
+ */
94
+ $data = (array) \apply_filters_ref_array( 'the_seo_framework_receive_json_data', array( $data, $key ) );
95
+ }
96
+
97
+ if ( $encode )
98
+ return $data ? (string) json_encode( $data ) : '';
99
+
100
+ return $data ?: array();
101
+ }
102
+
103
+ /**
104
+ * Builds up JSON data cache.
105
+ *
106
+ * @since 2.9.3
107
+ * @see $this->build_json_data()
108
+ *
109
+ * @param string $key The JSON data key.
110
+ * @param array $entry The JSON data entry.
111
+ * @return array The JSON data for $key.
112
+ */
113
+ protected function build_json_data_cache( $key, array $entry ) {
114
+ $this->cache_json_data( false, $key, $entry );
115
+ }
116
+
117
+ /**
118
+ * Builds up JSON data cache.
119
+ *
120
+ * @since 2.9.3
121
+ * @see $this->build_json_data()
122
+ * @see $this->receive_json_data()
123
+ *
124
+ * @param bool $get Whether to get or otherwise set the data.
125
+ * @param string $key The JSON data key.
126
+ * @param array $entry The JSON data entry.
127
+ * @return array The JSON data for $key.
128
+ */
129
+ protected function cache_json_data( $get = true, $key = '', array $entry = array() ) {
130
+
131
+ static $data = array();
132
+
133
+ if ( $get )
134
+ return $data[ $key ];
135
+
136
+ $data[ $key ][ key( $entry ) ] = reset( $entry );
137
+
138
+ return array();
139
+ }
140
+
141
+ /**
142
+ * Renders the LD+JSON scripts.
143
  *
144
  * @since 2.6.0
145
  *
146
+ * @return string The LD+JSON scripts.
147
  */
148
  public function render_ld_json_scripts() {
149
 
152
 
153
  $this->setup_ld_json_transient( $this->get_the_real_ID() );
154
 
155
+ $this->the_seo_framework_debug and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), array( 'LD Json transient' => $this->ld_json_transient, 'Output from transient' => false !== $this->get_transient( $this->ld_json_transient ) ) );
156
 
157
  $use_cache = $this->is_option_checked( 'cache_meta_schema' );
158
 
159
  $output = $use_cache ? $this->get_transient( $this->ld_json_transient ) : false;
160
  if ( false === $output ) :
 
 
 
 
161
  if ( $this->is_real_front_page() ) {
162
+ //= Home page Schema.
163
+ $output = '';
164
 
165
+ $output .= $this->get_ld_json_website() ?: '';
166
+ $output .= $this->get_ld_json_links() ?: '';
 
 
 
 
 
 
 
 
 
 
 
167
  } else {
168
+ //= All other pages' Schema.
169
+ $output = $this->get_ld_json_breadcrumbs() ?: '';
 
 
 
 
 
170
  }
171
 
172
  if ( $use_cache ) {
186
  }
187
 
188
  /**
189
+ * Generates LD+JSON Search and Sitename script.
190
  *
191
+ * @since 2.9.3
 
192
  *
193
+ * @return escaped LD+JSON Search and Sitename script.
194
  */
195
+ public function get_ld_json_website() {
 
 
196
 
197
+ $use_sitename = $this->enable_ld_json_sitename();
198
+ $use_searchbox = $this->enable_ld_json_searchbox();
199
 
200
+ if ( false === $use_sitename && false === $use_searchbox )
201
+ return '';
202
 
203
+ $data = array(
204
+ '@context' => 'http://schema.org',
205
+ '@type' => 'WebSite',
206
+ 'url' => $this->the_home_url_from_cache(),
207
+ );
 
 
 
 
208
 
209
+ if ( $use_sitename ) {
210
+ $name = $this->get_blogname();
211
+ $kn = $this->get_option( 'knowledge_name' );
212
 
213
+ $alternate_name = $kn && $kn !== $name ? $kn : '';
 
214
 
215
+ $data += array(
216
+ 'name' => $this->escape_title( $name ),
217
+ 'alternateName' => $this->escape_title( $alternate_name ),
218
+ );
219
+ }
220
 
221
+ if ( $use_searchbox ) {
222
+ $action_name = 'search_term_string';
223
+ /**
224
+ * Applies filters 'the_seo_framework_ld_json_search_url' : string
225
+ * @since 2.7.0
226
+ * @param string $search_url The default WordPress search URL without query parameters.
227
+ */
228
+ $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', \get_search_link() );
229
+
230
+ $data += array(
231
+ 'potentialAction' => array(
232
+ '@type' => 'SearchAction',
233
+ 'target' => sprintf( '%s{%s}', \esc_url( $search_url ), $action_name ),
234
+ 'query-input' => sprintf( 'required name=%s', $action_name ),
235
+ ),
236
+ );
237
+ }
238
 
239
+ $key = 'WebSite';
240
+ $this->build_json_data( $key, $data );
241
+ $json = $this->receive_json_data( $key );
242
 
243
+ if ( $json )
244
+ return '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
245
 
246
+ return '';
247
  }
248
 
249
  /**
250
+ * Generates LD+JSON Social Profile Links script.
251
  *
252
+ * @since 2.9.3
 
253
  *
254
+ * @return string LD+JSON Social Profile Links script.
255
  */
256
+ public function get_ld_json_links() {
 
 
257
 
258
+ if ( false === $this->enable_ld_json_knowledge() )
259
+ return '';
260
 
261
+ $knowledge_type = $this->get_option( 'knowledge_type' );
262
+ $knowledge_name = $this->get_option( 'knowledge_name' ) ?: $this->get_blogname();
263
 
264
+ $data = array(
265
+ '@context' => 'http://schema.org',
266
+ '@type' => ucfirst( \esc_attr( $knowledge_type ) ),
267
+ 'url' => $this->the_home_url_from_cache(),
268
+ 'name' => $this->escape_title( $knowledge_name ),
269
+ );
 
 
 
270
 
271
+ if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
272
+ $logo = $this->get_site_logo() ?: $this->get_site_icon();
273
+ $data += array(
274
+ 'logo' => \esc_url_raw( $logo ),
275
+ );
276
+ }
277
 
278
+ /**
279
+ * Applies filters 'the_seo_framework_json_options' : array The option names
280
+ * @since Unknown. Definitely 2.7 or later.
281
+ */
282
+ $sameurls_options = (array) \apply_filters( 'the_seo_framework_json_options', array(
283
+ 'knowledge_facebook',
284
+ 'knowledge_twitter',
285
+ 'knowledge_gplus',
286
+ 'knowledge_instagram',
287
+ 'knowledge_youtube',
288
+ 'knowledge_linkedin',
289
+ 'knowledge_pinterest',
290
+ 'knowledge_soundcloud',
291
+ 'knowledge_tumblr',
292
+ ) );
293
 
294
+ $sameurls = array();
295
+ foreach ( $sameurls_options as $_o ) {
296
+ $_ov = $this->get_option( $_o ) ?: '';
297
+ //* Sublevel array entries aren't getting caught by array_filter().
298
+ if ( $_ov )
299
+ $sameurls[] = \esc_url_raw( $_ov, array( 'https', 'http' ) );
300
+ }
301
 
302
+ if ( $sameurls ) {
303
+ $data += array(
304
+ 'sameAs' => $sameurls,
305
+ );
306
+ }
 
 
 
 
307
 
308
+ $key = 'Links';
309
+ $this->build_json_data( $key, $data );
310
+ $json = $this->receive_json_data( $key );
311
 
312
+ if ( $json )
313
+ return '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
314
 
315
+ return '';
316
  }
317
 
318
  /**
319
+ * Generates LD+JSON Breadcrumbs script.
320
  *
321
+ * @since 2.9.3
 
 
 
322
  *
323
+ * @return escaped LD+JSON Breadcrumbs script.
 
324
  */
325
+ public function get_ld_json_breadcrumbs() {
 
 
326
 
327
+ if ( false === $this->enable_ld_json_breadcrumbs() )
328
+ return '';
 
 
329
 
330
+ //* Used to count ancestors and categories.
331
+ $output = '';
332
 
333
+ if ( $this->is_single() || $this->is_wc_product() ) {
334
+ $output = $this->get_ld_json_breadcrumbs_post();
335
+ } elseif ( false === $this->is_real_front_page() && $this->is_page() ) {
336
+ $output = $this->get_ld_json_breadcrumbs_page();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  }
338
 
339
+ return $output;
 
 
 
 
 
 
 
 
 
340
  }
341
 
342
  /**
343
+ * Generates LD+JSON Breadcrumbs script for Pages.
344
  *
345
+ * @since 2.9.3
346
  *
347
+ * @return escaped LD+JSON breadcrumbs script for Pages.
348
  */
349
+ public function get_ld_json_breadcrumbs_page() {
 
 
 
350
 
351
+ $page_id = $this->get_the_real_ID();
352
+ //* Get ancestors.
353
+ $parents = \get_post_ancestors( $page_id );
 
 
 
 
 
 
 
 
 
354
 
355
+ if ( ! $parents )
356
+ return '';
357
 
358
+ $output = '';
359
+ $items = array();
360
+ $parents = array_reverse( $parents );
361
 
362
+ foreach ( $parents as $pos => $parent_id ) {
363
 
364
+ if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
365
+ $parent_name = $this->get_custom_field( '_genesis_title', $parent_id ) ?: ( $this->post_title_from_ID( $parent_id ) ?: $this->untitled() );
366
+ } else {
367
+ $parent_name = $this->post_title_from_ID( $parent_id ) ?: $this->untitled();
368
+ }
369
 
370
+ $position = $pos + 2;
 
371
 
372
+ $crumb = array(
373
+ '@type' => 'ListItem',
374
+ 'position' => $position,
375
+ 'item' => array(
376
+ '@id' => $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ),
377
+ 'name' => $this->escape_title( $parent_name ),
378
+ ),
379
+ );
380
 
381
+ if ( $image = $this->get_schema_image( $parent_id ) )
382
+ $crumb['item']['image'] = $image;
383
 
384
+ $items[] = $crumb;
385
+ }
386
 
387
+ if ( $items ) {
388
+ array_unshift( $items, $this->get_ld_json_breadcrumb_home_crumb() );
389
+ array_push( $items, $this->get_ld_json_breadcrumb_current( $position ) );
390
+ $output .= $this->make_breadcrumb_script( $items );
391
  }
392
 
393
  return $output;
394
  }
395
 
396
  /**
397
+ * Generates LD+JSON Breadcrumbs script for Posts.
398
  *
399
+ * @since 2.9.3
 
400
  *
401
+ * @return escaped LD+JSON breadcrumbs script for Posts.
402
  */
403
+ public function get_ld_json_breadcrumbs_post() {
404
 
405
  $output = '';
406
 
407
  $post_id = $this->get_the_real_ID();
408
 
 
 
409
  //* WooCommerce support.
410
+ $cat_type = $this->is_wc_product() ? 'product_cat' : 'category';
 
411
 
412
  //* Test categories.
413
  $r = \is_object_in_term( $post_id, $cat_type, '' );
 
414
  if ( ! $r || \is_wp_error( $r ) )
415
  return '';
416
 
418
  * Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
419
  * @since 2.8.0
420
  *
421
+ * @param array $cats The LD+JSON terms that are being used
422
+ * @param int $post_id The current Post ID.
423
  * @param string $cat_type The current taxonomy (either category or product_cat).
424
  */
425
  $cats = (array) \apply_filters_ref_array( 'the_seo_framework_ld_json_breadcrumb_terms', array( \get_the_terms( $post_id, $cat_type ), $post_id, $cat_type ) );
437
 
438
  //* Fetch cats children id's, if any.
439
  foreach ( $cats as $term_id => $parent_id ) :
 
 
 
440
 
441
+ //* Store all used IDs to compare and filter stray Cat ID's later.
442
+ //= i.e. $kittens => $term_id_1 => $term_id_maybe_unassigned_to_post.
443
  $assigned_ids[] = $term_id;
444
 
445
+ // Check if they have kittens (gets them all).
446
  $children = \get_term_children( $term_id, $cat_type );
447
+ if ( ! \is_wp_error( $children ) ) {
448
+ /**
449
+ * Save children id's as kittens.
450
+ * Although stray terms don't have children, we assign them as
451
+ * $kittens are also the latest version (even if $children === 0).
452
+ *
453
+ * This gets filtered later.
454
+ */
455
+ $kittens[ $term_id ] = $children;
456
+ }
457
 
458
+ // Check if they have parents (gets them all).
459
+ $ancestors = \get_ancestors( $term_id, $cat_type );
460
+ if ( $ancestors ) {
461
+ //= Save parents to find duplicates.
462
+ $parents[ $term_id ] = $ancestors;
463
+ }
464
  endforeach;
465
+ //= Circle of life...
466
  unset( $cats );
467
 
468
+ if ( ! $kittens )
469
+ return '';
470
+
471
  foreach ( $kittens as $kit_id => $child_id ) :
472
  foreach ( $child_id as $ckey => $cid ) :
473
 
475
  * Seed out children that aren't assigned.
476
  * (from levels too deep as get_term_children gets them all).
477
  */
478
+ if ( $cid && ! in_array( $cid, $assigned_ids, true ) )
479
  unset( $kittens[ $kit_id ][ $ckey ] );
480
 
481
  /**
505
  /**
506
  * Build category ID trees for kittens.
507
  */
508
+ $trees = $this->build_ld_json_breadcrumb_trees( $kittens );
509
 
510
  //* Empty parents.
511
  $parents = array();
529
  //* Temporarily array.
530
  $kitten[ $pid ] = $parents_ids;
531
 
532
+ $trees = $this->build_ld_json_breadcrumb_trees( $kitten, $trees );
533
  } else {
534
  //* Parents are reversed children. Let's fix that.
535
  $parents_ids = array_reverse( $parents_ids );
536
 
537
+ $trees = $this->build_ld_json_breadcrumb_trees( $parents_ids, $trees );
538
  }
539
  }
540
  endif;
541
 
542
+ if ( ! $trees )
543
+ return '';
544
+
545
  /**
546
  * Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
547
  */
548
  if ( count( $trees ) > 1 ) :
549
+ $cb_filter = null;
550
+ if ( \has_filter( 'the_seo_framework_breadcrumb_post_sorting_callback' ) ) {
551
+ /**
552
+ * Applies filter 'the_seo_framework_breadcrumb_post_sorting_callback' : string|array
553
+ * @since 2.8.0
554
+ *
555
+ * @param mixed $function The method or function callback. Default false.
556
+ * @param array $trees The current tree list.
557
+ */
558
+ $cb_filter = \apply_filters_ref_array( 'the_seo_framework_breadcrumb_post_sorting_callback', array( false, $trees ) );
559
+ }
560
+
561
+ if ( $cb_filter ) {
562
  $trees = $this->call_function( $callback_filter, '2.8.0', $trees );
563
  } else {
564
  array_multisort( array_map( 'count', $trees ), SORT_DESC, SORT_REGULAR, $trees );
565
  }
566
  endif;
567
 
568
+ if ( ! $trees )
569
+ return '';
570
 
571
  //* For each of the tree items, create a separated script.
572
+ foreach ( $trees as $tree_ids ) :
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
 
574
+ if ( is_scalar( $tree_ids ) )
575
+ $tree_ids = array( $tree_ids );
576
 
577
+ /**
578
+ * @staticvar int $item_cache
579
+ * Used to prevent duplicated item re-generation.
580
+ */
581
+ static $item_cache = array();
582
+
583
+ $items = array();
584
 
585
+ //* Put the children in the right order.
586
+ $tree_ids = array_reverse( $tree_ids, false );
 
587
 
588
+ foreach ( $tree_ids as $pos => $child_id ) :
589
+ if ( ! in_array( $child_id, $assigned_ids, true ) )
590
+ continue;
591
+
592
+ $position = $pos + 2;
593
+
594
+ //* Fetch item from cache if available.
595
+ if ( isset( $item_cache[ $child_id ] ) ) {
596
+ //* Adjust postition.
597
+ $item_cache[ $child_id ]['position'] = $position;
598
+ $items[] = $item_cache[ $child_id ];
599
+ } else {
600
+ $cat = \get_term( $child_id, $cat_type );
601
 
602
  if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
603
  //* Note: WordPress Core translation.
604
+ $data = $this->get_term_data( $cat, $child_id );
605
  $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
606
  } else {
607
  //* Note: WordPress Core translation.
608
  $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
609
  }
 
 
 
 
 
 
 
 
 
610
 
611
+ //* Store in cache.
612
+ $item_cache[ $child_id ] = array(
613
+ '@type' => 'ListItem',
614
+ 'position' => $position,
615
+ 'item' => array(
616
+ '@id' => $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ),
617
+ 'name' => $this->escape_title( $cat_name ),
618
+ // 'image' => $this->get_schema_image( $child_id ),
619
+ ),
620
+ );
621
 
622
+ $items[] = $item_cache[ $child_id ];
 
 
 
623
  }
624
  endforeach;
625
+
626
+ if ( $items ) {
627
+ array_unshift( $items, $this->get_ld_json_breadcrumb_home_crumb() );
628
+ array_push( $items, $this->get_ld_json_breadcrumb_current( $position ) );
629
+ $output .= $this->make_breadcrumb_script( $items );
630
+ }
631
+ endforeach;
632
 
633
  return $output;
634
  }
635
 
636
  /**
637
+ * Builds breadcrumb trees.
638
  *
639
+ * @since 2.9.3
 
640
  *
641
+ * @param array $kittens The breadcrumb trees, with the key as parent.
642
+ * @param array $previous_tree A previous set tree to compare to, if set.
643
+ * @return array Trees in order.
644
  */
645
+ protected function build_ld_json_breadcrumb_trees( $kittens, array $previous_tree = array() ) {
 
 
646
 
647
+ $trees = $previous_tree;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
 
649
+ foreach ( $kittens as $parent => $kitten ) {
650
+ if ( empty( $kitten ) ) {
651
+ //* Final cat.
652
+ $trees[] = $parent;
653
+ } else {
654
+ if ( 1 === count( $kitten ) ) {
655
+ //* Single tree.
656
+ $trees[] = array( reset( $kitten ), $parent );
657
  } else {
658
+ //* Nested categories.
659
+ $add = array();
 
 
 
 
 
 
 
 
 
 
 
660
 
661
+ foreach ( $kitten as $kit_id => $child_id ) {
662
+ //* Only add if non-existent in $trees.
663
+ if ( ! in_array( $child_id, $trees, true ) )
664
+ $add[] = $child_id;
665
+ }
666
 
667
+ //* Put children in right order.
668
+ $add = array_reverse( $add );
669
 
670
+ $trees[] = array_merge( $add, array( $parent ) );
671
+ }
672
  }
673
+ }
674
 
675
+ return $trees;
676
  }
677
 
678
  /**
679
+ * Generates homepage LD+JSON breadcrumb.
680
  *
681
+ * @since 2.9.3
682
+ * @staticvar array $crumb
 
683
  *
684
+ * @return array The HomePage crumb entry.
 
685
  */
686
+ public function get_ld_json_breadcrumb_home_crumb() {
687
 
688
+ static $crumb = null;
689
 
690
+ if ( isset( $crumb ) )
691
+ return $crumb;
692
 
693
+ $front_id = $this->get_the_front_page_ID();
 
 
 
694
 
695
+ $custom_name = '';
696
  if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
697
 
698
  $home_title = $this->get_option( 'homepage_title' );
700
  if ( $home_title ) {
701
  $custom_name = $home_title;
702
  } elseif ( $this->has_page_on_front() ) {
703
+ $custom_name = $this->get_custom_field( '_genesis_title', $front_id ) ?: $this->get_blogname();
 
 
 
 
704
  }
 
 
705
  }
706
 
707
+ $custom_name = $custom_name ?: $this->get_blogname();
 
708
 
709
+ $crumb = array(
710
+ '@type' => 'ListItem',
711
+ 'position' => 1,
712
+ 'item' => array(
713
+ '@id' => $this->the_home_url_from_cache(),
714
+ 'name' => $custom_name,
715
+ ),
716
  );
717
 
718
+ if ( $image = $this->get_schema_image( $front_id, true ) )
719
+ $crumb['item']['image'] = $image;
720
+
721
+ return $crumb;
722
  }
723
 
724
  /**
725
+ * Generates current Page/Post LD+JSON breadcrumb.
726
  *
727
+ * @since 2.9.3
728
+ * @staticvar array $crumb
 
 
 
 
729
  *
730
+ * @param int $position The previous crumb position.
731
+ * @return array The Current Page/Post crumb entry.
 
 
732
  */
733
+ public function get_ld_json_breadcrumb_current( $position ) {
734
 
735
+ static $crumb = null;
 
 
 
 
 
736
 
737
+ $position++;
 
738
 
739
+ if ( isset( $crumb ) ) {
740
+ $crumb['position'] = $position;
741
+ return $crumb;
 
 
 
 
742
  }
743
 
744
+ $post_id = $this->get_the_real_ID();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
 
746
+ if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
747
+ $name = $this->get_custom_field( '_genesis_title', $post_id ) ?: ( $this->post_title_from_ID( $post_id ) ?: $this->untitled() );
748
+ } else {
749
+ $name = $this->post_title_from_ID( $post_id ) ?: $this->untitled();
 
 
 
750
  }
751
 
752
+ $crumb = array(
753
+ '@type' => 'ListItem',
754
+ 'position' => $position,
755
+ 'item' => array(
756
+ '@id' => $this->the_url_from_cache(),
757
+ 'name' => $name,
758
+ ),
 
759
  );
760
 
761
+ if ( $image = $this->get_schema_image( $post_id, true ) )
762
+ $crumb['item']['image'] = $image;
763
 
764
+ return $crumb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
765
  }
766
 
767
  /**
768
+ * Creates LD+JSON Breadcrumb script from items.
769
  *
770
  * @since 2.9.0
771
+ * @since 2.9.3 : Rewritten to conform to the new generator.
772
+ * @staticvar int $it The iteration count for script generation cache busting.
773
  *
774
+ * @param array $items The LD+JSON breadcrumb items.
775
+ * @return string The LD+JSON Breadcrumb script.
776
  */
777
+ protected function make_breadcrumb_script( $items ) {
 
 
 
 
 
 
 
 
 
778
 
779
+ if ( ! $items )
780
+ return '';
781
 
782
+ static $it = 0;
 
 
 
 
 
 
 
 
 
783
 
784
+ $key = 'Breadcrumbs_' . $it;
785
 
786
+ $data = array(
787
+ '@context' => 'http://schema.org',
788
+ '@type' => 'BreadcrumbList',
789
+ 'itemListElement' => $items,
790
+ );
 
 
 
 
 
 
791
 
792
+ $this->build_json_data( $key, $data );
793
+ $json = $this->receive_json_data( $key );
 
 
 
794
 
795
+ $it++;
 
796
 
797
+ if ( $json )
798
+ return '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
 
 
799
 
800
+ return '';
801
  }
802
 
803
  /**
804
  * Determines whether to use the SEO title or only the fallback page title.
805
  *
806
+ * NOTE: Does not affect transient cache.
807
  *
808
  * @since 2.9.0
809
  * @staticvar bool $cache
820
  * Determines whether to use the SEO title or only the fallback page title
821
  * in breadcrumbs.
822
  *
823
+ * @since 2.9.0
824
+ * @param bool $retval
825
  */
826
  return isset( $cache ) ? $cache : $cache = (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true );
827
  }
828
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
829
  /**
830
  * Determines if breadcrumbs scripts are enabled.
831
  *
inc/classes/generate-title.class.php CHANGED
@@ -443,7 +443,7 @@ class Generate_Title extends Generate_Description {
443
  $title = $this->do_title_pre_filter( '', $args, false );
444
  $blogname = '';
445
 
446
- $is_front_page = $args['page_on_front'] || $this->is_real_front_page() || ( $this->is_front_page_by_id( $args['term_id'] ) && ! $this->is_archive() );
447
 
448
  $seplocation = $this->get_title_seplocation( $seplocation );
449
 
@@ -1210,11 +1210,11 @@ class Generate_Title extends Generate_Description {
1210
  $post = \get_post( $id, OBJECT );
1211
 
1212
  if ( isset( $post->post_password ) && '' !== $post->post_password ) {
1213
- /* translators: Front-end output */
1214
  $protected_title_format = (string) \apply_filters( 'protected_title_format', \__( 'Protected: %s', 'autodescription' ), $post );
1215
  $title = sprintf( $protected_title_format, $title );
1216
  } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
1217
- /* translators: Front-end output */
1218
  $private_title_format = (string) \apply_filters( 'private_title_format', \__( 'Private: %s', 'autodescription' ), $post );
1219
  $title = sprintf( $private_title_format, $title );
1220
  }
443
  $title = $this->do_title_pre_filter( '', $args, false );
444
  $blogname = '';
445
 
446
+ $is_front_page = $args['page_on_front'] || $this->is_real_front_page() || $this->is_front_page_by_id( $args['term_id'] );
447
 
448
  $seplocation = $this->get_title_seplocation( $seplocation );
449
 
1210
  $post = \get_post( $id, OBJECT );
1211
 
1212
  if ( isset( $post->post_password ) && '' !== $post->post_password ) {
1213
+ /* translators: Front-end output. */
1214
  $protected_title_format = (string) \apply_filters( 'protected_title_format', \__( 'Protected: %s', 'autodescription' ), $post );
1215
  $title = sprintf( $protected_title_format, $title );
1216
  } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
1217
+ /* translators: Front-end output. */
1218
  $private_title_format = (string) \apply_filters( 'private_title_format', \__( 'Private: %s', 'autodescription' ), $post );
1219
  $title = sprintf( $private_title_format, $title );
1220
  }
inc/classes/generate-url.class.php CHANGED
@@ -192,10 +192,10 @@ class Generate_Url extends Generate_Title {
192
  }
193
 
194
  if ( $this->pretty_permalinks ) {
195
- $url = \esc_url( $url );
196
  } else {
197
  //* Keep the &'s more readable.
198
- $url = \esc_url_raw( $url );
199
  }
200
 
201
  $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, false, $debug_key, array( 'url_output' => $url ) );
@@ -339,8 +339,10 @@ class Generate_Url extends Generate_Title {
339
  //* Nothing to see here...
340
  $path = '';
341
  }
 
 
 
342
  else :
343
-
344
  /**
345
  * Reworked to use the $args['id'] check based on get_the_real_ID.
346
  * @since 2.6.0 & 2.6.2
@@ -770,11 +772,13 @@ class Generate_Url extends Generate_Title {
770
  if ( 0 === $post_id )
771
  $post_id = $this->get_the_real_ID();
772
 
 
773
  $url = $this->the_url_from_cache( '', $post_id, false, false, false );
774
  $query = parse_url( $url, PHP_URL_QUERY );
775
 
776
  $additions = '';
777
- if ( isset( $query ) ) {
 
778
  if ( false !== strpos( $query, '&' ) ) {
779
  $query = explode( '&', $query );
780
  } else {
@@ -803,7 +807,7 @@ class Generate_Url extends Generate_Title {
803
  $home_url = $this->the_home_url_from_cache( true );
804
  $url = $home_url . $path . $additions;
805
 
806
- return \esc_url_raw( $url );
807
  }
808
 
809
  /**
@@ -824,7 +828,7 @@ class Generate_Url extends Generate_Title {
824
  $next = '';
825
 
826
  if ( $this->is_singular() ) :
827
- if ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
828
  $output_singular_paged = $this->is_option_checked( 'prev_next_frontpage' );
829
  } else {
830
  $output_singular_paged = $this->is_option_checked( 'prev_next_posts' );
@@ -877,10 +881,10 @@ class Generate_Url extends Generate_Title {
877
  endif;
878
 
879
  if ( $prev )
880
- return $this->set_preferred_url_scheme( \esc_url_raw( $prev ) );
881
 
882
  if ( $next )
883
- return $this->set_preferred_url_scheme( \esc_url_raw( $next ) );
884
 
885
  return '';
886
  }
192
  }
193
 
194
  if ( $this->pretty_permalinks ) {
195
+ $url = \esc_url( $url, array( 'http', 'https' ) );
196
  } else {
197
  //* Keep the &'s more readable.
198
+ $url = \esc_url_raw( $url, array( 'http', 'https' ) );
199
  }
200
 
201
  $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, false, $debug_key, array( 'url_output' => $url ) );
339
  //* Nothing to see here...
340
  $path = '';
341
  }
342
+ elseif ( $this->is_search() ) :
343
+ $_url = \get_search_link();
344
+ $path = $this->set_url_scheme( $_url, 'relative' );
345
  else :
 
346
  /**
347
  * Reworked to use the $args['id'] check based on get_the_real_ID.
348
  * @since 2.6.0 & 2.6.2
772
  if ( 0 === $post_id )
773
  $post_id = $this->get_the_real_ID();
774
 
775
+ //* Get additional public queries from the page URL.
776
  $url = $this->the_url_from_cache( '', $post_id, false, false, false );
777
  $query = parse_url( $url, PHP_URL_QUERY );
778
 
779
  $additions = '';
780
+ if ( ! empty( $query ) ) {
781
+
782
  if ( false !== strpos( $query, '&' ) ) {
783
  $query = explode( '&', $query );
784
  } else {
807
  $home_url = $this->the_home_url_from_cache( true );
808
  $url = $home_url . $path . $additions;
809
 
810
+ return \esc_url_raw( $url, array( 'http', 'https' ) );
811
  }
812
 
813
  /**
828
  $next = '';
829
 
830
  if ( $this->is_singular() ) :
831
+ if ( $this->is_real_front_page() || $this->is_static_frontpage( $post_id ) ) {
832
  $output_singular_paged = $this->is_option_checked( 'prev_next_frontpage' );
833
  } else {
834
  $output_singular_paged = $this->is_option_checked( 'prev_next_posts' );
881
  endif;
882
 
883
  if ( $prev )
884
+ return $this->set_preferred_url_scheme( \esc_url_raw( $prev, array( 'http', 'https' ) ) );
885
 
886
  if ( $next )
887
+ return $this->set_preferred_url_scheme( \esc_url_raw( $next, array( 'http', 'https' ) ) );
888
 
889
  return '';
890
  }
inc/classes/init.class.php CHANGED
@@ -247,6 +247,9 @@ class Init extends Query {
247
  */
248
  \add_action( 'pre_get_posts', array( $this, 'adjust_search_filter' ), 9999, 1 );
249
 
 
 
 
250
  /**
251
  * Outputs sitemap or stylesheet on request.
252
  *
@@ -276,24 +279,34 @@ class Init extends Query {
276
  //* Edit the robots.txt file
277
  \add_filter( 'robots_txt', array( $this, 'robots_txt' ), 10, 2 );
278
 
279
- //* Removes all pre_get_document_title filters.
280
- \remove_all_filters( 'pre_get_document_title', false );
281
-
282
- //* New WordPress 4.4.0 filter. Hurray! It's also much faster :)
283
- \add_filter( 'pre_get_document_title', array( $this, 'title_from_cache' ), 10 );
284
- //* Override AnsPress Theme Title
285
- \add_filter( 'ap_title', array( $this, 'title_from_cache' ), 99, 1 );
286
- //* Override Woo Themes Title
287
- \add_filter( 'woo_title', array( $this, 'title_from_cache' ), 99 );
288
-
289
  /**
290
- * Applies filters 'the_seo_framework_manipulate_title' : boolean
291
- * Disables the title tag manipulation on old themes.
292
- * @since 2.4.1
 
293
  */
294
- if ( (bool) \apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
295
- //* Override WordPress Title
296
- \add_filter( 'wp_title', array( $this, 'title_from_cache' ), 9, 3 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  }
298
  }
299
 
@@ -381,8 +394,8 @@ class Init extends Query {
381
  $before_actions = $this->header_actions( '', true );
382
 
383
  //* Limit processing on 404 or search
384
- if ( $this->is_404() || $this->is_search() ) :
385
- $output = $this->og_locale()
386
  . $this->og_type()
387
  . $this->og_title()
388
  . $this->og_url()
@@ -392,8 +405,13 @@ class Init extends Query {
392
  . $this->bing_site_output()
393
  . $this->yandex_site_output()
394
  . $this->pint_site_output();
 
 
 
 
 
395
  else :
396
- $output = $this->the_description()
397
  . $this->og_image()
398
  . $this->og_locale()
399
  . $this->og_type()
@@ -528,6 +546,7 @@ class Init extends Query {
528
  * non-administrative endpoints.
529
  *
530
  * @since 2.2.9
 
531
  * @uses robots_txt filter located at WP core
532
  *
533
  * @param string $robots_txt The current robots_txt output.
@@ -539,7 +558,7 @@ class Init extends Query {
539
  /**
540
  * Don't do anything if the blog isn't public.
541
  */
542
- if ( '0' === $public )
543
  return $robots_txt;
544
 
545
  if ( $this->use_object_cache ) {
@@ -620,17 +639,16 @@ class Init extends Query {
620
  public function adjust_search_filter( $query ) {
621
 
622
  // Don't exclude pages in wp-admin.
623
- if ( $query->is_search && false === $this->is_admin() ) {
624
 
625
- $q = $query->query;
626
  //* Only interact with an actual Search Query.
627
- if ( false === isset( $q['s'] ) )
628
  return;
629
 
630
  $meta_query = $query->get( 'meta_query' );
631
 
632
  //* Convert to array. Unset it if it's empty.
633
- if ( false === is_array( $meta_query ) )
634
  $meta_query = $meta_query ? (array) $meta_query : array();
635
 
636
  /**
@@ -651,4 +669,44 @@ class Init extends Query {
651
  $query->set( 'meta_query', $meta_query );
652
  }
653
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  }
247
  */
248
  \add_action( 'pre_get_posts', array( $this, 'adjust_search_filter' ), 9999, 1 );
249
 
250
+ //* Adjusts archives output based on options.
251
+ \add_action( 'pre_get_posts', array( $this, 'adjust_archive_query' ), 9999, 1 );
252
+
253
  /**
254
  * Outputs sitemap or stylesheet on request.
255
  *
279
  //* Edit the robots.txt file
280
  \add_filter( 'robots_txt', array( $this, 'robots_txt' ), 10, 2 );
281
 
 
 
 
 
 
 
 
 
 
 
282
  /**
283
+ * Applies filters 'the_seo_framework_overwrite_titles'
284
+ *
285
+ * @since 2.9.3
286
+ * @param bool $overwrite_titles
287
  */
288
+ $overwrite_titles = \apply_filters( 'the_seo_framework_overwrite_titles', true );
289
+
290
+ if ( $overwrite_titles ) {
291
+ //* Removes all pre_get_document_title filters.
292
+ \remove_all_filters( 'pre_get_document_title', false );
293
+
294
+ //* New WordPress 4.4.0 filter. Hurray! It's also much faster :)
295
+ \add_filter( 'pre_get_document_title', array( $this, 'title_from_cache' ), 10 );
296
+ //* Override AnsPress Theme Title
297
+ \add_filter( 'ap_title', array( $this, 'title_from_cache' ), 99, 1 );
298
+ //* Override Woo Themes Title
299
+ \add_filter( 'woo_title', array( $this, 'title_from_cache' ), 99 );
300
+
301
+ /**
302
+ * Applies filters 'the_seo_framework_manipulate_title' : boolean
303
+ * Disables the title tag manipulation on old themes.
304
+ * @since 2.4.1
305
+ */
306
+ if ( \apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
307
+ //* Override WordPress Title
308
+ \add_filter( 'wp_title', array( $this, 'title_from_cache' ), 9, 3 );
309
+ }
310
  }
311
  }
312
 
394
  $before_actions = $this->header_actions( '', true );
395
 
396
  //* Limit processing on 404 or search
397
+ if ( $this->is_search() ) :
398
+ $output = $this->og_locale()
399
  . $this->og_type()
400
  . $this->og_title()
401
  . $this->og_url()
405
  . $this->bing_site_output()
406
  . $this->yandex_site_output()
407
  . $this->pint_site_output();
408
+ elseif ( $this->is_404() ) :
409
+ $output = $this->google_site_output()
410
+ . $this->bing_site_output()
411
+ . $this->yandex_site_output()
412
+ . $this->pint_site_output();
413
  else :
414
+ $output = $this->the_description()
415
  . $this->og_image()
416
  . $this->og_locale()
417
  . $this->og_type()
546
  * non-administrative endpoints.
547
  *
548
  * @since 2.2.9
549
+ * @since 2.9.3 Casts $public to string for check.
550
  * @uses robots_txt filter located at WP core
551
  *
552
  * @param string $robots_txt The current robots_txt output.
558
  /**
559
  * Don't do anything if the blog isn't public.
560
  */
561
+ if ( '0' === (string) $public )
562
  return $robots_txt;
563
 
564
  if ( $this->use_object_cache ) {
639
  public function adjust_search_filter( $query ) {
640
 
641
  // Don't exclude pages in wp-admin.
642
+ if ( $query->is_search && ! $this->is_admin() ) {
643
 
 
644
  //* Only interact with an actual Search Query.
645
+ if ( ! isset( $query->query['s'] ) )
646
  return;
647
 
648
  $meta_query = $query->get( 'meta_query' );
649
 
650
  //* Convert to array. Unset it if it's empty.
651
+ if ( ! is_array( $meta_query ) )
652
  $meta_query = $meta_query ? (array) $meta_query : array();
653
 
654
  /**
669
  $query->set( 'meta_query', $meta_query );
670
  }
671
  }
672
+
673
+ /**
674
+ * Excludes posts from Archive results with certain metadata.
675
+ * For now, it only looks at 'exclude_from_archive'. If it exists, the post or
676
+ * page will be excluded from the Archive Results.
677
+ *
678
+ * @since 2.9.3
679
+ *
680
+ * @param array $query The possible archive query.
681
+ * @return void Early if no archive query is found.
682
+ */
683
+ public function adjust_archive_query( $query ) {
684
+
685
+ // Don't exclude pages in wp-admin.
686
+ if ( ( $query->is_archive || $query->is_home ) && ! $this->is_admin() ) {
687
+
688
+ $meta_query = $query->get( 'meta_query' );
689
+
690
+ //* Convert to array. Unset it if it's empty.
691
+ if ( ! is_array( $meta_query ) )
692
+ $meta_query = $meta_query ? (array) $meta_query : array();
693
+
694
+ /**
695
+ * Exclude posts with exclude_from_archive option on.
696
+ *
697
+ * Query is faster when the global relation is not set. Defaults to AND.
698
+ * Query is faster when no value is set. Defaults to 'IS NULL' because
699
+ * of 'compare'. Having no effect whatsoever as it's an exclusion.
700
+ */
701
+ $meta_query[] = array(
702
+ array(
703
+ 'key' => 'exclude_from_archive',
704
+ 'type' => 'NUMERIC',
705
+ 'compare' => 'NOT EXISTS',
706
+ ),
707
+ );
708
+
709
+ $query->set( 'meta_query', $meta_query );
710
+ }
711
+ }
712
  }
inc/classes/post-data.class.php CHANGED
@@ -83,6 +83,7 @@ class Post_Data extends Detect {
83
  * Some values get sanitized, the rest are pulled from identically named subkeys in the $_POST['autodescription'] array.
84
  *
85
  * @since 2.0.0
 
86
  * @uses $this->save_custom_fields() : Perform security checks and saves post meta / custom field data to a post or page.
87
  *
88
  * @param integer $post_id Post ID.
@@ -111,6 +112,7 @@ class Post_Data extends Detect {
111
  '_genesis_nofollow' => 0,
112
  '_genesis_noarchive' => 0,
113
  'exclude_local_search' => 0,
 
114
  ) );
115
 
116
  foreach ( (array) $data as $key => $value ) :
@@ -147,6 +149,7 @@ class Post_Data extends Detect {
147
  case '_genesis_nofollow' :
148
  case '_genesis_noarchive' :
149
  case 'exclude_local_search' :
 
150
  $data[ $key ] = $this->s_one_zero( $value );
151
  continue 2;
152
 
@@ -380,54 +383,32 @@ class Post_Data extends Detect {
380
  * Fetch latest public post ID.
381
  *
382
  * @since 2.4.3
383
- * @staticvar int $page_id
384
- * @global object $wpdb
385
- * @global int $blog_id
386
- *
387
- * @TODO use get_post() or WP_Query.
388
  *
389
  * @return int Latest Post ID.
390
  */
391
  public function get_latest_post_id() {
392
- global $wpdb, $blog_id;
393
-
394
- static $page_id = null;
395
-
396
- if ( isset( $page_id ) )
397
- return $page_id;
398
-
399
- $latest_posts_key = 'latest_post_id_' . $blog_id;
400
-
401
- //* @TODO consider transient.
402
- $page_id = $this->object_cache_get( $latest_posts_key );
403
- if ( false === $page_id ) {
404
-
405
- //* Prepare array
406
- $post_type = \esc_sql( array( 'post', 'page' ) );
407
- $post_type_in_string = "'" . implode( "','", $post_type ) . "'";
408
-
409
- //* Prepare array
410
- $post_status = \esc_sql( array( 'publish', 'future', 'pending' ) );
411
- $post_status_in_string = "'" . implode( "','", $post_status ) . "'";
412
-
413
- $sql = $wpdb->prepare(
414
- "SELECT ID
415
- FROM $wpdb->posts
416
- WHERE post_title <> %s
417
- AND post_type IN ($post_type_in_string)
418
- AND post_date < NOW()
419
- AND post_status IN ($post_status_in_string)
420
- ORDER BY post_date DESC
421
- LIMIT %d",
422
- '',
423
- 1
424
- );
425
 
426
- $page_id = (int) $wpdb->get_var( $sql );
427
- $this->object_cache_set( $latest_posts_key, $page_id, DAY_IN_SECONDS );
428
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
429
 
430
- return $page_id;
431
  }
432
 
433
  /**
83
  * Some values get sanitized, the rest are pulled from identically named subkeys in the $_POST['autodescription'] array.
84
  *
85
  * @since 2.0.0
86
+ * @since 2.9.3 : Added 'exclude_from_archive'.
87
  * @uses $this->save_custom_fields() : Perform security checks and saves post meta / custom field data to a post or page.
88
  *
89
  * @param integer $post_id Post ID.
112
  '_genesis_nofollow' => 0,
113
  '_genesis_noarchive' => 0,
114
  'exclude_local_search' => 0,
115
+ 'exclude_from_archive' => 0,
116
  ) );
117
 
118
  foreach ( (array) $data as $key => $value ) :
149
  case '_genesis_nofollow' :
150
  case '_genesis_noarchive' :
151
  case 'exclude_local_search' :
152
+ case 'exclude_from_archive' :
153
  $data[ $key ] = $this->s_one_zero( $value );
154
  continue 2;
155
 
383
  * Fetch latest public post ID.
384
  *
385
  * @since 2.4.3
386
+ * @since 2.9.3 : 1. Removed object caching.
387
+ * : 2. It now uses WP_Query, instead of wpdb.
388
+ * @staticvar int $post_id
 
 
389
  *
390
  * @return int Latest Post ID.
391
  */
392
  public function get_latest_post_id() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
 
394
+ static $post_id = null;
395
+
396
+ if ( null !== $post_id )
397
+ return $post_id;
398
+
399
+ $query = new \WP_Query( array(
400
+ 'posts_per_page' => 1,
401
+ 'post_type' => array( 'post', 'page' ),
402
+ 'orderby' => 'date',
403
+ 'order' => 'DESC',
404
+ 'post_status' => array( 'publish', 'future', 'pending' ),
405
+ 'fields' => 'ids',
406
+ 'cache_results' => false,
407
+ 'suppress_filters' => true,
408
+ 'no_found_rows' => true,
409
+ ) );
410
 
411
+ return $post_id = reset( $query->posts );
412
  }
413
 
414
  /**
inc/classes/query.class.php CHANGED
@@ -577,8 +577,9 @@ class Query extends Compat {
577
  * Returns true if on SEO settings page and when ID is 0.
578
  *
579
  * @since 2.9.0
 
580
  *
581
- * @param int The page ID, required.
582
  * @return bool True if ID if for the home page.
583
  */
584
  public function is_front_page_by_id( $id ) {
@@ -589,24 +590,30 @@ class Query extends Compat {
589
  return $cache;
590
 
591
  $is_front_page = false;
 
592
 
593
  //* Elegant Themes Support. Yay.
594
  if ( 0 === $id && $this->is_home() ) {
595
- $sof = \get_option( 'show_on_front' );
596
-
597
  if ( 'page' !== $sof && 'posts' !== $sof )
598
  $is_front_page = true;
599
  }
600
 
601
  //* Compare against $id
602
  if ( false === $is_front_page ) {
603
- $sof = \get_option( 'show_on_front' );
604
-
605
- if ( 'page' === $sof && (int) \get_option( 'page_on_front' ) === $id )
606
- $is_front_page = true;
607
-
608
- if ( 'posts' === $sof && (int) \get_option( 'page_for_posts' ) === $id )
609
- $is_front_page = true;
 
 
 
 
 
 
 
610
  }
611
 
612
  if ( false === $is_front_page && 0 === $id && $this->is_seo_settings_page() )
@@ -1002,12 +1009,16 @@ class Query extends Compat {
1002
  * @since 2.6.0
1003
  * @since 2.7.0 Added secure parameter.
1004
  * @since 2.9.0 If $secure is false, the cache is no longer used.
 
1005
  *
1006
  * @param bool $secure Whether to ignore the use of the second (insecure) parameter.
1007
  * @return bool
1008
  */
1009
  public function is_seo_settings_page( $secure = true ) {
1010
 
 
 
 
1011
  if ( ! $secure )
1012
  return $this->is_menu_page( $this->seo_settings_page_hook, $this->seo_settings_page_slug );
1013
 
@@ -1027,13 +1038,23 @@ class Query extends Compat {
1027
  /**
1028
  * Checks the screen base file through global $page_hook or $_GET.
1029
  *
 
 
 
 
 
 
 
 
 
1030
  * @since 2.2.2
1031
  * @since 2.7.0 Added pageslug parameter.
1032
  * @global string $page_hook the current page hook.
1033
- * @note Usage of $pageslug might be insecure. Check all variables!
1034
  *
1035
  * @param string $pagehook The menu pagehook to compare to.
 
1036
  * @param string $pageslug The menu page slug to compare to.
 
1037
  * @return bool true if screen match.
1038
  */
1039
  public function is_menu_page( $pagehook = '', $pageslug = '' ) {
577
  * Returns true if on SEO settings page and when ID is 0.
578
  *
579
  * @since 2.9.0
580
+ * @since 2.9.3 Now tests for archive and 404 before testing home page as blog.
581
  *
582
+ * @param int The page ID, required. Can be 0.
583
  * @return bool True if ID if for the home page.
584
  */
585
  public function is_front_page_by_id( $id ) {
590
  return $cache;
591
 
592
  $is_front_page = false;
593
+ $sof = \get_option( 'show_on_front' );
594
 
595
  //* Elegant Themes Support. Yay.
596
  if ( 0 === $id && $this->is_home() ) {
 
 
597
  if ( 'page' !== $sof && 'posts' !== $sof )
598
  $is_front_page = true;
599
  }
600
 
601
  //* Compare against $id
602
  if ( false === $is_front_page ) {
603
+ if ( 'page' === $sof ) {
604
+ if ( (int) \get_option( 'page_on_front' ) === $id ) {
605
+ $is_front_page = true;
606
+ }
607
+ } elseif ( 'posts' === $sof ) {
608
+ if ( 0 === $id ) {
609
+ //* 0 as ID causes a lot of issues. Just test for is_home().
610
+ if ( $this->is_home() ) {
611
+ $is_front_page = true;
612
+ }
613
+ } elseif ( (int) \get_option( 'page_for_posts' ) === $id ) {
614
+ $is_front_page = true;
615
+ }
616
+ }
617
  }
618
 
619
  if ( false === $is_front_page && 0 === $id && $this->is_seo_settings_page() )
1009
  * @since 2.6.0
1010
  * @since 2.7.0 Added secure parameter.
1011
  * @since 2.9.0 If $secure is false, the cache is no longer used.
1012
+ * @see $this->is_menu_page() for security notification.
1013
  *
1014
  * @param bool $secure Whether to ignore the use of the second (insecure) parameter.
1015
  * @return bool
1016
  */
1017
  public function is_seo_settings_page( $secure = true ) {
1018
 
1019
+ if ( ! $this->is_admin() )
1020
+ return false;
1021
+
1022
  if ( ! $secure )
1023
  return $this->is_menu_page( $this->seo_settings_page_hook, $this->seo_settings_page_slug );
1024
 
1038
  /**
1039
  * Checks the screen base file through global $page_hook or $_GET.
1040
  *
1041
+ * NOTE: Usage of $pageslug might be insecure. Check all variables and don't
1042
+ * perform lasting actions like saving to the database before `admin_init`!
1043
+ *
1044
+ * The second "insecure" parameter is actually secured by WordPress (read on...).
1045
+ * However, we can't verify its integrity, WordPress has to. It's also checked
1046
+ * against too late.
1047
+ * It's secure enough for loading files; nevertheless, it shouldn't be used
1048
+ * when passing sensitive data.
1049
+ *
1050
  * @since 2.2.2
1051
  * @since 2.7.0 Added pageslug parameter.
1052
  * @global string $page_hook the current page hook.
 
1053
  *
1054
  * @param string $pagehook The menu pagehook to compare to.
1055
+ * To be used after `admin_init`.
1056
  * @param string $pageslug The menu page slug to compare to.
1057
+ * To be used before `admin_init`.
1058
  * @return bool true if screen match.
1059
  */
1060
  public function is_menu_page( $pagehook = '', $pageslug = '' ) {
inc/classes/render.class.php CHANGED
@@ -403,7 +403,7 @@ class Render extends Admin_Init {
403
  if ( $id === $featured_id )
404
  continue;
405
 
406
- //* Parse 1500px url.
407
  $img = $this->parse_og_image( $id, array(), true );
408
 
409
  if ( $img ) {
@@ -450,14 +450,32 @@ class Render extends Admin_Init {
450
  * Renders Open Graph URL meta tag.
451
  *
452
  * @since 1.3.0
 
453
  * @uses $this->the_url_from_cache()
454
  *
455
  * @return string The Open Graph URL meta tag.
456
  */
457
  public function og_url() {
458
 
459
- if ( $this->use_og_tags() )
460
- return '<meta property="og:url" content="' . $this->the_url_from_cache() . '" />' . "\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
 
462
  return '';
463
  }
@@ -514,9 +532,10 @@ class Render extends Admin_Init {
514
 
515
  /**
516
  * Renders The Twitter Creator meta tag.
517
- * If no Twitter Site is found, it will render the Twitter Site ID meta tag.
518
  *
519
  * @since 2.2.2
 
 
520
  *
521
  * @return string The Twitter Creator or Twitter Site ID meta tag.
522
  */
@@ -532,17 +551,8 @@ class Render extends Admin_Init {
532
  */
533
  $creator = (string) \apply_filters( 'the_seo_framework_twittercreator_output', $this->get_option( 'twitter_creator' ), $this->get_the_real_ID() );
534
 
535
- if ( $creator ) {
536
- /**
537
- * Return site:id instead of creator is no twitter:site is found.
538
- * Per Twitter requirements.
539
- */
540
- if ( $this->get_option( 'twitter_site' ) ) {
541
- return '<meta name="twitter:site:id" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
542
- } else {
543
- return '<meta name="twitter:creator" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
544
- }
545
- }
546
 
547
  return '';
548
  }
@@ -656,7 +666,7 @@ class Render extends Admin_Init {
656
  $author = (string) \apply_filters( 'the_seo_framework_facebookauthor_output', $this->get_option( 'facebook_author' ), $this->get_the_real_ID() );
657
 
658
  if ( $author )
659
- return '<meta property="article:author" content="' . \esc_attr( \esc_url_raw( $author ) ) . '" />' . "\r\n";
660
 
661
  return '';
662
  }
@@ -681,7 +691,7 @@ class Render extends Admin_Init {
681
  $publisher = (string) \apply_filters( 'the_seo_framework_facebookpublisher_output', $this->get_option( 'facebook_publisher' ), $this->get_the_real_ID() );
682
 
683
  if ( $publisher )
684
- return '<meta property="article:publisher" content="' . \esc_attr( \esc_url_raw( $publisher ) ) . '" />' . "\r\n";
685
 
686
  return '';
687
  }
@@ -995,17 +1005,20 @@ class Render extends Admin_Init {
995
  * Renders Shortlink meta tag
996
  *
997
  * @since 2.2.2
 
998
  * @uses $this->get_shortlink()
999
  *
1000
  * @return string The Shortlink meta tag.
1001
  */
1002
  public function shortlink() {
1003
 
 
 
1004
  /**
1005
  * Applies filters 'the_seo_framework_shortlink_output' : string
1006
  * @since 2.6.0
1007
  */
1008
- $url = (string) \apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink(), $this->get_the_real_ID() );
1009
 
1010
  if ( $url )
1011
  return sprintf( '<link rel="shortlink" href="%s" />' . "\r\n", $url );
@@ -1064,9 +1077,11 @@ class Render extends Admin_Init {
1064
 
1065
  if ( ! isset( $run ) ) {
1066
  /**
1067
- * Applies filters 'the_seo_framework_indicator' : Boolean
1068
- * Whether to show the indicator in HTML.
1069
  * @since 2.0.0
 
 
1070
  */
1071
  $run = (bool) \apply_filters( 'the_seo_framework_indicator', true );
1072
  }
@@ -1079,9 +1094,11 @@ class Render extends Admin_Init {
1079
  $_cache = array();
1080
 
1081
  /**
1082
- * Applies filters 'sybre_waaijer_<3' : Boolean
1083
- * Whether to show the hidden author name in HTML.
1084
  * @since 2.4.0
 
 
1085
  */
1086
  $sybre = (bool) \apply_filters( 'sybre_waaijer_<3', true );
1087
 
@@ -1089,9 +1106,11 @@ class Render extends Admin_Init {
1089
  $tsf = 'The SEO Framework';
1090
 
1091
  /**
1092
- * Applies filters 'the_seo_framework_indicator_timing' : Boolean
1093
- * Whether to show the hidden generation time in HTML.
1094
  * @since 2.4.0
 
 
1095
  */
1096
  $_cache['show_timer'] = (bool) \apply_filters( 'the_seo_framework_indicator_timing', true );
1097
 
403
  if ( $id === $featured_id )
404
  continue;
405
 
406
+ //* Parse 4096px url.
407
  $img = $this->parse_og_image( $id, array(), true );
408
 
409
  if ( $img ) {
450
  * Renders Open Graph URL meta tag.
451
  *
452
  * @since 1.3.0
453
+ * @since 2.9.3 Added filter
454
  * @uses $this->the_url_from_cache()
455
  *
456
  * @return string The Open Graph URL meta tag.
457
  */
458
  public function og_url() {
459
 
460
+ if ( $this->use_og_tags() ) {
461
+
462
+ /**
463
+ * Applies filters 'the_seo_framework_ogurl_output' : string
464
+ * Changes og:url output.
465
+ *
466
+ * @since 2.9.3
467
+ *
468
+ * @param string $url The canonical/Open Graph URL. Must be escaped.
469
+ * @param int $id The current page or term ID.
470
+ */
471
+ $url = (string) \apply_filters( 'the_seo_framework_ogurl_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
472
+
473
+ /**
474
+ * @since 2.7.0 Listens to the second filter.
475
+ */
476
+ if ( $url )
477
+ return '<meta property="og:url" content="' . $url . '" />' . "\r\n";
478
+ }
479
 
480
  return '';
481
  }
532
 
533
  /**
534
  * Renders The Twitter Creator meta tag.
 
535
  *
536
  * @since 2.2.2
537
+ * @since 2.9.3 No longer has a fallback to twitter:site:id
538
+ * @link https://dev.twitter.com/cards/getting-started
539
  *
540
  * @return string The Twitter Creator or Twitter Site ID meta tag.
541
  */
551
  */
552
  $creator = (string) \apply_filters( 'the_seo_framework_twittercreator_output', $this->get_option( 'twitter_creator' ), $this->get_the_real_ID() );
553
 
554
+ if ( $creator )
555
+ return '<meta name="twitter:creator" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
 
 
 
 
 
 
 
 
 
556
 
557
  return '';
558
  }
666
  $author = (string) \apply_filters( 'the_seo_framework_facebookauthor_output', $this->get_option( 'facebook_author' ), $this->get_the_real_ID() );
667
 
668
  if ( $author )
669
+ return '<meta property="article:author" content="' . \esc_attr( \esc_url_raw( $author, array( 'http', 'https' ) ) ) . '" />' . "\r\n";
670
 
671
  return '';
672
  }
691
  $publisher = (string) \apply_filters( 'the_seo_framework_facebookpublisher_output', $this->get_option( 'facebook_publisher' ), $this->get_the_real_ID() );
692
 
693
  if ( $publisher )
694
+ return '<meta property="article:publisher" content="' . \esc_attr( \esc_url_raw( $publisher, array( 'http', 'https' ) ) ) . '" />' . "\r\n";
695
 
696
  return '';
697
  }
1005
  * Renders Shortlink meta tag
1006
  *
1007
  * @since 2.2.2
1008
+ * @since 2.9.3 : Now work when home page is a blog.
1009
  * @uses $this->get_shortlink()
1010
  *
1011
  * @return string The Shortlink meta tag.
1012
  */
1013
  public function shortlink() {
1014
 
1015
+ $id = $this->get_the_real_ID();
1016
+
1017
  /**
1018
  * Applies filters 'the_seo_framework_shortlink_output' : string
1019
  * @since 2.6.0
1020
  */
1021
+ $url = (string) \apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink( $id ), $this->get_the_real_ID( $id ) );
1022
 
1023
  if ( $url )
1024
  return sprintf( '<link rel="shortlink" href="%s" />' . "\r\n", $url );
1077
 
1078
  if ( ! isset( $run ) ) {
1079
  /**
1080
+ * Applies filters 'the_seo_framework_indicator'
1081
+ *
1082
  * @since 2.0.0
1083
+ *
1084
+ * @param bool $run Whether to run and show the indicator.
1085
  */
1086
  $run = (bool) \apply_filters( 'the_seo_framework_indicator', true );
1087
  }
1094
  $_cache = array();
1095
 
1096
  /**
1097
+ * Applies filters 'sybre_waaijer_<3'
1098
+ *
1099
  * @since 2.4.0
1100
+ *
1101
+ * @param bool $sybre Whether to show the hidden author name in HTML.
1102
  */
1103
  $sybre = (bool) \apply_filters( 'sybre_waaijer_<3', true );
1104
 
1106
  $tsf = 'The SEO Framework';
1107
 
1108
  /**
1109
+ * Applies filters 'the_seo_framework_indicator_timing'
1110
+ *
1111
  * @since 2.4.0
1112
+ *
1113
+ * @param bool $show_timer Whether to show the hidden generation time in HTML.
1114
  */
1115
  $_cache['show_timer'] = (bool) \apply_filters( 'the_seo_framework_indicator_timing', true );
1116
 
inc/classes/site-options.class.php CHANGED
@@ -45,7 +45,7 @@ class Site_Options extends Sanitize {
45
  * Hold the SEO Settings Page ID for this plugin.
46
  *
47
  * @since 2.2.2
48
- * @since 2.70 Renamed var from page_id and made public.
49
  *
50
  * @var string The page ID
51
  */
@@ -105,8 +105,8 @@ class Site_Options extends Sanitize {
105
  */
106
  return array(
107
  // General. Performance.
108
- 'cache_meta_description' => 1, // Description transient cache.
109
- 'cache_meta_schema' => 1, // Schema.org transient cache.
110
  'cache_sitemap' => 1, // Sitemap transient cache.
111
  'cache_object' => 1, // Object caching.
112
 
@@ -399,7 +399,12 @@ class Site_Options extends Sanitize {
399
  */
400
  protected function pre_output_site_updated_plugin_notice() {
401
 
402
- if ( $this->is_seo_settings_page( false ) ) {
 
 
 
 
 
403
  //* Redirect to current page if on options page to correct option values. Once.
404
  if ( ! isset( $_REQUEST['tsf-settings-updated'] ) || 'true' !== $_REQUEST['tsf-settings-updated'] )
405
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-updated' => 'true' ) );
@@ -624,8 +629,8 @@ class Site_Options extends Sanitize {
624
  */
625
  public function register_settings() {
626
 
627
- //* If this page doesn't store settings, no need to register them
628
- if ( empty( $this->settings_field ) )
629
  return;
630
 
631
  \register_setting( $this->settings_field, $this->settings_field );
@@ -644,7 +649,13 @@ class Site_Options extends Sanitize {
644
  */
645
  protected function check_options_reset() {
646
 
647
- if ( false === $this->is_seo_settings_page( false ) )
 
 
 
 
 
 
648
  return;
649
 
650
  if ( $this->get_option( 'tsf-settings-reset', false ) ) {
45
  * Hold the SEO Settings Page ID for this plugin.
46
  *
47
  * @since 2.2.2
48
+ * @since 2.7.0 Renamed var from page_id and made public.
49
  *
50
  * @var string The page ID
51
  */
105
  */
106
  return array(
107
  // General. Performance.
108
+ 'cache_meta_description' => 0, // Description transient cache.
109
+ 'cache_meta_schema' => 0, // Schema.org transient cache.
110
  'cache_sitemap' => 1, // Sitemap transient cache.
111
  'cache_object' => 1, // Object caching.
112
 
399
  */
400
  protected function pre_output_site_updated_plugin_notice() {
401
 
402
+ /**
403
+ * Security check:
404
+ * Only checks for extra parameters. Then redirects further to only output
405
+ * notice. User capability is checked beforehand.
406
+ */
407
+ if ( \current_user_can( $this->settings_capability() ) && $this->is_seo_settings_page( false ) ) {
408
  //* Redirect to current page if on options page to correct option values. Once.
409
  if ( ! isset( $_REQUEST['tsf-settings-updated'] ) || 'true' !== $_REQUEST['tsf-settings-updated'] )
410
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-updated' => 'true' ) );
629
  */
630
  public function register_settings() {
631
 
632
+ //* If the settings field doesn't exist, we can't register it.
633
+ if ( ! $this->settings_field )
634
  return;
635
 
636
  \register_setting( $this->settings_field, $this->settings_field );
649
  */
650
  protected function check_options_reset() {
651
 
652
+ /**
653
+ * Security check:
654
+ * Further checks are based on previously set options.
655
+ * These can only be set when one has access to the Settings Page or database.
656
+ * Also checks for capabilities.
657
+ */
658
+ if ( ! \current_user_can( $this->settings_capability() ) || ! $this->is_seo_settings_page( false ) )
659
  return;
660
 
661
  if ( $this->get_option( 'tsf-settings-reset', false ) ) {
inc/classes/sitemaps.class.php CHANGED
@@ -254,7 +254,7 @@ class Sitemaps extends Metaboxes {
254
 
255
  //* Fetch sitemap content and add trailing line. Already escaped internally.
256
  $this->output_sitemap_content();
257
- echo "\r\n";
258
 
259
  // We're done now.
260
  exit;
@@ -277,7 +277,7 @@ class Sitemaps extends Metaboxes {
277
  */
278
  $sitemap_content = $this->is_option_checked( 'cache_sitemap' ) ? $this->get_transient( $this->sitemap_transient ) : false;
279
 
280
- echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n";
281
  echo $this->get_sitemap_xsl_stylesheet_tag();
282
 
283
  /**
@@ -285,8 +285,8 @@ class Sitemaps extends Metaboxes {
285
  * @since 2.8.0
286
  */
287
  if ( $this->the_seo_framework_debug ) {
288
- echo '<!-- Site estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->' . "\r\n";
289
- echo '<!-- System estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->' . "\r\n";
290
  }
291
 
292
  echo $this->get_sitemap_urlset_open_tag();
@@ -294,9 +294,9 @@ class Sitemaps extends Metaboxes {
294
  echo $this->get_sitemap_urlset_close_tag();
295
 
296
  if ( false === $sitemap_content ) {
297
- echo "\r\n" . '<!-- ' . \esc_html__( 'Sitemap is generated for this view', 'autodescription' ) . ' -->';
298
  } else {
299
- echo "\r\n" . '<!-- ' . \esc_html__( 'Sitemap is served from cache', 'autodescription' ) . ' -->';
300
  }
301
 
302
  /**
@@ -304,10 +304,10 @@ class Sitemaps extends Metaboxes {
304
  * @since 2.3.7
305
  */
306
  if ( $this->the_seo_framework_debug ) {
307
- echo "\r\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->';
308
- echo "\r\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->';
309
- echo "\r\n" . '<!-- Freed memory prior to generation: ' . number_format( $this->clean_up_globals_for_sitemap( true ) / 1024, 3 ) . ' kB -->';
310
- echo "\r\n" . '<!-- Sitemap generation time: ' . ( number_format( microtime( true ) - $timer_start, 6 ) ) . ' seconds -->';
311
  }
312
  }
313
 
@@ -349,7 +349,7 @@ class Sitemaps extends Metaboxes {
349
  }
350
  $urlset .= '>';
351
 
352
- return $urlset . "\r\n";
353
  }
354
 
355
  /**
@@ -367,13 +367,27 @@ class Sitemaps extends Metaboxes {
367
  * Returns stylesheet XSL location tag.
368
  *
369
  * @since 2.8.0
 
370
  *
371
  * @return string The sitemap XSL location tag.
372
  */
373
  public function get_sitemap_xsl_stylesheet_tag() {
374
 
375
- if ( $this->is_option_checked( 'sitemap_styles' ) )
376
- return sprintf( '<?xml-stylesheet type="text/xsl" href="%s"?>', \esc_url( $this->get_sitemap_xsl_url() ) ) . "\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
377
 
378
  return '';
379
  }
@@ -519,12 +533,13 @@ class Sitemaps extends Metaboxes {
519
  *
520
  * @since 2.2.9
521
  * @since 2.8.0 Now adjusts memory limit when possible.
 
522
  *
523
  * @return string The sitemap content.
524
  */
525
  protected function generate_sitemap() {
526
 
527
- \wp_is_ini_value_changeable( 'memory_limit' ) and @ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
528
 
529
  $content = '';
530
 
@@ -589,7 +604,7 @@ class Sitemaps extends Metaboxes {
589
  $timestamp = (bool) \apply_filters( 'the_seo_framework_sitemap_timestamp', true );
590
 
591
  if ( $timestamp )
592
- $content .= '<!-- ' . \esc_html__( 'Sitemap is generated on', 'autodescription' ) . ' ' . \current_time( 'Y-m-d H:i:s' ) . ' -->' . "\r\n";
593
 
594
  $wp_query = new \WP_Query;
595
  $wp_query->init();
@@ -644,8 +659,8 @@ class Sitemaps extends Metaboxes {
644
 
645
  //* Continue if indexed.
646
  if ( $indexed ) {
647
- $content .= "\t<url>\r\n";
648
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'home' => true ) ) . "</loc>\r\n";
649
 
650
  // Keep it consistent. Only parse if page_lastmod is true.
651
  if ( $home_lastmod ) {
@@ -668,11 +683,11 @@ class Sitemaps extends Metaboxes {
668
  }
669
 
670
  if ( '0000-00-00 00:00:00' !== $front_modified_gmt )
671
- $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $front_modified_gmt ) . "</lastmod>\r\n";
672
  }
673
 
674
- $content .= "\t\t<priority>1.0</priority>\r\n";
675
- $content .= "\t</url>\r\n";
676
  }
677
  endif;
678
 
@@ -691,8 +706,8 @@ class Sitemaps extends Metaboxes {
691
 
692
  //* Continue if indexed.
693
  if ( $indexed && isset( $page->ID ) ) {
694
- $content .= "\t<url>\r\n";
695
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_for_posts_id ) ) . "</loc>\r\n";
696
 
697
  // Keep it consistent. Only parse if page_lastmod is true.
698
  if ( $page_lastmod ) {
@@ -716,11 +731,11 @@ class Sitemaps extends Metaboxes {
716
  }
717
 
718
  if ( '0000-00-00 00:00:00' !== $page_modified_gmt )
719
- $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $page_modified_gmt ) . "</lastmod>\r\n";
720
  }
721
 
722
- $content .= "\t\t<priority>0.9</priority>\r\n";
723
- $content .= "\t</url>\r\n";
724
  }
725
  endif;
726
 
@@ -743,19 +758,19 @@ class Sitemaps extends Metaboxes {
743
 
744
  //* Continue if indexed.
745
  if ( $indexed ) {
746
- $content .= "\t<url>\r\n";
747
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_id ) ) . "</loc>\r\n";
748
 
749
  // Keep it consistent. Only parse if page_lastmod is true.
750
  if ( $page_lastmod ) {
751
  $page_modified_gmt = $page->post_modified_gmt;
752
 
753
  if ( '0000-00-00 00:00:00' !== $page_modified_gmt )
754
- $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $page_modified_gmt ) . "</lastmod>\r\n";
755
  }
756
 
757
- $content .= "\t\t<priority>0.9</priority>\r\n";
758
- $content .= "\t</url>\r\n";
759
  }
760
  }
761
  endif;
@@ -837,20 +852,20 @@ class Sitemaps extends Metaboxes {
837
  //* Continue if indexed
838
  if ( $indexed ) {
839
 
840
- $content .= "\t<url>\r\n";
841
  // No need to use static vars
842
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $post, 'id' => $post_id ) ) . "</loc>\r\n";
843
 
844
  // Keep it consistent. Only parse if page_lastmod is true.
845
  if ( $post_lastmod ) {
846
  $post_modified_gmt = $post->post_modified_gmt;
847
 
848
  if ( '0000-00-00 00:00:00' !== $post_modified_gmt )
849
- $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $post_modified_gmt ) . "</lastmod>\r\n";
850
  }
851
 
852
- $content .= "\t\t<priority>" . number_format( $priority, 1 ) . "</priority>\r\n";
853
- $content .= "\t</url>\r\n";
854
 
855
  // Lower the priority for the next pass.
856
  $priority = $priority - $prioritydiff;
@@ -954,9 +969,9 @@ class Sitemaps extends Metaboxes {
954
  //* Continue if indexed
955
  if ( $indexed ) {
956
 
957
- $content .= "\t<url>\r\n";
958
  //* No need to use static vars
959
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $ctp_post, 'id' => $cpt_id ) ) . "</loc>\r\n";
960
 
961
  //* Keep it consistent. Only parse if page_lastmod is true.
962
  if ( $post_lastmod ) {
@@ -964,11 +979,11 @@ class Sitemaps extends Metaboxes {
964
 
965
  //* Some CPT don't set modified time.
966
  if ( '0000-00-00 00:00:00' !== $cpt_modified_gmt )
967
- $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $cpt_modified_gmt ) . "</lastmod>\r\n";
968
  }
969
 
970
- $content .= "\t\t<priority>" . number_format( $priority_cpt, 1 ) . "</priority>\r\n";
971
- $content .= "\t</url>\r\n";
972
 
973
  // Lower the priority for the next pass.
974
  $priority_cpt = $priority_cpt - $prioritydiff_cpt;
@@ -1008,12 +1023,12 @@ class Sitemaps extends Metaboxes {
1008
  $url = $args;
1009
  }
1010
 
1011
- $content .= "\t<url>\r\n";
1012
  //* No need to use static vars
1013
- $content .= "\t\t<loc>" . \ent2ncr( \esc_url_raw( $url ) ) . "</loc>\r\n";
1014
 
1015
  if ( isset( $args['lastmod'] ) && $args['lastmod'] ) {
1016
- $content .= "\t\t<lastmod>" . \mysql2date( $timestamp_format, $args['lastmod'], false ) . "</lastmod>\r\n";
1017
  }
1018
 
1019
  if ( isset( $args['priority'] ) && $args['priority'] ) {
@@ -1022,8 +1037,8 @@ class Sitemaps extends Metaboxes {
1022
  $priority = 0.9;
1023
  }
1024
 
1025
- $content .= "\t\t<priority>" . number_format( $priority, 1 ) . "</priority>\r\n";
1026
- $content .= "\t</url>\r\n";
1027
  }
1028
  }
1029
 
@@ -1034,7 +1049,7 @@ class Sitemaps extends Metaboxes {
1034
  $extend = (string) \apply_filters( 'the_seo_framework_sitemap_extend', '' );
1035
 
1036
  if ( $extend )
1037
- $content .= "\t" . $extend . "\r\n";
1038
 
1039
  //* Reset timezone to default.
1040
  $this->reset_timezone();
@@ -1055,9 +1070,7 @@ class Sitemaps extends Metaboxes {
1055
  if ( $this->is_option_checked( 'site_noindex' ) || $this->is_blog_public() )
1056
  return;
1057
 
1058
- $blog_id = (string) $GLOBALS['blog_id'];
1059
-
1060
- $transient = 'tsf_throttle_ping_' . $blog_id;
1061
 
1062
  //* NOTE: Use legacy get_transient to prevent ping spam.
1063
  if ( false === \get_transient( $transient ) ) {
254
 
255
  //* Fetch sitemap content and add trailing line. Already escaped internally.
256
  $this->output_sitemap_content();
257
+ echo "\n";
258
 
259
  // We're done now.
260
  exit;
277
  */
278
  $sitemap_content = $this->is_option_checked( 'cache_sitemap' ) ? $this->get_transient( $this->sitemap_transient ) : false;
279
 
280
+ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
281
  echo $this->get_sitemap_xsl_stylesheet_tag();
282
 
283
  /**
285
  * @since 2.8.0
286
  */
287
  if ( $this->the_seo_framework_debug ) {
288
+ echo '<!-- Site estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->' . "\n";
289
+ echo '<!-- System estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->' . "\n";
290
  }
291
 
292
  echo $this->get_sitemap_urlset_open_tag();
294
  echo $this->get_sitemap_urlset_close_tag();
295
 
296
  if ( false === $sitemap_content ) {
297
+ echo "\n" . '<!-- ' . \esc_html__( 'Sitemap is generated for this view', 'autodescription' ) . ' -->';
298
  } else {
299
+ echo "\n" . '<!-- ' . \esc_html__( 'Sitemap is served from cache', 'autodescription' ) . ' -->';
300
  }
301
 
302
  /**
304
  * @since 2.3.7
305
  */
306
  if ( $this->the_seo_framework_debug ) {
307
+ echo "\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->';
308
+ echo "\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->';
309
+ echo "\n" . '<!-- Freed memory prior to generation: ' . number_format( $this->clean_up_globals_for_sitemap( true ) / 1024, 3 ) . ' kB -->';
310
+ echo "\n" . '<!-- Sitemap generation time: ' . ( number_format( microtime( true ) - $timer_start, 6 ) ) . ' seconds -->';
311
  }
312
  }
313
 
349
  }
350
  $urlset .= '>';
351
 
352
+ return $urlset . "\n";
353
  }
354
 
355
  /**
367
  * Returns stylesheet XSL location tag.
368
  *
369
  * @since 2.8.0
370
+ * @since 2.9.3 Now checks against request to see if there's a domain mismatch.
371
  *
372
  * @return string The sitemap XSL location tag.
373
  */
374
  public function get_sitemap_xsl_stylesheet_tag() {
375
 
376
+ if ( $this->is_option_checked( 'sitemap_styles' ) ) {
377
+
378
+ $url = \esc_url( $this->get_sitemap_xsl_url(), array( 'http', 'https' ) );
379
+
380
+ if ( ! empty( $_SERVER['HTTP_HOST'] ) ) {
381
+ $_parsed = \wp_parse_url( $url );
382
+ $_r_parsed = \wp_parse_url( \esc_url( \wp_unslash( $_SERVER['HTTP_HOST'] ), array( 'http', 'https' ) ) );
383
+
384
+ if ( isset( $_parsed['host'] ) && isset( $_r_parsed['host'] ) )
385
+ if ( $_parsed['host'] !== $_r_parsed['host'] )
386
+ return '';
387
+ }
388
+
389
+ return sprintf( '<?xml-stylesheet type="text/xsl" href="%s"?>', $url ) . "\n";
390
+ }
391
 
392
  return '';
393
  }
533
  *
534
  * @since 2.2.9
535
  * @since 2.8.0 Now adjusts memory limit when possible.
536
+ * @since 2.9.3 No longer crashes on WordPress sites below WP 4.6.
537
  *
538
  * @return string The sitemap content.
539
  */
540
  protected function generate_sitemap() {
541
 
542
+ function_exists( '\wp_is_ini_value_changeable' ) and \wp_is_ini_value_changeable( 'memory_limit' ) and @ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
543
 
544
  $content = '';
545
 
604
  $timestamp = (bool) \apply_filters( 'the_seo_framework_sitemap_timestamp', true );
605
 
606
  if ( $timestamp )
607
+ $content .= '<!-- ' . \esc_html__( 'Sitemap is generated on', 'autodescription' ) . ' ' . \current_time( 'Y-m-d H:i:s' ) . ' GMT -->' . "\n";
608
 
609
  $wp_query = new \WP_Query;
610
  $wp_query->init();
659
 
660
  //* Continue if indexed.
661
  if ( $indexed ) {
662
+ $content .= "\t<url>\n";
663
+ $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'home' => true ) ) . "</loc>\n";
664
 
665
  // Keep it consistent. Only parse if page_lastmod is true.
666
  if ( $home_lastmod ) {
683
  }
684
 
685
  if ( '0000-00-00 00:00:00' !== $front_modified_gmt )
686
+ $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $front_modified_gmt ) . "</lastmod>\n";
687
  }
688
 
689
+ $content .= "\t\t<priority>1.0</priority>\n";
690
+ $content .= "\t</url>\n";
691
  }
692
  endif;
693
 
706
 
707
  //* Continue if indexed.
708
  if ( $indexed && isset( $page->ID ) ) {
709
+ $content .= "\t<url>\n";
710
+ $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_for_posts_id ) ) . "</loc>\n";
711
 
712
  // Keep it consistent. Only parse if page_lastmod is true.
713
  if ( $page_lastmod ) {
731
  }
732
 
733
  if ( '0000-00-00 00:00:00' !== $page_modified_gmt )
734
+ $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $page_modified_gmt ) . "</lastmod>\n";
735
  }
736
 
737
+ $content .= "\t\t<priority>0.9</priority>\n";
738
+ $content .= "\t</url>\n";
739
  }
740
  endif;
741
 
758
 
759
  //* Continue if indexed.
760
  if ( $indexed ) {
761
+ $content .= "\t<url>\n";
762
+ $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_id ) ) . "</loc>\n";
763
 
764
  // Keep it consistent. Only parse if page_lastmod is true.
765
  if ( $page_lastmod ) {
766
  $page_modified_gmt = $page->post_modified_gmt;
767
 
768
  if ( '0000-00-00 00:00:00' !== $page_modified_gmt )
769
+ $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $page_modified_gmt ) . "</lastmod>\n";
770
  }
771
 
772
+ $content .= "\t\t<priority>0.9</priority>\n";
773
+ $content .= "\t</url>\n";
774
  }
775
  }
776
  endif;
852
  //* Continue if indexed
853
  if ( $indexed ) {
854
 
855
+ $content .= "\t<url>\n";
856
  // No need to use static vars
857
+ $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $post, 'id' => $post_id ) ) . "</loc>\n";
858
 
859
  // Keep it consistent. Only parse if page_lastmod is true.
860
  if ( $post_lastmod ) {
861
  $post_modified_gmt = $post->post_modified_gmt;
862
 
863
  if ( '0000-00-00 00:00:00' !== $post_modified_gmt )
864
+ $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $post_modified_gmt ) . "</lastmod>\n";
865
  }
866
 
867
+ $content .= "\t\t<priority>" . number_format( $priority, 1 ) . "</priority>\n";
868
+ $content .= "\t</url>\n";
869
 
870
  // Lower the priority for the next pass.
871
  $priority = $priority - $prioritydiff;
969
  //* Continue if indexed
970
  if ( $indexed ) {
971
 
972
+ $content .= "\t<url>\n";
973
  //* No need to use static vars
974
+ $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $ctp_post, 'id' => $cpt_id ) ) . "</loc>\n";
975
 
976
  //* Keep it consistent. Only parse if page_lastmod is true.
977
  if ( $post_lastmod ) {
979
 
980
  //* Some CPT don't set modified time.
981
  if ( '0000-00-00 00:00:00' !== $cpt_modified_gmt )
982
+ $content .= "\t\t<lastmod>" . $this->gmt2date( $timestamp_format, $cpt_modified_gmt ) . "</lastmod>\n";
983
  }
984
 
985
+ $content .= "\t\t<priority>" . number_format( $priority_cpt, 1 ) . "</priority>\n";
986
+ $content .= "\t</url>\n";
987
 
988
  // Lower the priority for the next pass.
989
  $priority_cpt = $priority_cpt - $prioritydiff_cpt;
1023
  $url = $args;
1024
  }
1025
 
1026
+ $content .= "\t<url>\n";
1027
  //* No need to use static vars
1028
+ $content .= "\t\t<loc>" . \ent2ncr( \esc_url_raw( $url, array( 'http', 'https' ) ) ) . "</loc>\n";
1029
 
1030
  if ( isset( $args['lastmod'] ) && $args['lastmod'] ) {
1031
+ $content .= "\t\t<lastmod>" . \mysql2date( $timestamp_format, $args['lastmod'], false ) . "</lastmod>\n";
1032
  }
1033
 
1034
  if ( isset( $args['priority'] ) && $args['priority'] ) {
1037
  $priority = 0.9;
1038
  }
1039
 
1040
+ $content .= "\t\t<priority>" . number_format( $priority, 1 ) . "</priority>\n";
1041
+ $content .= "\t</url>\n";
1042
  }
1043
  }
1044
 
1049
  $extend = (string) \apply_filters( 'the_seo_framework_sitemap_extend', '' );
1050
 
1051
  if ( $extend )
1052
+ $content .= "\t" . $extend . "\n";
1053
 
1054
  //* Reset timezone to default.
1055
  $this->reset_timezone();
1070
  if ( $this->is_option_checked( 'site_noindex' ) || $this->is_blog_public() )
1071
  return;
1072
 
1073
+ $transient = 'tsf_throttle_ping_' . $GLOBALS['blog_id'];
 
 
1074
 
1075
  //* NOTE: Use legacy get_transient to prevent ping spam.
1076
  if ( false === \get_transient( $transient ) ) {
inc/compat/plugin-donncha-dm.php CHANGED
@@ -38,7 +38,7 @@ function _donncha_domainmap_sanitize_redirect_url( $args = array(), $path = '' )
38
  *
39
  * @param string $path The post relative path.
40
  * @param bool $get_scheme Output array with scheme.
41
- * @return string|array|void The unescaped URL, the scheme
42
  */
43
  function _donncha_domainmap_get_url( $path, $get_scheme = false ) {
44
  global $current_blog;
38
  *
39
  * @param string $path The post relative path.
40
  * @param bool $get_scheme Output array with scheme.
41
+ * @return string|array The unescaped URL, or the URL and the Scheme.
42
  */
43
  function _donncha_domainmap_get_url( $path, $get_scheme = false ) {
44
  global $current_blog;
inc/compat/plugin-polylang.php CHANGED
@@ -69,7 +69,7 @@ function _polylang_external_filter_url_args( $args = array(), $path = '', $id =
69
  static $home_url = null;
70
  //* We don't want to fire internal filters that lead to this function.
71
  if ( null === $home_url )
72
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ) ) );
73
 
74
  $_post = \get_post( $id );
75
  $_link = $home_url . $path;
@@ -109,7 +109,7 @@ function _polylang_admin_filter_url_args( $args = array(), $path = '', $id = 0,
109
  global $polylang;
110
 
111
  //* We don't want to fire internal filters that lead to this function.
112
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ) ) );
113
 
114
  if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_front_page_by_id( $id ) || \the_seo_framework()->is_404() ) {
115
  if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
@@ -155,7 +155,7 @@ function _polylang_frontend_filter_url_args( $args = array(), $path = '', $id =
155
  global $polylang;
156
 
157
  //* We don't want to fire internal filters that lead to this function.
158
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ) ) );
159
 
160
  if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_404() || \the_seo_framework()->is_search() ) {
161
  if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
69
  static $home_url = null;
70
  //* We don't want to fire internal filters that lead to this function.
71
  if ( null === $home_url )
72
+ $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
73
 
74
  $_post = \get_post( $id );
75
  $_link = $home_url . $path;
109
  global $polylang;
110
 
111
  //* We don't want to fire internal filters that lead to this function.
112
+ $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
113
 
114
  if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_front_page_by_id( $id ) || \the_seo_framework()->is_404() ) {
115
  if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
155
  global $polylang;
156
 
157
  //* We don't want to fire internal filters that lead to this function.
158
+ $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
159
 
160
  if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_404() || \the_seo_framework()->is_search() ) {
161
  if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
inc/compat/plugin-wpmudev-dm.php CHANGED
@@ -35,13 +35,14 @@ function _wpmudev_sanitize_redirect_url( $args = array(), $path = '' ) {
35
  * @since 2.3.0
36
  * @since 2.4.0 Added $get_scheme parameter.
37
  * @since 2.8.0 Moved to compat file.
 
38
  * @global object $wpdb
39
  * @global int $blog_id
40
  * @access private
41
  *
42
  * @param string $path The post relative path.
43
  * @param bool $get_scheme Output array with scheme.
44
- * @return string|array|void The unescaped URL, the scheme
45
  */
46
  function _wpmudev_domainmap_get_url( $path, $get_scheme = false ) {
47
  global $wpdb, $blog_id;
@@ -125,5 +126,9 @@ function _wpmudev_domainmap_get_url( $path, $get_scheme = false ) {
125
  }
126
  endif;
127
 
128
- return '';
 
 
 
 
129
  }
35
  * @since 2.3.0
36
  * @since 2.4.0 Added $get_scheme parameter.
37
  * @since 2.8.0 Moved to compat file.
38
+ * @since 2.9.2 Now also returns an array if $get_scheme is true when no output is found.
39
  * @global object $wpdb
40
  * @global int $blog_id
41
  * @access private
42
  *
43
  * @param string $path The post relative path.
44
  * @param bool $get_scheme Output array with scheme.
45
+ * @return string|array The unescaped URL, or the URL and the Scheme.
46
  */
47
  function _wpmudev_domainmap_get_url( $path, $get_scheme = false ) {
48
  global $wpdb, $blog_id;
126
  }
127
  endif;
128
 
129
+ if ( $get_scheme ) {
130
+ return array( '', '' );
131
+ } else {
132
+ return '';
133
+ }
134
  }
inc/compat/theme-genesis.php CHANGED
@@ -35,12 +35,13 @@ function _disable_genesis_seo( $plugins ) {
35
  return $plugins;
36
  }
37
 
38
- \add_action( 'init', __NAMESPACE__ . '\\_genesis_add_head_attributes' );
39
  /**
40
  * Adds Genesis SEO compatibility.
41
  *
42
  * @since 2.6.0
43
  * @since 2.8.0 Moved to compat file and renamed.
 
44
  * @access private
45
  */
46
  function _genesis_add_head_attributes() {
35
  return $plugins;
36
  }
37
 
38
+ // \add_action( 'init', 'The_SEO_Framework\\_genesis_add_head_attributes' );
39
  /**
40
  * Adds Genesis SEO compatibility.
41
  *
42
  * @since 2.6.0
43
  * @since 2.8.0 Moved to compat file and renamed.
44
+ * @since 2.9.3 No longer used. It is conflicting with the homepage Schema output.
45
  * @access private
46
  */
47
  function _genesis_add_head_attributes() {
inc/views/inpost/seo-settings-singular.php CHANGED
@@ -112,7 +112,7 @@ switch ( $instance ) :
112
  </div>
113
  <div class="tsf-flex-setting-input tsf-flex">
114
  <div id="tsf-title-wrap">
115
- <input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" placeholder="<?php echo esc_attr( $doctitle_placeholder ); ?>" value="<?php echo esc_attr( $this->get_custom_field( '_genesis_title' ) ); ?>" />
116
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
117
  </div>
118
  </div>
@@ -207,7 +207,7 @@ switch ( $instance ) :
207
  <div class="tsf-flex-setting-label tsf-flex">
208
  <div class="tsf-flex-setting-label-inner-wrap tsf-flex">
209
  <div class="tsf-flex-setting-label-item tsf-flex">
210
- <div><strong><?php esc_html_e( 'Local Search Settings', 'autodescription' ); ?></strong></div>
211
  </div>
212
  </div>
213
  </div>
@@ -221,6 +221,17 @@ switch ( $instance ) :
221
  ?>
222
  </label>
223
  </div>
 
 
 
 
 
 
 
 
 
 
 
224
  </div>
225
  </div>
226
 
@@ -271,9 +282,9 @@ switch ( $instance ) :
271
  </div>
272
  <?php
273
  /**
274
- * Insert form element only if JS is active. If JS is inactive, then this will cause it to be emptied on $_POST
275
- * @TODO use disabled and jQuery.removeprop( 'disabled' )?
276
- */
277
  ?>
278
  <script>
279
  document.getElementById( 'autodescription_socialimage-url' ).insertAdjacentHTML( 'afterend', '<input type="hidden" name="autodescription[_social_image_id]" id="autodescription_socialimage-id" value="<?php echo absint( $this->get_custom_field( '_social_image_id' ) ); ?>" />' );
112
  </div>
113
  <div class="tsf-flex-setting-input tsf-flex">
114
  <div id="tsf-title-wrap">
115
+ <input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" placeholder="<?php echo esc_attr( $doctitle_placeholder ); ?>" value="<?php echo esc_attr( $this->get_custom_field( '_genesis_title' ) ); ?>" autocomplete=off />
116
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
117
  </div>
118
  </div>
207
  <div class="tsf-flex-setting-label tsf-flex">
208
  <div class="tsf-flex-setting-label-inner-wrap tsf-flex">
209
  <div class="tsf-flex-setting-label-item tsf-flex">
210
+ <div><strong><?php esc_html_e( 'Archive Settings', 'autodescription' ); ?></strong></div>
211
  </div>
212
  </div>
213
  </div>
221
  ?>
222
  </label>
223
  </div>
224
+ <?php if ( $this->post_type_supports_taxonomies() ) : ?>
225
+ <div class="tsf-checkbox-wrapper">
226
+ <label for="autodescription_exclude_from_archive"><input type="checkbox" name="autodescription[exclude_from_archive]" id="autodescription_exclude_from_archive" value="1" <?php checked( $this->get_custom_field( 'exclude_from_archive' ) ); ?> />
227
+ <?php
228
+ printf( esc_html__( 'Exclude this %s from archive listing', 'autodescription' ), esc_html( $type ) );
229
+ echo ' ';
230
+ $this->make_info( sprintf( __( 'This excludes this %s from on-site archive pages', 'autodescription' ), $type ) );
231
+ ?>
232
+ </label>
233
+ </div>
234
+ <?php endif; ?>
235
  </div>
236
  </div>
237
 
282
  </div>
283
  <?php
284
  /**
285
+ * Insert form element only if JS is active. If JS is inactive, then this will cause it to be emptied on $_POST
286
+ * @TODO use disabled and jQuery.removeprop( 'disabled' )?
287
+ */
288
  ?>
289
  <script>
290
  document.getElementById( 'autodescription_socialimage-url' ).insertAdjacentHTML( 'afterend', '<input type="hidden" name="autodescription[_social_image_id]" id="autodescription_socialimage-id" value="<?php echo absint( $this->get_custom_field( '_social_image_id' ) ); ?>" />' );
inc/views/inpost/seo-settings-tt.php CHANGED
@@ -89,7 +89,7 @@ $description_placeholder = $generated_description;
89
  </th>
90
  <td>
91
  <div id="tsf-title-wrap">
92
- <input name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]" type="text" placeholder="<?php echo esc_attr( $title_placeholder ) ?>" value="<?php echo esc_attr( $title ); ?>" size="40" />
93
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
94
  </div>
95
  <p class="description tsf-counter">
89
  </th>
90
  <td>
91
  <div id="tsf-title-wrap">
92
+ <input name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]" type="text" placeholder="<?php echo esc_attr( $title_placeholder ) ?>" value="<?php echo esc_attr( $title ); ?>" size="40" autocomplete=off />
93
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
94
  </div>
95
  <p class="description tsf-counter">
inc/views/metaboxes/homepage-metabox.php CHANGED
@@ -163,7 +163,7 @@ switch ( $instance ) :
163
  </label>
164
  </p>
165
  <p>
166
- <input type="text" name="<?php $this->field_name( 'homepage_title_tagline' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title_tagline' ); ?>" placeholder="<?php echo esc_attr( $this->escape_title( $this->get_blogdescription() ) ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title_tagline' ) ); ?>" />
167
  </p>
168
 
169
  <hr>
@@ -179,7 +179,7 @@ switch ( $instance ) :
179
  </label>
180
  </p>
181
  <p id="tsf-title-wrap">
182
- <input type="text" name="<?php $this->field_name( 'homepage_title' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title' ); ?>" placeholder="<?php echo esc_attr( $home_title_placeholder ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title' ) ); ?>" />
183
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
184
  </p>
185
  <?php
@@ -212,7 +212,8 @@ switch ( $instance ) :
212
  esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
213
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
214
  ),
215
- array( 'a' )
 
216
  )
217
  );
218
  }
@@ -230,7 +231,7 @@ switch ( $instance ) :
230
  </label>
231
  </p>
232
  <p>
233
- <textarea name="<?php $this->field_name( 'homepage_description' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_description' ); ?>" rows="3" cols="70" placeholder="<?php echo esc_attr( $description_placeholder ); ?>"><?php echo esc_attr( $this->get_field_value( 'homepage_description' ) ); ?></textarea>
234
  </p>
235
  <?php
236
  $this->description( __( 'The meta description can be used to determine the text used under the title on Search Engine results pages.', 'autodescription' ) );
@@ -252,7 +253,8 @@ switch ( $instance ) :
252
  esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
253
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
254
  ),
255
- array( 'a' )
 
256
  )
257
  );
258
  }
163
  </label>
164
  </p>
165
  <p>
166
+ <input type="text" name="<?php $this->field_name( 'homepage_title_tagline' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title_tagline' ); ?>" placeholder="<?php echo esc_attr( $this->escape_title( $this->get_blogdescription() ) ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title_tagline' ) ); ?>" autocomplete=off />
167
  </p>
168
 
169
  <hr>
179
  </label>
180
  </p>
181
  <p id="tsf-title-wrap">
182
+ <input type="text" name="<?php $this->field_name( 'homepage_title' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title' ); ?>" placeholder="<?php echo esc_attr( $home_title_placeholder ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title' ) ); ?>" autocomplete=off />
183
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
184
  </p>
185
  <?php
212
  esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
213
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
214
  ),
215
+ array( 'a' ),
216
+ array( 'a_internal' => false )
217
  )
218
  );
219
  }
231
  </label>
232
  </p>
233
  <p>
234
+ <textarea name="<?php $this->field_name( 'homepage_description' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_description' ); ?>" rows="3" cols="70" placeholder="<?php echo esc_attr( $description_placeholder ); ?>"><?php echo esc_attr( $this->get_field_value( 'homepage_description' ) ); ?></textarea>
235
  </p>
236
  <?php
237
  $this->description( __( 'The meta description can be used to determine the text used under the title on Search Engine results pages.', 'autodescription' ) );
253
  esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
254
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
255
  ),
256
+ array( 'a' ),
257
+ array( 'a_internal' => false )
258
  )
259
  );
260
  }
inc/views/metaboxes/schema-metabox.php CHANGED
@@ -199,67 +199,67 @@ switch ( $instance ) :
199
  */
200
  $socialsites = array(
201
  'facebook' => array(
202
- 'option' => 'knowledge_facebook',
203
- 'dashicon' => 'dashicons-facebook',
204
- 'desc' => 'Facebook ' . __( 'Page', 'autodescription' ),
205
- 'placeholder' => 'https://www.facebook.com/' . $connectedi18n,
206
- 'examplelink' => esc_url( 'https://www.facebook.com/me' ),
207
  ),
208
  'twitter' => array(
209
- 'option' => 'knowledge_twitter',
210
- 'dashicon' => 'dashicons-twitter',
211
- 'desc' => 'Twitter ' . $profile18n,
212
- 'placeholder' => 'https://twitter.com/' . $connectedi18n,
213
- 'examplelink' => esc_url( 'https://twitter.com/home' ), // No example link available.
214
  ),
215
  'gplus' => array(
216
- 'option' => 'knowledge_gplus',
217
- 'dashicon' => 'dashicons-googleplus',
218
- 'desc' => 'Google+ ' . $profile18n,
219
- 'placeholder' => 'https://plus.google.com/' . $connectedi18n,
220
- 'examplelink' => esc_url( 'https://plus.google.com/me' ),
221
  ),
222
  'instagram' => array(
223
- 'option' => 'knowledge_instagram',
224
- 'dashicon' => 'genericon-instagram',
225
- 'desc' => 'Instagram ' . $profile18n,
226
- 'placeholder' => 'https://instagram.com/' . $connectedi18n,
227
- 'examplelink' => esc_url( 'https://instagram.com/' ), // No example link available.
228
  ),
229
  'youtube' => array(
230
- 'option' => 'knowledge_youtube',
231
- 'dashicon' => 'genericon-youtube',
232
- 'desc' => 'Youtube ' . $profile18n,
233
- 'placeholder' => 'https://www.youtube.com/channel/' . $connectedi18n,
234
- 'examplelink' => esc_url( 'https://www.youtube.com/user/%2f' ), // Yes a double slash.
235
  ),
236
  'linkedin' => array(
237
- 'option' => 'knowledge_linkedin',
238
- 'dashicon' => 'genericon-linkedin-alt',
239
- 'desc' => 'LinkedIn ' . $profile18n . ' ID',
240
- 'placeholder' => 'https://www.linkedin.com/in/' . $connectedi18n,
241
- 'examplelink' => esc_url( 'https://www.linkedin.com/profile/view' ),
242
  ),
243
  'pinterest' => array(
244
- 'option' => 'knowledge_pinterest',
245
- 'dashicon' => 'genericon-pinterest-alt',
246
- 'desc' => 'Pinterest ' . $profile18n,
247
- 'placeholder' => 'https://www.pinterest.com/' . $connectedi18n . '/',
248
- 'examplelink' => esc_url( 'https://www.pinterest.com/me/' ),
249
  ),
250
  'soundcloud' => array(
251
- 'option' => 'knowledge_soundcloud',
252
- 'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
253
- 'desc' => 'SoundCloud ' . $profile18n,
254
- 'placeholder' => 'https://soundcloud.com/' . $connectedi18n,
255
- 'examplelink' => esc_url( 'https://soundcloud.com/you' ),
256
  ),
257
  'tumblr' => array(
258
- 'option' => 'knowledge_tumblr',
259
- 'dashicon' => 'genericon-tumblr',
260
- 'desc' => 'Tumblr ' . __( 'Blog', 'autodescription' ),
261
- 'placeholder' => 'https://www.tumblr.com/blog/' . $connectedi18n,
262
- 'examplelink' => esc_url( 'https://www.tumblr.com/dashboard' ), // No example link available.
263
  ),
264
  );
265
 
199
  */
200
  $socialsites = array(
201
  'facebook' => array(
202
+ 'option' => 'knowledge_facebook',
203
+ 'dashicon' => 'dashicons-facebook',
204
+ 'desc' => 'Facebook ' . __( 'Page', 'autodescription' ),
205
+ 'placeholder' => 'https://www.facebook.com/' . $connectedi18n,
206
+ 'examplelink' => 'https://www.facebook.com/me',
207
  ),
208
  'twitter' => array(
209
+ 'option' => 'knowledge_twitter',
210
+ 'dashicon' => 'dashicons-twitter',
211
+ 'desc' => 'Twitter ' . $profile18n,
212
+ 'placeholder' => 'https://twitter.com/' . $connectedi18n,
213
+ 'examplelink' => 'https://twitter.com/home', // No example link available.
214
  ),
215
  'gplus' => array(
216
+ 'option' => 'knowledge_gplus',
217
+ 'dashicon' => 'dashicons-googleplus',
218
+ 'desc' => 'Google+ ' . $profile18n,
219
+ 'placeholder' => 'https://plus.google.com/' . $connectedi18n,
220
+ 'examplelink' => 'https://plus.google.com/me',
221
  ),
222
  'instagram' => array(
223
+ 'option' => 'knowledge_instagram',
224
+ 'dashicon' => 'genericon-instagram',
225
+ 'desc' => 'Instagram ' . $profile18n,
226
+ 'placeholder' => 'https://instagram.com/' . $connectedi18n,
227
+ 'examplelink' => 'https://instagram.com/', // No example link available.
228
  ),
229
  'youtube' => array(
230
+ 'option' => 'knowledge_youtube',
231
+ 'dashicon' => 'genericon-youtube',
232
+ 'desc' => 'Youtube ' . $profile18n,
233
+ 'placeholder' => 'https://www.youtube.com/channel/' . $connectedi18n,
234
+ 'examplelink' => 'https://www.youtube.com/user/%2f', // Yes a double slash.
235
  ),
236
  'linkedin' => array(
237
+ 'option' => 'knowledge_linkedin',
238
+ 'dashicon' => 'genericon-linkedin-alt',
239
+ 'desc' => 'LinkedIn ' . $profile18n,
240
+ 'placeholder' => 'https://www.linkedin.com/in/' . $connectedi18n,
241
+ 'examplelink' => 'https://www.linkedin.com/profile/view',
242
  ),
243
  'pinterest' => array(
244
+ 'option' => 'knowledge_pinterest',
245
+ 'dashicon' => 'genericon-pinterest-alt',
246
+ 'desc' => 'Pinterest ' . $profile18n,
247
+ 'placeholder' => 'https://www.pinterest.com/' . $connectedi18n . '/',
248
+ 'examplelink' => 'https://www.pinterest.com/me/',
249
  ),
250
  'soundcloud' => array(
251
+ 'option' => 'knowledge_soundcloud',
252
+ 'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
253
+ 'desc' => 'SoundCloud ' . $profile18n,
254
+ 'placeholder' => 'https://soundcloud.com/' . $connectedi18n,
255
+ 'examplelink' => 'https://soundcloud.com/you',
256
  ),
257
  'tumblr' => array(
258
+ 'option' => 'knowledge_tumblr',
259
+ 'dashicon' => 'genericon-tumblr',
260
+ 'desc' => 'Tumblr ' . __( 'Blog', 'autodescription' ),
261
+ 'placeholder' => 'https://www.tumblr.com/blog/' . $connectedi18n,
262
+ 'examplelink' => 'https://www.tumblr.com/dashboard', // No example link available.
263
  ),
264
  );
265
 
inc/views/metaboxes/sitemaps-metabox.php CHANGED
@@ -111,7 +111,7 @@ switch ( $instance ) :
111
  endif;
112
 
113
  if ( ! $has_sitemap_plugin && ( $this->get_option( 'sitemaps_output' ) || $sitemap_detected ) ) {
114
- $here = '<a href="' . esc_url( $sitemap_url ) . '" target="_blank" title="' . esc_attr__( 'View sitemap', 'autodescription' ) . '">' . esc_attr_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
115
  $this->description_noesc( sprintf( _x( 'The sitemap can be found %s.', '%s = here', 'autodescription' ), $here ) );
116
  }
117
  break;
@@ -129,7 +129,7 @@ switch ( $instance ) :
129
  elseif ( ! $this->pretty_permalinks ) :
130
 
131
  $permalink_settings_url = admin_url( 'options-permalink.php' );
132
- $here = '<a href="' . esc_url( $permalink_settings_url ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
133
 
134
  ?><h4><?php esc_html_e( "You're using the plain permalink structure.", 'autodescription' ); ?></h4><?php
135
  $this->description( __( "This means the robots.txt file can't be outputted through the WordPress rewrite rules.", 'autodescription' ) );
@@ -167,7 +167,7 @@ switch ( $instance ) :
167
 
168
  if ( $locate_url ) {
169
  $robots_url = $this->get_robots_txt_url();
170
- $here = '<a href="' . esc_url( $robots_url ) . '" target="_blank" title="' . esc_attr__( 'View robots.txt', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
171
 
172
  $this->description_noesc( sprintf( esc_html_x( 'The robots.txt file can be found %s.', '%s = here', 'autodescription' ), $here ) );
173
  }
111
  endif;
112
 
113
  if ( ! $has_sitemap_plugin && ( $this->get_option( 'sitemaps_output' ) || $sitemap_detected ) ) {
114
+ $here = '<a href="' . esc_url( $sitemap_url, array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr__( 'View sitemap', 'autodescription' ) . '">' . esc_attr_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
115
  $this->description_noesc( sprintf( _x( 'The sitemap can be found %s.', '%s = here', 'autodescription' ), $here ) );
116
  }
117
  break;
129
  elseif ( ! $this->pretty_permalinks ) :
130
 
131
  $permalink_settings_url = admin_url( 'options-permalink.php' );
132
+ $here = '<a href="' . esc_url( $permalink_settings_url, array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
133
 
134
  ?><h4><?php esc_html_e( "You're using the plain permalink structure.", 'autodescription' ); ?></h4><?php
135
  $this->description( __( "This means the robots.txt file can't be outputted through the WordPress rewrite rules.", 'autodescription' ) );
167
 
168
  if ( $locate_url ) {
169
  $robots_url = $this->get_robots_txt_url();
170
+ $here = '<a href="' . esc_url( $robots_url, array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr__( 'View robots.txt', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
171
 
172
  $this->description_noesc( sprintf( esc_html_x( 'The robots.txt file can be found %s.', '%s = here', 'autodescription' ), $here ) );
173
  }
inc/views/metaboxes/social-metabox.php CHANGED
@@ -166,10 +166,10 @@ switch ( $instance ) :
166
  case 'the_seo_framework_social_metabox_facebook' :
167
 
168
  $fb_author = $this->get_field_value( 'facebook_author' );
169
- $fb_author_placeholder = empty( $fb_publisher ) ? _x( 'http://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' ) : '';
170
 
171
  $fb_publisher = $this->get_field_value( 'facebook_publisher' );
172
- $fb_publisher_placeholder = empty( $fb_publisher ) ? _x( 'http://www.facebook.com/YourVerifiedBusinessProfile', 'Example Verified Facebook Business URL', 'autodescription' ) : '';
173
 
174
  $fb_appid = $this->get_field_value( 'facebook_appid' );
175
  $fb_appid_placeholder = empty( $fb_appid ) ? '123456789012345' : '';
166
  case 'the_seo_framework_social_metabox_facebook' :
167
 
168
  $fb_author = $this->get_field_value( 'facebook_author' );
169
+ $fb_author_placeholder = empty( $fb_publisher ) ? _x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' ) : '';
170
 
171
  $fb_publisher = $this->get_field_value( 'facebook_publisher' );
172
+ $fb_publisher_placeholder = empty( $fb_publisher ) ? _x( 'https://www.facebook.com/YourVerifiedBusinessProfile', 'Example Verified Facebook Business URL', 'autodescription' ) : '';
173
 
174
  $fb_appid = $this->get_field_value( 'facebook_appid' );
175
  $fb_appid_placeholder = empty( $fb_appid ) ? '123456789012345' : '';
inc/views/sitemap/xsl-stylesheet.php CHANGED
@@ -86,6 +86,7 @@ $xml = '<?xml version="1.0" encoding="UTF-8"?>
86
  h1 img {
87
  vertical-align: bottom;
88
  margin-right: 14px;
 
89
  }
90
  #description {
91
  background-color: ' . $sitemap_color_main . ';
@@ -137,7 +138,7 @@ $xml = '<?xml version="1.0" encoding="UTF-8"?>
137
  </head>
138
  <body>
139
  <div id="description">
140
- <a href="' . esc_url( ent2ncr( get_home_url() ) ) . '"><h1>' .
141
  ent2ncr( $logo ) .
142
  esc_html( ent2ncr( $this->get_blogname() . ' &mdash; ' . __( 'XML Sitemap', 'autodescription' ) ) ) . '</h1></a>
143
  <p>' .
@@ -146,12 +147,14 @@ $xml = '<?xml version="1.0" encoding="UTF-8"?>
146
  $this->convert_markdown(
147
  /* translators: URLs are in Markdown. Don't forget to localize the URLs. */
148
  __( 'This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/).', 'autodescription' ),
149
- array( 'a' )
 
150
  )
151
  ),
152
  array(
153
  'a' => array(
154
  'href' => true,
 
155
  'rel' => true,
156
  ),
157
  )
@@ -162,12 +165,14 @@ $xml = '<?xml version="1.0" encoding="UTF-8"?>
162
  $this->convert_markdown(
163
  /* translators: URLs are in Markdown. Don't localize this URL. */
164
  __( 'You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/).', 'autodescription' ),
165
- array( 'a' )
 
166
  )
167
  ),
168
  array(
169
  'a' => array(
170
  'href' => true,
 
171
  'rel' => true,
172
  ),
173
  )
@@ -229,12 +234,14 @@ if ( $indicator ) :
229
  $this->convert_markdown(
230
  /* translators: URLs are in Markdown. */
231
  __( 'Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)', 'autodescription' ),
232
- array( 'a' )
 
233
  )
234
  ),
235
  array(
236
  'a' => array(
237
  'href' => true,
 
238
  'rel' => true,
239
  ),
240
  )
@@ -248,4 +255,5 @@ $xml .= '
248
  </xsl:template>
249
  </xsl:stylesheet>';
250
 
 
251
  echo $xml;
86
  h1 img {
87
  vertical-align: bottom;
88
  margin-right: 14px;
89
+ image-rendering: -webkit-optimize-contrast;
90
  }
91
  #description {
92
  background-color: ' . $sitemap_color_main . ';
138
  </head>
139
  <body>
140
  <div id="description">
141
+ <a href="' . esc_url( ent2ncr( get_home_url() ), array( 'http', 'https' ) ) . '"><h1>' .
142
  ent2ncr( $logo ) .
143
  esc_html( ent2ncr( $this->get_blogname() . ' &mdash; ' . __( 'XML Sitemap', 'autodescription' ) ) ) . '</h1></a>
144
  <p>' .
147
  $this->convert_markdown(
148
  /* translators: URLs are in Markdown. Don't forget to localize the URLs. */
149
  __( 'This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/).', 'autodescription' ),
150
+ array( 'a' ),
151
+ array( 'a_internal' => false )
152
  )
153
  ),
154
  array(
155
  'a' => array(
156
  'href' => true,
157
+ 'target' => true,
158
  'rel' => true,
159
  ),
160
  )
165
  $this->convert_markdown(
166
  /* translators: URLs are in Markdown. Don't localize this URL. */
167
  __( 'You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/).', 'autodescription' ),
168
+ array( 'a' ),
169
+ array( 'a_internal' => false )
170
  )
171
  ),
172
  array(
173
  'a' => array(
174
  'href' => true,
175
+ 'target' => true,
176
  'rel' => true,
177
  ),
178
  )
234
  $this->convert_markdown(
235
  /* translators: URLs are in Markdown. */
236
  __( 'Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)', 'autodescription' ),
237
+ array( 'a' ),
238
+ array( 'a_internal' => false )
239
  )
240
  ),
241
  array(
242
  'a' => array(
243
  'href' => true,
244
+ 'target' => true,
245
  'rel' => true,
246
  ),
247
  )
255
  </xsl:template>
256
  </xsl:stylesheet>';
257
 
258
+ //* Already escaped.
259
  echo $xml;
language/autodescription.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the The SEO Framework package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: The SEO Framework 2.9.2-dev-2017.05.05.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
- "POT-Creation-Date: 2017-05-07 05:43:12+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -38,7 +38,7 @@ msgstr ""
38
 
39
  #. translators: %s = Redirect URL markdown
40
 
41
- #: inc/classes/admin-init.class.php:593
42
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
43
  msgstr ""
44
 
@@ -67,7 +67,7 @@ msgid "New SEO Settings have been updated."
67
  msgstr ""
68
 
69
  #: inc/classes/admin-pages.class.php:109 inc/classes/core.class.php:253
70
- #: inc/classes/site-options.class.php:429
71
  msgid "SEO Settings"
72
  msgstr ""
73
 
@@ -165,7 +165,7 @@ msgstr ""
165
  msgid "Dismiss"
166
  msgstr ""
167
 
168
- #: inc/classes/core.class.php:413
169
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
170
  msgid "en"
171
  msgstr ""
@@ -209,228 +209,232 @@ msgstr ""
209
  msgid "%1$s is not accessible. %2$s"
210
  msgstr ""
211
 
212
- #: inc/classes/doing-it-right.class.php:82
213
  msgid "No Search"
214
  msgstr ""
215
 
216
- #: inc/classes/doing-it-right.class.php:361
 
 
 
 
217
  msgid "Refresh to see the SEO Bar status."
218
  msgstr ""
219
 
220
- #: inc/classes/doing-it-right.class.php:445
221
  msgid "Post"
222
  msgstr ""
223
 
224
- #: inc/classes/doing-it-right.class.php:449 inc/classes/inpost.class.php:379
225
  #: inc/classes/term-data.class.php:332
226
  #: inc/views/metaboxes/schema-metabox.php:204
227
  msgid "Page"
228
  msgstr ""
229
 
230
- #: inc/classes/doing-it-right.class.php:493
231
  msgid "Failed to fetch post ID."
232
  msgstr ""
233
 
234
  #. translators: %s = But or And
235
 
236
- #: inc/classes/doing-it-right.class.php:881
237
  msgid "%s the Title contains the Blogname multiple times."
238
  msgstr ""
239
 
240
  #. translators: 1: Word, 2: Occurrences
241
 
242
- #: inc/classes/doing-it-right.class.php:1052
243
  msgid "%1$s is used %2$d times."
244
  msgstr ""
245
 
246
  #. Translators: %s = Post / Page / Category, etc.
247
 
248
- #: inc/classes/doing-it-right.class.php:1097
249
  msgid "%s is being indexed."
250
  msgstr ""
251
 
252
- #: inc/classes/doing-it-right.class.php:1106
253
  msgid "But you've discouraged indexing for the whole site."
254
  msgstr ""
255
 
256
  #. translators: 1: But or And, 2: Current taxonomy term plural label
257
 
258
- #: inc/classes/doing-it-right.class.php:1130
259
  msgid "%1$s indexing for %2$s have been discouraged."
260
  msgstr ""
261
 
262
  #. translators: 1 = But or And, 1 = Post/Page
263
 
264
- #: inc/classes/doing-it-right.class.php:1143
265
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
266
  msgstr ""
267
 
268
  #. translators: %s = But or And
269
 
270
- #: inc/classes/doing-it-right.class.php:1152
271
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
272
  msgstr ""
273
 
274
  #. translators: %s = But or And
275
 
276
- #: inc/classes/doing-it-right.class.php:1166
277
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
278
  msgstr ""
279
 
280
- #: inc/classes/doing-it-right.class.php:1250
281
  msgid "%s links aren't being followed."
282
  msgstr ""
283
 
284
- #: inc/classes/doing-it-right.class.php:1256
285
  msgid "%s links are being followed."
286
  msgstr ""
287
 
288
  #. translators: %s = But or And
289
 
290
- #: inc/classes/doing-it-right.class.php:1268
291
  msgid "%s you've discouraged the following of links for the whole site."
292
  msgstr ""
293
 
294
  #. translators: 1: But or And, 2: Current taxonomy term plural label
295
 
296
- #: inc/classes/doing-it-right.class.php:1294
297
  msgid "%1$s following for %2$s have been discouraged."
298
  msgstr ""
299
 
300
  #. translators: %s = But or And
301
 
302
- #: inc/classes/doing-it-right.class.php:1306
303
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
304
  msgstr ""
305
 
306
- #: inc/classes/doing-it-right.class.php:1358
307
  msgid "Search Engines aren't allowed to archive this %s."
308
  msgstr ""
309
 
310
- #: inc/classes/doing-it-right.class.php:1363
311
  msgid "Search Engines are allowed to archive this %s."
312
  msgstr ""
313
 
314
- #: inc/classes/doing-it-right.class.php:1375
315
  msgid "But you've discouraged archiving for the whole site."
316
  msgstr ""
317
 
318
  #. translators: 1: But or And, 2: Current taxonomy term plural label
319
 
320
- #: inc/classes/doing-it-right.class.php:1401
321
  msgid "%1$s archiving for %2$s have been discouraged."
322
  msgstr ""
323
 
324
  #. translators: %s = But or And
325
 
326
- #: inc/classes/doing-it-right.class.php:1414
327
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
328
  msgstr ""
329
 
330
- #: inc/classes/doing-it-right.class.php:1460
331
  msgid "%s isn't being redirected."
332
  msgstr ""
333
 
334
- #: inc/classes/doing-it-right.class.php:1502
335
- #: inc/classes/doing-it-right.class.php:1531
336
  msgid "%s is being redirected. This means no SEO values have to be set."
337
  msgstr ""
338
 
339
- #: inc/classes/doing-it-right.class.php:1505
340
- #: inc/classes/doing-it-right.class.php:1547
341
  msgid "%s is not being indexed. This means no SEO values have to be set."
342
  msgstr ""
343
 
344
- #: inc/classes/doing-it-right.class.php:1661
345
  msgid "Title:"
346
  msgstr ""
347
 
348
- #: inc/classes/doing-it-right.class.php:1662
349
  msgid "Description:"
350
  msgstr ""
351
 
352
- #: inc/classes/doing-it-right.class.php:1663
353
  msgid "Index:"
354
  msgstr ""
355
 
356
- #: inc/classes/doing-it-right.class.php:1664
357
  msgid "Follow:"
358
  msgstr ""
359
 
360
- #: inc/classes/doing-it-right.class.php:1665
361
  msgid "Archive:"
362
  msgstr ""
363
 
364
- #: inc/classes/doing-it-right.class.php:1666
365
  msgid "Redirect:"
366
  msgstr ""
367
 
368
- #: inc/classes/doing-it-right.class.php:1668
369
  msgid "Generated: Automatically generated."
370
  msgstr ""
371
 
372
- #: inc/classes/doing-it-right.class.php:1670
373
  msgctxt "Generated"
374
  msgid "G"
375
  msgstr ""
376
 
377
- #: inc/classes/doing-it-right.class.php:1671
378
  msgctxt "Title"
379
  msgid "T"
380
  msgstr ""
381
 
382
- #: inc/classes/doing-it-right.class.php:1672
383
  msgctxt "Description"
384
  msgid "D"
385
  msgstr ""
386
 
387
- #: inc/classes/doing-it-right.class.php:1673
388
  msgctxt "no-Index"
389
  msgid "I"
390
  msgstr ""
391
 
392
- #: inc/classes/doing-it-right.class.php:1674
393
  msgctxt "no-Follow"
394
  msgid "F"
395
  msgstr ""
396
 
397
- #: inc/classes/doing-it-right.class.php:1675
398
  msgctxt "no-Archive"
399
  msgid "A"
400
  msgstr ""
401
 
402
- #: inc/classes/doing-it-right.class.php:1676
403
  msgctxt "Redirect"
404
  msgid "R"
405
  msgstr ""
406
 
407
- #: inc/classes/doing-it-right.class.php:1678
408
  msgctxt "But there are..."
409
  msgid "But"
410
  msgstr ""
411
 
412
- #: inc/classes/doing-it-right.class.php:1679
413
  msgctxt "And there are..."
414
  msgid "And"
415
  msgstr ""
416
 
417
- #: inc/classes/doing-it-right.class.php:1681
418
  msgid "Length is far too short."
419
  msgstr ""
420
 
421
- #: inc/classes/doing-it-right.class.php:1682
422
  msgid "Length is too short."
423
  msgstr ""
424
 
425
- #: inc/classes/doing-it-right.class.php:1683
426
  msgid "Length is too long."
427
  msgstr ""
428
 
429
- #: inc/classes/doing-it-right.class.php:1684
430
  msgid "Length is far too long."
431
  msgstr ""
432
 
433
- #: inc/classes/doing-it-right.class.php:1685
434
  msgid "Length is good."
435
  msgstr ""
436
 
@@ -455,7 +459,7 @@ msgstr ""
455
 
456
  #. translators: Front-end output.
457
 
458
- #: inc/classes/generate-description.class.php:684
459
  #: inc/views/metaboxes/description-metabox.php:18
460
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
461
  msgid "on"
@@ -463,14 +467,12 @@ msgstr ""
463
 
464
  #. translators: Front-end output.
465
 
466
- #: inc/classes/generate-description.class.php:746
467
  msgid "Latest posts:"
468
  msgstr ""
469
 
470
- #: inc/classes/generate-ldjson.class.php:538
471
- #: inc/classes/generate-ldjson.class.php:541
472
- #: inc/classes/generate-ldjson.class.php:581
473
- #: inc/classes/generate-ldjson.class.php:584
474
  msgid "Uncategorized"
475
  msgstr ""
476
 
@@ -614,13 +616,13 @@ msgstr ""
614
  msgid "Search results for:"
615
  msgstr ""
616
 
617
- #. translators: Front-end output
618
 
619
  #: inc/classes/generate-title.class.php:1214
620
  msgid "Protected: %s"
621
  msgstr ""
622
 
623
- #. translators: Front-end output
624
 
625
  #: inc/classes/generate-title.class.php:1218
626
  msgid "Private: %s"
@@ -638,25 +640,25 @@ msgstr ""
638
 
639
  #. translators: %s = 'The SEO Framework'
640
 
641
- #: inc/classes/render.class.php:1089
642
  msgid "Start %s"
643
  msgstr ""
644
 
645
  #. translators: %s = 'The SEO Framework'
646
 
647
- #: inc/classes/render.class.php:1091
648
  msgid "End %s"
649
  msgstr ""
650
 
651
- #: inc/classes/render.class.php:1092
652
  msgid "by Sybre Waaijer"
653
  msgstr ""
654
 
655
- #: inc/classes/site-options.class.php:429
656
  msgid "here"
657
  msgstr ""
658
 
659
- #: inc/classes/site-options.class.php:430
660
  msgctxt "%s = here"
661
  msgid "View the new options %s."
662
  msgstr ""
@@ -669,7 +671,7 @@ msgstr ""
669
  msgid "Sitemap is served from cache"
670
  msgstr ""
671
 
672
- #: inc/classes/sitemaps.class.php:592
673
  msgid "Sitemap is generated on"
674
  msgstr ""
675
 
@@ -724,18 +726,18 @@ msgstr ""
724
  #: inc/views/inpost/seo-settings-tt.php:96
725
  #: inc/views/inpost/seo-settings-tt.php:112
726
  #: inc/views/metaboxes/homepage-metabox.php:176
727
- #: inc/views/metaboxes/homepage-metabox.php:227
728
  msgid "Characters Used: %s"
729
  msgstr ""
730
 
731
  #: inc/views/inpost/seo-settings-singular.php:126
732
- #: inc/views/metaboxes/homepage-metabox.php:224
733
  msgid "Custom %s Description"
734
  msgstr ""
735
 
736
  #: inc/views/inpost/seo-settings-singular.php:127
737
  #: inc/views/inpost/seo-settings-tt.php:106
738
- #: inc/views/metaboxes/homepage-metabox.php:225
739
  msgid "Recommended Length: 145 to 155 characters"
740
  msgstr ""
741
 
@@ -768,7 +770,7 @@ msgid "Tell Search Engines not to save a cached copy of this %s"
768
  msgstr ""
769
 
770
  #: inc/views/inpost/seo-settings-singular.php:210
771
- msgid "Local Search Settings"
772
  msgstr ""
773
 
774
  #: inc/views/inpost/seo-settings-singular.php:218
@@ -779,19 +781,27 @@ msgstr ""
779
  msgid "This excludes this %s from local on-site search results"
780
  msgstr ""
781
 
782
- #: inc/views/inpost/seo-settings-singular.php:232
 
 
 
 
 
 
 
 
783
  msgid "Custom 301 Redirect URL"
784
  msgstr ""
785
 
786
- #: inc/views/inpost/seo-settings-singular.php:236
787
  msgid "This will force visitors to go to another URL"
788
  msgstr ""
789
 
790
- #: inc/views/inpost/seo-settings-singular.php:259
791
  msgid "Custom Social Image URL"
792
  msgstr ""
793
 
794
- #: inc/views/inpost/seo-settings-singular.php:260
795
  msgid "Preferred %s Social Image URL location"
796
  msgstr ""
797
 
@@ -810,17 +820,17 @@ msgid "Apply %s to this term?"
810
  msgstr ""
811
 
812
  #: inc/views/inpost/seo-settings-tt.php:123
813
- #: inc/views/metaboxes/homepage-metabox.php:350
814
  msgid "Tell Search Engines not to show this page in their search results"
815
  msgstr ""
816
 
817
  #: inc/views/inpost/seo-settings-tt.php:130
818
- #: inc/views/metaboxes/homepage-metabox.php:360
819
  msgid "Tell Search Engines not to follow links on this page"
820
  msgstr ""
821
 
822
  #: inc/views/inpost/seo-settings-tt.php:137
823
- #: inc/views/metaboxes/homepage-metabox.php:370
824
  msgid "Tell Search Engines not to save a cached copy of this page"
825
  msgstr ""
826
 
@@ -837,7 +847,7 @@ msgid "Automated Description Settings"
837
  msgstr ""
838
 
839
  #: inc/views/metaboxes/description-metabox.php:42
840
- #: inc/views/metaboxes/homepage-metabox.php:236
841
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
842
  msgstr ""
843
 
@@ -1118,8 +1128,8 @@ msgid "Description"
1118
  msgstr ""
1119
 
1120
  #: inc/views/metaboxes/homepage-metabox.php:73
1121
- #: inc/views/metaboxes/homepage-metabox.php:272
1122
- #: inc/views/metaboxes/homepage-metabox.php:317
1123
  #: inc/views/metaboxes/social-metabox.php:283
1124
  #: inc/views/metaboxes/social-metabox.php:314
1125
  msgid "Home Page"
@@ -1144,90 +1154,90 @@ msgstr ""
1144
  #. translators: %s = Home page URL markdown
1145
 
1146
  #: inc/views/metaboxes/homepage-metabox.php:212
1147
- #: inc/views/metaboxes/homepage-metabox.php:252
1148
  msgid "A plugin has been detected that suggests to maintain this option on the [Home Page](%s)."
1149
  msgstr ""
1150
 
1151
- #: inc/views/metaboxes/homepage-metabox.php:276
1152
  #: inc/views/metaboxes/title-metabox.php:132
1153
  msgid "Document Title Additions Location"
1154
  msgstr ""
1155
 
1156
- #: inc/views/metaboxes/homepage-metabox.php:277
1157
  #: inc/views/metaboxes/title-metabox.php:134
1158
  msgid "Determines which side the added title text will go on."
1159
  msgstr ""
1160
 
1161
- #: inc/views/metaboxes/homepage-metabox.php:283
1162
  #: inc/views/metaboxes/title-metabox.php:140
1163
  msgid "Left:"
1164
  msgstr ""
1165
 
1166
- #: inc/views/metaboxes/homepage-metabox.php:293
1167
  #: inc/views/metaboxes/title-metabox.php:147
1168
  msgid "Right:"
1169
  msgstr ""
1170
 
1171
- #: inc/views/metaboxes/homepage-metabox.php:304
1172
  msgid "%s Tagline"
1173
  msgstr ""
1174
 
1175
- #: inc/views/metaboxes/homepage-metabox.php:308
1176
  msgid "Add site description (tagline) to the Title on the %s?"
1177
  msgstr ""
1178
 
1179
- #: inc/views/metaboxes/homepage-metabox.php:334
1180
  msgid "View Home Page Settings"
1181
  msgstr ""
1182
 
1183
- #: inc/views/metaboxes/homepage-metabox.php:334
1184
  msgid "Checked in Page"
1185
  msgstr ""
1186
 
1187
- #: inc/views/metaboxes/homepage-metabox.php:338
1188
  msgid "Home Page Robots Meta Settings"
1189
  msgstr ""
1190
 
1191
  #. translators: 1: Option, 2: Location
1192
 
1193
- #: inc/views/metaboxes/homepage-metabox.php:347
1194
- #: inc/views/metaboxes/homepage-metabox.php:357
1195
- #: inc/views/metaboxes/homepage-metabox.php:367
1196
  msgid "Apply %1$s to the %2$s?"
1197
  msgstr ""
1198
 
1199
- #: inc/views/metaboxes/homepage-metabox.php:402
1200
  msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
1201
  msgstr ""
1202
 
1203
- #: inc/views/metaboxes/homepage-metabox.php:408
1204
  msgid "Home Page Pagination Robots Settings"
1205
  msgstr ""
1206
 
1207
- #: inc/views/metaboxes/homepage-metabox.php:409
1208
  msgid "If your Home Page is paginated and outputs content that's also found elsewhere on the website, enabling this option might prevent duplicate content."
1209
  msgstr ""
1210
 
1211
  #. translators: 1: Option, 2: Location
1212
 
1213
- #: inc/views/metaboxes/homepage-metabox.php:417
1214
  msgid "Apply %1$s to every second or later page on the %2$s?"
1215
  msgstr ""
1216
 
1217
- #: inc/views/metaboxes/homepage-metabox.php:427
1218
  #: inc/views/metaboxes/social-metabox.php:116
1219
  msgid "Social Image Settings"
1220
  msgstr ""
1221
 
1222
- #: inc/views/metaboxes/homepage-metabox.php:429
1223
  msgid "A social image can be displayed when your homepage is shared. It is a great way to grab attention."
1224
  msgstr ""
1225
 
1226
- #: inc/views/metaboxes/homepage-metabox.php:458
1227
  msgid "Custom Home Page Image URL"
1228
  msgstr ""
1229
 
1230
- #: inc/views/metaboxes/homepage-metabox.php:459
1231
  msgid "Preferred Home Page Social Image URL location"
1232
  msgstr ""
1233
 
@@ -1801,12 +1811,12 @@ msgstr ""
1801
 
1802
  #: inc/views/metaboxes/social-metabox.php:169
1803
  msgctxt "Example Facebook Personal URL"
1804
- msgid "http://www.facebook.com/YourPersonalProfile"
1805
  msgstr ""
1806
 
1807
  #: inc/views/metaboxes/social-metabox.php:172
1808
  msgctxt "Example Verified Facebook Business URL"
1809
- msgid "http://www.facebook.com/YourVerifiedBusinessProfile"
1810
  msgstr ""
1811
 
1812
  #: inc/views/metaboxes/social-metabox.php:177
@@ -2048,37 +2058,37 @@ msgid "Get the Pinterest Verification Code"
2048
  msgstr ""
2049
 
2050
  #: inc/views/sitemap/xsl-stylesheet.php:8
2051
- #: inc/views/sitemap/xsl-stylesheet.php:142
2052
  msgid "XML Sitemap"
2053
  msgstr ""
2054
 
2055
  #. translators: URLs are in Markdown. Don't forget to localize the URLs.
2056
 
2057
- #: inc/views/sitemap/xsl-stylesheet.php:148
2058
  msgid "This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/)."
2059
  msgstr ""
2060
 
2061
  #. translators: URLs are in Markdown. Don't localize this URL.
2062
 
2063
- #: inc/views/sitemap/xsl-stylesheet.php:164
2064
  msgid "You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/)."
2065
  msgstr ""
2066
 
2067
- #: inc/views/sitemap/xsl-stylesheet.php:179
2068
  msgid "URL"
2069
  msgstr ""
2070
 
2071
- #: inc/views/sitemap/xsl-stylesheet.php:183
2072
  msgid "Last Updated"
2073
  msgstr ""
2074
 
2075
- #: inc/views/sitemap/xsl-stylesheet.php:187
2076
  msgid "Priority"
2077
  msgstr ""
2078
 
2079
  #. translators: URLs are in Markdown.
2080
 
2081
- #: inc/views/sitemap/xsl-stylesheet.php:231
2082
  msgid "Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)"
2083
  msgstr ""
2084
  #. Plugin Name of the plugin/theme
2
  # This file is distributed under the same license as the The SEO Framework package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: The SEO Framework 2.9.3\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
+ "POT-Creation-Date: 2017-07-03 03:25:56+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
38
 
39
  #. translators: %s = Redirect URL markdown
40
 
41
+ #: inc/classes/admin-init.class.php:595
42
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
43
  msgstr ""
44
 
67
  msgstr ""
68
 
69
  #: inc/classes/admin-pages.class.php:109 inc/classes/core.class.php:253
70
+ #: inc/classes/site-options.class.php:434
71
  msgid "SEO Settings"
72
  msgstr ""
73
 
165
  msgid "Dismiss"
166
  msgstr ""
167
 
168
+ #: inc/classes/core.class.php:459
169
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
170
  msgid "en"
171
  msgstr ""
209
  msgid "%1$s is not accessible. %2$s"
210
  msgstr ""
211
 
212
+ #: inc/classes/doing-it-right.class.php:83
213
  msgid "No Search"
214
  msgstr ""
215
 
216
+ #: inc/classes/doing-it-right.class.php:86
217
+ msgid "No Archive"
218
+ msgstr ""
219
+
220
+ #: inc/classes/doing-it-right.class.php:365
221
  msgid "Refresh to see the SEO Bar status."
222
  msgstr ""
223
 
224
+ #: inc/classes/doing-it-right.class.php:449
225
  msgid "Post"
226
  msgstr ""
227
 
228
+ #: inc/classes/doing-it-right.class.php:453 inc/classes/inpost.class.php:379
229
  #: inc/classes/term-data.class.php:332
230
  #: inc/views/metaboxes/schema-metabox.php:204
231
  msgid "Page"
232
  msgstr ""
233
 
234
+ #: inc/classes/doing-it-right.class.php:497
235
  msgid "Failed to fetch post ID."
236
  msgstr ""
237
 
238
  #. translators: %s = But or And
239
 
240
+ #: inc/classes/doing-it-right.class.php:885
241
  msgid "%s the Title contains the Blogname multiple times."
242
  msgstr ""
243
 
244
  #. translators: 1: Word, 2: Occurrences
245
 
246
+ #: inc/classes/doing-it-right.class.php:1056
247
  msgid "%1$s is used %2$d times."
248
  msgstr ""
249
 
250
  #. Translators: %s = Post / Page / Category, etc.
251
 
252
+ #: inc/classes/doing-it-right.class.php:1101
253
  msgid "%s is being indexed."
254
  msgstr ""
255
 
256
+ #: inc/classes/doing-it-right.class.php:1110
257
  msgid "But you've discouraged indexing for the whole site."
258
  msgstr ""
259
 
260
  #. translators: 1: But or And, 2: Current taxonomy term plural label
261
 
262
+ #: inc/classes/doing-it-right.class.php:1134
263
  msgid "%1$s indexing for %2$s have been discouraged."
264
  msgstr ""
265
 
266
  #. translators: 1 = But or And, 1 = Post/Page
267
 
268
+ #: inc/classes/doing-it-right.class.php:1147
269
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
270
  msgstr ""
271
 
272
  #. translators: %s = But or And
273
 
274
+ #: inc/classes/doing-it-right.class.php:1156
275
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
276
  msgstr ""
277
 
278
  #. translators: %s = But or And
279
 
280
+ #: inc/classes/doing-it-right.class.php:1170
281
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
282
  msgstr ""
283
 
284
+ #: inc/classes/doing-it-right.class.php:1254
285
  msgid "%s links aren't being followed."
286
  msgstr ""
287
 
288
+ #: inc/classes/doing-it-right.class.php:1260
289
  msgid "%s links are being followed."
290
  msgstr ""
291
 
292
  #. translators: %s = But or And
293
 
294
+ #: inc/classes/doing-it-right.class.php:1272
295
  msgid "%s you've discouraged the following of links for the whole site."
296
  msgstr ""
297
 
298
  #. translators: 1: But or And, 2: Current taxonomy term plural label
299
 
300
+ #: inc/classes/doing-it-right.class.php:1298
301
  msgid "%1$s following for %2$s have been discouraged."
302
  msgstr ""
303
 
304
  #. translators: %s = But or And
305
 
306
+ #: inc/classes/doing-it-right.class.php:1310
307
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
308
  msgstr ""
309
 
310
+ #: inc/classes/doing-it-right.class.php:1362
311
  msgid "Search Engines aren't allowed to archive this %s."
312
  msgstr ""
313
 
314
+ #: inc/classes/doing-it-right.class.php:1367
315
  msgid "Search Engines are allowed to archive this %s."
316
  msgstr ""
317
 
318
+ #: inc/classes/doing-it-right.class.php:1379
319
  msgid "But you've discouraged archiving for the whole site."
320
  msgstr ""
321
 
322
  #. translators: 1: But or And, 2: Current taxonomy term plural label
323
 
324
+ #: inc/classes/doing-it-right.class.php:1405
325
  msgid "%1$s archiving for %2$s have been discouraged."
326
  msgstr ""
327
 
328
  #. translators: %s = But or And
329
 
330
+ #: inc/classes/doing-it-right.class.php:1418
331
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
332
  msgstr ""
333
 
334
+ #: inc/classes/doing-it-right.class.php:1464
335
  msgid "%s isn't being redirected."
336
  msgstr ""
337
 
338
+ #: inc/classes/doing-it-right.class.php:1506
339
+ #: inc/classes/doing-it-right.class.php:1535
340
  msgid "%s is being redirected. This means no SEO values have to be set."
341
  msgstr ""
342
 
343
+ #: inc/classes/doing-it-right.class.php:1509
344
+ #: inc/classes/doing-it-right.class.php:1551
345
  msgid "%s is not being indexed. This means no SEO values have to be set."
346
  msgstr ""
347
 
348
+ #: inc/classes/doing-it-right.class.php:1665
349
  msgid "Title:"
350
  msgstr ""
351
 
352
+ #: inc/classes/doing-it-right.class.php:1666
353
  msgid "Description:"
354
  msgstr ""
355
 
356
+ #: inc/classes/doing-it-right.class.php:1667
357
  msgid "Index:"
358
  msgstr ""
359
 
360
+ #: inc/classes/doing-it-right.class.php:1668
361
  msgid "Follow:"
362
  msgstr ""
363
 
364
+ #: inc/classes/doing-it-right.class.php:1669
365
  msgid "Archive:"
366
  msgstr ""
367
 
368
+ #: inc/classes/doing-it-right.class.php:1670
369
  msgid "Redirect:"
370
  msgstr ""
371
 
372
+ #: inc/classes/doing-it-right.class.php:1672
373
  msgid "Generated: Automatically generated."
374
  msgstr ""
375
 
376
+ #: inc/classes/doing-it-right.class.php:1674
377
  msgctxt "Generated"
378
  msgid "G"
379
  msgstr ""
380
 
381
+ #: inc/classes/doing-it-right.class.php:1675
382
  msgctxt "Title"
383
  msgid "T"
384
  msgstr ""
385
 
386
+ #: inc/classes/doing-it-right.class.php:1676
387
  msgctxt "Description"
388
  msgid "D"
389
  msgstr ""
390
 
391
+ #: inc/classes/doing-it-right.class.php:1677
392
  msgctxt "no-Index"
393
  msgid "I"
394
  msgstr ""
395
 
396
+ #: inc/classes/doing-it-right.class.php:1678
397
  msgctxt "no-Follow"
398
  msgid "F"
399
  msgstr ""
400
 
401
+ #: inc/classes/doing-it-right.class.php:1679
402
  msgctxt "no-Archive"
403
  msgid "A"
404
  msgstr ""
405
 
406
+ #: inc/classes/doing-it-right.class.php:1680
407
  msgctxt "Redirect"
408
  msgid "R"
409
  msgstr ""
410
 
411
+ #: inc/classes/doing-it-right.class.php:1682
412
  msgctxt "But there are..."
413
  msgid "But"
414
  msgstr ""
415
 
416
+ #: inc/classes/doing-it-right.class.php:1683
417
  msgctxt "And there are..."
418
  msgid "And"
419
  msgstr ""
420
 
421
+ #: inc/classes/doing-it-right.class.php:1685
422
  msgid "Length is far too short."
423
  msgstr ""
424
 
425
+ #: inc/classes/doing-it-right.class.php:1686
426
  msgid "Length is too short."
427
  msgstr ""
428
 
429
+ #: inc/classes/doing-it-right.class.php:1687
430
  msgid "Length is too long."
431
  msgstr ""
432
 
433
+ #: inc/classes/doing-it-right.class.php:1688
434
  msgid "Length is far too long."
435
  msgstr ""
436
 
437
+ #: inc/classes/doing-it-right.class.php:1689
438
  msgid "Length is good."
439
  msgstr ""
440
 
459
 
460
  #. translators: Front-end output.
461
 
462
+ #: inc/classes/generate-description.class.php:685
463
  #: inc/views/metaboxes/description-metabox.php:18
464
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
465
  msgid "on"
467
 
468
  #. translators: Front-end output.
469
 
470
+ #: inc/classes/generate-description.class.php:773
471
  msgid "Latest posts:"
472
  msgstr ""
473
 
474
+ #: inc/classes/generate-ldjson.class.php:605
475
+ #: inc/classes/generate-ldjson.class.php:608
 
 
476
  msgid "Uncategorized"
477
  msgstr ""
478
 
616
  msgid "Search results for:"
617
  msgstr ""
618
 
619
+ #. translators: Front-end output.
620
 
621
  #: inc/classes/generate-title.class.php:1214
622
  msgid "Protected: %s"
623
  msgstr ""
624
 
625
+ #. translators: Front-end output.
626
 
627
  #: inc/classes/generate-title.class.php:1218
628
  msgid "Private: %s"
640
 
641
  #. translators: %s = 'The SEO Framework'
642
 
643
+ #: inc/classes/render.class.php:1118
644
  msgid "Start %s"
645
  msgstr ""
646
 
647
  #. translators: %s = 'The SEO Framework'
648
 
649
+ #: inc/classes/render.class.php:1120
650
  msgid "End %s"
651
  msgstr ""
652
 
653
+ #: inc/classes/render.class.php:1121
654
  msgid "by Sybre Waaijer"
655
  msgstr ""
656
 
657
+ #: inc/classes/site-options.class.php:434
658
  msgid "here"
659
  msgstr ""
660
 
661
+ #: inc/classes/site-options.class.php:435
662
  msgctxt "%s = here"
663
  msgid "View the new options %s."
664
  msgstr ""
671
  msgid "Sitemap is served from cache"
672
  msgstr ""
673
 
674
+ #: inc/classes/sitemaps.class.php:607
675
  msgid "Sitemap is generated on"
676
  msgstr ""
677
 
726
  #: inc/views/inpost/seo-settings-tt.php:96
727
  #: inc/views/inpost/seo-settings-tt.php:112
728
  #: inc/views/metaboxes/homepage-metabox.php:176
729
+ #: inc/views/metaboxes/homepage-metabox.php:228
730
  msgid "Characters Used: %s"
731
  msgstr ""
732
 
733
  #: inc/views/inpost/seo-settings-singular.php:126
734
+ #: inc/views/metaboxes/homepage-metabox.php:225
735
  msgid "Custom %s Description"
736
  msgstr ""
737
 
738
  #: inc/views/inpost/seo-settings-singular.php:127
739
  #: inc/views/inpost/seo-settings-tt.php:106
740
+ #: inc/views/metaboxes/homepage-metabox.php:226
741
  msgid "Recommended Length: 145 to 155 characters"
742
  msgstr ""
743
 
770
  msgstr ""
771
 
772
  #: inc/views/inpost/seo-settings-singular.php:210
773
+ msgid "Archive Settings"
774
  msgstr ""
775
 
776
  #: inc/views/inpost/seo-settings-singular.php:218
781
  msgid "This excludes this %s from local on-site search results"
782
  msgstr ""
783
 
784
+ #: inc/views/inpost/seo-settings-singular.php:228
785
+ msgid "Exclude this %s from archive listing"
786
+ msgstr ""
787
+
788
+ #: inc/views/inpost/seo-settings-singular.php:230
789
+ msgid "This excludes this %s from on-site archive pages"
790
+ msgstr ""
791
+
792
+ #: inc/views/inpost/seo-settings-singular.php:243
793
  msgid "Custom 301 Redirect URL"
794
  msgstr ""
795
 
796
+ #: inc/views/inpost/seo-settings-singular.php:247
797
  msgid "This will force visitors to go to another URL"
798
  msgstr ""
799
 
800
+ #: inc/views/inpost/seo-settings-singular.php:270
801
  msgid "Custom Social Image URL"
802
  msgstr ""
803
 
804
+ #: inc/views/inpost/seo-settings-singular.php:271
805
  msgid "Preferred %s Social Image URL location"
806
  msgstr ""
807
 
820
  msgstr ""
821
 
822
  #: inc/views/inpost/seo-settings-tt.php:123
823
+ #: inc/views/metaboxes/homepage-metabox.php:352
824
  msgid "Tell Search Engines not to show this page in their search results"
825
  msgstr ""
826
 
827
  #: inc/views/inpost/seo-settings-tt.php:130
828
+ #: inc/views/metaboxes/homepage-metabox.php:362
829
  msgid "Tell Search Engines not to follow links on this page"
830
  msgstr ""
831
 
832
  #: inc/views/inpost/seo-settings-tt.php:137
833
+ #: inc/views/metaboxes/homepage-metabox.php:372
834
  msgid "Tell Search Engines not to save a cached copy of this page"
835
  msgstr ""
836
 
847
  msgstr ""
848
 
849
  #: inc/views/metaboxes/description-metabox.php:42
850
+ #: inc/views/metaboxes/homepage-metabox.php:237
851
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
852
  msgstr ""
853
 
1128
  msgstr ""
1129
 
1130
  #: inc/views/metaboxes/homepage-metabox.php:73
1131
+ #: inc/views/metaboxes/homepage-metabox.php:274
1132
+ #: inc/views/metaboxes/homepage-metabox.php:319
1133
  #: inc/views/metaboxes/social-metabox.php:283
1134
  #: inc/views/metaboxes/social-metabox.php:314
1135
  msgid "Home Page"
1154
  #. translators: %s = Home page URL markdown
1155
 
1156
  #: inc/views/metaboxes/homepage-metabox.php:212
1157
+ #: inc/views/metaboxes/homepage-metabox.php:253
1158
  msgid "A plugin has been detected that suggests to maintain this option on the [Home Page](%s)."
1159
  msgstr ""
1160
 
1161
+ #: inc/views/metaboxes/homepage-metabox.php:278
1162
  #: inc/views/metaboxes/title-metabox.php:132
1163
  msgid "Document Title Additions Location"
1164
  msgstr ""
1165
 
1166
+ #: inc/views/metaboxes/homepage-metabox.php:279
1167
  #: inc/views/metaboxes/title-metabox.php:134
1168
  msgid "Determines which side the added title text will go on."
1169
  msgstr ""
1170
 
1171
+ #: inc/views/metaboxes/homepage-metabox.php:285
1172
  #: inc/views/metaboxes/title-metabox.php:140
1173
  msgid "Left:"
1174
  msgstr ""
1175
 
1176
+ #: inc/views/metaboxes/homepage-metabox.php:295
1177
  #: inc/views/metaboxes/title-metabox.php:147
1178
  msgid "Right:"
1179
  msgstr ""
1180
 
1181
+ #: inc/views/metaboxes/homepage-metabox.php:306
1182
  msgid "%s Tagline"
1183
  msgstr ""
1184
 
1185
+ #: inc/views/metaboxes/homepage-metabox.php:310
1186
  msgid "Add site description (tagline) to the Title on the %s?"
1187
  msgstr ""
1188
 
1189
+ #: inc/views/metaboxes/homepage-metabox.php:336
1190
  msgid "View Home Page Settings"
1191
  msgstr ""
1192
 
1193
+ #: inc/views/metaboxes/homepage-metabox.php:336
1194
  msgid "Checked in Page"
1195
  msgstr ""
1196
 
1197
+ #: inc/views/metaboxes/homepage-metabox.php:340
1198
  msgid "Home Page Robots Meta Settings"
1199
  msgstr ""
1200
 
1201
  #. translators: 1: Option, 2: Location
1202
 
1203
+ #: inc/views/metaboxes/homepage-metabox.php:349
1204
+ #: inc/views/metaboxes/homepage-metabox.php:359
1205
+ #: inc/views/metaboxes/homepage-metabox.php:369
1206
  msgid "Apply %1$s to the %2$s?"
1207
  msgstr ""
1208
 
1209
+ #: inc/views/metaboxes/homepage-metabox.php:404
1210
  msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
1211
  msgstr ""
1212
 
1213
+ #: inc/views/metaboxes/homepage-metabox.php:410
1214
  msgid "Home Page Pagination Robots Settings"
1215
  msgstr ""
1216
 
1217
+ #: inc/views/metaboxes/homepage-metabox.php:411
1218
  msgid "If your Home Page is paginated and outputs content that's also found elsewhere on the website, enabling this option might prevent duplicate content."
1219
  msgstr ""
1220
 
1221
  #. translators: 1: Option, 2: Location
1222
 
1223
+ #: inc/views/metaboxes/homepage-metabox.php:419
1224
  msgid "Apply %1$s to every second or later page on the %2$s?"
1225
  msgstr ""
1226
 
1227
+ #: inc/views/metaboxes/homepage-metabox.php:429
1228
  #: inc/views/metaboxes/social-metabox.php:116
1229
  msgid "Social Image Settings"
1230
  msgstr ""
1231
 
1232
+ #: inc/views/metaboxes/homepage-metabox.php:431
1233
  msgid "A social image can be displayed when your homepage is shared. It is a great way to grab attention."
1234
  msgstr ""
1235
 
1236
+ #: inc/views/metaboxes/homepage-metabox.php:460
1237
  msgid "Custom Home Page Image URL"
1238
  msgstr ""
1239
 
1240
+ #: inc/views/metaboxes/homepage-metabox.php:461
1241
  msgid "Preferred Home Page Social Image URL location"
1242
  msgstr ""
1243
 
1811
 
1812
  #: inc/views/metaboxes/social-metabox.php:169
1813
  msgctxt "Example Facebook Personal URL"
1814
+ msgid "https://www.facebook.com/YourPersonalProfile"
1815
  msgstr ""
1816
 
1817
  #: inc/views/metaboxes/social-metabox.php:172
1818
  msgctxt "Example Verified Facebook Business URL"
1819
+ msgid "https://www.facebook.com/YourVerifiedBusinessProfile"
1820
  msgstr ""
1821
 
1822
  #: inc/views/metaboxes/social-metabox.php:177
2058
  msgstr ""
2059
 
2060
  #: inc/views/sitemap/xsl-stylesheet.php:8
2061
+ #: inc/views/sitemap/xsl-stylesheet.php:143
2062
  msgid "XML Sitemap"
2063
  msgstr ""
2064
 
2065
  #. translators: URLs are in Markdown. Don't forget to localize the URLs.
2066
 
2067
+ #: inc/views/sitemap/xsl-stylesheet.php:149
2068
  msgid "This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/)."
2069
  msgstr ""
2070
 
2071
  #. translators: URLs are in Markdown. Don't localize this URL.
2072
 
2073
+ #: inc/views/sitemap/xsl-stylesheet.php:167
2074
  msgid "You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/)."
2075
  msgstr ""
2076
 
2077
+ #: inc/views/sitemap/xsl-stylesheet.php:184
2078
  msgid "URL"
2079
  msgstr ""
2080
 
2081
+ #: inc/views/sitemap/xsl-stylesheet.php:188
2082
  msgid "Last Updated"
2083
  msgstr ""
2084
 
2085
+ #: inc/views/sitemap/xsl-stylesheet.php:192
2086
  msgid "Priority"
2087
  msgstr ""
2088
 
2089
  #. translators: URLs are in Markdown.
2090
 
2091
+ #: inc/views/sitemap/xsl-stylesheet.php:236
2092
  msgid "Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)"
2093
  msgstr ""
2094
  #. Plugin Name of the plugin/theme
lib/css/tsf-rtl.css CHANGED
@@ -121,6 +121,7 @@ th.column-tsf-seo-bar-wrap ~ th {
121
  overflow: hidden;
122
  white-space: pre;
123
  text-overflow: ellipsis;
 
124
  }
125
 
126
  /* START Character Counters */
@@ -132,6 +133,7 @@ th.column-tsf-seo-bar-wrap ~ th {
132
  -moz-user-select: none;
133
  -ms-user-select: none;
134
  user-select: none;
 
135
  }
136
 
137
  span.tsf-count-bad {
121
  overflow: hidden;
122
  white-space: pre;
123
  text-overflow: ellipsis;
124
+ will-change: left, right;
125
  }
126
 
127
  /* START Character Counters */
133
  -moz-user-select: none;
134
  -ms-user-select: none;
135
  user-select: none;
136
+ will-change: contents;
137
  }
138
 
139
  span.tsf-count-bad {
lib/css/tsf-rtl.min.css CHANGED
@@ -1 +1 @@
1
- #tsf-title-offset,#tsf-title-placeholder{right:0;white-space:pre;position:absolute}.tsf-metaboxes .tsf-top-buttons,.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-left:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;left:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;color:transparent}#tsf-title-placeholder{color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;overflow:hidden;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.tsf-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left;pointer-events:none}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}.tsf-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-metaboxes .tsf-nav-tab{float:right;border:1px solid #ccc;margin-right:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-counter .tsf-ajax{margin-right:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-left:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
1
+ #tsf-title-offset,#tsf-title-placeholder{right:0;white-space:pre;position:absolute}.tsf-metaboxes .tsf-top-buttons,.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-left:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;left:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;color:transparent}#tsf-title-placeholder{color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;overflow:hidden;text-overflow:ellipsis;will-change:left,right}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.tsf-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left;pointer-events:none}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}.tsf-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-metaboxes .tsf-nav-tab{float:right;border:1px solid #ccc;margin-right:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-counter .tsf-ajax{margin-right:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-left:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
lib/css/tsf.css CHANGED
@@ -126,6 +126,7 @@ th.column-tsf-seo-bar-wrap ~ th {
126
  overflow: hidden;
127
  white-space: pre;
128
  text-overflow: ellipsis;
 
129
  }
130
 
131
  /* START Character Counters */
@@ -137,6 +138,7 @@ th.column-tsf-seo-bar-wrap ~ th {
137
  -moz-user-select: none;
138
  -ms-user-select: none;
139
  user-select: none;
 
140
  }
141
 
142
  span.tsf-count-bad {
126
  overflow: hidden;
127
  white-space: pre;
128
  text-overflow: ellipsis;
129
+ will-change: left, right;
130
  }
131
 
132
  /* START Character Counters */
138
  -moz-user-select: none;
139
  -ms-user-select: none;
140
  user-select: none;
141
+ will-change: contents;
142
  }
143
 
144
  span.tsf-count-bad {
lib/css/tsf.min.css CHANGED
@@ -1 +1 @@
1
- .tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-right:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;right:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;left:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:pre;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.tsf-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left;pointer-events:none}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-top-buttons{float:right}.tsf-metaboxes .tsf-bottom-buttons{text-align:right}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}.tsf-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-metaboxes .tsf-nav-tab{float:left;border:1px solid #ccc;margin-left:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-counter .tsf-ajax{margin-left:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-right:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
1
+ .tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-right:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;right:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;left:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:pre;text-overflow:ellipsis;will-change:left,right}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.tsf-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left;pointer-events:none}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-top-buttons{float:right}.tsf-metaboxes .tsf-bottom-buttons{text-align:right}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}.tsf-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-metaboxes .tsf-nav-tab{float:left;border:1px solid #ccc;margin-left:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-counter .tsf-ajax{margin-left:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-right:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:color .33s ease-in,text-shadow .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
lib/js/tsf.js CHANGED
@@ -31,6 +31,8 @@
31
  // ==/ClosureCompiler==
32
  // http://closure-compiler.appspot.com/home
33
 
 
 
34
  /**
35
  * Holds The SEO Framework values in an object to avoid polluting global namespace.
36
  *
@@ -183,17 +185,13 @@ window.tsf = {
183
  * @return {!jQuery} The jQuery doctitle ID's
184
  */
185
  docTitles: function() {
186
- 'use strict';
187
-
188
  /** Concept:
189
  if ( this.docTitles.cache )
190
  return this.docTitles.cache;
191
 
192
- // converted to var in compiler.
193
  let $doctitles = this.docTitles.cache = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
194
  */
195
 
196
- // converted to var in compiler.
197
  let $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
198
 
199
  return $doctitles;
@@ -209,17 +207,13 @@ window.tsf = {
209
  * @return {!jQuery} The jQuery description ID's
210
  */
211
  docDescriptions: function() {
212
- 'use strict';
213
-
214
  /** Concept:
215
  if ( this.docDescriptions.cache )
216
  return this.docDescriptions.cache;
217
 
218
- // converted to var in compiler.
219
  let $descriptions = this.docDescriptions.cache = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
220
  */
221
 
222
- // converted to var in compiler.
223
  let $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
224
 
225
  return $descriptions;
@@ -235,8 +229,6 @@ window.tsf = {
235
  * @return {(Boolean|null)} True on OK, false on cancel.
236
  */
237
  confirm: function( text ) {
238
- 'use strict';
239
-
240
  return confirm( text );
241
  },
242
 
@@ -244,17 +236,18 @@ window.tsf = {
244
  * Description length counter.
245
  *
246
  * @since 2.2.4
 
247
  *
248
  * @function
249
  * @param {!jQuery.Event} event
250
  * @return {undefined}
251
  */
252
  updateCharacterCountDescription: function( event ) {
253
- 'use strict';
254
 
255
- var $this = jQuery( event.target ),
256
- calcLength = $this.val().length,
257
- $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
 
258
  counterClass = '',
259
  name = '',
260
  output = '';
@@ -262,7 +255,7 @@ window.tsf = {
262
  // Emptied input, get Description placeholder.
263
  if ( 0 === calcLength ) {
264
  //* Output length from placeholder.
265
- calcLength = $this.prop( 'placeholder' ).length;
266
  }
267
 
268
  if ( calcLength < 100 || calcLength >= 175 ) {
@@ -276,19 +269,22 @@ window.tsf = {
276
  name = tsf.getCounterName( 'good' );
277
  }
278
 
279
- if ( tsf.additionsClass )
280
- counterClass += ' ' + tsf.additionsClass;
281
-
282
  //* Not strict by design.
283
- if ( ! tsf.counterType || 1 == tsf.counterType ) {
284
- output = calcLength.toString();
285
- } else if ( 2 == tsf.counterType ) {
286
  output = name;
287
- } else if ( 3 == tsf.counterType ) {
288
- output = calcLength.toString() + ' - ' + name;
289
  }
290
 
291
- $counter.html( output ).removeClass().addClass( counterClass );
 
 
 
 
 
 
292
  },
293
 
294
  /**
@@ -301,14 +297,13 @@ window.tsf = {
301
  * @return {undefined}
302
  */
303
  updateCharacterCountTitle: function( event ) {
304
- 'use strict';
305
 
306
  var $this = jQuery( event.target ),
307
  additions = tsf.params['titleAdditions'].length,
308
  description = tsf.params['blogDescription'].length,
309
  siteTitle = tsf.params['siteTitle'].length,
310
- titleLength = $this.val().length,
311
- placeholder = $this.prop( 'placeholder' ).length,
312
  tagline = jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).val(),
313
  seplen = 3,
314
  $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
@@ -379,7 +374,7 @@ window.tsf = {
379
  output = calcLength.toString() + ' - ' + name;
380
  }
381
 
382
- $counter.html( output ).removeClass().addClass( counterClass );
383
  },
384
 
385
  /**
@@ -393,10 +388,9 @@ window.tsf = {
393
  * @return {(String|null)} HTML to jQuery converted string
394
  */
395
  escapeStr: function( str ) {
396
- 'use strict';
397
 
398
  if ( str )
399
- return str.replace( /([\[\]\/])/g,'\\$1');
400
 
401
  return str;
402
  },
@@ -411,9 +405,7 @@ window.tsf = {
411
  * @return {undefined}
412
  */
413
  separatorSwitchTitle: function( event ) {
414
- 'use strict';
415
 
416
- // converted to var in compiler.
417
  let $sep = jQuery( ".tsf-sep-js" ),
418
  val = jQuery( event.target ).val();
419
 
@@ -425,7 +417,7 @@ window.tsf = {
425
  } else if ( 'dash' === val ) {
426
  $sep.text( " - " );
427
  } else {
428
- $sep.html( " &" + val + "; " );
429
  }
430
  },
431
 
@@ -433,15 +425,14 @@ window.tsf = {
433
  * Dynamic Description separator replacement in metabox
434
  *
435
  * @since 2.3.4
 
436
  *
437
  * @function
438
  * @param {!jQuery.Event} event
439
  * @return {undefined}
440
  */
441
  separatorSwitchDesc: function( event ) {
442
- 'use strict';
443
 
444
- // converted to var in compiler.
445
  let $sep = jQuery( "#autodescription-descsep-js" ),
446
  val = jQuery( event.target ).val();
447
 
@@ -450,7 +441,7 @@ window.tsf = {
450
  } else if ( 'dash' === val ) {
451
  $sep.text( " - " );
452
  } else {
453
- $sep.html( " &" + val + "; " );
454
  }
455
  },
456
 
@@ -463,14 +454,17 @@ window.tsf = {
463
  * @return {undefined}
464
  */
465
  statusBarHover: function() {
466
- 'use strict';
467
 
468
- // converted to var in compiler.
469
  let $wrap = jQuery( '.tsf-seo-bar-inner-wrap' ).find( 'a' );
470
 
471
- $wrap.on( 'mouseenter', tsf.statusBarHoverEnter );
472
- $wrap.on( 'mousemove', tsf.statusBarHoverMove );
473
- $wrap.on( 'mouseleave', tsf.statusBarHoverLeave );
 
 
 
 
 
474
  },
475
 
476
  /**
@@ -483,9 +477,7 @@ window.tsf = {
483
  * @return {undefined}
484
  */
485
  statusBarHoverEnter: function( event ) {
486
- 'use strict';
487
 
488
- // converted to var in compiler.
489
  let $this = jQuery( event.target ),
490
  desc = $this.data( 'desc' );
491
 
@@ -508,7 +500,6 @@ window.tsf = {
508
  * @return {undefined}
509
  */
510
  statusBarHoverMove: function( event ) {
511
- 'use strict';
512
 
513
  var $this = jQuery( event.target ),
514
  pagex = event.pageX,
@@ -540,28 +531,25 @@ window.tsf = {
540
  * @return {undefined}
541
  */
542
  statusBarHoverLeave: function( event ) {
543
- 'use strict';
544
-
545
  jQuery( event.target ).find( 'div.tsf-explanation-desc' ).remove();
546
  },
547
 
548
  /**
549
- * Remove Status bar desc if clicked outside (touch support)
550
  *
551
- * @since 2.1.9
552
  *
553
  * @function
554
- * @return {undefined}
555
  */
556
- removeDesc: function() {
557
- 'use strict';
558
 
559
- // converted to var in compiler.
560
- let $target = jQuery( document.body.target ),
561
- $desc = jQuery( '.tsf-seo-bar-inner-wrap a' );
562
 
563
- if ( ! $target.closest( $desc ).length )
564
- $desc.find( 'div.tsf-explanation-desc' ).remove();
 
565
  },
566
 
567
  /**
@@ -577,26 +565,22 @@ window.tsf = {
577
  * @return {(undefined|null)}
578
  */
579
  tabToggle: function( event ) {
580
- 'use strict';
581
 
582
  let $this = jQuery( event.target );
583
 
584
  if ( ! $this.is( ':checked' ) )
585
  return;
586
 
587
- // converted to var in compiler.
588
  let target = $this.prop( 'id' ),
589
  name = $this.prop( 'name' );
590
 
591
  if ( typeof name !== 'undefined' ) {
592
- // converted to var in compiler.
593
  let activeClass = 'tsf-active-tab-content',
594
  $newContent = jQuery( '#' + target + '-content' ),
595
  $previousContent = jQuery( '.' + activeClass );
596
 
597
  //* Only parse if old content isn't the new.
598
  if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
599
- // converted to var in compiler.
600
  let $allContent = jQuery( '.' + name + '-content' );
601
 
602
  $allContent.fadeOut( 150, function() {
@@ -622,27 +606,23 @@ window.tsf = {
622
  * @param {!jQuery.Event} event
623
  * @return {(undefined|null)}
624
  */
625
- flexTabToggle : function( event ){
626
- 'use strict';
627
 
628
  let $this = jQuery( event.target );
629
 
630
  if ( ! $this.is( ':checked' ) )
631
  return;
632
 
633
- // converted to var in compiler.
634
  let target = $this.prop( 'id' ),
635
  name = $this.prop( 'name' );
636
 
637
  if ( typeof name !== 'undefined' ) {
638
- // converted to var in compiler.
639
  let activeClass = 'tsf-flex-tab-content-active',
640
  $newContent = jQuery( '#' + target + '-content' ),
641
  $previousContent = jQuery( '.' + activeClass );
642
 
643
  //* Only parse if old content isn't the new.
644
  if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
645
- // converted to var in compiler.
646
  let $allContent = jQuery( '.' + name + '-content' );
647
 
648
  $allContent.fadeOut( 150, function() {
@@ -671,19 +651,16 @@ window.tsf = {
671
 
672
  if ( tsf.hasInput ) {
673
  if ( tsf.states['isSettingsPage'] ) {
674
- // converted to var in compiler.
675
  let $buttons = jQuery( '.tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked' );
676
 
677
  // Select all second or later tabs that have attribute checked.
678
  if ( $buttons.length ) {
679
  $buttons.each( function( i ) {
680
- // converted to var in compiler.
681
  let $this = jQuery( this ),
682
  target = $this.prop( 'id' ),
683
  name = $this.prop( 'name' );
684
 
685
  if ( typeof name !== 'undefined' ) {
686
- // converted to var in compiler.
687
  let activeClass = 'tsf-active-tab-content',
688
  $newContent = jQuery( '#' + target + '-content' );
689
 
@@ -716,9 +693,7 @@ window.tsf = {
716
  * @return {undefined}
717
  */
718
  taglineToggleTitle: function( event ) {
719
- 'use strict';
720
 
721
- // converted to var in compiler.
722
  let $this = jQuery( event.target ),
723
  $tag = jQuery( '.tsf-custom-blogname-js' );
724
 
@@ -743,9 +718,7 @@ window.tsf = {
743
  * @return {undefined}
744
  */
745
  taglineToggleDesc: function( event ) {
746
- 'use strict';
747
 
748
- // converted to var in compiler.
749
  let $this = jQuery( event.target ),
750
  $tagDesc = jQuery( '#tsf-on-blogname-js' );
751
 
@@ -766,9 +739,7 @@ window.tsf = {
766
  * @return {undefined}
767
  */
768
  titleLocationToggle: function( event ) {
769
- 'use strict';
770
 
771
- // converted to var in compiler.
772
  let val = jQuery( event.target ).val(),
773
  $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
774
  $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
@@ -792,9 +763,7 @@ window.tsf = {
792
  * @return {undefined}
793
  */
794
  titlePrefixToggle: function( event ) {
795
- 'use strict';
796
 
797
- // converted to var in compiler.
798
  let $this = jQuery( event.target ),
799
  $prefix = jQuery( '.tsf-title-prefix-example' );
800
 
@@ -815,9 +784,7 @@ window.tsf = {
815
  * @return {undefined}
816
  */
817
  additionsToggleDesc: function( event ) {
818
- 'use strict';
819
 
820
- // converted to var in compiler.
821
  let $this = jQuery( event.target ),
822
  $tagDesc = jQuery( '#tsf-description-additions-js' );
823
 
@@ -838,12 +805,10 @@ window.tsf = {
838
  * @return {undefined}
839
  */
840
  taglineToggleOnload: function() {
841
- 'use strict';
842
 
843
  if ( ! tsf.hasInput )
844
  return;
845
 
846
- // converted to var in compiler.
847
  let $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
848
  $title = jQuery( '.tsf-custom-blogname-js' ),
849
  $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
@@ -889,12 +854,11 @@ window.tsf = {
889
  * @return {undefined}
890
  */
891
  titleProp: function( event ) {
892
- 'use strict';
893
 
894
- var val = jQuery( event.target ).val(),
895
  $title = jQuery( '.tsf-custom-title-js' );
896
 
897
- if ( val.length === 0 ) {
898
  $title.text( tsf.params['siteTitle'] );
899
  } else {
900
  $title.text( val );
@@ -911,9 +875,8 @@ window.tsf = {
911
  * @return {undefined}
912
  */
913
  taglineProp: function( event ) {
914
- 'use strict';
915
 
916
- var val = jQuery( event.target ).val(),
917
  $floatTag = jQuery( '.tsf-custom-tagline-js' ),
918
  $target = jQuery( '#autodescription-site-settings\\[homepage_title\\]' ),
919
  leftRight = jQuery( '#tsf-home-title-location input:checked' ).val(),
@@ -952,9 +915,7 @@ window.tsf = {
952
  * @return {undefined}
953
  */
954
  taglinePropTrigger: function() {
955
- 'use strict';
956
 
957
- // converted to var in compiler.
958
  let settingsChangedCache = tsf.settingsChanged;
959
 
960
  if ( tsf.states['isSettingsPage'] ) {
@@ -980,7 +941,6 @@ window.tsf = {
980
  * @return {undefined}
981
  */
982
  taglinePropTriggerResize: function() {
983
- 'use strict';
984
 
985
  let resizeTimeout = 0,
986
  prevWidth = 0;
@@ -1017,9 +977,7 @@ window.tsf = {
1017
  * @return {undefined}
1018
  */
1019
  titleToggle: function() {
1020
- 'use strict';
1021
 
1022
- // converted to var in compiler.
1023
  let $this = jQuery( event.target ),
1024
  $tagDesc = jQuery( '.tsf-title-additions-js' );
1025
 
@@ -1034,31 +992,40 @@ window.tsf = {
1034
  * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
1035
  *
1036
  * @since 2.0.0
 
1037
  *
1038
  * @function
1039
  * @return {undefined}
1040
  */
1041
  attachUnsavedChangesListener: function() {
1042
- 'use strict';
1043
 
1044
  if ( ! tsf.hasInput )
1045
  return;
1046
 
1047
- jQuery( '.tsf-metaboxes :input, #tsf-inpost-box .inside :input' ).not( '.tsf-tab :input, .tsf-flex-nav-tab :input' ).change( function() {
1048
- tsf.registerChange();
1049
- } );
 
 
1050
 
1051
- jQuery( '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea' ).not(
1052
- '.tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input' ).on( 'input', function() {
1053
- tsf.registerChange();
1054
- } );
 
 
 
 
 
1055
 
 
1056
  window.onbeforeunload = function() {
1057
  if ( tsf.settingsChanged ) {
1058
  return tsf.i18n['saveAlert'];
1059
  }
1060
  };
1061
 
 
1062
  jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
1063
  window.onbeforeunload = null;
1064
  } );
@@ -1073,8 +1040,6 @@ window.tsf = {
1073
  * @return {undefined}
1074
  */
1075
  registerChange: function() {
1076
- 'use strict';
1077
-
1078
  tsf.settingsChanged = true;
1079
  },
1080
 
@@ -1087,8 +1052,6 @@ window.tsf = {
1087
  * @return {(Boolean|null)} True if reset should occur, false if not.
1088
  */
1089
  confirmedReset: function() {
1090
- 'use strict';
1091
-
1092
  return confirm( tsf.i18n['confirmReset'] );
1093
  },
1094
 
@@ -1102,9 +1065,7 @@ window.tsf = {
1102
  * @return {(!jQuery|undefined)}
1103
  */
1104
  dynamicPlaceholder: function( event ) {
1105
- 'use strict';
1106
 
1107
- // converted to var in compiler.
1108
  let hasAdditions = tsf.params['titleAdditions'].length,
1109
  $placeholder = jQuery( '#tsf-title-placeholder' );
1110
 
@@ -1115,7 +1076,6 @@ window.tsf = {
1115
  return $placeholder.empty();
1116
  }
1117
 
1118
- // converted to var in compiler.
1119
  let after = false,
1120
  check = jQuery( '#tsf-home-title-location input:checked' ).val(),
1121
  rtl = tsf.states['isRTL'],
@@ -1165,7 +1125,6 @@ window.tsf = {
1165
 
1166
  if ( typeof $tagbox !== "undefined" && $tagbox.length > 0 && ! $tagbox.is( ':checked' ) ) {
1167
  //* We're on SEO Settings Page now, and tagline has been disabled.
1168
- // converted to var in compiler.
1169
  let $this = jQuery( event.target );
1170
 
1171
  $this.css( 'text-indent', "initial" );
@@ -1175,7 +1134,6 @@ window.tsf = {
1175
  inputVal = $this.val(),
1176
  $offsetTest = jQuery( "#tsf-title-offset" );
1177
 
1178
- // converted to var in compiler.
1179
  let offsetWidth = 0,
1180
  outerWidth = $this.outerWidth(),
1181
  heightPad = ( $this.outerHeight( true ) - $this.height() ) / 2,
@@ -1254,7 +1212,6 @@ window.tsf = {
1254
  if ( after ) {
1255
  $placeholder.css( pos, horPad + leftOffset + $offsetTest.width() + "px" );
1256
  } else {
1257
- // converted to var in compiler.
1258
  let indent = horPad + $placeholder.width();
1259
 
1260
  if ( indent < 0 )
@@ -1277,16 +1234,13 @@ window.tsf = {
1277
  * @return {undefined}
1278
  */
1279
  selectTitleInput: function() {
1280
- 'use strict';
1281
 
1282
- // converted to var in compiler.
1283
  let $input = tsf.docTitles();
1284
 
1285
  $input.focus();
1286
 
1287
  if ( $input.setSelectionRange ) {
1288
  // Go to end times 2 if setSelectionRange exists.
1289
- // converted to var in compiler.
1290
  let length = $input.val().length * 2;
1291
  $input.setSelectionRange( length, length );
1292
  } else {
@@ -1304,12 +1258,10 @@ window.tsf = {
1304
  * @return {undefined}
1305
  */
1306
  triggerDescriptionOnLoad: function() {
1307
- 'use strict';
1308
 
1309
  if ( ! tsf.hasInput )
1310
  return;
1311
 
1312
- // converted to var in compiler.
1313
  let $input = tsf.docDescriptions();
1314
 
1315
  $input.trigger( 'input', tsf.updateCharacterCountDescription );
@@ -1324,12 +1276,10 @@ window.tsf = {
1324
  * @return {undefined}
1325
  */
1326
  triggerTitleOnLoad: function() {
1327
- 'use strict';
1328
 
1329
  if ( ! tsf.hasInput )
1330
  return;
1331
 
1332
- // converted to var in compiler.
1333
  let $input = tsf.docTitles();
1334
 
1335
  $input.trigger( 'input', tsf.updateCharacterCountTitle );
@@ -1344,8 +1294,6 @@ window.tsf = {
1344
  * @return {undefined}
1345
  */
1346
  onLoadUnregisterChange: function() {
1347
- 'use strict';
1348
-
1349
  //* Prevent trigger of settings change
1350
  tsf.settingsChanged = false;
1351
  },
@@ -1354,19 +1302,15 @@ window.tsf = {
1354
  * Dismissible notices. Uses class .tsf-notice.
1355
  *
1356
  * @since 2.6.0
 
1357
  *
1358
  * @function
1359
  * @param {!jQuery.Event} event
1360
  * @return {undefined}
1361
  */
1362
  dismissNotice: function( event ) {
1363
- 'use strict';
1364
-
1365
- // converted to var in compiler.
1366
- let $this = jQuery( event.target );
1367
-
1368
- $this.parents( '.tsf-notice' ).slideUp( 200, function() {
1369
- $this.remove();
1370
  } );
1371
  },
1372
 
@@ -1380,8 +1324,6 @@ window.tsf = {
1380
  * @return {undefined}
1381
  */
1382
  setAjaxLoader: function( target ) {
1383
- 'use strict';
1384
-
1385
  jQuery( target ).toggleClass( 'tsf-loading' );
1386
  },
1387
 
@@ -1396,9 +1338,7 @@ window.tsf = {
1396
  * @return {undefined}
1397
  */
1398
  unsetAjaxLoader: function( target, success ) {
1399
- 'use strict';
1400
 
1401
- // converted to var in compiler.
1402
  let newclass = 'tsf-success',
1403
  fade = 2500;
1404
 
@@ -1421,8 +1361,6 @@ window.tsf = {
1421
  * @return {undefined}
1422
  */
1423
  resetAjaxLoader: function( target ) {
1424
- 'use strict';
1425
-
1426
  jQuery( target ).stop().empty().prop( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeProp( 'style' );
1427
  },
1428
 
@@ -1436,7 +1374,6 @@ window.tsf = {
1436
  * @return {undefined}
1437
  */
1438
  counterUpdate: function( event ) {
1439
- 'use strict';
1440
 
1441
  // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1442
  tsf.counterType = tsf.counterType + 1;
@@ -1468,7 +1405,11 @@ window.tsf = {
1468
  async: true,
1469
  success: function( response ) {
1470
 
1471
- // TODO convert to json header and/or test for availability of response.type before parsing?
 
 
 
 
1472
  response = jQuery.parseJSON( response );
1473
 
1474
  //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
@@ -1493,8 +1434,6 @@ window.tsf = {
1493
  * @return {undefined}
1494
  */
1495
  counterUpdatedResponse: function( target, success ) {
1496
- 'use strict';
1497
-
1498
  switch ( success ) {
1499
  case 0:
1500
  tsf.unsetAjaxLoader( target, false );
@@ -1518,12 +1457,10 @@ window.tsf = {
1518
  * @return {undefined}
1519
  */
1520
  additionsClassInit: function() {
1521
- 'use strict';
1522
 
1523
  if ( ! tsf.hasInput )
1524
  return;
1525
 
1526
- // converted to var in compiler.
1527
  let counterType = tsf.counterType,
1528
  settingsChangedCache = tsf.settingsChanged;
1529
 
@@ -1556,8 +1493,6 @@ window.tsf = {
1556
  * @return {undefined}
1557
  */
1558
  updateCounters: function() {
1559
- 'use strict';
1560
-
1561
  tsf.triggerTitleOnLoad();
1562
  tsf.triggerDescriptionOnLoad();
1563
  },
@@ -1572,8 +1507,6 @@ window.tsf = {
1572
  * @return {String} name Human readable counter name.
1573
  */
1574
  getCounterName: function( type ) {
1575
- 'use strict';
1576
-
1577
  return tsf.i18n[ type ];
1578
  },
1579
 
@@ -1588,9 +1521,7 @@ window.tsf = {
1588
  * @return {String} sep The converted separator.
1589
  */
1590
  getSep: function( type ) {
1591
- 'use strict';
1592
 
1593
- // converted to var in compiler.
1594
  let sep = '',
1595
  retVal = '';
1596
 
@@ -1649,7 +1580,6 @@ window.tsf = {
1649
  * @return {(undefined|null)}
1650
  */
1651
  openImageEditor: function( event ) {
1652
- 'use strict';
1653
 
1654
  if ( jQuery( event.target ).prop( 'disabled' ) || 'undefined' === typeof wp.media ) {
1655
  //* TODO error handling?
@@ -1701,7 +1631,6 @@ window.tsf = {
1701
  frame.on( 'select', selectFunc );
1702
 
1703
  let croppedFunc = (function( croppedImage ) {
1704
- // converted to var in compiler.
1705
  let url = croppedImage.url,
1706
  attachmentId = croppedImage.id,
1707
  w = croppedImage.width,
@@ -1715,7 +1644,6 @@ window.tsf = {
1715
  frame.on( 'cropped', croppedFunc );
1716
 
1717
  let skippedcropFunc = (function( selection ) {
1718
- // converted to var in compiler.
1719
  let url = selection.get( 'url' ),
1720
  attachmentId = selection.get( 'id' ),
1721
  w = selection.get( 'width' ),
@@ -1756,7 +1684,6 @@ window.tsf = {
1756
  * @return {(undefined|null)}
1757
  */
1758
  appendRemoveButton: function( target, inputID, animate ) {
1759
- 'use strict';
1760
 
1761
  if ( target && inputID ) {
1762
  if ( ! jQuery( '#' + inputID + '-remove' ).length ) {
@@ -1790,7 +1717,6 @@ window.tsf = {
1790
  * @return {(undefined|null)}
1791
  */
1792
  removeEditorImage: function( event ) {
1793
- 'use strict';
1794
 
1795
  var $target = jQuery( event.target ),
1796
  inputID = $target.data( 'inputid' );
@@ -1826,7 +1752,6 @@ window.tsf = {
1826
  * @return {(undefined|null)}
1827
  */
1828
  extendCropper: function() {
1829
- 'use strict';
1830
 
1831
  if ( 'undefined' !== typeof tsf.cropper.control )
1832
  return;
@@ -1842,7 +1767,6 @@ window.tsf = {
1842
  * @augments Backbone.Model
1843
  */
1844
  var TSFCropper;
1845
- // converted to var in compiler.
1846
  let Controller = wp.media.controller;
1847
 
1848
  TSFCropper = Controller.Cropper.extend( {
@@ -1896,8 +1820,8 @@ window.tsf = {
1896
  TSFCropper.prototype.control = {};
1897
  TSFCropper.control = {
1898
  'params' : {
1899
- 'flex_width' : 1500,
1900
- 'flex_height' : 1500,
1901
  'width' : 1200,
1902
  'height' : 630,
1903
  },
@@ -1913,15 +1837,15 @@ window.tsf = {
1913
  * control-specific data, to be fed to the imgAreaSelect plugin in
1914
  * wp.media.view.Cropper.
1915
  *
 
 
1916
  * @function
1917
  * @param {wp.media.model.Attachment} attachment
1918
  * @param {wp.media.controller.Cropper} controller
1919
  * @return {Object} imgSelectOptions
1920
  */
1921
  calculateImageSelectOptions: function( attachment, controller ) {
1922
- 'use strict';
1923
 
1924
- // converted to var in compiler.
1925
  let control = tsf.cropper.control;
1926
 
1927
  var flexWidth = !! parseInt( control.params.flex_width, 10 ),
@@ -1929,7 +1853,6 @@ window.tsf = {
1929
  xInit = parseInt( control.params.width, 10 ),
1930
  yInit = parseInt( control.params.height, 10 );
1931
 
1932
- // converted to var in compiler.
1933
  let realWidth = attachment.get( 'width' ),
1934
  realHeight = attachment.get( 'height' ),
1935
  ratio = xInit / yInit,
@@ -1974,6 +1897,7 @@ window.tsf = {
1974
 
1975
  // @TODO Convert set img min-width/height to output ratio.
1976
  // i.e. 200x2000 will become x = 1500/2000*200 = 150px, which is too small.
 
1977
 
1978
  if ( true === flexHeight ) {
1979
  imgSelectOptions.minHeight = 200;
@@ -1992,6 +1916,8 @@ window.tsf = {
1992
  * Return whether the image must be cropped, based on required dimensions.
1993
  * Disregards flexWidth/Height.
1994
  *
 
 
1995
  * @function
1996
  * @param {Number} dstW
1997
  * @param {Number} dstH
@@ -2000,7 +1926,6 @@ window.tsf = {
2000
  * @return {Boolean}
2001
  */
2002
  mustBeCropped: function( dstW, dstH, imgW, imgH ) {
2003
- 'use strict';
2004
 
2005
  if ( imgW <= dstW && imgH <= dstH )
2006
  return false;
@@ -2017,8 +1942,6 @@ window.tsf = {
2017
  * @return {(undefined|null)}
2018
  */
2019
  resetImageEditorActions: function() {
2020
- 'use strict';
2021
-
2022
  jQuery( '.tsf-remove-social-image' ).off( 'click', tsf.removeEditorImage );
2023
  jQuery( '.tsf-remove-social-image' ).on( 'click', tsf.removeEditorImage );
2024
  },
@@ -2032,8 +1955,6 @@ window.tsf = {
2032
  * @return {(undefined|null)}
2033
  */
2034
  setupImageEditorActions: function() {
2035
- 'use strict';
2036
-
2037
  jQuery( '.tsf-set-social-image' ).off( 'click', tsf.openImageEditor );
2038
  jQuery( '.tsf-remove-social-image' ).off( 'click', tsf.removeEditorImage );
2039
  jQuery( '.tsf-set-social-image' ).on( 'click', tsf.openImageEditor );
@@ -2049,9 +1970,7 @@ window.tsf = {
2049
  * @return {(undefined|null)}
2050
  */
2051
  checkImageEditorInput: function() {
2052
- 'use strict';
2053
 
2054
- // converted to var in compiler.
2055
  let $buttons = jQuery( '.tsf-set-social-image' );
2056
 
2057
  if ( $buttons.length ) {
@@ -2083,14 +2002,11 @@ window.tsf = {
2083
  * @return {(undefined|null)}
2084
  */
2085
  setColorOnload: function() {
2086
- 'use strict';
2087
 
2088
- // converted to var in compiler.
2089
  let $selectors = jQuery( '.tsf-color-picker' );
2090
 
2091
  if ( $selectors.length ) {
2092
  jQuery.each( $selectors, function( index, value ) {
2093
- // converted to var in compiler.
2094
  let $input = jQuery( value ),
2095
  currentColor = '',
2096
  defaultColor = $input.data( 'tsf-default-color' );
@@ -2129,7 +2045,6 @@ window.tsf = {
2129
  * @return {(undefined|null)}
2130
  */
2131
  setupVars: function() {
2132
- 'use strict';
2133
 
2134
  //The current title separator.
2135
  tsf.titleSeparator = tsf.params['titleSeparator'];
@@ -2156,7 +2071,6 @@ window.tsf = {
2156
  * @return {(undefined|null)}
2157
  */
2158
  _initTitlepropListener: function() {
2159
- 'use strict';
2160
 
2161
  if ( tsf.hasInput ) {
2162
  let jQ = jQuery;
@@ -2206,7 +2120,6 @@ window.tsf = {
2206
  * @return {(undefined|null)}
2207
  */
2208
  _doFlexResizeListener: function() {
2209
- 'use strict';
2210
 
2211
  if ( ! jQuery( '.tsf-flex' ).length )
2212
  return;
@@ -2299,8 +2212,6 @@ window.tsf = {
2299
  * @return {(undefined|null)}
2300
  */
2301
  _setResizeListeners: function() {
2302
- 'use strict';
2303
-
2304
  jQuery( window ).on( 'resize orientationchange', tsf._triggerResize );
2305
  jQuery( '#collapse-menu' ).click( tsf._triggerResize );
2306
  jQuery( '.columns-prefs :input[type=radio]' ).change( tsf._triggerResize );
@@ -2316,8 +2227,6 @@ window.tsf = {
2316
  * @return {(undefined|null)}
2317
  */
2318
  _triggerResize: function() {
2319
- 'use strict';
2320
-
2321
  jQuery( window ).trigger( 'tsf-flex-resize' );
2322
  },
2323
 
@@ -2332,8 +2241,6 @@ window.tsf = {
2332
  * @function
2333
  */
2334
  _triggerReady: function() {
2335
- 'use strict';
2336
-
2337
  jQuery( document.body ).trigger( 'tsf-ready' );
2338
  },
2339
 
@@ -2356,7 +2263,6 @@ window.tsf = {
2356
  * @return {undefined}
2357
  */
2358
  ready: function( jQ ) {
2359
- 'use strict';
2360
 
2361
  // Set up object parameters.
2362
  tsf.setupVars();
@@ -2405,7 +2311,7 @@ window.tsf = {
2405
  jQ( document.body ).ready( tsf._doFlexResizeListener );
2406
 
2407
  // Initialize status bar removal hover for touch screens.
2408
- jQ( document.body ).on( 'click touchstart MSPointerDown', tsf.removeDesc );
2409
 
2410
  // Bind character counters.
2411
  tsf.docDescriptions().on( 'input', tsf.updateCharacterCountDescription );
31
  // ==/ClosureCompiler==
32
  // http://closure-compiler.appspot.com/home
33
 
34
+ 'use strict';
35
+
36
  /**
37
  * Holds The SEO Framework values in an object to avoid polluting global namespace.
38
  *
185
  * @return {!jQuery} The jQuery doctitle ID's
186
  */
187
  docTitles: function() {
 
 
188
  /** Concept:
189
  if ( this.docTitles.cache )
190
  return this.docTitles.cache;
191
 
 
192
  let $doctitles = this.docTitles.cache = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
193
  */
194
 
 
195
  let $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
196
 
197
  return $doctitles;
207
  * @return {!jQuery} The jQuery description ID's
208
  */
209
  docDescriptions: function() {
 
 
210
  /** Concept:
211
  if ( this.docDescriptions.cache )
212
  return this.docDescriptions.cache;
213
 
 
214
  let $descriptions = this.docDescriptions.cache = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
215
  */
216
 
 
217
  let $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
218
 
219
  return $descriptions;
229
  * @return {(Boolean|null)} True on OK, false on cancel.
230
  */
231
  confirm: function( text ) {
 
 
232
  return confirm( text );
233
  },
234
 
236
  * Description length counter.
237
  *
238
  * @since 2.2.4
239
+ * @since 2.9.3 Refactored to plain JS for discovering performance bugs.
240
  *
241
  * @function
242
  * @param {!jQuery.Event} event
243
  * @return {undefined}
244
  */
245
  updateCharacterCountDescription: function( event ) {
 
246
 
247
+ let calcLength = event.target.value && event.target.value.length || 0,
248
+ item = document.getElementById( event.target.id + '_chars' ),
249
+ counterType = tsf.counterType,
250
+ additionsClass = tsf.additionsClass,
251
  counterClass = '',
252
  name = '',
253
  output = '';
255
  // Emptied input, get Description placeholder.
256
  if ( 0 === calcLength ) {
257
  //* Output length from placeholder.
258
+ calcLength = event.target.placeholder && event.target.placeholder.length;
259
  }
260
 
261
  if ( calcLength < 100 || calcLength >= 175 ) {
269
  name = tsf.getCounterName( 'good' );
270
  }
271
 
 
 
 
272
  //* Not strict by design.
273
+ if ( counterType < 2 ) {
274
+ output = calcLength;
275
+ } else if ( 2 == counterType ) {
276
  output = name;
277
+ } else if ( 3 == counterType ) {
278
+ output = calcLength + ' - ' + name;
279
  }
280
 
281
+ item.innerHTML = output;
282
+
283
+ if ( additionsClass )
284
+ counterClass += ' ' + additionsClass;
285
+
286
+ if ( item.className !== counterClass )
287
+ item.className = counterClass;
288
  },
289
 
290
  /**
297
  * @return {undefined}
298
  */
299
  updateCharacterCountTitle: function( event ) {
 
300
 
301
  var $this = jQuery( event.target ),
302
  additions = tsf.params['titleAdditions'].length,
303
  description = tsf.params['blogDescription'].length,
304
  siteTitle = tsf.params['siteTitle'].length,
305
+ titleLength = event.target.value && event.target.value.length || 0,
306
+ placeholder = jQuery( event.target ).prop( 'placeholder' ).length,
307
  tagline = jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).val(),
308
  seplen = 3,
309
  $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
374
  output = calcLength.toString() + ' - ' + name;
375
  }
376
 
377
+ $counter.text( output ).removeClass().addClass( counterClass );
378
  },
379
 
380
  /**
388
  * @return {(String|null)} HTML to jQuery converted string
389
  */
390
  escapeStr: function( str ) {
 
391
 
392
  if ( str )
393
+ return str.replace( /([\[\]\/])/g, '\\$1' );
394
 
395
  return str;
396
  },
405
  * @return {undefined}
406
  */
407
  separatorSwitchTitle: function( event ) {
 
408
 
 
409
  let $sep = jQuery( ".tsf-sep-js" ),
410
  val = jQuery( event.target ).val();
411
 
417
  } else if ( 'dash' === val ) {
418
  $sep.text( " - " );
419
  } else {
420
+ $sep.html( " &" + val + "; " ).text();
421
  }
422
  },
423
 
425
  * Dynamic Description separator replacement in metabox
426
  *
427
  * @since 2.3.4
428
+ * @since 2.9.3 Removed sanitation on hardcoded input.
429
  *
430
  * @function
431
  * @param {!jQuery.Event} event
432
  * @return {undefined}
433
  */
434
  separatorSwitchDesc: function( event ) {
 
435
 
 
436
  let $sep = jQuery( "#autodescription-descsep-js" ),
437
  val = jQuery( event.target ).val();
438
 
441
  } else if ( 'dash' === val ) {
442
  $sep.text( " - " );
443
  } else {
444
+ $sep.html( " &" + val + "; " ).text();
445
  }
446
  },
447
 
454
  * @return {undefined}
455
  */
456
  statusBarHover: function() {
 
457
 
 
458
  let $wrap = jQuery( '.tsf-seo-bar-inner-wrap' ).find( 'a' );
459
 
460
+ $wrap.off( 'mouseenter mousemove mouseleave mouseout' );
461
+
462
+ $wrap.on( {
463
+ 'mouseenter' : tsf.statusBarHoverEnter,
464
+ 'mousemove' : tsf.statusBarHoverMove,
465
+ 'mouseleave' : tsf.statusBarHoverLeave,
466
+ 'mouseout' : tsf.statusBarHoverLeave,
467
+ } );
468
  },
469
 
470
  /**
477
  * @return {undefined}
478
  */
479
  statusBarHoverEnter: function( event ) {
 
480
 
 
481
  let $this = jQuery( event.target ),
482
  desc = $this.data( 'desc' );
483
 
500
  * @return {undefined}
501
  */
502
  statusBarHoverMove: function( event ) {
 
503
 
504
  var $this = jQuery( event.target ),
505
  pagex = event.pageX,
531
  * @return {undefined}
532
  */
533
  statusBarHoverLeave: function( event ) {
 
 
534
  jQuery( event.target ).find( 'div.tsf-explanation-desc' ).remove();
535
  },
536
 
537
  /**
538
+ * Remove Status bar desc if clicked outside (touch support).
539
  *
540
+ * @since 2.9.3
541
  *
542
  * @function
543
+ * @param {jQuery.event} event jQuery event
544
  */
545
+ touchRemoveDesc: function( event ) {
 
546
 
547
+ let $target = jQuery( event.target ),
548
+ hasBalloon = $target.closest( '.tsf-seo-bar-inner-wrap a' ).length;
 
549
 
550
+ if ( ! hasBalloon ) {
551
+ $target.closest( '.tsf-seo-bar-inner-wrap a' ).find( 'div.tsf-explanation-desc' ).remove();
552
+ }
553
  },
554
 
555
  /**
565
  * @return {(undefined|null)}
566
  */
567
  tabToggle: function( event ) {
 
568
 
569
  let $this = jQuery( event.target );
570
 
571
  if ( ! $this.is( ':checked' ) )
572
  return;
573
 
 
574
  let target = $this.prop( 'id' ),
575
  name = $this.prop( 'name' );
576
 
577
  if ( typeof name !== 'undefined' ) {
 
578
  let activeClass = 'tsf-active-tab-content',
579
  $newContent = jQuery( '#' + target + '-content' ),
580
  $previousContent = jQuery( '.' + activeClass );
581
 
582
  //* Only parse if old content isn't the new.
583
  if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
 
584
  let $allContent = jQuery( '.' + name + '-content' );
585
 
586
  $allContent.fadeOut( 150, function() {
606
  * @param {!jQuery.Event} event
607
  * @return {(undefined|null)}
608
  */
609
+ flexTabToggle : function( event ) {
 
610
 
611
  let $this = jQuery( event.target );
612
 
613
  if ( ! $this.is( ':checked' ) )
614
  return;
615
 
 
616
  let target = $this.prop( 'id' ),
617
  name = $this.prop( 'name' );
618
 
619
  if ( typeof name !== 'undefined' ) {
 
620
  let activeClass = 'tsf-flex-tab-content-active',
621
  $newContent = jQuery( '#' + target + '-content' ),
622
  $previousContent = jQuery( '.' + activeClass );
623
 
624
  //* Only parse if old content isn't the new.
625
  if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
 
626
  let $allContent = jQuery( '.' + name + '-content' );
627
 
628
  $allContent.fadeOut( 150, function() {
651
 
652
  if ( tsf.hasInput ) {
653
  if ( tsf.states['isSettingsPage'] ) {
 
654
  let $buttons = jQuery( '.tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked' );
655
 
656
  // Select all second or later tabs that have attribute checked.
657
  if ( $buttons.length ) {
658
  $buttons.each( function( i ) {
 
659
  let $this = jQuery( this ),
660
  target = $this.prop( 'id' ),
661
  name = $this.prop( 'name' );
662
 
663
  if ( typeof name !== 'undefined' ) {
 
664
  let activeClass = 'tsf-active-tab-content',
665
  $newContent = jQuery( '#' + target + '-content' );
666
 
693
  * @return {undefined}
694
  */
695
  taglineToggleTitle: function( event ) {
 
696
 
 
697
  let $this = jQuery( event.target ),
698
  $tag = jQuery( '.tsf-custom-blogname-js' );
699
 
718
  * @return {undefined}
719
  */
720
  taglineToggleDesc: function( event ) {
 
721
 
 
722
  let $this = jQuery( event.target ),
723
  $tagDesc = jQuery( '#tsf-on-blogname-js' );
724
 
739
  * @return {undefined}
740
  */
741
  titleLocationToggle: function( event ) {
 
742
 
 
743
  let val = jQuery( event.target ).val(),
744
  $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
745
  $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
763
  * @return {undefined}
764
  */
765
  titlePrefixToggle: function( event ) {
 
766
 
 
767
  let $this = jQuery( event.target ),
768
  $prefix = jQuery( '.tsf-title-prefix-example' );
769
 
784
  * @return {undefined}
785
  */
786
  additionsToggleDesc: function( event ) {
 
787
 
 
788
  let $this = jQuery( event.target ),
789
  $tagDesc = jQuery( '#tsf-description-additions-js' );
790
 
805
  * @return {undefined}
806
  */
807
  taglineToggleOnload: function() {
 
808
 
809
  if ( ! tsf.hasInput )
810
  return;
811
 
 
812
  let $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
813
  $title = jQuery( '.tsf-custom-blogname-js' ),
814
  $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
854
  * @return {undefined}
855
  */
856
  titleProp: function( event ) {
 
857
 
858
+ let val = event.target.value || '',
859
  $title = jQuery( '.tsf-custom-title-js' );
860
 
861
+ if ( 0 === val.length ) {
862
  $title.text( tsf.params['siteTitle'] );
863
  } else {
864
  $title.text( val );
875
  * @return {undefined}
876
  */
877
  taglineProp: function( event ) {
 
878
 
879
+ var val = event.target.value || '',
880
  $floatTag = jQuery( '.tsf-custom-tagline-js' ),
881
  $target = jQuery( '#autodescription-site-settings\\[homepage_title\\]' ),
882
  leftRight = jQuery( '#tsf-home-title-location input:checked' ).val(),
915
  * @return {undefined}
916
  */
917
  taglinePropTrigger: function() {
 
918
 
 
919
  let settingsChangedCache = tsf.settingsChanged;
920
 
921
  if ( tsf.states['isSettingsPage'] ) {
941
  * @return {undefined}
942
  */
943
  taglinePropTriggerResize: function() {
 
944
 
945
  let resizeTimeout = 0,
946
  prevWidth = 0;
977
  * @return {undefined}
978
  */
979
  titleToggle: function() {
 
980
 
 
981
  let $this = jQuery( event.target ),
982
  $tagDesc = jQuery( '.tsf-title-additions-js' );
983
 
992
  * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
993
  *
994
  * @since 2.0.0
995
+ * @since 2.9.3 No longer heavily invokes change listeners after change has been set.
996
  *
997
  * @function
998
  * @return {undefined}
999
  */
1000
  attachUnsavedChangesListener: function() {
 
1001
 
1002
  if ( ! tsf.hasInput )
1003
  return;
1004
 
1005
+ //= Self calling and cancelling function.
1006
+ let setUnsetChange = (function( event ) {
1007
+ tsf.settingsChanged || tsf.registerChange();
1008
+ jQuery( input ).not( except ).off( event.type, setUnsetChange );
1009
+ });
1010
 
1011
+ //= Mouse input
1012
+ let input = '.tsf-metaboxes :input, #tsf-inpost-box .inside :input',
1013
+ except = '.tsf-tab :input, .tsf-flex-nav-tab :input';
1014
+ jQuery( input ).not( except ).on( 'change', setUnsetChange );
1015
+
1016
+ //= Text input
1017
+ input = '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea';
1018
+ except = '.tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input';
1019
+ jQuery( input ).not( except ).on( 'input', setUnsetChange );
1020
 
1021
+ //= Alert caller (doesn't work well when leave alerts have been disabled)
1022
  window.onbeforeunload = function() {
1023
  if ( tsf.settingsChanged ) {
1024
  return tsf.i18n['saveAlert'];
1025
  }
1026
  };
1027
 
1028
+ //= Remove alert on saving object or delete calls.
1029
  jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
1030
  window.onbeforeunload = null;
1031
  } );
1040
  * @return {undefined}
1041
  */
1042
  registerChange: function() {
 
 
1043
  tsf.settingsChanged = true;
1044
  },
1045
 
1052
  * @return {(Boolean|null)} True if reset should occur, false if not.
1053
  */
1054
  confirmedReset: function() {
 
 
1055
  return confirm( tsf.i18n['confirmReset'] );
1056
  },
1057
 
1065
  * @return {(!jQuery|undefined)}
1066
  */
1067
  dynamicPlaceholder: function( event ) {
 
1068
 
 
1069
  let hasAdditions = tsf.params['titleAdditions'].length,
1070
  $placeholder = jQuery( '#tsf-title-placeholder' );
1071
 
1076
  return $placeholder.empty();
1077
  }
1078
 
 
1079
  let after = false,
1080
  check = jQuery( '#tsf-home-title-location input:checked' ).val(),
1081
  rtl = tsf.states['isRTL'],
1125
 
1126
  if ( typeof $tagbox !== "undefined" && $tagbox.length > 0 && ! $tagbox.is( ':checked' ) ) {
1127
  //* We're on SEO Settings Page now, and tagline has been disabled.
 
1128
  let $this = jQuery( event.target );
1129
 
1130
  $this.css( 'text-indent', "initial" );
1134
  inputVal = $this.val(),
1135
  $offsetTest = jQuery( "#tsf-title-offset" );
1136
 
 
1137
  let offsetWidth = 0,
1138
  outerWidth = $this.outerWidth(),
1139
  heightPad = ( $this.outerHeight( true ) - $this.height() ) / 2,
1212
  if ( after ) {
1213
  $placeholder.css( pos, horPad + leftOffset + $offsetTest.width() + "px" );
1214
  } else {
 
1215
  let indent = horPad + $placeholder.width();
1216
 
1217
  if ( indent < 0 )
1234
  * @return {undefined}
1235
  */
1236
  selectTitleInput: function() {
 
1237
 
 
1238
  let $input = tsf.docTitles();
1239
 
1240
  $input.focus();
1241
 
1242
  if ( $input.setSelectionRange ) {
1243
  // Go to end times 2 if setSelectionRange exists.
 
1244
  let length = $input.val().length * 2;
1245
  $input.setSelectionRange( length, length );
1246
  } else {
1258
  * @return {undefined}
1259
  */
1260
  triggerDescriptionOnLoad: function() {
 
1261
 
1262
  if ( ! tsf.hasInput )
1263
  return;
1264
 
 
1265
  let $input = tsf.docDescriptions();
1266
 
1267
  $input.trigger( 'input', tsf.updateCharacterCountDescription );
1276
  * @return {undefined}
1277
  */
1278
  triggerTitleOnLoad: function() {
 
1279
 
1280
  if ( ! tsf.hasInput )
1281
  return;
1282
 
 
1283
  let $input = tsf.docTitles();
1284
 
1285
  $input.trigger( 'input', tsf.updateCharacterCountTitle );
1294
  * @return {undefined}
1295
  */
1296
  onLoadUnregisterChange: function() {
 
 
1297
  //* Prevent trigger of settings change
1298
  tsf.settingsChanged = false;
1299
  },
1302
  * Dismissible notices. Uses class .tsf-notice.
1303
  *
1304
  * @since 2.6.0
1305
+ * @since 2.9.3 Now correctly removes the node from DOM.
1306
  *
1307
  * @function
1308
  * @param {!jQuery.Event} event
1309
  * @return {undefined}
1310
  */
1311
  dismissNotice: function( event ) {
1312
+ jQuery( event.target ).parents( '.tsf-notice' ).slideUp( 200, function() {
1313
+ this.remove();
 
 
 
 
 
1314
  } );
1315
  },
1316
 
1324
  * @return {undefined}
1325
  */
1326
  setAjaxLoader: function( target ) {
 
 
1327
  jQuery( target ).toggleClass( 'tsf-loading' );
1328
  },
1329
 
1338
  * @return {undefined}
1339
  */
1340
  unsetAjaxLoader: function( target, success ) {
 
1341
 
 
1342
  let newclass = 'tsf-success',
1343
  fade = 2500;
1344
 
1361
  * @return {undefined}
1362
  */
1363
  resetAjaxLoader: function( target ) {
 
 
1364
  jQuery( target ).stop().empty().prop( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeProp( 'style' );
1365
  },
1366
 
1374
  * @return {undefined}
1375
  */
1376
  counterUpdate: function( event ) {
 
1377
 
1378
  // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1379
  tsf.counterType = tsf.counterType + 1;
1405
  async: true,
1406
  success: function( response ) {
1407
 
1408
+ /**
1409
+ * @TODO convert to json header and/or test for availability of response.type before parsing?
1410
+ * @see convertJSONResponse() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/lib/js/tsfem.js
1411
+ * @see send_json() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/inc/classes/core.class.php
1412
+ */
1413
  response = jQuery.parseJSON( response );
1414
 
1415
  //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
1434
  * @return {undefined}
1435
  */
1436
  counterUpdatedResponse: function( target, success ) {
 
 
1437
  switch ( success ) {
1438
  case 0:
1439
  tsf.unsetAjaxLoader( target, false );
1457
  * @return {undefined}
1458
  */
1459
  additionsClassInit: function() {
 
1460
 
1461
  if ( ! tsf.hasInput )
1462
  return;
1463
 
 
1464
  let counterType = tsf.counterType,
1465
  settingsChangedCache = tsf.settingsChanged;
1466
 
1493
  * @return {undefined}
1494
  */
1495
  updateCounters: function() {
 
 
1496
  tsf.triggerTitleOnLoad();
1497
  tsf.triggerDescriptionOnLoad();
1498
  },
1507
  * @return {String} name Human readable counter name.
1508
  */
1509
  getCounterName: function( type ) {
 
 
1510
  return tsf.i18n[ type ];
1511
  },
1512
 
1521
  * @return {String} sep The converted separator.
1522
  */
1523
  getSep: function( type ) {
 
1524
 
 
1525
  let sep = '',
1526
  retVal = '';
1527
 
1580
  * @return {(undefined|null)}
1581
  */
1582
  openImageEditor: function( event ) {
 
1583
 
1584
  if ( jQuery( event.target ).prop( 'disabled' ) || 'undefined' === typeof wp.media ) {
1585
  //* TODO error handling?
1631
  frame.on( 'select', selectFunc );
1632
 
1633
  let croppedFunc = (function( croppedImage ) {
 
1634
  let url = croppedImage.url,
1635
  attachmentId = croppedImage.id,
1636
  w = croppedImage.width,
1644
  frame.on( 'cropped', croppedFunc );
1645
 
1646
  let skippedcropFunc = (function( selection ) {
 
1647
  let url = selection.get( 'url' ),
1648
  attachmentId = selection.get( 'id' ),
1649
  w = selection.get( 'width' ),
1684
  * @return {(undefined|null)}
1685
  */
1686
  appendRemoveButton: function( target, inputID, animate ) {
 
1687
 
1688
  if ( target && inputID ) {
1689
  if ( ! jQuery( '#' + inputID + '-remove' ).length ) {
1717
  * @return {(undefined|null)}
1718
  */
1719
  removeEditorImage: function( event ) {
 
1720
 
1721
  var $target = jQuery( event.target ),
1722
  inputID = $target.data( 'inputid' );
1752
  * @return {(undefined|null)}
1753
  */
1754
  extendCropper: function() {
 
1755
 
1756
  if ( 'undefined' !== typeof tsf.cropper.control )
1757
  return;
1767
  * @augments Backbone.Model
1768
  */
1769
  var TSFCropper;
 
1770
  let Controller = wp.media.controller;
1771
 
1772
  TSFCropper = Controller.Cropper.extend( {
1820
  TSFCropper.prototype.control = {};
1821
  TSFCropper.control = {
1822
  'params' : {
1823
+ 'flex_width' : 4096,
1824
+ 'flex_height' : 4096,
1825
  'width' : 1200,
1826
  'height' : 630,
1827
  },
1837
  * control-specific data, to be fed to the imgAreaSelect plugin in
1838
  * wp.media.view.Cropper.
1839
  *
1840
+ * @since 2.8.0
1841
+ *
1842
  * @function
1843
  * @param {wp.media.model.Attachment} attachment
1844
  * @param {wp.media.controller.Cropper} controller
1845
  * @return {Object} imgSelectOptions
1846
  */
1847
  calculateImageSelectOptions: function( attachment, controller ) {
 
1848
 
 
1849
  let control = tsf.cropper.control;
1850
 
1851
  var flexWidth = !! parseInt( control.params.flex_width, 10 ),
1853
  xInit = parseInt( control.params.width, 10 ),
1854
  yInit = parseInt( control.params.height, 10 );
1855
 
 
1856
  let realWidth = attachment.get( 'width' ),
1857
  realHeight = attachment.get( 'height' ),
1858
  ratio = xInit / yInit,
1897
 
1898
  // @TODO Convert set img min-width/height to output ratio.
1899
  // i.e. 200x2000 will become x = 1500/2000*200 = 150px, which is too small.
1900
+ //= Unlikely...
1901
 
1902
  if ( true === flexHeight ) {
1903
  imgSelectOptions.minHeight = 200;
1916
  * Return whether the image must be cropped, based on required dimensions.
1917
  * Disregards flexWidth/Height.
1918
  *
1919
+ * @since 2.8.0
1920
+ *
1921
  * @function
1922
  * @param {Number} dstW
1923
  * @param {Number} dstH
1926
  * @return {Boolean}
1927
  */
1928
  mustBeCropped: function( dstW, dstH, imgW, imgH ) {
 
1929
 
1930
  if ( imgW <= dstW && imgH <= dstH )
1931
  return false;
1942
  * @return {(undefined|null)}
1943
  */
1944
  resetImageEditorActions: function() {
 
 
1945
  jQuery( '.tsf-remove-social-image' ).off( 'click', tsf.removeEditorImage );
1946
  jQuery( '.tsf-remove-social-image' ).on( 'click', tsf.removeEditorImage );
1947
  },
1955
  * @return {(undefined|null)}
1956
  */
1957
  setupImageEditorActions: function() {
 
 
1958
  jQuery( '.tsf-set-social-image' ).off( 'click', tsf.openImageEditor );
1959
  jQuery( '.tsf-remove-social-image' ).off( 'click', tsf.removeEditorImage );
1960
  jQuery( '.tsf-set-social-image' ).on( 'click', tsf.openImageEditor );
1970
  * @return {(undefined|null)}
1971
  */
1972
  checkImageEditorInput: function() {
 
1973
 
 
1974
  let $buttons = jQuery( '.tsf-set-social-image' );
1975
 
1976
  if ( $buttons.length ) {
2002
  * @return {(undefined|null)}
2003
  */
2004
  setColorOnload: function() {
 
2005
 
 
2006
  let $selectors = jQuery( '.tsf-color-picker' );
2007
 
2008
  if ( $selectors.length ) {
2009
  jQuery.each( $selectors, function( index, value ) {
 
2010
  let $input = jQuery( value ),
2011
  currentColor = '',
2012
  defaultColor = $input.data( 'tsf-default-color' );
2045
  * @return {(undefined|null)}
2046
  */
2047
  setupVars: function() {
 
2048
 
2049
  //The current title separator.
2050
  tsf.titleSeparator = tsf.params['titleSeparator'];
2071
  * @return {(undefined|null)}
2072
  */
2073
  _initTitlepropListener: function() {
 
2074
 
2075
  if ( tsf.hasInput ) {
2076
  let jQ = jQuery;
2120
  * @return {(undefined|null)}
2121
  */
2122
  _doFlexResizeListener: function() {
 
2123
 
2124
  if ( ! jQuery( '.tsf-flex' ).length )
2125
  return;
2212
  * @return {(undefined|null)}
2213
  */
2214
  _setResizeListeners: function() {
 
 
2215
  jQuery( window ).on( 'resize orientationchange', tsf._triggerResize );
2216
  jQuery( '#collapse-menu' ).click( tsf._triggerResize );
2217
  jQuery( '.columns-prefs :input[type=radio]' ).change( tsf._triggerResize );
2227
  * @return {(undefined|null)}
2228
  */
2229
  _triggerResize: function() {
 
 
2230
  jQuery( window ).trigger( 'tsf-flex-resize' );
2231
  },
2232
 
2241
  * @function
2242
  */
2243
  _triggerReady: function() {
 
 
2244
  jQuery( document.body ).trigger( 'tsf-ready' );
2245
  },
2246
 
2263
  * @return {undefined}
2264
  */
2265
  ready: function( jQ ) {
 
2266
 
2267
  // Set up object parameters.
2268
  tsf.setupVars();
2311
  jQ( document.body ).ready( tsf._doFlexResizeListener );
2312
 
2313
  // Initialize status bar removal hover for touch screens.
2314
+ jQ( document.body ).on( 'click touchstart MSPointerDown', tsf.touchRemoveDesc );
2315
 
2316
  // Bind character counters.
2317
  tsf.docDescriptions().on( 'input', tsf.updateCharacterCountDescription );
lib/js/tsf.min.js CHANGED
@@ -1,37 +1,38 @@
1
- window.tsf={nonce:tsfL10n.nonce,nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,other:tsfL10n.other,g:!1,m:!1,B:"",F:"",a:0,c:!1,f:"",cropper:{},h:function(){return jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]")},G:function(){return jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]")},confirm:function(a){return confirm(a)},
2
- M:function(a){var b=jQuery(a.target),c=b.val().length;a=jQuery("#"+tsf.H(a.target.id)+"_chars");var d="";0===c&&(c=b.prop("placeholder").length);if(100>c||175<=c){b="tsf-count-bad";var e=tsf.i("bad")}else 137>c||155<c&&175>c?(b="tsf-count-okay",e=tsf.i("okay")):(b="tsf-count-good",e=tsf.i("good"));tsf.f&&(b+=" "+tsf.f);tsf.a&&1!=tsf.a?2==tsf.a?d=e:3==tsf.a&&(d=c.toString()+" - "+e):d=c.toString();a.html(d).removeClass().addClass(b)},u:function(a){var b=jQuery(a.target),c=tsf.params.titleAdditions.length,
3
- d=tsf.params.blogDescription.length,e=tsf.params.siteTitle.length,f=b.val().length,k=b.prop("placeholder").length,h=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val(),m=3;a=jQuery("#"+tsf.H(a.target.id)+"_chars");var l=0,b=tsf.f,g=tsf.a,n="";tsf.m||(m=c=0);0===f&&(0!==e?f=e:l=k);0!==f&&(0!==c&&"undefined"!==typeof h&&(c=h.length,c=0!==c?c:d),l=0===c?f:f+m+c);25>l||75<=l?(d="tsf-count-bad",f=tsf.i("bad")):42>l||55<l&&75>l?(d="tsf-count-okay",f=tsf.i("okay")):(d="tsf-count-good",
4
- f=tsf.i("good"));b&&(d+=" "+b);g&&1!=g?2==g?n=f:3==g&&(n=l.toString()+" - "+f):n=l.toString();a.html(n).removeClass().addClass(d)},H:function(a){return a?a.replace(/([\[\]\/])/g,"\\$1"):a},ja:function(a){var b=jQuery(".tsf-sep-js");a=jQuery(a.target).val();tsf.B=a;"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ")},ia:function(a){var b=jQuery("#autodescription-descsep-js");a=jQuery(a.target).val();"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ")},statusBarHover:function(){var a=
5
- jQuery(".tsf-seo-bar-inner-wrap").find("a");a.on("mouseenter",tsf.pa);a.on("mousemove",tsf.ra);a.on("mouseleave",tsf.qa)},pa:function(a){a=jQuery(a.target);var b=a.data("desc");void 0!==b&&0===a.find("div").length&&(a.append('<div class="tsf-explanation-desc">'+b+"<div></div></div>"),b=a.find("div.tsf-explanation-desc").height()+28,a.find("div.tsf-explanation-desc").css("top",a.position().top-b+"px"))},ra:function(a){var b=jQuery(a.target);a=a.pageX;var c=a-b.closest(".tsf-seo-bar-inner-wrap").offset().left-
6
- 11,d=b.find(".tsf-explanation-desc"),b=d.find("div");if(1>c)b.css("left","0px");else if(void 0!==d.offset()){var e=d.width(),d=d.offset().left+e+11;a>d?b.css("left",e+"px"):b.css("left",c+"px")}},qa:function(a){jQuery(a.target).find("div.tsf-explanation-desc").remove()},fa:function(){var a=jQuery(document.body.target),b=jQuery(".tsf-seo-bar-inner-wrap a");a.closest(b).length||b.find("div.tsf-explanation-desc").remove()},sa:function(a){a=jQuery(a.target);if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");
7
- if("undefined"!==typeof a){var c=jQuery("#"+b+"-content"),d=jQuery(".tsf-active-tab-content");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-active-tab-content")}),setTimeout(function(){c.addClass("tsf-active-tab-content").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-tab-toggled")},175))}}},ba:function(a){a=jQuery(a.target);if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var c=
8
- jQuery("#"+b+"-content"),d=jQuery(".tsf-flex-tab-content-active");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-flex-tab-content-active")}),setTimeout(function(){c.addClass("tsf-flex-tab-content-active").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-flex-tab-toggled")},175))}}},ma:function(){if(tsf.c&&tsf.states.isSettingsPage){var a=jQuery(".tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked");a.length&&
9
- a.each(function(){var a=jQuery(this),c=a.prop("id"),a=a.prop("name");if("undefined"!==typeof a){var d=jQuery("#"+c+"-content");"undefined"!==typeof d&&(jQuery("."+a+"-content").removeClass("tsf-active-tab-content"),d.addClass("tsf-active-tab-content"),setTimeout(function(){jQuery("#"+c).trigger("tsf-tab-toggled")},20))}})}},wa:function(a){a=jQuery(a.target);var b=jQuery(".tsf-custom-blogname-js");a.is(":checked")?(b.css("display","inline"),tsf.m=!0):(b.css("display","none"),tsf.m=!1);tsf.h().trigger("keyup",
10
- tsf.u)},ua:function(a){a=jQuery(a.target);var b=jQuery("#tsf-on-blogname-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},xa:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-title-additions-example-left"),c=jQuery(".tsf-title-additions-example-right");"right"===a?(b.css("display","none"),c.css("display","inline")):(b.css("display","inline"),c.css("display","none"))},ya:function(a){a=jQuery(a.target);var b=jQuery(".tsf-title-prefix-example");a.is(":checked")?b.css("display",
11
- "none"):b.css("display","inline")},S:function(a){a=jQuery(a.target);var b=jQuery("#tsf-description-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},va:function(){if(tsf.c){var a=jQuery("#tsf-title-tagline-toggle :input"),b=jQuery(".tsf-custom-blogname-js"),c=jQuery("#tsf-description-additions-toggle :input"),d=jQuery("#tsf-description-additions-js"),e=jQuery("#tsf-description-onblogname-toggle :input"),f=jQuery("#tsf-on-blogname-js"),k=jQuery("#tsf-title-additions-toggle :input"),
12
- h=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none");c.is(":checked")?d.css("display","inline"):d.css("display","none");e.is(":checked")?f.css("display","inline"):f.css("display","none");k.is(":checked")?h.css("display","none"):h.css("display","inline")}},za:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-custom-title-js");0===a.length?b.text(tsf.params.siteTitle):b.text(a)},A:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-custom-tagline-js"),
13
- c=jQuery("#autodescription-site-settings\\[homepage_title\\]"),d=jQuery("#tsf-home-title-location input:checked").val(),e=jQuery("#autodescription-site-settings\\[homepage_tagline\\]"),f=tsf.params.siteTitle,k=f,h=tsf.params.blogDescription,m=tsf.I("title");e.is(":checked")&&(0!==a.length&&(h=a),k=0!==d.length&&"left"===d?f+" "+m+" "+h:h+" "+m+" "+f);b.text(h);c.prop("placeholder",k);tsf.h().trigger("input",tsf.u)},l:function(){var a=tsf.g;tsf.states.isSettingsPage?jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input",
14
- tsf.A):jQuery("#autodescription_title").trigger("input",tsf.A);tsf.g=a},ta:function(){var a=0,b=0;jQuery(window).resize(function(){clearTimeout(a);a=setTimeout(function(){var a=jQuery(window).width();b<a?782>=b&&782<=a&&tsf.l():782<=b&&782>=a&&tsf.l();b=a},250)})},Aa:function(){var a=jQuery(event.target),b=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","none"):b.css("display","inline")},T:function(){tsf.c&&(jQuery(".tsf-metaboxes :input, #tsf-inpost-box .inside :input").not(".tsf-tab :input, .tsf-flex-nav-tab :input").change(function(){tsf.j()}),
15
- jQuery(".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea").not(".tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input").on("input",function(){tsf.j()}),window.onbeforeunload=function(){if(tsf.g)return tsf.i18n.saveAlert},jQuery('.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete').click(function(){window.onbeforeunload=null}))},j:function(){tsf.g=
16
- !0},V:function(){return confirm(tsf.i18n.confirmReset)},Z:function(a){var b=tsf.params.titleAdditions.length,c=jQuery("#tsf-title-placeholder");if(!b)return jQuery(a.target).css("text-indent","initial"),c.empty();var b=!1,d=jQuery("#tsf-home-title-location input:checked").val(),e=tsf.states.isRTL;"undefined"!==typeof d&&0!==d.length?e?"right"===d&&(b=!0):"left"===d&&(b=!0):(d=tsf.params.titleLocation,tsf.states.isHome?tsf.m&&(e?"right"===d&&(b=!0):"left"===d&&(b=!0)):e?"left"===d&&(b=!0):"right"===
17
- d&&(b=!0));d=jQuery("#tsf-title-tagline-toggle :input");if("undefined"!==typeof d&&0<d.length&&!d.is(":checked"))jQuery(a.target).css("text-indent","initial"),c.css("display","none");else{a=jQuery(a.target);var f=a.val(),k=jQuery("#tsf-title-offset"),h=a.outerWidth(),m=(a.outerHeight(!0)-a.height())/2,l=(h-a.innerWidth())/2,d=(a.outerWidth(!0)-a.width())/2;var g=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val();var n="left",p=tsf.I("title");e&&(n="right");"undefined"!==typeof g&&
18
- 0===g.length&&(g=tsf.params.blogDescription);b?(e=" "+p+" "+tsf.params.titleAdditions,"undefined"!==typeof g&&0<g.length&&(e=" "+p+" "+g),a.css("text-indent","initial")):(e=tsf.params.titleAdditions+" "+p+" ","undefined"!==typeof g&&0<g.length&&(e=g+" "+p+" "));k.text(f);k.css({fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),fontSize:a.css("fontSize")});g=k.width();g=a.width()-l-g;0>g&&(g=0);c.css({display:a.css("display"),lineHeight:a.css("lineHeight"),
19
- paddingTop:m+"px",paddingBottom:m+"px",fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),fontSize:a.css("fontSize"),letterSpacing:a.css("letterSpacing"),maxWidth:g+"px"});"undefined"===typeof f||1>f.length?(b||a.css("text-indent","initial"),c.empty()):(c.text(e),h>d&&(b?c.css(n,l+d+k.width()+"px"):(b=l+c.width(),0>b&&(b=0),c.css(n,d+"px"),a.css("text-indent",b+"px"))))}},ha:function(){var a=tsf.h();a.focus();if(a.setSelectionRange){var b=2*a.val().length;a.setSelectionRange(b,b)}else a.val(a.val()).focus()},
20
- Ba:function(){tsf.c&&tsf.G().trigger("input",tsf.M)},Ca:function(){tsf.c&&tsf.h().trigger("input",tsf.u)},ea:function(){tsf.g=!1},Y:function(a){var b=jQuery(a.target);b.parents(".tsf-notice").slideUp(200,function(){b.remove()})},ka:function(a){jQuery(a).toggleClass("tsf-loading")},L:function(a,b){var c="tsf-success",d=2500;b||(c="tsf-error",d=5E3);jQuery(a).removeClass("tsf-loading").addClass(c).fadeOut(d)},K:function(a){jQuery(a).stop().empty().prop("class","tsf-ajax").css("opacity","1").removeProp("style")},
21
- W:function(){tsf.a+=1;3<tsf.a&&(tsf.a=0);tsf.C();var a=0;tsf.K(".tsf-counter .tsf-ajax");tsf.ka(".tsf-counter .tsf-ajax");jQuery.ajax({method:"POST",url:ajaxurl,Fa:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.nonces.edit_posts,val:tsf.a},async:!0,success:function(b){b=jQuery.parseJSON(b);"success"===b.type&&(a=1);tsf.X(".tsf-counter .tsf-ajax",a)}})},X:function(a,b){switch(b){case 0:tsf.L(a,!1);break;case 1:tsf.L(a,!0);break;default:tsf.K(a)}},C:function(){if(tsf.c){var a=tsf.a,
22
- b=tsf.g;1==a?(tsf.f="tsf-counter-one",tsf.a=1):2==a?(tsf.f="tsf-counter-two",tsf.a=2):3==a?(tsf.f="tsf-counter-three",tsf.a=3):(tsf.f="tsf-counter-zero",tsf.a=0);tsf.Da();tsf.g=b}},Da:function(){tsf.Ca();tsf.Ba()},i:function(a){return tsf.i18n[a]},I:function(a){var b="";a="title"===a?tsf.B:tsf.F;"pipe"===a||"|"===a?b="|":"dash"===a||"-"===a?b="-":123>a.charCodeAt(0)&&("&"===a.charAt(0)&&";"===a.slice(-1)&&(a=a.substr(1).slice(0,-1)),b=jQuery("<div/>").html("&"+a+";").text());return b},J:function(a){if(jQuery(a.target).prop("disabled")||
23
- "undefined"===typeof wp.media)a.preventDefault(),a.stopPropagation();else{var b=jQuery(a.target),c=b.data("inputid");if(!d){a.preventDefault();a.stopPropagation();tsf.aa();var d=wp.media({button:{text:tsf.other[c].frame_button,close:!1},states:[new wp.media.controller.Library({title:tsf.other[c].frame_title,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:1200,suggestedHeight:630}),new tsf.cropper({imgSelectOptions:tsf.calculateImageSelectOptions})]});a=function(){d.setState("cropper")};
24
- d.off("select",a);d.on("select",a);a=function(a){var b=a.url;a=a.id;jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(a)};d.off("cropped",a);d.on("cropped",a);a=function(a){var b=a.get("url"),d=a.get("id");a.get("width");a.get("height");jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(d)};d.off("skippedcrop",a);d.on("skippedcrop",a);a=function(){jQuery("#"+c+"-select").text(tsf.other[c].change);jQuery("#"+c+"-url").prop("readonly",!0).css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},
25
- "swing");tsf.D(b,c,!0);tsf.j()};d.off("skippedcrop cropped",a);d.on("skippedcrop cropped",a)}d.open()}},D:function(a,b,c){a&&b&&!jQuery("#"+b+"-remove").length&&(a.after('<a href="javascript:void(0)" id="'+b+'-remove" class="tsf-remove-social-image button button-small" data-inputid="'+b+'" title="'+tsf.other[b].remove_title+'">'+tsf.other[b].remove+"</a>"),c&&jQuery("#"+b+"-remove").css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},"swing"));tsf.ga()},s:function(a){var b=jQuery(a.target).data("inputid");
26
- jQuery("#"+b+"-select").prop("disabled")||(jQuery("#"+b+"-select").addClass("disabled").prop("disabled",!0),jQuery("#"+b+"-remove").addClass("disabled").prop("disabled",!0).fadeOut(500,function(){jQuery(this).remove();jQuery("#"+b+"-select").text(tsf.other[b].select).removeClass("disabled").removeProp("disabled")}),jQuery("#"+b+"-url").val("").removeProp("readonly").css("opacity",0).animate({opacity:1},{queue:!0,duration:500},"swing"),jQuery("#"+b+"-id").val(""),tsf.j())},aa:function(){if("undefined"===
27
- typeof tsf.cropper.control){var a=wp.media.controller.Cropper.extend({doCrop:function(a){var b=a.get("cropDetails"),d=tsf.cropper.control;if(d.params.flex_width&&d.params.flex_height)if(b.width===b.height)b.width>d.params.flex_width&&(b.dst_width=b.dst_height=d.params.flex_width);else if(b.width>d.params.flex_width||b.height>d.params.flex_height)if(b.width>b.height){var e=b.width/d.params.flex_width;b.dst_width=d.params.flex_width;b.dst_height=Math.round(b.height/e)}else e=b.height/d.params.flex_height,
28
- b.dst_height=d.params.flex_height,b.dst_width=Math.round(b.width/e);"undefined"===typeof b.dst_width&&(b.dst_width=0,b.dst_height=0);return wp.ajax.post("tsf-crop-image",{nonce:tsf.nonces.upload_files,id:a.get("id"),context:"tsf-image",cropDetails:b})}});a.prototype.control={};a.control={params:{flex_width:1500,flex_height:1500,width:1200,height:630}};tsf.cropper=a}},calculateImageSelectOptions:function(a,b){var c=tsf.cropper.control,d=!!parseInt(c.params.flex_width,10),e=!!parseInt(c.params.flex_height,
29
- 10),f=parseInt(c.params.width,10),k=parseInt(c.params.height,10),h=a.get("width"),m=a.get("height"),l=f/k,g=f,n=k;b.set("control",c.params);b.set("canSkipCrop",!tsf.da(c.params.flex_width,c.params.flex_height,h,m));h/m>l?(k=m,f=k*l):(f=h,k=f/l);c=(h-f)/2;l=(m-k)/2;g={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:h,imageHeight:m,minWidth:g>f?f:g,minHeight:n>k?k:n,x1:c,y1:l,x2:f+c,y2:k+l};!1===e&&!1===d&&(g.Ea=f+":"+k);!0===e&&(g.minHeight=200,g.maxWidth=h);!0===d&&(g.minWidth=200,g.maxHeight=
30
- m);return g},da:function(a,b,c,d){return c<=a&&d<=b?!1:!0},ga:function(){jQuery(".tsf-remove-social-image").off("click",tsf.s);jQuery(".tsf-remove-social-image").on("click",tsf.s)},na:function(){jQuery(".tsf-set-social-image").off("click",tsf.J);jQuery(".tsf-remove-social-image").off("click",tsf.s);jQuery(".tsf-set-social-image").on("click",tsf.J);jQuery(".tsf-remove-social-image").on("click",tsf.s)},U:function(){var a=jQuery(".tsf-set-social-image");if(a.length){var b="",c="";jQuery.each(a,function(a,
31
- e){b=jQuery(e).data("inputid");c=jQuery("#"+b+"-id");c.length&&0<c.val()&&(jQuery("#"+b+"-url").prop("readonly",!0),tsf.D(jQuery(e),b,!1));jQuery("#"+b+"-url").val()&&jQuery("#"+b+"-select").text(tsf.other[b].change)})}},la:function(){var a=jQuery(".tsf-color-picker");a.length&&jQuery.each(a,function(a,c){var b=jQuery(c),e="",f=b.data("tsf-default-color");b.wpColorPicker({defaultColor:f,width:238,change:function(){e=b.wpColorPicker("color");""===e&&(e=f);b.val(e);tsf.j()},clear:function(){b.parent().siblings(".wp-color-result").css("backgroundColor",
32
- f);tsf.j()},palettes:!1})})},oa:function(){tsf.B=tsf.params.titleSeparator;tsf.F=tsf.params.descriptionSeparator;tsf.m=tsf.states.titleTagline;tsf.a=parseInt(tsf.states.counterType);tsf.c=tsf.states.hasInput},O:function(){if(tsf.c){var a=jQuery;a("#tsf-title-tagline-toggle :input").on("click",tsf.wa);a("#tsf-title-location input").on("click",tsf.xa);a("#title-prefixes-toggle :input").on("click",tsf.ya);a("#autodescription-site-settings\\[homepage_title\\]").on("input",tsf.za);a("#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input").on("click",
33
- tsf.l);a("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input",tsf.A);a("#homepage-tab-general").on("tsf-tab-toggled",tsf.l);a("#autodescription-homepage-settings > button").on("click",tsf.l);a("#tsf-inpost-box > button").on("click",tsf.l);a("#autodescription-site-settings\\[title_rem_additions\\]").on("click",tsf.Aa);tsf.h().on("input",tsf.Z);a("#tsf-title-placeholder").on("click",tsf.ha);a(window).resize(tsf.ta)}},N:function(){if(jQuery(".tsf-flex").length){tsf.P();var a=0,b=
34
- {},c=0,d=jQuery(".tsf-flex-nav-tab-wrapper");jQuery(window).on("tsf-flex-resize",function(){clearTimeout(a);var e=0;a=setTimeout(function(){if(d.length){var a=jQuery(".tsf-flex-nav-tab-inner"),c=d.width(),h=a.width(),m=jQuery(".tsf-flex-nav-name");b.b||(b.b={},b.b.v=0,b.b.ca=0,b.b.w=1);!b.b.w&&b.b.v<c&&(m.fadeIn(250),setTimeout(function(){h=a.width()},e));setTimeout(function(){h>c?(m.hide(),b.b.w=0):b.b.v<c&&(m.fadeIn(250),b.b.w=1)},2*e);setTimeout(function(){b.b.v=c;b.b.ca=h},3*e)}},c);e=10;c=75});
35
- jQuery(window).trigger("tsf-flex-resize")}},P:function(){jQuery(window).on("resize orientationchange",tsf.o);jQuery("#collapse-menu").click(tsf.o);jQuery(".columns-prefs :input[type=radio]").change(tsf.o);jQuery(".meta-box-sortables").on("sortupdate",tsf.o)},o:function(){jQuery(window).trigger("tsf-flex-resize")},R:function(){jQuery(document.body).trigger("tsf-ready")},ready:function(a){tsf.oa();a("div.updated, div.error, div.notice-warning").insertAfter("div.tsf-top-wrap");a(document.body).ready(tsf.O);
36
- a(document.body).ready(tsf.ma);a(document.body).ready(tsf.C);a(document.body).ready(tsf.va);a(document.body).ready(tsf.statusBarHover);a(document.body).ready(tsf.na);a(document.body).ready(tsf.U);a(document.body).ready(tsf.la);a(document.body).ready(tsf.T);a(document.body).ready(tsf.ea);a(document.body).ready(tsf.R);a(document.body).ready(tsf.N);a(document.body).on("click touchstart MSPointerDown",tsf.fa);tsf.G().on("input",tsf.M);tsf.h().on("input",tsf.u);a("#tsf-title-separator input").on("click",
37
- tsf.ja);a("#tsf-description-separator input").on("click",tsf.ia);a(".tsf-js-confirm-reset").on("click",tsf.V);a(".tsf-tabs-radio").on("change",tsf.sa);a(".tsf-flex-nav-tab-radio").on("change",tsf.ba);a("#tsf-description-onblogname-toggle :input").on("click",tsf.ua);a("#tsf-description-additions-toggle :input").on("click",tsf.S);a(".tsf-dismiss").on("click",tsf.Y);a(".tsf-counter").on("click",tsf.W)}};jQuery(tsf.ready);
 
1
+ window.tsf={nonce:tsfL10n.nonce,nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,other:tsfL10n.other,f:!1,m:!1,B:"",F:"",a:0,c:!1,g:"",cropper:{},h:function(){return jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]")},G:function(){return jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]")},confirm:function(a){return confirm(a)},
2
+ M:function(a){var b=a.target.value&&a.target.value.length||0,c=document.getElementById(a.target.id+"_chars"),d=tsf.a,e=tsf.g,f="";0===b&&(b=a.target.placeholder&&a.target.placeholder.length);if(100>b||175<=b){a="tsf-count-bad";var k=tsf.i("bad")}else 137>b||155<b&&175>b?(a="tsf-count-okay",k=tsf.i("okay")):(a="tsf-count-good",k=tsf.i("good"));2>d?f=b:2==d?f=k:3==d&&(f=b+" - "+k);c.innerHTML=f;e&&(a+=" "+e);c.className!==a&&(c.className=a)},u:function(a){jQuery(a.target);var b=tsf.params.titleAdditions.length,
3
+ c=tsf.params.blogDescription.length,d=tsf.params.siteTitle.length,e=a.target.value&&a.target.value.length||0,f=jQuery(a.target).prop("placeholder").length,k=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val(),l=3;a=jQuery("#"+tsf.aa(a.target.id)+"_chars");var h=0,m=tsf.g,g=tsf.a,n="";tsf.m||(l=b=0);0===e&&(0!==d?e=d:h=f);0!==e&&(0!==b&&"undefined"!==typeof k&&(h=k.length,b=0!==h?h:c),h=0===b?e:e+l+b);25>h||75<=h?(c="tsf-count-bad",e=tsf.i("bad")):42>h||55<h&&75>h?(c="tsf-count-okay",
4
+ e=tsf.i("okay")):(c="tsf-count-good",e=tsf.i("good"));m&&(c+=" "+m);g&&1!=g?2==g?n=e:3==g&&(n=h.toString()+" - "+e):n=h.toString();a.text(n).removeClass().addClass(c)},aa:function(a){return a?a.replace(/([\[\]\/])/g,"\\$1"):a},ja:function(a){var b=jQuery(".tsf-sep-js");a=jQuery(a.target).val();tsf.B=a;"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ").text()},ia:function(a){var b=jQuery("#autodescription-descsep-js");a=jQuery(a.target).val();"pipe"===a?b.text(" | "):"dash"===a?
5
+ b.text(" - "):b.html(" &"+a+"; ").text()},statusBarHover:function(){var a=jQuery(".tsf-seo-bar-inner-wrap").find("a");a.off("mouseenter mousemove mouseleave mouseout");a.on({mouseenter:tsf.pa,mousemove:tsf.qa,mouseleave:tsf.K,mouseout:tsf.K})},pa:function(a){a=jQuery(a.target);var b=a.data("desc");void 0!==b&&0===a.find("div").length&&(a.append('<div class="tsf-explanation-desc">'+b+"<div></div></div>"),b=a.find("div.tsf-explanation-desc").height()+28,a.find("div.tsf-explanation-desc").css("top",
6
+ a.position().top-b+"px"))},qa:function(a){var b=jQuery(a.target);a=a.pageX;var c=a-b.closest(".tsf-seo-bar-inner-wrap").offset().left-11,d=b.find(".tsf-explanation-desc");b=d.find("div");if(1>c)b.css("left","0px");else if(void 0!==d.offset()){var e=d.width();d=d.offset().left+e+11;a>d?b.css("left",e+"px"):b.css("left",c+"px")}},K:function(a){jQuery(a.target).find("div.tsf-explanation-desc").remove()},Aa:function(a){a=jQuery(a.target);a.closest(".tsf-seo-bar-inner-wrap a").length||a.closest(".tsf-seo-bar-inner-wrap a").find("div.tsf-explanation-desc").remove()},
7
+ ra:function(a){a=jQuery(a.target);if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var c=jQuery("#"+b+"-content"),d=jQuery(".tsf-active-tab-content");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-active-tab-content")}),setTimeout(function(){c.addClass("tsf-active-tab-content").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-tab-toggled")},175))}}},ca:function(a){a=jQuery(a.target);
8
+ if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var c=jQuery("#"+b+"-content"),d=jQuery(".tsf-flex-tab-content-active");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-flex-tab-content-active")}),setTimeout(function(){c.addClass("tsf-flex-tab-content-active").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-flex-tab-toggled")},175))}}},ma:function(){if(tsf.c&&tsf.states.isSettingsPage){var a=
9
+ jQuery(".tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked");a.length&&a.each(function(){var a=jQuery(this),c=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var d=jQuery("#"+c+"-content");"undefined"!==typeof d&&(jQuery("."+a+"-content").removeClass("tsf-active-tab-content"),d.addClass("tsf-active-tab-content"),setTimeout(function(){jQuery("#"+c).trigger("tsf-tab-toggled")},20))}})}},va:function(a){a=jQuery(a.target);var b=jQuery(".tsf-custom-blogname-js");a.is(":checked")?(b.css("display",
10
+ "inline"),tsf.m=!0):(b.css("display","none"),tsf.m=!1);tsf.h().trigger("keyup",tsf.u)},ta:function(a){a=jQuery(a.target);var b=jQuery("#tsf-on-blogname-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},wa:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-title-additions-example-left"),c=jQuery(".tsf-title-additions-example-right");"right"===a?(b.css("display","none"),c.css("display","inline")):(b.css("display","inline"),c.css("display","none"))},xa:function(a){a=jQuery(a.target);
11
+ var b=jQuery(".tsf-title-prefix-example");a.is(":checked")?b.css("display","none"):b.css("display","inline")},S:function(a){a=jQuery(a.target);var b=jQuery("#tsf-description-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},ua:function(){if(tsf.c){var a=jQuery("#tsf-title-tagline-toggle :input"),b=jQuery(".tsf-custom-blogname-js"),c=jQuery("#tsf-description-additions-toggle :input"),d=jQuery("#tsf-description-additions-js"),e=jQuery("#tsf-description-onblogname-toggle :input"),
12
+ f=jQuery("#tsf-on-blogname-js"),k=jQuery("#tsf-title-additions-toggle :input"),l=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none");c.is(":checked")?d.css("display","inline"):d.css("display","none");e.is(":checked")?f.css("display","inline"):f.css("display","none");k.is(":checked")?l.css("display","none"):l.css("display","inline")}},ya:function(a){a=a.target.value||"";var b=jQuery(".tsf-custom-title-js");0===a.length?b.text(tsf.params.siteTitle):b.text(a)},
13
+ A:function(a){a=a.target.value||"";var b=jQuery(".tsf-custom-tagline-js"),c=jQuery("#autodescription-site-settings\\[homepage_title\\]"),d=jQuery("#tsf-home-title-location input:checked").val(),e=jQuery("#autodescription-site-settings\\[homepage_tagline\\]"),f=tsf.params.siteTitle,k=f,l=tsf.params.blogDescription,h=tsf.H("title");e.is(":checked")&&(0!==a.length&&(l=a),k=0!==d.length&&"left"===d?f+" "+h+" "+l:l+" "+h+" "+f);b.text(l);c.prop("placeholder",k);tsf.h().trigger("input",tsf.u)},j:function(){var a=
14
+ tsf.f;tsf.states.isSettingsPage?jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input",tsf.A):jQuery("#autodescription_title").trigger("input",tsf.A);tsf.f=a},sa:function(){var a=0,b=0;jQuery(window).resize(function(){clearTimeout(a);a=setTimeout(function(){var a=jQuery(window).width();b<a?782>=b&&782<=a&&tsf.j():782<=b&&782>=a&&tsf.j();b=a},250)})},za:function(){var a=jQuery(event.target),b=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","none"):b.css("display",
15
+ "inline")},T:function(){if(tsf.c){var a=function(d){tsf.f||tsf.l();jQuery(b).not(c).off(d.type,a)},b=".tsf-metaboxes :input, #tsf-inpost-box .inside :input",c=".tsf-tab :input, .tsf-flex-nav-tab :input";jQuery(b).not(c).on("change",a);b=".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea";c=".tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input";jQuery(b).not(c).on("input",a);window.onbeforeunload=function(){if(tsf.f)return tsf.i18n.saveAlert};
16
+ jQuery('.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete').click(function(){window.onbeforeunload=null})}},l:function(){tsf.f=!0},V:function(){return confirm(tsf.i18n.confirmReset)},Z:function(a){var b=tsf.params.titleAdditions.length,c=jQuery("#tsf-title-placeholder");if(!b)return jQuery(a.target).css("text-indent","initial"),c.empty();b=!1;var d=jQuery("#tsf-home-title-location input:checked").val(),e=tsf.states.isRTL;
17
+ "undefined"!==typeof d&&0!==d.length?e?"right"===d&&(b=!0):"left"===d&&(b=!0):(d=tsf.params.titleLocation,tsf.states.isHome?tsf.m&&(e?"right"===d&&(b=!0):"left"===d&&(b=!0)):e?"left"===d&&(b=!0):"right"===d&&(b=!0));d=jQuery("#tsf-title-tagline-toggle :input");if("undefined"!==typeof d&&0<d.length&&!d.is(":checked"))jQuery(a.target).css("text-indent","initial"),c.css("display","none");else{a=jQuery(a.target);var f=a.val(),k=jQuery("#tsf-title-offset"),l=a.outerWidth(),h=(a.outerHeight(!0)-a.height())/
18
+ 2,m=(l-a.innerWidth())/2;d=(a.outerWidth(!0)-a.width())/2;var g=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val();var n="left",p=tsf.H("title");e&&(n="right");"undefined"!==typeof g&&0===g.length&&(g=tsf.params.blogDescription);b?(e=" "+p+" "+tsf.params.titleAdditions,"undefined"!==typeof g&&0<g.length&&(e=" "+p+" "+g),a.css("text-indent","initial")):(e=tsf.params.titleAdditions+" "+p+" ","undefined"!==typeof g&&0<g.length&&(e=g+" "+p+" "));k.text(f);k.css({fontFamily:a.css("fontFamily"),
19
+ fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),fontSize:a.css("fontSize")});g=k.width();g=a.width()-m-g;0>g&&(g=0);c.css({display:a.css("display"),lineHeight:a.css("lineHeight"),paddingTop:h+"px",paddingBottom:h+"px",fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),fontSize:a.css("fontSize"),letterSpacing:a.css("letterSpacing"),maxWidth:g+"px"});"undefined"===typeof f||1>f.length?(b||a.css("text-indent","initial"),c.empty()):(c.text(e),l>d&&(b?c.css(n,m+d+k.width()+
20
+ "px"):(b=m+c.width(),0>b&&(b=0),c.css(n,d+"px"),a.css("text-indent",b+"px"))))}},ha:function(){var a=tsf.h();a.focus();if(a.setSelectionRange){var b=2*a.val().length;a.setSelectionRange(b,b)}else a.val(a.val()).focus()},Ba:function(){tsf.c&&tsf.G().trigger("input",tsf.M)},Ca:function(){tsf.c&&tsf.h().trigger("input",tsf.u)},fa:function(){tsf.f=!1},Y:function(a){jQuery(a.target).parents(".tsf-notice").slideUp(200,function(){this.remove()})},ka:function(a){jQuery(a).toggleClass("tsf-loading")},L:function(a,
21
+ b){var c="tsf-success",d=2500;b||(c="tsf-error",d=5E3);jQuery(a).removeClass("tsf-loading").addClass(c).fadeOut(d)},J:function(a){jQuery(a).stop().empty().prop("class","tsf-ajax").css("opacity","1").removeProp("style")},W:function(){tsf.a+=1;3<tsf.a&&(tsf.a=0);tsf.C();var a=0;tsf.J(".tsf-counter .tsf-ajax");tsf.ka(".tsf-counter .tsf-ajax");jQuery.ajax({method:"POST",url:ajaxurl,Ea:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.nonces.edit_posts,val:tsf.a},async:!0,success:function(b){b=
22
+ jQuery.parseJSON(b);"success"===b.type&&(a=1);tsf.X(".tsf-counter .tsf-ajax",a)}})},X:function(a,b){switch(b){case 0:tsf.L(a,!1);break;case 1:tsf.L(a,!0);break;default:tsf.J(a)}},C:function(){if(tsf.c){var a=tsf.a,b=tsf.f;1==a?(tsf.g="tsf-counter-one",tsf.a=1):2==a?(tsf.g="tsf-counter-two",tsf.a=2):3==a?(tsf.g="tsf-counter-three",tsf.a=3):(tsf.g="tsf-counter-zero",tsf.a=0);tsf.Da();tsf.f=b}},Da:function(){tsf.Ca();tsf.Ba()},i:function(a){return tsf.i18n[a]},H:function(a){var b="";a="title"===a?tsf.B:
23
+ tsf.F;"pipe"===a||"|"===a?b="|":"dash"===a||"-"===a?b="-":123>a.charCodeAt(0)&&("&"===a.charAt(0)&&";"===a.slice(-1)&&(a=a.substr(1).slice(0,-1)),b=jQuery("<div/>").html("&"+a+";").text());return b},I:function(a){if(jQuery(a.target).prop("disabled")||"undefined"===typeof wp.media)a.preventDefault(),a.stopPropagation();else{var b=jQuery(a.target),c=b.data("inputid");if(!d){a.preventDefault();a.stopPropagation();tsf.ba();var d=wp.media({button:{text:tsf.other[c].frame_button,close:!1},states:[new wp.media.controller.Library({title:tsf.other[c].frame_title,
24
+ library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:1200,suggestedHeight:630}),new tsf.cropper({imgSelectOptions:tsf.calculateImageSelectOptions})]});a=function(){d.setState("cropper")};d.off("select",a);d.on("select",a);a=function(a){var b=a.url;a=a.id;jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(a)};d.off("cropped",a);d.on("cropped",a);a=function(a){var b=a.get("url"),d=a.get("id");a.get("width");a.get("height");jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(d)};
25
+ d.off("skippedcrop",a);d.on("skippedcrop",a);a=function(){jQuery("#"+c+"-select").text(tsf.other[c].change);jQuery("#"+c+"-url").prop("readonly",!0).css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},"swing");tsf.D(b,c,!0);tsf.l()};d.off("skippedcrop cropped",a);d.on("skippedcrop cropped",a)}d.open()}},D:function(a,b,c){a&&b&&!jQuery("#"+b+"-remove").length&&(a.after('<a href="javascript:void(0)" id="'+b+'-remove" class="tsf-remove-social-image button button-small" data-inputid="'+b+'" title="'+
26
+ tsf.other[b].remove_title+'">'+tsf.other[b].remove+"</a>"),c&&jQuery("#"+b+"-remove").css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},"swing"));tsf.ga()},s:function(a){var b=jQuery(a.target).data("inputid");jQuery("#"+b+"-select").prop("disabled")||(jQuery("#"+b+"-select").addClass("disabled").prop("disabled",!0),jQuery("#"+b+"-remove").addClass("disabled").prop("disabled",!0).fadeOut(500,function(){jQuery(this).remove();jQuery("#"+b+"-select").text(tsf.other[b].select).removeClass("disabled").removeProp("disabled")}),
27
+ jQuery("#"+b+"-url").val("").removeProp("readonly").css("opacity",0).animate({opacity:1},{queue:!0,duration:500},"swing"),jQuery("#"+b+"-id").val(""),tsf.l())},ba:function(){if("undefined"===typeof tsf.cropper.control){var a=wp.media.controller.Cropper.extend({doCrop:function(a){var b=a.get("cropDetails"),d=tsf.cropper.control;if(d.params.flex_width&&d.params.flex_height)if(b.width===b.height)b.width>d.params.flex_width&&(b.dst_width=b.dst_height=d.params.flex_width);else if(b.width>d.params.flex_width||
28
+ b.height>d.params.flex_height)if(b.width>b.height){var e=b.width/d.params.flex_width;b.dst_width=d.params.flex_width;b.dst_height=Math.round(b.height/e)}else e=b.height/d.params.flex_height,b.dst_height=d.params.flex_height,b.dst_width=Math.round(b.width/e);"undefined"===typeof b.dst_width&&(b.dst_width=0,b.dst_height=0);return wp.ajax.post("tsf-crop-image",{nonce:tsf.nonces.upload_files,id:a.get("id"),context:"tsf-image",cropDetails:b})}});a.prototype.control={};a.control={params:{flex_width:4096,
29
+ flex_height:4096,width:1200,height:630}};tsf.cropper=a}},calculateImageSelectOptions:function(a,b){var c=tsf.cropper.control,d=!!parseInt(c.params.flex_width,10),e=!!parseInt(c.params.flex_height,10),f=parseInt(c.params.width,10),k=parseInt(c.params.height,10),l=a.get("width"),h=a.get("height"),m=f/k,g=f,n=k;b.set("control",c.params);b.set("canSkipCrop",!tsf.ea(c.params.flex_width,c.params.flex_height,l,h));l/h>m?(k=h,f=k*m):(f=l,k=f/m);c=(l-f)/2;m=(h-k)/2;g={handles:!0,keys:!0,instance:!0,persistent:!0,
30
+ imageWidth:l,imageHeight:h,minWidth:g>f?f:g,minHeight:n>k?k:n,x1:c,y1:m,x2:f+c,y2:k+m};!1===e&&!1===d&&(g.aspectRatio=f+":"+k);!0===e&&(g.minHeight=200,g.maxWidth=l);!0===d&&(g.minWidth=200,g.maxHeight=h);return g},ea:function(a,b,c,d){return c<=a&&d<=b?!1:!0},ga:function(){jQuery(".tsf-remove-social-image").off("click",tsf.s);jQuery(".tsf-remove-social-image").on("click",tsf.s)},na:function(){jQuery(".tsf-set-social-image").off("click",tsf.I);jQuery(".tsf-remove-social-image").off("click",tsf.s);
31
+ jQuery(".tsf-set-social-image").on("click",tsf.I);jQuery(".tsf-remove-social-image").on("click",tsf.s)},U:function(){var a=jQuery(".tsf-set-social-image");if(a.length){var b="",c="";jQuery.each(a,function(a,e){b=jQuery(e).data("inputid");c=jQuery("#"+b+"-id");c.length&&0<c.val()&&(jQuery("#"+b+"-url").prop("readonly",!0),tsf.D(jQuery(e),b,!1));jQuery("#"+b+"-url").val()&&jQuery("#"+b+"-select").text(tsf.other[b].change)})}},la:function(){var a=jQuery(".tsf-color-picker");a.length&&jQuery.each(a,function(a,
32
+ c){var b=jQuery(c),e="",f=b.data("tsf-default-color");b.wpColorPicker({defaultColor:f,width:238,change:function(){e=b.wpColorPicker("color");""===e&&(e=f);b.val(e);tsf.l()},clear:function(){b.parent().siblings(".wp-color-result").css("backgroundColor",f);tsf.l()},palettes:!1})})},oa:function(){tsf.B=tsf.params.titleSeparator;tsf.F=tsf.params.descriptionSeparator;tsf.m=tsf.states.titleTagline;tsf.a=parseInt(tsf.states.counterType);tsf.c=tsf.states.hasInput},O:function(){if(tsf.c){var a=jQuery;a("#tsf-title-tagline-toggle :input").on("click",
33
+ tsf.va);a("#tsf-title-location input").on("click",tsf.wa);a("#title-prefixes-toggle :input").on("click",tsf.xa);a("#autodescription-site-settings\\[homepage_title\\]").on("input",tsf.ya);a("#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input").on("click",tsf.j);a("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input",tsf.A);a("#homepage-tab-general").on("tsf-tab-toggled",tsf.j);a("#autodescription-homepage-settings > button").on("click",
34
+ tsf.j);a("#tsf-inpost-box > button").on("click",tsf.j);a("#autodescription-site-settings\\[title_rem_additions\\]").on("click",tsf.za);tsf.h().on("input",tsf.Z);a("#tsf-title-placeholder").on("click",tsf.ha);a(window).resize(tsf.sa)}},N:function(){if(jQuery(".tsf-flex").length){tsf.P();var a=0,b={},c=0,d=jQuery(".tsf-flex-nav-tab-wrapper");jQuery(window).on("tsf-flex-resize",function(){clearTimeout(a);var e=0;a=setTimeout(function(){if(d.length){var a=jQuery(".tsf-flex-nav-tab-inner"),c=d.width(),
35
+ l=a.width(),h=jQuery(".tsf-flex-nav-name");b.b||(b.b={},b.b.v=0,b.b.da=0,b.b.w=1);!b.b.w&&b.b.v<c&&(h.fadeIn(250),setTimeout(function(){l=a.width()},e));setTimeout(function(){l>c?(h.hide(),b.b.w=0):b.b.v<c&&(h.fadeIn(250),b.b.w=1)},2*e);setTimeout(function(){b.b.v=c;b.b.da=l},3*e)}},c);e=10;c=75});jQuery(window).trigger("tsf-flex-resize")}},P:function(){jQuery(window).on("resize orientationchange",tsf.o);jQuery("#collapse-menu").click(tsf.o);jQuery(".columns-prefs :input[type=radio]").change(tsf.o);
36
+ jQuery(".meta-box-sortables").on("sortupdate",tsf.o)},o:function(){jQuery(window).trigger("tsf-flex-resize")},R:function(){jQuery(document.body).trigger("tsf-ready")},ready:function(a){tsf.oa();a("div.updated, div.error, div.notice-warning").insertAfter("div.tsf-top-wrap");a(document.body).ready(tsf.O);a(document.body).ready(tsf.ma);a(document.body).ready(tsf.C);a(document.body).ready(tsf.ua);a(document.body).ready(tsf.statusBarHover);a(document.body).ready(tsf.na);a(document.body).ready(tsf.U);a(document.body).ready(tsf.la);
37
+ a(document.body).ready(tsf.T);a(document.body).ready(tsf.fa);a(document.body).ready(tsf.R);a(document.body).ready(tsf.N);a(document.body).on("click touchstart MSPointerDown",tsf.Aa);tsf.G().on("input",tsf.M);tsf.h().on("input",tsf.u);a("#tsf-title-separator input").on("click",tsf.ja);a("#tsf-description-separator input").on("click",tsf.ia);a(".tsf-js-confirm-reset").on("click",tsf.V);a(".tsf-tabs-radio").on("change",tsf.ra);a(".tsf-flex-nav-tab-radio").on("change",tsf.ca);a("#tsf-description-onblogname-toggle :input").on("click",
38
+ tsf.ta);a("#tsf-description-additions-toggle :input").on("click",tsf.S);a(".tsf-dismiss").on("click",tsf.Y);a(".tsf-counter").on("click",tsf.W)}};jQuery(tsf.ready);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://theseoframework.com/donate/
4
  Tags: google, bing, open graph, seo, xml sitemap, breadcrumbs, meta, search engine, woocommerce, cpt, facebook, twitter
5
  Requires at least: 4.4.0
6
  Tested up to: 4.8.0
7
- Stable tag: 2.9.2
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -115,7 +115,7 @@ A caching plugin isn't even needed for this plugin as you won't notice a differe
115
  * Internationalization through WordPress.org.
116
  * Multibyte calculation and rendering, including Emoji and CJK.
117
  * Right to Left (RTL) languages, through its interface and generation.
118
- * Extended Color vision deficiency accessibility.
119
  * Screen reader accessibility.
120
  * MultiSite, this plugin is in fact built upon one.
121
  * Detection of robots.txt and sitemap.xml files.
@@ -225,6 +225,52 @@ Transporting Terms and Taxonomies SEO data isn't supported.
225
 
226
  == Changelog ==
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  = 2.9.2 - Diminutive Consolidation =
229
 
230
  **Release date:**
@@ -333,6 +379,9 @@ Transporting Terms and Taxonomies SEO data isn't supported.
333
 
334
  == Upgrade Notice ==
335
 
 
 
 
336
  = 2.8.0 =
337
  In the 2.8.0 update WordPress 4.3 and PHP 5.2 support have been dropped for better code quality.
338
 
4
  Tags: google, bing, open graph, seo, xml sitemap, breadcrumbs, meta, search engine, woocommerce, cpt, facebook, twitter
5
  Requires at least: 4.4.0
6
  Tested up to: 4.8.0
7
+ Stable tag: 2.9.3
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
115
  * Internationalization through WordPress.org.
116
  * Multibyte calculation and rendering, including Emoji and CJK.
117
  * Right to Left (RTL) languages, through its interface and generation.
118
+ * Extended color vision deficiency accessibility.
119
  * Screen reader accessibility.
120
  * MultiSite, this plugin is in fact built upon one.
121
  * Detection of robots.txt and sitemap.xml files.
225
 
226
  == Changelog ==
227
 
228
+ = 2.9.3 - Assiduous Substratum =
229
+
230
+ **Release date:**
231
+
232
+ * July 3rd, 2017
233
+
234
+ **Announcement: Local SEO Beta**
235
+
236
+ * Local SEO is a premium extension, and it's almost ready for testing.
237
+ * As we do not want to spam your WordPress dashboard, I've created a new [Twitter account](https://twitter.com/TheSEOFramework) for future announcements.
238
+ * Feel free to follow us to receive the latest updates. As we're planning a test-run prior to release, further details for beta-access will also follow in a tweet.
239
+
240
+ [youtube https://www.youtube.com/?v=q_ZnBuU1BwY&w=611&h=642&showinfo=0&rel=0&showsearch=0]
241
+
242
+ **Summarized:**
243
+
244
+ * Social images can now scale up to 4K resolution. This means (manual and automated) forced cropping no longer initiates at 1500px but at 4096px.
245
+ * A new option has been added for every taxonomical post type in the Visibility tab. It allows you to prevent the annotated pages from showing up in Archives.
246
+ * Structured Data output has been revisited. This includes merging of output, removal of misplaced output, and performance improvements.
247
+ * When your home page is a blog, pages without an ID (404, search, date archives, etc.) had output and caching issues. These issues have been resolved.
248
+ * Several security concerns have also been addressed. Although, none of them could be verified as the coding environment is already well protected.
249
+
250
+ **For everyone: Caching changes:**
251
+
252
+ * Descriptions and Schema.org output transients are no longer enabled by default. Because for most sites, it's better left disabled.
253
+ * This has been done to reduce database calls. Ultimately, the performance benefits of using the transients are use-case specific.
254
+
255
+ **For developers: Schema.org output code changes:**
256
+
257
+ * The Schema.org output code has been [rewritten](https://github.com/sybrew/the-seo-framework/issues/97). This improves reliability, performance and extensibility.
258
+ * If you've extended or altered the Schema.org generation output, you might wish to revisit your coding implementations.
259
+ * All affronted methods have been correctly deprecated and tested once more. So, 500 errors shouldn't occur.
260
+ * To be certain, visit the detailed changelog and compare your code.
261
+
262
+ **For high-traffic webmasters and Google Analytics integration plugin authors: About the Search URL change:**
263
+
264
+ * From this update, new canonical URLs will be generated for search queries to comply to the pretty permalink structure.
265
+ * WordPress natively supports the `/search/{search_term}` endpoint; however, Google Analytics does not.
266
+ * To enable support, please visit [this page](https://support.google.com/analytics/answer/1012264?hl=en&ref_topic=1031951#Post) for more information.
267
+ * I've created a plugin that will enhance support for you. You can download it [here](https://gist.github.com/sybrew/ab5553dd8a06e73794680c4a2cc24661).
268
+ * An extension is planned that will implement Google Analytics for you, complying to those guidelines.
269
+
270
+ **Detailed log:**
271
+
272
+ ***Already the Sun is climbing to noon, and I feel the need of [something to strengthen me](https://theseoframework.com/?p=2064#detailed).***
273
+
274
  = 2.9.2 - Diminutive Consolidation =
275
 
276
  **Release date:**
379
 
380
  == Upgrade Notice ==
381
 
382
+ = 2.9.3 =
383
+ A highly recommended update that fixes "Home Page as Blog" query issues.
384
+
385
  = 2.8.0 =
386
  In the 2.8.0 update WordPress 4.3 and PHP 5.2 support have been dropped for better code quality.
387
 
seotips/seotips.txt CHANGED
@@ -86,7 +86,7 @@
86
 
87
  = 2.6.0 - Redirects & Canonical =
88
 
89
- * A change in the Canonical URL or the use of a 301 Redirect URL indicate that your page has moved.
90
  * These can be seen by Search Engines as the same. However, the 301 Redirect enforces the relocation of the page to everyone, whereas the Canonical URL softly indicates.
91
  * When changing the Canonical URL of a Page, you're telling robots to look and elsewhere, be sure to include a link to the new Page on the canonicalized Page to indicate where everything has moved to.
92
  * However, it's even better to enforce a 301 redirect. This makes sure both your visitors as Search Engines know where to be instantaneously.
@@ -97,7 +97,7 @@
97
  * Do you use Images in your Posts and Pages? Be sure to describe them! This way people are able to find your website through the Image Results.
98
  * This can be easily done when editing the Image through WordPress' Media Library or when inserting an Image in the content. When you click on an Image, you can define various details.
99
  * The Alt Text is to be used. If that's not found, the Image Caption is used. And if that's also not found, then the Image Title will be used.
100
- * Make sure it clearly describes the Image, and be aware that it will fall back to it when the browser can't render the Image. It's also a great additions for people who are vision impaired.
101
 
102
  = 2.6.2 - Geo Targetting =
103
 
86
 
87
  = 2.6.0 - Redirects & Canonical =
88
 
89
+ * A change in the Canonical URL or the use of a 301 Redirect URL indicates that your page has moved.
90
  * These can be seen by Search Engines as the same. However, the 301 Redirect enforces the relocation of the page to everyone, whereas the Canonical URL softly indicates.
91
  * When changing the Canonical URL of a Page, you're telling robots to look and elsewhere, be sure to include a link to the new Page on the canonicalized Page to indicate where everything has moved to.
92
  * However, it's even better to enforce a 301 redirect. This makes sure both your visitors as Search Engines know where to be instantaneously.
97
  * Do you use Images in your Posts and Pages? Be sure to describe them! This way people are able to find your website through the Image Results.
98
  * This can be easily done when editing the Image through WordPress' Media Library or when inserting an Image in the content. When you click on an Image, you can define various details.
99
  * The Alt Text is to be used. If that's not found, the Image Caption is used. And if that's also not found, then the Image Title will be used.
100
+ * Make sure it clearly describes the Image, and be aware that it will fall back to it when the browser can't render the Image. It's also a great addition for people who are vision impaired.
101
 
102
  = 2.6.2 - Geo Targetting =
103