The SEO Framework - Version 3.2.4

Version Description

In this minor update, we bring you the most advanced description generation yet. The generator is now context-sensitive, so you can expect the descriptions to be even more natural; a real time-saver!

Oh, we also fixed some bugs, and we've implemented some improvements in preparation for version 3.3.0.

Download this release

Release Info

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

Code changes from version 3.2.3 to 3.2.4

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 your WordPress website.
6
- * Version: 3.2.3
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
@@ -53,7 +53,7 @@ defined( 'ABSPATH' ) or die;
53
  *
54
  * @since 2.3.5
55
  */
56
- define( 'THE_SEO_FRAMEWORK_VERSION', '3.2.3' );
57
 
58
  /**
59
  * The plugin Database version.
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 your WordPress website.
6
+ * Version: 3.2.4
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
53
  *
54
  * @since 2.3.5
55
  */
56
+ define( 'THE_SEO_FRAMEWORK_VERSION', '3.2.4' );
57
 
58
  /**
59
  * The plugin Database version.
bootstrap/activation.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework
4
- */
5
- namespace The_SEO_Framework;
 
6
 
7
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
8
 
@@ -23,10 +24,14 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
 
 
26
  //! @php7+ convert to IIFE
27
- \The_SEO_Framework\_activation_setup_sitemap();
28
- \The_SEO_Framework\_activation_set_options_autoload();
29
- \The_SEO_Framework\_activation_set_plugin_check_caches();
30
 
31
  /**
32
  * Nudges the plugin to check for conflicting SEO plugins.
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrap
5
+ */
6
+ namespace The_SEO_Framework\Bootstrap;
7
 
8
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
24
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
  */
26
 
27
+ /**
28
+ * @since 3.2.4 Applied namspacing to this file. All method names have changed.
29
+ */
30
+
31
  //! @php7+ convert to IIFE
32
+ _activation_setup_sitemap();
33
+ _activation_set_options_autoload();
34
+ _activation_set_plugin_check_caches();
35
 
36
  /**
37
  * Nudges the plugin to check for conflicting SEO plugins.
bootstrap/deactivation.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework
4
- */
5
- namespace The_SEO_Framework;
 
6
 
7
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
8
 
@@ -23,9 +24,13 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
 
 
26
  //! @php7+ convert to IIFE
27
- \The_SEO_Framework\_deactivation_unset_options_autoload();
28
- \The_SEO_Framework\_deactivation_unset_sitemap();
29
 
30
  /**
31
  * Flush rewrite rules on plugin deactivation.
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrap
5
+ */
6
+ namespace The_SEO_Framework\Bootstrap;
7
 
8
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
24
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
  */
26
 
27
+ /**
28
+ * @since 3.2.4 Applied namspacing to this file. All method names have changed.
29
+ */
30
+
31
  //! @php7+ convert to IIFE
32
+ _deactivation_unset_options_autoload();
33
+ _deactivation_unset_sitemap();
34
 
35
  /**
36
  * Flush rewrite rules on plugin deactivation.
bootstrap/define.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework/Bootstrap
 
 
4
  */
5
 
6
  defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrap
5
+ * No need to annotate namespacing here... there are only plain PHP queries.
6
  */
7
 
8
  defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
bootstrap/envtest.php CHANGED
@@ -1,6 +1,10 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework/Bootstrap
 
 
 
 
4
  */
5
 
6
  defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
@@ -27,9 +31,6 @@ defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
27
  * This file will only be called ONCE if the required version option is lower
28
  * compared to The SEO Framework version constant.
29
  *
30
- * @NOTE This file MUST be written according to WordPress' minimum PHP requirements.
31
- * Which is PHP 5.2.
32
- *
33
  * @since 3.1.0
34
  * @access private
35
  */
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrap
5
+ *
6
+ * @NOTE This file MUST be written according to WordPress' minimum PHP requirements.
7
+ * Which is PHP 5.2.
8
  */
9
 
10
  defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
31
  * This file will only be called ONCE if the required version option is lower
32
  * compared to The SEO Framework version constant.
33
  *
 
 
 
34
  * @since 3.1.0
35
  * @access private
36
  */
bootstrap/load.php CHANGED
@@ -1,7 +1,10 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework/Bootstrap
4
- */
 
 
 
5
  namespace The_SEO_Framework;
6
 
7
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrap
5
+ * @TODO change namespace to The_SEO_Framework\Bootstrap
6
+ * in a future major release.
7
+ */
8
  namespace The_SEO_Framework;
9
 
10
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
bootstrap/upgrade.php CHANGED
@@ -1,7 +1,9 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework/Bootstrap
 
4
  */
 
5
 
6
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
7
 
@@ -31,6 +33,8 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
31
  * @access private
32
  * @TODO convert to class, see \TSF_Extension_Manager\Upgrader
33
  * It's a generator/iterator, so we must wait to PHP>5.5 support.
 
 
34
  */
35
 
36
  /**
@@ -41,12 +45,12 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
41
  *
42
  * @return array The default site options.
43
  */
44
- function the_seo_framework_upgrade_default_site_options() {
45
  static $cache;
46
- return isset( $cache ) ? $cache : $cache = the_seo_framework()->get_default_site_options();
47
  }
48
 
49
- the_seo_framework_previous_db_version(); // sets cache.
50
  /**
51
  * Returns the version set before upgrading began.
52
  *
@@ -55,12 +59,12 @@ the_seo_framework_previous_db_version(); // sets cache.
55
  *
56
  * @return string The prior-to-upgrade TSF db version.
57
  */
58
- function the_seo_framework_previous_db_version() {
59
  static $cache;
60
- return isset( $cache ) ? $cache : $cache = get_option( 'the_seo_framework_upgraded_db_version', '0' );
61
  }
62
 
63
- add_action( 'init', 'the_seo_framework_do_upgrade', 20 );
64
  /**
65
  * Upgrade The SEO Framework to the latest version.
66
  *
@@ -82,12 +86,14 @@ add_action( 'init', 'the_seo_framework_do_upgrade', 20 );
82
  * 9. Now runs on the front-end, too, via `init`, instead of `admin_init`.
83
  * @since 3.1.4 Now flushes object cache before the upgrade settings are called.
84
  */
