The SEO Framework - Version 4.2.7

Version Description

This minor update brings you a revamped HTML parser and a new option for tuning its accuracy for descriptions. First-time installers are now notified when metadata can be transported from other SEO plugins, the SEO Bar recognizes syntax from Rank Math, and Advanced Query Protection blocks new SEO attacks that could tank your rankings. We also fixed a couple of bugs.

Psst: Check out our Cyber Sale.

Download this release

Release Info

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

Code changes from version 4.2.6 to 4.2.7

Files changed (61) hide show
  1. autodescription.php +3 -3
  2. bootstrap/load.php +5 -10
  3. bootstrap/upgrade.php +87 -8
  4. inc/classes/admin-init.class.php +69 -62
  5. inc/classes/admin-pages.class.php +6 -4
  6. inc/classes/bridges/ajax.class.php +2 -4
  7. inc/classes/bridges/feed.class.php +44 -74
  8. inc/classes/bridges/scripts.class.php +35 -33
  9. inc/classes/builders/coresitemaps/main.class.php +27 -0
  10. inc/classes/builders/images.class.php +8 -3
  11. inc/classes/builders/robots/args.class.php +1 -6
  12. inc/classes/builders/robots/main.class.php +1 -1
  13. inc/classes/builders/robots/query.class.php +12 -13
  14. inc/classes/builders/scripts.class.php +14 -23
  15. inc/classes/builders/seobar/page.class.php +8 -6
  16. inc/classes/builders/seobar/term.class.php +2 -2
  17. inc/classes/builders/sitemap/base.class.php +9 -6
  18. inc/classes/builders/sitemap/index.php +9 -0
  19. inc/classes/builders/sitemap/main.class.php +1 -1
  20. inc/classes/core.class.php +58 -16
  21. inc/classes/detect.class.php +204 -13
  22. inc/classes/generate-description.class.php +16 -14
  23. inc/classes/generate-ldjson.class.php +3 -3
  24. inc/classes/generate-title.class.php +6 -7
  25. inc/classes/generate.class.php +2 -2
  26. inc/classes/init.class.php +13 -6
  27. inc/classes/post-data.class.php +18 -15
  28. inc/classes/query.class.php +2 -4
  29. inc/classes/render.class.php +12 -16
  30. inc/classes/sanitize.class.php +206 -50
  31. inc/classes/site-options.class.php +3 -1
  32. inc/classes/term-data.class.php +11 -11
  33. inc/classes/user-data.class.php +4 -3
  34. inc/compat/theme-genesis.php +1 -0
  35. inc/functions/upgrade-suggestion.php +28 -100
  36. inc/views/settings/metaboxes/description.php +61 -9
  37. inc/views/settings/metaboxes/general.php +0 -15
  38. inc/views/settings/metaboxes/post-type-archive.php +1 -1
  39. inc/views/settings/metaboxes/sitemaps.php +16 -2
  40. inc/views/settings/metaboxes/title.php +0 -1
  41. inc/views/sitemap/xml-sitemap.php +12 -12
  42. language/autodescription.pot +323 -294
  43. lib/css/post.css +0 -1
  44. lib/css/post.min.css +1 -1
  45. lib/js/c.js +2 -2
  46. lib/js/c.min.js +1 -1
  47. lib/js/le.js +5 -1
  48. lib/js/le.min.js +1 -1
  49. lib/js/media.js +1 -1
  50. lib/js/media.min.js +1 -1
  51. lib/js/post.js +4 -1
  52. lib/js/post.min.js +1 -1
  53. lib/js/pt.js +11 -11
  54. lib/js/pt.min.js +1 -1
  55. lib/js/settings.js +16 -9
  56. lib/js/settings.min.js +1 -1
  57. lib/js/social.js +3 -3
  58. lib/js/term.js +8 -2
  59. lib/js/term.min.js +1 -1
  60. lib/js/tsf.js +20 -43
  61. readme.txt +11 -6
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: 4.2.6
7
  * Author: The SEO Framework Team
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
@@ -41,7 +41,7 @@ defined( 'ABSPATH' ) or die;
41
  *
42
  * @since 2.3.5
43
  */
44
- define( 'THE_SEO_FRAMEWORK_VERSION', '4.2.6' );
45
 
46
  /**
47
  * The plugin Database version.
@@ -50,7 +50,7 @@ define( 'THE_SEO_FRAMEWORK_VERSION', '4.2.6' );
50
  *
51
  * @since 2.7.0
52
  */
53
- define( 'THE_SEO_FRAMEWORK_DB_VERSION', '4200' );
54
 
55
  /**
56
  * The plugin file, absolute unix path.
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: 4.2.7
7
  * Author: The SEO Framework Team
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
41
  *
42
  * @since 2.3.5
43
  */
44
+ define( 'THE_SEO_FRAMEWORK_VERSION', '4.2.7' );
45
 
46
  /**
47
  * The plugin Database version.
50
  *
51
  * @since 2.7.0
52
  */
53
+ define( 'THE_SEO_FRAMEWORK_DB_VERSION', '4270' );
54
 
55
  /**
56
  * The plugin file, absolute unix path.
bootstrap/load.php CHANGED
@@ -71,23 +71,18 @@ function _init_tsf() {
71
  * @param bool $load
72
  */
73
  if ( \apply_filters( 'the_seo_framework_load', true ) ) {
74
- if ( \is_admin() ) {
75
- //! TODO: admin-only loader?
76
- $tsf = new Load();
77
- $tsf->loaded = true;
78
 
79
- $tsf->_load_early_compat_files();
80
 
 
 
81
  /**
82
  * @since 3.1.0
83
  * Runs after TSF is loaded in the admin.
84
  */
85
  \do_action( 'the_seo_framework_admin_loaded' );
86
- } else {
87
- $tsf = new Load();
88
- $tsf->loaded = true;
89
-
90
- $tsf->_load_early_compat_files();
91
  }
92
 
93
  /**
71
  * @param bool $load
72
  */
73
  if ( \apply_filters( 'the_seo_framework_load', true ) ) {
74
+ $tsf = new Load();
75
+ $tsf->loaded = true;
 
 
76
 
77
+ $tsf->_load_early_compat_files();
78
 
79
+ if ( \is_admin() ) {
80
+ //! TODO: admin-only loader?
81
  /**
82
  * @since 3.1.0
83
  * Runs after TSF is loaded in the admin.
84
  */
85
  \do_action( 'the_seo_framework_admin_loaded' );
 
 
 
 
 
86
  }
87
 
88
  /**
bootstrap/upgrade.php CHANGED
@@ -211,7 +211,7 @@ function _upgrade( $previous_version ) {
211
  // This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
212
  // We must manually delete settings that are no longer used; we merge them otherwise.
213
  // When a user upgrades beyond this scope, they aren't expected to roll back.
214
- $versions = [ '1', '2701', '2802', '2900', '3001', '3103', '3300', '4051', '4103', '4110', '4120', '4200' ];
215
 
216
  foreach ( $versions as $_version ) {
217
  if ( $current_version < $_version ) {
@@ -396,6 +396,7 @@ function _prepare_downgrade_notice( $previous_version, $current_version ) {
396
  * 2. Now registers persistent notice for the update version.
397
  * @since 4.1.2 No longer can accidentally show the install notice after stale upgrade.
398
  * @since 4.2.0 The installation notice is now persistent, shown twice, to users with activate_plugins capability, on the main site.
 
399
  * @TODO Add browser cache flush notice? Or set a pragma/cache-control header?
400
  * Users that remove query strings (thanks to YSlow) are to blame, though.
401
  * The authors of the plugin that allowed this to happen are even more to blame.
@@ -406,10 +407,10 @@ function _prepare_downgrade_notice( $previous_version, $current_version ) {
406
  */
407
  function _prepare_upgrade_notice( $previous_version, $current_version ) {
408
 
 
 
409
  // phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
410
  if ( $previous_version && $previous_version != $current_version ) { // User successfully upgraded.
411
- $tsf = \tsf();
412
-
413
  $tsf->register_dismissible_persistent_notice(
414
  $tsf->convert_markdown(
415
  sprintf(
@@ -437,10 +438,8 @@ function _prepare_upgrade_notice( $previous_version, $current_version ) {
437
  } elseif ( ! $previous_version && $current_version ) { // User successfully installed.
438
  $network_mode = (bool) ( \get_site_option( 'active_sitewide_plugins' )[ THE_SEO_FRAMEWORK_PLUGIN_BASENAME ] ?? false );
439
 
440
- // Only show notice when not in network mode, or on main site otherwise.
441
  if ( ! $network_mode || \is_main_site() ) {
442
- $tsf = \tsf();
443
-
444
  $tsf->register_dismissible_persistent_notice(
445
  sprintf(
446
  '<p>%s</p><p>%s</p>',
@@ -471,6 +470,76 @@ function _prepare_upgrade_notice( $previous_version, $current_version ) {
471
  ]
472
  );
473
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
  }
475
  }
476
 
@@ -807,8 +876,7 @@ function _do_upgrade_4110() {
807
  */
808
  function _do_upgrade_4120() {
809
  if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4120' ) {
810
- $tsf = \tsf();
811
- $tsf->update_option( 'ping_use_cron_prerender', 0 );
812
  }
813
  }
814
 
@@ -822,3 +890,14 @@ function _do_upgrade_4200() {
822
  \delete_option( 'the_seo_framework_tested_upgrade_version' );
823
  }
824
  }
 
 
 
 
 
 
 
 
 
 
 
211
  // This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
212
  // We must manually delete settings that are no longer used; we merge them otherwise.
213
  // When a user upgrades beyond this scope, they aren't expected to roll back.
214
+ $versions = [ '1', '2701', '2802', '2900', '3001', '3103', '3300', '4051', '4103', '4110', '4120', '4200', '4270' ];
215
 
216
  foreach ( $versions as $_version ) {
217
  if ( $current_version < $_version ) {
396
  * 2. Now registers persistent notice for the update version.
397
  * @since 4.1.2 No longer can accidentally show the install notice after stale upgrade.
398
  * @since 4.2.0 The installation notice is now persistent, shown twice, to users with activate_plugins capability, on the main site.
399
+ * @since 4.2.7 Added data checker directing users to the Transport extension.
400
  * @TODO Add browser cache flush notice? Or set a pragma/cache-control header?
401
  * Users that remove query strings (thanks to YSlow) are to blame, though.
402
  * The authors of the plugin that allowed this to happen are even more to blame.
407
  */
408
  function _prepare_upgrade_notice( $previous_version, $current_version ) {
409
 
410
+ $tsf = \tsf();
411
+
412
  // phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
413
  if ( $previous_version && $previous_version != $current_version ) { // User successfully upgraded.
 
 
414
  $tsf->register_dismissible_persistent_notice(
415
  $tsf->convert_markdown(
416
  sprintf(
438
  } elseif ( ! $previous_version && $current_version ) { // User successfully installed.
439
  $network_mode = (bool) ( \get_site_option( 'active_sitewide_plugins' )[ THE_SEO_FRAMEWORK_PLUGIN_BASENAME ] ?? false );
440
 
441
+ // Only show notices when not in network mode, or on main site otherwise.
442
  if ( ! $network_mode || \is_main_site() ) {
 
 
443
  $tsf->register_dismissible_persistent_notice(
444
  sprintf(
445
  '<p>%s</p><p>%s</p>',
470
  ]
471
  );
472
  }
473
+
474
+ global $wpdb;
475
+
476
+ // Not everything's included. Only data likely to be inserted by the user manually, and which is actually carried over.
477
+ $meta_types = [
478
+ 'wordpress-seo' => [
479
+ 'title' => 'Yoast SEO',
480
+ 'from' => $wpdb->postmeta,
481
+ 'in' => [ '_yoast_wpseo_title', '_yoast_wpseo_metadesc', '_yoast_wpseo_opengraph-title', '_yoast_wpseo_opengraph-description', '_yoast_wpseo_twitter-title', '_yoast_wpseo_twitter-description', '_yoast_wpseo_meta-robots-noindex', '_yoast_wpseo_meta-robots-nofollow', '_yoast_wpseo_canonical', '_yoast_wpseo_redirect' ],
482
+ ],
483
+ 'seo-by-rank-math' => [
484
+ 'title' => 'Rank Math',
485
+ 'from' => $wpdb->postmeta,
486
+ 'in' => [ 'rank_math_title', 'rank_math_description', 'rank_math_facebook_title', 'rank_math_facebook_description', 'rank_math_twitter_title', 'rank_math_twitter_description', 'rank_math_canonical_url', 'rank_math_robots' ],
487
+ ],
488
+ ];
489
+
490
+ $esc_sql_in = function( $var ) {
491
+ if ( ! is_scalar( $var ) )
492
+ $var = array_filter( (array) $var, 'is_scalar' );
493
+ return \esc_sql( $var );
494
+ };
495
+
496
+ $found_titles = [];
497
+
498
+ foreach ( $meta_types as $type => $data ) {
499
+ // in WP 6.2 we can use %i and whatnot. <https://core.trac.wordpress.org/ticket/52506>
500
+ // <https://make.wordpress.org/core/2022/10/08/escaping-table-and-field-names-with-wpdbprepare-in-wordpress-6-1/>
501
+ $indexes = implode( "', '", $esc_sql_in( $data['in'] ) );
502
+ $table = \esc_sql( $data['from'] );
503
+
504
+ if ( $wpdb->get_var(
505
+ // phpcs:ignore, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table/$indexes are escaped.
506
+ "SELECT 1 FROM `$table` WHERE meta_key IN ('$indexes') LIMIT 1"
507
+ ) ) {
508
+ $found_titles[] = $data['title'];
509
+ }
510
+ }
511
+
512
+ $found_titles and $tsf->register_dismissible_persistent_notice(
513
+ sprintf(
514
+ '<p>%s</p>',
515
+ $tsf->convert_markdown(
516
+ sprintf(
517
+ /* translators: 1: SEO plugin name(s), 2: link to guide, in Markdown! */
518
+ \esc_html__( 'The SEO Framework detected metadata from %1$s. Whenever you are set, read our [migration guide](%2$s).', 'autodescription' ),
519
+ \esc_html(
520
+ count( $found_titles ) > 1 ? wp_sprintf_l( '%l', $found_titles ) : current( $found_titles )
521
+ ),
522
+ 'https://theseoframework.com/docs/seo-data-migration/'
523
+ ),
524
+ [ 'a' ],
525
+ [ 'a_internal' => false ]
526
+ )
527
+ ),
528
+ 'installed-migration-notice',
529
+ [
530
+ 'type' => 'info',
531
+ 'icon' => true,
532
+ 'escape' => false,
533
+ ],
534
+ [
535
+ 'screens' => [ 'edit', 'edit-tags', 'dashboard', 'toplevel_page_theseoframework-settings' ],
536
+ 'excl_screens' => [],
537
+ 'capability' => 'activate_plugins',
538
+ 'user' => 0,
539
+ 'count' => 69,
540
+ 'timeout' => 7 * DAY_IN_SECONDS,
541
+ ]
542
+ );
543
  }
544
  }
545
 
876
  */
877
  function _do_upgrade_4120() {
878
  if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4120' ) {
879
+ \tsf()->update_option( 'ping_use_cron_prerender', 0 );
 
880
  }
881
  }
882
 
890
  \delete_option( 'the_seo_framework_tested_upgrade_version' );
891
  }
892
  }
893
+
894
+ /**
895
+ * Registers the `auto_descripton_html_method` option, string.
896
+ *
897
+ * @since 4.2.7
898
+ */
899
+ function _do_upgrade_4270() {
900
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4270' ) {
901
+ \tsf()->update_option( 'auto_descripton_html_method', 'fast' );
902
+ }
903
+ }
inc/classes/admin-init.class.php CHANGED
@@ -218,81 +218,88 @@ class Admin_Init extends Init {
218
  // phpcs:disable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
219
  /**
220
  * @since 3.1.0
221
- * @param array $guidelines The title and description guidelines.
222
- * Don't alter the format. Only change the numeric values.
 
 
 
223
  */
224
  return memo(
225
- (array) \apply_filters(
226
  'the_seo_framework_input_guidelines',
227
  [
228
- 'title' => [
229
- 'search' => [
230
- 'chars' => [
231
- 'lower' => (int) ( 25 * $c_adjust ),
232
- 'goodLower' => (int) ( 35 * $c_adjust ),
233
- 'goodUpper' => (int) ( 65 * $c_adjust ),
234
- 'upper' => (int) ( 75 * $c_adjust ),
 
 
 
 
 
 
 
 
235
  ],
236
- 'pixels' => [
237
- 'lower' => (int) ( 200 * $p_adjust ),
238
- 'goodLower' => (int) ( 280 * $p_adjust ),
239
- 'goodUpper' => (int) ( 520 * $p_adjust ),
240
- 'upper' => (int) ( 600 * $p_adjust ),
 
 
 
241
  ],
242
- ],
243
- 'opengraph' => [
244
- 'chars' => [
245
- 'lower' => 15,
246
- 'goodLower' => 25,
247
- 'goodUpper' => 88,
248
- 'upper' => 100,
249
- ],
250
- 'pixels' => [],
251
- ],
252
- 'twitter' => [
253
- 'chars' => [
254
- 'lower' => 15,
255
- 'goodLower' => 25,
256
- 'goodUpper' => 69,
257
- 'upper' => 70,
258
  ],
259
- 'pixels' => [],
260
  ],
261
- ],
262
- 'description' => [
263
- 'search' => [
264
- 'chars' => [
265
- 'lower' => (int) ( 45 * $c_adjust ),
266
- 'goodLower' => (int) ( 80 * $c_adjust ),
267
- 'goodUpper' => (int) ( 160 * $c_adjust ),
268
- 'upper' => (int) ( 320 * $c_adjust ),
 
 
 
 
 
 
269
  ],
270
- 'pixels' => [
271
- 'lower' => (int) ( 256 * $p_adjust ),
272
- 'goodLower' => (int) ( 455 * $p_adjust ),
273
- 'goodUpper' => (int) ( 910 * $p_adjust ),
274
- 'upper' => (int) ( 1820 * $p_adjust ),
 
 
 
275
  ],
276
- ],
277
- 'opengraph' => [
278
- 'chars' => [
279
- 'lower' => 45,
280
- 'goodLower' => 80,
281
- 'goodUpper' => 200,
282
- 'upper' => 300,
283
- ],
284
- 'pixels' => [],
285
- ],
286
- 'twitter' => [
287
- 'chars' => [
288
- 'lower' => 45,
289
- 'goodLower' => 80,
290
- 'goodUpper' => 200,
291
- 'upper' => 200,
292
  ],
293
- 'pixels' => [],
294
  ],
295
  ],
 
 
296
  ]
297
  ),
298
  $locale
218
  // phpcs:disable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
219
  /**
220
  * @since 3.1.0
221
+ * @since 4.2.7 Added two more paramters (`$c_adjust` and `$locale`)
222
+ * @param array $guidelines The title and description guidelines.
223
+ * Don't alter the format. Only change the numeric values.
224
+ * @param array[$c_adjust,$p_adjust] The guideline calibration (Character and Pixels respectively).
225
+ * @param string $locale The current locale.
226
  */
227
  return memo(
228
+ (array) \apply_filters_ref_array(
229
  'the_seo_framework_input_guidelines',
230
  [
231
+ [
232
+ 'title' => [
233
+ 'search' => [
234
+ 'chars' => [
235
+ 'lower' => (int) ( 25 * $c_adjust ),
236
+ 'goodLower' => (int) ( 35 * $c_adjust ),
237
+ 'goodUpper' => (int) ( 65 * $c_adjust ),
238
+ 'upper' => (int) ( 75 * $c_adjust ),
239
+ ],
240
+ 'pixels' => [
241
+ 'lower' => (int) ( 200 * $p_adjust ),
242
+ 'goodLower' => (int) ( 280 * $p_adjust ),
243
+ 'goodUpper' => (int) ( 520 * $p_adjust ),
244
+ 'upper' => (int) ( 600 * $p_adjust ),
245
+ ],
246
  ],
247
+ 'opengraph' => [
248
+ 'chars' => [
249
+ 'lower' => 15,
250
+ 'goodLower' => 25,
251
+ 'goodUpper' => 88,
252
+ 'upper' => 100,
253
+ ],
254
+ 'pixels' => [],
255
  ],
256
+ 'twitter' => [
257
+ 'chars' => [
258
+ 'lower' => 15,
259
+ 'goodLower' => 25,
260
+ 'goodUpper' => 69,
261
+ 'upper' => 70,
262
+ ],
263
+ 'pixels' => [],
 
 
 
 
 
 
 
 
264
  ],
 
265
  ],
266
+ 'description' => [
267
+ 'search' => [
268
+ 'chars' => [
269
+ 'lower' => (int) ( 45 * $c_adjust ),
270
+ 'goodLower' => (int) ( 80 * $c_adjust ),
271
+ 'goodUpper' => (int) ( 160 * $c_adjust ),
272
+ 'upper' => (int) ( 320 * $c_adjust ),
273
+ ],
274
+ 'pixels' => [
275
+ 'lower' => (int) ( 256 * $p_adjust ),
276
+ 'goodLower' => (int) ( 455 * $p_adjust ),
277
+ 'goodUpper' => (int) ( 910 * $p_adjust ),
278
+ 'upper' => (int) ( 1820 * $p_adjust ),
279
+ ],
280
  ],
281
+ 'opengraph' => [
282
+ 'chars' => [
283
+ 'lower' => 45,
284
+ 'goodLower' => 80,
285
+ 'goodUpper' => 200,
286
+ 'upper' => 300,
287
+ ],
288
+ 'pixels' => [],
289
  ],
290
+ 'twitter' => [
291
+ 'chars' => [
292
+ 'lower' => 45,
293
+ 'goodLower' => 80,
294
+ 'goodUpper' => 200,
295
+ 'upper' => 200,
296
+ ],
297
+ 'pixels' => [],
 
 
 
 
 
 
 
 
298
  ],
 
299
  ],
300
  ],
301
+ [ $c_adjust, $p_adjust ],
302
+ $locale,
303
  ]
304
  ),
305
  $locale
inc/classes/admin-pages.class.php CHANGED
@@ -362,10 +362,12 @@ class Admin_Pages extends Generate_Ldjson {
362
  foreach ( $notices as $key => $notice ) {
363
  $cond = $notice['conditions'];
364
 
365
- if ( ! \current_user_can( $cond['capability'] ) ) continue;
366
- if ( $cond['user'] && $cond['user'] !== $this->get_user_id() ) continue;
367
- if ( $cond['screens'] && ! \in_array( $screenbase, $cond['screens'], true ) ) continue;
368
- if ( $cond['excl_screens'] && \in_array( $screenbase, $cond['excl_screens'], true ) ) continue;
 
 
369
 
370
  if ( -1 !== $cond['timeout'] && $cond['timeout'] < time() ) {
371
  $this->clear_persistent_notice( $key );
362
  foreach ( $notices as $key => $notice ) {
363
  $cond = $notice['conditions'];
364
 
365
+ if (
366
+ ! \current_user_can( $cond['capability'] )
367
+ || ( $cond['user'] && $cond['user'] !== $this->get_user_id() )
368
+ || ( $cond['screens'] && ! \in_array( $screenbase, $cond['screens'], true ) )
369
+ || ( $cond['excl_screens'] && \in_array( $screenbase, $cond['excl_screens'], true ) )
370
+ ) continue;
371
 
372
  if ( -1 !== $cond['timeout'] && $cond['timeout'] < time() ) {
373
  $this->clear_persistent_notice( $key );
inc/classes/bridges/ajax.class.php CHANGED
@@ -215,16 +215,14 @@ final class AJAX {
215
  ];
216
 
217
  // Copy the image caption attribute (post_excerpt field) from the original image.
218
- if ( \strlen( trim( $original_attachment->post_excerpt ) ) ) {
219
  $attachment['post_excerpt'] = $original_attachment->post_excerpt;
220
- }
221
 
222
  // Copy the image alt text attribute from the original image.
223
- if ( \strlen( trim( $original_attachment->_wp_attachment_image_alt ) ) ) {
224
  $attachment['meta_input'] = [
225
  '_wp_attachment_image_alt' => \wp_slash( $original_attachment->_wp_attachment_image_alt ),
226
  ];
227
- }
228
 
229
  $attachment_id = \wp_insert_attachment( $attachment, $cropped );
230
  $metadata = \wp_generate_attachment_metadata( $attachment_id, $cropped );
215
  ];
216
 
217
  // Copy the image caption attribute (post_excerpt field) from the original image.
218
+ if ( \strlen( trim( $original_attachment->post_excerpt ) ) )
219
  $attachment['post_excerpt'] = $original_attachment->post_excerpt;
 
220
 
221
  // Copy the image alt text attribute from the original image.
222
+ if ( \strlen( trim( $original_attachment->_wp_attachment_image_alt ) ) )
223
  $attachment['meta_input'] = [
224
  '_wp_attachment_image_alt' => \wp_slash( $original_attachment->_wp_attachment_image_alt ),
225
  ];
 
226
 
227
  $attachment_id = \wp_insert_attachment( $attachment, $cropped );
228
  $metadata = \wp_generate_attachment_metadata( $attachment_id, $cropped );
inc/classes/bridges/feed.class.php CHANGED
@@ -29,7 +29,7 @@ namespace The_SEO_Framework\Bridges;
29
  * Prepares feed mofifications.
30
  *
31
  * @since 4.1.0
32
- * @access protected
33
  * @final Can't be extended.
34
  */
35
  final class Feed {
@@ -37,18 +37,16 @@ final class Feed {
37
  /**
38
  * @since 4.1.0
39
  * @var \The_SEO_Framework\Bridges\Feed
 
40
  */
41
  private static $instance;
42
 
43
- /**
44
- * @var null|\The_SEO_Framework\Load
45
- */
46
- private static $tsf = null;
47
-
48
  /**
49
  * Returns this instance.
50
  *
51
  * @since 4.1.0
 
 
52
  *
53
  * @return \The_SEO_Framework\Bridges\Feed $instance
54
  */
@@ -63,27 +61,21 @@ final class Feed {
63
  * this class is needed yet.
64
  *
65
  * @since 4.1.0
 
 
66
  */
67
  public static function prepare() {
68
  static::get_instance();
69
  }
70
 
71
  /**
72
- * The constructor. Can't be instantiated externally from this file.
73
- * Kills PHP on subsequent duplicated request. Enforces singleton.
74
- *
75
- * This probably autoloads at action "template_redirect", priority "1".
76
  *
77
- * @since 4.1.0
78
  * @access private
79
- * @internal
80
  */
81
  public function __construct() {
82
-
83
- static $count = 0;
84
- 0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
85
-
86
- static::$tsf = \tsf();
87
  }
88
 
89
  /**
@@ -91,9 +83,12 @@ final class Feed {
91
  *
92
  * @since 4.1.0
93
  * @access private
 
94
  */
95
  public function _init() {
96
 
 
 
97
  // Alter the content feed.
98
  \add_filter( 'the_content_feed', [ $this, '_modify_the_content_feed' ], 10, 2 );
99
 
@@ -117,73 +112,48 @@ final class Feed {
117
  */
118
  public function _modify_the_content_feed( $content = '', $feed_type = null ) {
119
 
 
120
  if ( ! $content ) return '';
121
 
 
 
122
  /**
123
  * Don't alter already-excerpts or descriptions.
124
  * $feed_type is only set on 'the_content_feed' filter.
125
  */
126
- if ( isset( $feed_type ) && static::$tsf->get_option( 'excerpt_the_feed' ) ) {
127
- $content = $this->convert_feed_entry_to_excerpt( $content );
 
 
 
 
 
 
 
 
 
 
 
128
  }
129
 
130
- if ( static::$tsf->get_option( 'source_the_feed' ) ) {
131
- $content .= "\n" . $this->get_feed_entry_source_link();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
133
 
134
  return $content;
135
  }
136
-
137
- /**
138
- * Converts feed content to excerpt.
139
- *
140
- * @since 4.1.0
141
- *
142
- * @param string $content The full feed entry content.
143
- * @return string The excerpted feed.
144
- */
145
- protected function convert_feed_entry_to_excerpt( $content = '' ) {
146
-
147
- if ( ! $content ) return '';
148
-
149
- /**
150
- * @since 2.5.2
151
- * @param int $max_len The maximum feed (multibyte) string length.
152
- */
153
- $max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
154
-
155
- // Strip all code and lines, and AI-trim it.
156
- $excerpt = static::$tsf->trim_excerpt(
157
- static::$tsf->s_excerpt_raw( $content, false ),
158
- 0,
159
- $max_len
160
- );
161
-
162
- return "<p>$excerpt</p>";
163
- }
164
-
165
- /**
166
- * Generates and returns feed source link.
167
- *
168
- * @since 4.1.0
169
- *
170
- * @return string The translatable feed entry source link.
171
- */
172
- protected function get_feed_entry_source_link() {
173
- /**
174
- * @since 2.6.0
175
- * @since 2.7.2 or 2.7.3 : Escaped output.
176
- * @param string $source The source indication string.
177
- */
178
- $source_i18n = (string) \apply_filters(
179
- 'the_seo_framework_feed_source_link_text',
180
- \_x( 'Source', 'The content source', 'autodescription' )
181
- );
182
-
183
- return sprintf(
184
- '<p><a href="%s" rel="nofollow">%s</a></p>', // Keep XHTML
185
- \esc_url( \get_permalink() ),
186
- \esc_html( $source_i18n )
187
- );
188
- }
189
  }
29
  * Prepares feed mofifications.
30
  *
31
  * @since 4.1.0
32
+ * @access private
33
  * @final Can't be extended.
34
  */
35
  final class Feed {
37
  /**
38
  * @since 4.1.0
39
  * @var \The_SEO_Framework\Bridges\Feed
40
+ * @ignore
41
  */
42
  private static $instance;
43
 
 
 
 
 
 
44
  /**
45
  * Returns this instance.
46
  *
47
  * @since 4.1.0
48
+ * @TODO deprecate. Use constructor instead.
49
+ * @ignore
50
  *
51
  * @return \The_SEO_Framework\Bridges\Feed $instance
52
  */
61
  * this class is needed yet.
62
  *
63
  * @since 4.1.0
64
+ * @TODO deprecate. Use constructor instead.
65
+ * @ignore
66
  */
67
  public static function prepare() {
68
  static::get_instance();
69
  }
70
 
71
  /**
72
+ * Initialized feed modifications.
 
 
 
73
  *
74
+ * @since 4.2.7
75
  * @access private
 
76
  */
77
  public function __construct() {
78
+ $this->_init();
 
 
 
 
79
  }
80
 
81
  /**
83
  *
84
  * @since 4.1.0
85
  * @access private
86
+ * @TODO deprecate. Use constructor instead.
87
  */
88
  public function _init() {
89
 
90
+ if ( \The_SEO_Framework\has_run( __METHOD__ ) ) return;
91
+
92
  // Alter the content feed.
93
  \add_filter( 'the_content_feed', [ $this, '_modify_the_content_feed' ], 10, 2 );
94
 
112
  */
113
  public function _modify_the_content_feed( $content = '', $feed_type = null ) {
114
 
115
+ // When there's no content, there's nothing to modify or quote.
116
  if ( ! $content ) return '';
117
 
118
+ $tsf = \tsf();
119
+
120
  /**
121
  * Don't alter already-excerpts or descriptions.
122
  * $feed_type is only set on 'the_content_feed' filter.
123
  */
124
+ if ( isset( $feed_type ) && $tsf->get_option( 'excerpt_the_feed' ) ) {
125
+ // Strip all code and lines, and AI-trim it.
126
+ $excerpt = $tsf->trim_excerpt(
127
+ $tsf->s_excerpt_raw( $content, false ),
128
+ 0,
129
+ /**
130
+ * @since 2.5.2
131
+ * @param int $max_len The maximum feed (multibyte) string length.
132
+ */
133
+ \apply_filters( 'the_seo_framework_max_content_feed_length', 400 )
134
+ );
135
+
136
+ $content = "<p>$excerpt</p>";
137
  }
138
 
139
+ if ( $tsf->get_option( 'source_the_feed' ) ) {
140
+ $content .= sprintf(
141
+ "\n" . '<p><a href="%s" rel="nofollow">%s</a></p>', // Keep XHTML valid!
142
+ \esc_url( \get_permalink() ),
143
+ \esc_html(
144
+ /**
145
+ * @since 2.6.0
146
+ * @since 2.7.2 or 2.7.3: Escaped output.
147
+ * @param string $source The source indication string.
148
+ */
149
+ \apply_filters(
150
+ 'the_seo_framework_feed_source_link_text',
151
+ \_x( 'Source', 'The content source', 'autodescription' )
152
+ )
153
+ )
154
+ );
155
  }
156
 
157
  return $content;
158
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
inc/classes/bridges/scripts.class.php CHANGED
@@ -75,7 +75,7 @@ final class Scripts {
75
 
76
  $tsf = \tsf();
77
 
78
- $_scripts = [
79
  static::get_tsf_scripts(),
80
  static::get_tt_scripts(),
81
  ];
@@ -83,73 +83,75 @@ final class Scripts {
83
  if ( $tsf->is_post_edit() ) {
84
  static::prepare_media_scripts();
85
 
86
- $_scripts[] = static::get_post_edit_scripts();
87
- $_scripts[] = static::get_tabs_scripts();
88
- $_scripts[] = static::get_media_scripts();
89
- $_scripts[] = static::get_title_scripts();
90
- $_scripts[] = static::get_description_scripts();
91
- $_scripts[] = static::get_social_scripts();
92
- $_scripts[] = static::get_primaryterm_scripts();
93
- $_scripts[] = static::get_ays_scripts();
94
 
95
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
96
- $_scripts[] = static::get_counter_scripts();
97
 
98
  if ( $tsf->is_gutenberg_page() )
99
- $_scripts[] = static::get_gutenberg_compat_scripts();
100
  } elseif ( $tsf->is_term_edit() ) {
101
  static::prepare_media_scripts();
102
 
103
- $_scripts[] = static::get_term_edit_scripts();
104
- $_scripts[] = static::get_media_scripts();
105
- $_scripts[] = static::get_title_scripts();
106
- $_scripts[] = static::get_description_scripts();
107
- $_scripts[] = static::get_social_scripts();
108
- $_scripts[] = static::get_ays_scripts();
109
 
110
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
111
- $_scripts[] = static::get_counter_scripts();
112
  } elseif ( $tsf->is_wp_lists_edit() ) {
113
- $_scripts[] = static::get_list_edit_scripts();
114
- $_scripts[] = static::get_title_scripts();
115
- $_scripts[] = static::get_description_scripts();
116
 
117
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
118
- $_scripts[] = static::get_counter_scripts();
119
  } elseif ( $tsf->is_seo_settings_page() ) {
120
  static::prepare_media_scripts();
121
  static::prepare_metabox_scripts();
122
 
123
- $_scripts[] = static::get_seo_settings_scripts();
124
- $_scripts[] = static::get_tabs_scripts();
125
- $_scripts[] = static::get_media_scripts();
126
- $_scripts[] = static::get_title_scripts();
127
- $_scripts[] = static::get_description_scripts();
128
- $_scripts[] = static::get_social_scripts();
129
- $_scripts[] = static::get_ays_scripts();
130
 
131
  // Always load unconditionally, options may enable the counters dynamically.
132
- $_scripts[] = static::get_counter_scripts();
133
  }
134
 
135
  /**
136
  * @since 3.1.0
137
  * @since 4.0.0 1. Now holds all scripts.
138
  * 2. Added $loader parameter.
 
139
  * @param array $scripts The default CSS and JS loader settings.
140
  * @param string $builder The \The_SEO_Framework\Builders\Scripts builder class name.
141
  * @param string $loader The \The_SEO_Framework\Bridges\Scripts loader class name.
142
  */
143
- $_scripts = \apply_filters_ref_array(
144
  'the_seo_framework_scripts',
145
  [
146
- $_scripts,
 
147
  \The_SEO_Framework\Builders\Scripts::class,
148
  static::class, // i.e. `\The_SEO_Framework\Bridges\Scripts::class`
149
  ]
150
  );
151
 
152
- \The_SEO_Framework\Builders\Scripts::register( $_scripts );
153
  }
154
 
155
  /**
75
 
76
  $tsf = \tsf();
77
 
78
+ $scripts = [
79
  static::get_tsf_scripts(),
80
  static::get_tt_scripts(),
81
  ];
83
  if ( $tsf->is_post_edit() ) {
84
  static::prepare_media_scripts();
85
 
86
+ $scripts[] = static::get_post_edit_scripts();
87
+ $scripts[] = static::get_tabs_scripts();
88
+ $scripts[] = static::get_media_scripts();
89
+ $scripts[] = static::get_title_scripts();
90
+ $scripts[] = static::get_description_scripts();
91
+ $scripts[] = static::get_social_scripts();
92
+ $scripts[] = static::get_primaryterm_scripts();
93
+ $scripts[] = static::get_ays_scripts();
94
 
95
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
96
+ $scripts[] = static::get_counter_scripts();
97
 
98
  if ( $tsf->is_gutenberg_page() )
99
+ $scripts[] = static::get_gutenberg_compat_scripts();
100
  } elseif ( $tsf->is_term_edit() ) {
101
  static::prepare_media_scripts();
102
 
103
+ $scripts[] = static::get_term_edit_scripts();
104
+ $scripts[] = static::get_media_scripts();
105
+ $scripts[] = static::get_title_scripts();
106
+ $scripts[] = static::get_description_scripts();
107
+ $scripts[] = static::get_social_scripts();
108
+ $scripts[] = static::get_ays_scripts();
109
 
110
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
111
+ $scripts[] = static::get_counter_scripts();
112
  } elseif ( $tsf->is_wp_lists_edit() ) {
113
+ $scripts[] = static::get_list_edit_scripts();
114
+ $scripts[] = static::get_title_scripts();
115
+ $scripts[] = static::get_description_scripts();
116
 
117
  if ( $tsf->get_option( 'display_pixel_counter' ) || $tsf->get_option( 'display_character_counter' ) )
118
+ $scripts[] = static::get_counter_scripts();
119
  } elseif ( $tsf->is_seo_settings_page() ) {
120
  static::prepare_media_scripts();
121
  static::prepare_metabox_scripts();
122
 
123
+ $scripts[] = static::get_seo_settings_scripts();
124
+ $scripts[] = static::get_tabs_scripts();
125
+ $scripts[] = static::get_media_scripts();
126
+ $scripts[] = static::get_title_scripts();
127
+ $scripts[] = static::get_description_scripts();
128
+ $scripts[] = static::get_social_scripts();
129
+ $scripts[] = static::get_ays_scripts();
130
 
131
  // Always load unconditionally, options may enable the counters dynamically.
132
+ $scripts[] = static::get_counter_scripts();
133
  }
134
 
135
  /**
136
  * @since 3.1.0
137
  * @since 4.0.0 1. Now holds all scripts.
138
  * 2. Added $loader parameter.
139
+ * @since 4.2.7 Consolidated all input scripts into a list.
140
  * @param array $scripts The default CSS and JS loader settings.
141
  * @param string $builder The \The_SEO_Framework\Builders\Scripts builder class name.
142
  * @param string $loader The \The_SEO_Framework\Bridges\Scripts loader class name.
143
  */
144
+ $scripts = \apply_filters_ref_array(
145
  'the_seo_framework_scripts',
146
  [
147
+ // Flattening is 3% of this method's total time, we can improve by simplifying the getters above like do_meta_output().
148
+ $tsf->array_flatten_list( $scripts ),
149
  \The_SEO_Framework\Builders\Scripts::class,
150
  static::class, // i.e. `\The_SEO_Framework\Bridges\Scripts::class`
151
  ]
152
  );
153
 
154
+ \The_SEO_Framework\Builders\Scripts::register( $scripts );
155
  }
156
 
157
  /**
inc/classes/builders/coresitemaps/main.class.php CHANGED
@@ -57,6 +57,7 @@ class Main extends \The_SEO_Framework\Builders\Sitemap\Main {
57
  * @since 4.1.2
58
  * @abstract
59
  * @ignore
 
60
  *
61
  * @return string The sitemap content.
62
  */
@@ -64,6 +65,32 @@ class Main extends \The_SEO_Framework\Builders\Sitemap\Main {
64
  return '';
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  /**
68
  * Filters Core sitemap provider.
69
  *
57
  * @since 4.1.2
58
  * @abstract
59
  * @ignore
60
+ * @override
61
  *
62
  * @return string The sitemap content.
63
  */
65
  return '';
66
  }
67
 
68
+ /**
69
+ * Sets "doing sitemap" in TSF if preliminary conditions pass.
70
+ * We do this via a filter, which is unconventional but a bypass.
71
+ *
72
+ * @link <https://core.trac.wordpress.org/ticket/56954>
73
+ * @since 4.2.7
74
+ * @access private
75
+ * @global \WP_Query $wp_query We test against the main query here.
76
+ *
77
+ * @param array $args Array of proposed WP_Query arguments.
78
+ * @return array $args The WP_Query arguments, unaltered.
79
+ */
80
+ public static function _trick_filter_doing_sitemap( $args ) {
81
+ global $wp_query;
82
+
83
+ // If doing Core sitemaps, verify if is actual sitemap, and block if so.
84
+ if ( isset( $wp_query->query_vars['sitemap'] ) ) {
85
+ // Didn't we request a simple API function for this? Anyway, null safe operators would also be nice here.
86
+ // For now, let's assume this API won't change. Test periodically.
87
+ if ( \wp_sitemaps_get_server()->registry->get_provider( $wp_query->query_vars['sitemap'] ) )
88
+ \tsf()->is_sitemap( true );
89
+ }
90
+
91
+ return $args;
92
+ }
93
+
94
  /**
95
  * Filters Core sitemap provider.
96
  *
inc/classes/builders/images.class.php CHANGED
@@ -117,6 +117,9 @@ final class Images {
117
  * 2. Now only yields at most 5 images.
118
  * @since 4.2.0 1. Fixed OB1 error causing the first image to be ignored.
119
  * 2. Now supports the `$args['pta']` index.
 
 
 
120
  * @generator
121
  * @TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
122
  * Combine query, instead of using WP API? Only do that for the first image, instead?
@@ -148,19 +151,21 @@ final class Images {
148
  $matches = [];
149
 
150
  // \strlen( '<img src=a>' ) === 11; yes, that's a valid self-closing tag with a relative source.
151
- if ( \strlen( $content ) > 10 && false !== stripos( $content, '<img' ) ) {
 
152
  $content = $tsf->strip_tags_cs(
153
  $content,
154
  [
155
  'space' => [],
156
  'clear' =>
157
- [ 'address', 'aside', 'blockquote', 'dd', 'dl', 'dt', 'fieldset', 'figcaption', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'nav', 'ol', 'pre', 'table', 'tfoot', 'ul', 'bdo', 'br', 'button', 'canvas', 'code', 'hr', 'iframe', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
158
  'strip' => false,
159
  ]
160
  );
 
161
  // TODO can we somehow limit this search to static::MAX_CONTENT_IMAGES? -> We could, via preg_match(), but the opcodes won't help.
162
  preg_match_all(
163
- '/<img[^>]+?src=(\"|\')?([^\"\'>\s]+)\1?[^>]*?>/mi',
164
  $content,
165
  $matches,
166
  PREG_SET_ORDER
117
  * 2. Now only yields at most 5 images.
118
  * @since 4.2.0 1. Fixed OB1 error causing the first image to be ignored.
119
  * 2. Now supports the `$args['pta']` index.
120
+ * @since 4.2.7 1. No longer accidentally matches `<imganything` or `<img notsrc="source">`.
121
+ * 2. Can no longer use images from `datalist`, `dialog`, `hgroup`, `menu`, `ol`, `object`, `output`, and `template` elements.
122
+ * 3. No longer expect images from `dd`, `dt`, `figcaption`, `li`, `tfoot`, `br`, `hr`, `link`, `meta`, `option`, `samp`.
123
  * @generator
124
  * @TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
125
  * Combine query, instead of using WP API? Only do that for the first image, instead?
151
  $matches = [];
152
 
153
  // \strlen( '<img src=a>' ) === 11; yes, that's a valid self-closing tag with a relative source.
154
+ if ( \strlen( $content ) > 10 && false !== stripos( $content, '<img ' ) ) {
155
+ // Clear what might have unfavourable images.
156
  $content = $tsf->strip_tags_cs(
157
  $content,
158
  [
159
  'space' => [],
160
  'clear' =>
161
+ [ 'address', 'aside', 'blockquote', 'button', 'canvas', 'code', 'datalist', 'dialog', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'iframe', 'input', 'label', 'map', 'menu', 'nav', 'noscript', 'ol', 'object', 'output', 'pre', 'script', 'select', 'style', 'svg', 'table', 'template', 'textarea', 'ul', 'var', 'video' ],
162
  'strip' => false,
163
  ]
164
  );
165
+
166
  // TODO can we somehow limit this search to static::MAX_CONTENT_IMAGES? -> We could, via preg_match(), but the opcodes won't help.
167
  preg_match_all(
168
+ '/<img\b[^>]+?\bsrc=(["\'])?([^\"\'>\s]+)\1?[^>]*?>/mi',
169
  $content,
170
  $matches,
171
  PREG_SET_ORDER
inc/classes/builders/robots/args.class.php CHANGED
@@ -113,15 +113,10 @@ final class Args extends Factory {
113
  yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, \get_post_type( $args['id'] ) );
114
  }
115
 
116
- index_protection: if ( $asserting_noindex ) {
117
- // We assert options here for a jump to index_protection might be unaware.
118
- if ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION )
119
- goto after_index_protection;
120
-
121
  if ( ! $args['taxonomy'] )
122
  yield from static::assert_noindex_query_pass( 'protected' );
123
  }
124
- after_index_protection:;
125
 
126
  end:;
127
  }
113
  yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, \get_post_type( $args['id'] ) );
114
  }
115
 
116
+ index_protection: if ( $asserting_noindex && ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) ) {
 
 
 
 
117
  if ( ! $args['taxonomy'] )
118
  yield from static::assert_noindex_query_pass( 'protected' );
119
  }
 
120
 
121
  end:;
122
  }
inc/classes/builders/robots/main.class.php CHANGED
@@ -128,7 +128,7 @@ final class Main {
128
  // Remit FETCH_OBJ_R opcode calls every time we'd otherwise use $this->options hereinafter.
129
  $options = $this->options;
130
 
131
- $assert = $options & \The_SEO_Framework\ROBOTS_ASSERT;
132
 
133
  $assert
134
  and $this->reset_assertions();
128
  // Remit FETCH_OBJ_R opcode calls every time we'd otherwise use $this->options hereinafter.
129
  $options = $this->options;
130
 
131
+ $assert = (bool) ( $options & \The_SEO_Framework\ROBOTS_ASSERT );
132
 
133
  $assert
134
  and $this->reset_assertions();
inc/classes/builders/robots/query.class.php CHANGED
@@ -131,20 +131,19 @@ final class Query extends Factory {
131
  index_protection: if ( $asserting_noindex && ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) ) {
132
  if ( $tsf->is_real_front_page() ) {
133
  yield from static::assert_noindex_query_pass( 'paged_home' );
134
- } else {
135
- if ( $tsf->is_archive() || $tsf->is_singular_archive() ) {
136
- yield from static::assert_noindex_query_pass( 'paged' );
137
- } elseif ( $tsf->is_singular() ) {
138
- yield from static::assert_noindex_query_pass( 'protected' );
139
 
140
- /**
141
- * N.B. WordPress protects this query variable with options 'page_comments'
142
- * and 'default_comments_page' via `redirect_canonical()`, so we don't have to.
143
- * For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
144
- */
145
- if ( (int) \get_query_var( 'cpage', 0 ) > 0 )
146
- yield from static::assert_noindex_query_pass( 'cpage' );
147
- }
148
  }
149
  }
150
 
131
  index_protection: if ( $asserting_noindex && ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) ) {
132
  if ( $tsf->is_real_front_page() ) {
133
  yield from static::assert_noindex_query_pass( 'paged_home' );
134
+ } elseif ( $tsf->is_archive() || $tsf->is_singular_archive() ) {
135
+ yield from static::assert_noindex_query_pass( 'paged' );
136
+ }
137
+ if ( $tsf->is_singular() ) {
138
+ yield from static::assert_noindex_query_pass( 'protected' );
139
 
140
+ /**
141
+ * N.B. WordPress protects this query variable with options 'page_comments'
142
+ * and 'default_comments_page' via `redirect_canonical()`, so we don't have to.
143
+ * For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
144
+ */
145
+ if ( (int) \get_query_var( 'cpage', 0 ) > 0 )
146
+ yield from static::assert_noindex_query_pass( 'cpage' );
 
147
  }
148
  }
149
 
inc/classes/builders/scripts.class.php CHANGED
@@ -209,7 +209,7 @@ final class Scripts {
209
  * @NOTE If the script is associative, it'll be registered as-is.
210
  * If the script is sequential, it'll be iterated over, and then registered.
211
  *
212
- * @param array $script The script : {
213
  * 'id' => string The script ID,
214
  * 'type' => string 'css|js',
215
  * 'autoload' => boolean If true, the script will be loaded directly.
@@ -231,6 +231,7 @@ final class Scripts {
231
  * }
232
  */
233
  public static function register( $script ) {
 
234
  if ( array_values( $script ) === $script ) {
235
  foreach ( $script as $s ) static::register( $s );
236
  return;
@@ -470,6 +471,8 @@ final class Scripts {
470
  * Converts color CSS.
471
  *
472
  * @since 3.1.0
 
 
473
  *
474
  * @param array $css The CSS to convert.
475
  * @return array $css
@@ -484,10 +487,8 @@ final class Scripts {
484
 
485
  $tsf = \tsf();
486
 
487
- if (
488
- ! isset( $_colors[ $_scheme ]->colors )
489
- || ! \is_array( $_colors[ $_scheme ]->colors )
490
- || \count( $_colors[ $_scheme ]->colors ) < 4 // unexpected scheme, ignore and override.
491
  ) {
492
  $_colors = [
493
  '#222',
@@ -499,25 +500,15 @@ final class Scripts {
499
  $_colors = $_colors[ $_scheme ]->colors;
500
  }
501
 
502
- $_bg = $_colors[0];
503
- $_bg_accent = $_colors[1];
504
- $_color = $_colors[2];
505
- $_color_accent = $_colors[3];
506
-
507
- $_rel_bg = '#' . $tsf->get_relative_fontcolor( $_colors[0] );
508
- $_rel_bg_accent = '#' . $tsf->get_relative_fontcolor( $_colors[1] );
509
- $_rel_color = '#' . $tsf->get_relative_fontcolor( $_colors[2] );
510
- $_rel_color_accent = '#' . $tsf->get_relative_fontcolor( $_colors[3] );
511
-
512
  $_table = [
513
- '{{$bg}}' => $_bg,
514
- '{{$rel_bg}}' => $_rel_bg,
515
- '{{$bg_accent}}' => $_bg_accent,
516
- '{{$rel_bg_accent}}' => $_rel_bg_accent,
517
- '{{$color}}' => $_color,
518
- '{{$rel_color}}' => $_rel_color,
519
- '{{$color_accent}}' => $_color_accent,
520
- '{{$rel_color_accent}}' => $_rel_color_accent,
521
  ];
522
 
523
  $c_ck = array_keys( $_table );
209
  * @NOTE If the script is associative, it'll be registered as-is.
210
  * If the script is sequential, it'll be iterated over, and then registered.
211
  *
212
+ * @param array|array[] $script The script or sequential array of scripts : {
213
  * 'id' => string The script ID,
214
  * 'type' => string 'css|js',
215
  * 'autoload' => boolean If true, the script will be loaded directly.
231
  * }
232
  */
233
  public static function register( $script ) {
234
+ // This is 350x faster than a polyfill for `array_is_list()`.
235
  if ( array_values( $script ) === $script ) {
236
  foreach ( $script as $s ) static::register( $s );
237
  return;
471
  * Converts color CSS.
472
  *
473
  * @since 3.1.0
474
+ * @TODO WordPress will one day normalize this correctly.
475
+ * @link <https://make.wordpress.org/core/2021/02/23/standardization-of-wp-admin-colors-in-wordpress-5-7/>
476
  *
477
  * @param array $css The CSS to convert.
478
  * @return array $css
487
 
488
  $tsf = \tsf();
489
 
490
+ if ( ! \is_array( $_colors[ $_scheme ]->colors ?? null )
491
+ || \count( $_colors[ $_scheme ]->colors ) < 4 // unexpected scheme, ignore and override.
 
 
492
  ) {
493
  $_colors = [
494
  '#222',
500
  $_colors = $_colors[ $_scheme ]->colors;
501
  }
502
 
 
 
 
 
 
 
 
 
 
 
503
  $_table = [
504
+ '{{$bg}}' => $_colors[0],
505
+ '{{$rel_bg}}' => "#{$tsf->get_relative_fontcolor( $_colors[0] )}",
506
+ '{{$bg_accent}}' => $_colors[1],
507
+ '{{$rel_bg_accent}}' => "#{$tsf->get_relative_fontcolor( $_colors[1] )}",
508
+ '{{$color}}' => $_colors[2],
509
+ '{{$rel_color}}' => "#{$tsf->get_relative_fontcolor( $_colors[2] )}",
510
+ '{{$color_accent}}' => $_colors[3],
511
+ '{{$rel_color_accent}}' => "#{$tsf->get_relative_fontcolor( $_colors[3] )}",
512
  ];
513
 
514
  $c_ck = array_keys( $_table );
inc/classes/builders/seobar/page.class.php CHANGED
@@ -218,7 +218,7 @@ final class Page extends Main {
218
  }
219
  }
220
 
221
- if ( static::$tsf->has_yoast_syntax( $title_part ) ) {
222
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
223
  $item['reason'] = $cache['reason']['syntax'];
224
  $item['assess']['syntax'] = $cache['assess']['syntax'];
@@ -436,7 +436,7 @@ final class Page extends Main {
436
  }
437
  }
438
 
439
- if ( static::$tsf->has_yoast_syntax( $desc ) ) {
440
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
441
  $item['reason'] = $cache['reason']['syntax'];
442
  $item['assess']['syntax'] = $cache['assess']['syntax'];
@@ -474,10 +474,11 @@ final class Page extends Main {
474
 
475
  // No description is found. There's no need to continue parsing.
476
  return $item;
477
- } else {
478
- if ( ! empty( $this->query_cache['post']->post_excerpt ) ) {
479
- $item['assess']['base'] = $cache['assess']['excerpt'];
480
- }
 
481
  }
482
  }
483
 
@@ -518,6 +519,7 @@ final class Page extends Main {
518
  $guidelines = static::$tsf->get_input_guidelines( $this->query_cache['states']['locale'] )['description']['search']['chars'];
519
  $guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
520
 
 
521
  $desc_len = mb_strlen(
522
  html_entity_decode(
523
  \wp_specialchars_decode( static::$tsf->s_description_raw( $desc ), ENT_QUOTES ),
218
  }
219
  }
220
 
221
+ if ( static::$tsf->has_unprocessed_syntax( $title_part ) ) {
222
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
223
  $item['reason'] = $cache['reason']['syntax'];
224
  $item['assess']['syntax'] = $cache['assess']['syntax'];
436
  }
437
  }
438
 
439
+ if ( static::$tsf->has_unprocessed_syntax( $desc ) ) {
440
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
441
  $item['reason'] = $cache['reason']['syntax'];
442
  $item['assess']['syntax'] = $cache['assess']['syntax'];
474
 
475
  // No description is found. There's no need to continue parsing.
476
  return $item;
477
+ } elseif ( ! empty( $this->query_cache['post']->post_excerpt ) ) {
478
+ // FIXME: This is not necessarily true if the field is filtered...
479
+ // TODO test if filter "the_seo_framework_fetched_description_excerpt" is used?
480
+ // Use something like the robots generator...? Ugh, here we go again.
481
+ $item['assess']['base'] = $cache['assess']['excerpt'];
482
  }
483
  }
484
 
519
  $guidelines = static::$tsf->get_input_guidelines( $this->query_cache['states']['locale'] )['description']['search']['chars'];
520
  $guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
521
 
522
+ // TODO FIXME: Use s_description() instead of s_description_raw()? E.g, hellip gets converted to dot dot dot..
523
  $desc_len = mb_strlen(
524
  html_entity_decode(
525
  \wp_specialchars_decode( static::$tsf->s_description_raw( $desc ), ENT_QUOTES ),
inc/classes/builders/seobar/term.class.php CHANGED
@@ -224,7 +224,7 @@ final class Term extends Main {
224
  if ( \strlen( $title_part ) ) {
225
  $item = $cache['defaults']['custom'];
226
 
227
- if ( static::$tsf->has_yoast_syntax( $title_part, false ) ) {
228
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
229
  $item['reason'] = $cache['reason']['syntax'];
230
  $item['assess']['syntax'] = $cache['assess']['syntax'];
@@ -417,7 +417,7 @@ final class Term extends Main {
417
  if ( \strlen( $desc ) ) {
418
  $item = $cache['defaults']['custom'];
419
 
420
- if ( static::$tsf->has_yoast_syntax( $desc ) ) {
421
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
422
  $item['reason'] = $cache['reason']['syntax'];
423
  $item['assess']['syntax'] = $cache['assess']['syntax'];
224
  if ( \strlen( $title_part ) ) {
225
  $item = $cache['defaults']['custom'];
226
 
227
+ if ( static::$tsf->has_unprocessed_syntax( $title_part, false ) ) {
228
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
229
  $item['reason'] = $cache['reason']['syntax'];
230
  $item['assess']['syntax'] = $cache['assess']['syntax'];
417
  if ( \strlen( $desc ) ) {
418
  $item = $cache['defaults']['custom'];
419
 
420
+ if ( static::$tsf->has_unprocessed_syntax( $desc ) ) {
421
  $item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
422
  $item['reason'] = $cache['reason']['syntax'];
423
  $item['assess']['syntax'] = $cache['assess']['syntax'];
inc/classes/builders/sitemap/base.class.php CHANGED
@@ -25,8 +25,6 @@ namespace The_SEO_Framework\Builders\Sitemap;
25
 
26
  \defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
27
 
28
- use function \The_SEO_Framework\umemo;
29
-
30
  /**
31
  * Generates the base sitemap.
32
  *
@@ -152,7 +150,7 @@ class Base extends Main {
152
  * 2. Improved performance by a factor of two+.
153
  * 3. Renamed method from "generate_sitemap" to abstract extension "build_sitemap".
154
  * 4. Moved to \The_SEO_Framework\Builders\Sitemap\Base
155
- * @abstract
156
  * @slow The queried results are not stored in WP Post's cache, which would allow direct access
157
  * to all values of the post (if requested). This is because we're using
158
  * `'fields' => 'ids'` instead of `'fields' => 'all'`. However, this would fill RAM
@@ -163,6 +161,12 @@ class Base extends Main {
163
  */
164
  public function build_sitemap() {
165
 
 
 
 
 
 
 
166
  $content = '';
167
  $count = 0;
168
 
@@ -351,9 +355,8 @@ class Base extends Main {
351
  ]
352
  );
353
 
354
- if ( $extend ) {
355
- $content .= "\t" . $extend . "\n";
356
- }
357
 
358
  return $content;
359
  }
25
 
26
  \defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
27
 
 
 
28
  /**
29
  * Generates the base sitemap.
30
  *
150
  * 2. Improved performance by a factor of two+.
151
  * 3. Renamed method from "generate_sitemap" to abstract extension "build_sitemap".
152
  * 4. Moved to \The_SEO_Framework\Builders\Sitemap\Base
153
+ * @override
154
  * @slow The queried results are not stored in WP Post's cache, which would allow direct access
155
  * to all values of the post (if requested). This is because we're using
156
  * `'fields' => 'ids'` instead of `'fields' => 'all'`. However, this would fill RAM
161
  */
162
  public function build_sitemap() {
163
 
164
+ /**
165
+ * @since 4.2.7
166
+ * @param \The_SEO_Framework\Builders\Sitemap\Base
167
+ */
168
+ \do_action( 'the_seo_framework_build_sitemap_base', $this );
169
+
170
  $content = '';
171
  $count = 0;
172
 
355
  ]
356
  );
357
 
358
+ if ( $extend )
359
+ $content .= "\t$extend\n";
 
360
 
361
  return $content;
362
  }
inc/classes/builders/sitemap/index.php CHANGED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * So essential did I consider an index to be to every book, that I proposed
4
+ * to bring a bill into Parliament to deprive an author who publishes a book
5
+ * without an index of the privilege of copyright, and, moreover, to subject
6
+ * him for his offense to a pecuniary penalty.
7
+ *
8
+ * - John Campbell, 1st Baron Campbell
9
+ */
inc/classes/builders/sitemap/main.class.php CHANGED
@@ -131,7 +131,7 @@ abstract class Main {
131
  $tabs = str_repeat( "\t", $level );
132
 
133
  if ( \is_array( $value ) )
134
- $value = "\n" . $this->create_xml_entry( $value, $level + 1 ) . $tabs;
135
 
136
  $out .= "$tabs<$key>$value</$key>\n";
137
  }
131
  $tabs = str_repeat( "\t", $level );
132
 
133
  if ( \is_array( $value ) )
134
+ $value = "\n{$this->create_xml_entry( $value, $level + 1 )}$tabs";
135
 
136
  $out .= "$tabs<$key>$value</$key>\n";
137
  }
inc/classes/core.class.php CHANGED
@@ -241,7 +241,7 @@ class Core {
241
  * @return string The view location.
242
  */
243
  public function get_view_location( $file ) {
244
- return THE_SEO_FRAMEWORK_DIR_PATH_VIEWS . $file . '.php';
245
  }
246
 
247
  /**
@@ -417,7 +417,7 @@ class Core {
417
  * @return string The converted time. Empty string if no $time is given.
418
  */
419
  public function gmt2date( $format = 'Y-m-d', $time = '' ) {
420
- return $time ? gmdate( $format, strtotime( $time . ' GMT' ) ) : '';
421
  }
422
 
423
  /**
@@ -455,30 +455,69 @@ class Core {
455
  return '1' === $this->get_option( 'timestamps_format' );
456
  }
457
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  /**
459
  * Merges arrays distinctly, much like `array_merge()`, but then for multidimensionals.
460
  * Unlike PHP's `array_merge_recursive()`, this method doesn't convert non-unique keys as sequential.
461
  *
462
- * A do-while is faster than while. Sorry for the legibility.
463
- * TODO instead of calling thyself, would a goto not be better?
464
  *
465
  * @since 4.1.4
 
 
 
 
466
  *
467
  * @param array ...$arrays The arrays to merge. The rightmost array's values are dominant.
468
  * @return array The merged arrays.
469
  */
470
- public function array_merge_recursive_distinct( array ...$arrays ) {
471
 
472
  $i = \count( $arrays );
473
 
474
- if ( 2 === $i ) foreach ( $arrays[1] as $key => $value ) {
475
- $arrays[0][ $key ] = \is_array( $arrays[0][ $key ] ?? null )
476
- ? $this->array_merge_recursive_distinct( $arrays[0][ $key ], $value )
477
- : $value;
478
- } else do {
479
- // phpcs:ignore -- Imagine assigning from right to left, but also left to right. Yes:
480
- $arrays[ --$i - 1 ] = $this->array_merge_recursive_distinct( $arrays[ $i - 1 ], $arrays[ $i ] );
481
- } while ( $i > 1 );
482
 
483
  return $arrays[0];
484
  }
@@ -535,6 +574,7 @@ class Core {
535
 
536
  if ( ! $string ) return [];
537
 
 
538
  $use_mb = memo( null, 'use_mb' ) ?? memo( \extension_loaded( 'mbstring' ), 'use_mb' );
539
 
540
  $word_list = preg_split(
@@ -592,19 +632,21 @@ class Core {
592
  * @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
593
  * @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
594
  *
595
- * @param string $hex The 3 to 6 character RGB hex. The '#' prefix may be added.
596
- * RRGGBBAA is supported, but the Alpha channels won't be returned.
597
  * @return string The hexadecimal RGB relative font color, without '#' prefix.
598
  */
599
  public function get_relative_fontcolor( $hex = '' ) {
600
 
 
 
601
  $hex = ltrim( $hex, '#' );
602
 
603
  // Convert hex to usable numerics.
604
  [ $r, $g, $b ] = array_map(
605
  'hexdec',
606
  str_split(
607
- // rgb == rrggbb.
608
  \strlen( $hex ) >= 6 ? $hex : "$hex[0]$hex[0]$hex[1]$hex[1]$hex[2]$hex[2]",
609
  2
610
  )
241
  * @return string The view location.
242
  */
243
  public function get_view_location( $file ) {
244
+ return THE_SEO_FRAMEWORK_DIR_PATH_VIEWS . "$file.php";
245
  }
246
 
247
  /**
417
  * @return string The converted time. Empty string if no $time is given.
418
  */
419
  public function gmt2date( $format = 'Y-m-d', $time = '' ) {
420
+ return $time ? gmdate( $format, strtotime( "$time GMT" ) ) : '';
421
  }
422
 
423
  /**
455
  return '1' === $this->get_option( 'timestamps_format' );
456
  }
457
 
458
+ /**
459
+ * Flattens multidimensional lists into a single dimensional list.
460
+ * Deeply nested lists are merged as well. Won't dig associative arrays.
461
+ *
462
+ * E.g., this [ [ 'one' => 1 ], [ [ 'two' => 2 ], [ 'three' => [ 3, 4 ] ] ] ]
463
+ * becomes [ [ 'one' => 1 ], [ 'two', => 2 ], [ 'three' => [ 3, 4 ] ] ];
464
+ *
465
+ * @link <https://3v4l.org/XBSFa>, test it here.
466
+ *
467
+ * @since 4.2.7
468
+ * @access private
469
+ * @ignore This will move to new "helper" classes in a future update, becoming public then.
470
+ *
471
+ * @param array $array The array to flatten. If input is not an array, it'll be casted.
472
+ * @return array The flattened array.
473
+ */
474
+ public function array_flatten_list( $array ) {
475
+
476
+ // We can later use `!array_is_list()`.
477
+ // This is 350x faster than a polyfill for `!array_is_list()`.
478
+ if ( [] === $array || array_values( $array ) !== $array ) return $array;
479
+
480
+ $ret = [];
481
+
482
+ foreach ( $array as $key => $value ) {
483
+ // We can later use `array_is_list()`.
484
+ if ( \is_array( $value ) && [] !== $value && array_values( $value ) === $value ) {
485
+ $ret = array_merge( $ret, $this->array_flatten_list( $value ) );
486
+ } else {
487
+ array_push( $ret, $value );
488
+ }
489
+ }
490
+
491
+ return $ret;
492
+ }
493
+
494
  /**
495
  * Merges arrays distinctly, much like `array_merge()`, but then for multidimensionals.
496
  * Unlike PHP's `array_merge_recursive()`, this method doesn't convert non-unique keys as sequential.
497
  *
498
+ * @link <https://3v4l.org/9pnW1#v8.1.8> Test it here.
 
499
  *
500
  * @since 4.1.4
501
+ * @since 4.2.7 1. Now supports a single array entry without causing issues.
502
+ * 2. Reduced number of opcodes by roughly 27% by reworking it.
503
+ * 3. Now no longer throws warnings with qubed+ arrays.
504
+ * 4. Now no longer prevents scalar values overwriting arrays.
505
  *
506
  * @param array ...$arrays The arrays to merge. The rightmost array's values are dominant.
507
  * @return array The merged arrays.
508
  */
509
+ public function array_merge_recursive_distinct( ...$arrays ) {
510
 
511
  $i = \count( $arrays );
512
 
513
+ while ( --$i ) {
514
+ $p = $i - 1;
515
+
516
+ foreach ( $arrays[ $i ] as $key => $value )
517
+ $arrays[ $p ][ $key ] = isset( $arrays[ $p ][ $key ] ) && \is_array( $value )
518
+ ? $this->array_merge_recursive_distinct( $arrays[ $p ][ $key ], $value )
519
+ : $value;
520
+ }
521
 
522
  return $arrays[0];
523
  }
574
 
575
  if ( ! $string ) return [];
576
 
577
+ // Not if-function-exists; we're going for speed over accuracy. Hosts must do their job correctly.
578
  $use_mb = memo( null, 'use_mb' ) ?? memo( \extension_loaded( 'mbstring' ), 'use_mb' );
579
 
580
  $word_list = preg_split(
632
  * @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
633
  * @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
634
  *
635
+ * @param string $hex The 3 to 6+ character RGB hex. The '#' prefix may be added.
636
+ * RGBA/RRGGBBAA is supported, but the Alpha channels won't be returned.
637
  * @return string The hexadecimal RGB relative font color, without '#' prefix.
638
  */
639
  public function get_relative_fontcolor( $hex = '' ) {
640
 
641
+ // TODO: To support RGBA, we must fill to 4 or 8 via sprintf `%0{1,2}x`
642
+ // But doing this will add processing requirements for something we do not need... yet.
643
  $hex = ltrim( $hex, '#' );
644
 
645
  // Convert hex to usable numerics.
646
  [ $r, $g, $b ] = array_map(
647
  'hexdec',
648
  str_split(
649
+ // rgb[..] == rrggbb[..].
650
  \strlen( $hex ) >= 6 ? $hex : "$hex[0]$hex[0]$hex[1]$hex[1]$hex[2]$hex[2]",
651
  2
652
  )
inc/classes/detect.class.php CHANGED
@@ -672,6 +672,8 @@ class Detect extends Render {
672
  * the homepage is not a blog, then this query is malformed. Otherwise, however, it's a good query.
673
  *
674
  * @since 4.0.5
 
 
675
  * @global \WP_Query $wp_query
676
  *
677
  * @return bool Whether the query is (accidentally) exploited.
@@ -701,11 +703,12 @@ class Detect extends Render {
701
  /**
702
  * @since 4.0.5
703
  * @param array $exploitables The exploitable endpoints by type.
 
704
  */
705
  $exploitables = \apply_filters(
706
  'the_seo_framework_exploitable_query_endpoints',
707
  [
708
- 'numeric' => [
709
  'page_id',
710
  'attachment_id',
711
  'year',
@@ -720,13 +723,18 @@ class Detect extends Render {
720
  'second',
721
  'subpost_id',
722
  ],
723
- 'numeric_array' => [
724
  'cat',
725
  'author',
726
  ],
727
- 'requires_s' => [
728
  'sentence',
729
  ],
 
 
 
 
 
730
  ]
731
  );
732
 
@@ -749,7 +757,7 @@ class Detect extends Render {
749
 
750
  // If WordPress didn't canonical_redirect() the user yet, it's exploited.
751
  // WordPress mitigates this via a 404 query when a numeric value is found.
752
- if ( ! preg_match( '/[0-9]/', $query[ $qv ] ) )
753
  return memo( true );
754
  break;
755
 
@@ -758,6 +766,13 @@ class Detect extends Render {
758
  return memo( true );
759
  break;
760
 
 
 
 
 
 
 
 
761
  default:
762
  break;
763
  endswitch;
@@ -1245,29 +1260,205 @@ class Detect extends Render {
1245
  );
1246
  }
1247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1248
  /**
1249
  * Determines if the input text has transformative Yoast SEO syntax.
1250
  *
 
 
1251
  * @since 4.0.5
1252
- * @link <https://yoast.com/help/list-available-snippet-variables-yoast-seo/>
 
 
 
 
1253
  *
1254
  * @param string $text The text to evaluate.
1255
  * @return bool
1256
  */
1257
  public function has_yoast_syntax( $text ) {
1258
 
1259
- if ( false === strpos( $text, '%%' ) ) return false;
 
 
1260
 
1261
- $tags_simple = [ 'date', 'title', 'parent_title', 'archive_title', 'sitename', 'sitedesc', 'excerpt', 'excerpt_only', 'tag', 'category', 'primary_category', 'category_description', 'tag_description', 'term_description', 'term_title', 'searchphrase', 'sep', 'pt_single', 'pt_plural', 'modified', 'id', 'name', 'user_description', 'page', 'pagetotal', 'pagenumber', 'caption', 'focuskw', 'term404', 'ct_product_cat', 'ct_product_tag', 'wc_shortdesc', 'wc_sku', 'wc_brand', 'wc_price' ];
1262
- $_regex = sprintf( '%%%s%%', implode( '|', $tags_simple ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1263
 
1264
- if ( preg_match( "/$_regex/i", $text ) ) return true;
 
 
 
1265
 
1266
- $tags_wildcard_end = [ 'cs_', 'ct_desc_', 'ct_pa_' ];
1267
- $_regex = sprintf( '%%(%s)[^\s]*?%%', implode( '|', $tags_wildcard_end ) );
 
 
 
 
 
 
 
 
 
1268
 
1269
- if ( preg_match( "/$_regex/", $text ) ) return true;
 
 
1270
 
1271
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1272
  }
1273
  }
672
  * the homepage is not a blog, then this query is malformed. Otherwise, however, it's a good query.
673
  *
674
  * @since 4.0.5
675
+ * @since 4.2.7 1. Added detection `not_home_as_page`, specifically for query variable `search`.
676
+ * 2. Improved detection for `cat` and `author`, where the value may only be numeric above 0.
677
  * @global \WP_Query $wp_query
678
  *
679
  * @return bool Whether the query is (accidentally) exploited.
703
  /**
704
  * @since 4.0.5
705
  * @param array $exploitables The exploitable endpoints by type.
706
+ * @since 4.2.7 Added index `not_home_as_page` with value `search`.
707
  */
708
  $exploitables = \apply_filters(
709
  'the_seo_framework_exploitable_query_endpoints',
710
  [
711
+ 'numeric' => [
712
  'page_id',
713
  'attachment_id',
714
  'year',
723
  'second',
724
  'subpost_id',
725
  ],
726
+ 'numeric_array' => [
727
  'cat',
728
  'author',
729
  ],
730
+ 'requires_s' => [
731
  'sentence',
732
  ],
733
+ 'not_home_as_page' => [
734
+ // No public application registered in WP for this, yet it is a public variable.
735
+ // Having any other valid query mitigates.
736
+ 'search',
737
+ ],
738
  ]
739
  );
740
 
757
 
758
  // If WordPress didn't canonical_redirect() the user yet, it's exploited.
759
  // WordPress mitigates this via a 404 query when a numeric value is found.
760
+ if ( ! preg_match( '/^[1-9][0-9]*$/', $query[ $qv ] ) )
761
  return memo( true );
762
  break;
763
 
766
  return memo( true );
767
  break;
768
 
769
+ case 'not_home_as_page':
770
+ // isset($query[$qv]) is already executed. Just test if homepage ID still works.
771
+ // !$this->get_the_real_ID() is already executed. Just test if home is a page.
772
+ if ( $this->is_home_as_page() )
773
+ return memo( true );
774
+ break;
775
+
776
  default:
777
  break;
778
  endswitch;
1260
  );
1261
  }
1262
 
1263
+ /**
1264
+ * Determines whether the text has recognizable transformative syntax.
1265
+ *
1266
+ * It tests Yoast SEO before Rank Math because
1267
+ *
1268
+ * @todo test all [ 'extension', 'yoast', 'aioseo', 'rankmath', 'seopress' ]
1269
+ * @since 4.2.7
1270
+ *
1271
+ * @param string $text The text to evaluate
1272
+ * @return bool
1273
+ */
1274
+ public function has_unprocessed_syntax( $text ) {
1275
+
1276
+ foreach ( [ 'yoast', 'rankmath' ] as $type )
1277
+ if ( $this->{"has_{$type}_syntax"}( $text ) ) return true;
1278
+
1279
+ return false;
1280
+ }
1281
+
1282
  /**
1283
  * Determines if the input text has transformative Yoast SEO syntax.
1284
  *
1285
+ * TODO rename to yoast_seo?
1286
+ *
1287
  * @since 4.0.5
1288
+ * @since 4.2.7 1. Added wildcard `ct_`, and `cf_` detection.
1289
+ * 2. Added detection for various other types
1290
+ * 2. Removed wildcard `cs_` detection.
1291
+ * @link <https://yoast.com/help/list-available-snippet-variables-yoast-seo/> (This list containts false information)
1292
+ * @link <https://theseoframework.com/extensions/transport/#faq/what-data-is-transformed>
1293
  *
1294
  * @param string $text The text to evaluate.
1295
  * @return bool
1296
  */
1297
  public function has_yoast_syntax( $text ) {
1298
 
1299
+ // %%id%% is the shortest valid tag... ish. Let's stop at 6.
1300
+ if ( \strlen( $text ) < 6 || false === strpos( $text, '%%' ) )
1301
+ return false;
1302
 
1303
+ $tags = umemo( __METHOD__ . '/tags' );
1304
+
1305
+ if ( ! $tags ) {
1306
+ $tags = umemo(
1307
+ __METHOD__ . '/tags',
1308
+ [
1309
+ 'simple' => implode(
1310
+ '|',
1311
+ [
1312
+ // These are Preserved by Transport. Test first, for they are more likely in text.
1313
+ 'focuskw',
1314
+ 'page',
1315
+ 'pagenumber',
1316
+ 'pagetotal',
1317
+ 'primary_category',
1318
+ 'searchphrase',
1319
+ 'term404',
1320
+ 'wc_brand',
1321
+ 'wc_price',
1322
+ 'wc_shortdesc',
1323
+ 'wc_sku',
1324
+
1325
+ // These are transformed by Transport
1326
+ 'archive_title',
1327
+ 'author_first_name',
1328
+ 'author_last_name',
1329
+ 'caption',
1330
+ 'category',
1331
+ 'category_description',
1332
+ 'category_title',
1333
+ 'currentdate',
1334
+ 'currentday',
1335
+ 'currentmonth',
1336
+ 'currentyear',
1337
+ 'date',
1338
+ 'excerpt',
1339
+ 'excerpt_only',
1340
+ 'id',
1341
+ 'modified',
1342
+ 'name',
1343
+ 'parent_title',
1344
+ 'permalink',
1345
+ 'post_content',
1346
+ 'post_year',
1347
+ 'post_month',
1348
+ 'post_day',
1349
+ 'pt_plural',
1350
+ 'pt_single',
1351
+ 'sep',
1352
+ 'sitedesc',
1353
+ 'sitename',
1354
+ 'tag',
1355
+ 'tag_description',
1356
+ 'term_description',
1357
+ 'term_title',
1358
+ 'title',
1359
+ 'user_description',
1360
+ 'userid',
1361
+ ]
1362
+ ),
1363
+ 'wildcard_end' => implode( '|', [ 'ct_', 'cf_' ] ),
1364
+ ]
1365
+ );
1366
+ }
1367
 
1368
+ // https://en.wikipedia.org/wiki/Leaning_toothpick_syndrome... crap.
1369
+ return preg_match( sprintf( '/%%%%(?:%s)%%%%/', $tags['simple'] ), $text )
1370
+ || preg_match( sprintf( '/%%%%(?:%s)[^%%]+?%%%%/', $tags['wildcard_end'] ), $text );
1371
+ }
1372
 
1373
+ /**
1374
+ * Determines if the input text has transformative Rank Math syntax.
1375
+ *
1376
+ * @since 4.2.7
1377
+ * @link <https://theseoframework.com/extensions/transport/#faq/what-data-is-transformed>
1378
+ * Rank Math has no documentation on this list.
1379
+ *
1380
+ * @param string $text The text to evaluate.
1381
+ * @return bool
1382
+ */
1383
+ public function has_rankmath_syntax( $text ) {
1384
 
1385
+ // %id% is the shortest valid tag... ish. Let's stop at 4.
1386
+ if ( \strlen( $text ) < 4 || false === strpos( $text, '%' ) )
1387
+ return false;
1388
 
1389
+ $tags = umemo( __METHOD__ . '/tags' );
1390
+
1391
+ if ( ! $tags ) {
1392
+ $tags = umemo(
1393
+ __METHOD__ . '/tags',
1394
+ [
1395
+ 'simple' => implode(
1396
+ '|',
1397
+ [
1398
+ // These are Preserved by Transport. Test first, for they are more likely in text.
1399
+ 'currenttime', // Rank Math has two currenttime, this one is simple.
1400
+ 'filename',
1401
+ 'focuskw',
1402
+ 'org_name',
1403
+ 'org_logo',
1404
+ 'org_url',
1405
+ 'page',
1406
+ 'pagenumber',
1407
+ 'pagetotal',
1408
+ 'primary_category',
1409
+ 'searchphrase',
1410
+ 'term404',
1411
+ 'wc_brand',
1412
+ 'wc_price',
1413
+ 'wc_shortdesc',
1414
+ 'wc_sku',
1415
+
1416
+ // These are transformed by Transport
1417
+ 'archive_title',
1418
+ 'author_first_name',
1419
+ 'author_last_name',
1420
+ 'caption',
1421
+ 'category',
1422
+ 'category_description',
1423
+ 'category_title',
1424
+ 'currentdate',
1425
+ 'currentday',
1426
+ 'currentmonth',
1427
+ 'currentyear',
1428
+ 'date',
1429
+ 'excerpt',
1430
+ 'excerpt_only',
1431
+ 'id',
1432
+ 'modified',
1433
+ 'name',
1434
+ 'parent_title',
1435
+ 'permalink',
1436
+ 'post_content',
1437
+ 'post_year',
1438
+ 'post_month',
1439
+ 'post_day',
1440
+ 'pt_plural',
1441
+ 'pt_single',
1442
+ 'sep',
1443
+ 'sitedesc',
1444
+ 'sitename',
1445
+ 'tag',
1446
+ 'tag_description',
1447
+ 'term_description',
1448
+ 'term',
1449
+ 'title',
1450
+ 'user_description',
1451
+ 'userid',
1452
+ ]
1453
+ ),
1454
+ // See RankMath\Replace_Variables\Replacer::set_up_replacements();
1455
+ 'wildcard_end' => implode( '|', [ 'count', 'currenttime', 'customfield', 'customterm' ] ),
1456
+ ]
1457
+ );
1458
+ }
1459
+
1460
+ // https://en.wikipedia.org/wiki/Leaning_toothpick_syndrome... crap.
1461
+ return preg_match( sprintf( '/%%(?:%s)%%/', $tags['simple'] ), $text )
1462
+ || preg_match( sprintf( '/%%(?:%s)\([^\)]+?\)%%/', $tags['wildcard_end'] ), $text );
1463
  }
1464
  }
inc/classes/generate-description.class.php CHANGED
@@ -483,6 +483,9 @@ class Generate_Description extends Generate {
483
 
484
  if ( ! $this->is_auto_description_enabled( $args ) ) return '';
485
 
 
 
 
486
  if ( null === $args ) {
487
  $excerpt = $this->get_description_excerpt_from_query();
488
  } else {
@@ -490,9 +493,6 @@ class Generate_Description extends Generate {
490
  $excerpt = $this->get_description_excerpt_from_args( $args );
491
  }
492
 
493
- if ( ! \in_array( $type, [ 'opengraph', 'twitter', 'search' ], true ) )
494
- $type = 'search';
495
-
496
  /**
497
  * @since 2.9.0
498
  * @since 3.1.0 No longer passes 3rd and 4th parameter.
@@ -582,12 +582,8 @@ class Generate_Description extends Generate {
582
  */
583
  protected function get_description_excerpt_from_query() {
584
 
585
- static $excerpt;
586
-
587
- if ( isset( $excerpt ) )
588
- return $excerpt;
589
-
590
- $excerpt = '';
591
 
592
  if ( $this->is_real_front_page() ) {
593
  $excerpt = $this->get_front_page_description_excerpt();
@@ -599,7 +595,7 @@ class Generate_Description extends Generate {
599
  $excerpt = $this->get_archival_description_excerpt();
600
  }
601
 
602
- return $excerpt;
603
  }
604
 
605
  /**
@@ -746,6 +742,9 @@ class Generate_Description extends Generate {
746
  * Returns a description excerpt for singular post types.
747
  *
748
  * @since 3.1.0
 
 
 
749
  *
750
  * @param int $id The singular ID.
751
  * @return string
@@ -797,6 +796,7 @@ class Generate_Description extends Generate {
797
  * @since 3.1.0 1. No longer returns anything for terms.
798
  * 2. Now strips plausible embeds URLs.
799
  * @since 4.0.1 The second parameter `$id` now defaults to int 0, instead of an empty string.
 
800
  *
801
  * @param string $excerpt The Excerpt.
802
  * @param int $id The Post ID.
@@ -840,10 +840,10 @@ class Generate_Description extends Generate {
840
  */
841
  if ( ! empty( $post->post_excerpt ) ) {
842
  $excerpt = $post->post_excerpt;
843
- } elseif ( isset( $post->post_content ) ) {
844
  // We should actually get the parsed content here... but that can be heavy on the server.
845
  // We could cache that parsed content, but that'd be asinine for a plugin. WordPress should've done that.
846
- $excerpt = $this->uses_non_html_page_builder( $post->ID ) ? '' : $post->post_content;
847
 
848
  if ( $excerpt ) {
849
  $excerpt = $this->strip_newline_urls( $excerpt );
@@ -888,6 +888,7 @@ class Generate_Description extends Generate {
888
  * 4. Resolved some backtracking issues.
889
  * 5. Resolved an issue where a character followed by punctuation would cause the match to fail.
890
  * @since 4.2.0 Now enforces at least a character length of 1. This prevents needless processing.
 
891
  * @see https://secure.php.net/manual/en/regexp.reference.unicode.php
892
  *
893
  * We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`.
@@ -926,7 +927,7 @@ class Generate_Description extends Generate {
926
  $excerpt = \wptexturize( $excerpt );
927
  $excerpt = html_entity_decode( $excerpt, ENT_QUOTES, 'UTF-8' );
928
  /**
929
- * Play with it here: https://regex101.com/r/u0DIgx/5/ (old) https://regex101.com/r/G92lUt/3 (new)
930
  *
931
  * TODO Group 4's match is repeated. However, referring to it as (4) will cause it to congeal into 3.
932
  *
@@ -949,7 +950,7 @@ class Generate_Description extends Generate {
949
  * }
950
  */
951
  preg_match(
952
- '/(?:\A[\p{P}\p{Z}]*?)?([\P{Po}\p{M}\xBF\xA1:\p{Z}]+[\p{Z}\w])(?:([^\P{Po}\p{M}\xBF\xA1:]\Z(*ACCEPT))|((?(?=.+(?:\w+[\p{Pc}\p{Pd}\p{Pf}\p{Z}]*){1,3}|[\p{Po}]\Z)(?:.+[\p{Pe}\p{Pf}](*THEN)\Z(*ACCEPT)|.*[^\P{Po}\p{M}\xBF\xA1:])|.*\Z(*ACCEPT)))(?>(.+?\p{Z}*(?:\w+[\p{Pc}\p{Pd}\p{Pf}\p{Z}]*){1,3})|[^\p{Pc}\p{Pd}\p{M}\xBF\xA1:])?)(.+)?/su',
953
  $excerpt,
954
  $matches
955
  );
@@ -964,6 +965,7 @@ class Generate_Description extends Generate {
964
  } elseif ( isset( $matches[1] ) ) {
965
  $excerpt = $matches[1];
966
  }
 
967
 
968
  if ( \strlen( $excerpt ) < $min_char_length ) return '';
969
 
483
 
484
  if ( ! $this->is_auto_description_enabled( $args ) ) return '';
485
 
486
+ if ( ! \in_array( $type, [ 'opengraph', 'twitter', 'search' ], true ) )
487
+ $type = 'search';
488
+
489
  if ( null === $args ) {
490
  $excerpt = $this->get_description_excerpt_from_query();
491
  } else {
493
  $excerpt = $this->get_description_excerpt_from_args( $args );
494
  }
495
 
 
 
 
496
  /**
497
  * @since 2.9.0
498
  * @since 3.1.0 No longer passes 3rd and 4th parameter.
582
  */
583
  protected function get_description_excerpt_from_query() {
584
 
585
+ // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
586
+ if ( null !== $memo = memo() ) return $memo;
 
 
 
 
587
 
588
  if ( $this->is_real_front_page() ) {
589
  $excerpt = $this->get_front_page_description_excerpt();
595
  $excerpt = $this->get_archival_description_excerpt();
596
  }
597
 
598
+ return memo( $excerpt ?? '' );
599
  }
600
 
601
  /**
742
  * Returns a description excerpt for singular post types.
743
  *
744
  * @since 3.1.0
745
+ * NOTE: Don't add memo; large memory heaps can occur.
746
+ * It only runs twice on the post edit screen (post.php).
747
+ * Front-end caller get_description_excerpt_from_query() uses memo.
748
  *
749
  * @param int $id The singular ID.
750
  * @return string
796
  * @since 3.1.0 1. No longer returns anything for terms.
797
  * 2. Now strips plausible embeds URLs.
798
  * @since 4.0.1 The second parameter `$id` now defaults to int 0, instead of an empty string.
799
+ * TODO deprecate and simplify (remove $excerpt and $deprecated).
800
  *
801
  * @param string $excerpt The Excerpt.
802
  * @param int $id The Post ID.
840
  */
841
  if ( ! empty( $post->post_excerpt ) ) {
842
  $excerpt = $post->post_excerpt;
843
+ } elseif ( isset( $post->post_content, $post->ID ) && ! $this->uses_non_html_page_builder( $post->ID ) ) {
844
  // We should actually get the parsed content here... but that can be heavy on the server.
845
  // We could cache that parsed content, but that'd be asinine for a plugin. WordPress should've done that.
846
+ $excerpt = $post->post_content;
847
 
848
  if ( $excerpt ) {
849
  $excerpt = $this->strip_newline_urls( $excerpt );
888
  * 4. Resolved some backtracking issues.
889
  * 5. Resolved an issue where a character followed by punctuation would cause the match to fail.
890
  * @since 4.2.0 Now enforces at least a character length of 1. This prevents needless processing.
891
+ * @since 4.2.7 Now considers floating numerics as one word.
892
  * @see https://secure.php.net/manual/en/regexp.reference.unicode.php
893
  *
894
  * We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`.
927
  $excerpt = \wptexturize( $excerpt );
928
  $excerpt = html_entity_decode( $excerpt, ENT_QUOTES, 'UTF-8' );
929
  /**
930
+ * Play with it here: https://regex101.com/r/u0DIgx/5/ (old) https://regex101.com/r/G92lUt/5 (new)
931
  *
932
  * TODO Group 4's match is repeated. However, referring to it as (4) will cause it to congeal into 3.
933
  *
950
  * }
951
  */
952
  preg_match(
953
+ '/(?:\A[\p{P}\p{Z}]*?)?([\P{Po}\p{M}\xBF\xA1:\p{Z}]+[\p{Z}\w])(?:([^\P{Po}\p{M}\xBF\xA1:]\Z(*ACCEPT))|((?(?=.+(?:\w+[\p{Pc}\p{Pd}\p{Pf}\p{Z}]*){1,3}|[\p{Po}]\Z)(?:.+[\p{Pe}\p{Pf}](*THEN)\Z(*ACCEPT)|.*[^\P{Po}\p{M}\xBF\xA1:][^\P{Nd}\p{Z}]*)|.*\Z(*ACCEPT)))(?>(.+?\p{Z}*(?:\w+[\p{Pc}\p{Pd}\p{Pf}\p{Z}]*){1,3})|[^\p{Pc}\p{Pd}\p{M}\xBF\xA1:])?)(.+)?/su',
954
  $excerpt,
955
  $matches
956
  );
965
  } elseif ( isset( $matches[1] ) ) {
966
  $excerpt = $matches[1];
967
  }
968
+ // else { TODO Should we empty excerpt here? Can we even reach this? }
969
 
970
  if ( \strlen( $excerpt ) < $min_char_length ) return '';
971
 
inc/classes/generate-ldjson.class.php CHANGED
@@ -202,7 +202,7 @@ class Generate_Ldjson extends Generate_Image {
202
  */
203
  $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $search_link );
204
 
205
- if ( ! empty( $GLOBALS['wp_rewrite']->get_search_permastruct() ) ) {
206
  $pattern = \user_trailingslashit( '%s{%s}', 'search' );
207
  $search_url = \trailingslashit( $search_url );
208
  }
@@ -465,7 +465,7 @@ class Generate_Ldjson extends Generate_Image {
465
  if ( empty( $terms ) )
466
  return '';
467
 
468
- $terms = \wp_list_pluck( $terms, 'parent', 'term_id' );
469
 
470
  $parents = [];
471
  $assigned_ids = [];
@@ -483,7 +483,7 @@ class Generate_Ldjson extends Generate_Image {
483
  $parents[ $term_id ] = [];
484
  }
485
  endforeach;
486
- // Circle of life...
487
  unset( $terms );
488
 
489
  if ( ! $parents )
202
  */
203
  $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $search_link );
204
 
205
+ if ( $GLOBALS['wp_rewrite']->get_search_permastruct() ) {
206
  $pattern = \user_trailingslashit( '%s{%s}', 'search' );
207
  $search_url = \trailingslashit( $search_url );
208
  }
465
  if ( empty( $terms ) )
466
  return '';
467
 
468
+ $terms = \array_column( $terms, 'parent', 'term_id' );
469
 
470
  $parents = [];
471
  $assigned_ids = [];
483
  $parents[ $term_id ] = [];
484
  }
485
  endforeach;
486
+
487
  unset( $terms );
488
 
489
  if ( ! $parents )
inc/classes/generate-title.class.php CHANGED
@@ -713,7 +713,7 @@ class Generate_Title extends Generate_Description {
713
  *
714
  * @since 3.1.0
715
  * @since 4.2.0 Flipped order of query tests.
716
- * @since 4.3.0 Added failover filter for failed queries.
717
  * @internal
718
  * @see $this->get_raw_generated_title()
719
  *
@@ -783,7 +783,7 @@ class Generate_Title extends Generate_Description {
783
  /**
784
  * Returns the archive title. Also works in admin.
785
  *
786
- * @NOTE Taken from WordPress core. Altered to work for metadata.
787
  * @see WP Core get_the_archive_title()
788
  *
789
  * @since 3.1.0
@@ -795,8 +795,7 @@ class Generate_Title extends Generate_Description {
795
  *
796
  * @param \WP_Term|\WP_User|\WP_Post_Type|\WP_Error|null $object The Term object or error.
797
  * Leave null to autodetermine query.
798
- * @return string|string[] The generated archive title, not escaped.
799
- * When $get is 'admin', it returns an map of [prefix,title].
800
  */
801
  public function get_generated_archive_title( $object = null ) {
802
 
@@ -1063,6 +1062,7 @@ class Generate_Title extends Generate_Description {
1063
  * @since 3.1.0
1064
  * @since 4.0.0 No longer redundantly tests the query, now only uses the term input or queried object.
1065
  * @since 4.0.2 Now asserts the correct tag taxonomy condition.
 
1066
  *
1067
  * @param null|\WP_Term $term The term name, required in the admin area.
1068
  * @return string The generated single term title.
@@ -1074,7 +1074,7 @@ class Generate_Title extends Generate_Description {
1074
 
1075
  if ( ! isset( $term->name ) ) return '';
1076
 
1077
- switch ( $term->category ) :
1078
  case 'category':
1079
  /**
1080
  * Filter the category archive page title.
@@ -1350,7 +1350,7 @@ class Generate_Title extends Generate_Description {
1350
  */
1351
  $protected_title_format = (string) \apply_filters( 'protected_title_format', $prepend, $post );
1352
  $title = sprintf( $protected_title_format, $title );
1353
- } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
1354
 
1355
  /* translators: %s: Private post title. */
1356
  $prepend = \__( 'Private: %s', 'default' );
@@ -1366,7 +1366,6 @@ class Generate_Title extends Generate_Description {
1366
  * Default 'Private: %s'.
1367
  * @param WP_Post $post Current post object.
1368
  */
1369
- /* translators: %s: Private post title. */
1370
  $private_title_format = (string) \apply_filters( 'private_title_format', $prepend, $post );
1371
  $title = sprintf( $private_title_format, $title );
1372
  }
713
  *
714
  * @since 3.1.0
715
  * @since 4.2.0 Flipped order of query tests.
716
+ * @since 4.2.7 Added failover filter for failed queries.
717
  * @internal
718
  * @see $this->get_raw_generated_title()
719
  *
783
  /**
784
  * Returns the archive title. Also works in admin.
785
  *
786
+ * @NOTE Taken from WordPress core. Altered to work for metadata and in admin.
787
  * @see WP Core get_the_archive_title()
788
  *
789
  * @since 3.1.0
795
  *
796
  * @param \WP_Term|\WP_User|\WP_Post_Type|\WP_Error|null $object The Term object or error.
797
  * Leave null to autodetermine query.
798
+ * @return string The generated archive title, not escaped.
 
799
  */
800
  public function get_generated_archive_title( $object = null ) {
801
 
1062
  * @since 3.1.0
1063
  * @since 4.0.0 No longer redundantly tests the query, now only uses the term input or queried object.
1064
  * @since 4.0.2 Now asserts the correct tag taxonomy condition.
1065
+ * @since 4.2.7 Now invokes proper filters when 'category' or 'tag' taxonomies are used.
1066
  *
1067
  * @param null|\WP_Term $term The term name, required in the admin area.
1068
  * @return string The generated single term title.
1074
 
1075
  if ( ! isset( $term->name ) ) return '';
1076
 
1077
+ switch ( $term->taxonomy ) :
1078
  case 'category':
1079
  /**
1080
  * Filter the category archive page title.
1350
  */
1351
  $protected_title_format = (string) \apply_filters( 'protected_title_format', $prepend, $post );
1352
  $title = sprintf( $protected_title_format, $title );
1353
+ } elseif ( 'private' === ( $post->post_status ?? null ) ) {
1354
 
1355
  /* translators: %s: Private post title. */
1356
  $prepend = \__( 'Private: %s', 'default' );
1366
  * Default 'Private: %s'.
1367
  * @param WP_Post $post Current post object.
1368
  */
 
1369
  $private_title_format = (string) \apply_filters( 'private_title_format', $prepend, $post );
1370
  $title = sprintf( $private_title_format, $title );
1371
  }
inc/classes/generate.class.php CHANGED
@@ -212,7 +212,7 @@ class Generate extends User_Data {
212
  * @return string The separator.
213
  */
214
  public function get_separator( $type = 'title' ) {
215
- return $this->get_separator_list()[ $this->get_option( $type . '_separator' ) ] ?? '&#x2d;';
216
  }
217
 
218
  /**
@@ -378,7 +378,7 @@ class Generate extends User_Data {
378
  if ( null !== $memo = memo() ) return $memo;
379
 
380
  $id = $this->get_the_real_ID();
381
- $post_modified_gmt = \get_post( $id )->post_modified_gmt;
382
 
383
  return memo(
384
  '0000-00-00 00:00:00' === $post_modified_gmt
212
  * @return string The separator.
213
  */
214
  public function get_separator( $type = 'title' ) {
215
+ return $this->get_separator_list()[ $this->get_option( "{$type}_separator" ) ] ?? '&#x2d;';
216
  }
217
 
218
  /**
378
  if ( null !== $memo = memo() ) return $memo;
379
 
380
  $id = $this->get_the_real_ID();
381
+ $post_modified_gmt = \get_post( $id )->post_modified_gmt ?? '0000-00-00 00:00:00';
382
 
383
  return memo(
384
  '0000-00-00 00:00:00' === $post_modified_gmt
inc/classes/init.class.php CHANGED
@@ -479,7 +479,7 @@ class Init extends Query {
479
  * @since 4.0.4 1. Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
480
  * 2. Now always sets timezone regardless of settings, because, again, bug.
481
  * @since 4.2.0 No longer sets timezone.
482
- * @access private
483
  */
484
  public function html_output() {
485
 
@@ -719,6 +719,8 @@ class Init extends Query {
719
  // It's not a bridge, don't treat it like one: So, submit hooks here... But, clean me up?
720
  \add_filter( 'wp_sitemaps_add_provider', [ Builders\CoreSitemaps\Main::class, '_filter_add_provider' ], 9, 2 );
721
  \add_filter( 'wp_sitemaps_max_urls', [ Builders\CoreSitemaps\Main::class, '_filter_max_urls' ], 9 );
 
 
722
  }
723
 
724
  /**
@@ -728,7 +730,7 @@ class Init extends Query {
728
  * @access private
729
  */
730
  public function _init_feed() {
731
- \is_feed() and Bridges\Feed::get_instance()->_init();
732
  }
733
 
734
  /**
@@ -1066,7 +1068,8 @@ class Init extends Query {
1066
  * 2. Added taxonomy-supported lookups.
1067
  * 3. Added WP Rest checks for the Block Editor.
1068
  * @since 4.2.0 Improved supported taxonomy loop.
1069
- * @since 4.2.6 Added check for `did_action( 'wp_loaded' )`.
 
1070
  *
1071
  * @param \WP_Query $wp_query WP_Query object.
1072
  * @return bool
@@ -1109,7 +1112,11 @@ class Init extends Query {
1109
  }
1110
  }
1111
 
1112
- // This primarily affects 'terms'.
 
 
 
 
1113
  if ( ! empty( $wp_query->tax_query->queries ) ) :
1114
  $supported = true;
1115
 
@@ -1138,12 +1145,12 @@ class Init extends Query {
1138
  * @access private
1139
  *
1140
  * @param array $data The response data.
1141
- * @param \WP_Post $post The post object. May not be its placeholder `null`.
1142
  * @param int $width The requested width.
1143
  * @param int $height The calculated height.
1144
  * @return array Possibly altered $data.
1145
  */
1146
- public function _alter_oembed_response_data( $data = [], $post = null, $width = 0, $height = 0 ) {
1147
 
1148
  // Don't use cache. See @WARNING in doc comment.
1149
  if ( $this->get_option( 'oembed_use_og_title', false ) )
479
  * @since 4.0.4 1. Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
480
  * 2. Now always sets timezone regardless of settings, because, again, bug.
481
  * @since 4.2.0 No longer sets timezone.
482
+ * @since 4.2.7 No longer marked as private.
483
  */
484
  public function html_output() {
485
 
719
  // It's not a bridge, don't treat it like one: So, submit hooks here... But, clean me up?
720
  \add_filter( 'wp_sitemaps_add_provider', [ Builders\CoreSitemaps\Main::class, '_filter_add_provider' ], 9, 2 );
721
  \add_filter( 'wp_sitemaps_max_urls', [ Builders\CoreSitemaps\Main::class, '_filter_max_urls' ], 9 );
722
+ // We miss the proper hooks. https://github.com/sybrew/the-seo-framework/issues/610#issuecomment-1300191500
723
+ \add_filter( 'wp_sitemaps_posts_query_args', [ Builders\CoreSitemaps\Main::class, '_trick_filter_doing_sitemap' ], 11 );
724
  }
725
 
726
  /**
730
  * @access private
731
  */
732
  public function _init_feed() {
733
+ \is_feed() and new Bridges\Feed;
734
  }
735
 
736
  /**
1068
  * 2. Added taxonomy-supported lookups.
1069
  * 3. Added WP Rest checks for the Block Editor.
1070
  * @since 4.2.0 Improved supported taxonomy loop.
1071
+ * @since 4.2.6 Added check for `did_action( 'wp_loaded' )` early, before queries are tested and cached.
1072
+ * @since 4.2.7 No longer affects the sitemap query.
1073
  *
1074
  * @param \WP_Query $wp_query WP_Query object.
1075
  * @return bool
1112
  }
1113
  }
1114
 
1115
+ // If doing sitemap, don't adjust query via query settings.
1116
+ if ( $this->is_sitemap() )
1117
+ return true;
1118
+
1119
+ // This should primarily affect 'terms'. Test if TSF is blocked from supporting said terms.
1120
  if ( ! empty( $wp_query->tax_query->queries ) ) :
1121
  $supported = true;
1122
 
1145
  * @access private
1146
  *
1147
  * @param array $data The response data.
1148
+ * @param \WP_Post $post The post object.
1149
  * @param int $width The requested width.
1150
  * @param int $height The calculated height.
1151
  * @return array Possibly altered $data.
1152
  */
1153
+ public function _alter_oembed_response_data( $data, $post, $width, $height ) {
1154
 
1155
  // Don't use cache. See @WARNING in doc comment.
1156
  if ( $this->get_option( 'oembed_use_og_title', false ) )
inc/classes/post-data.class.php CHANGED
@@ -357,16 +357,17 @@ class Post_Data extends Detect {
357
  * @link https://github.com/sybrew/the-seo-framework/issues/48
358
  * @link https://johnblackbourn.com/post-meta-revisions-wordpress
359
  */
360
- if ( \wp_is_post_autosave( $post ) ) return;
361
- if ( \wp_is_post_revision( $post ) ) return;
362
 
363
  $nonce_name = $this->inpost_nonce_name;
364
  $nonce_action = $this->inpost_nonce_field;
365
 
366
  // Check that the user is allowed to edit the post
367
- if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
368
- if ( ! isset( $_POST[ $nonce_name ] ) ) return;
369
- if ( ! \wp_verify_nonce( $_POST[ $nonce_name ], $nonce_action ) ) return;
 
 
370
 
371
  $data = (array) $_POST['autodescription'];
372
 
@@ -392,8 +393,10 @@ class Post_Data extends Detect {
392
 
393
  // Check again against ambiguous injection...
394
  // Note, however: function wp_ajax_inline_save() already performs all these checks for us before firing this callback's action.
395
- if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
396
- if ( ! \check_ajax_referer( 'inlineeditnonce', '_inline_edit', false ) ) return;
 
 
397
 
398
  $new_data = [];
399
 
@@ -446,7 +449,7 @@ class Post_Data extends Detect {
446
 
447
  $post = \get_post( $post );
448
 
449
- if ( empty( $post->ID ) ) return;
450
 
451
  // Check again against ambiguous injection...
452
  // Note, however: function bulk_edit_posts() already performs all these checks for us before firing this callback's action.
@@ -510,7 +513,7 @@ class Post_Data extends Detect {
510
 
511
  $post = \get_post( $post );
512
 
513
- if ( empty( $post->ID ) ) return;
514
 
515
  /**
516
  * Don't try to save the data prior autosave, or revision post (is_preview).
@@ -519,8 +522,7 @@ class Post_Data extends Detect {
519
  * @link https://github.com/sybrew/the-seo-framework/issues/48
520
  * @link https://johnblackbourn.com/post-meta-revisions-wordpress
521
  */
522
- if ( \wp_is_post_autosave( $post ) ) return;
523
- if ( \wp_is_post_revision( $post ) ) return;
524
 
525
  // Check that the user is allowed to edit the post. Nonce checks are done in bulk later.
526
  if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
@@ -534,7 +536,7 @@ class Post_Data extends Detect {
534
 
535
  if ( \wp_verify_nonce(
536
  $_POST[ "{$this->inpost_nonce_name}_pt_{$_taxonomy}" ] ?? '', // If empty, wp_verify_nonce will return false.
537
- $this->inpost_nonce_field . '_pt'
538
  ) ) { // Redundant. Fortified.
539
  $this->update_primary_term_id(
540
  $post->ID,
@@ -695,6 +697,7 @@ class Post_Data extends Detect {
695
  * Returns list of post IDs that are excluded from search.
696
  *
697
  * @since 3.0.0
 
698
  *
699
  * @return array The excluded post IDs.
700
  */
@@ -706,6 +709,7 @@ class Post_Data extends Detect {
706
  * Returns list of post IDs that are excluded from archive.
707
  *
708
  * @since 3.0.0
 
709
  *
710
  * @return array The excluded post IDs.
711
  */
@@ -737,6 +741,7 @@ class Post_Data extends Detect {
737
  * 2. The first and second parameters are now required.
738
  * @since 4.1.5.1 1. No longer causes a PHP warning in the unlikely event a post's taxonomy gets deleted.
739
  * 2. This method now converts the post meta to an integer, making the comparison work again.
 
740
  *
741
  * @param int $post_id The post ID.
742
  * @param string $taxonomy The taxonomy name.
@@ -744,8 +749,6 @@ class Post_Data extends Detect {
744
  */
745
  public function get_primary_term( $post_id, $taxonomy ) {
746
 
747
- static $primary_terms = [];
748
-
749
  // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
750
  if ( null !== $memo = memo( null, $post_id, $taxonomy ) ) return $memo;
751
 
@@ -762,7 +765,7 @@ class Post_Data extends Detect {
762
  $primary_term = false;
763
 
764
  // Test for otherwise foreach emits a PHP warning in the unlikely event a post's taxonomy is gone.
765
- if ( ! \is_array( $terms ) ) return $primary_terms[ $post_id ][ $taxonomy ] = false;
766
 
767
  foreach ( $terms as $term ) {
768
  if ( $primary_id === (int) $term->term_id ) {
357
  * @link https://github.com/sybrew/the-seo-framework/issues/48
358
  * @link https://johnblackbourn.com/post-meta-revisions-wordpress
359
  */
360
+ if ( \wp_is_post_autosave( $post ) || \wp_is_post_revision( $post ) ) return;
 
361
 
362
  $nonce_name = $this->inpost_nonce_name;
363
  $nonce_action = $this->inpost_nonce_field;
364
 
365
  // Check that the user is allowed to edit the post
366
+ if (
367
+ ! \current_user_can( 'edit_post', $post->ID )
368
+ || ! isset( $_POST[ $nonce_name ] )
369
+ || ! \wp_verify_nonce( $_POST[ $nonce_name ], $nonce_action )
370
+ ) return;
371
 
372
  $data = (array) $_POST['autodescription'];
373
 
393
 
394
  // Check again against ambiguous injection...
395
  // Note, however: function wp_ajax_inline_save() already performs all these checks for us before firing this callback's action.
396
+ if (
397
+ ! \current_user_can( 'edit_post', $post->ID )
398
+ || ! \check_ajax_referer( 'inlineeditnonce', '_inline_edit', false )
399
+ ) return;
400
 
401
  $new_data = [];
402
 
449
 
450
  $post = \get_post( $post );
451
 
452
+ if ( ! $post ) return;
453
 
454
  // Check again against ambiguous injection...
455
  // Note, however: function bulk_edit_posts() already performs all these checks for us before firing this callback's action.
513
 
514
  $post = \get_post( $post );
515
 
516
+ if ( ! $post ) return;
517
 
518
  /**
519
  * Don't try to save the data prior autosave, or revision post (is_preview).
522
  * @link https://github.com/sybrew/the-seo-framework/issues/48
523
  * @link https://johnblackbourn.com/post-meta-revisions-wordpress
524
  */
525
+ if ( \wp_is_post_autosave( $post ) || \wp_is_post_revision( $post ) ) return;
 
526
 
527
  // Check that the user is allowed to edit the post. Nonce checks are done in bulk later.
528
  if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
536
 
537
  if ( \wp_verify_nonce(
538
  $_POST[ "{$this->inpost_nonce_name}_pt_{$_taxonomy}" ] ?? '', // If empty, wp_verify_nonce will return false.
539
+ "{$this->inpost_nonce_field}_pt"
540
  ) ) { // Redundant. Fortified.
541
  $this->update_primary_term_id(
542
  $post->ID,
697
  * Returns list of post IDs that are excluded from search.
698
  *
699
  * @since 3.0.0
700
+ * @TODO deprecate and require procedural API? This is needless function overhead.
701
  *
702
  * @return array The excluded post IDs.
703
  */
709
  * Returns list of post IDs that are excluded from archive.
710
  *
711
  * @since 3.0.0
712
+ * @TODO deprecate and require procedural API? This is needless function overhead.
713
  *
714
  * @return array The excluded post IDs.
715
  */
741
  * 2. The first and second parameters are now required.
742
  * @since 4.1.5.1 1. No longer causes a PHP warning in the unlikely event a post's taxonomy gets deleted.
743
  * 2. This method now converts the post meta to an integer, making the comparison work again.
744
+ * @since 4.2.7 Now correctly memoizes when no terms for a post can be found.
745
  *
746
  * @param int $post_id The post ID.
747
  * @param string $taxonomy The taxonomy name.
749
  */
750
  public function get_primary_term( $post_id, $taxonomy ) {
751
 
 
 
752
  // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
753
  if ( null !== $memo = memo( null, $post_id, $taxonomy ) ) return $memo;
754
 
765
  $primary_term = false;
766
 
767
  // Test for otherwise foreach emits a PHP warning in the unlikely event a post's taxonomy is gone.
768
+ if ( ! \is_array( $terms ) ) memo( false, $post_id, $taxonomy );
769
 
770
  foreach ( $terms as $term ) {
771
  if ( $primary_id === (int) $term->term_id ) {
inc/classes/query.class.php CHANGED
@@ -534,12 +534,10 @@ class Query extends Core {
534
  ? $post
535
  : ( \get_post( $post )->ID ?? 0 );
536
 
537
- $is_pfp = (int) \get_option( 'page_for_posts' ) === $id;
538
- } else {
539
- $is_pfp = \is_home();
540
  }
541
 
542
- return $is_pfp;
543
  }
544
 
545
  /**
534
  ? $post
535
  : ( \get_post( $post )->ID ?? 0 );
536
 
537
+ return (int) \get_option( 'page_for_posts' ) === $id;
 
 
538
  }
539
 
540
+ return \is_home();
541
  }
542
 
543
  /**
inc/classes/render.class.php CHANGED
@@ -202,13 +202,11 @@ class Render extends Admin_Init {
202
  ]
203
  );
204
  } else {
205
- $el = vsprintf(
206
  '<%s%s />',
207
- [
208
- /** @link <https://www.w3.org/TR/2011/WD-html5-20110525/syntax.html#syntax-tag-name> */
209
- preg_replace( '/[^0-9a-zA-Z]+/', '', $tag ),
210
- $attr,
211
- ]
212
  );
213
  }
214
 
@@ -824,10 +822,8 @@ class Render extends Admin_Init {
824
 
825
  if ( ! $this->output_published_time() ) return '';
826
 
827
- $id = $this->get_the_real_ID();
828
- $post = \get_post( $id );
829
-
830
- $post_date_gmt = $post->post_date_gmt;
831
 
832
  if ( '0000-00-00 00:00:00' === $post_date_gmt )
833
  return '';
@@ -1251,8 +1247,8 @@ class Render extends Admin_Init {
1251
  *
1252
  * @param string $where Determines the position of the indicator.
1253
  * Accepts 'before' for before, anything else for after.
1254
- * @param int $meta_timer Total meta time.
1255
- * @param int $bootstrap_timer Total bootstrap time.
1256
  * @return string The SEO Framework's HTML plugin indicator.
1257
  */
1258
  protected function get_plugin_indicator( $where = 'before', $meta_timer = 0, $bootstrap_timer = 0 ) {
@@ -1268,9 +1264,9 @@ class Render extends Admin_Init {
1268
  * @param bool $show_timer Whether to show the generation time in the indicator.
1269
  */
1270
  'show_timer' => (bool) \apply_filters( 'the_seo_framework_indicator_timing', true ),
1271
- 'annotation' => trim( vsprintf(
1272
  /* translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer */
1273
- \esc_html__( '%1$s %2$s', 'autodescription' ),
1274
  [
1275
  'The SEO Framework',
1276
  /**
@@ -1278,10 +1274,10 @@ class Render extends Admin_Init {
1278
  * @param bool $sybre Whether to show the author name in the indicator.
1279
  */
1280
  \apply_filters( 'sybre_waaijer_<3', true ) // phpcs:ignore, WordPress.NamingConventions.ValidHookName -- Easter egg.
1281
- ? \esc_html__( 'by Sybre Waaijer', 'autodescription' )
1282
  : '',
1283
  ]
1284
- ) ),
1285
  ] );
1286
 
1287
  if ( ! $cache['run'] ) return '';
202
  ]
203
  );
204
  } else {
205
+ $el = sprintf(
206
  '<%s%s />',
207
+ /** @link <https://www.w3.org/TR/2011/WD-html5-20110525/syntax.html#syntax-tag-name> */
208
+ preg_replace( '/[^0-9a-zA-Z]+/', '', $tag ),
209
+ $attr
 
 
210
  );
211
  }
212
 
822
 
823
  if ( ! $this->output_published_time() ) return '';
824
 
825
+ $id = $this->get_the_real_ID();
826
+ $post_date_gmt = \get_post( $id )->post_date_gmt ?? '0000-00-00 00:00:00';
 
 
827
 
828
  if ( '0000-00-00 00:00:00' === $post_date_gmt )
829
  return '';
1247
  *
1248
  * @param string $where Determines the position of the indicator.
1249
  * Accepts 'before' for before, anything else for after.
1250
+ * @param float $meta_timer Total meta time in seconds.
1251
+ * @param float $bootstrap_timer Total bootstrap time in seconds.
1252
  * @return string The SEO Framework's HTML plugin indicator.
1253
  */
1254
  protected function get_plugin_indicator( $where = 'before', $meta_timer = 0, $bootstrap_timer = 0 ) {
1264
  * @param bool $show_timer Whether to show the generation time in the indicator.
1265
  */
1266
  'show_timer' => (bool) \apply_filters( 'the_seo_framework_indicator_timing', true ),
1267
+ 'annotation' => \esc_html( trim( vsprintf(
1268
  /* translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer */
1269
+ \__( '%1$s %2$s', 'autodescription' ),
1270
  [
1271
  'The SEO Framework',
1272
  /**
1274
  * @param bool $sybre Whether to show the author name in the indicator.
1275
  */
1276
  \apply_filters( 'sybre_waaijer_<3', true ) // phpcs:ignore, WordPress.NamingConventions.ValidHookName -- Easter egg.
1277
+ ? \__( 'by Sybre Waaijer', 'autodescription' )
1278
  : '',
1279
  ]
1280
+ ) ) ),
1281
  ] );
1282
 
1283
  if ( ! $cache['run'] ) return '';
inc/classes/sanitize.class.php CHANGED
@@ -228,6 +228,14 @@ class Sanitize extends Admin_Pages {
228
  ]
229
  );
230
 
 
 
 
 
 
 
 
 
231
  $this->add_option_filter(
232
  's_one_zero',
233
  THE_SEO_FRAMEWORK_SITE_OPTIONS,
@@ -678,6 +686,7 @@ class Sanitize extends Admin_Pages {
678
  's_title_raw' => [ $this, 's_title_raw' ],
679
  's_knowledge_type' => [ $this, 's_knowledge_type' ],
680
  's_alter_query_type' => [ $this, 's_alter_query_type' ],
 
681
  's_one_zero' => [ $this, 's_one_zero' ],
682
  's_disabled_post_types' => [ $this, 's_disabled_post_types' ],
683
  's_disabled_taxonomies' => [ $this, 's_disabled_taxonomies' ],
@@ -964,14 +973,15 @@ class Sanitize extends Admin_Pages {
964
  *
965
  * @since 2.8.2
966
  * @since 4.0.5 Now normalized `-` entities.
 
967
  *
968
  * @param string $new_value The Description.
969
  * @return string One line sanitized description.
970
  */
971
  public function s_description_raw( $new_value ) {
972
 
973
- $new_value = $this->s_singleline( $new_value );
974
  $new_value = $this->s_nbsp( $new_value );
 
975
  $new_value = $this->s_tabs( $new_value );
976
  $new_value = $this->s_hyphen( $new_value );
977
  $new_value = $this->s_bsol( $new_value );
@@ -1012,6 +1022,7 @@ class Sanitize extends Admin_Pages {
1012
  * @return string The input string without duplicated spaces.
1013
  */
1014
  public function s_dupe_space( $new_value ) {
 
1015
  return preg_replace( '/\p{Zs}{2,}/u', ' ', $new_value );
1016
  }
1017
 
@@ -1039,6 +1050,12 @@ class Sanitize extends Admin_Pages {
1039
  * 2. Added $escape parameter.
1040
  * @since 3.2.4 Now selectively clears tags.
1041
  * @since 4.1.0 Moved `figcaption`, `figure`, `footer`, and `tfoot`, from `space` to `clear`.
 
 
 
 
 
 
1042
  * @see `$this->strip_tags_cs()`
1043
  *
1044
  * @param string $excerpt The excerpt.
@@ -1048,14 +1065,30 @@ class Sanitize extends Admin_Pages {
1048
  */
1049
  public function s_excerpt( $excerpt = '', $allow_shortcodes = true, $escape = true ) {
1050
 
1051
- // No need to parse an empty excerpt.
1052
  if ( '' === $excerpt ) return '';
1053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1054
  $strip_args = [
1055
- 'space' =>
1056
- [ 'article', 'aside', 'blockquote', 'br', 'dd', 'div', 'dl', 'dt', 'li', 'main', 'ol', 'p', 'section', 'ul' ],
1057
- 'clear' =>
1058
- [ 'address', 'bdo', 'button', 'canvas', 'code', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'iframe', 'input', 'label', 'link', 'meta', 'nav', 'noscript', 'option', 'pre', 'samp', 'script', 'select', 'style', 'svg', 'table', 'textarea', 'tfoot', 'var', 'video' ],
 
1059
  ];
1060
 
1061
  /**
@@ -1132,14 +1165,15 @@ class Sanitize extends Admin_Pages {
1132
  * @since 2.8.2
1133
  * @since 4.0.0 Now normalizes `&` entities.
1134
  * @since 4.0.5 Now normalized `-` entities.
 
1135
  *
1136
  * @param string $new_value The input Title.
1137
  * @return string Sanitized, beautified and trimmed title.
1138
  */
1139
  public function s_title_raw( $new_value ) {
1140
 
1141
- $new_value = $this->s_singleline( $new_value );
1142
  $new_value = $this->s_nbsp( $new_value );
 
1143
  $new_value = $this->s_tabs( $new_value );
1144
  $new_value = $this->s_hyphen( $new_value );
1145
  $new_value = $this->s_bsol( $new_value );
@@ -1232,6 +1266,22 @@ class Sanitize extends Admin_Pages {
1232
  return 'in_query';
1233
  }
1234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1235
  /**
1236
  * Returns a 1 or 0, for all truthy / falsy values.
1237
  *
@@ -1886,6 +1936,7 @@ class Sanitize extends Admin_Pages {
1886
  * @return string $content Without the paragraphs containing simple URLs.
1887
  */
1888
  public function strip_paragraph_urls( $content ) {
 
1889
  return preg_replace( '/(<p(?: [^>]*)?>\s*)(https?:\/\/[^\s<>"]+)(\s*<\/p>)/i', '', $content );
1890
  }
1891
 
@@ -1895,7 +1946,7 @@ class Sanitize extends Admin_Pages {
1895
  * It essentially strips all tags, and replaces block-type tags' endings with spaces.
1896
  * When done, it performs a sanity-cleanup via `strip_tags()`.
1897
  *
1898
- * Tip: You might want to use method `s_dupe_space()` to clear up the duplicated spaces afterward.
1899
  *
1900
  * @since 3.2.4
1901
  * @since 4.0.0 Now allows emptying the indexes `space` and `clear`.
@@ -1905,71 +1956,174 @@ class Sanitize extends Admin_Pages {
1905
  * 4. Now performs a separate query for void elements; to prevent regex recursion.
1906
  * @since 4.1.0 Now detects nested elements and preserves that content correctly--as if we'd pass through scrupulously beyond infinity.
1907
  * @since 4.1.1 Can now replace void elements with spaces when so inclined via the arguments (space vs clear).
1908
- * @link https://www.w3schools.com/html/html_blocks.asp
 
 
 
 
 
 
 
 
 
 
 
 
 
1909
  * @link https://html.spec.whatwg.org/multipage/syntax.html#void-elements
1910
  *
1911
  * @param string $input The input text that needs its tags stripped.
1912
- * @param array $args The input arguments: {
1913
- * 'space' : @param array|null HTML elements that should have a space added around it.
1914
- * If not set or null, skip check.
1915
- * If empty array, skips stripping; otherwise, use input.
1916
- * 'clear' : @param array|null HTML elements that should be emptied and replaced with a space.
1917
- * If not set or null, skip check.
1918
- * If empty array, skips stripping; otherwise, use input.
1919
- * 'strip' : @param bool If set, strip_tags() is performed before returning the output.
1920
- * Recommended always true, since Regex doesn't understand XML.
 
 
 
1921
  * }
1922
  * NOTE: WARNING The array values are forwarded to a regex without sanitization/quoting.
1923
  * NOTE: Unlisted, script, and style tags will be stripped via PHP's `strip_tags()`. (togglable via `$args['strip']`)
1924
  * Also note that their contents are maintained as-is, without added spaces.
1925
- * It is why you should always list `style` and `script` in the `clear` array.
1926
- * @return string The output string without tags.
 
1927
  */
1928
  public function strip_tags_cs( $input, $args = [] ) {
1929
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1930
  $default_args = [
1931
- 'space' =>
1932
- [ 'address', 'article', 'aside', 'blockquote', 'br', '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' ],
1933
- 'clear' =>
1934
- [ 'bdo', 'button', 'canvas', 'code', 'hr', 'iframe', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
1935
- 'strip' => true,
 
1936
  ];
1937
 
1938
- $void = [ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' ];
1939
-
1940
  if ( ! $args ) {
1941
  $args = $default_args;
1942
  } else {
1943
- foreach ( [ 'space', 'clear' ] as $type ) {
1944
- if ( isset( $args[ $type ] ) )
1945
- $args[ $type ] = $args[ $type ] ? (array) $args[ $type ] : [];
1946
- }
1947
- $args['strip'] = $args['strip'] ?? $default_args['strip'];
1948
- }
1949
 
1950
- // Clear first, so there's less to process; then add spaces.
1951
- foreach ( [ 'clear', 'space' ] as $type ) {
1952
- if ( empty( $args[ $type ] ) ) continue;
1953
 
1954
- // void = element without content.
1955
- $void_query = array_intersect( $args[ $type ], $void );
1956
- // fill = <normal | template | raw text | escapable text | foreign> element.
1957
- $fill_query = array_diff( $args[ $type ], $void );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1958
 
1959
- if ( $void_query ) {
1960
- $_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $void_query ) );
1961
- $_replace = 'space' === $type ? ' ' : '';
1962
- $input = preg_replace( "/$_regex/si", $_replace, $input );
1963
- }
1964
- if ( $fill_query ) {
1965
- $_regex = sprintf( '<(%s)\b[^>]*>([^<]*)(<\/\1>)?|(<\/?(?1)>)', implode( '|', $fill_query ) );
1966
- $_replace = 'space' === $type ? ' $2 ' : ' ';
1967
- $input = preg_replace( "/$_regex/si", $_replace, $input );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1968
  }
1969
  }
1970
 
1971
  // phpcs:ignore, WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- $args defines stripping of 'script' and 'style'.
1972
- return $args['strip'] ? strip_tags( $input ) : $input;
1973
  }
1974
 
1975
  /**
@@ -1995,6 +2149,7 @@ class Sanitize extends Admin_Pages {
1995
  */
1996
  public function s_image_details( $details ) {
1997
 
 
1998
  if ( array_values( $details ) === $details )
1999
  return $this->s_image_details_deep( $details );
2000
 
@@ -2039,6 +2194,7 @@ class Sanitize extends Admin_Pages {
2039
  if ( ! $width || ! $height )
2040
  $width = $height = 0;
2041
 
 
2042
  if ( $id && ( $width > 4096 || $height > 4096 || $filesize > 5 * MB_IN_BYTES ) ) {
2043
  $new_image = $this->get_largest_acceptable_image_src( $id, 4096, 5 * MB_IN_BYTES );
2044
  $url = $new_image ? $this->s_url_relative_to_current_scheme( $new_image[0] ) : '';
228
  ]
229
  );
230
 
231
+ $this->add_option_filter(
232
+ 's_description_html_method',
233
+ THE_SEO_FRAMEWORK_SITE_OPTIONS,
234
+ [
235
+ 'auto_descripton_html_method',
236
+ ]
237
+ );
238
+
239
  $this->add_option_filter(
240
  's_one_zero',
241
  THE_SEO_FRAMEWORK_SITE_OPTIONS,
686
  's_title_raw' => [ $this, 's_title_raw' ],
687
  's_knowledge_type' => [ $this, 's_knowledge_type' ],
688
  's_alter_query_type' => [ $this, 's_alter_query_type' ],
689
+ 's_description_html_method' => [ $this, 's_description_html_method' ],
690
  's_one_zero' => [ $this, 's_one_zero' ],
691
  's_disabled_post_types' => [ $this, 's_disabled_post_types' ],
692
  's_disabled_taxonomies' => [ $this, 's_disabled_taxonomies' ],
973
  *
974
  * @since 2.8.2
975
  * @since 4.0.5 Now normalized `-` entities.
976
+ * @since 4.2.7 Now converts nbsp before singleline, because singleline must also trim old nbsp.
977
  *
978
  * @param string $new_value The Description.
979
  * @return string One line sanitized description.
980
  */
981
  public function s_description_raw( $new_value ) {
982
 
 
983
  $new_value = $this->s_nbsp( $new_value );
984
+ $new_value = $this->s_singleline( $new_value );
985
  $new_value = $this->s_tabs( $new_value );
986
  $new_value = $this->s_hyphen( $new_value );
987
  $new_value = $this->s_bsol( $new_value );
1022
  * @return string The input string without duplicated spaces.
1023
  */
1024
  public function s_dupe_space( $new_value ) {
1025
+ // TODO consider returning the original unicode space? Test if necessary.
1026
  return preg_replace( '/\p{Zs}{2,}/u', ' ', $new_value );
1027
  }
1028
 
1050
  * 2. Added $escape parameter.
1051
  * @since 3.2.4 Now selectively clears tags.
1052
  * @since 4.1.0 Moved `figcaption`, `figure`, `footer`, and `tfoot`, from `space` to `clear`.
1053
+ * @since 4.2.7 1. No longer clears `figcaption`, `hr`, `link`, `meta`, `option`, or `tfoot`.
1054
+ * 2. Now clears `area`, `audio`, `datalist`, `del`, `dialog`, `dl`, `hgroup`, `menu`, `meter`, `ol`,
1055
+ * `object`, `output`, `progress`, `s`, `template`, and `ul`.
1056
+ * 3. Now adds spaces around `blockquote`, `details`, and `hr`.
1057
+ * 4. Now ignores `dd`, `dl`, `dt`, `li`, `main`, for they are inherently excluded or ignored anyway.
1058
+ * 5. Now processed the `auto_descripton_html_method` option for stripping tags.
1059
  * @see `$this->strip_tags_cs()`
1060
  *
1061
  * @param string $excerpt The excerpt.
1065
  */
1066
  public function s_excerpt( $excerpt = '', $allow_shortcodes = true, $escape = true ) {
1067
 
1068
+ // No need to parse an empty excerpt. TODO consider not parsing '0' as well?
1069
  if ( '' === $excerpt ) return '';
1070
 
1071
+ // Oh, how I'd like PHP 8's match()...
1072
+ switch ( $this->get_option( 'auto_descripton_html_method' ) ) {
1073
+ case 'thorough':
1074
+ $passes = 12;
1075
+ break;
1076
+ case 'accurate':
1077
+ $passes = 6;
1078
+ break;
1079
+ default:
1080
+ case 'fast':
1081
+ $passes = 2;
1082
+ break;
1083
+ }
1084
+
1085
+ // Missing 'dd', 'dt', and 'li' -- these are obligatory subelements of what's already cleared.
1086
  $strip_args = [
1087
+ 'space' =>
1088
+ [ 'article', 'br', 'blockquote', 'details', 'div', 'hr', 'p', 'section' ],
1089
+ 'clear' =>
1090
+ [ 'address', 'area', 'aside', 'audio', 'blockquote', 'button', 'canvas', 'code', 'datalist', 'del', 'dialog', 'dl', 'fieldset', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'iframe', 'input', 'label', 'map', 'menu', 'meter', 'nav', 'noscript', 'ol', 'object', 'output', 'pre', 'progress', 's', 'script', 'select', 'style', 'svg', 'table', 'template', 'textarea', 'ul', 'video' ],
1091
+ 'passes' => $passes,
1092
  ];
1093
 
1094
  /**
1165
  * @since 2.8.2
1166
  * @since 4.0.0 Now normalizes `&` entities.
1167
  * @since 4.0.5 Now normalized `-` entities.
1168
+ * @since 4.2.7 Now converts nbsp before singleline, because singleline must also trim old nbsp.
1169
  *
1170
  * @param string $new_value The input Title.
1171
  * @return string Sanitized, beautified and trimmed title.
1172
  */
1173
  public function s_title_raw( $new_value ) {
1174
 
 
1175
  $new_value = $this->s_nbsp( $new_value );
1176
+ $new_value = $this->s_singleline( $new_value );
1177
  $new_value = $this->s_tabs( $new_value );
1178
  $new_value = $this->s_hyphen( $new_value );
1179
  $new_value = $this->s_bsol( $new_value );
1266
  return 'in_query';
1267
  }
1268
 
1269
+ /**
1270
+ * Sanitizes the html method value.
1271
+ *
1272
+ * @since 4.2.7
1273
+ *
1274
+ * @param mixed $new_value Should ideally be a string 'fast', 'accurate', or 'thorough' passed in.
1275
+ * @return string 'fast', 'accurate', or 'thorough'.
1276
+ */
1277
+ public function s_description_html_method( $new_value ) {
1278
+
1279
+ if ( \in_array( $new_value, [ 'fast', 'accurate', 'thorough' ], true ) )
1280
+ return $new_value;
1281
+
1282
+ return 'fast';
1283
+ }
1284
+
1285
  /**
1286
  * Returns a 1 or 0, for all truthy / falsy values.
1287
  *
1936
  * @return string $content Without the paragraphs containing simple URLs.
1937
  */
1938
  public function strip_paragraph_urls( $content ) {
1939
+ // TODO maybe later, this would be faster: '/<p\b[^>]*>\s*https?:\/\/[^\s<>"]+\s*<\/p>/i'
1940
  return preg_replace( '/(<p(?: [^>]*)?>\s*)(https?:\/\/[^\s<>"]+)(\s*<\/p>)/i', '', $content );
1941
  }
1942
 
1946
  * It essentially strips all tags, and replaces block-type tags' endings with spaces.
1947
  * When done, it performs a sanity-cleanup via `strip_tags()`.
1948
  *
1949
+ * Tip: You might want to use method `s_dupe_space()` to clear up the duplicated/repeated spaces afterward.
1950
  *
1951
  * @since 3.2.4
1952
  * @since 4.0.0 Now allows emptying the indexes `space` and `clear`.
1956
  * 4. Now performs a separate query for void elements; to prevent regex recursion.
1957
  * @since 4.1.0 Now detects nested elements and preserves that content correctly--as if we'd pass through scrupulously beyond infinity.
1958
  * @since 4.1.1 Can now replace void elements with spaces when so inclined via the arguments (space vs clear).
1959
+ * @since 4.2.7 1. Revamped the HTML lookup: it now (more) accurately processes HTML, and is less likely to be fooled by HTML tags
1960
+ * in attributes.
1961
+ * 2. The 'space' index no longer has default `fieldset`, `figcaption`, `form`, `main`, `nav`, `pre`, `table`, and `tfoot`.
1962
+ * 3. The space index now has added to default `details`, `hgroup`, and `hr`.
1963
+ * 4. The 'clear' index no longer has default `bdo`, `hr`, `link`, `meta`, `option`, `samp`, `style`, and `var`.
1964
+ * 5. The 'clear' index now has added to default `area`, `audio`, `datalist`, `del`, `dialog`, `fieldset`, `form`, `map`,
1965
+ * `menu`, `meter`, `nav`, `object`, `output`, `pre`, `progress`, `s`, `table`, and `template`.
1966
+ * 6. Added the 'passes' index to `$args`. This tells the maximum passes 'space' may process.
1967
+ * Read TSF option `auto_descripton_html_method` to use the user-defined method.
1968
+ * 7. Now replaces all elements passed with spaces. For void elements, or phrasing elements, you'd want to omit
1969
+ * those from '$args' so it falls through to `strip_tags()`.
1970
+ * 8. Added preparation memoization using cache delimiters `$args['space']` and `$args['clear']`.
1971
+ *
1972
+ * @link https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories
1973
  * @link https://html.spec.whatwg.org/multipage/syntax.html#void-elements
1974
  *
1975
  * @param string $input The input text that needs its tags stripped.
1976
+ * @param array $args The input arguments. Tags not included are ignored. {
1977
+ * 'space' : @param ?string[] HTML elements that should be processed for spacing. If the space
1978
+ * element is of void element type, it'll be treated as 'clear'.
1979
+ * If not set or null, skip check.
1980
+ * If empty array, skips stripping; otherwise, use input.
1981
+ * 'clear' : @param ?string[] HTML elements that should be emptied and replaced with a space.
1982
+ * If not set or null, skip check.
1983
+ * If empty array, skips stripping; otherwise, use input.
1984
+ * 'strip' : @param bool If set, strip_tags() is performed before returning the output.
1985
+ * Recommended always true, since Regex doesn't understand XML.
1986
+ * 'passes' : @param int The maximum number of passes 'space' may conduct. More is slower,
1987
+ * but more accurate.
1988
  * }
1989
  * NOTE: WARNING The array values are forwarded to a regex without sanitization/quoting.
1990
  * NOTE: Unlisted, script, and style tags will be stripped via PHP's `strip_tags()`. (togglable via `$args['strip']`)
1991
  * Also note that their contents are maintained as-is, without added spaces.
1992
+ * It is why you should always list `style` and `script` in the `clear` array, never in 'space'.
1993
+ * @return string The output string without tags. May have many stray and repeated spaces.
1994
+ * Not secure for display! Don't trust this method. Always use esc_* functionality.
1995
  */
1996
  public function strip_tags_cs( $input, $args = [] ) {
1997
 
1998
+ if ( false === strpos( $input, '<' ) ) return $input;
1999
+
2000
+ /**
2001
+ * Find the optimized version in `s_excerpt()`. The defaults here treats HTML for a18y reading, not description generation.
2002
+ *
2003
+ * Contains HTML5 supported flow content elements only, even though browsers might behave differently.
2004
+ * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#flow_content
2005
+ *
2006
+ * Missing phrasing elements: 'a', 'abbr', 'b', 'bdo', 'bdi', 'cite', 'data', 'dfn', 'em', 'embed', 'i', 'img', 'ins', 'kbd',
2007
+ * 'mark', 'math', 'picture', 'q', 'ruby', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', and 'wbr'.
2008
+ * There's no need to add these, for they're cleared plainly by `strip_tags()`.
2009
+ *
2010
+ * Missing flow elements: 'link', 'meta'
2011
+ * There's no need to add these, for they are void content.
2012
+ *
2013
+ * Contains all form elements. Those must be stripped in almost any context.
2014
+ */
2015
  $default_args = [
2016
+ 'space' =>
2017
+ [ 'address', 'article', 'aside', 'br', 'blockquote', 'details', 'dd', 'div', 'dl', 'dt', 'figure', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'li', 'ol', 'p', 'section', 'ul' ],
2018
+ 'clear' =>
2019
+ [ 'area', 'audio', 'button', 'canvas', 'code', 'datalist', 'del', 'dialog', 'fieldset', 'form', 'iframe', 'input', 'label', 'map', 'menu', 'meter', 'nav', 'noscript', 'object', 'output', 'pre', 'progress', 's', 'script', 'select', 'style', 'svg', 'table', 'template', 'textarea', 'video' ],
2020
+ 'strip' => true,
2021
+ 'passes' => 1,
2022
  ];
2023
 
 
 
2024
  if ( ! $args ) {
2025
  $args = $default_args;
2026
  } else {
2027
+ // We don't use array_merge() here because we want to default these to [] when $args is given.
2028
+ foreach ( [ 'clear', 'space' ] as $type )
2029
+ $args[ $type ] = (array) ( $args[ $type ] ?? [] );
 
 
 
2030
 
2031
+ $args['strip'] = $args['strip'] ?? $default_args['strip'];
2032
+ $args['passes'] = $args['passes'] ?? $default_args['passes'];
2033
+ }
2034
 
2035
+ $parse = umemo( __METHOD__ . '/parse', null, $args['space'], $args['clear'] );
2036
+ // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
2037
+ if ( ! $parse ) {
2038
+ // Void elements never have content. 'param', 'source', 'track',
2039
+ $void = [ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'wbr' ];
2040
+ // Phrase elements should be replaced without spacing. There are more phrasing (54) than block elements (39)...
2041
+ // Blocks: address, area, article, aside, audio, blockquote, br, button, canvas, dd, details, dialog, div, dl, dt, fieldset, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, li, ol, pre, table, td, template, textarea, th, tr, ul, video
2042
+ // 'br' is a phrase element, but also a struct whitespace -- let's omit it so we can substitute it with a space as block.
2043
+ $phrase = [ 'a', 'area', 'abbr', 'audio', 'b', 'bdo', 'bdi', 'button', 'canvas', 'cite', 'code', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'link', 'kbd', 'label', 'map', 'mark', 'meta', 'math', 'meter', 'noscript', 'object', 'output', 'picture', 'progress', 'q', 'ruby', 's', 'samp', 'script', 'select', 'small', 'span', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'u', 'var', 'video', 'wbr' ];
2044
+
2045
+ $marked_for_parsing = array_merge( $args['space'], $args['clear'] );
2046
+
2047
+ $void_elements = array_intersect( $marked_for_parsing, $void );
2048
+ $flow_elements = array_diff( $marked_for_parsing, $void );
2049
+
2050
+ $clear_elements = array_intersect( $flow_elements, $args['clear'] );
2051
+
2052
+ $parse = umemo(
2053
+ __METHOD__ . '/parse',
2054
+ [
2055
+ // void = element without content.
2056
+ 'void_query' => [
2057
+ 'phrase' => array_intersect( $void_elements, $phrase ),
2058
+ 'block' => array_diff( $void_elements, $phrase ),
2059
+ ],
2060
+ // fill = <normal | template | raw text | escapable text | foreign> element.
2061
+ 'clear_query' => [
2062
+ 'phrase' => array_intersect( $clear_elements, $phrase ),
2063
+ 'block' => array_diff( $clear_elements, $phrase ),
2064
+ ],
2065
+ 'space_query' => [
2066
+ 'phrase' => array_intersect( $flow_elements, $args['space'] ),
2067
+ ],
2068
+ ],
2069
+ $args['space'],
2070
+ $args['clear']
2071
+ );
2072
+ }
2073
 
2074
+ foreach ( $parse as $query_type => $handles ) {
2075
+ foreach ( $handles as $flow_type => $elements ) {
2076
+ if ( false === strpos( $input, '<' ) || ! $elements ) break 2;
2077
+
2078
+ switch ( $query_type ) {
2079
+ case 'void_query':
2080
+ $input = preg_replace(
2081
+ /**
2082
+ * This one grabs opening tags only, and no content.
2083
+ * Basically, the content and closing tag reader is split from clear_query/flow_query's regex.
2084
+ */
2085
+ sprintf(
2086
+ '/<(?:%s)\b(?:[^=>\/]+|(?>[^=>\/]*(?:=([\'"])[^\'"]+\g{-1})|[^>]+?)+)*?\/?>/i',
2087
+ implode( '|', $elements )
2088
+ ),
2089
+ 'phrase' === $flow_type ? '' : ' ', // Add space if block, otherwise clear.
2090
+ $input
2091
+ ) ?? '';
2092
+ break;
2093
+
2094
+ case 'space_query':
2095
+ $passes = $args['passes'];
2096
+ $replacement = ' $3 ';
2097
+ // Fall through;
2098
+ case 'clear_query':
2099
+ $passes = $passes ?? 1;
2100
+ $replacement = $replacement ?? ( 'phrase' === $flow_type ? '' : ' ' );
2101
+
2102
+ $i = 0;
2103
+ // To be most accurate, we should parse 'space' $type at least twice, up to 6 times. This is a performance hog.
2104
+ // This is because we process the tags from the outer layer to the most inner. Each pass goes deeper.
2105
+ while ( $i++ < $passes ) {
2106
+ $pre_pass_input = $input;
2107
+ // Akin to https://regex101.com/r/ml2iBW/16. (This might be outdated, copy work!)
2108
+ $input = preg_replace(
2109
+ sprintf(
2110
+ '/<(%s)\b(?:[^=>\/]+|(?>[^=>\/]*(?:=([\'"])[^\'"]+\g{-1})|[^>]+?)+)*?(?:\/>(*ACCEPT))?>((?:[^<]*+(?:<(?!\/?\1)[^<]+)*|(?R)|$(*ACCEPT))+?)<\/\1[^>]*>/i',
2111
+ implode( '|', $elements )
2112
+ ),
2113
+ $replacement,
2114
+ $input
2115
+ ) ?? '';
2116
+ // If nothing changed, or no more HTML is present, we're done.
2117
+ if ( $pre_pass_input === $input || false === strpos( $input, '<' ) ) break;
2118
+ }
2119
+ unset( $passes, $replacement );
2120
+ break;
2121
+ }
2122
  }
2123
  }
2124
 
2125
  // phpcs:ignore, WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- $args defines stripping of 'script' and 'style'.
2126
+ return $args['strip'] ? \strip_tags( $input ) : $input;
2127
  }
2128
 
2129
  /**
2149
  */
2150
  public function s_image_details( $details ) {
2151
 
2152
+ // This is 350x faster than a polyfill for `array_is_list()`.
2153
  if ( array_values( $details ) === $details )
2154
  return $this->s_image_details_deep( $details );
2155
 
2194
  if ( ! $width || ! $height )
2195
  $width = $height = 0;
2196
 
2197
+ // TODO add filter for 5 * MB_IN_BYTES; Facebook allows 8MB; Twitter 5MB (Q4 2022).
2198
  if ( $id && ( $width > 4096 || $height > 4096 || $filesize > 5 * MB_IN_BYTES ) ) {
2199
  $new_image = $this->get_largest_acceptable_image_src( $id, 4096, 5 * MB_IN_BYTES );
2200
  $url = $new_image ? $this->s_url_relative_to_current_scheme( $new_image[0] ) : '';
inc/classes/site-options.class.php CHANGED
@@ -51,6 +51,7 @@ class Site_Options extends Sanitize {
51
  * @since 3.1.0 Now applies filters 'the_seo_framework_default_site_options'
52
  * @since 4.0.0 `home_title_location` is now switched from right to left, or vice-versa.
53
  * @since 4.2.4 `max_image_preview` now defaults to `large`, from `standard`, matching WordPress's default.
 
54
  *
55
  * @return array Default site options.
56
  */
@@ -108,7 +109,8 @@ class Site_Options extends Sanitize {
108
  'title_strip_tags' => 1, // Apply 'strip tags' on titles.
109
 
110
  // Description.
111
- 'auto_description' => 1, // Enables auto description.
 
112
 
113
  // Robots index.
114
  'author_noindex' => 0, // Author Archive robots noindex
51
  * @since 3.1.0 Now applies filters 'the_seo_framework_default_site_options'
52
  * @since 4.0.0 `home_title_location` is now switched from right to left, or vice-versa.
53
  * @since 4.2.4 `max_image_preview` now defaults to `large`, from `standard`, matching WordPress's default.
54
+ * @since 4.2.7 Added `auto_descripton_html_method`, defaults to `fast`.
55
  *
56
  * @return array Default site options.
57
  */
109
  'title_strip_tags' => 1, // Apply 'strip tags' on titles.
110
 
111
  // Description.
112
+ 'auto_description' => 1, // Enables auto description.
113
+ 'auto_descripton_html_method' => 'fast', // Auto description HTML passes.
114
 
115
  // Robots index.
116
  'author_noindex' => 0, // Author Archive robots noindex
inc/classes/term-data.class.php CHANGED
@@ -247,14 +247,14 @@ class Term_Data extends Post_Data {
247
 
248
  $term = \get_term( $term_id, $taxonomy );
249
 
250
- // We could test for is_wp_error( $term ), but this is more to the point.
251
- if ( empty( $term->term_id ) ) return;
252
-
253
  // Check again against ambiguous injection...
254
  // Note, however: function wp_update_term() already performs all these checks for us before firing this callback's action.
255
- if ( ! \current_user_can( 'edit_term', $term->term_id ) ) return;
256
- if ( ! isset( $_POST['_wpnonce'] ) ) return;
257
- if ( ! \wp_verify_nonce( $_POST['_wpnonce'], "update-tag_{$term->term_id}" ) ) return;
 
 
 
258
 
259
  $data = (array) $_POST['autodescription-meta'];
260
 
@@ -278,13 +278,13 @@ class Term_Data extends Post_Data {
278
 
279
  $term = \get_term( $term_id, $taxonomy );
280
 
281
- // We could test for is_wp_error( $term ), but this is more to the point.
282
- if ( empty( $term->term_id ) ) return;
283
-
284
  // Check again against ambiguous injection...
285
  // Note, however: function wp_ajax_inline_save_tax() already performs all these checks for us before firing this callback's action.
286
- if ( ! \current_user_can( 'edit_term', $term->term_id ) ) return;
287
- if ( ! \check_ajax_referer( 'taxinlineeditnonce', '_inline_edit', false ) ) return;
 
 
 
288
 
289
  // Unlike the term-edit saving, we don't reset the data, just overwrite what's given.
290
  // This is because we only update a portion of the meta.
247
 
248
  $term = \get_term( $term_id, $taxonomy );
249
 
 
 
 
250
  // Check again against ambiguous injection...
251
  // Note, however: function wp_update_term() already performs all these checks for us before firing this callback's action.
252
+ if (
253
+ empty( $term->term_id ) // We could test for is_wp_error( $term ), but this is more to the point.
254
+ || ! \current_user_can( 'edit_term', $term->term_id )
255
+ || ! isset( $_POST['_wpnonce'] )
256
+ || ! \wp_verify_nonce( $_POST['_wpnonce'], "update-tag_{$term->term_id}" )
257
+ ) return;
258
 
259
  $data = (array) $_POST['autodescription-meta'];
260
 
278
 
279
  $term = \get_term( $term_id, $taxonomy );
280
 
 
 
 
281
  // Check again against ambiguous injection...
282
  // Note, however: function wp_ajax_inline_save_tax() already performs all these checks for us before firing this callback's action.
283
+ if (
284
+ empty( $term->term_id ) // We could test for is_wp_error( $term ), but this is more to the point.
285
+ || ! \current_user_can( 'edit_term', $term->term_id )
286
+ || ! \check_ajax_referer( 'taxinlineeditnonce', '_inline_edit', false )
287
+ ) return;
288
 
289
  // Unlike the term-edit saving, we don't reset the data, just overwrite what's given.
290
  // This is because we only update a portion of the meta.
inc/classes/user-data.class.php CHANGED
@@ -76,12 +76,13 @@ class User_Data extends Term_Data {
76
  * Memoizes the return value for the current request.
77
  *
78
  * @since 4.1.4
79
- * @TODO Throw this away? We do not use it... never have.
 
80
  *
81
  * @return array The current author meta.
82
  */
83
  public function get_current_post_author_meta() {
84
- return memo() ?? memo( $this->get_user_meta( $this->get_current_post_author_id() ) );
85
  }
86
 
87
  /**
@@ -93,7 +94,7 @@ class User_Data extends Term_Data {
93
  * @since 4.1.4 1. Now returns default values when custom values are missing.
94
  * 2. Now listens to headlessness.
95
  * 3. Deprecated the third argument, and moved it to the second.
96
- * @todo Send deprecation warning for 3rd parameter
97
  *
98
  * @param int $user_id The user ID.
99
  * @param bool $use_cache Whether to store and use options from cache, or bypass it.
76
  * Memoizes the return value for the current request.
77
  *
78
  * @since 4.1.4
79
+ * @since 4.2.7 Removed redundant memoization.
80
+ * @ignore Unused locally. Public API.
81
  *
82
  * @return array The current author meta.
83
  */
84
  public function get_current_post_author_meta() {
85
+ return $this->get_user_meta( $this->get_current_post_author_id() );
86
  }
87
 
88
  /**
94
  * @since 4.1.4 1. Now returns default values when custom values are missing.
95
  * 2. Now listens to headlessness.
96
  * 3. Deprecated the third argument, and moved it to the second.
97
+ * @todo deprecate: Send deprecation warning for 3rd parameter -> Does anybody actually use this??
98
  *
99
  * @param int $user_id The user ID.
100
  * @param bool $use_cache Whether to store and use options from cache, or bypass it.
inc/compat/theme-genesis.php CHANGED
@@ -43,6 +43,7 @@ function _disable_genesis_seo( $plugins ) {
43
  *
44
  * @since 2.8.0
45
  * @since 3.1.0 Now filters empty fields.
 
46
  *
47
  * @param array $data The current term meta.
48
  * @param int $term_id The current term ID.
43
  *
44
  * @since 2.8.0
45
  * @since 3.1.0 Now filters empty fields.
46
+ * @TODO remove or shift this, so that we can reduce what's stored in the database via s_term_meta?
47
  *
48
  * @param array $data The current term meta.
49
  * @param int $term_id The current term ID.
inc/functions/upgrade-suggestion.php CHANGED
@@ -40,11 +40,6 @@ namespace The_SEO_Framework\Suggestion;
40
  _prepare( $previous_version, $current_version );
41
  /**
42
  * Prepares a suggestion notification to ALL applicable plugin users on upgrade;
43
- * For TSFEM, it's shown when:
44
- * 0. The upgrade actually happened.
45
- * 1. The constant 'TSF_DISABLE_SUGGESTIONS' is not defined or false.
46
- * 2. The current dashboard is the main site's.
47
- * 3. TSFEM isn't already installed.
48
  *
49
  * The notice is automatically dismissed after X views, and it can be ignored without reappearing.
50
  *
@@ -57,6 +52,7 @@ _prepare( $previous_version, $current_version );
57
  * @since 4.1.2 Can now communicate with Extension Manager for the edge-case sale.
58
  * @since 4.1.3 Commented out sale notification conditions, as those can't be met anyway.
59
  * @since 4.2.1 No longer tests WP and PHP requirements for Extension Manager.
 
60
  * @access private
61
  *
62
  * @param string $previous_version The previous version the site upgraded from, if any.
@@ -72,79 +68,14 @@ function _prepare( $previous_version, $current_version ) {
72
  // 2
73
  if ( ! \is_main_site() ) return;
74
 
75
- // phpcs:disable -- There is no sale, leftover code.
76
- // $show_sale = true;
77
- // if ( \function_exists( '\\tsf_extension_manager' ) && method_exists( \tsf_extension_manager(), 'is_connected_user' ) ) {
78
- // $show_sale = ! \tsf_extension_manager()->is_connected_user();
79
- // }
80
- // if ( $show_sale ) {
81
- // // phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
82
- // _suggest_temp_sale( $previous_version, $current_version );
83
- // }
84
- // phpcs:enable
85
-
86
- // 3a
87
- if ( \defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) return;
88
-
89
- if ( ! \function_exists( '\\get_plugins' ) )
90
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
91
-
92
- // 3b
93
- if ( ! empty( \get_plugins()['the-seo-framework-extension-manager/the-seo-framework-extension-manager.php'] ) ) return;
94
-
95
- // phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
96
- _suggest_extension_manager( $previous_version, $current_version );
97
- }
98
-
99
- /**
100
- * Registers "look at TSFEM" notification to applicable plugin users on upgrade.
101
- *
102
- * @since 3.0.6
103
- * @since 4.1.0 Is now a persistent notice, that outputs at most 3 times, on some admin pages, only for users that can install plugins.
104
- * @access private
105
- *
106
- * @param string $previous_version The previous version the site upgraded from, if any.
107
- * @param string $current_version The current version of the site.
108
- */
109
- function _suggest_extension_manager( $previous_version, $current_version ) {
110
-
111
- $tsf = \tsf();
112
-
113
- $suggest_key = 'suggest-extension-manager';
114
- $suggest_args = [
115
- 'type' => 'info',
116
- 'icon' => false,
117
- 'escape' => false,
118
- ];
119
- $suggest_conditions = [
120
- 'screens' => [],
121
- 'excl_screens' => [ 'update-core', 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes', 'widgets', 'user', 'nav-menus', 'theme-editor', 'profile', 'export', 'site-health', 'export-personal-data', 'erase-personal-data' ],
122
- 'capability' => 'install_plugins',
123
- 'user' => 0,
124
- 'count' => 3,
125
- 'timeout' => DAY_IN_SECONDS * 7,
126
- ];
127
-
128
- if ( $previous_version < '4100' && $current_version < '4200' )
129
- $tsf->register_dismissible_persistent_notice(
130
- $tsf->convert_markdown(
131
- vsprintf(
132
- '<p>The SEO Framework was updated to v4.1! It brings 9 new features and [over 350 QOL improvements for performance and accessibility](%s).</p>
133
- <p>Did you know we have [10 premium extensions](%s), adding features beyond SEO? Our anti-spam extension runs locally, has a 99.98%% catch rate, and adds only 0.13KB to your website.</p>
134
- <p>We want to make TSF even better for you &mdash; please consider [filling out our survey](%s), it has 5 questions and should take you about 2 minutes. Thank you.</p>',
135
- [
136
- 'https://theseoframework.com/?p=3598',
137
- 'https://theseoframework.com/?p=3599',
138
- 'https://theseoframework.com/?p=3591',
139
- ]
140
- ),
141
- [ 'a', 'em', 'strong' ],
142
- [ 'a_internal' => false ]
143
- ),
144
- $suggest_key,
145
- $suggest_args,
146
- $suggest_conditions
147
- );
148
  }
149
 
150
  /**
@@ -162,35 +93,32 @@ function _suggest_extension_manager( $previous_version, $current_version ) {
162
  */
163
  function _suggest_temp_sale( $previous_version, $current_version ) {
164
 
165
- $tsf = \tsf();
166
-
167
- $suggest_key = 'suggest-sale';
168
- $suggest_args = [
169
- 'type' => 'info',
170
- 'icon' => false,
171
- 'escape' => false,
172
- ];
173
- $suggest_conditions = [
174
- 'screens' => [],
175
- 'excl_screens' => [ 'update-core', 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes', 'widgets', 'user', 'nav-menus', 'theme-editor', 'profile', 'export', 'site-health', 'export-personal-data', 'erase-personal-data' ],
176
- 'capability' => 'install_plugins',
177
- 'user' => 0,
178
- 'count' => 3,
179
- 'timeout' => strtotime( 'December 6th, 2021, 22:50GMT+1' ) - time(),
180
- ];
181
 
182
- if ( $previous_version < '4200' && $current_version < '4201' )
183
  $tsf->register_dismissible_persistent_notice(
184
  $tsf->convert_markdown(
185
  sprintf(
186
- '<p>The SEO Framework: [Cyber Sale &ndash; 60%% off](%s). This notification will self-destruct when the sale ends, or when you dismiss it.</p>',
187
  'https://theseoframework.com/?p=3527'
188
  ),
189
- [ 'a', 'em', 'strong' ],
190
  [ 'a_internal' => false ]
191
  ),
192
- $suggest_key,
193
- $suggest_args,
194
- $suggest_conditions
 
 
 
 
 
 
 
 
 
 
 
195
  );
 
196
  }
40
  _prepare( $previous_version, $current_version );
41
  /**
42
  * Prepares a suggestion notification to ALL applicable plugin users on upgrade;
 
 
 
 
 
43
  *
44
  * The notice is automatically dismissed after X views, and it can be ignored without reappearing.
45
  *
52
  * @since 4.1.2 Can now communicate with Extension Manager for the edge-case sale.
53
  * @since 4.1.3 Commented out sale notification conditions, as those can't be met anyway.
54
  * @since 4.2.1 No longer tests WP and PHP requirements for Extension Manager.
55
+ * @since 4.2.7 Removed test for Extension Manager upgrade.
56
  * @access private
57
  *
58
  * @param string $previous_version The previous version the site upgraded from, if any.
68
  // 2
69
  if ( ! \is_main_site() ) return;
70
 
71
+ $show_sale = true;
72
+ if ( \function_exists( '\\tsf_extension_manager' ) && method_exists( \tsf_extension_manager(), 'is_connected_user' ) ) {
73
+ $show_sale = ! \tsf_extension_manager()->is_connected_user();
74
+ }
75
+ if ( $show_sale ) {
76
+ // phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
77
+ _suggest_temp_sale( $previous_version, $current_version );
78
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
  /**
93
  */
94
  function _suggest_temp_sale( $previous_version, $current_version ) {
95
 
96
+ if ( $previous_version < '4270' && $current_version < '4280' ) {
97
+ $tsf = \tsf();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
99
  $tsf->register_dismissible_persistent_notice(
100
  $tsf->convert_markdown(
101
  sprintf(
102
+ '<p>The SEO Framework: [Cyber Sale &ndash; 50%% off](%s). This notification will self-destruct when the sale ends, or when you dismiss it.</p>',
103
  'https://theseoframework.com/?p=3527'
104
  ),
105
+ [ 'a' ],
106
  [ 'a_internal' => false ]
107
  ),
108
+ 'suggest-sale',
109
+ [
110
+ 'type' => 'info',
111
+ 'icon' => false,
112
+ 'escape' => false,
113
+ ],
114
+ [
115
+ 'screens' => [],
116
+ 'excl_screens' => [ 'update-core', 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes', 'widgets', 'user', 'nav-menus', 'theme-editor', 'profile', 'export', 'site-health', 'export-personal-data', 'erase-personal-data' ],
117
+ 'capability' => 'install_plugins',
118
+ 'user' => 0,
119
+ 'count' => 4,
120
+ 'timeout' => strtotime( 'December 4th, 2022, 23:00GMT+1' ) - time(),
121
+ ]
122
  );
123
+ }
124
  }
inc/views/settings/metaboxes/description.php CHANGED
@@ -14,28 +14,20 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secr
14
 
15
  switch ( $this->get_view_instance( 'description', $instance ) ) :
16
  case 'description_main':
17
- HTML::header_title( __( 'Description Settings', 'autodescription' ) );
18
  HTML::description(
19
- __( 'The meta description can be used to determine the text used under the title on search engine results pages.', 'autodescription' )
20
  );
21
 
22
  ?>
23
  <hr>
24
  <?php
25
  HTML::header_title( __( 'Automated Description Settings', 'autodescription' ) );
26
- HTML::description(
27
- __( 'A description can be automatically generated for every page.', 'autodescription' )
28
- );
29
- HTML::description(
30
- __( 'Open Graph and Twitter Cards require descriptions. Therefore, it is best to leave this option enabled.', 'autodescription' )
31
- );
32
 
33
  $info = HTML::make_info(
34
  __( 'Learn how this feature works.', 'autodescription' ),
35
  'https://kb.theseoframework.com/?p=65',
36
  false
37
  );
38
-
39
  HTML::wrap_fields(
40
  Input::make_checkbox( [
41
  'id' => 'auto_description',
@@ -44,6 +36,66 @@ switch ( $this->get_view_instance( 'description', $instance ) ) :
44
  ] ),
45
  true
46
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  break;
48
 
49
  default:
14
 
15
  switch ( $this->get_view_instance( 'description', $instance ) ) :
16
  case 'description_main':
 
17
  HTML::description(
18
+ __( 'The meta description suggests text to be used under the title on search engine results pages.', 'autodescription' )
19
  );
20
 
21
  ?>
22
  <hr>
23
  <?php
24
  HTML::header_title( __( 'Automated Description Settings', 'autodescription' ) );
 
 
 
 
 
 
25
 
26
  $info = HTML::make_info(
27
  __( 'Learn how this feature works.', 'autodescription' ),
28
  'https://kb.theseoframework.com/?p=65',
29
  false
30
  );
 
31
  HTML::wrap_fields(
32
  Input::make_checkbox( [
33
  'id' => 'auto_description',
36
  ] ),
37
  true
38
  );
39
+ HTML::description(
40
+ __( "Open Graph and Twitter require descriptions. So, it's best to leave description generation enabled.", 'autodescription' )
41
+ );
42
+
43
+ ?>
44
+ <hr>
45
+ <?php
46
+ HTML::header_title( __( 'Advanced Generation Settings', 'autodescription' ) );
47
+
48
+ HTML::description(
49
+ __( 'The HTML content of your pages can be used to generate descriptions. The generator processes this HTML in passing layers to understand the layout. If the HTML is complex, not all layers may be processed, and you might find spaces missing between sentences. Increasing the maximum number of passes reduces the chance of this happening, but at the cost of performance.', 'autodescription' )
50
+ );
51
+
52
+ /**
53
+ * @since 4.2.7
54
+ * @param array $html_passes_method The HTML pass option by [ 'option_value' => 'Name' ]
55
+ */
56
+ $html_passes_methods = (array) apply_filters(
57
+ 'the_seo_framework_auto_descripton_html_method_methods',
58
+ [
59
+ 'fast' => __( 'Fast (max. 2 passes)', 'autodescription' ),
60
+ 'accurate' => __( 'Accurate (max. 6 passes)', 'autodescription' ),
61
+ 'thorough' => __( 'Thorough (max. 12 passes)', 'autodescription' ),
62
+ ]
63
+ );
64
+
65
+ $html_passes_select_options = '';
66
+ $_current = $this->get_option( 'auto_descripton_html_method' );
67
+ foreach ( $html_passes_methods as $value => $name ) {
68
+ $html_passes_select_options .= vsprintf(
69
+ '<option value="%s" %s>%s</option>',
70
+ [
71
+ esc_attr( $value ),
72
+ selected( $_current, esc_attr( $value ), false ),
73
+ esc_html( $name ),
74
+ ]
75
+ );
76
+ }
77
+
78
+ HTML::wrap_fields(
79
+ vsprintf(
80
+ '<label for="%1$s">%2$s</label>
81
+ <select name="%3$s" id="%1$s">%4$s</select>',
82
+ [
83
+ Input::get_field_id( 'auto_descripton_html_method' ),
84
+ esc_html__( 'HTML parsing method:', 'autodescription' ),
85
+ Input::get_field_name( 'auto_descripton_html_method' ),
86
+ $html_passes_select_options,
87
+ ]
88
+ ),
89
+ true
90
+ );
91
+
92
+ HTML::description_noesc(
93
+ sprintf(
94
+ '<a href="%s" target=_blank rel="noreferrer noopener">%s</a>',
95
+ 'https://kb.theseoframework.com/?p=65#html-passes',
96
+ esc_html__( 'Learn how this works.', 'autodescription' )
97
+ )
98
+ );
99
  break;
100
 
101
  default:
inc/views/settings/metaboxes/general.php CHANGED
@@ -225,21 +225,6 @@ switch ( $this->get_view_instance( 'general', $instance ) ) :
225
  ],
226
  true
227
  );
228
- ?>
229
- <hr>
230
- <?php
231
- HTML::header_title( __( 'Transient Cache Settings', 'autodescription' ) );
232
- HTML::description( __( 'To improve performance, generated output can be stored in the database as transient cache.', 'autodescription' ) );
233
-
234
- HTML::wrap_fields(
235
- Input::make_checkbox( [
236
- 'id' => 'cache_sitemap',
237
- 'label' => esc_html__( 'Enable optimized sitemap generation cache?', 'autodescription' )
238
- . ' ' . HTML::make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
239
- 'escape' => false,
240
- ] ),
241
- true
242
- );
243
  break;
244
 
245
  case 'general_canonical_tab':
225
  ],
226
  true
227
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  break;
229
 
230
  case 'general_canonical_tab':
inc/views/settings/metaboxes/post-type-archive.php CHANGED
@@ -175,7 +175,7 @@ switch ( $this->get_view_instance( 'post_type_archive', $instance ) ) :
175
  <input type="text" name="<?php Input::field_name( $_option_map['doctitle'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['doctitle'] ); ?>" value="<?= $this->esc_attr_preserve_amp( $this->get_post_type_archive_meta_item( 'doctitle', $post_type ) ) ?>" autocomplete=off />
176
  <?php
177
  [ $_full_title, $_prefix_value, $_default_title ] =
178
- $this->get_raw_generated_archive_title_items( get_post_type_object( $post_type ), 'admin' );
179
 
180
  $this->output_js_title_data(
181
  Input::get_field_id( $_option_map['doctitle'] ),
175
  <input type="text" name="<?php Input::field_name( $_option_map['doctitle'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['doctitle'] ); ?>" value="<?= $this->esc_attr_preserve_amp( $this->get_post_type_archive_meta_item( 'doctitle', $post_type ) ) ?>" autocomplete=off />
176
  <?php
177
  [ $_full_title, $_prefix_value, $_default_title ] =
178
+ $this->get_raw_generated_archive_title_items( get_post_type_object( $post_type ) );
179
 
180
  $this->output_js_title_data(
181
  Input::get_field_id( $_option_map['doctitle'] ),
inc/views/settings/metaboxes/sitemaps.php CHANGED
@@ -59,7 +59,6 @@ switch ( $this->get_view_instance( 'sitemaps', $instance ) ) :
59
  case 'sitemaps_general_tab':
60
  $sitemap_url = The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
61
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
62
- $use_core_sitemaps = $this->use_core_sitemaps();
63
  $sitemap_detected = $this->has_sitemap_xml();
64
 
65
  HTML::header_title( __( 'Sitemap Integration Settings', 'autodescription' ) );
@@ -114,7 +113,7 @@ switch ( $this->get_view_instance( 'sitemaps', $instance ) ) :
114
  );
115
  // TODO In settings generator (TSF 5.0): Overwite this section for Polylang/WPML and output each sitemap language link respectively.
116
  // TODO Also add a link telling where why it may not work consistently ('try opening in another browser, incognito, etc.')
117
- } elseif ( $use_core_sitemaps ) {
118
  $_index_url = get_sitemap_url( 'index' );
119
  if ( $_index_url )
120
  HTML::description_noesc(
@@ -162,6 +161,21 @@ switch ( $this->get_view_instance( 'sitemaps', $instance ) ) :
162
  </p>
163
  <?php
164
  HTML::description( __( 'Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion.', 'autodescription' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  break;
166
 
167
  case 'sitemaps_robots_tab':
59
  case 'sitemaps_general_tab':
60
  $sitemap_url = The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
61
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
 
62
  $sitemap_detected = $this->has_sitemap_xml();
63
 
64
  HTML::header_title( __( 'Sitemap Integration Settings', 'autodescription' ) );
113
  );
114
  // TODO In settings generator (TSF 5.0): Overwite this section for Polylang/WPML and output each sitemap language link respectively.
115
  // TODO Also add a link telling where why it may not work consistently ('try opening in another browser, incognito, etc.')
116
+ } elseif ( $this->use_core_sitemaps() ) {
117
  $_index_url = get_sitemap_url( 'index' );
118
  if ( $_index_url )
119
  HTML::description_noesc(
161
  </p>
162
  <?php
163
  HTML::description( __( 'Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion.', 'autodescription' ) );
164
+ ?>
165
+ <hr>
166
+ <?php
167
+ HTML::header_title( __( 'Transient Cache Settings', 'autodescription' ) );
168
+ HTML::description( __( 'To improve performance, generated output can be stored in the database as transient cache.', 'autodescription' ) );
169
+
170
+ HTML::wrap_fields(
171
+ Input::make_checkbox( [
172
+ 'id' => 'cache_sitemap',
173
+ 'label' => esc_html__( 'Enable optimized sitemap generation cache?', 'autodescription' )
174
+ . ' ' . HTML::make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
175
+ 'escape' => false,
176
+ ] ),
177
+ true
178
+ );
179
  break;
180
 
181
  case 'sitemaps_robots_tab':
inc/views/settings/metaboxes/title.php CHANGED
@@ -48,7 +48,6 @@ switch ( $this->get_view_instance( 'title', $instance ) ) :
48
  $example_tax_left = "<em>{$additions_left}{$cat_title}</em>";
49
  $example_tax_right = "<em>{$cat_title}{$additions_right}</em>";
50
 
51
- HTML::header_title( __( 'Automated Title Settings', 'autodescription' ) );
52
  HTML::description( __( 'The page title is prominently shown within the browser tab as well as within the search engine results pages.', 'autodescription' ) );
53
 
54
  // Yes, this is a mess. But, we cannot circumvent this because we do not control the translations.
48
  $example_tax_left = "<em>{$additions_left}{$cat_title}</em>";
49
  $example_tax_right = "<em>{$cat_title}{$additions_right}</em>";
50
 
 
51
  HTML::description( __( 'The page title is prominently shown within the browser tab as well as within the search engine results pages.', 'autodescription' ) );
52
 
53
  // Yes, this is a mess. But, we cannot circumvent this because we do not control the translations.
inc/views/sitemap/xml-sitemap.php CHANGED
@@ -16,8 +16,8 @@ $sitemap_bridge = The_SEO_Framework\Bridges\Sitemap::get_instance();
16
  $sitemap_bridge->output_sitemap_header();
17
 
18
  if ( $this->the_seo_framework_debug ) {
19
- echo '<!-- Site estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage() / MB_IN_BYTES, 3 ) . ' MB -->' . "\n";
20
- echo '<!-- System estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage( true ) / MB_IN_BYTES, 3 ) . ' MB -->' . "\n";
21
  }
22
 
23
  $sitemap_bridge->output_sitemap_urlset_open_tag();
@@ -29,21 +29,21 @@ echo $sitemap_base->generate_sitemap( $sitemap_id );
29
  $sitemap_bridge->output_sitemap_urlset_close_tag();
30
 
31
  if ( $sitemap_base->base_is_regenerated ) {
32
- echo "\n" . '<!-- ' . esc_html__( 'Sitemap is generated for this view', 'autodescription' ) . ' -->';
33
  } else {
34
- echo "\n" . '<!-- ' . esc_html__( 'Sitemap is served from cache', 'autodescription' ) . ' -->';
35
  }
36
 
37
  // Destruct class.
38
  $sitemap_base = null;
39
 
40
  if ( $this->the_seo_framework_debug ) {
41
- echo "\n" . '<!-- Site estimated current usage: ' . number_format( memory_get_usage() / MB_IN_BYTES, 3 ) . ' MB -->';
42
- echo "\n" . '<!-- System estimated current usage: ' . number_format( memory_get_usage( true ) / MB_IN_BYTES, 3 ) . ' MB -->';
43
- echo "\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / MB_IN_BYTES, 3 ) . ' MB -->';
44
- echo "\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / MB_IN_BYTES, 3 ) . ' MB -->';
45
- echo "\n" . '<!-- Freed memory prior to generation: ' . number_format( $sitemap_bridge->get_freed_memory( true ) / KB_IN_BYTES, 3 ) . ' kB -->';
46
- echo "\n" . '<!-- Sitemap generation time: ' . number_format( microtime( true ) - $timer_start, 6 ) . ' seconds -->';
47
- echo "\n" . '<!-- Sitemap caching enabled: ' . ( $this->get_option( 'cache_sitemap' ) ? 'yes' : 'no' ) . ' -->';
48
- echo "\n" . '<!-- Sitemap transient key: ' . esc_html( $this->get_sitemap_transient_name() ) . ' -->';
49
  }
16
  $sitemap_bridge->output_sitemap_header();
17
 
18
  if ( $this->the_seo_framework_debug ) {
19
+ echo '<!-- Site estimated peak usage prior to generation: ', number_format( memory_get_peak_usage() / MB_IN_BYTES, 3 ), ' MB -->' . "\n";
20
+ echo '<!-- System estimated peak usage prior to generation: ', number_format( memory_get_peak_usage( true ) / MB_IN_BYTES, 3 ), ' MB -->' . "\n";
21
  }
22
 
23
  $sitemap_bridge->output_sitemap_urlset_open_tag();
29
  $sitemap_bridge->output_sitemap_urlset_close_tag();
30
 
31
  if ( $sitemap_base->base_is_regenerated ) {
32
+ echo "\n<!-- ", esc_html__( 'Sitemap is generated for this view', 'autodescription' ), ' -->';
33
  } else {
34
+ echo "\n<!-- ", esc_html__( 'Sitemap is served from cache', 'autodescription' ), ' -->';
35
  }
36
 
37
  // Destruct class.
38
  $sitemap_base = null;
39
 
40
  if ( $this->the_seo_framework_debug ) {
41
+ echo "\n<!-- Site estimated current usage: ", number_format( memory_get_usage() / MB_IN_BYTES, 3 ), ' MB -->';
42
+ echo "\n<!-- System estimated current usage: ", number_format( memory_get_usage( true ) / MB_IN_BYTES, 3 ), ' MB -->';
43
+ echo "\n<!-- Site estimated peak usage: ", number_format( memory_get_peak_usage() / MB_IN_BYTES, 3 ), ' MB -->';
44
+ echo "\n<!-- System estimated peak usage: ", number_format( memory_get_peak_usage( true ) / MB_IN_BYTES, 3 ), ' MB -->';
45
+ echo "\n<!-- Freed memory prior to generation: ", number_format( $sitemap_bridge->get_freed_memory( true ) / KB_IN_BYTES, 3 ), ' kB -->';
46
+ echo "\n<!-- Sitemap generation time: ", number_format( microtime( true ) - $timer_start, 6 ), ' seconds -->';
47
+ echo "\n<!-- Sitemap caching enabled: ", ( $this->get_option( 'cache_sitemap' ) ? 'yes' : 'no' ), ' -->';
48
+ echo "\n<!-- Sitemap transient key: ", esc_html( $this->get_sitemap_transient_name() ), ' -->';
49
  }
language/autodescription.pot CHANGED
@@ -1,15 +1,15 @@
1
- # Copyright (C) 2021 The SEO Framework Team
2
  # This file is distributed under the same license as the The SEO Framework plugin.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: The SEO Framework 4.2.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/trunk\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2021-11-14T18:31:15+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: autodescription\n"
@@ -32,37 +32,42 @@ msgid "The SEO Framework Team"
32
  msgstr ""
33
 
34
  #. translators: %1$s = New, lower version number, surrounded in markdown-backticks. %2$s = Old, higher version number, surrounded in markdown-backticks.
35
- #: bootstrap/upgrade.php:365
36
  msgid "Your website has been downgraded successfully to use The SEO Framework at database version `%1$s` from `%2$s`."
37
  msgstr ""
38
 
39
  #. translators: %s = Version number, surrounded in markdown-backticks.
40
- #: bootstrap/upgrade.php:415
41
  msgid "Thank you for updating The SEO Framework! Your website has been upgraded successfully to use The SEO Framework at database version `%s`."
42
  msgstr ""
43
 
44
- #: bootstrap/upgrade.php:445
45
  msgid "The SEO Framework automatically optimizes your website for search engines and social media."
46
  msgstr ""
47
 
48
  #. translators: %s = Link, markdown.
49
- #: bootstrap/upgrade.php:449
50
  msgid "To take full advantage of all SEO features, please follow our [5-minute setup guide](%s)."
51
  msgstr ""
52
 
53
- #: bootstrap/upgrade.php:581
 
 
 
 
 
54
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
55
  msgstr ""
56
 
57
- #: bootstrap/upgrade.php:606
58
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
59
  msgstr ""
60
 
61
- #: bootstrap/upgrade.php:698
62
  msgid "A cronjob is now used to ping search engines, and it alerts them to changes in your sitemap."
63
  msgstr ""
64
 
65
- #: bootstrap/upgrade.php:711
66
  msgid "The positions in the \"Meta Title Additions Location\" setting for the homepage have been reversed, left to right, but the output has not been changed. If you must downgrade for some reason, remember to switch the location back again."
67
  msgstr ""
68
 
@@ -74,82 +79,82 @@ msgstr ""
74
  msgid "No Archive"
75
  msgstr ""
76
 
77
- #: inc/classes/admin-init.class.php:317
78
  msgid "There's no content."
79
  msgstr ""
80
 
81
- #: inc/classes/admin-init.class.php:318
82
  msgid "It's too short and it should have more information."
83
  msgstr ""
84
 
85
- #: inc/classes/admin-init.class.php:319
86
  msgid "It's short and it could have more information."
87
  msgstr ""
88
 
89
- #: inc/classes/admin-init.class.php:320
90
  msgid "It's long and it might get truncated in search."
91
  msgstr ""
92
 
93
- #: inc/classes/admin-init.class.php:321
94
  msgid "It's too long and it will get truncated in search."
95
  msgstr ""
96
 
97
- #: inc/classes/admin-init.class.php:322
98
  msgid "Length is good."
99
  msgstr ""
100
 
101
- #: inc/classes/admin-init.class.php:325
102
  msgctxt "The string is empty"
103
  msgid "Empty"
104
  msgstr ""
105
 
106
- #: inc/classes/admin-init.class.php:326
107
  msgid "Far too short"
108
  msgstr ""
109
 
110
- #: inc/classes/admin-init.class.php:327
111
  msgid "Too short"
112
  msgstr ""
113
 
114
- #: inc/classes/admin-init.class.php:328
115
  msgid "Too long"
116
  msgstr ""
117
 
118
- #: inc/classes/admin-init.class.php:329
119
  msgid "Far too long"
120
  msgstr ""
121
 
122
- #: inc/classes/admin-init.class.php:330
123
  msgid "Good"
124
  msgstr ""
125
 
126
- #: inc/classes/admin-init.class.php:333
127
  msgctxt "The string is empty"
128
  msgid "Empty."
129
  msgstr ""
130
 
131
- #: inc/classes/admin-init.class.php:334
132
  msgid "Far too short."
133
  msgstr ""
134
 
135
- #: inc/classes/admin-init.class.php:335
136
  msgid "Too short."
137
  msgstr ""
138
 
139
- #: inc/classes/admin-init.class.php:336
140
  msgid "Too long."
141
  msgstr ""
142
 
143
- #: inc/classes/admin-init.class.php:337
144
  msgid "Far too long."
145
  msgstr ""
146
 
147
- #: inc/classes/admin-init.class.php:338
148
  msgid "Good."
149
  msgstr ""
150
 
151
  #. translators: %s = Redirect URL markdown
152
- #: inc/classes/admin-init.class.php:431
153
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
154
  msgstr ""
155
 
@@ -181,7 +186,7 @@ msgstr ""
181
  msgid "Multiple SEO tools have been detected. You should only use one."
182
  msgstr ""
183
 
184
- #: inc/classes/bridges/feed.class.php:180
185
  msgctxt "The content source"
186
  msgid "Source"
187
  msgstr ""
@@ -191,6 +196,8 @@ msgid "Settings"
191
  msgstr ""
192
 
193
  #: inc/classes/bridges/plugintable.class.php:64
 
 
194
  msgctxt "Plugin extensions"
195
  msgid "Extensions"
196
  msgstr ""
@@ -231,70 +238,70 @@ msgstr ""
231
  msgid "%s SEO Settings"
232
  msgstr ""
233
 
234
- #: inc/classes/bridges/scripts.class.php:330
235
  msgid "The changes you made will be lost if you navigate away from this page."
236
  msgstr ""
237
 
238
- #: inc/classes/bridges/scripts.class.php:611
239
  #: inc/classes/interpreters/form.class.php:230
240
  msgid "Select Image"
241
  msgstr ""
242
 
243
- #: inc/classes/bridges/scripts.class.php:613
244
  msgid "Change Image"
245
  msgstr ""
246
 
247
- #: inc/classes/bridges/scripts.class.php:614
248
  msgid "Remove Image"
249
  msgstr ""
250
 
251
- #: inc/classes/bridges/scripts.class.php:616
252
  msgctxt "Frame title"
253
  msgid "Select Social Image"
254
  msgstr ""
255
 
256
- #: inc/classes/bridges/scripts.class.php:617
257
- #: inc/classes/bridges/scripts.class.php:626
258
  msgid "Use this image"
259
  msgstr ""
260
 
261
- #: inc/classes/bridges/scripts.class.php:620
262
  #: inc/classes/internal/deprecated.class.php:414
263
- #: inc/views/settings/metaboxes/schema.php:189
264
- #: inc/views/settings/metaboxes/sitemaps.php:403
265
  msgid "Select Logo"
266
  msgstr ""
267
 
268
- #: inc/classes/bridges/scripts.class.php:622
269
  msgid "Change Logo"
270
  msgstr ""
271
 
272
- #: inc/classes/bridges/scripts.class.php:623
273
  msgid "Remove Logo"
274
  msgstr ""
275
 
276
- #: inc/classes/bridges/scripts.class.php:625
277
  msgctxt "Frame title"
278
  msgid "Select Logo"
279
  msgstr ""
280
 
281
  #. translators: %s = term name
282
- #: inc/classes/bridges/scripts.class.php:763
283
  msgid "Select Primary %s"
284
  msgstr ""
285
 
286
  #. translators: %s = term name
287
- #: inc/classes/bridges/scripts.class.php:768
288
  msgid "Make primary %s"
289
  msgstr ""
290
 
291
  #. translators: %s = term name
292
- #: inc/classes/bridges/scripts.class.php:770
293
  msgid "Primary %s"
294
  msgstr ""
295
 
296
  #. translators: Pixel counter. 1: number (value), 2: number (guideline)
297
- #: inc/classes/bridges/scripts.class.php:875
298
  msgid "%1$d out of %2$d pixels are used."
299
  msgstr ""
300
 
@@ -570,87 +577,87 @@ msgid "The description inputted at the Edit Page screen is used."
570
  msgstr ""
571
 
572
  #. translators: 1: Word found, 2: Occurrences
573
- #: inc/classes/builders/seobar/page.class.php:495
574
  #: inc/classes/builders/seobar/term.class.php:464
575
  msgid "&#8220;%1$s&#8221; is used %2$d times."
576
  msgstr ""
577
 
578
- #: inc/classes/builders/seobar/page.class.php:573
579
- #: inc/classes/builders/seobar/page.class.php:730
580
- #: inc/classes/builders/seobar/page.class.php:861
581
  #: inc/classes/builders/seobar/term.class.php:543
582
  #: inc/classes/builders/seobar/term.class.php:694
583
  #: inc/classes/builders/seobar/term.class.php:811
584
  msgid "The robots.txt file is nonstandard, and may still direct search engines differently."
585
  msgstr ""
586
 
587
- #: inc/classes/builders/seobar/page.class.php:574
588
- #: inc/classes/builders/seobar/page.class.php:731
589
- #: inc/classes/builders/seobar/page.class.php:862
590
  #: inc/classes/builders/seobar/term.class.php:544
591
  #: inc/classes/builders/seobar/term.class.php:695
592
  #: inc/classes/builders/seobar/term.class.php:812
593
  msgid "WordPress discourages crawling via the Reading Settings."
594
  msgstr ""
595
 
596
- #: inc/classes/builders/seobar/page.class.php:575
597
  #: inc/classes/builders/seobar/term.class.php:545
598
  msgid "Indexing is discouraged for the whole site at the SEO Settings screen."
599
  msgstr ""
600
 
601
- #: inc/classes/builders/seobar/page.class.php:576
602
  msgid "Indexing is discouraged for this post type at the SEO Settings screen."
603
  msgstr ""
604
 
605
- #: inc/classes/builders/seobar/page.class.php:577
606
  msgid "The page is protected, so indexing is discouraged."
607
  msgstr ""
608
 
609
- #: inc/classes/builders/seobar/page.class.php:578
610
  msgid "The page SEO meta input overrides the indexing state."
611
  msgstr ""
612
 
613
- #: inc/classes/builders/seobar/page.class.php:579
614
  #: inc/classes/builders/seobar/term.class.php:551
615
  msgid "A custom canonical URL is set that points to another page."
616
  msgstr ""
617
 
618
- #: inc/classes/builders/seobar/page.class.php:582
619
- #: inc/classes/builders/seobar/page.class.php:738
620
- #: inc/classes/builders/seobar/page.class.php:869
621
  #: inc/classes/builders/seobar/term.class.php:554
622
  #: inc/classes/builders/seobar/term.class.php:703
623
  #: inc/classes/builders/seobar/term.class.php:820
624
  msgid "WordPress overrides the robots directive."
625
  msgstr ""
626
 
627
- #: inc/classes/builders/seobar/page.class.php:583
628
  msgid "The page is protected."
629
  msgstr ""
630
 
631
- #: inc/classes/builders/seobar/page.class.php:584
632
- #: inc/classes/builders/seobar/page.class.php:739
633
- #: inc/classes/builders/seobar/page.class.php:870
634
  msgid "The page is not published."
635
  msgstr ""
636
 
637
- #: inc/classes/builders/seobar/page.class.php:585
638
  #: inc/classes/builders/seobar/term.class.php:557
639
  msgid "The canonical URL points to another page."
640
  msgstr ""
641
 
642
- #: inc/classes/builders/seobar/page.class.php:589
643
- #: inc/classes/builders/seobar/page.class.php:598
644
- #: inc/classes/builders/seobar/page.class.php:607
645
  #: inc/classes/builders/seobar/term.class.php:561
646
  #: inc/classes/builders/seobar/term.class.php:570
647
  msgctxt "Indexing"
648
  msgid "I"
649
  msgstr ""
650
 
651
- #: inc/classes/builders/seobar/page.class.php:590
652
- #: inc/classes/builders/seobar/page.class.php:599
653
- #: inc/classes/builders/seobar/page.class.php:608
654
  #: inc/classes/builders/seobar/term.class.php:562
655
  #: inc/classes/builders/seobar/term.class.php:571
656
  #: inc/views/edit/seo-settings-singular.php:241
@@ -663,69 +670,69 @@ msgstr ""
663
  msgid "Indexing"
664
  msgstr ""
665
 
666
- #: inc/classes/builders/seobar/page.class.php:592
667
  msgid "Page may be indexed."
668
  msgstr ""
669
 
670
- #: inc/classes/builders/seobar/page.class.php:594
671
  #: inc/classes/builders/seobar/term.class.php:566
672
  msgid "The robots meta tag allows indexing."
673
  msgstr ""
674
 
675
- #: inc/classes/builders/seobar/page.class.php:601
676
  msgid "Page may not be indexed."
677
  msgstr ""
678
 
679
- #: inc/classes/builders/seobar/page.class.php:603
680
  #: inc/classes/builders/seobar/term.class.php:575
681
  msgid "The robots meta tag does not allow indexing."
682
  msgstr ""
683
 
684
- #: inc/classes/builders/seobar/page.class.php:610
685
- #: inc/classes/builders/seobar/page.class.php:764
686
- #: inc/classes/builders/seobar/page.class.php:895
687
- msgid "Page is invisible."
688
- msgstr ""
689
-
690
  #: inc/classes/builders/seobar/page.class.php:612
691
  #: inc/classes/builders/seobar/page.class.php:766
692
  #: inc/classes/builders/seobar/page.class.php:897
 
 
 
 
 
 
693
  msgid "This page isn't published and can't be found publicly."
694
  msgstr ""
695
 
696
- #: inc/classes/builders/seobar/page.class.php:667
697
  msgid "Indexing is discouraged for the homepage at the SEO Settings screen."
698
  msgstr ""
699
 
700
- #: inc/classes/builders/seobar/page.class.php:732
701
  #: inc/classes/builders/seobar/term.class.php:696
702
  msgid "Link following is discouraged for the whole site at the SEO Settings screen."
703
  msgstr ""
704
 
705
- #: inc/classes/builders/seobar/page.class.php:733
706
  msgid "Link following is discouraged for this post type at the SEO Settings screen."
707
  msgstr ""
708
 
709
- #: inc/classes/builders/seobar/page.class.php:734
710
  msgid "The page SEO meta input overrides the link following state."
711
  msgstr ""
712
 
713
- #: inc/classes/builders/seobar/page.class.php:735
714
  msgid "The page may not be indexed, this may also discourage link following."
715
  msgstr ""
716
 
717
- #: inc/classes/builders/seobar/page.class.php:743
718
- #: inc/classes/builders/seobar/page.class.php:752
719
- #: inc/classes/builders/seobar/page.class.php:761
720
  #: inc/classes/builders/seobar/term.class.php:707
721
  #: inc/classes/builders/seobar/term.class.php:716
722
  msgctxt "Following"
723
  msgid "F"
724
  msgstr ""
725
 
726
- #: inc/classes/builders/seobar/page.class.php:744
727
- #: inc/classes/builders/seobar/page.class.php:753
728
- #: inc/classes/builders/seobar/page.class.php:762
729
  #: inc/classes/builders/seobar/term.class.php:708
730
  #: inc/classes/builders/seobar/term.class.php:717
731
  #: inc/views/list/quick-term.php:29
@@ -733,57 +740,57 @@ msgstr ""
733
  msgid "Following"
734
  msgstr ""
735
 
736
- #: inc/classes/builders/seobar/page.class.php:746
737
  msgid "Page links may be followed."
738
  msgstr ""
739
 
740
- #: inc/classes/builders/seobar/page.class.php:748
741
  #: inc/classes/builders/seobar/term.class.php:712
742
  msgid "The robots meta tag allows link following."
743
  msgstr ""
744
 
745
- #: inc/classes/builders/seobar/page.class.php:755
746
  msgid "Page links may not be followed."
747
  msgstr ""
748
 
749
- #: inc/classes/builders/seobar/page.class.php:757
750
  #: inc/classes/builders/seobar/term.class.php:721
751
  msgid "The robots meta tag does not allow link following."
752
  msgstr ""
753
 
754
- #: inc/classes/builders/seobar/page.class.php:809
755
  msgid "Link following is discouraged for the homepage at the SEO Settings screen."
756
  msgstr ""
757
 
758
- #: inc/classes/builders/seobar/page.class.php:863
759
  #: inc/classes/builders/seobar/term.class.php:813
760
  msgid "Archiving is discouraged for the whole site at the SEO Settings screen."
761
  msgstr ""
762
 
763
- #: inc/classes/builders/seobar/page.class.php:864
764
  msgid "Archiving is discouraged for this post type at the SEO Settings screen."
765
  msgstr ""
766
 
767
- #: inc/classes/builders/seobar/page.class.php:865
768
  msgid "The page SEO meta input overrides the archiving state."
769
  msgstr ""
770
 
771
- #: inc/classes/builders/seobar/page.class.php:866
772
  msgid "The page may not be indexed, this may also discourage archiving."
773
  msgstr ""
774
 
775
- #: inc/classes/builders/seobar/page.class.php:874
776
- #: inc/classes/builders/seobar/page.class.php:883
777
- #: inc/classes/builders/seobar/page.class.php:892
778
  #: inc/classes/builders/seobar/term.class.php:824
779
  #: inc/classes/builders/seobar/term.class.php:833
780
  msgctxt "Archiving"
781
  msgid "A"
782
  msgstr ""
783
 
784
- #: inc/classes/builders/seobar/page.class.php:875
785
- #: inc/classes/builders/seobar/page.class.php:884
786
- #: inc/classes/builders/seobar/page.class.php:893
787
  #: inc/classes/builders/seobar/term.class.php:825
788
  #: inc/classes/builders/seobar/term.class.php:834
789
  #: inc/views/edit/seo-settings-singular.php:257
@@ -796,60 +803,60 @@ msgstr ""
796
  msgid "Archiving"
797
  msgstr ""
798
 
799
- #: inc/classes/builders/seobar/page.class.php:877
800
  msgid "Page may be archived."
801
  msgstr ""
802
 
803
- #: inc/classes/builders/seobar/page.class.php:879
804
  #: inc/classes/builders/seobar/term.class.php:829
805
  msgid "The robots meta tag allows archiving."
806
  msgstr ""
807
 
808
- #: inc/classes/builders/seobar/page.class.php:886
809
  msgid "Page may not be archived."
810
  msgstr ""
811
 
812
- #: inc/classes/builders/seobar/page.class.php:888
813
  #: inc/classes/builders/seobar/term.class.php:838
814
  msgid "The robots meta tag does not allow archiving."
815
  msgstr ""
816
 
817
- #: inc/classes/builders/seobar/page.class.php:940
818
  msgid "Archiving is discouraged for the homepage at the SEO Settings screen."
819
  msgstr ""
820
 
821
- #: inc/classes/builders/seobar/page.class.php:991
822
- #: inc/classes/builders/seobar/page.class.php:1012
823
  #: inc/classes/builders/seobar/term.class.php:925
824
  #: inc/classes/builders/seobar/term.class.php:941
825
  msgctxt "Redirect"
826
  msgid "R"
827
  msgstr ""
828
 
829
- #: inc/classes/builders/seobar/page.class.php:992
830
- #: inc/classes/builders/seobar/page.class.php:1013
831
  #: inc/classes/builders/seobar/term.class.php:926
832
  #: inc/classes/builders/seobar/term.class.php:942
833
  msgid "Redirection"
834
  msgstr ""
835
 
836
- #: inc/classes/builders/seobar/page.class.php:994
837
  msgid "Page does not redirect visitors."
838
  msgstr ""
839
 
840
- #: inc/classes/builders/seobar/page.class.php:996
841
  msgid "Visitors and crawlers may view this page."
842
  msgstr ""
843
 
844
- #: inc/classes/builders/seobar/page.class.php:1005
845
  msgid "Visitors and crawlers may view this page once published."
846
  msgstr ""
847
 
848
- #: inc/classes/builders/seobar/page.class.php:1015
849
  msgid "Page redirects visitors."
850
  msgstr ""
851
 
852
- #: inc/classes/builders/seobar/page.class.php:1017
853
  #: inc/classes/builders/seobar/term.class.php:946
854
  msgid "All visitors and crawlers are being redirected. So, no other SEO enhancements are effective."
855
  msgstr ""
@@ -987,17 +994,17 @@ msgid "Term redirects visitors."
987
  msgstr ""
988
 
989
  #. translators: %s = timestamp
990
- #: inc/classes/builders/sitemap/base.class.php:175
991
  msgid "Sitemap is prerendered on %s"
992
  msgstr ""
993
 
994
  #. translators: %s = timestamp
995
- #: inc/classes/builders/sitemap/base.class.php:177
996
  msgid "Sitemap is generated on %s"
997
  msgstr ""
998
 
999
  #. translators: %s = Blog page title. Front-end output.
1000
- #: inc/classes/generate-description.class.php:787
1001
  msgid "Latest posts: %s"
1002
  msgstr ""
1003
 
@@ -1071,11 +1078,11 @@ msgid "Assessments"
1071
  msgstr ""
1072
 
1073
  #. translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer
1074
- #: inc/classes/render.class.php:1279
1075
  msgid "%1$s %2$s"
1076
  msgstr ""
1077
 
1078
- #: inc/classes/render.class.php:1287
1079
  msgid "by Sybre Waaijer"
1080
  msgstr ""
1081
 
@@ -1089,7 +1096,7 @@ msgstr ""
1089
  #: inc/views/settings/metaboxes/robots.php:61
1090
  #: inc/views/settings/metaboxes/sitemaps.php:23
1091
  #: inc/views/settings/metaboxes/social.php:23
1092
- #: inc/views/settings/metaboxes/title.php:138
1093
  msgid "General"
1094
  msgstr ""
1095
 
@@ -1153,7 +1160,6 @@ msgstr ""
1153
 
1154
  #: inc/views/edit/seo-settings-singular.php:191
1155
  #: inc/views/edit/seo-settings-tt.php:173
1156
- #: inc/views/settings/metaboxes/description.php:19
1157
  #: inc/views/settings/metaboxes/homepage.php:137
1158
  #: inc/views/settings/metaboxes/post-type-archive.php:225
1159
  msgid "The meta description can be used to determine the text used under the title on search engine results pages."
@@ -1342,28 +1348,52 @@ msgstr ""
1342
  msgid "This may be shown publicly."
1343
  msgstr ""
1344
 
1345
- #: inc/views/settings/metaboxes/description.php:17
1346
- msgid "Description Settings"
1347
  msgstr ""
1348
 
1349
- #: inc/views/settings/metaboxes/description.php:25
1350
  msgid "Automated Description Settings"
1351
  msgstr ""
1352
 
1353
  #: inc/views/settings/metaboxes/description.php:27
1354
- msgid "A description can be automatically generated for every page."
1355
  msgstr ""
1356
 
1357
- #: inc/views/settings/metaboxes/description.php:30
1358
- msgid "Open Graph and Twitter Cards require descriptions. Therefore, it is best to leave this option enabled."
1359
  msgstr ""
1360
 
1361
- #: inc/views/settings/metaboxes/description.php:34
1362
- msgid "Learn how this feature works."
1363
  msgstr ""
1364
 
1365
- #: inc/views/settings/metaboxes/description.php:42
1366
- msgid "Automatically generate descriptions?"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1367
  msgstr ""
1368
 
1369
  #: inc/views/settings/metaboxes/feed.php:17
@@ -1542,141 +1572,125 @@ msgid "This allows you to exclude pages from on-site archive listings."
1542
  msgstr ""
1543
 
1544
  #: inc/views/settings/metaboxes/general.php:231
1545
- msgid "Transient Cache Settings"
1546
- msgstr ""
1547
-
1548
- #: inc/views/settings/metaboxes/general.php:232
1549
- msgid "To improve performance, generated output can be stored in the database as transient cache."
1550
- msgstr ""
1551
-
1552
- #: inc/views/settings/metaboxes/general.php:237
1553
- msgid "Enable optimized sitemap generation cache?"
1554
- msgstr ""
1555
-
1556
- #: inc/views/settings/metaboxes/general.php:238
1557
- msgid "Generating the sitemap can use a lot of server resources."
1558
- msgstr ""
1559
-
1560
- #: inc/views/settings/metaboxes/general.php:246
1561
  msgid "Canonical URL Settings"
1562
  msgstr ""
1563
 
1564
- #: inc/views/settings/metaboxes/general.php:247
1565
  msgid "The canonical URL meta tag urges search engines to go to the outputted URL."
1566
  msgstr ""
1567
 
1568
- #: inc/views/settings/metaboxes/general.php:248
1569
  msgid "If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL."
1570
  msgstr ""
1571
 
1572
- #: inc/views/settings/metaboxes/general.php:252
1573
  msgid "Scheme Settings"
1574
  msgstr ""
1575
 
1576
- #: inc/views/settings/metaboxes/general.php:253
1577
  msgid "If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines."
1578
  msgstr ""
1579
 
1580
- #: inc/views/settings/metaboxes/general.php:255
1581
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1582
  msgid "Preferred canonical URL scheme:"
1583
  msgstr ""
1584
 
1585
  #. translators: %s = HTTP or HTTPS
1586
- #: inc/views/settings/metaboxes/general.php:263
1587
  msgid "Detect automatically (%s)"
1588
  msgstr ""
1589
 
1590
- #: inc/views/settings/metaboxes/general.php:277
1591
  msgid "Link Relationship Settings"
1592
  msgstr ""
1593
 
1594
- #: inc/views/settings/metaboxes/general.php:278
1595
  msgid "Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results."
1596
  msgstr ""
1597
 
1598
- #: inc/views/settings/metaboxes/general.php:279
1599
  msgid "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues."
1600
  msgstr ""
1601
 
1602
  #. translators: the backticks are Markdown! Preserve them as-is!
1603
- #: inc/views/settings/metaboxes/general.php:285
1604
  msgid "Add `rel` link tags to posts and pages?"
1605
  msgstr ""
1606
 
1607
  #. translators: the backticks are Markdown! Preserve them as-is!
1608
- #: inc/views/settings/metaboxes/general.php:295
1609
  msgid "Add `rel` link tags to archives?"
1610
  msgstr ""
1611
 
1612
  #. translators: the backticks are Markdown! Preserve them as-is!
1613
- #: inc/views/settings/metaboxes/general.php:305
1614
  msgid "Add `rel` link tags to the homepage?"
1615
  msgstr ""
1616
 
1617
- #: inc/views/settings/metaboxes/general.php:318
1618
  msgid "Timestamp Settings"
1619
  msgstr ""
1620
 
1621
- #: inc/views/settings/metaboxes/general.php:319
1622
  msgid "Timestamps help indicate when a page has been published and modified."
1623
  msgstr ""
1624
 
1625
- #: inc/views/settings/metaboxes/general.php:324
1626
  msgid "Timestamp Format Settings"
1627
  msgstr ""
1628
 
1629
- #: inc/views/settings/metaboxes/general.php:325
1630
  msgid "This setting determines how specific the timestamp is."
1631
  msgstr ""
1632
 
1633
- #: inc/views/settings/metaboxes/general.php:334
1634
  msgid "This outputs the complete date."
1635
  msgstr ""
1636
 
1637
- #: inc/views/settings/metaboxes/general.php:345
1638
  msgid "This outputs the complete date including hours, minutes, and timezone."
1639
  msgstr ""
1640
 
1641
- #: inc/views/settings/metaboxes/general.php:356
1642
  msgid "Exclusion Settings"
1643
  msgstr ""
1644
 
1645
- #: inc/views/settings/metaboxes/general.php:357
1646
  msgid "When checked, these options will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types and taxonomies. This will allow search engines to crawl the post type and taxonomies without advanced restrictions or directions."
1647
  msgstr ""
1648
 
1649
  #. translators: backticks are code wraps. Markdown!
1650
- #: inc/views/settings/metaboxes/general.php:361
1651
  msgid "These options should not need changing when post types and taxonomies are registered correctly. When they aren't, consider applying `noindex` to purge them from search engines, instead."
1652
  msgstr ""
1653
 
1654
- #: inc/views/settings/metaboxes/general.php:365
1655
  msgid "Default post types and taxonomies can not be excluded."
1656
  msgstr ""
1657
 
1658
- #: inc/views/settings/metaboxes/general.php:370
1659
  msgid "Post Type Exclusions"
1660
  msgstr ""
1661
 
1662
- #: inc/views/settings/metaboxes/general.php:371
1663
  msgid "Select post types which should be excluded."
1664
  msgstr ""
1665
 
1666
- #: inc/views/settings/metaboxes/general.php:372
1667
  #: inc/views/settings/metaboxes/robots.php:306
1668
  msgid "These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect."
1669
  msgstr ""
1670
 
1671
- #: inc/views/settings/metaboxes/general.php:401
1672
  msgid "Taxonomy Exclusions"
1673
  msgstr ""
1674
 
1675
- #: inc/views/settings/metaboxes/general.php:402
1676
  msgid "Select taxonomies which should be excluded."
1677
  msgstr ""
1678
 
1679
- #: inc/views/settings/metaboxes/general.php:403
1680
  msgid "When taxonomies have all their bound post types excluded, they will inherit their exclusion status."
1681
  msgstr ""
1682
 
@@ -1685,7 +1699,7 @@ msgid "These settings will take precedence over the settings set within the home
1685
  msgstr ""
1686
 
1687
  #: inc/views/settings/metaboxes/homepage.php:36
1688
- #: inc/views/settings/metaboxes/title.php:143
1689
  msgid "Additions"
1690
  msgstr ""
1691
 
@@ -1728,12 +1742,12 @@ msgid "Meta Title Additions Location"
1728
  msgstr ""
1729
 
1730
  #: inc/views/settings/metaboxes/homepage.php:242
1731
- #: inc/views/settings/metaboxes/title.php:255
1732
  msgid "Left:"
1733
  msgstr ""
1734
 
1735
  #: inc/views/settings/metaboxes/homepage.php:252
1736
- #: inc/views/settings/metaboxes/title.php:265
1737
  msgid "Right:"
1738
  msgstr ""
1739
 
@@ -2069,7 +2083,7 @@ msgstr ""
2069
  #: inc/views/settings/metaboxes/schema.php:64
2070
  #: inc/views/settings/metaboxes/schema.php:84
2071
  #: inc/views/settings/metaboxes/schema.php:103
2072
- #: inc/views/settings/metaboxes/schema.php:150
2073
  msgid "Learn how this data is used."
2074
  msgstr ""
2075
 
@@ -2120,96 +2134,96 @@ msgstr ""
2120
  msgid "A Person"
2121
  msgstr ""
2122
 
2123
- #: inc/views/settings/metaboxes/schema.php:139
2124
  msgid "The organization or personal name"
2125
  msgstr ""
2126
 
2127
- #: inc/views/settings/metaboxes/schema.php:147
2128
  msgid "Website logo"
2129
  msgstr ""
2130
 
2131
- #: inc/views/settings/metaboxes/schema.php:148
2132
  msgid "These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere."
2133
  msgstr ""
2134
 
2135
- #: inc/views/settings/metaboxes/schema.php:157
2136
  msgid "Enable logo?"
2137
  msgstr ""
2138
 
2139
- #: inc/views/settings/metaboxes/schema.php:166
2140
- #: inc/views/settings/metaboxes/sitemaps.php:380
2141
  msgid "Logo URL"
2142
  msgstr ""
2143
 
2144
- #: inc/views/settings/metaboxes/schema.php:169
2145
- #: inc/views/settings/metaboxes/sitemaps.php:383
2146
  msgid "Setting a logo requires JavaScript."
2147
  msgstr ""
2148
 
2149
- #: inc/views/settings/metaboxes/schema.php:196
2150
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
2151
  msgid "RelatedProfile"
2152
  msgstr ""
2153
 
2154
- #: inc/views/settings/metaboxes/schema.php:204
2155
  msgid "Facebook Page"
2156
  msgstr ""
2157
 
2158
- #: inc/views/settings/metaboxes/schema.php:211
2159
  msgid "Twitter Profile"
2160
  msgstr ""
2161
 
2162
- #: inc/views/settings/metaboxes/schema.php:218
2163
  msgctxt "Google+ is dead. &#8224; is a cross, indicating that."
2164
  msgid "Google+ Profile&#8224;"
2165
  msgstr ""
2166
 
2167
- #: inc/views/settings/metaboxes/schema.php:225
2168
  msgid "Instagram Profile"
2169
  msgstr ""
2170
 
2171
- #: inc/views/settings/metaboxes/schema.php:232
2172
  msgid "Youtube Profile"
2173
  msgstr ""
2174
 
2175
- #: inc/views/settings/metaboxes/schema.php:239
2176
  msgid "LinkedIn Profile"
2177
  msgstr ""
2178
 
2179
- #: inc/views/settings/metaboxes/schema.php:250
2180
  msgid "Pinterest Profile"
2181
  msgstr ""
2182
 
2183
- #: inc/views/settings/metaboxes/schema.php:257
2184
  msgid "SoundCloud Profile"
2185
  msgstr ""
2186
 
2187
- #: inc/views/settings/metaboxes/schema.php:264
2188
  msgid "Tumblr Blog"
2189
  msgstr ""
2190
 
2191
- #: inc/views/settings/metaboxes/schema.php:283
2192
  msgid "Connected Social Pages"
2193
  msgstr ""
2194
 
2195
- #: inc/views/settings/metaboxes/schema.php:284
2196
  msgid "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway."
2197
  msgstr ""
2198
 
2199
- #: inc/views/settings/metaboxes/schema.php:285
2200
  msgid "Add links that lead directly to the connected social pages of this website."
2201
  msgstr ""
2202
 
2203
- #: inc/views/settings/metaboxes/schema.php:286
2204
  msgid "These settings do not affect sharing behavior with the social networks."
2205
  msgstr ""
2206
 
2207
  #. translators: %s = Learn more URL. Markdown!
2208
- #: inc/views/settings/metaboxes/schema.php:291
2209
  msgid "These settings are marked for removal. When you clear a field, it will be hidden forever. [Learn more](%s)."
2210
  msgstr ""
2211
 
2212
- #: inc/views/settings/metaboxes/schema.php:310
2213
  msgid "View your profile."
2214
  msgstr ""
2215
 
@@ -2226,196 +2240,212 @@ msgstr ""
2226
  msgid "Style"
2227
  msgstr ""
2228
 
2229
- #: inc/views/settings/metaboxes/sitemaps.php:65
2230
  msgid "Sitemap Integration Settings"
2231
  msgstr ""
2232
 
2233
- #: inc/views/settings/metaboxes/sitemaps.php:66
2234
  msgid "The sitemap is an XML file that lists indexable pages of your website along with optional metadata. It helps search engines find new and updated content quickly."
2235
  msgstr ""
2236
 
2237
  #. translators: %s = Learn more URL. Markdown!
2238
- #: inc/views/settings/metaboxes/sitemaps.php:72
2239
  msgid "The sitemap does not contribute to ranking; [it can only help with indexing](%s). Search engines process smaller, less complicated sitemaps quicker, which shortens the time required for indexing pages."
2240
  msgstr ""
2241
 
2242
- #: inc/views/settings/metaboxes/sitemaps.php:82
2243
  msgid "Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect."
2244
  msgstr ""
2245
 
2246
- #: inc/views/settings/metaboxes/sitemaps.php:85
2247
  msgid "Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect."
2248
  msgstr ""
2249
 
2250
- #: inc/views/settings/metaboxes/sitemaps.php:90
2251
  msgid "Sitemap Output"
2252
  msgstr ""
2253
 
2254
- #: inc/views/settings/metaboxes/sitemaps.php:95
2255
  msgid "Output optimized sitemap?"
2256
  msgstr ""
2257
 
2258
- #: inc/views/settings/metaboxes/sitemaps.php:97
2259
  msgid "This sitemap is processed quicker by search engines."
2260
  msgstr ""
2261
 
2262
- #: inc/views/settings/metaboxes/sitemaps.php:112
2263
  msgid "View the base sitemap."
2264
  msgstr ""
2265
 
2266
- #: inc/views/settings/metaboxes/sitemaps.php:124
2267
  msgid "View the sitemap index."
2268
  msgstr ""
2269
 
2270
  #. translators: %s = Documentation URL in markdown
2271
- #: inc/views/settings/metaboxes/sitemaps.php:139
2272
  msgid "A multilingual plugin has been detected, so your site may have multiple sitemaps. [Learn more](%s)."
2273
  msgstr ""
2274
 
2275
- #: inc/views/settings/metaboxes/sitemaps.php:153
2276
  msgid "Sitemap Query Limit"
2277
  msgstr ""
2278
 
2279
- #: inc/views/settings/metaboxes/sitemaps.php:157
2280
  msgid "This setting affects how many pages are requested from the database per query."
2281
  msgstr ""
2282
 
2283
- #: inc/views/settings/metaboxes/sitemaps.php:173
2284
  msgid "Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion."
2285
  msgstr ""
2286
 
2287
- #: inc/views/settings/metaboxes/sitemaps.php:180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2288
  msgid "Robots.txt Settings"
2289
  msgstr ""
2290
 
2291
- #: inc/views/settings/metaboxes/sitemaps.php:184
2292
  msgid "Note: A robots.txt file has been detected in the root folder of your website. This means these settings have no effect."
2293
  msgstr ""
2294
 
2295
- #: inc/views/settings/metaboxes/sitemaps.php:190
2296
  msgid "Note: robots.txt files can't be generated or used on subdirectory installations."
2297
  msgstr ""
2298
 
2299
- #: inc/views/settings/metaboxes/sitemaps.php:195
2300
  msgid "Note: You're using the plain permalink structure; so, no robots.txt file can be generated."
2301
  msgstr ""
2302
 
2303
  #. translators: 1 = Link to settings, Markdown. 2 = example input, also markdown! Preserve the Markdown as-is!
2304
- #: inc/views/settings/metaboxes/sitemaps.php:201
2305
  msgid "Change your [Permalink Settings](%1$s). Recommended structure: `%2$s`."
2306
  msgstr ""
2307
 
2308
- #: inc/views/settings/metaboxes/sitemaps.php:213
2309
  msgid "The robots.txt output is the first thing search engines look for before crawling your site. If you add the sitemap location in that output, then search engines may automatically access and index the sitemap."
2310
  msgstr ""
2311
 
2312
- #: inc/views/settings/metaboxes/sitemaps.php:214
2313
  msgid "If you do not add the sitemap location to the robots.txt output, you should notify search engines manually through webmaster-interfaces provided by the search engines."
2314
  msgstr ""
2315
 
2316
- #: inc/views/settings/metaboxes/sitemaps.php:219
2317
  msgid "Sitemap Hinting"
2318
  msgstr ""
2319
 
2320
- #: inc/views/settings/metaboxes/sitemaps.php:223
2321
  msgid "Add sitemap location to robots.txt?"
2322
  msgstr ""
2323
 
2324
- #: inc/views/settings/metaboxes/sitemaps.php:236
2325
  msgid "View the robots.txt output."
2326
  msgstr ""
2327
 
2328
- #: inc/views/settings/metaboxes/sitemaps.php:243
2329
  msgid "Timestamps Settings"
2330
  msgstr ""
2331
 
2332
- #: inc/views/settings/metaboxes/sitemaps.php:244
2333
  msgid "The modified time suggests to search engines where to look for content changes first."
2334
  msgstr ""
2335
 
2336
  #. translators: the backticks are Markdown! Preserve them as-is!
2337
- #: inc/views/settings/metaboxes/sitemaps.php:251
2338
  msgid "Add `<lastmod>` to the sitemap?"
2339
  msgstr ""
2340
 
2341
- #: inc/views/settings/metaboxes/sitemaps.php:261
2342
  msgid "Ping Settings"
2343
  msgstr ""
2344
 
2345
- #: inc/views/settings/metaboxes/sitemaps.php:262
2346
  msgid "Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible."
2347
  msgstr ""
2348
 
2349
- #: inc/views/settings/metaboxes/sitemaps.php:263
2350
  msgid "By default this will happen at most once an hour."
2351
  msgstr ""
2352
 
2353
- #: inc/views/settings/metaboxes/sitemaps.php:269
2354
  msgid "Use cron for pinging?"
2355
  msgstr ""
2356
 
2357
- #: inc/views/settings/metaboxes/sitemaps.php:271
2358
  msgid "This speeds up post and term saving processes, by offsetting pinging to a later time."
2359
  msgstr ""
2360
 
2361
- #: inc/views/settings/metaboxes/sitemaps.php:279
2362
  msgid "Prerender optimized sitemap before pinging via cron?"
2363
  msgstr ""
2364
 
2365
- #: inc/views/settings/metaboxes/sitemaps.php:281
2366
  msgid "This mitigates timeouts some search engines may experience when waiting for the sitemap to render. Transient caching for the sitemap must be enabled for this to work."
2367
  msgstr ""
2368
 
2369
- #: inc/views/settings/metaboxes/sitemaps.php:285
2370
  msgid "Only enable prerendering when generating the sitemap takes over 60 seconds."
2371
  msgstr ""
2372
 
2373
- #: inc/views/settings/metaboxes/sitemaps.php:295
2374
  msgid "Notify Search Engines"
2375
  msgstr ""
2376
 
2377
  #. translators: %s = Google
2378
- #: inc/views/settings/metaboxes/sitemaps.php:306
2379
  msgid "Notify %s about sitemap changes?"
2380
  msgstr ""
2381
 
2382
- #: inc/views/settings/metaboxes/sitemaps.php:317
2383
  msgid "Optimized Sitemap Styling Settings"
2384
  msgstr ""
2385
 
2386
- #: inc/views/settings/metaboxes/sitemaps.php:318
2387
  msgid "You can style the optimized sitemap to give it a more personal look for your visitors. Search engines do not use these styles."
2388
  msgstr ""
2389
 
2390
- #: inc/views/settings/metaboxes/sitemaps.php:319
2391
  msgid "Note: Changes may not appear to have an effect directly because the stylesheet is cached in the browser for 30 minutes."
2392
  msgstr ""
2393
 
2394
- #: inc/views/settings/metaboxes/sitemaps.php:323
2395
  msgid "Enable Styling"
2396
  msgstr ""
2397
 
2398
- #: inc/views/settings/metaboxes/sitemaps.php:328
2399
  msgid "Style sitemap?"
2400
  msgstr ""
2401
 
2402
- #: inc/views/settings/metaboxes/sitemaps.php:328
2403
  msgid "This makes the sitemap more readable for humans."
2404
  msgstr ""
2405
 
2406
- #: inc/views/settings/metaboxes/sitemaps.php:344
2407
  msgid "Sitemap Header Background Color"
2408
  msgstr ""
2409
 
2410
- #: inc/views/settings/metaboxes/sitemaps.php:353
2411
  msgid "Sitemap Title and Lines Color"
2412
  msgstr ""
2413
 
2414
- #: inc/views/settings/metaboxes/sitemaps.php:362
2415
  msgid "Header Title Logo"
2416
  msgstr ""
2417
 
2418
- #: inc/views/settings/metaboxes/sitemaps.php:367
2419
  msgid "Show logo next to sitemap header title?"
2420
  msgstr ""
2421
 
@@ -2694,114 +2724,113 @@ msgid "Example Category"
2694
  msgstr ""
2695
 
2696
  #: inc/views/settings/metaboxes/title.php:51
2697
- #: inc/views/settings/metaboxes/title.php:203
2698
- msgid "Automated Title Settings"
2699
- msgstr ""
2700
-
2701
- #: inc/views/settings/metaboxes/title.php:52
2702
  msgid "The page title is prominently shown within the browser tab as well as within the search engine results pages."
2703
  msgstr ""
2704
 
2705
- #: inc/views/settings/metaboxes/title.php:58
2706
  msgid "Example Page Title Output"
2707
  msgstr ""
2708
 
2709
- #: inc/views/settings/metaboxes/title.php:75
2710
  msgid "Example Archive Title Output"
2711
  msgstr ""
2712
 
2713
  #. translators: %s = title-tag
2714
- #: inc/views/settings/metaboxes/title.php:113
2715
  msgid "Theme %s Support Missing"
2716
  msgstr ""
2717
 
2718
  #. translators: 1: Extension name, 2: Extension link. Markdown!
2719
- #: inc/views/settings/metaboxes/title.php:121
2720
  msgid "The current theme doesn't support a feature that allows predictable output of titles. Consider installing [%1$s](%2$s) when you notice the title output in the browser-tab isn't as you have configured."
2721
  msgstr ""
2722
 
2723
- #: inc/views/settings/metaboxes/title.php:154
2724
  msgid "Prefixes"
2725
  msgstr ""
2726
 
2727
- #: inc/views/settings/metaboxes/title.php:177
2728
  msgid "Title Separator"
2729
  msgstr ""
2730
 
2731
- #: inc/views/settings/metaboxes/title.php:179
2732
  msgid "If the title consists of multiple parts, then the separator will go in-between them."
2733
  msgstr ""
2734
 
2735
  #: inc/views/settings/metaboxes/title.php:204
2736
- msgid "A title is generated for every page."
2737
  msgstr ""
2738
 
2739
  #: inc/views/settings/metaboxes/title.php:205
 
 
 
 
2740
  msgid "Some titles may have HTML tags inserted by the author for styling."
2741
  msgstr ""
2742
 
2743
  #. translators: %s = HTML tag example
2744
- #: inc/views/settings/metaboxes/title.php:210
2745
  msgid "This strips HTML tags, like %s, from the title. Disable this option to display generated HTML tags as plain text in meta titles."
2746
  msgstr ""
2747
 
2748
- #: inc/views/settings/metaboxes/title.php:219
2749
  msgid "Strip HTML tags from generated titles?"
2750
  msgstr ""
2751
 
2752
- #: inc/views/settings/metaboxes/title.php:225
2753
  msgid "Tip: It is a bad practice to style page titles with HTML as inconsistent behavior might occur."
2754
  msgstr ""
2755
 
2756
- #: inc/views/settings/metaboxes/title.php:232
2757
  msgid "Site Title"
2758
  msgstr ""
2759
 
2760
- #: inc/views/settings/metaboxes/title.php:239
2761
  msgid "This option does not affect titles displayed directly on your website."
2762
  msgstr ""
2763
 
2764
- #: inc/views/settings/metaboxes/title.php:247
2765
  msgid "This option does not affect the homepage; it uses a different one."
2766
  msgstr ""
2767
 
2768
- #: inc/views/settings/metaboxes/title.php:250
2769
  msgid "Site Title Location"
2770
  msgstr ""
2771
 
2772
- #: inc/views/settings/metaboxes/title.php:278
2773
  msgid "Site Title Removal"
2774
  msgstr ""
2775
 
2776
- #: inc/views/settings/metaboxes/title.php:282
2777
  msgid "Always brand your titles. Search engines may ignore your titles with this feature enabled."
2778
  msgstr ""
2779
 
2780
- #: inc/views/settings/metaboxes/title.php:290
2781
  msgid "Remove site title from the title?"
2782
  msgstr ""
2783
 
2784
- #: inc/views/settings/metaboxes/title.php:298
2785
  msgid "Note: Only use this option if you are aware of its SEO effects."
2786
  msgstr ""
2787
 
2788
- #: inc/views/settings/metaboxes/title.php:304
2789
  msgid "Title Prefix Options"
2790
  msgstr ""
2791
 
2792
- #: inc/views/settings/metaboxes/title.php:305
2793
  msgid "For archives, a descriptive prefix may be added to generated titles."
2794
  msgstr ""
2795
 
2796
- #: inc/views/settings/metaboxes/title.php:310
2797
  msgid "Archive Title Prefixes"
2798
  msgstr ""
2799
 
2800
- #: inc/views/settings/metaboxes/title.php:314
2801
  msgid "The prefix helps visitors and search engines determine what kind of page they're visiting."
2802
  msgstr ""
2803
 
2804
- #: inc/views/settings/metaboxes/title.php:321
2805
  msgid "Remove term type prefixes from generated archive titles?"
2806
  msgstr ""
2807
 
@@ -2858,15 +2887,15 @@ msgstr ""
2858
  msgid "Verifying your website has no SEO value whatsoever. But you might gain added benefits such as search ranking insights to help you improve your website's content."
2859
  msgstr ""
2860
 
2861
- #: inc/views/settings/wrap.php:15
2862
- msgid "Are you sure you want to reset all SEO settings to their defaults?"
2863
  msgstr ""
2864
 
2865
- #: inc/views/settings/wrap.php:18
2866
- msgid "Save Settings"
2867
  msgstr ""
2868
 
2869
- #: inc/views/settings/wrap.php:25
2870
  msgid "Reset Settings"
2871
  msgstr ""
2872
 
1
+ # Copyright (C) 2022 The SEO Framework Team
2
  # This file is distributed under the same license as the The SEO Framework plugin.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: The SEO Framework 4.2.7\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/trunk\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2022-11-09T16:55:21+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: autodescription\n"
32
  msgstr ""
33
 
34
  #. translators: %1$s = New, lower version number, surrounded in markdown-backticks. %2$s = Old, higher version number, surrounded in markdown-backticks.
35
+ #: bootstrap/upgrade.php:367
36
  msgid "Your website has been downgraded successfully to use The SEO Framework at database version `%1$s` from `%2$s`."
37
  msgstr ""
38
 
39
  #. translators: %s = Version number, surrounded in markdown-backticks.
40
+ #: bootstrap/upgrade.php:418
41
  msgid "Thank you for updating The SEO Framework! Your website has been upgraded successfully to use The SEO Framework at database version `%s`."
42
  msgstr ""
43
 
44
+ #: bootstrap/upgrade.php:446
45
  msgid "The SEO Framework automatically optimizes your website for search engines and social media."
46
  msgstr ""
47
 
48
  #. translators: %s = Link, markdown.
49
+ #: bootstrap/upgrade.php:450
50
  msgid "To take full advantage of all SEO features, please follow our [5-minute setup guide](%s)."
51
  msgstr ""
52
 
53
+ #. translators: 1: SEO plugin name(s), 2: link to guide, in Markdown!
54
+ #: bootstrap/upgrade.php:518
55
+ msgid "The SEO Framework detected metadata from %1$s. Whenever you are set, read our [migration guide](%2$s)."
56
+ msgstr ""
57
+
58
+ #: bootstrap/upgrade.php:652
59
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
60
  msgstr ""
61
 
62
+ #: bootstrap/upgrade.php:677
63
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
64
  msgstr ""
65
 
66
+ #: bootstrap/upgrade.php:769
67
  msgid "A cronjob is now used to ping search engines, and it alerts them to changes in your sitemap."
68
  msgstr ""
69
 
70
+ #: bootstrap/upgrade.php:782
71
  msgid "The positions in the \"Meta Title Additions Location\" setting for the homepage have been reversed, left to right, but the output has not been changed. If you must downgrade for some reason, remember to switch the location back again."
72
  msgstr ""
73
 
79
  msgid "No Archive"
80
  msgstr ""
81
 
82
+ #: inc/classes/admin-init.class.php:324
83
  msgid "There's no content."
84
  msgstr ""
85
 
86
+ #: inc/classes/admin-init.class.php:325
87
  msgid "It's too short and it should have more information."
88
  msgstr ""
89
 
90
+ #: inc/classes/admin-init.class.php:326
91
  msgid "It's short and it could have more information."
92
  msgstr ""
93
 
94
+ #: inc/classes/admin-init.class.php:327
95
  msgid "It's long and it might get truncated in search."
96
  msgstr ""
97
 
98
+ #: inc/classes/admin-init.class.php:328
99
  msgid "It's too long and it will get truncated in search."
100
  msgstr ""
101
 
102
+ #: inc/classes/admin-init.class.php:329
103
  msgid "Length is good."
104
  msgstr ""
105
 
106
+ #: inc/classes/admin-init.class.php:332
107
  msgctxt "The string is empty"
108
  msgid "Empty"
109
  msgstr ""
110
 
111
+ #: inc/classes/admin-init.class.php:333
112
  msgid "Far too short"
113
  msgstr ""
114
 
115
+ #: inc/classes/admin-init.class.php:334
116
  msgid "Too short"
117
  msgstr ""
118
 
119
+ #: inc/classes/admin-init.class.php:335
120
  msgid "Too long"
121
  msgstr ""
122
 
123
+ #: inc/classes/admin-init.class.php:336
124
  msgid "Far too long"
125
  msgstr ""
126
 
127
+ #: inc/classes/admin-init.class.php:337
128
  msgid "Good"
129
  msgstr ""
130
 
131
+ #: inc/classes/admin-init.class.php:340
132
  msgctxt "The string is empty"
133
  msgid "Empty."
134
  msgstr ""
135
 
136
+ #: inc/classes/admin-init.class.php:341
137
  msgid "Far too short."
138
  msgstr ""
139
 
140
+ #: inc/classes/admin-init.class.php:342
141
  msgid "Too short."
142
  msgstr ""
143
 
144
+ #: inc/classes/admin-init.class.php:343
145
  msgid "Too long."
146
  msgstr ""
147
 
148
+ #: inc/classes/admin-init.class.php:344
149
  msgid "Far too long."
150
  msgstr ""
151
 
152
+ #: inc/classes/admin-init.class.php:345
153
  msgid "Good."
154
  msgstr ""
155
 
156
  #. translators: %s = Redirect URL markdown
157
+ #: inc/classes/admin-init.class.php:417
158
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
159
  msgstr ""
160
 
186
  msgid "Multiple SEO tools have been detected. You should only use one."
187
  msgstr ""
188
 
189
+ #: inc/classes/bridges/feed.class.php:151
190
  msgctxt "The content source"
191
  msgid "Source"
192
  msgstr ""
196
  msgstr ""
197
 
198
  #: inc/classes/bridges/plugintable.class.php:64
199
+ #: inc/views/settings/wrap.php:25
200
+ #: inc/views/settings/wrap.php:31
201
  msgctxt "Plugin extensions"
202
  msgid "Extensions"
203
  msgstr ""
238
  msgid "%s SEO Settings"
239
  msgstr ""
240
 
241
+ #: inc/classes/bridges/scripts.class.php:332
242
  msgid "The changes you made will be lost if you navigate away from this page."
243
  msgstr ""
244
 
245
+ #: inc/classes/bridges/scripts.class.php:613
246
  #: inc/classes/interpreters/form.class.php:230
247
  msgid "Select Image"
248
  msgstr ""
249
 
250
+ #: inc/classes/bridges/scripts.class.php:615
251
  msgid "Change Image"
252
  msgstr ""
253
 
254
+ #: inc/classes/bridges/scripts.class.php:616
255
  msgid "Remove Image"
256
  msgstr ""
257
 
258
+ #: inc/classes/bridges/scripts.class.php:618
259
  msgctxt "Frame title"
260
  msgid "Select Social Image"
261
  msgstr ""
262
 
263
+ #: inc/classes/bridges/scripts.class.php:619
264
+ #: inc/classes/bridges/scripts.class.php:628
265
  msgid "Use this image"
266
  msgstr ""
267
 
268
+ #: inc/classes/bridges/scripts.class.php:622
269
  #: inc/classes/internal/deprecated.class.php:414
270
+ #: inc/views/settings/metaboxes/schema.php:196
271
+ #: inc/views/settings/metaboxes/sitemaps.php:408
272
  msgid "Select Logo"
273
  msgstr ""
274
 
275
+ #: inc/classes/bridges/scripts.class.php:624
276
  msgid "Change Logo"
277
  msgstr ""
278
 
279
+ #: inc/classes/bridges/scripts.class.php:625
280
  msgid "Remove Logo"
281
  msgstr ""
282
 
283
+ #: inc/classes/bridges/scripts.class.php:627
284
  msgctxt "Frame title"
285
  msgid "Select Logo"
286
  msgstr ""
287
 
288
  #. translators: %s = term name
289
+ #: inc/classes/bridges/scripts.class.php:765
290
  msgid "Select Primary %s"
291
  msgstr ""
292
 
293
  #. translators: %s = term name
294
+ #: inc/classes/bridges/scripts.class.php:770
295
  msgid "Make primary %s"
296
  msgstr ""
297
 
298
  #. translators: %s = term name
299
+ #: inc/classes/bridges/scripts.class.php:772
300
  msgid "Primary %s"
301
  msgstr ""
302
 
303
  #. translators: Pixel counter. 1: number (value), 2: number (guideline)
304
+ #: inc/classes/bridges/scripts.class.php:877
305
  msgid "%1$d out of %2$d pixels are used."
306
  msgstr ""
307
 
577
  msgstr ""
578
 
579
  #. translators: 1: Word found, 2: Occurrences
580
+ #: inc/classes/builders/seobar/page.class.php:496
581
  #: inc/classes/builders/seobar/term.class.php:464
582
  msgid "&#8220;%1$s&#8221; is used %2$d times."
583
  msgstr ""
584
 
585
+ #: inc/classes/builders/seobar/page.class.php:575
586
+ #: inc/classes/builders/seobar/page.class.php:732
587
+ #: inc/classes/builders/seobar/page.class.php:863
588
  #: inc/classes/builders/seobar/term.class.php:543
589
  #: inc/classes/builders/seobar/term.class.php:694
590
  #: inc/classes/builders/seobar/term.class.php:811
591
  msgid "The robots.txt file is nonstandard, and may still direct search engines differently."
592
  msgstr ""
593
 
594
+ #: inc/classes/builders/seobar/page.class.php:576
595
+ #: inc/classes/builders/seobar/page.class.php:733
596
+ #: inc/classes/builders/seobar/page.class.php:864
597
  #: inc/classes/builders/seobar/term.class.php:544
598
  #: inc/classes/builders/seobar/term.class.php:695
599
  #: inc/classes/builders/seobar/term.class.php:812
600
  msgid "WordPress discourages crawling via the Reading Settings."
601
  msgstr ""
602
 
603
+ #: inc/classes/builders/seobar/page.class.php:577
604
  #: inc/classes/builders/seobar/term.class.php:545
605
  msgid "Indexing is discouraged for the whole site at the SEO Settings screen."
606
  msgstr ""
607
 
608
+ #: inc/classes/builders/seobar/page.class.php:578
609
  msgid "Indexing is discouraged for this post type at the SEO Settings screen."
610
  msgstr ""
611
 
612
+ #: inc/classes/builders/seobar/page.class.php:579
613
  msgid "The page is protected, so indexing is discouraged."
614
  msgstr ""
615
 
616
+ #: inc/classes/builders/seobar/page.class.php:580
617
  msgid "The page SEO meta input overrides the indexing state."
618
  msgstr ""
619
 
620
+ #: inc/classes/builders/seobar/page.class.php:581
621
  #: inc/classes/builders/seobar/term.class.php:551
622
  msgid "A custom canonical URL is set that points to another page."
623
  msgstr ""
624
 
625
+ #: inc/classes/builders/seobar/page.class.php:584
626
+ #: inc/classes/builders/seobar/page.class.php:740
627
+ #: inc/classes/builders/seobar/page.class.php:871
628
  #: inc/classes/builders/seobar/term.class.php:554
629
  #: inc/classes/builders/seobar/term.class.php:703
630
  #: inc/classes/builders/seobar/term.class.php:820
631
  msgid "WordPress overrides the robots directive."
632
  msgstr ""
633
 
634
+ #: inc/classes/builders/seobar/page.class.php:585
635
  msgid "The page is protected."
636
  msgstr ""
637
 
638
+ #: inc/classes/builders/seobar/page.class.php:586
639
+ #: inc/classes/builders/seobar/page.class.php:741
640
+ #: inc/classes/builders/seobar/page.class.php:872
641
  msgid "The page is not published."
642
  msgstr ""
643
 
644
+ #: inc/classes/builders/seobar/page.class.php:587
645
  #: inc/classes/builders/seobar/term.class.php:557
646
  msgid "The canonical URL points to another page."
647
  msgstr ""
648
 
649
+ #: inc/classes/builders/seobar/page.class.php:591
650
+ #: inc/classes/builders/seobar/page.class.php:600
651
+ #: inc/classes/builders/seobar/page.class.php:609
652
  #: inc/classes/builders/seobar/term.class.php:561
653
  #: inc/classes/builders/seobar/term.class.php:570
654
  msgctxt "Indexing"
655
  msgid "I"
656
  msgstr ""
657
 
658
+ #: inc/classes/builders/seobar/page.class.php:592
659
+ #: inc/classes/builders/seobar/page.class.php:601
660
+ #: inc/classes/builders/seobar/page.class.php:610
661
  #: inc/classes/builders/seobar/term.class.php:562
662
  #: inc/classes/builders/seobar/term.class.php:571
663
  #: inc/views/edit/seo-settings-singular.php:241
670
  msgid "Indexing"
671
  msgstr ""
672
 
673
+ #: inc/classes/builders/seobar/page.class.php:594
674
  msgid "Page may be indexed."
675
  msgstr ""
676
 
677
+ #: inc/classes/builders/seobar/page.class.php:596
678
  #: inc/classes/builders/seobar/term.class.php:566
679
  msgid "The robots meta tag allows indexing."
680
  msgstr ""
681
 
682
+ #: inc/classes/builders/seobar/page.class.php:603
683
  msgid "Page may not be indexed."
684
  msgstr ""
685
 
686
+ #: inc/classes/builders/seobar/page.class.php:605
687
  #: inc/classes/builders/seobar/term.class.php:575
688
  msgid "The robots meta tag does not allow indexing."
689
  msgstr ""
690
 
 
 
 
 
 
 
691
  #: inc/classes/builders/seobar/page.class.php:612
692
  #: inc/classes/builders/seobar/page.class.php:766
693
  #: inc/classes/builders/seobar/page.class.php:897
694
+ msgid "Page is invisible."
695
+ msgstr ""
696
+
697
+ #: inc/classes/builders/seobar/page.class.php:614
698
+ #: inc/classes/builders/seobar/page.class.php:768
699
+ #: inc/classes/builders/seobar/page.class.php:899
700
  msgid "This page isn't published and can't be found publicly."
701
  msgstr ""
702
 
703
+ #: inc/classes/builders/seobar/page.class.php:669
704
  msgid "Indexing is discouraged for the homepage at the SEO Settings screen."
705
  msgstr ""
706
 
707
+ #: inc/classes/builders/seobar/page.class.php:734
708
  #: inc/classes/builders/seobar/term.class.php:696
709
  msgid "Link following is discouraged for the whole site at the SEO Settings screen."
710
  msgstr ""
711
 
712
+ #: inc/classes/builders/seobar/page.class.php:735
713
  msgid "Link following is discouraged for this post type at the SEO Settings screen."
714
  msgstr ""
715
 
716
+ #: inc/classes/builders/seobar/page.class.php:736
717
  msgid "The page SEO meta input overrides the link following state."
718
  msgstr ""
719
 
720
+ #: inc/classes/builders/seobar/page.class.php:737
721
  msgid "The page may not be indexed, this may also discourage link following."
722
  msgstr ""
723
 
724
+ #: inc/classes/builders/seobar/page.class.php:745
725
+ #: inc/classes/builders/seobar/page.class.php:754
726
+ #: inc/classes/builders/seobar/page.class.php:763
727
  #: inc/classes/builders/seobar/term.class.php:707
728
  #: inc/classes/builders/seobar/term.class.php:716
729
  msgctxt "Following"
730
  msgid "F"
731
  msgstr ""
732
 
733
+ #: inc/classes/builders/seobar/page.class.php:746
734
+ #: inc/classes/builders/seobar/page.class.php:755
735
+ #: inc/classes/builders/seobar/page.class.php:764
736
  #: inc/classes/builders/seobar/term.class.php:708
737
  #: inc/classes/builders/seobar/term.class.php:717
738
  #: inc/views/list/quick-term.php:29
740
  msgid "Following"
741
  msgstr ""
742
 
743
+ #: inc/classes/builders/seobar/page.class.php:748
744
  msgid "Page links may be followed."
745
  msgstr ""
746
 
747
+ #: inc/classes/builders/seobar/page.class.php:750
748
  #: inc/classes/builders/seobar/term.class.php:712
749
  msgid "The robots meta tag allows link following."
750
  msgstr ""
751
 
752
+ #: inc/classes/builders/seobar/page.class.php:757
753
  msgid "Page links may not be followed."
754
  msgstr ""
755
 
756
+ #: inc/classes/builders/seobar/page.class.php:759
757
  #: inc/classes/builders/seobar/term.class.php:721
758
  msgid "The robots meta tag does not allow link following."
759
  msgstr ""
760
 
761
+ #: inc/classes/builders/seobar/page.class.php:811
762
  msgid "Link following is discouraged for the homepage at the SEO Settings screen."
763
  msgstr ""
764
 
765
+ #: inc/classes/builders/seobar/page.class.php:865
766
  #: inc/classes/builders/seobar/term.class.php:813
767
  msgid "Archiving is discouraged for the whole site at the SEO Settings screen."
768
  msgstr ""
769
 
770
+ #: inc/classes/builders/seobar/page.class.php:866
771
  msgid "Archiving is discouraged for this post type at the SEO Settings screen."
772
  msgstr ""
773
 
774
+ #: inc/classes/builders/seobar/page.class.php:867
775
  msgid "The page SEO meta input overrides the archiving state."
776
  msgstr ""
777
 
778
+ #: inc/classes/builders/seobar/page.class.php:868
779
  msgid "The page may not be indexed, this may also discourage archiving."
780
  msgstr ""
781
 
782
+ #: inc/classes/builders/seobar/page.class.php:876
783
+ #: inc/classes/builders/seobar/page.class.php:885
784
+ #: inc/classes/builders/seobar/page.class.php:894
785
  #: inc/classes/builders/seobar/term.class.php:824
786
  #: inc/classes/builders/seobar/term.class.php:833
787
  msgctxt "Archiving"
788
  msgid "A"
789
  msgstr ""
790
 
791
+ #: inc/classes/builders/seobar/page.class.php:877
792
+ #: inc/classes/builders/seobar/page.class.php:886
793
+ #: inc/classes/builders/seobar/page.class.php:895
794
  #: inc/classes/builders/seobar/term.class.php:825
795
  #: inc/classes/builders/seobar/term.class.php:834
796
  #: inc/views/edit/seo-settings-singular.php:257
803
  msgid "Archiving"
804
  msgstr ""
805
 
806
+ #: inc/classes/builders/seobar/page.class.php:879
807
  msgid "Page may be archived."
808
  msgstr ""
809
 
810
+ #: inc/classes/builders/seobar/page.class.php:881
811
  #: inc/classes/builders/seobar/term.class.php:829
812
  msgid "The robots meta tag allows archiving."
813
  msgstr ""
814
 
815
+ #: inc/classes/builders/seobar/page.class.php:888
816
  msgid "Page may not be archived."
817
  msgstr ""
818
 
819
+ #: inc/classes/builders/seobar/page.class.php:890
820
  #: inc/classes/builders/seobar/term.class.php:838
821
  msgid "The robots meta tag does not allow archiving."
822
  msgstr ""
823
 
824
+ #: inc/classes/builders/seobar/page.class.php:942
825
  msgid "Archiving is discouraged for the homepage at the SEO Settings screen."
826
  msgstr ""
827
 
828
+ #: inc/classes/builders/seobar/page.class.php:993
829
+ #: inc/classes/builders/seobar/page.class.php:1014
830
  #: inc/classes/builders/seobar/term.class.php:925
831
  #: inc/classes/builders/seobar/term.class.php:941
832
  msgctxt "Redirect"
833
  msgid "R"
834
  msgstr ""
835
 
836
+ #: inc/classes/builders/seobar/page.class.php:994
837
+ #: inc/classes/builders/seobar/page.class.php:1015
838
  #: inc/classes/builders/seobar/term.class.php:926
839
  #: inc/classes/builders/seobar/term.class.php:942
840
  msgid "Redirection"
841
  msgstr ""
842
 
843
+ #: inc/classes/builders/seobar/page.class.php:996
844
  msgid "Page does not redirect visitors."
845
  msgstr ""
846
 
847
+ #: inc/classes/builders/seobar/page.class.php:998
848
  msgid "Visitors and crawlers may view this page."
849
  msgstr ""
850
 
851
+ #: inc/classes/builders/seobar/page.class.php:1007
852
  msgid "Visitors and crawlers may view this page once published."
853
  msgstr ""
854
 
855
+ #: inc/classes/builders/seobar/page.class.php:1017
856
  msgid "Page redirects visitors."
857
  msgstr ""
858
 
859
+ #: inc/classes/builders/seobar/page.class.php:1019
860
  #: inc/classes/builders/seobar/term.class.php:946
861
  msgid "All visitors and crawlers are being redirected. So, no other SEO enhancements are effective."
862
  msgstr ""
994
  msgstr ""
995
 
996
  #. translators: %s = timestamp
997
+ #: inc/classes/builders/sitemap/base.class.php:187
998
  msgid "Sitemap is prerendered on %s"
999
  msgstr ""
1000
 
1001
  #. translators: %s = timestamp
1002
+ #: inc/classes/builders/sitemap/base.class.php:189
1003
  msgid "Sitemap is generated on %s"
1004
  msgstr ""
1005
 
1006
  #. translators: %s = Blog page title. Front-end output.
1007
+ #: inc/classes/generate-description.class.php:783
1008
  msgid "Latest posts: %s"
1009
  msgstr ""
1010
 
1078
  msgstr ""
1079
 
1080
  #. translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer
1081
+ #: inc/classes/render.class.php:1269
1082
  msgid "%1$s %2$s"
1083
  msgstr ""
1084
 
1085
+ #: inc/classes/render.class.php:1277
1086
  msgid "by Sybre Waaijer"
1087
  msgstr ""
1088
 
1096
  #: inc/views/settings/metaboxes/robots.php:61
1097
  #: inc/views/settings/metaboxes/sitemaps.php:23
1098
  #: inc/views/settings/metaboxes/social.php:23
1099
+ #: inc/views/settings/metaboxes/title.php:139
1100
  msgid "General"
1101
  msgstr ""
1102
 
1160
 
1161
  #: inc/views/edit/seo-settings-singular.php:191
1162
  #: inc/views/edit/seo-settings-tt.php:173
 
1163
  #: inc/views/settings/metaboxes/homepage.php:137
1164
  #: inc/views/settings/metaboxes/post-type-archive.php:225
1165
  msgid "The meta description can be used to determine the text used under the title on search engine results pages."
1348
  msgid "This may be shown publicly."
1349
  msgstr ""
1350
 
1351
+ #: inc/views/settings/metaboxes/description.php:18
1352
+ msgid "The meta description suggests text to be used under the title on search engine results pages."
1353
  msgstr ""
1354
 
1355
+ #: inc/views/settings/metaboxes/description.php:24
1356
  msgid "Automated Description Settings"
1357
  msgstr ""
1358
 
1359
  #: inc/views/settings/metaboxes/description.php:27
1360
+ msgid "Learn how this feature works."
1361
  msgstr ""
1362
 
1363
+ #: inc/views/settings/metaboxes/description.php:34
1364
+ msgid "Automatically generate descriptions?"
1365
  msgstr ""
1366
 
1367
+ #: inc/views/settings/metaboxes/description.php:40
1368
+ msgid "Open Graph and Twitter require descriptions. So, it's best to leave description generation enabled."
1369
  msgstr ""
1370
 
1371
+ #: inc/views/settings/metaboxes/description.php:46
1372
+ msgid "Advanced Generation Settings"
1373
+ msgstr ""
1374
+
1375
+ #: inc/views/settings/metaboxes/description.php:49
1376
+ msgid "The HTML content of your pages can be used to generate descriptions. The generator processes this HTML in passing layers to understand the layout. If the HTML is complex, not all layers may be processed, and you might find spaces missing between sentences. Increasing the maximum number of passes reduces the chance of this happening, but at the cost of performance."
1377
+ msgstr ""
1378
+
1379
+ #: inc/views/settings/metaboxes/description.php:59
1380
+ msgid "Fast (max. 2 passes)"
1381
+ msgstr ""
1382
+
1383
+ #: inc/views/settings/metaboxes/description.php:60
1384
+ msgid "Accurate (max. 6 passes)"
1385
+ msgstr ""
1386
+
1387
+ #: inc/views/settings/metaboxes/description.php:61
1388
+ msgid "Thorough (max. 12 passes)"
1389
+ msgstr ""
1390
+
1391
+ #: inc/views/settings/metaboxes/description.php:84
1392
+ msgid "HTML parsing method:"
1393
+ msgstr ""
1394
+
1395
+ #: inc/views/settings/metaboxes/description.php:96
1396
+ msgid "Learn how this works."
1397
  msgstr ""
1398
 
1399
  #: inc/views/settings/metaboxes/feed.php:17
1572
  msgstr ""
1573
 
1574
  #: inc/views/settings/metaboxes/general.php:231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1575
  msgid "Canonical URL Settings"
1576
  msgstr ""
1577
 
1578
+ #: inc/views/settings/metaboxes/general.php:232
1579
  msgid "The canonical URL meta tag urges search engines to go to the outputted URL."
1580
  msgstr ""
1581
 
1582
+ #: inc/views/settings/metaboxes/general.php:233
1583
  msgid "If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL."
1584
  msgstr ""
1585
 
1586
+ #: inc/views/settings/metaboxes/general.php:237
1587
  msgid "Scheme Settings"
1588
  msgstr ""
1589
 
1590
+ #: inc/views/settings/metaboxes/general.php:238
1591
  msgid "If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines."
1592
  msgstr ""
1593
 
1594
+ #: inc/views/settings/metaboxes/general.php:240
1595
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1596
  msgid "Preferred canonical URL scheme:"
1597
  msgstr ""
1598
 
1599
  #. translators: %s = HTTP or HTTPS
1600
+ #: inc/views/settings/metaboxes/general.php:248
1601
  msgid "Detect automatically (%s)"
1602
  msgstr ""
1603
 
1604
+ #: inc/views/settings/metaboxes/general.php:270
1605
  msgid "Link Relationship Settings"
1606
  msgstr ""
1607
 
1608
+ #: inc/views/settings/metaboxes/general.php:271
1609
  msgid "Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results."
1610
  msgstr ""
1611
 
1612
+ #: inc/views/settings/metaboxes/general.php:272
1613
  msgid "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues."
1614
  msgstr ""
1615
 
1616
  #. translators: the backticks are Markdown! Preserve them as-is!
1617
+ #: inc/views/settings/metaboxes/general.php:278
1618
  msgid "Add `rel` link tags to posts and pages?"
1619
  msgstr ""
1620
 
1621
  #. translators: the backticks are Markdown! Preserve them as-is!
1622
+ #: inc/views/settings/metaboxes/general.php:288
1623
  msgid "Add `rel` link tags to archives?"
1624
  msgstr ""
1625
 
1626
  #. translators: the backticks are Markdown! Preserve them as-is!
1627
+ #: inc/views/settings/metaboxes/general.php:298
1628
  msgid "Add `rel` link tags to the homepage?"
1629
  msgstr ""
1630
 
1631
+ #: inc/views/settings/metaboxes/general.php:311
1632
  msgid "Timestamp Settings"
1633
  msgstr ""
1634
 
1635
+ #: inc/views/settings/metaboxes/general.php:312
1636
  msgid "Timestamps help indicate when a page has been published and modified."
1637
  msgstr ""
1638
 
1639
+ #: inc/views/settings/metaboxes/general.php:317
1640
  msgid "Timestamp Format Settings"
1641
  msgstr ""
1642
 
1643
+ #: inc/views/settings/metaboxes/general.php:318
1644
  msgid "This setting determines how specific the timestamp is."
1645
  msgstr ""
1646
 
1647
+ #: inc/views/settings/metaboxes/general.php:327
1648
  msgid "This outputs the complete date."
1649
  msgstr ""
1650
 
1651
+ #: inc/views/settings/metaboxes/general.php:338
1652
  msgid "This outputs the complete date including hours, minutes, and timezone."
1653
  msgstr ""
1654
 
1655
+ #: inc/views/settings/metaboxes/general.php:349
1656
  msgid "Exclusion Settings"
1657
  msgstr ""
1658
 
1659
+ #: inc/views/settings/metaboxes/general.php:350
1660
  msgid "When checked, these options will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types and taxonomies. This will allow search engines to crawl the post type and taxonomies without advanced restrictions or directions."
1661
  msgstr ""
1662
 
1663
  #. translators: backticks are code wraps. Markdown!
1664
+ #: inc/views/settings/metaboxes/general.php:354
1665
  msgid "These options should not need changing when post types and taxonomies are registered correctly. When they aren't, consider applying `noindex` to purge them from search engines, instead."
1666
  msgstr ""
1667
 
1668
+ #: inc/views/settings/metaboxes/general.php:358
1669
  msgid "Default post types and taxonomies can not be excluded."
1670
  msgstr ""
1671
 
1672
+ #: inc/views/settings/metaboxes/general.php:363
1673
  msgid "Post Type Exclusions"
1674
  msgstr ""
1675
 
1676
+ #: inc/views/settings/metaboxes/general.php:364
1677
  msgid "Select post types which should be excluded."
1678
  msgstr ""
1679
 
1680
+ #: inc/views/settings/metaboxes/general.php:365
1681
  #: inc/views/settings/metaboxes/robots.php:306
1682
  msgid "These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect."
1683
  msgstr ""
1684
 
1685
+ #: inc/views/settings/metaboxes/general.php:394
1686
  msgid "Taxonomy Exclusions"
1687
  msgstr ""
1688
 
1689
+ #: inc/views/settings/metaboxes/general.php:395
1690
  msgid "Select taxonomies which should be excluded."
1691
  msgstr ""
1692
 
1693
+ #: inc/views/settings/metaboxes/general.php:396
1694
  msgid "When taxonomies have all their bound post types excluded, they will inherit their exclusion status."
1695
  msgstr ""
1696
 
1699
  msgstr ""
1700
 
1701
  #: inc/views/settings/metaboxes/homepage.php:36
1702
+ #: inc/views/settings/metaboxes/title.php:144
1703
  msgid "Additions"
1704
  msgstr ""
1705
 
1742
  msgstr ""
1743
 
1744
  #: inc/views/settings/metaboxes/homepage.php:242
1745
+ #: inc/views/settings/metaboxes/title.php:256
1746
  msgid "Left:"
1747
  msgstr ""
1748
 
1749
  #: inc/views/settings/metaboxes/homepage.php:252
1750
+ #: inc/views/settings/metaboxes/title.php:266
1751
  msgid "Right:"
1752
  msgstr ""
1753
 
2083
  #: inc/views/settings/metaboxes/schema.php:64
2084
  #: inc/views/settings/metaboxes/schema.php:84
2085
  #: inc/views/settings/metaboxes/schema.php:103
2086
+ #: inc/views/settings/metaboxes/schema.php:157
2087
  msgid "Learn how this data is used."
2088
  msgstr ""
2089
 
2134
  msgid "A Person"
2135
  msgstr ""
2136
 
2137
+ #: inc/views/settings/metaboxes/schema.php:146
2138
  msgid "The organization or personal name"
2139
  msgstr ""
2140
 
2141
+ #: inc/views/settings/metaboxes/schema.php:154
2142
  msgid "Website logo"
2143
  msgstr ""
2144
 
2145
+ #: inc/views/settings/metaboxes/schema.php:155
2146
  msgid "These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere."
2147
  msgstr ""
2148
 
2149
+ #: inc/views/settings/metaboxes/schema.php:164
2150
  msgid "Enable logo?"
2151
  msgstr ""
2152
 
2153
+ #: inc/views/settings/metaboxes/schema.php:173
2154
+ #: inc/views/settings/metaboxes/sitemaps.php:385
2155
  msgid "Logo URL"
2156
  msgstr ""
2157
 
2158
+ #: inc/views/settings/metaboxes/schema.php:176
2159
+ #: inc/views/settings/metaboxes/sitemaps.php:388
2160
  msgid "Setting a logo requires JavaScript."
2161
  msgstr ""
2162
 
2163
+ #: inc/views/settings/metaboxes/schema.php:203
2164
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
2165
  msgid "RelatedProfile"
2166
  msgstr ""
2167
 
2168
+ #: inc/views/settings/metaboxes/schema.php:211
2169
  msgid "Facebook Page"
2170
  msgstr ""
2171
 
2172
+ #: inc/views/settings/metaboxes/schema.php:218
2173
  msgid "Twitter Profile"
2174
  msgstr ""
2175
 
2176
+ #: inc/views/settings/metaboxes/schema.php:225
2177
  msgctxt "Google+ is dead. &#8224; is a cross, indicating that."
2178
  msgid "Google+ Profile&#8224;"
2179
  msgstr ""
2180
 
2181
+ #: inc/views/settings/metaboxes/schema.php:232
2182
  msgid "Instagram Profile"
2183
  msgstr ""
2184
 
2185
+ #: inc/views/settings/metaboxes/schema.php:239
2186
  msgid "Youtube Profile"
2187
  msgstr ""
2188
 
2189
+ #: inc/views/settings/metaboxes/schema.php:246
2190
  msgid "LinkedIn Profile"
2191
  msgstr ""
2192
 
2193
+ #: inc/views/settings/metaboxes/schema.php:257
2194
  msgid "Pinterest Profile"
2195
  msgstr ""
2196
 
2197
+ #: inc/views/settings/metaboxes/schema.php:264
2198
  msgid "SoundCloud Profile"
2199
  msgstr ""
2200
 
2201
+ #: inc/views/settings/metaboxes/schema.php:271
2202
  msgid "Tumblr Blog"
2203
  msgstr ""
2204
 
2205
+ #: inc/views/settings/metaboxes/schema.php:290
2206
  msgid "Connected Social Pages"
2207
  msgstr ""
2208
 
2209
+ #: inc/views/settings/metaboxes/schema.php:291
2210
  msgid "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway."
2211
  msgstr ""
2212
 
2213
+ #: inc/views/settings/metaboxes/schema.php:292
2214
  msgid "Add links that lead directly to the connected social pages of this website."
2215
  msgstr ""
2216
 
2217
+ #: inc/views/settings/metaboxes/schema.php:293
2218
  msgid "These settings do not affect sharing behavior with the social networks."
2219
  msgstr ""
2220
 
2221
  #. translators: %s = Learn more URL. Markdown!
2222
+ #: inc/views/settings/metaboxes/schema.php:298
2223
  msgid "These settings are marked for removal. When you clear a field, it will be hidden forever. [Learn more](%s)."
2224
  msgstr ""
2225
 
2226
+ #: inc/views/settings/metaboxes/schema.php:317
2227
  msgid "View your profile."
2228
  msgstr ""
2229
 
2240
  msgid "Style"
2241
  msgstr ""
2242
 
2243
+ #: inc/views/settings/metaboxes/sitemaps.php:64
2244
  msgid "Sitemap Integration Settings"
2245
  msgstr ""
2246
 
2247
+ #: inc/views/settings/metaboxes/sitemaps.php:65
2248
  msgid "The sitemap is an XML file that lists indexable pages of your website along with optional metadata. It helps search engines find new and updated content quickly."
2249
  msgstr ""
2250
 
2251
  #. translators: %s = Learn more URL. Markdown!
2252
+ #: inc/views/settings/metaboxes/sitemaps.php:71
2253
  msgid "The sitemap does not contribute to ranking; [it can only help with indexing](%s). Search engines process smaller, less complicated sitemaps quicker, which shortens the time required for indexing pages."
2254
  msgstr ""
2255
 
2256
+ #: inc/views/settings/metaboxes/sitemaps.php:81
2257
  msgid "Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect."
2258
  msgstr ""
2259
 
2260
+ #: inc/views/settings/metaboxes/sitemaps.php:84
2261
  msgid "Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect."
2262
  msgstr ""
2263
 
2264
+ #: inc/views/settings/metaboxes/sitemaps.php:89
2265
  msgid "Sitemap Output"
2266
  msgstr ""
2267
 
2268
+ #: inc/views/settings/metaboxes/sitemaps.php:94
2269
  msgid "Output optimized sitemap?"
2270
  msgstr ""
2271
 
2272
+ #: inc/views/settings/metaboxes/sitemaps.php:96
2273
  msgid "This sitemap is processed quicker by search engines."
2274
  msgstr ""
2275
 
2276
+ #: inc/views/settings/metaboxes/sitemaps.php:111
2277
  msgid "View the base sitemap."
2278
  msgstr ""
2279
 
2280
+ #: inc/views/settings/metaboxes/sitemaps.php:123
2281
  msgid "View the sitemap index."
2282
  msgstr ""
2283
 
2284
  #. translators: %s = Documentation URL in markdown
2285
+ #: inc/views/settings/metaboxes/sitemaps.php:138
2286
  msgid "A multilingual plugin has been detected, so your site may have multiple sitemaps. [Learn more](%s)."
2287
  msgstr ""
2288
 
2289
+ #: inc/views/settings/metaboxes/sitemaps.php:152
2290
  msgid "Sitemap Query Limit"
2291
  msgstr ""
2292
 
2293
+ #: inc/views/settings/metaboxes/sitemaps.php:156
2294
  msgid "This setting affects how many pages are requested from the database per query."
2295
  msgstr ""
2296
 
2297
+ #: inc/views/settings/metaboxes/sitemaps.php:163
2298
  msgid "Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion."
2299
  msgstr ""
2300
 
2301
+ #: inc/views/settings/metaboxes/sitemaps.php:167
2302
+ msgid "Transient Cache Settings"
2303
+ msgstr ""
2304
+
2305
+ #: inc/views/settings/metaboxes/sitemaps.php:168
2306
+ msgid "To improve performance, generated output can be stored in the database as transient cache."
2307
+ msgstr ""
2308
+
2309
+ #: inc/views/settings/metaboxes/sitemaps.php:173
2310
+ msgid "Enable optimized sitemap generation cache?"
2311
+ msgstr ""
2312
+
2313
+ #: inc/views/settings/metaboxes/sitemaps.php:174
2314
+ msgid "Generating the sitemap can use a lot of server resources."
2315
+ msgstr ""
2316
+
2317
+ #: inc/views/settings/metaboxes/sitemaps.php:185
2318
  msgid "Robots.txt Settings"
2319
  msgstr ""
2320
 
2321
+ #: inc/views/settings/metaboxes/sitemaps.php:189
2322
  msgid "Note: A robots.txt file has been detected in the root folder of your website. This means these settings have no effect."
2323
  msgstr ""
2324
 
2325
+ #: inc/views/settings/metaboxes/sitemaps.php:195
2326
  msgid "Note: robots.txt files can't be generated or used on subdirectory installations."
2327
  msgstr ""
2328
 
2329
+ #: inc/views/settings/metaboxes/sitemaps.php:200
2330
  msgid "Note: You're using the plain permalink structure; so, no robots.txt file can be generated."
2331
  msgstr ""
2332
 
2333
  #. translators: 1 = Link to settings, Markdown. 2 = example input, also markdown! Preserve the Markdown as-is!
2334
+ #: inc/views/settings/metaboxes/sitemaps.php:206
2335
  msgid "Change your [Permalink Settings](%1$s). Recommended structure: `%2$s`."
2336
  msgstr ""
2337
 
2338
+ #: inc/views/settings/metaboxes/sitemaps.php:218
2339
  msgid "The robots.txt output is the first thing search engines look for before crawling your site. If you add the sitemap location in that output, then search engines may automatically access and index the sitemap."
2340
  msgstr ""
2341
 
2342
+ #: inc/views/settings/metaboxes/sitemaps.php:219
2343
  msgid "If you do not add the sitemap location to the robots.txt output, you should notify search engines manually through webmaster-interfaces provided by the search engines."
2344
  msgstr ""
2345
 
2346
+ #: inc/views/settings/metaboxes/sitemaps.php:224
2347
  msgid "Sitemap Hinting"
2348
  msgstr ""
2349
 
2350
+ #: inc/views/settings/metaboxes/sitemaps.php:228
2351
  msgid "Add sitemap location to robots.txt?"
2352
  msgstr ""
2353
 
2354
+ #: inc/views/settings/metaboxes/sitemaps.php:241
2355
  msgid "View the robots.txt output."
2356
  msgstr ""
2357
 
2358
+ #: inc/views/settings/metaboxes/sitemaps.php:248
2359
  msgid "Timestamps Settings"
2360
  msgstr ""
2361
 
2362
+ #: inc/views/settings/metaboxes/sitemaps.php:249
2363
  msgid "The modified time suggests to search engines where to look for content changes first."
2364
  msgstr ""
2365
 
2366
  #. translators: the backticks are Markdown! Preserve them as-is!
2367
+ #: inc/views/settings/metaboxes/sitemaps.php:256
2368
  msgid "Add `<lastmod>` to the sitemap?"
2369
  msgstr ""
2370
 
2371
+ #: inc/views/settings/metaboxes/sitemaps.php:266
2372
  msgid "Ping Settings"
2373
  msgstr ""
2374
 
2375
+ #: inc/views/settings/metaboxes/sitemaps.php:267
2376
  msgid "Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible."
2377
  msgstr ""
2378
 
2379
+ #: inc/views/settings/metaboxes/sitemaps.php:268
2380
  msgid "By default this will happen at most once an hour."
2381
  msgstr ""
2382
 
2383
+ #: inc/views/settings/metaboxes/sitemaps.php:274
2384
  msgid "Use cron for pinging?"
2385
  msgstr ""
2386
 
2387
+ #: inc/views/settings/metaboxes/sitemaps.php:276
2388
  msgid "This speeds up post and term saving processes, by offsetting pinging to a later time."
2389
  msgstr ""
2390
 
2391
+ #: inc/views/settings/metaboxes/sitemaps.php:284
2392
  msgid "Prerender optimized sitemap before pinging via cron?"
2393
  msgstr ""
2394
 
2395
+ #: inc/views/settings/metaboxes/sitemaps.php:286
2396
  msgid "This mitigates timeouts some search engines may experience when waiting for the sitemap to render. Transient caching for the sitemap must be enabled for this to work."
2397
  msgstr ""
2398
 
2399
+ #: inc/views/settings/metaboxes/sitemaps.php:290
2400
  msgid "Only enable prerendering when generating the sitemap takes over 60 seconds."
2401
  msgstr ""
2402
 
2403
+ #: inc/views/settings/metaboxes/sitemaps.php:300
2404
  msgid "Notify Search Engines"
2405
  msgstr ""
2406
 
2407
  #. translators: %s = Google
2408
+ #: inc/views/settings/metaboxes/sitemaps.php:311
2409
  msgid "Notify %s about sitemap changes?"
2410
  msgstr ""
2411
 
2412
+ #: inc/views/settings/metaboxes/sitemaps.php:322
2413
  msgid "Optimized Sitemap Styling Settings"
2414
  msgstr ""
2415
 
2416
+ #: inc/views/settings/metaboxes/sitemaps.php:323
2417
  msgid "You can style the optimized sitemap to give it a more personal look for your visitors. Search engines do not use these styles."
2418
  msgstr ""
2419
 
2420
+ #: inc/views/settings/metaboxes/sitemaps.php:324
2421
  msgid "Note: Changes may not appear to have an effect directly because the stylesheet is cached in the browser for 30 minutes."
2422
  msgstr ""
2423
 
2424
+ #: inc/views/settings/metaboxes/sitemaps.php:328
2425
  msgid "Enable Styling"
2426
  msgstr ""
2427
 
2428
+ #: inc/views/settings/metaboxes/sitemaps.php:333
2429
  msgid "Style sitemap?"
2430
  msgstr ""
2431
 
2432
+ #: inc/views/settings/metaboxes/sitemaps.php:333
2433
  msgid "This makes the sitemap more readable for humans."
2434
  msgstr ""
2435
 
2436
+ #: inc/views/settings/metaboxes/sitemaps.php:349
2437
  msgid "Sitemap Header Background Color"
2438
  msgstr ""
2439
 
2440
+ #: inc/views/settings/metaboxes/sitemaps.php:358
2441
  msgid "Sitemap Title and Lines Color"
2442
  msgstr ""
2443
 
2444
+ #: inc/views/settings/metaboxes/sitemaps.php:367
2445
  msgid "Header Title Logo"
2446
  msgstr ""
2447
 
2448
+ #: inc/views/settings/metaboxes/sitemaps.php:372
2449
  msgid "Show logo next to sitemap header title?"
2450
  msgstr ""
2451
 
2724
  msgstr ""
2725
 
2726
  #: inc/views/settings/metaboxes/title.php:51
 
 
 
 
 
2727
  msgid "The page title is prominently shown within the browser tab as well as within the search engine results pages."
2728
  msgstr ""
2729
 
2730
+ #: inc/views/settings/metaboxes/title.php:57
2731
  msgid "Example Page Title Output"
2732
  msgstr ""
2733
 
2734
+ #: inc/views/settings/metaboxes/title.php:74
2735
  msgid "Example Archive Title Output"
2736
  msgstr ""
2737
 
2738
  #. translators: %s = title-tag
2739
+ #: inc/views/settings/metaboxes/title.php:114
2740
  msgid "Theme %s Support Missing"
2741
  msgstr ""
2742
 
2743
  #. translators: 1: Extension name, 2: Extension link. Markdown!
2744
+ #: inc/views/settings/metaboxes/title.php:122
2745
  msgid "The current theme doesn't support a feature that allows predictable output of titles. Consider installing [%1$s](%2$s) when you notice the title output in the browser-tab isn't as you have configured."
2746
  msgstr ""
2747
 
2748
+ #: inc/views/settings/metaboxes/title.php:155
2749
  msgid "Prefixes"
2750
  msgstr ""
2751
 
2752
+ #: inc/views/settings/metaboxes/title.php:178
2753
  msgid "Title Separator"
2754
  msgstr ""
2755
 
2756
+ #: inc/views/settings/metaboxes/title.php:180
2757
  msgid "If the title consists of multiple parts, then the separator will go in-between them."
2758
  msgstr ""
2759
 
2760
  #: inc/views/settings/metaboxes/title.php:204
2761
+ msgid "Automated Title Settings"
2762
  msgstr ""
2763
 
2764
  #: inc/views/settings/metaboxes/title.php:205
2765
+ msgid "A title is generated for every page."
2766
+ msgstr ""
2767
+
2768
+ #: inc/views/settings/metaboxes/title.php:206
2769
  msgid "Some titles may have HTML tags inserted by the author for styling."
2770
  msgstr ""
2771
 
2772
  #. translators: %s = HTML tag example
2773
+ #: inc/views/settings/metaboxes/title.php:211
2774
  msgid "This strips HTML tags, like %s, from the title. Disable this option to display generated HTML tags as plain text in meta titles."
2775
  msgstr ""
2776
 
2777
+ #: inc/views/settings/metaboxes/title.php:220
2778
  msgid "Strip HTML tags from generated titles?"
2779
  msgstr ""
2780
 
2781
+ #: inc/views/settings/metaboxes/title.php:226
2782
  msgid "Tip: It is a bad practice to style page titles with HTML as inconsistent behavior might occur."
2783
  msgstr ""
2784
 
2785
+ #: inc/views/settings/metaboxes/title.php:233
2786
  msgid "Site Title"
2787
  msgstr ""
2788
 
2789
+ #: inc/views/settings/metaboxes/title.php:240
2790
  msgid "This option does not affect titles displayed directly on your website."
2791
  msgstr ""
2792
 
2793
+ #: inc/views/settings/metaboxes/title.php:248
2794
  msgid "This option does not affect the homepage; it uses a different one."
2795
  msgstr ""
2796
 
2797
+ #: inc/views/settings/metaboxes/title.php:251
2798
  msgid "Site Title Location"
2799
  msgstr ""
2800
 
2801
+ #: inc/views/settings/metaboxes/title.php:279
2802
  msgid "Site Title Removal"
2803
  msgstr ""
2804
 
2805
+ #: inc/views/settings/metaboxes/title.php:283
2806
  msgid "Always brand your titles. Search engines may ignore your titles with this feature enabled."
2807
  msgstr ""
2808
 
2809
+ #: inc/views/settings/metaboxes/title.php:291
2810
  msgid "Remove site title from the title?"
2811
  msgstr ""
2812
 
2813
+ #: inc/views/settings/metaboxes/title.php:299
2814
  msgid "Note: Only use this option if you are aware of its SEO effects."
2815
  msgstr ""
2816
 
2817
+ #: inc/views/settings/metaboxes/title.php:305
2818
  msgid "Title Prefix Options"
2819
  msgstr ""
2820
 
2821
+ #: inc/views/settings/metaboxes/title.php:306
2822
  msgid "For archives, a descriptive prefix may be added to generated titles."
2823
  msgstr ""
2824
 
2825
+ #: inc/views/settings/metaboxes/title.php:311
2826
  msgid "Archive Title Prefixes"
2827
  msgstr ""
2828
 
2829
+ #: inc/views/settings/metaboxes/title.php:315
2830
  msgid "The prefix helps visitors and search engines determine what kind of page they're visiting."
2831
  msgstr ""
2832
 
2833
+ #: inc/views/settings/metaboxes/title.php:322
2834
  msgid "Remove term type prefixes from generated archive titles?"
2835
  msgstr ""
2836
 
2887
  msgid "Verifying your website has no SEO value whatsoever. But you might gain added benefits such as search ranking insights to help you improve your website's content."
2888
  msgstr ""
2889
 
2890
+ #: inc/views/settings/wrap.php:36
2891
+ msgid "Save Settings"
2892
  msgstr ""
2893
 
2894
+ #: inc/views/settings/wrap.php:43
2895
+ msgid "Are you sure you want to reset all SEO settings to their defaults?"
2896
  msgstr ""
2897
 
2898
+ #: inc/views/settings/wrap.php:45
2899
  msgid "Reset Settings"
2900
  msgstr ""
2901
 
lib/css/post.css CHANGED
@@ -146,7 +146,6 @@ input.tsf-flex-nav-tab-radio {
146
 
147
  .tsf-flex-nav-tab {
148
  flex-direction: row;
149
- flex: 1 1 auto;
150
  max-width: 125px;
151
  }
152
 
146
 
147
  .tsf-flex-nav-tab {
148
  flex-direction: row;
 
149
  max-width: 125px;
150
  }
151
 
lib/css/post.min.css CHANGED
@@ -1 +1 @@
1
- #tsf-inpost-box .inside{margin:0;padding:14px}#tsf-inpost-box:not(.tsf-is-block-editor) .inside,.edit-post-sidebar #tsf-inpost-box .inside{width:100%;padding:0}#tsf-inpost-box.closed .inside{display:none}.tsf-flex-inside-wrap{flex-direction:row;width:100%}.tsf-is-block-editor .tsf-flex-inside-wrap{border:1px solid #ddd}.edit-post-sidebar .tsf-is-block-editor .tsf-flex-inside-wrap{border:0}.tsf-flex-setting{width:100%;flex-direction:row;border-bottom:1px solid #e2e4e7}.tsf-flex-setting:last-of-type{border-bottom:0}.tsf-flex-setting-input .tsf-flex-setting{border-left:1px solid #e2e4e7;border-right:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:first-of-type{border-top:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:last-of-type{border-bottom:1px solid #e2e4e7}#tsf-inpost-box .inside select{width:100%;max-width:99%;text-overflow:ellipsis}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;flex:10 1 350px}.tsf-flex-setting-label{background-color:#f9f9f9;flex:1 1 200px}.tsf-flex-setting-input{justify-content:center;flex-wrap:nowrap}.tsf-flex-setting-label-item{flex-flow:row nowrap;justify-content:space-between;flex-grow:0}.tsf-flex-setting-label-inner-wrap{justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label-sub-item{margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}body.rtl .tsf-social-image-buttons{margin-right:1px;margin-left:0}.tsf-flex-setting-input textarea{max-height:250px}input.tsf-flex-nav-tab-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-flex-nav-tab-wrapper{background-color:#f5f5f5;border-bottom:1px solid #dadada;align-items:baseline;flex-flow:row nowrap;max-width:100%;overflow:hidden;font-weight:600}.tsf-is-block-editor .tsf-flex-nav-tab-wrapper{background-color:#f3f4f5;border-bottom-color:#e2e4e7}.tsf-flex-nav-tab-inner{flex-flow:row nowrap}.tsf-flex-nav-tab{flex-direction:row;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;flex-direction:row;box-shadow:0 0 0 0 transparent inset;transition:box-shadow .15s ease-out;align-items:center;align-content:space-around;position:relative}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{align-items:center;justify-content:center;margin:0 2px}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset,0 0 0 0 #007bd2 inset;transition:box-shadow .25s ease-in}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus+.tsf-flex-nav-tab-label:not(.tsf-no-focus-ring){box-shadow:0 0 0 0 #007bd2 inset,0 0 0 1px #007bd2 inset}.tsf-flex-tab-content{flex:1 0 100%;max-width:100%;flex-wrap:nowrap}body.js .tsf-flex-tab-content{display:none}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{align-items:baseline;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;flex-direction:row;flex:0 1 auto}#tsf-inpost-box .hndle{justify-content:unset;white-space:pre-wrap}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-js .tsf-flex-hide-if-js,.tsf-no-js .tsf-flex-hide-if-no-js{display:none}
1
+ #tsf-inpost-box .inside{margin:0;padding:14px}#tsf-inpost-box:not(.tsf-is-block-editor) .inside,.edit-post-sidebar #tsf-inpost-box .inside{width:100%;padding:0}#tsf-inpost-box.closed .inside{display:none}.tsf-flex-inside-wrap{flex-direction:row;width:100%}.tsf-is-block-editor .tsf-flex-inside-wrap{border:1px solid #ddd}.edit-post-sidebar .tsf-is-block-editor .tsf-flex-inside-wrap{border:0}.tsf-flex-setting{width:100%;flex-direction:row;border-bottom:1px solid #e2e4e7}.tsf-flex-setting:last-of-type{border-bottom:0}.tsf-flex-setting-input .tsf-flex-setting{border-left:1px solid #e2e4e7;border-right:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:first-of-type{border-top:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:last-of-type{border-bottom:1px solid #e2e4e7}#tsf-inpost-box .inside select{width:100%;max-width:99%;text-overflow:ellipsis}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;flex:10 1 350px}.tsf-flex-setting-label{background-color:#f9f9f9;flex:1 1 200px}.tsf-flex-setting-input{justify-content:center;flex-wrap:nowrap}.tsf-flex-setting-label-item{flex-flow:row nowrap;justify-content:space-between;flex-grow:0}.tsf-flex-setting-label-inner-wrap{justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label-sub-item{margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}body.rtl .tsf-social-image-buttons{margin-right:1px;margin-left:0}.tsf-flex-setting-input textarea{max-height:250px}input.tsf-flex-nav-tab-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-flex-nav-tab-wrapper{background-color:#f5f5f5;border-bottom:1px solid #dadada;align-items:baseline;flex-flow:row nowrap;max-width:100%;overflow:hidden;font-weight:600}.tsf-is-block-editor .tsf-flex-nav-tab-wrapper{background-color:#f3f4f5;border-bottom-color:#e2e4e7}.tsf-flex-nav-tab-inner{flex-flow:row nowrap}.tsf-flex-nav-tab{flex-direction:row;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;flex-direction:row;box-shadow:0 0 0 0 transparent inset;transition:box-shadow .15s ease-out;align-items:center;align-content:space-around;position:relative}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{align-items:center;justify-content:center;margin:0 2px}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset,0 0 0 0 #007bd2 inset;transition:box-shadow .25s ease-in}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus+.tsf-flex-nav-tab-label:not(.tsf-no-focus-ring){box-shadow:0 0 0 0 #007bd2 inset,0 0 0 1px #007bd2 inset}.tsf-flex-tab-content{flex:1 0 100%;max-width:100%;flex-wrap:nowrap}body.js .tsf-flex-tab-content{display:none}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{align-items:baseline;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;flex-direction:row;flex:0 1 auto}#tsf-inpost-box .hndle{justify-content:unset;white-space:pre-wrap}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-js .tsf-flex-hide-if-js,.tsf-no-js .tsf-flex-hide-if-no-js{display:none}
lib/js/c.js CHANGED
@@ -129,14 +129,14 @@ window.tsfC = function() {
129
 
130
  switch ( counterType ) {
131
  case 3:
132
- exclaimer = testLength.toString() + ' - ' + exclaimer;
133
  break;
134
  case 2:
135
  // 2 uses exclaimer as-is.
136
  break;
137
  case 1:
138
  default:
139
- exclaimer = testLength.toString();
140
  break;
141
  }
142
 
129
 
130
  switch ( counterType ) {
131
  case 3:
132
+ exclaimer = `${testLength} &ndash; ${exclaimer}`;
133
  break;
134
  case 2:
135
  // 2 uses exclaimer as-is.
136
  break;
137
  case 1:
138
  default:
139
+ exclaimer = testLength;
140
  break;
141
  }
142
 
lib/js/c.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfC=function(){const a="undefined"!=typeof tsfCL10n&&tsfCL10n;let b=+(a.counterType||0);const c=()=>b,d={0:"tsf-counter-zero",1:"tsf-counter-one",2:"tsf-counter-two",3:"tsf-counter-three"},e=c=>{let e=c.e,f=tsf.decodeEntities(c.text),g=a.guidelines[c.field][c.type].chars,h=tsf.getStringLength(f),i="",j="",k={bad:"tsf-count-bad",okay:"tsf-count-okay",good:"tsf-count-good",unknown:"tsf-count-unknown"};switch(h?h<g.lower?(i=k.bad,j=a.i18n.guidelines.short.farTooShort):h<g.goodLower?(i=k.okay,j=a.i18n.guidelines.short.tooShort):h>g.upper?(i=k.bad,j=a.i18n.guidelines.short.farTooLong):h>g.goodUpper?(i=k.okay,j=a.i18n.guidelines.short.tooLong):(i=k.good,j=a.i18n.guidelines.short.good):(i=k.unknown,j=a.i18n.guidelines.short.empty),b){case 3:j=h.toString()+" - "+j;break;case 2:break;case 1:default:j=h.toString();}for(let a in e.innerHTML=j,k)e.classList.remove(k[a]);for(let a in d)e.classList.remove(d[a]);e.classList.add(i),e.classList.add(d[b])},f=()=>{window.dispatchEvent(new CustomEvent("tsf-counter-updated"))},g=a=>{a&&++b,3<b&&(b=0),f()},h=()=>{g(!0);let a=".tsf-counter-wrap .tsf-ajax",c=0;tsf.resetAjaxLoader(a),tsf.setAjaxLoader(a),wp.ajax.post("tsf_update_counter",{nonce:tsf.l10n.nonces.edit_posts,val:b}).done(b=>{switch(b=tsf.convertJSONResponse(b),"success"===b.type&&(c=1),c){case 0:tsf.unsetAjaxLoader(a,!1);break;case 1:tsf.unsetAjaxLoader(a,!0);break;default:tsf.resetAjaxLoader(a);}}).fail(()=>{tsf.unsetAjaxLoader(a,!1)})},i=()=>document.querySelectorAll(".tsf-counter").forEach(a=>a.addEventListener("click",h)),j=()=>{i()};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",j)}},{updatePixelCounter:b=>{let c=b.e,d=tsf.decodeEntities(b.text),e=a.guidelines[b.field][b.type].pixels,f=c.parentElement;if(!f)return;let g=f.querySelector(".tsf-pixel-counter-bar"),h=f.querySelector(".tsf-pixel-counter-shadow");if(!g||!h)return;h.innerHTML=tsf.escapeString(d);let i=h.offsetWidth,j="",k="",l="",m={bad:"tsf-pixel-counter-bad",okay:"tsf-pixel-counter-okay",good:"tsf-pixel-counter-good",unknown:"tsf-pixel-counter-unknown"};k=100*(i/e.goodUpper)+"%",i?i<e.lower?(j=m.bad,l=a.i18n.guidelines.long.farTooShort):i<e.goodLower?(j=m.okay,l=a.i18n.guidelines.long.tooShort):i>e.upper?(k=100*(e.upper/(i+2*(i-e.upper)/3))+"%",j=m.bad,l=a.i18n.guidelines.long.farTooLong):i>e.goodUpper?(j=m.okay,l=a.i18n.guidelines.long.tooLong,k="100%"):(j=m.good,l=a.i18n.guidelines.long.good):(j=m.unknown,k="100%",l=a.i18n.guidelines.long.empty);let n,o=g.querySelector(".tsf-pixel-counter-fluid");n=a.i18n.pixelsUsed.replace(/%1\$d/g,i),n=n.replace(/%2\$d/g,e.goodUpper),n+="<br>"+l,g.classList.remove(...Object.values(m)),g.classList.add(j),o.style.width=k,g.dataset.desc=n,g.setAttribute("aria-label",tsf.escapeString(n.replace(/(<([^>]+)?>?)/ig," "))),tsfTT.triggerUpdate(g)},updateCharacterCounter:e,triggerCounterUpdate:f,resetCounterListener:i,getCounterType:c},{counterClasses:d,l10n:a})}(),window.tsfC.load();
1
+ 'use strict';window.tsfC=function(){const a="undefined"!=typeof tsfCL10n&&tsfCL10n;let b=+(a.counterType||0);const c=()=>b,d={0:"tsf-counter-zero",1:"tsf-counter-one",2:"tsf-counter-two",3:"tsf-counter-three"},e=c=>{let e=c.e,f=tsf.decodeEntities(c.text),g=a.guidelines[c.field][c.type].chars,h=tsf.getStringLength(f),i="",j="",k={bad:"tsf-count-bad",okay:"tsf-count-okay",good:"tsf-count-good",unknown:"tsf-count-unknown"};switch(h?h<g.lower?(i=k.bad,j=a.i18n.guidelines.short.farTooShort):h<g.goodLower?(i=k.okay,j=a.i18n.guidelines.short.tooShort):h>g.upper?(i=k.bad,j=a.i18n.guidelines.short.farTooLong):h>g.goodUpper?(i=k.okay,j=a.i18n.guidelines.short.tooLong):(i=k.good,j=a.i18n.guidelines.short.good):(i=k.unknown,j=a.i18n.guidelines.short.empty),b){case 3:j=`${h} &ndash; ${j}`;break;case 2:break;case 1:default:j=h;}for(let a in e.innerHTML=j,k)e.classList.remove(k[a]);for(let a in d)e.classList.remove(d[a]);e.classList.add(i),e.classList.add(d[b])},f=()=>{window.dispatchEvent(new CustomEvent("tsf-counter-updated"))},g=a=>{a&&++b,3<b&&(b=0),f()},h=()=>{g(!0);let a=".tsf-counter-wrap .tsf-ajax",c=0;tsf.resetAjaxLoader(a),tsf.setAjaxLoader(a),wp.ajax.post("tsf_update_counter",{nonce:tsf.l10n.nonces.edit_posts,val:b}).done(b=>{switch(b=tsf.convertJSONResponse(b),"success"===b.type&&(c=1),c){case 0:tsf.unsetAjaxLoader(a,!1);break;case 1:tsf.unsetAjaxLoader(a,!0);break;default:tsf.resetAjaxLoader(a);}}).fail(()=>{tsf.unsetAjaxLoader(a,!1)})},i=()=>document.querySelectorAll(".tsf-counter").forEach(a=>a.addEventListener("click",h)),j=()=>{i()};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",j)}},{updatePixelCounter:b=>{let c=b.e,d=tsf.decodeEntities(b.text),e=a.guidelines[b.field][b.type].pixels,f=c.parentElement;if(!f)return;let g=f.querySelector(".tsf-pixel-counter-bar"),h=f.querySelector(".tsf-pixel-counter-shadow");if(!g||!h)return;h.innerHTML=tsf.escapeString(d);let i=h.offsetWidth,j="",k="",l="",m={bad:"tsf-pixel-counter-bad",okay:"tsf-pixel-counter-okay",good:"tsf-pixel-counter-good",unknown:"tsf-pixel-counter-unknown"};k=100*(i/e.goodUpper)+"%",i?i<e.lower?(j=m.bad,l=a.i18n.guidelines.long.farTooShort):i<e.goodLower?(j=m.okay,l=a.i18n.guidelines.long.tooShort):i>e.upper?(k=100*(e.upper/(i+2*(i-e.upper)/3))+"%",j=m.bad,l=a.i18n.guidelines.long.farTooLong):i>e.goodUpper?(j=m.okay,l=a.i18n.guidelines.long.tooLong,k="100%"):(j=m.good,l=a.i18n.guidelines.long.good):(j=m.unknown,k="100%",l=a.i18n.guidelines.long.empty);let n,o=g.querySelector(".tsf-pixel-counter-fluid");n=a.i18n.pixelsUsed.replace(/%1\$d/g,i),n=n.replace(/%2\$d/g,e.goodUpper),n+="<br>"+l,g.classList.remove(...Object.values(m)),g.classList.add(j),o.style.width=k,g.dataset.desc=n,g.setAttribute("aria-label",tsf.escapeString(n.replace(/(<([^>]+)?>?)/ig," "))),tsfTT.triggerUpdate(g)},updateCharacterCounter:e,triggerCounterUpdate:f,resetCounterListener:i,getCounterType:c},{counterClasses:d,l10n:a})}(),window.tsfC.load();
lib/js/le.js CHANGED
@@ -88,7 +88,7 @@ window.tsfLe = function() {
88
  // Do `sprintf( 'Default (%s)', x.default )`.
89
  let _default = element.querySelector( '[value="0"]' );
90
  if ( _default )
91
- _default.innerHTML = _default.innerHTML.replace( '%s', tsf.decodeEntities( data[ option ].default ) );
92
  } else {
93
  element.value = tsf.decodeEntities( data[ option ].value );
94
 
@@ -210,6 +210,8 @@ window.tsfLe = function() {
210
  const titleId = 'autodescription-quick[doctitle]',
211
  titleInput = document.getElementById( titleId );
212
 
 
 
213
  // Reset and rebuild. Map won't be affected.
214
  tsfTitle.setInputElement( titleInput );
215
 
@@ -274,6 +276,8 @@ window.tsfLe = function() {
274
  const descId = 'autodescription-quick[description]',
275
  descInput = document.getElementById( descId );
276
 
 
 
277
  // Reset and rebuild. Map won't be affected.
278
  tsfDescription.setInputElement( descInput );
279
 
88
  // Do `sprintf( 'Default (%s)', x.default )`.
89
  let _default = element.querySelector( '[value="0"]' );
90
  if ( _default )
91
+ _default.innerHTML = _default.innerHTML.replace( '%s', tsf.escapeString( tsf.decodeEntities( data[ option ].default ) ) );
92
  } else {
93
  element.value = tsf.decodeEntities( data[ option ].value );
94
 
210
  const titleId = 'autodescription-quick[doctitle]',
211
  titleInput = document.getElementById( titleId );
212
 
213
+ if ( ! titleInput ) return;
214
+
215
  // Reset and rebuild. Map won't be affected.
216
  tsfTitle.setInputElement( titleInput );
217
 
276
  const descId = 'autodescription-quick[description]',
277
  descInput = document.getElementById( descId );
278
 
279
+ if ( ! descInput ) return;
280
+
281
  // Reset and rebuild. Map won't be affected.
282
  tsfDescription.setInputElement( descInput );
283
 
lib/js/le.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfLe=function(){let a;const b=()=>{clearTimeout(a),a=setTimeout(()=>{document.dispatchEvent(new Event("tsfLeUpdated"))},50)},c=()=>{tsfTT?.triggerReset()},d=a=>{const b=JSON.parse(document.getElementById(`tsfLeData[${a}]`)?.dataset.le||0)||{};for(const c in b){const a=document.getElementById("autodescription-quick[%s]".replace("%s",c));if(a)if(b[c].isSelect){tsf.selectByValue(a,b[c].value);let d=a.querySelector("[value=\"0\"]");d&&(d.innerHTML=d.innerHTML.replace("%s",tsf.decodeEntities(b[c].default)))}else a.value=tsf.decodeEntities(b[c].value),b[c].placeholder&&(a.placeholder=tsf.decodeEntities(b[c].placeholder))}},e=a=>d(a),f=a=>JSON.parse(document.getElementById(`tsfLePostData[${a}]`)?.dataset.lePostData||0)||{},g=a=>{let b=(a.originalEvent||a).target,c=b.dataset.tsfTitleId,d="",e="public";switch(e="keep_private"===b.name?b.checked?"private":"public":b.value&&b.value.length?"password":"public",e){case"password":d=tsfTitle.protectedPrefix;break;case"private":d=tsfTitle.privatePrefix;break;default:case"public":d="";}tsfTitle.updateStateOf(c,"prefixValue",d)},h=a=>{const b=(a.originalEvent||a).target,c=b.dataset?.tsfTitleId,d=b.value?.trim()||"",e=b.dataset?.termPrefix?.trim()||"";let f=tsfTitle.stripTitleTags?tsf.stripTags(d):d;f||=tsfTitle.untitledTitle,e.length&&(window.isRtl?f=`${f} ${e}`:f=`${e} ${f}`),f=tsf.escapeString(tsf.decodeEntities(f.trim())),tsfTitle.updateStateOf(c,"defaultTitle",f)},i=a=>{const b="autodescription-quick[doctitle]",c=document.getElementById(b);tsfTitle.setInputElement(c);const d=JSON.parse(document.getElementById(`tsfLeTitleData[${a}]`)?.dataset.leTitle||0);d&&(tsfTitle.updateStateOf(b,"allowReferenceChange",!d.refTitleLocked),tsfTitle.updateStateOf(b,"defaultTitle",d.defaultTitle.trim()),tsfTitle.updateStateOf(b,"addAdditions",d.addAdditions),tsfTitle.updateStateOf(b,"additionValue",d.additionValue.trim()),tsfTitle.updateStateOf(b,"additionPlacement",d.additionPlacement));let e=document.getElementById(`edit-${a}`);e&&(e.querySelectorAll("[name=post_password]").forEach(a=>{a.dataset.tsfTitleId=b,a.addEventListener("input",g),a.dispatchEvent(new CustomEvent("input"))}),e.querySelectorAll("[name=keep_private]").forEach(a=>{a.dataset.tsfTitleId=b,a.addEventListener("click",g),a.dispatchEvent(new CustomEvent("click"))}),e.querySelectorAll("[name=post_title]").forEach(c=>{c.dataset.tsfTitleId=b,f(a).isFront||(c.addEventListener("input",h),c.dispatchEvent(new CustomEvent("input")))}),e.querySelectorAll("[name=name]").forEach(a=>{a.dataset.tsfTitleId=b,a.dataset.termPrefix=d.termPrefix||"",a.addEventListener("input",h),a.dispatchEvent(new CustomEvent("input"))})),tsfTT?.triggerReset()},j=a=>{const b="autodescription-quick[description]",c=document.getElementById(b);tsfDescription.setInputElement(c);const d=JSON.parse(document.getElementById(`tsfLeDescriptionData[${a}]`)?.dataset.leDescription||0);d&&(tsfDescription.updateStateOf(b,"allowReferenceChange",!d.refDescriptionLocked),tsfDescription.updateStateOf(b,"defaultDescription",d.defaultDescription.trim())),tsfTT.triggerReset()},k=()=>{document.addEventListener("tsfLeDispatchUpdate",b),document.addEventListener("tsfLeUpdated",c)},l=()=>{let a,b;a=window.inlineEditPost?.edit,a&&(window.inlineEditPost.edit=function(b){let c=a.apply(this,arguments);return("object"==typeof b&&(b=window.inlineEditPost?.getId(b)),!b)?c:(d(b),i(b),j(b),window.tsfC?.resetCounterListener(),c)}),b=window.inlineEditTax?.edit,b&&(window.inlineEditTax.edit=function(a){let c=b.apply(this,arguments);return("object"==typeof a&&(a=window.inlineEditTax?.getId(a)),!a)?c:(e(a),i(a),j(a),window.tsfC?.resetCounterListener(),c)})};return{load:()=>{document.body.addEventListener("tsf-onload",k),document.body.addEventListener("tsf-onload",l)}}}(),window.tsfLe.load();
1
+ 'use strict';window.tsfLe=function(){let a;const b=()=>{clearTimeout(a),a=setTimeout(()=>{document.dispatchEvent(new Event("tsfLeUpdated"))},50)},c=()=>{tsfTT?.triggerReset()},d=a=>{const b=JSON.parse(document.getElementById(`tsfLeData[${a}]`)?.dataset.le||0)||{};for(const c in b){const a=document.getElementById("autodescription-quick[%s]".replace("%s",c));if(a)if(b[c].isSelect){tsf.selectByValue(a,b[c].value);let d=a.querySelector("[value=\"0\"]");d&&(d.innerHTML=d.innerHTML.replace("%s",tsf.escapeString(tsf.decodeEntities(b[c].default))))}else a.value=tsf.decodeEntities(b[c].value),b[c].placeholder&&(a.placeholder=tsf.decodeEntities(b[c].placeholder))}},e=a=>d(a),f=a=>JSON.parse(document.getElementById(`tsfLePostData[${a}]`)?.dataset.lePostData||0)||{},g=a=>{let b=(a.originalEvent||a).target,c=b.dataset.tsfTitleId,d="",e="public";switch(e="keep_private"===b.name?b.checked?"private":"public":b.value&&b.value.length?"password":"public",e){case"password":d=tsfTitle.protectedPrefix;break;case"private":d=tsfTitle.privatePrefix;break;default:case"public":d="";}tsfTitle.updateStateOf(c,"prefixValue",d)},h=a=>{const b=(a.originalEvent||a).target,c=b.dataset?.tsfTitleId,d=b.value?.trim()||"",e=b.dataset?.termPrefix?.trim()||"";let f=tsfTitle.stripTitleTags?tsf.stripTags(d):d;f||=tsfTitle.untitledTitle,e.length&&(window.isRtl?f=`${f} ${e}`:f=`${e} ${f}`),f=tsf.escapeString(tsf.decodeEntities(f.trim())),tsfTitle.updateStateOf(c,"defaultTitle",f)},i=a=>{const b="autodescription-quick[doctitle]",c=document.getElementById(b);if(!c)return;tsfTitle.setInputElement(c);const d=JSON.parse(document.getElementById(`tsfLeTitleData[${a}]`)?.dataset.leTitle||0);d&&(tsfTitle.updateStateOf(b,"allowReferenceChange",!d.refTitleLocked),tsfTitle.updateStateOf(b,"defaultTitle",d.defaultTitle.trim()),tsfTitle.updateStateOf(b,"addAdditions",d.addAdditions),tsfTitle.updateStateOf(b,"additionValue",d.additionValue.trim()),tsfTitle.updateStateOf(b,"additionPlacement",d.additionPlacement));let e=document.getElementById(`edit-${a}`);e&&(e.querySelectorAll("[name=post_password]").forEach(a=>{a.dataset.tsfTitleId=b,a.addEventListener("input",g),a.dispatchEvent(new CustomEvent("input"))}),e.querySelectorAll("[name=keep_private]").forEach(a=>{a.dataset.tsfTitleId=b,a.addEventListener("click",g),a.dispatchEvent(new CustomEvent("click"))}),e.querySelectorAll("[name=post_title]").forEach(c=>{c.dataset.tsfTitleId=b,f(a).isFront||(c.addEventListener("input",h),c.dispatchEvent(new CustomEvent("input")))}),e.querySelectorAll("[name=name]").forEach(a=>{a.dataset.tsfTitleId=b,a.dataset.termPrefix=d.termPrefix||"",a.addEventListener("input",h),a.dispatchEvent(new CustomEvent("input"))})),tsfTT?.triggerReset()},j=a=>{const b="autodescription-quick[description]",c=document.getElementById(b);if(c){tsfDescription.setInputElement(c);const d=JSON.parse(document.getElementById(`tsfLeDescriptionData[${a}]`)?.dataset.leDescription||0);d&&(tsfDescription.updateStateOf(b,"allowReferenceChange",!d.refDescriptionLocked),tsfDescription.updateStateOf(b,"defaultDescription",d.defaultDescription.trim())),tsfTT.triggerReset()}},k=()=>{document.addEventListener("tsfLeDispatchUpdate",b),document.addEventListener("tsfLeUpdated",c)},l=()=>{let a,b;a=window.inlineEditPost?.edit,a&&(window.inlineEditPost.edit=function(b){let c=a.apply(this,arguments);return("object"==typeof b&&(b=window.inlineEditPost?.getId(b)),!b)?c:(d(b),i(b),j(b),window.tsfC?.resetCounterListener(),c)}),b=window.inlineEditTax?.edit,b&&(window.inlineEditTax.edit=function(a){let c=b.apply(this,arguments);return("object"==typeof a&&(a=window.inlineEditTax?.getId(a)),!a)?c:(e(a),i(a),j(a),window.tsfC?.resetCounterListener(),c)})};return{load:()=>{document.body.addEventListener("tsf-onload",k),document.body.addEventListener("tsf-onload",l)}}}(),window.tsfLe.load();
lib/js/media.js CHANGED
@@ -233,7 +233,7 @@ window.tsfMedia = function( $ ) {
233
  button.dataset.inputId = inputId;
234
  button.dataset.inputType = inputType;
235
  button.title = tsf.decodeEntities( l10n.labels[ inputType ].imgRemoveTitle );
236
- button.innerHTML = tsf.escapeString( l10n.labels[ inputType ].imgRemove );
237
  button.classList.add( 'tsf-remove-image-button', 'button', 'button-small' );
238
 
239
  target.insertAdjacentElement( 'afterend', button );
233
  button.dataset.inputId = inputId;
234
  button.dataset.inputType = inputType;
235
  button.title = tsf.decodeEntities( l10n.labels[ inputType ].imgRemoveTitle );
236
+ button.innerHTML = tsf.escapeString( tsf.decodeEntities( l10n.labels[ inputType ].imgRemove ) );
237
  button.classList.add( 'tsf-remove-image-button', 'button', 'button-small' );
238
 
239
  target.insertAdjacentElement( 'afterend', button );
lib/js/media.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfMedia=function(a){const b="undefined"!=typeof tsfMediaL10n&&tsfMediaL10n;let c={};const d=a=>{const d=a.target;if(d.disabled||"undefined"==typeof wp.media)return a.preventDefault(),void a.stopPropagation();const f=d.dataset.inputType||"",i=d.dataset.inputId||"";let j;a.preventDefault(),a.stopPropagation(),g();const k={suggestedWidth:+(d.dataset.width||1200),suggestedHeight:+(d.dataset.height||630),isFlex:+(d.dataset.flex||1),minWidth:+(d.dataset.minWidth||200),minHeight:+(d.dataset.minHeight||200)};c.control={params:{flex_width:k.isFlex?4096:0,flex_height:k.isFlex?4096:0,width:k.suggestedWidth,height:k.suggestedHeight,isFlex:k.isFlex,minWidth:k.minWidth,minHeight:k.minHeight}},j=wp.media({button:{text:b.labels[f].imgFrameButton,close:!1},states:[new wp.media.controller.Library({title:b.labels[f].imgFrameTitle,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:k.suggestedWidth,suggestedHeight:k.suggestedHeight}),new c({imgSelectOptions:h})]});const l=document.getElementById(`${i}-url`),m=document.getElementById(`${i}-id`),n=()=>{j.setState("cropper")};j.off("select",n),j.on("select",n);const o=a=>{let b=a.url,c=a.id;l&&(l.value=b,l.dispatchEvent(new Event("change"))),m&&(m.value=c,m.dispatchEvent(new Event("change")))};j.off("cropped",o),j.on("cropped",o);const p=a=>{let b=a.get("url"),c=a.get("id");l&&(l.value=b,l.dispatchEvent(new Event("change"))),m&&(m.value=c,m.dispatchEvent(new Event("change")))};j.off("skippedcrop",p),j.on("skippedcrop",p);const q=()=>{d.textContent=b.labels[f].imgChange,l&&(l.readOnly=!0),e(d,!0),"tsfAys"in window&&tsfAys.registerChange()};j.off("skippedcrop cropped",q),j.on("skippedcrop cropped",q),j.open()},e=(c,d)=>{const e=c.dataset?.inputId,f=c.dataset?.inputType;if(e&&f&&!document.getElementById(`${e}-remove`)){let g=document.createElement("button");g.type="button",g.id=`${e}-remove`,g.dataset.inputId=e,g.dataset.inputType=f,g.title=tsf.decodeEntities(b.labels[f].imgRemoveTitle),g.innerHTML=tsf.escapeString(b.labels[f].imgRemove),g.classList.add("tsf-remove-image-button","button","button-small"),c.insertAdjacentElement("afterend",g),d&&a(g).css("opacity",0).animate({opacity:1},{queue:!0,duration:1e3}),m()}},f=c=>{const d=c.target.dataset.inputId||"",e=c.target.dataset.inputType||"";if(!d||!e)return;const f=document.getElementById(`${d}-select`);if(f.disabled)return;f.disabled=!0,f.classList.add("disabled");const g=document.getElementById(`${d}-remove`);g&&(g.disabled=!0,g.classList.add("disabled"),a(g).fadeOut(250,()=>{g.remove(),f.textContent=b.labels[e].imgSelect,f.classList.remove("disabled"),f.disabled=!1}));const h=document.getElementById(`${d}-url`);h&&(h.value="",h.dispatchEvent(new Event("change")),!h.dataset.readonly&&(h.readOnly=!1));const i=document.getElementById(`${d}-id`);i&&(i.value="",i.dispatchEvent(new Event("change"))),"tsfAys"in window&&tsfAys.registerChange()},g=()=>{if("undefined"!=typeof c.control)return;const a=wp.media.view,d=a.Cropper.extend({className:"crop-content tsf-image",ready:function(){a.Cropper.prototype.ready.apply(this,arguments)},onImageLoad:function(){let a,b=this.controller.get("imgSelectOptions");"function"==typeof b&&(b=b(this.options.attachment,this.controller)),"undefined"==typeof b.aspectRatio&&(b=_.extend(b,{parent:this.$el,onInit:function(){this.parent.children().on("mousedown touchstart",function(b){b.shiftKey?a.setOptions({aspectRatio:"1:1"}):a.setOptions({aspectRatio:!1})})}})),this.trigger("image-loaded"),a=this.controller.imgSelect=this.$image.imgAreaSelect(b)}}),e=wp.media.controller.Cropper.extend({createCropContent:function(){this.cropperView=new d({controller:this,attachment:this.get("selection").first()}),this.cropperView.on("image-loaded",this.createCropToolbar,this),this.frame.content.set(this.cropperView)},doCrop:function(a){var d=Math.round;let e=a.get("cropDetails"),f=c.control;if(f.params.flex_width&&f.params.flex_height)if(e.width===e.height)e.width>f.params.flex_width&&(e.dst_width=e.dst_height=f.params.flex_width);else if(e.width>f.params.flex_width||e.height>f.params.flex_height)if(e.width>e.height){let a=e.width/f.params.flex_width;e.dst_width=f.params.flex_width,e.dst_height=d(e.height/a)}else{let a=e.height/f.params.flex_height;e.dst_height=f.params.flex_height,e.dst_width=d(e.width/a)}return"undefined"==typeof e.dst_width&&(e.dst_width=0,e.dst_height=0),wp.ajax.post("tsf_crop_image",{nonce:b.nonce,id:a.get("id"),context:"tsf-image",cropDetails:e})}});e.prototype.control={},c=e},h=(a,b)=>{const d=c.control;let e=parseInt(d.params.width,10),f=parseInt(d.params.height,10);const g=!!parseInt(d.params.flex_width,10),h=!!parseInt(d.params.flex_height,10),j=a.get("width"),k=a.get("height"),l=e/f,m=e,n=f;let o;o=d.params.isFlex?!i(d.params.flex_width,d.params.flex_height,j,k):l===j/k,b.set("control",d.params),b.set("canSkipCrop",o),j/k>l?(f=k,e=f*l):(e=j,f=e/l);let p=(j-e)/2,q=(k-f)/2;const r={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:j,imageHeight:k,minWidth:m>e?e:m,minHeight:n>f?f:n,x1:p,y1:q,x2:e+p,y2:f+q};return d.params.isFlex?h||g?(h&&(r.minHeight=d.params.minHeight,r.maxWidth=j),g&&(r.minWidth=d.params.minWidth,r.maxHeight=k)):r.aspectRatio=e+":"+f:(r.handles="corners",r.aspectRatio=e+":"+f),r},i=(a,b,c,d)=>!(c<=a&&d<=b),j=a=>{const c=a.target.dataset.id||"",d=a.target.dataset.type||"";if(c&&d){const e=document.getElementById(`${c}-select`);e.disabled||(e.textContent=a.target.value.length?b.labels[d].imgChange:b.labels[d].imgSelect)}},k=()=>{document.querySelectorAll(".tsf-set-image-button").forEach(a=>{const b=a.dataset.inputId||"",c=b&&document.getElementById(`${b}-id`),d=b&&document.getElementById(`${b}-url`);c&&0<c.value&&(d&&(d.readOnly=!0),e(a,!1)),d&&(d.addEventListener("change",j),d.dispatchEvent(new Event("change")))})},l=()=>{document.querySelectorAll(".tsf-set-image-button").forEach(a=>{a.addEventListener("click",d)})},m=()=>{document.querySelectorAll(".tsf-remove-image-button").forEach(a=>{a.addEventListener("click",f)})},n=()=>{l(),m(),document.querySelectorAll(".tsf-enable-media-if-js").forEach(a=>{a.disabled=!1,a.classList.remove("tsf-enable-media-if-js")}),k(),s()};let o;const p=()=>{clearTimeout(o),o=setTimeout(n,500)};let q={};const r=b=>{const c=t(b.target.id||""),d=c&&document.getElementById(`${c}-preview`);if(!d)return;c in q&&clearTimeout(q[c]);let e=d.dataset.tsfLoaded||!1;d.dataset.tsfLoaded=1;let f=b.target.value||b.target.placeholder||"";q[c]=setTimeout(()=>{return f.length?void(d.dataset.desc=`<img src=${tsf.escapeString(f)} style="${"max-width:225px;max-height:225px;min-width:60px;min-height:60px;border-radius:3px;display:block;"}" />`,e?a(d).not(":visible").fadeIn(250):a(d).show(),new Image().src=f,tsfTT.triggerUpdate(d)):void(e?a(d).not(":hidden").fadeOut(250):a(d).hide())},e&&f.length?1e3/(115/60):0)},s=()=>{document.querySelectorAll(".tsf-image-preview").forEach(a=>{const b=document.getElementById(`${a.dataset.for}-url`);b&&(b.addEventListener("input",r),b.addEventListener("change",r),b.dispatchEvent(new Event("change")))})},t=a=>a.replace(/-[a-z]+$/,"");return Object.assign({load:()=>{document.body.addEventListener("tsf-ready",n)}},{resetImageEditorActions:p},{l10n:b})}(jQuery),window.tsfMedia.load();
1
+ 'use strict';window.tsfMedia=function(a){const b="undefined"!=typeof tsfMediaL10n&&tsfMediaL10n;let c={};const d=a=>{const d=a.target;if(d.disabled||"undefined"==typeof wp.media)return a.preventDefault(),void a.stopPropagation();const f=d.dataset.inputType||"",i=d.dataset.inputId||"";let j;a.preventDefault(),a.stopPropagation(),g();const k={suggestedWidth:+(d.dataset.width||1200),suggestedHeight:+(d.dataset.height||630),isFlex:+(d.dataset.flex||1),minWidth:+(d.dataset.minWidth||200),minHeight:+(d.dataset.minHeight||200)};c.control={params:{flex_width:k.isFlex?4096:0,flex_height:k.isFlex?4096:0,width:k.suggestedWidth,height:k.suggestedHeight,isFlex:k.isFlex,minWidth:k.minWidth,minHeight:k.minHeight}},j=wp.media({button:{text:b.labels[f].imgFrameButton,close:!1},states:[new wp.media.controller.Library({title:b.labels[f].imgFrameTitle,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:k.suggestedWidth,suggestedHeight:k.suggestedHeight}),new c({imgSelectOptions:h})]});const l=document.getElementById(`${i}-url`),m=document.getElementById(`${i}-id`),n=()=>{j.setState("cropper")};j.off("select",n),j.on("select",n);const o=a=>{let b=a.url,c=a.id;l&&(l.value=b,l.dispatchEvent(new Event("change"))),m&&(m.value=c,m.dispatchEvent(new Event("change")))};j.off("cropped",o),j.on("cropped",o);const p=a=>{let b=a.get("url"),c=a.get("id");l&&(l.value=b,l.dispatchEvent(new Event("change"))),m&&(m.value=c,m.dispatchEvent(new Event("change")))};j.off("skippedcrop",p),j.on("skippedcrop",p);const q=()=>{d.textContent=b.labels[f].imgChange,l&&(l.readOnly=!0),e(d,!0),"tsfAys"in window&&tsfAys.registerChange()};j.off("skippedcrop cropped",q),j.on("skippedcrop cropped",q),j.open()},e=(c,d)=>{const e=c.dataset?.inputId,f=c.dataset?.inputType;if(e&&f&&!document.getElementById(`${e}-remove`)){let g=document.createElement("button");g.type="button",g.id=`${e}-remove`,g.dataset.inputId=e,g.dataset.inputType=f,g.title=tsf.decodeEntities(b.labels[f].imgRemoveTitle),g.innerHTML=tsf.escapeString(tsf.decodeEntities(b.labels[f].imgRemove)),g.classList.add("tsf-remove-image-button","button","button-small"),c.insertAdjacentElement("afterend",g),d&&a(g).css("opacity",0).animate({opacity:1},{queue:!0,duration:1e3}),m()}},f=c=>{const d=c.target.dataset.inputId||"",e=c.target.dataset.inputType||"";if(!d||!e)return;const f=document.getElementById(`${d}-select`);if(f.disabled)return;f.disabled=!0,f.classList.add("disabled");const g=document.getElementById(`${d}-remove`);g&&(g.disabled=!0,g.classList.add("disabled"),a(g).fadeOut(250,()=>{g.remove(),f.textContent=b.labels[e].imgSelect,f.classList.remove("disabled"),f.disabled=!1}));const h=document.getElementById(`${d}-url`);h&&(h.value="",h.dispatchEvent(new Event("change")),!h.dataset.readonly&&(h.readOnly=!1));const i=document.getElementById(`${d}-id`);i&&(i.value="",i.dispatchEvent(new Event("change"))),"tsfAys"in window&&tsfAys.registerChange()},g=()=>{if("undefined"!=typeof c.control)return;const a=wp.media.view,d=a.Cropper.extend({className:"crop-content tsf-image",ready:function(){a.Cropper.prototype.ready.apply(this,arguments)},onImageLoad:function(){let a,b=this.controller.get("imgSelectOptions");"function"==typeof b&&(b=b(this.options.attachment,this.controller)),"undefined"==typeof b.aspectRatio&&(b=_.extend(b,{parent:this.$el,onInit:function(){this.parent.children().on("mousedown touchstart",function(b){b.shiftKey?a.setOptions({aspectRatio:"1:1"}):a.setOptions({aspectRatio:!1})})}})),this.trigger("image-loaded"),a=this.controller.imgSelect=this.$image.imgAreaSelect(b)}}),e=wp.media.controller.Cropper.extend({createCropContent:function(){this.cropperView=new d({controller:this,attachment:this.get("selection").first()}),this.cropperView.on("image-loaded",this.createCropToolbar,this),this.frame.content.set(this.cropperView)},doCrop:function(a){var d=Math.round;let e=a.get("cropDetails"),f=c.control;if(f.params.flex_width&&f.params.flex_height)if(e.width===e.height)e.width>f.params.flex_width&&(e.dst_width=e.dst_height=f.params.flex_width);else if(e.width>f.params.flex_width||e.height>f.params.flex_height)if(e.width>e.height){let a=e.width/f.params.flex_width;e.dst_width=f.params.flex_width,e.dst_height=d(e.height/a)}else{let a=e.height/f.params.flex_height;e.dst_height=f.params.flex_height,e.dst_width=d(e.width/a)}return"undefined"==typeof e.dst_width&&(e.dst_width=0,e.dst_height=0),wp.ajax.post("tsf_crop_image",{nonce:b.nonce,id:a.get("id"),context:"tsf-image",cropDetails:e})}});e.prototype.control={},c=e},h=(a,b)=>{const d=c.control;let e=parseInt(d.params.width,10),f=parseInt(d.params.height,10);const g=!!parseInt(d.params.flex_width,10),h=!!parseInt(d.params.flex_height,10),j=a.get("width"),k=a.get("height"),l=e/f,m=e,n=f;let o;o=d.params.isFlex?!i(d.params.flex_width,d.params.flex_height,j,k):l===j/k,b.set("control",d.params),b.set("canSkipCrop",o),j/k>l?(f=k,e=f*l):(e=j,f=e/l);let p=(j-e)/2,q=(k-f)/2;const r={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:j,imageHeight:k,minWidth:m>e?e:m,minHeight:n>f?f:n,x1:p,y1:q,x2:e+p,y2:f+q};return d.params.isFlex?h||g?(h&&(r.minHeight=d.params.minHeight,r.maxWidth=j),g&&(r.minWidth=d.params.minWidth,r.maxHeight=k)):r.aspectRatio=e+":"+f:(r.handles="corners",r.aspectRatio=e+":"+f),r},i=(a,b,c,d)=>!(c<=a&&d<=b),j=a=>{const c=a.target.dataset.id||"",d=a.target.dataset.type||"";if(c&&d){const e=document.getElementById(`${c}-select`);e.disabled||(e.textContent=a.target.value.length?b.labels[d].imgChange:b.labels[d].imgSelect)}},k=()=>{document.querySelectorAll(".tsf-set-image-button").forEach(a=>{const b=a.dataset.inputId||"",c=b&&document.getElementById(`${b}-id`),d=b&&document.getElementById(`${b}-url`);c&&0<c.value&&(d&&(d.readOnly=!0),e(a,!1)),d&&(d.addEventListener("change",j),d.dispatchEvent(new Event("change")))})},l=()=>{document.querySelectorAll(".tsf-set-image-button").forEach(a=>{a.addEventListener("click",d)})},m=()=>{document.querySelectorAll(".tsf-remove-image-button").forEach(a=>{a.addEventListener("click",f)})},n=()=>{l(),m(),document.querySelectorAll(".tsf-enable-media-if-js").forEach(a=>{a.disabled=!1,a.classList.remove("tsf-enable-media-if-js")}),k(),s()};let o;const p=()=>{clearTimeout(o),o=setTimeout(n,500)};let q={};const r=b=>{const c=t(b.target.id||""),d=c&&document.getElementById(`${c}-preview`);if(!d)return;c in q&&clearTimeout(q[c]);let e=d.dataset.tsfLoaded||!1;d.dataset.tsfLoaded=1;let f=b.target.value||b.target.placeholder||"";q[c]=setTimeout(()=>{return f.length?void(d.dataset.desc=`<img src=${tsf.escapeString(f)} style="${"max-width:225px;max-height:225px;min-width:60px;min-height:60px;border-radius:3px;display:block;"}" />`,e?a(d).not(":visible").fadeIn(250):a(d).show(),new Image().src=f,tsfTT.triggerUpdate(d)):void(e?a(d).not(":hidden").fadeOut(250):a(d).hide())},e&&f.length?1e3/(115/60):0)},s=()=>{document.querySelectorAll(".tsf-image-preview").forEach(a=>{const b=document.getElementById(`${a.dataset.for}-url`);b&&(b.addEventListener("input",r),b.addEventListener("change",r),b.dispatchEvent(new Event("change")))})},t=a=>a.replace(/-[a-z]+$/,"");return Object.assign({load:()=>{document.body.addEventListener("tsf-ready",n)}},{resetImageEditorActions:p},{l10n:b})}(jQuery),window.tsfMedia.load();
lib/js/post.js CHANGED
@@ -278,7 +278,10 @@ window.tsfPost = function( $ ) {
278
  }
279
 
280
  if ( _defaultIndexOption )
281
- _defaultIndexOption.innerHTML = indexSelect.dataset.defaultI18n.replace( '%s', tsf.decodeEntities( indexDefaultValue ) );
 
 
 
282
 
283
  updateCanonicalPlaceholder();
284
  }
278
  }
279
 
280
  if ( _defaultIndexOption )
281
+ _defaultIndexOption.innerHTML = indexSelect.dataset.defaultI18n.replace(
282
+ '%s',
283
+ tsf.escapeString( tsf.decodeEntities( indexDefaultValue ) )
284
+ );
285
 
286
  updateCanonicalPlaceholder();
287
  }
lib/js/post.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfPost=function(a){const b="undefined"!=typeof tsfPostL10n&&tsfPostL10n,c="autodescription_title",d="autodescription_description",e="autodescription_social_singular",f=()=>{if(!document.querySelector(".tsf-flex"))return;let b={};const c=d=>{let e=d.querySelector(".tsf-flex-nav-tab-inner"),f=d.getElementsByClassName("tsf-flex-nav-name"),g=e.clientWidth<=d.clientWidth;if(g){if(+(d.dataset.displayedNames||1))return;d.dataset.displayedNames=1,a(f).stop(!1,!0).fadeIn(250)}else{if(!+(d.dataset.displayedNames||1))return;d.dataset.displayedNames=0,a(f).hide()}+d.dataset.displayedNames&&(e.clientWidth>d.clientWidth?(a(f).stop(!1,!0).hide(),d.dataset.displayedNames=0):setTimeout(()=>{cancelAnimationFrame(b[d.id]),b[d.id]=requestAnimationFrame(()=>c(d))},7))};window.addEventListener("tsf-flex-resize",a=>{const d=a.detail.target||document.getElementById("tsf-flex-inpost-tabs-wrapper");d&&(b[d.id]=requestAnimationFrame(()=>c(d)))});const d=a=>{window.dispatchEvent(new CustomEvent("tsf-flex-resize",{bubbles:!1,cancelable:!1,detail:{target:a}}))};let e={};const f=new ResizeObserver(a=>{for(const b of a){let a=b.target;cancelAnimationFrame(e[a.id]),e[a.id]=requestAnimationFrame(()=>{a.dataset.lastWidth||=0,+a.clientWidth!=+a.dataset.lastWidth&&(a.dataset.lastWidth=a.clientWidth,d(a))})}});f.observe(document.getElementById("tsf-flex-inpost-tabs-wrapper")),d()},g=()=>{tsfTabs.initStack("tsfSettings",{tabToggledEvent:new CustomEvent("tsf-flex-tab-toggled"),HTMLClasses:{wrapper:"tsf-flex-nav-tab-wrapper",tabRadio:"tsf-flex-nav-tab-radio",tabLabel:"tsf-flex-nav-tab-label",activeTab:"tsf-flex-tab-active",activeTabContent:"tsf-flex-tab-content-active"},fixHistory:!0})},h=()=>{const c=document.getElementById("autodescription_noindex");if(!c)return;const d=document.getElementById("autodescription_canonical"),e=1,f=2;let g,h=0,i="";const j=()=>{clearTimeout(g),g=setTimeout(()=>{d&&(i||=d.placeholder,d.placeholder=h&e||h&f?"":i)},50)},k=a=>{i=a,j()};a(document).on("tsf-updated-gutenberg-link",(a,b)=>k(b));const l=a=>{let b=c.querySelector("[value=\"0\"]"),d="";switch(a){case"password":case"private":d="noindex",h|=e;break;default:case"public":d=c.dataset.defaultUnprotected,h&=~e;}b&&(b.innerHTML=c.dataset.defaultI18n.replace("%s",tsf.decodeEntities(d))),j()};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>l(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}l(b)}),b.states.isPrivate?l("private"):b.states.isProtected?l("password"):l("public");const m=a=>{let b="";switch(+a){case 0:b=c.dataset.defaultUnprotected;break;case-1:b="index";break;case 1:b="noindex";}"noindex"===b?h|=f:h&=~f,j()};c.addEventListener("change",a=>m(a.target.value)),m(c.value)},i=()=>{const d=document.getElementById(c);if(!d)return;tsfTitle.setInputElement(d);const e=JSON.parse(document.getElementById(`tsf-title-data_${c}`)?.dataset.state||0);e&&(tsfTitle.updateStateOf(c,"allowReferenceChange",!e.refTitleLocked),tsfTitle.updateStateOf(c,"defaultTitle",e.defaultTitle),tsfTitle.updateStateOf(c,"addAdditions",e.addAdditions),tsfTitle.updateStateOf(c,"additionValue",e.additionValue),tsfTitle.updateStateOf(c,"additionPlacement",e.additionPlacement),tsfTitle.updateStateOf(c,"hasLegacy",!!(e.hasLegacy||!1)));const f=document.getElementById("autodescription_title_no_blogname");f&&(f.addEventListener("change",a=>{let d=!a.target.checked;b.params.additionsForcedDisabled?d=!1:b.params.additionsForcedEnabled&&(d=!0),tsfTitle.updateStateOf(c,"addAdditions",d)}),f.dispatchEvent(new Event("change")));const g=a=>{let b="";switch(a){case"password":b=tsfTitle.protectedPrefix;break;case"private":b=tsfTitle.privatePrefix;break;default:case"public":b="";}tsfTitle.updateStateOf(c,"prefixValue",b)};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>g(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}g(b)}),b.states.isPrivate?g("private"):b.states.isProtected&&g("password");const h=a=>{a=a?.trim()||"";let b=tsfTitle.stripTitleTags?tsf.stripTags(a):a;tsfTitle.updateStateOf(c,"defaultTitle",b||tsfTitle.untitledTitle)};if(!b.params.isFront){const b=document.querySelector("#titlewrap #title");b&&b.addEventListener("input",a=>h(a.target.value)),a(document).on("tsf-updated-gutenberg-title",(a,b)=>h(b))}tsfTitle.enqueueUnregisteredInputTrigger(c)},j=()=>{const c=document.getElementById(d);if(!c)return;tsfDescription.setInputElement(c);const e=JSON.parse(document.getElementById(`tsf-description-data_${d}`)?.dataset.state||0);e&&(tsfDescription.updateStateOf(d,"allowReferenceChange",!e.refDescriptionLocked),tsfDescription.updateStateOf(d,"defaultDescription",e.defaultDescription.trim()),tsfDescription.updateStateOf(d,"hasLegacy",!!(e.hasLegacy||!1))),tsfDescription.enqueueUnregisteredInputTrigger(d);const f=a=>{let b=tsfDescription.getStateOf(d,"useDefaultDescription"),c=!0;switch(a){case"password":case"private":c=!1;break;default:case"public":c=!0;}c!==b&&tsfDescription.updateStateOf(d,"useDefaultDescription",c)};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>f(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}f(b)}),b.states.isPrivate?f("private"):b.states.isProtected&&f("password")},k=()=>{tsfSocial.setInputInstance(e,c,d);const a=JSON.parse(document.getElementById(`tsf-social-data_${e}`)?.dataset.settings||0);a&&(tsfSocial.updateStateOf(e,"addAdditions",a.og.state.addAdditions),tsfSocial.updateStateOf(e,"defaults",{ogTitle:a.og.state.defaultTitle,twTitle:a.tw.state.defaultTitle,ogDesc:a.og.state.defaultDesc,twDesc:a.tw.state.defaultDesc}),tsfSocial.updateStateOf(e,"inputLocks",{ogTitle:a.og.state?.titleLock||!1,twTitle:a.tw.state?.titleLock||!1,ogDesc:a.og.state?.descLock||!1,twDesc:a.tw.state?.descLock||!1}))},l=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(c),tsfDescription.enqueueUnregisteredInputTrigger(d)};a("#tsf-flex-inpost-tab-general").on("tsf-flex-tab-toggled",b),window.addEventListener("tsf-flex-resize",b)},m=()=>{b.states.isGutenbergPage&&("tsfTT"in window&&tsfTT.addBoundary("#editor"),document.addEventListener("tsf-gutenberg-sidebar-opened",()=>{"tsfTT"in window&&tsfTT.addBoundary(".edit-post-sidebar .components-panel")}))},n=()=>{if(!b.states.isGutenbergPage)return;const c=document.querySelector(".tsf-seo-bar"),f=document.querySelector("#tsf-doing-it-right-wrap .tsf-ajax"),g=document.getElementById("autodescription_socialimage-url"),h=tsfSocial.getInputInstance(e)?.inputs?.ogDesc,i=tsfSocial.getInputInstance(e)?.inputs?.twDesc,j={seobar:!!c,metadescription:!!document.getElementById(d),ogdescription:!!h,twdescription:!!i,imageurl:!!g},k=b=>{b=tsf.convertJSONResponse(b);const h=75;setTimeout(()=>{if("tsfDescription"in window&&tsfDescription.updateStateOf(d,"defaultDescription",b.data.metadescription.trim()),"tsfSocial"in window){const a=tsfSocial.getStateOf(e,"defaults");a.ogDesc=b.data.ogdescription.trim(),a.twDesc=b.data.twdescription.trim(),tsfSocial.updateStateOf(e,"defaults",a)}g&&(g.placeholder=tsf.decodeEntities(b.data.imageurl),g.dispatchEvent(new Event("change"))),"tsfAys"in window&&tsfAys.reset()},h),a(c).fadeOut(h,()=>{f&&tsf.unsetAjaxLoader(f,!0),c.innerHTML=b.data.seobar}).fadeIn(250,()=>{"tsfTT"in window&&tsfTT.triggerReset()})},l=()=>{f&&tsf.unsetAjaxLoader(f,!1)};document.addEventListener("tsf-gutenberg-onsave",()=>{f&&tsf.resetAjaxLoader(f),f&&tsf.setAjaxLoader(f),wp.ajax.send("tsf_update_post_data",{data:{nonce:tsf.l10n.nonces.edit_posts,post_id:b.states.id,get:j},timeout:7e3}).done(k).fail(l)})},o=()=>{h(),i(),j(),k(),l()},p=()=>{f(),g(),m(),n()};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",o),document.body.addEventListener("tsf-ready",p)}},{l10n:b})}(jQuery),window.tsfPost.load();
1
+ 'use strict';window.tsfPost=function(a){const b="undefined"!=typeof tsfPostL10n&&tsfPostL10n,c="autodescription_title",d="autodescription_description",e="autodescription_social_singular",f=()=>{if(!document.querySelector(".tsf-flex"))return;let b={};const c=d=>{let e=d.querySelector(".tsf-flex-nav-tab-inner"),f=d.getElementsByClassName("tsf-flex-nav-name"),g=e.clientWidth<=d.clientWidth;if(g){if(+(d.dataset.displayedNames||1))return;d.dataset.displayedNames=1,a(f).stop(!1,!0).fadeIn(250)}else{if(!+(d.dataset.displayedNames||1))return;d.dataset.displayedNames=0,a(f).hide()}+d.dataset.displayedNames&&(e.clientWidth>d.clientWidth?(a(f).stop(!1,!0).hide(),d.dataset.displayedNames=0):setTimeout(()=>{cancelAnimationFrame(b[d.id]),b[d.id]=requestAnimationFrame(()=>c(d))},7))};window.addEventListener("tsf-flex-resize",a=>{const d=a.detail.target||document.getElementById("tsf-flex-inpost-tabs-wrapper");d&&(b[d.id]=requestAnimationFrame(()=>c(d)))});const d=a=>{window.dispatchEvent(new CustomEvent("tsf-flex-resize",{bubbles:!1,cancelable:!1,detail:{target:a}}))};let e={};const f=new ResizeObserver(a=>{for(const b of a){let a=b.target;cancelAnimationFrame(e[a.id]),e[a.id]=requestAnimationFrame(()=>{a.dataset.lastWidth||=0,+a.clientWidth!=+a.dataset.lastWidth&&(a.dataset.lastWidth=a.clientWidth,d(a))})}});f.observe(document.getElementById("tsf-flex-inpost-tabs-wrapper")),d()},g=()=>{tsfTabs.initStack("tsfSettings",{tabToggledEvent:new CustomEvent("tsf-flex-tab-toggled"),HTMLClasses:{wrapper:"tsf-flex-nav-tab-wrapper",tabRadio:"tsf-flex-nav-tab-radio",tabLabel:"tsf-flex-nav-tab-label",activeTab:"tsf-flex-tab-active",activeTabContent:"tsf-flex-tab-content-active"},fixHistory:!0})},h=()=>{const c=document.getElementById("autodescription_noindex");if(!c)return;const d=document.getElementById("autodescription_canonical"),e=1,f=2;let g,h=0,i="";const j=()=>{clearTimeout(g),g=setTimeout(()=>{d&&(i||=d.placeholder,d.placeholder=h&e||h&f?"":i)},50)},k=a=>{i=a,j()};a(document).on("tsf-updated-gutenberg-link",(a,b)=>k(b));const l=a=>{let b=c.querySelector("[value=\"0\"]"),d="";switch(a){case"password":case"private":d="noindex",h|=e;break;default:case"public":d=c.dataset.defaultUnprotected,h&=~e;}b&&(b.innerHTML=c.dataset.defaultI18n.replace("%s",tsf.escapeString(tsf.decodeEntities(d)))),j()};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>l(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}l(b)}),b.states.isPrivate?l("private"):b.states.isProtected?l("password"):l("public");const m=a=>{let b="";switch(+a){case 0:b=c.dataset.defaultUnprotected;break;case-1:b="index";break;case 1:b="noindex";}"noindex"===b?h|=f:h&=~f,j()};c.addEventListener("change",a=>m(a.target.value)),m(c.value)},i=()=>{const d=document.getElementById(c);if(!d)return;tsfTitle.setInputElement(d);const e=JSON.parse(document.getElementById(`tsf-title-data_${c}`)?.dataset.state||0);e&&(tsfTitle.updateStateOf(c,"allowReferenceChange",!e.refTitleLocked),tsfTitle.updateStateOf(c,"defaultTitle",e.defaultTitle),tsfTitle.updateStateOf(c,"addAdditions",e.addAdditions),tsfTitle.updateStateOf(c,"additionValue",e.additionValue),tsfTitle.updateStateOf(c,"additionPlacement",e.additionPlacement),tsfTitle.updateStateOf(c,"hasLegacy",!!(e.hasLegacy||!1)));const f=document.getElementById("autodescription_title_no_blogname");f&&(f.addEventListener("change",a=>{let d=!a.target.checked;b.params.additionsForcedDisabled?d=!1:b.params.additionsForcedEnabled&&(d=!0),tsfTitle.updateStateOf(c,"addAdditions",d)}),f.dispatchEvent(new Event("change")));const g=a=>{let b="";switch(a){case"password":b=tsfTitle.protectedPrefix;break;case"private":b=tsfTitle.privatePrefix;break;default:case"public":b="";}tsfTitle.updateStateOf(c,"prefixValue",b)};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>g(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}g(b)}),b.states.isPrivate?g("private"):b.states.isProtected&&g("password");const h=a=>{a=a?.trim()||"";let b=tsfTitle.stripTitleTags?tsf.stripTags(a):a;tsfTitle.updateStateOf(c,"defaultTitle",b||tsfTitle.untitledTitle)};if(!b.params.isFront){const b=document.querySelector("#titlewrap #title");b&&b.addEventListener("input",a=>h(a.target.value)),a(document).on("tsf-updated-gutenberg-title",(a,b)=>h(b))}tsfTitle.enqueueUnregisteredInputTrigger(c)},j=()=>{const c=document.getElementById(d);if(!c)return;tsfDescription.setInputElement(c);const e=JSON.parse(document.getElementById(`tsf-description-data_${d}`)?.dataset.state||0);e&&(tsfDescription.updateStateOf(d,"allowReferenceChange",!e.refDescriptionLocked),tsfDescription.updateStateOf(d,"defaultDescription",e.defaultDescription.trim()),tsfDescription.updateStateOf(d,"hasLegacy",!!(e.hasLegacy||!1))),tsfDescription.enqueueUnregisteredInputTrigger(d);const f=a=>{let b=tsfDescription.getStateOf(d,"useDefaultDescription"),c=!0;switch(a){case"password":case"private":c=!1;break;default:case"public":c=!0;}c!==b&&tsfDescription.updateStateOf(d,"useDefaultDescription",c)};a(document).on("tsf-updated-gutenberg-visibility",(a,b)=>f(b));document.querySelector("#visibility .save-post-visibility")?.addEventListener("click",()=>{let b=a("#visibility").find("input:radio:checked").val();if("password"===b){let c=a("#visibility").find("#post_password").val();c&&c.length||(b="public")}f(b)}),b.states.isPrivate?f("private"):b.states.isProtected&&f("password")},k=()=>{tsfSocial.setInputInstance(e,c,d);const a=JSON.parse(document.getElementById(`tsf-social-data_${e}`)?.dataset.settings||0);a&&(tsfSocial.updateStateOf(e,"addAdditions",a.og.state.addAdditions),tsfSocial.updateStateOf(e,"defaults",{ogTitle:a.og.state.defaultTitle,twTitle:a.tw.state.defaultTitle,ogDesc:a.og.state.defaultDesc,twDesc:a.tw.state.defaultDesc}),tsfSocial.updateStateOf(e,"inputLocks",{ogTitle:a.og.state?.titleLock||!1,twTitle:a.tw.state?.titleLock||!1,ogDesc:a.og.state?.descLock||!1,twDesc:a.tw.state?.descLock||!1}))},l=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(c),tsfDescription.enqueueUnregisteredInputTrigger(d)};a("#tsf-flex-inpost-tab-general").on("tsf-flex-tab-toggled",b),window.addEventListener("tsf-flex-resize",b)},m=()=>{b.states.isGutenbergPage&&("tsfTT"in window&&tsfTT.addBoundary("#editor"),document.addEventListener("tsf-gutenberg-sidebar-opened",()=>{"tsfTT"in window&&tsfTT.addBoundary(".edit-post-sidebar .components-panel")}))},n=()=>{if(!b.states.isGutenbergPage)return;const c=document.querySelector(".tsf-seo-bar"),f=document.querySelector("#tsf-doing-it-right-wrap .tsf-ajax"),g=document.getElementById("autodescription_socialimage-url"),h=tsfSocial.getInputInstance(e)?.inputs?.ogDesc,i=tsfSocial.getInputInstance(e)?.inputs?.twDesc,j={seobar:!!c,metadescription:!!document.getElementById(d),ogdescription:!!h,twdescription:!!i,imageurl:!!g},k=b=>{b=tsf.convertJSONResponse(b);const h=75;setTimeout(()=>{if("tsfDescription"in window&&tsfDescription.updateStateOf(d,"defaultDescription",b.data.metadescription.trim()),"tsfSocial"in window){const a=tsfSocial.getStateOf(e,"defaults");a.ogDesc=b.data.ogdescription.trim(),a.twDesc=b.data.twdescription.trim(),tsfSocial.updateStateOf(e,"defaults",a)}g&&(g.placeholder=tsf.decodeEntities(b.data.imageurl),g.dispatchEvent(new Event("change"))),"tsfAys"in window&&tsfAys.reset()},h),a(c).fadeOut(h,()=>{f&&tsf.unsetAjaxLoader(f,!0),c.innerHTML=b.data.seobar}).fadeIn(250,()=>{"tsfTT"in window&&tsfTT.triggerReset()})},l=()=>{f&&tsf.unsetAjaxLoader(f,!1)};document.addEventListener("tsf-gutenberg-onsave",()=>{f&&tsf.resetAjaxLoader(f),f&&tsf.setAjaxLoader(f),wp.ajax.send("tsf_update_post_data",{data:{nonce:tsf.l10n.nonces.edit_posts,post_id:b.states.id,get:j},timeout:7e3}).done(k).fail(l)})},o=()=>{h(),i(),j(),k(),l()},p=()=>{f(),g(),m(),n()};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",o),document.body.addEventListener("tsf-ready",p)}},{l10n:b})}(jQuery),window.tsfPost.load();
lib/js/pt.js CHANGED
@@ -83,13 +83,13 @@ window.tsfPT = function( $ ) {
83
  const nsAction = ( action, taxonomy ) => action + '.tsfShowPrimary' + taxonomy;
84
 
85
  const addInput = ( taxonomy ) => {
86
- let $wrap = $( '#' + taxonomy + 'div' ),
87
- template = inputTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } );
88
  $wrap.append( template );
89
  }
90
  const addHelp = ( taxonomy ) => {
91
- let $wrap = $( '#taxonomy-' + taxonomy ),
92
- template = helpTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } ),
93
  $ulChild = $wrap.children( 'ul:first' );
94
 
95
  if ( $ulChild.length ) {
@@ -101,7 +101,7 @@ window.tsfPT = function( $ ) {
101
  fixHelpPos( taxonomy );
102
  }
103
  const fixHelpPos = ( taxonomy ) => {
104
- let wrap = document.getElementById( 'taxonomy-' + taxonomy ),
105
  tabs = wrap.querySelectorAll( '.tabs-panel' );
106
 
107
  let postbox = wrap.closest( '.postbox' );
@@ -118,9 +118,9 @@ window.tsfPT = function( $ ) {
118
  : 25;
119
 
120
  if ( window.isRtl ) {
121
- wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.left = offset + 'px';
122
  } else {
123
- wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.right = offset + 'px';
124
  }
125
  }
126
  const fixHelpPosOnTabToggle = ( event ) => {
@@ -133,7 +133,7 @@ window.tsfPT = function( $ ) {
133
  return selector;
134
  }
135
  const setPostValue = ( taxonomy, value ) => {
136
- let element = document.getElementById( 'autodescription[_primary_term_' + taxonomy + ']' );
137
  if ( element && element instanceof Element )
138
  element.value = value || 0;
139
  }
@@ -142,10 +142,10 @@ window.tsfPT = function( $ ) {
142
  if ( ! reset && box$[ taxonomy ] )
143
  return box$[ taxonomy ];
144
 
145
- box$[ taxonomy ] = $( '#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop' );
146
  return box$[ taxonomy ];
147
  }
148
- const getInputWithVal = ( taxonomy, value ) => input$[ taxonomy ].filter( '[value="' + value + '"]' );
149
 
150
  const makePrimary = ( taxonomy, value ) => {
151
  let $label = getInputWithVal( taxonomy, value ).closest( 'label' );
@@ -285,7 +285,7 @@ window.tsfPT = function( $ ) {
285
  }
286
  }
287
  const initActions = ( taxonomy ) => {
288
- let data = { 'taxonomy': taxonomy },
289
  $box = getBox( taxonomy ),
290
  $div = $( `#${taxonomy}div` ),
291
  $tabs = $( `#${taxonomy}-tabs` ),
83
  const nsAction = ( action, taxonomy ) => action + '.tsfShowPrimary' + taxonomy;
84
 
85
  const addInput = ( taxonomy ) => {
86
+ let $wrap = $( `#${taxonomy}div` ),
87
+ template = inputTemplate( { taxonomy: taxonomies[ taxonomy ] } );
88
  $wrap.append( template );
89
  }
90
  const addHelp = ( taxonomy ) => {
91
+ let $wrap = $( `#taxonomy-${taxonomy}` ),
92
+ template = helpTemplate( { taxonomy: taxonomies[ taxonomy ] } ),
93
  $ulChild = $wrap.children( 'ul:first' );
94
 
95
  if ( $ulChild.length ) {
101
  fixHelpPos( taxonomy );
102
  }
103
  const fixHelpPos = ( taxonomy ) => {
104
+ let wrap = document.getElementById( `taxonomy-${taxonomy}` ),
105
  tabs = wrap.querySelectorAll( '.tabs-panel' );
106
 
107
  let postbox = wrap.closest( '.postbox' );
118
  : 25;
119
 
120
  if ( window.isRtl ) {
121
+ wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.left = `${offset}px`;
122
  } else {
123
+ wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.right = `${offset}px`;
124
  }
125
  }
126
  const fixHelpPosOnTabToggle = ( event ) => {
133
  return selector;
134
  }
135
  const setPostValue = ( taxonomy, value ) => {
136
+ let element = document.getElementById( `autodescription[_primary_term_${taxonomy}]` );
137
  if ( element && element instanceof Element )
138
  element.value = value || 0;
139
  }
142
  if ( ! reset && box$[ taxonomy ] )
143
  return box$[ taxonomy ];
144
 
145
+ box$[ taxonomy ] = $( `#${taxonomy}checklist, #${taxonomy}checklist-pop` );
146
  return box$[ taxonomy ];
147
  }
148
+ const getInputWithVal = ( taxonomy, value ) => input$[ taxonomy ].filter( `[value="${value}"]` );
149
 
150
  const makePrimary = ( taxonomy, value ) => {
151
  let $label = getInputWithVal( taxonomy, value ).closest( 'label' );
285
  }
286
  }
287
  const initActions = ( taxonomy ) => {
288
+ let data = { taxonomy },
289
  $box = getBox( taxonomy ),
290
  $div = $( `#${taxonomy}div` ),
291
  $tabs = $( `#${taxonomy}-tabs` ),
lib/js/pt.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfPT=function(a){const b="undefined"!=typeof tsfPTL10n&&tsfPTL10n,c=()=>{if(!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","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]}),g=d.children("ul:first");g.length?a(f).insertAfter(g):d.prepend(f),tsfTT.triggerReset(),o(b)},o=a=>{let b=document.getElementById("taxonomy-"+a),c=b.querySelectorAll(".tabs-panel"),d=b.closest(".postbox");if(!(d&&d.classList.contains("closed"))){let a=[].slice.call(c).filter(a=>0<a.offsetWidth||0<a.offsetHeight||0<a.getClientRects().length)[0];if(a){let c=a.scrollHeight>a.clientHeight?a.offsetWidth-a.clientWidth+25-2:25;window.isRtl?b.querySelector(".tsf-primary-term-selector-help-wrap").style.left=c+"px":b.querySelector(".tsf-primary-term-selector-help-wrap").style.right=c+"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=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((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 Object.assign({load:()=>{document.body.addEventListener("tsf-onload",c)}},{l10n:b})}(jQuery),window.tsfPT.load();
1
+ 'use strict';window.tsfPT=function(a){const b="undefined"!=typeof tsfPTL10n&&tsfPTL10n,c=()=>{if(!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","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]}),g=d.children("ul:first");g.length?a(f).insertAfter(g):d.prepend(f),tsfTT.triggerReset(),o(b)},o=a=>{let b=document.getElementById(`taxonomy-${a}`),c=b.querySelectorAll(".tabs-panel"),d=b.closest(".postbox");if(!(d&&d.classList.contains("closed"))){let a=[].slice.call(c).filter(a=>0<a.offsetWidth||0<a.offsetHeight||0<a.getClientRects().length)[0];if(a){let c=a.scrollHeight>a.clientHeight?a.offsetWidth-a.clientWidth+25-2:25;window.isRtl?b.querySelector(".tsf-primary-term-selector-help-wrap").style.left=`${c}px`:b.querySelector(".tsf-primary-term-selector-help-wrap").style.right=`${c}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=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((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 Object.assign({load:()=>{document.body.addEventListener("tsf-onload",c)}},{l10n:b})}(jQuery),window.tsfPT.load();
lib/js/settings.js CHANGED
@@ -465,9 +465,9 @@ window.tsfSettings = function( $ ) {
465
  let examples = document.querySelectorAll( '.tsf-site-title-js' ),
466
  newVal = tsf.decodeEntities( tsf.sDoubleSpace( event.target.value.trim() ) );
467
 
468
- newVal = newVal || tsf.decodeEntities( event.target.placeholder );
469
 
470
- tsfTitle.updateStateOf( homeTitleId, 'defaultTitle', newVal );
471
  tsfTitle.updateStateAll( 'additionValue', newVal, homeTitleId );
472
 
473
  let htmlVal = tsf.escapeString( newVal );
@@ -495,6 +495,8 @@ window.tsfSettings = function( $ ) {
495
  taglineInput = document.getElementById( _getSettingsId( 'homepage_title_tagline' ) ),
496
  taglineToggle = document.getElementById( _getSettingsId( 'homepage_tagline' ) );
497
 
 
 
498
  tsfTitle.setInputElement( titleInput );
499
 
500
  const state = JSON.parse(
@@ -803,7 +805,7 @@ window.tsfSettings = function( $ ) {
803
  * @access private
804
  *
805
  * @param {string|undefined} postType
806
- * @return {Object<string,{label:string,url:string,hasPosts:boolean}>}
807
  */
808
  const _getPtaData = () => _cachedPtaData ||= JSON.parse(
809
  document.getElementById( 'tsf-post-type-archive-data' )?.dataset.postTypes || 0
@@ -960,10 +962,12 @@ window.tsfSettings = function( $ ) {
960
  */
961
  const _initPtaTitleSettings = postType => {
962
 
963
- const _titleId = _getPtaInputId( postType, 'doctitle' ),
964
- _inputEl = document.getElementById( _titleId );
 
 
965
 
966
- tsfTitle.setInputElement( _inputEl );
967
 
968
  const state = JSON.parse(
969
  document.getElementById( `tsf-title-data_${_titleId}` )?.dataset.state || 0
@@ -993,7 +997,7 @@ window.tsfSettings = function( $ ) {
993
 
994
  tsfTitle.updateStateOf( _titleId, 'showPrefix', showPrefix );
995
  }
996
- _inputEl.addEventListener( 'input', updateTitlePrefix );
997
 
998
  /**
999
  * Updates title additions, based on singular settings change.
@@ -1048,9 +1052,12 @@ window.tsfSettings = function( $ ) {
1048
  */
1049
  const _initPtaDescriptionSettings = postType => {
1050
 
1051
- const _descId = _getPtaInputId( postType, 'description' );
 
 
 
1052
 
1053
- tsfDescription.setInputElement( document.getElementById( _descId ) );
1054
 
1055
  const state = JSON.parse(
1056
  document.getElementById( `tsf-description-data_${_descId}` )?.dataset.state || 0
465
  let examples = document.querySelectorAll( '.tsf-site-title-js' ),
466
  newVal = tsf.decodeEntities( tsf.sDoubleSpace( event.target.value.trim() ) );
467
 
468
+ newVal ||= tsf.decodeEntities( event.target.placeholder );
469
 
470
+ tsfTitle.updateStateOf( homeTitleId, 'defaultTitle', newVal );
471
  tsfTitle.updateStateAll( 'additionValue', newVal, homeTitleId );
472
 
473
  let htmlVal = tsf.escapeString( newVal );
495
  taglineInput = document.getElementById( _getSettingsId( 'homepage_title_tagline' ) ),
496
  taglineToggle = document.getElementById( _getSettingsId( 'homepage_tagline' ) );
497
 
498
+ if ( ! titleInput ) return;
499
+
500
  tsfTitle.setInputElement( titleInput );
501
 
502
  const state = JSON.parse(
805
  * @access private
806
  *
807
  * @param {string|undefined} postType
808
+ * @return {{label:string,url:string,hasPosts:boolean}}
809
  */
810
  const _getPtaData = () => _cachedPtaData ||= JSON.parse(
811
  document.getElementById( 'tsf-post-type-archive-data' )?.dataset.postTypes || 0
962
  */
963
  const _initPtaTitleSettings = postType => {
964
 
965
+ const _titleId = _getPtaInputId( postType, 'doctitle' ),
966
+ titleInput = document.getElementById( _titleId );
967
+
968
+ if ( ! titleInput ) return;
969
 
970
+ tsfTitle.setInputElement( titleInput );
971
 
972
  const state = JSON.parse(
973
  document.getElementById( `tsf-title-data_${_titleId}` )?.dataset.state || 0
997
 
998
  tsfTitle.updateStateOf( _titleId, 'showPrefix', showPrefix );
999
  }
1000
+ titleInput.addEventListener( 'input', updateTitlePrefix );
1001
 
1002
  /**
1003
  * Updates title additions, based on singular settings change.
1052
  */
1053
  const _initPtaDescriptionSettings = postType => {
1054
 
1055
+ const _descId = _getPtaInputId( postType, 'description' ),
1056
+ descInput = document.getElementById( _descId );
1057
+
1058
+ if ( ! descInput ) return;
1059
 
1060
+ tsfDescription.setInputElement( descInput );
1061
 
1062
  const state = JSON.parse(
1063
  document.getElementById( `tsf-description-data_${_descId}` )?.dataset.state || 0
lib/js/settings.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfSettings=function(a){const b="undefined"!=typeof tsfSettingsL10n&&tsfSettingsL10n,c=a=>`autodescription-site-settings[${a}]`,d=tsf.dispatchAtInteractive,e=()=>{document.getElementById(c("display_character_counter"))?.addEventListener("click",a=>{document.querySelectorAll(".tsf-counter-wrap").forEach(b=>{b.style.display=a.target.checked?"":"none"}),a.target.checked&&tsfC.triggerCounterUpdate()});document.getElementById(c("display_pixel_counter"))?.addEventListener("click",a=>{document.querySelectorAll(".tsf-pixel-counter-wrap").forEach(b=>{b.style.display=a.target.checked?"":"none"}),a.target.checked&&tsfC.triggerCounterUpdate()});const a=new Set,b=new Set,e=new Set,f=new Set;document.body.addEventListener("tsf-post-type-support-changed",()=>{let b=document.querySelectorAll(".tsf-excluded-taxonomies"),c=!1;b.forEach(b=>{const d=b.name.split(/(?:.+\[)(.+?)(?:])/).join(""),f=JSON.parse(b.dataset?.postTypes||0)||[],g=f&&f.every(b=>a.has(b));g?(!e.has(d)&&(c=!0),e.add(d)):e.has(d)&&(e.delete(d),c=!0),h(),c&&i(d)})});const g=new Map;document.body.addEventListener("tsf-taxonomy-support-changed",()=>{g.set("excludedTaxonomiesAll",new Set(f)),g.set("excludedTaxonomies",new Set(b)),g.set("excludedPtTaxonomies",new Set(e))});const h=()=>{f.clear(),b.forEach(a=>f.add(a)),e.forEach(a=>f.add(a))},i=a=>{document.body.dispatchEvent(new CustomEvent("tsf-taxonomy-support-changed",{detail:{taxonomy:a,set:b,setPt:e,setAll:f}}))},j=b=>{document.body.dispatchEvent(new CustomEvent("tsf-post-type-support-changed",{detail:{postType:b,set:a}}))};let k=!1;const l=b=>{if(b.target.name){let c=b.target.name.split(/(?:.+\[)(.+?)(?:])/).join("");b.target.checked?(a.add(c),j(c)):k&&(a.delete(c),j(c))}},m=a=>{if(a.target.name){let c=a.target.name.split(/(?:.+\[)(.+?)(?:])/).join("");a.target.checked?(b.add(c),h(),i(c)):k&&(b.delete(c),h(),i(c))}};document.querySelectorAll(".tsf-excluded-post-types").forEach(a=>{a.addEventListener("change",l),d(a,"change")}),document.querySelectorAll(".tsf-excluded-taxonomies").forEach(a=>{a.addEventListener("change",m),d(a,"change")}),k=!0},f=()=>{document.querySelectorAll(".tsf-color-picker").forEach(b=>{let c=a(b),d="",e=c.data("tsf-default-color");c.wpColorPicker({defaultColor:e,width:238,change:()=>{d=c.wpColorPicker("color"),""===d&&(d=e),b.value=e,tsfAys.registerChange()},clear:()=>{e.length&&(b.value=e,c.closest(".wp-picker-container").find(".wp-color-result").css("backgroundColor",e)),tsfAys.registerChange()},palettes:!1})})},g=()=>{const a=document.getElementById(c("title_rem_additions")),b=document.getElementById(c("social_title_rem_additions")),e=wp.template("tsf-disabled-title-additions-help-social")();a&&(a.addEventListener("change",a=>{a.target.checked?(document.querySelectorAll(".tsf-title-additions-js").forEach(a=>a.style.display="none"),b&&(b.dataset.disabledWarning=1,b.closest("label").insertAdjacentHTML("beforeend",e),tsfTT.triggerReset())):(document.querySelectorAll(".tsf-title-additions-js").forEach(a=>a.style.display="inline"),b?.dataset.disabledWarning&&b.closest("label").querySelector(".tsf-title-additions-warning-social")?.remove()),document.body.dispatchEvent(new CustomEvent("tsf-update-title-rem-additions",{detail:{removeAdditions:!!a.target.checked}}))}),d(a,"change"));const f=a=>{let b;document.getElementsByName(a.target.name).forEach(a=>{a.checked&&(b=a.value)});const d="left"===b,e="tsf-title-additions-location-hidden";document.querySelectorAll(".tsf-title-additions-example-left").forEach(a=>{a.classList.toggle(e,!d),a.classList.remove("hidden")}),document.querySelectorAll(".tsf-title-additions-example-right").forEach(a=>{a.classList.toggle(e,d),a.classList.remove("hidden")}),tsfTitle.updateStateAll("additionPlacement",d?"before":"after",c("homepage_title"))};document.querySelectorAll("#tsf-title-location input").forEach(a=>{a.addEventListener("change",f),a.checked&&d(a,"change")});const g=document.getElementById(c("title_rem_prefixes"));g&&(g.addEventListener("change",a=>{const b=!a.target.checked,d="tsf-title-tax-prefix-hidden";document.querySelectorAll(".tsf-title-tax-prefix").forEach(a=>{a.classList.toggle(d,!b),a.classList.remove("hidden")}),document.querySelectorAll(".tsf-title-tax-noprefix").forEach(a=>{a.classList.toggle(d,b),a.classList.remove("hidden")}),tsfTitle.updateStateAll("showPrefix",b,c("homepage_title"))}),d(g,"change"));const h=a=>{const b=tsf.decodeEntities(a.target.dataset.entity),c="tsf-title-separator-active";document.querySelectorAll(".tsf-sep-js").forEach(a=>{a.textContent=` ${b} `}),window.dispatchEvent(new CustomEvent("tsf-title-sep-updated",{detail:{separator:b}}));let d=document.querySelector(`.${c}`);d&&d.classList.remove(c,"tsf-no-focus-ring");let e=document.querySelector(`label[for="${a.target.id}"]`);e&&e.classList.add(c)};document.querySelectorAll("#tsf-title-separator input").forEach(a=>{a.addEventListener("click",h)});const i=a=>{a.target.classList.add("tsf-no-focus-ring")};document.querySelectorAll("#tsf-title-separator label").forEach(a=>{a.addEventListener("click",i)});const j=c("homepage_title"),k=document.getElementById(c("site_title"));k&&(k.addEventListener("input",a=>{let b=document.querySelectorAll(".tsf-site-title-js"),c=tsf.decodeEntities(tsf.sDoubleSpace(a.target.value.trim()));c=c||tsf.decodeEntities(a.target.placeholder),tsfTitle.updateStateOf(j,"defaultTitle",c),tsfTitle.updateStateAll("additionValue",c,j);let d=tsf.escapeString(c);b.forEach(a=>{a.innerHTML=d})}),d(k,"input"))},h=()=>{const a=c("homepage_title"),e=document.getElementById(a),f=document.getElementById(c("homepage_title_tagline")),g=document.getElementById(c("homepage_tagline"));tsfTitle.setInputElement(e);const h=JSON.parse(document.getElementById(`tsf-title-data_${a}`)?.dataset.state||0);tsfTitle.updateStateOf(a,"allowReferenceChange",!h.refTitleLocked),tsfTitle.updateStateOf(a,"defaultTitle",h.defaultTitle),tsfTitle.updateStateOf(a,"addAdditions",h.addAdditions),tsfTitle.updateStateOf(a,"useSocialTagline",!!(h.useSocialTagline||!1)),tsfTitle.updateStateOf(a,"additionValue",h.additionValue),tsfTitle.updateStateOf(a,"additionPlacement",h.additionPlacement),tsfTitle.updateStateOf(a,"hasLegacy",!!(h.hasLegacy||!1)),tsfTitle.enqueueUnregisteredInputTrigger(a);const i=b=>{let c="left"===b.target.value?"before":"after";tsfTitle.updateStateOf(a,"additionPlacement",c)};document.querySelectorAll("#tsf-home-title-location input").forEach(a=>{a.addEventListener("change",i),d(a,"change")});const j=b=>{let c=tsfTitle.getStateOf(a,"prefixValue"),d="";switch(b){case"password":d=tsfTitle.protectedPrefix;break;case"private":d=tsfTitle.privatePrefix;break;default:case"public":d="";}d!==c&&tsfTitle.updateStateOf(a,"prefixValue",d)};b.states.isFrontPrivate?j("private"):b.states.isFrontProtected&&j("password");e.addEventListener("input",b=>{let c=document.querySelectorAll(".tsf-custom-title-js"),d=tsf.decodeEntities(tsf.sDoubleSpace(b.target.value.trim()));d.length?(d=tsf.escapeString(d),c.forEach(a=>a.innerHTML=d)):(d=tsf.escapeString(tsf.decodeEntities(tsfTitle.getStateOf(a,"defaultTitle"))),c.forEach(a=>a.innerHTML=d))}),d(e,"input");let k;const l=()=>{clearTimeout(k),k=setTimeout(()=>{let b=tsfTitle.getStateOf(a,"additionValue");b=tsf.decodeEntities(tsf.sDoubleSpace(b.trim())),b.length&&tsfTitle.getStateOf(a,"addAdditions")?(document.querySelectorAll(".tsf-custom-tagline-js").forEach(a=>{a.innerHTML=tsf.escapeString(b)}),document.querySelectorAll(".tsf-custom-blogname-js").forEach(a=>{a.style.display=null})):document.querySelectorAll(".tsf-custom-blogname-js").forEach(a=>{a.style.display="none"})},1e3/60)};f.addEventListener("input",()=>{let b=f.value.trim();b.length||(b=f.placeholder||""),b=tsf.escapeString(tsf.decodeEntities(b.trim())),tsfTitle.updateStateOf(a,"additionValue",b),l()}),d(f,"input");g.addEventListener("change",b=>{let c=!1;b.target.checked?(c=!0,f.readOnly=!1):(c=!1,f.readOnly=!0),tsfTitle.updateStateOf(a,"addAdditions",c),l()}),d(g,"change");window.addEventListener("tsf-title-sep-updated",a=>{tsfTitle.updateStateAll("separator",a.detail.separator)})},i=()=>{const a=c("homepage_description");tsfDescription.setInputElement(document.getElementById(a));const b=JSON.parse(document.getElementById(`tsf-description-data_${a}`)?.dataset.state||0);b&&(tsfDescription.updateStateOf(a,"defaultDescription",b.defaultDescription.trim()),tsfDescription.updateStateOf(a,"hasLegacy",!!(b.hasLegacy||!1))),tsfDescription.enqueueUnregisteredInputTrigger(a)},j=()=>{const a="homepage_social_settings";tsfSocial.setInputInstance(a,c("homepage_title"),c("homepage_description"));const b=JSON.parse(document.getElementById(`tsf-social-data_${a}`)?.dataset.settings||0);b&&(tsfSocial.updateStateOf(a,"addAdditions",b.og.state.addAdditions),tsfSocial.updateStateOf(a,"defaults",{ogTitle:b.og.state.defaultTitle,twTitle:b.tw.state.defaultTitle,ogDesc:b.og.state.defaultDesc,twDesc:b.tw.state.defaultDesc}),tsfSocial.updateStateOf(a,"placeholderLocks",{ogTitle:b.og.state?.titlePhLock||!1,twTitle:b.tw.state?.titlePhLock||!1,ogDesc:b.og.state?.descPhLock||!1,twDesc:b.tw.state?.descPhLock||!1}))},k=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(c("homepage_title")),tsfDescription.enqueueUnregisteredInputTrigger(c("homepage_description"))};a(document).on("postbox-toggled",(a,c)=>{if("autodescription-homepage-settings"===c.id){let a=c.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&b()}}),document.getElementById("tsf-homepage-tab-general")?.addEventListener("tsf-tab-toggled",b)},l=(a,b)=>`${c("pta")}[${a}][${b}]`;let m;const n=()=>m||=JSON.parse(document.getElementById("tsf-post-type-archive-data")?.dataset.postTypes||0)||{},o=()=>{const a=n(),b=Object.keys(a).length;switch(!0){case 1<b:p();case 0<b:q();break;default:}for(const b in a)r(b),s(b),t(b),u(b),v(b)},p=()=>{const a=n(),b=document.getElementById("tsf-post-type-archive-selector"),c=document.createElement("option"),e=document.getElementById("tsf-post-type-archive-header-wrap");e&&(e.style.display=null);(()=>{for(const d in a){let e=c.cloneNode();e.value=tsf.escapeString(d),e.innerHTML=tsf.escapeString(a[d].label),b?.appendChild(e)}})(),document.querySelectorAll(".tsf-post-type-header").forEach(a=>a.classList.add("hidden"));let f,g;const h=a=>{clearTimeout(f),f=setTimeout(()=>{g&&e?.removeChild(g),document.querySelectorAll(".tsf-post-type-archive-wrap").forEach(b=>{a.target.value===b.dataset.postType?(b.style.display=null,g=b.querySelector(".tsf-post-type-archive-details")?.cloneNode(!0)):b.style.display="none",b.classList.remove("hide-if-tsf-js")}),g&&e?.appendChild(g),document.body.dispatchEvent(new CustomEvent("tsf-post-type-archive-switched",{detail:{postType:a.target.value,hasKompaanChocolateBananaBeer:!1}}))},1e3/60)};b&&(b.addEventListener("change",h),d(b,"change"))},q=()=>{document.body.addEventListener("tsf-post-type-support-changed",a=>{const{postType:b,set:c}=a.detail,d=document.querySelector(`.tsf-post-type-archive-wrap[data-post-type="${b}"]`),e=c.has(b);d?.querySelector(".tsf-post-type-archive-if-excluded")?.classList.toggle("hidden",!e),d?.querySelector(".tsf-post-type-archive-if-not-excluded")?.classList.toggle("hidden",e),document.body.dispatchEvent(new CustomEvent("tsf-post-type-archive-switched",{detail:{postType:b}}))})},r=a=>{const b=l(a,"doctitle"),e=document.getElementById(b);tsfTitle.setInputElement(e);const f=JSON.parse(document.getElementById(`tsf-title-data_${b}`)?.dataset.state||0);f&&(tsfTitle.updateStateOf(b,"defaultTitle",f.defaultTitle),tsfTitle.updateStateOf(b,"addAdditions",f.addAdditions),tsfTitle.updateStateOf(b,"useSocialTagline",!!(f.useSocialTagline||!1)),tsfTitle.updateStateOf(b,"additionValue",f.additionValue),tsfTitle.updateStateOf(b,"additionPlacement",f.additionPlacement),tsfTitle.updateStateOf(b,"prefixValue",f.prefixValue),tsfTitle.updateStateOf(b,"showPrefix",f.showPrefix));e.addEventListener("input",a=>{let d=!a.target.value.trim().length;document.getElementById(c("title_rem_prefixes"))?.checked&&(d=!1),tsfTitle.updateStateOf(b,"showPrefix",d)});const g=wp.template("tsf-disabled-title-additions-help")(),h=document.getElementById(l(a,"title_no_blog_name"));h&&(document.body.addEventListener("tsf-update-title-rem-additions",a=>{const{removeAdditions:b}=a.detail;h.disabled=b,b?(h.closest("label").insertAdjacentHTML("beforeend",g),tsfTT.triggerReset()):h.closest("label").querySelector(".tsf-title-additions-warning")?.remove(),h.dispatchEvent(new Event("change"))}),h.addEventListener("change",a=>{let d=!a.target.checked;document.getElementById(c("title_rem_additions"))?.checked&&(d=!1),tsfTitle.updateStateOf(b,"addAdditions",d)}),d(h,"change")),tsfTitle.enqueueUnregisteredInputTrigger(b)},s=a=>{const b=l(a,"description");tsfDescription.setInputElement(document.getElementById(b));const c=JSON.parse(document.getElementById(`tsf-description-data_${b}`)?.dataset.state||0);c&&tsfDescription.updateStateOf(b,"defaultDescription",c.defaultDescription.trim()),tsfDescription.enqueueUnregisteredInputTrigger(b)},t=a=>{const b=`pta_social_settings_${a}`,c=JSON.parse(document.getElementById(`tsf-social-data_${b}`)?.dataset.settings||0);tsfSocial.setInputInstance(b,l(a,"doctitle"),l(a,"description")),tsfSocial.updateStateOf(b,"addAdditions",c.og.state.addAdditions),tsfSocial.updateStateOf(b,"defaults",{ogTitle:c.og.state.defaultTitle,twTitle:c.tw.state.defaultTitle,ogDesc:c.og.state.defaultDesc,twDesc:c.tw.state.defaultDesc})},u=a=>{const b={site:new Map,pt:new Map},c=c=>{let d=!1;return"noindex"===c&&(d=!n()[a].hasPosts),d||b.site.get(c)||b.pt.get(c)},d=b=>{const d=document.getElementById(l(a,b)),e=d?.querySelector("[value=\"0\"]"),f=d?.dataset||{};let g=f.defaultI18n?.replace("%s",tsf.decodeEntities(c(b)?f.defaultOff:f.defaultOn));g!==e.innerHTML&&(e.innerHTML=g,d.dispatchEvent(new Event("change")))};document.body.addEventListener("tsf-post-type-robots-changed",c=>{const{postType:e,robotsType:f,set:g}=c.detail;a!==e||(b.pt.set(f,g.has(a)),d(f))}),document.body.addEventListener("tsf-site-robots-changed",a=>{const{checked:c,robotsType:e}=a.detail;b.site.set(e,!!c),d(e)}),["noindex","nofollow","noarchive"].forEach(a=>{d(a)});const e=document.getElementById(l(a,"canonical")),f=document.getElementById(l(a,"noindex")),g=b=>{let d="",f="";0===b?d=c("noindex")?"noindex":"index":-1===b?d="index":1===b?d="noindex":void 0;f="noindex"==d?"":n()[a].url,e.placeholder=f};e&&f&&(f.addEventListener("change",a=>g(+a.target.value)),g(+f.value))},v=b=>{const c=()=>{tsfTitle.enqueueUnregisteredInputTrigger(l(b,"doctitle")),tsfDescription.enqueueUnregisteredInputTrigger(l(b,"description"))};a(document).on("postbox-toggled",(a,b)=>{if("autodescription-post-type-archive-settings"===b.id){let a=b.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&c()}});document.body.addEventListener("tsf-post-type-archive-switched",a=>{a.detail?.postType===b&&c()}),document.getElementById(`tsf-post_type_archive_${b}-tab-general`)?.addEventListener("tsf-tab-toggled",c)},w=()=>{const a=document.getElementById(c("social_title_rem_additions"));a&&(a.addEventListener("change",a=>{a.target.checked?tsfSocial.updateStateAll("addAdditions",!1):tsfSocial.updateStateAll("addAdditions",!0)}),d(a,"change"))},x=()=>{const a=document.getElementById(c("set_copyright_directives"));if(a){const b=["max_snippet_length","max_image_preview","max_video_preview"].map(a=>document.getElementById(c(a))),e="tsf-toggle-directives-surrogate";a.addEventListener("change",a=>{a.target.checked?(b.forEach(a=>a.disabled=!1),document.querySelectorAll(`.${e}`).forEach(a=>a.remove())):b.forEach(a=>{a.disabled=!0;let b=document.createElement("input");b.type="hidden",b.name=a.name||"",b.value=a.value||0,b.classList.add(e),a.insertAdjacentElement("afterend",b)})}),d(a,"change")}const b={},e={};[b,e].forEach(a=>{a.noindex=new Set,a.nofollow=new Set,a.noarchive=new Set});const f=(a,c)=>{document.body.dispatchEvent(new CustomEvent("tsf-post-type-robots-changed",{detail:{postType:a,robotsType:c,set:b[c]}}))},g=(a,b)=>{document.body.dispatchEvent(new CustomEvent("tsf-taxonomy-robots-changed",{detail:{taxonomy:a,robotsType:b,set:e[b]}}))},h=(a,b)=>{document.body.dispatchEvent(new CustomEvent("tsf-site-robots-changed",{detail:{checked:a,robotsType:b}}))},i=wp.template("tsf-robots-pt-help")(),j=(a,b,d)=>{let e=document.getElementById(`${c(`${b}_taxonomies`)}[${a}]`);d?(e.closest("label").insertAdjacentHTML("beforeend",i),tsfTT.triggerReset()):e.closest("label").querySelector(".tsf-taxonomy-from-pt-robots-warning")?.remove(),n(a)},k=a=>{const c=document.querySelectorAll(`.tsf-robots-taxonomies[data-robots="${a}"]`);let d=!1;c.forEach(c=>{let f=c.name.split(/(?:.+\[)(.+?)(?:])/).join("");const h=JSON.parse(c.dataset.postTypes||0),i=h&&h.every(c=>b[a].has(c));i?(!e[a].has(f)&&(d=!0),e[a].add(f)):e[a].has(f)&&(e[a].delete(f),d=!0),d&&g(f,a)})},l={noindex:new Map,nofollow:new Map,noarchive:new Map},m=(a,b)=>l[b].get(a)||new Set;document.body.addEventListener("tsf-taxonomy-robots-changed",a=>{const{taxonomy:b,robotsType:c}=a.detail;m("robotsPtTaxonomies",c).size!==e[c].size&&j(b,c,e[c].has(b)),l[c].set("robotsPtTaxonomies",new Set(e[c]))});document.body.addEventListener("tsf-post-type-robots-changed",a=>{k(a.detail.robotsType)});const n=a=>{for(let b in e)if(e[b].has(a)){let d=document.getElementById(`${c(`${b}_taxonomies`)}[${a}]`),e=d.closest("label").querySelector(".tsf-taxonomy-from-pt-robots-warning");e.style.display=d.dataset.disabledWarning?"none":""}};document.body.addEventListener("tsf-taxonomy-support-changed",a=>n(a.detail.taxonomy));let o=!1;const p=a=>{let c=a.target?.name.split(/(?:.+\[)(.+?)(?:])/).join(""),d=a.target?.dataset.robots;a.target.checked?(b[d].add(c),f(c,d)):o&&(b[d].delete(c),f(c,d))};document.querySelectorAll(".tsf-robots-post-types").forEach(a=>{a.addEventListener("change",p),d(a,"change")});const q=a=>{let b=a.target?.dataset.robots,c=a.target.checked;c?h(c,b):o&&h(c,b)};document.querySelectorAll(".tsf-robots-site").forEach(a=>{a.addEventListener("change",q),d(a,"change")}),o=!0},y=()=>{const a=a=>tsf.escapeString(`tsf-disabled-post-type-input-clone-${a}`),b=wp.template("tsf-disabled-post-type-help")(),d=a=>[document.getElementById(`${c("noindex_post_types")}[${a}]`),document.getElementById(`${c("nofollow_post_types")}[${a}]`),document.getElementById(`${c("noarchive_post_types")}[${a}]`)].filter(a=>a);document.body.addEventListener("tsf-post-type-support-changed",c=>{const{postType:e,set:f}=c.detail;f.has(e)?(d(e).forEach(c=>{if(c){let d=c.cloneNode(!0);d.type="hidden",d.value=c.checked?c.value:"",d.id+="-cloned",d.classList.add(a(e)),c.disabled=!0,c.dataset.disabledWarning=1;const f=c.closest("label");f.insertAdjacentHTML("beforeend",b),f.append(d)}}),tsfTT.triggerReset()):d(e).forEach(b=>{b&&b.dataset.disabledWarning&&(b.closest("label").querySelector(".tsf-post-type-warning").remove(),document.querySelectorAll(`.${a(e)}`).forEach(a=>{a.remove()}),b.disabled=!1,b.dataset.disabledWarning="")})});const e=wp.template("tsf-disabled-taxonomy-help")(),f=wp.template("tsf-disabled-taxonomy-from-pt-help")(),g=a=>tsf.escapeString(`tsf-disabled-taxonomy-input-clone-${a}`),h=a=>[document.getElementById(`${c("noindex_taxonomies")}[${a}]`),document.getElementById(`${c("nofollow_taxonomies")}[${a}]`),document.getElementById(`${c("noarchive_taxonomies")}[${a}]`)].filter(a=>a);document.body.addEventListener("tsf-taxonomy-support-changed",a=>{const{taxonomy:b,set:d,setPt:i,setAll:j}=a.detail;j.has(b)?(h(b).forEach(a=>{if(a){let c=a.cloneNode(!0);c.type="hidden",c.value=a.checked?a.value:"",c.id+="-cloned",c.classList.add(g(b)),a.disabled=!0,a.dataset.disabledWarning=1;const d=a.closest("label");d.querySelector(".tsf-taxonomy-warning")||d.insertAdjacentHTML("beforeend",e),d.querySelector(g(b))||d.append(c)}}),tsfTT.triggerReset()):h(b).forEach(a=>{a&&a.dataset.disabledWarning&&(a.closest("label").querySelector(".tsf-taxonomy-warning")?.remove(),document.querySelectorAll(`.${g(b)}`).forEach(a=>{a.remove()}),a.disabled=!1,a.dataset.disabledWarning="")});const k=document.getElementById(`${c("disabled_taxonomies")}[${b}]`);i.has(b)?!k.closest("label").querySelector(".tsf-taxonomy-from-pt-warning")&&(k.closest("label").insertAdjacentHTML("beforeend",f),tsfTT.triggerReset()):k.closest("label").querySelector(".tsf-taxonomy-from-pt-warning")?.remove()})},z=()=>{const a=["google_verification","bing_verification","yandex_verification","baidu_verification","pint_verification"].map(a=>document.getElementById(c(a))),b=a=>{let b=a.clipboardData&&a.clipboardData.getData("text")||"";if(b){let c=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(b);c?.[2]?.length&&(a.stopPropagation(),a.preventDefault(),a.target.value=c[2],tsfAys.registerChange())}};a.forEach(a=>a.addEventListener("paste",b))},A=()=>{e(),g(),h(),i(),j(),k(),o(),w(),x(),y(),z(),f()},B=()=>{},C=()=>{tsfTabs.initStack("tsfSettings",{tabToggledEvent:new CustomEvent("tsf-tab-toggled"),HTMLClasses:{wrapper:"tsf-nav-tab-wrapper",tabRadio:"tsf-nav-tab-radio",tabLabel:"tsf-nav-tab-label",activeTab:"tsf-nav-tab-active",activeTabContent:"tsf-nav-tab-content-active"},fixHistory:!0})};return Object.assign({load:()=>{const a=document.querySelector(".wp-header-end");document.querySelectorAll("div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info").forEach(b=>{a.insertAdjacentElement("afterend",b)}),document.body.addEventListener("tsf-onload",A),document.body.addEventListener("tsf-ready",B),C()}},{l10n:b})}(jQuery),window.tsfSettings.load();
1
+ 'use strict';window.tsfSettings=function(a){const b="undefined"!=typeof tsfSettingsL10n&&tsfSettingsL10n,c=a=>`autodescription-site-settings[${a}]`,d=tsf.dispatchAtInteractive,e=()=>{document.getElementById(c("display_character_counter"))?.addEventListener("click",a=>{document.querySelectorAll(".tsf-counter-wrap").forEach(b=>{b.style.display=a.target.checked?"":"none"}),a.target.checked&&tsfC.triggerCounterUpdate()});document.getElementById(c("display_pixel_counter"))?.addEventListener("click",a=>{document.querySelectorAll(".tsf-pixel-counter-wrap").forEach(b=>{b.style.display=a.target.checked?"":"none"}),a.target.checked&&tsfC.triggerCounterUpdate()});const a=new Set,b=new Set,e=new Set,f=new Set;document.body.addEventListener("tsf-post-type-support-changed",()=>{let b=document.querySelectorAll(".tsf-excluded-taxonomies"),c=!1;b.forEach(b=>{const d=b.name.split(/(?:.+\[)(.+?)(?:])/).join(""),f=JSON.parse(b.dataset?.postTypes||0)||[],g=f&&f.every(b=>a.has(b));g?(!e.has(d)&&(c=!0),e.add(d)):e.has(d)&&(e.delete(d),c=!0),h(),c&&i(d)})});const g=new Map;document.body.addEventListener("tsf-taxonomy-support-changed",()=>{g.set("excludedTaxonomiesAll",new Set(f)),g.set("excludedTaxonomies",new Set(b)),g.set("excludedPtTaxonomies",new Set(e))});const h=()=>{f.clear(),b.forEach(a=>f.add(a)),e.forEach(a=>f.add(a))},i=a=>{document.body.dispatchEvent(new CustomEvent("tsf-taxonomy-support-changed",{detail:{taxonomy:a,set:b,setPt:e,setAll:f}}))},j=b=>{document.body.dispatchEvent(new CustomEvent("tsf-post-type-support-changed",{detail:{postType:b,set:a}}))};let k=!1;const l=b=>{if(b.target.name){let c=b.target.name.split(/(?:.+\[)(.+?)(?:])/).join("");b.target.checked?(a.add(c),j(c)):k&&(a.delete(c),j(c))}},m=a=>{if(a.target.name){let c=a.target.name.split(/(?:.+\[)(.+?)(?:])/).join("");a.target.checked?(b.add(c),h(),i(c)):k&&(b.delete(c),h(),i(c))}};document.querySelectorAll(".tsf-excluded-post-types").forEach(a=>{a.addEventListener("change",l),d(a,"change")}),document.querySelectorAll(".tsf-excluded-taxonomies").forEach(a=>{a.addEventListener("change",m),d(a,"change")}),k=!0},f=()=>{document.querySelectorAll(".tsf-color-picker").forEach(b=>{let c=a(b),d="",e=c.data("tsf-default-color");c.wpColorPicker({defaultColor:e,width:238,change:()=>{d=c.wpColorPicker("color"),""===d&&(d=e),b.value=e,tsfAys.registerChange()},clear:()=>{e.length&&(b.value=e,c.closest(".wp-picker-container").find(".wp-color-result").css("backgroundColor",e)),tsfAys.registerChange()},palettes:!1})})},g=()=>{const a=document.getElementById(c("title_rem_additions")),b=document.getElementById(c("social_title_rem_additions")),e=wp.template("tsf-disabled-title-additions-help-social")();a&&(a.addEventListener("change",a=>{a.target.checked?(document.querySelectorAll(".tsf-title-additions-js").forEach(a=>a.style.display="none"),b&&(b.dataset.disabledWarning=1,b.closest("label").insertAdjacentHTML("beforeend",e),tsfTT.triggerReset())):(document.querySelectorAll(".tsf-title-additions-js").forEach(a=>a.style.display="inline"),b?.dataset.disabledWarning&&b.closest("label").querySelector(".tsf-title-additions-warning-social")?.remove()),document.body.dispatchEvent(new CustomEvent("tsf-update-title-rem-additions",{detail:{removeAdditions:!!a.target.checked}}))}),d(a,"change"));const f=a=>{let b;document.getElementsByName(a.target.name).forEach(a=>{a.checked&&(b=a.value)});const d="left"===b,e="tsf-title-additions-location-hidden";document.querySelectorAll(".tsf-title-additions-example-left").forEach(a=>{a.classList.toggle(e,!d),a.classList.remove("hidden")}),document.querySelectorAll(".tsf-title-additions-example-right").forEach(a=>{a.classList.toggle(e,d),a.classList.remove("hidden")}),tsfTitle.updateStateAll("additionPlacement",d?"before":"after",c("homepage_title"))};document.querySelectorAll("#tsf-title-location input").forEach(a=>{a.addEventListener("change",f),a.checked&&d(a,"change")});const g=document.getElementById(c("title_rem_prefixes"));g&&(g.addEventListener("change",a=>{const b=!a.target.checked,d="tsf-title-tax-prefix-hidden";document.querySelectorAll(".tsf-title-tax-prefix").forEach(a=>{a.classList.toggle(d,!b),a.classList.remove("hidden")}),document.querySelectorAll(".tsf-title-tax-noprefix").forEach(a=>{a.classList.toggle(d,b),a.classList.remove("hidden")}),tsfTitle.updateStateAll("showPrefix",b,c("homepage_title"))}),d(g,"change"));const h=a=>{const b=tsf.decodeEntities(a.target.dataset.entity),c="tsf-title-separator-active";document.querySelectorAll(".tsf-sep-js").forEach(a=>{a.textContent=` ${b} `}),window.dispatchEvent(new CustomEvent("tsf-title-sep-updated",{detail:{separator:b}}));let d=document.querySelector(`.${c}`);d&&d.classList.remove(c,"tsf-no-focus-ring");let e=document.querySelector(`label[for="${a.target.id}"]`);e&&e.classList.add(c)};document.querySelectorAll("#tsf-title-separator input").forEach(a=>{a.addEventListener("click",h)});const i=a=>{a.target.classList.add("tsf-no-focus-ring")};document.querySelectorAll("#tsf-title-separator label").forEach(a=>{a.addEventListener("click",i)});const j=c("homepage_title"),k=document.getElementById(c("site_title"));k&&(k.addEventListener("input",a=>{let b=document.querySelectorAll(".tsf-site-title-js"),c=tsf.decodeEntities(tsf.sDoubleSpace(a.target.value.trim()));c||=tsf.decodeEntities(a.target.placeholder),tsfTitle.updateStateOf(j,"defaultTitle",c),tsfTitle.updateStateAll("additionValue",c,j);let d=tsf.escapeString(c);b.forEach(a=>{a.innerHTML=d})}),d(k,"input"))},h=()=>{const a=c("homepage_title"),e=document.getElementById(a),f=document.getElementById(c("homepage_title_tagline")),g=document.getElementById(c("homepage_tagline"));if(!e)return;tsfTitle.setInputElement(e);const h=JSON.parse(document.getElementById(`tsf-title-data_${a}`)?.dataset.state||0);tsfTitle.updateStateOf(a,"allowReferenceChange",!h.refTitleLocked),tsfTitle.updateStateOf(a,"defaultTitle",h.defaultTitle),tsfTitle.updateStateOf(a,"addAdditions",h.addAdditions),tsfTitle.updateStateOf(a,"useSocialTagline",!!(h.useSocialTagline||!1)),tsfTitle.updateStateOf(a,"additionValue",h.additionValue),tsfTitle.updateStateOf(a,"additionPlacement",h.additionPlacement),tsfTitle.updateStateOf(a,"hasLegacy",!!(h.hasLegacy||!1)),tsfTitle.enqueueUnregisteredInputTrigger(a);const i=b=>{let c="left"===b.target.value?"before":"after";tsfTitle.updateStateOf(a,"additionPlacement",c)};document.querySelectorAll("#tsf-home-title-location input").forEach(a=>{a.addEventListener("change",i),d(a,"change")});const j=b=>{let c=tsfTitle.getStateOf(a,"prefixValue"),d="";switch(b){case"password":d=tsfTitle.protectedPrefix;break;case"private":d=tsfTitle.privatePrefix;break;default:case"public":d="";}d!==c&&tsfTitle.updateStateOf(a,"prefixValue",d)};b.states.isFrontPrivate?j("private"):b.states.isFrontProtected&&j("password");e.addEventListener("input",b=>{let c=document.querySelectorAll(".tsf-custom-title-js"),d=tsf.decodeEntities(tsf.sDoubleSpace(b.target.value.trim()));d.length?(d=tsf.escapeString(d),c.forEach(a=>a.innerHTML=d)):(d=tsf.escapeString(tsf.decodeEntities(tsfTitle.getStateOf(a,"defaultTitle"))),c.forEach(a=>a.innerHTML=d))}),d(e,"input");let k;const l=()=>{clearTimeout(k),k=setTimeout(()=>{let b=tsfTitle.getStateOf(a,"additionValue");b=tsf.decodeEntities(tsf.sDoubleSpace(b.trim())),b.length&&tsfTitle.getStateOf(a,"addAdditions")?(document.querySelectorAll(".tsf-custom-tagline-js").forEach(a=>{a.innerHTML=tsf.escapeString(b)}),document.querySelectorAll(".tsf-custom-blogname-js").forEach(a=>{a.style.display=null})):document.querySelectorAll(".tsf-custom-blogname-js").forEach(a=>{a.style.display="none"})},1e3/60)};f.addEventListener("input",()=>{let b=f.value.trim();b.length||(b=f.placeholder||""),b=tsf.escapeString(tsf.decodeEntities(b.trim())),tsfTitle.updateStateOf(a,"additionValue",b),l()}),d(f,"input");g.addEventListener("change",b=>{let c=!1;b.target.checked?(c=!0,f.readOnly=!1):(c=!1,f.readOnly=!0),tsfTitle.updateStateOf(a,"addAdditions",c),l()}),d(g,"change");window.addEventListener("tsf-title-sep-updated",a=>{tsfTitle.updateStateAll("separator",a.detail.separator)})},i=()=>{const a=c("homepage_description");tsfDescription.setInputElement(document.getElementById(a));const b=JSON.parse(document.getElementById(`tsf-description-data_${a}`)?.dataset.state||0);b&&(tsfDescription.updateStateOf(a,"defaultDescription",b.defaultDescription.trim()),tsfDescription.updateStateOf(a,"hasLegacy",!!(b.hasLegacy||!1))),tsfDescription.enqueueUnregisteredInputTrigger(a)},j=()=>{const a="homepage_social_settings";tsfSocial.setInputInstance(a,c("homepage_title"),c("homepage_description"));const b=JSON.parse(document.getElementById(`tsf-social-data_${a}`)?.dataset.settings||0);b&&(tsfSocial.updateStateOf(a,"addAdditions",b.og.state.addAdditions),tsfSocial.updateStateOf(a,"defaults",{ogTitle:b.og.state.defaultTitle,twTitle:b.tw.state.defaultTitle,ogDesc:b.og.state.defaultDesc,twDesc:b.tw.state.defaultDesc}),tsfSocial.updateStateOf(a,"placeholderLocks",{ogTitle:b.og.state?.titlePhLock||!1,twTitle:b.tw.state?.titlePhLock||!1,ogDesc:b.og.state?.descPhLock||!1,twDesc:b.tw.state?.descPhLock||!1}))},k=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(c("homepage_title")),tsfDescription.enqueueUnregisteredInputTrigger(c("homepage_description"))};a(document).on("postbox-toggled",(a,c)=>{if("autodescription-homepage-settings"===c.id){let a=c.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&b()}}),document.getElementById("tsf-homepage-tab-general")?.addEventListener("tsf-tab-toggled",b)},l=(a,b)=>`${c("pta")}[${a}][${b}]`;let m;const n=()=>m||=JSON.parse(document.getElementById("tsf-post-type-archive-data")?.dataset.postTypes||0)||{},o=()=>{const a=n(),b=Object.keys(a).length;switch(!0){case 1<b:p();case 0<b:q();break;default:}for(const b in a)r(b),s(b),t(b),u(b),v(b)},p=()=>{const a=n(),b=document.getElementById("tsf-post-type-archive-selector"),c=document.createElement("option"),e=document.getElementById("tsf-post-type-archive-header-wrap");e&&(e.style.display=null);(()=>{for(const d in a){let e=c.cloneNode();e.value=tsf.escapeString(d),e.innerHTML=tsf.escapeString(a[d].label),b?.appendChild(e)}})(),document.querySelectorAll(".tsf-post-type-header").forEach(a=>a.classList.add("hidden"));let f,g;const h=a=>{clearTimeout(f),f=setTimeout(()=>{g&&e?.removeChild(g),document.querySelectorAll(".tsf-post-type-archive-wrap").forEach(b=>{a.target.value===b.dataset.postType?(b.style.display=null,g=b.querySelector(".tsf-post-type-archive-details")?.cloneNode(!0)):b.style.display="none",b.classList.remove("hide-if-tsf-js")}),g&&e?.appendChild(g),document.body.dispatchEvent(new CustomEvent("tsf-post-type-archive-switched",{detail:{postType:a.target.value,hasKompaanChocolateBananaBeer:!1}}))},1e3/60)};b&&(b.addEventListener("change",h),d(b,"change"))},q=()=>{document.body.addEventListener("tsf-post-type-support-changed",a=>{const{postType:b,set:c}=a.detail,d=document.querySelector(`.tsf-post-type-archive-wrap[data-post-type="${b}"]`),e=c.has(b);d?.querySelector(".tsf-post-type-archive-if-excluded")?.classList.toggle("hidden",!e),d?.querySelector(".tsf-post-type-archive-if-not-excluded")?.classList.toggle("hidden",e),document.body.dispatchEvent(new CustomEvent("tsf-post-type-archive-switched",{detail:{postType:b}}))})},r=a=>{const b=l(a,"doctitle"),e=document.getElementById(b);if(!e)return;tsfTitle.setInputElement(e);const f=JSON.parse(document.getElementById(`tsf-title-data_${b}`)?.dataset.state||0);f&&(tsfTitle.updateStateOf(b,"defaultTitle",f.defaultTitle),tsfTitle.updateStateOf(b,"addAdditions",f.addAdditions),tsfTitle.updateStateOf(b,"useSocialTagline",!!(f.useSocialTagline||!1)),tsfTitle.updateStateOf(b,"additionValue",f.additionValue),tsfTitle.updateStateOf(b,"additionPlacement",f.additionPlacement),tsfTitle.updateStateOf(b,"prefixValue",f.prefixValue),tsfTitle.updateStateOf(b,"showPrefix",f.showPrefix));e.addEventListener("input",a=>{let d=!a.target.value.trim().length;document.getElementById(c("title_rem_prefixes"))?.checked&&(d=!1),tsfTitle.updateStateOf(b,"showPrefix",d)});const g=wp.template("tsf-disabled-title-additions-help")(),h=document.getElementById(l(a,"title_no_blog_name"));h&&(document.body.addEventListener("tsf-update-title-rem-additions",a=>{const{removeAdditions:b}=a.detail;h.disabled=b,b?(h.closest("label").insertAdjacentHTML("beforeend",g),tsfTT.triggerReset()):h.closest("label").querySelector(".tsf-title-additions-warning")?.remove(),h.dispatchEvent(new Event("change"))}),h.addEventListener("change",a=>{let d=!a.target.checked;document.getElementById(c("title_rem_additions"))?.checked&&(d=!1),tsfTitle.updateStateOf(b,"addAdditions",d)}),d(h,"change")),tsfTitle.enqueueUnregisteredInputTrigger(b)},s=a=>{const b=l(a,"description"),c=document.getElementById(b);if(c){tsfDescription.setInputElement(c);const a=JSON.parse(document.getElementById(`tsf-description-data_${b}`)?.dataset.state||0);a&&tsfDescription.updateStateOf(b,"defaultDescription",a.defaultDescription.trim()),tsfDescription.enqueueUnregisteredInputTrigger(b)}},t=a=>{const b=`pta_social_settings_${a}`,c=JSON.parse(document.getElementById(`tsf-social-data_${b}`)?.dataset.settings||0);tsfSocial.setInputInstance(b,l(a,"doctitle"),l(a,"description")),tsfSocial.updateStateOf(b,"addAdditions",c.og.state.addAdditions),tsfSocial.updateStateOf(b,"defaults",{ogTitle:c.og.state.defaultTitle,twTitle:c.tw.state.defaultTitle,ogDesc:c.og.state.defaultDesc,twDesc:c.tw.state.defaultDesc})},u=a=>{const b={site:new Map,pt:new Map},c=c=>{let d=!1;return"noindex"===c&&(d=!n()[a].hasPosts),d||b.site.get(c)||b.pt.get(c)},d=b=>{const d=document.getElementById(l(a,b)),e=d?.querySelector("[value=\"0\"]"),f=d?.dataset||{};let g=f.defaultI18n?.replace("%s",tsf.decodeEntities(c(b)?f.defaultOff:f.defaultOn));g!==e.innerHTML&&(e.innerHTML=g,d.dispatchEvent(new Event("change")))};document.body.addEventListener("tsf-post-type-robots-changed",c=>{const{postType:e,robotsType:f,set:g}=c.detail;a!==e||(b.pt.set(f,g.has(a)),d(f))}),document.body.addEventListener("tsf-site-robots-changed",a=>{const{checked:c,robotsType:e}=a.detail;b.site.set(e,!!c),d(e)}),["noindex","nofollow","noarchive"].forEach(a=>{d(a)});const e=document.getElementById(l(a,"canonical")),f=document.getElementById(l(a,"noindex")),g=b=>{let d="",f="";0===b?d=c("noindex")?"noindex":"index":-1===b?d="index":1===b?d="noindex":void 0;f="noindex"==d?"":n()[a].url,e.placeholder=f};e&&f&&(f.addEventListener("change",a=>g(+a.target.value)),g(+f.value))},v=b=>{const c=()=>{tsfTitle.enqueueUnregisteredInputTrigger(l(b,"doctitle")),tsfDescription.enqueueUnregisteredInputTrigger(l(b,"description"))};a(document).on("postbox-toggled",(a,b)=>{if("autodescription-post-type-archive-settings"===b.id){let a=b.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&c()}});document.body.addEventListener("tsf-post-type-archive-switched",a=>{a.detail?.postType===b&&c()}),document.getElementById(`tsf-post_type_archive_${b}-tab-general`)?.addEventListener("tsf-tab-toggled",c)},w=()=>{const a=document.getElementById(c("social_title_rem_additions"));a&&(a.addEventListener("change",a=>{a.target.checked?tsfSocial.updateStateAll("addAdditions",!1):tsfSocial.updateStateAll("addAdditions",!0)}),d(a,"change"))},x=()=>{const a=document.getElementById(c("set_copyright_directives"));if(a){const b=["max_snippet_length","max_image_preview","max_video_preview"].map(a=>document.getElementById(c(a))),e="tsf-toggle-directives-surrogate";a.addEventListener("change",a=>{a.target.checked?(b.forEach(a=>a.disabled=!1),document.querySelectorAll(`.${e}`).forEach(a=>a.remove())):b.forEach(a=>{a.disabled=!0;let b=document.createElement("input");b.type="hidden",b.name=a.name||"",b.value=a.value||0,b.classList.add(e),a.insertAdjacentElement("afterend",b)})}),d(a,"change")}const b={},e={};[b,e].forEach(a=>{a.noindex=new Set,a.nofollow=new Set,a.noarchive=new Set});const f=(a,c)=>{document.body.dispatchEvent(new CustomEvent("tsf-post-type-robots-changed",{detail:{postType:a,robotsType:c,set:b[c]}}))},g=(a,b)=>{document.body.dispatchEvent(new CustomEvent("tsf-taxonomy-robots-changed",{detail:{taxonomy:a,robotsType:b,set:e[b]}}))},h=(a,b)=>{document.body.dispatchEvent(new CustomEvent("tsf-site-robots-changed",{detail:{checked:a,robotsType:b}}))},i=wp.template("tsf-robots-pt-help")(),j=(a,b,d)=>{let e=document.getElementById(`${c(`${b}_taxonomies`)}[${a}]`);d?(e.closest("label").insertAdjacentHTML("beforeend",i),tsfTT.triggerReset()):e.closest("label").querySelector(".tsf-taxonomy-from-pt-robots-warning")?.remove(),n(a)},k=a=>{const c=document.querySelectorAll(`.tsf-robots-taxonomies[data-robots="${a}"]`);let d=!1;c.forEach(c=>{let f=c.name.split(/(?:.+\[)(.+?)(?:])/).join("");const h=JSON.parse(c.dataset.postTypes||0),i=h&&h.every(c=>b[a].has(c));i?(!e[a].has(f)&&(d=!0),e[a].add(f)):e[a].has(f)&&(e[a].delete(f),d=!0),d&&g(f,a)})},l={noindex:new Map,nofollow:new Map,noarchive:new Map},m=(a,b)=>l[b].get(a)||new Set;document.body.addEventListener("tsf-taxonomy-robots-changed",a=>{const{taxonomy:b,robotsType:c}=a.detail;m("robotsPtTaxonomies",c).size!==e[c].size&&j(b,c,e[c].has(b)),l[c].set("robotsPtTaxonomies",new Set(e[c]))});document.body.addEventListener("tsf-post-type-robots-changed",a=>{k(a.detail.robotsType)});const n=a=>{for(let b in e)if(e[b].has(a)){let d=document.getElementById(`${c(`${b}_taxonomies`)}[${a}]`),e=d.closest("label").querySelector(".tsf-taxonomy-from-pt-robots-warning");e.style.display=d.dataset.disabledWarning?"none":""}};document.body.addEventListener("tsf-taxonomy-support-changed",a=>n(a.detail.taxonomy));let o=!1;const p=a=>{let c=a.target?.name.split(/(?:.+\[)(.+?)(?:])/).join(""),d=a.target?.dataset.robots;a.target.checked?(b[d].add(c),f(c,d)):o&&(b[d].delete(c),f(c,d))};document.querySelectorAll(".tsf-robots-post-types").forEach(a=>{a.addEventListener("change",p),d(a,"change")});const q=a=>{let b=a.target?.dataset.robots,c=a.target.checked;c?h(c,b):o&&h(c,b)};document.querySelectorAll(".tsf-robots-site").forEach(a=>{a.addEventListener("change",q),d(a,"change")}),o=!0},y=()=>{const a=a=>tsf.escapeString(`tsf-disabled-post-type-input-clone-${a}`),b=wp.template("tsf-disabled-post-type-help")(),d=a=>[document.getElementById(`${c("noindex_post_types")}[${a}]`),document.getElementById(`${c("nofollow_post_types")}[${a}]`),document.getElementById(`${c("noarchive_post_types")}[${a}]`)].filter(a=>a);document.body.addEventListener("tsf-post-type-support-changed",c=>{const{postType:e,set:f}=c.detail;f.has(e)?(d(e).forEach(c=>{if(c){let d=c.cloneNode(!0);d.type="hidden",d.value=c.checked?c.value:"",d.id+="-cloned",d.classList.add(a(e)),c.disabled=!0,c.dataset.disabledWarning=1;const f=c.closest("label");f.insertAdjacentHTML("beforeend",b),f.append(d)}}),tsfTT.triggerReset()):d(e).forEach(b=>{b&&b.dataset.disabledWarning&&(b.closest("label").querySelector(".tsf-post-type-warning").remove(),document.querySelectorAll(`.${a(e)}`).forEach(a=>{a.remove()}),b.disabled=!1,b.dataset.disabledWarning="")})});const e=wp.template("tsf-disabled-taxonomy-help")(),f=wp.template("tsf-disabled-taxonomy-from-pt-help")(),g=a=>tsf.escapeString(`tsf-disabled-taxonomy-input-clone-${a}`),h=a=>[document.getElementById(`${c("noindex_taxonomies")}[${a}]`),document.getElementById(`${c("nofollow_taxonomies")}[${a}]`),document.getElementById(`${c("noarchive_taxonomies")}[${a}]`)].filter(a=>a);document.body.addEventListener("tsf-taxonomy-support-changed",a=>{const{taxonomy:b,set:d,setPt:i,setAll:j}=a.detail;j.has(b)?(h(b).forEach(a=>{if(a){let c=a.cloneNode(!0);c.type="hidden",c.value=a.checked?a.value:"",c.id+="-cloned",c.classList.add(g(b)),a.disabled=!0,a.dataset.disabledWarning=1;const d=a.closest("label");d.querySelector(".tsf-taxonomy-warning")||d.insertAdjacentHTML("beforeend",e),d.querySelector(g(b))||d.append(c)}}),tsfTT.triggerReset()):h(b).forEach(a=>{a&&a.dataset.disabledWarning&&(a.closest("label").querySelector(".tsf-taxonomy-warning")?.remove(),document.querySelectorAll(`.${g(b)}`).forEach(a=>{a.remove()}),a.disabled=!1,a.dataset.disabledWarning="")});const k=document.getElementById(`${c("disabled_taxonomies")}[${b}]`);i.has(b)?!k.closest("label").querySelector(".tsf-taxonomy-from-pt-warning")&&(k.closest("label").insertAdjacentHTML("beforeend",f),tsfTT.triggerReset()):k.closest("label").querySelector(".tsf-taxonomy-from-pt-warning")?.remove()})},z=()=>{const a=["google_verification","bing_verification","yandex_verification","baidu_verification","pint_verification"].map(a=>document.getElementById(c(a))),b=a=>{let b=a.clipboardData&&a.clipboardData.getData("text")||"";if(b){let c=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(b);c?.[2]?.length&&(a.stopPropagation(),a.preventDefault(),a.target.value=c[2],tsfAys.registerChange())}};a.forEach(a=>a.addEventListener("paste",b))},A=()=>{e(),g(),h(),i(),j(),k(),o(),w(),x(),y(),z(),f()},B=()=>{},C=()=>{tsfTabs.initStack("tsfSettings",{tabToggledEvent:new CustomEvent("tsf-tab-toggled"),HTMLClasses:{wrapper:"tsf-nav-tab-wrapper",tabRadio:"tsf-nav-tab-radio",tabLabel:"tsf-nav-tab-label",activeTab:"tsf-nav-tab-active",activeTabContent:"tsf-nav-tab-content-active"},fixHistory:!0})};return Object.assign({load:()=>{const a=document.querySelector(".wp-header-end");document.querySelectorAll("div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info").forEach(b=>{a.insertAdjacentElement("afterend",b)}),document.body.addEventListener("tsf-onload",A),document.body.addEventListener("tsf-ready",B),C()}},{l10n:b})}(jQuery),window.tsfSettings.load();
lib/js/social.js CHANGED
@@ -40,9 +40,9 @@ window.tsfSocial = function() {
40
  * @since 4.2.0
41
  * @access private
42
  * @type {(Map<string,{
43
- * group: string,
44
- * inputs: {ogTitle:Element,twTitle:Element,ogDesc:Element,twDesc:Element}
45
- * refs: {titleInput:Element,descInput:Element,title:Element,titleNa:Element,desc:Element}
46
  * }>)} The input element instances.
47
  */
48
  const inputInstances = new Map();
40
  * @since 4.2.0
41
  * @access private
42
  * @type {(Map<string,{
43
+ * group: string,
44
+ * inputs: {ogTitle:Element,twTitle:Element,ogDesc:Element,twDesc:Element}
45
+ * refs: {titleInput:Element,descInput:Element,title:Element,titleNa:Element,desc:Element}
46
  * }>)} The input element instances.
47
  */
48
  const inputInstances = new Map();
lib/js/term.js CHANGED
@@ -140,7 +140,10 @@ window.tsfTerm = function() {
140
  */
141
  const _initTitleListeners = () => {
142
 
143
- tsfTitle.setInputElement( document.getElementById( _titleId ) );
 
 
 
144
 
145
  const state = JSON.parse(
146
  document.getElementById( `tsf-title-data_${_titleId}` )?.dataset.state || 0
@@ -226,7 +229,10 @@ window.tsfTerm = function() {
226
  */
227
  const _initDescriptionListeners = () => {
228
 
229
- tsfDescription.setInputElement( document.getElementById( _descId ) );
 
 
 
230
 
231
  const state = JSON.parse(
232
  document.getElementById( `tsf-description-data_${_descId}` )?.dataset.state || 0
140
  */
141
  const _initTitleListeners = () => {
142
 
143
+ const titleInput = document.getElementById( _titleId );
144
+ if ( ! titleInput ) return;
145
+
146
+ tsfTitle.setInputElement( titleInput );
147
 
148
  const state = JSON.parse(
149
  document.getElementById( `tsf-title-data_${_titleId}` )?.dataset.state || 0
229
  */
230
  const _initDescriptionListeners = () => {
231
 
232
+ const descInput = document.getElementById( _descId );
233
+ if ( ! descInput ) return;
234
+
235
+ tsfDescription.setInputElement( descInput );
236
 
237
  const state = JSON.parse(
238
  document.getElementById( `tsf-description-data_${_descId}` )?.dataset.state || 0
lib/js/term.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfTerm=function(){const a="undefined"!=typeof tsfTermL10n&&tsfTermL10n,b="autodescription-meta[doctitle]",c="autodescription-meta[description]",d="autodescription_social_tt",e=()=>{const a=document.getElementById("autodescription-meta[noindex]");let b="",c=!0;const d=()=>{let a=document.getElementById("autodescription-meta[canonical]");a&&(b||=a.placeholder,a.placeholder=c?b:"")},e=b=>{let e="";switch(+b){case 0:e=a.dataset.defaultUnprotected;break;case-1:e="index";break;case 1:e="noindex";}c="noindex"!==e,d()};a&&(a.addEventListener("change",a=>e(a.target.value)),e(a.value))},f=()=>{tsfTitle.setInputElement(document.getElementById(b));const c=JSON.parse(document.getElementById(`tsf-title-data_${b}`)?.dataset.state||0);c&&(tsfTitle.updateStateOf(b,"allowReferenceChange",!c.refTitleLocked),tsfTitle.updateStateOf(b,"defaultTitle",c.defaultTitle.trim()),tsfTitle.updateStateOf(b,"addAdditions",c.addAdditions),tsfTitle.updateStateOf(b,"useSocialTagline",!!(c.useSocialTagline||!1)),tsfTitle.updateStateOf(b,"additionValue",c.additionValue.trim()),tsfTitle.updateStateOf(b,"additionPlacement",c.additionPlacement),tsfTitle.updateStateOf(b,"hasLegacy",!!(c.hasLegacy||!1)));const d=tsf.escapeString(a.params.termPrefix),e=document.getElementById("autodescription-meta[title_no_blog_name]");e&&(e.addEventListener("change",c=>{let d=!c.target.checked;a.params.additionsForcedDisabled&&(d=!1),tsfTitle.updateStateOf(b,"addAdditions",d)}),e.dispatchEvent(new Event("change")));const f=a=>{a=a?.trim();let c=tsfTitle.stripTitleTags?tsf.stripTags(a):a;c||=tsfTitle.untitledTitle;let e;e=window.isRtl?`${c} ${d}`:`${d} ${c}`,tsfTitle.updateStateOf(b,"defaultTitle",e)};document.querySelector("#edittag #name")?.addEventListener("input",a=>f(a.target.value)),tsfTitle.enqueueUnregisteredInputTrigger(b)},g=()=>{tsfDescription.setInputElement(document.getElementById(c));const a=JSON.parse(document.getElementById(`tsf-description-data_${c}`)?.dataset.state||0);a&&(tsfDescription.updateStateOf(c,"defaultDescription",a.defaultDescription.trim()),tsfDescription.updateStateOf(c,"hasLegacy",!!(a.hasLegacy||!1))),tsfDescription.enqueueUnregisteredInputTrigger(c)},h=()=>{tsfSocial.setInputInstance(d,b,c);const a=JSON.parse(document.getElementById(`tsf-social-data_${d}`)?.dataset.settings||0);a&&(tsfSocial.updateStateOf(d,"addAdditions",a.og.state.addAdditions),tsfSocial.updateStateOf(d,"defaults",{ogTitle:a.og.state.defaultTitle,twTitle:a.tw.state.defaultTitle,ogDesc:a.og.state.defaultDesc,twDesc:a.tw.state.defaultDesc}))},i=()=>{e(),f(),g(),h()},j=()=>{};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",i),document.body.addEventListener("tsf-ready",j)}},{l10n:a})}(),window.tsfTerm.load();
1
+ 'use strict';window.tsfTerm=function(){const a="undefined"!=typeof tsfTermL10n&&tsfTermL10n,b="autodescription-meta[doctitle]",c="autodescription-meta[description]",d="autodescription_social_tt",e=()=>{const a=document.getElementById("autodescription-meta[noindex]");let b="",c=!0;const d=()=>{let a=document.getElementById("autodescription-meta[canonical]");a&&(b||=a.placeholder,a.placeholder=c?b:"")},e=b=>{let e="";switch(+b){case 0:e=a.dataset.defaultUnprotected;break;case-1:e="index";break;case 1:e="noindex";}c="noindex"!==e,d()};a&&(a.addEventListener("change",a=>e(a.target.value)),e(a.value))},f=()=>{const c=document.getElementById(b);if(!c)return;tsfTitle.setInputElement(c);const d=JSON.parse(document.getElementById(`tsf-title-data_${b}`)?.dataset.state||0);d&&(tsfTitle.updateStateOf(b,"allowReferenceChange",!d.refTitleLocked),tsfTitle.updateStateOf(b,"defaultTitle",d.defaultTitle.trim()),tsfTitle.updateStateOf(b,"addAdditions",d.addAdditions),tsfTitle.updateStateOf(b,"useSocialTagline",!!(d.useSocialTagline||!1)),tsfTitle.updateStateOf(b,"additionValue",d.additionValue.trim()),tsfTitle.updateStateOf(b,"additionPlacement",d.additionPlacement),tsfTitle.updateStateOf(b,"hasLegacy",!!(d.hasLegacy||!1)));const e=tsf.escapeString(a.params.termPrefix),f=document.getElementById("autodescription-meta[title_no_blog_name]");f&&(f.addEventListener("change",c=>{let d=!c.target.checked;a.params.additionsForcedDisabled&&(d=!1),tsfTitle.updateStateOf(b,"addAdditions",d)}),f.dispatchEvent(new Event("change")));const g=a=>{a=a?.trim();let c=tsfTitle.stripTitleTags?tsf.stripTags(a):a;c||=tsfTitle.untitledTitle;let d;d=window.isRtl?`${c} ${e}`:`${e} ${c}`,tsfTitle.updateStateOf(b,"defaultTitle",d)};document.querySelector("#edittag #name")?.addEventListener("input",a=>g(a.target.value)),tsfTitle.enqueueUnregisteredInputTrigger(b)},g=()=>{const a=document.getElementById(c);if(a){tsfDescription.setInputElement(a);const b=JSON.parse(document.getElementById(`tsf-description-data_${c}`)?.dataset.state||0);b&&(tsfDescription.updateStateOf(c,"defaultDescription",b.defaultDescription.trim()),tsfDescription.updateStateOf(c,"hasLegacy",!(!b.hasLegacy&&1))),tsfDescription.enqueueUnregisteredInputTrigger(c)}},h=()=>{tsfSocial.setInputInstance(d,b,c);const a=JSON.parse(document.getElementById(`tsf-social-data_${d}`)?.dataset.settings||0);a&&(tsfSocial.updateStateOf(d,"addAdditions",a.og.state.addAdditions),tsfSocial.updateStateOf(d,"defaults",{ogTitle:a.og.state.defaultTitle,twTitle:a.tw.state.defaultTitle,ogDesc:a.og.state.defaultDesc,twDesc:a.tw.state.defaultDesc}))},i=()=>{e(),f(),g(),h()},j=()=>{};return Object.assign({load:()=>{document.body.addEventListener("tsf-onload",i),document.body.addEventListener("tsf-ready",j)}},{l10n:a})}(),window.tsfTerm.load();
lib/js/tsf.js CHANGED
@@ -72,38 +72,24 @@ window.tsf = function( $ ) {
72
  */
73
  const stripTags = str => str.length && str.replace( /(<([^>]+)?>?)/ig, '' ) || '';
74
 
75
- let _canUseDOMParserTest = void 0;
76
- /**
77
- * Tests if DOMParser is supported.
78
- *
79
- * @since 4.0.0
80
- *
81
- * @return {Boolean}
82
- */
83
- const _canUseDOMParser = () => {
84
- if ( void 0 === _canUseDOMParserTest ) {
85
- try {
86
- // text/html parsing is natively supported when true.
87
- _canUseDOMParserTest = !! ( new DOMParser() ).parseFromString( '', 'text/html' );
88
- } catch ( e ) { }
89
-
90
- _canUseDOMParserTest = !! _canUseDOMParserTest;
91
- }
92
-
93
- return _canUseDOMParserTest;
94
- }
95
-
96
- let _decodeEntitiesDOMParser = void 0;
97
  /**
98
  * Decodes string entities securely.
99
  *
100
  * Uses a fallback when the browser doesn't support DOMParser.
101
  * This fallback sends out exactly the same output.
102
  *
103
- * The output of this function is considered secure against XSS attacks.
 
104
  *
105
  * @since 4.0.0
106
  * @access public
 
107
  *
108
  * @credit <https://stackoverflow.com/questions/1912501/unescape-html-entities-in-javascript/34064434#34064434>
109
  * Modified to allow <, >, and \ entities, and cached the parser.
@@ -115,24 +101,13 @@ window.tsf = function( $ ) {
115
 
116
  if ( ! str?.length ) return '';
117
 
118
- let map = {
119
- '<': '&#x3C;',
120
- '>': '&#x3E;',
121
- "\\": '&#x5C;',
122
- };
123
- // Prevent "tags" from being stripped.
124
- str = str.replace( /[<>\\]/g, m => map[ m ] );
125
 
126
- if ( _canUseDOMParser() ) {
127
- _decodeEntitiesDOMParser = _decodeEntitiesDOMParser || new DOMParser();
128
- str = _decodeEntitiesDOMParser.parseFromString( str, 'text/html' ).documentElement.textContent;
129
- } else {
130
- _decodeEntitiesDOMParser = _decodeEntitiesDOMParser || document.createElement( 'span' );
131
- _decodeEntitiesDOMParser.innerHTML = str;
132
- str = ampHTMLtoText( _decodeEntitiesDOMParser.textContent );
133
- }
134
-
135
- return str;
136
  }
137
 
138
  /**
@@ -152,7 +127,7 @@ window.tsf = function( $ ) {
152
  */
153
  const escapeString = str => {
154
 
155
- if ( ! str.length ) return '';
156
 
157
  let map = {
158
  '&': '&#x26;',
@@ -164,7 +139,8 @@ window.tsf = function( $ ) {
164
  "/": '&#x2F;',
165
  };
166
 
167
- return str.replace( /[&<>"'\\\/]/g, m => map[ m ] );
 
168
  }
169
 
170
  /**
@@ -172,7 +148,8 @@ window.tsf = function( $ ) {
172
  *
173
  * @since 4.0.0
174
  * @access public
175
-
 
176
  * @function
177
  * @param {string} str
178
  * @return {string}
72
  */
73
  const stripTags = str => str.length && str.replace( /(<([^>]+)?>?)/ig, '' ) || '';
74
 
75
+ let _decodeEntitiesDOMParser = void 0,
76
+ _decodeEntitiesMap = {
77
+ '<': '&#x3C;',
78
+ '>': '&#x3E;',
79
+ "\\": '&#x5C;',
80
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  /**
82
  * Decodes string entities securely.
83
  *
84
  * Uses a fallback when the browser doesn't support DOMParser.
85
  * This fallback sends out exactly the same output.
86
  *
87
+ * The rendering of this function is considered secure against XSS attacks.
88
+ * However, you must consider the output as insecure HTML, and may only append via innerText.
89
  *
90
  * @since 4.0.0
91
  * @access public
92
+ * @see tsf.escapeString;
93
  *
94
  * @credit <https://stackoverflow.com/questions/1912501/unescape-html-entities-in-javascript/34064434#34064434>
95
  * Modified to allow <, >, and \ entities, and cached the parser.
101
 
102
  if ( ! str?.length ) return '';
103
 
104
+ _decodeEntitiesDOMParser ||= new DOMParser();
 
 
 
 
 
 
105
 
106
+ return _decodeEntitiesDOMParser.parseFromString(
107
+ // Prevent "tags" from being stripped. When not string, return ''.
108
+ str.replace?.( /[<>\\]/g, m => _decodeEntitiesMap[ m ] ) || '',
109
+ 'text/html'
110
+ ).documentElement.textContent;
 
 
 
 
 
111
  }
112
 
113
  /**
127
  */
128
  const escapeString = str => {
129
 
130
+ if ( ! str?.length ) return '';
131
 
132
  let map = {
133
  '&': '&#x26;',
139
  "/": '&#x2F;',
140
  };
141
 
142
+ // When not string, return ''
143
+ return str.replace?.( /[&<>"'\\\/]/g, m => map[ m ] ) || '';
144
  }
145
 
146
  /**
148
  *
149
  * @since 4.0.0
150
  * @access public
151
+ * @todo deprecate, unused internally. Should've also been named ampEntitytoHTML.
152
+ *
153
  * @function
154
  * @param {string} str
155
  * @return {string}
readme.txt CHANGED
@@ -5,19 +5,19 @@ Tags: seo, xml sitemap, google search, open graph, schema.org, twitter card, per
5
  Requires at least: 5.5
6
  Tested up to: 6.1
7
  Requires PHP: 7.2.0
8
- Stable tag: 4.2.6
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
12
- Purely professional, feature-complete, and the ad-free WordPress SEO plugin. Secure, fast, automated, and white-hat SEO. Do less; get better results.
13
 
14
  == Description ==
15
 
16
- **The only feature-complete SEO plugin that follows the white-hat guidelines and rules imposed by WordPress and search engines.**
17
 
18
  Start using proven methods to optimize your website for SEO. Clean, dedicated, extensible, unrestricted, ad-free, and no strings attached.
19
 
20
- To top it off, this is the fastest full-featured SEO plugin, and it blends right into your WordPress website, without leaving you in the dark.
21
 
22
  It's easy to get started. Activate this plugin, and your site's instantly protected against prominent SEO attacks. The SEO Framework will also prefill all critical meta tags for you. A real time-saver. Ingenious.
23
 
@@ -79,6 +79,7 @@ For additional functionality, check out our free companion plugin [Extension Man
79
 
80
  * [Focus](https://theseoframework.com/?p=2305) guides you through the process of writing targeted content that ranks with **focus keywords and synonyms**.
81
  * [Articles](https://theseoframework.com/?p=2303) **enhances your published posts** by automatically adding important Structured Data.
 
82
  * [Honeypot](https://theseoframework.com/?p=2300) **catches comment spammers** through four lightweight yet powerful ways.
83
  * [Cord](https://theseoframework.com/?p=3404) helps you connect your website to **Google Analytics and Facebook Pixel**.
84
  * [Local](https://theseoframework.com/?p=2306) lets you set up **important local business information** for search engines to consume.
@@ -247,6 +248,12 @@ If you wish to display breadcrumbs, then your theme should provide this. Alterna
247
 
248
  == Changelog ==
249
 
 
 
 
 
 
 
250
  = 4.2.6 =
251
 
252
  This patch resolves an issue with WordPress 6.1, which queries template parts before posts are requested. This premature query causes TSF to fail in recognizing support for Custom Post Types, [preventing all meta output](https://theseoframework.com/?p=4015).
@@ -283,8 +290,6 @@ This minor update addresses a few regressions brought in v4.2.0; it fixes the ca
283
  * Developers can now enjoy using the new `tsf()` function -- an alias of `the_seo_framework()`.
284
  * If you're a developer, you should also check out our perfectly tuned `memo()`. `umemo()`, and `fmemo()` [functions](https://github.com/sybrew/the-seo-framework/blob/4.2.0/inc/functions/api.php#L155-L335), which help make TSF so performant.
285
 
286
- *Psst: Check out our [Cyber Sale](https://theseoframework.com/?p=3527).*
287
-
288
  **Perfect**
289
 
290
  TSF is finally what I (Sybre) envisioned it to become when I first named it "The SEO Framework": It's lightning-fast, hassle-free, and has all necessary options while giving you the best in class experience. I hope you enjoy what I believe is a perfect product!
5
  Requires at least: 5.5
6
  Tested up to: 6.1
7
  Requires PHP: 7.2.0
8
+ Stable tag: 4.2.7
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
12
+ The fastest feature-complete SEO plugin for professional WordPress websites. Secure, fast, automated, and ethical SEO. Do less; get better results.
13
 
14
  == Description ==
15
 
16
+ **The fastest and only feature-complete SEO plugin that follows the guidelines and rules imposed by WordPress and search engines.**
17
 
18
  Start using proven methods to optimize your website for SEO. Clean, dedicated, extensible, unrestricted, ad-free, and no strings attached.
19
 
20
+ To top it off, this is the [fastest full-featured SEO plugin](https://twitter.com/TheSEOFramework/status/1493352649445580804/photo/1), and it blends right into your WordPress website, without leaving you in the dark.
21
 
22
  It's easy to get started. Activate this plugin, and your site's instantly protected against prominent SEO attacks. The SEO Framework will also prefill all critical meta tags for you. A real time-saver. Ingenious.
23
 
79
 
80
  * [Focus](https://theseoframework.com/?p=2305) guides you through the process of writing targeted content that ranks with **focus keywords and synonyms**.
81
  * [Articles](https://theseoframework.com/?p=2303) **enhances your published posts** by automatically adding important Structured Data.
82
+ * [Transport](https://theseoframework.com/?p=3962) **migrates and transforms metadata** from Rank Math and Yoast SEO to this plugin.
83
  * [Honeypot](https://theseoframework.com/?p=2300) **catches comment spammers** through four lightweight yet powerful ways.
84
  * [Cord](https://theseoframework.com/?p=3404) helps you connect your website to **Google Analytics and Facebook Pixel**.
85
  * [Local](https://theseoframework.com/?p=2306) lets you set up **important local business information** for search engines to consume.
248
 
249
  == Changelog ==
250
 
251
+ = 4.2.7 =
252
+
253
+ This minor update brings you a revamped HTML parser and a new option for tuning its accuracy for descriptions. First-time installers are now notified when metadata can be transported from other SEO plugins, the SEO Bar recognizes syntax from Rank Math, and Advanced Query Protection blocks new SEO attacks that could tank your rankings. We also [fixed a couple of bugs](https://theseoframework.com/?p=4021).
254
+
255
+ *Psst: Check out our [Cyber Sale](https://theseoframework.com/?p=3527).*
256
+
257
  = 4.2.6 =
258
 
259
  This patch resolves an issue with WordPress 6.1, which queries template parts before posts are requested. This premature query causes TSF to fail in recognizing support for Custom Post Types, [preventing all meta output](https://theseoframework.com/?p=4015).
290
  * Developers can now enjoy using the new `tsf()` function -- an alias of `the_seo_framework()`.
291
  * If you're a developer, you should also check out our perfectly tuned `memo()`. `umemo()`, and `fmemo()` [functions](https://github.com/sybrew/the-seo-framework/blob/4.2.0/inc/functions/api.php#L155-L335), which help make TSF so performant.
292
 
 
 
293
  **Perfect**
294
 
295
  TSF is finally what I (Sybre) envisioned it to become when I first named it "The SEO Framework": It's lightning-fast, hassle-free, and has all necessary options while giving you the best in class experience. I hope you enjoy what I believe is a perfect product!