From 608004f7feae3b9bf91c763a69a5ac7f6bc20f01 Mon Sep 17 00:00:00 2001
From: David Bowman
Date: Mon, 10 Aug 2026 10:55:02 -0600
Subject: [PATCH 1/2] Add site-wide generation defaults for the suggestion
features
Title Suggestions and Excerpt Suggestions each start from a tone and a
persona, and Excerpt Suggestions also from a desired length. Those starting
points were hardcoded, so a site had no way to express its own editorial
voice.
Each feature now exposes its defaults in the Content Intelligence section of
the settings page, and the Editor Sidebar settings endpoint resolves its
defaults from them. They apply to users who have not yet chosen their own
values in the editor.
The new Suggestion_Defaults class holds the tones, the personas, the length
bounds, and a validator for each setting, so that a missing or invalid stored
value falls back to the shipped default. Installations that predate these
settings therefore need no migration.
The defaults are validated outside the Content Intelligence sanitizer, which
coerces every scalar into a boolean and would otherwise discard them.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01MXxy3dkvUCyMxsBQNMJbaq
---
src/UI/class-settings-page.php | 153 ++++++++++++++++-
src/class-parsely.php | 9 +
src/class-permissions.php | 7 +
.../common/class-suggestion-defaults.php | 156 ++++++++++++++++++
...class-endpoint-editor-sidebar-settings.php | 42 ++++-
.../EndpointEditorSidebarSettingsTest.php | 92 +++++++++++
6 files changed, 449 insertions(+), 10 deletions(-)
create mode 100644 src/content-helper/common/class-suggestion-defaults.php
diff --git a/src/UI/class-settings-page.php b/src/UI/class-settings-page.php
index 498b60c3aa..a386105640 100644
--- a/src/UI/class-settings-page.php
+++ b/src/UI/class-settings-page.php
@@ -11,6 +11,7 @@
namespace Parsely\UI;
use Parsely\Content_Helper\Excerpt_Suggestions;
+use Parsely\Content_Helper\Suggestion_Defaults;
use Parsely\Parsely;
use Parsely\Permissions;
use Parsely\Utils\Utils;
@@ -110,6 +111,19 @@ final class Settings_Page {
*/
private $managed_options_badge = array();
+ /**
+ * The Content Intelligence features that expose site-wide generation
+ * defaults in the settings page.
+ *
+ * @since 3.24.0
+ *
+ * @var string[]
+ */
+ private const FEATURES_WITH_DEFAULTS = array(
+ 'title_suggestions',
+ 'excerpt_suggestions',
+ );
+
/**
* The Content Intelligence features that can be configured in the settings
* page.
@@ -1122,9 +1136,107 @@ public function print_content_helper_ai_feature_section( $args ): void {
echo '';
+ if ( in_array( $feature_id, self::FEATURES_WITH_DEFAULTS, true ) ) {
+ $this->print_suggestion_defaults( $args, $options, $feature_id );
+ }
+
$this->print_filter_text( $args );
}
+ /**
+ * Prints out a feature's site-wide generation defaults.
+ *
+ * These apply to users who have not yet set their own values in the editor.
+ * The desired length is printed for Excerpt Suggestions only, as Title
+ * Suggestions has no equivalent setting.
+ *
+ * @since 3.24.0
+ *
+ * @param Setting_Arguments $args The arguments for the fieldset.
+ * @param Parsely_Options $options The plugin's options.
+ * @param string $feature_id The feature's name.
+ */
+ private function print_suggestion_defaults( $args, $options, string $feature_id ): void {
+ /** @var array $feature_options */
+ $feature_options = $options['content_helper'][ $feature_id ] ?? array();
+ $is_managed = key_exists( 'content_helper', $this->parsely->managed_options );
+
+ echo '';
+ }
+
+ /**
+ * Prints out a select tag for a feature's default generation setting.
+ *
+ * @since 3.24.0
+ *
+ * @param string $option_key The nested option key.
+ * @param string $label The visible label.
+ * @param array $choices The choices, as value => label pairs.
+ * @param string $selected The currently selected value.
+ */
+ private function print_suggestion_defaults_select(
+ string $option_key,
+ string $label,
+ array $choices,
+ string $selected
+ ): void {
+ printf(
+ '
';
+ }
+
/**
* Prints out the select tags
*
@@ -1558,10 +1670,49 @@ private function validate_content_helper_section( $input ) {
// Produce the final array.
$options = $this->parsely->get_options()['content_helper'];
- $merged = array_merge( $options, $input['content_helper'] );
+
+ // Validate the generation defaults separately, as the sanitizer above
+ // coerces every scalar into a boolean. Values that were not submitted
+ // fall back to the stored ones, and anything invalid falls back to the
+ // shipped default.
+ $validated_defaults = array();
+ foreach ( self::FEATURES_WITH_DEFAULTS as $feature_id ) {
+ /** @var array $submitted */
+ $submitted = $input['content_helper'][ $feature_id ] ?? array();
+ /** @var array $stored */
+ $stored = $options[ $feature_id ];
+
+ $defaults = array(
+ 'default_tone' => Suggestion_Defaults::get_default_tone(
+ array( 'default_tone' => $submitted['default_tone'] ?? $stored['default_tone'] ?? null )
+ ),
+ 'default_persona' => Suggestion_Defaults::get_default_persona(
+ array( 'default_persona' => $submitted['default_persona'] ?? $stored['default_persona'] ?? null )
+ ),
+ );
+
+ // Only Excerpt Suggestions has a desired length.
+ if ( Excerpt_Suggestions::get_feature_name() === $feature_id ) {
+ $length = $submitted['default_length'] ?? $stored['default_length'] ?? null;
+ $defaults['default_length'] = Suggestion_Defaults::get_default_length(
+ array( 'default_length' => is_numeric( $length ) ? (int) $length : null )
+ );
+ }
+
+ $validated_defaults[ $feature_id ] = $defaults;
+ }
+
+ $merged = array_merge( $options, $input['content_helper'] );
$input['content_helper'] = $sanitize( $merged );
+ foreach ( $validated_defaults as $feature_id => $defaults ) {
+ $input['content_helper'][ $feature_id ] = array_merge(
+ $input['content_helper'][ $feature_id ],
+ $defaults
+ );
+ }
+
return $input;
}
diff --git a/src/class-parsely.php b/src/class-parsely.php
index 8d617b079a..f9f7d75ea4 100644
--- a/src/class-parsely.php
+++ b/src/class-parsely.php
@@ -10,6 +10,7 @@
namespace Parsely;
+use Parsely\Content_Helper\Suggestion_Defaults;
use Parsely\REST_API\REST_API_Controller;
use Parsely\Services\Content_API\Content_API_Service;
use Parsely\Services\Suggestions_API\Suggestions_API_Service;
@@ -60,6 +61,9 @@
* @phpstan-type Parsely_Options_Content_Helper_Feature array{
* enabled: bool,
* allowed_user_roles: string[],
+ * default_length?: int,
+ * default_tone?: string,
+ * default_persona?: string,
* }
*
* @phpstan-type Parsely_Options_Headline_Testing array{
@@ -136,10 +140,15 @@ class Parsely {
'title_suggestions' => array(
'enabled' => true,
'allowed_user_roles' => array( 'administrator' ),
+ 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
+ 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
),
'excerpt_suggestions' => array(
'enabled' => true,
'allowed_user_roles' => array( 'administrator' ),
+ 'default_length' => Suggestion_Defaults::DEFAULT_LENGTH,
+ 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
+ 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
),
'traffic_boost' => array(
'enabled' => true,
diff --git a/src/class-permissions.php b/src/class-permissions.php
index 9fdfb600b9..87b5a34757 100644
--- a/src/class-permissions.php
+++ b/src/class-permissions.php
@@ -10,6 +10,8 @@
namespace Parsely;
+use Parsely\Content_Helper\Suggestion_Defaults;
+
/**
* Class implementing user/role permissions functionality.
*
@@ -201,10 +203,15 @@ public static function build_pch_permissions_settings_array(
'title_suggestions' => array(
'enabled' => $enabled,
'allowed_user_roles' => $allowed_user_roles,
+ 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
+ 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
),
'excerpt_suggestions' => array(
'enabled' => $enabled,
'allowed_user_roles' => $allowed_user_roles,
+ 'default_length' => Suggestion_Defaults::DEFAULT_LENGTH,
+ 'default_tone' => Suggestion_Defaults::DEFAULT_TONE,
+ 'default_persona' => Suggestion_Defaults::DEFAULT_PERSONA,
),
'traffic_boost' => array(
'enabled' => $enabled,
diff --git a/src/content-helper/common/class-suggestion-defaults.php b/src/content-helper/common/class-suggestion-defaults.php
new file mode 100644
index 0000000000..5667a05f57
--- /dev/null
+++ b/src/content-helper/common/class-suggestion-defaults.php
@@ -0,0 +1,156 @@
+ The tones, as value => label pairs.
+ */
+ public static function get_tones(): array {
+ return array(
+ 'neutral' => __( 'Neutral', 'wp-parsely' ),
+ 'formal' => __( 'Formal', 'wp-parsely' ),
+ 'humorous' => __( 'Humorous', 'wp-parsely' ),
+ 'confident' => __( 'Confident', 'wp-parsely' ),
+ 'provocative' => __( 'Provocative', 'wp-parsely' ),
+ 'serious' => __( 'Serious', 'wp-parsely' ),
+ 'inspirational' => __( 'Inspirational', 'wp-parsely' ),
+ 'skeptical' => __( 'Skeptical', 'wp-parsely' ),
+ 'conversational' => __( 'Conversational', 'wp-parsely' ),
+ 'analytical' => __( 'Analytical', 'wp-parsely' ),
+ );
+ }
+
+ /**
+ * Returns the predefined personas, keyed by their stored value.
+ *
+ * The custom persona is absent, for the same reason as the custom tone.
+ *
+ * @since 3.24.0
+ *
+ * @return array The personas, as value => label pairs.
+ */
+ public static function get_personas(): array {
+ return array(
+ 'journalist' => __( 'Journalist', 'wp-parsely' ),
+ 'editorialWriter' => __( 'Editorial Writer', 'wp-parsely' ),
+ 'investigativeReporter' => __( 'Investigative Reporter', 'wp-parsely' ),
+ 'techAnalyst' => __( 'Tech Analyst', 'wp-parsely' ),
+ 'businessAnalyst' => __( 'Business Analyst', 'wp-parsely' ),
+ 'culturalCommentator' => __( 'Cultural Commentator', 'wp-parsely' ),
+ 'scienceCorrespondent' => __( 'Science Correspondent', 'wp-parsely' ),
+ 'politicalAnalyst' => __( 'Political Analyst', 'wp-parsely' ),
+ 'healthWellnessAdvocate' => __( 'Health and Wellness Advocate', 'wp-parsely' ),
+ 'environmentalJournalist' => __( 'Environmental Journalist', 'wp-parsely' ),
+ );
+ }
+
+ /**
+ * Returns a feature's site-wide default excerpt length.
+ *
+ * Falls back to the shipped default when the option is missing, which is
+ * the case for installations that predate these settings, or when it holds
+ * an out-of-range value.
+ *
+ * @since 3.24.0
+ *
+ * @param array $feature_options The feature's options.
+ * @return int The default length, in characters.
+ */
+ public static function get_default_length( array $feature_options ): int {
+ $length = $feature_options['default_length'] ?? self::DEFAULT_LENGTH;
+
+ if ( ! is_int( $length ) ||
+ $length < self::MIN_LENGTH ||
+ $length > self::MAX_LENGTH
+ ) {
+ return self::DEFAULT_LENGTH;
+ }
+
+ return $length;
+ }
+
+ /**
+ * Returns a feature's site-wide default tone.
+ *
+ * @since 3.24.0
+ *
+ * @param array $feature_options The feature's options.
+ * @return string The default tone.
+ */
+ public static function get_default_tone( array $feature_options ): string {
+ $tone = $feature_options['default_tone'] ?? self::DEFAULT_TONE;
+
+ if ( ! is_string( $tone ) || ! isset( self::get_tones()[ $tone ] ) ) {
+ return self::DEFAULT_TONE;
+ }
+
+ return $tone;
+ }
+
+ /**
+ * Returns a feature's site-wide default persona.
+ *
+ * @since 3.24.0
+ *
+ * @param array $feature_options The feature's options.
+ * @return string The default persona.
+ */
+ public static function get_default_persona( array $feature_options ): string {
+ $persona = $feature_options['default_persona'] ?? self::DEFAULT_PERSONA;
+
+ if ( ! is_string( $persona ) || ! isset( self::get_personas()[ $persona ] ) ) {
+ return self::DEFAULT_PERSONA;
+ }
+
+ return $persona;
+ }
+}
diff --git a/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php b/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php
index 5680725daf..bc75d7a97e 100644
--- a/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php
+++ b/src/rest-api/settings/class-endpoint-editor-sidebar-settings.php
@@ -10,6 +10,8 @@
namespace Parsely\REST_API\Settings;
+use Parsely\Content_Helper\Suggestion_Defaults;
+
/**
* Endpoint for saving and retrieving Content Intelligence Editor Sidebar
* settings.
@@ -29,9 +31,9 @@ class Endpoint_Editor_Sidebar_Settings extends Base_Settings_Endpoint {
*
* @var int
*/
- public const MIN_EXCERPT_LENGTH = 50;
- public const MAX_EXCERPT_LENGTH = 300;
- public const DEFAULT_EXCERPT_LENGTH = 160;
+ public const MIN_EXCERPT_LENGTH = Suggestion_Defaults::MIN_LENGTH;
+ public const MAX_EXCERPT_LENGTH = Suggestion_Defaults::MAX_LENGTH;
+ public const DEFAULT_EXCERPT_LENGTH = Suggestion_Defaults::DEFAULT_LENGTH;
/**
* Returns the endpoint's name.
@@ -64,10 +66,15 @@ protected function get_meta_key(): string {
* @since 3.24.0 Added the ExcerptSuggestions `Length` setting.
* @since 3.24.0 Removed the ExcerptSuggestions `Open` setting, as the panel's
* collapsed state is now persisted by the block editor itself.
+ * @since 3.24.0 The ExcerptSuggestions and TitleSuggestions defaults come
+ * from the site-wide settings of their respective features.
*
* @return array
*/
protected function get_subvalues_specs(): array {
+ $excerpt_options = $this->get_feature_options( 'excerpt_suggestions' );
+ $title_options = $this->get_feature_options( 'title_suggestions' );
+
return array(
'ExcerptSuggestions' => array(
'values' => array(
@@ -76,9 +83,9 @@ protected function get_subvalues_specs(): array {
'Tone' => array(),
),
'default' => array(
- 'Length' => self::DEFAULT_EXCERPT_LENGTH,
- 'Persona' => 'journalist',
- 'Tone' => 'neutral',
+ 'Length' => Suggestion_Defaults::get_default_length( $excerpt_options ),
+ 'Persona' => Suggestion_Defaults::get_default_persona( $excerpt_options ),
+ 'Tone' => Suggestion_Defaults::get_default_tone( $excerpt_options ),
),
),
'InitialTabName' => array(
@@ -129,8 +136,8 @@ protected function get_subvalues_specs(): array {
),
'default' => array(
'Open' => false,
- 'Persona' => 'journalist',
- 'Tone' => 'neutral',
+ 'Persona' => Suggestion_Defaults::get_default_persona( $title_options ),
+ 'Tone' => Suggestion_Defaults::get_default_tone( $title_options ),
),
),
);
@@ -154,7 +161,9 @@ protected function sanitize_subvalue( string $composite_key, $value ) {
$value < self::MIN_EXCERPT_LENGTH ||
$value > self::MAX_EXCERPT_LENGTH
) {
- return self::DEFAULT_EXCERPT_LENGTH;
+ return Suggestion_Defaults::get_default_length(
+ $this->get_feature_options( 'excerpt_suggestions' )
+ );
}
return $value;
@@ -162,4 +171,19 @@ protected function sanitize_subvalue( string $composite_key, $value ) {
return parent::sanitize_subvalue( $composite_key, $value );
}
+
+ /**
+ * Returns the site-wide options of a Content Intelligence feature.
+ *
+ * @since 3.24.0
+ *
+ * @param string $feature_id The feature's name.
+ * @return array The feature's options.
+ */
+ private function get_feature_options( string $feature_id ): array {
+ /** @var array $options */
+ $options = $this->parsely->get_options()['content_helper'][ $feature_id ] ?? array();
+
+ return $options;
+ }
}
diff --git a/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php
index 87a78cb640..0f16ab9f30 100644
--- a/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php
+++ b/tests/Integration/RestAPI/Settings/EndpointEditorSidebarSettingsTest.php
@@ -10,6 +10,7 @@
namespace Parsely\Tests\Integration\RestAPI\Settings;
+use Parsely\Content_Helper\Suggestion_Defaults;
use Parsely\REST_API\Content_Helper\Content_Helper_Controller;
use Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings;
@@ -308,6 +309,97 @@ public function test_excerpt_length_is_validated( $length, int $expected ): void
self::assertSame( $expected, $value['ExcerptSuggestions']['Length'] );
}
+ /**
+ * Verifies that the ExcerptSuggestions defaults come from the site-wide
+ * settings of the Excerpt Suggestions feature.
+ *
+ * @since 3.24.0
+ *
+ * @covers \Parsely\Content_Helper\Suggestion_Defaults::get_default_length
+ * @covers \Parsely\Content_Helper\Suggestion_Defaults::get_default_persona
+ * @covers \Parsely\Content_Helper\Suggestion_Defaults::get_default_tone
+ * @covers \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_subvalues_specs
+ * @uses \Parsely\Parsely::get_options
+ * @uses \Parsely\REST_API\Base_API_Controller::__construct
+ * @uses \Parsely\REST_API\Base_API_Controller::get_parsely
+ * @uses \Parsely\REST_API\Base_API_Controller::init
+ * @uses \Parsely\REST_API\Base_Endpoint::__construct
+ * @uses \Parsely\REST_API\Base_Endpoint::is_available_to_current_user
+ * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::get_settings
+ * @uses \Parsely\REST_API\Settings\Base_Settings_Endpoint::register_routes
+ * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_endpoint_name
+ * @uses \Parsely\REST_API\Settings\Endpoint_Editor_Sidebar_Settings::get_meta_key
+ * @dataProvider provide_site_default_data
+ *
+ * @param array $feature_options The feature's stored options.
+ * @param array $expected The expected defaults.
+ */
+ public function test_excerpt_defaults_come_from_site_settings(
+ array $feature_options,
+ array $expected
+ ): void {
+ // Only the feature under test is stored. Parsely::get_options() fills
+ // in the remaining Content Intelligence features from its defaults.
+ $options = self::DEFAULT_OPTIONS;
+ $options['content_helper'] = array( 'excerpt_suggestions' => $feature_options );
+ update_option( \Parsely\Parsely::OPTIONS_KEY, $options );
+
+ $this->set_current_user_to_admin();
+ delete_user_meta(
+ get_current_user_id(),
+ 'parsely_content_helper_settings_editor_sidebar'
+ );
+
+ // The base endpoint snapshots the specs, and therefore the defaults,
+ // in its constructor. Build the endpoint after the options are stored,
+ // as a real request would.
+ $endpoint = new Endpoint_Editor_Sidebar_Settings( $this->api_controller );
+ $value = $endpoint->get_settings()->get_data();
+
+ assert( is_array( $value ) && is_array( $value['ExcerptSuggestions'] ) );
+ self::assertSame( $expected, $value['ExcerptSuggestions'] );
+ }
+
+ /**
+ * Provides data for testing the site-wide defaults.
+ *
+ * @since 3.24.0
+ *
+ * @return array> The test data.
+ */
+ public function provide_site_default_data(): array {
+ $shipped = array(
+ 'Length' => Suggestion_Defaults::DEFAULT_LENGTH,
+ 'Persona' => Suggestion_Defaults::DEFAULT_PERSONA,
+ 'Tone' => Suggestion_Defaults::DEFAULT_TONE,
+ );
+
+ return array(
+ 'configured defaults' => array(
+ array(
+ 'default_length' => 220,
+ 'default_tone' => 'analytical',
+ 'default_persona' => 'techAnalyst',
+ ),
+ array(
+ 'Length' => 220,
+ 'Persona' => 'techAnalyst',
+ 'Tone' => 'analytical',
+ ),
+ ),
+ 'missing keys' => array( array(), $shipped ),
+ 'out-of-range length' => array( array( 'default_length' => 99999 ), $shipped ),
+ 'non-integer length' => array( array( 'default_length' => 'abc' ), $shipped ),
+ 'unknown tone and persona' => array(
+ array(
+ 'default_tone' => 'bogus',
+ 'default_persona' => 'bogus',
+ ),
+ $shipped,
+ ),
+ );
+ }
+
/**
* Provides data for testing the excerpt length validation.
*
From a01e9f664ff69e890ddda5b5ef2b22aec30d6252 Mon Sep 17 00:00:00 2001
From: David Bowman
Date: Mon, 10 Aug 2026 10:55:14 -0600
Subject: [PATCH 2/2] Source the tones and personas from PHP
The tone and persona lists existed in both PHP and TypeScript, as the settings
page is rendered by PHP and cannot read a TypeScript constant. Keeping two
copies of the same vocabulary in step is not something the build or the tests
would have caught.
PHP is now their single source. The Editor Sidebar injects them alongside the
values it already passes to the bundle, and the selectors build their maps
from that, adding only the custom entry. That entry stays in TypeScript, as it
is a UI affordance rather than part of the vocabulary, and it carries an icon
that PHP cannot express.
Nothing is lost in the move: ToneProp and PersonaProp are declared as
`keyof typeof PARSELY_* | string`, which collapses to `string`, so the literal
types were never checking anything.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01MXxy3dkvUCyMxsBQNMJbaq
---
build/content-helper/editor-sidebar.asset.php | 2 +-
build/content-helper/editor-sidebar.js | 26 +++++------
src/@types/assets/window.d.ts | 2 +
.../components/persona-selector/component.tsx | 43 ++++---------------
.../components/tone-selector/component.tsx | 43 ++++---------------
src/content-helper/common/utils/vocabulary.ts | 35 +++++++++++++++
.../editor-sidebar/class-editor-sidebar.php | 11 +++++
7 files changed, 80 insertions(+), 82 deletions(-)
create mode 100644 src/content-helper/common/utils/vocabulary.ts
diff --git a/build/content-helper/editor-sidebar.asset.php b/build/content-helper/editor-sidebar.asset.php
index 97f8acfe5c..091cf1235f 100644
--- a/build/content-helper/editor-sidebar.asset.php
+++ b/build/content-helper/editor-sidebar.asset.php
@@ -1 +1 @@
- array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '7619d859e906db1a12b2');
+ array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '6a0f76ecef09743f788b');
diff --git a/build/content-helper/editor-sidebar.js b/build/content-helper/editor-sidebar.js
index 81b4f6a4d2..51ae95ee24 100644
--- a/build/content-helper/editor-sidebar.js
+++ b/build/content-helper/editor-sidebar.js
@@ -1,20 +1,20 @@
-!function(){"use strict";var e={20:function(e,t,n){var r=n(609),i=Symbol.for("react.element"),s=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,a=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,n){var r,s={},c=null,u=null;for(r in void 0!==n&&(c=""+n),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)o.call(t,r)&&!l.hasOwnProperty(r)&&(s[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===s[r]&&(s[r]=t[r]);return{$$typeof:i,type:e,key:c,ref:u,props:s,_owner:a.current}}t.Fragment=s,t.jsx=c,t.jsxs=c},848:function(e,t,n){e.exports=n(20)},609:function(e){e.exports=window.React}},t={};function n(r){var i=t[r];if(void 0!==i)return i.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,n),s.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){n.d({},{w:function(){return Wr},_:function(){return Yr}});var e,t,r,i,s,o,a,l,c,u,p,d,f=n(848),h=window.wp.components,v=window.wp.data,g=window.wp.domReady,y=n.n(g),m=window.wp.element,w=window.wp.i18n,b=window.wp.primitives,_=(0,f.jsx)(b.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(b.Path,{fillRule:"evenodd",d:"M11.25 5h1.5v15h-1.5V5zM6 10h1.5v10H6V10zm12 4h-1.5v6H18v-6z",clipRule:"evenodd"})}),x=window.wp.plugins;void 0!==window.wp&&(p=null!==(t=null===(e=window.wp.editor)||void 0===e?void 0:e.PluginDocumentSettingPanel)&&void 0!==t?t:null!==(i=null===(r=window.wp.editPost)||void 0===r?void 0:r.PluginDocumentSettingPanel)&&void 0!==i?i:null===(s=window.wp.editSite)||void 0===s?void 0:s.PluginDocumentSettingPanel,d=null!==(a=null===(o=window.wp.editor)||void 0===o?void 0:o.PluginSidebar)&&void 0!==a?a:null!==(c=null===(l=window.wp.editPost)||void 0===l?void 0:l.PluginSidebar)&&void 0!==c?c:null===(u=window.wp.editSite)||void 0===u?void 0:u.PluginSidebar);var k=function(){function e(){this._tkq=[],this.isLoaded=!1,this.isEnabled=!1,"undefined"!=typeof wpParselyTracksTelemetry&&(this.isEnabled=!0,this.loadTrackingLibrary())}return e.getInstance=function(){return window.wpParselyTelemetryInstance||Object.defineProperty(window,"wpParselyTelemetryInstance",{value:new e,writable:!1,configurable:!1,enumerable:!1}),window.wpParselyTelemetryInstance},e.prototype.loadTrackingLibrary=function(){var e=this,t=document.createElement("script");t.async=!0,t.src="//stats.wp.com/w.js",t.onload=function(){e.isLoaded=!0,e._tkq=window._tkq||[]},document.head.appendChild(t)},e.trackEvent=function(t){return n=this,r=arguments,s=function(t,n){var r;return void 0===n&&(n={}),function(e,t){var n,r,i,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return o.next=a(0),o.throw=a(1),o.return=a(2),"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(a){return function(l){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;o&&(o=0,a[0]&&(s=0)),s;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,r=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!((i=(i=s.trys).length>0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=1e4&&(clearInterval(s),n("Telemetry library not loaded"))}),100);else n("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,n){var r;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(n=this.prepareProperties(n),null===(r=this._tkq)||void 0===r||r.push(["recordEvent",t,n])):console.error("Error tracking event: Invalid event name")):console.error("Error tracking event: Telemetry not loaded")},e.prototype.isTelemetryEnabled=function(){return this.isEnabled},e.prototype.isProprietyValid=function(t){return e.PROPERTY_REGEX.test(t)},e.prototype.isEventNameValid=function(t){return e.EVENT_NAME_REGEX.test(t)},e.prototype.prepareProperties=function(e){return(e=this.sanitizeProperties(e)).parsely_version=wpParselyTracksTelemetry.version,wpParselyTracksTelemetry.user&&(e._ut=wpParselyTracksTelemetry.user.type,e._ui=wpParselyTracksTelemetry.user.id),wpParselyTracksTelemetry.vipgo_env&&(e.vipgo_env=wpParselyTracksTelemetry.vipgo_env),this.sanitizeProperties(e)},e.prototype.sanitizeProperties=function(e){var t=this,n={};return Object.keys(e).forEach((function(r){t.isProprietyValid(r)&&(n[r]=e[r])})),n},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),S=(k.trackEvent,function(){return(0,f.jsx)(h.SVG,{"aria-hidden":"true",version:"1.1",viewBox:"0 0 15 15",width:"15",height:"15",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(h.Path,{d:"M0 14.0025V11.0025L7.5 3.5025L10.5 6.5025L3 14.0025H0ZM12 5.0025L13.56 3.4425C14.15 2.8525 14.15 1.9025 13.56 1.3225L12.68 0.4425C12.09 -0.1475 11.14 -0.1475 10.56 0.4425L9 2.0025L12 5.0025Z"})})}),j=function(e){var t=e.size,n=void 0===t?24:t,r=e.className,i=void 0===r?"wp-parsely-icon":r;return(0,f.jsxs)(h.SVG,{className:i,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M23.72,51.53c0-.18,0-.34-.06-.52a13.11,13.11,0,0,0-2.1-5.53A14.74,14.74,0,0,0,19.12,43c-.27-.21-.5-.11-.51.22l-.24,3.42c0,.33-.38.35-.49,0l-1.5-4.8a1.4,1.4,0,0,0-.77-.78,23.91,23.91,0,0,0-3.1-.84c-1.38-.24-3.39-.39-3.39-.39-.34,0-.45.21-.25.49l2.06,3.76c.2.27,0,.54-.29.33l-4.51-3.6a3.68,3.68,0,0,0-2.86-.48c-1,.16-2.44.46-2.44.46a.68.68,0,0,0-.39.25.73.73,0,0,0-.14.45S.41,43,.54,44a3.63,3.63,0,0,0,1.25,2.62L6.48,50c.28.2.09.49-.23.37l-4.18-.94c-.32-.12-.5,0-.4.37,0,0,.69,1.89,1.31,3.16a24,24,0,0,0,1.66,2.74,1.34,1.34,0,0,0,1,.52l5,.13c.33,0,.41.38.1.48L7.51,58c-.31.1-.34.35-.07.55a14.29,14.29,0,0,0,3.05,1.66,13.09,13.09,0,0,0,5.9.5,25.13,25.13,0,0,0,4.34-1,9.55,9.55,0,0,1-.08-1.2,9.32,9.32,0,0,1,3.07-6.91"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M59.7,41.53a.73.73,0,0,0-.14-.45.68.68,0,0,0-.39-.25s-1.43-.3-2.44-.46a3.64,3.64,0,0,0-2.86.48l-4.51,3.6c-.26.21-.49-.06-.29-.33l2.06-3.76c.2-.28.09-.49-.25-.49,0,0-2,.15-3.39.39a23.91,23.91,0,0,0-3.1.84,1.4,1.4,0,0,0-.77.78l-1.5,4.8c-.11.32-.48.3-.49,0l-.24-3.42c0-.33-.24-.43-.51-.22a14.74,14.74,0,0,0-2.44,2.47A13.11,13.11,0,0,0,36.34,51c0,.18,0,.34-.06.52a9.26,9.26,0,0,1,3,8.1,24.1,24.1,0,0,0,4.34,1,13.09,13.09,0,0,0,5.9-.5,14.29,14.29,0,0,0,3.05-1.66c.27-.2.24-.45-.07-.55l-3.22-1.17c-.31-.1-.23-.47.1-.48l5-.13a1.38,1.38,0,0,0,1-.52A24.6,24.6,0,0,0,57,52.92c.61-1.27,1.31-3.16,1.31-3.16.1-.33-.08-.49-.4-.37l-4.18.94c-.32.12-.51-.17-.23-.37l4.69-3.34A3.63,3.63,0,0,0,59.46,44c.13-1,.24-2.47.24-2.47"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M46.5,25.61c0-.53-.35-.72-.8-.43l-4.86,2.66c-.45.28-.56-.27-.23-.69l4.66-6.23a2,2,0,0,0,.28-1.68,36.51,36.51,0,0,0-2.19-4.89,34,34,0,0,0-2.81-3.94c-.33-.41-.74-.35-.91.16l-2.28,5.68c-.16.5-.6.48-.59-.05l.28-8.93a2.54,2.54,0,0,0-.66-1.64S35,4.27,33.88,3.27,30.78.69,30.78.69a1.29,1.29,0,0,0-1.54,0s-1.88,1.49-3.12,2.59-2.48,2.35-2.48,2.35A2.5,2.5,0,0,0,23,7.27l.27,8.93c0,.53-.41.55-.58.05l-2.29-5.69c-.17-.5-.57-.56-.91-.14a35.77,35.77,0,0,0-3,4.2,35.55,35.55,0,0,0-2,4.62,2,2,0,0,0,.27,1.67l4.67,6.24c.33.42.23,1-.22.69l-4.87-2.66c-.45-.29-.82-.1-.82.43a18.6,18.6,0,0,0,.83,5.07,20.16,20.16,0,0,0,5.37,7.77c3.19,3,5.93,7.8,7.45,11.08A9.6,9.6,0,0,1,30,49.09a9.31,9.31,0,0,1,2.86.45c1.52-3.28,4.26-8.11,7.44-11.09a20.46,20.46,0,0,0,5.09-7,19,19,0,0,0,1.11-5.82"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M36.12,58.44A6.12,6.12,0,1,1,30,52.32a6.11,6.11,0,0,1,6.12,6.12"})]})},P=function(){return P=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0?"".concat(i," ").concat(n):n)||this).hint=null,s.name=s.constructor.name,s.code=r;var o=[U.FetchError,U.HttpRequestFailed,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiOpenAiError,U.ParselySuggestionsApiOpenAiSchema,U.ParselySuggestionsApiOpenAiUnavailable,U.ParselySuggestionsApiSchemaError];return s.retryFetch=o.includes(s.code),Object.setPrototypeOf(s,t.prototype),s.CustomizeErrorMessaging(),s}return se(t,e),t.prototype.CustomizeErrorMessaging=function(){this.code===U.AccessToFeatureDisabled?this.message=(0,w.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):this.code===U.ParselySuggestionsApiNoAuthorization?this.message=(0,w.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):this.code===U.ParselySuggestionsApiOpenAiError||this.code===U.ParselySuggestionsApiOpenAiUnavailable?this.message=(0,w.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):this.code===U.HttpRequestFailed&&this.message.includes("cURL error 28")?this.message=(0,w.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):this.code===U.ParselySuggestionsApiSchemaError||this.code===U.ParselySuggestionsInvalidRequest?this.message=(0,w.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):this.code===U.ParselySuggestionsApiNoData||this.code===U.ParselySuggestionsApiNoDataManualLinking?this.message=(0,w.__)("The Parse.ly API couldn't find any relevant data to fulfill the request.","wp-parsely"):this.code===U.ParselySuggestionsApiOpenAiSchema||this.code===U.ParselySuggestionsApiResponseValidationError?this.message=(0,w.__)("The Parse.ly API returned an incorrect response.","wp-parsely"):this.code===U.ParselySuggestionsApiAuthUnavailable&&(this.message=(0,w.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),this.code===U.FetchError&&(this.hint=this.Hint((0,w.__)("This error can sometimes be caused by ad-blockers or browser tracking protections. Please add this site to any applicable allow lists and try again.","wp-parsely"))),this.code!==U.ParselyApiForbidden&&this.code!==U.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,w.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===U.HttpRequestFailed&&(this.hint=this.Hint((0,w.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely")))},t.prototype.Hint=function(e){return'
").concat(this.hint?this.hint:"")})},t.prototype.createErrorSnackbar=function(){//.test(this.message)||(0,v.dispatch)("core/notices").createNotice("error",this.message,{type:"snackbar"})},t}(Error),ae=function(e){var t=e.size,n=void 0===t?24:t,r=e.className,i=void 0===r?"wp-parsely-icon":r;return(0,f.jsxs)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",className:i,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",children:[(0,f.jsx)(h.Path,{d:"M8.18983 5.90381L8.83642 7.54325L10.4758 8.18983L8.83642 8.8364L8.18983 10.4759L7.54324 8.8364L5.90381 8.18983L7.54324 7.54325L8.18983 5.90381Z"}),(0,f.jsx)(h.Path,{d:"M15.048 5.90381L15.9101 8.08972L18.0961 8.95186L15.9101 9.81397L15.048 11.9999L14.1859 9.81397L12 8.95186L14.1859 8.08972L15.048 5.90381Z"}),(0,f.jsx)(h.Path,{d:"M11.238 10.4761L12.3157 13.2085L15.048 14.2861L12.3157 15.3638L11.238 18.0962L10.1603 15.3638L7.42798 14.2861L10.1603 13.2085L11.238 10.4761Z"})]})},le=(0,f.jsx)(b.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,f.jsx)(b.Path,{d:"m19 7-3-3-8.5 8.5-1 4 4-1L19 7Zm-7 11.5H5V20h7v-1.5Z"})}),ce=(0,m.forwardRef)((({icon:e,size:t=24,...n},r)=>(0,m.cloneElement)(e,{width:t,height:t,...n,ref:r}))),ue=function(){return(0,f.jsx)(h.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",children:(0,f.jsx)(h.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M13.5034 7.91642L9 12.0104L4.49662 7.91642L5.25337 7.08398L8.99999 10.49L12.7466 7.08398L13.5034 7.91642Z",fill:"#1E1E1E"})})},pe={journalist:{label:(0,w.__)("Journalist","wp-parsely")},editorialWriter:{label:(0,w.__)("Editorial Writer","wp-parsely")},investigativeReporter:{label:(0,w.__)("Investigative Reporter","wp-parsely")},techAnalyst:{label:(0,w.__)("Tech Analyst","wp-parsely")},businessAnalyst:{label:(0,w.__)("Business Analyst","wp-parsely")},culturalCommentator:{label:(0,w.__)("Cultural Commentator","wp-parsely")},scienceCorrespondent:{label:(0,w.__)("Science Correspondent","wp-parsely")},politicalAnalyst:{label:(0,w.__)("Political Analyst","wp-parsely")},healthWellnessAdvocate:{label:(0,w.__)("Health and Wellness Advocate","wp-parsely")},environmentalJournalist:{label:(0,w.__)("Environmental Journalist","wp-parsely")},custom:{label:(0,w.__)("Custom Persona","wp-parsely"),icon:le}},de=Object.keys(pe),fe=function(e){return"custom"===e||""===e?pe.custom.label:he(e)?e:pe[e].label},he=function(e){return!de.includes(e)||"custom"===e},ve=function(e){var t=e.value,n=e.onChange,r=(0,m.useState)(""),i=r[0],s=r[1],o=(0,ee.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-persona-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,w.__)("Enter a custom persona…","wp-parsely"),onChange:function(e){if(""===e)return n(""),void s("");e.length>32&&(e=e.slice(0,32)),o(e),s(e)}})})},ge=function(e){var t=e.persona,n=e.value,r=void 0===n?(0,w.__)("Select a persona…","wp-parsely"):n,i=e.label,s=void 0===i?(0,w.__)("Persona","wp-parsely"):i,o=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u,d="parsely-persona-selector-".concat((0,ee.useInstanceId)(ge));return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[s&&(0,f.jsx)("label",{htmlFor:d,className:"wp-parsely-editor-sidebar-label",children:s}),(0,f.jsx)(h.DropdownMenu,{label:(0,w.__)("Persona","wp-parsely"),className:"parsely-persona-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{id:d,children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-persona-selector-label",children:he(t)?pe.custom.label:r}),(0,f.jsx)(ue,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,w.__)("Persona","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:de.map((function(e){if(!p&&"custom"===e)return null;var r=pe[e],i=e===t||he(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),o(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-persona-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,f.jsx)(ce,{icon:r.icon}),r.label]},e)}))})})}}),p&&he(t)&&(0,f.jsx)(ve,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ye={neutral:{label:(0,w.__)("Neutral","wp-parsely")},formal:{label:(0,w.__)("Formal","wp-parsely")},humorous:{label:(0,w.__)("Humorous","wp-parsely")},confident:{label:(0,w.__)("Confident","wp-parsely")},provocative:{label:(0,w.__)("Provocative","wp-parsely")},serious:{label:(0,w.__)("Serious","wp-parsely")},inspirational:{label:(0,w.__)("Inspirational","wp-parsely")},skeptical:{label:(0,w.__)("Skeptical","wp-parsely")},conversational:{label:(0,w.__)("Conversational","wp-parsely")},analytical:{label:(0,w.__)("Analytical","wp-parsely")},custom:{label:(0,w.__)("Custom Tone","wp-parsely"),icon:le}},me=Object.keys(ye),we=function(e){return"custom"===e||""===e?ye.custom.label:be(e)?e:ye[e].label},be=function(e){return!me.includes(e)||"custom"===e},_e=function(e){var t=e.value,n=e.onChange,r=(0,m.useState)(""),i=r[0],s=r[1],o=(0,ee.useDebounce)(n,500);return(0,f.jsx)("div",{className:"parsely-tone-selector-custom",children:(0,f.jsx)(h.TextControl,{value:i||t,placeholder:(0,w.__)("Enter a custom tone","wp-parsely"),onChange:function(e){if(""===e)return n(""),void s("");e.length>32&&(e=e.slice(0,32)),o(e),s(e)}})})},xe=function(e){var t=e.tone,n=e.value,r=void 0===n?(0,w.__)("Select a tone","wp-parsely"):n,i=e.label,s=void 0===i?(0,w.__)("Tone","wp-parsely"):i,o=e.onChange,a=e.onDropdownChange,l=e.disabled,c=void 0!==l&&l,u=e.allowCustom,p=void 0!==u&&u,d="parsely-tone-selector-".concat((0,ee.useInstanceId)(xe));return(0,f.jsxs)(h.Disabled,{isDisabled:c,children:[(0,f.jsx)("label",{htmlFor:d,className:"wp-parsely-editor-sidebar-label",children:s}),(0,f.jsx)(h.DropdownMenu,{label:(0,w.__)("Tone","wp-parsely"),className:"parsely-tone-selector-dropdown"+(c?" is-disabled":""),popoverProps:{className:"wp-parsely-popover"},toggleProps:{id:d,children:(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)("div",{className:"parsely-tone-selector-label",children:be(t)?ye.custom.label:r}),(0,f.jsx)(ue,{})]})},children:function(e){var n=e.onClose;return(0,f.jsx)(h.MenuGroup,{label:(0,w.__)("Select a tone","wp-parsely"),children:(0,f.jsx)(f.Fragment,{children:me.map((function(e){if(!p&&"custom"===e)return null;var r=ye[e],i=e===t||be(t)&&"custom"===e;return(0,f.jsxs)(h.MenuItem,{isSelected:i,className:i?"is-selected":"",role:"menuitemradio",onClick:function(){null==a||a(e),o(e),n(),"custom"===e&&setTimeout((function(){var e=document.querySelector(".parsely-tone-selector-custom input");e&&e.focus()}),0)},children:[r.icon&&(0,f.jsx)(ce,{icon:r.icon}),r.label]},e)}))})})}}),p&&be(t)&&(0,f.jsx)(_e,{onChange:function(e){o(""!==e?e:"custom")},value:"custom"===t?"":t})]})},ke=function(e){return Object.entries(e).map((function(e){var t=e[0];return{label:e[1].label,value:t}}))},Se=ke(ye),je=ke(pe),Pe=function(e,t){var n=(0,m.useState)(e),r=n[0],i=n[1],s=(0,m.useRef)(r),o=(0,m.useRef)(t),a=(0,m.useRef)(e);s.current=r,o.current=t;var l=(0,m.useCallback)((function(e){a.current=e,o.current(e)}),[]),c=(0,ee.useDebounce)(l,500);return(0,m.useEffect)((function(){return function(){s.current!==a.current&&l(s.current)}}),[l]),[r,function(e,t){if(void 0===t&&(t=!1),i(e),t)return c.cancel(),void l(e);c(e)}]},Te=function(e){var t=e.customLabel,n=e.disabled,r=e.label,i=e.onChange,s=e.onSelect,o=e.options,a=e.value,l=function(e,t){return K===e||!t.some((function(t){return t.value===e}))}(a,o),c=Pe(a,i)[1],u=(0,m.useState)(l?K:a),p=u[0],d=u[1],v=(0,m.useState)(l&&K!==a?a:""),g=v[0],y=v[1];return(0,f.jsxs)(h.__experimentalVStack,{spacing:2,children:[(0,f.jsx)(h.SelectControl,{__nextHasNoMarginBottom:!0,__next40pxDefaultSize:!0,label:r,value:p,options:o,onChange:function(e){d(e),c(K===e?g||K:e,!0),s(e)},disabled:n}),K===p&&(0,f.jsx)(h.TextControl,{__nextHasNoMarginBottom:!0,__next40pxDefaultSize:!0,label:t,maxLength:32,value:g,onChange:function(e){y(e),c(""===e?K:e)},disabled:n})]})},Le=function(e){var t=e.isLoading,n=e.length,r=e.onLengthChange,i=e.onPersonaChange,s=e.onToneChange,o=e.persona,a=e.tone,l=Pe(n,r),c=l[0],u=l[1];return(0,f.jsxs)(h.__experimentalVStack,{spacing:4,children:[(0,f.jsx)(h.RangeControl,{__nextHasNoMarginBottom:!0,__next40pxDefaultSize:!0,value:c,onChange:function(e){void 0!==e&&u(e)},label:(0,w.__)("Desired length (characters)","wp-parsely"),min:50,max:300,disabled:t}),(0,f.jsx)(Te,{label:(0,w.__)("Tone","wp-parsely"),customLabel:(0,w.__)("Custom tone","wp-parsely"),value:a,options:Se,onChange:s,onSelect:function(e){k.trackEvent("excerpt_generator_ai_tone_changed",{selectedTone:e})},disabled:t}),(0,f.jsx)(Te,{label:(0,w.__)("Persona","wp-parsely"),customLabel:(0,w.__)("Custom persona","wp-parsely"),value:o,options:je,onChange:i,onSelect:function(e){k.trackEvent("excerpt_generator_ai_persona_changed",{persona:e})},disabled:t})]})},Ee=function(){return Ee=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=1e4&&(clearInterval(o),n("Telemetry library not loaded"))}),100);else n("Telemetry not enabled")}))},e.prototype.trackEvent=function(t,n){var r;this.isLoaded?(0!==t.indexOf(e.TRACKS_PREFIX)&&(t=e.TRACKS_PREFIX+t),this.isEventNameValid(t)?(n=this.prepareProperties(n),null===(r=this._tkq)||void 0===r||r.push(["recordEvent",t,n])):console.error("Error tracking event: Invalid event name")):console.error("Error tracking event: Telemetry not loaded")},e.prototype.isTelemetryEnabled=function(){return this.isEnabled},e.prototype.isProprietyValid=function(t){return e.PROPERTY_REGEX.test(t)},e.prototype.isEventNameValid=function(t){return e.EVENT_NAME_REGEX.test(t)},e.prototype.prepareProperties=function(e){return(e=this.sanitizeProperties(e)).parsely_version=wpParselyTracksTelemetry.version,wpParselyTracksTelemetry.user&&(e._ut=wpParselyTracksTelemetry.user.type,e._ui=wpParselyTracksTelemetry.user.id),wpParselyTracksTelemetry.vipgo_env&&(e.vipgo_env=wpParselyTracksTelemetry.vipgo_env),this.sanitizeProperties(e)},e.prototype.sanitizeProperties=function(e){var t=this,n={};return Object.keys(e).forEach((function(r){t.isProprietyValid(r)&&(n[r]=e[r])})),n},e.TRACKS_PREFIX="wpparsely_",e.EVENT_NAME_REGEX=/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/,e.PROPERTY_REGEX=/^[a-z_][a-z0-9_]*$/,e}(),S=(k.trackEvent,function(){return(0,f.jsx)(h.SVG,{"aria-hidden":"true",version:"1.1",viewBox:"0 0 15 15",width:"15",height:"15",xmlns:"http://www.w3.org/2000/svg",children:(0,f.jsx)(h.Path,{d:"M0 14.0025V11.0025L7.5 3.5025L10.5 6.5025L3 14.0025H0ZM12 5.0025L13.56 3.4425C14.15 2.8525 14.15 1.9025 13.56 1.3225L12.68 0.4425C12.09 -0.1475 11.14 -0.1475 10.56 0.4425L9 2.0025L12 5.0025Z"})})}),j=function(e){var t=e.size,n=void 0===t?24:t,r=e.className,i=void 0===r?"wp-parsely-icon":r;return(0,f.jsxs)(h.SVG,{className:i,height:n,viewBox:"0 0 60 65",width:n,xmlns:"http://www.w3.org/2000/svg",children:[(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M23.72,51.53c0-.18,0-.34-.06-.52a13.11,13.11,0,0,0-2.1-5.53A14.74,14.74,0,0,0,19.12,43c-.27-.21-.5-.11-.51.22l-.24,3.42c0,.33-.38.35-.49,0l-1.5-4.8a1.4,1.4,0,0,0-.77-.78,23.91,23.91,0,0,0-3.1-.84c-1.38-.24-3.39-.39-3.39-.39-.34,0-.45.21-.25.49l2.06,3.76c.2.27,0,.54-.29.33l-4.51-3.6a3.68,3.68,0,0,0-2.86-.48c-1,.16-2.44.46-2.44.46a.68.68,0,0,0-.39.25.73.73,0,0,0-.14.45S.41,43,.54,44a3.63,3.63,0,0,0,1.25,2.62L6.48,50c.28.2.09.49-.23.37l-4.18-.94c-.32-.12-.5,0-.4.37,0,0,.69,1.89,1.31,3.16a24,24,0,0,0,1.66,2.74,1.34,1.34,0,0,0,1,.52l5,.13c.33,0,.41.38.1.48L7.51,58c-.31.1-.34.35-.07.55a14.29,14.29,0,0,0,3.05,1.66,13.09,13.09,0,0,0,5.9.5,25.13,25.13,0,0,0,4.34-1,9.55,9.55,0,0,1-.08-1.2,9.32,9.32,0,0,1,3.07-6.91"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M59.7,41.53a.73.73,0,0,0-.14-.45.68.68,0,0,0-.39-.25s-1.43-.3-2.44-.46a3.64,3.64,0,0,0-2.86.48l-4.51,3.6c-.26.21-.49-.06-.29-.33l2.06-3.76c.2-.28.09-.49-.25-.49,0,0-2,.15-3.39.39a23.91,23.91,0,0,0-3.1.84,1.4,1.4,0,0,0-.77.78l-1.5,4.8c-.11.32-.48.3-.49,0l-.24-3.42c0-.33-.24-.43-.51-.22a14.74,14.74,0,0,0-2.44,2.47A13.11,13.11,0,0,0,36.34,51c0,.18,0,.34-.06.52a9.26,9.26,0,0,1,3,8.1,24.1,24.1,0,0,0,4.34,1,13.09,13.09,0,0,0,5.9-.5,14.29,14.29,0,0,0,3.05-1.66c.27-.2.24-.45-.07-.55l-3.22-1.17c-.31-.1-.23-.47.1-.48l5-.13a1.38,1.38,0,0,0,1-.52A24.6,24.6,0,0,0,57,52.92c.61-1.27,1.31-3.16,1.31-3.16.1-.33-.08-.49-.4-.37l-4.18.94c-.32.12-.51-.17-.23-.37l4.69-3.34A3.63,3.63,0,0,0,59.46,44c.13-1,.24-2.47.24-2.47"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M46.5,25.61c0-.53-.35-.72-.8-.43l-4.86,2.66c-.45.28-.56-.27-.23-.69l4.66-6.23a2,2,0,0,0,.28-1.68,36.51,36.51,0,0,0-2.19-4.89,34,34,0,0,0-2.81-3.94c-.33-.41-.74-.35-.91.16l-2.28,5.68c-.16.5-.6.48-.59-.05l.28-8.93a2.54,2.54,0,0,0-.66-1.64S35,4.27,33.88,3.27,30.78.69,30.78.69a1.29,1.29,0,0,0-1.54,0s-1.88,1.49-3.12,2.59-2.48,2.35-2.48,2.35A2.5,2.5,0,0,0,23,7.27l.27,8.93c0,.53-.41.55-.58.05l-2.29-5.69c-.17-.5-.57-.56-.91-.14a35.77,35.77,0,0,0-3,4.2,35.55,35.55,0,0,0-2,4.62,2,2,0,0,0,.27,1.67l4.67,6.24c.33.42.23,1-.22.69l-4.87-2.66c-.45-.29-.82-.1-.82.43a18.6,18.6,0,0,0,.83,5.07,20.16,20.16,0,0,0,5.37,7.77c3.19,3,5.93,7.8,7.45,11.08A9.6,9.6,0,0,1,30,49.09a9.31,9.31,0,0,1,2.86.45c1.52-3.28,4.26-8.11,7.44-11.09a20.46,20.46,0,0,0,5.09-7,19,19,0,0,0,1.11-5.82"}),(0,f.jsx)(h.Path,{fill:"#5ba745",d:"M36.12,58.44A6.12,6.12,0,1,1,30,52.32a6.11,6.11,0,0,1,6.12,6.12"})]})},P=function(){return P=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0?"".concat(i," ").concat(n):n)||this).hint=null,o.name=o.constructor.name,o.code=r;var s=[U.FetchError,U.HttpRequestFailed,U.ParselySuggestionsApiAuthUnavailable,U.ParselySuggestionsApiOpenAiError,U.ParselySuggestionsApiOpenAiSchema,U.ParselySuggestionsApiOpenAiUnavailable,U.ParselySuggestionsApiSchemaError];return o.retryFetch=s.includes(o.code),Object.setPrototypeOf(o,t.prototype),o.CustomizeErrorMessaging(),o}return oe(t,e),t.prototype.CustomizeErrorMessaging=function(){this.code===U.AccessToFeatureDisabled?this.message=(0,w.__)("Access to this feature is disabled by the site's administration.","wp-parsely"):this.code===U.ParselySuggestionsApiNoAuthorization?this.message=(0,w.__)('This AI-powered feature is opt-in. To gain access, please submit a request here.',"wp-parsely"):this.code===U.ParselySuggestionsApiOpenAiError||this.code===U.ParselySuggestionsApiOpenAiUnavailable?this.message=(0,w.__)("The Parse.ly API returned an internal server error. Please retry with a different input, or try again later.","wp-parsely"):this.code===U.HttpRequestFailed&&this.message.includes("cURL error 28")?this.message=(0,w.__)("The Parse.ly API did not respond in a timely manner. Please try again later.","wp-parsely"):this.code===U.ParselySuggestionsApiSchemaError||this.code===U.ParselySuggestionsInvalidRequest?this.message=(0,w.__)("The Parse.ly API returned a validation error. Please try again with different parameters.","wp-parsely"):this.code===U.ParselySuggestionsApiNoData||this.code===U.ParselySuggestionsApiNoDataManualLinking?this.message=(0,w.__)("The Parse.ly API couldn't find any relevant data to fulfill the request.","wp-parsely"):this.code===U.ParselySuggestionsApiOpenAiSchema||this.code===U.ParselySuggestionsApiResponseValidationError?this.message=(0,w.__)("The Parse.ly API returned an incorrect response.","wp-parsely"):this.code===U.ParselySuggestionsApiAuthUnavailable&&(this.message=(0,w.__)("The Parse.ly API is currently unavailable. Please try again later.","wp-parsely")),this.code===U.FetchError&&(this.hint=this.Hint((0,w.__)("This error can sometimes be caused by ad-blockers or browser tracking protections. Please add this site to any applicable allow lists and try again.","wp-parsely"))),this.code!==U.ParselyApiForbidden&&this.code!==U.ParselySuggestionsApiNoAuthentication||(this.hint=this.Hint((0,w.__)("Please ensure that the Site ID and API Secret given in the plugin's settings are correct.","wp-parsely"))),this.code===U.HttpRequestFailed&&(this.hint=this.Hint((0,w.__)("The Parse.ly API cannot be reached. Please verify that you are online.","wp-parsely")))},t.prototype.Hint=function(e){return'