85
- function the_seo_framework_do_upgrade() {
 
 
86
 
87
- if ( ! the_seo_framework()->loaded ) return;
88
 
89
- if ( the_seo_framework()->is_seo_settings_page( false ) ) {
90
- wp_redirect( self_admin_url() ); // phpcs:ignore -- self_admin_url() is safe.
91
  exit;
92
  }
93
 
@@ -98,61 +104,61 @@ function the_seo_framework_do_upgrade() {
98
  * @since 3.1.4
99
  */
100
  // Clear the cache to prevent an update_option() from saving a stale database version to the cache
101
- wp_cache_flush();
102
  // (Not all cache back ends listen to 'flush')
103
- wp_cache_delete( 'alloptions', 'options' );
104
 
105
- $version = the_seo_framework_previous_db_version();
106
 
107
- if ( ! get_option( 'the_seo_framework_initial_db_version' ) ) {
108
  //* Sets to previous if previous is known. This is a late addition.
109
- update_option( 'the_seo_framework_initial_db_version', $version ?: THE_SEO_FRAMEWORK_DB_VERSION, 'no' );
110
  }
111
 
112
  if ( $version >= THE_SEO_FRAMEWORK_DB_VERSION ) {
113
- the_seo_framework_upgrade_to_current();
114
  return;
115
  }
116
 
117
  if ( ! $version ) {
118
- the_seo_framework_do_upgrade_1();
119
  $version = '1';
120
  }
121
  if ( $version < '2701' ) {
122
- the_seo_framework_do_upgrade_2701();
123
  $version = '2701';
124
  }
125
  if ( $version < '2802' ) {
126
- the_seo_framework_do_upgrade_2802();
127
  $version = '2802';
128
  }
129
  if ( $version < '2900' ) {
130
- the_seo_framework_do_upgrade_2900();
131
  $version = '2900';
132
  }
133
  if ( $version < '3001' ) {
134
- the_seo_framework_do_upgrade_3001();
135
  $version = '3001';
136
  }
137
  if ( $version < '3060' ) {
138
- the_seo_framework_do_upgrade_3060();
139
  $version = '3060';
140
  }
141
 
142
  //! From here, the upgrade procedures should be backward compatible.
143
  //? This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
144
  if ( $version < '3103' ) {
145
- the_seo_framework_do_upgrade_3103();
146
  $version = '3103';
147
  }
148
 
149
  /**
150
  * @since 2.7.0
151
  */
152
- do_action( 'the_seo_framework_upgraded' );
153
  }
154
 
155
- add_action( 'the_seo_framework_upgraded', 'the_seo_framework_upgrade_to_current' );
156
  /**
157
  * Upgrades the Database version to the latest version.
158
  *
@@ -163,20 +169,21 @@ add_action( 'the_seo_framework_upgraded', 'the_seo_framework_upgrade_to_current'
163
  * @since 2.7.0
164
  * @since 3.1.4 Now flushes the object cache after the setting's updated.
165
  */
166
- function the_seo_framework_upgrade_to_current() {
167
- update_option( 'the_seo_framework_upgraded_db_version', THE_SEO_FRAMEWORK_DB_VERSION );
 
168
 
169
  /**
170
  * From WordPress' .../update-core.php
171
  * @since 3.1.4
172
  */
173
  // Clear the cache to prevent a get_option() from retrieving a stale database version to the cache
174
- wp_cache_flush();
175
  // (Not all cache back ends listen to 'flush')
176
- wp_cache_delete( 'alloptions', 'options' );
177
  }
178
 
179
- add_action( 'the_seo_framework_upgraded', 'the_seo_framework_upgrade_reinitialize_rewrite', 99 );
180
  /**
181
  * Reinitializes the rewrite cache.
182
  *
@@ -185,29 +192,29 @@ add_action( 'the_seo_framework_upgraded', 'the_seo_framework_upgrade_reinitializ
185
  *
186
  * @since 3.1.2
187
  */
188
- function the_seo_framework_upgrade_reinitialize_rewrite() {
189
- the_seo_framework()->reinitialize_rewrite();
190
  }
191
 
192
- add_action( 'the_seo_framework_upgraded', 'the_seo_framework_prepare_extension_manager_suggestion', 100 );
193
  /**
194
  * Enqueues and outputs an Extension Manager suggestion.
195
  *
196
  * @since 3.1.0
197
- * @since 3.2.2. No longer suggests when the user is new.
 
198
  * @staticvar bool $run
199
  *
200
  * @return void Early when already enqueued
201
  */
202
- function the_seo_framework_prepare_extension_manager_suggestion() {
203
  static $run = false;
204
  if ( $run ) return;
205
 
206
- if ( is_admin() ) {
207
- add_action( 'admin_init', function() {
208
- if ( ! the_seo_framework_previous_db_version() ) return;
209
- require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'tsfem-suggestion.php';
210
- the_seo_framework_load_extension_manager_suggestion();
211
  }, 20 );
212
  }
213
 
@@ -224,7 +231,7 @@ function the_seo_framework_prepare_extension_manager_suggestion() {
224
  * @param bool $get Whether to return the upgrade notices.
225
  * @return array|void The notices when $get is true.
226
  */
227
- function the_seo_framework_add_upgrade_notice( $notice = '', $get = false ) {
228
 
229
  static $cache = [];
230
 
@@ -234,21 +241,21 @@ function the_seo_framework_add_upgrade_notice( $notice = '', $get = false ) {
234
  $cache[] = $notice;
235
  }
236
 
237
- add_action( 'admin_notices', 'the_seo_framework_output_upgrade_notices' );
238
  /**
239
  * Outputs available upgrade notices.
240
  *
241
  * @since 2.9.0
242
  * @since 3.0.0 Added prefix.
243
- * @uses the_seo_framework_add_upgrade_notice()
244
  */
245
- function the_seo_framework_output_upgrade_notices() {
246
 
247
- $notices = the_seo_framework_add_upgrade_notice( '', true );
248
 
249
  foreach ( $notices as $notice ) {
250
  //* @TODO rtl?
251
- the_seo_framework()->do_dismissible_notice( 'SEO: ' . $notice, 'updated' );
252
  }
253
  }
254
 
@@ -257,9 +264,9 @@ function the_seo_framework_output_upgrade_notices() {
257
  *
258
  * @since 3.1.0
259
  */
260
- function the_seo_framework_do_upgrade_1() {
261
- the_seo_framework()->register_settings();
262
- update_option( 'the_seo_framework_upgraded_db_version', '1' );
263
  }
264
 
265
  /**
@@ -269,20 +276,20 @@ function the_seo_framework_do_upgrade_1() {
269
  * @since 3.1.0 No longer tries to set term meta for ID 0.
270
  * `add_metadata()` already blocked this, this is defensive.
271
  */
272
- function the_seo_framework_do_upgrade_2701() {
273
 
274
- $term_meta = get_option( 'autodescription-term-meta' );
275
 
276
  if ( $term_meta ) {
277
  foreach ( (array) $term_meta as $term_id => $meta ) {
278
- add_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $meta, true );
279
  }
280
 
281
  //= Rudimentary test for remaining ~300 users of the past passed, set initial version to 2600.
282
- update_option( 'the_seo_framework_initial_db_version', '2600', 'no' );
283
  }
284
 
285
- update_option( 'the_seo_framework_upgraded_db_version', '2701' );
286
  }
287
 
288
  /**
@@ -291,13 +298,13 @@ function the_seo_framework_do_upgrade_2701() {
291
  *
292
  * @since 2.8.0
293
  */
294
- function the_seo_framework_do_upgrade_2802() {
295
 
296
  //* Delete old values from database. Removes backwards compatibility.
297
- if ( get_option( 'the_seo_framework_initial_db_version' ) < '2701' )
298
- delete_option( 'autodescription-term-meta' );
299
 
300
- update_option( 'the_seo_framework_upgraded_db_version', '2802' );
301
  }
302
 
303
  /**
@@ -306,25 +313,25 @@ function the_seo_framework_do_upgrade_2802() {
306
  * @since 2.9.0
307
  * @since 3.1.0 Now only sets new options when defaults exists.
308
  */
309
- function the_seo_framework_do_upgrade_2900() {
310
 
311
- if ( get_option( 'the_seo_framework_initial_db_version' ) < '2900' ) {
312
- $defaults = the_seo_framework_upgrade_default_site_options();
313
 
314
  if ( isset( $defaults['twitter_card'] ) ) {
315
- $tsf = the_seo_framework();
316
 
317
- $card_type = trim( esc_attr( $tsf->get_option( 'twitter_card', false ) ) );
318
  if ( 'photo' === $card_type ) {
319
  $tsf->update_option( 'twitter_card', 'summary_large_image' );
320
- the_seo_framework_add_upgrade_notice(
321
- esc_html__( 'Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable.', 'autodescription' )
322
  );
323
  }
324
  }
325
  }
326
 
327
- update_option( 'the_seo_framework_upgraded_db_version', '2900' );
328
  }
329
 
330
  /**
@@ -335,20 +342,20 @@ function the_seo_framework_do_upgrade_2900() {
335
  * @since 3.0.6 'display_character_counter' option now correctly defaults to 1.
336
  * @since 3.1.0 Now only sets new options when defaults exist, and when it's an upgraded site.
337
  */
338
- function the_seo_framework_do_upgrade_3001() {
339
 
340
- if ( get_option( 'the_seo_framework_initial_db_version' ) < '3001' ) {
341
- $tsf = the_seo_framework();
342
 
343
- $defaults = the_seo_framework_upgrade_default_site_options();
344
 
345
  if ( isset( $defaults['timestamps_format'] ) ) {
346
  //= Only change if old option exists. Falls back to default upgrader otherwise.
347
  $sitemap_timestamps = $tsf->get_option( 'sitemap_timestamps', false );
348
  $tsf->update_option( 'timestamps_format', (string) (int) $sitemap_timestamps ?: $defaults['timestamps_format'] );
349
  if ( '' !== $sitemap_timestamps ) {
350
- the_seo_framework_add_upgrade_notice(
351
- esc_html__( 'The previous sitemap timestamp settings have been converted into new global timestamp settings.', 'autodescription' )
352
  );
353
  }
354
  }
@@ -360,7 +367,7 @@ function the_seo_framework_do_upgrade_3001() {
360
  $tsf->update_option( 'display_pixel_counter', $defaults['display_pixel_counter'] );
361
  }
362
 
363
- update_option( 'the_seo_framework_upgraded_db_version', '3001' );
364
  }
365
 
366
  /**
@@ -369,12 +376,12 @@ function the_seo_framework_do_upgrade_3001() {
369
  *
370
  * @since 3.0.6
371
  */
372
- function the_seo_framework_do_upgrade_3060() {
373
 
374
- if ( get_option( 'the_seo_framework_initial_db_version' ) < '3060' )
375
- the_seo_framework()->delete_cache( 'sitemap' );
376
 
377
- update_option( 'the_seo_framework_upgraded_db_version', '3060' );
378
  }
379
 
380
  /**
@@ -391,16 +398,16 @@ function the_seo_framework_do_upgrade_3060() {
391
  *
392
  * @since 3.1.0
393
  */
394
- function the_seo_framework_do_upgrade_3103() {
395
 
396
  // Prevent database lookups when checking for cache.
397
- add_option( THE_SEO_FRAMEWORK_SITE_CACHE, [] );
398
 
399
  // If it's an older installation, upgrade these options.
400
- if ( get_option( 'the_seo_framework_initial_db_version' ) < '3103' ) {
401
- $tsf = the_seo_framework();
402
 
403
- $defaults = the_seo_framework_upgrade_default_site_options();
404
 
405
  // Transport title separator.
406
  if ( isset( $defaults['title_separator'] ) )
@@ -433,5 +440,5 @@ function the_seo_framework_do_upgrade_3103() {
433
  $tsf->update_option( 'sitemaps_priority', 1 );
434
  }
435
 
436
- update_option( 'the_seo_framework_upgraded_db_version', '3103' );
437
  }
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework
4
+ * @subpackage Bootstrapp
5
  */
6
+ namespace The_SEO_Framework\Bootstrap;
7
 
8
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
33
  * @access private
34
  * @TODO convert to class, see \TSF_Extension_Manager\Upgrader
35
  * It's a generator/iterator, so we must wait to PHP>5.5 support.
36
+ *
37
+ * @since 3.2.4 Applied namspacing to this file. All method names have changed.
38
  */
39
 
40
  /**
45
  *
46
  * @return array The default site options.
47
  */
48
+ function _upgrade_default_site_options() {
49
  static $cache;
50
+ return isset( $cache ) ? $cache : $cache = \the_seo_framework()->get_default_site_options();
51
  }
52
 
53
+ _previous_db_version(); // sets cache.
54
  /**
55
  * Returns the version set before upgrading began.
56
  *
59
  *
60
  * @return string The prior-to-upgrade TSF db version.
61
  */
62
+ function _previous_db_version() {
63
  static $cache;
64
+ return isset( $cache ) ? $cache : $cache = \get_option( 'the_seo_framework_upgraded_db_version', '0' );
65
  }
66
 
67
+ \add_action( 'init', __NAMESPACE__ . '\\_do_upgrade', 20 );
68
  /**
69
  * Upgrade The SEO Framework to the latest version.
70
  *
86
  * 9. Now runs on the front-end, too, via `init`, instead of `admin_init`.
87
  * @since 3.1.4 Now flushes object cache before the upgrade settings are called.
88
  */
89
+ function _do_upgrade() {
90
+
91
+ $tsf = \the_seo_framework();
92
 
93
+ if ( ! $tsf->loaded ) return;
94
 
95
+ if ( $tsf->is_seo_settings_page( false ) ) {
96
+ \wp_redirect( \self_admin_url() ); // phpcs:ignore -- self_admin_url() is safe.
97
  exit;
98
  }
99
 
104
  * @since 3.1.4
105
  */
106
  // Clear the cache to prevent an update_option() from saving a stale database version to the cache
107
+ \wp_cache_flush();
108
  // (Not all cache back ends listen to 'flush')
109
+ \wp_cache_delete( 'alloptions', 'options' );
110
 
111
+ $version = _previous_db_version();
112
 
113
+ if ( ! \get_option( 'the_seo_framework_initial_db_version' ) ) {
114
  //* Sets to previous if previous is known. This is a late addition.
115
+ \update_option( 'the_seo_framework_initial_db_version', $version ?: THE_SEO_FRAMEWORK_DB_VERSION, 'no' );
116
  }
117
 
118
  if ( $version >= THE_SEO_FRAMEWORK_DB_VERSION ) {
119
+ _upgrade_to_current();
120
  return;
121
  }
122
 
123
  if ( ! $version ) {
124
+ _do_upgrade_1();
125
  $version = '1';
126
  }
127
  if ( $version < '2701' ) {
128
+ _do_upgrade_2701();
129
  $version = '2701';
130
  }
131
  if ( $version < '2802' ) {
132
+ _do_upgrade_2802();
133
  $version = '2802';
134
  }
135
  if ( $version < '2900' ) {
136
+ _do_upgrade_2900();
137
  $version = '2900';
138
  }
139
  if ( $version < '3001' ) {
140
+ _do_upgrade_3001();
141
  $version = '3001';
142
  }
143
  if ( $version < '3060' ) {
144
+ _do_upgrade_3060();
145
  $version = '3060';
146
  }
147
 
148
  //! From here, the upgrade procedures should be backward compatible.
149
  //? This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
150
  if ( $version < '3103' ) {
151
+ _do_upgrade_3103();
152
  $version = '3103';
153
  }
154
 
155
  /**
156
  * @since 2.7.0
157
  */
158
+ \do_action( 'the_seo_framework_upgraded' );
159
  }
160
 
161
+ \add_action( 'the_seo_framework_upgraded', __NAMESPACE__ . '\\_upgrade_to_current' );
162
  /**
163
  * Upgrades the Database version to the latest version.
164
  *
169
  * @since 2.7.0
170
  * @since 3.1.4 Now flushes the object cache after the setting's updated.
171
  */
172
+ function _upgrade_to_current() {
173
+
174
+ \update_option( 'the_seo_framework_upgraded_db_version', THE_SEO_FRAMEWORK_DB_VERSION );
175
 
176
  /**
177
  * From WordPress' .../update-core.php
178
  * @since 3.1.4
179
  */
180
  // Clear the cache to prevent a get_option() from retrieving a stale database version to the cache
181
+ \wp_cache_flush();
182
  // (Not all cache back ends listen to 'flush')
183
+ \wp_cache_delete( 'alloptions', 'options' );
184
  }
185
 
186
+ \add_action( 'the_seo_framework_upgraded', __NAMESPACE__ . '\\_upgrade_reinitialize_rewrite', 99 );
187
  /**
188
  * Reinitializes the rewrite cache.
189
  *
192
  *
193
  * @since 3.1.2
194
  */
195
+ function _upgrade_reinitialize_rewrite() {
196
+ \the_seo_framework()->reinitialize_rewrite();
197
  }
198
 
199
+ \add_action( 'the_seo_framework_upgraded', __NAMESPACE__ . '\\_prepare_upgrade_suggestion', 100 );
200
  /**
201
  * Enqueues and outputs an Extension Manager suggestion.
202
  *
203
  * @since 3.1.0
204
+ * @since 3.2.2 No longer suggests when the user is new.
205
+ * @since 3.2.4 Moved upgrade suggestion call to applicable file.
206
  * @staticvar bool $run
207
  *
208
  * @return void Early when already enqueued
209
  */
210
+ function _prepare_upgrade_suggestion() {
211
  static $run = false;
212
  if ( $run ) return;
213
 
214
+ if ( \is_admin() ) {
215
+ \add_action( 'admin_init', function() {
216
+ if ( ! _previous_db_version() ) return;
217
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'upgrade-suggestion.php';
 
218
  }, 20 );
219
  }
220
 
231
  * @param bool $get Whether to return the upgrade notices.
232
  * @return array|void The notices when $get is true.
233
  */
234
+ function _add_upgrade_notice( $notice = '', $get = false ) {
235
 
236
  static $cache = [];
237
 
241
  $cache[] = $notice;
242
  }
243
 
244
+ \add_action( 'admin_notices', __NAMESPACE__ . '\\_output_upgrade_notices' );
245
  /**
246
  * Outputs available upgrade notices.
247
  *
248
  * @since 2.9.0
249
  * @since 3.0.0 Added prefix.
250
+ * @uses _add_upgrade_notice()
251
  */
252
+ function _output_upgrade_notices() {
253
 
254
+ $notices = _add_upgrade_notice( '', true );
255
 
256
  foreach ( $notices as $notice ) {
257
  //* @TODO rtl?
258
+ \the_seo_framework()->do_dismissible_notice( 'SEO: ' . $notice, 'updated' );
259
  }
260
  }
261
 
264
  *
265
  * @since 3.1.0
266
  */
267
+ function _do_upgrade_1() {
268
+ \the_seo_framework()->register_settings();
269
+ \update_option( 'the_seo_framework_upgraded_db_version', '1' );
270
  }
271
 
272
  /**
276
  * @since 3.1.0 No longer tries to set term meta for ID 0.
277
  * `add_metadata()` already blocked this, this is defensive.
278
  */
279
+ function _do_upgrade_2701() {
280
 
281
+ $term_meta = \get_option( 'autodescription-term-meta' );
282
 
283
  if ( $term_meta ) {
284
  foreach ( (array) $term_meta as $term_id => $meta ) {
285
+ \add_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $meta, true );
286
  }
287
 
288
  //= Rudimentary test for remaining ~300 users of the past passed, set initial version to 2600.
289
+ \update_option( 'the_seo_framework_initial_db_version', '2600', 'no' );
290
  }
291
 
292
+ \update_option( 'the_seo_framework_upgraded_db_version', '2701' );
293
  }
294
 
295
  /**
298
  *
299
  * @since 2.8.0
300
  */
301
+ function _do_upgrade_2802() {
302
 
303
  //* Delete old values from database. Removes backwards compatibility.
304
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '2701' )
305
+ \delete_option( 'autodescription-term-meta' );
306
 
307
+ \update_option( 'the_seo_framework_upgraded_db_version', '2802' );
308
  }
309
 
310
  /**
313
  * @since 2.9.0
314
  * @since 3.1.0 Now only sets new options when defaults exists.
315
  */
316
+ function _do_upgrade_2900() {
317
 
318
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '2900' ) {
319
+ $defaults = _upgrade_default_site_options();
320
 
321
  if ( isset( $defaults['twitter_card'] ) ) {
322
+ $tsf = \the_seo_framework();
323
 
324
+ $card_type = trim( \esc_attr( $tsf->get_option( 'twitter_card', false ) ) );
325
  if ( 'photo' === $card_type ) {
326
  $tsf->update_option( 'twitter_card', 'summary_large_image' );
327
+ _add_upgrade_notice(
328
+ \esc_html__( 'Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable.', 'autodescription' )
329
  );
330
  }
331
  }
332
  }
333
 
334
+ \update_option( 'the_seo_framework_upgraded_db_version', '2900' );
335
  }
336
 
337
  /**
342
  * @since 3.0.6 'display_character_counter' option now correctly defaults to 1.
343
  * @since 3.1.0 Now only sets new options when defaults exist, and when it's an upgraded site.
344
  */
345
+ function _do_upgrade_3001() {
346
 
347
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3001' ) {
348
+ $tsf = \the_seo_framework();
349
 
350
+ $defaults = _upgrade_default_site_options();
351
 
352
  if ( isset( $defaults['timestamps_format'] ) ) {
353
  //= Only change if old option exists. Falls back to default upgrader otherwise.
354
  $sitemap_timestamps = $tsf->get_option( 'sitemap_timestamps', false );
355
  $tsf->update_option( 'timestamps_format', (string) (int) $sitemap_timestamps ?: $defaults['timestamps_format'] );
356
  if ( '' !== $sitemap_timestamps ) {
357
+ _add_upgrade_notice(
358
+ \esc_html__( 'The previous sitemap timestamp settings have been converted into new global timestamp settings.', 'autodescription' )
359
  );
360
  }
361
  }
367
  $tsf->update_option( 'display_pixel_counter', $defaults['display_pixel_counter'] );
368
  }
369
 
370
+ \update_option( 'the_seo_framework_upgraded_db_version', '3001' );
371
  }
372
 
373
  /**
376
  *
377
  * @since 3.0.6
378
  */
379
+ function _do_upgrade_3060() {
380
 
381
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3060' )
382
+ \the_seo_framework()->delete_cache( 'sitemap' );
383
 
384
+ \update_option( 'the_seo_framework_upgraded_db_version', '3060' );
385
  }
386
 
387
  /**
398
  *
399
  * @since 3.1.0
400
  */
401
+ function _do_upgrade_3103() {
402
 
403
  // Prevent database lookups when checking for cache.
404
+ \add_option( THE_SEO_FRAMEWORK_SITE_CACHE, [] );
405
 
406
  // If it's an older installation, upgrade these options.
407
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3103' ) {
408
+ $tsf = \the_seo_framework();
409
 
410
+ $defaults = _upgrade_default_site_options();
411
 
412
  // Transport title separator.
413
  if ( isset( $defaults['title_separator'] ) )
440
  $tsf->update_option( 'sitemaps_priority', 1 );
441
  }
442
 
443
+ \update_option( 'the_seo_framework_upgraded_db_version', '3103' );
444
  }
inc/classes/admin-pages.class.php CHANGED
@@ -184,7 +184,7 @@ class Admin_Pages extends Inpost {
184
  * @see $this->title_metabox() Callback for Title Settings box.
185
  * @see $this->description_metabox() Callback for Description Settings box.
186
  * @see $this->robots_metabox() Callback for Robots Settings box.
187
- * @see $this->homepage_metabox() Callback for Home Page Settings box.
188
  * @see $this->social_metabox() Callback for Social Settings box.
189
  * @see $this->schema_metabox() Callback for Schema Settings box.
190
  * @see $this->webmaster_metabox() Callback for Webmaster Settings box.
@@ -244,11 +244,11 @@ class Admin_Pages extends Inpost {
244
  []
245
  );
246
 
247
- //* Home Page Meta Box
248
  if ( $home )
249
  \add_meta_box(
250
  'autodescription-homepage-settings',
251
- \esc_html__( 'Home Page Settings', 'autodescription' ),
252
  [ $this, 'homepage_metabox' ],
253
  $this->seo_settings_page_hook,
254
  'main',
184
  * @see $this->title_metabox() Callback for Title Settings box.
185
  * @see $this->description_metabox() Callback for Description Settings box.
186
  * @see $this->robots_metabox() Callback for Robots Settings box.
187
+ * @see $this->homepage_metabox() Callback for Homepage Settings box.
188
  * @see $this->social_metabox() Callback for Social Settings box.
189
  * @see $this->schema_metabox() Callback for Schema Settings box.
190
  * @see $this->webmaster_metabox() Callback for Webmaster Settings box.
244
  []
245
  );
246
 
247
+ //* Homepage Meta Box
248
  if ( $home )
249
  \add_meta_box(
250
  'autodescription-homepage-settings',
251
+ \esc_html__( 'Homepage Settings', 'autodescription' ),
252
  [ $this, 'homepage_metabox' ],
253
  $this->seo_settings_page_hook,
254
  'main',
inc/classes/builders/scripts.class.php CHANGED
@@ -530,6 +530,7 @@ final class Scripts {
530
  * @see static::verify( $secret )
531
  *
532
  * @since 3.1.0
 
533
  * @uses static::$include_secret
534
  *
535
  * @param string $file The file location.
@@ -542,7 +543,7 @@ final class Scripts {
542
  unset( $_key, $_val, $args );
543
 
544
  //= Prevent private includes hijacking.
545
- static::$include_secret = $_secret = mt_rand() . uniqid();
546
  include $file;
547
  static::$include_secret = null;
548
  }
530
  * @see static::verify( $secret )
531
  *
532
  * @since 3.1.0
533
+ * @since 3.2.4 Enabled entropy to prevent system sleep.
534
  * @uses static::$include_secret
535
  *
536
  * @param string $file The file location.
543
  unset( $_key, $_val, $args );
544
 
545
  //= Prevent private includes hijacking.
546
+ static::$include_secret = $_secret = mt_rand() . uniqid( '', true );
547
  include $file;
548
  static::$include_secret = null;
549
  }
inc/classes/core.class.php CHANGED
@@ -222,8 +222,6 @@ class Core {
222
  */
223
  public function _add_plugin_action_links( $links = [] ) {
224
 
225
- $tsf_links = [];
226
-
227
  if ( $this->load_options )
228
  $tsf_links['settings'] = sprintf(
229
  '<a href="%s">%s</a>',
@@ -232,7 +230,7 @@ class Core {
232
  );
233
 
234
  $tsf_links['about'] = sprintf(
235
- '<a href="https://theseoframework.com/" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
236
  \esc_html__( 'About', 'autodescription' )
237
  );
238
  $tsf_links['tsfem'] = sprintf(
@@ -241,7 +239,49 @@ class Core {
241
  \esc_html_x( 'Extensions', 'Plugin extensions', 'autodescription' )
242
  );
243
 
244
- return array_merge( $links, $tsf_links );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  }
246
 
247
  /**
222
  */
223
  public function _add_plugin_action_links( $links = [] ) {
224
 
 
 
225
  if ( $this->load_options )
226
  $tsf_links['settings'] = sprintf(
227
  '<a href="%s">%s</a>',
230
  );
231
 
232
  $tsf_links['about'] = sprintf(
233
+ '<a href="https://theseoframework.com/about-us/" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
234
  \esc_html__( 'About', 'autodescription' )
235
  );
236
  $tsf_links['tsfem'] = sprintf(
239
  \esc_html_x( 'Extensions', 'Plugin extensions', 'autodescription' )
240
  );
241
 
242
+ return array_merge( $tsf_links, $links );
243
+ }
244
+
245
+ /**
246
+ * Adds more row meta on the plugin screen.
247
+ *
248
+ * @since 3.2.4
249
+ * @access private
250
+ *
251
+ * @param string[] $plugin_meta An array of the plugin's metadata,
252
+ * including the version, author,
253
+ * author URI, and plugin URI.
254
+ * @param string $plugin_file Path to the plugin file relative to the plugins directory.
255
+ * @return array $plugin_meta
256
+ */
257
+ public function _add_plugin_row_meta( $plugin_meta, $plugin_file ) {
258
+
259
+ if ( THE_SEO_FRAMEWORK_PLUGIN_BASENAME !== $plugin_file )
260
+ return $plugin_meta;
261
+
262
+ return array_merge( $plugin_meta, [
263
+ 'docs' => vsprintf(
264
+ '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
265
+ [
266
+ 'https://theseoframework.com/?p=80',
267
+ \esc_html__( 'View documentation', 'autodescription' ),
268
+ ]
269
+ ),
270
+ 'API' => vsprintf(
271
+ '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
272
+ [
273
+ 'https://theseoframework.com/?p=82',
274
+ \esc_html__( 'View API docs', 'autodescription' ),
275
+ ]
276
+ ),
277
+ 'EM' => vsprintf(
278
+ '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
279
+ [
280
+ 'https://theseoframework.com/?p=2760',
281
+ \esc_html_x( 'Get the Extension Manager', 'Extension Manager is a product name; do not translate', 'autodescription' ),
282
+ ]
283
+ ),
284
+ ] );
285
  }
286
 
287
  /**
inc/classes/deprecated.class.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  /**
3
- * @package The_SEO_Framework\Classes\Deprecated
 
4
  */
5
  namespace The_SEO_Framework;
6
 
1
  <?php
2
  /**
3
+ * @package The_SEO_Framework\Classes
4
+ * @subpackage Classes\Deprecated
5
  */
6
  namespace The_SEO_Framework;
7
 
inc/classes/detect.class.php CHANGED
@@ -288,7 +288,7 @@ class Detect extends Render {
288
  * @since 2.5.2
289
  *
290
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
291
- * @return boolean True if ALL functions classes and constants exists or false if plugin constant, class or function not detected.
292
  */
293
  public function detect_plugin_multi( array $plugins ) {
294
 
288
  * @since 2.5.2
289
  *
290
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
291
+ * @return bool True if ALL functions classes and constants exists or false if plugin constant, class or function not detected.
292
  */
293
  public function detect_plugin_multi( array $plugins ) {
294
 
inc/classes/doing-it-right.class.php CHANGED
@@ -571,10 +571,11 @@ class Doing_It_Right extends Generate_Ldjson {
571
  [
572
  $args['width'],
573
  vsprintf(
574
- '<span class="tsf-seo-bar-item tsf-tooltip-item %1$s" aria-label="%2$s" data-desc="%2$s">%3$s</span>',
575
  [
576
  $args['class'],
577
  $args['notice'],
 
578
  $args['indicator'],
579
  ]
580
  ),
571
  [
572
  $args['width'],
573
  vsprintf(
574
+ '<span class="tsf-seo-bar-item tsf-tooltip-item %s" data-desc="%s" aria-label="%s">%s</span>',
575
  [
576
  $args['class'],
577
  $args['notice'],
578
+ $this->strip_tags_cs( $args['notice'], [ 'clear' => 'br' ] ),
579
  $args['indicator'],
580
  ]
581
  ),
inc/classes/generate-description.class.php CHANGED
@@ -104,7 +104,7 @@ class Generate_Description extends Generate {
104
  * Falls back to meta description.
105
  *
106
  * @since 3.1.0
107
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
108
  * @see $this->get_open_graph_description()
109
  * @see $this->get_open_graph_description_from_custom_field()
110
  *
@@ -138,7 +138,7 @@ class Generate_Description extends Generate {
138
  * Falls back to meta description.
139
  *
140
  * @since 3.1.0
141
- * @since 3.2.2: 1. Now tests for the home page as page prior getting custom field data.
142
  * 2. Now obtains custom field data for terms.
143
  * @see $this->get_open_graph_description()
144
  * @see $this->get_open_graph_description_from_custom_field()
@@ -221,7 +221,7 @@ class Generate_Description extends Generate {
221
  * Falls back to Open Graph description.
222
  *
223
  * @since 3.1.0
224
- * @since 3.2.2: 1. Now tests for the home page as page prior getting custom field data.
225
  * 2. Now obtains custom field data for terms.
226
  * @see $this->get_twitter_description()
227
  * @see $this->get_twitter_description_from_custom_field()
@@ -260,7 +260,7 @@ class Generate_Description extends Generate {
260
  * Falls back to Open Graph description.
261
  *
262
  * @since 3.1.0
263
- * @since 3.2.2: 1. Now tests for the home page as page prior getting custom field data.
264
  * 2. Now obtains custom field data for terms.
265
  * @see $this->get_twitter_description()
266
  * @see $this->get_twitter_description_from_custom_field()
@@ -338,7 +338,7 @@ class Generate_Description extends Generate {
338
  * Gets a custom description, based on expected or current query, without escaping.
339
  *
340
  * @since 3.1.0
341
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
342
  * @internal
343
  * @see $this->get_description_from_custom_field()
344
  *
@@ -370,7 +370,7 @@ class Generate_Description extends Generate {
370
  * Gets a custom description, based on input arguments query, without escaping.
371
  *
372
  * @since 3.1.0
373
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
374
  * @internal
375
  * @see $this->get_description_from_custom_field()
376
  *
@@ -411,7 +411,6 @@ class Generate_Description extends Generate {
411
  * 2. Now no longer converts additions into excerpt when no excerpt is found.
412
  * @since 3.2.2 Now converts HTML characters prior trimming.
413
  * @uses $this->generate_description()
414
- * @staticvar array $cache
415
  *
416
  * @param array|null $args An array of 'id' and 'taxonomy' values.
417
  * Accepts int values for backward compatibility.
@@ -653,7 +652,7 @@ class Generate_Description extends Generate {
653
  * @since 3.1.0
654
  * @since 3.2.0 : 1. Now no longer listens to options.
655
  * 2. Now only works for the front and blog pages.
656
- * @since 3.2.2 Now works for home pages from external requests.
657
  * @see $this->get_generated_description()
658
  *
659
  * @param array|null $args An array of 'id' and 'taxonomy' values.
104
  * Falls back to meta description.
105
  *
106
  * @since 3.1.0
107
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
108
  * @see $this->get_open_graph_description()
109
  * @see $this->get_open_graph_description_from_custom_field()
110
  *
138
  * Falls back to meta description.
139
  *
140
  * @since 3.1.0
141
+ * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
142
  * 2. Now obtains custom field data for terms.
143
  * @see $this->get_open_graph_description()
144
  * @see $this->get_open_graph_description_from_custom_field()
221
  * Falls back to Open Graph description.
222
  *
223
  * @since 3.1.0
224
+ * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
225
  * 2. Now obtains custom field data for terms.
226
  * @see $this->get_twitter_description()
227
  * @see $this->get_twitter_description_from_custom_field()
260
  * Falls back to Open Graph description.
261
  *
262
  * @since 3.1.0
263
+ * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
264
  * 2. Now obtains custom field data for terms.
265
  * @see $this->get_twitter_description()
266
  * @see $this->get_twitter_description_from_custom_field()
338
  * Gets a custom description, based on expected or current query, without escaping.
339
  *
340
  * @since 3.1.0
341
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
342
  * @internal
343
  * @see $this->get_description_from_custom_field()
344
  *
370
  * Gets a custom description, based on input arguments query, without escaping.
371
  *
372
  * @since 3.1.0
373
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
374
  * @internal
375
  * @see $this->get_description_from_custom_field()
376
  *
411
  * 2. Now no longer converts additions into excerpt when no excerpt is found.
412
  * @since 3.2.2 Now converts HTML characters prior trimming.
413
  * @uses $this->generate_description()
 
414
  *
415
  * @param array|null $args An array of 'id' and 'taxonomy' values.
416
  * Accepts int values for backward compatibility.
652
  * @since 3.1.0
653
  * @since 3.2.0 : 1. Now no longer listens to options.
654
  * 2. Now only works for the front and blog pages.
655
+ * @since 3.2.2 Now works for homepages from external requests.
656
  * @see $this->get_generated_description()
657
  *
658
  * @param array|null $args An array of 'id' and 'taxonomy' values.
inc/classes/generate-ldjson.class.php CHANGED
@@ -150,7 +150,7 @@ class Generate_Ldjson extends Generate_Image {
150
  $output = $transient_name ? $this->get_transient( $transient_name ) : false;
151
  if ( false === $output ) :
152
  if ( $this->is_real_front_page() ) {
153
- //= Home page Schema.
154
  $output = '';
155
 
156
  $output .= $this->get_ld_json_website() ?: '';
@@ -364,7 +364,7 @@ class Generate_Ldjson extends Generate_Image {
364
  $items = [];
365
  $parents = array_reverse( \get_post_ancestors( $this->get_the_real_ID() ) );
366
 
367
- $position = 1; // 0 is the home page.
368
  foreach ( $parents as $parent_id ) {
369
 
370
  ++$position;
@@ -647,8 +647,8 @@ class Generate_Ldjson extends Generate_Image {
647
  * Generates homepage LD+JSON breadcrumb.
648
  *
649
  * @since 2.9.3
650
- * @since 3.2.2: 1. The title now works for the home page as blog.
651
- * 2. The image has been disabled for the home page as blog.
652
  * - I couldn't fix it without evading the API, which is bad.
653
  * @staticvar array $crumb
654
  *
150
  $output = $transient_name ? $this->get_transient( $transient_name ) : false;
151
  if ( false === $output ) :
152
  if ( $this->is_real_front_page() ) {
153
+ //= Homepage Schema.
154
  $output = '';
155
 
156
  $output .= $this->get_ld_json_website() ?: '';
364
  $items = [];
365
  $parents = array_reverse( \get_post_ancestors( $this->get_the_real_ID() ) );
366
 
367
+ $position = 1; // 0 is the homepage.
368
  foreach ( $parents as $parent_id ) {
369
 
370
  ++$position;
647
  * Generates homepage LD+JSON breadcrumb.
648
  *
649
  * @since 2.9.3
650
+ * @since 3.2.2: 1. The title now works for the homepage as blog.
651
+ * 2. The image has been disabled for the homepage as blog.
652
  * - I couldn't fix it without evading the API, which is bad.
653
  * @staticvar array $crumb
654
  *
inc/classes/generate-title.class.php CHANGED
@@ -28,6 +28,9 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
28
  *
29
  * Generates title SEO data based on content.
30
  *
 
 
 
31
  * @since 2.8.0
32
  */
33
  class Generate_Title extends Generate_Description {
@@ -98,6 +101,8 @@ class Generate_Title extends Generate_Description {
98
  * Returns the autogenerated meta title.
99
  *
100
  * @since 3.1.0
 
 
101
  * @uses $this->s_title_raw() : This is the same method used to prepare custom title on save.
102
  * @uses $this->build_generated_title()
103
  *
@@ -112,7 +117,7 @@ class Generate_Title extends Generate_Description {
112
  * Filters the title from query.
113
  *
114
  * @NOTE: This filter doesn't consistently run on the SEO Settings page.
115
- * You might want to avoid this filter on the home page.
116
  * @since 3.1.0
117
  * @param string $title The title.
118
  * @param array $args The title arguments.
@@ -122,16 +127,14 @@ class Generate_Title extends Generate_Description {
122
  $args,
123
  ] );
124
 
125
- $this->merge_title_protection( $title, $args );
126
- //? Only add protection if the query is autodetermined, and on a real page.
127
- if ( null === $args
128
- && ! ( $this->is_404() || $this->is_admin() ) ) {
129
  $this->merge_title_pagination( $title );
130
- }
131
 
132
- if ( $this->use_title_branding( $args ) ) {
133
  $this->merge_title_branding( $title, $args );
134
- }
135
 
136
  $title = $this->s_title_raw( $title );
137
 
@@ -187,7 +190,7 @@ class Generate_Title extends Generate_Description {
187
  * Falls back to Open Graph title.
188
  *
189
  * @since 3.1.0
190
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
191
  * @see $this->get_twitter_title()
192
  * @see $this->get_twitter_title_from_custom_field()
193
  *
@@ -223,7 +226,7 @@ class Generate_Title extends Generate_Description {
223
  * Falls back to Open Graph title.
224
  *
225
  * @since 3.1.0
226
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
227
  * @see $this->get_twitter_title()
228
  * @see $this->get_twitter_title_from_custom_field()
229
  *
@@ -324,7 +327,7 @@ class Generate_Title extends Generate_Description {
324
  * Falls back to meta title.
325
  *
326
  * @since 3.1.0
327
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
328
  * @see $this->get_open_graph_title()
329
  * @see $this->get_open_graph_title_from_custom_field()
330
  *
@@ -354,7 +357,7 @@ class Generate_Title extends Generate_Description {
354
  * Falls back to meta title.
355
  *
356
  * @since 3.1.0
357
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
358
  * @see $this->get_open_graph_title()
359
  * @see $this->get_open_graph_title_from_custom_field()
360
  *
@@ -430,7 +433,7 @@ class Generate_Title extends Generate_Description {
430
  * Gets a custom title, based on current query, without additions or prefixes.
431
  *
432
  * @since 3.1.0
433
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
434
  * @internal
435
  * @see $this->get_raw_custom_field_title()
436
  *
@@ -463,7 +466,7 @@ class Generate_Title extends Generate_Description {
463
  *
464
  * @since 3.1.0
465
  * @since 3.1.4 Now uses the 'id' to get custom singular title.
466
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
467
  * @internal
468
  * @see $this->get_raw_custom_field_title()
469
  *
@@ -1005,7 +1008,6 @@ class Generate_Title extends Generate_Description {
1005
  return compact( 'addition', 'seplocation' );
1006
  }
1007
 
1008
-
1009
  /**
1010
  * Returns the addition and seplocation from arguments.
1011
  *
@@ -1163,6 +1165,60 @@ class Generate_Title extends Generate_Description {
1163
  return $this->get_title_seplocation( true );
1164
  }
1165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1166
  /**
1167
  * Determines whether to add or remove title branding additions.
1168
  *
@@ -1254,7 +1310,7 @@ class Generate_Title extends Generate_Description {
1254
  }
1255
 
1256
  /**
1257
- * Determines whether to add home page tagline.
1258
  *
1259
  * @since 2.6.0
1260
  * @since 3.0.4 Now checks for custom tagline or blogname existence.
@@ -1278,7 +1334,7 @@ class Generate_Title extends Generate_Description {
1278
  }
1279
 
1280
  /**
1281
- * Returns the home page tagline from option or bloginfo, when set.
1282
  *
1283
  * @since 3.0.4
1284
  * @uses $this->get_blogdescription(), this method already trims.
28
  *
29
  * Generates title SEO data based on content.
30
  *
31
+ * NOTE: Don't supply $args in any of the methods for non-term taxomies, like author archives.
32
+ * ID collision isn't accounted for in these scenarios.
33
+ *
34
  * @since 2.8.0
35
  */
36
  class Generate_Title extends Generate_Description {
101
  * Returns the autogenerated meta title.
102
  *
103
  * @since 3.1.0
104
+ * @since 3.x.x 1. Added check for title protection.
105
+ * 2. Moved check for title pagination.
106
  * @uses $this->s_title_raw() : This is the same method used to prepare custom title on save.
107
  * @uses $this->build_generated_title()
108
  *
117
  * Filters the title from query.
118
  *
119
  * @NOTE: This filter doesn't consistently run on the SEO Settings page.
120
+ * You might want to avoid this filter on the homepage.
121
  * @since 3.1.0
122
  * @param string $title The title.
123
  * @param array $args The title arguments.
127
  $args,
128
  ] );
129
 
130
+ if ( $this->use_title_protection( $args ) )
131
+ $this->merge_title_protection( $title, $args );
132
+
133
+ if ( $this->use_title_pagination( $args ) )
134
  $this->merge_title_pagination( $title );
 
135
 
136
+ if ( $this->use_title_branding( $args ) )
137
  $this->merge_title_branding( $title, $args );
 
138
 
139
  $title = $this->s_title_raw( $title );
140
 
190
  * Falls back to Open Graph title.
191
  *
192
  * @since 3.1.0
193
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
194
  * @see $this->get_twitter_title()
195
  * @see $this->get_twitter_title_from_custom_field()
196
  *
226
  * Falls back to Open Graph title.
227
  *
228
  * @since 3.1.0
229
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
230
  * @see $this->get_twitter_title()
231
  * @see $this->get_twitter_title_from_custom_field()
232
  *
327
  * Falls back to meta title.
328
  *
329
  * @since 3.1.0
330
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
331
  * @see $this->get_open_graph_title()
332
  * @see $this->get_open_graph_title_from_custom_field()
333
  *
357
  * Falls back to meta title.
358
  *
359
  * @since 3.1.0
360
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
361
  * @see $this->get_open_graph_title()
362
  * @see $this->get_open_graph_title_from_custom_field()
363
  *
433
  * Gets a custom title, based on current query, without additions or prefixes.
434
  *
435
  * @since 3.1.0
436
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
437
  * @internal
438
  * @see $this->get_raw_custom_field_title()
439
  *
466
  *
467
  * @since 3.1.0
468
  * @since 3.1.4 Now uses the 'id' to get custom singular title.
469
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
470
  * @internal
471
  * @see $this->get_raw_custom_field_title()
472
  *
1008
  return compact( 'addition', 'seplocation' );
1009
  }
1010
 
 
1011
  /**
1012
  * Returns the addition and seplocation from arguments.
1013
  *
1165
  return $this->get_title_seplocation( true );
1166
  }
1167
 
1168
+ /**
1169
+ * Determines whether to add or remove title protection prefixes.
1170
+ *
1171
+ * NOTE: This does not guarantee that protection is to be added.
1172
+ *
1173
+ * @since 3.x.x
1174
+ * @see $this->merge_title_protection()
1175
+ *
1176
+ * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
1177
+ * Leave null to autodetermine query.
1178
+ * @return bool True when prefixes are allowed.
1179
+ */
1180
+ public function use_title_protection( $args = null ) {
1181
+
1182
+ if ( null === $args ) {
1183
+ $use = $this->is_singular();
1184
+ } else {
1185
+ $this->fix_generation_args( $args );
1186
+ $use = $args && ! $args['taxonomy'];
1187
+ }
1188
+
1189
+ return $use;
1190
+ }
1191
+
1192
+ /**
1193
+ * Determines whether to add or remove title pagination additions.
1194
+ *
1195
+ * NOTE: This does not guarantee that pagination is to be added.
1196
+ * @see $this->paged()
1197
+ * @see $this->page()
1198
+ *
1199
+ * @since 3.x.x
1200
+ * @see $this->merge_title_pagination()
1201
+ *
1202
+ * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
1203
+ * Leave null to autodetermine query.
1204
+ * @return bool True when additions are allowed.
1205
+ */
1206
+ public function use_title_pagination( $args = null ) {
1207
+
1208
+ //? Only add pagination if the query is autodetermined, and on a real page.
1209
+ if ( null === $args ) {
1210
+ if ( $this->is_404() || $this->is_admin() ) {
1211
+ $use = false;
1212
+ } else {
1213
+ $use = true;
1214
+ }
1215
+ } else {
1216
+ $use = false;
1217
+ }
1218
+
1219
+ return $use;
1220
+ }
1221
+
1222
  /**
1223
  * Determines whether to add or remove title branding additions.
1224
  *
1310
  }
1311
 
1312
  /**
1313
+ * Determines whether to add homepage tagline.
1314
  *
1315
  * @since 2.6.0
1316
  * @since 3.0.4 Now checks for custom tagline or blogname existence.
1334
  }
1335
 
1336
  /**
1337
+ * Returns the homepage tagline from option or bloginfo, when set.
1338
  *
1339
  * @since 3.0.4
1340
  * @uses $this->get_blogdescription(), this method already trims.
inc/classes/generate-url.class.php CHANGED
@@ -32,6 +32,37 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
32
  */
33
  class Generate_Url extends Generate_Title {
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  /**
36
  * Caches and returns the current URL.
37
  *
@@ -49,6 +80,8 @@ class Generate_Url extends Generate_Title {
49
  * Caches and returns the current permalink.
50
  * This link excludes any pagination. Great for structured data.
51
  *
 
 
52
  * @since 3.0.0
53
  * @since 3.1.0 Now properly generates taxonomical URLs.
54
  * @staticvar string $cache
@@ -106,6 +139,7 @@ class Generate_Url extends Generate_Title {
106
 
107
  /**
108
  * Returns the current canonical URL.
 
109
  *
110
  * @since 3.0.0
111
  * @see $this->create_canonical_url()
@@ -142,7 +176,7 @@ class Generate_Url extends Generate_Title {
142
  * Builds canonical URL from input arguments.
143
  *
144
  * @since 3.0.0
145
- * @since 3.2.2 Now tests for the home page as page prior getting custom field data.
146
  * @see $this->create_canonical_url()
147
  *
148
  * @param array $args. Use $this->create_canonical_url().
@@ -196,7 +230,6 @@ class Generate_Url extends Generate_Title {
196
  $url = $this->get_home_canonical_url();
197
  } elseif ( $this->is_singular() ) {
198
  $url = $this->get_singular_custom_canonical_url( $id );
199
-
200
  if ( ! $url )
201
  $url = $this->get_singular_canonical_url( $id );
202
  } elseif ( $this->is_archive() ) {
@@ -248,6 +281,9 @@ class Generate_Url extends Generate_Title {
248
  * Automatically adds pagination if the ID matches the query.
249
  *
250
  * @since 3.0.0
 
 
 
251
  *
252
  * @return string The home canonical URL.
253
  */
@@ -256,15 +292,31 @@ class Generate_Url extends Generate_Title {
256
  //= Prevent admin bias by passing preferred scheme.
257
  $url = \get_home_url( null, '', $this->get_preferred_scheme() );
258
 
259
- if ( $url ) {
260
- if ( $this->get_the_real_ID() === (int) \get_option( 'page_for_posts' ) ) {
261
- $url = $this->add_url_pagination( $url, $this->paged(), true );
 
 
 
 
 
262
  }
 
 
 
263
 
264
- return \user_trailingslashit( $url );
 
 
 
 
 
 
 
 
265
  }
266
 
267
- return '';
268
  }
269
 
270
  /**
@@ -281,34 +333,30 @@ class Generate_Url extends Generate_Title {
281
 
282
  /**
283
  * Returns singular canonical URL.
284
- * Automatically adds pagination if the ID matches the query.
285
- *
286
- * Prevents SEO attacks regarding pagination.
287
  *
288
  * @since 3.0.0
289
  * @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
 
290
  *
291
  * @param int|null $id The page ID.
292
  * @return string The custom canonical URL, if any.
293
  */
294
  public function get_singular_canonical_url( $id = null ) {
295
 
296
- $canonical_url = \wp_get_canonical_url( $id );
297
 
298
- if ( ! $canonical_url )
299
- return '';
300
-
301
- //* @link https://core.trac.wordpress.org/ticket/37505
302
- $_page = \get_query_var( 'page', 0 );
303
- if ( $_page !== $this->page() ) {
304
- $canonical_url = $this->remove_pagination_from_url( $canonical_url, $_page );
305
  }
306
- $_paged = \get_query_var( 'paged', 0 );
307
- if ( $_paged === $this->paged() ) {
308
- $canonical_url = $this->add_url_pagination( $canonical_url, $_paged, true );
 
309
  }
310
 
311
- return $canonical_url;
312
  }
313
 
314
  /**
@@ -461,7 +509,7 @@ class Generate_Url extends Generate_Title {
461
  $_paginate = false;
462
 
463
  if ( ! isset( $query ) ) {
464
- $query = \get_search_query( false );
465
  $_paginate = true;
466
  }
467
 
@@ -572,31 +620,50 @@ class Generate_Url extends Generate_Title {
572
  * Adds pagination to input URL.
573
  *
574
  * @since 3.0.0
 
 
575
  *
576
  * @param string $url The fully qualified URL.
577
  * @param int $page The page number. Should be bigger than 1 to paginate.
578
- * @param bool $use_base Whether to use pagination base. True on archives, false on pages.
 
 
 
579
  * @return string The fully qualified URL with pagination.
580
  */
581
- public function add_url_pagination( $url, $page, $use_base ) {
 
 
582
 
583
- if ( $page < 2 )
584
  return $url;
585
 
 
 
 
586
  if ( $this->pretty_permalinks ) {
587
- if ( $use_base ) {
588
- static $base;
589
- $base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
590
 
591
- $url = \user_trailingslashit( \trailingslashit( $url ) . $base . '/' . $page, 'single_paged' );
 
 
 
 
 
 
 
 
 
592
  } else {
593
- $url = \user_trailingslashit( \trailingslashit( $url ) . $page, 'single_paged' );
594
  }
 
 
 
595
  } else {
596
- if ( $use_base ) {
597
- $url = \add_query_arg( 'paged', $page, $url );
598
  } else {
599
- $url = \add_query_arg( 'page', $page, $url );
600
  }
601
  }
602
 
@@ -605,44 +672,59 @@ class Generate_Url extends Generate_Title {
605
 
606
  /**
607
  * Removes pagination from input URL.
608
- * The URL must match this query.
609
  *
610
  * @since 3.0.0
611
- *
612
- * @param string $url The fully qualified URL to remove pagination from.
613
- * @param int $page The page number to remove. If empty, it will get query.
614
- * @param int $paged The page number to remove. If empty, it will get query.
 
 
 
 
 
 
 
 
615
  * @return string $url The fully qualified URL without pagination.
616
  */
617
- protected function remove_pagination_from_url( $url, $page = 0, $paged = 0 ) {
618
 
619
  if ( $this->pretty_permalinks ) {
620
  //* Defensive programming...
621
- static $user_slash;
622
  $user_slash = isset( $user_slash ) ? $user_slash :
623
  ( $GLOBALS['wp_rewrite']->use_trailing_slashes ? '/' : '' );
 
624
 
625
- $paged = $paged ?: $this->paged();
626
- $page = $page ?: $this->page();
627
 
628
- $find = '';
 
 
629
 
630
- if ( $paged > 1 ) {
631
- static $base;
632
- $base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
 
 
633
 
634
- $find = '/' . $base . '/' . $paged . $user_slash;
635
- } elseif ( $page > 1 ) {
636
- $find = '/' . $page . $user_slash;
637
- }
638
 
639
- if ( $find ) {
640
  $pos = strrpos( $url, $find );
641
- //* Defensive programming...
642
  $continue = $pos && $pos + strlen( $find ) === strlen( $url );
 
643
  if ( $continue ) {
644
  $url = substr( $url, 0, $pos );
645
  $url = \user_trailingslashit( $url );
 
 
 
646
  }
647
  }
648
  } else {
@@ -656,6 +738,7 @@ class Generate_Url extends Generate_Title {
656
  * Adjusts category post link.
657
  *
658
  * @since 3.0.0
 
659
  *
660
  * @param \WP_Term $term The category to use in the permalink.
661
  * @param array $terms Array of all categories (WP_Term objects) associated with the post.
@@ -764,20 +847,25 @@ class Generate_Url extends Generate_Title {
764
  * Generates Previous and Next links.
765
  *
766
  * @since 3.1.0
767
- * @staticvar array $ret
 
 
768
  *
769
- * @param string $prev_next Whether to get the previous or next page link.
770
- * Accepts 'prev' and 'next'.
771
- * @return array Escaped site Pagination URL
 
772
  */
773
  public function get_paged_urls() {
774
 
775
- static $ret;
776
- if ( isset( $ret ) ) return $ret;
777
 
778
  $prev = $next = '';
779
  $_run = false;
780
 
 
 
781
  if ( $this->is_singular() && ! $this->is_singular_archive() && $this->is_multipage() ) {
782
  $_run = $this->is_real_front_page()
783
  ? $this->get_option( 'prev_next_frontpage' )
@@ -785,7 +873,6 @@ class Generate_Url extends Generate_Title {
785
 
786
  if ( ! $_run ) goto end;
787
 
788
- $archive = false;
789
  $page = $this->page();
790
  $_numpages = $this->numpages();
791
  } elseif ( $this->is_real_front_page() || $this->is_archive() || $this->is_singular_archive() || $this->is_search() ) {
@@ -795,27 +882,26 @@ class Generate_Url extends Generate_Title {
795
 
796
  if ( ! $_run ) goto end;
797
 
798
- $archive = true;
799
  $page = $this->paged();
800
  $_numpages = $this->numpages();
 
 
801
  }
802
 
803
- if ( ! $_run ) goto end;
804
-
805
  $canonical = $this->remove_pagination_from_url( $this->get_current_canonical_url() );
806
 
807
  // If this page is not the last, create a next-URL.
808
  if ( $page + 1 <= $_numpages ) {
809
- $next = $this->add_url_pagination( $canonical, $page + 1, $archive );
810
  }
811
  // If this page is not the first, create a prev-URL.
812
  if ( $page > 1 ) {
813
- $prev = $this->add_url_pagination( $canonical, $page - 1, $archive );
814
  }
815
 
816
  end:;
817
 
818
- return $ret = compact( 'next', 'prev' );
819
  }
820
 
821
  /**
32
  */
33
  class Generate_Url extends Generate_Title {
34
 
35
+ /**
36
+ * Determines if the given page has a custom canonical URL.
37
+ *
38
+ * @since 3.2.4
39
+ *
40
+ * @param null|array $args The canonical URL arguments, leave null to autodetermine query : {
41
+ * int $id The Post, Page or Term ID to generate the URL for.
42
+ * string $taxonomy The taxonomy.
43
+ * }
44
+ * @return bool
45
+ */
46
+ public function has_custom_canonical_url( $args = null ) {
47
+
48
+ if ( ! $args ) {
49
+ if ( $this->is_singular() ) {
50
+ $has = $this->get_singular_custom_canonical_url( $this->get_the_real_ID() );
51
+ } else {
52
+ $has = false;
53
+ }
54
+ } else {
55
+ $this->fix_generation_args( $args );
56
+ if ( ! $args || $args['taxonomy'] ) {
57
+ $has = false;
58
+ } else {
59
+ $has = $this->get_singular_custom_canonical_url( $args['id'] );
60
+ }
61
+ }
62
+
63
+ return (bool) $has;
64
+ }
65
+
66
  /**
67
  * Caches and returns the current URL.
68
  *
80
  * Caches and returns the current permalink.
81
  * This link excludes any pagination. Great for structured data.
82
  *
83
+ * Does not work for unregistered pages, like search, 404, date, author, and CPTA.
84
+ *
85
  * @since 3.0.0
86
  * @since 3.1.0 Now properly generates taxonomical URLs.
87
  * @staticvar string $cache
139
 
140
  /**
141
  * Returns the current canonical URL.
142
+ * Removes pagination if the URL isn't obtained via the query.
143
  *
144
  * @since 3.0.0
145
  * @see $this->create_canonical_url()
176
  * Builds canonical URL from input arguments.
177
  *
178
  * @since 3.0.0
179
+ * @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
180
  * @see $this->create_canonical_url()
181
  *
182
  * @param array $args. Use $this->create_canonical_url().
230
  $url = $this->get_home_canonical_url();
231
  } elseif ( $this->is_singular() ) {
232
  $url = $this->get_singular_custom_canonical_url( $id );
 
233
  if ( ! $url )
234
  $url = $this->get_singular_canonical_url( $id );
235
  } elseif ( $this->is_archive() ) {
281
  * Automatically adds pagination if the ID matches the query.
282
  *
283
  * @since 3.0.0
284
+ * @since 3.2.4 1. Now adds a slash to the home URL when it's a root URL.
285
+ * 2. Now skips slashing when queries have been appended to the URL.
286
+ * 3. Home-as-page pagination is now supported.
287
  *
288
  * @return string The home canonical URL.
289
  */
292
  //= Prevent admin bias by passing preferred scheme.
293
  $url = \get_home_url( null, '', $this->get_preferred_scheme() );
294
 
295
+ if ( ! $url ) return '';
296
+
297
+ $query_id = $this->get_the_real_ID();
298
+
299
+ if ( $this->has_page_on_front() ) {
300
+ if ( $this->is_static_frontpage( $query_id ) ) {
301
+ // Yes, use the pagination base for the homepage-as-page!
302
+ $url = $this->add_url_pagination( $url, $this->page(), true );
303
  }
304
+ } elseif ( (int) \get_option( 'page_for_posts' ) === $query_id ) {
305
+ $url = $this->add_url_pagination( $url, $this->paged(), true );
306
+ }
307
 
308
+ $parsed = parse_url( $url );
309
+
310
+ // Don't slash the home URL if it's been modified by a (translation) plugin.
311
+ if ( ! isset( $parsed['query'] ) ) {
312
+ if ( isset( $parsed['path'] ) && '/' !== $parsed['path'] ) {
313
+ $url = \user_trailingslashit( $url, 'home' );
314
+ } else {
315
+ $url = \trailingslashit( $url );
316
+ }
317
  }
318
 
319
+ return $url;
320
  }
321
 
322
  /**
333
 
334
  /**
335
  * Returns singular canonical URL.
 
 
 
336
  *
337
  * @since 3.0.0
338
  * @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
339
+ * @since 3.2.4 Removed pagination support for singular posts, as the SEO attack is now mitigated via WordPress.
340
  *
341
  * @param int|null $id The page ID.
342
  * @return string The custom canonical URL, if any.
343
  */
344
  public function get_singular_canonical_url( $id = null ) {
345
 
346
+ $url = \wp_get_canonical_url( $id ) ?: '';
347
 
348
+ $_page = \get_query_var( 'page', 1 ) ?: 1; // WP_Query tests isset, not empty.
349
+ if ( $url && $_page !== $this->page() ) {
350
+ /** @link https://core.trac.wordpress.org/ticket/37505 */
351
+ $url = $this->remove_pagination_from_url( $url, $_page, false );
 
 
 
352
  }
353
+
354
+ if ( $url && $this->is_singular_archive() ) {
355
+ // Singular archives, like blog pages and shop pages, use the pagination base with paged.
356
+ $url = $this->add_url_pagination( $url, $this->paged(), true );
357
  }
358
 
359
+ return $url;
360
  }
361
 
362
  /**
509
  $_paginate = false;
510
 
511
  if ( ! isset( $query ) ) {
512
+ $query = \get_search_query( false );
513
  $_paginate = true;
514
  }
515
 
620
  * Adds pagination to input URL.
621
  *
622
  * @since 3.0.0
623
+ * @since 3.2.4 1. Now considers query arguments when using pretty permalinks.
624
+ * 2. The second and third parameters are now optional.
625
  *
626
  * @param string $url The fully qualified URL.
627
  * @param int $page The page number. Should be bigger than 1 to paginate.
628
+ * @param bool $use_base Whether to use pagination base.
629
+ * If null, it will autodetermine.
630
+ * Should be true on archives and the homepage (blog and static!).
631
+ * False on singular post types.
632
  * @return string The fully qualified URL with pagination.
633
  */
634
+ public function add_url_pagination( $url, $page = null, $use_base = null ) {
635
+
636
+ $_page = isset( $page ) ? $page : max( $this->paged(), $this->page() );
637
 
638
+ if ( $_page < 2 )
639
  return $url;
640
 
641
+ $_use_base = isset( $use_base ) ? $use_base :
642
+ $this->is_archive() || $this->is_real_front_page() || $this->is_singular_archive();
643
+
644
  if ( $this->pretty_permalinks ) {
 
 
 
645
 
646
+ $_query = parse_url( $url, PHP_URL_QUERY );
647
+ // Remove queries, add them back later.
648
+ if ( $_query )
649
+ $url = $this->s_url( $url );
650
+
651
+ static $base;
652
+ $base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
653
+
654
+ if ( $_use_base ) {
655
+ $url = \user_trailingslashit( \trailingslashit( $url ) . $base . '/' . $_page, 'paged' );
656
  } else {
657
+ $url = \user_trailingslashit( \trailingslashit( $url ) . $_page, 'single_paged' );
658
  }
659
+
660
+ if ( $_query )
661
+ $url = $this->append_php_query( $url, $_query );
662
  } else {
663
+ if ( $_use_base ) {
664
+ $url = \add_query_arg( 'paged', $_page, $url );
665
  } else {
666
+ $url = \add_query_arg( 'page', $_page, $url );
667
  }
668
  }
669
 
672
 
673
  /**
674
  * Removes pagination from input URL.
675
+ * The URL must match this query if no second parameter is provided.
676
  *
677
  * @since 3.0.0
678
+ * @since 3.2.4 1. Now correctly removes the pagination base on singular post types.
679
+ * 2. The second parameter now accepts null or a value.
680
+ * 3. The third parameter is now changed to $use_base, from the archive pagination number.
681
+ * 4. Now supports pretty permalinks with query parameters.
682
+ * 5. Is now public.
683
+ *
684
+ * @param string $url The fully qualified URL to remove pagination from.
685
+ * @param int|null $page The page number to remove. If null, it will get number from query.
686
+ * @param bool|null $use_base Whether to remove the pagination base.
687
+ * If null, it will autodetermine.
688
+ * Should be true on archives and the homepage (blog and static!).
689
+ * False on singular post types.
690
  * @return string $url The fully qualified URL without pagination.
691
  */
692
+ public function remove_pagination_from_url( $url, $page = null, $use_base = null ) {
693
 
694
  if ( $this->pretty_permalinks ) {
695
  //* Defensive programming...
696
+ static $user_slash, $base;
697
  $user_slash = isset( $user_slash ) ? $user_slash :
698
  ( $GLOBALS['wp_rewrite']->use_trailing_slashes ? '/' : '' );
699
+ $base = isset( $base ) ? $base : $GLOBALS['wp_rewrite']->pagination_base;
700
 
701
+ $_page = isset( $page ) ? $page : max( $this->paged(), $this->page() );
 
702
 
703
+ if ( $_page > 1 ) {
704
+ $_use_base = isset( $use_base ) ? $use_base
705
+ : $this->is_archive() || $this->is_real_front_page() || $this->is_singular_archive();
706
 
707
+ if ( $_use_base ) {
708
+ $find = '/' . $base . '/' . $_page . $user_slash;
709
+ } else {
710
+ $find = '/' . $_page . $user_slash;
711
+ }
712
 
713
+ $_query = parse_url( $url, PHP_URL_QUERY );
714
+ // Remove queries, add them back later.
715
+ if ( $_query )
716
+ $url = $this->s_url( $url );
717
 
 
718
  $pos = strrpos( $url, $find );
719
+ //* Defensive programming, only remove if $find matches the stack length, without query arguments.
720
  $continue = $pos && $pos + strlen( $find ) === strlen( $url );
721
+
722
  if ( $continue ) {
723
  $url = substr( $url, 0, $pos );
724
  $url = \user_trailingslashit( $url );
725
+
726
+ if ( $_query )
727
+ $url = $this->append_php_query( $url, $_query );
728
  }
729
  }
730
  } else {
738
  * Adjusts category post link.
739
  *
740
  * @since 3.0.0
741
+ * @access private
742
  *
743
  * @param \WP_Term $term The category to use in the permalink.
744
  * @param array $terms Array of all categories (WP_Term objects) associated with the post.
847
  * Generates Previous and Next links.
848
  *
849
  * @since 3.1.0
850
+ * @since 3.2.4 1. Now correctly removes the pagination base from singular URLs.
851
+ * 2. Now returns no URLs when a custom canonical URL is set.
852
+ * @staticvar array $cache
853
  *
854
+ * @return array Escaped site Pagination URLs: {
855
+ * string 'prev'
856
+ * string 'next'
857
+ * }
858
  */
859
  public function get_paged_urls() {
860
 
861
+ static $cache;
862
+ if ( isset( $cache ) ) return $cache;
863
 
864
  $prev = $next = '';
865
  $_run = false;
866
 
867
+ if ( $this->has_custom_canonical_url() ) goto end;
868
+
869
  if ( $this->is_singular() && ! $this->is_singular_archive() && $this->is_multipage() ) {
870
  $_run = $this->is_real_front_page()
871
  ? $this->get_option( 'prev_next_frontpage' )
873
 
874
  if ( ! $_run ) goto end;
875
 
 
876
  $page = $this->page();
877
  $_numpages = $this->numpages();
878
  } elseif ( $this->is_real_front_page() || $this->is_archive() || $this->is_singular_archive() || $this->is_search() ) {
882
 
883
  if ( ! $_run ) goto end;
884
 
 
885
  $page = $this->paged();
886
  $_numpages = $this->numpages();
887
+ } else {
888
+ goto end;
889
  }
890
 
 
 
891
  $canonical = $this->remove_pagination_from_url( $this->get_current_canonical_url() );
892
 
893
  // If this page is not the last, create a next-URL.
894
  if ( $page + 1 <= $_numpages ) {
895
+ $next = $this->add_url_pagination( $canonical, $page + 1 );
896
  }
897
  // If this page is not the first, create a prev-URL.
898
  if ( $page > 1 ) {
899
+ $prev = $this->add_url_pagination( $canonical, $page - 1 );
900
  }
901
 
902
  end:;
903
 
904
+ return $cache = compact( 'next', 'prev' );
905
  }
906
 
907
  /**
inc/classes/generate.class.php CHANGED
@@ -81,7 +81,7 @@ class Generate extends User_Data {
81
  'noarchive' => $this->get_option( 'site_noarchive' ) ? 'noarchive' : '',
82
  ];
83
 
84
- //* Check home page SEO settings, set noindex, nofollow and noarchive
85
  if ( $this->is_real_front_page() ) {
86
  $meta['noindex'] = $this->get_option( 'homepage_noindex' ) ? 'noindex' : $meta['noindex'];
87
  $meta['nofollow'] = $this->get_option( 'homepage_nofollow' ) ? 'nofollow' : $meta['nofollow'];
@@ -95,7 +95,7 @@ class Generate extends User_Data {
95
 
96
  /**
97
  * Check for 404, or if archive is empty: set noindex for those.
98
- * Don't check this on the home page. The home page is sacred in this regard,
99
  * because page builders and templates likely take over.
100
  * @since 2.2.8
101
  *
81
  'noarchive' => $this->get_option( 'site_noarchive' ) ? 'noarchive' : '',
82
  ];
83
 
84
+ //* Check homepage SEO settings, set noindex, nofollow and noarchive
85
  if ( $this->is_real_front_page() ) {
86
  $meta['noindex'] = $this->get_option( 'homepage_noindex' ) ? 'noindex' : $meta['noindex'];
87
  $meta['nofollow'] = $this->get_option( 'homepage_nofollow' ) ? 'nofollow' : $meta['nofollow'];
95
 
96
  /**
97
  * Check for 404, or if archive is empty: set noindex for those.
98
+ * Don't check this on the homepage. The homepage is sacred in this regard,
99
  * because page builders and templates likely take over.
100
  * @since 2.2.8
101
  *
inc/classes/init.class.php CHANGED
@@ -160,6 +160,7 @@ class Init extends Query {
160
 
161
  //* Add plugin links to the plugin activation page.
162
  \add_filter( 'plugin_action_links_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, [ $this, '_add_plugin_action_links' ], 10, 2 );
 
163
 
164
  //* Initialize post states.
165
  \add_action( 'current_screen', [ $this, 'post_state' ] );
160
 
161
  //* Add plugin links to the plugin activation page.
162
  \add_filter( 'plugin_action_links_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, [ $this, '_add_plugin_action_links' ], 10, 2 );
163
+ \add_filter( 'plugin_row_meta', [ $this, '_add_plugin_row_meta' ], 10, 2 );
164
 
165
  //* Initialize post states.
166
  \add_action( 'current_screen', [ $this, 'post_state' ] );
inc/classes/metaboxes.class.php CHANGED
@@ -360,7 +360,7 @@ class Metaboxes extends Site_Options {
360
  }
361
 
362
  /**
363
- * Home Page meta box on the Site SEO Settings page.
364
  *
365
  * @since 2.2.2
366
  *
@@ -380,44 +380,44 @@ class Metaboxes extends Site_Options {
380
  }
381
 
382
  /**
383
- * HomePage Metabox General Tab Output.
384
  *
385
  * @since 2.7.0
386
  * @since 3.1.0 Is now protected.
387
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
388
  */
389
  protected function homepage_metabox_general_tab() {
390
  $this->get_view( 'metaboxes/homepage-metabox', [], 'general' );
391
  }
392
 
393
  /**
394
- * HomePage Metabox Additions Tab Output.
395
  *
396
  * @since 2.7.0
397
  * @since 3.1.0 Is now protected.
398
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
399
  */
400
  protected function homepage_metabox_additions_tab() {
401
  $this->get_view( 'metaboxes/homepage-metabox', [], 'additions' );
402
  }
403
 
404
  /**
405
- * HomePage Metabox Robots Tab Output
406
  *
407
  * @since 2.7.0
408
  * @since 3.1.0 Is now protected.
409
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
410
  */
411
  protected function homepage_metabox_robots_tab() {
412
  $this->get_view( 'metaboxes/homepage-metabox', [], 'robots' );
413
  }
414
 
415
  /**
416
- * HomePage Metabox Social Tab Output
417
  *
418
  * @since 2.9.0
419
  * @since 3.1.0 Is now protected.
420
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
421
  */
422
  protected function homepage_metabox_social_tab() {
423
  $this->get_view( 'metaboxes/homepage-metabox', [], 'social' );
360
  }
361
 
362
  /**
363
+ * Outputs the Homepage meta box on the Site SEO Settings page.
364
  *
365
  * @since 2.2.2
366
  *
380
  }
381
 
382
  /**
383
+ * Homepage Metabox General Tab Output.
384
  *
385
  * @since 2.7.0
386
  * @since 3.1.0 Is now protected.
387
+ * @see $this->homepage_metabox() Callback for Homepage Settings box.
388
  */
389
  protected function homepage_metabox_general_tab() {
390
  $this->get_view( 'metaboxes/homepage-metabox', [], 'general' );
391
  }
392
 
393
  /**
394
+ * Homepage Metabox Additions Tab Output.
395
  *
396
  * @since 2.7.0
397
  * @since 3.1.0 Is now protected.
398
+ * @see $this->homepage_metabox() Callback for Homepage Settings box.
399
  */
400
  protected function homepage_metabox_additions_tab() {
401
  $this->get_view( 'metaboxes/homepage-metabox', [], 'additions' );
402
  }
403
 
404
  /**
405
+ * Homepage Metabox Robots Tab Output
406
  *
407
  * @since 2.7.0
408
  * @since 3.1.0 Is now protected.
409
+ * @see $this->homepage_metabox() Callback for Homepage Settings box.
410
  */
411
  protected function homepage_metabox_robots_tab() {
412
  $this->get_view( 'metaboxes/homepage-metabox', [], 'robots' );
413
  }
414
 
415
  /**
416
+ * Homepage Metabox Social Tab Output
417
  *
418
  * @since 2.9.0
419
  * @since 3.1.0 Is now protected.
420
+ * @see $this->homepage_metabox() Callback for Homepage Settings box.
421
  */
422
  protected function homepage_metabox_social_tab() {
423
  $this->get_view( 'metaboxes/homepage-metabox', [], 'social' );
inc/classes/query.class.php CHANGED
@@ -629,16 +629,16 @@ class Query extends Compat {
629
  /**
630
  * Checks for front page by input ID.
631
  *
632
- * Doesn't always return true when the ID is 0, although the home page might be.
633
  * This is because it checks for the query, to prevent conflicts.
634
  * @see $this->is_real_front_page_by_id().
635
  *
636
  * @since 2.9.0
637
- * @since 2.9.3 Now tests for archive and 404 before testing home page as blog.
638
  * @since 3.2.2: Removed SEO settings page check. This now returns false on that page.
639
  *
640
  * @param int The page ID, required. Can be 0.
641
- * @return bool True if ID if for the home page.
642
  */
643
  public function is_front_page_by_id( $id ) {
644
 
@@ -681,7 +681,7 @@ class Query extends Compat {
681
  }
682
 
683
  /**
684
- * Detects home page.
685
  *
686
  * @since 2.6.0
687
  * @staticvar bool $cache
@@ -1123,6 +1123,8 @@ class Query extends Compat {
1123
  * Fetches global $page through Query Var to prevent conflicts.
1124
  *
1125
  * @since 2.6.0
 
 
1126
  *
1127
  * @return int (R>0) $page Always a positive number.
1128
  */
@@ -1131,11 +1133,20 @@ class Query extends Compat {
1131
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1132
  return $cache;
1133
 
1134
- $page = $this->is_multipage() ? \get_query_var( 'page' ) : 1;
 
 
 
 
 
 
 
 
 
1135
 
1136
  $this->set_query_cache(
1137
  __METHOD__,
1138
- $page = $page ? (int) $page : 1
1139
  );
1140
 
1141
  return $page;
@@ -1146,6 +1157,8 @@ class Query extends Compat {
1146
  * Fetches global $paged through Query var to prevent conflicts.
1147
  *
1148
  * @since 2.6.0
 
 
1149
  *
1150
  * @return int (R>0) $paged Always a positive number.
1151
  */
@@ -1154,11 +1167,21 @@ class Query extends Compat {
1154
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1155
  return $cache;
1156
 
1157
- $paged = $this->is_multipage() ? \get_query_var( 'paged' ) : 1;
 
 
 
 
 
 
 
 
 
 
1158
 
1159
  $this->set_query_cache(
1160
  __METHOD__,
1161
- $paged = $paged ? (int) $paged : 1
1162
  );
1163
 
1164
  return $paged;
@@ -1171,6 +1194,7 @@ class Query extends Compat {
1171
  * we need is set up in the loop, not in the header; where TSF is active.
1172
  *
1173
  * @since 3.1.0
 
1174
  * @global \WP_Query $wp_query
1175
  *
1176
  * @return int
@@ -1180,6 +1204,8 @@ class Query extends Compat {
1180
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1181
  return $cache;
1182
 
 
 
1183
  global $wp_query;
1184
 
1185
  $post = null;
@@ -1230,6 +1256,7 @@ class Query extends Compat {
1230
  * @since 2.7.0
1231
  * @since 3.1.0 1. Now also works on archives.
1232
  * 2. Now is public.
 
1233
  *
1234
  * @return bool True if multipage.
1235
  */
629
  /**
630
  * Checks for front page by input ID.
631
  *
632
+ * Doesn't always return true when the ID is 0, although the homepage might be.
633
  * This is because it checks for the query, to prevent conflicts.
634
  * @see $this->is_real_front_page_by_id().
635
  *
636
  * @since 2.9.0
637
+ * @since 2.9.3 Now tests for archive and 404 before testing homepage as blog.
638
  * @since 3.2.2: Removed SEO settings page check. This now returns false on that page.
639
  *
640
  * @param int The page ID, required. Can be 0.
641
+ * @return bool True if ID if for the homepage.
642
  */
643
  public function is_front_page_by_id( $id ) {
644
 
681
  }
682
 
683
  /**
684
+ * Determines whether the query is for the blog page.
685
  *
686
  * @since 2.6.0
687
  * @staticvar bool $cache
1123
  * Fetches global $page through Query Var to prevent conflicts.
1124
  *
1125
  * @since 2.6.0
1126
+ * @since 3.2.4 1. Added overflow protection.
1127
+ * 2. Now always returns 1 on the admin screens.
1128
  *
1129
  * @return int (R>0) $page Always a positive number.
1130
  */
1133
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1134
  return $cache;
1135
 
1136
+ if ( $this->is_multipage() ) {
1137
+ $page = (int) \get_query_var( 'page' );
1138
+
1139
+ if ( $page > $this->numpages() ) {
1140
+ // On overflow, WP returns the first page.
1141
+ $page = 1;
1142
+ }
1143
+ } else {
1144
+ $page = 1;
1145
+ }
1146
 
1147
  $this->set_query_cache(
1148
  __METHOD__,
1149
+ $page = $page ?: 1
1150
  );
1151
 
1152
  return $page;
1157
  * Fetches global $paged through Query var to prevent conflicts.
1158
  *
1159
  * @since 2.6.0
1160
+ * @since 3.2.4 1. Added overflow protection.
1161
+ * 2. Now always returns 1 on the admin screens.
1162
  *
1163
  * @return int (R>0) $paged Always a positive number.
1164
  */
1167
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1168
  return $cache;
1169
 
1170
+ if ( $this->is_multipage() ) {
1171
+ $paged = (int) \get_query_var( 'paged' );
1172
+ $max = $this->numpages();
1173
+
1174
+ if ( $paged > $max ) {
1175
+ // On overflow, WP returns the last page.
1176
+ $paged = $max;
1177
+ }
1178
+ } else {
1179
+ $paged = 1;
1180
+ }
1181
 
1182
  $this->set_query_cache(
1183
  __METHOD__,
1184
+ $paged = $paged ?: 1
1185
  );
1186
 
1187
  return $paged;
1194
  * we need is set up in the loop, not in the header; where TSF is active.
1195
  *
1196
  * @since 3.1.0
1197
+ * @since 3.2.4 Now only returns "1" in the admin.
1198
  * @global \WP_Query $wp_query
1199
  *
1200
  * @return int
1204
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1205
  return $cache;
1206
 
1207
+ if ( $this->is_admin() ) return 1;
1208
+
1209
  global $wp_query;
1210
 
1211
  $post = null;
1256
  * @since 2.7.0
1257
  * @since 3.1.0 1. Now also works on archives.
1258
  * 2. Now is public.
1259
+ * @since 3.2.4 Now always returns false on the admin pages.
1260
  *
1261
  * @return bool True if multipage.
1262
  */
inc/classes/render.class.php CHANGED
@@ -851,12 +851,15 @@ class Render extends Admin_Init {
851
  *
852
  * @since 2.0.6
853
  * @since 3.0.0 Deleted filter `the_seo_framework_output_canonical`.
 
854
  * @uses $this->get_current_canonical_url()
855
  *
856
  * @return string The Canonical URL meta tag.
857
  */
858
  public function canonical() {
859
 
 
 
860
  /**
861
  * @since 2.6.5
862
  * @param string $url The canonical URL. Must be escaped.
@@ -865,14 +868,20 @@ class Render extends Admin_Init {
865
  $url = (string) \apply_filters_ref_array(
866
  'the_seo_framework_rel_canonical_output',
867
  [
868
- $this->get_current_canonical_url(),
869
  $this->get_the_real_ID(),
870
  ]
871
  );
872
 
873
- /**
874
- * @since 2.7.0 Listens to the second filter.
875
- */
 
 
 
 
 
 
876
  if ( $url )
877
  return '<link rel="canonical" href="' . $url . '" />' . PHP_EOL;
878
 
@@ -1031,30 +1040,43 @@ class Render extends Admin_Init {
1031
  if ( false === $this->is_blog_public() )
1032
  return '';
1033
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1034
  /**
1035
  * @since 2.6.0
1036
  * @param array $meta The robots meta.
1037
  * @param int $id The current post or term ID.
1038
  */
1039
- $meta = (array) \apply_filters_ref_array(
1040
  'the_seo_framework_robots_meta',
1041
  [
1042
  $this->robots_meta(),
1043
  $this->get_the_real_ID(),
1044
  ]
1045
  );
1046
-
1047
- if ( empty( $meta ) )
1048
- return '';
1049
-
1050
- return sprintf( '<meta name="robots" content="%s" />' . PHP_EOL, implode( ',', $meta ) );
1051
  }
1052
 
1053
  /**
1054
  * Renders Shortlink meta tag
1055
  *
1056
  * @since 2.2.2
1057
- * @since 2.9.3 : Now work when home page is a blog.
1058
  * @uses $this->get_shortlink()
1059
  *
1060
  * @return string The Shortlink meta tag.
851
  *
852
  * @since 2.0.6
853
  * @since 3.0.0 Deleted filter `the_seo_framework_output_canonical`.
854
+ * @since 3.2.4 Now no longer returns a value when the post is not indexed with a non-custom URL.
855
  * @uses $this->get_current_canonical_url()
856
  *
857
  * @return string The Canonical URL meta tag.
858
  */
859
  public function canonical() {
860
 
861
+ $_url = $this->get_current_canonical_url();
862
+
863
  /**
864
  * @since 2.6.5
865
  * @param string $url The canonical URL. Must be escaped.
868
  $url = (string) \apply_filters_ref_array(
869
  'the_seo_framework_rel_canonical_output',
870
  [
871
+ $_url,
872
  $this->get_the_real_ID(),
873
  ]
874
  );
875
 
876
+ // If the page should not be indexed, consider removing the canonical URL.
877
+ if ( in_array( 'noindex', $this->get_robots_meta(), true ) ) {
878
+ // If the URL is filtered, don't empty it.
879
+ // If a custom canonical URL is set, don't empty it.
880
+ if ( $url === $_url && ! $this->has_custom_canonical_url() ) {
881
+ $url = '';
882
+ }
883
+ }
884
+
885
  if ( $url )
886
  return '<link rel="canonical" href="' . $url . '" />' . PHP_EOL;
887
 
1040
  if ( false === $this->is_blog_public() )
1041
  return '';
1042
 
1043
+ $meta = $this->get_robots_meta();
1044
+
1045
+ if ( empty( $meta ) )
1046
+ return '';
1047
+
1048
+ return sprintf( '<meta name="robots" content="%s" />' . PHP_EOL, implode( ',', $meta ) );
1049
+ }
1050
+
1051
+ /**
1052
+ * Returns the robots meta array.
1053
+ *
1054
+ * @since 3.2.4
1055
+ * @staticvar array|null $cache
1056
+ *
1057
+ * @return array
1058
+ */
1059
+ public function get_robots_meta() {
1060
+ static $cache = null;
1061
  /**
1062
  * @since 2.6.0
1063
  * @param array $meta The robots meta.
1064
  * @param int $id The current post or term ID.
1065
  */
1066
+ return isset( $cache ) ? $cache : $cache = (array) \apply_filters_ref_array(
1067
  'the_seo_framework_robots_meta',
1068
  [
1069
  $this->robots_meta(),
1070
  $this->get_the_real_ID(),
1071
  ]
1072
  );
 
 
 
 
 
1073
  }
1074
 
1075
  /**
1076
  * Renders Shortlink meta tag
1077
  *
1078
  * @since 2.2.2
1079
+ * @since 2.9.3 Now work when homepage is a blog.
1080
  * @uses $this->get_shortlink()
1081
  *
1082
  * @return string The Shortlink meta tag.
inc/classes/sanitize.class.php CHANGED
@@ -94,6 +94,7 @@ class Sanitize extends Admin_Pages {
94
  \add_action( "update_option_{$this->settings_field}", [ $this, 'delete_main_cache' ] );
95
  \add_action( "update_option_{$this->settings_field}", [ $this, 'reinitialize_rewrite' ], 11 );
96
  \add_action( "update_option_{$this->settings_field}", [ $this, 'update_db_version' ], 12 );
 
97
  \add_action( "update_option_{$this->settings_field}", [ $this, '_set_backward_compatibility' ], 13 );
98
  }
99
 
@@ -780,14 +781,21 @@ class Sanitize extends Admin_Pages {
780
  //* No need to parse an empty excerpt.
781
  if ( '' === $excerpt ) return '';
782
 
 
 
 
 
 
 
 
783
  /**
784
  * @since 2.6.6.1
785
  * @param bool $allow_shortcodes Whether to allow shortcodes.
786
  */
787
  if ( $allow_shortcodes && \apply_filters( 'the_seo_framework_allow_excerpt_shortcode_tags', false ) ) {
788
- $excerpt = \wp_strip_all_tags( $excerpt );
789
  } else {
790
- $excerpt = \wp_strip_all_tags( \strip_shortcodes( $excerpt ) );
791
  }
792
 
793
  if ( $escape )
@@ -1462,4 +1470,64 @@ class Sanitize extends Admin_Pages {
1462
  public function strip_paragraph_urls( $content ) {
1463
  return preg_replace( '/(<p(?: [^>]*)?>\s*)(https?:\/\/[^\s<>"]+)(\s*<\/p>)/i', '', $content );
1464
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1465
  }
94
  \add_action( "update_option_{$this->settings_field}", [ $this, 'delete_main_cache' ] );
95
  \add_action( "update_option_{$this->settings_field}", [ $this, 'reinitialize_rewrite' ], 11 );
96
  \add_action( "update_option_{$this->settings_field}", [ $this, 'update_db_version' ], 12 );
97
+ //* TEMP: Set backward compatibility
98
  \add_action( "update_option_{$this->settings_field}", [ $this, '_set_backward_compatibility' ], 13 );
99
  }
100
 
781
  //* No need to parse an empty excerpt.
782
  if ( '' === $excerpt ) return '';
783
 
784
+ $strip_args = [
785
+ 'space' =>
786
+ [ 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure', 'footer', 'li', 'main', 'ol', 'p', 'section', 'tfoot', 'ul' ],
787
+ 'clear' =>
788
+ [ 'address', 'bdo', 'br', 'button', 'canvas', 'code', 'fieldset', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'input', 'label', 'link', 'meta', 'nav', 'noscript', 'option', 'pre', 'samp', 'script', 'select', 'style', 'svg', 'table', 'textarea', 'var', 'video' ],
789
+ ];
790
+
791
  /**
792
  * @since 2.6.6.1
793
  * @param bool $allow_shortcodes Whether to allow shortcodes.
794
  */
795
  if ( $allow_shortcodes && \apply_filters( 'the_seo_framework_allow_excerpt_shortcode_tags', false ) ) {
796
+ $excerpt = $this->strip_tags_cs( $excerpt, $strip_args );
797
  } else {
798
+ $excerpt = $this->strip_tags_cs( \strip_shortcodes( $excerpt ), $strip_args );
799
  }
800
 
801
  if ( $escape )
1470
  public function strip_paragraph_urls( $content ) {
1471
  return preg_replace( '/(<p(?: [^>]*)?>\s*)(https?:\/\/[^\s<>"]+)(\s*<\/p>)/i', '', $content );
1472
  }
1473
+
1474
+ /**
1475
+ * Strips tags with HTML Context-Sensitivity and ouputs its breakdown.
1476
+ *
1477
+ * It essentially strips all tags, and replaces block-type tags' endings with spaces.
1478
+ * When done, it performs a sanity-cleanup via `strip_tags()`.
1479
+ *
1480
+ * Tip: You might want to use method `s_dupe_space()` to clear up the duplicated spaces afterward.
1481
+ *
1482
+ * @since 3.2.4
1483
+ * @link: https://www.w3schools.com/html/html_blocks.asp
1484
+ *
1485
+ * @param string $input The input text that needs its tags stripped.
1486
+ * @param array $args The input arguments: {
1487
+ * 'space' : @param array|null HTML elements that should have a space added.
1488
+ * If not set or null, skip check.
1489
+ * If empty array, use default; otherwise, use array.
1490
+ * 'clear' : @param array|null HTML elements that should be emptied and replaced with a space.
1491
+ * If not set or null, skip check.
1492
+ * If empty array, use default; otherwise, use array.
1493
+ * }
1494
+ * NOTE: WARNING The array values are forwarded to a regex without sanitization.
1495
+ * NOTE: Unlisted, script, and style tags will be stripped via PHP's `strip_tags()`.
1496
+ * @return string The output string without tags.
1497
+ */
1498
+ public function strip_tags_cs( $input, $args = [] ) {
1499
+
1500
+ $default_args = [
1501
+ 'space' =>
1502
+ [ 'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'tfoot', 'ul' ],
1503
+ 'clear' =>
1504
+ [ 'bdo', 'br', 'button', 'canvas', 'code', 'hr', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
1505
+ ];
1506
+
1507
+ if ( ! $args ) {
1508
+ $args = $default_args;
1509
+ } else {
1510
+ foreach ( [ 'space', 'clear' ] as $type ) {
1511
+ if ( isset( $args[ $type ] ) ) {
1512
+ if ( ! $args[ $type ] ) {
1513
+ $args[ $type ] = $default_args[ $type ];
1514
+ } else {
1515
+ $args[ $type ] = (array) $args[ $type ];
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ // Clear first, so there's less to process; then add spaces.
1522
+ foreach ( [ 'clear', 'space' ] as $type ) {
1523
+ if ( empty( $args[ $type ] ) ) continue;
1524
+
1525
+ $_regex = sprintf( '<(%s)[^>]*?>((.*?)(<\/\1>))?', implode( $args[ $type ], '|' ) );
1526
+ $_replace = 'space' === $type ? ' $2 ' : ' ';
1527
+
1528
+ $input = preg_replace( "/$_regex/si", $_replace, $input );
1529
+ }
1530
+
1531
+ return strip_tags( $input );
1532
+ }
1533
  }
inc/classes/site-options.class.php CHANGED
@@ -158,15 +158,15 @@ class Site_Options extends Sanitize {
158
  'home_paged_noindex' => 0, // Every second or later homepage noindex
159
 
160
  // Robots home.
161
- 'homepage_noindex' => 0, // Home Page robots noindex
162
- 'homepage_nofollow' => 0, // Home Page robots noarchive
163
- 'homepage_noarchive' => 0, // Home Page robots nofollow
164
 
165
  // Home meta.
166
- 'homepage_title' => '', // Home Page Title string
167
- 'homepage_tagline' => 1, // Home Page add blog Tagline
168
- 'homepage_description' => '', // Home Page Description string
169
- 'homepage_title_tagline' => '', // Home Page Tagline string
170
  'home_title_location' => $h_titleloc, // Title separation location
171
 
172
  // Homepage Social
@@ -294,8 +294,8 @@ class Site_Options extends Sanitize {
294
  'title_rem_additions' => 1, // Title remove additions.
295
  'site_noindex' => 1, // Site Page robots noindex
296
  'site_nofollow' => 1, // Site Page robots nofollow
297
- 'homepage_noindex' => 1, // Home Page robots noindex
298
- 'homepage_nofollow' => 1, // Home Page robots noarchive
299
  ]
300
  );
301
  }
158
  'home_paged_noindex' => 0, // Every second or later homepage noindex
159
 
160
  // Robots home.
161
+ 'homepage_noindex' => 0, // Homepage robots noindex
162
+ 'homepage_nofollow' => 0, // Homepage robots noarchive
163
+ 'homepage_noarchive' => 0, // Homepage robots nofollow
164
 
165
  // Home meta.
166
+ 'homepage_title' => '', // Homepage Title string
167
+ 'homepage_tagline' => 1, // Homepage add blog Tagline
168
+ 'homepage_description' => '', // Homepage Description string
169
+ 'homepage_title_tagline' => '', // Homepage Tagline string
170
  'home_title_location' => $h_titleloc, // Title separation location
171
 
172
  // Homepage Social
294
  'title_rem_additions' => 1, // Title remove additions.
295
  'site_noindex' => 1, // Site Page robots noindex
296
  'site_nofollow' => 1, // Site Page robots nofollow
297
+ 'homepage_noindex' => 1, // Homepage robots noindex
298
+ 'homepage_nofollow' => 1, // Homepage robots noarchive
299
  ]
300
  );
301
  }
inc/compat/plugin-polylang.php CHANGED
@@ -34,3 +34,46 @@ function pll__( $string ) {
34
  }
35
  return $string;
36
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
  return $string;
36
  }
37
+
38
+ \add_filter( 'pll_home_url_white_list', __NAMESPACE__ . '\\_whitelist_tsf_urls' );
39
+ \add_filter( 'pll_home_url_black_list', __NAMESPACE__ . '\\_blaclist_tsf_sitemap_styles' );
40
+ /**
41
+ * Accompany the most broken and asinine idea in WordPress' history.
42
+ * Adds The SEO Framework's files to their whitelist of autoincompatible doom.
43
+ *
44
+ * @since 3.2.4
45
+ *
46
+ * @param array $whitelist
47
+ * @return array
48
+ */
49
+ function _whitelist_tsf_urls( $whitelist ) {
50
+ $whitelist[] = [ 'file' => 'autodescription/inc' ];
51
+ return $whitelist;
52
+ }
53
+
54
+ /**
55
+ * Accompany the most broken and asinine idea in WordPress' history.
56
+ * ...and stop messing with the rewrite system while doing so.
57
+ * Also, you should add support for class methods. Stop living in the PHP 4 era.
58
+ *
59
+ * @since 3.2.4
60
+ *
61
+ * @param array $blacklist
62
+ * @return array
63
+ */
64
+ function _blaclist_tsf_sitemap_styles( $blacklist ) {
65
+ $blacklist[] = [ 'function' => 'get_sitemap_xsl_url' ];
66
+ return $blacklist;
67
+ }
68
+
69
+ \add_filter( 'the_seo_framework_rel_canonical_output', __NAMESPACE__ . '\\_fix_home_url', 10, 2 );
70
+ \add_filter( 'the_seo_framework_ogurl_output', __NAMESPACE__ . '\\_fix_home_url', 10, 2 );
71
+ /**
72
+ * Adds a trailing slash to whatever's deemed as the homepage URL.
73
+ * This fixes user_trailingslashit() issues.
74
+ *
75
+ * @since 3.2.4
76
+ */
77
+ function _fix_home_url( $url, $id ) {
78
+ return \the_seo_framework()->is_front_page_by_ID( $id ) && \get_option( 'permalink_structure' ) ? \trailingslashit( $url ) : $url;
79
+ }
inc/functions/deprecated.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * @package The_SEO_Framework
4
- * @subpackage The_SEO_Framework\Deprecated
5
  */
6
 
7
  /**
1
  <?php
2
  /**
3
  * @package The_SEO_Framework
4
+ * @subpackage Deprecated
5
  */
6
 
7
  /**
inc/functions/{tsfem-suggestion.php → upgrade-suggestion.php} RENAMED
@@ -1,8 +1,9 @@
1
  <?php
2
  /**
3
  * @package The_SEO_Framework
4
- * @subpackage The_SEO_Framework\TSFEM\Suggestion
5
  */
 
6
 
7
  /**
8
  * The SEO Framework plugin
@@ -28,36 +29,39 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
28
  * This file will only be called ONCE on plugin install, or upgrade from pre-v3.0.6.
29
  *
30
  * @since 3.0.6
 
31
  * @access private
32
  */
33
 
 
34
  /**
35
- * Prepares a "look at TSFEM" notification to ALL applicable plugin users on upgrade;
36
- * when:
37
  * 0. The upgrade happens when an applicable user is on the admin pages. (always true w/ default actions)
38
  * 1. The constant 'TSF_DISABLE_SUGGESTIONS' is not defined or false.
39
  * 2. The current dashboard is the main site's.
40
  * 3. The applicable user can install plugins.
41
  * 4. TSFEM isn't already installed.
42
  * 5. PHP and WP requirements of TSFEM are met.
43
- * This notice is automatically dismissed, and can be ignored without reappearing.
 
44
  *
45
  * @since 3.0.6
46
  * @access private
47
  * @uses the_seo_framework_add_upgrade_notice();
48
  */
49
- function the_seo_framework_load_extension_manager_suggestion() {
50
 
51
  //? 1
52
  if ( defined( 'TSF_DISABLE_SUGGESTIONS' ) && TSF_DISABLE_SUGGESTIONS ) return;
53
  //? 2
54
- if ( ! is_main_site() ) return;
55
  //? 3
56
- if ( ! current_user_can( 'install_plugins' ) ) return;
57
  //? 4a
58
  if ( defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) return;
59
  //= PHP<5.5 can't write in empty()
60
- $plugin = get_plugins();
61
  //? 4b
62
  if ( ! empty( $plugin['the-seo-framework-extension-manager/the-seo-framework-extension-manager.php'] ) ) return;
63
 
@@ -67,10 +71,11 @@ function the_seo_framework_load_extension_manager_suggestion() {
67
  '5.5' => 50521,
68
  '5.6' => 50605,
69
  ],
70
- 'wp' => '37965',
71
  ];
72
  $envtest = false;
73
 
 
74
  ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < $_req['php']['5.5'] and $envtest = 1
75
  or PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < $_req['php']['5.6'] and $envtest = 2
76
  or $GLOBALS['wp_db_version'] < $_req['wp'] and $envtest = 3
@@ -79,27 +84,35 @@ function the_seo_framework_load_extension_manager_suggestion() {
79
  //? 5
80
  if ( true !== $envtest ) return;
81
 
82
- add_action( 'admin_notices', 'the_seo_framework_suggest_extension_manager' );
83
  }
84
 
85
  /**
86
- * Outputs "look at TSFEM" notification to ALL applicable plugin users on upgrade.
 
 
 
 
 
 
 
 
 
 
87
  *
88
  * @since 3.0.6
89
  * @access private
90
  */
91
- function the_seo_framework_suggest_extension_manager() {
92
 
93
- $suggestion = sprintf(
94
- /* translators: %s: SEO extensions link. */
95
- esc_html__( 'Looking for more SEO functionality? Check out %s.', 'autodescription' ),
96
- sprintf(
97
- '<a href="%s" target=_blank rel="noopener noreferrer">%s</a>',
98
- 'https://theseoframework.com/extensions/',
99
- esc_html__( "The SEO Framework's extensions", 'autodescription' )
100
- )
101
- );
102
 
103
- //= This loads the JS files.
104
- the_seo_framework()->do_dismissible_notice( $suggestion, 'updated', false, false );
 
 
 
 
 
 
105
  }
1
  <?php
2
  /**
3
  * @package The_SEO_Framework
4
+ * @subpackage The_SEO_Framework\Suggestion
5
  */
6
+ namespace The_SEO_Framework\Suggestion;
7
 
8
  /**
9
  * The SEO Framework plugin
29
  * This file will only be called ONCE on plugin install, or upgrade from pre-v3.0.6.
30
  *
31
  * @since 3.0.6
32
+ * @since 3.2.4 Applied namspacing to this file. All method names have changed.
33
  * @access private
34
  */
35
 
36
+ _prepare();
37
  /**
38
+ * Prepares a suggestion notification to ALL applicable plugin users on upgrade;
39
+ * For TSFEM, it's shown when:
40
  * 0. The upgrade happens when an applicable user is on the admin pages. (always true w/ default actions)
41
  * 1. The constant 'TSF_DISABLE_SUGGESTIONS' is not defined or false.
42
  * 2. The current dashboard is the main site's.
43
  * 3. The applicable user can install plugins.
44
  * 4. TSFEM isn't already installed.
45
  * 5. PHP and WP requirements of TSFEM are met.
46
+ *
47
+ * This notice is automatically dismissed, and it can be ignored without reappearing.
48
  *
49
  * @since 3.0.6
50
  * @access private
51
  * @uses the_seo_framework_add_upgrade_notice();
52
  */
53
+ function _prepare() {
54
 
55
  //? 1
56
  if ( defined( 'TSF_DISABLE_SUGGESTIONS' ) && TSF_DISABLE_SUGGESTIONS ) return;
57
  //? 2
58
+ if ( ! \is_main_site() ) return;
59
  //? 3
60
+ if ( ! \current_user_can( 'install_plugins' ) ) return;
61
  //? 4a
62
  if ( defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) return;
63
  //= PHP<5.5 can't write in empty()
64
+ $plugin = \get_plugins();
65
  //? 4b
66
  if ( ! empty( $plugin['the-seo-framework-extension-manager/the-seo-framework-extension-manager.php'] ) ) return;
67
 
71
  '5.5' => 50521,
72
  '5.6' => 50605,
73
  ],
74
+ 'wp' => '37965',
75
  ];
76
  $envtest = false;
77
 
78
+ //? PHP_VERSION_ID is definitely defined, but let's keep it homonymous with the envtest of TSFEM.
79
  ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < $_req['php']['5.5'] and $envtest = 1
80
  or PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < $_req['php']['5.6'] and $envtest = 2
81
  or $GLOBALS['wp_db_version'] < $_req['wp'] and $envtest = 3
84
  //? 5
85
  if ( true !== $envtest ) return;
86
 
87
+ _load_tsfem_suggestion();
88
  }
89
 
90
  /**
91
+ * Loads the TSFEM suggestion.
92
+ *
93
+ * @since 3.2.4
94
+ * @access private
95
+ */
96
+ function _load_tsfem_suggestion() {
97
+ \add_action( 'admin_notices', __NAMESPACE__ . '\\_suggest_extension_manager' );
98
+ }
99
+
100
+ /**
101
+ * Outputs "look at TSFEM" notification to applicable plugin users on upgrade.
102
  *
103
  * @since 3.0.6
104
  * @access private
105
  */
106
+ function _suggest_extension_manager() {
107
 
108
+ $tsf = \the_seo_framework();
 
 
 
 
 
 
 
 
109
 
110
+ $tsf->do_dismissible_notice( $tsf->convert_markdown(
111
+ sprintf(
112
+ /* translators: %s = Extension URL markdown */
113
+ \esc_html__( "Looking for more SEO functionality? Check out [The SEO Framework's extensions](%s).", 'autodescription' ),
114
+ 'https://theseoframework.com/extensions/'
115
+ ),
116
+ [ 'a' ]
117
+ ), 'updated', false, false );
118
  }
inc/views/debug/output.php CHANGED
@@ -9,7 +9,7 @@ $id = $this->get_the_real_ID();
9
  $mdash = ' &mdash; ';
10
  $taxonomy = $this->get_current_taxonomy();
11
 
12
- //* This will return 'Page' on all non-archive types (except the home page)
13
  if ( ! $this->is_archive() && $this->is_real_front_page() || $this->is_front_page_by_id( $id ) ) {
14
  $type = 'Front Page';
15
  } elseif ( $taxonomy ) {
9
  $mdash = ' &mdash; ';
10
  $taxonomy = $this->get_current_taxonomy();
11
 
12
+ //* This will return 'Page' on all non-archive types (except the homepage)
13
  if ( ! $this->is_archive() && $this->is_real_front_page() || $this->is_front_page_by_id( $id ) ) {
14
  $type = 'Front Page';
15
  } elseif ( $taxonomy ) {
inc/views/metaboxes/general-metabox.php CHANGED
@@ -302,15 +302,15 @@ switch ( $instance ) :
302
  $this->description( __( "It's recommended to turn these options on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
303
 
304
  /* translators: %s = <code>rel</code> */
305
- $prev_next_posts_label = sprintf( esc_html__( 'Add %s link tags to Posts and Pages?', 'autodescription' ), $this->code_wrap( 'rel' ) );
306
  $prev_next_posts_checkbox = $this->make_checkbox( 'prev_next_posts', $prev_next_posts_label, '', false );
307
 
308
  /* translators: %s = <code>rel</code> */
309
- $prev_next_archives_label = sprintf( esc_html__( 'Add %s link tags to Archives?', 'autodescription' ), $this->code_wrap( 'rel' ) );
310
  $prev_next_archives_checkbox = $this->make_checkbox( 'prev_next_archives', $prev_next_archives_label, '', false );
311
 
312
  /* translators: %s = <code>rel</code> */
313
- $prev_next_frontpage_label = sprintf( esc_html__( 'Add %s link tags to the Home Page?', 'autodescription' ), $this->code_wrap( 'rel' ) );
314
  $prev_next_frontpage_checkbox = $this->make_checkbox( 'prev_next_frontpage', $prev_next_frontpage_label, '', false );
315
 
316
  //* Echo checkboxes.
302
  $this->description( __( "It's recommended to turn these options on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
303
 
304
  /* translators: %s = <code>rel</code> */
305
+ $prev_next_posts_label = sprintf( esc_html__( 'Add %s link tags to posts and pages?', 'autodescription' ), $this->code_wrap( 'rel' ) );
306
  $prev_next_posts_checkbox = $this->make_checkbox( 'prev_next_posts', $prev_next_posts_label, '', false );
307
 
308
  /* translators: %s = <code>rel</code> */
309
+ $prev_next_archives_label = sprintf( esc_html__( 'Add %s link tags to archives?', 'autodescription' ), $this->code_wrap( 'rel' ) );
310
  $prev_next_archives_checkbox = $this->make_checkbox( 'prev_next_archives', $prev_next_archives_label, '', false );
311
 
312
  /* translators: %s = <code>rel</code> */
313
+ $prev_next_frontpage_label = sprintf( esc_html__( 'Add %s link tags to the homepage?', 'autodescription' ), $this->code_wrap( 'rel' ) );
314
  $prev_next_frontpage_checkbox = $this->make_checkbox( 'prev_next_frontpage', $prev_next_frontpage_label, '', false );
315
 
316
  //* Echo checkboxes.
inc/views/metaboxes/sitemaps-metabox.php CHANGED
@@ -112,7 +112,7 @@ switch ( $instance ) :
112
  </label>
113
  </p>
114
  <?php
115
- $this->description( __( 'The sitemap is generated with three queries: Pages, Posts, and other Post Types. This setting affects how many posts are requested from the database per query. The home and blog pages are included separately.', 'autodescription' ) );
116
 
117
  if ( \has_filter( 'the_seo_framework_sitemap_post_limit' ) ) :
118
  ?>
@@ -178,7 +178,6 @@ switch ( $instance ) :
178
  echo '<hr>';
179
 
180
  if ( $show_settings ) :
181
-
182
  printf(
183
  '<h4>%s</h4>',
184
  esc_html__( 'Add sitemap location in robots.txt', 'autodescription' )
112
  </label>
113
  </p>
114
  <?php
115
+ $this->description( __( 'The sitemap is generated with three queries: Pages, posts, and other post types. This setting affects how many posts are requested from the database per query. The homepage and blog page are included separately.', 'autodescription' ) );
116
 
117
  if ( \has_filter( 'the_seo_framework_sitemap_post_limit' ) ) :
118
  ?>
178
  echo '<hr>';
179
 
180
  if ( $show_settings ) :
 
181
  printf(
182
  '<h4>%s</h4>',
183
  esc_html__( 'Add sitemap location in robots.txt', 'autodescription' )
inc/views/metaboxes/social-metabox.php CHANGED
@@ -74,14 +74,14 @@ switch ( $instance ) :
74
  $this->make_checkbox(
75
  'og_tags',
76
  __( 'Output Open Graph meta tags?', 'autodescription' ),
77
- __( 'Facebook, Twitter, Pinterest and many other social sites make use of these tags.', 'autodescription' ),
78
  true
79
  ),
80
  true
81
  );
82
 
83
  if ( $this->detect_og_plugin() )
84
- $this->attention_description( __( 'Note: Another Open Graph plugin has been detected. These tags might conflict.', 'autodescription' ) );
85
 
86
  //* Echo Facebook Tags checkbox.
87
  $this->wrap_fields(
@@ -89,7 +89,7 @@ switch ( $instance ) :
89
  'facebook_tags',
90
  __( 'Output Facebook meta tags?', 'autodescription' ),
91
  /* translators: %s = Facebook */
92
- sprintf( __( 'Output various tags targeted at %s.', 'autodescription' ), 'Facebook' ),
93
  true
94
  ),
95
  true
@@ -101,14 +101,14 @@ switch ( $instance ) :
101
  'twitter_tags',
102
  __( 'Output Twitter meta tags?', 'autodescription' ),
103
  /* translators: %s = Facebook */
104
- sprintf( __( 'Output various tags targeted at %s.', 'autodescription' ), 'Twitter' ),
105
  true
106
  ),
107
  true
108
  );
109
 
110
  if ( $this->detect_twitter_card_plugin() )
111
- $this->attention_description( __( 'Note: Another Twitter Card plugin has been detected. These tags might conflict.', 'autodescription' ) );
112
 
113
  ?>
114
  <hr>
@@ -311,26 +311,35 @@ switch ( $instance ) :
311
 
312
  case 'the_seo_framework_social_metabox_postdates':
313
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
314
- $home_i18n = esc_html__( 'Home Page', 'autodescription' );
315
 
316
  ?>
317
  <h4><?php esc_html_e( 'Post Date Settings', 'autodescription' ); ?></h4>
318
  <?php
319
- $this->description( __( 'Some social sites output the published date and modified date in the sharing snippet.', 'autodescription' ) );
320
  ?>
321
  <hr>
322
  <?php
323
 
324
- /* translators: 1: Option, 2: Post Type */
325
- $post_publish_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:published_time' ), $posts_i18n );
326
- $post_publish_time_checkbox = $this->make_checkbox( 'post_publish_time', $post_publish_time_label, '', false );
 
 
 
 
 
327
 
328
- /* translators: 1: Option, 2: Post Type */
329
- $post_modify_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:modified_time' ), $posts_i18n );
330
- $post_modify_time_checkbox = $this->make_checkbox( 'post_modify_time', $post_modify_time_label, '', false );
 
 
 
 
 
331
 
332
  //* Echo checkboxes.
333
- $this->wrap_fields( $post_publish_time_checkbox . $post_modify_time_checkbox, true );
334
  break;
335
 
336
  default:
74
  $this->make_checkbox(
75
  'og_tags',
76
  __( 'Output Open Graph meta tags?', 'autodescription' ),
77
+ __( 'Facebook, Twitter, Pinterest and many other social sites make use of these meta tags.', 'autodescription' ),
78
  true
79
  ),
80
  true
81
  );
82
 
83
  if ( $this->detect_og_plugin() )
84
+ $this->attention_description( __( 'Note: Another Open Graph plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
85
 
86
  //* Echo Facebook Tags checkbox.
87
  $this->wrap_fields(
89
  'facebook_tags',
90
  __( 'Output Facebook meta tags?', 'autodescription' ),
91
  /* translators: %s = Facebook */
92
+ sprintf( __( 'Output various meta tags targeted at %s.', 'autodescription' ), 'Facebook' ),
93
  true
94
  ),
95
  true
101
  'twitter_tags',
102
  __( 'Output Twitter meta tags?', 'autodescription' ),
103
  /* translators: %s = Facebook */
104
+ sprintf( __( 'Output various meta tags targeted at %s.', 'autodescription' ), 'Twitter' ),
105
  true
106
  ),
107
  true
108
  );
109
 
110
  if ( $this->detect_twitter_card_plugin() )
111
+ $this->attention_description( __( 'Note: Another Twitter Card plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
112
 
113
  ?>
114
  <hr>
311
 
312
  case 'the_seo_framework_social_metabox_postdates':
313
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
 
314
 
315
  ?>
316
  <h4><?php esc_html_e( 'Post Date Settings', 'autodescription' ); ?></h4>
317
  <?php
318
+ $this->description( __( 'Some social sites output the publishing and modified date in the sharing snippet.', 'autodescription' ) );
319
  ?>
320
  <hr>
321
  <?php
322
 
323
+ $_options = [
324
+ 'post_publish_time' => 'article:published_time',
325
+ 'post_modify_time' => 'article:modified_time',
326
+ ];
327
+
328
+ /* translators: %s = code example */
329
+ $label = esc_html__( 'Add %s to posts?', 'autodescription' );
330
+ $output = '';
331
 
332
+ foreach ( $_options as $_option => $_example ) {
333
+ $output .= $this->make_checkbox(
334
+ $_option,
335
+ sprintf( $label, $this->code_wrap( $_example ) ),
336
+ '',
337
+ false
338
+ );
339
+ }
340
 
341
  //* Echo checkboxes.
342
+ $this->wrap_fields( $output, true );
343
  break;
344
 
345
  default:
inc/views/metaboxes/title-metabox.php CHANGED
@@ -140,7 +140,7 @@ switch ( $instance ) :
140
  $example_left = $examples['left'];
141
  $example_right = $examples['right'];
142
 
143
- $home_page_has_option = __( 'The Home Page has a specific option.', 'autodescription' );
144
 
145
  ?>
146
  <fieldset>
@@ -164,7 +164,7 @@ switch ( $instance ) :
164
  </label>
165
  </span>
166
  </p>
167
- <?php $this->description( $home_page_has_option ); ?>
168
  </fieldset>
169
 
170
  <hr>
@@ -177,7 +177,7 @@ switch ( $instance ) :
177
  <fieldset>
178
  <legend>
179
  <h4><?php esc_html_e( 'Title Separator', 'autodescription' ); ?></h4>
180
- <?php $this->description( __( 'If the title consists of two parts (original title, pagination, and blogname), then the separator will go in-between them.', 'autodescription' ) ); ?>
181
  </legend>
182
  <p id="tsf-title-separator" class="tsf-fields">
183
  <?php foreach ( $title_separator as $name => $html ) : ?>
@@ -212,7 +212,7 @@ switch ( $instance ) :
212
  <?php
213
  $this->attention_description( __( 'Note: Only use this option if you are aware of its SEO effects.', 'autodescription' ), false );
214
  echo ' ';
215
- $this->description( $home_page_has_option, false );
216
  break;
217
 
218
  case 'the_seo_framework_title_metabox_prefixes':
140
  $example_left = $examples['left'];
141
  $example_right = $examples['right'];
142
 
143
+ $homepage_has_option = __( 'The homepage has a specific option.', 'autodescription' );
144
 
145
  ?>
146
  <fieldset>
164
  </label>
165
  </span>
166
  </p>
167
+ <?php $this->description( $homepage_has_option ); ?>
168
  </fieldset>
169
 
170
  <hr>
177
  <fieldset>
178
  <legend>
179
  <h4><?php esc_html_e( 'Title Separator', 'autodescription' ); ?></h4>
180
+ <?php $this->description( __( 'If the title consists of multiple parts (original title, pagination, and blogname), then the separator will go in-between them.', 'autodescription' ) ); ?>
181
  </legend>
182
  <p id="tsf-title-separator" class="tsf-fields">
183
  <?php foreach ( $title_separator as $name => $html ) : ?>
212
  <?php
213
  $this->attention_description( __( 'Note: Only use this option if you are aware of its SEO effects.', 'autodescription' ), false );
214
  echo ' ';
215
+ $this->description( $homepage_has_option, false );
216
  break;
217
 
218
  case 'the_seo_framework_title_metabox_prefixes':
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 3.2.2\n"
6
- "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/the-seo-framework\n"
7
- "POT-Creation-Date: 2019-01-21 21:55:27+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,11 +12,11 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: bootstrap/upgrade.php:321
16
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
17
  msgstr ""
18
 
19
- #: bootstrap/upgrade.php:351
20
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
21
  msgstr ""
22
 
@@ -98,12 +98,12 @@ msgid "Are you sure you want to reset all SEO settings to their defaults?"
98
  msgstr ""
99
 
100
  #: inc/classes/admin-init.class.php:576
101
- #: inc/classes/generate-title.class.php:1114
102
  msgid "Private: %s"
103
  msgstr ""
104
 
105
  #: inc/classes/admin-init.class.php:578
106
- #: inc/classes/generate-title.class.php:1099
107
  msgid "Protected: %s"
108
  msgstr ""
109
 
@@ -217,7 +217,7 @@ msgid "Description Meta Settings"
217
  msgstr ""
218
 
219
  #: inc/classes/admin-pages.class.php:251
220
- msgid "Home Page Settings"
221
  msgstr ""
222
 
223
  #: inc/classes/admin-pages.class.php:262
@@ -268,19 +268,32 @@ msgstr ""
268
  msgid "Characters Used: %s"
269
  msgstr ""
270
 
271
- #: inc/classes/core.class.php:231
272
  msgid "Settings"
273
  msgstr ""
274
 
275
- #: inc/classes/core.class.php:236
276
  msgid "About"
277
  msgstr ""
278
 
279
- #: inc/classes/core.class.php:241
280
  msgctxt "Plugin extensions"
281
  msgid "Extensions"
282
  msgstr ""
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
285
  #. notification, 4: Replacement function
286
 
@@ -324,7 +337,7 @@ msgstr ""
324
 
325
  #. translators: %d = page number. Front-end output.
326
 
327
- #: inc/classes/deprecated.class.php:314
328
  msgid "Page %d"
329
  msgstr ""
330
 
@@ -346,223 +359,223 @@ msgstr ""
346
 
347
  #. translators: %s = But or And
348
 
349
- #: inc/classes/doing-it-right.class.php:927
350
  msgid "%s the Title contains the Blogname multiple times."
351
  msgstr ""
352
 
353
  #. translators: 1: Word, 2: Occurrences
354
 
355
- #: inc/classes/doing-it-right.class.php:1110
356
  msgid "%1$s is used %2$d times."
357
  msgstr ""
358
 
359
  #. Translators: %s = Post / Page / Category, etc.
360
 
361
- #: inc/classes/doing-it-right.class.php:1148
362
  msgid "%s is being indexed."
363
  msgstr ""
364
 
365
- #: inc/classes/doing-it-right.class.php:1157
366
  msgid "But you've discouraged indexing for the whole site."
367
  msgstr ""
368
 
369
  #. translators: 1: But or And, 2: Current taxonomy term plural label
370
 
371
- #: inc/classes/doing-it-right.class.php:1180
372
  msgid "%1$s indexing for %2$s have been discouraged."
373
  msgstr ""
374
 
375
  #. translators: 1 = But or And, 1 = Post/Page
376
 
377
- #: inc/classes/doing-it-right.class.php:1189
378
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
379
  msgstr ""
380
 
381
  #. translators: %s = But or And
382
 
383
- #: inc/classes/doing-it-right.class.php:1203
384
  msgid "%s the post type is discouraging from being indexed."
385
  msgstr ""
386
 
387
  #. translators: %s = But or And
388
 
389
- #: inc/classes/doing-it-right.class.php:1212
390
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
391
  msgstr ""
392
 
393
  #. translators: %s = But or And
394
 
395
- #: inc/classes/doing-it-right.class.php:1241
396
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
397
  msgstr ""
398
 
399
  #. translators: %s = But or And
400
 
401
- #: inc/classes/doing-it-right.class.php:1266
402
  msgid "%s there are no posts on this blog; therefore, indexing has been discouraged."
403
  msgstr ""
404
 
405
  #. translators: 1 = But or And, 1 = Post/Page
406
 
407
- #: inc/classes/doing-it-right.class.php:1278
408
  msgid "%1$s this %2$s is in draft; therefore, indexing has been discouraged."
409
  msgstr ""
410
 
411
- #: inc/classes/doing-it-right.class.php:1359
412
  msgid "%s links aren't being followed."
413
  msgstr ""
414
 
415
- #: inc/classes/doing-it-right.class.php:1365
416
  msgid "%s links are being followed."
417
  msgstr ""
418
 
419
  #. translators: %s = But or And
420
 
421
- #: inc/classes/doing-it-right.class.php:1377
422
  msgid "%s you've discouraged the following of links for the whole site."
423
  msgstr ""
424
 
425
  #. translators: 1: But or And, 2: Current taxonomy term plural label
426
 
427
- #: inc/classes/doing-it-right.class.php:1403
428
  msgid "%1$s following of links for %2$s have been discouraged."
429
  msgstr ""
430
 
431
  #. translators: %s = But or And
432
 
433
- #: inc/classes/doing-it-right.class.php:1419
434
  msgid "%s this post type is discouraging from having its links followed."
435
  msgstr ""
436
 
437
  #. translators: %s = But or And
438
 
439
- #: inc/classes/doing-it-right.class.php:1429
440
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
441
  msgstr ""
442
 
443
  #. translators: %s is Post/Page/Term
444
 
445
- #: inc/classes/doing-it-right.class.php:1477
446
  msgid "Bots are discouraged to archive this %s."
447
  msgstr ""
448
 
449
  #. translators: %s is Post/Page/Term
450
 
451
- #: inc/classes/doing-it-right.class.php:1482
452
  msgid "Bots are allowed to archive this %s."
453
  msgstr ""
454
 
455
- #: inc/classes/doing-it-right.class.php:1495
456
  msgid "%s you've discouraged archiving for the whole site."
457
  msgstr ""
458
 
459
  #. translators: 1: But or And, 2: Current taxonomy term plural label
460
 
461
- #: inc/classes/doing-it-right.class.php:1520
462
  msgid "%1$s archiving for %2$s have been discouraged."
463
  msgstr ""
464
 
465
  #. translators: %s = But or And
466
 
467
- #: inc/classes/doing-it-right.class.php:1537
468
  msgid "%s this post type is discouraging from being archived."
469
  msgstr ""
470
 
471
  #. translators: %s = But or And
472
 
473
- #: inc/classes/doing-it-right.class.php:1547
474
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
475
  msgstr ""
476
 
477
  #. translators:* %s = post type name
478
 
479
- #: inc/classes/doing-it-right.class.php:1591
480
  msgid "%s isn't being redirected."
481
  msgstr ""
482
 
483
  #. translators:* %s = post type name
484
 
485
- #: inc/classes/doing-it-right.class.php:1632
486
- #: inc/classes/doing-it-right.class.php:1663
487
  msgid "%s is being redirected. This means no SEO values have to be set."
488
  msgstr ""
489
 
490
  #. translators:* %s = post type name
491
 
492
- #: inc/classes/doing-it-right.class.php:1636
493
- #: inc/classes/doing-it-right.class.php:1680
494
  msgid "%s is not being indexed. This means no SEO values have to be set."
495
  msgstr ""
496
 
497
- #: inc/classes/doing-it-right.class.php:1784
498
  msgid "Title:"
499
  msgstr ""
500
 
501
- #: inc/classes/doing-it-right.class.php:1785
502
  msgid "Description:"
503
  msgstr ""
504
 
505
- #: inc/classes/doing-it-right.class.php:1786
506
  msgid "Index:"
507
  msgstr ""
508
 
509
- #: inc/classes/doing-it-right.class.php:1787
510
  msgid "Follow:"
511
  msgstr ""
512
 
513
- #: inc/classes/doing-it-right.class.php:1788
514
  msgid "Archive:"
515
  msgstr ""
516
 
517
- #: inc/classes/doing-it-right.class.php:1789
518
  msgid "Redirect:"
519
  msgstr ""
520
 
521
- #: inc/classes/doing-it-right.class.php:1791
522
  msgid "Generated: Automatically generated."
523
  msgstr ""
524
 
525
- #: inc/classes/doing-it-right.class.php:1793
526
  msgctxt "Generated"
527
  msgid "G"
528
  msgstr ""
529
 
530
- #: inc/classes/doing-it-right.class.php:1794
531
  msgctxt "Title"
532
  msgid "T"
533
  msgstr ""
534
 
535
- #: inc/classes/doing-it-right.class.php:1795
536
  msgctxt "Description"
537
  msgid "D"
538
  msgstr ""
539
 
540
- #: inc/classes/doing-it-right.class.php:1796
541
  msgctxt "no-Index"
542
  msgid "I"
543
  msgstr ""
544
 
545
- #: inc/classes/doing-it-right.class.php:1797
546
  msgctxt "no-Follow"
547
  msgid "F"
548
  msgstr ""
549
 
550
- #: inc/classes/doing-it-right.class.php:1798
551
  msgctxt "no-Archive"
552
  msgid "A"
553
  msgstr ""
554
 
555
- #: inc/classes/doing-it-right.class.php:1799
556
  msgctxt "Redirect"
557
  msgid "R"
558
  msgstr ""
559
 
560
- #: inc/classes/doing-it-right.class.php:1801
561
  msgctxt "But there are..."
562
  msgid "But"
563
  msgstr ""
564
 
565
- #: inc/classes/doing-it-right.class.php:1802
566
  msgctxt "And there are..."
567
  msgid "And"
568
  msgstr ""
@@ -574,149 +587,149 @@ msgstr ""
574
 
575
  #. translators: %s = Blog page title. Front-end output.
576
 
577
- #: inc/classes/generate-description.class.php:671
578
  msgid "Latest posts: %s"
579
  msgstr ""
580
 
581
- #: inc/classes/generate-description.class.php:680
582
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
583
  msgid "on"
584
  msgstr ""
585
 
586
  #. translators: 1: Title, 2: on, 3: Blogname
587
 
588
- #: inc/classes/generate-description.class.php:684
589
  msgid "%1$s %2$s %3$s"
590
  msgstr ""
591
 
592
  #. translators: Category archive title. 1: Category name
593
 
594
- #: inc/classes/generate-title.class.php:693
595
- #: inc/classes/generate-title.class.php:713
596
  msgid "Category: %s"
597
  msgstr ""
598
 
599
  #. translators: Tag archive title. 1: Tag name
600
 
601
- #: inc/classes/generate-title.class.php:697
602
- #: inc/classes/generate-title.class.php:717
603
  msgid "Tag: %s"
604
  msgstr ""
605
 
606
  #. translators: Taxonomy term archive title. 1: Taxonomy singular name, 2:
607
  #. Current taxonomy term
608
 
609
- #: inc/classes/generate-title.class.php:703
610
- #: inc/classes/generate-title.class.php:765
611
  msgid "%1$s: %2$s"
612
  msgstr ""
613
 
614
- #: inc/classes/generate-title.class.php:707
615
- #: inc/classes/generate-title.class.php:768
616
  msgid "Archives"
617
  msgstr ""
618
 
619
  #. translators: Author archive title. 1: Author name
620
 
621
- #: inc/classes/generate-title.class.php:721
622
  msgid "Author: %s"
623
  msgstr ""
624
 
625
- #: inc/classes/generate-title.class.php:724
626
  msgctxt "yearly archives date format"
627
  msgid "Y"
628
  msgstr ""
629
 
630
  #. translators: Yearly archive title. 1: Year
631
 
632
- #: inc/classes/generate-title.class.php:726
633
  msgid "Year: %s"
634
  msgstr ""
635
 
636
- #: inc/classes/generate-title.class.php:728
637
  msgctxt "monthly archives date format"
638
  msgid "F Y"
639
  msgstr ""
640
 
641
  #. translators: Monthly archive title. 1: Month name and year
642
 
643
- #: inc/classes/generate-title.class.php:730
644
  msgid "Month: %s"
645
  msgstr ""
646
 
647
- #: inc/classes/generate-title.class.php:732
648
  msgctxt "daily archives date format"
649
  msgid "F j, Y"
650
  msgstr ""
651
 
652
  #. translators: Daily archive title. 1: Date
653
 
654
- #: inc/classes/generate-title.class.php:734
655
  msgid "Day: %s"
656
  msgstr ""
657
 
658
- #: inc/classes/generate-title.class.php:738
659
  msgctxt "post format archive title"
660
  msgid "Asides"
661
  msgstr ""
662
 
663
- #: inc/classes/generate-title.class.php:740
664
  msgctxt "post format archive title"
665
  msgid "Galleries"
666
  msgstr ""
667
 
668
- #: inc/classes/generate-title.class.php:742
669
  msgctxt "post format archive title"
670
  msgid "Images"
671
  msgstr ""
672
 
673
- #: inc/classes/generate-title.class.php:744
674
  msgctxt "post format archive title"
675
  msgid "Videos"
676
  msgstr ""
677
 
678
- #: inc/classes/generate-title.class.php:746
679
  msgctxt "post format archive title"
680
  msgid "Quotes"
681
  msgstr ""
682
 
683
- #: inc/classes/generate-title.class.php:748
684
  msgctxt "post format archive title"
685
  msgid "Links"
686
  msgstr ""
687
 
688
- #: inc/classes/generate-title.class.php:750
689
  msgctxt "post format archive title"
690
  msgid "Statuses"
691
  msgstr ""
692
 
693
- #: inc/classes/generate-title.class.php:752
694
  msgctxt "post format archive title"
695
  msgid "Audio"
696
  msgstr ""
697
 
698
- #: inc/classes/generate-title.class.php:754
699
  msgctxt "post format archive title"
700
  msgid "Chats"
701
  msgstr ""
702
 
703
  #. translators: Post type archive title. 1: Post type name
704
 
705
- #: inc/classes/generate-title.class.php:759
706
  msgid "Archives: %s"
707
  msgstr ""
708
 
709
- #: inc/classes/generate-title.class.php:919
710
  msgid "Untitled"
711
  msgstr ""
712
 
713
  #. translators: %s: search phrase
714
 
715
- #: inc/classes/generate-title.class.php:931
716
  msgid "Search Results for &#8220;%s&#8221;"
717
  msgstr ""
718
 
719
- #: inc/classes/generate-title.class.php:1048
720
  msgid "Page %s"
721
  msgstr ""
722
 
@@ -773,17 +786,17 @@ msgstr ""
773
 
774
  #. translators: %s = 'The SEO Framework'
775
 
776
- #: inc/classes/render.class.php:1175
777
  msgid "Start %s"
778
  msgstr ""
779
 
780
  #. translators: %s = 'The SEO Framework'
781
 
782
- #: inc/classes/render.class.php:1177
783
  msgid "End %s"
784
  msgstr ""
785
 
786
- #: inc/classes/render.class.php:1178
787
  msgid "by Sybre Waaijer"
788
  msgstr ""
789
 
@@ -801,14 +814,10 @@ msgstr ""
801
  msgid "Sitemap is generated on %s"
802
  msgstr ""
803
 
804
- #. translators: %s: SEO extensions link.
805
-
806
- #: inc/functions/tsfem-suggestion.php:95
807
- msgid "Looking for more SEO functionality? Check out %s."
808
- msgstr ""
809
 
810
- #: inc/functions/tsfem-suggestion.php:99
811
- msgid "The SEO Framework's extensions"
812
  msgstr ""
813
 
814
  #: inc/views/inpost/seo-settings-singular.php:31
@@ -1262,19 +1271,19 @@ msgstr ""
1262
  #. translators: %s = <code>rel</code>
1263
 
1264
  #: inc/views/metaboxes/general-metabox.php:305
1265
- msgid "Add %s link tags to Posts and Pages?"
1266
  msgstr ""
1267
 
1268
  #. translators: %s = <code>rel</code>
1269
 
1270
  #: inc/views/metaboxes/general-metabox.php:309
1271
- msgid "Add %s link tags to Archives?"
1272
  msgstr ""
1273
 
1274
  #. translators: %s = <code>rel</code>
1275
 
1276
  #: inc/views/metaboxes/general-metabox.php:313
1277
- msgid "Add %s link tags to the Home Page?"
1278
  msgstr ""
1279
 
1280
  #: inc/views/metaboxes/general-metabox.php:337
@@ -1772,7 +1781,7 @@ msgstr ""
1772
 
1773
  #: inc/views/metaboxes/sitemaps-metabox.php:101
1774
  #: inc/views/metaboxes/sitemaps-metabox.php:159
1775
- #: inc/views/metaboxes/sitemaps-metabox.php:198
1776
  msgctxt "The sitemap can be found %s."
1777
  msgid "here"
1778
  msgstr ""
@@ -1788,7 +1797,7 @@ msgid "Sitemap Query Limit"
1788
  msgstr ""
1789
 
1790
  #: inc/views/metaboxes/sitemaps-metabox.php:115
1791
- msgid "The sitemap is generated with three queries: Pages, Posts, and other Post Types. This setting affects how many posts are requested from the database per query. The home and blog pages are included separately."
1792
  msgstr ""
1793
 
1794
  #: inc/views/metaboxes/sitemaps-metabox.php:131
@@ -1836,113 +1845,113 @@ msgstr ""
1836
  msgid "If you do not add the sitemap location to the robots.txt file, you will need to notify search engines manually through the Webmaster Console provided by the search engines."
1837
  msgstr ""
1838
 
1839
- #: inc/views/metaboxes/sitemaps-metabox.php:184
1840
  msgid "Add sitemap location in robots.txt"
1841
  msgstr ""
1842
 
1843
- #: inc/views/metaboxes/sitemaps-metabox.php:189
1844
  msgid "Add sitemap location in robots?"
1845
  msgstr ""
1846
 
1847
- #: inc/views/metaboxes/sitemaps-metabox.php:189
1848
  msgid "This only has effect when the sitemap is active."
1849
  msgstr ""
1850
 
1851
- #: inc/views/metaboxes/sitemaps-metabox.php:198
1852
  msgid "View robots.txt"
1853
  msgstr ""
1854
 
1855
- #: inc/views/metaboxes/sitemaps-metabox.php:200
1856
  msgctxt "%s = here"
1857
  msgid "The robots.txt file can be found %s."
1858
  msgstr ""
1859
 
1860
- #: inc/views/metaboxes/sitemaps-metabox.php:206
1861
  msgid "Timestamps Settings"
1862
  msgstr ""
1863
 
1864
- #: inc/views/metaboxes/sitemaps-metabox.php:208
1865
  msgid "The modified time suggests to search engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed."
1866
  msgstr ""
1867
 
1868
  #. translators: %s = An XML tag example
1869
 
1870
- #: inc/views/metaboxes/sitemaps-metabox.php:215
1871
- #: inc/views/metaboxes/sitemaps-metabox.php:233
1872
  msgid "Add %s to the sitemap?"
1873
  msgstr ""
1874
 
1875
- #: inc/views/metaboxes/sitemaps-metabox.php:224
1876
  msgid "Priority Settings"
1877
  msgstr ""
1878
 
1879
- #: inc/views/metaboxes/sitemaps-metabox.php:226
1880
  msgid "The priority index suggests to search engines which pages are deemed more important. It has no known impact on the SEO value and it is generally ignored."
1881
  msgstr ""
1882
 
1883
- #: inc/views/metaboxes/sitemaps-metabox.php:242
1884
  msgid "Ping Settings"
1885
  msgstr ""
1886
 
1887
- #: inc/views/metaboxes/sitemaps-metabox.php:244
1888
  msgid "Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible."
1889
  msgstr ""
1890
 
1891
- #: inc/views/metaboxes/sitemaps-metabox.php:245
1892
  msgid "By default this will happen at most once an hour."
1893
  msgstr ""
1894
 
1895
- #: inc/views/metaboxes/sitemaps-metabox.php:250
1896
  msgid "Notify Search Engines"
1897
  msgstr ""
1898
 
1899
  #. translators: %s = Google
1900
 
1901
- #: inc/views/metaboxes/sitemaps-metabox.php:263
1902
  msgid "Notify %s about sitemap changes?"
1903
  msgstr ""
1904
 
1905
- #: inc/views/metaboxes/sitemaps-metabox.php:273
1906
  msgid "Sitemap Styling Settings"
1907
  msgstr ""
1908
 
1909
- #: inc/views/metaboxes/sitemaps-metabox.php:275
1910
  msgid "You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever."
1911
  msgstr ""
1912
 
1913
- #: inc/views/metaboxes/sitemaps-metabox.php:276
1914
  msgid "Note: Changes might not appear to have effect directly because the stylesheet is cached in the browser for 30 minutes."
1915
  msgstr ""
1916
 
1917
- #: inc/views/metaboxes/sitemaps-metabox.php:280
1918
  msgid "Enable styling"
1919
  msgstr ""
1920
 
1921
- #: inc/views/metaboxes/sitemaps-metabox.php:287
1922
  msgid "Style Sitemap?"
1923
  msgstr ""
1924
 
1925
- #: inc/views/metaboxes/sitemaps-metabox.php:287
1926
  msgid "This makes the sitemap more readable for humans."
1927
  msgstr ""
1928
 
1929
- #: inc/views/metaboxes/sitemaps-metabox.php:296
1930
  msgid "Style configuration"
1931
  msgstr ""
1932
 
1933
- #: inc/views/metaboxes/sitemaps-metabox.php:304
1934
  msgid "Add site logo?"
1935
  msgstr ""
1936
 
1937
- #: inc/views/metaboxes/sitemaps-metabox.php:304
1938
  msgid "The logo is set in Customizer."
1939
  msgstr ""
1940
 
1941
- #: inc/views/metaboxes/sitemaps-metabox.php:317
1942
  msgid "Sitemap header background color"
1943
  msgstr ""
1944
 
1945
- #: inc/views/metaboxes/sitemaps-metabox.php:326
1946
  msgid "Sitemap title and lines color"
1947
  msgstr ""
1948
 
@@ -1963,11 +1972,11 @@ msgid "Output Open Graph meta tags?"
1963
  msgstr ""
1964
 
1965
  #: inc/views/metaboxes/social-metabox.php:77
1966
- msgid "Facebook, Twitter, Pinterest and many other social sites make use of these tags."
1967
  msgstr ""
1968
 
1969
  #: inc/views/metaboxes/social-metabox.php:84
1970
- msgid "Note: Another Open Graph plugin has been detected. These tags might conflict."
1971
  msgstr ""
1972
 
1973
  #: inc/views/metaboxes/social-metabox.php:90
@@ -1978,7 +1987,7 @@ msgstr ""
1978
 
1979
  #: inc/views/metaboxes/social-metabox.php:92
1980
  #: inc/views/metaboxes/social-metabox.php:104
1981
- msgid "Output various tags targeted at %s."
1982
  msgstr ""
1983
 
1984
  #: inc/views/metaboxes/social-metabox.php:102
@@ -1986,7 +1995,7 @@ msgid "Output Twitter meta tags?"
1986
  msgstr ""
1987
 
1988
  #: inc/views/metaboxes/social-metabox.php:111
1989
- msgid "Note: Another Twitter Card plugin has been detected. These tags might conflict."
1990
  msgstr ""
1991
 
1992
  #: inc/views/metaboxes/social-metabox.php:118
@@ -2107,23 +2116,18 @@ msgstr ""
2107
  msgid "Posts"
2108
  msgstr ""
2109
 
2110
- #: inc/views/metaboxes/social-metabox.php:314
2111
- msgid "Home Page"
2112
- msgstr ""
2113
-
2114
- #: inc/views/metaboxes/social-metabox.php:317
2115
  msgid "Post Date Settings"
2116
  msgstr ""
2117
 
2118
- #: inc/views/metaboxes/social-metabox.php:319
2119
- msgid "Some social sites output the published date and modified date in the sharing snippet."
2120
  msgstr ""
2121
 
2122
- #. translators: 1: Option, 2: Post Type
2123
 
2124
- #: inc/views/metaboxes/social-metabox.php:325
2125
  #: inc/views/metaboxes/social-metabox.php:329
2126
- msgid "Add %1$s to %2$s?"
2127
  msgstr ""
2128
 
2129
  #: inc/views/metaboxes/title-metabox.php:21
@@ -2162,7 +2166,7 @@ msgid "Tip: It is a bad practice to style page titles with HTML as inconsistent
2162
  msgstr ""
2163
 
2164
  #: inc/views/metaboxes/title-metabox.php:143
2165
- msgid "The Home Page has a specific option."
2166
  msgstr ""
2167
 
2168
  #: inc/views/metaboxes/title-metabox.php:148
@@ -2178,7 +2182,7 @@ msgid "Title Separator"
2178
  msgstr ""
2179
 
2180
  #: inc/views/metaboxes/title-metabox.php:180
2181
- msgid "If the title consists of two parts (original title, pagination, and blogname), then the separator will go in-between them."
2182
  msgstr ""
2183
 
2184
  #: inc/views/metaboxes/title-metabox.php:192
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 3.2.4\n"
6
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
+ "POT-Creation-Date: 2019-03-18 18:14:20+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: bootstrap/upgrade.php:328
16
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
17
  msgstr ""
18
 
19
+ #: bootstrap/upgrade.php:358
20
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
21
  msgstr ""
22
 
98
  msgstr ""
99
 
100
  #: inc/classes/admin-init.class.php:576
101
+ #: inc/classes/generate-title.class.php:1116
102
  msgid "Private: %s"
103
  msgstr ""
104
 
105
  #: inc/classes/admin-init.class.php:578
106
+ #: inc/classes/generate-title.class.php:1101
107
  msgid "Protected: %s"
108
  msgstr ""
109
 
217
  msgstr ""
218
 
219
  #: inc/classes/admin-pages.class.php:251
220
+ msgid "Homepage Settings"
221
  msgstr ""
222
 
223
  #: inc/classes/admin-pages.class.php:262
268
  msgid "Characters Used: %s"
269
  msgstr ""
270
 
271
+ #: inc/classes/core.class.php:229
272
  msgid "Settings"
273
  msgstr ""
274
 
275
+ #: inc/classes/core.class.php:234
276
  msgid "About"
277
  msgstr ""
278
 
279
+ #: inc/classes/core.class.php:239
280
  msgctxt "Plugin extensions"
281
  msgid "Extensions"
282
  msgstr ""
283
 
284
+ #: inc/classes/core.class.php:267
285
+ msgid "View documentation"
286
+ msgstr ""
287
+
288
+ #: inc/classes/core.class.php:274
289
+ msgid "View API docs"
290
+ msgstr ""
291
+
292
+ #: inc/classes/core.class.php:281
293
+ msgctxt "Extension Manager is a product name; do not translate"
294
+ msgid "Get the Extension Manager"
295
+ msgstr ""
296
+
297
  #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
298
  #. notification, 4: Replacement function
299
 
337
 
338
  #. translators: %d = page number. Front-end output.
339
 
340
+ #: inc/classes/deprecated.class.php:315
341
  msgid "Page %d"
342
  msgstr ""
343
 
359
 
360
  #. translators: %s = But or And
361
 
362
+ #: inc/classes/doing-it-right.class.php:928
363
  msgid "%s the Title contains the Blogname multiple times."
364
  msgstr ""
365
 
366
  #. translators: 1: Word, 2: Occurrences
367
 
368
+ #: inc/classes/doing-it-right.class.php:1111
369
  msgid "%1$s is used %2$d times."
370
  msgstr ""
371
 
372
  #. Translators: %s = Post / Page / Category, etc.
373
 
374
+ #: inc/classes/doing-it-right.class.php:1149
375
  msgid "%s is being indexed."
376
  msgstr ""
377
 
378
+ #: inc/classes/doing-it-right.class.php:1158
379
  msgid "But you've discouraged indexing for the whole site."
380
  msgstr ""
381
 
382
  #. translators: 1: But or And, 2: Current taxonomy term plural label
383
 
384
+ #: inc/classes/doing-it-right.class.php:1181
385
  msgid "%1$s indexing for %2$s have been discouraged."
386
  msgstr ""
387
 
388
  #. translators: 1 = But or And, 1 = Post/Page
389
 
390
+ #: inc/classes/doing-it-right.class.php:1190
391
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
392
  msgstr ""
393
 
394
  #. translators: %s = But or And
395
 
396
+ #: inc/classes/doing-it-right.class.php:1204
397
  msgid "%s the post type is discouraging from being indexed."
398
  msgstr ""
399
 
400
  #. translators: %s = But or And
401
 
402
+ #: inc/classes/doing-it-right.class.php:1213
403
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
404
  msgstr ""
405
 
406
  #. translators: %s = But or And
407
 
408
+ #: inc/classes/doing-it-right.class.php:1242
409
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
410
  msgstr ""
411
 
412
  #. translators: %s = But or And
413
 
414
+ #: inc/classes/doing-it-right.class.php:1267
415
  msgid "%s there are no posts on this blog; therefore, indexing has been discouraged."
416
  msgstr ""
417
 
418
  #. translators: 1 = But or And, 1 = Post/Page
419
 
420
+ #: inc/classes/doing-it-right.class.php:1279
421
  msgid "%1$s this %2$s is in draft; therefore, indexing has been discouraged."
422
  msgstr ""
423
 
424
+ #: inc/classes/doing-it-right.class.php:1360
425
  msgid "%s links aren't being followed."
426
  msgstr ""
427
 
428
+ #: inc/classes/doing-it-right.class.php:1366
429
  msgid "%s links are being followed."
430
  msgstr ""
431
 
432
  #. translators: %s = But or And
433
 
434
+ #: inc/classes/doing-it-right.class.php:1378
435
  msgid "%s you've discouraged the following of links for the whole site."
436
  msgstr ""
437
 
438
  #. translators: 1: But or And, 2: Current taxonomy term plural label
439
 
440
+ #: inc/classes/doing-it-right.class.php:1404
441
  msgid "%1$s following of links for %2$s have been discouraged."
442
  msgstr ""
443
 
444
  #. translators: %s = But or And
445
 
446
+ #: inc/classes/doing-it-right.class.php:1420
447
  msgid "%s this post type is discouraging from having its links followed."
448
  msgstr ""
449
 
450
  #. translators: %s = But or And
451
 
452
+ #: inc/classes/doing-it-right.class.php:1430
453
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
454
  msgstr ""
455
 
456
  #. translators: %s is Post/Page/Term
457
 
458
+ #: inc/classes/doing-it-right.class.php:1478
459
  msgid "Bots are discouraged to archive this %s."
460
  msgstr ""
461
 
462
  #. translators: %s is Post/Page/Term
463
 
464
+ #: inc/classes/doing-it-right.class.php:1483
465
  msgid "Bots are allowed to archive this %s."
466
  msgstr ""
467
 
468
+ #: inc/classes/doing-it-right.class.php:1496
469
  msgid "%s you've discouraged archiving for the whole site."
470
  msgstr ""
471
 
472
  #. translators: 1: But or And, 2: Current taxonomy term plural label
473
 
474
+ #: inc/classes/doing-it-right.class.php:1521
475
  msgid "%1$s archiving for %2$s have been discouraged."
476
  msgstr ""
477
 
478
  #. translators: %s = But or And
479
 
480
+ #: inc/classes/doing-it-right.class.php:1538
481
  msgid "%s this post type is discouraging from being archived."
482
  msgstr ""
483
 
484
  #. translators: %s = But or And
485
 
486
+ #: inc/classes/doing-it-right.class.php:1548
487
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
488
  msgstr ""
489
 
490
  #. translators:* %s = post type name
491
 
492
+ #: inc/classes/doing-it-right.class.php:1592
493
  msgid "%s isn't being redirected."
494
  msgstr ""
495
 
496
  #. translators:* %s = post type name
497
 
498
+ #: inc/classes/doing-it-right.class.php:1633
499
+ #: inc/classes/doing-it-right.class.php:1664
500
  msgid "%s is being redirected. This means no SEO values have to be set."
501
  msgstr ""
502
 
503
  #. translators:* %s = post type name
504
 
505
+ #: inc/classes/doing-it-right.class.php:1637
506
+ #: inc/classes/doing-it-right.class.php:1681
507
  msgid "%s is not being indexed. This means no SEO values have to be set."
508
  msgstr ""
509
 
510
+ #: inc/classes/doing-it-right.class.php:1785
511
  msgid "Title:"
512
  msgstr ""
513
 
514
+ #: inc/classes/doing-it-right.class.php:1786
515
  msgid "Description:"
516
  msgstr ""
517
 
518
+ #: inc/classes/doing-it-right.class.php:1787
519
  msgid "Index:"
520
  msgstr ""
521
 
522
+ #: inc/classes/doing-it-right.class.php:1788
523
  msgid "Follow:"
524
  msgstr ""
525
 
526
+ #: inc/classes/doing-it-right.class.php:1789
527
  msgid "Archive:"
528
  msgstr ""
529
 
530
+ #: inc/classes/doing-it-right.class.php:1790
531
  msgid "Redirect:"
532
  msgstr ""
533
 
534
+ #: inc/classes/doing-it-right.class.php:1792
535
  msgid "Generated: Automatically generated."
536
  msgstr ""
537
 
538
+ #: inc/classes/doing-it-right.class.php:1794
539
  msgctxt "Generated"
540
  msgid "G"
541
  msgstr ""
542
 
543
+ #: inc/classes/doing-it-right.class.php:1795
544
  msgctxt "Title"
545
  msgid "T"
546
  msgstr ""
547
 
548
+ #: inc/classes/doing-it-right.class.php:1796
549
  msgctxt "Description"
550
  msgid "D"
551
  msgstr ""
552
 
553
+ #: inc/classes/doing-it-right.class.php:1797
554
  msgctxt "no-Index"
555
  msgid "I"
556
  msgstr ""
557
 
558
+ #: inc/classes/doing-it-right.class.php:1798
559
  msgctxt "no-Follow"
560
  msgid "F"
561
  msgstr ""
562
 
563
+ #: inc/classes/doing-it-right.class.php:1799
564
  msgctxt "no-Archive"
565
  msgid "A"
566
  msgstr ""
567
 
568
+ #: inc/classes/doing-it-right.class.php:1800
569
  msgctxt "Redirect"
570
  msgid "R"
571
  msgstr ""
572
 
573
+ #: inc/classes/doing-it-right.class.php:1802
574
  msgctxt "But there are..."
575
  msgid "But"
576
  msgstr ""
577
 
578
+ #: inc/classes/doing-it-right.class.php:1803
579
  msgctxt "And there are..."
580
  msgid "And"
581
  msgstr ""
587
 
588
  #. translators: %s = Blog page title. Front-end output.
589
 
590
+ #: inc/classes/generate-description.class.php:670
591
  msgid "Latest posts: %s"
592
  msgstr ""
593
 
594
+ #: inc/classes/generate-description.class.php:679
595
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
596
  msgid "on"
597
  msgstr ""
598
 
599
  #. translators: 1: Title, 2: on, 3: Blogname
600
 
601
+ #: inc/classes/generate-description.class.php:683
602
  msgid "%1$s %2$s %3$s"
603
  msgstr ""
604
 
605
  #. translators: Category archive title. 1: Category name
606
 
607
+ #: inc/classes/generate-title.class.php:696
608
+ #: inc/classes/generate-title.class.php:716
609
  msgid "Category: %s"
610
  msgstr ""
611
 
612
  #. translators: Tag archive title. 1: Tag name
613
 
614
+ #: inc/classes/generate-title.class.php:700
615
+ #: inc/classes/generate-title.class.php:720
616
  msgid "Tag: %s"
617
  msgstr ""
618
 
619
  #. translators: Taxonomy term archive title. 1: Taxonomy singular name, 2:
620
  #. Current taxonomy term
621
 
622
+ #: inc/classes/generate-title.class.php:706
623
+ #: inc/classes/generate-title.class.php:768
624
  msgid "%1$s: %2$s"
625
  msgstr ""
626
 
627
+ #: inc/classes/generate-title.class.php:710
628
+ #: inc/classes/generate-title.class.php:771
629
  msgid "Archives"
630
  msgstr ""
631
 
632
  #. translators: Author archive title. 1: Author name
633
 
634
+ #: inc/classes/generate-title.class.php:724
635
  msgid "Author: %s"
636
  msgstr ""
637
 
638
+ #: inc/classes/generate-title.class.php:727
639
  msgctxt "yearly archives date format"
640
  msgid "Y"
641
  msgstr ""
642
 
643
  #. translators: Yearly archive title. 1: Year
644
 
645
+ #: inc/classes/generate-title.class.php:729
646
  msgid "Year: %s"
647
  msgstr ""
648
 
649
+ #: inc/classes/generate-title.class.php:731
650
  msgctxt "monthly archives date format"
651
  msgid "F Y"
652
  msgstr ""
653
 
654
  #. translators: Monthly archive title. 1: Month name and year
655
 
656
+ #: inc/classes/generate-title.class.php:733
657
  msgid "Month: %s"
658
  msgstr ""
659
 
660
+ #: inc/classes/generate-title.class.php:735
661
  msgctxt "daily archives date format"
662
  msgid "F j, Y"
663
  msgstr ""
664
 
665
  #. translators: Daily archive title. 1: Date
666
 
667
+ #: inc/classes/generate-title.class.php:737
668
  msgid "Day: %s"
669
  msgstr ""
670
 
671
+ #: inc/classes/generate-title.class.php:741
672
  msgctxt "post format archive title"
673
  msgid "Asides"
674
  msgstr ""
675
 
676
+ #: inc/classes/generate-title.class.php:743
677
  msgctxt "post format archive title"
678
  msgid "Galleries"
679
  msgstr ""
680
 
681
+ #: inc/classes/generate-title.class.php:745
682
  msgctxt "post format archive title"
683
  msgid "Images"
684
  msgstr ""
685
 
686
+ #: inc/classes/generate-title.class.php:747
687
  msgctxt "post format archive title"
688
  msgid "Videos"
689
  msgstr ""
690
 
691
+ #: inc/classes/generate-title.class.php:749
692
  msgctxt "post format archive title"
693
  msgid "Quotes"
694
  msgstr ""
695
 
696
+ #: inc/classes/generate-title.class.php:751
697
  msgctxt "post format archive title"
698
  msgid "Links"
699
  msgstr ""
700
 
701
+ #: inc/classes/generate-title.class.php:753
702
  msgctxt "post format archive title"
703
  msgid "Statuses"
704
  msgstr ""
705
 
706
+ #: inc/classes/generate-title.class.php:755
707
  msgctxt "post format archive title"
708
  msgid "Audio"
709
  msgstr ""
710
 
711
+ #: inc/classes/generate-title.class.php:757
712
  msgctxt "post format archive title"
713
  msgid "Chats"
714
  msgstr ""
715
 
716
  #. translators: Post type archive title. 1: Post type name
717
 
718
+ #: inc/classes/generate-title.class.php:762
719
  msgid "Archives: %s"
720
  msgstr ""
721
 
722
+ #: inc/classes/generate-title.class.php:922
723
  msgid "Untitled"
724
  msgstr ""
725
 
726
  #. translators: %s: search phrase
727
 
728
+ #: inc/classes/generate-title.class.php:934
729
  msgid "Search Results for &#8220;%s&#8221;"
730
  msgstr ""
731
 
732
+ #: inc/classes/generate-title.class.php:1050
733
  msgid "Page %s"
734
  msgstr ""
735
 
786
 
787
  #. translators: %s = 'The SEO Framework'
788
 
789
+ #: inc/classes/render.class.php:1197
790
  msgid "Start %s"
791
  msgstr ""
792
 
793
  #. translators: %s = 'The SEO Framework'
794
 
795
+ #: inc/classes/render.class.php:1199
796
  msgid "End %s"
797
  msgstr ""
798
 
799
+ #: inc/classes/render.class.php:1200
800
  msgid "by Sybre Waaijer"
801
  msgstr ""
802
 
814
  msgid "Sitemap is generated on %s"
815
  msgstr ""
816
 
817
+ #. translators: %s = Extension URL markdown
 
 
 
 
818
 
819
+ #: inc/functions/upgrade-suggestion.php:113
820
+ msgid "Looking for more SEO functionality? Check out [The SEO Framework's extensions](%s)."
821
  msgstr ""
822
 
823
  #: inc/views/inpost/seo-settings-singular.php:31
1271
  #. translators: %s = <code>rel</code>
1272
 
1273
  #: inc/views/metaboxes/general-metabox.php:305
1274
+ msgid "Add %s link tags to posts and pages?"
1275
  msgstr ""
1276
 
1277
  #. translators: %s = <code>rel</code>
1278
 
1279
  #: inc/views/metaboxes/general-metabox.php:309
1280
+ msgid "Add %s link tags to archives?"
1281
  msgstr ""
1282
 
1283
  #. translators: %s = <code>rel</code>
1284
 
1285
  #: inc/views/metaboxes/general-metabox.php:313
1286
+ msgid "Add %s link tags to the homepage?"
1287
  msgstr ""
1288
 
1289
  #: inc/views/metaboxes/general-metabox.php:337
1781
 
1782
  #: inc/views/metaboxes/sitemaps-metabox.php:101
1783
  #: inc/views/metaboxes/sitemaps-metabox.php:159
1784
+ #: inc/views/metaboxes/sitemaps-metabox.php:197
1785
  msgctxt "The sitemap can be found %s."
1786
  msgid "here"
1787
  msgstr ""
1797
  msgstr ""
1798
 
1799
  #: inc/views/metaboxes/sitemaps-metabox.php:115
1800
+ msgid "The sitemap is generated with three queries: Pages, posts, and other post types. This setting affects how many posts are requested from the database per query. The homepage and blog page are included separately."
1801
  msgstr ""
1802
 
1803
  #: inc/views/metaboxes/sitemaps-metabox.php:131
1845
  msgid "If you do not add the sitemap location to the robots.txt file, you will need to notify search engines manually through the Webmaster Console provided by the search engines."
1846
  msgstr ""
1847
 
1848
+ #: inc/views/metaboxes/sitemaps-metabox.php:183
1849
  msgid "Add sitemap location in robots.txt"
1850
  msgstr ""
1851
 
1852
+ #: inc/views/metaboxes/sitemaps-metabox.php:188
1853
  msgid "Add sitemap location in robots?"
1854
  msgstr ""
1855
 
1856
+ #: inc/views/metaboxes/sitemaps-metabox.php:188
1857
  msgid "This only has effect when the sitemap is active."
1858
  msgstr ""
1859
 
1860
+ #: inc/views/metaboxes/sitemaps-metabox.php:197
1861
  msgid "View robots.txt"
1862
  msgstr ""
1863
 
1864
+ #: inc/views/metaboxes/sitemaps-metabox.php:199
1865
  msgctxt "%s = here"
1866
  msgid "The robots.txt file can be found %s."
1867
  msgstr ""
1868
 
1869
+ #: inc/views/metaboxes/sitemaps-metabox.php:205
1870
  msgid "Timestamps Settings"
1871
  msgstr ""
1872
 
1873
+ #: inc/views/metaboxes/sitemaps-metabox.php:207
1874
  msgid "The modified time suggests to search engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed."
1875
  msgstr ""
1876
 
1877
  #. translators: %s = An XML tag example
1878
 
1879
+ #: inc/views/metaboxes/sitemaps-metabox.php:214
1880
+ #: inc/views/metaboxes/sitemaps-metabox.php:232
1881
  msgid "Add %s to the sitemap?"
1882
  msgstr ""
1883
 
1884
+ #: inc/views/metaboxes/sitemaps-metabox.php:223
1885
  msgid "Priority Settings"
1886
  msgstr ""
1887
 
1888
+ #: inc/views/metaboxes/sitemaps-metabox.php:225
1889
  msgid "The priority index suggests to search engines which pages are deemed more important. It has no known impact on the SEO value and it is generally ignored."
1890
  msgstr ""
1891
 
1892
+ #: inc/views/metaboxes/sitemaps-metabox.php:241
1893
  msgid "Ping Settings"
1894
  msgstr ""
1895
 
1896
+ #: inc/views/metaboxes/sitemaps-metabox.php:243
1897
  msgid "Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible."
1898
  msgstr ""
1899
 
1900
+ #: inc/views/metaboxes/sitemaps-metabox.php:244
1901
  msgid "By default this will happen at most once an hour."
1902
  msgstr ""
1903
 
1904
+ #: inc/views/metaboxes/sitemaps-metabox.php:249
1905
  msgid "Notify Search Engines"
1906
  msgstr ""
1907
 
1908
  #. translators: %s = Google
1909
 
1910
+ #: inc/views/metaboxes/sitemaps-metabox.php:261
1911
  msgid "Notify %s about sitemap changes?"
1912
  msgstr ""
1913
 
1914
+ #: inc/views/metaboxes/sitemaps-metabox.php:271
1915
  msgid "Sitemap Styling Settings"
1916
  msgstr ""
1917
 
1918
+ #: inc/views/metaboxes/sitemaps-metabox.php:273
1919
  msgid "You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever."
1920
  msgstr ""
1921
 
1922
+ #: inc/views/metaboxes/sitemaps-metabox.php:274
1923
  msgid "Note: Changes might not appear to have effect directly because the stylesheet is cached in the browser for 30 minutes."
1924
  msgstr ""
1925
 
1926
+ #: inc/views/metaboxes/sitemaps-metabox.php:278
1927
  msgid "Enable styling"
1928
  msgstr ""
1929
 
1930
+ #: inc/views/metaboxes/sitemaps-metabox.php:285
1931
  msgid "Style Sitemap?"
1932
  msgstr ""
1933
 
1934
+ #: inc/views/metaboxes/sitemaps-metabox.php:285
1935
  msgid "This makes the sitemap more readable for humans."
1936
  msgstr ""
1937
 
1938
+ #: inc/views/metaboxes/sitemaps-metabox.php:294
1939
  msgid "Style configuration"
1940
  msgstr ""
1941
 
1942
+ #: inc/views/metaboxes/sitemaps-metabox.php:302
1943
  msgid "Add site logo?"
1944
  msgstr ""
1945
 
1946
+ #: inc/views/metaboxes/sitemaps-metabox.php:302
1947
  msgid "The logo is set in Customizer."
1948
  msgstr ""
1949
 
1950
+ #: inc/views/metaboxes/sitemaps-metabox.php:315
1951
  msgid "Sitemap header background color"
1952
  msgstr ""
1953
 
1954
+ #: inc/views/metaboxes/sitemaps-metabox.php:324
1955
  msgid "Sitemap title and lines color"
1956
  msgstr ""
1957
 
1972
  msgstr ""
1973
 
1974
  #: inc/views/metaboxes/social-metabox.php:77
1975
+ msgid "Facebook, Twitter, Pinterest and many other social sites make use of these meta tags."
1976
  msgstr ""
1977
 
1978
  #: inc/views/metaboxes/social-metabox.php:84
1979
+ msgid "Note: Another Open Graph plugin has been detected. These meta tags might conflict."
1980
  msgstr ""
1981
 
1982
  #: inc/views/metaboxes/social-metabox.php:90
1987
 
1988
  #: inc/views/metaboxes/social-metabox.php:92
1989
  #: inc/views/metaboxes/social-metabox.php:104
1990
+ msgid "Output various meta tags targeted at %s."
1991
  msgstr ""
1992
 
1993
  #: inc/views/metaboxes/social-metabox.php:102
1995
  msgstr ""
1996
 
1997
  #: inc/views/metaboxes/social-metabox.php:111
1998
+ msgid "Note: Another Twitter Card plugin has been detected. These meta tags might conflict."
1999
  msgstr ""
2000
 
2001
  #: inc/views/metaboxes/social-metabox.php:118
2116
  msgid "Posts"
2117
  msgstr ""
2118
 
2119
+ #: inc/views/metaboxes/social-metabox.php:316
 
 
 
 
2120
  msgid "Post Date Settings"
2121
  msgstr ""
2122
 
2123
+ #: inc/views/metaboxes/social-metabox.php:318
2124
+ msgid "Some social sites output the publishing and modified date in the sharing snippet."
2125
  msgstr ""
2126
 
2127
+ #. translators: %s = code example
2128
 
 
2129
  #: inc/views/metaboxes/social-metabox.php:329
2130
+ msgid "Add %s to posts?"
2131
  msgstr ""
2132
 
2133
  #: inc/views/metaboxes/title-metabox.php:21
2166
  msgstr ""
2167
 
2168
  #: inc/views/metaboxes/title-metabox.php:143
2169
+ msgid "The homepage has a specific option."
2170
  msgstr ""
2171
 
2172
  #: inc/views/metaboxes/title-metabox.php:148
2182
  msgstr ""
2183
 
2184
  #: inc/views/metaboxes/title-metabox.php:180
2185
+ msgid "If the title consists of multiple parts (original title, pagination, and blogname), then the separator will go in-between them."
2186
  msgstr ""
2187
 
2188
  #: inc/views/metaboxes/title-metabox.php:192
lib/js/pt.js CHANGED
@@ -44,7 +44,7 @@ window.tsfPT = function( $ ) {
44
  * @access private
45
  * @type {(Object<string, *>)|boolean|null} l10n Localized strings
46
  */
47
- var l10n = 'undefined' !== typeof tsfPTL10n && tsfPTL10n;
48
 
49
  /**
50
  * Initializes primary term selection.
@@ -81,6 +81,8 @@ window.tsfPT = function( $ ) {
81
  box$ = {},
82
  primaries = {};
83
 
 
 
84
  const addInput = ( taxonomy ) => {
85
  let $wrap = $( '#' + taxonomy + 'div' ),
86
  template = inputTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } );
@@ -179,13 +181,21 @@ window.tsfPT = function( $ ) {
179
  }
180
 
181
  const setPrimary = ( event ) => {
182
- let taxonomy = event.data.taxonomy,
183
- value = $( event.target ).closest( 'label' ).find( 'input[type=checkbox]' ).val();
 
 
 
 
 
 
 
 
184
 
185
  unsetPrimaries( taxonomy );
186
- makePrimary( taxonomy, value );
187
 
188
- //= Stop propagation
189
  return false;
190
  }
191
  const toggleShowSwitch = ( event ) => {
@@ -200,31 +210,35 @@ window.tsfPT = function( $ ) {
200
  }
201
 
202
  switch ( uniqueChecked$[ taxonomy ].length ) {
203
- case 0 :
204
  unsetPrimaries( taxonomy );
205
  break;
206
 
207
- case 1 :
208
  makeFirstPrimary( taxonomy );
209
  break;
210
  }
211
  }
212
  const appendButton = ( taxonomy, element ) => {
213
- let $label;
214
  getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
215
  $label = $( e ).closest( 'label' );
216
  if ( ! $label.find( '.tsf-primary-term-selector' ).length ) {
217
- $label.find( 'input' ).after( createSelector( taxonomy ) );
 
218
  }
219
  } );
220
  }
221
  const removeButton = ( taxonomy, element ) => {
222
  let $label, wasPrimary;
223
  getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
224
- $label = $( e ).closest( 'label' );
225
  wasPrimary = $label.hasClass( 'tsf-is-primary-term' );
 
226
  $label.removeClass( 'tsf-is-primary-term' );
 
227
  $label.find( '.tsf-primary-term-selector' ).remove();
 
228
  if ( wasPrimary ) makeFirstPrimary( taxonomy );
229
  } );
230
  }
@@ -266,25 +280,26 @@ window.tsfPT = function( $ ) {
266
  }
267
  }
268
  const initActions = ( taxonomy ) => {
269
- let ns = 'tsfShowPrimary' + taxonomy,
270
- data = { 'taxonomy': taxonomy },
271
  $box = getBox( taxonomy ),
272
  $div = $( '#' + taxonomy + 'div' ),
273
  $tabs = $( '#' + taxonomy + '-tabs' ),
274
  $postbox = $box.closest( '.postbox' );
275
 
276
- $box.off( 'click.' + ns );
277
- $box.on( 'click.' + ns, 'input[type="checkbox"]', data, toggleShowSwitch );
278
- $box.on( 'click.' + ns, '.tsf-primary-term-selector', data, setPrimary );
 
 
279
 
280
- $div.off( 'wpListAddEnd.' + ns );
281
- $div.on( 'wpListAddEnd.' + ns, '#' + taxonomy + 'checklist', updateList );
282
 
283
- $tabs.off( 'click.' + ns );
284
- $tabs.on( 'click.' + ns, 'a', data, fixHelpPosOnTabToggle );
285
 
286
- $postbox.off( 'click.postboxes.' + ns );
287
- $postbox.on( 'click.postboxes.' + ns, data, togglePostbox );
288
  }
289
  const reload = ( taxonomy ) => {
290
  getBox( taxonomy ).find( 'input[type="checkbox"]:checked' )
44
  * @access private
45
  * @type {(Object<string, *>)|boolean|null} l10n Localized strings
46
  */
47
+ let l10n = 'undefined' !== typeof tsfPTL10n && tsfPTL10n;
48
 
49
  /**
50
  * Initializes primary term selection.
81
  box$ = {},
82
  primaries = {};
83
 
84
+ const nsAction = ( action, taxonomy ) => action + '.tsfShowPrimary' + taxonomy;
85
+
86
  const addInput = ( taxonomy ) => {
87
  let $wrap = $( '#' + taxonomy + 'div' ),
88
  template = inputTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } );
181
  }
182
 
183
  const setPrimary = ( event ) => {
184
+ let taxonomy = event.data.taxonomy;
185
+
186
+ if ( event.target instanceof HTMLInputElement ) {
187
+ // Stop the loop.
188
+ event.stopPropagation();
189
+
190
+ $( event.target ).closest( '.tsf-set-primary-term' ).trigger( nsAction( 'click', taxonomy ) );
191
+ // Forward default: Check the button.
192
+ return true;
193
+ }
194
 
195
  unsetPrimaries( taxonomy );
196
+ makePrimary( taxonomy, $( event.target ).closest( 'label' ).find( 'input[type=checkbox]' ).val() );
197
 
198
+ //= Stop default, don't deselect the term.
199
  return false;
200
  }
201
  const toggleShowSwitch = ( event ) => {
210
  }
211
 
212
  switch ( uniqueChecked$[ taxonomy ].length ) {
213
+ case 0:
214
  unsetPrimaries( taxonomy );
215
  break;
216
 
217
+ case 1:
218
  makeFirstPrimary( taxonomy );
219
  break;
220
  }
221
  }
222
  const appendButton = ( taxonomy, element ) => {
223
+ let $label, selector;
224
  getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
225
  $label = $( e ).closest( 'label' );
226
  if ( ! $label.find( '.tsf-primary-term-selector' ).length ) {
227
+ selector = createSelector( taxonomy );
228
+ $label.find( 'input' ).after( selector );
229
  }
230
  } );
231
  }
232
  const removeButton = ( taxonomy, element ) => {
233
  let $label, wasPrimary;
234
  getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
235
+ $label = $( e ).closest( 'label' );
236
  wasPrimary = $label.hasClass( 'tsf-is-primary-term' );
237
+
238
  $label.removeClass( 'tsf-is-primary-term' );
239
+ // This should also remove all attached events.
240
  $label.find( '.tsf-primary-term-selector' ).remove();
241
+
242
  if ( wasPrimary ) makeFirstPrimary( taxonomy );
243
  } );
244
  }
280
  }
281
  }
282
  const initActions = ( taxonomy ) => {
283
+ let data = { 'taxonomy': taxonomy },
 
284
  $box = getBox( taxonomy ),
285
  $div = $( '#' + taxonomy + 'div' ),
286
  $tabs = $( '#' + taxonomy + '-tabs' ),
287
  $postbox = $box.closest( '.postbox' );
288
 
289
+ let defaultClickAction = nsAction( 'click', taxonomy );
290
+
291
+ $box.off( defaultClickAction )
292
+ .on( defaultClickAction, 'input[type="checkbox"]', data, toggleShowSwitch )
293
+ .on( defaultClickAction, '.tsf-primary-term-selector', data, setPrimary );
294
 
295
+ $div.off( nsAction( 'wpListAddEnd', taxonomy ) )
296
+ .on( nsAction( 'wpListAddEnd', taxonomy ), '#' + taxonomy + 'checklist', updateList );
297
 
298
+ $tabs.off( defaultClickAction )
299
+ .on( defaultClickAction, 'a', data, fixHelpPosOnTabToggle );
300
 
301
+ $postbox.off( nsAction( 'click.postboxes', taxonomy ) )
302
+ .on( nsAction( 'click.postboxes', taxonomy ), data, togglePostbox );
303
  }
304
  const reload = ( taxonomy ) => {
305
  getBox( taxonomy ).find( 'input[type="checkbox"]:checked' )
lib/js/pt.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfPT=function(a){var b='undefined'!=typeof tsfPTL10n&&tsfPTL10n;const c=function(){if(tsf.hasInput&&Object.keys(b.taxonomies).length){let d=b.taxonomies,f=wp.template('tsf-primary-term-selector'),g=wp.template('tsf-primary-term-selector-help'),h=document.createElement('span');h.classList.add('tsf-primary-term-selector'),h.classList.add('tsf-set-primary-term'),function(){let L=document.createElement('input');L.setAttribute('type','radio'),h.appendChild(L)}();let i={},j={},k={},l={},m={};const n=function(L){let M=a('#'+L+'div'),N=f({taxonomy:d[L]});M.append(N)},o=function(L){let M=a('#taxonomy-'+L),N=g({taxonomy:d[L]});M.append(N),tsfTT.triggerReset(),p(L)},p=function(L){let M=document.getElementById('taxonomy-'+L),N=M.querySelectorAll('.tabs-panel'),O=a(M).closest('.postbox');if(!(O.length&&O.hasClass('closed'))){let P=Array.prototype.slice.call(N).filter(function(R){return 0<R.offsetWidth||0<R.offsetHeight||0<R.getClientRects().length})[0];if(P){let Q=P.scrollHeight>P.clientHeight?P.offsetWidth-P.clientWidth+25-2:25;tsf.states.isRTL?M.querySelector('.tsf-primary-term-selector-help-wrap').style.left=Q+'px':M.querySelector('.tsf-primary-term-selector-help-wrap').style.right=Q+'px'}}},q=function(L){p(L.data.taxonomy)},r=function(L){let M=h.cloneNode(!0);return M.setAttribute('title',d[L].i18n.makePrimary),M.setAttribute('aria-label',d[L].i18n.makePrimary),M},s=function(L,M){let N=document.getElementById('autodescription[_primary_term_'+L+']');N&&N instanceof Element&&(N.value=M||0)},t=function(L,M){return!M&&l[L]?l[L]:(l[L]=a('#'+L+'checklist, #'+L+'checklist-pop'),l[L])},u=function(L,M){return i[L].filter('[value="'+M+'"]')},v=function(L,M){let N=u(L,M).closest('label');N.length?(N.addClass('tsf-is-primary-term'),N.find('.tsf-set-primary-term').each(function(O,P){P.setAttribute('title',d[L].i18n.primary),P.setAttribute('aria-label',d[L].i18n.primary),P.querySelector('input').checked=!0}),s(L,M),m[L]=M):x(L)},w=function(L){let M=t(L).find('label');M.removeClass('tsf-is-primary-term'),M.find('.tsf-set-primary-term').each(function(N,O){O.setAttribute('title',d[L].i18n.makePrimary),O.setAttribute('aria-label',d[L].i18n.makePrimary),O.querySelector('input').checked=!1}),s(L,0),m[L]=0},x=function(L){let N,M=k[L].first();M.length?(N=M.val()||'',v(L,N),m[L]=N):m[L]=0},y=function(L){let M=L.data.taxonomy,N=a(L.target).closest('label').find('input[type=checkbox]').val();return w(M),v(M,N),!1},z=function(L){let M=L.data.taxonomy;switch(L.target.checked?(C(M,L.target),A(M,L.target)):(D(M,L.target),B(M,L.target)),k[M].length){case 0:w(M);break;case 1:x(M);}},A=function(L,M){let N;u(L,M.value).each(function(O,P){N=a(P).closest('label'),N.find('.tsf-primary-term-selector').length||N.find('input').after(r(L))})},B=function(L,M){let N,O;u(L,M.value).each(function(P,Q){N=a(Q).closest('label'),O=N.hasClass('tsf-is-primary-term'),N.removeClass('tsf-is-primary-term'),N.find('.tsf-primary-term-selector').remove(),O&&x(L)})},C=function(L,M){j[L]=j[L].add('[value="'+M.value+'"]'),k[L]=k[L].add(M)},D=function(L,M){j[L]=j[L].not('[value="'+M.value+'"]'),k[L]=k[L].not('[value="'+M.value+'"]')},E=function(L){p(L.data.taxonomy)},F=function(L){let M=t(L,1);i[L]=M.find('input[type=checkbox]'),j[L]=M.find('input[type=checkbox]:checked');let O,N={};k[L]=j[L],k[L].each(function(P,Q){O=a(Q).val(),N[O]?k[L].splice(P,1):N[O]=!0})},G=function(L,M,N){N.hasOwnProperty('settings')&&N.settings.hasOwnProperty('what')&&(F(N.settings.what),H(N.settings.what),I(N.settings.what),p(N.settings.what))},H=function(L){let M='tsfShowPrimary'+L,N={taxonomy:L},O=t(L),P=a('#'+L+'div'),Q=a('#'+L+'-tabs'),R=O.closest('.postbox');O.off('click.'+M),O.on('click.'+M,'input[type="checkbox"]',N,z),O.on('click.'+M,'.tsf-primary-term-selector',N,y),P.off('wpListAddEnd.'+M),P.on('wpListAddEnd.'+M,'#'+L+'checklist',G),Q.off('click.'+M),Q.on('click.'+M,'a',N,q),R.off('click.postboxes.'+M),R.on('click.postboxes.'+M,N,E)},I=function(L){t(L).find('input[type="checkbox"]:checked').each(function(M,N){A(L,N)}),m[L]?v(L,m[L]):x(L)},J=function(L){t(L).find('input[type="checkbox"]:checked').each(function(M,N){A(L,N)}),d[L].primary?v(L,d[L].primary):x(L)};(function(){for(let L in d)t(L).length&&(n(L),o(L),F(L),H(L),J(L))})()}};return a.extend({load:function(){a(document.body).on('tsf-onload',c)}},{})}(jQuery),jQuery(window.tsfPT.load);
1
+ 'use strict';window.tsfPT=function(a){let b="undefined"!=typeof tsfPTL10n&&tsfPTL10n;const c=()=>{if(!tsf.hasInput||!Object.keys(b.taxonomies).length)return;let c=b.taxonomies,d=wp.template("tsf-primary-term-selector"),e=wp.template("tsf-primary-term-selector-help"),f=document.createElement("span");f.classList.add("tsf-primary-term-selector"),f.classList.add("tsf-set-primary-term"),(()=>{let a=document.createElement("input");a.setAttribute("type","radio"),f.appendChild(a)})();let g={},h={},i={},j={},k={};const l=(a,b)=>a+".tsfShowPrimary"+b,m=b=>{let e=a("#"+b+"div"),f=d({taxonomy:c[b]});e.append(f)},n=b=>{let d=a("#taxonomy-"+b),f=e({taxonomy:c[b]});d.append(f),tsfTT.triggerReset(),o(b)},o=b=>{let c=document.getElementById("taxonomy-"+b),d=c.querySelectorAll(".tabs-panel"),e=a(c).closest(".postbox");if(!(e.length&&e.hasClass("closed"))){let a=Array.prototype.slice.call(d).filter(a=>0<a.offsetWidth||0<a.offsetHeight||0<a.getClientRects().length)[0];if(a){let b=a.scrollHeight>a.clientHeight?a.offsetWidth-a.clientWidth+25-2:25;tsf.states.isRTL?c.querySelector(".tsf-primary-term-selector-help-wrap").style.left=b+"px":c.querySelector(".tsf-primary-term-selector-help-wrap").style.right=b+"px"}}},p=a=>{o(a.data.taxonomy)},q=a=>{let b=f.cloneNode(!0);return b.setAttribute("title",c[a].i18n.makePrimary),b.setAttribute("aria-label",c[a].i18n.makePrimary),b},r=(a,b)=>{let c=document.getElementById("autodescription[_primary_term_"+a+"]");c&&c instanceof Element&&(c.value=b||0)},s=(b,c)=>!c&&j[b]?j[b]:(j[b]=a("#"+b+"checklist, #"+b+"checklist-pop"),j[b]),t=(a,b)=>g[a].filter("[value=\""+b+"\"]"),u=(a,b)=>{let d=t(a,b).closest("label");d.length?(d.addClass("tsf-is-primary-term"),d.find(".tsf-set-primary-term").each(function(b,d){d.setAttribute("title",c[a].i18n.primary),d.setAttribute("aria-label",c[a].i18n.primary),d.querySelector("input").checked=!0}),r(a,b),k[a]=b):w(a)},v=a=>{let b=s(a).find("label");b.removeClass("tsf-is-primary-term"),b.find(".tsf-set-primary-term").each(function(b,d){d.setAttribute("title",c[a].i18n.makePrimary),d.setAttribute("aria-label",c[a].i18n.makePrimary),d.querySelector("input").checked=!1}),r(a,0),k[a]=0},w=a=>{let b,c=i[a].first();c.length?(b=c.val()||"",u(a,b),k[a]=b):k[a]=0},x=b=>{let c=b.data.taxonomy;return b.target instanceof HTMLInputElement?(b.stopPropagation(),a(b.target).closest(".tsf-set-primary-term").trigger(l("click",c)),!0):(v(c),u(c,a(b.target).closest("label").find("input[type=checkbox]").val()),!1)},y=a=>{let b=a.data.taxonomy;switch(a.target.checked?(B(b,a.target),z(b,a.target)):(C(b,a.target),A(b,a.target)),i[b].length){case 0:v(b);break;case 1:w(b);}},z=(b,c)=>{let d,f;t(b,c.value).each((c,g)=>{d=a(g).closest("label"),d.find(".tsf-primary-term-selector").length||(f=q(b),d.find("input").after(f))})},A=(b,c)=>{let d,f;t(b,c.value).each((c,g)=>{d=a(g).closest("label"),f=d.hasClass("tsf-is-primary-term"),d.removeClass("tsf-is-primary-term"),d.find(".tsf-primary-term-selector").remove(),f&&w(b)})},B=(a,b)=>{h[a]=h[a].add("[value=\""+b.value+"\"]"),i[a]=i[a].add(b)},C=(a,b)=>{h[a]=h[a].not("[value=\""+b.value+"\"]"),i[a]=i[a].not("[value=\""+b.value+"\"]")},D=a=>{o(a.data.taxonomy)},E=function(b){let c=s(b,1);g[b]=c.find("input[type=checkbox]"),h[b]=c.find("input[type=checkbox]:checked");let d,e={};i[b]=h[b],i[b].each(function(c,f){d=a(f).val(),e[d]?i[b].splice(c,1):e[d]=!0})},F=(a,b,c)=>{c.hasOwnProperty("settings")&&c.settings.hasOwnProperty("what")&&(E(c.settings.what),G(c.settings.what),H(c.settings.what),o(c.settings.what))},G=b=>{let c={taxonomy:b},d=s(b),e=a("#"+b+"div"),f=a("#"+b+"-tabs"),g=d.closest(".postbox"),h=l("click",b);d.off(h).on(h,"input[type=\"checkbox\"]",c,y).on(h,".tsf-primary-term-selector",c,x),e.off(l("wpListAddEnd",b)).on(l("wpListAddEnd",b),"#"+b+"checklist",F),f.off(h).on(h,"a",c,p),g.off(l("click.postboxes",b)).on(l("click.postboxes",b),c,D)},H=a=>{s(a).find("input[type=\"checkbox\"]:checked").each((b,c)=>{z(a,c)}),k[a]?u(a,k[a]):w(a)},I=a=>{s(a).find("input[type=\"checkbox\"]:checked").each((b,c)=>{z(a,c)}),c[a].primary?u(a,c[a].primary):w(a)};(()=>{for(let a in c)s(a).length&&(m(a),n(a),E(a),G(a),I(a))})()};return a.extend({load:function(){a(document.body).on("tsf-onload",c)}},{})}(jQuery),jQuery(window.tsfPT.load);
lib/js/tsf.js CHANGED
@@ -480,9 +480,12 @@ window.tsf = {
480
  bar.classList.add( newClass );
481
  sub.style.width = newWidth;
482
 
483
- // Update tooltip.
484
  bar.dataset.desc = label;
485
- bar.setAttribute( 'aria-label', label );
 
 
 
486
  tsfTT.triggerUpdate( bar );
487
  },
488
 
480
  bar.classList.add( newClass );
481
  sub.style.width = newWidth;
482
 
483
+ // Update tooltip and ARIA label.
484
  bar.dataset.desc = label;
485
+ // Replace HTML with spaces. TODO see TSF's PHP-code `strip_tags_cs()` for a better solution.
486
+ // NOTE: Screen readers don't always read out HTML entities as intended. They should fix that, not us, as it's an escaping issue.
487
+ bar.setAttribute( 'aria-label', tsf.escapeString( label.replace( /(<([^>]+)?>?)/ig, ' ' ) ) );
488
+
489
  tsfTT.triggerUpdate( bar );
490
  },
491
 
lib/js/tsf.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsf={nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,settingsChanged:!1,counterType:0,hasInput:!1,browseUnhappy:!!navigator.userAgent.match(/Trident\/7\./),counterClasses:{0:'tsf-counter-zero',1:'tsf-counter-one',2:'tsf-counter-two',3:'tsf-counter-three'},confirm:function(t){return confirm(t)},stripTags:function(t){return t.replace(/(<([^>]+)?>?)/ig,'')},escapeString:function(t){if(!t.length)return'';let s={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;','\'':'&#039;','\\\\':'&#92;','\\':''};return t.replace(/[&<>"']|\\\\|\\/g,function(n){return s[n]})},unescapeString:function(t){if(!t.length)return'';let s={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;','\'':'&#039;','\\':'&#92;'},n={};n=tsf.browseUnhappy?Object.keys(s).map(function(o){return s[o]}):Object.values(s);let a=new RegExp(n.map(function(o){return o.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,'\\$&')}).join('|'),'g');return tsf.browseUnhappy?t.replace(a,function(o){for(let r in s)if(s[r]===o)return r;return o}):t.replace(a,function(o){return Object.keys(s).find(function(r){return s[r]===o})})},sDoubleSpace:function(t){return t.replace(/\s\s+/g,' ')},getStringLength:function(t){let s,n=0;return t.length&&(s=document.createElement('span'),s.innerHTML=tsf.escapeString(t).trim(),'undefined'!=typeof s.childNodes[0]&&(n=s.childNodes[0].nodeValue.length)),+n},convertJSONResponse:function(t){let s=t&&t.json||void 0,n=1===s;if(!n){let a=t;try{t=JSON.parse(t),n=!0}catch(o){n=!1}n||(t=a)}return t},updateCharacterCounter:function(t){let s=t.e,n=t.text,a=t.guidelines,o=tsf.getStringLength(n),r='',l='',c={bad:'tsf-count-bad',okay:'tsf-count-okay',good:'tsf-count-good',unknown:'tsf-count-unknown'};switch(o?o<a.lower?(r=c.bad,l=tsf.i18n.inputGuidelines.short.farTooShort):o<a.goodLower?(r=c.okay,l=tsf.i18n.inputGuidelines.short.tooShort):o>a.upper?(r=c.bad,l=tsf.i18n.inputGuidelines.short.farTooLong):o>a.goodUpper?(r=c.okay,l=tsf.i18n.inputGuidelines.short.tooLong):(r=c.good,l=tsf.i18n.inputGuidelines.short.good):(r=c.unknown,l=tsf.i18n.inputGuidelines.short.empty),tsf.counterType){case 3:l=o.toString()+' - '+l;break;case 2:break;case 1:default:l=o.toString();}for(let g in s.innerHTML=l,c)s.classList.remove(c[g]);for(let g in tsf.counterClasses)s.classList.remove(tsf.counterClasses[g]);s.classList.add(r),s.classList.add(tsf.counterClasses[tsf.counterType])},updatePixelCounter:function(t){let s=t.e,n=t.text,a=t.guidelines,o=s.parentElement;if(o){let r=o.querySelector('.tsf-pixel-counter-bar'),l=o.querySelector('.tsf-pixel-counter-shadow');if(r&&l){l.innerHTML=tsf.escapeString(n);let c=l.offsetWidth,g='',d='',u='',f={bad:'tsf-pixel-counter-bad',okay:'tsf-pixel-counter-okay',good:'tsf-pixel-counter-good',unknown:'tsf-pixel-counter-unknown'};d=100*(c/a.goodUpper)+'%',c?c<a.lower?(g=f.bad,u=tsf.i18n.inputGuidelines.long.farTooShort):c<a.goodLower?(g=f.okay,u=tsf.i18n.inputGuidelines.long.tooShort):c>a.upper?(d=100*(a.upper/(c+2*(c-a.upper)/3))+'%',g=f.bad,u=tsf.i18n.inputGuidelines.long.farTooLong):c>a.goodUpper?(g=f.okay,u=tsf.i18n.inputGuidelines.long.tooLong,d='100%'):(g=f.good,u=tsf.i18n.inputGuidelines.long.good):(g=f.unknown,d='100%',u=tsf.i18n.inputGuidelines.long.empty);let b,h=r.querySelector('.tsf-pixel-counter-fluid');for(let x in b=tsf.i18n.pixelsUsed.replace(/%1\$d/g,c),b=b.replace(/%2\$d/g,a.goodUpper),b=b+'<br>'+u,f)r.classList.remove(f[x]);r.classList.add(g),h.style.width=d,r.dataset.desc=b,r.setAttribute('aria-label',b),tsfTT.triggerUpdate(r)}}},_initTitleInputs:function(){if(tsf.hasInput){let t=jQuery(['#autodescription_title','#autodescription-meta\\[doctitle\\]','#autodescription-site-settings\\[homepage_title\\]'].join(', '));if(t.length){let n,a,o,l,s=!1,r='',c='',g=tsf.params.titleSeparator,d=tsf.params.defaultTitle,u=tsf.states.useTagline,f=tsf.states.isRTL,h=tsf.states.isPrivate,b=tsf.states.isPasswordProtected,x=tsf.states.stripTitleTags;n=f?'after':'before';const y=function(){let Q='before';tsf.states.isSettingsPage?f?'right'===jQuery('#tsf-home-title-location input:checked').val()&&(Q='after'):'left'===jQuery('#tsf-home-title-location input:checked').val()&&(Q='after'):tsf.states.isHome?f?'right'===tsf.params.titleLocation&&(Q='after'):'left'===tsf.params.titleLocation&&(Q='after'):f?'left'===tsf.params.titleLocation&&(Q='after'):'right'===tsf.params.titleLocation&&(Q='after'),a=Q};y();const _=function(){let Q='';if(!tsf.states.isSettingsPage)tsf.states.isHome?u&&(Q=tsf.params.titleAdditions):u&&(Q=tsf.params.titleAdditions);else if(u){let X=document.getElementById('autodescription-site-settings[homepage_title_tagline]'),Y=X&&X.value||'';Y=tsf.sDoubleSpace(Y.trim()),Q=Y.length?Y:tsf.params.blogDescription}Q.length&&(Q=tsf.escapeString(tsf.sDoubleSpace(Q.trim())),'before'===a?Q=Q+' '+g+' ':'after'===a?Q=' '+g+' '+Q:void 0),c=Q.length?Q:'',l=document.getElementById('tsf-title-placeholder'),c.length&&l&&(l.innerHTML=c)};_();const L=function(){let Q='';h?Q=tsf.i18n.privateTitle:b&&(Q=tsf.i18n.protectedTitle),Q.length&&(Q=tsf.escapeString(Q),'before'===n?Q+=' ':'after'===n?Q=' '+Q:void 0),r=Q.length?Q:'',r.length&&o&&(o.innerHTML=r),o=document.getElementById('tsf-title-placeholder-prefix'),r.length&&o&&(o.innerHTML=r)};L();const C=function(Q){if(l||o){let X=jQuery(Q.target),Y=X.val(),Z=!!c.length,ee=!!r.length;if(!Z&&l&&(l.style.display='none'),!ee&&o&&(o.style.display='none'),!Z&&!ee)return void X.css('text-indent','initial');if(!Y.length)return X.css('text-indent','initial'),l&&(l.style.display='none'),void(o&&(o.style.display='none'));let te=X.outerWidth(!0),se=(X.outerHeight(!0)-X.height())/2,ie=(te-X.innerWidth())/2,ne=f?'right':'left',ae=(X.outerWidth(!0)-X.width())/2,oe={display:X.css('display'),lineHeight:X.css('lineHeight'),fontFamily:X.css('fontFamily'),fontWeight:X.css('fontWeight'),fontSize:X.css('fontSize'),letterSpacing:X.css('letterSpacing'),paddingTop:se+'px',paddingBottom:se+'px'},re=jQuery(o),le=jQuery(l),pe=0,ce=0,ge=0,de=0,ue=0,fe=0;if(ee&&(re.css(oe),re.css({maxWidth:'initial'}),ue=re[0].getBoundingClientRect().width,ue<fe&&(ue=0)),Z){let me=0;switch(function(){let be=jQuery('#tsf-title-offset');be.text(Y),be.css({fontFamily:oe.fontFamily,fontWeight:oe.fontWeight,letterSpacing:oe.letterSpacing,fontSize:oe.fontSize}),me=be[0].getBoundingClientRect().width}(),pe=X[0].getBoundingClientRect().width-ie-ae-me-ue,pe<fe&&(ue+=pe,pe=0),le.css(oe),le.css({maxWidth:'initial'}),a){case'before':let be=le[0].getBoundingClientRect().width;be=pe<be?pe:be,be<fe&&(be=0),pe=be,de+=pe,ge+=pe,ce+=ae;break;case'after':ce+=ae+me+ue;}}ge+=ae,ue=0>ue?0:ue,de+=ue;let he;ee&&(he={},he[ne]=ge+'px',he.maxWidth=ue+'px',re.css(he)),Z&&(he={},he[ne]=ce+'px',he.maxWidth=pe+'px',le.css(he)),he={},he['text-indent']=de+'px',X.css(he)}},w=function(){let X='',Y=!!c.length,Z=!!r.length,ee=c,te=r;tsf.states.isTermEdit&&tsf.params.termName&&(te=f?' :'+tsf.params.termName:tsf.params.termName+': ',Z=tsf.states.useTermPrefix),X=d,Z&&('before'===n?X=te+X:'after'===n?X+=te:void 0),Y&&('before'===a?X=ee+X:'after'===a?X+=ee:void 0),tsf.browseUnhappy&&(s=!0);let se=document.createElement('span');se.innerHTML=tsf.escapeString(tsf.sDoubleSpace(X)),t.prop('placeholder',tsf.unescapeString(se.textContent)),tsf.browseUnhappy&&setTimeout(function(){s=!1},0)},T=function(Q){let X=document.getElementById('tsf-title-reference'),Y=Q.target.value;X&&(Y=Y.trim(),1>Y.length||tsf.states.homeLocks.refTitleLock?Y=Q.target.placeholder:(r.length&&('before'===n?Y=r+Y:'after'===n?Y+=r:void 0),c.length&&('before'===a?Y=c+Y:'after'===a?Y+=c:void 0)),X.innerHTML=tsf.escapeString(tsf.sDoubleSpace(Y)),setTimeout(function(){jQuery(X).change()},0))},S=function(Q){let X=document.getElementById(Q.target.id+'_chars'),Y=document.getElementById('tsf-title-reference');if(X&&Y){let Z={e:X,text:tsf.unescapeString(Y.innerHTML),guidelines:tsf.params.inputGuidelines.title.search.chars};tsf.updateCharacterCounter(Z)}},I=function(Q){let X=document.getElementById(Q.target.id+'_pixels'),Y=document.getElementById('tsf-title-reference');if(X&&Y){let Z={e:X,text:tsf.unescapeString(Y.innerHTML),guidelines:tsf.params.inputGuidelines.title.search.pixels};tsf.updatePixelCounter(Z)}};t.on('input.tsfUpdateTitles',function(Q){return!s&&void(C(Q),w(),T(Q),S(Q),I(Q))});t.on('tsf-update-title-counter',function(Q){T(Q),S(Q),I(Q)});const U=function(){t.trigger('tsf-update-title-counter')},P=function(){_(),z()};jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').on('input',P),jQuery('#autodescription-site-settings\\[homepage_tagline\\]').on('change',P);jQuery('#tsf-title-tagline-toggle :input').on('click',function(Q){let X=u;jQuery(Q.target).is(':checked')?(jQuery('.tsf-custom-blogname-js').css('display','inline'),u=!0):(jQuery('.tsf-custom-blogname-js').css('display','none'),u=!1),X^u&&(_(),O())});const H=function(Q){switch(h=!1,b=!1,Q){case'password':b=!0;break;case'private':h=!0;break;default:case'public':}L(),O()};jQuery(document).on('tsf-updated-gutenberg-visibility',function(Q,X){return H(X)});jQuery('#visibility .save-post-visibility').on('click',function(){let X=jQuery('#visibility').find('input:radio:checked').val();if('password'===X){let Y=jQuery('#visibility').find('#post_password').val(),Z=!!Y&&!!Y.length;Z||(X='public')}H(X)});jQuery('#tsf-title-separator :input').on('click',function(Q){let X=jQuery(Q.target).val(),Y='';Y='pipe'===X?'|':'dash'===X?'-':jQuery('<div/>').html('&'+X+';').text(),g=Y,jQuery('.tsf-sep-js').text(' '+g+' '),_(),O()});const z=function(){t.trigger('input.tsfUpdateTitles')};let B=0;const O=function(){clearTimeout(B),B=setTimeout(z,10)};jQuery(window).on('tsf-counter-updated',O);const G=function(){let Q=tsf.settingsChanged;z(),tsf.settingsChanged=Q};let A=0;const M=function(){clearTimeout(A),A=setTimeout(G,10)};jQuery(window).on('tsf-flex-resize',M),jQuery('#tsf-homepage-tab-general').on('tsf-tab-toggled',M),jQuery('#tsf-flex-inpost-tab-general').on('tsf-flex-tab-toggled',M),M();let N=['autodescription-homepage-settings','tsf-inpost-box'];jQuery(document).on('postbox-toggled',function(Q,X){if(0<=N.indexOf(X.id)){let Y=X.querySelector('.inside');0<Y.offsetHeight&&0<Y.offsetWidth&&G()}});jQuery('#tsf-home-title-location :input').on('click',function(){y(),_(),O()});const V=function(Q){Q='string'==typeof Q&&Q.trim()||'',d=Q.length?tsf.escapeString(x?tsf.stripTags(Q):Q):tsf.params.untitledTitle,w(),U()};tsf.states.isHome||(jQuery('#edittag #name, #titlewrap #title').on('input',function(Q){return V(Q.target.value)}),jQuery(document).on('tsf-updated-gutenberg-title',function(Q,X){return V(X)}));tsf.states.isHome||(jQuery('#autodescription_title_no_blogname').on('change',function(Q){if(!tsf.states.taglineLocked){let X=u;u=!jQuery(Q.target).is(':checked'),X^u&&(_(),O())}}),jQuery('#autodescription_title_no_blogname').trigger('change'));(function(){let Q=0,X=window.innerWidth;window.addEventListener('resize',function(){clearTimeout(Q),Q=setTimeout(function(){let Y=window.innerWidth;X<Y?782>=X&&782<=Y&&G():782<=X&&782>=Y&&G(),X=Y},50)})})()}}},_initUnboundTitleSettings:function(){if(tsf.hasInput){let t=jQuery(['#autodescription_title','#autodescription-meta\\[doctitle\\]','#autodescription-site-settings\\[homepage_title\\]'].join(', '));jQuery('#tsf-title-placeholder, #tsf-title-placeholder-prefix').on('click',function(c){let g=jQuery(c.target).siblings(t)[0];if('function'==typeof g.setSelectionRange){g.focus();let d=2*g.value.length;g.setSelectionRange(d,d)}else{let d=g.value;g.value='',g.focus(),g.value=d}});jQuery('#autodescription-site-settings\\[title_rem_additions\\]').on('click',function(c){jQuery(c.target).is(':checked')?jQuery('.tsf-title-additions-js').css('display','none'):jQuery('.tsf-title-additions-js').css('display','inline')});jQuery('#tsf-title-location input').on('click',function(c){let g=jQuery('.tsf-title-additions-example-left'),d=jQuery('.tsf-title-additions-example-right');'right'===jQuery(c.target).val()?(g.css('display','none'),d.css('display','inline')):(g.css('display','inline'),d.css('display','none'))});jQuery('#autodescription-site-settings\\[homepage_title\\]').on('input',function(c){let g=c.target.value||'',d=jQuery('.tsf-custom-title-js');0===g.length?d.text(tsf.params.defaultTitle):d.text(g)});jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').on('input.tsfInputTagline',function(c){let g=c.target.value||'',d=jQuery('.tsf-custom-tagline-js');g=tsf.escapeString(tsf.sDoubleSpace(g.trim())),g.length?(d.html(g),jQuery('#tsf-home-title-location .tsf-sep-js').show()):(d.text(tsf.params.blogDescription),0===tsf.params.blogDescription.length?jQuery('#tsf-home-title-location .tsf-sep-js').hide():jQuery('#tsf-home-title-location .tsf-sep-js').show())}),jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').trigger('input.tsfInputTagline');jQuery('#tsf-title-prefixes-toggle :input').on('click',function(c){let g=jQuery(c.target),d=jQuery('.tsf-title-prefix-example');g.is(':checked')?d.css('display','none'):d.css('display','inline')})}},_initDescInputs:function(){if(tsf.hasInput){let t=jQuery(['#autodescription_description','#autodescription-meta\\[description\\]','#autodescription-site-settings\\[homepage_description\\]'].join(', '));if(t.length){const s=function(b){let x=document.getElementById(b.target.id+'_chars'),y=document.getElementById('tsf-description-reference');if(x&&y){let _={e:x,text:tsf.unescapeString(y.innerHTML),guidelines:tsf.params.inputGuidelines.description.search.chars};tsf.updateCharacterCounter(_)}},n=function(b){let x=document.getElementById('tsf-description-reference'),y=b.target.value;x&&(y=y.trim(),(1>y.length||tsf.states.homeLocks.refDescriptionLock)&&(y=b.target.placeholder),x.innerHTML=tsf.escapeString(tsf.sDoubleSpace(y)),setTimeout(function(){jQuery(x).change()},0))},a=function(b){let x=document.getElementById(b.target.id+'_pixels'),y=document.getElementById('tsf-description-reference');if(x&&y){let _={e:x,text:tsf.unescapeString(y.innerHTML),guidelines:tsf.params.inputGuidelines.description.search.pixels};tsf.updatePixelCounter(_)}};t.on('input.tsfUpdateDescriptions',function(b){n(b),s(b),a(b)});const r=function(){t.trigger('input.tsfUpdateDescriptions')};let l=0;const c=function(){clearTimeout(l),l=setTimeout(r,10)};jQuery(window).on('tsf-counter-updated',c);const g=function(){let b=tsf.settingsChanged;r(),tsf.settingsChanged=b};let d=0;const u=function(){clearTimeout(d),d=setTimeout(g,10)};jQuery('#tsf-homepage-tab-general').on('tsf-tab-toggled',u),jQuery('#tsf-flex-inpost-tab-general').on('tsf-flex-tab-toggled',u),u();let f=['autodescription-homepage-settings','tsf-inpost-box'];jQuery(document).on('postbox-toggled',function(b,x){if(0<=f.indexOf(x.id)){let y=x.querySelector('.inside');0<y.offsetHeight&&0<y.offsetWidth&&c()}})}}},_initSocialTitleInputs:function(){if(tsf.hasInput){let t=jQuery('#autodescription_og_title, #autodescription-site-settings\\[homepage_og_title\\]'),s=jQuery('#autodescription_twitter_title, #autodescription-site-settings\\[homepage_twitter_title\\]'),n=jQuery('#tsf-title-reference');if(t.length&&s.length&&n.length){let a=!1,o=tsf.states.homeLocks.ogTitleLock,r=tsf.states.homeLocks.ogTitlePHLock,l=tsf.states.homeLocks.twTitleLock,c=tsf.states.homeLocks.twTitlePHLock,g=o?t.prop('placeholder'):t.val(),d=l?s.prop('placeholder'):s.val(),u=n.text();const f=function(C){let w='';switchActive:switch(C){case'twitter':if(w=d,l||c){w=w.length?w:s.prop('placeholder');break switchActive}case'og':if(w=w.length?w:g,o||r){w=w.length?w:t.prop('placeholder');break switchActive}case'reference':w=w.length?w:u;}return w},h=function(){tsf.browseUnhappy&&(a=!0),o||r||t.prop('placeholder',f('reference')),l||c||s.prop('placeholder',f('og')),tsf.browseUnhappy&&setTimeout(function(){a=!1},0)},b=function(C,w,T){let S=document.getElementById(C.id+'_chars');if(S){let I={e:S,text:tsf.unescapeString(w),guidelines:tsf.params.inputGuidelines.title[T].chars};tsf.updateCharacterCounter(I)}};let x=0;const y=function(){clearTimeout(x),x=setTimeout(function(){t.each(function(C,w){return b(w,f('og'),'opengraph')}),s.each(function(C,w){return b(w,f('twitter'),'twitter')})},10)};n.on('change',function(){u=n.text(),h(),y()});t.on('input.tsfUpdateOgTitle',function(C){if(!a){if(!o){let w=C.target.value.trim();g=w.length?tsf.sDoubleSpace(w):''}h(),y()}}),s.on('input.tsfUpdateTwTitle',function(C){if(!a){if(!l){let w=C.target.value.trim();d=w.length?tsf.sDoubleSpace(w):''}h(),y()}})}}},_initSocialDescInputs:function(){if(tsf.hasInput){let t=jQuery('#autodescription_og_description, #autodescription-site-settings\\[homepage_og_description\\]'),s=jQuery('#autodescription_twitter_description, #autodescription-site-settings\\[homepage_twitter_description\\]'),n=jQuery('#tsf-description-reference');if(t.length&&s.length&&n.length){let a=!1,o=tsf.states.homeLocks.ogDescriptionLock,r=tsf.states.homeLocks.ogDescriptionPHLock,l=tsf.states.homeLocks.twDescriptionLock,c=tsf.states.homeLocks.twDescriptionPHLock,g=o?t.prop('placeholder'):t.val(),d=l?s.prop('placeholder'):s.val(),u=n.text(),f=jQuery(['#autodescription_description','#autodescription-meta\\[description\\]','#autodescription-site-settings\\[homepage_description\\]'].join(', '));const h=function(w,T){let S='';switchActive:switch(w){case'twitter':if(S=d,l||c){S=S.length?S:s.prop('placeholder');break switchActive}case'og':if(S=S.length?S:g,o||r){S=S.length?S:t.prop('placeholder');break switchActive}case'reference':S.length||(f.val().length?S=u:'twitter'===T?S=tsf.params.socialPlaceholders.twDesc:'og'==T&&(S=tsf.params.socialPlaceholders.ogDesc));}return S},b=function(){tsf.browseUnhappy&&(a=!0),o||r||t.attr('placeholder',h('reference','og')),l||c||s.attr('placeholder',h('og','twitter')),tsf.browseUnhappy&&setTimeout(function(){a=!1},0)},x=function(w,T,S){let I=document.getElementById(w.id+'_chars');if(I){let j={e:I,text:tsf.unescapeString(T),guidelines:tsf.params.inputGuidelines.description[S].chars};tsf.updateCharacterCounter(j)}};let y=0;const _=function(){clearTimeout(y),y=setTimeout(function(){t.each(function(w,T){return x(T,h('og','og'),'opengraph')}),s.each(function(w,T){return x(T,h('twitter','twitter'),'twitter')})},10)};n.on('change',function(){u=n.text(),b(),_()});t.on('input.tsfUpdateOgDesc',function(w){if(!a){if(!o){let T=w.target.value.trim();g=T.length?tsf.sDoubleSpace(T):''}b(),_()}}),s.on('input.tsfUpdateOgDesc',function(w){if(!a){if(!l){let T=w.target.value.trim();d=T.length?tsf.sDoubleSpace(T):''}b(),_()}})}}},_initCanonicalInput:function(){let t=jQuery('#autodescription_canonical');if(t){const s=function(n){t.attr('placeholder',n)};jQuery(document).on('tsf-updated-gutenberg-link',function(n,a){return s(a)})}},_initWebmastersInput:function(){if(tsf.states.isSettingsPage){let t=jQuery(['#autodescription-site-settings\\[google_verification\\]','#autodescription-site-settings\\[bing_verification\\]','#autodescription-site-settings\\[yandex_verification\\]','#autodescription-site-settings\\[pint_verification\\]'].join(', '));t.length&&t.on('paste',function(s){let n=s.originalEvent.clipboardData&&s.originalEvent.clipboardData.getData('text')||void 0;if(n){let a=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(n);a&&2 in a&&'string'==typeof a[2]&&a[2].length&&(s.stopPropagation(),s.preventDefault(),s.target.value=a[2])}})}},_initCounters:function(){if(tsf.hasInput){jQuery('.tsf-counter').on('click',function(){++tsf.counterType,3<tsf.counterType&&(tsf.counterType=0),s();let r='.tsf-counter-wrap .tsf-ajax',l=0;tsf.resetAjaxLoader(r),tsf.setAjaxLoader(r);let c={method:'POST',url:ajaxurl,datatype:'json',data:{action:'the_seo_framework_update_counter',nonce:tsf.nonces.edit_posts,val:tsf.counterType},async:!0,success:function(g){switch(g=tsf.convertJSONResponse(g),'success'===g.type&&(l=1),l){case 0:tsf.unsetAjaxLoader(r,!1);break;case 1:tsf.unsetAjaxLoader(r,!0);break;default:tsf.resetAjaxLoader(r);}}};jQuery.ajax(c)});const s=function(){tsf.counterType=+tsf.counterType,3<tsf.counterType&&(tsf.counterType=0),tsf._triggerCounterUpdate()};jQuery('#autodescription-site-settings\\[display_character_counter\\]').on('click',function(o){jQuery(o.target).is(':checked')?jQuery('.tsf-counter-wrap').show():jQuery('.tsf-counter-wrap').hide()});jQuery('#autodescription-site-settings\\[display_pixel_counter\\]').on('click',function(o){jQuery(o.target).is(':checked')?(jQuery('.tsf-pixel-counter-wrap').show(),tsf._triggerCounterUpdate()):jQuery('.tsf-pixel-counter-wrap').hide()})}},tabToggle:function(t,s){let n=jQuery(t.target);if(n.is(':checked')){s='boolean'==typeof s&&s;let a=t.target.id,o=t.target.name,r='tsf-active-tab-content',l='tsf-tab-active',c=jQuery('.'+r),g=n.closest('.tsf-nav-tab-wrapper').find('.'+l),d=c.find('input:invalid, select:invalid, textarea:invalid');if(d.length){try{d[0].reportValidity()}catch(f){let h=jQuery(t.target.form).find('input[type=submit]').not('.autodescription-site-settings\\[tsf-settings-reset\\]');h.length&&h[0].click()}return g.prop('checked',!0),n.prop('checked',!1),t.stopPropagation(),t.preventDefault(),!1}let u=jQuery('#'+a+'-content');if(g.removeClass(l),g.siblings('label').removeClass('tsf-no-focus-ring'),n.addClass(l),s){let f=jQuery('.'+o+'-content');f.removeClass(r).hide(),u.addClass(r).show(),jQuery('#'+a).trigger('tsf-tab-toggled')}else if(u.length&&!u.is(c)){let f=jQuery('.'+o+'-content');f.fadeOut(150,function(){jQuery(this).removeClass(r)}),setTimeout(function(){u.addClass(r).fadeIn(250)},150),setTimeout(function(){jQuery('#'+a).trigger('tsf-tab-toggled')},175)}}},flexTabToggle:function(t,s){let n=jQuery(t.target);if(n.is(':checked')){s='boolean'==typeof s&&s;let a=t.target.id,o=t.target.name,r='tsf-flex-tab-content-active',l='tsf-flex-tab-active',c=jQuery('.'+r),g=n.closest('.tsf-flex-nav-tab-wrapper').find('.'+l),d=c.find('input:invalid, select:invalid, textarea:invalid');if(d.length){try{d[0].reportValidity()}catch(f){let h=jQuery(t.target.form).find('#publishing-action input[type="submit"], #save-action input[type="submit"]');h.length&&h[0].click()}return g.prop('checked',!0),n.prop('checked',!1),t.stopPropagation(),t.preventDefault(),!1}let u=jQuery('#'+a+'-content');if(g.removeClass(l),g.siblings('label').removeClass('tsf-no-focus-ring'),n.addClass(l),s){let f=jQuery('.'+o+'-content');f.removeClass(r).hide(),u.addClass(r).show(),jQuery('#'+a).trigger('tsf-flex-tab-toggled')}else if(u.length&&!u.is(c)){let f=jQuery('.'+o+'-content');f.fadeOut(150,function(){jQuery(this).removeClass(r)}),setTimeout(function(){u.addClass(r).fadeIn(250)},150),setTimeout(function(){jQuery('#'+a).trigger('tsf-flex-tab-toggled')},175)}}},addNoFocusClass:function(){this.classList.add('tsf-no-focus-ring')},setTabsOnload:function(){tsf.hasInput&&(tsf.states.isPostEdit&&jQuery('.tsf-flex-nav-tab-radio:checked').trigger('change',[!0]),tsf.states.isSettingsPage&&jQuery('.tsf-tabs-radio:checked').each(function(t,s){jQuery(s).trigger('change',[!0])}))},_initPostboxToggle:function(){let t;if(tsf.states.isSettingsPage?t=jQuery('.postbox[id^="autodescription-"]').find('.hndle, .handlediv'):tsf.states.isPostEdit&&(t=jQuery('.postbox#tsf-inpost-box').find('.hndle, .handlediv')),t&&t.length){let s;const n=function(){try{s[0].reportValidity()}catch(o){let r=jQuery(s[0].form).find('input[type=submit]').not('.autodescription-site-settings\\[tsf-settings-reset\\]');r.length&&r[0].click()}};t.on('click.tsfPostboxes',function(o){let r=jQuery(o.target).closest('.postbox');r[0].classList.contains('closed')&&(s=r.find('input:invalid, select:invalid, textarea:invalid'),s.length&&(jQuery(document).one('postbox-toggled',n),jQuery(o.target).trigger('click')))})}},taglineToggleOnload:function(){if(tsf.hasInput){let t=jQuery('#tsf-title-tagline-toggle :input'),s=jQuery('.tsf-custom-blogname-js'),n=jQuery('#tsf-title-additions-toggle :input'),a=jQuery('.tsf-title-additions-js');t.is(':checked')?s.css('display','inline'):s.css('display','none'),n.is(':checked')?a.css('display','none'):a.css('display','inline')}},attachUnsavedChangesListener:function(){if(tsf.hasInput){const t=function(o){jQuery(o.data._input).not(o.data._except).off(o.type,s)},s=function(o){tsf.registerChange(),t(o)};let n,a='.tsf-input-not-saved';n=['.tsf-metaboxes :input','#tsf-inpost-box .inside :input'].join(', '),jQuery(n).not(a).off('change.tsfChangeListener').on('change.tsfChangeListener',{_input:n,_except:a},s),jQuery(document).off('tsf-gutenberg-saved-document.tsfChangeListener').on('tsf-gutenberg-saved-document.tsfChangeListener',function(){tsf.settingsChanged=!1}),n=['.tsf-metaboxes input[type=text]','.tsf-metaboxes textarea','#tsf-inpost-box .inside input[type=text]','#tsf-inpost-box .inside textarea'].join(', '),jQuery(n).not(a).off('input.tsfChangeListener').on('input.tsfChangeListener',{_input:n,_except:a},s),jQuery(window).off('beforeunload.tsfChangeListener').on('beforeunload.tsfChangeListener',function(){if(tsf.settingsChanged)return tsf.i18n.saveAlert}),jQuery(['.tsf-metaboxes input[type="submit"]','#publishing-action input[type="submit"]','#save-action input[type="submit"]','a.submitdelete'].join(', ')).off('click.tsfChangeListener').on('click.tsfChangeListener',function(){tsf.settingsChanged=!1})}},registerChange:function(){tsf.settingsChanged=!0},confirmedReset:function(){return confirm(tsf.i18n.confirmReset)},onLoadUnregisterChange:function(){tsf.settingsChanged=!1},dismissNotice:function(t){jQuery(t.target).parents('.tsf-notice').slideUp(200,function(){this.remove()})},setAjaxLoader:function(t){jQuery(t).toggleClass('tsf-loading')},unsetAjaxLoader:function(t,s){let n='tsf-success',a=2500;s||(n='tsf-error',a=5e3),jQuery(t).removeClass('tsf-loading').addClass(n).fadeOut(a)},resetAjaxLoader:function(t){jQuery(t).stop().empty().prop('class','tsf-ajax').css('opacity','1').removeProp('style')},setColorOnload:function(){let t=jQuery('.tsf-color-picker');t.length&&jQuery.each(t,function(s,n){let a=jQuery(n),o='',r=a.data('tsf-default-color');a.wpColorPicker({defaultColor:r,width:238,change:function(){o=a.wpColorPicker('color'),''==o&&(o=r),a.val(o),tsf.registerChange()},clear:function(){a.parent().siblings('.wp-color-result').css('backgroundColor',r),tsf.registerChange()},palettes:!1})})},_doFlexResizeListener:function(){if(jQuery('.tsf-flex').length){tsf._setResizeListeners();let t=0,s={},n=0,a=jQuery('.tsf-flex-nav-tab-wrapper'),o=jQuery(window);o.on('tsf-flex-resize',function(){clearTimeout(t);let r=0;t=setTimeout(function(){if(a.length){let l=jQuery('.tsf-flex-nav-tab-inner'),c=a.width(),g=l.width(),d=jQuery('.tsf-flex-nav-name');s.tabWrapper||(s.tabWrapper={},s.tabWrapper.outer=0,s.tabWrapper.inner=0,s.tabWrapper.shown=1),!s.tabWrapper.shown&&s.tabWrapper.outer<c&&(d.fadeIn(250),setTimeout(function(){g=l.width()},r)),setTimeout(function(){g>c?(d.hide(),s.tabWrapper.shown=0):s.tabWrapper.outer<c&&(d.fadeIn(250),s.tabWrapper.shown=1)},2*r),setTimeout(function(){s.tabWrapper.outer=c,s.tabWrapper.inner=g},3*r)}},n),r=10,n=75}),o.trigger('tsf-flex-resize')}},_setResizeListeners:function(){jQuery(window).on('resize orientationchange',tsf._triggerResize),jQuery('#collapse-menu').click(tsf._triggerResize),jQuery('.columns-prefs :input[type=radio]').change(tsf._triggerResize),jQuery('.meta-box-sortables').on('sortupdate',tsf._triggerResize)},_triggerResize:function(){jQuery(window).trigger('tsf-flex-resize')},_triggerCounterUpdate:function(){jQuery(window).trigger('tsf-counter-updated')},_triggerReady:function(){jQuery(document.body).trigger('tsf-ready')},_triggerOnLoad:function(){jQuery(document.body).trigger('tsf-onload')},_doReady:function(){tsf._triggerOnLoad(),tsf._initCounters(),tsf._initTitleInputs(),tsf._initUnboundTitleSettings(),tsf._initSocialTitleInputs(),tsf._initDescInputs(),tsf._initSocialDescInputs(),tsf._initCanonicalInput(),tsf._initWebmastersInput(),tsf.setTabsOnload(),tsf._initPostboxToggle(),tsf.taglineToggleOnload(),tsf.setColorOnload(),tsf.attachUnsavedChangesListener(),tsf.onLoadUnregisterChange(),tsf._doFlexResizeListener(),tsf._triggerReady()},setupVars:function(){tsf.counterType=parseInt(tsf.states.counterType),tsf.hasInput=tsf.states.hasInput},ready:function(t){t('.updated, .error, .notice-error, .notice-warning').insertAfter('.tsf-top-wrap'),tsf.setupVars(),t('.tsf-js-confirm-reset').on('click',tsf.confirmedReset),t('.tsf-tabs-radio').on('change',tsf.tabToggle),t('.tsf-tab').on('click','.tsf-nav-tab',tsf.addNoFocusClass),t('.tsf-flex-nav-tab-radio').on('change',tsf.flexTabToggle),t('.tsf-flex-nav-tab').on('click','.tsf-flex-nav-tab-label',tsf.addNoFocusClass),t('.tsf-dismiss').on('click',tsf.dismissNotice),t(document.body).ready(tsf._doReady)}},jQuery(tsf.ready);
1
+ 'use strict';window.tsf={nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,settingsChanged:!1,counterType:0,hasInput:!1,browseUnhappy:!!navigator.userAgent.match(/Trident\/7\./),counterClasses:{0:"tsf-counter-zero",1:"tsf-counter-one",2:"tsf-counter-two",3:"tsf-counter-three"},confirm:function(e){return confirm(e)},stripTags:function(e){return e.replace(/(<([^>]+)?>?)/ig,"")},escapeString:function(e){if(!e.length)return"";let t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;","\\\\":"&#92;","\\":""};return e.replace(/[&<>"']|\\\\|\\/g,e=>t[e])},unescapeString:function(e){if(!e.length)return"";let t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;","\\":"&#92;"},i={};i=tsf.browseUnhappy?Object.keys(t).map(i=>t[i]):Object.values(t);let s=new RegExp(i.map(e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")).join("|"),"g");return tsf.browseUnhappy?e.replace(s,e=>{for(let i in t)if(t[i]===e)return i;return e}):e.replace(s,e=>Object.keys(t).find(i=>t[i]===e))},sDoubleSpace:function(e){return e.replace(/\s\s+/g," ")},getStringLength:function(t){let i,s=0;return t.length&&(i=document.createElement("span"),i.innerHTML=tsf.escapeString(t).trim(),"undefined"!=typeof i.childNodes[0]&&(s=i.childNodes[0].nodeValue.length)),+s},convertJSONResponse:function(e){let t=e&&e.json||void 0,i=1===t;if(!i){let t=e;try{e=JSON.parse(e),i=!0}catch(e){i=!1}i||(e=t)}return e},updateCharacterCounter:function(e){let t=e.e,i=e.text,s=e.guidelines,n=tsf.getStringLength(i),a="",o="",r={bad:"tsf-count-bad",okay:"tsf-count-okay",good:"tsf-count-good",unknown:"tsf-count-unknown"};switch(n?n<s.lower?(a=r.bad,o=tsf.i18n.inputGuidelines.short.farTooShort):n<s.goodLower?(a=r.okay,o=tsf.i18n.inputGuidelines.short.tooShort):n>s.upper?(a=r.bad,o=tsf.i18n.inputGuidelines.short.farTooLong):n>s.goodUpper?(a=r.okay,o=tsf.i18n.inputGuidelines.short.tooLong):(a=r.good,o=tsf.i18n.inputGuidelines.short.good):(a=r.unknown,o=tsf.i18n.inputGuidelines.short.empty),tsf.counterType){case 3:o=n.toString()+" - "+o;break;case 2:break;case 1:default:o=n.toString();}for(let i in t.innerHTML=o,r)t.classList.remove(r[i]);for(let i in tsf.counterClasses)t.classList.remove(tsf.counterClasses[i]);t.classList.add(a),t.classList.add(tsf.counterClasses[tsf.counterType])},updatePixelCounter:function(e){let t=e.e,i=e.text,s=e.guidelines,n=t.parentElement;if(!n)return;let a=n.querySelector(".tsf-pixel-counter-bar"),o=n.querySelector(".tsf-pixel-counter-shadow");if(!a||!o)return;o.innerHTML=tsf.escapeString(i);let r=o.offsetWidth,l="",p="",c="",g={bad:"tsf-pixel-counter-bad",okay:"tsf-pixel-counter-okay",good:"tsf-pixel-counter-good",unknown:"tsf-pixel-counter-unknown"};p=100*(r/s.goodUpper)+"%",r?r<s.lower?(l=g.bad,c=tsf.i18n.inputGuidelines.long.farTooShort):r<s.goodLower?(l=g.okay,c=tsf.i18n.inputGuidelines.long.tooShort):r>s.upper?(p=100*(s.upper/(r+2*(r-s.upper)/3))+"%",l=g.bad,c=tsf.i18n.inputGuidelines.long.farTooLong):r>s.goodUpper?(l=g.okay,c=tsf.i18n.inputGuidelines.long.tooLong,p="100%"):(l=g.good,c=tsf.i18n.inputGuidelines.long.good):(l=g.unknown,p="100%",c=tsf.i18n.inputGuidelines.long.empty);let d,u=a.querySelector(".tsf-pixel-counter-fluid");for(let t in d=tsf.i18n.pixelsUsed.replace(/%1\$d/g,r),d=d.replace(/%2\$d/g,s.goodUpper),d=d+"<br>"+c,g)a.classList.remove(g[t]);a.classList.add(l),u.style.width=p,a.dataset.desc=d,a.setAttribute("aria-label",tsf.escapeString(d.replace(/(<([^>]+)?>?)/ig," "))),tsfTT.triggerUpdate(a)},_initTitleInputs:function(){if(!tsf.hasInput)return;let e=jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]");if(!e.length)return;let t,i,s,n,a=!1,o="",r="",l=tsf.params.titleSeparator,p=tsf.params.defaultTitle,c=tsf.states.useTagline,g=tsf.states.isRTL,d=tsf.states.isPrivate,u=tsf.states.isPasswordProtected,f=tsf.states.stripTitleTags;t=g?"after":"before";const h=function(){let e="before";tsf.states.isSettingsPage?g?"right"===jQuery("#tsf-home-title-location input:checked").val()&&(e="after"):"left"===jQuery("#tsf-home-title-location input:checked").val()&&(e="after"):tsf.states.isHome?g?"right"===tsf.params.titleLocation&&(e="after"):"left"===tsf.params.titleLocation&&(e="after"):g?"left"===tsf.params.titleLocation&&(e="after"):"right"===tsf.params.titleLocation&&(e="after"),i=e};h();const m=function(){let t="";if(!tsf.states.isSettingsPage)tsf.states.isHome?c&&(t=tsf.params.titleAdditions):c&&(t=tsf.params.titleAdditions);else if(c){let i=document.getElementById("autodescription-site-settings[homepage_title_tagline]"),e=i&&i.value||"";e=tsf.sDoubleSpace(e.trim()),t=e.length?e:tsf.params.blogDescription}t.length&&(t=tsf.escapeString(tsf.sDoubleSpace(t.trim())),"before"===i?t=t+" "+l+" ":"after"===i?t=" "+l+" "+t:void 0);r=t.length?t:"",n=document.getElementById("tsf-title-placeholder"),r.length&&n&&(n.innerHTML=r)};m();const b=function(){let e="";d?e=tsf.i18n.privateTitle:u&&(e=tsf.i18n.protectedTitle);e.length&&(e=tsf.escapeString(e),"before"===t?e+=" ":"after"===t?e=" "+e:void 0);o=e.length?e:"",o.length&&s&&(s.innerHTML=o),s=document.getElementById("tsf-title-placeholder-prefix"),o.length&&s&&(s.innerHTML=o)};b();const x=function(e){if(!n&&!s)return;let t=jQuery(e.target),a=t.val(),l=!!r.length,p=!!o.length;if(!l&&n&&(n.style.display="none"),!p&&s&&(s.style.display="none"),!l&&!p)return void t.css("text-indent","initial");if(!a.length)return t.css("text-indent","initial"),n&&(n.style.display="none"),void(s&&(s.style.display="none"));let c=t.outerWidth(!0),d=(t.outerHeight(!0)-t.height())/2,u=(c-t.innerWidth())/2,f=g?"right":"left",h=(t.outerWidth(!0)-t.width())/2,m={display:t.css("display"),lineHeight:t.css("lineHeight"),fontFamily:t.css("fontFamily"),fontWeight:t.css("fontWeight"),fontSize:t.css("fontSize"),letterSpacing:t.css("letterSpacing"),paddingTop:d+"px",paddingBottom:d+"px"},b=jQuery(s),x=jQuery(n),y=0,_=0,v=0,k=0,L=0,C=0;if(p&&(b.css(m),b.css({maxWidth:"initial"}),L=b[0].getBoundingClientRect().width,L<C&&(L=0)),l){let e=0;switch(function(){let t=jQuery("#tsf-title-offset");t.text(a),t.css({fontFamily:m.fontFamily,fontWeight:m.fontWeight,letterSpacing:m.letterSpacing,fontSize:m.fontSize}),e=t[0].getBoundingClientRect().width}(),y=t[0].getBoundingClientRect().width-u-h-e-L,y<C&&(L+=y,y=0),x.css(m),x.css({maxWidth:"initial"}),i){case"before":let s=x[0].getBoundingClientRect().width;s=y<s?y:s,s<C&&(s=0),y=s,k+=y,v+=y,_+=h;break;case"after":_+=h+e+L;}}v+=h,L=0>L?0:L,k+=L;let w;p&&(w={},w[f]=v+"px",w.maxWidth=L+"px",b.css(w)),l&&(w={},w[f]=_+"px",w.maxWidth=y+"px",x.css(w)),w={},w["text-indent"]=k+"px",t.css(w)},y=function(){let s="",n=!!r.length,l=!!o.length,c=r,d=o;tsf.states.isTermEdit&&tsf.params.termName&&(d=g?" :"+tsf.params.termName:tsf.params.termName+": ",l=tsf.states.useTermPrefix),s=p;l&&("before"===t?s=d+s:"after"===t?s+=d:void 0);n&&("before"===i?s=c+s:"after"===i?s+=c:void 0);tsf.browseUnhappy&&(a=!0);let u=document.createElement("span");u.innerHTML=tsf.escapeString(tsf.sDoubleSpace(s)),e.prop("placeholder",tsf.unescapeString(u.textContent)),tsf.browseUnhappy&&setTimeout(function(){a=!1},0)},_=function(e){let s=document.getElementById("tsf-title-reference"),n=e.target.value;s&&(n=n.trim(),1>n.length||tsf.states.homeLocks.refTitleLock?n=e.target.placeholder:(o.length&&("before"===t?n=o+n:"after"===t?n+=o:void 0),r.length&&("before"===i?n=r+n:"after"===i?n+=r:void 0)),s.innerHTML=tsf.escapeString(tsf.sDoubleSpace(n)),setTimeout(()=>{jQuery(s).change()},0))},v=function(e){let t=document.getElementById(e.target.id+"_chars"),i=document.getElementById("tsf-title-reference");if(t&&i){let e={e:t,text:tsf.unescapeString(i.innerHTML),guidelines:tsf.params.inputGuidelines.title.search.chars};tsf.updateCharacterCounter(e)}},k=function(e){let t=document.getElementById(e.target.id+"_pixels"),i=document.getElementById("tsf-title-reference");if(t&&i){let e={e:t,text:tsf.unescapeString(i.innerHTML),guidelines:tsf.params.inputGuidelines.title.search.pixels};tsf.updatePixelCounter(e)}},L=function(e){return!a&&void(x(e),y(),_(e),v(e),k(e))};e.on("input.tsfUpdateTitles",L);e.on("tsf-update-title-counter",function(e){_(e),v(e),k(e)});const C=function(){e.trigger("tsf-update-title-counter")},w=function(){m(),D()};jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input",w),jQuery("#autodescription-site-settings\\[homepage_tagline\\]").on("change",w);const T=function(e){let t=c;jQuery(e.target).is(":checked")?(jQuery(".tsf-custom-blogname-js").css("display","inline"),c=!0):(jQuery(".tsf-custom-blogname-js").css("display","none"),c=!1),t^c&&(m(),P())};jQuery("#tsf-title-tagline-toggle :input").on("click",T);const S=e=>{switch(d=!1,u=!1,e){case"password":u=!0;break;case"private":d=!0;break;default:case"public":}b(),P()};jQuery(document).on("tsf-updated-gutenberg-visibility",(e,t)=>S(t));jQuery("#visibility .save-post-visibility").on("click",()=>{let e=jQuery("#visibility").find("input:radio:checked").val();if("password"===e){let t=jQuery("#visibility").find("#post_password").val(),i=!!t&&!!t.length;i||(e="public")}S(e)});const I=function(e){let t=jQuery(e.target).val(),i="";switch(t){case"pipe":i="|";break;case"dash":i="-";break;default:i=jQuery("<div/>").html("&"+t+";").text();}l=i,jQuery(".tsf-sep-js").text(" "+l+" "),m(),P()};jQuery("#tsf-title-separator :input").on("click",I);const D=function(){e.trigger("input.tsfUpdateTitles")};let U=0;const P=function(){clearTimeout(U),U=setTimeout(D,10)};jQuery(window).on("tsf-counter-updated",P);const W=function(){let e=tsf.settingsChanged;D(),tsf.settingsChanged=e};let j=0;const H=function(){clearTimeout(j),j=setTimeout(W,10)};jQuery(window).on("tsf-flex-resize",H),jQuery("#tsf-homepage-tab-general").on("tsf-tab-toggled",H),jQuery("#tsf-flex-inpost-tab-general").on("tsf-flex-tab-toggled",H),H();let R=["autodescription-homepage-settings","tsf-inpost-box"];jQuery(document).on("postbox-toggled",function(e,t){if(0<=R.indexOf(t.id)){let e=t.querySelector(".inside");0<e.offsetHeight&&0<e.offsetWidth&&W()}});jQuery("#tsf-home-title-location :input").on("click",function(){h(),m(),P()});const E=function(e){e="string"==typeof e&&e.trim()||"",p=e.length?tsf.escapeString(f?tsf.stripTags(e):e):tsf.params.untitledTitle,y(),C()};tsf.states.isHome||(jQuery("#edittag #name, #titlewrap #title").on("input",e=>E(e.target.value)),jQuery(document).on("tsf-updated-gutenberg-title",(e,t)=>E(t)));const z=function(e){if(!tsf.states.taglineLocked){let t=c;c=!jQuery(e.target).is(":checked"),t^c&&(m(),P())}};tsf.states.isHome||(jQuery("#autodescription_title_no_blogname").on("change",z),jQuery("#autodescription_title_no_blogname").trigger("change"));(function(){let e=0,t=window.innerWidth;window.addEventListener("resize",function(){clearTimeout(e),e=setTimeout(function(){let e=window.innerWidth;t<e?782>=t&&782<=e&&W():782<=t&&782>=e&&W(),t=e},50)})})()},_initUnboundTitleSettings:function(){if(!tsf.hasInput)return;let e=jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]");jQuery("#tsf-title-placeholder, #tsf-title-placeholder-prefix").on("click",function(t){let i=jQuery(t.target).siblings(e)[0];if("function"==typeof i.setSelectionRange){i.focus();let e=2*i.value.length;i.setSelectionRange(e,e)}else{let e=i.value;i.value="",i.focus(),i.value=e}});jQuery("#autodescription-site-settings\\[title_rem_additions\\]").on("click",function(e){jQuery(e.target).is(":checked")?jQuery(".tsf-title-additions-js").css("display","none"):jQuery(".tsf-title-additions-js").css("display","inline")});jQuery("#tsf-title-location input").on("click",function(e){let t=jQuery(".tsf-title-additions-example-left"),i=jQuery(".tsf-title-additions-example-right");"right"===jQuery(e.target).val()?(t.css("display","none"),i.css("display","inline")):(t.css("display","inline"),i.css("display","none"))});jQuery("#autodescription-site-settings\\[homepage_title\\]").on("input",function(e){let t=e.target.value||"",i=jQuery(".tsf-custom-title-js");0===t.length?i.text(tsf.params.defaultTitle):i.text(t)});jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input.tsfInputTagline",function(e){let t=e.target.value||"",i=jQuery(".tsf-custom-tagline-js");t=tsf.escapeString(tsf.sDoubleSpace(t.trim())),t.length?(i.html(t),jQuery("#tsf-home-title-location .tsf-sep-js").show()):(i.text(tsf.params.blogDescription),0===tsf.params.blogDescription.length?jQuery("#tsf-home-title-location .tsf-sep-js").hide():jQuery("#tsf-home-title-location .tsf-sep-js").show())}),jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input.tsfInputTagline");jQuery("#tsf-title-prefixes-toggle :input").on("click",function(e){let t=jQuery(e.target),i=jQuery(".tsf-title-prefix-example");t.is(":checked")?i.css("display","none"):i.css("display","inline")})},_initDescInputs:function(){if(!tsf.hasInput)return;let e=jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]");if(!e.length)return;const t=function(e){let t=document.getElementById(e.target.id+"_chars"),i=document.getElementById("tsf-description-reference");if(t&&i){let e={e:t,text:tsf.unescapeString(i.innerHTML),guidelines:tsf.params.inputGuidelines.description.search.chars};tsf.updateCharacterCounter(e)}},i=function(e){let t=document.getElementById("tsf-description-reference"),i=e.target.value;t&&(i=i.trim(),(1>i.length||tsf.states.homeLocks.refDescriptionLock)&&(i=e.target.placeholder),t.innerHTML=tsf.escapeString(tsf.sDoubleSpace(i)),setTimeout(()=>{jQuery(t).change()},0))},s=function(e){let t=document.getElementById(e.target.id+"_pixels"),i=document.getElementById("tsf-description-reference");if(t&&i){let e={e:t,text:tsf.unescapeString(i.innerHTML),guidelines:tsf.params.inputGuidelines.description.search.pixels};tsf.updatePixelCounter(e)}};e.on("input.tsfUpdateDescriptions",function(e){i(e),t(e),s(e)});const n=function(){e.trigger("input.tsfUpdateDescriptions")};let a=0;const o=function(){clearTimeout(a),a=setTimeout(n,10)};jQuery(window).on("tsf-counter-updated",o);const r=function(){let e=tsf.settingsChanged;n(),tsf.settingsChanged=e};let l=0;const p=function(){clearTimeout(l),l=setTimeout(r,10)};jQuery("#tsf-homepage-tab-general").on("tsf-tab-toggled",p),jQuery("#tsf-flex-inpost-tab-general").on("tsf-flex-tab-toggled",p),p();let c=["autodescription-homepage-settings","tsf-inpost-box"];jQuery(document).on("postbox-toggled",function(e,t){if(0<=c.indexOf(t.id)){let e=t.querySelector(".inside");0<e.offsetHeight&&0<e.offsetWidth&&o()}})},_initSocialTitleInputs:function(){if(!tsf.hasInput)return;let e=jQuery("#autodescription_og_title, #autodescription-site-settings\\[homepage_og_title\\]"),t=jQuery("#autodescription_twitter_title, #autodescription-site-settings\\[homepage_twitter_title\\]"),i=jQuery("#tsf-title-reference");if(!e.length||!t.length||!i.length)return;let s=!1,n=tsf.states.homeLocks.ogTitleLock,a=tsf.states.homeLocks.ogTitlePHLock,o=tsf.states.homeLocks.twTitleLock,r=tsf.states.homeLocks.twTitlePHLock,l=n?e.prop("placeholder"):e.val(),p=o?t.prop("placeholder"):t.val(),c=i.text();const g=i=>{let s="";switchActive:switch(i){case"twitter":if(s=p,o||r){s=s.length?s:t.prop("placeholder");break switchActive}case"og":if(s=s.length?s:l,n||a){s=s.length?s:e.prop("placeholder");break switchActive}case"reference":s=s.length?s:c;}return s},d=()=>{tsf.browseUnhappy&&(s=!0),n||a||e.prop("placeholder",g("reference")),o||r||t.prop("placeholder",g("og")),tsf.browseUnhappy&&setTimeout(()=>{s=!1},0)},u=(e,t,i)=>{let s=document.getElementById(e.id+"_chars");if(s){let e={e:s,text:tsf.unescapeString(t),guidelines:tsf.params.inputGuidelines.title[i].chars};tsf.updateCharacterCounter(e)}};let f=0;const h=()=>{clearTimeout(f),f=setTimeout(()=>{e.each((e,t)=>u(t,g("og"),"opengraph")),t.each((e,t)=>u(t,g("twitter"),"twitter"))},10)};i.on("change",()=>{c=i.text(),d(),h()});const m=e=>{if(!s){if(!n){let t=e.target.value.trim();l=t.length?tsf.sDoubleSpace(t):""}d(),h()}},b=e=>{if(!s){if(!o){let t=e.target.value.trim();p=t.length?tsf.sDoubleSpace(t):""}d(),h()}};e.on("input.tsfUpdateOgTitle",m),t.on("input.tsfUpdateTwTitle",b)},_initSocialDescInputs:function(){if(!tsf.hasInput)return;let e=jQuery("#autodescription_og_description, #autodescription-site-settings\\[homepage_og_description\\]"),t=jQuery("#autodescription_twitter_description, #autodescription-site-settings\\[homepage_twitter_description\\]"),i=jQuery("#tsf-description-reference");if(!e.length||!t.length||!i.length)return;let s=!1,n=tsf.states.homeLocks.ogDescriptionLock,a=tsf.states.homeLocks.ogDescriptionPHLock,o=tsf.states.homeLocks.twDescriptionLock,r=tsf.states.homeLocks.twDescriptionPHLock,l=n?e.prop("placeholder"):e.val(),p=o?t.prop("placeholder"):t.val(),c=i.text(),g=jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]");const d=(i,s)=>{let d="";switchActive:switch(i){case"twitter":if(d=p,o||r){d=d.length?d:t.prop("placeholder");break switchActive}case"og":if(d=d.length?d:l,n||a){d=d.length?d:e.prop("placeholder");break switchActive}case"reference":d.length||(g.val().length?d=c:"twitter"===s?d=tsf.params.socialPlaceholders.twDesc:"og"==s&&(d=tsf.params.socialPlaceholders.ogDesc));}return d},u=()=>{tsf.browseUnhappy&&(s=!0),n||a||e.attr("placeholder",d("reference","og")),o||r||t.attr("placeholder",d("og","twitter")),tsf.browseUnhappy&&setTimeout(function(){s=!1},0)},f=(e,t,i)=>{let s=document.getElementById(e.id+"_chars");if(s){let e={e:s,text:tsf.unescapeString(t),guidelines:tsf.params.inputGuidelines.description[i].chars};tsf.updateCharacterCounter(e)}};let h=0;const m=()=>{clearTimeout(h),h=setTimeout(()=>{e.each((e,t)=>f(t,d("og","og"),"opengraph")),t.each((e,t)=>f(t,d("twitter","twitter"),"twitter"))},10)};i.on("change",()=>{c=i.text(),u(),m()});const b=e=>{if(!s){if(!n){let t=e.target.value.trim();l=t.length?tsf.sDoubleSpace(t):""}u(),m()}},x=e=>{if(!s){if(!o){let t=e.target.value.trim();p=t.length?tsf.sDoubleSpace(t):""}u(),m()}};e.on("input.tsfUpdateOgDesc",b),t.on("input.tsfUpdateOgDesc",x)},_initCanonicalInput:function(){let e=jQuery("#autodescription_canonical");if(!e)return;const t=t=>{e.attr("placeholder",t)};jQuery(document).on("tsf-updated-gutenberg-link",(e,i)=>t(i))},_initWebmastersInput:function(){if(tsf.states.isSettingsPage){let e=jQuery("#autodescription-site-settings\\[google_verification\\], #autodescription-site-settings\\[bing_verification\\], #autodescription-site-settings\\[yandex_verification\\], #autodescription-site-settings\\[pint_verification\\]");e.length&&e.on("paste",e=>{let t=e.originalEvent.clipboardData&&e.originalEvent.clipboardData.getData("text")||void 0;if(t){let i=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(t);i&&2 in i&&"string"==typeof i[2]&&i[2].length&&(e.stopPropagation(),e.preventDefault(),e.target.value=i[2])}})}},_initCounters:function(){if(!tsf.hasInput)return;jQuery(".tsf-counter").on("click",function(){++tsf.counterType,3<tsf.counterType&&(tsf.counterType=0),e();let t=".tsf-counter-wrap .tsf-ajax",i=0;tsf.resetAjaxLoader(".tsf-counter-wrap .tsf-ajax"),tsf.setAjaxLoader(".tsf-counter-wrap .tsf-ajax");let s={method:"POST",url:ajaxurl,datatype:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.nonces.edit_posts,val:tsf.counterType},async:!0,success:function(e){switch(e=tsf.convertJSONResponse(e),"success"===e.type&&(i=1),i){case 0:tsf.unsetAjaxLoader(t,!1);break;case 1:tsf.unsetAjaxLoader(t,!0);break;default:tsf.resetAjaxLoader(t);}}};jQuery.ajax(s)});const e=function(){tsf.counterType=+tsf.counterType,3<tsf.counterType&&(tsf.counterType=0),tsf._triggerCounterUpdate()};jQuery("#autodescription-site-settings\\[display_character_counter\\]").on("click",function(e){jQuery(e.target).is(":checked")?jQuery(".tsf-counter-wrap").show():jQuery(".tsf-counter-wrap").hide()});jQuery("#autodescription-site-settings\\[display_pixel_counter\\]").on("click",function(e){jQuery(e.target).is(":checked")?(jQuery(".tsf-pixel-counter-wrap").show(),tsf._triggerCounterUpdate()):jQuery(".tsf-pixel-counter-wrap").hide()})},tabToggle:function(e,t){let i=jQuery(e.target);if(!i.is(":checked"))return;t="boolean"==typeof t&&t;let s=e.target.id,n=e.target.name,a="tsf-active-tab-content",o="tsf-tab-active",r=jQuery("."+a),l=i.closest(".tsf-nav-tab-wrapper").find("."+o),p=r.find("input:invalid, select:invalid, textarea:invalid");if(p.length){try{p[0].reportValidity()}catch(t){let i=jQuery(e.target.form).find("input[type=submit]").not(".autodescription-site-settings\\[tsf-settings-reset\\]");i.length&&i[0].click()}return l.prop("checked",!0),i.prop("checked",!1),e.stopPropagation(),e.preventDefault(),!1}let c=jQuery("#"+s+"-content");if(l.removeClass(o),l.siblings("label").removeClass("tsf-no-focus-ring"),i.addClass(o),t){let e=jQuery("."+n+"-content");e.removeClass(a).hide(),c.addClass(a).show(),jQuery("#"+s).trigger("tsf-tab-toggled")}else if(c.length&&!c.is(r)){let e=jQuery("."+n+"-content");e.fadeOut(150,function(){jQuery(this).removeClass(a)}),setTimeout(()=>{c.addClass(a).fadeIn(250)},150),setTimeout(()=>{jQuery("#"+s).trigger("tsf-tab-toggled")},175)}},flexTabToggle:function(e,t){let i=jQuery(e.target);if(!i.is(":checked"))return;t="boolean"==typeof t&&t;let s=e.target.id,n=e.target.name,a="tsf-flex-tab-content-active",o="tsf-flex-tab-active",r=jQuery("."+a),l=i.closest(".tsf-flex-nav-tab-wrapper").find("."+o),p=r.find("input:invalid, select:invalid, textarea:invalid");if(p.length){try{p[0].reportValidity()}catch(t){let i=jQuery(e.target.form).find("#publishing-action input[type=\"submit\"], #save-action input[type=\"submit\"]");i.length&&i[0].click()}return l.prop("checked",!0),i.prop("checked",!1),e.stopPropagation(),e.preventDefault(),!1}let c=jQuery("#"+s+"-content");if(l.removeClass(o),l.siblings("label").removeClass("tsf-no-focus-ring"),i.addClass(o),t){let e=jQuery("."+n+"-content");e.removeClass(a).hide(),c.addClass(a).show(),jQuery("#"+s).trigger("tsf-flex-tab-toggled")}else if(c.length&&!c.is(r)){let e=jQuery("."+n+"-content");e.fadeOut(150,function(){jQuery(this).removeClass(a)}),setTimeout(()=>{c.addClass(a).fadeIn(250)},150),setTimeout(()=>{jQuery("#"+s).trigger("tsf-flex-tab-toggled")},175)}},addNoFocusClass:function(){this.classList.add("tsf-no-focus-ring")},setTabsOnload:function(){tsf.hasInput&&(tsf.states.isPostEdit&&jQuery(".tsf-flex-nav-tab-radio:checked").trigger("change",[!0]),tsf.states.isSettingsPage&&jQuery(".tsf-tabs-radio:checked").each((e,t)=>{jQuery(t).trigger("change",[!0])}))},_initPostboxToggle:function(){let e;if(tsf.states.isSettingsPage?e=jQuery(".postbox[id^=\"autodescription-\"]").find(".hndle, .handlediv"):tsf.states.isPostEdit&&(e=jQuery(".postbox#tsf-inpost-box").find(".hndle, .handlediv")),!e||!e.length)return;let t;const i=()=>{try{t[0].reportValidity()}catch(e){let i=jQuery(t[0].form).find("input[type=submit]").not(".autodescription-site-settings\\[tsf-settings-reset\\]");i.length&&i[0].click()}},s=e=>{let s=jQuery(e.target).closest(".postbox");s[0].classList.contains("closed")&&(t=s.find("input:invalid, select:invalid, textarea:invalid"),t.length&&(jQuery(document).one("postbox-toggled",i),jQuery(e.target).trigger("click")))};e.on("click.tsfPostboxes",s)},taglineToggleOnload:function(){if(tsf.hasInput){let e=jQuery("#tsf-title-tagline-toggle :input"),t=jQuery(".tsf-custom-blogname-js"),i=jQuery("#tsf-title-additions-toggle :input"),s=jQuery(".tsf-title-additions-js");e.is(":checked")?t.css("display","inline"):t.css("display","none"),i.is(":checked")?s.css("display","none"):s.css("display","inline")}},attachUnsavedChangesListener:function(){if(!tsf.hasInput)return;const e=e=>{jQuery(e.data._input).not(e.data._except).off(e.type,t)},t=t=>{tsf.registerChange(),e(t)};let i;i=".tsf-metaboxes :input, #tsf-inpost-box .inside :input",jQuery(i).not(".tsf-input-not-saved").off("change.tsfChangeListener").on("change.tsfChangeListener",{_input:i,_except:".tsf-input-not-saved"},t),jQuery(document).off("tsf-gutenberg-saved-document.tsfChangeListener").on("tsf-gutenberg-saved-document.tsfChangeListener",()=>{tsf.settingsChanged=!1}),i=".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea",jQuery(i).not(".tsf-input-not-saved").off("input.tsfChangeListener").on("input.tsfChangeListener",{_input:i,_except:".tsf-input-not-saved"},t),jQuery(window).off("beforeunload.tsfChangeListener").on("beforeunload.tsfChangeListener",()=>{if(tsf.settingsChanged)return tsf.i18n.saveAlert}),jQuery(".tsf-metaboxes input[type=\"submit\"], #publishing-action input[type=\"submit\"], #save-action input[type=\"submit\"], a.submitdelete").off("click.tsfChangeListener").on("click.tsfChangeListener",()=>{tsf.settingsChanged=!1})},registerChange:function(){tsf.settingsChanged=!0},confirmedReset:function(){return confirm(tsf.i18n.confirmReset)},onLoadUnregisterChange:function(){tsf.settingsChanged=!1},dismissNotice:function(e){jQuery(e.target).parents(".tsf-notice").slideUp(200,function(){this.remove()})},setAjaxLoader:function(e){jQuery(e).toggleClass("tsf-loading")},unsetAjaxLoader:function(e,t){let i="tsf-success",s=2500;t||(i="tsf-error",s=5e3),jQuery(e).removeClass("tsf-loading").addClass(i).fadeOut(s)},resetAjaxLoader:function(e){jQuery(e).stop().empty().prop("class","tsf-ajax").css("opacity","1").removeProp("style")},setColorOnload:function(){let e=jQuery(".tsf-color-picker");e.length&&jQuery.each(e,function(e,t){let i=jQuery(t),s="",n=i.data("tsf-default-color");i.wpColorPicker({defaultColor:n,width:238,change:function(){s=i.wpColorPicker("color"),""===s&&(s=n),i.val(s),tsf.registerChange()},clear:function(){i.parent().siblings(".wp-color-result").css("backgroundColor",n),tsf.registerChange()},palettes:!1})})},_doFlexResizeListener:function(){if(!jQuery(".tsf-flex").length)return;tsf._setResizeListeners();let e=0,t={},i=0,s=jQuery(".tsf-flex-nav-tab-wrapper"),n=jQuery(window);n.on("tsf-flex-resize",function(){clearTimeout(e);let n=0;e=setTimeout(function(){if(s.length){let e=jQuery(".tsf-flex-nav-tab-inner"),i=s.width(),a=e.width(),o=jQuery(".tsf-flex-nav-name");t.tabWrapper||(t.tabWrapper={},t.tabWrapper.outer=0,t.tabWrapper.inner=0,t.tabWrapper.shown=1),!t.tabWrapper.shown&&t.tabWrapper.outer<i&&(o.fadeIn(250),setTimeout(function(){a=e.width()},n)),setTimeout(function(){a>i?(o.hide(),t.tabWrapper.shown=0):t.tabWrapper.outer<i&&(o.fadeIn(250),t.tabWrapper.shown=1)},2*n),setTimeout(function(){t.tabWrapper.outer=i,t.tabWrapper.inner=a},3*n)}},i),n=10,i=75}),n.trigger("tsf-flex-resize")},_setResizeListeners:function(){jQuery(window).on("resize orientationchange",tsf._triggerResize),jQuery("#collapse-menu").click(tsf._triggerResize),jQuery(".columns-prefs :input[type=radio]").change(tsf._triggerResize),jQuery(".meta-box-sortables").on("sortupdate",tsf._triggerResize)},_triggerResize:function(){jQuery(window).trigger("tsf-flex-resize")},_triggerCounterUpdate:function(){jQuery(window).trigger("tsf-counter-updated")},_triggerReady:function(){jQuery(document.body).trigger("tsf-ready")},_triggerOnLoad:function(){jQuery(document.body).trigger("tsf-onload")},_doReady:function(){tsf._triggerOnLoad(),tsf._initCounters(),tsf._initTitleInputs(),tsf._initUnboundTitleSettings(),tsf._initSocialTitleInputs(),tsf._initDescInputs(),tsf._initSocialDescInputs(),tsf._initCanonicalInput(),tsf._initWebmastersInput(),tsf.setTabsOnload(),tsf._initPostboxToggle(),tsf.taglineToggleOnload(),tsf.setColorOnload(),tsf.attachUnsavedChangesListener(),tsf.onLoadUnregisterChange(),tsf._doFlexResizeListener(),tsf._triggerReady()},setupVars:function(){tsf.counterType=parseInt(tsf.states.counterType),tsf.hasInput=tsf.states.hasInput},ready:function(e){e(".updated, .error, .notice-error, .notice-warning").insertAfter(".tsf-top-wrap"),tsf.setupVars(),e(".tsf-js-confirm-reset").on("click",tsf.confirmedReset),e(".tsf-tabs-radio").on("change",tsf.tabToggle),e(".tsf-tab").on("click",".tsf-nav-tab",tsf.addNoFocusClass),e(".tsf-flex-nav-tab-radio").on("change",tsf.flexTabToggle),e(".tsf-flex-nav-tab").on("click",".tsf-flex-nav-tab-label",tsf.addNoFocusClass),e(".tsf-dismiss").on("click",tsf.dismissNotice),e(document.body).ready(tsf._doReady)}},jQuery(tsf.ready);
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: Cybr
3
  Donate link: https://theseoframework.com/donate/
4
  Tags: SEO, XML Sitemap, Google, Open Graph, Schema.org, Twitter
5
  Requires at least: 4.6.0
6
- Tested up to: 5.1.0
7
  Requires PHP: 5.4.0
8
- Stable tag: 3.2.3
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -242,6 +242,12 @@ Please be sure to clear your cache or adjust the plugin's caching settings if de
242
 
243
  == Changelog ==
244
 
 
 
 
 
 
 
245
  = 3.2.3 =
246
 
247
  This minor update fixes some old, [leftover bugs](https://theseoframework.com/?p=3105). We've also removed the sitemap pinging options for Yandex, as they no longer allow this.
3
  Donate link: https://theseoframework.com/donate/
4
  Tags: SEO, XML Sitemap, Google, Open Graph, Schema.org, Twitter
5
  Requires at least: 4.6.0
6
+ Tested up to: 5.2
7
  Requires PHP: 5.4.0
8
+ Stable tag: 3.2.4
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
242
 
243
  == Changelog ==
244
 
245
+ = 3.2.4 =
246
+
247
+ In this minor update, we bring you the most advanced description generation yet. The generator is now context-sensitive, so you can expect the descriptions to be even more natural; a real time-saver!
248
+
249
+ Oh, we also [fixed some bugs](https://theseoframework.com/?p=3130), and we've implemented some improvements in preparation for version 3.3.0.
250
+
251
  = 3.2.3 =
252
 
253
  This minor update fixes some old, [leftover bugs](https://theseoframework.com/?p=3105). We've also removed the sitemap pinging options for Yandex, as they no longer allow this.